Skip to content

Commit b302aab

Browse files
os-zhuangclaude
andauthored
fix(pm): widen H8's inputs — branch-name delivery, closed-card residue (H22), and open-PR suppression (#11107)
* fix(pm): H8 counts a merged PR's branch name as delivery when its body declares none `h8MergedPrStillDispatched` read delivery from the PR body alone — `Part of #N` or a closing keyword bound to `#N`. A merged delivery spelled any third way was invisible: the measured specimen was a merged PR whose body said only `Refs #10757`, leaving that card carrying `pm:dispatched` unreported for ~22h in a sweep that reported six other H8 rows correctly. Every dev branch here is `claude/issue-<n>-<slug>` by protocol and every PR row already carries `head.ref`, so the recovery costs no API call. It is spelled as a FALLBACK rather than a third `||` term, because widening the delivery relation has a cost: a branch cut for card N and later re-scoped would otherwise be counted as delivering N forever, on the authority of a name nobody updated. The body is the channel an author maintains, so a body declaring ANY delivery is authoritative and the branch name is consulted only for bodies declaring none. Both directions are pinned in the self-test per the card's binding caveat: the `Refs #N` specimen shape reports, and a re-scoped branch does not false-fire. Fixes #11036 * fix(pm): H8 consults the open-PR list and stops prescribing a destructive drop on half-delivered cards `h8MergedPrStillDispatched`'s entire input was the merged-PR window, so it had no way to ask the question that decides the answer: is there ALSO an unmerged PR delivering this card? On a card delivered in halves the first half's merge made the row fire, and it kept firing on every subsequent sweep until the last half landed — pointing at the card whose remaining work was most active, and prescribing a destructive write against it ("drop `pm:dispatched`"). A reader who followed it de-labelled a card with live work, which then read as un-dispatched and was liable to be re-dispatched: two agents on one card. Measured on #9834, whose error-counter half sat open as draft #10226 while its duration half had merged as #10004. The open-PR list is already in hand from the H7/H12/H21 pass, so this adds no API call; delivery is read through the same relation, branch-name fallback included. Drafts are deliberately not filtered — the specimen was one. The half-delivered case DOWNGRADES rather than falling silent. Silence would fix the harm and buy a new one, per the card's binding caveat: it loses the genuine #8683 case where the last half is later abandoned. The quieter sentence names both sides, counts them, and says `pm:dispatched` is correct and must not be dropped. The destructive prescription now fires only when every delivering PR has merged, and that path is pinned unchanged. Fixes #10468 * feat(pm): H22 — a bounded closed-card sweep for `pm:*` state residue Every collector in this sweep is open-only by construction, and for most items that is right. It is a gap for H8 specifically: H8's subject is a write that has not happened yet, but the card is usually closed by the same merge that discharges the PR — often by a `Closes #N` in the same instant. So whether H8 ever fired was decided by a race it normally loses. Once the card closes, no run looks at it again and the duty is discharged by disappearance. Measured at filing: 129 of the 500 most recently updated closed cards carried a live `pm:` label, 118 of them `pm:dispatched` — the signature of exactly the write H8 was built to catch, unmet at scale because the card closed first. This is direction A: ONE bounded closed reader (`sort=updated`, two pages, the same convention and quota decision as the merged-PR window), every other collector unchanged and still open-only, so the race closes without widening the sweep. The window is the stated boundary and it is load-bearing — a 2026-08-22 re-measure paged past 500 closed `pm:dispatched` carriers repo-wide, so an unbounded read would bury every other item under one-time historical residue. The residue vocabulary is its own constant. It is deliberately NOT H13's `PM_STATE_LABELS`, which answers a different question ("does this label make the card visible to a reader?") and diverges in both directions: `finding` and `needs-user-decision` are fine states to close in, while `pm:blocking` is a live-work claim H13 omits. Sharing one list would make H22 report every closed finding card and miss the blocking-cache residue entirely; the divergence is pinned in both directions. Fixes #10688 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent f59035c commit b302aab

1 file changed

Lines changed: 494 additions & 16 deletions

File tree

0 commit comments

Comments
 (0)