Repository navigation
Description
Context
Observed on PR #3245, head b80acd2a1624d16e532e8750b874d5cc272cfaf6, base a84d9bfbcb4e608b504aa0a9feb1144ad9a0b77e: the unit (3) shard failed (check run 125037245269, started 2026-11-02T00:54:46Z) with 16 failures in ui-server and ui-react tests. The same shard passed on the previous head 830dbfbdc367efd674e20cdf7bf9b02d6fa0c7d7 about 45 minutes earlier. The two trees differ only in docs/integration-contract.md (prose only), so the PR's change cannot explain the failures.
Failing tests in that shard:
packages/ui-server/tests/subscription-status.test.ts: all six/api/status's subscriptiontests that need a completed turn. Example:subscription-status.test.ts:307expectedprovenBy"turn"and receivednull, so the turn did not record as a successful subscription turn.packages/ui-server/tests/turn-scope.test.ts: freeze/resume and storage-accounting tests, for exampleturn-scope.test.ts:41and:73(toMatchObjectmismatches) andIGNORED_BYTES_ONCE_PER_PATH_SCOPE_COUNTER.packages/ui-react/tests/answer-delivery-runtime.test.ts:976: "Liveness B: a blackholed idle socket is probed after 15 s…", which failed withLiveness native event did not complete.
Locally, subscription-status.test.ts passes. In a sandbox without the native tmpfs runtime, some turn-scope.test.ts cases fail on both this branch and main. That is not the CI symptom.
Related, but not the same symptom: #2551 (low-space failures in running-turn fixtures) and #2989 (answer-delivery storage refusal).
Scope
Scoped on 2026-11-02 (see Acceptance criteria). Original note: needs scoping. First establish whether these tests fail together under runner load or resource pressure (shared worker directories under .brain-unit-workers-*, disk, timing). Then establish whether one shared fixture or harness cause explains all three files.
Out of scope
Raising timeouts or retrying to get green without a diagnosed cause.
Acceptance criteria
Attributed on 2026-11-02 from the second occurrence. Hosted run 41505209464, unit (1), had 2,665,242,624 bytes free on the root filesystem that holds the fixture brains. The turn floor max(5% of 76.9 GB, 2 GiB) is 3,844,357,734.4 bytes, so turns stopped at the floor. A preload that fakes those statfs figures reproduces the CI failure lines on an unchanged base.
- Hosted unit shards begin proof with free space on the fixtures' filesystem of at least the turn-fixture floor plus the proof's own consumption. This is a provisioning fix: it reclaims or measures what fills the runner. It does not change the floor formula.
- A runner that cannot provide that headroom fails in environment setup, as a named infrastructure prerequisite, before any test runs.
- Each proof records the fixtures' filesystem (total, free at start, minimum, free at end, floor). A dip below the floor produces a named annotation that attributes turn-dependent failures to runner disk exhaustion.
- The floor's protective purpose is unchanged. The production
checkandrequireTurnFreeSpacekeepmax(5%, SCOPE_FREE_BYTES), and a test pins the CI copy of the formula to it. - Failing-first and mutation receipts are recorded. Off-main qualification is recorded on the PR (proof-system lane): hosted unit shards with the measured runner disk, none of which reaches the floor.
- Coordination with tests: attribute low-space failures in remaining running-turn fixtures #2551. Per-fixture
requireTurnFreeSpacecalls in the remaining suites, includingsubscription-status.test.ts, stay in tests: attribute low-space failures in remaining running-turn fixtures #2551's scope. This issue covers the runner and the job-level attribution.
The first occurrence's turn-scope.test.ts and answer-delivery liveness symptoms have no disk figures. If they recur on a runner with recorded headroom above the floor, they get a new issue.
Contract impact
None expected.
Triage notes (2026-11-02, main 3b9f3e84b)
No local reproduction was attempted in triage. The single natural receipt above, from a shard that passed on the neighbouring head with a prose-only tree difference, is the only evidence. It establishes the failure but not its cause.
What would complete the reproduction. Any one of these would do:
- A second natural occurrence with the shard's runner resource figures (free disk and inode counts in the worker and
.brain-unit-workers-*directories, and load). - A controlled local run that pins the three files to one worker under constrained disk or CPU and reproduces at least two of the three symptoms together.
- A per-file run showing that the symptoms are independent.
The provenBy: null at subscription-status.test.ts:307 is the most specific symptom. Establishing why the completed turn did not record as a subscription turn is the first narrowing step.
Acceptance once attributed. A named cause per symptom, or one shared cause shown to explain all three. A fixture or harness repair scoped to that cause, with a controlled failing-first receipt. No raised deadline or retry.
Labels: added priority: p2 and needs: repro. Left standalone. #736, which owns non-browser verification determinism, is at GitHub's 100 direct sub-issue limit, so this is related to it by reference only. #2753 covers only browser runs.
Activity
schlessera commentedon Nov 2, 2026
Second natural occurrence, with resource figures and a controlled reproduction (2026-11-02)
Natural occurrence. CI run 41505209464, job
unit (1)(shard 1/4), PR #3342 headb2c0cbcdd, base4cd198552(merge checkout475bd80bb). All six/api/status's subscriptionturn tests failed exactly as described above, atsubscription-status.test.ts:307,:321,:345,:363,:501and:539. Two other failures in the same worker named the cause directly:packages/ui-react/tests/connection-continuity-runtime.test.ts:215:TurnFixtureFreeSpaceError, with 2,665,242,624 bytes available and at least 3,844,357,734.4 required (max(5% of total, 2 GiB)).packages/ui-server/tests/session-taint.test.ts:90: the turn journal carries afree_space_floorreceipt (count2,618,183,680,cap3,844,357,734.4, statestopped).Worker 2's
html-preview-runtime.test.tsfailures came afterwards. The runner SIGKILLed worker 2 (exit 137) after worker 1 failed.Controlled reproduction. A throwaway
--preload, not committed, wrapsstatfsSync. For the test'ssubscription-app-*brains it returns the CI figures above, about 76.9 GB total and 2,618,183,680 bytes free. Everything else stays real.4cd198552,bun test tests/subscription-status.test.tswith the preload fails the same tests at:307,:321,:345,:363and:501, each withprovenBy/lastProvenAtnull. Without the preload it passes 32/32.Attribution. The turn scope's free-space floor (
check,packages/ui-server/src/brain/turn-scope.ts:94-120) stops the fixture turn before it succeeds, so no successful subscription turn is recorded. This explains the subscription-status symptom. Unlike the continuity fixture,subscription-status.test.tsdoes not callrequireTurnFreeSpace, so it reports anullassertion instead of naming low space. That is the same gap #2551 tracks. This note does not attribute theturn-scope.test.tsand answer-delivery symptoms from the first occurrence.schlessera commentedon Nov 2, 2026
Claimed (token
claim-3256-a7d2). Intended branch:fix/3256-unit-shard-disk-floor, fromorigin/main3984040f1. Collision check follows. #2551 is unassigned and has no open PR, so this issue's scope is coordinated with it below rather than taken over.schlessera commentedon Nov 2, 2026
Readiness (2026-11-02)
needs: repro→agent-ready. The second occurrence has resource figures, and a controlled reproduction attributes the subscription-status symptom to the turn floor. The body now has acceptance criteria.priority: p2→priority: p1, milestone 0.45.0. The failure lands at random on whichever 0.45.0 PR's unit shard draws a low-disk runner: fix(core): keep asset descriptions while the index lacks asset hashes #3245 (for p0 core: plain indexing after a rebuild prunes committed asset descriptions #3242) and CONTRACT: feat(ui-server): admit generic chat files as durable server-owned originals #3342. It holds back confirmation of higher-priority work, so the blocker rule puts it at p1 or above.requireTurnFreeSpacecalls stay in tests: attribute low-space failures in remaining running-turn fixtures #2551, which is unassigned and has no open PR. This work does not change any test suite.schlessera commentedon Nov 3, 2026
Handoff (2026-11-03): at the orchestrator's direction, PR #3379 is taken over as the declared red-main fix for incident #3427. Main went red at
e04768a3fbecause a unit shard's runner disk fell below the turn floor: 2.67 GB free against 3.84 GB required. I'm refreshing the PR onto current main and landing it throughintegrate.ts declare-fix/confirm. The earlier claimclaim-3256-a7d2has had no activity since 2026-11-02 21:50Z.fix(ci): reclaim unit runner disk and attribute dips below the turn-f…