Repository navigation
Rules and records: the ABI and kernel rulings, the no-panic track, the owner's 2026-09-30 rulings, CPU microcode, the crate track, the LLVM-bytes and TCO-overflow defects - #673
Conversation
Almost every single-consumer `toyos-*` crate says, in its manifest or module doc, that it is a crate so that its tests run on the host. Measured today: - The gated userland programs already host-test their own modules (`src/userlandhost.rs`), and blockd, calc, pkg and terminal carry a lib beside their bin. - A package with a `no_std`/`no_main` bin under a bare-target `.cargo/config.toml` and a `cfg_attr(not(test), no_std)` lib builds both for `x86_64-unknown-none`. Its lib's tests run under `cargo test --lib --target aarch64-apple-darwin`, and a host package that depends on it by path builds the lib alone. - The kernel binary itself runs a `#[cfg(test)]` test on aarch64-apple-darwin. That takes `cfg_attr(not(test), no_main)`, the panic handler, the global allocator and three aarch64 entry assembly items out under test, and allows dead code in the test build. Its x86_64 Linux test object links as a PIE under `-z text`, with only libc, unwinder and allocator-shim symbols left undefined. - `#![forbid(unsafe_code)]` is enforced at module scope, including against a local `allow`. The track folds 16 packages away, 95 to 79, and ends in a `src/hostws.rs` gate. That gate reds on an rlib-only package with fewer than two consumers unless it declares one of four exception kinds. Two defects found on the way are filed rather than fixed: - `toyos-pcid`'s `counting-allocator` control is run by nothing. By hand it still reds. - No userland crate is linted, though the gated ones build for the host. soundd shows 8 clippy findings and netd 10. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner's direction on the first round: no gate, and push the cleanup as far as the measured facts allow. The track is renamed from a-crate-has-two-consumers-or-says-why-it-is-alone, because it no longer makes that claim, and it is rewritten as five steps, each with an exit and a check. - The kernel-only crates become a lib target of the kernel package, in kernel/pure/. The loom models become kernel/loom/, and the simulators kernel/sim/. - Single-program userland crates become modules of their program, or its library where another program reads them. - Shared crates on one subject merge: toyos-boot, toyos-log, toyos-block, and swap into toyos-manifest. - toyos-userpin is deleted. That takes the tree from 95 packages to 66, and the root's toyos-* directories from 44 to 16. Trial folds in scratch back the plan: - Seven kernel crates in kernel/pure/: the kernel builds for both bare targets, and the library lists 276 tests, the seven crates' sum. The simulator and loom counts are unchanged, four controls still red, the harness builds against the library, and both clippy shapes exit 0. - The mixer in soundd lists 58 tests, and the desktop in the compositor 95. soundd at opt-level 0 takes 34.31 s, and 3.07 s at 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in CLAUDE.md Agents kill what they started before reporting, give rg an explicit path in scripts, and keep PR evidence out of /tmp; the orchestrator acts on a finished report before dispatching. CLAUDE.md states the general-purpose scope and that ARM64 is a QEMU target only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
Restore "keep the architecture portable" beside the ARM64 sentence and drop "proving machines"; fold kill-by-PID into "Leave the machine as you found it"; keep the rg and /tmp rules in implementer.md only; drop the ARM-hardware clause from the process-memory issue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
…ragraph The kill-by-PID rule moves from implementer.md into the CLAUDE.md "Leave the machine as you found it" bullet, "for ever" becomes "forever", and the process-memory issue drops its ARM64 clause. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
The child-process track's fourteen questions are ruled as recommended,
each written as one line at the stage it governs, and
issues/kernel/the-child-process-track-waits-on-the-owners-rulings.md
goes:
- Q2, Q6d at stage 2: an end reads as an exit, a kill or a fault kind
alike on every architecture, a bare code reads the last two as
failures, and no end reads as a quit's reason.
- Q3a, Q3b, Q3c at stage 3: libc imitates SIGCHLD; a handler runs at
once, beside the program; a C child starts with descriptors 0-2 and
what its file actions name, a stated departure from POSIX.
- Q5a, Q5b, Q5c at stage 5: a login's session is a program that only
parents what its user starts; init hands the compositor or sshd the
right to start programs in it; sshd's right also quits and kills it.
- Q6a, Q6b, Q6c, Q6e, Q6f at stage 6, whose text already said each as
recommended: a quit carries interrupt, hang-up or terminate, reaches
the subtree, kills a process that never listens, reaches a Rust
program through std and ctrlc, and a C program as SIGINT, SIGHUP and
SIGTERM.
- Q7 at stage 7: a second Ctrl+C kills only a program that has not yet
taken the first.
Cut as moot: the pointer to the question file, the question labels on
the stage headings, the Ruled block's session clause (now stage 5's
line), stage 6's reason for the shell relaying nothing (now stage 6's
reach line), and stage 7's "Stop and continue need a suspend primitive
and are not proposed", which scoped the proposal the rulings closed. The
track stays at 260 lines.
The supervisor track's open item on the ask's ABI cited Q6a; Q6a is
ruled and its stage 3 already asks by stage 6's quit, so the item goes.
The rest:
- The kernel is to load CPU microcode signed by the CPU's maker and
pinned by version and hash, as vendor device firmware is. The question
becomes the defect issues/kernel/the-kernel-loads-no-cpu-microcode.md,
exit: current microcode loaded early on every CPU, at least as current
as Linux's. The security track's list follows the rename.
- std::os::toyos::io::{AsRawFd, FromRawFd} are renamed the next time the
trait is touched in the fork: an open defect with that exit.
- A boot start's device refusal is fatal only for a device the
[programs] row marks as required; otherwise init logs it loudly and
starts the program without it: an open defect whose exit is the row's
mark and the two outcomes.
- doomgeneric's fetch stays; its question file goes.
- doom.jpg is the owner's own screenshot, which he keeps, and no licence
question applies; its question file goes and its COMMITTED_FILES row
says so in the column that names where its terms are recorded. The
terms column stays NOASSERTION.
- The blocked-task dump keeps painting its report on the panel and
holding it there: one line at the small-kernel track's step 5 replaces
that step's open question and stage 6's hold on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Found while scouting whether rustc's bootstrap builds LLVM under n2 in place of Ninja. `llvm::tests::keyed_and_built` built key 64453b64c91c17c2 (LLVM, clang and LLD) from a fork checkout at c4c65e3e87a whose src/llvm-project was a git worktree of the primary's at a79bc52c1d5e, with only an n2 link named `ninja` reachable; exit 0 in 1693 s. The store holds a Ninja-built LLVM at the same key, made in toyos-mtime on 2026-09-29, before n2 was first fetched on this host. Both hold the same 3841 paths; 3660 are byte-identical. Every one of the other 181 is explained by something the key does not name: the LLVM checkout's origin URL (LLVM_REPOSITORY), the build directory (lld's LC_RPATH, llvm-config's roots), or the dates in 161 archives whose members are byte-identical. None traces to the build tool. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Review round 1 on 7eb4428. - The microcode ruling orders the kernel to load what root CLAUDE.md's firmware rule still bars: it admits only device firmware that never executes on the CPU. PR #636 amends that sentence to admit the CPU's own microcode, which the kernel loads, and this branch lands after it. The defect regains the deleted question's pointer at that rule, as one line saying the rule admits the microcode once #636 lands. - Step 6 of the small-kernel track loses its heading "The scheduler knows nothing about devices": step 5 now keeps the pass painting the panel, a device the pass reaches. - The child-process track's stage headings lose " (ruled)", and stage 3 loses "ruled; ": every stage carried it, so it distinguished nothing. The track is 35 bytes longer than on main (18608 -> 18643), at 260 lines. - doom.jpg's row loses "he keeps it, and rules that": the committed file shows it is kept, and "no licence question applies" carries the ruling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…y a check that can fail Review of 90e2b17 on PR #646. The exit named two worktrees, while the origin that differs is the primary's against a worktree's, and it named no check. Which LLVM_REPOSITORY each checkout's build writes, from LLVM's own GenerateVersionFromVCS.cmake run as llvm/include/llvm/Support/CMakeLists.txt runs it, exit 0 each: - the primary's rust/src/llvm-project, gitlink a79bc52c1d5e, checkout 52ed14fcd56a: https://github.com/rust-lang/llvm-project.git - toyos-libcllvm's, gitlink and checkout 849da7d62fbc: https://github.com/ToyOSOrg/llvm-project.git The fork's .gitmodules and its shared config both name ToyOSOrg. Bootstrap's update_submodule, its git commands run on scratch repositories in the primary's state (cloned from A, .gitmodules and config naming B): with the checkout behind its gitlink, `submodule sync` and `update` exit 0 and the script then writes B; with the checkout at its gitlink, bootstrap runs nothing and it writes A. The exit now names the check: one key built in two fork checkouts at different paths whose origins name different repositories, every file of the two installs byte-identical. Path and origin together cover every pair: the primary's and a worktree's, two worktrees', a checkout made by hand. kind: defect. The origin reaches guest bytes: `llvm-readelf -p .comment` on sysroot d8a0215fc9eae3c5's libstd-1d0a603a43d0da8a.so gives "Linker: LLD 22.1.8 (https://github.com/ToyOSOrg/llvm-project.git 849da7d6...)", and 75 of the 77 members of its c/lib/libc++.a carry clang's version with the same URL; the other two are UnwindRegistersSave.S.o and UnwindRegistersRestore.S.o, which have no .comment. issues/build/toyos-builds-itself.md points M4 at it. The Ninja row of issues/build/the-build-runs-host-tools-outside-rust-and-qemu.md takes the scout's result: bootstrap built LLVM, clang and LLD under n2, exit 0. The counts that rested on the n2 tree (181 different, 3660 identical, 161 archives differing only in dates) went with it, and the issue carries none of the comparison's counts. The stored side, rust/build/llvm/64453b64c91c17c2, reproduces: 3841 paths, 162 archives, 19 files naming ToyOSOrg/llvm-project, llvm-config and lld naming toyos-mtime, and every member of all 162 archives dated 2026 by `ar tv`. Removed as the review asked: "none of them the build tool", "every --version prints it", the key and toyos-mtime, and the examples of byte-identical tools. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…rates
The owner decided a rule graded by what a panic costs: no panic at all at
an input boundary, no implicit panic in the kernel or the system services,
normal Rust for apps, ports, tests and tooling. He asked that it be
recorded, not done now. The track carries the rule, what holds today and
the five stages with their exits.
Measured for it:
- `rg -o '\.unwrap\(\)|\.expect\(' kernel/src | wc -l` is 157 (154 lines
by `rg -c`).
- `cargo clippy --target x86_64-unknown-none -- -W clippy::indexing_slicing
-W clippy::arithmetic_side_effects -W clippy::unwrap_used
-W clippy::expect_used -W clippy::panic -W clippy::unreachable
-W clippy::cast_possible_truncation --message-format=json`, in kernel/,
counted per lint code with jq: 2,008 findings in the kernel crate.
- `rustc -Z unstable-options --print target-spec-json` gives
`"panic-strategy": "abort"` for x86_64-unknown-none and
aarch64-unknown-none-softfloat. The no-panic README calls its attribute
"useless in code built with panic = abort", so a link proof has to come
from a host build.
- A scratch crate run under the seven lints drew no warning for `assert!`,
`copy_from_slice` or `split_at`. It drew one each for `a[3]` and `panic!`.
The brief expected `issues/` to hold the two crafted-ELF panics an overflow
check found, and it holds neither. The closed entry left the tracker at
fa2799d, yet seven comments still cite `issues/` for it, and the tree's
rule is to file that rather than fix it here. The second file records it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…el can do Two owner rulings of 2026-10-01, written into the prompts that govern agents. The ABI. "We can change system calls. We can remove them, add them, change them. I want to have the cleanest, most sustainable ABI." Three lines said the opposite and steered agents away from the ABI: - Root CLAUDE.md, "Syscall ABI": "Never add or change a syscall without discussion; a deleted syscall's number is retired, never reused." It now says the cleanest, most sustainable ABI beats convenience and a removed number is free. "read the code" goes with it: the Architecture section's header already says it. The line is shorter than the one it replaces. Workflow's "An ABI change lands with the work that needs it" stays. - implementer.md: "Never touch toyos-abi/src, toyos/src or userland/libc/src unless the brief is an ABI brief." Deleted. The brief's fence already bounds what an implementer touches. - reviewer.md, "What no gate reads": a BLOCKER for reusing a retired syscall, SYS_DEBUG action or inbox op number, or declaring a retired ABI name. Deleted. Connect-by-name and pid-as-authority stay banned by root CLAUDE.md's Capabilities paragraph, which bans the design whatever it is called. Kernel or server. In the symlink incident, libc's symlink needed "refuse an existing name". The implementer avoided the kernel change and returned ENOSYS, and the reviewer asked for the kernel to refuse the name. Neither asked whether the kernel should own symlinks at all; fsd already resolves them. The owner: "one less thing for the kernel to do… the reviewer and implementer should know we try to use userland programs instead of the kernel." - implementer.md: before adding or keeping kernel behaviour, ask whether a userland server can own it. When the clean design changes the ABI, change the ABI. - reviewer.md, "Fit": a BLOCKER each for a kernel addition or a kept kernel path a userland server could own, and for a design made worse to spare the ABI. The code still keeps retired numbers: retired_syscalls!, the "formerly …" entries in toyos-abi, four test sites that use syscall 26 as their logged refusal, and seven issue files that plan by retirement. That is outside this branch's fence, so it is filed as issues/design-debt/the-abi-still-keeps-retired-syscall-numbers.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…llow]; seven crafted-ELF clauses go Answers the review of 6b2eef1 on PR #665. The set covers every operation that can panic on input. Each lint name was checked against clippy 0.1.98 (48a229ceae) on a scratch crate under `#![deny(unknown_lints)]`. All fifteen drew a finding on their own form. A bogus `clippy::no_such_lint_control` was refused, and it was the only error (exit 101). The set adds these to PR #653's nine: - `string_slice`, because `indexing_slicing` drew nothing on `&s[1..]` and `string_slice` did; - `cast_possible_truncation`, which the owner names; - `disallowed_methods` naming `slice::split_at` and `slice::copy_from_slice`; - `disallowed_macros` naming `core::assert`, `assert_eq` and `assert_ne`. Each of those configured names fired. What the set does not see, measured: `a << b`, `a >> b`, `1u64 << b`, `a.pow(b)` and `a.abs()` drew no finding. Built with `-C overflow-checks=on`, the shift, the `pow` and the `abs` each exit 101: "attempt to shift left with overflow", "attempt to exponentiate with overflow", "attempt to negate with overflow". The gate: - `#![forbid(clippy::indexing_slicing)]` turns an inner `#[expect(…, reason)]` into E0453, and an inner `#![allow(…, reason)]` too. - With `allow_attributes` and `allow_attributes_without_reason` on, an outer `#[allow]` draws the first lint, with or without a reason. - A bare `#[allow]`, `#![allow]` or `#[expect]` draws the second. - An inner `#![allow(…, reason = …)]` draws neither. Stage 3's exit closes that hole with a `--ci host` step. clippy.toml: with a parent file listing `copy_from_slice` and a child listing `split_at`, the child crate drew only `split_at`. With the child's file removed, it drew only `copy_from_slice`. Only the nearest file is read. The count. `cargo clippy --target x86_64-unknown-none --message-format=json` ran in kernel/ with the set as `-W`. The two methods and three macros were added to a copy of the root clippy.toml, passed through CLIPPY_CONF_DIR. It exits 101 under the kernel's `-Dwarnings`. Counted by code with jq: - 992 arithmetic_side_effects - 408 indexing_slicing - 394 cast_possible_truncation - 208 disallowed_macros (200 assert, 8 assert_eq) - 109 expect_used - 60 panic - 39 disallowed_methods (all copy_from_slice) - 29 unwrap_used - 16 unreachable - 14 panic_in_result_fn - 5 string_slice That is 2,274. Beside them are 26 allow_attributes and 28 allow_attributes_without_reason. Seven clauses cited `issues/` for crafted-ELF panics that the tracker closed at fa2799d. They sat at Cargo.toml (two), bootloader/, kernel/ and userland/Cargo.toml, and src/build.rs (two). All are deleted, with the file that recorded them. None of the five files is a sysroot input. Also deleted, as REMOVEs: - the "seven crates" claim; - the boundary and service lists; - "where a reviewer sees it"; - the per-crate inventory; - the rg count; - the crafted-ELF history; - the microcode citation; - the constraint's provenance; - stage 5; - the mutation line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Review of 066e1a0 on #666 sent the branch back. - CLAUDE.md's Kernel line said new additions are "discussed" and named the filesystem a kernel job, against both rulings. It now says the kernel takes on only what userland cannot, keeps the job list without the filesystem, and points at the Capabilities paragraph, whose "Not yet true of files" sentence already records the machine-wide tree the kernel still holds. 132 characters replace 135. - implementer.md's closed list of kernel jobs was a second declaration of the kernel's scope that the owner never gave; deleted, along with the restated rule, which root CLAUDE.md now carries. - "or keeping" (implementer.md) and "or a kernel path the branch keeps" (reviewer.md) made every kernel-side defect fix a BLOCKER outside its fence; deleted. A kernel refusal is still "a kernel addition", and an ENOSYS dodge is still "a design made worse to spare the ABI". - "a userland server" became "userland" in both files: the owner's loader move puts relocation in a Ring 3 loader in the target's own address space, which is userland but no server. - implementer.md says a clean design that reaches past the fence blocks the implementer, so the ABI sentence does not widen the fence. - The Syscall ABI line drops "add, change or remove syscalls", which "completely unstable" already says. - issues/design-debt/the-abi-still-keeps-retired-syscall-numbers.md names an owner and lists the retired device classes 3 and 4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…nel takes on only what userland cannot One conflict, reviewer.md's tinycc sentence beside "What no gate reads": main deleted `hello.c` from the files tracked under `tests/testcases/`, and #666 deleted the retired-ABI BLOCKER from the bullet below it. Both are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…afted-ELF clauses go Clean merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…t its microcode files Clean merge. Three of #645's hunks are left out, because #653 carries the microcode defect and lands on its own: - the new `issues/kernel/the-kernel-loads-no-cpu-microcode.md`, an add/add conflict with #653's file of that name, whose body is a superset; - the deletion of `issues/kernel/whether-the-kernel-loads-cpu-microcode-is-the-owners.md`, which #653 deletes; - the security track's citation of the new file, which #653 changes. So the security track still cites a file that exists, and #653 merges onto this without a conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…d CLAUDE.md Clean merge; what of it stays is decided in the commit after this one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…n that program Clean merge; its counts and premises are refreshed against main in a later commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…heir bytes One conflict, the host-tools table's Ninja row. #646 added the scout's n2 result to the row's verdict; main deleted the row when the LLVM build began running n2 as its only Ninja (b2b1713), which is the row's exit. Main's side is taken: the row is gone, and with it #646's hunk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…ites are main's Round 1 of #666's review asked that "the 'only what only a kernel can' rule replaces that 135-character span, written as a rule on what the kernel takes on and not as a snapshot". Round 2 kept the job list beside the rule, less the filesystem, with a "files: see Capabilities" pointer. The job list is the snapshot the review named, and the rule alone states what the kernel takes on; the pointer's subject is already the Capabilities paragraph's own "Not yet true of files". So the span is now the rule alone: "takes on only what userland cannot." The ABI issue listed four test sites that take syscall 26 as their logged refusal. Since #660 landed, `log_hold.rs` and `tests/common/origin.rs` are gone; `panic_halts_first.rs` and `tests/toyos.rs` remain, and the exit names both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…admitted #613's first review sent it back because root CLAUDE.md's line 3 grew and its ARM64 sentence contradicted the cores issue. Since then main's ARM64 track has stated the ruling itself ("no ARM hardware is a target and no work goes into one"), and the cores issue no longer says otherwise. What of #613 stays: - Line 3 goes back to main's text with two additions: "general-purpose", and "Its test machines decide its feature set, never its design." Both are the owner's ruling of 2026-09-29 ("ToyOS is a general-purpose OS for modern hardware; the T14 may decide the feature set but is not the design centre"), recorded at 314f874 in the Raspberry Pi track and lost when that track was deleted; nothing on main says it now. #613's ARM64 sentence goes: main's track says it. - "Leave the machine as you found it" says "kills by PID what it started" where it said "stops what it started". By PID is the one thing the lesson adds to that bullet; "before reporting" is already its "never leaves ... running". - implementer.md keeps the rule that a pull request's evidence never lives only in /tmp, and that mutation patches are posted to the pull request. Nothing in implementer.md said either. - implementer.md loses the rule that rg without a path waits forever on stdin. In the agents' shell, foreground and background, stdin is a character device (`stat -f '%HT' /dev/fd/0`), and `rg -l <needle>` with no path searched the working directory and exited 1, no match, in both. - The process-memory track keeps main's sentence that one paging design serves x86-64 and the ARM64 the tree is kept portable for. ARM64 under QEMU is still that second architecture; nothing in it contradicts the QEMU-only ruling. #645's one BLOCKER is answered here too: the firmware paragraph now says vendor firmware "never executes on the CPU, save the CPU's own microcode, which the kernel loads", #636's clause for the owner's ruling that the kernel loads CPU microcode signed by its maker and pinned by version and hash. Root CLAUDE.md is 16075 bytes; main's is 16077. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…ernel's crates Answers round 2 of #665's review (f469e90). Blockers: - The set names every lossy cast: `cast_possible_wrap`, `cast_sign_loss` and `cast_precision_loss` beside `cast_possible_truncation`. Each changes a value silently, which "Fail fast" puts below a panic; that is the reason the track now gives, in place of "the owner names it". - Stage 3's `--ci host` step also refuses an `#[expect]` of the set on a `mod`, on an `impl`, and as an inner `#![expect]`: any of them passes every finding beneath it. - Stage 3 ends with every crate of this tree that `kernel/Cargo.toml` links under the same attributes, unless stage 1 already forbids the set in it. Notes: the set names `slice::split_at_mut` and `slice::clone_from_slice`; the clause on `issues/design-debt/elf-domain-lint-line-not-yet-added.md` goes, and that issue is left to its holder; stage 1's "one declaration" now states what was measured: Cargo's `[lints]` reaches test code and `cargo clippy --lib -- -F` does not, and neither reaches a single module, so an input boundary inside the kernel becomes a crate first. Removed: the clippy version line, "(fail fast)" and the unrepresentable-type sentence, everything after "No crate carries the set.", and the ELF clause. Measured on scratch crates with cargo 1.98.1 and clippy 0.1.98 (48a229ceae), each `cargo clippy -p <crate>` unless named: - `#![forbid(clippy::indexing_slicing)]` and an `#[expect(…, reason)]` of it: E0453, exit 101. The same forbid and an inner `#![allow(…, reason)]` in a module: E0453, exit 101. - With `clippy::allow_attributes` and `allow_attributes_without_reason` forbidden: an outer `#[allow(…, reason)]` draws `allow_attributes`, exit 101; an `#[expect]` with no reason draws the second, exit 101; an inner `#![allow(…, reason)]` in a module draws neither, exit 0. - Under the same attributes and `deny` of indexing and arithmetic, one `#[expect(…, reason)]` on `mod drivers;` over five findings, an inner `#![expect]` over two and an `#[expect]` on an `impl` over two: exit 0, no warning, so every expectation was fulfilled. - `&s[1..]` on a `str` draws `string_slice`, and `indexing_slicing`, also denied, draws nothing: exit 101. - Shift left and right by a variable, `pow` and `abs` under the whole set denied: exit 0. Built with `-C overflow-checks=on`, each exits 101: "attempt to shift left with overflow", "attempt to shift right with overflow", "attempt to exponentiate with overflow", "attempt to negate with overflow". - `[lints.clippy] indexing_slicing = "forbid"`: `--all-targets` exits 101 at a `#[cfg(test)]` slice index, `--lib` exits 0; with `#![cfg_attr(test, allow(clippy::indexing_slicing))]` added, `--all-targets` gives E0453, exit 101. - `--lib -- -F clippy::indexing_slicing`: exit 101 on the library's index; exit 0 on a clean library whose test indexes a slice, which `--all-targets -- -F` refuses, exit 101; and E0453, exit 101, on an inner `#[expect(…, reason)]` of the lint. - `CLIPPY_CONF_DIR` naming the four methods and three macros: each of the seven fires, exit 101. The kernel count: in kernel/, with the root clippy.toml plus those methods and macros through `CLIPPY_CONF_DIR`, `cargo clippy --target x86_64-unknown-none --message-format=json -- -W <each of the 16 lints>` exits 101 under the kernel's `-Dwarnings` with 2,282 errors, counted by code: 984 arithmetic_side_effects, 405 indexing_slicing, 392 cast_possible_truncation, 205 disallowed_macros (198 assert, 7 assert_eq), 107 expect_used, 55 panic, 39 disallowed_methods (all copy_from_slice), 29 unwrap_used, 20 cast_possible_wrap, 16 unreachable, 14 panic_in_result_fn, 9 cast_sign_loss, 5 string_slice, 2 cast_precision_loss. That is the kernel package alone: clippy lints no crate it links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
#604 was written against main as of 7e15181, 574 commits back. Each premise was checked against this branch, and each count was relisted with `cargo test -p <package> -- --list`, exit 0 for every package. Premises that moved: - The network stack's stage 3 landed as `toyos-net-ip`, `toyos-net-udp` and `toyos-dhcp`. Nothing but each other depends on them, so step 5 folds them into netd's library beside the four it already named. Stage 4's `toyos-net-shard` and `toyos-net-testnet` are what the network track still plans. - `toyos-gicv3` and `toyos-cpuvuln` arrived. `kernel/Cargo.toml` is the one manifest that names `toyos-gicv3`. `toyos-cpuvuln` has no dependent yet, and its track (`a-pure-function-decides-a-cpus-speculation-mitigations- as-linux-does.md`) has it "built by the kernel and by a host test". Both go into the kernel's library in step 3. - `src/redlist.rs` is deleted, so step 1's redlist check goes. `munmap_reissues_read_window` is still a test binary and rides `shared_metal`. - Three scheduler tests need a feature, not six, and `check` is the one they need: toyos-sched lists 92 tests bare, 95 with `check`, 92 with `protocol-port` and 95 with both. Counts, old and new: - The kernel's library: 391 becomes 495. dma 17, pci 75, pcid 6, proclife 34, ps2 24, sched 95, userbound 34, xhci 150, gicv3 8 and cpuvuln 52. toyos-symbols is still 9. - `kernel/loom`: 81 becomes 79 (kernel-loom 53, sched-loom 26). `kernel/sim` is still 99 (sched-sim 53, xhci-sim 46). - The merged crates, 157, 26, 45, 25 and 67, become 170, 26, 45, 26 and 67. toyos-boot is acpi 52, bootmap 43, rootimage 21, blackbox 33, tco 13 and quiesce 8. toyos-log is elide 12 and logstream 14. toyos-block is blockhold 9, blockring 19 and transport 17. Manifest 19 and swap 7, and fat32-check 67. - netd's library: 709 becomes 1105. dns 43, mdns 12, net-wire 292, net-tcp 363, net-ip 261, net-udp 58 and dhcp 76. The mixer is still 55, the desktop 95 and inspect 21. Still true, so unchanged: - The pcid issue. `src/ci.rs`'s CONTROLS has no toyos-pcid row, and `declared_model_controls` reads no toyos-pcid manifest. `cargo test -p toyos-pcid --features counting-allocator` exits 101 with `tests::two_live_address_spaces_never_share_a_pcid ... FAILED`. - The userland-lint issue. `cargo clippy --manifest-path userland/<crate>/Cargo.toml --target aarch64-apple-darwin --all-targets -- -D warnings` exits 101 with 8 errors in soundd, 10 in netd's test target, and 1 in toyos-window under the compositor. - `the_corpus_is_reproduced_bit_for_bit` is still the mixer's. - Userland's `[profile.dev]` is still at opt-level 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…es M4 Answers round 2 of #646's review (865239c). - Told apart from the two-checkouts defect. Each file now says what it holds fixed and names the other. The two-checkouts defect holds the LLVM fixed and varies rustc's inputs. This one varies the LLVM's build. Every checkout on a host links the one LLVM its key names, so the two-checkouts gate cannot see an origin, and a comparison of two LLVM installs cannot see a panic path. - A host exit. LLVM's own `GenerateVersionFromVCS.cmake`, at the primary's `src/llvm-project` 52ed14fcd56a, ran with `cmake -DNAMES=LLVM -DLLVM_SOURCE_DIR=<checkout>/llvm -DHEADER_FILE=<out> -P <script>` on two scratch checkouts of one commit, whose origins name `rust-lang` and `ToyOSOrg`, exit 0 each: - with both forcing variables empty, as `config_text` leaves them today, the headers differ in `LLVM_REPOSITORY`; - with `LLVM_FORCE_VC_REPOSITORY` alone, they match, but the revision is gone: `#undef LLVM_REVISION`; - with `LLVM_FORCE_VC_REVISION` set too, they match and both are defined. So the exit names both variables, and a host test running that script on two such checkouts. It is red today, and it has no `update_submodule` in it to sync the origins together. The nightly's two full builds stay only for what a configure or a build writes, the build directory and the archive dates. That check now has to show the two origins still differ after each build, because bootstrap syncs a checkout that is behind its gitlink. - M4's line goes. M4's guest side links with the LLD that bootstrap builds for a ToyOS host, and no `src/llvm.rs` key builds that LLD, so this exit could be met while M4's hashes still differ. The issue no longer says the primary's checkout names `rust-lang`, which was a snapshot of this host (round 2's REMOVE). It no longer says one of the two builds ran under n2 in place of Ninja: on main every `build_in_fork` build runs n2 (4f2bea1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Scratch crates behind #665's measurements in this batch (cargo 1.98.1, clippy 0.1.98 48a229ceae; edition 2024; one workspace, each crate c1
#![forbid(clippy::indexing_slicing)]
#[expect(clippy::indexing_slicing, reason = "one stop")]
pub fn first(v: &[u8]) -> u8 {
v[0]
}c2
#![forbid(clippy::indexing_slicing)]
pub mod m {
#![allow(clippy::indexing_slicing, reason = "a module")]
pub fn first(v: &[u8]) -> u8 {
v[0]
}
}c3
#![deny(clippy::indexing_slicing)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
#[allow(clippy::indexing_slicing, reason = "outer")]
pub fn first(v: &[u8]) -> u8 {
v[0]
}c4
#![deny(clippy::indexing_slicing)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
pub mod m {
#![allow(clippy::indexing_slicing, reason = "inner")]
pub fn first(v: &[u8]) -> u8 {
v[0]
}
pub fn second(v: &[u8]) -> u8 {
v[1]
}
}c5
#![deny(clippy::indexing_slicing)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
#[expect(clippy::indexing_slicing)]
pub fn first(v: &[u8]) -> u8 {
v[0]
}c6
pub fn a(v: &[u8]) -> u8 {
v[0]
}
pub fn b(v: &[u8]) -> u8 {
v[1]
}
pub fn c(v: &[u8], i: usize) -> u8 {
v[i]
}
pub fn d(x: u32, y: u32) -> u32 {
x + y
}
pub fn e(x: u32, y: u32) -> u32 {
x * y
}
#![expect(clippy::indexing_slicing, reason = "inner")]
pub fn a(v: &[u8]) -> u8 {
v[0]
}
pub fn b(v: &[u8]) -> u8 {
v[1]
}
#![deny(clippy::indexing_slicing, clippy::arithmetic_side_effects)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
#[expect(clippy::arithmetic_side_effects, clippy::indexing_slicing, reason = "drivers")]
pub mod drivers;
pub mod inner;
pub struct S(pub [u8; 4]);
#[expect(clippy::indexing_slicing, reason = "impl")]
impl S {
pub fn a(&self, i: usize) -> u8 {
self.0[i]
}
pub fn b(&self, j: usize) -> u8 {
self.0[j]
}
}c7
#![deny(clippy::indexing_slicing, clippy::string_slice)]
pub fn tail(s: &str) -> &str {
&s[1..]
}c8
#![deny(
clippy::indexing_slicing,
clippy::string_slice,
clippy::arithmetic_side_effects,
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::unreachable,
clippy::todo,
clippy::unimplemented,
clippy::panic_in_result_fn,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::cast_precision_loss,
clippy::disallowed_methods,
clippy::disallowed_macros
)]
pub fn shl(a: u32, b: u32) -> u32 {
a << b
}
pub fn shr(a: u32, b: u32) -> u32 {
a >> b
}
pub fn pow(a: u32, b: u32) -> u32 {
a.pow(b)
}
pub fn abs(a: i32) -> i32 {
a.abs()
}
fn main() {
let which = std::env::args().nth(1).unwrap_or_default();
let big: u32 = std::hint::black_box(40);
let min: i32 = std::hint::black_box(i32::MIN);
let r = match which.as_str() {
"shl" => i64::from(c8::shl(1, big)),
"shr" => i64::from(c8::shr(1, big)),
"pow" => i64::from(c8::pow(10, big)),
"abs" => i64::from(c8::abs(min)),
_ => 0,
};
println!("{which} returned {r}");
}c9
[lints.clippy]
indexing_slicing = "forbid"
pub fn first(v: &[u8]) -> Option<&u8> {
v.first()
}
#[cfg(test)]
mod tests {
#[test]
fn indexes() {
let v: &[u8] = &[1];
assert_eq!(v[0], 1);
}
}c10
[lints.clippy]
indexing_slicing = "forbid"
#![cfg_attr(test, allow(clippy::indexing_slicing))]
pub fn first(v: &[u8]) -> Option<&u8> {
v.first()
}
#[cfg(test)]
mod tests {
#[test]
fn indexes() {
let v: &[u8] = &[1];
assert_eq!(v[0], 1);
}
}c11
pub fn first(v: &[u8]) -> u8 {
v[0]
}
#[cfg(test)]
mod tests {
#[test]
fn indexes() {
let v: &[u8] = &[1];
assert_eq!(v[0], 1);
}
}c12
pub fn first(v: &[u8]) -> Option<&u8> {
v.first()
}
#[cfg(test)]
mod tests {
#[test]
fn indexes() {
let v: &[u8] = &[1];
assert_eq!(v[0], 1);
}
}c13
#[expect(clippy::indexing_slicing, reason = "one stop")]
pub fn first(v: &[u8]) -> u8 {
v[0]
}c14
#![deny(clippy::disallowed_methods, clippy::disallowed_macros)]
pub fn methods(a: &mut [u8], b: &[u8], m: usize) -> u8 {
let (x, _) = b.split_at(m);
let (y, _) = a.split_at_mut(m);
y.copy_from_slice(x);
a.clone_from_slice(b);
a.first().copied().unwrap_or(0)
}
pub fn macros(a: u8, b: u8) {
assert!(a > 0);
assert_eq!(a, b);
assert_ne!(a, b);
}c14's
|
…ill of a locked build, and the crate track yields to the no-panic track Answers issuecomment-5931861144 (review of dc45e23). BLOCKERs: - Firmware. The shipping terms are shared and the loading clause splits: a device's firmware is loaded only by its own driver through its IOMMU domain and never executes on the CPU; CPU microcode is loaded by the kernel. Root CLAUDE.md is 16076 bytes, main's 16077. - Panics. Stage 3's step refuses an #[expect] of the set over more than one finding. It lints a copy in which each #[expect] of the set is a #[deny] whose reason is its own file and line; rustc attaches that reason to every finding the attribute governs. It also refuses a copy with fewer findings than --force-warn of the set, which catches an #[expect] the copy missed, as one inside cfg_attr. The tier-2 row says the stop is spelled out at its site. - Kill order. src/CLAUDE.md:24 is true: bootstrap recreates stage2 without its cargo, and reassemble puts it back in the same process under the same hold (src/toolchain.rs). Root CLAUDE.md's bullet no longer orders a kill: an agent stops what it started, killing only by PID and waiting out a build that holds the global lock. - Conflicting tracks. #604's track yields and names #665's: an input boundary is a crate of its own, because tier 1 is forbidden per crate and a crate holding a tier-2 stop cannot forbid the set (E0453, c1 of issuecomment-5931382112). toyos-userbound, -dma, -pci, -acpi, -transport, -blockring and -dns say so at their roots, -ps2 decodes a device's wire, and the network crates read the network; no step moves them. Step 3 takes 345 tests, step 4 drops acpi from toyos-boot and drops toyos-block, step 5 drops netd's library, and the network track's stage 4 no longer conflicts. NOTEs: the ABI issue lists the SYS_DEBUG issue and the small-kernel track; the boot-start exit asks a host test of the mark and the choice and a metal row or, where none can, a guest test of the fatal boot, and its false sentence on refused_claim and pci_function_is_exclusive goes; step 3 checks declared_model_controls; step 1's grep excludes issues/; the Fit line carries the layout rule from step 3; stage 4 waits on the userland-lint issue, whose exit is a src/clippy.rs shape; compile-time assertions and nested arithmetic are constraints; the mixer's timing is re-measured. REMOVEs: ", which is the only question worth asking" and ", so this build system no longer has the flag" (four manifests). Measured with cargo 1.98.1, clippy 0.1.98 (48a229ceae), on scratch crates posted to the pull request: - The review's patch to c6 (an #[expect] on a fn over v[i] and "+ x * x", one on a trait over two indexes): git apply --check 0, cargo build 0, cargo clippy -p c6 0 with no warning; reverted, clean. - The copy of that c6, cargo clippy --message-format=json: 101, every one of 13 findings carries its attribute's reason: mod drivers 5, the inner #![expect] 2, the impl 2, the fn 2, the trait 2. The same under RUSTFLAGS="-D warnings". With #[warn] in place of #[deny] under -D warnings no finding carries its reason: two carry "`-D clippy::...` implied by `-D warnings`" and eleven nothing. - --force-warn of the two lints on c6: 0, 13 warnings, those under each #[expect] included, no unfulfilled_lint_expectations. - c15, every #[expect] over one site and one nested in another: clippy 0; its copy gives five reasons, one finding each. - c18, an #[expect] inside cfg_attr over two indexes: clippy 0; the copy 0 findings; --force-warn 2. - c16: x * x + y * y - 1 and (a + b) * (c + d) are one arithmetic_side_effects finding each; v[i][j] is two indexing_slicing. cargo rustc --lib -- -C overflow-checks=on --emit=mir: 0, one overflow assert per operator, no source spans. - c17 with c14's clippy.toml: disallowed_macros fires on const _: () = assert!(...), const { assert!(...) } and a run-time assert!; clippy::panic passes panic! in a const item and in an inline const block; cargo build 0. git grep -h -E 'const _: \(\) = assert!|const \{ assert!' -- kernel/src | wc -l: 41. - CARGO_PROFILE_DEV_OPT_LEVEL=<n> cargo test -p toyos-mixer, scratch target, twice per level, exit 0 each; libtest's "finished in" for 55 tests: 9.94 s and 9.99 s at 0, 1.00 s and 1.00 s at 2. - cargo test -p <package> -- --list, lines ending ": test", exit 0 each: pcid 6, proclife 34, sched with check 95, xhci 150, gicv3 8, cpuvuln 52 (345); bootmap 43, rootimage 21, blackbox 33, tco 13, quiesce 8 (118); elide 12, logstream 14; manifest 19, swap 7; fat32-check 67; desktop 95; inspect 21; symbols 9. Staying: dma 17, pci 75, ps2 24, userbound 34, acpi 52, transport 17, blockring 19, blockhold 9. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Scratch measurements behind the answers to issuecomment-5931861144 (cargo 1.98.1, clippy 0.1.98 48a229ceae, rustc 1.98.1; edition 2024; one scratch workspace; The review's patch to c6--- a/c6/src/lib.rs
+++ b/c6/src/lib.rs
@@ -17,3 +17,6 @@ impl S {
self.0[j]
}
}
+
+#[expect(clippy::arithmetic_side_effects, clippy::indexing_slicing, reason = "fn")] pub fn f(v: &[u8], i: usize, x: u32) -> u32 { u32::from(v[i]) + x * x }
+#[expect(clippy::indexing_slicing, reason = "trait")] pub trait T { fn a(&self, v: &[u8]) -> u8 { v[0] } fn b(&self, v: &[u8]) -> u8 { v[1] } }The copy that tells one site from severalIn a copy of the crate's sources, every Patched c6, its copy ( c15, every #![deny(clippy::indexing_slicing, clippy::arithmetic_side_effects)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
pub fn f(v: &[u8], i: usize, x: u32) -> u32 {
#[expect(clippy::indexing_slicing, reason = "i < v.len()")]
let b = v[i];
#[expect(clippy::arithmetic_side_effects, reason = "x < 2^16")]
let y = x * x;
#[expect(clippy::arithmetic_side_effects, reason = "y < 2^32 - 255")]
let z = u32::from(b) + y;
z
}
#[expect(clippy::indexing_slicing, reason = "the one index the inner expect leaves")]
pub fn g(v: &[u8; 4], i: usize) -> u8 {
#[expect(clippy::indexing_slicing, reason = "i < 4")]
let a = v[i];
a ^ v[i]
}c18, an #![deny(clippy::indexing_slicing)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
#[cfg_attr(all(), expect(clippy::indexing_slicing, reason = "two sites"))]
pub fn two(v: &[u8]) -> u8 {
v[0] ^ v[1]
}Nested arithmetic (c16)#![deny(clippy::arithmetic_side_effects)]
pub fn one(x: u32, y: u32) -> u32 {
x * x + y * y - 1
}
pub fn two(a: u32, b: u32, c: u32, d: u32) -> u32 {
(a + b) * (c + d)
}
pub fn three(a: u32, b: u32) -> u32 {
let t = a + b;
t * 2
}
pub fn four(v: &[&[u8]], i: usize, j: usize) -> u8 {
v[i][j]
}Compile-time assertions (c17), with c14's
|
|
Round-2 review of CI:
The merge af9fe18 resolves nothing by hand: Earlier BLOCKERs
BLOCKER
NOTE
REMOVE
SEND BACK |
…k merges no crate that reads what a device, a previous boot or a program wrote
The no-panic track's stage 4 gave a service only stage 3's attributes.
Those attributes pass an inner `#![allow(…, reason)]` and an `#[expect]`
on a `fn` over two findings. Stage 3 refuses both with its `--ci host`
step, so a service's exit now names that step as well:
- c4 is an inner `#![allow]` under stage 3's attributes. `cargo clippy`
exits 0. Its copy reports 0 findings and `--force-warn` reports 2
(lib.rs:7, :10), so the step's count refuses it.
- Patched c6's copy puts two findings under the one reason of the `fn`'s
`#[expect]` (issuecomment-5932520362).
The crate track said the no-panic track names the boundary crates. It names
none, so that clause goes. The track now says no step merges an input
boundary into a program or another crate, and lists the ones it keeps.
- `toyos-xhci` leaves step 3, because it decodes a USB device's answers
(`scsi.rs:5-6`, `identity.rs:82-85`).
- `toyos-blackbox` leaves step 4, because it decodes a previous boot's page
(`lib.rs:15`, and `recover` takes its length from the page at `:705`).
- The same test is a crate's own source saying it does not believe what it
reads. It finds four more crates that steps 4 and 5 merged:
- `toyos-swap`: `Request::decode` refuses "the requester's claim"
(`lib.rs:241-244`);
- `toyos-logstream`: whose line a line is is decided "never by its
words", and "no program's bytes" reach a line's head (`lib.rs:6-11`);
- `toyos-mixer`: a client's gain "crossed the trust boundary"
(`gain.rs:8`);
- `toyos-desktop`: a client's rectangle crosses "a trust boundary", and
every verdict on a window request "is an answer to untrusted input, so
none of them is a panic" (`rect.rs:34`, `budget.rs:52-53`).
- So step 4 makes no `toyos-log`, and `toyos-manifest` takes nothing in.
Step 5 moves neither the mixer nor the desktop. The opt-level line goes
with them, since only the mixer's tests needed it.
- `toyos-xhci/sim` stays with xhci, so `kernel/sim` is `toyos-sched/sim`
alone.
Each count is from `cargo test -p <package> -- --list` at 77a8f12, which
exits 0 for every package:
- step 3: pcid 6, proclife 34, sched with `check` 95, gicv3 8 and cpuvuln
52 make 195;
- step 4: bootmap 43, rootimage 21, tco 13 and quiesce 8 make 85, and
fat32-check lists 67;
- step 5: inspect 21;
- the models: toyos-sched-sim 53 and toyos-xhci-sim 46, kernel-loom 53 and
toyos-sched-loom 26, so 79.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Scratch measurements behind the answers to issuecomment-5932882581 (cargo 1.98.1, clippy 0.1.98 48a229ceae, rustc 1.98.1; edition 2024). Posted so the evidence does not live only in a temporary directory. c4 through stage 3's step
#![deny(clippy::indexing_slicing)]
#![forbid(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
pub mod m {
#![allow(clippy::indexing_slicing, reason = "inner")]
pub fn first(v: &[u8]) -> u8 {
v[0]
}
pub fn second(v: &[u8]) -> u8 {
v[1]
}
}c4 holds no The copy's 0 findings against Test counts
Step 3's library is 6 + 34 + 95 + 8 + 52 = 195, and #674
|
|
Round-3 review of CI:
Earlier BLOCKERs
Earlier NOTEs and REMOVE
The four keepsEach reads a program's words, by its own source:
Dropping BLOCKER
NOTE
REMOVE
SEND BACK |
… tier is every crate of this tree it links, and a TCO base word that panics is filed
The third review found step 4 merging `toyos-tco`, which decodes a PCH's
configuration words, and `toyos-bootmap`, which reads firmware's memory map,
into `toyos-boot`. Round 3 had judged a crate by its wording. This round puts
every crate a step moved, merged or deleted to one question about its own
source: does it decode or refuse input from outside its trust? Hardware
registers, firmware tables, disk bytes, network bytes and what another program
sent, a syscall's arguments included, all count. The track now states that
test and moves no crate that meets it.
- Eleven crates meet it and leave every step:
- step 3: `toyos-proclife` refuses a tid the joining program named
(`join.rs:11-13`, `:43`); `toyos-gicv3` walks `GICR_TYPER` words
(`lib.rs:44-61`); `toyos-cpuvuln` decodes CPUID and MSR words
(`lib.rs:48-49`, `:61-83`); `toyos-symbols` bounds every extent an ELF
file declares (`lib.rs:71-77`, `:92-102`);
- step 4: `toyos-bootmap` refuses ranges of firmware's map
(`x86_64.rs:17-25`, `lib.rs:165-167`); `toyos-rootimage` checks the
loader's extent against firmware's map and takes the media's granularity
(`handoff.rs:14-34`, `chunk.rs:33-35`); `toyos-tco` decodes a PCI
function's ids and configuration words (`lib.rs:261-289`);
`toyos-quiesce` parses a log line off a stick (`lib.rs:14-16`,
`:126-129`); `toyos-fat32-check` judges a volume's bytes
(`lib.rs:181-187`);
- step 5: `filepicker-api` refuses the picker's reply by type and by UTF-8
(`lib.rs:75-84`); `toyos-inspect` decodes another owner's snapshot
(`wire.rs:13-15`).
- Seven do not: `toyos-userpin`, `toyos-pcid`, `toyos-sched`, `kernel-loom`,
`toyos-sched-loom`, `toyos-sched-sim` and `toyos-libc-copies`. The
simulator's `replay` decodes a trace, but only one it wrote itself.
- So the kernel's library is `toyos-pcid` and `toyos-sched`: at least 101
tests, 6 and 95 with `check`. Step 4 goes whole. Step 5 keeps
`toyos-libc-copies` alone, and its check names no count: the package lists
14 tests on this AArch64 host, one of them in a module only AArch64 builds.
- Step 2, "Lint userland first", goes. No step moves code into a userland
program now, and the userland lint reads `userland/` alone. Each remaining
move's check says `--clippy` lints what it moved.
- The sentence reconciling the supervisor track before step 5 goes with
step 5.
The no-panic track's stage 4 held a service's own crate and nothing it
links. Tiers 2 to 4 are now processes: a tier holds every crate of this tree
its processes link, and a crate in two tiers is held to the stricter. The
system services are init and every program `system.toml` starts at boot or
marks `service = true`. Stage 4 ends when every crate of this tree a service
links, `toyos` included, is linted under stage 3's attributes and passes
stage 3's step. The step finds them from `system.toml` and `cargo metadata`
over userland's workspace: it walks the normal edges as `src/licence.rs`
does, and keeps the packages whose manifests lie in this repository.
Measured at 75bf096, the nine services' closures name 38 packages of this
tree, and `kernel/Cargo.toml` links none of 27 of them, `toyos` among them.
`--filter-platform x86_64-unknown-toyos` gives the same sets.
The review's NOTE on `toyos-tco/src/lib.rs:284` is filed as a defect. Under
`8086:a0a3`, the 17 base words from `0xFFFF_FFEE` to `0xFFFF_FFFE` overflow
`u32` there, as a host program calling `port` with every `u32` word shows.
q35's row has no such word.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Evidence for the answers to issuecomment-5933706988. Measured at The services' closure
(.packages | map({key: .id, value: .}) | from_entries) as $pkg
| (.resolve.nodes | map({key: .id, value: [.deps[] | select(any(.dep_kinds[]; .kind == null)) | .pkg]}) | from_entries) as $edges
| def intree($id): ($pkg[$id].source == null) and ($pkg[$id].manifest_path | startswith($root + "/"));
def reach($start):
{seen: [$start], todo: [$start]}
| until(.todo | length == 0;
.todo[0] as $cur
| .todo |= .[1:]
| reduce ($edges[$cur] // [])[] as $n (.;
if (.seen | index($n)) then . else .seen += [$n] | .todo += [$n] end))
| .seen;
[ $names[] as $name
| ($pkg | to_entries | map(select(.value.name == $name and intree(.key))) | .[0].key) as $id
| { root: $name,
intree: [reach($id)[] | select(intree(.)) | $pkg[.] | {name, kinds: [.targets[].kind[]] | unique, path: (.manifest_path | ltrimstr($root + "/"))}] | sort_by(.name),
thirdparty: [reach($id)[] | select(intree(.) | not)] | length } ]Each service's in-tree closure, every The kernel's, for comparison:
|
| package | tests |
|---|---|
toyos-pcid |
6 |
toyos-sched --features check |
95 |
kernel-loom |
53 |
toyos-sched-loom |
26 |
toyos-sched-sim |
53 |
toyos-libc-copies |
14, long_double::strtold_widens_as_compiler_builtins_does among them, whose module is #[cfg(all(test, target_arch = "aarch64"))] |
|
Round-4 review of
CI: Net lines (
Earlier BLOCKERs
Earlier NOTEs and REMOVE
The 18 verdictsI read 14 against their source:
By the test the track states, 17 of the 18 stand. The details:
|
Two hunks conflict, and each keeps both sides' changes. - `implementer.md`: this branch drops the ABI-brief sentence, and #674's dependency sentence replaces "No new dependency.". - `reviewer.md`'s Fit line: this branch's two BLOCKER clauses stay, and #674's dependency clause replaces "No new dependency or fetch.". The rest of #674 merged clean. `git diff origin/main -- .claude userland/CLAUDE.md` shows only this branch's own changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…-panic track, cut to a screen; proclife moves with the scheduler, and five single-consumer crates go under their consumer The no-panic track, `issues/kernel/a-panic-is-never-an-accident.md`, goes from 104 lines to 54. - The loader is tier 2. It is not a process, yet `bootloader/src/watchdog.rs` decodes PCI configuration words and checks the MCFG's word against firmware's memory map. Tiers 2 to 4 are now programs. Stage 1 moves an input boundary out of the loader as well, and stage 3 ends with `bootloader/src/main.rs` and every crate of this tree its manifest links. The loader's `--clippy` shapes exist for both architectures. - The services are read from the three modes' configs, as `build::shipped` reads them, and every boot start counts. That adds `console`, which the console mode starts and which owns the framebuffer as the compositor does, and `toybox`, which the diag mode starts with nobody asking. - Both REMOVEs are applied: the clause restating that tier 3 holds `toyos`, and the sentence on registry and git packages. - Cut to a screen. These go: "Today" and its counts, the rationale clauses, the constraints, the stage-3 step's copy mechanism and stage 4's metadata walk. The tiers, the set, what the set does not see, and every stage's exit stay. `git log -p` of the file keeps what went. The crate track, `issues/build/code-used-by-one-program-lives-in-that-program.md`: - The boundary test now reads "decodes a word from outside its trust, or bounds it by its form", and a lookup of a key a program named is neither. `toyos-proclife`'s only refusal is `ok_or` on `threads.get(tid)` (`join.rs:42-43`, `kernel/src/process.rs:382-384`), and the crate indexes only in its interleaving model. So it moves into the kernel's library with the scheduler. - The library's floor is 135 tests. `cargo test -p` lists 6 for `toyos-pcid`, 95 for `toyos-sched` with `check`, and 34 for `toyos-proclife`, each exit 0. Re-read against their sources, the other 17 verdicts stand under the new test. - "moves" goes, so a step may move a boundary but never merge one. - Step 4 puts each crate under its consumer as a crate of its own. Measured with jq over `cargo metadata --locked --offline` of the root, kernel, loader, userland and `toyos` workspaces, each exit 0: - `toyos-mixer` is linked only by soundd; - `toyos-desktop` only by the compositor; - `toyos-ps2` and `toyos-gicv3` only by the kernel; - `toyos-xhci` by the kernel, its own sim, and the harness's dev edge. - `toyos-fat32-check` is not single-consumer. `toyos-build` links it (`image::certify`, `src/metal.rs`), and `toyos-fat32`'s tests dev-depend on it. It goes to `toyos-fat32/check/` on the one-subject rule, as the step says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Round 5's commands, outputs and exits, at 42f3fb5. Host gate. Consumers. It exited 0 and printed every local crate that has a local dependent, as the count, the crate, and each dependent with its edge: A grep of every tracked manifest outside The library's floor of 135.
Stage 1's "its own copy". Lines. |
|
Round-5 review of CI: Net lines (
The merge
Earlier findingsNo BLOCKER was open.
The PR body
For the rulings (not findings)
BLOCKERNone. NOTE
REMOVE
LAND AFTER NAMED CHANGES |
…owns`, step 4 moves every crate with one consumer, and two clippy limits return The no-panic track, `issues/kernel/a-panic-is-never-an-accident.md`: - A system service is a program whose manifest declares `exempt.owns`, read as `src/userlandhost.rs` reads it. Every other program that gate reads is an app, `toybox` and the `exempt.manages` tools too. The config marker could not be the rule: `fsd` is a boot start in all three configs and none marks it `service = true`. `cargo metadata --no-deps --offline` over every package manifest, exit 0 each, reads `exempt.owns` from blockd, compositor, console, fsd, init, logd, netd and soundd, and `exempt.manages` from inspect, swap and update. sshd and filepicker, which the shipped config marks `service = true`, declare nothing, so they are apps. - Two measured limits return, each at the stage whose exit it bounds. Stage 1: `disallowed_methods` and `disallowed_macros` read the nearest `clippy.toml` alone. Stage 3: one `arithmetic_side_effects` finding spans a whole expression. clippy 0.1.98 shows both on scratch crates. A crate with no `clippy.toml` of its own, under a directory whose file disallows `core::assert`, warns on `assert!`. One with an empty `clippy.toml` of its own does not. `x * x + y * y - 1` draws one warning. - "the three" goes, with the boot-start rule it counted. The crate track, `issues/build/code-used-by-one-program-lives-in-that-program.md`: - Step 4 states its rule and how it is measured, not a list. Every crate of this tree with exactly one consumer moves under it, as a crate of its own. A consumer is a package whose manifest names the crate as a dependency of any kind, under any `cfg`. They are counted over every manifest `git ls-files '*Cargo.toml'` lists, excluded packages and `tests/` included. `cargo metadata --no-deps --offline` ran on each of the 98 package manifests, exit 0 each. Counted over their path dependencies, the rule yields `terminal`, `tls-dep`, `toyos-desktop`, `toyos-dma`, `toyos-gicv3`, `toyos-mdns`, `toyos-mixer`, `toyos-net-udp`, `toyos-pci`, `toyos-pcid`, `toyos-proclife`, `toyos-ps2` and `toyos-transport`. `git grep -F <name> -- '*Cargo.toml'` finds exactly one dependency line for each. `toyos-xhci` has three consumers: the kernel, its sim and the harness's dev edge. So does `toyos-i219`: netd, the harness's dev edge and `tests/toyos-rust-tests`. `toyos-userbound` has two, and so does `blockd`. - The step names what must change with a move under a userland program: `src/userlandhost.rs`'s survey lists every test of a nested crate as an escape, and `every_userland_test_is_in_the_gate` reds `host` on one. - `toyos-fat32-check` has two consumers and keeps a step of its own, step 5. - The exit counts step 4's rule, since that step no longer names a directory. - "the feature three scheduler tests need" loses its count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Round 6's commands, outputs and exits, at d974223. Host gate. Merge. After Every package's metadata. Each exited 0, and the dumps hold 98 distinct packages, one per manifest, The services. Over the dumps: It exited 0 and printed: All eight The consumers. The dumps were merged into one list, one entry per manifest, exit 0: Every dependency carrying a It exited 0 and printed every tree crate that some tree package names, with its count and each consumer's edge:
A search of every The two clippy limits. clippy 0.1.98 (
Lines. |
…service = true` or whose manifest declares `exempt.owns`, and a shipped program is its own consumer The no-panic track's services tier is now the union of two classes. Round 6's rule, a program whose manifest declares `exempt.owns`, made `sshd` and `filepicker` apps, though the shipped config marks both `service = true` and `sshd` takes untrusted input from the network. The config marker alone misses `fsd`, which starts at boot without it. Read as `build::shipped` reads the three modes and as `src/userlandhost.rs` reads the manifests, the rule yields ten services today: blockd, compositor, console, filepicker, fsd, init, logd, netd, soundd and sshd. Every other shipped program is an app: calc, doom, editor, files, host, input-test, inspect, paint, pkg, proctest, shell, snake, swap, terminal, toybox, toyos-ld and update. The crate track's step 4 counts a crate the images ship as a program of its own as its own consumer, so `terminal`, which console links, has two consumers and stays where it is. Over the 98 package manifests `git ls-files '*Cargo.toml'` lists, twelve crates have exactly one consumer, each of them another package: `toyos-dma`, `toyos-gicv3`, `toyos-pci`, `toyos-pcid`, `toyos-proclife` and `toyos-ps2` (the kernel), `toyos-desktop` (compositor), `toyos-mixer` (soundd), `toyos-mdns` (netd), `toyos-net-udp` (`toyos-dhcp`'s tests), `toyos-transport` (`toyos-blockring`) and `tls-dep` (`tls-multi-crate`, already beneath it). A shipped program that no package names is its own one consumer, so it moves nowhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Round 7's commands, outputs and exits, at 7131598. Host gate. Merge. After The services. The worktree's absolute path is written The reader's whole output at 7131598, then its source
[package]
name = "svc-measure"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
toyos-build = { path = "<worktree>" }
toml = "0.8"
serde = { version = "1", features = ["derive"] }
[workspace]
//! The services rule of `issues/kernel/a-panic-is-never-an-accident.md`, measured:
//! a shipped program is a service when any mode's config marks its row
//! `service = true`, or its manifest declares `exempt.owns`.
//!
//! The program set is `toyos_build::build::shipped` itself; the host verdict is
//! `toyos_build::userlandhost::programs` itself. `service` is private to
//! `src/build.rs`, so it is read here with the same serde shape
//! `ProgramConfig` has (`rename_all = "kebab-case"`, `default`), and a row's
//! directory with `ProgramConfig::crate_dir`'s rule.
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
use serde::Deserialize;
use toyos_build::userlandhost::Host;
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
struct Config {
#[serde(default)]
programs: BTreeMap<String, Row>,
}
#[derive(Deserialize, Default)]
#[serde(default, rename_all = "kebab-case")]
struct Row {
path: Option<String>,
service: bool,
}
fn manifest(dir: &Path) -> toml::Value {
let text = std::fs::read_to_string(dir.join("Cargo.toml")).expect("read manifest");
text.parse().expect("manifest is TOML")
}
fn main() {
let arg = std::env::args().nth(1).expect("usage: svc-measure <root>");
let root = std::fs::canonicalize(arg).expect("canonical root");
let shipped = toyos_build::build::shipped(&root).expect("build::shipped");
let program_dirs: BTreeSet<PathBuf> = shipped.programs.iter().map(|(d, _)| d.clone()).collect();
println!("build::shipped: {} (dir, features) programs, {} distinct dirs", shipped.programs.len(), program_dirs.len());
for (dir, features) in &shipped.programs {
println!(" shipped program {} {:?}", dir.strip_prefix(&root).unwrap().display(), features);
}
// Every row any mode's config marks `service = true`, by crate directory.
let mut marked: BTreeMap<PathBuf, Vec<String>> = BTreeMap::new();
for mode in ["", "diag", "console"] {
let at = root.join(mode).join("system.toml");
let config: Config =
toml::from_str(&std::fs::read_to_string(&at).expect("read config")).expect("config");
for (name, row) in &config.programs {
println!(
" row {}:{name} path={:?} service={}",
at.strip_prefix(&root).unwrap().display(),
row.path,
row.service
);
if row.service {
let dir = match &row.path {
Some(p) => root.join(p),
None => root.join("userland").join(name),
};
marked
.entry(dir)
.or_default()
.push(format!("{}", at.strip_prefix(&root).unwrap().display()));
}
}
}
for dir in marked.keys() {
assert!(program_dirs.contains(dir), "{} is marked service and not shipped", dir.display());
}
// The real host reader's verdict for every shipped program.
let hosts = toyos_build::userlandhost::programs(&root).expect("userlandhost::programs");
let mut services = BTreeSet::new();
let mut apps = BTreeSet::new();
for p in &hosts {
let dir = root.join(&p.dir);
let m = manifest(&dir);
let name = m["package"]["name"].as_str().expect("package name").to_string();
let exempt = m
.get("package")
.and_then(|p| p.get("metadata"))
.and_then(|m| m.get("toyos"))
.and_then(|t| t.get("host"))
.and_then(|h| h.get("exempt"))
.and_then(|e| e.as_table())
.map(|t| t.keys().cloned().collect::<Vec<_>>());
let owns = exempt.as_ref().is_some_and(|k| k == &["owns".to_string()]);
let manages = exempt.as_ref().is_some_and(|k| k == &["manages".to_string()]);
// The real reader agrees: an `exempt` table is `Host::Exempt`, else an app.
assert_eq!(exempt.is_some(), p.host == Host::Exempt, "{name}: reader disagrees");
let by_marker = marked.get(&dir);
let declared = match (&p.host, owns, manages) {
(Host::Exempt, true, false) => "exempt.owns".to_string(),
(Host::Exempt, false, true) => "exempt.manages".to_string(),
(Host::App(on), false, false) if on.is_empty() => "app, nothing declared".to_string(),
(Host::App(on), false, false) => {
format!("app, fails on {:?}", on.iter().map(|o| o.name()).collect::<Vec<_>>())
}
other => panic!("{name}: unexpected {other:?}"),
};
println!(
" program {name} ({}) features={:?}: {declared}; service = true in {:?}",
p.dir, p.features, by_marker
);
if owns || by_marker.is_some() {
services.insert(name);
} else {
apps.insert(name);
}
}
let both: BTreeSet<_> = services.iter().cloned().collect();
println!("services ({}): {}", both.len(), both.into_iter().collect::<Vec<_>>().join(", "));
println!("apps ({}): {}", apps.len(), apps.into_iter().collect::<Vec<_>>().join(", "));
for dir in &program_dirs {
println!(" shipped manifest {}", dir.join("Cargo.toml").display());
}
}The consumers. Each exited 0, at d974223 and again at 7131598, and No dependency names a tree package without a path. The dependencies that carry no path and share a tree package's name, or that name a ToyOSOrg git source, are three fork edges, none of them to a tree package: No tree edge sits under a The count is now taken once per package rather than once per edge. Over these dumps that changes no number from round 6's: # Step 4's count: a tree crate's consumers are the tree packages that name it as
# a dependency of any kind under any cfg, counted once per package; a crate the
# images ship as a program of its own counts as its own consumer.
($shipped[0]) as $ship
| (map({key: .manifest_path, value: .name}) | from_entries) as $byman
| [ .[] as $p | $p.deps[] | select(.path != null)
| {dep: (.path + "/Cargo.toml"), user: $p.manifest_path,
edge: "\($p.name)[\(.kind // "normal")\(if .target then " " + .target else "" end)]"} ] as $edges
| .[] | .manifest_path as $m
| ([$edges[] | select(.dep == $m)]) as $in
| ([$in[].user] | unique | length) as $users
| (if any($ship[]; . == $m) then 1 else 0 end) as $self
| "\($users + $self)\t\($byman[$m])\tpackages=\($users)\tshipped-program=\($self)\t\([$in[].edge] | unique | join(", "))"
Twelve crates have exactly one consumer, and it is another package: Lines. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Three modify/delete conflicts, each hunk of this branch's side accounted for: - tests/toyos-rust-tests/src/bin/log_hold.rs, deleted by 520c0d1: the one hunk moved its 192 records from syscall 26 to `SYS_DEBUG` `LOG_PATTERNED`. The binary and `log_program_line_after_its_records` are gone, so it goes. - tests/common/origin.rs, deleted by 520c0d1: `staged_job`, `one_job` on it, `PATTERNED` in `RETIRED`'s place and `after_records` on the test kernel with its per-index count all served that one test. They go. - issues/build/no-device-class-answers-for-a-block-device.md, deleted on main: the one hunk dropped "(3 and 4 are retired.)". It goes. Content conflicts: - tests/common/logstream.rs and tests/common/qemu.rs are main's: this branch's `stage_on_test_kernel`, `write_staged` and `build_test_kernel_image` had `origin::after_records` as their only caller. - issues/build/the-boot-census-guesses-a-staged-images-kernel.md, which this branch filed against `build_test_kernel_image` and a staged `BootOptions::boot_image`, goes: main has neither. - CLAUDE.md and .claude/agents/reviewer.md are main's: #673 landed this branch's half of both. - issues/kernel/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md is main's: this branch's hunk edited stage 0, which #642 landed and deleted. - issues/kernel/the-capability-end-state-is-twelve-answers.md: main deleted the sentence this branch's first hunk edited; the second hunk, which drops "85 `SYS_LISTEN` and 87 `SYS_CONNECT` are retired numbers", is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
Six open pull requests of rules and records land here as one: #666, #665, #645, #613, #604 and #646, each merged in that order with
git merge, with #636's firmware clause. Landing this closes all six. RootCLAUDE.mdis 16076 bytes, against main's 16077.Not high-risk: prose, issue files and comments, and one licence row's text in
src/licence.rs. No code path changes.What lands
The ABI is free to change, and the kernel takes on only what userland cannot (The ABI is free to change, and the kernel takes on only what userland cannot #666).
CLAUDE.md's Kernel and Syscall ABI lines say so.implementer.mdasks whether userland can own a kernel addition, and drops the ABI-brief sentence.reviewer.md's Fit line makes each of these a BLOCKER: a kernel addition userland could own, and a design made worse to spare the ABI.reviewer.md's "What no gate reads" retires its BLOCKER on a diff that declares a retired ABI name, or reuses a retired syscall,SYS_DEBUGaction or inbox op number.issues/design-debt/the-abi-still-keeps-retired-syscall-numbers.mdrecords what still keeps retired numbers, and every plan that still retires one.No panic, by tier (issues: a panic is never an accident, the owner's rule as a track, not yet enforced; seven stale crafted-ELF clauses go #665), the track
issues/kernel/a-panic-is-never-an-accident.md.#[expect]of its own at its site.service = true, or whose manifest declaresexempt.owns. Every other shipped program is an app,toybox,terminaland theexempt.managestools included. Today that makes ten services: blockd, compositor, console, filepicker, fsd, init, logd, netd, soundd and sshd.src/build.rs.The owner's 2026-09-30 rulings (The owner's rulings of 2026-09-30 written where they govern #645), written into the child-process, small-kernel and supervisor tracks and into two design-debt issues. Three question files are deleted, and
doom.jpg's licence row says it is the owner's own screenshot.CPU microcode is its own case. Vendor firmware a device or CPU verifies by its maker's signature may be shipped: pinned by version and hash, redistributable unmodified, and recorded in
NOTICE.Operating lessons (Place operating lessons in the role files and the ARM64 ruling in CLAUDE.md #613):
/tmp.Code used by one program lives in that program (Track: code used by one program lives in that program #604), the track
issues/build/code-used-by-one-program-lives-in-that-program.md. An input boundary stays a crate of its own: a step may move one but never merge it.toyos-userpingoes.toyos-pcid,toyos-proclifeandtoyos-schedbecome the kernel's library, with the loom and sim crates underkernel/.toyos-libc-copiesmoves to the tests.tests/included, and a crate the images ship as a program of its own counts as its own consumer.toyos-fat32-checkgoes undertoyos-fat32/, in a step of its own.With it land
issues/build/the-pcid-negative-control-runs-nowhere.md, which its step 2 closes, andissues/build/userland-programs-are-never-linted.md, which the no-panic track's stage 4 waits on.Two builds of one LLVM key differ in their bytes (File: two builds of one LLVM key differ in their bytes, a defect M4 waits on #646): a defect, with an exit a host test reaches.
A TCO base word near all-ones panics the loader and the kernel: a defect,
issues/hardware/a-tco-base-word-near-all-ones-panics-the-loader-and-the-kernel.md.What was dropped
From The ABI is free to change, and the kernel takes on only what userland cannot #666: the Kernel line's list of kernel jobs. The rule alone says what the kernel takes on, and the Capabilities paragraph covers files.
From issues: a panic is never an accident, the owner's rule as a track, not yet enforced; seven stale crafted-ELF clauses go #665: the track's counts of today's findings, its rationale, and its constraints but what the set does not see and which
clippy.tomlthedisallowed_*lints read. They were cut so the track fits a screen; the file's history keeps them.From The owner's rulings of 2026-09-30 written where they govern #645: its microcode files. toyos-microcode: Intel microcode update files validated and matched to a CPU, pure, and no input can panic it; the kernel step's design in its issue #653 carries all three: the defect that replaces the question file, the question file's deletion, and the security track's citation.
From Place operating lessons in the role files and the ARM64 ruling in CLAUDE.md #613:
rgrule, measured false in the agents' shell.From Track: code used by one program lives in that program #604:
toyos-boot,toyos-log,toyos-block, andtoyos-manifesttaking intoyos-swap;toyos-dma,-pci,-userbound,-cpuvulnandtoyos-symbols' name budget into the kernel.Each of those took in a crate whose source decodes a word from outside its trust, or bounds it by its form. The no-panic track forbids tier 1 per crate. Its "lint userland first" step, its opt-level line, and its reconciliation of the supervisor and network tracks went with them.
From File: two builds of one LLVM key differ in their bytes, a defect M4 waits on #646:
src/llvm.rskey builds.Until #653 lands
issues/kernel/whether-the-kernel-loads-cpu-microcode-is-the-owners.md:9-10say that rootCLAUDE.mdadmits no CPU microcode. This landing makes that false, and #653 deletes the file. If #653 lands first, there is no such window.Gates
cargo run -- --ci hostat 7131598: EXIT=0, "[ci] Host: 59 step(s), all green". Every FAILED line in its log is a negative control's red, which that control's step demands.Round 5's commands, outputs and exits are in issuecomment-5935427621, round 6's in issuecomment-5936162566, and round 7's in issuecomment-5936487478.
Unsure
Step 4's rule, measured at 7131598 over every package manifest the tree tracks, yields these crates, each with one consumer:
toyos-dma,toyos-gicv3,toyos-pciandtoyos-ps2, under the kernel, andtoyos-pcidandtoyos-proclife, which step 2 takes into the kernel's library;toyos-desktopunder the compositor,toyos-mixerunder soundd andtoyos-mdnsunder netd;toyos-net-udpundertoyos-dhcp, whose tests alone use it, andtoyos-transportundertoyos-blockring;tls-dep, already undertests/toyos-rust-tests/tls-multi-crate/.terminalhas two consumers: console links it, and the images ship it as a program of its own. More than one package links each of these:toyos-xhci(the kernel, its sim and the harness's dev edge),toyos-i219(netd, the harness's dev edge andtests/toyos-rust-tests),toyos-userbound(the kernel and the harness's dev edge) andblockd(fsd andtests/toyos-rust-tests).toyos-fat32-checkhas two consumers: the build links it, andtoyos-fat32's tests dev-depend on it. Step 5 moves it on the one-subject rule.🤖 Generated with Claude Code
https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L