Built by filbert, approved by darkwing in round 1 (#1508 comment 26651). Manifest fe7da3ef, 10 paths. Suites green on an index export. Co-Authored-By: Claude Opus 5.5 <[email protected]>
6.4 KiB
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
- Genesis and the owner-not-reviewer rule.
parseMigrationMaprefuses 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. - 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.
- HEAD moved.
queue-commit.shgainshead_moved, called inguard_checkbefore 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. - Calendar dates.
checkTimerefuses any ISO time or date that doesn't format back to itself throughDate.parseandtoISOString: "WHAT is not a calendar time|date: VALUE". A shape error keeps its old message. Every time the validator reads goes throughcheckTime: row times, review times and log entry times. - 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 incheckGenesiswould 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-parseon 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.
- "HEAD moving after commit-tree and before update-ref" moved its
trigger to
- C5. 24:00 is refused. V8 parses
T24:00:00.000Zas 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
requiredSinceandcreatedAt; the same days plus 24:00, minute 60 and second 60 as ISO times inupdatedAtandrequiredSince; 2028-02-29 valid in both forms; the shape message kept; a log entryatrefused 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 nestedqueue-commit.shrun 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.
- after
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 andbash scripts/test-queue.sh29/0; - an export of HEAD with the candidate files:
bash scripts/test-queue.sh27/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.