Skip to content

Commit 10da5c4

Browse files
os-litantclaude
andauthored
feat(pm): H4 reads the prose blocker and prints its upstream's state (#17494)
* feat(pm): H4 reads the prose blocker and prints its upstream's state `pm:blocked` is a PAIR — the label plus the body line `Blocked-by: #N` — and the unlock scan fires from that line and nothing else. Seats state the block in prose instead, which a human reads perfectly and no machine reads at all, so when the upstream closes nothing returns the card. Three cards were measured in that shape, each past a satisfied unlock, one of them `priority:p1` + `security` and stalled four days after its own ruling. H4 already caught the missing line; it could not say the half that costs — that the stated condition has already been met. H19 cannot reach this class either, because it resolves the target of a `Blocked-by:` line and the whole defect is that there is no such line. So H4 now scans the anchored prose of a card it is already firing on, reads the candidate upstreams out of it, and prints each candidate's current state. The row reads "line missing, and the upstream already closed" when it is. - `PROSE_BLOCKER_ANCHORS` is a MEASURED list: the three specimens plus every H4-firing card on the 2026-09-10 board. Bare `blocking` is deliberately out (it is the label being discussed, not a block being stated). - Report-only, exit codes unchanged. A candidate is never a verdict: the row names candidates and their state, writes no label, and keeps H4's remedy. - Cost rides H19's per-target cache: only a card already firing H4 is scanned, at most `H4_PROSE_CANDIDATE_CAP` (5) candidates per card are resolved, an open local candidate is answered free from the listing already in hand, and the clause declares anything the cap held back. - The row is emitted in the blocker-liveness loop rather than the main loop, because that is where the resolver lives; the gathering stays where it was, ahead of the total-shortfall rethrow. Same population, same answer. Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK Co-authored-by: Claude <noreply@anthropic.com> * test(pm): the prose cases must FAIL, not throw The ablation leg that empties the anchor set made `proseBlockerRefs(...)[0].repo` throw, aborting the whole self-test and hiding every case after it — the exact shape the `blockedByTargets` cases already warn about, and the shape a real regression in this reader produces. Read through `.map(...).join()` instead, so an empty reading is a failed assertion with a name. Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 634f23d commit 10da5c4

1 file changed

Lines changed: 383 additions & 7 deletions

File tree

0 commit comments

Comments
 (0)