0%

Section 02: No-Side-Effect-Hooks Rule

Status: Not Started Goal: A hook is a pure gate. Author the rule SSOT, then convert every mutating hook (regenerate + stage at commit) to verify-only (fail-on-stale, never write).

Success Criteria:

  • .claude/rules/no-side-effect-hooks.md SSOT defines: hooks verify→pass/reject; mutation/staging banned.
  • Mutating lefthook hooks (bug-tracker render --write-back && git add, render-index) converted to fail-on-stale verify-only.
  • Commit-time reviewed_field_guard.py lefthook entry removed (superseded by §01 + §04).
  • STRUCTURE:hook-side-effect reviewer label + cure; audit finds zero hook-body mutation.

Context: Hooks that --write-back and git add regenerated content mutate tracked plan files as a hidden side-effect of committing — a write the user never approved. A hook must only verify and reject.

Depends on: None.


Intelligence Reconnaissance

Queries run 2026-05-26:

  • scripts/intel-query.sh search "lefthook hook write-back side-effect" — N/A on the Rust-only code-symbol graph; this section touches lefthook.yml, .claude/hooks/, .claude/rules/. Recorded per plan-schema non-Rust allowance.
  • Direct grounding (this session): lefthook.yml line ~77 runs python3 -m scripts.plan_corpus.bug_tracker.render --mode=by-subsystem --split-per-section --write-back && git add bug-tracker/section-*.md; a render-index hook regenerates index.md on staged plan.json change; reviewed-field-guard runs python3 -m scripts.plan_corpus.reviewed_field_guard at pre-commit.

Results summary [ori]: three mutating/at-commit hooks to address — bug-tracker render (--write-back && git add), render-index, reviewed_field_guard (removed, not converted — its enforcement moves to §01+§04). Verify-only conversion = run the renderer in --check mode; FAIL with “run render --write-back then re-commit” when output is stale.


02.1 Author no-side-effect-hooks rule SSOT

File(s): .claude/rules/no-side-effect-hooks.md (new)

  • Author the rule: hooks (PreToolUse, pre-commit, commit-msg, any) MUST be pure gates — read state, verify, emit pass/reject + reason; NEVER write/stage/mutate. A hook needing regenerated output FAILS-on-stale with an explicit “run X to regenerate, then re-commit” message.
  • Define reviewer enforcement: STRUCTURE:hook-side-effect (severity + trigger: any hook body that writes/stages/git adds) + cure pointer.
  • Cross-reference: state-discipline.md (plan file SSOT), skill-control-contract.md, workflow-ownership.md.
  • Subsection close-out (02.1) — MANDATORY before 02.2:
    • Tasks [x]; python3 scripts/prose-lint.py .claude/rules/no-side-effect-hooks.md exit 0.
    • Update subsection statuscomplete.
    • Repo hygiene checkcompiler_repo/diagnostics/repo-hygiene.sh --check.

02.2 Convert mutating hooks to verify-only

File(s): lefthook.yml; scripts/plan_corpus/bug_tracker/render.py (add/confirm --check); the render-index hook

  • Convert the bug-tracker render hook: replace render ... --write-back && git add ... with a --check invocation that exits non-zero + prints the regenerate command when output is stale. No write, no stage.
  • Convert the render-index hook to --check fail-on-stale (no write-back).
  • Remove the reviewed-field-guard lefthook entry (its enforcement is §01 write-time deny + §04 read-time rejection). Note the removal in the rule’s HISTORY/cross-ref so the supersession is traceable.
  • Audit: grep -nE "write-back|git add" lefthook.yml returns zero hook-body matches.
  • Subsection close-out (02.2) — MANDATORY before 02.N:
    • Tasks [x]; a deliberately-stale render FAILS the hook with the regenerate message (verified).
    • Update subsection statuscomplete.
    • Repo hygiene checkcompiler_repo/diagnostics/repo-hygiene.sh --check.

02.N Completion Checklist

  • 02.1–02.2 [x] and status complete.
  • .claude/rules/no-side-effect-hooks.md exists; prose-lint exit 0.
  • No hook body mutates/stages: grep -nE "write-back|git add" lefthook.yml zero matches in hook run: lines.
  • A stale generated artifact FAILS its hook with a regenerate instruction (manual proof).
  • Plan sync — close via §06 /independent-review (bootstrap caveat); update 00-overview.md + index.md.
  • Repo hygiene checkcompiler_repo/diagnostics/repo-hygiene.sh --check.

Exit Criteria: .claude/rules/no-side-effect-hooks.md is the SSOT; the bug-tracker render + render-index hooks are verify-only (fail-on-stale, no write/stage); the commit-time reviewed_field_guard entry is removed; an audit finds zero hook-body mutation.