Repository navigation
Worktrees and the primary's sync are git commands in the role prompts, a sysroot placement sweeps its store, and the prompts take the owner's decisions - #678
Conversation
…ts take the owner's rulings
`--worktree add|list|remove` and `--sync` go, with `src/worktree.rs` (838
lines), `src/sync.rs` (263), their flags, dispatch and tests. What a build
needs stays in the build: `toolchain::owner` sends a linked worktree's
compiler reads to the primary and never runs `ensure_submodules`, a bootstrap
or the rustup link there, and `sysroot::fork_checkout` makes its `rust/` a
git worktree of the primary's fork repository on first build. Those two are
why a plain `git worktree add` is safe: the clone of the fork's history, the
second toolchain and the stolen rustup link come only from a `git clone` or a
`git submodule` in a linked worktree, which root `CLAUDE.md` now forbids by
name.
The recipe, run in the primary checkout:
make: git fetch origin && git worktree add -b wt/<name> ../<name> origin/main
resume: git worktree add ../<name> wt/<name>
remove: git -C ../<name> status --porcelain --ignore-submodules=none (prints nothing)
rm -rf ../<name> && git worktree prune && git -C rust worktree prune &&
git -C rust/library/backtrace worktree prune && git branch -d wt/<name>
sync: git pull --ff-only origin main
`rm -rf` and three prunes rather than `git worktree remove`: a worktree's
fork checkout and its `library/backtrace` are worktrees of the primary's, git
refuses to remove a worktree holding a populated submodule unless forced, and
a forced removal of a path deeper than PATH_MAX exits 255 after unregistering
it, leaving the directory (measured on a fixture; `rm -rf` of the remainder
exits 0). The status check is the guard on uncommitted work; `git branch -d`
refuses a branch that is not pushed.
The sweep `--worktree remove` ran moves into the build: sysroot and
freestanding placements go through `keystore::made`, as compiler and LLVM
placements already did, so every placement removes the products no
registered worktree records and nobody holds. A recipe step could not do it
without a command of the build system's own, because only the build reads
the records and takes the keys' locks. `a_sysroot_is_whole_or_it_is_made_again`
now asserts a placement takes an orphan; reverting `held` to
`buildlock::keyed_made` reds it (exit 101).
`remove_tree` moves next to its callers in `src/sysroot.rs`, `sync::git` to
the crate root for `ci`, `sdkversion` and `release`.
The prompts take the owner's rulings: a rule a reader can check lives in a
prompt and code enforces only what reading cannot see; nothing a type refuses
is tested; tooling is code, added only for what a sentence cannot do; agents
run their own guest tests and the T14 alone is the orchestrator's; a
high-risk change names a negative control only where a defect would land
unseen and an oracle where one exists; agents get the model the owner names;
the orchestrator is the owner's assistant, edits only trivial text and lands
on LAND plus green CI. `CLAUDE.md` does not grow (16076 -> 15745 bytes).
Closes sync-from-a-worktree-never-moves-main-because-the-primary-reads-dirty
(the recipe moved a scratch clone's main with ` M rust`) and
worktree-remove-leaves-wt-branch-behind-so-the-name-is-refused-later (the
recipe deletes the branch, and the refusal is gone). Opens the track
issues/build/the-workflow-machinery-becomes-agent-instructions.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Negative control for the sweep moved into the build: the whole move reverted at --- a/src/sysroot.rs
+++ b/src/sysroot.rs
@@ -512,8 +512,7 @@ fn unfinished(dir: &Path) -> Option<String> {
/// The sysroot `key` names at `dir`, recorded as `root`'s, made by `make` if
/// nobody has made it, and held in use for as long as the returned guard lives.
fn held(root: &Path, key: &Key, dir: &Path, make: impl FnMut()) -> Guard {
- let store = dir.parent().expect("a sysroot is a directory of its store");
- keystore::made(root, Keyed::Sysroot, store, key, || unfinished(dir), make)
+ buildlock::keyed_made(root, Keyed::Sysroot, key, || unfinished(dir), make)
}
/// The sysroot this worktree's sources name, made if nobody has made it, and |
|
CI: BLOCKER
NOTE
REMOVE
SEND BACK |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
… one git runner, one removal Round 1's first BLOCKER: `TestBuild::begin` and the harness's `c_sysroot` dropped the `Sysroot`, and its `_using` guard with it, while they kept compiling against its directory, and every placement now sweeps any key nobody holds. `Sysroot`'s directory is private and lent only by `Sysroot::dir`. `GuestEnv` owns the `Sysroot`, so `TestBuild`, `shipped_parts` and `build_test_parts` hold it for as long as they build; the kernel build borrows it from a scoped thread instead of a clone; the harness's `OnceLock` keeps the `Sysroot` itself, held until the process ends. Two of round 1's NOTEs: - `crate::git` was a second git runner beside `sysroot::git_try`. It goes, and its four callers read through `sysroot::git_out`; `release::manifest` stops returning a `Result` nothing in it can fail. - `sysroot::remove`, `sysroot::remove_tree` and `keystore::remove` were three removals of a build product. `keystore::remove` is the one left: a file, or a directory read-only or not, outlasting a writer that adds a file while it runs, and a name already gone is removed. A second sweeper of one store meets exactly that once the first has taken a key's names, which panicked on the stat before. The switch test makes a removal fail with a read-only parent instead of a read-only child, since a removal now gives back the write permission of what it removes. The bare-word "sync" clause in `src/sysroot.rs`'s header goes (REMOVE). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…e decisions Round 1's second BLOCKER: this branch's track restated `issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md`, an assigned track. Its lock stage and its gate stage join that track as two of its bullets, `src/keystore.rs` beside `src/buildlock.rs`, each with its exit; its line counts, its first stage (this branch) and its empty fourth go, and so does the file. Nothing cited it. Root `CLAUDE.md`, `orchestrator.md`, `implementer.md` and `reviewer.md` are the read-only reviewer's proposals with the owner's decisions of 2026-10-01 applied over them: - branches stay drafts through their rounds; the orchestrator marks one ready and arms it on LAND, or batches several, which closes `issues/build/who-arms-auto-merge-has-two-answers.md`; - NOT READY FOR REVIEW goes, and missing evidence is a BLOCKER; - LAND AFTER NAMED CHANGES is one fix round and landing, with no re-review; - "deleted, never corrected" binds source comments and docs; bodies, issues and prompts are records kept true; - a ToyOS-only app is one whose job exists only on ToyOS, and "system service" stays the panic track's term; - an implementer makes and resumes its worktree and checks it clean before it reports, the orchestrator removes it and syncs the primary, and root keeps only why a worktree is never a `git clone` and never runs `git submodule`; - "tooling comes first" goes; - `.claude/agents/upstreamer.md` goes, with its `.gitignore` line; - the orchestrator edits a pull request's description and comments, nothing else; - a `src/clippy.rs` shape is read, never proven by a planted mutation; - guest suites run side by side, and a red seen only under load is a defect recorded with the host's load. Root keeps every rule whose breach no role file could undo: personal data and the User-Agent, history, `main`, `git clone` and `git submodule`, the T14, and another agent's process. `orchestrator.md` loses its `tools:` line, so the main session keeps every tool, and every agent gets a type as well as a model. The subdirectory files take the clear findings and shrink: the kernel's caveats name AArch64's files, label the direction flag x86 and drop the spinlock count; userland's portability rule moves to root, its POSIX line and stale filepicker note go (`c3c42e137` fixed that violation); tests' sleep caveat stops saying re-run, the T14's CI-container clause goes, and the TCG caveats are true of the HVF and KVM hosts; `src/CLAUDE.md` drops the boot modes, the locks it restated and both REMOVE lines, points at the lock header and the track, makes the std type-check portable, and its hosted-runner rule moves into `reviewer.md`'s Arrivals; `issues/README.md` drops its history and its stale or contradicting lines; the PR template agrees with `implementer.md`; the fork example clones `ToyOSOrg/cpal`. Citations of the lines that moved follow them, and the Windows issue's corrected counts are deleted (REMOVE). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Round 2 gate logs at
The build system's
|
|
Round 2, at f325be7. Evidence: issuecomment-5940391731: Round 1
Checked, nothing found:
BLOCKER
NOTE
REMOVE
SEND BACK |
…ce and docs leave a citation uncorrected Applies the round-2 re-review of #678 (issuecomment-5940927376). BLOCKER, reviewer.md "Prose": the sentence that made a wrong line number, count, date or citation never a send-back and never corrected now binds source comments and docs alone, as root CLAUDE.md's "Prose" does; a record (a pull request body, an issue, a prompt) is kept true. Its heading, "Prose is removed, never reviewed", said the same of records, and is now "Prose". BLOCKER, reviewer.md "Evidence": a missing guest exit code was a BLOCKER only for a test the branch adds, and no guest boots before main: ci.yml runs `host` alone, and guests run nightly. It is now a BLOCKER for every guest test the change reaches. NOTE, the T14 handoff: implementer.md told an agent to build a metal row's image while root CLAUDE.md barred `--metal`, and the harness builds a row's images only under `--metal`. `--metal --metal-readback <dir>` builds them, writes `<dir>/request.txt` and touches no machine (src/testargs.rs, tests/common/metal.rs). Root now bars `--metal` without `--metal-readback`, implementer.md names the staging command, and the report line and orchestrator.md both carry `<dir>/request.txt`, where one named an image and the other a request file. NOTE, orchestrator.md: a metal mutation loop is a measurement, not an edit, so the loop no longer contradicts "you edit only a pull request's description and comments". NOTE: the hosted-rustc issue cites `env.sysroot.primary_compiler`, where round 2 moved it. REMOVE: implementer.md's "CI capacity is limited:", compile.rs's count of C programs, the Windows issue's undated error list, and the tooling track's rationale clause. The Windows issue also loses the paragraph after the list: its "every other crate" meant every crate but the list's, and the `#[cfg(unix)]` it places at src/ci.rs:489 is in neither main nor this tree (`git grep -F 'cfg(unix)' <rev> -- src` exits 1 on both). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Round 3 gate logs at
The build system's
Negative control for the sysroot sweep, re-run at The green arm, The mutated tree's build, The red arm, the same test under the patch. Its first panic is the refusal the test itself asserts (src/sysroot.rs:1356); the red is the orphan assertion, src/sysroot.rs:1370 on the clean tree and :1369 under the patch, which removes a line above it: |
|
Orchestrator's run at |
|
Round 3, at 3c2cd64. Evidence at this head: issuecomment-5941266209 — Round 2
Checked, nothing found:
BLOCKER
NOTE
REMOVE
SEND BACK |
`cargo test -- --metal ...` hands `--metal` to every test binary of the root package. The libtest ones refuse a flag they do not know before the harness starts (`parse_opts` in library/test/src/cli.rs, exit 101 in lib.rs's `test_main_inner`), so the command staged nothing. Root `CLAUDE.md`, `implementer.md`, `orchestrator.md` and the process-memory track's `copy_cost` A/B now spell it `cargo test --test toyos-build -- --metal ...`, as `suite_args` in src/ci.rs does. The bench paragraph of `orchestrator.md` is rewrapped at 100 columns around the longer command, with no other word moved. The Windows issue's last sentence loses "and it decides two of the errors": the error list it counted went in round 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Round 4 gate logs at
The build system's The bare spelling, The corrected spelling, |
Three files conflicted or needed adapting. .claude/agents/reviewer.md: main's text is taken whole, and this branch's Caches bullet is kept, between "What no gate reads" and "Growth". The two sentences this branch added to the Tests bullet are dropped, because main now states both in its own words: "Rank every finding" names no mutation a type refuses or a reader of the diff catches, and "Growth" sends back a new gate, check, lock or test that guards what a reader can check. The round 10 BLOCKER was against the second of those sentences, which this branch no longer adds. src/ci.rs: both imports are kept, this branch's `cicache` and main's `sysroot::git_out`. src/cicache.rs: main deleted `src/sync.rs`, and with it `sync::git`. The seal reads HEAD through `sysroot::git_out`, as main's `ci::publish` now does, and trims it; a git that cannot answer panics instead of returning the refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
#678 (de5f63c) restructured the review prompt, deleted src/sync.rs and src/worktree.rs, made a Sysroot owned by what compiles against it, and swept the sysroot stores at each placement. #669 (74a2e70) landed the host cache: src/cicache.rs, `--ci seal`, and the review prompt's Caches. Resolved by hand: - .claude/agents/reviewer.md: main's text whole, with this branch's six Workflows rules after Caches. Caches opened "Each cache has one writer, a nightly.yml job"; toolchain.yml's `build` saves the toolchain's layers from three workflows, so that sentence is now the host cache's alone. - .github/workflows/ci.yml: main's header comment said "no guest" and goes; the host job is main's, the toolchain and guest jobs this branch's. - src/ci.rs: main's `seal` job beside this branch's `toolchain`, `bootstrap` and `release`; five workflow files. - src/release.rs: this branch's module; `sync::git` is gone, so its four git reads are `sysroot::git_out`, as main's `publish` reads them. - src/build.rs, tests/common/compile.rs: main's owned Sysroot, with this branch's `hosted_rustc` argument to `toolchain::ensure`. - src/llvm.rs: main's unconditional `keystore::remove`, this branch's `keep`. - issues/build/the-build-runs-host-tools-outside-rust-and-qemu.md: main's git rows less src/worktree.rs and src/sync.rs, with this branch's submodule callers and "CI's containers". What the merge makes false, and so changes with it: - CLAUDE.md said "Guests run nightly."; it says where they run now. - nightly.yml's guest cache is gone with the jobs that carried it, so issues/build/the-guest-cache-is-read-by-mtime-and-its-writer-restores- before-it-saves.md is deleted, src/cicache.rs's LIMIT no longer names a guest entry, and the host-cache limit issue sums two host entries beside the toolchain's layers (918,708,556 B a set, run 36934214557's saves) where it summed them beside guest entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
#660 cut the guest suite to what no cheaper tier reaches and moved the shared boot to the T14; #678 rewrote the role prompts and the worktree commands. Conflicts, hunk by hunk: - `tests/toyos.rs`: main's harness, with this branch's registrations re-made in its shape. `process_tree` was a QEMU machine test on `tests/proctreecase`; it is now a `METAL` row on that config (`PROCTREECASE`), its binary on `RUST_SKIP`, and its judge (`process_tree`) reads off the stick what the QEMU arm read off the console: the job's exit, the loader's refusal of `/system/bin/no_such_program` once per B, and one depth refusal naming 65. `spawn_lands_claimed` stays an `ACTUATOR_TESTS` member, so it rides the shared boot on the kernel that carries `SYS_DEBUG`. The `Sched` and `CARRIES` rows have no table left to sit in. - `src/build.rs`: main's list of boot configs, plus `tests/proctreecase`. - The child-process track: main's text, with stage 4 deleted as this branch deletes it. Main's stage 6 gained "A quit reaches the process's subtree by stage 4's walk"; the citation of the deleted stage goes and the sentence stays. - `blockd_io.rs`, `spawn_cwd.rs` (modify/delete): this branch's hunk in each was the `place` field `SpawnArgs` gained. Main deleted both tests; the hunk has nothing left to adapt. - `compositor_client_death.rs` (modify/delete): this branch's hunk placed the test's relay under the test's root, because the relay outlived the creator that started it. Main deleted the test; nothing is left to adapt. - `pkg_launch_gbae.rs` (modify/delete): this branch's hunk has the client start gbae under init. Main deleted the client with `pkg_install_gbae`, which the guest-suite track brings back as a metal row from main before the cut, where the client still exits over a child that now ends with it. That track's `pkg_install_gbae` item now says the client starts gbae under init. Not a conflict, and broken by the merge: `src/ci.rs`'s `CONTROLS` rows take a `Verdict` on main, so this branch's five `toyos-proclife` rows name their tests as `Fails(...)` with the module path, and the landed-child control names its `tree` test as well. Filed: `issues/build/a-metal-judge-takes-a-names-lowest-pid-for-the-job.md`. `Readback::exit_code` takes a name's lowest pid for the job, and this branch's kernel gives a refused spawn's pid to the next admission. Before this commit, on the merged tree: `cargo run -- --build-only` exit 0, `cargo test --test toyos-build -- --list` exit 0, and `--metal --list` for `process_tree`, `abuse_handle_table` and `spawn_lands_claimed` exit 0 each (one boot each: `proctreecase`, `shared`, `shared-debug`), which builds every guest binary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
The four conflicts are the four prompts: CLAUDE.md, implementer.md, orchestrator.md and reviewer.md. Each is taken from main whole. #678 rewrote them from the owner's later decisions, which override every prompt rule this branch wrote on 2026-09-30; none of this branch's prompt hunks survives. Everything else merged without a conflict: the kernelprobe move, the two case configs, the closed issue and the filed one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
…among them) into wt/toyos-winitstall Three content conflicts, each a deletion on main's side of a block this branch had edited: - kernel/src/inbox/mod.rs: main deleted `Staged`, `handler-post`'s ring, with the actuator (#660). This branch's hunks inside it — the `owed` field, `Poll::new`, the `WatchFlags` direction and "fires" for "completes" in its doc — adapted it to the ring's new fields and go with it. `Inbox::complete` keeps this branch's wording and loses main's `raise_if_staged` call. - kernel/src/watch.rs: main deleted the `handler_post` module, `holding`, `note_post` and the `raise_if_staged` call in `IrqLock::with`. This branch's one hunk inside it was "fires" for "completes" in the module's doc, which goes with it. - userland/fsd/src/main.rs: main deleted the four test actuators (`--end-on`, `--end-at-read`, `--end-at-mount`, `--let-go-at-read`) and kept the acceptor probe; this branch deleted the probe and kept the actuators. Both deletions stand: no `caps_len`, no `probe` field, no actuator field, and `accept` is this branch's. Two resolutions no marker asked for: - src/ci.rs: #668 made a control's verdicts `Fails(..)` values, so `post-is-an-answer`'s three verdict strings become three `Fails`. - issues/build: main filed the C++ runtime's scratch removal as an issue of its own (`the-cxx-runtimes-scratch-removal-dies-on-a-finder-file.md`) beside the sweep's, which this branch had merged into one file. Main's two files stand and this branch's file goes. The `rust` gitlink is main's, `95960d6c2`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
The worktree and landing machinery becomes
gitcommands in the role prompts, and the prompts take the owner's decisions of 2026-10-01. The authority for every prompt rule below is those decisions, numbered as the owner ruled them.What goes, and what replaces it
cargo run -- --worktree add|list|removeandcargo run -- --syncgo:src/worktree.rs(838 lines, 299 of them tests),src/sync.rs(263, 131 tests), theWORKTREEandSYNCflags, their dispatch insrc/main.rs, and the sysroot test of the deletedworktree::remove. The recipe below replaces them. What only refused, reported or measured goes with nothing in its place:--worktree list, with its sizes and its "landed, reclaimable" line;--sync's dirty-primary skip and its stranded-commits message.Each refusal that guarded a real mistake has a replacement:
M rustfor each of: a tracked edit, an untracked file and a new commit in the fork checkout, and an edit and an untracked file in itslibrary/backtrace.git branch -d.git worktree add -brefuses a name whose branch exists, and the remote refuses a push that does not fast-forward.maingit cannot fast-forward is refused by--ff-only.--worktree removeswept the sysroot, freestanding, compiler and LLVM stores. The sweep moves into the build: sysroot and freestanding placements now go throughkeystore::made, as compiler placements andllvm::resolve's already did, and such a placement removes what no registered worktree records and nobody holds. Only the build reads the records and takes the keys' locks, so a recipe step would have needed a command of the build system's own. Accepted by name: a removed worktree's keys now stay on disk until the next placement of their kind, and an LLVM placed throughllvm::heldsweeps nothing. A store grows only at a placement.The recipe
.claude/agents/implementer.mdmakes, resumes and checks a worktree;.claude/agents/orchestrator.mdsyncs the primary and removes a landed branch's worktree (decision 6). All of it runs in the primary checkout:Root
CLAUDE.mdkeeps only the invariant: a worktree is never made withgit clone, andgit submodulenever runs in one. Those are the only sources of the three failures: a 913 MiB fetch of the fork's history, a second toolchain, and the rustuptoyoslink taken from every other checkout. A clone is its own primary, soensure_submodulesclones the fork,Bootstrap::Fullbuilds a toolchain and the toolchain is linked to rustup;git submodulein a linked worktree writescore.worktreeinto the fork's shared config. A linked worktree's build runs none of the three:toolchain::ownerreads ownership offgit rev-parse --git-common-dir,main.rsrunsensure_submodulesonly forOwner::Us, andtoolchain::ensurereturns before the bootstrap and the link forOwner::Elsewhere.Why
rm -rfand three prunes rather thangit worktree remove. Measured on a scratch fixture of the real shape: a primary whoserustcarrieslibrary/backtrace, a linked worktree, and its fork checkout made asfork_checkoutmakes it.working trees containing submodules cannot be moved or removed, exit 128.contains modified or untracked files, because itslibrary/backtraceis now missing.File name too long) after unregistering the worktree, and leaves it on disk.rm -rfof what is left exits 0.The proof run
The recipe ran end to end from the primary, with a second worktree
toyos-recipeproof; snapshots were taken before, after the add, after the build and after the removal.git fetch origin: EXIT=0.git worktree add -b wt/toyos-recipeproof ../toyos-recipeproof origin/main: EXIT=0.cargo run -- --build-onlyin it: EXIT=0, 76 s. Its log saysMaking …/rust a fork checkout at aca5f527f (a git worktree of the primary's), and has noInitializing submodule, noBuilding full toolchain, noBuilding compilerand noBuilding sysroot.count-objects -vwas identical in all four snapshots: in-pack 3,518,737, 3 packs, size-pack 1,100,435 KiB.rust/build/*/stage2list was identical (3 entries), and so were the store keys: 7 sysroots, 3 freestanding, 2 compilers, 2 LLVMs.~/.rustup/toolchains/toyospointed at the primary'sstage2in all four snapshots.git branch -dEXIT=0.git worktree list --porcelainof the repository, the primary'srust/and itslibrary/backtracehad 86 entries, as before (89 while built);.git/worktrees,.git/modules/rust/worktreesand the store keys were as before.Every key the proof run's build used was already in the stores, so it placed nothing: the per-placement sweep stands on the unit test and its mutation below, not on this run.
The resume line, on a scratch repository: a worktree made with
-b, a commit in it, removed withrm -rfandgit worktree prune(EXIT=0, one worktree left registered), thengit worktree add ../demo wt/demo: EXIT=0,HEADat the branch's commit onwt/demo. Making it again with-bunder the same name:fatal: a branch named 'wt/demo' already exists, EXIT=255.The sync line, on a scratch clone whose
rust/readM rustas the primary's does:git pull --ff-only origin mainmovedmainfroma97ff80dfto the remote's tip, EXIT=0. With a local commit on a currentmainit printed "Already up to date.", EXIT=0; on amainbehind the remote,fatal: Not possible to fast-forward, aborting., EXIT=128,mainunmoved.A sysroot is held while anything compiles against it
Placements now sweep any key nobody holds, so a sysroot's directory must never be read without its guard.
TestBuild::beginand the harness'sc_sysrootdropped theSysroot, and its guard with it, then kept compiling against its directory: once a build in the same worktree recorded a new key, the next placement in any worktree could remove the sysroot a running suite compiled with. The race is closed by construction, shown by reading:Sysroot's directory is a private field.Sysroot::dironly lends it, as&Path.toolchain::ensureresult is moved into aGuestEnv(shipped_parts,build_test_parts,TestBuild::begin) or into the harness'sstatic SYSROOT: OnceLock<Sysroot>, which is never dropped.GuestEnvits caller holds (cargo_build,assert_kernel_is_softfloat,build_and_assemble, andbuild_programs, whose C environment is used within the call) or from that static.TestBuildowns itsGuestEnvacross every build→read pair. The kernel build borrows the env from astd::thread::scopethread, which is joined before the env can drop, where it used to clone it into a detached thread.keyed_idlecannot take a key while any of these hold its shared lock.One git runner, one removal
crate::gitwas a second runner besidesysroot::git_try. It goes; its four callers read throughsysroot::git_out, andrelease::manifestno longer returns aResultnothing in it can fail.sysroot::remove,sysroot::remove_treeandkeystore::removewere three removals of a build product.keystore::removeis the one left: a file or a directory, read-only or not, outlasting a writer that adds a file while it runs, and a name already gone counts as removed. That last is what a second sweeper of one store meets after the first has taken a key's names; before, the second build panicked on the stat.a_switch_that_cannot_remove_records_nothing_and_the_next_one_removesnow makes its removal fail with a read-only parent, because a removal gives back the write permission of what it removes.The prompts
Root
CLAUDE.md,orchestrator.md,implementer.mdandreviewer.mdstart from a read-only reviewer's proposals written at round 1's head, and the decisions override them where they differ.Root
CLAUDE.mdholds what every agent needs, an agent spawned without a type included. That means every rule whose breach is unrecoverable:toyos-build (https://github.com/ToyOSOrg/ToyOS);mainis never touched;git cloneorgit submodulefor a worktree;--metalwithout--metal-readback, which builds a metal row's images and touches no machine (src/testargs.rs);Root's other changes:
userland/CLAUDE.mdas a principle. A ToyOS-only program is one whose job exists only on ToyOS, and "system service" stays the panic track's term as 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 landed it (decision 5).orchestrator.md; waiting, worktree making and the PR mechanics toimplementer.md.-mis dangerous, "five artifacts from one wrong model still agree", why no upstream pull request is sent (the rule stays), and the DOOM1.WAD sale line, whichNOTICEcarries.orchestrator.md:tools:line is gone, so a session started as the orchestrator keeps every tool;issues/build/who-arms-auto-merge-has-two-answers.md;T14 RUN REQUESTED:line names<dir>/request.txt, the request file a staging run writes, whereimplementer.mdhad it name an image andorchestrator.mda request file;implementer.md:cargo runthat launches QEMU, and--metalonly beside--metal-readback: a metal row's images are staged withcargo test --test toyos-build -- --metal --metal-readback <dir> <row>, and the report endsT14 RUN REQUESTED: <dir>/request.txt;reviewer.md:--ci host, every guest test the change reaches, since no guest boots beforemain, and the hardware's reading where the change targets hardware;src/clippy.rsshape is read, never proven by a planted mutation (decision 10);issues/change againstissues/README.md, as that file already claimed;runs-on:names a GitHub-hosted runner, moved fromsrc/CLAUDE.md;exemptis for a program whose job exists only on ToyOS.Deleted:
.claude/agents/upstreamer.mdand its.gitignoreline (decision 8). The private memory the round-1 review named is the orchestrator's own housekeeping (decision 12).The subdirectory files take the findings the owner listed, and none grows:
kernel/CLAUDE.mdnames AArch64's transition files, labels the direction flag x86, and drops the spinlock count.userland/CLAUDE.mdloses the portability rule to root, its POSIX sentence to root, and the filepicker note:c3c42e137fixed that violation and closed its issue.tests/CLAUDE.md: the sleep caveat stops saying re-run, the T14's CI-container clause goes, and the TCG caveats say which guests are TCG (Arch::accel); the guest-lane line repeatedsrc/CLAUDE.md.src/CLAUDE.mddrops the boot modes, which their site documents; "a flashable artifact is built from a committed tree" moves toimplementer.md. The lock lines become a pointer tosrc/buildlock.rsand the track, and the std type-check is made portable.issues/README.mddrops its history and the lines that were stale or contradicted root..github/pull_request_template.mdnow agrees withimplementer.md: the body is the record and the reviewer's evidence, and it says what is unsure..cargo/config.toml.exampleclonesToyOSOrg/cpalattoyos-0.18.0, the branch the tree consumes.Every citation of a moved or deleted line or function follows it: the fork-checkout, loaded-suite, C++-runtime, app-portability and hosted-rustc issues, and a
src/hostws.rscomment. The Windows issue keeps its judge. It loses its error list, which no dated run printed, the paragraph after it, which placed a#[cfg(unix)]atsrc/ci.rs:489that neithermainnor this tree has, and the clause of its last sentence that counted that list's errors.Every metal command names the harness's test target:
cargo test --test toyos-build -- --metal …in root,orchestrator.md,implementer.mdand the process-memory track'scopy_costA/B. A barecargo test -- --metalpasses the flag to each test binary of the root package, andsrc/lib.rs's unit tests refuse it before the harness starts; Gates records both spellings.One track holds the machinery cut. This branch's track restated the assigned
issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md. Its lock stage and its gate stage join that track as two bullets, each with its exit; its line counts, its first stage and its empty fourth stage go, and so does the file.The example of a gate replaced by a prompt. #669's workflow gate read the workflows as text, and a review found a quoted cache key and a comment on the
jobs:line past it (#669 (comment)). It became a YAML parser with a closed allow-list, and the next review found auses:path that GitHub splits and the gate did not, and a U+2028 line end that GitHub breaks on and yaml-rust2 does not (#669 (comment)). Atc282a7669, #669 carries those rules as sentences inreviewer.md, and no parser.Kept in the build system
toolchain::ownerandrust_dir: a linked worktree's build reads the primary's compiler through them.sysroot::fork_checkout, unchanged:git worktree addleavesrust/an empty stub, and std must compile in a checkout at<worktree>/rust, becauselibrary/stdnames../../../toyos-abi.main.rs'sOwner::Usguard onensure_submodules, which makes a plaingit worktree addsafe.Gates
At this head,
7da54b120, run one after another; their logs, and the host's load before and after each, are in #678 (comment).cargo run -- --ci host: EXIT=0,Host: 59 step(s), all green. The build system'scargo test --libgave 363 passed, 0 failed, 7 ignored.metal_sim_scanout_wc, with--metal-readback, which builds images and touches no machine:cargo test -- --metal --metal-readback <dir> metal_sim_scanout_wc: EXIT=101.src/lib.rs's unit tests, the first test binary cargo ran, printederror: Unrecognized option: 'metal', and nothing was staged.cargo test --test toyos-build -- --metal --metal-readback <dir> metal_sim_scanout_wc: EXIT=2,[metal] staged 1 image(s); <dir>/request.txt lists them. The machine was not touched, so this run establishes nothing about it.It reachedc_sysroot:[metal] 1 registration(s) and 0 shared member(s) over 1 boot(s)prints only afterbuild_shared_binsreturns.git diff --shortstat origin/main...HEAD: 43 files changed, 375 insertions(+), 1711 deletions(-). Its Rust (-- '*.rs'): 15 files, +116 −1249, none of it this round's.At
3c2cd6408, whose tree differs from this head only in the five Markdown files this round edits (git diff --stat 3c2cd6408..HEAD). The orchestrator's run is in #678 (comment); the others ran one after another, and their logs and the host's load are in #678 (comment).cargo run -- --build-only: EXIT=0,Build finished.,target/bootable.img. Every key was already in the stores, so it placed and swept nothing.cargo test --test toyos-build, the whole guest suite: EXIT=0,test result: ok. 21 passed, 21 total (126.9s); the load average was 15.22 on 14 cores as it ended. It reachesTestBuild::begin:virt_readonly_copyoutandvirt_fatal_halts_the_others_firstbuild their binary throughbuild_toyos_bin. It does not reachc_sysroot, which onlybuild_shared_binscalls, under--metalor--debug.cargo test --test toyos-build -- --metal --list: EXIT=0,[toyos] Compiling 133 C tests, and attempting 24 declared ones...,[metal] 48 registration(s) and 213 shared member(s) over 27 boot(s). It reachedc_sysrootand touched no machine.a_sysroot_is_whole_or_it_is_made_againplaces a sysroot beside an orphan and asserts the orphan is gone. The mutation reverts the sysroot placement inheldalone tobuildlock::keyed_made; the freestanding placement inbuild()keepskeystore::made, which no test places. The posted patch (Worktrees and the primary's sync are git commands in the role prompts, a sysroot placement sweeps its store, and the prompts take the owner's decisions #678 (comment)), applied as a checked patch: the test ran green on the clean tree, EXIT=0; the mutated tree built, EXIT=0; the test ran red under it, EXIT=101,placing a sysroot left one no worktree names; the restore leftgit status --porcelainempty.Instruction files, in bytes (
git cat-file -s),origin/main→ round 1's head5aaec89ce→ this head:CLAUDE.md.claude/agents/orchestrator.md.claude/agents/implementer.md.claude/agents/reviewer.md.claude/agents/upstreamer.mdsrc/CLAUDE.mdkernel/CLAUDE.mduserland/CLAUDE.mdtests/CLAUDE.mdissues/README.mdClosed issues
sync-from-a-worktree-never-moves-main-because-the-primary-reads-dirty: the sync line moved a scratchmainwithM rust, and the dirty check is gone.worktree-remove-leaves-wt-branch-behind-so-the-name-is-refused-later: the removal ends ingit branch -d.who-arms-auto-merge-has-two-answers: decision 1 names one owner, the orchestrator, and every file now says so.No slug of the three is cited anywhere (
git grep).What I am unsure of
--metalbeside--metal-readback, so that an implementer can stage a metal row's images, where round 3's brief barred--metaloutright. Without it, the orchestrator builds every metal image itself.rm -rfdeletes whatever the reader let through, and a fork commit pinned by a pushed branch but on no fork ref is protected only by the instruction..DS_Storewritten duringrm -rfmakes it exit non-zero, and running it again finishes. The recipe does not say so.src/ci.rs'sworkflows_run_against_main_on_hosted_runnersstill holds theruns-on:rule thatreviewer.mdnow carries, until the track's gate bullet judges it.issues/hardware/anonymous-mmap-is-not-demand-paged.mdcites the line and records where it is not true.src/cicache.rscallscrate::sync::git, which is nowcrate::sysroot::git_out. Itsreviewer.mdhunks meet the rewritten file, and its two Tests sentences restate root's "code enforces only what reading cannot see" and "nothing a type refuses is tested", so it deletes its copy. Its workflow-gates issue meets the track's gate bullet..claude/settings.json's"agent": "orchestrator"..gitignoreignores.claude/*, and the primary holds the owner's own untracked.claude/settings.json. On a scratch repository, the nextgit pull --ff-only origin mainafter a commit tracking that path exited 0 and silently replaced the ignored local file, which would erase the owner's permission list. The owner adds the line to the local file, or first moves its permissions into.claude/settings.local.json.🤖 Generated with Claude Code
https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L