Finding — recording only, not claimed. Filed under the maintainer direct-dispatch channel, this session, verbatim: 「然后 把 1–4 落成 finding 卡」. PM session session_0124Qg8rLvpXnQDwCmpKUmaJ.
The mechanism
The unlock predicate is "the Blocked-by: target CLOSED". pm:on-hold and needs-user-decision are, by definition, states a card sits in while open. A block naming such a target is therefore structurally indefinite: nothing in the machinery can ever fire it, and no predicate reports that.
It is not the same as H9 (a hold with no fireable Restart-when:). H9 audits the held card. This is about the waiting card, which looks perfectly well-formed — it has its machine-readable line, its target resolves, the target is open. Every check passes and the card still cannot move.
Measured, 2026-08-23
| waiting card | target | target's state |
|---|
| cloud#1119 | cloud#987 | pm:on-hold |
| cloud#799 | cloud#987 | pm:on-hold |
| cloud#861 | cloud#855 | pm:on-hold |
| objectos#75 | objectos#68 | needs-user-decision |
| objectos#135 | objectos#68 (prose only — no machine line in either channel) | needs-user-decision |
| cloud#1332 | cloud#1331 | pm:queue, but titled [Decision] — a decision card wearing a work label |
Two structural notes fall out of that table:
A third variant found in the same sweep: the stale chain
cloud#1395 → objectstack#10101, which is open — so the block looks live. But #10101 was itself an H19 finding on the same sweep: both of its own blockers had already closed. The block was real one level up and false two levels up, and a single-level predicate cannot see that.
Shape of the fix
A predicate over data the patrol already holds — it fetches the target's state to answer H19, so the target's labels are one field further:
an open pm:blocked card whose Blocked-by: target is open and carries pm:on-hold / needs-user-decision ⇒ name it.
Report-only, like everything else there. It does not say the block is wrong — sometimes waiting on a deferred card is exactly right. It says this block has no mechanism that will ever release it, which is the thing a human should see rather than discover in a hand sweep.
Optional second leg, cheap on the same data: flag when the target is itself pm:blocked (the chain case).
Re-check
# for each open pm:blocked card, resolve its Blocked-by target and read the target's labels
Finding — recording only, not claimed. Filed under the maintainer direct-dispatch channel, this session, verbatim: 「然后 把 1–4 落成 finding 卡」. PM session
session_0124Qg8rLvpXnQDwCmpKUmaJ.The mechanism
The unlock predicate is "the
Blocked-by:target CLOSED".pm:on-holdandneeds-user-decisionare, by definition, states a card sits in while open. A block naming such a target is therefore structurally indefinite: nothing in the machinery can ever fire it, and no predicate reports that.It is not the same as H9 (a hold with no fireable
Restart-when:). H9 audits the held card. This is about the waiting card, which looks perfectly well-formed — it has its machine-readable line, its target resolves, the target is open. Every check passes and the card still cannot move.Measured, 2026-08-23
pm:on-holdpm:on-holdpm:on-holdneeds-user-decisionneeds-user-decisionpm:queue, but titled[Decision]— a decision card wearing a work labelTwo structural notes fall out of that table:
A third variant found in the same sweep: the stale chain
cloud#1395→objectstack#10101, which is open — so the block looks live. But #10101 was itself an H19 finding on the same sweep: both of its own blockers had already closed. The block was real one level up and false two levels up, and a single-level predicate cannot see that.Shape of the fix
A predicate over data the patrol already holds — it fetches the target's state to answer H19, so the target's labels are one field further:
Report-only, like everything else there. It does not say the block is wrong — sometimes waiting on a deferred card is exactly right. It says this block has no mechanism that will ever release it, which is the thing a human should see rather than discover in a hand sweep.
Optional second leg, cheap on the same data: flag when the target is itself
pm:blocked(the chain case).Re-check