Packet commit, agents/researcher/work/queue-98 only. Secrets scan clean. Not pushed. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
76 lines
4.9 KiB
Markdown
76 lines
4.9 KiB
Markdown
# Row 98 (#1592): Row 77 follow-up, four refusal cases in the service tests
|
|
|
|
Owner: Researcher. Reviewer: Filbert. Brief: `docs/plans/2026-10-12_console-pinned-copy.md`, "Row 77
|
|
follow-up". Built in a scratch worktree at 646e3f77; between 646e3f77 and HEAD nothing changed on the
|
|
candidate paths or on `scripts/webui-service.sh`. **No change to `scripts/webui-service.sh`**: no new
|
|
test found a defect in it. Tests only; nothing goes live; no Mos notice.
|
|
|
|
## Candidate
|
|
|
|
`candidate-manifest.sha256`: two files, repo-relative, hashed from the candidate worktree.
|
|
`build.patch` is `git diff` of them (71 insertions, 2 deletions; sha256
|
|
c5127ba725f41bfa8cd255192839597f88803ae3decc53009a5453553c708cc3).
|
|
|
|
- `packages/webui/tests/service.test.mjs`: the bus and status cases, and a `busOther` option on the
|
|
`standIn` systemctl so a second loaded unit can answer `show` apart from the first.
|
|
- `packages/webui/tests/pinned-copy.test.mjs`: the three rename cases. Placement: the brief names
|
|
`service.test.mjs`, but the rename cases need the fixture repository (`fixtureRepo`, `run`) that
|
|
only this file has, beside the existing rename-race test. Sage allowed it (note at rev 841);
|
|
Filbert confirms.
|
|
|
|
## Cases and mutants
|
|
|
|
`mutants.py` makes each edit to `scripts/webui-service.sh` alone, runs the test file that holds the
|
|
case, and restores the script (sha256 checked). Baseline worktree = 3bd3f85c; candidate = this build.
|
|
|
|
| # | mutant | case | baseline | candidate |
|
|
|---|---|---|---|---|
|
|
| 1 | `LoadState` check refuses only `not-found` | N1 (Filbert): `bad-setting`, `error`, `masked` units, each with an `ExecStart` on the copy, refuse naming the state | ALIVE | killed |
|
|
| 2 | rename failure without a target not refused (the `[ -e "$target" ] \|\| die` line dropped) | N2 (Filbert): stand-in `mv` exits 1 and creates nothing: status 1, stderr "could not rename the copy into <target>", stdout empty, `copies/` empty | ALIVE | killed |
|
|
| 3 | `mv -T` becomes `mv` | N2 (Filbert), second half: an empty target directory exists at rename time and the real `mv` runs: `copied:` and the target holds the copy | ALIVE | killed |
|
|
| 4a | status copy id loses both anchors | N1 (Darkwing): `WorkingDirectory` ending `<40 hex>x`, `x<40 hex>` or 41 hex digits prints `copy: none` and no `refactor:` line | ALIVE | killed |
|
|
| 4b | loses its start anchor | same | ALIVE | killed |
|
|
| 4c | loses its end anchor | same (the 41-hex case) | ALIVE | killed |
|
|
| 5a | bus check reads only the first unit | N2 (Darkwing): two loaded units | killed | killed |
|
|
| 5b | path rule applied to the first unit only | N2 (Darkwing): the second unit runs from the checkout; install refuses naming `[email protected]` and its path, and both `show` calls are logged | ALIVE | killed |
|
|
|
|
Baseline 1 of 8 killed; candidate 8 of 8 (`mut-base.txt`, `mut-candidate.txt`). The brief lists five
|
|
mutants (four edits plus dropping `-T`); 4 is split into three anchor variants and 5 into two, so the
|
|
table is eight. 5a was already killed in the baseline by the call-log assertion in the existing
|
|
two-unit case; it is Darkwing's gap (5b) the new case closes.
|
|
|
|
## Mutant 3 needs care: what `-T` actually changes
|
|
|
|
The brief's reasoning ("without `-T`, `mv` survives for the same reason") held for the stand-in `mv`
|
|
that ignores its flags. With a real `mv`, a non-empty target does not tell the two apart. The copy's
|
|
directories are `0555`, and renaming a directory into a new parent needs write permission on the
|
|
directory itself, so plain `mv` fails with Permission denied, where `mv -T` fails with Directory not
|
|
empty. Both end at `exists:`. Probed directly, as the user, on a `0555` source:
|
|
|
|
| target | `mv -T` | `mv` |
|
|
|---|---|---|
|
|
| empty directory | rc 0, replaces it | rc 1, Permission denied, target stays empty |
|
|
| non-empty directory | rc 1, Directory not empty | rc 1, Permission denied |
|
|
|
|
So only an empty target tells them apart: with `-T` the copy replaces it and prints `copied:`;
|
|
without, `copy` would print `exists:` over an empty directory, a copy that was never written.
|
|
`a copy that meets an empty target directory ...` pins that. It also fixes in a test the behaviour
|
|
that an empty directory at the target is replaced. If Filbert judges that incidental, mutant 3 is
|
|
equivalent under real inputs and that test can go; the non-empty test
|
|
(`a copy that meets a target holding files ...`) stays either way, since it holds the stand-in-free
|
|
outcome (`exists:`, nothing moved into the target, temp directory removed).
|
|
|
|
## Suites
|
|
|
|
- Both service test files on the unmodified script, candidate: 33 pass, 0 fail (32 before the
|
|
empty-target test).
|
|
- webui `node --test tests/`: 104 pass, 0 fail.
|
|
- Not run here: `scripts/test-*.sh` and the control-board suite (tests-only change in webui; Sage's
|
|
gate rerun covers them).
|
|
- After the runs no process had a cwd under my scratch (checked through /proc cwd links, 0 found).
|
|
|
|
## Secrets scan
|
|
|
|
`build.patch`, `mutants.py` and the mutant outputs: no token, secret, password, api key or private
|
|
key marker.
|