Closes Stream H Task 5 (H6). Adds the PreToolUse wrapper around the pure
decomposition-detector module (Stream A Direction 3 / v4.1 §3.8).
What this catches:
- A feature secretly decomposed into 3+ small prompts whose primary_keywords
overlap heavily AND no planning skill (writing-plans / brainstorming) has
been invoked in the window. v4.1 hard-blocks mutating tools when the LLM
judge confirms decomposition; soft-flags on legit-distinct verdict; allows
when threshold not met or a planning skill was invoked.
Defensive design choices:
- decide() takes llmVerdict as an explicit string ('YES'|'NO'|null), not an
async LLM call — keeps the function pure and unit-testable
without network.
- llmVerdict=null degrades to soft_flag (with degraded:true), NOT hard_block.
This avoids repeating the Stream G Task 8 self-lockout where a fail-CLOSE
LLM hook bricked the session.
- main() is a no-op (exit 0) until the deferred wiring lands (history-ledger
reader from observer Stop hook + LLM judge config from Stream D). Until
then, the hook never blocks anything.
Regression: vitest tools 1748/1748 GREEN (was 1742; +6 wrapper-decide tests
under "enforce-decomposition-detector wrapper (Stream H Task 5)" describe
block, covering: empty history → allow, below threshold → allow, threshold
+ LLM YES → hard_block_mutating, threshold + LLM NO → soft_flag, threshold
+ skill present → allow, threshold + LLM unavailable → degraded soft_flag).
DEFERRED: .claude/settings.json registration (PreToolUse matcher
"Edit|Write|MultiEdit|NotebookEdit|Bash|Task", timeout 8000ms) AND main()
wiring (history-ledger reader + LLM judge integration). Batched with
H5/H7/H8 hook activations at end of Phase H-α/H-β.
Stream H Task 5 of 11. Plan: docs/superpowers/plans/2026-05-30-router-gate-v4-stream-H.md