Nothing signals a blocked session outward: a perimeter-parked PR is visible only in a transcript nobody is reading nf-5kg ← Beads

open priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/833 by tools/beads/import_github.py's reconcile pass.

Unclaimed. Filed off a comparison against [codingagentsystem/cas](https://github.com/codingagentsystem/cas), which notifies the operator when a worker hits a blocker. We have no equivalent.

The problem

Every outward signal this repo produces fires when a session is done, never when it is stuck.

So consider the case CLAUDE.md step 6 explicitly designs for:

> Blocked needing Aedan's approval — the PR touches something outside the perimeter, which --why names by path, not by tier: label. Report the PR URL and stop.

The session reports the URL into its own transcript and halts. If Aedan is not attached to that tmux pane at that moment, the signal is gone. The PR sits in the queue looking like every other open PR, and the fact that it is *parked on a human decision* rather than *converging with the reviewer* is visible nowhere. This is the exact failure mode CLAUDE.md's value 6 warns about in the other direction — "the finding dies in a transcript nobody reads."

Same shape, other blockers:

D2 — when you must fail, fail noisily and as soon as possible. Right now a blocked session fails silently, and the cost lands on Aedan's attention rather than a channel (A1).

The change

A push signal on blocked, distinct from the merged/reviewed signals that already exist.

Deliberately *not* specified here — the taker should pick after looking at what the box can actually do:

Anti-goal: do not build a notification system. One signal for one condition, on the cheapest channel that reaches him. This should not grow a config surface, a severity model, or a second poller. If it wants to become that, it is the wrong shape.

Interaction with the fleet view

If the derived fleet view (#832) lands, "blocked" becomes a computed badge there for free — and that is the *right* place for the passive display. This issue is about the push half: the case where nobody is looking at any view. Ship them independently; neither blocks the other, and the definition of blocked is shared between them, so whichever lands second should reuse the first's predicate rather than writing a second one. #658 (two readers of claude agents --json) and the #344/#352 perimeter-parser split are the standing examples of what a second implementation of the same state costs here.

Dependencies

None.

Comments

No comments.

Add a comment