⛔ Unassigned; for triage to grade. Filed by a /pm-dispatch devx fire that self-retired on this, 2026-08-20T01:3xZ. No card was claimed, no label written.
The defect
pm-dispatch's 开轮互斥读法 gates a fire on two readings, both of which live on the seat post:
fire 开始、首个写动作之前读两个读数 —— 最近收班简报未满一个轮次,或最新「开轮」标记晚于收班简报且自身未满一个轮次 … ⇒ 自退;两读数皆清,先在座位贴留一行开轮标记(session ID + fire 时刻)再跑轮。
A session that is running but has stopped writing to its seat post is therefore indistinguishable from no session at all — and the protocol's own text names why that gap is load-bearing: 「轮中会话按设计还没发收班贴,开轮标记是它唯一可见的痕迹」. The marker is treated as the sole visible trace, so when it is missing the mutex concludes absent rather than unknown.
Measured
domain:devx, seat post #6023, at fire time 2026-08-20T01:32:13Z:
| reading | value | mutex verdict |
|---|
| latest shift-end brief | 5322606816 — 2026-08-18T02:15:55Z | ~47h old ⇒ clear |
| latest round-open marker | 5324000428 — 2026-08-18T05:25:52Z | ~44h old ⇒ clear |
Both clear. The seat was occupied and mid-round. Evidence, all off-seat-post:
⇒ The incumbent's rounds 8–27 left zero seat-post writes while claiming cards, dispatching devs, opening PRs and flipping them ready throughout.
Why this is worth a card
The mutex exists to stop 「两个同座位会话并行写标签」, and this is the failure shape that reaches that outcome while both readings say go. The second session does not detect the collision at the point the rule is designed to fire; it detects it later, if at all — here, only because the fire happened to inspect the in-flight cards' claim comments before dispatching, which is not something the protocol requires at that point. Had it dispatched on the clear readings, two seats would have been claiming from one queue with 4 cards already in flight.
⚠️ Note the incumbent is not misbehaving in a way any gate can see: nothing forces a round-open marker, and a session that skips it is fully functional — it just becomes invisible to the next fire. A protocol whose safety depends on a write no one checks for is a protocol with an unreported failure mode, not a strict one.
Suggested shape — not a ruling, triage's call
The cheap fix is a third reading that does not live on the seat post, taken from data the lane already fetches:
- the newest
Claim:-prefixed comment across the lane's pm:dispatched cards. Claim: is already a machine predicate with a pinned spelling and already carries Session: and a timestamp — a claim newer than one round from a different session ID is positive evidence of a live seat, symmetric to the marker but written on a surface the incumbent cannot forget, because claiming is not optional.
Direction matters: this reading can only ever add self-retirements (it is a second way to detect occupancy, never a way to clear a seat), so it cannot make the mutex more permissive than it is today.
⛔ Explicitly not proposed here: a heartbeat, a lock, or any new label — the state model already carries every input this needs.
Not claimed
- ⛔ No assertion that the incumbent session did anything wrong; skipping the marker is not currently a gate violation, which is the point.
- ⛔ I did not audit whether other seats have the same stale-marker shape — measured on
domain:devx only. The rule is common to all seats, so the exposure presumably is too, but that is unmeasured. - ⛔ The suggested predicate is unimplemented and unmeasured; I did not check how many lanes carry a lane-newest claim that would trip it.
Refs: seat post #6023 (retraction comment 5350102345 carries the same measurement) · #9757 / PR #10084 (the live-session evidence)
⛔ Unassigned; for triage to grade. Filed by a
/pm-dispatch devxfire that self-retired on this, 2026-08-20T01:3xZ. No card was claimed, no label written.The defect
pm-dispatch's 开轮互斥读法 gates a fire on two readings, both of which live on the seat post:A session that is running but has stopped writing to its seat post is therefore indistinguishable from no session at all — and the protocol's own text names why that gap is load-bearing: 「轮中会话按设计还没发收班贴,开轮标记是它唯一可见的痕迹」. The marker is treated as the sole visible trace, so when it is missing the mutex concludes absent rather than unknown.
Measured
domain:devx, seat post #6023, at fire time 2026-08-20T01:32:13Z:5322606816— 2026-08-18T02:15:55Z5324000428— 2026-08-18T05:25:52ZBoth clear. The seat was occupied and mid-round. Evidence, all off-seat-post:
scripts/pm/dispatch-gates.mjsdispatches its CLI at module top level, so the re-exports its header offers cannot be imported —importruns the tool andprocess.exit(2)s the importer #9757 claim5349681895—Claim: PM loop round 27, sessionsession_01XqDQYVU5smx29ts9pAErja, 2026-08-20T00:29:52Z (62 min before the fire).scripts/pm/dispatch-gates.mjsdispatches its CLI at module top level, so the re-exports its header offers cannot be imported —importruns the tool andprocess.exit(2)s the importer #9757 dev report5349808742— 2026-08-20T00:49:51Z (42 min before).draft: falseatupdated_at 2026-08-20T01:23:38Z⇒ a PM-only action ~9 minutes before the fire. Sibling PR docs(webhooks): documentheaders_secretand stop pointing authors atdefinition_json#10067 updated 01:23:33Z, 5s apart.⇒ The incumbent's rounds 8–27 left zero seat-post writes while claiming cards, dispatching devs, opening PRs and flipping them ready throughout.
Why this is worth a card
The mutex exists to stop 「两个同座位会话并行写标签」, and this is the failure shape that reaches that outcome while both readings say go. The second session does not detect the collision at the point the rule is designed to fire; it detects it later, if at all — here, only because the fire happened to inspect the in-flight cards' claim comments before dispatching, which is not something the protocol requires at that point. Had it dispatched on the clear readings, two seats would have been claiming from one queue with 4 cards already in flight.
Suggested shape — not a ruling, triage's call
The cheap fix is a third reading that does not live on the seat post, taken from data the lane already fetches:
Claim:-prefixed comment across the lane'spm:dispatchedcards.Claim:is already a machine predicate with a pinned spelling and already carriesSession:and a timestamp — a claim newer than one round from a different session ID is positive evidence of a live seat, symmetric to the marker but written on a surface the incumbent cannot forget, because claiming is not optional.Direction matters: this reading can only ever add self-retirements (it is a second way to detect occupancy, never a way to clear a seat), so it cannot make the mutex more permissive than it is today.
⛔ Explicitly not proposed here: a heartbeat, a lock, or any new label — the state model already carries every input this needs.
Not claimed
domain:devxonly. The rule is common to all seats, so the exposure presumably is too, but that is unmeasured.Refs: seat post #6023 (retraction comment
5350102345carries the same measurement) · #9757 / PR #10084 (the live-session evidence)