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.
3.9 KiB
3.9 KiB
Filbert review: row 113 round 1 (#1607): approve
Candidate manifest sha256 4eed1d6405a505e88cde5062c61f768639d899b8f301019b1403d68fb15d9d36 (5 files), as named in comment 28402. I rebuilt it in my own worktree at BASE cc48b124f with build.patch from packet d6ea56831. All 5 hashes match, git diff --check is clean, no manifest path has drifted from cc48b124f to HEAD, and the patch's added lines have no dashes, bidi or control characters.
The brief, item by item
- Reasoning summaries. In
t3.mjs, the skip is the first thing after the counted-thread filter. It sits before the role, text,created_atand header checks, and it needs both rolereasoningand an id startingreasoning:. The message query reads every message in the project's threads with no date bound, so "at any date" in the README is accurate. Rolereasoningwith any other id, andsystem, still fall through to the unknown-role refusal. - Issue pages.
readIssuessends the same query withpage=Nand stops at the first page with fewer than 50 rows. At most 10 pages are read, and a full page 10 refuses with exit 2. Each page gets the old record checks. A duplicate number, within a page or across pages, refuses with exit 2. A failed page keeps the old reason rules (exit status or ENOENT, never stderr or body) and adds the page number. The text printsIssues: N pages read from Gitea, and the JSON hasissueSource.readIssueshas one caller,cli.mjs. - README. It covers the reasoning skip and the remaining refusals. The Gitea section describes the loop, the ceiling, the 50-row check and the duplicate refusal. "one-call boundary" and "not hidden pagination" are gone.
- Tests. The brief's T3 and page cases are all present (see build.md's table).
The points Darkwing asked about
- cli.mjs scope. I agree.
readIssuesnow returns{ issues, pages }, socli.mjshas to unpack it. The page count it records is the coverage line the brief allows there. The three changed lines are the whole cli diff. reasoningMessagesin the JSON only. I agree.t3Lineprints no excluded counts, and the imported and deleted thread counts are already JSON-only, so "next to" them means int3.excluded. Adding a text line would change output the brief didn't ask about.- More than 50 rows refuses. Correct, and needed. Without it, a 51-row page counts as full and the loop reads on. It shares the malformed-records message, which the test pins.
- "at most 21 calls". Correct: up to 10 metric pages, 1 open-list call and up to 10 lookups. The open-list and lookup code is unchanged.
Mutants, rerun by me (ledger.test.mjs alone)
| Mutant | Result |
|---|---|
| m1, the packet's (no id prefix check) | 55 pass, 1 fail: the role table's x-1 row |
| m2, the packet's (return after page 1) | 50 pass, 6 fail: the six multi-page tests |
| f3: duplicate check disabled | 55 pass, 1 fail: "an issue number on two pages refuses" |
| f4: the more-than-50 check dropped | 55 pass, 1 fail: "page 2 with more than 50 rows refuses" |
f5: ceiling page < 10 |
55 pass, 1 fail: "a short page 10 is read..." |
I restored the source after each one and rechecked all 5 hashes.
Notes (not blocking)
- N1. The comments in
queue-checks.mjs(lines 4, 81 and 113) still say "the metric call". The brief puts that file out of scope, so this is for a later row that touches it. - N2. I agree with build.md's scope note 4. An issue deleted mid-read can shift a row up across a page boundary without being caught.
updated_atonly grows, so an update can't cause it. The brief asks only for the duplicate refusal.
What I ran (single files, no slot)
ledger: ledger.test.mjs 56/56, queue-checks.test.mjs 20/20, plus the five mutants above. I didn't rerun the full gate. For that I relied on gate-run.log: GATE_PASSED, ledger 86/0. The worktree is removed and no process is left in it.
Verdict: approve.