Uh oh!
There was an error while loading. Please reload this page.
feat(pm): H4/H14/blocking-index read comment-level Blocked-by lines - #10075
Merged
Conversation
…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
marked this pull request as ready for review
August 19, 2026 22:28
os-warren
enabled auto-merge
August 19, 2026 22:29
This was referenced Aug 19, 2026
This was referenced Aug 20, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:impersonate_userandset_user_rolestill 403 every platform admin — neither route is safely raw-mountable, and each blocks for a different reason #9968 as stale caches while their dependents (release.yml restores the console dist from the same cache key but has nocheck:console-injectionstep — and its combined cache action saves even on failure #9709/[finding] cut-rc.yml's hotcrm smoke warning still tells the readerchangeset pre exitre-arms that gate — release.yml records the keying was changed away from pre-exit #9828, finding: seven better-auth/admin/routes refuse platform admins and have no ObjectStack consumer — decide whether they are capability or just vendor surface #9969/Every better-auth-native /admin/ route refuses ObjectStack platform admins — the vendor gates on the legacyuser.role === 'admin'scalar ADR-0068 D2 stopped synthesizing #9652) stated the wait in comments — the gauge misplacement the request: run the pm:blocking derivation pass — cache measured at 0% coherence with the Blocked-by index (1 stale / 5 missing, 2026-08-19 census) #9948 ruling named on 2026-08-19 (「修量具而非追假 stale」).What changed —
scripts/pm/check-half-states.mjsnull-or-sentence (the file's idiom for anything sentence-bearing) because it has more than one thing to say.buildBlockingIndextakesoptions.commentsand 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.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.pm:blocked/pm:blockingcards (needsBlockedByComments, exported for the same reasonh17NeedsCommentsis) and share the existingcommentCache, so a card costs one request across H2, H17 and this. Total failure rethrows as transport, reusingh16DetailPassUnreadable; a partial shortfall is a bounded gap the summary line states as a thirdread X of Ypair.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_atis on every row, but an issue's body-edit time is on no REST payload: the issues API carriescreated_at/updated_atonly, body edit history lives behind GraphQLuserContentEdits, 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 commit7ab290652withnode scripts/pm/dispatch-gates.mjs(no args) — 6 families, all run: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)PREREQUISITE NOT MET, the classified transport verdict; this container has no GitHub credential, expectedThe two
node scripts/...rows in the derived list invoke the same scripts as theirpnpmtwins.Reverse verification — directions predicted in writing, then observed
No build step is involved:
nodeexecutes this script's source directly, nothing resolves through a packagedist/. Each leg was ablated from the committed state and restored withgit checkout(the restore leg re-verified: 469 pass, zeroABLATIONmarkers left in the tree).null, and #9465 reportspm:blocking carried while NO open card's Blocked-by line ... targets it— the measured false stale reproduced. Restored: edges =[9709,9828], row = cleancommentBodies8 of 469 case(s) failed, the 8 named ones1 of 469 case(s) failed,H14-A: stale is SUSPENDED when the index is known incompleteThe #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