# Outcome

status: DONE (six-hook prefilter slice landed+deployed); statusline-cache scope
addition resolved as a documented finding (no code — see Acceptance criteria);
SessionStart audit scope addition delivered as a measurement table (see report)
task IDs: sh-hook-fastpath
source request: owner-ordered PERFORMANCE lane — apply slopgate's baseline-guard
cheap-prefilter pattern to overdeck's always-on shell PreToolUse hooks. Mid-task
coordinator additions: (1) statusline-router.sh render-cache, (2) SessionStart
hook battery audit (measurement + in-lane `.sh` fixes only).

## Acceptance criteria

- quietcontext-nudge.sh, fs-scan-gate.sh, main-checkout-guard.sh,
  worktree-lock-gate.sh, bg-gate.sh, bash-gate.sh each get a bash-builtin
  literal prefilter (`$(</dev/stdin)`, `case`, `[[ =~ ]]`) that only ever
  causes exit-0-allow on payloads the unmodified hook would also allow.
- No new external process spawns added to any fast path.
- Committed differential/verdict test under `hooks/test/` proving no guard
  weakened; all existing hook tests (`bun test`) stay green.
- Per-hook before/after timing, 20-run EPOCHREALTIME median.
- Zero deleted files in the commit (`git diff --cached --name-status | grep -c
  '^D'` == 0, checked standalone, not `&&`-chained — exits 1 at count 0).
- Land via the worktree's direct-land path, deploy, then re-measure the LIVE
  installed copy of at least one hook.
- Statusline addition: implement OR — if the premise (pure file-cache-driven
  output) doesn't hold on inspection — document the conflict and recommend
  instead of shipping dishonest caching. `.sh`-lane only; no `.mjs`/settings.json.
- SessionStart addition: list+time the 9 hooks, determine empirically whether
  subagent spawns fire SessionStart, classify main-only vs subagent-relevant,
  fix only what's in `.sh`-lane scope, relay anything needing settings.json/
  matcher wiring to the dispatcher lane instead of touching it.

## Preserved WIP

None at start; worktree was already claimed and empty of other agents' edits.

## Constraints

- Guards must never weaken — deny cases stay denied. Prefilter is a superset
  check on raw JSON (safe: extra fall-through, never extra allow).
- Dispatcher/.mjs/settings.json territory belongs to another active lane —
  `.sh` files only.
- Never fabricate a caching win the code doesn't actually deliver (statusline
  premise conflict below).

## Execution steps

1. Read slopgate's baseline-guard.sh (reference pattern) and all six target hooks.
2. advisor() before editing — corrected scope: main-checkout-guard.sh needs the
   git-verb literals UNION the wt_write_targets literals (not verbs alone);
   fs-scan-gate perl untouched (prefilter already removes ~all perl spawns);
   bash-gate's win is lifting the existing token check above the jq call, not
   touching the rewrite logic below it; bg-gate needed a live check of whether
   `~/.config/overdeck/hook-controls.json` exists (it does) before assuming
   zero headroom; `\b` inside `[[ =~ ]]` needs an unquoted variable + positive
   per-branch test coverage (invalid regex silently takes the false/allow branch).
3. Implemented all six prefilters; built a differential harness (scratchpad)
   comparing pristine vs edited hook output byte-for-byte across a deny+allow
   matrix per hook, using a real fake git repo + worktree for the two guards
   with lock/write-target side effects.
4. advisor() review of the committed test — found two gaps: (a) both git-verb
   deny-path test cases used a worktree cwd, which can never deny — added
   `cwd=$FAKE` (main-root) deny cases for `git restore .` / `git checkout .`;
   (b) worktree-lock-gate's committed cases were both same-session (never
   denies) — added a real deny case via `WT_LOCK_PROC_DIR` fake-proc simulation
   of a second session while the lock owner is "alive"; (c) bash-gate's
   deny-proxy (any stdout) doesn't prove byte-identical rewrite — added exact
   `updatedInput.command` string assertions for `git log` and `find . -name x`.
5. Committed `hooks/test/sh-fastpath-verdicts.test.sh` (plain bash, no
   framework, exit non-zero on mismatch) — 26 assertions, all pass.
6. `bun test` in hooks/ — 58/58 green, unaffected.
7. Measured before/after per hook (20-run median) and the `pnpm install`
   fall-through case for main-checkout-guard.sh flagged by review (`install`
   is one of the trigger literals, so package-manager installs pay the
   ~59-82ms full-logic cost, same as before — prefilter helps the majority of
   non-mutating Bash but not that command family; correctness preserved by design).
8. Statusline: read statusline.py — `_core_line` renders `turn_count`, `cwd`,
   `model`, `context_window.used_percentage` straight from the per-call stdin
   payload, which changes on ~every render. An mtime-keyed cache of the
   rendered line would freeze those fields until an unrelated health/rate-limit
   file changed next — visibly wrong data on the line the owner reads most.
   Coordinator's message pre-authorized this outcome ("skip caching those
   fields' variance honestly and say so"). Decision: no code change to
   statusline-router.sh or statusline.py. Recommendation for relay:
   `refreshInterval` 60→180 in settings.json is the actual safe, cheap win
   (halves render calls without touching correctness); that edit belongs to
   the dispatcher lane (settings.json).
9. SessionStart audit: measured + classified (see receipt/report).
10. Land: direct-land path (worktree isolation rules), deploy, re-measure one
    live hook post-deploy.

## Current receipt

- Six-hook prefilter slice: implemented, differential-tested, verdict-tested,
  measured, `bun test` green. Landing next.
- Statusline: investigated, decision = no-op with documented reason + relay
  recommendation (refreshInterval). No code.
- SessionStart: measurement table delivered in chat/report; any `.sh` fix
  applied is listed there; matcher/settings.json changes relayed, not applied.

## Next executable action

Land the six-hook commit via the worktree's direct-land path, deploy, verify
the live installed copies carry the prefilters, re-measure one live hook.
