docs: the two-box brief states the raw sweep result and its reconciliation, points at the 1b-next ledger with Task 7's two open concerns, gives the worktree paths, and cites the committed diagnosis
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1 file changed,
+15
−8
docs/superpowers/plans/CODEX-REVIEW-BRIEF-TWO-BOX-R1.md+15 −8
diff --git a/docs/superpowers/plans/CODEX-REVIEW-BRIEF-TWO-BOX-R1.md b/docs/superpowers/plans/CODEX-REVIEW-BRIEF-TWO-BOX-R1.md| index e17e50607..bf6117570 100644 |
| --- a/docs/superpowers/plans/CODEX-REVIEW-BRIEF-TWO-BOX-R1.md |
| +++ b/docs/superpowers/plans/CODEX-REVIEW-BRIEF-TWO-BOX-R1.md |
| @@ -87,22 +87,29 @@ branch, so the tip holds the same model plus this file) against plan 1b-next rev |
| Three things changed or arrived after the plan's rev 11 was accepted. Read the first two as part of the model under review. The third is a request about 1b-next. |
| -**1. Two-box model fixes after the 3,000-seed sweep (cf566b41).** The first sweep was void: the unmutated two-box model failed INV-10 on seeds 819, 1674, 2106 and 2627, which hid 19 of the 28 stale readings. The one-box shape and the 300-seed gate never reach those seeds. The diagnosis (`task-6-diagnosis.md`, with the controller's rulings in `progress.md`) found three causes, and cf566b41 fixes them: |
| +Readers read the code in two local worktrees, by path, not from a remote. The model is in `/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-two-box-build` (branch `region-ha-two-box-build`). The 1b-next stage A build is in `/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-1b-next-build` (branch `region-ha-1b-next-build`). |
| -- INV-10 has a `SweepOwed` exemption for files keys the at-rest sweep owns (spec §5.6, claim §6.2a, 1b-next ruling 21). A park keeps such a key live; the key later goes obsolete; the sweep retires it. INV-10 at an operation's end used to fire before the sweep ran. `final()` still requires every such key to be retired, so a key the sweep never retires still fails the seed. Seeds 1674, 2106, 2627. |
| -- Park-replica and park-superseded in a two-box region now wait for stop evidence from every other live box of the region, as hostops `collectEvidence` does (`internal/hostops/evidence.go`, lines 240 to 272). Before, the owner checked only its own box, so a sibling's replicator could still write after the region was parked. Seed 819. One box is unaffected: the wait is gated on two boxes per region. |
| -- `fence()` replaces the target when a fenced source is also the operator-named target. This is the ruling-13 stand-in path only: the operator's resolve replays from `pinning` with the source eligible, and without this the replay stalled for ever (seed 236, INV-3). The worker's own target choices already exclude the source (1b-next ruling 26), and a model-wide source exclusion was tried and rejected because it breaks the three operator tests of plan ruling 13. Say whether the stand-in is faithful enough, or whether the model wants a real return-to-source action. |
| +**1. Two-box model fixes after the 3,000-seed sweep (cf566b41).** The first sweep was void: the unmutated two-box model failed INV-10 on seeds 819, 1674, 2106 and 2627, which hid 19 of the 28 stale readings. The one-box shape and the 300-seed gate never reach those seeds. The diagnosis is committed as `docs/superpowers/notes/2026-10-08-region-ha-two-box-sweep-diagnosis.md` (it covers the first two causes, and its follow-ups cover the third). cf566b41 fixes three causes: |
| -**2. The two-box expectations file (5766a0e1, with df1a5f20).** `expected-outcomes.two-box.txt` is new. `mutate.sh` reads it only at `HOSTLIFE_BOXES=2` and it overrides the one-box file rule by rule; the one-box file, which moves owns, is untouched except that df1a5f20 dropped two lines the two-box sweep contradicts. The two-box sweep result was 118 caught, 39 expected, 0 unexpected and 0 errors, and all 54 region HA rules were caught or expected. The override records that `timer-canonical` and `source-readiness` are missed at two boxes (caught at one box), and that `exec-writer` is caught at two boxes (1 of 3,000, seed 2319). `create-choice-once` and `reloc-replacement-table` are caught by the sweep (239 and 2 of 3,000) and by their direct tests, so they have no expectation line. Results has the verdict lines and how the five flagged ones were reclassified. |
| +- INV-10 has a `SweepOwed` exemption for files keys the at-rest sweep owns (spec §5.6, claim §6.2a, 1b-next ruling 21). The exemption also covers keys that moves' push, install and return parks keep live, including current-generation keys, which is wider than the diagnosis's dead-generation case, so INV-10 at an operation's end cannot tell those from a key a later chore should have parked. A park keeps such a key live; the key later goes obsolete; the sweep retires it. INV-10 at an operation's end used to fire before the sweep ran. `final()` still requires every such key to be retired, so a key the sweep never retires still fails the seed. Seeds 1674, 2106, 2627. |
| +- Park-replica and park-superseded in a two-box region now wait for stop evidence from every other live box of the region, as hostops `collectEvidence` does (`internal/hostops/evidence.go`, lines 240 to 272). Before, the owner checked only its own box, so a sibling's replicator could still write after the region was parked. Seed 819. One divergence from hostops: the model's wait skips a sibling that is already stopped, where hostops would still wait for its evidence. One box is unaffected: the wait is gated on two boxes per region. |
| +- `fence()` replaces the target when a fenced source is also the operator-named target. This is the ruling-13 stand-in path only (the operator's resolve): it replays from `pinning` with the source eligible, and without this the replay stalled for ever (seed 236, INV-3). The worker's own target choices already exclude the source (1b-next ruling 26), and a model-wide source exclusion was tried and rejected because it breaks the three ruling 26 tests (`TestProbeFailedInATwoBoxRegion`, `reloc-no-spare-bound` and `reloc-dead-target-bound`), which rely on the operator's resolve returning the host to the source. Say whether the stand-in is faithful enough, or whether the model wants a real return-to-source action. |
| -**3. 1b-next stage A is being built, and the build changed 1b-next from rev 19.** The branch is `region-ha-1b-next-build` (worktree `.claude/worktrees/region-ha-1b-next-build`; its ledger is `.superpowers/sdd/2026-10-07-region-ha-1b-next-relocation/progress.md`, and the code is under `internal/hostclaim`, `internal/hostops`, `internal/hostguard`, `internal/hostbox` and `internal/hostrelocate`). Tasks 1 to 6 are built and reviewed, at 4879c1e5; Task 7 had just been dispatched. The model was written against the rev 19 text, so please check that it mirrors each change below, and say for each one whether the model already has the behaviour, needs a step or a rule, or is right to leave it out. |
| +**2. The two-box expectations file (5766a0e1, with df1a5f20 and 9ef58e4b).** `expected-outcomes.two-box.txt` is new. `mutate.sh` reads it only at `HOSTLIFE_BOXES=2` and it overrides the one-box file, which moves owns, rule by rule; a `-` line drops the base line. The raw result of the two-box 3,000-seed sweep was 118 caught, 39 expected, 3 STALE, 2 MISSED and 0 ERROR, exit 1. Five lines were reconciled afterwards by editing expectation files only. `create-choice-once` and `reloc-replacement-table` were STALE because the sweep catches them (239 and 2 of 3,000): df1a5f20 first dropped their lines from the one-box file, and 9ef58e4b restored the one-box file to its cf1a2bd5 content and put `-` lines for both in the two-box file instead, so the one-box file is as moves left it. `exec-writer` was STALE the same way (caught 1 of 3,000, seed 2319) and has a `-` line. `timer-canonical` and `source-readiness` were MISSED and are recorded as missed at two boxes (caught at one box). The three moves rules (`exec-writer`, `timer-canonical`, `source-readiness`) were rerun alone and exited 0; there was no complete second run. All 54 region HA rules were caught or expected. Results has the verdict lines and the arithmetic. |
| + |
| +**3. 1b-next stage A is being built, and the build changed 1b-next from rev 19.** The branch is `region-ha-1b-next-build` (worktree `.claude/worktrees/region-ha-1b-next-build`; the code is under `internal/hostclaim`, `internal/hostops`, `internal/hostguard`, `internal/hostbox` and `internal/hostrelocate`). The ledger for the current state is `/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-1b-next-build/.superpowers/sdd/2026-10-07-region-ha-1b-next-relocation/progress.md`; read it at review time, because it moves. The changes below are those up to its Task 6 (4879c1e5); its Task 7 is implemented and in review, and has two open concerns, listed after the changes. The model was written against the rev 19 text, so please check that it mirrors each change below, and say for each one whether the model already has the behaviour, needs a step or a rule, or is right to leave it out. |
| - `JournalPin` refuses until every journaled fence has `observed_at`, so a converted move pins only after `FenceSource` plus 30 s (03da9300). Rev 19 relied on the worker's order. The nearest model rule is `reloc-pin-delay-every-fence`; check that it covers a converted move's source fence, which the move journals without `observed_at`. |
| - The create chooser is scoped to claim Plan 5's namespace and pool, and reads fences only for in-scope boxes (53f26ad6). The worker's chooser is scoped the same way (f9f254ac). No rule in the guards table names this scope. |
| - `AdmissionFenced` agrees with the guard's `With`: a retired fenced installation still reads as fenced, because absence is never evidence. `probe` also waits out `quiet_after` like every other execution action (cec08019). |
| - `NameTarget` drops a converted move's other-region target from the barrier in the same CAS (151261fe). Before, an other-region target that never acknowledged, or was dead, held the relocation in `pinning` for ever. The nearest model rule is `reloc-name-before-pin`; check that the model also drops that target from the barrier. |
| - A converted move's missing bound fence is an error, never "not fenced" (032db0d3). A journaled `fence.<src>` whose fence object cannot be read refuses the worker's pass. |
| -- Other behaviour that `progress.md` records after rev 19: the HA chooser plugs into main's `selectExecutor` and keeps the plan's soft load rule (d1ce3f72); the relocation row's serving case calls main's `hostbox.Serving`, so a malformed serving claim holds its row (bfaa307d); `writers-stopped` allows only the replicator's identified descriptors, matched by process, number and path (e13f6941), with a deferred note that a kcmp ESRCH is assumed to be an exited thread without checking, which the final review is to fix. The model abstracts volume evidence as one flag per box (plan ruling 10), so these have no model step unless you say otherwise. Task 6 (4879c1e5) changed no rev 19 behaviour; it added a test. |
| +- Other behaviour that the ledger records after rev 19: the HA chooser plugs into main's `selectExecutor` and keeps the plan's soft load rule (d1ce3f72); the relocation row's serving case calls main's `hostbox.Serving`, so a malformed serving claim holds its row (bfaa307d); `writers-stopped` allows only the replicator's identified descriptors, matched by process, number and path (e13f6941), with a deferred note that a kcmp ESRCH is assumed to be an exited thread without checking, which the final review is to fix. The model abstracts volume evidence as one flag per box (plan ruling 10), so these have no model step unless you say otherwise. Task 6 (4879c1e5) changed no rev 19 behaviour; it added a test. |
| + |
| +Open questions from 1b-next Task 7 (the release receipt, commit 1ee322d6 when this was written), for the joint round. Both bear on What to check 21 and on `reloc-release-needs-receipt`: |
| + |
| +- Controller restart detection. Whether "this process already flushed" is decided by boot ID plus controller ID alone, while main's `claimLaunchOwner.local` also compares the PID and the process start time. A restarted agent could offer its own drain where main requires recovery, if the controller ID survives a restart. This is the question What to check 21 asks of `box.Epoch`: is it a faithful stand-in for the boot and controller identity, or does the model need the PID and start-time check as well? |
| +- The release receipt's `.sig`. `StopReceiptReleases` binds the receipt by digest, bytes, key and fields but does not verify the box's `.sig`, which main's console-side retirement check does. Say whether the model's receipt (two-box R8 #1) needs a signature step, or whether leaving it out is right. |
| ## Findings F1 to F3, closed, and the open window L21 |
| @@ -284,7 +291,7 @@ sweep: 5 rule(s) ERROR, MISSED or STALE |
| EXIT=1 |
| ``` |
| - The sweep caught 118 rules and read 39 as expected misses, with 0 errors. The five lines it flagged were answered afterwards by editing only the expectation files, and the rules the override covers were rerun alone (exit 0), with no complete second run: `create-choice-once` and `reloc-replacement-table` are caught by the sweep, so df1a5f20 dropped their `missed` lines; `exec-writer` is caught at two boxes, so the override drops its one-box line; `timer-canonical` and `source-readiness` are missed at two boxes, so the override records them as expected misses (each is caught at one box). With those five reclassified, no rule is unexpected: the sweep's 118 catches plus the three that now read as caught are 121 caught, and its 39 expected misses plus the two the override adds are 41 expected. All 54 region HA rules are caught or expected. The sweep's own exit 1 and the five lines above are from the expectation files as they stood before those edits. |
| + The raw result is 118 caught, 39 expected, 3 STALE, 2 MISSED, 0 ERROR, EXIT=1. Reconciliation, by expectation files only: the STALE `create-choice-once` and `reloc-replacement-table` are caught by the sweep, so df1a5f20 removed their `missed` lines and 9ef58e4b moved that to `-` lines in the two-box file (the one-box file is back to its cf1a2bd5 content); `exec-writer` is caught at two boxes, so the override drops its one-box line; `timer-canonical` and `source-readiness` are missed at two boxes, so the override records them as expected misses (each is caught at one box). The three moves rules were rerun alone and exited 0; there was no complete second run of the final classification. With the five reclassified the count is 121 caught and 41 expected, none unexpected, and all 54 region HA rules are caught or expected. The log's exit 1 and its five flagged lines are from the expectation files as they stood before those edits. |
| - Findings the model made while being built, beyond F1 to F6: five seeds violated with the rules on, all found by the 3,000-seed runs (the 300-seed gate never reaches them), and in each the model was changed, not a spec. Seeds 819, 1674, 2106 and 2627 failed INV-10 at an operation's end: 1674, 2106 and 2627 were an oracle that fired before the at-rest sweep retired a files key a park kept live (the first item under "Changes made while building"), and seed 819 was the park-replica owner checking only its own box's stop evidence (the second item). Seed 236 then failed INV-3 once those were fixed: the operator's resolve named the source as the target and `fence()` never replaced it (the third item). None is a 1b-next gap. Two more model-side corrections came from task reviews rather than seeds, and Task 5G closed both (Astra's round 7, findings 1 and 2): INV-26 was a tautology on the operation's discharges and the operator's discharge had no volume check, and the operator stopped slow targets as well as unrecoverable ones. |
| ## What to check |