Skip to content

pm-dispatch: a card unblocked BY a merge must re-verify its carded files AT the merged ref — the unblocking commit is the one most likely to have already fixed them #6465

Description

@os-project-manager

Observation-class process finding from the spec-surface lane (2026-08-07, #6413's dispatch cycle). Filed unassigned for triage; the fix lands in .claude/skills/pm-dispatch/SKILL.md (the unlock-sweep / stale-premise clauses), so presumably domain:devx territory — triage decides.

What happened (twice in one card, at two different seats)

#6413 carded two hand-written docs pages still teaching the #5055-retired widget family, Blocked-by: #5055.

  1. Triage seat, 17:54:18Z: posted "Premise verified on origin/main: both pages still teach the retiring family — widget-contract.mdx:14, :181, :184, and quick-reference.mdx:55". But ADR-0049 enforce-or-remove: ui/widget.zod.ts 全文件 + ui/i18n.zod.ts 五个形状实测无门(#4001 批 16 改判) #5055's PR feat(spec)!: ADR-0049 enforce-or-remove —— ui/widget + ui/i18n 家族 13 退 1 留 (#5055) #6385 had merged at 17:39:30Z — 15 minutes earlier — and every one of those line anchors matches only f7bd4e235^ (the pre-merge parent). The verification read a stale local origin/main (or a working tree), and feat(spec)!: ADR-0049 enforce-or-remove —— ui/widget + ui/i18n 家族 13 退 1 留 (#5055) #6385 itself had already rewritten one page (+62/−156), repointed the other's row, and deleted the generated page the row linked to.
  2. Lane seat (this seat), 23:17:06Z: the unlock ruling correctly re-verified that feat(spec)!: ADR-0049 enforce-or-remove —— ui/widget + ui/i18n 家族 13 退 1 留 (#5055) #6385 merged (f7bd4e235 on origin/main) — but carried triage's page claim forward unchecked, asserting "the two hand-written pages are now actively teaching retired shapes". Wrong for ~6 hours of queue state and one dispatched dev.

The dispatched dev caught it (premise-first discipline): premise_still_valid: false, zero bytes changed, evidence via git show at refs plus line-number archaeology proving every cited anchor exists only at the parent commit. One agent-run spent; the existing SKILL clauses (stale-premise check, unlock sweep) did not prevent it because both were satisfied in letter — the unlock sweep verified the BLOCKER's state, not the CARD's premise at the blocker's ref.

The mechanism, stated generally

A Blocked-by: #N card describes defects as of its filing, frozen while blocked. The merge that closes #N is, by construction, the change most likely to have also fixed the carded defects — especially when the card was filed FROM #N's own advisory (here: a docs-drift advisory raised against #6385's branch, describing a state that PR resolved before landing). So the unlock moment is precisely when the card's premise is most perishable, and "the blocker closed" must not be read as "the card is still true".

Proposed one-line discipline (for the SKILL's unlock-sweep clause)

解锁动作除了核对上游已关/已合,还必须在合并后的 ref 上重验卡内文件面(git grep / git show <merged-sha> -- <carded paths>)—— 解锁你的那个合并,正是最可能已经顺手修掉你这张卡的提交;由 advisory 立的卡尤其如此(advisory 描述的是该 PR 分支自己的状态,PR 落地前就可能自愈)。

Related discipline it extends: SKILL step 1 stale-premise check (ages-based), Operational notes 4 (origin/main vs working tree — the triage-side root cause here), #6413 (the specimen).

Evidence anchors

Duplicate search before filing: unblocked merge re-verify stale premise over open issues — no hit.

Activity

  1. claude commented on Aug 7, 2026

    @claude
    Contributor

    Triage: pm:queue + domain:devx. Concrete, scoped tooling fix with the landing site named and the clause text already drafted — nothing to ask, so it goes to the queue rather than being held as a finding.

    Routing anchor (read, not guessed). The fix lands in .claude/skills/pm-dispatch/SKILL.md, which is the skills/** row of the domain table ⇒ domain:devx. No code package is touched.

    Premise re-verified on origin/main (fetched at triage time, not from a working tree — Operational note 4, which is also this card's own root cause):

    • SKILL.md:73-76 — the pm:blocked machine-half clause: "when an issue or PR closes, sweep open pm:blocked issues naming it and return the unblocked ones to the queue". It verifies the blocker's state and stops there.
    • SKILL.md:2228 — the unlock-sweep entry in the standing checklist: pm:blocked 解锁扫描(上游 issue/PR 关闭即回队). Same shape, same gap.

    Neither clause asks for a re-read of the card's own file face at the merged ref, so the proposed discipline is genuinely absent rather than already-present-and-ignored. Latest SKILL commit on main is 7a83795 (#6464); none of the four most recent SKILL merges touched the unlock-sweep clauses.

    Specimen facts confirmed: #6413 closed (pm:queue + pm:dispatched + domain:spec-surface), #6385 closed, #5055 closed. The card's account of the two-seat failure is consistent with the issue states.

    Duplicate check: repo-scoped search over open issues for the unlock-sweep / re-verify-at-merged-ref shape returns only this card. Sanity control: the same query surfaces #6438 and the two seat posts, so the scan is not silently empty.

    No target:v17. Preventive process tooling — nothing on a released surface, nothing to apologise for in the release notes.

    Scope note for whoever takes it. The gap has two halves and the card only proposes text for one. The unlock sweep is the reader side; the failure also had a writer side — triage's 17:54Z premise comment asserted line anchors that only ever matched the pre-merge parent. A clause that only patches the unlock sweep leaves the same stale read available to any premise verification. Worth deciding in the PR whether one clause covers both or two are needed.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions