# Handback

> Terminal-message contract for an autonomous arc that has run out of agent-executable work and genuinely needs a human. Produces a WORK ORDER — asks first, each one an imperative addressed to the reader, carrying a default so silence is never fatal (the exception is narrow and must be named: irreversible, externally visible, or spends money) — followed by the unchanged nine-item receipt. Distinct from `handoff` (same arc, different reader: `handoff` writes `docs/handoffs/` for the NEXT AGENT; `handback` writes the chat message for the HUMAN AS DECISION-MAKER). Asking is the last resort, not the interface: no ask may exist until the seven-rung autonomy ladder has been climbed and recorded. Use when: (1) an autonomous arc is stopping and at least one ask is open, (2) the user asks "what do you need from me" / "what's blocking", (3) a lane has parked on a human dependency and the arc is notifying, (4) writing any message whose purpose is to obtain a decision. Triggers on "handback", "hand back", "what do you need

- Skill: `broomva/handback` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add broomva/handback`
- Raw SKILL.md: https://api.skillmd.com/api/skills/broomva/handback/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: broomva (https://skillmd.com/u/broomva)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/broomva/handback

---


# handback — end an arc with a work order, not a lab notebook

**Spec:** `broomva/workspace` → `docs/specs/2026-08-18-agent-handback-contract.html` (BRO-2179).

## Why this skill exists

Measured over 994 Claude Code transcripts (analysis set: 100 sessions of ≥6h
wall-clock and ≥150 assistant turns):

| | |
|---|---|
| Long arcs whose final message mentions a blocker at all | 31 / 100 |
| Long arcs **halting on a human** (terminal-stance phrasing) | **18 / 100** |
| …of those 18, containing a conforming ask block | **0 / 18** |
| …containing an imperative anywhere in the message | 3 / 18 |
| …containing any `?` at all | 13% |
| …with the question next to the blocker it describes | 6% |
| Stating a default if the human stays silent | 5% of all 100 |
| Ever emitting a push notification | **0 / 100** |
| Blockers knowable before the arc started | **81%** |

The two blocker rows differ on purpose. The broad count (31) includes messages
that merely *mention* being blocked — "the pre-commit hook blocked it", "#381
remains blocked by the hang". The narrow count (18) is the defensible one: a
terminal message that stops the arc **on a person**. The enforcement gate keys on
the narrow definition, because refusing a healthy receipt that happens to contain
the word "blocked" would fight the operator.

The ask usually exists. It is placed last, written in the indicative ("Not
merged — auto-merge correctly blocked"), and carries no default, so the arc
dies on it — median 2.4h of stalled arc-time behind such a message, 25 of them
overnight-length.

## Rule zero — asking is the last resort, not the interface

**No ask may exist until every rung below has been tried and recorded.** A row
with an empty `exhausted` list is a defect, not a question.

| Rung | Try this | |
|---|---|---|
| 1 · Read | Is the answer already on disk — ticket history, prior conversations, the knowledge graph, the handoff doc, the code? | Most "decisions" are recoverable, not new |
| 2 · Standing grant | Has this exact question been answered before? Check `.control/preauth.yaml` | Re-asking a settled question is the cheapest failure to eliminate |
| 3 · Delegate | Can a fresh agent resolve it — a reader, a researcher, an adversarial reviewer with different context? | Chain agents instead of chaining to the human |
| 4 · Reroute | Can another lane, worktree, fan-out, or approach go around it? | The blocker is often a path, not a wall |
| 5 · Loop | Can iteration resolve it — retry under a changed assumption, let a persist loop converge? | Slow beats blocked when nobody is awake |
| 6 · Default | Is the choice reversible? **Take it, log it, tell the human afterwards. Do not ask.** — "log it" means an entry in the ledger's `decisions:`, and "tell the human" means the 🔀 block below | Reversible decisions are not the human's to make in real time |
| 7 · Ask | Only now. Record which rungs were tried and why each failed. | |

**Rung 6 is where most asks should die.** A choice that can be undone with one
commit does not warrant stopping an arc; it warrants a line in the receipt.
Only actions that are **irreversible**, **externally visible**, or **spend
money** may reach rung 7 without a default — and the ask must say which.

## Rule minus-one — never stop the arc while an unblocked lane remains

Blocked is a **lane** state, not an **arc** state. When an ask fires: park the
lanes it gates, emit the ask (push it if outside the waking window), and
continue on the next unblocked lane. Run `handback` only when the unblocked set
is empty. An arc that halts with runnable work left is the failure this skill
exists to prevent.

## The shape — six blocks, always in this order

*"Always in this order" constrains **order**, never presence.* A block with no
content is omitted, not rendered empty — an empty 🔀 block would assert that
nothing was decided, and an empty ⛔ block would assert that nothing is blocked.
Only the receipt is unconditional.

```
## ⛔ Blocked on you — N items, ~M min
   table: # | ask (imperative, addressed to "you") | unblocks | if you say nothing
   a decision row lists options A/B/C, one marked suggested, each with its cost
   plain language only; hard cap 7 rows, ranked by what each unblocks

## ▶ Running meanwhile
   what is still executing, or what ran with zero input from you

## ✅ Shipped
   PR table. One line each. No narrative.

## 🔀 Decided for you — N choices, least-confident first
   table: # | what I decided | why it was mine to take | undo
   rendered from the ledger's `decisions:` list, never free prose
   every row carries its one-line reversal — that is what made it safe not to ask
   hard cap 7, same as the ask block; overflow counted in the header

## 📋 Receipt — the nine items, unchanged
   1 dep chain · 2 plan vs done · 3 parallel streams · 4 files changed · 5 PRs
   6 deploys · 7 validation · 8 merge result · 9 follow-ups

## 📎 Detail → docs/handoffs/<arc>.md
   the NARRATIVE lives there: what happened and why, the review sagas, the
   corrections. That prose is what this contract displaces.
```

## The ten rules

Each is derived from a measured failure, not a style preference.

1. **The ask block is first.** Not a "Your call" section at 80% depth.
   *Measured: the ask lands around p80 of the message.*
2. **Every row is an imperative addressed to "you"** — a command to run, a link
   to click, a value to paste, or a one-line answer to a closed question.
   *Measured: 0 of the 18 halting messages contained a conforming ask block.*
3. **A decision row offers options, not an open question.** Two or three
   concrete choices, each with its consequence in one line, one marked as the
   recommendation. Never "what should we do about X?" — always "A, B, or C; I
   suggest B because …".
4. **Plain language, no internal vocabulary.** No primitive numbers, no gate
   names, no acronyms, no ticket ID standing in for the question. If a term
   needs the spec to understand, it does not belong in an ask.
5. **Every row carries a default.** "If you say nothing, I do X." A row with no
   safe default must say so explicitly and name what it costs.
   *Measured: 5% stated a default. Silence is otherwise fatal.*
6. **Every row is self-contained.** Answerable without opening a ticket. The
   ticket ID is a reference for later, never the carrier of the question.
   *Measured: 58% used a ticket as the carrier; median 1 ticket, up to 13.*
7. **Rows are ranked by what they unblock**, stated in the row — "unblocks 9 of
   18 rows", "unblocks 1 lane". A tired person answering one thing should be
   answering the right one.
8. **Hard cap: 7 rows.** More than seven means the arc should have asked
   earlier. Overflow goes to the ledger, with the total stated in the header
   ("3 of 11 shown").
9. **The nine-item receipt stays, underneath the asks.** It is structured and
   proves the work. What this contract displaces is the **free-form narrative**
   — that moves to `docs/handoffs/`.
10. **The ask block ends with the reply already drafted — one line per row,
   numbered to match.** A copy-pasteable
   skeleton, one line per row, recommendation pre-filled — so answering is an
   *edit*, not a composition. Rules 2–6 fix what a row **says**; none of them
   lowers the cost of **replying**, and a perfectly-formed ask still stalls if
   answering it means composing prose at 1am. Reacting beats imagining: hand
   the reader something to strike through, not a blank box. The skeleton is
   generated *from the rows*: if it has four lines and the table has five, the
   fifth ask is one the reader is never prompted to answer — a silent drop
   dressed as a convenience.

## The 🔀 block — what rung 6 owes the human

Rung 6 is where most asks are supposed to die: *take the reversible default, log
it, tell the human afterwards.* For as long as this contract defined five blocks,
there was nowhere for that last clause to land — the ladder told the arc to decide
and say so, and the message shape had no room for it. Every silent-but-correct
decision therefore looked identical to no decision at all, while the user still
inherited it.

The 🔀 block is that room. It is **not** an ask block: nothing in it is a
question, and the arc did not wait for any of it.

| Property | Why |
|---|---|
| Rendered by `ask_ledger.py decisions --render-handback`, not written free-hand | The rules below — ordering, the undo, the cap, the overflow header — are executable there and tested. Stated only in prose they are four things an agent forgets one at a time |
| An **irreversible** choice may not appear here as a settled default | Rung 6 licenses reversible choices only. Recording an irreversible one is still right, but the schema forces it to carry `verdict: needs-user` and name the ask that took it to the human |
| A `needs-user` row is **excluded** from this block | It reached the human, so it belongs in ⛔ keyed by its `ask`. Rendering it in both would print one item twice under contradictory headings — "decided for you" and "blocked on you" — which this workspace's own arc ledger did before the renderer excluded them |
| **Least-confident first** | Confidence ranks; verdict groups. The reader's attention is finite and should land on the choice most likely to be wrong, not the one that happened to be made first |
| Every row shows its **undo** | The reversal is the entire justification for not having asked. A row that cannot state one is a row that should have been an ask |
| Hard cap 7, overflow counted | Same discipline as the ask block. More than seven means the plan was foggy — the clustering *is* the signal, and the fix is upstream in the spec, not a longer table |

**Where each verdict surfaces**, so nothing is duplicated and nothing is dropped:

| Verdict | Block | Why |
|---|---|---|
| `sound` | 🔀 | Decided and settled. The user owns it now |
| `unsound` | 🔀, with its corrected decision | Decided, and known to need redoing |
| `needs-user` | **⛔ only**, via its `ask` | It was not decided for them — it was asked |

Consequence worth stating plainly: because the schema forces an irreversible
choice to be `needs-user`, no valid ledger can render one in 🔀 at all. The
renderer keeps a defensive branch for a ledger nobody validated — an empty undo
column would read as "no undo needed", the opposite of the truth — but on a valid
ledger that branch is unreachable.

**`sound` is not skippable.** The temptation is to list only the shaky calls, but
a confident decision the user never made is still architecture the user now owns.
Trivial discretion — internal naming, cosmetic calls — compresses to a one-line
count; everything load-bearing gets a row.

## Anti-patterns

| Rationalization | Why it fails |
|---|---|
| "I'll describe the blocker; they'll know what to do" | A statement about the world transfers no obligation. Zero of 31 measured messages contained a request addressed to a person. |
| "The ticket explains it" | The reader has no context loaded and may be on a phone. The ticket was written by an agent for an agent. |
| "It's a big decision, I shouldn't presume a default" | Defaults are for **reversible** choices, and most are. Reserve no-default for irreversible / externally visible / money-spending. |
| "I'll list everything so they have full context" | Seven rows maximum. More means the ladder was not climbed or the hour-zero batch was skipped. |
| "I'll ask now and keep working after they answer" | Wrong order. Park the gated lanes and keep working *now*; the answer arrives whenever it arrives. |
| "Asking is safer than assuming" | Asking is expensive — median 2.4h of stalled arc-time, 25 overnight stalls in the measured corpus. Rung 6 exists for this. |
| "I'll write the narrative first so they understand the ask" | That ordering is the measured defect. Narrative goes to the handoff doc; the ask goes first. |
| "I took a reversible default, so there is nothing to report" | Rung 6 is a licence to **not ask**, not a licence to **not tell**. The whole clause is "take it, log it, tell the human afterwards." A decision with no record is one the user inherits without ever seeing. |
| "The 🔀 rows are really questions — I'll move them into the ask block" | Then the ladder was not climbed. If it still needs the human it never reached rung 6; if it reached rung 6 it is settled and reversible. Rows do not belong in both. |
| "I'll list only the decisions I'm unsure about" | `sound` is not skippable. A confident call the user never made is still architecture they now own — the point is disclosure, not confession. |
| "They can just tell me what they want in their own words" | That is the blank box rule 10 exists to remove. An answer that requires composing prose costs more than one that requires striking a line through, and the measured stall is hours, not minutes. |

## Composition

- **`handoff`** — same arc, different reader. `handoff` writes
  `docs/handoffs/YYYY-MM-DD-<arc>.md` for the next *agent*; `handback` writes
  the chat message for the *human*. A stopping arc usually produces both, and
  the handback's Detail block links to the handoff.
- **`autonomous`** — supplies the nine-item receipt that block 4 renders, and
  owns the pre-flight that builds the ask ledger.
- **`persist` / `governed-autonomy-loop`** — a parked lane is a lane the next
  iteration's `PROMPT.md` omits; `handback` fires only when none remain.

## References

- `references/template.md` — copy-paste skeleton with a worked example.

