Restricted, and still all 34 hooks fired

CC 2.1.248 added --restricted: no Bash, no WebFetch, no user or project settings, file tools fenced to the working directory. The open question for a plugin with 154 hook entries was which of them break in that mode. Measured on 2.1.251: none. This page shows the lane that keeps it that way on every PR, at zero model spend.

1. What the process was offered, by mode

tools in the request CC sent
Bash / WebFetch present
distinct plugin hooks that fired
hooks reporting ok: false
model spend$0 (local stub of the Messages API answered all 7 requests)

2. The hooks that fired under --restricted

One-turn session ("reply ok"). PreToolUse and PostToolUse hooks are absent because no tool ran, which is correct for a one-turn prompt; Stop and SessionEnd hooks are included because the runner waits three seconds for them to flush.

3. How the lane asserts it

#AssertionWhat proves itNegative control
1the run completed and answeredresult: ok, is_error: falsestub down: run fails
2the process really was restrictedthe stub logged the tool list; no Bash, no WebFetchsame run without the flag: FAIL, 38 tools including Bash and WebFetch
3plugin hooks firedhook-timing.jsonl in the run's private HOME has entriesplugin not loaded: file absent, FAIL
4the failing set is the accepted sethooks with ok:false equal expected-hook-failures.txt (empty)list edited to name one hook: FAIL, [] != ["lifecycle/nonexistent-hook"]

The runner gives claude a fresh HOME, so the hook log it reads can only have been written by this run (twelve other sessions were live on the machine that produced these numbers). The stub is 60 lines of node: every POST /v1/messages gets an SSE stream that says "ok"; everything else is logged and 404s. The policy that real model calls never run in CI holds.