# Queue row 33 build notes (#1508) Filbert, 2026-10-04. Brief: `docs/plans/2026-10-04_queue-follow-ups.md` (blob 1dc08bf0…). Reviewer: Darkwing. Base: HEAD 3e39a26a, queue rev 45. Candidate: `candidate-manifest.sha256` in this directory, uncommitted. Sage commits it after approval. ## What changed 1. **Genesis and the owner-not-reviewer rule.** `parseMigrationMap` refuses a map row whose owner is among its reviewers: "migration map row N owner SEAT can't be a listed reviewer", exit 2. Genesis parses the map before it writes anything, so no file, witness or view changes. 2. **Assign wording.** "can't assign row N to SEAT: SEAT is one of its reviewers". The two tests that matched the old text now match this one. 3. **HEAD moved.** `queue-commit.sh` gains `head_moved`, called in `guard_check` before the canary and again when the clean run fails. A moved HEAD exits 2 with "refused (STEP): HEAD moved since H was recorded (another commit landed); run queue-commit.sh again". A real guard failure, with HEAD unmoved, keeps the old message. 4. **Calendar dates.** `checkTime` refuses any ISO time or date that doesn't format back to itself through `Date.parse` and `toISOString`: "WHAT is not a calendar time|date: VALUE". A shape error keeps its old message. Every time the validator reads goes through `checkTime`: row times, review times and log entry times. 5. **Cold start.** See "Cold runs" below. README: the commit steps, the owner rule and the time format. DEFERRED: four items move to Done, and the cold-start item too, if no failure shows up. ## Choices - **C1. The genesis check sits in the map parser, not in replay.** The review-record refusal is kept as defense in depth for a log written before the rule (`review.test.mjs`). A check in `checkGenesis` would make such a log unreadable. A new data test pins this: the parser refuses the map, and a genesis document built past the parser still loads. Mutant M10 (the rule added to replay) is killed by it. - **C2. "another commit landed", not "another queue commit landed".** The brief quotes the second wording. The check before the canary fires for any commit, including one that touches no queue file, so "queue" would be wrong there. The rest of the message is the brief's. - **C3. HEAD is checked twice.** The brief asks for a check before the canary. A commit can still land between that check and the hook run, and then the old misdiagnosis comes back. A second check, only when the clean run fails, closes that gap. It adds one `rev-parse` on a failing path only. - **C4. Two existing F1 tests changed.** - "HEAD moving after commit-tree and before update-ref" moved its trigger to `before update-ref`. A move after commit-tree is now caught at the step-7 check (exit 2). The test still proves update-ref's expected-old-value check, now at the only point where it's the last line. - "H is recorded before the canary…": a commit outside the queue files during the step-1 canary used to reach update-ref (exit 1). It's now refused at the step-7 check (exit 2), before that check's canary, and update-ref never runs. The test asserts that. - **C5. 24:00 is refused.** V8 parses `T24:00:00.000Z` as the next day's midnight, so it doesn't round-trip. Minute 60 and second 60 already parse as NaN. ## Tests - `data.test.mjs`: - a new genesis test (map refusal; replay tolerance); - a new calendar test: month 13, month 0, day 32, 2026-02-30, 2027-02-29 and 2026-04-31 as dates in `requiredSince` and `createdAt`; the same days plus 24:00, minute 60 and second 60 as ISO times in `updatedAt` and `requiredSince`; 2028-02-29 valid in both forms; the shape message kept; a log entry `at` refused on replay; - the assign wording. - `store.test.mjs`: genesis from a map with row 9's owner among its reviewers exits 2. For that repository and the two refusals before it, there's no queue.json, no witness and an unchanged QUEUE.md. Also the assign wording. - `commit.test.mjs`, two new tests, both with a nested `queue-commit.sh` run landing a real queue commit: - after `symbolic-ref` (H recorded, before step 1's check): refused at step 1 with the HEAD-moved message, no canary run, and a rerun commits the next revision; - before the first `git hook run`: the clean run fails on the moved HEAD, and the recheck reports HEAD moved, not the guard. The existing "the canary refuses a hook that git would not run" test still covers the guard message. ## Mutants Eleven, run on an export of the candidate. Ten are killed: | | Mutant | Killed by | |---|---|---| | M1 | no HEAD check before the canary | step-1 and step-7 HEAD tests | | M2 | no recheck after a failed clean run | the between-check-and-canary test | | M3 | `head_moved` exits 1 | all three HEAD tests | | M4 | no round trip | calendar test | | M5 | NaN check only | calendar test | | M6 | round trip on ISO times only | calendar test | | M7 | round trip on dates only | calendar test | | M9 | genesis rule removed | data and store genesis tests | | M10 | genesis rule also in replay | data genesis test | | M11 | old assign wording | data and store assign tests | One survives: - **M8** compares only the date part of an ISO time. It's equivalent under V8. The only out-of-range time V8 parses is 24:00, and that moves the date, so the date part catches it. ## Suites On the final candidate bytes, HEAD 3e39a26a: - canonical checkout: `node --test packages/queue/tests/` passes 148/148 and `bash scripts/test-queue.sh` 29/0; - an export of HEAD with the candidate files: `bash scripts/test-queue.sh` 27/0 (the live checks skip, as designed); - `queue verify --current`: ok at rev 45. The live log replays under the calendar check. ## Cold runs Not reproduced in 20 cold runs. `cold.sh` (here) built each tree fresh from HEAD 3e39a26a plus the candidate files: odd runs as a `git clone --shared` with push set to DISABLED, even runs as a `git archive` export. It ran `node --test packages/queue/tests/` once in each, one run at a time with nothing else running, then deleted the tree. Every run passed 148/148, 2960 of 2960 in total, taking 39 to 61 s each. The counts are in `cold-runs.txt`. The 300 ms deadline test is unchanged. Run 1 started with a `queue-commit.sh` that differed from the candidate in one comment line, the step-1 comment, which I reworded during run 1. Runs 2 to 20 used the candidate bytes.