diagnose-wave-stall · git:20260912.0dda5ab · 2026-09-12 · sha256 c81d8daee690a1e4

diagnose-wave-stall git:20260912.0dda5abA

Immutable. This exact content is served forever at /api/v1/blob/c81d8daee690a1e4.

---
name: diagnose-wave-stall
description: 'Use when a dispatched agent wave has stopped progressing — a result that never arrives or one that exists but stays unconsumed — and the blocking node must be named. Not for a configured loop misbehaving: use diagnose-loop-health. Clearing actions are recorded, never executed; re-dispatch follows only an explicit caller instruction.'
---

# Diagnose wave stall

## Contract

| Field | Bound contract |
|---|---|
| Trigger | A dispatched wave has stopped progressing and the blocking node is unknown. |
| Authority | Read-only diagnosis; writes only the named stall report. Cancelling or re-dispatching a node happens only on an explicit instruction recorded in the report. No remote mutation. |
| Side effect | A stall report naming the blocking node, its classification, and the clearing action taken or withheld. |
| Done | Every non-progressing node is classified and the blocking edge is named, or the wave is shown to be progressing and no stall exists. |

## Inputs

- Dispatched nodes (required): The wave's node list with handles or ids, and how to observe each node's live status. Supplied by the caller; if absent, stop and ask.
- Dependency edges (optional): The declared edges between nodes, if the wave was compiled from a map. Without them, blocking edges are reconstructed from each node's stated wait.
- Stall report path (required): Where the report is written. No other file is created or mutated.

This skill owns a dispatched wave blocked on a dependency edge. A configured loop whose setup soundness is questioned belongs to `diagnose-loop-health`; hand it there instead.

## Procedure

1. Enumerate dispatched nodes and their live status. For each node record its id, current state (running, exited, completed, unknown), and the observation evidence. **Done when:** every dispatched node carries a recorded live status with its evidence.

2. Separate still-working nodes from non-progressing ones. A node that is running and producing output is slow, not stalled; only a node with no observable progress across the observation window enters the non-progressing set. **Done when:** the two sets are partitioned and the non-progressing set is named.

3. Classify each non-progressing node into exactly one cause: dead worker (exited without returning a result), unsatisfiable input (waiting on an artifact no node in the wave produces), external limit (quota, rate limit, or credential), or satisfied-but-unconsumed (its result exists but nothing consumes it). Attach the evidence for each classification. **Done when:** every non-progressing node carries exactly one classification with evidence.

4. Name the blocking edge for each non-progressing node: which node, waiting on which artifact or result, produced by whom. **Done when:** every non-progressing node has its blocking edge named.

5. Choose the clearing action per class — re-dispatch for a dead worker, cut the edge for an unsatisfiable input, wait with a stated bound for an external limit, consume the result for satisfied-but-unconsumed — and record it in the stall report. This step is record-only: no procedure step re-dispatches, cuts an edge, waits on a bound, or consumes a result; a chosen action is executed only on an explicit caller instruction recorded in the report, outside this skill. **Done when:** every non-progressing node has its clearing action named in the report, or withheld where its class is unresolved.

6. Write the stall report to the named path: the partition, every classification with its evidence, every blocking edge, and every clearing action named or withheld. **Done when:** the report exists with all recorded classifications and named actions.

## Failure and recovery

- No stall found: report the wave as progressing and change nothing; write no stall report and take no clearing action.
- A cycle is discovered as the real cause: do not emit a clearing action; hand off to `schedule-dependency-waves` and record the handoff in the report.
- A class that cannot be determined: record the node as unresolved with the evidence inspected rather than guessing a clearing action; no action is taken on an unresolved node.
- Node status unreadable: record the node as unresolved rather than classify it as stalled; never swallow the observation error.

## Output

A stall report at the named path listing every non-progressing node with its classification, evidence, blocking edge, and clearing action named or withheld — the report names the chosen action and never executes one; execution follows only an explicit caller instruction recorded in the report. Or a progressing verdict with no artifact written when no stall exists.