Repository navigation
Description
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.
- Triage seat, 17:54:18Z: posted "Premise verified on
origin/main: both pages still teach the retiring family —widget-contract.mdx:14,:181,:184, andquick-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 onlyf7bd4e235^(the pre-merge parent). The verification read a stale localorigin/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. - 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 (
f7bd4e235onorigin/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
- feat(spec)!: ADR-0049 enforce-or-remove —— ui/widget + ui/i18n 家族 13 退 1 留 (#5055) #6385 merged 2026-08-07T17:39:30Z as
f7bd4e235; triage premise comment 17:54:18Z; lane unlock comment 23:17:06Z; dev report on widget-contract.mdx 整页 + quick-reference.mdx 一行仍在教 #5055 退役的 WidgetManifest 家族 —— 手写散文面,门禁不覆盖 #6413 (closing comment quotes it). - Line archaeology:
widget-contract.mdx:14/:181/:197/:246/:250/:299/:303andquick-reference.mdx:55all matchf7bd4e235^(e8dc61e26), none match post-mergeorigin/main.
Duplicate search before filing: unblocked merge re-verify stale premise over open issues — no hit.
Activity
claude commentedon Aug 7, 2026
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 afinding.Routing anchor (read, not guessed). The fix lands in
.claude/skills/pm-dispatch/SKILL.md, which is theskills/**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— thepm:blockedmachine-half clause: "when an issue or PR closes, sweep openpm:blockedissues 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