Skip to content

[finding] A Blocked-by: target parked in pm:on-hold or needs-user-decision can never fire the unlock — 6 measured cards waiting on a card that will not close #11219

Description

@os-zhuang

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 cardtargettarget's state
cloud#1119cloud#987pm:on-hold
cloud#799cloud#987pm:on-hold
cloud#861cloud#855pm:on-hold
objectos#75objectos#68needs-user-decision
objectos#135objectos#68 (prose only — no machine line in either channel)needs-user-decision
cloud#1332cloud#1331pm: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#1395objectstack#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

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