Files

5.9 KiB

Filbert review: row 187 round 1 (#1685), approve

Request 29423. Candidate manifest 52a5ecc1d143750507942506cc71b65f51ab23c69ae206053b12fbb2682fe5e0 (3 paths) on base f81ebfbae. The brief is docs/plans/2026-10-20_activate-proof-pair.md (blob 5940115e37).

Verdict: approve. No findings block. N1 and N2 are test gaps that no brief test requires. N3 is a comment nit that Sage ruled non-blocking (sage-1271, sage-1272). N4 is doc-only.

What I ran

  • I built ~/filbert-scratch/r187-r1/wt at f81ebfbae (the refactor head), then ran git apply --index build.patch.
    • sha256sum -c on the manifest passed 3/3.
    • The patch-id is 6b57c47bc661: 3 files, +376/-16.
  • Base drift: the refactor head is f81ebfbae, so there is none.
  • Readers and pins: the only test that reads any of the 3 paths is stack-release.test.mjs. No test reads docs/TOOLS.md, and no 64-hex pin names any of the 3 paths.
  • I took the slot on sage-1272. The /proc busy check was CLEAR at 10:06:11Z and 10:12:12Z, and TMPDIR was ~/fs187.
    • stack-release.test.mjs: 144/144 pass, 0 fail, rc 0, from 10:06:12Z to 10:11:01Z. The counts are awk sums over the spec log.
  • I ran two mutants of my own against ^T53 (12 tests), each restored by git checkout. After them the tree had only the 3 staged paths.
    • M8: a carried pair skips proof_checks ([ -z "$PROOF_HEADER" ] || proof_checks ... at :739). It survived: rc 0, 12/12. See N1.
    • M9: the realpath check drops the $REPO case (:775). It survived: rc 0, 12/12. See N2.
  • Darkwing's run (144/144, the red base on all 11 T53 subtests, m1-m7 killed) and Sage's gate are their receipts, not mine.

Checked against the brief

  • Changes 1 and 2. parse_opts takes the three flags for activate only (:82-84). One of the pair alone, or --no-proof with the pair, is a usage error (:97-98).
    • proof_for_target (:694) strips any pair from RUN_CONSOLE and then picks one case: --no-proof, a new pair, no pair, the rollback drop, or the carry.
    • A carried pair keeps its place, because RUN_CONSOLE isn't rebuilt in that branch.
    • write_pointer and the install both take RUN_CONSOLE, the same way --tester-port works.
  • Change 3. Every refusal goes through check_refuse, and precheck calls console_for_target before instance_busy, the units read and any stop.
    • proof_checks (:745) checks for the preview flags in the run's own flags.
    • The header rule is the same as proofOptions (serve.mjs HEADER, plus host, origin, x-mosaic-tester and the auth header, all lowercased) and as render's.
    • proof_file_problem (:765) follows render's order. It adds "cannot be found" and a mode or uid reason, where render dies with a generic message.
  • Change 4. The file gets only [ -L ], stat -c and realpath, and none of them opens it. The inotify watch (0x21, IN_ACCESS | IN_OPEN) is a sound check because /home is noatime. The plan and step lines carry the header name and the path, never the value.
  • Change 5. A rollback to an unsupported copy drops the pair and says so. An activate to one refuses proof-target with the --no-proof hint. Test 7 covers both.
  • Change 6. One proof: line, after the drop-tester line. planTail gains proof: off, and the four T36 slices move by one.
  • Change 7. pm-on is unchanged, and T53 test 3 pins it.
  • Change 8. TOOLS.md "Pinned stack update" has the flags (and the missing --tester-port) and one paragraph. The paragraph matches the code.
  • Brief tests 1-9. They map to the 11 T53 subtests as BUILD.md's table says. Every subtest ends in noLeak, and each --plan goes through planOnly.
  • Brief mutants. Darkwing's m1-m5 are the brief's five, so they're their receipts.

Deviations

I agree with all three.

  1. The live-copy exception (:243-250). check_target lets the pointer's copy through only with a new pair, or with --no-proof while the pointer holds one. Test 2 pins the refusals for the plain, --no-proof without a pair, and --tester-port forms, and Darkwing's m6 is killed.
    • from_log previous skips to == pointer copy lines (:163), so a rollback after a same-copy activate still goes to the earlier distinct copy. Test 2 checks this.
    • The backup order (stop, backup, install) is pinned by the live-copy subtest.
  2. The pair's position matches render (webui-service.sh, proof before --send and --tester-port), and flags_drift compares exact strings. Test 1 checks status reads "match the pointer" after a set and after a replace.
  3. The repository and copies refusal turns render's die after the stop into a refusal before it. The copies case is tested. The repo case is not (N2).

Notes

  • N1 (test gap, doesn't block): BUILD.md says the checks also run on a carried pair, so a file that was moved or chmodded since the pair went in refuses before the stop. No test pins that, and my M8 survives.
    • Without the check, the run would stop both units and the Console start would fail. The run would then roll back inside itself.
    • Brief test 5 tests each refusal on a new pair only, so this isn't a missing brief-required test.
    • A follow-up could chmod 644 the file after a set, then check that activate C1 and rollback refuse proof-file-invalid.
  • N2 (test gap, doesn't block): no test puts a proof file under the repository, so dropping the $REPO case (my M9) survives. It's the same follow-up shape, with a file under repo instead of COPIES.
  • N3 (comment, non-blocking per sage-1271): the comment above proof_for_target (:689) says a new pair "goes last". The code (:717-725) and deviation 2 put it before --send and --tester-port.
  • N4 (doc-only, follow-up): TOOLS.md:904, in the row 178 proxy proof paragraph, still says "stack-release.sh preserves both flags unchanged on re-pin and rollback". Now activate can set, replace or drop the pair, and a rollback to an unsupported copy drops it. The paragraph could point to "Pinned stack update" instead. No test reads TOOLS.md.