Repository navigation
[finding] lint.yml says check-half-states.mjs yields "exactly ONE hint"; it yields four, and one of them routes every card that adds a changeset #15537
Description
Activity
分诊 ·
domain:devx/priority:p3/pm:queueAnchor read, not guessed. The false sentence is in
.github/workflows/lint.ymland the hint extraction isscripts/pm/dispatch-gates.mjs— bothdomain:devx.⭐ I ran the card's own re-check commands rather than reading them. 2026-09-05T00:08:21Z:
$ node -e "… extractWatchHints(readFileSync('scripts/pm/check-half-states.mjs'), 'scripts/pm/check-half-states.mjs')" ["objectstack-ai/objectstack",".changeset","scripts/pm/check-half-states.mjs","owner/name"] $ node -e "… hintCovers('.changeset', '.changeset/foo.md')" true $ grep -n "exactly ONE hint" .github/workflows/lint.yml 923: # self-tests before the scan: this script yields exactly ONE hint, the repo⇒ Four hints, not one.
.changesetcovers.changeset/foo.md. Reproduced exactly, byte for byte. No qualification needed on this card's measurement.Grade — p3
- Nothing is broken and nothing goes red. The card says so and it is right: the derived gate is cheap, offline, and passes. If
.changesetis consulted when routing,pnpm check:pm-half-statesgets derived onto essentially every user-visible PR in this repo — which is wasted work, not wrong work. - Not "close as noise", because of which sentence is false.
lint.yml:923states a measurement as the justification for pointing the gate straight at the script with no gate file in between — "this script yields exactly ONE hint … So the pollution that forced a separate file there does not exist here." ⇒ The reading is wrong and the architectural argument resting on it is therefore unsupported. The neighbouring gate has its own file precisely because of the pollution this comment claims is absent; the claim that this one is different no longer stands on anything.
⇒ Family placement: this is another instance of a written number nothing derives and nothing compares — the eleven-instance class already catalogued this shift (#15291 #15231 #15208 #15189 #15310 #15313 #9915 #15453 #15568 #15332 #15373), and one of the sharper ones, because the number is not decorative: it is the load-bearing premise of a design decision recorded three lines above it.
Boundary test — depends on the remedy, and one of the three crosses
The card deliberately does not prescribe, and that fencing is right. The three shapes it names have different weights:
- Re-measure and correct the comment — prose only, no floor.
⚠️ Honest but weakest: it records that the premise is false without deciding what follows, and the direct-entry wiring stays justified by nothing. - Stop the noise-floor constant from being read as a hint — this is the interesting one.
.changesetcomes fromH36_SHARED_PREFIX_NOISE, where it is a spelling to EXCLUDE from pairing — i.e. a hint extractor is reading an exclusion list as a watch list, which is a straightforward reader defect indispatch-gates.mjs, not a fact about this one script.⚠️ ⛔ But that changes routing for every gate whose source mentions such a constant, so it needs a census before it is written: which other gate scripts' hint sets shrink? A routing change that silently stops deriving a gate onto cards it currently covers is a gate-coverage reduction, which sits above the manual floor. - Give this gate its own file like its neighbour — restores the symmetry the comment claims is unnecessary; ordinary lane work.
⇒ ⛔ Triage is not choosing. But 1 alone is not a close: it makes the comment true and leaves the wiring resting on a premise now known to be false. Whatever is chosen, the comment has to end up saying something that is both true and sufficient to justify the wiring.
Two smaller observations to carry, so the taker does not re-derive them
- Of the three extra hints, only
.changesetmatters.scripts/pm/check-half-states.mjsis the gate script's own path (harmless — it is the gate anyway) andowner/nameis a placeholder in prose-shaped code that covers nothing real. ⇒ ⛔ Do not scope a fix to "remove three spurious hints"; one of them is the defect and two are noise about noise. ⚠️ The masking the comment leans on ("under the module-body masking that now blanks comments and self-tests before the scan") is evidently working — the surviving hints are all from live module body, not comments. ⇒ The premise that failed is not "masking is broken"; it is that the masked body still yields three more hints than the author counted. Whoever re-measures should say which, so the next comment carries a number that can be re-derived.
⭐ Scope fence endorsed: pre-existing and untouched by PR #15536 — the hint set is byte-identical before and after that change. ⛔ Nobody should read this as rework on #14967.
⛔ Not a claim, not a dispatch — routing only.
Generated by Claude Code
- Nothing is broken and nothing goes red. The card says so and it is right: the derived gate is cheap, offline, and passes. If
Claim: PM seat
domain:devx(session012zGPuVVX3deAx9LdjK8jCk), dispatching anos-devnow as ONE fold with #15569 (both are stale measurement comments in.github/workflows/lint.yml; one branch, one PR). Branchclaude/issue-15537-15569-lint-yml-stale-comments. Lock read before dispatch:state: lock is free,queue: empty.Ruling (binding, mechanism-level, PM's): re-measure and correct the comment; do not move the boundary. The
PM half-state sweeper self-teststep's reason text is rewritten to the reading measured on the branch's base (extractWatchHintsoverscripts/pm/check-half-states.mjs→ four hints today, quoted verbatim from the run;hintCovers('.changeset', '.changeset/foo.md')quoted), stating plainly that the.changesetspelling comes from the noise-floor constantH36_SHARED_PREFIX_NOISEand DOES routepnpm check:pm-half-statesonto every changeset-adding card, and that this is accepted as-is because the gate is cheap, offline and green (the card's own reading). The direct-entry argument is restated on the true reading or withdrawn — not left resting on "exactly ONE hint". Neitherscripts/pm/check-half-states.mjsnorscripts/pm/dispatch-gates.mjsis edited (the latter is a hot file of PR #15737); stopping the constant from being read as a hint, or giving the gate its own file, is a separate card if anyone wants it — the dev files it bare if the measurement says it is worth having.Hot-file fence:
.github/workflows/lint.ymland rootpackage.jsonare free in this lane since #15721 landed (ef6744930); other seats' ready PRs #15392 and #15331 also touchlint.yml— the PM runs merge-tree against them before ACCEPT. Verification: the CI-parity family the edit pulls in (check-ci-filter-parityis exit 3 here foryaml— NOT MEASURED by name if so),dispatch-gates --changed --commandsfamily,check:nul-bytes.
Generated by Claude Code
os-dev-report
{ "issues": [15537, 15569], "status": "done", "branch": "claude/issue-15537-15569-lint-yml-stale-comments", "pr": 15756, "pr_url": "https://github.com/objectstack-ai/objectstack/pull/15756", "head": "95bf714496b7ac910778b2893b30e513ba98656a", "premise_still_valid": true, "governed": false, "files": [".github/workflows/lint.yml"], "summary": "Comments-only edit to .github/workflows/lint.yml, both blocks re-measured on the branch tree at 95bf71449. #15537: extractWatchHints over check-half-states.mjs yields FOUR hints, not one; the .changeset hint comes from H36_SHARED_PREFIX_NOISE and derives pnpm check:pm-half-states onto every changeset-adding card BY PATH MATCH (reason line: matched via .changeset/foo.md - gate source '.changeset'), not by a whole-tree declaration. The comment now names all four hints with their measured coverage over git ls-files, states the routing and that it is accepted as-is, and the 'no pollution here' half of the direct-entry argument is explicitly WITHDRAWN and restated on the true reading (the cost is one offline self-test, not fan-out across unrelated gates). #15569: the card's recollection of six declared / five in gated is OFF BY ONE in both halves - its own bullet list enumerates seven. Measured: SEVEN families declared, SIX run in gated (POSITIVE is the only one dropped, by the single expression 'gated ? [] : POSITIVE_CONTROLS' at line 1922). The comment now NAMES the six rather than counting them, keeps the asymmetry argument in substance, and extends it to say why the three newer cross-checks are equally repair-proof. Neither check-half-states.mjs, dispatch-gates.mjs nor the census script is touched. origin/main was merged into the branch mid-run to clear a STALE TREE warning from dispatch-gates; the PR diff is lint.yml alone.", "measurements": { "extractWatchHints(check-half-states.mjs)": "EXIT=0 -> [\"objectstack-ai/objectstack\",\".changeset\",\"scripts/pm/check-half-states.mjs\",\"owner/name\"] (four, not one)", "hintCovers('.changeset','.changeset/foo.md')": "EXIT=0 -> true", "dispatch-gates --commands .changeset/foo.md | grep -c check:pm-half-states": "1", "routing reason line": "pnpm check:pm-half-states [lint.yml] matched via .changeset/foo.md - gate source '.changeset' (PATH MATCH, not whole-tree)", "hint coverage over git ls-files": "objectstack-ai/objectstack=0, .changeset=84, scripts/pm/check-half-states.mjs=1 (itself), owner/name=0", "hint provenance": "H36_SHARED_PREFIX_NOISE at line 6544; DEFAULT_SWEEP_REPO at 903; owner/name survives masking via the string literal at 18383, not the JSDoc at 905", "swallow-census families declared": "SEVEN - POSITIVE, NEGATIVE, REGRESSION, RESOLUTION control tables plus the DETERMINED register cross-check (#13886), the copied gate-vocabulary cross-check (#15459), WORKLIST_READING_CONTROLS (#15503)", "swallow-census families in gated": "SIX - the gated verdict line at 2102-2117 names all six; POSITIVE is dropped by 'for (const control of gated ? [] : POSITIVE_CONTROLS)' at line 1922", "comments-only proof": "git diff -U0 filtered to non-comment changed lines prints NOTHING; and PyYAML safe_load of HEAD vs working copy compares EQUAL ('parsed structure identical to HEAD: True'), both steps' run: strings unchanged", "dispatch-gates --changed --commands (final tree)": "EXIT=0, 1 path vs merge base 5b0c77909, 37 families; all 37 run: 18 green, 1 green on re-run, 18 NOT MEASURED", "pnpm check:pm-dispatch-gates": "EXIT=0 - 'dispatch-gates self-test: 1445 cases pass.' First run was EXIT=1 purely from this box's node_modules SYMLINK (git check-ignore exited 128: pathspec is beyond a symbolic link); re-run with the symlink moved aside is green. The same symlink inflated the first derivation to 2 paths / 38 families", "pnpm check:nul-bytes": "EXIT=0 - scanned 7610 text files, no raw ASCII control bytes; targeted grep -naP over the edited file also EXIT=1 (no match)", "check-governed-merges --test .github/workflows/lint.yml": "EXIT=0 - NOT governed, 0 of 1 paths hit the register" }, "not_measured": [ "pnpm check:swallow-census-controls - EXIT=1, ERR_MODULE_NOT_FOUND: Cannot find package 'typescript'. Not a red gate. The verdict line is quoted from the source that BUILDS it; the family count is a static reading of the declarations and does not depend on the run.", "EXIT=3 PREREQUISITE NOT MET, dependency 'yaml' not installed (14): check-aggregator-roster and --self-test, check-closing-keyword-parity and --self-test, check-merged-branch-reaper-outcome and --self-test, check-step-collectors and --self-test, check:pnpm-acquisition, check:required-contexts, check:shard-attestation, check:stall-guard-budget, check:stall-guard-headroom, check:workflow-status-functions", "EXIT=3 PREREQUISITE NOT MET, dependency 'typescript' not installed: pnpm check:driver-memory-census", "EXIT=3 PREREQUISITE NOT MET, needs a built package closure: pnpm check:type-check-debt", "EXIT=1 ERR_MODULE_NOT_FOUND '@typescript-eslint/parser' - a missing module, not a red gate: node scripts/check-comment-mask-corpus.mjs", "EXIT=2 NOT VERIFIED, GET /repos/objectstack-ai/objectstack answered HTTP 401 - exit 2 classifies the ENVIRONMENT: node scripts/check-required-contexts.mjs --verify-required-set", "check-ci-filter-parity - named in the dispatch but NOT in the runnable list at all: the derivation scores it 'silent' as an artifact roster. check-closing-keyword-parity IS derived and is yaml-blocked above. Both run for real in CI.", "CI convergence itself - reported at draft-PR time per the dispatch contract; no CI waiting was done." ], "filed": [ "#15753 - extractWatchHints reads the noise-floor EXCLUSION constant as a watch hint (the CLASS: an exclusion list read as an inclusion surface). Includes the precedent reading that the sibling spelling pnpm-lock.yaml is already dropped by the hint reader. Bare: no labels, no assignee.", "#15754 - the census script's own usage header carries the same stale arithmetic one level in ('all 4 control families' / 'the 3 families CI runs') against the seven-declared / six-gated reading. Bare: no labels, no assignee." ], "open_questions": [], "notes": [ "#15569's card states six declared / five in gated. VERIFIED and CORRECTED: seven declared, six in gated. The card's own bullet list already enumerates seven, so its prose arithmetic was off by one - the reading in the PR is the measured one, not the card's.", "skip-changeset applied additively via POST /issues/15756/labels and READ BACK: ['size/s','skip-changeset'] - the size labeler's concurrent write did not strip it. AGENTS.md line 1122 is the authority: that label is for a diff that publishes nothing from any released package.", "MCP GitHub calls this run: 0. REST search/issues is 403 in this session ('sessions are bound to their configured repositories'), so the dedup sweep used the repo-scoped list endpoint - 617 open items, 584 issues, grepped locally, control word 'exactly ONE hint' verified to hit exactly #15537 and nothing else.", "The shared verify lock was read (--status: holder pid 5455) but never taken - no heavy verification was needed for a comments-only diff." ], "mcp_calls": 0 }
Generated by Claude Code
LANDED — PR #15756 merged as
ef60224fc. Card closed byFixes.Probe on re-fetched
origin/main(PM seat):.github/workflows/lint.ymlno longer saysexactly ONE hint(grep count 0) nordeclares four(0); the re-measured blocks are present (RE-MEASURED for #15537/RE-COUNTED for #15569at lines 921 4173 ). Comments only, so no gate reading changes; both required jobs were success on95bf71449.Stripping
pm:dispatchedand the assignee in the same action.
Generated by Claude Code
Correction to the LANDED note above: the grep count for
exactly ONE hintonorigin/mainis 1, not 0 — the surviving occurrence is the new comment QUOTING the withdrawn reading (the reading this step used to cite ("exactly ONE hint, the repo slug in its API base") no longer describes the tree), which is the intended text. Thedeclares fourcount of 0 stands. The LANDED verdict is unchanged; the number was misread from the run and is corrected here rather than edited in place.
Generated by Claude Code
Found while adding a row to
scripts/pm/check-half-states.mjs(PR #15536, card #14967). Pre-existing and untouched by that change — the hint set is byte-identical before and after it.The claim
.github/workflows/lint.yml, on thePM half-state sweeper self-teststep, states a measurement as its reason for pointing the gate straight at the script with no gate file in between, verbatim:The reading
On today's
origin/main,extractWatchHintsover that script returns four, not one:Two of the three extra hints ARE repo paths, and one of them routes:
.changesetcomes from the shared-file row's noise-floor constant (H36_SHARED_PREFIX_NOISE), where it is a spelling to EXCLUDE from pairing — not a surface the patrol watches.scripts/pm/check-half-states.mjsis the script's own path, which is harmless (it is the gate script anyway).owner/nameis a placeholder in prose-shaped code and covers nothing real.Why it matters, stated at the size it is
Every user-visible PR in this repo adds a
.changeset/*.mdfile. If that hint is consulted when routing,pnpm check:pm-half-statesis derived onto essentially every such card — which is precisely the "fabricate MATCHED leads across the tree" pollution the comment above says does not exist for this script, and the reason the neighbouring gate needs a file of its own. Nothing is broken and nothing goes red: the derived gate is cheap, offline and passes. What is wrong is that a documented measurement no longer describes the tree, and the argument resting on it ("the direct entry is safe here") is no longer supported by the reading it cites.⛔ Not judged here: whether the remedy is to re-measure and correct the comment, to stop the noise-floor constant from being read as a hint, or to give this gate its own file like its neighbour. Filed as an observation, not a prescription.
Re-check
Generated by Claude Code