Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
4.2 KiB
Row 101 round 1 (#1595), Filbert: approve.
Candidate manifest SHA-256: ee1335a6e44610f676ade116733d180ac6f0b3603a58306110cbd1dd1e9c1f69. Base: 0d71b9ddd. Packet: agents/researcher/work/queue-101/r1/. This answers request 28244.
I rebuilt the candidate in my own worktree at 0d71b9ddd and applied build.patch. All 5 manifest hashes match, git diff --check is clean, and the worktree shows only the 5 paths. None of the 5 paths changed from 0d71b9ddd to the current refactor head. No dashes, curly quotes, bidi or soft-hyphen characters appear in added lines. My review is static: I ran no suites, mutants or queue-commit.sh.
What Sage asked me to check
The refusal follows the idempotent-retry return. In mutateAs the order is: step 3 (a recorded op with the same verb and args returns its receipt, or a different payload is refused), then accept-history, then step 4 (view unknown or stale refusals), then the new check, then step 5 (resolveFor, applyEntry, write). So a retried add whose op is already in the log still gets (already recorded at rev N), including an add recorded before this row with gateOwner: null. canonArgs gives gateOwner: null when the flag is absent (nullable, queue.mjs:459), so === null is the right test. The refusal throws inside withLock before any write, and test 3 shows queue.json, QUEUE.md and the revision unchanged for both jason and sage. Correct.
data.test.mjs direct applyEntry adds rightly untouched. step() (data.test.mjs:38) builds the entry and calls applyEntry directly. It never reaches mutateAs, and applyEntry is unchanged from base (queue.mjs isn't in the patch). Adding gateOwner there would change rows those tests assert (a.gateOwner ?? "jason", queue.mjs:916). Leaving them alone is right.
Brief and rulings
- What ships: a privileged add without
--gate-owneris refused with exit 2, the message names the flag, and the refusal comes before the entry is written. A non-privileged add is unchanged (refused if it names one, getsjasonotherwise).applyEntry,canonArgs, replay and the log format are unchanged, and SEMANTICS stays 2, so the live Console's old store.mjs keeps loading new entries. Explicit--gate-owner jasonstill works for a gate that is meant to be Jason's. - The store.mjs change is one check in the write path, per Sage's ruling. The store.test.mjs edits are exactly the four listed lines (179, 229, 248, 397), each gaining
--gate-owner filbertand nothing else. - No other code calls
queue add(I searched packages and scripts outside tests), so no programmatic caller breaks. - Tests cover the four cases the brief names: refused and nothing written, named owner carried, non-privileged gets
jason, and an old privileged add with null gate owner replays (semantics 1 and 2, throughloadDoc). - usage text and README say the flag is required for jason and sage, and why. The README paragraph is new and sits after the owner-as-reviewer paragraph. Since the README had no
addparagraph before, that is a fair reading of "the add paragraph only".
Notes (none blocking)
- N1. The ordering Sage asked about is right by the code but no test pins it. Every retry test passes
--gate-owner, so moving the new check above step 3 would still pass the suite. Then a retry of an add recorded before this lands (for example, a request repeated after landing) would be refused instead of answered with its receipt. A test that appends a sage add with null gate owner to the log (asaddUnderdoes), then retries the same op and args through the CLI and expects(already recorded at rev N), would pin it. A sixth mutant that hoists the check would show it. Worth a follow-up, not a reason to hold the row. - N2. The refusal message ends with "(row 100 got jason by default)". A permanent CLI message that cites one row's history will read oddly later. The store.mjs comment already carries that history. Cosmetic.
- N3. The packet's gate ran in a worktree, so the
queue verify and render --checkcase of test-queue.sh was skipped, and that is the check closest to the brief's "queue verify --currentpasses on the current file". Replay is unchanged by construction, but Sage's gate rerun from the canonical root is the evidence of record for it.