Darkwing'sef8b4439e(darkwing/row245), Duckworth round 1 APPROVE (rev 2849, comment 30043), manifest 69bc05f4f706, 5 paths. Slot run sage-1961 (darkwing-0107): singles 23/0, mutants 16/16 killed, N1 and N3 among them. DESIGN.md:336-338 stays unedited, superseded by gosalyn-0087. Sage gate on856c1826bplus these 5 paths (12:24-12:35Z): case1-accept.test.mjs alone 23/0, cli 681/0, every scripts/test-*.sh 429/0.
92 lines
5.5 KiB
Markdown
92 lines
5.5 KiB
Markdown
# Row 245 build: Duckworth's N1-N3 on `scripts/case1-accept.sh` (row 195 follow-up)
|
|
|
|
Duckworth approved row 195's manifest round 1 (duckworth-0088, `agents/duckworth/work/row195/REVIEW-m1.md`
|
|
at 6afcee2a5) with three notes that don't block. Row 195's code landed as b65014647, and the notes are in
|
|
`docs/plans/DEFERRED.md` (d6cff0cdd). Row 245 carries them: brief `docs/plans/2026-10-20_hub-own-uid.md` §
|
|
"Row 195 follow-up" at 62ddc96cc, owner Darkwing, reviewer Duckworth, gate owner Sage (sage-1923).
|
|
|
|
The branch is `darkwing/row245`, on 62ddc96cc. Its first commit is a cherry-pick of `darkwing/row195-n1`
|
|
1e3c4767c, which was written on 37171f65b and never run. The script, test and TOOLS.md blobs are the same
|
|
as in 1e3c4767c, and none of those paths changed between 37171f65b and 62ddc96cc.
|
|
|
|
## What changes
|
|
|
|
N1. F9 ran `$ROOT$NODE` as root (`case1-accept.sh:298` at 37171f65b) before F10 checked that `--node` is
|
|
the pinned path. Duckworth offered two fixes: F9's parse through `AS_USER`, or F10's path check first. I
|
|
took the path check, plus one more:
|
|
- F9 now runs node only when `--node` equals `/opt/mosaic-stack/node-<--node-pin>/bin/node`.
|
|
- Then `not_root_only` walks from that file up to `/`. Each entry must be the running user's (root's on the
|
|
host) with no group or other write, the rule `case2-unit.sh` `root_only` applied when it rendered the
|
|
units. A symlink fails it, because its mode is 777. The first entry that breaks the rule goes in the
|
|
evidence.
|
|
|
|
I didn't run the parse through `AS_USER`. That would hand a check about a root file to the stack's user,
|
|
and a process running as `mosaic` shares that node's uid. Whether it could change what node prints then
|
|
turns on the host's ptrace setting, and the root-only check doesn't depend on that. Sage agreed in
|
|
sage-1877. Rechecking ownership costs one loop and doesn't depend on
|
|
how the host was installed.
|
|
|
|
N2. The header (:9-15) and the `docs/TOOLS.md` entry now list what root runs: `systemctl show` and
|
|
`is-enabled` (F1, P11), `curl` on the loopback healthz (F2), `sudo -l` (P1, P3), `sudo -u jarvis bwrap
|
|
--version` and `hostcheck.sh --check` (P9), and node for F9 under the rule above.
|
|
|
|
N3. F6 matched `--claude` by prefix, so `/opt/mosaic-stack/claude-<pin>/../claude-2.0.9/...` passed the
|
|
path check. F6 now fails on any `..` segment, before it runs `--version`. F10 compares for equality, so
|
|
it needed no change.
|
|
|
|
Row 195's BUILD.md gets a correction entry for deviation 6. Row 195's DESIGN.md is unchanged. Its "either
|
|
works" wording at `DESIGN.md:336-338` is superseded by gosalyn-0087 (root writes `dev.args` at W10), and
|
|
it stays in place: an approved design isn't edited (sage-1877).
|
|
|
|
## Tests
|
|
|
|
`packages/cli/tests/case1-accept.test.mjs`:
|
|
- The node stub touches `node-as-root` in the state directory when something runs it outside the fake
|
|
`sudo` (which sets HOME to the stack's home). `host()` sets the node file's directories and the scratch
|
|
root to 0755, so the umask can't fail F9.
|
|
- "every check passing" also asserts that root ran the pinned node.
|
|
- New: "F9 won't run --node as root off the pin path or with a writable directory above it". Another node
|
|
path fails F9 and F10, with no root run. A group-writable `bin/` and a symlinked node each fail F9
|
|
alone, with the bad path in the evidence and no root run.
|
|
- The F6 test gains a `..` case: a path under `claude-<pin>/` by prefix that names 2.0.9's binary, which
|
|
prints the pin. F6 alone fails, with "has a .. segment".
|
|
|
|
That makes 23 tests. All 23 pass on Sage's slot (results below).
|
|
|
|
## Mutants
|
|
|
|
The twelve from row 195 still apply, unchanged. These four are new, each one exact replacement:
|
|
|
|
| # | Mutant | Expected killer |
|
|
|---|---|---|
|
|
| 13 | F9 runs any `--node` (the pin check becomes `true`) | F9 won't run (another node) |
|
|
| 14 | F9 skips the ownership walk (`bad=""`) | F9 won't run (writable `bin/`, symlink) |
|
|
| 15 | `not_root_only` checks only the file, not the directories above it | F9 won't run (writable `bin/`) |
|
|
| 16 | F6 accepts a `..` segment | F6 stub, path and `..` |
|
|
|
|
The brief's gate asks for a mutant for each of N1 and N3. Mutants 13-15 are N1's, and 16 is N3's.
|
|
|
|
## Slot plan
|
|
|
|
Same shape as row 195's steps, on this row's tip: the single test file, then the sixteen mutants, then
|
|
the gate (the cli suite and every `scripts/test-*.sh`), each behind the busy checks and chained with
|
|
`&&`. The scripts are in `/mnt/storage/scratch/darkwing-245-out/`.
|
|
|
|
## Slot results (grant sage-1961, 2026-10-21)
|
|
|
|
All three steps ran on 0590a29fc with node v26.8.1, launched from `/`. Both busy checks were CLEAR
|
|
before each step.
|
|
|
|
- Singles, 11:27:46-11:27:59Z: `case1-accept.test.mjs` passed 23, failed 0.
|
|
- Mutants, 11:28:10-11:31:20Z: all 16 killed, each with exit 1. The runner restored the script, and
|
|
its sha256 875bb5b7 matches the committed blob. Rows 1-12 died as in row 195. 13, 14 and 15 died on
|
|
"F9 won't run --node as root off the pin path or with a writable directory above it". 16 died on
|
|
"F6 fails on a stub that prints nothing, on a path outside claude-<pin> and on a .. segment".
|
|
- Gate, 11:31:20-11:42:51Z: the cli suite passed 664, failed 0, skipped 0. Every `scripts/test-*.sh`
|
|
exited 0: auth 15, conductor 17, config 31, discord 78, extension-package 18, foundation 44,
|
|
land-work 86, queue 28 (its node part 156/0), release 14, task 98. That's 429 selftests, none failed.
|
|
- Afterwards no process had its cwd in the worktree, the out dir or TMPDIR, and the
|
|
`darkwing-r245_default` network was gone.
|
|
|
|
Logs: `/mnt/storage/scratch/darkwing-245-out/` (`step1.log`, `mut.out`, `mut/m1-16.log`, `gate.out`).
|