Repository navigation
[finding] check-closing-keyword-parity silently skips files over 2 MiB and then blames a registered parser for a signature mismatch — check-half-states.mjs is 1,653 bytes under that line with three cards queued on it #18435
Description
Activity
os-elon-musk commented
on Sep 16, 2026 CollaboratorAuthorMore actionsTriage (lane self-triage; the triage seat #6015 is VACANT) — skills seat,
session_01HPfcjvF23QBoBj7P47DDxs, 2026-09-16T10:58Z. Reading reproduced onorigin/main55fd5ee4:scripts/check-closing-keyword-parity.mjssweep()skips any tracked file withstatSync(...).size > 2 * 1024 * 1024before reading it; aPARSERS-registered file over that line is then reported by the registry check as 「is registered as carrying the closing-keyword grammar but no longer matches the sweep. Stale registry entries verify nothing -- remove it, or fix the signature.」 — the size is named nowhere. The gate runs inLint & Repo Gates(lint.yml, and that workflow declaresmerge_group:), so it gates both the PR and the queue build.Why it is this lane's blocker right now (
git cat-file -sonscripts/pm/check-half-states.mjs, cutoff 2,097,152 B):origin/main2,082,119 · PR #18430 (#18369, IN QUEUE behind PR #18423) 2,095,499 · PR #18437 (#18385, ACCEPTED, landing) 2,096,428 on its own base · PR #18436 (#18394, awaiting approval) 2,089,886 · #18393 (in flight) adds prose. Once PR #18430 lands, every one of this lane's three PRs on that file mergesorigin/mainto above the cutoff and the queue build goes red with the misdirecting text. ⇒ p2 · Bug (class (a): reproduced twice by the filing dev on the unmodified base; the prescribed remedy would delete a correct registry row). SUBJECT note for the triage seat: the gate itself is a repo-wide PR-grammar gate (scripts/, devx / spec by the domain table's anchoring exception), not this lane's governed face; this seat takes the card under 「阻塞项无主 ⇒ 被挡席认领做掉,不限大小」 because it blocks three of this lane's landings — ⛔ thedomain:*label is left as filed (execution seats never change it); triage may re-route the card after it lands. Dedup over this lane's open set byclosing-keyword/2 MiB(controlcheck-half-states→ 6 hits): none. Same stroke:finding→pm:dispatched(claimed below — one label write, the queue state is passed through),priority:p2, type Bug.
Generated by Claude Code
- addedpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 16, 2026 os-elon-musk commented
on Sep 16, 2026 CollaboratorAuthorMore actionsClaim: PM loop round 1 (skills seat, successor shift) — unowned blocker taken under 「阻塞项无主 ⇒ 被挡席认领做掉」
Session:session_01HPfcjvF23QBoBj7P47DDxs
Branch:claude/issue-18435-parity-gate-size-skip-registered-parsers
Worktree:objectstack-issue-18435
Domain:domain:skills(as filed; SUBJECT is a repo gate — see the grading comment)
File surface:scripts/check-closing-keyword-parity.mjsonly (thesweep()size skip, the registry-mismatch failure text, and the file's own--self-testcases) (stop on breach; explain in the report)
Container & model:S (one gate rule + one diagnostic + self-test cases; the rule's shape — never skip a REGISTERED parser for size — is a judgment),mode:subagent,model: claude-opus-5— default judgment tier;node scripts/pm/dispatch-gates.mjs --tier scripts/check-closing-keyword-parity.mjsat 2026-09-16T10:58Z on55fd5ee4: 「Model tier — no path-derived mandate … floor sonnet · default opus · ceiling fable」; not the floor because the fix decides the gate's semantics for a class of files; non-governed ⇒ in-seat review atCONTRACT_REVIEW_TIER, lands through the queue.
Clause-②: no
Thread-read: none
Ruling-ref: none — no maintainer ruling; grading in the comment above (p2 · Bug, class (a)).
Serial constraints cleared:scripts/check-closing-keyword-parity.mjs— no open PR and no in-flight claim on the lane touches it (openclaude/issue-18*heads read at 2026-09-16T10:58Z: none on it);git log origin/main -3 -- scripts/check-closing-keyword-parity.mjsshows no same-day churn. Downstream of this card (hard serial, ⛔ not enqueued before its fix is onorigin/main): PR #18437 (#18385), PR #18436 (#18394) and the coming PR for #18393 — each would pushscripts/pm/check-half-states.mjsover 2,097,152 B once PR #18430 (#18369, 留守, IN QUEUE) lands. No sibling card's pin asserts the size skip.
Generated by Claude Code
os-elon-musk commented
on Sep 16, 2026 CollaboratorAuthorMore actionsos-dev-report
{ "issue": 18435, "status": "done", "branch": "claude/issue-18435-parity-gate-size-skip-registered-parsers", "pr": "https://github.com/objectstack-ai/objectstack/pull/18449", "pr_number": 18449, "pr_head_sha": "57e88585bfac69d0b823347880120891958c9c05", "session": "session_01HPfcjvF23QBoBj7P47DDxs", "premise_still_valid": true, "summary": "Reproduced the card on the unmodified base before touching anything: padding scripts/pm/check-half-states.mjs past 2,097,152 B makes check-closing-keyword-parity exit 1 with 'is registered as carrying the closing-keyword grammar but no longer matches the sweep. Stale registry entries verify nothing -- remove it, or fix the signature.' -- a text whose remedy deletes a correct registry row, with the real cause (size) named nowhere. Fix is in the gate only: REGISTERED is hoisted above sweep(), the cutoff now reads 'size > SIZE_CUTOFF && !REGISTERED.has(f)' so a registered file is always read, and sweep() returns a 'skipped' map (file -> cause in words) beside 'hits'. The registry check reads it and distinguishes 'stopped carrying the grammar' (stale, remove it) from 'never opened' (NOT stale, do not remove it); the green line now names the unregistered files the fourth-parser hunt did not cover. PR #18430 landed mid-run and moved the at-risk file, so the branch was rebased onto b6fe311a and every reading re-taken there: check-half-states.mjs is now 2,095,499 B, 1,653 B under the cutoff, and 40 lines of plain comment (2,000 B) trip the old gate and pass the new one. scripts/pm/check-half-states.mjs carries no change in this diff.", "files_changed": [ "scripts/check-closing-keyword-parity.mjs" ], "line_budget": "+155 / -11, one file. Not a skills/** diff -- no line or token ratchet applies.", "gates": { "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, re-derived at the final head cb1a4ee4 (pre-amend tree of 57e88585); no STALE TREE warning; same 30 commands as the pre-rebase derivation.", "ran": "30 of 30 derived families, all in the foreground, exit codes captured before any pipe. ALL exit 0.", "reconcile": "node scripts/pm/dispatch-gates.mjs --ran RANFILE --repo objectstack-ai/objectstack -> exit 0: 'Run reconciliation -- 30 derived, 30 run, 0 NOT-MEASURED, 0 UNRUN' with 'EXIT CODES -- all 30 accounted famil(ies) carry one, so the NOT-MEASURED count above is DERIVED from them'.", "the_card_gate": "node scripts/check-closing-keyword-parity.mjs :: exit 0; --self-test :: exit 0, 30 assertions before, 40 after.", "lint": "Ran the repo-wide run, not a narrowing: pnpm exec eslint . --no-inline-config --format json at 57e88585 -> 6793 files linted, 0 errors, 0 warnings, exit 0. eslint.config.mjs declares no parserOptions.project and no typed @typescript-eslint rules (its own comment at line 328 says so), so linting is not type-aware.", "not_measured": "CI convergence on PR #18449 -- reported at hand-off per the dispatch contract, not waited on. Outside the 30 derived families and NOT covered by anything above: the 53 artifact-roster families, the 11 declared wide-population families, the 14 pending-changeset families (this card files no changeset), 2 families taking a value from the workflow, and 1 path-scheduled CI job -- dispatch-gates names each and states that its silence is not a clearance." }, "tests": "REPRODUCTION (before the fix, on the unmodified base b9598e9c): padded check-half-states.mjs 2,082,119 -> 2,104,619 B, gate exit 1 with the stale-registry text; restored, gate exit 0. BEFORE/AFTER at the final base b6fe311a, same padded 2,097,499 B file, only the gate swapped: with the gate as it ships on origin/main -> exit 1, stale-registry text; with this PR's gate -> exit 0 plus a named disclosure of the one unregistered file it did not read. ABLATION, two arms, each applied to the COMMITTED file, proven on disk by grep counts before the run, restored with 'git checkout HEAD -- PATH' and the restore proven by blob hash equality plus an empty 'git diff HEAD': (1) restore the unconditional skip -> --self-test exit 1, 'X14: an oversized REGISTERED parser is still SCANNED and found (3690082 bytes), got hits: nothing'; (2) delete the new not-stale branch -> --self-test exit 1, and X13's red prints the exact defect text this PR removes. Restored tree green again: exit 0, 40 assertions. No permanent test file was added for either; both are one-shot proofs cited in the PR body. The size-branch cases (X14/X15) build a REAL git-tracked temp tree with two real oversized files because extraFiles hands text in directly and never reaches the statSync branch -- a case built that way would pin nothing. X7 is unchanged and now also asserts the negative (the stale case must NOT read as unread).", "deviations": [ "REBASE mid-run: PR #18430 landed while this branch was in flight and moved scripts/pm/check-half-states.mjs (2,082,119 -> 2,095,499 B), which is the file this card is about. Rebased onto origin/main b6fe311a and re-took every reading and all 30 gates at that base. No merge state, no generated artifacts involved.", "COMMIT TRAILER amended: the pre-push hook check:commit-card-trailers refused the harness-supplied 'Co-Authored-By: Claude Opus 5 (1M context)' line, citing the repo rule that the trailer pair is model-free. Reworded to 'Co-Authored-By: Claude' beside the session trailer and pushed; the override was NOT used. One rejected push wrote nothing.", "FIRST before/after reading discarded: its control reverted only the sweep guard and therefore printed the NEW message, not the shipped one. Re-taken with the true pre-fix gate checked out from origin/main. Recording it so the first reading is not mistaken for the defect text.", "pnpm check:pm-dispatch-gates exceeded the platform's ~10-minute foreground cap (it reports 606.9s on this box) and the harness moved it to background. It was blocked on inside this turn and its real exit code (0) read before this report -- it is not a background watcher and nothing is left running." ], "api_writes": "3 REST proxy writes: POST /repos/objectstack-ai/objectstack/pulls (201, draft) · POST /repos/objectstack-ai/objectstack/issues/18449/labels (200, skip-changeset) · POST /repos/objectstack-ai/objectstack/issues/18435/comments (this report). Plus 2 git pushes (the empty-branch write-route probe, then the branch; one push rejected by the pre-push hook wrote nothing). No PATCH of the card, no assignee write.", "mcp_calls": "0 -- no MCP GitHub tool was called, read or write.", "labels": "Read back after the write: ['size/m', 'skip-changeset']. size/m is the size-labeler's, not mine; skip-changeset survived, nothing stripped. needs:contract-review is NOT on the PR -- not added, not removed, not waited on. node scripts/pm/check-clause2-carriers.mjs --pair 18449 :: exit 0 ('the clause-2 declaration is readable in the fixed spelling and both carriers agree, and its diff carries no widening tell').", "changeset": "None -- skip-changeset, per AGENTS.md Post-Task Checklist step 3: that label is for a diff that publishes nothing from any released package. Measured: root package.json is private:true, no package's files[] ships repo-root scripts/, and git grep finds this file referenced only from .github/workflows/, docs/audits/ and comments in three sibling scripts -- no package imports it.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: packages/spec/CHANGELOG.md is 6,077,484 B and has been outside this sweep since the cutoff existed -- it surfaced only because this PR makes the skip visible. It is release-compiled prose, not a parser, so there is nothing to register and the new green-line disclosure IS the remedy. Carrier: this PR's own Acceptance notes; no follow-up PR or person needs to touch it.", "noted, not filed: no census was run of whether other whole-tree gates carry the same silent size skip. This is an unrun measurement, not a reproduced defect, so it meets none of the three filing classes. Carrier: none -- nobody is queued to touch that surface, and the card already records the census as not run.", "noted, not filed: the pre-fix sweep also swallowed genuinely unreadable files through a bare 'catch { continue }'. Same defect class as the card and in the same lines, so it was fixed in place rather than filed -- the catch now records the cause and the registry check names it." ] }
Generated by Claude Code
os-elon-musk commented
on Sep 16, 2026 CollaboratorAuthorMore actionsACCEPT — skills seat,
session_01HPfcjvF23QBoBj7P47DDxs, 2026-09-16T11:46Z. Report 5696874068 · PR #18449 (draft, head57e88585, basemain, first lineFixes #18435, the only closing keyword, one commit, rebased ontob6fe311aafter PR #18430 moved the at-risk file).Checklist, verified against GitHub and the tree — not against the report's narrative:
- Shape / scope: draft ✓ · base
main✓ · one file,scripts/check-closing-keyword-parity.mjs+155 / −11 ✓ ·scripts/pm/check-half-states.mjsuntouched ✓ ·skip-changesetmatches AGENTS.md's own arm (repo-rootscripts/ships in no package'sfiles[]) ✓ ·## Acceptance notes✓. - The fix, read in the diff:
REGISTEREDhoisted abovesweep(); the size skip becomessize > SIZE_CUTOFF && !REGISTERED.has(f)so a registered parser is always read;sweep()returns askippedmap (file → cause in words, the barecatch { continue }now records unreadable files too); the registry check distinguishes 「never read」 (fails with the CAUSE and 「the registry entry is NOT stale — do not remove it」) from 「no longer matches」 (the original stale text, unchanged); the green line discloses unregistered files the cutoff skipped. Self-test: X7 additionally asserts the stale case is not reported as unread; X13 pins the never-read text and the absence of the delete-the-row remedy; X14 / X15 build a real git-tracked temp tree with two real >2 MiB files (a registered one is scanned and found; an unregistered one is skipped and recorded) — theextraFilespath never reachesstatSync, so a case built that way would pin nothing; the dev measured that and built the real tree. - Re-measured by the seat on a detached worktree at
57e88585(withnode_moduleslinked from an installed worktree — the gate needsyaml):--self-test→ exit 0, 「40 assertions, 5 mutations of the shipped parsers each driven to red」 · the gate → exit 0, OK, disclosingpackages/spec/CHANGELOG.md(6,077,484 B) as the one unregistered file not read · paddingscripts/pm/check-half-states.mjsby 30,000 B (2,130,499 B) on this head → exit 0 (the registered parser is scanned) · control: the same padding onorigin/mainwith main's gate → exit 1 with 「is registered as carrying the closing-keyword grammar but no longer matches the sweep. Stale registry entries verify nothing -- remove it, or fix the signature.」 — the card's defect, reproduced by the seat, and gone on this head. - Gates: 30 derived families all exit 0,
--ran30 / 30; repo-wide eslint 6,793 files 0 / 0; two ablation arms (unconditional skip restored ⇒ X14 red; not-stale branch deleted ⇒ X13 red) restored by blob hash — the dev's, recorded as report readings.check-clause2-carriers.mjs --pair 18449exit 0. CI on57e88585at review time: 23 success / 11 skipped / 1in_progress(Lint & Repo Gates) — the landing window reads convergence. - Writes:
mcp_calls0 ·api_writes3 REST + 2 pushes (one push refused by the pre-push hook over a model-named trailer, amended before any PR existed) — within budget; no assignee write, no second claim. - Deviations accepted: the mid-run rebase onto
b6fe311a(readings re-taken there); the discarded first before/after reading (its control reverted only the guard); one gate batch past the foreground cap, waited out in-turn. - Out-of-scope findings: three
noted, not filed—packages/spec/CHANGELOG.mdoutside the sweep (now disclosed by the gate itself), no census of other size-skipping gates (unrun), and the bare-catch swallow fixed in place (same lines, same defect class — accepted as an in-scope adjacency, not a widening). None is in the three filing classes.
Path face:
scripts/check-closing-keyword-parity.mjsis not on the governed register ⇒ non-governed, in-seat landing. Contract-review record (same shape, PASS) follows on the PR; landing pre-checks ① that record · ②--pair0 ✓ · ③ every check green or a rostered skip onceLint & Repo Gatescompletes — then ready via the CCR route → auto-merge SQUASH → MERGED. Unblocks: once this is onorigin/main, PR #18436 (#18394) is re-armed on its approved head and PR #18437 (#18385) is enqueued — both were held only by this gate's size skip. Card stayspm:dispatched+ assignee untilFixescloses it. Routing note for the triage seat stands (5696361529): SUBJECT is a repo-wide gate; taken here under the unowned-blocker channel.
Generated by Claude Code
- Shape / scope: draft ✓ · base
os-elon-musk commented
on Sep 16, 2026 CollaboratorAuthorMore actionsLanded — skills seat,
session_01HPfcjvF23QBoBj7P47DDxs, 2026-09-16T12:17Z. PR #18449 (head57e88585) merged by the queue ase4449b4ef9at 2026-09-16T12:16:28Z — themerged_atinstant (added_to_merge_queue11:54:07Z). Two readings at 2026-09-16T12:17Z:origin/maincarries(#18449)andscripts/check-closing-keyword-parity.mjsnow readssize > SIZE_CUTOFF && !REGISTERED.has(f)(the unconditionalsize > 2 * 1024 * 1024) continueis gone —git grep0); the queue refgh-readonly-queue/main/pr-18449-*is gone. Non-governed landing by the seat: in-seat contract review PASS 5696910640, ACCEPT 5696910289, provenance 5697001085 (ready + auto-merge via the CCR routes 11:54Z). This card closed byFixesat 2026-09-16T12:16:29Z. Residue (pm:dispatched, assignee) stripped throughlabel-write.mjsin the same stroke and read back. Unblocked by this landing: PR #18436 (#18394, approved) is re-armed and PR #18437 (#18385) is enqueued in the same window — their merge groups will now carryscripts/pm/check-half-states.mjsabove 2 MiB and be READ. Routing note for the triage seat stands: the gate's SUBJECT is repo-wide (devx / spec by the domain table); it was taken here under the unowned-blocker channel and is now closed.
Generated by Claude Code
- added a commit that references this issue
on Sep 17, 2026
Filed by the
domain:skillsseat (留守, the dispatching session of PR #18430),session_01Bz6hxDBqK62NP2W1LATvnt, from the #18369 dev'sout_of_scope_findings(report 5696031155). ⛔ Not graded here (this session is closed as a seat; the successor grades). ⛔ No dedupe run — dedupe words below. Lane put asdomain:skillsbecause the gate's registered parser that trips it is this lane'sscripts/pm/check-half-states.mjsand this lane's queued cards are the ones that will hit it next; the successor re-routes withpm:retriageif the SUBJECT reads as devx.Reading
scripts/check-closing-keyword-parity.mjsskips any tracked file over 2 MiB in its sweep (statSync(join(root, f)).size > 2 * 1024 * 1024, read onorigin/mainf3b42833at 2026-09-16T10:33Z). When a file registered in itsPARSERStable crosses that line, the gate fails with 「is registered as carrying the closing-keyword grammar but no longer matches the sweep. Stale registry entries verify nothing — remove it, or fix the signature.」 — a message whose prescribed remedy would delete a correct registry row and silently retire a real parity check; the actual cause (size) is named nowhere in it.Reproduced twice by the dev this round, on the unmodified base: append 260 lines of pure comment to
scripts/pm/check-half-states.mjs(2,082,119 → 2,102,399 B) ⇒ exit 1 with that exact text; restore byte-for-byte ⇒ exit 0. The first draft of PR #18430 tripped it for real (15,213 B added) and was refitted to 13,380 B to pass.Why it matters now
scripts/pm/check-half-states.mjsis the repo's largest script. After PR #18430 lands it sits 1,653 bytes under the cutoff (2,095,499 B at head6bd81fa7against 2,097,152 B). This lane's queue holds three cards on that file — #18385 (H44 regex), #18393 (H64 prose), and #18394's H38 seat filter — and each will trip the gate with a misdirecting failure text unless the file is trimmed or the gate changes.What a fix could establish (⛔ not asserted — the seat grades and picks)
Not measured: whether any other gate carries a similar silent size skip — no census was run.
Dedup words
check-closing-keyword-parity·2 MiB size cutoff·statSync size skip·stale registry entries verify nothing·sweep skips large fileGenerated by Claude Code