6.2 KiB
Row 51, cohort release follow-ups, round 2 review (Darkwing)
Issue #1537, request comment 27072, notes comment 27073, queue revs
304-306. My round 1 was comment 27071 (changes); Sage ruled to move the
call and keep the text. Base b7e9efb7, which changes nothing under
packages/ or scripts/ since round 1's bbb2167f. Candidate manifest
sha256
c34039dc0d52b965bd73cc9f079ae7b253140d77713a3323abc4743f359f0c02,
the same 5 files as round 1. ctrl-child.mjs is unchanged from round 1.
Verdict: approve. #recover now retries the release after the
confirmation check and before the acquire, so a refused recover has no
side effect. The packet's K6 line and the README now match the code. R9
pins the order: every placement of the release above the confirmation
check that I tried (round 1's, above the stop-proof check, and between
the target and confirmation checks) fails R9. The three notes Dewey took
from round 1 each kill the mutant they were aimed at. noseat still
survives and the packet lists it as a follow-up, which I accept.
Method
- Detached worktree at
b7e9efb7, the five candidate files copied from a snapshot of the canonical tree, thensha256sum -c: 5 OK. A second worktree for the mutants; its five files check OK after all runs (r2/mut/manifest-after.txt). - I read the round 1 to round 2 diff in full,
#recoveragain from top to bottom, R7 and R9-R11, the README bullet, the packet's "Round 2" section, and therecovercommand indocs/plans/chat-01/contracts.schema.json. - 11 mutants (
r2/mut/mutate.py,run.sh), the whole conversation suite each, own TMPDIR each, run after the gate finished. After each run the runner lists any shim left under that TMPDIR. No mutant left one.
Node v26.8.1, TMPDIR=~/darkwing-scratch/r51b/tmp, gate.sh with
DOCKER_HOST=unix:///nonexistent.sock, 06:43:17Z to 06:46:47Z, then
control-board and queue (node).
Suites
| Suite | Result |
|---|---|
| conversation | 177/0 |
| webui | 22/0 |
| control-board | 124/0 |
| queue (node) | 148/0 |
| test-auth | 15/0 |
| test-conductor | 17/0 |
| test-config | 24/0 |
| test-discord | 66/0 |
| test-extension-package | 18/0 |
| test-foundation | 44/0 |
| test-queue | 27/0 |
| test-release | 4/0 without Docker, 14/0 with it (test-release-docker.txt) |
| test-task | 26/2 |
The two test-task failures are "user recall run succeeds" and "recalled
user name", the live worker check that needs Docker and a model call, as in
round 1. Dewey's 98/0 ran them. The one mosaic-chat-* unit counted right
after the conversation suite was gone at the gate's end, and none was
listed after the mutants.
The recover order
if (... !this.#stopped(s)) return refused("stop-proof");
... pins, refused(ENGINE_PIN_MISMATCH) ...
... session leaf and branch, refused("target") ...
if (!this.#checkConfirmation(r, c, "recover")) return refused("confirmation");
// After every check, so a refused recover changes nothing (K6).
await this.#releaseListed("recover", this.claim);
... acquire ...
That's option 1 from my round 1 review. R9 now sends two recovers with the
socket back before the confirmed one: one with a confirmation ID that was
never issued, and one with a confirmation confirmed for force-stop. Both
come back confirmation, evidence.releases is still the one unavailable
entry, and the unit is still active. The packet says a recover with no
confirmation field is refused malformed before #recover. I checked:
the schema's recover command lists stop and confirmation as required,
and the controller's malformedRequest runs before dispatch and refuses a
recover whose fields don't match SHAPES.recover (stop and
confirmation, both IDs).
The await between the confirmation check and the acquire lets another
command run in between. That isn't new: the acquire was already awaited,
so two recovers could interleave before this row.
Mutants
| Mutant | Change | Conversation | Result |
|---|---|---|---|
| recconf | the release right after the stop-proof check (round 1's order) | 176/1 | killed: R9 |
| recbefore | the release above the stop-proof check | 176/1 | killed: R9 |
| recpreconf | the release after the target check, before the confirmation | 176/1 | killed: R9 |
| norecover | recover releases nothing | 176/1 | killed: R9 |
| nodelete | #releaseListed never drops an earlier result |
176/1 | killed: R9 |
| startnoawait | the free-path release isn't awaited | 176/1 | killed: R7 |
| nolookup | #releaseListed sends a request for a unit already absent |
176/1 | killed: R11 |
| closeproof | close skips the signal only while #stopped() still accepts the stop |
176/1 | killed: R10 |
| closekill | close signals after a proven stop | 175/2 | killed: R10, R11 |
| recafteracq | the release moves to just after the acquire | 177/0 | survives: see note 1 |
| noseat | the free path checks only the session head | 177/0 | survives: the packet's follow-up |
recpreconf is the one placement Dewey's table doesn't have. It's the
closest wrong order, past every check except the confirmation, and R9
catches it like the others.
Notes (not blocking)
recafteracqsurvives. The packet's K17 line says the recover release runs "after them and before the acquire". After the acquire it still acts onthis.claim, the stopped record the acquire doesn't replace, so no test can tell the two apart from outside. I see no safety difference either: both orders release only a proven-stopped cohort, and both run only on a recover that passed every check. The one difference is a recover whose acquire throws: before the acquire, the release has already happened. That's fine for a recover that passed its confirmation. R7's trick (the launcher readsevidence.releases.length) would pin the order if anyone wants it. I don't need it.noseatsurvives, as the packet says. It needs a second session on the same seat. I agree it's a follow-up and not this row.- Dewey's other follow-ups stand as in round 1. The
uncertainbinding whose engine exited on its own is row 52's.
Files
r2/candidate-manifest.sha256: copy of Dewey's.r2/gate.sh,r2/out/: suite runs andsummary.txt.r2/mut/: mutant definitions, runner, per-mutant output and shims-left lists,summary.txt, and the manifest check after the runs.