# ADR 0006: prompt-hook continueOnBlock Migration

> Status: ACCEPTED · session main-2026-05-19-deep-2 · issue #447
> Source research: docs/research/2026-05-19-prompt-hook-migration.md
> Project-instruction file: this repo uses `CLAUDE.md` on Claude Code / Cursor; the Codex CLI equivalent is `AGENTS.md` (instruction-file-resolution per repo doc-consistency rule).

## Context

Issue #428 ("Adopt PostToolUse `continueOnBlock: true` for quality-gate feedback") set out to route `hooks/post-edit-validate.mjs`'s typecheck failure back into the *same* Claude turn instead of dying silently on stderr — the motivating cautionary tale is the 8-pipeline silent-regression incident (2026-05-09 deep-3 → 2026-05-10 deep-2, fixed in deep-2), still cited in `CLAUDE.md`/`AGENTS.md` "Critical Gotchas" as the canonical reason CI status is the session-start source of truth.

#428 **shipped partial**: W1-D1 (2026-05-17 deep-1) verified against the official docs that `continueOnBlock` is documented only for **prompt-type and agent-type** hooks, while all 13 entries in `hooks/hooks.json` are **command-type** (verified: `hooks/hooks.json:8,13,26,36,41,53,65,77,83,94,106,116,128,140` — zero `prompt`/`agent`, zero `continueOnBlock`). #428 therefore shipped the documented command-hook alternative — `additionalContext` via `hookSpecificOutput` — and filed #447 to investigate a prompt-type migration. The research note resolves #447's three acceptance criteria; three findings from it are load-bearing for this decision:

1. **PostToolUse blocking is an event-level constraint, not a handler-level one.** The official exit-code table reads `PostToolUse | No | Shows stderr to Claude (tool already ran)` (https://code.claude.com/docs/en/hooks.md), corroborated by four independent sources (claudefa.st, stevekinney.com, thepromptshelf.dev — research note F5, W3 Step 2). Because the tool has *already executed* by PostToolUse, no hook type — `command`, `prompt`, or `agent` — can block-and-continue there. A `decision: "block"` from a PostToolUse hook (stevekinney.com, verbatim) "cannot prevent the action" — it only "can provide feedback for future actions."

2. **The "v2.1.142 extended `continueOnBlock` to PostToolUse command hooks" claim is REFUTED.** The W2 research carried this as F7 with an UNVERIFIED flag. W3 Step 2 (2026-05-19) fetched four authoritative/community sources fresh: the live official docs list exactly five common fields (`type`, `if`, `timeout`, `statusMessage`, `once`) with **no `continueOnBlock`** and **no `v2.1.142` changelog entry** at the confirmed runtime version `2.1.144` (`claude --version`). The claim traced to an uncorroborated techsy.io web-search summary and is resolved **FALSE**: `continueOnBlock` exists only for `prompt`/`agent` handler types, never for `command` type.

3. **`additionalContext` already delivers the #428 goal in-turn.** The Agent-SDK hooks doc (https://code.claude.com/docs/en/agent-sdk/hooks, Outputs §) states a PostToolUse command hook may set `additionalContext` "to append information to the tool result" — read by Claude *in the same turn*. The capability #447 chases is already closed by #428's shipped command-hook path (research note F6).

The decisive reframing: #447 assumed prompt-type migration would unlock in-turn blocking on a post-edit failure. The event-level constraint forbids in-turn *blocking* at PostToolUse for every handler type, and the in-turn *feedback* objective is already met at zero marginal cost.

## Decision

**Decision: Stay — migrate-none.** No PostToolUse / PostToolBatch / PostToolUseFailure hook is migrated from command-type to prompt-type or agent-type; all 13 hooks in `hooks/hooks.json` remain command-type. This verdict rests on a single falsifiable claim: *prompt-type migration buys zero new PostToolUse capability* — because PostToolUse blocking is event-level (the tool has already run, per F5/W3-Step-2) and the in-turn-feedback goal of #428 is already delivered by the shipped command-hook `additionalContext` channel (F6). The migration would add a per-invocation Haiku LLM call, a 30s timeout exposure (vs the repo's 5s command override at `hooks/hooks.json:54`), model nondeterminism, and the loss of free deterministic ground truth (`tsgo --noEmit` for `post-edit-validate`, a 13-rule policy file for `pre-bash-destructive-guard`, a lookup table for `post-tool-failure-corrective-context`) — in exchange for nothing the PostToolUse event permits. For `pre-bash-destructive-guard.mjs` specifically, inserting a Haiku judgement into the `rm -rf` path with a fail-open LLM-timeout branch (`hooks/pre-bash-destructive-guard.mjs:299-304`) would be a security regression, not an improvement. **Narrow documented exception:** a *new* agent-type hook at **Stop or PreToolUse only** (never PostToolUse) is the correct primitive *if* a future need requires model reasoning over repo files before a gate that a deterministic check cannot make (e.g., "block this commit unless changed files have matching tests") — added beside the command hooks, never as a migration of an existing one. **No current hook meets this bar.**

## Consequences

- **No hook changes.** `hooks/hooks.json` and all hook sources stay command-type. Zero per-invocation LLM cost is preserved; the fail-open-by-design auditability of every hook (`exit 0`/`emitAllow`) is preserved.
- **`.claude/rules/loop-and-monitor.md` needs NO change.** #447 AC-3 ("update if the answer changes routing guidance") resolves to *no update required*: hook handler-type selection is orthogonal to the `/loop` vs `Monitor` vs `Routines` routing decision (the file LM-001..LM-007 does not mention hooks). The relevant rule surface is instead `.claude/rules/verification-before-completion.md` § "The Gate Function" — the #428 command-hook `additionalContext` feedback-loop note belongs there, carried over from #428's own acceptance criteria (this ADR does not itself edit that file; the follow-up tracks it).
- **#428's goal is confirmed met, not regressed.** The in-turn typecheck-failure feedback that motivated the 8-pipeline-incident defence is already live via command-hook `additionalContext`; this ADR documents *why* no further migration is warranted, closing the #447 investigation rather than deferring it.
- **Residual unknowns (preserved honestly):** the exact token-billing treatment of hook-internal prompt-type LLM calls is UNVERIFIED — no official Anthropic source states whether such calls bill the operator's API account, count against context, or are handled differently (research note F4, W3 Step 4). This does not affect the verdict: even at zero cost, the event-level blocking constraint (F5) and the compiler-ground-truth/accuracy argument stand independently. The F7 v2.1.142 `continueOnBlock`-for-command-hooks claim is now RESOLVED FALSE against pinned runtime `2.1.144` and is retained below only as a low-priority watch item against future CC versions.

## Follow-ups

- **Close #447 with this ADR as the answer** — verdict: migrate-none (Stay). All three acceptance criteria resolved: (AC-1) cost/latency model synthesised from cited docs, live spike correctly scoped out (nested `claude` session out of scope; hook needs project infra absent in /tmp); (AC-2) zero hooks warrant migration; (AC-3) loop-and-monitor.md unchanged.
- **File a low-priority watch-item issue:** re-verify the F7 "`continueOnBlock` for PostToolUse command hooks" claim against the pinned CC runtime on each major Claude Code upgrade. Resolved FALSE at `2.1.144` (2026-05-19); reopen the migration question only if a future version documents `continueOnBlock` for `command`-type handlers *and* a PostToolUse blocking primitive.
- **Carry-over from #428 (tracked, not done here):** add the command-hook `additionalContext` feedback-loop note to `.claude/rules/verification-before-completion.md` § "The Gate Function" (originally a #428 AC item; explicitly NOT `.claude/rules/loop-and-monitor.md`).
- **Optional doc-note:** record in the hooks-relevant documentation that PostToolUse blocking is event-level (the tool has already run) — no handler type changes this — to pre-empt a future re-derivation of the #447 question.

Sources: https://code.claude.com/docs/en/hooks.md · https://code.claude.com/docs/en/agent-sdk/hooks · https://claudefa.st/blog/tools/hooks/hooks-guide · https://stevekinney.com/courses/ai-development/claude-code-hook-control-flow · https://thepromptshelf.dev/blog/claude-code-hooks-complete-reference-2026/ · `claude --version` → 2.1.144 (W3, 2026-05-19)
