Skip to content

feat(pm): H4/H14/blocking-index read comment-level Blocked-by lines - #10075

Merged
os-warren merged 3 commits into
mainfrom
claude/issue-10061-comment-level-blockedby
Aug 20, 2026
Merged

feat(pm): H4/H14/blocking-index read comment-level Blocked-by lines#10075
os-warren merged 3 commits into
mainfrom
claude/issue-10061-comment-level-blockedby

Conversation

@os-warren

Copy link
Copy Markdown
Collaborator

Fixes#10061

The unlock scan and this patrol read issue bodies only, while seats deliberately park the Blocked-by: line in a comment — a body rewrite goes through the MCP escaping hazard (#8813) and is the riskier write. 26 of 40 blocked cards were body-clean at the 2026-08-19 census. Two measured consequences, both addressed here:

What changed — scripts/pm/check-half-states.mjs

  • H4 judges both channels. Either discharges the duty; the finding sentence names both so a reader knows which one to correct. It now returns null-or-sentence (the file's idiom for anything sentence-bearing) because it has more than one thing to say.
  • buildBlockingIndex takes options.comments and unions comment-borne refs with body ones. Not a priority order: both are real edges, and a card naming one target in each channel is waiting on both. Cross-repo and self-reference filtering is applied identically whichever channel a ref arrived in.
  • H14's two directions treat an incomplete index asymmetrically, on purpose. Stale is a claim about absent evidence, so it is suspended when any gated fetch failed (check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690 — unreadable evidence is not absent evidence; the remedy it prescribes, dropping a label the selection order ranks second only to priority:p0, is destructive). Missing is a claim about evidence in hand — reading more sources can only add edges, never remove one — so it stays live regardless.
  • Fetches are gated to body-clean pm:blocked / pm:blocking cards (needsBlockedByComments, exported for the same reason h17NeedsComments is) and share the existing commentCache, so a card costs one request across H2, H17 and this. Total failure rethrows as transport, reusing h16DetailPassUnreadable; a partial shortfall is a bounded gap the summary line states as a third read X of Y pair.
  • H4's unreadable case fires where H14-stale goes quiet — a transport failure must not shrink the patrol below its pre-fallback reach, and H4's remedy ("add a line") is idempotent where H14-stale's is not.

Stated boundary — the read-closure cut-off is NOT implemented

The seat-post protocol's rule is 「只读晚于正文最后编辑时间的评论」 on the ground that 「两个时刻都是平台盖章的硬读数」. One of those two stamps does not exist in REST. A comment's created_at is on every row, but an issue's body-edit time is on no REST payload: the issues API carries created_at/updated_at only, body edit history lives behind GraphQL userContentEdits, and this file is REST-only by a standing operational note. The issue timeline endpoint does not record body edits either.

So the cut-off is omitted rather than implemented against a proxy. The one proxy in reach, updated_at, is worse than nothing: it bumps when a comment is posted, so "newer than the body's last edit" would be false for every comment ever written and the fallback would read nothing while looking like it read — an unfalsifiable check, the shape this file exists to catch.

Reading the whole first page instead errs in one direction and it is the safe one: extra evidence can only add edges, so it can clear an H4 row or an H14 stale row, and cannot invent a card's silence. Full direction analysis and the residual-cost argument sit at the predicates. This is a declared narrowing of the card's wording — flagged for the PM in the report's open_questions, with options.

Verification

Self-test 414 to 469 (pnpm check:pm-half-states), all green. Gate union re-derived from the real diff on the final commit 7ab290652 with node scripts/pm/dispatch-gates.mjs (no args) — 6 families, all run:

gateverdict line
pnpm check:pm-half-statescheck-half-states self-test: 469 cases pass.
pnpm check:partof-closing-keywordcheck-partof-closing-keyword self-test: 28 cases pass.
pnpm check:cross-package-test-inputsOK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.
pnpm check:nul-bytescheck-nul-bytes: OK (scanned 6367 text file(s) ... no raw ASCII control bytes).
node scripts/pm/check-half-states.mjs (live sweep)exit 3PREREQUISITE NOT MET, the classified transport verdict; this container has no GitHub credential, expected

The two node scripts/... rows in the derived list invoke the same scripts as their pnpm twins.

Reverse verification — directions predicted in writing, then observed

No build step is involved: node executes this script's source directly, nothing resolves through a package dist/. Each leg was ablated from the committed state and restored with git checkout (the restore leg re-verified: 469 pass, zero ABLATION markers left in the tree).

ablationpredictedobserved
index union reverted to body-onlyred on the union-dependent rows; the two "reads STALE against a body-only index" pins stay green (they encode the pre-change behaviour deliberately)held — exit 1. Probed directly: edges at #9465 = null, and #9465 reports pm:blocking carried while NO open card's Blocked-by line ... targets it — the measured false stale reproduced. Restored: edges = [9709,9828], row = clean
H4 ignores commentBodiesred on the H4 comment-channel rows only, body-channel rows unaffected — 8 named rowsheld exactly8 of 469 case(s) failed, the 8 named ones
stale suspension removedexactly one rowheld1 of 469 case(s) failed, H14-A: stale is SUSPENDED when the index is known incomplete

The #9465/#9968 false-stale shapes are regression pins in the self-test, built from the real comment bodies on #9709/#9828/#9969/#9652, and each is pinned in both directions (stale against a body-only index, clean against the union).

Boundaries honoured: no seat-resume body rewrites, Restart-when:/Unlock-action: reading untouched, no cloud-repo backfill, no new labels, report-only discipline unchanged.

skip-changeset: this PR ships no user-visible change (a PM patrol script), so no changeset.


Generated by Claude Code

…10061)
The unlock scan and this patrol read issue BODIES only, while seats
deliberately park the `Blocked-by:` line in a COMMENT — a body rewrite
goes through the MCP escaping hazard (#8813) and is the riskier write.
26 of 40 blocked cards were body-clean at the 2026-08-19 census, so the
body-only read reported a duty as unmet that had in fact been met in the
other channel, and H14 reported #9465 and #9968 as stale caches while
their dependents (#9709/#9828, #9969/#9652) stated the wait in comments.
- H4 judges BOTH channels; either discharges the duty, and the finding
names both so a reader knows which one to fix.
- `buildBlockingIndex` takes `options.comments` and UNIONs comment-borne
refs with body ones — both are real edges, so neither wins.
- H14's two directions treat an incomplete index asymmetrically: stale
(a claim about absent evidence) is suspended when any gated fetch
failed; missing (a claim about evidence in hand) survives.
- Fetches are gated to body-clean `pm:blocked` / `pm:blocking` cards and
share the existing `commentCache`, so a card costs one request across
H2, H17 and this. Total failure rethrows as transport (#4690); a
partial shortfall is stated by the summary line's third `read X of Y`.
Stated boundary: the seat protocol's read-closure cut-off (comments newer
than the body's last edit) is NOT implemented — REST carries no body-edit
timestamp and this file is REST-only; the one proxy in reach makes the
check unfalsifiable. Rationale and direction analysis at the predicates.
Self-test 414 -> 469.
Fixes#10061
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeA3nU1B5Q2pgxqxgUrexd
@os-warren
os-warren added this pull request to the merge queueAug 20, 2026
Merged via the queue into main with commit 2cd5f81Aug 20, 2026
24 checks passed
@os-warren
os-warren deleted the claude/issue-10061-comment-level-blockedby branch August 20, 2026 07:43
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

patrol: H4/H14/blocking-index read comment-level Blocked-by lines when the body carries none — the #8941 gauge fix

2 participants

@os-warren@claude