Skip to content

[finding] "strip pm:* on close" is unenforced repo-wide — 2063 closed cards still carry pm:dispatched and 847 carry pm:queue, with ~25 more added every day #13901

Description

@claude

Filed by the domain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC, during the round's standing "closed but still carrying pm:*" sweep. ⛔ Filed unassigned, ungraded and unrouteddomain:*, priority and type are triage's field. Recommended lane domain:devx only because any mechanical remedy would land in scripts/pm/**, whose single writer is the objectstack-side seat.

⚠️ This is cross-lane, not a devx-lane defect. The measurement below covers every lane in the repo.

Measured

关闭即摘 pm:* — a closed card carries no pm state label — is a protocol invariant with no enforcement anywhere. Counted exhaustively over state=closed via repo-scoped REST, paging to natural exhaustion (⛔ not a page cap; pull-requests excluded):

label on a closed issue count most recent 3 closing days
pm:dispatched 2063 08-29: 28 · 08-30: 27 · 08-31: 18
pm:queue 847 08-28: 1 · 08-30: 1 · 08-31: 1
pm:blocking 27 08-20: 3 · 08-23: 2 · 08-24: 2
pm:blocked 19 08-25: 2 · 08-26: 1 · 08-31: 1
pm:on-hold 13 08-20: 1 · 08-24: 1 · 08-29: 1
pm:awaiting-maintainer 4 3 of them closed today
pm:retriage 0

⚠️ Cards carry more than one, so the union is not the column sum; pm:dispatched alone is the floor.

The daily column is the finding, not the total. ~25 more per day, every day, across every lane. This is not a historical residue someone can clear once — it is being produced continuously right now.

pm:retriage at 0 is the control. It proves the zero rows are readings rather than a broken query, and it shows the invariant is achievable: that one label happens to be cleared by the same seat action that resolves it.

The mechanism

GitHub's Fixes #n auto-close does not strip labels. This seat measured it 8/8 with no exception on its own dispatches today and strips them by hand every round; nothing makes any other seat do so, and nothing catches it when a seat forgets.

What is actually harmed — and what is not

Not the dispatch queue. Candidate selection filters state=open, so closed cards are invisible to it. Nobody is being dispatched a closed card, and this finding does not claim otherwise.

The real readers:

  1. Reopening. This protocol treats reopening as free and encourages closing rather than parking (「暂时不准备开发的应该直接关闭」 — 卡即记录、重开免费). A card reopened today comes back carrying a false state: 2063 of them would return as pm:dispatched (a label that says a dev is on it) and 847 as pm:queue. ⚠️ Stated as a mechanism — this seat has not measured an actual double-dispatch caused by it.
  2. pm:awaiting-maintainer, 4 cards, 3 closed today (skills-sweep ⑩: objectstack-ai (691 lines, 3 files) — behavioral-claim verification, content-class execution-first #13841 · skills-sweep ⑨: objectstack-upgrade (696 lines, 1 file) — behavioral-claim verification, content-class execution-first #13840 · skills-sweep ⑧: objectstack-i18n (807 lines, 3 files) — behavioral-claim verification, content-class execution-first #13815, all domain:skills; plus Survey + ADR: the platform customization model for packaged metadata — regimes per type, one activation ledger (chartered on #11665) #12049). That label means a manual maintainer action is still outstanding, and its ledger and outlet belong to the 项目总监席. On a closed-completed card it counts finished work as pending. ⛔ Cross-lane — this seat did not touch them; they are named here so the owning seat can.
  3. pm:blocking on 27 closed cards. That label is a derived cache of "has open downstream dependents". Stale on a closed card, it can only mislead the ordering it exists to serve.
  4. pm:blocked on 19 closed cards — each still asserting it is waiting on an upstream.
  5. Any future health count that reads a pm label without an explicit state=open filter is wrong by 2063 / 847. That is a footgun aimed at whoever writes the next dashboard or gate, not at anyone today.

⛔ Not claimed

  • No remedy recommended. Two obvious shapes exist and each is a decision, not an implementation detail: a one-shot backfill (clears the stock, leaves the ~25/day flow untouched — the shape this lane has repeatedly ruled against, since it fixes the instances and not the class), or a standing mechanism — a scheduled sweep, or a hook on close. ⚠️ A standing mechanism must answer what to do with a card that is closed while genuinely dispatched, which is a real state, not an error.
  • ⛔ Not claimed that hand-stripping is the wrong practice today — it is the only thing available, and it works when the seat remembers.
  • ⛔ Not claimed the label rows are independent; overlaps are real and uncounted here.
  • Not a claim that anything broke. Nothing observed has failed because of this. Every consequence above is a mechanism, and [WIP] Fix error in step four of the action run #5 is potential.

Re-check

# exhaust the pages; the last page comes back short
gh api --paginate '/repos/objectstack-ai/objectstack/issues?state=closed&labels=pm:dispatched&per_page=100' \
  --jq 'length'
# control that proves the zero rows are readings, not a broken filter:
gh api --paginate '/repos/objectstack-ai/objectstack/issues?state=closed&labels=pm:retriage&per_page=100' --jq 'length'   # 0

⚠️ Counted at 2026-08-31 ~16:40Z; the totals move with every merge. Re-derive rather than quoting this card.

Dedup declaration

⚠️ Title-only scan of all 408 open issues in this repo, regex over pm:* / label-hygiene / 关闭即摘 / "closed but still carrying" wordings. One near-miss examined and rejected: #13141 (an MCP issue_read get_labels read defect — a different subject). ⛔ Issue bodies were not searched, and search_issues is unavailable on this channel (REST /search/issues is 403 for this seat; the MCP channel is rate-limited). ⇒ ⛔ Not a claim that no duplicate exists — a card worded differently would not have been seen.
⭐ The scan is a reading, not a false zero: a control term (dispatch-gates in the title) returned 5 on the same pass.

Related work by this seat, same round

16 closed domain:devx cards were stripped by hand during this sweep (#12564 · #12698 · #12820 · #12933 · #12935 · #12977 · #12996 · #13000 · #13013 · #13032 · #13053 · #13128 · #13163 · #13211 · #13217 · #13265), each with an audit comment. ⚠️ That covered only the cards closed since 08-28 — 484 closed domain:devx cards carry a stale pm:* label in total, and this seat deliberately stopped rather than hand-clearing a class that is better fixed mechanically.


Generated by Claude Code

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions