Public: anyone can read this; the crew can change it.
The cell suites pass on a pull's check: spawn-cell-e2e and crew-sandbox #560 are green on today's main #10551
Check · Review · Land · Live done — Landed and live in production.
The #560 sandbox red is fixed. It was a code regression from 636aa0355, not the disk and not only the test. The two child-forge cell reds are **not** fixed: their cause is still unknown, so this pull makes those tests report the cause the next time they fail.
shipped production is serving it deploy abf00b0
The #560 sandbox red is fixed. It was a code regression from 636aa0355, not the disk and not only the test. The two child-forge cell reds are not fixed: their cause is still unknown, so this pull makes those tests report the cause the next time they fail.
#560 sandbox (test/crew-sandbox.test.ts). In a check, tmpdir() is /data/checks/<id>.home/shard-*/tmp, a long path. That makes runTmpDir move the run's temp directory into the machine's temp directory. When it moved there, the new branch in tempDenied denied every entry of the temp directory except the run's own. The data directory was one of those entries, so the agent's own crew directory got denied. That is three reds in this suite plus the one in outsiders-member.test.ts; this sandbox's own TMPDIR is long enough to reproduce all of them. The fix is in src/crew/sandbox.ts:
- When the data directory is inside the temp directory, the old by-name denials apply again:
claude-<uid>and eachfc-*cell socket directory. - Every other run's
fr-*temp directory is now denied too. - The temp directory is still denied whole, or every entry but the run's own, when the data directory lives elsewhere.
Nothing about the sandbox is loosened. The test was also wrong: it assumed the run's temp always sits under crew/<agent>/.t/, which runTmpDir changes on purpose for long paths. It now expects whatever runTmpDir returns. A new test points TMPDIR at a check-shaped long path and checks:
- the agent keeps its own crew directory and run temp;
crew/mason,repos, another run'sfr-, anfc-andclaude-<uid>are all denied.
Child forge cell tests (spawn-cell-e2e, spawn-cell "a real child forge"). Both runs that went red (01m71msjzc8vvx97tk4dn9xz8k and 01m71p58da9ddktr72wwdvbt27) stored only the tail of the check log, so those shards' assertion text is gone. Both failed at about 14 s, in different shards, while the e2e helper waits up to 150 s. That looks like the child forge exiting soon after it starts, not a timeout from load or disk; the other tests in those runs passed. I could not test this here: bwrap cannot create a namespace in this sandbox.
- The diffs of 0dfe641b7 (cell hides the parent's home and temp), 9cecaf275 (log rate limit) and 95969e118 (hosted child's cells) show nothing that would kill a child at boot. The check cell's home was already hidden from nested cells through the mount list before 0dfe641b7.
- So both tests now fail with one message holding: what the helper printed (the child's "its cell did not come up: …" lines), the stderr tail, the disk's free share and the load against the cores. This comes from
test/helpers/machine-note.ts, which has its own test. - The forge's next check on this pull will either pass these two tests or name the cause. The "fixed so all three pass" item is open until then.
What to look at: tempDenied in src/crew/sandbox.ts, and the new test at the end of test/crew-sandbox.test.ts.
Checks run here: gate and tsc pass. bun scripts/fast.ts named 233 files (about 20 minutes), so I ran the 17 test files that import crew/sandbox plus the spawn and machine-note tests: 155 pass, 17 skip, 0 fail. The cell suites skip here (port mode, no user namespaces); only the forge's check runs them. I could not keep the plan on the issue: the keep_plan tool was not available in this run.
🤖 Generated with Claude Code
This fixes the three reds in the check for #10541: the two cell tests had a bug in the test itself, and the third was a stale allow list. Nothing in src/ changes.
a child forge spawned into a cell serves its app at <app>--<child>--<parent>: the test was wrong; the cell was working. The log shows the helper printed its result, ending …"body":"bakery says hi","app":"bakery"}. The helper prints that line before it stops its cell children, and their shutdown lines ("forge draining", "forge shutting down") reach stdout after it. The test took the last line of stdout, got a log line, and failed with "printed no result". The child had served the app.
a real child forge > boots in its own forge:<name> cell…: probably the same cause, but not confirmed. That shard's output was cut off at the start of the check log, so its error message isn't there. Its helper (test/helpers/real-child-forge.ts) prints its result before stopCellChildren too, and the test read the last line the same way.
an allowed module that has become reached leaves the list: src/kernel/why_now.ts was deleted on main in 64e585b98 but was still listed in scripts/unreached-allow.json. It is removed from the list.
Changes:
- A new helper,
test/helpers/result-line.ts(resultLine), returns the last line of stdout that is a JSON object. test/spawn-cell-e2e.test.tsandtest/spawn-cell.test.tsuse it instead of taking the last line.test/result-line.test.tscovers the case from the log: the result followed by shutdown lines.
Causes the issue asks to name:
- Code regression: none of 636aa0355, 0dfe641b7 or 9cecaf275 is the cause of these reds.
- Disk and load: the run had 16% disk free and load 55.7 on 64 cores, now printed in the failure message by the earlier commit. They were not the cause; the child answered in time.
- #560 shell-sandbox test: passed in this check after 366ab70fd. The sandbox is not loosened.
Checks run here: bun scripts/gate.ts, bun x tsc --noEmit and bun test on the result-line, unreached, machine-note and both cell suites all pass (34 pass, 4 skipped). The real-cell tests are among the skipped: this sandbox runs in FORGE_TEST_SOCKET mode, where bwrap cells and unix sockets are off. The forge's check on this push is the one that runs them.
🤖 Generated with Claude Code
This fixes the reds on the check for #10541. In each case the test was wrong, not the code: nothing under src/ changes.
a child forge spawned into a cell serves its app at <app>--<child>--<parent>: the child answered 200 withbakery says hi, and the helper printed that result. But it prints before it stops its cell children, and their "forge draining" and "forge shutting down" lines reach stdout after it. The test read the last line of stdout, got a log line, and failed with "printed no result". A new helper,test/helpers/result-line.ts, takes the last line that is a JSON object instead.a real child forge > boots in its own forge:<name> cell…: its helper prints its result before stopping its children the same way. The log for that shard was cut off, so I matched the cause from the helper's code, not from its error message. It now uses the same helper.an allowed module that has become reached leaves the list:src/kernel/why_now.tswas deleted on main in 64e585b98 but was still listed inscripts/unreached-allow.json. The entry is removed.child quota > room for small but not large is refused only for large: the test typed a 2000 MiB limit as room for one small child. Since ab3dadb9f a small child holds 2048 MiB, and an earlier test in the file leaves one small child in the ledger. So small was refused too. The limit is now worked out from what the ledger holds plusSIZES.small.
On the causes the issue names: none of these reds is a regression from 636aa0355, 0dfe641b7 or 9cecaf275. Disk and load were not the cause either: the child answered in time, at 16% disk free and load 55.7 on 64 cores. Those figures are now in the failure message of both cell tests. The #560 shell-sandbox test passed in the last check after 366ab70fd, and the sandbox is not loosened.
Checks: bun scripts/gate.ts, bun x tsc --noEmit and the covering tests pass: result-line, unreached, machine-note, child-quota and both cell suites. The quota test fails on the old line here and passes with the fix. The real-cell tests are skipped in this sandbox (FORGE_TEST_SOCKET mode, no bwrap cells), so the forge's check on this push is where they run.
🤖 Generated with Claude Code
Clean. The sandbox fix in tempDenied keeps the claude-<uid> and fc-* denials and adds every other run's fr-* temp, so nothing is loosened. resultLine fixes the last-line-of-stdout bug in both cell tests. The failure messages now carry disk and load. The quota test is derived from SIZES. Minor, not blocking: the new crew-sandbox test leaves its forge-long-temp-* directory under tmpdir; remove it in the finally block. The pull description says nothing in src/ changes, but sandbox.ts does.
The #560 sandbox red is fixed. It was a code regression from 636aa0355, not the disk and not only the test. The two child-forge cell reds are not fixed: their cause is still unknown, so this pull makes those tests report the cause the next time they fail.
#560 sandbox (
test/crew-sandbox.test.ts). In a check,tmpdir()is/data/checks/<id>.home/shard-*/tmp, a long path. That makesrunTmpDirmove the run's temp directory into the machine's temp directory. When it moved there, the new branch intempDenieddenied every entry of the temp directory except the run's own. The data directory was one of those entries, so the agent's own crew directory got denied. That is three reds in this suite plus the one inoutsiders-member.test.ts; this sandbox's ownTMPDIRis long enough to reproduce all of them. The fix is insrc/crew/sandbox.ts:claude-<uid>and eachfc-*cell socket directory.fr-*temp directory is now denied too.Nothing about the sandbox is loosened. The test was also wrong: it assumed the run's temp always sits under
crew/<agent>/.t/, whichrunTmpDirchanges on purpose for long paths. It now expects whateverrunTmpDirreturns. A new test pointsTMPDIRat a check-shaped long path and checks:crew/mason,repos, another run'sfr-, anfc-andclaude-<uid>are all denied.Child forge cell tests (
spawn-cell-e2e,spawn-cell"a real child forge"). Both runs that went red (01m71msjzc8vvx97tk4dn9xz8k and 01m71p58da9ddktr72wwdvbt27) stored only the tail of the check log, so those shards' assertion text is gone. Both failed at about 14 s, in different shards, while the e2e helper waits up to 150 s. That looks like the child forge exiting soon after it starts, not a timeout from load or disk; the other tests in those runs passed. I could not test this here: bwrap cannot create a namespace in this sandbox.test/helpers/machine-note.ts, which has its own test.What to look at:
tempDeniedinsrc/crew/sandbox.ts, and the new test at the end oftest/crew-sandbox.test.ts.Checks run here: gate and
tscpass.bun scripts/fast.tsnamed 233 files (about 20 minutes), so I ran the 17 test files that importcrew/sandboxplus the spawn and machine-note tests: 155 pass, 17 skip, 0 fail. The cell suites skip here (port mode, no user namespaces); only the forge's check runs them. I could not keep the plan on the issue: thekeep_plantool was not available in this run.🤖 Generated with Claude Code
Closes #10541