Build Log · July 16, 2026

Gate Enforcement Gap

Gates were checklists enforced by Claude's own memory — built a real PreToolUse hook that mechanically blocks commits/pushes without fresh gate evidence.

  • OS
  • Enforcement
  • Hooks
  • Crucible
PreToolUse hook shipped
1

PreToolUse hook shipped

live commit attempts proving deny/deny/allow
3

live commit attempts proving deny/deny/allow

Council personas run (architect, QE, steward)
3

Council personas run (architect, QE, steward)

Timeline

  1. Start

    Zeb names the gap

    Gates are self-graded — no mechanism stops Claude from skipping triggers.md

  2. Early

    Crucible attempt fails

    npm run crucible:architect crashed under non-interactive Bash — misdiagnosed as inconsistency

  3. Mid

    Root cause found

    runPre() uses readline, blocks on stdin — deterministic failure under any non-interactive caller, not flaky

  4. Mid

    Council ran clean via crucible:council

    One API call, three personas (architect/QE/steward) + synthesis, converged on process-vs-substance ceiling

  5. Late

    Hook built, tested, wired

    .claude/hooks/gate-check.mjs proven against 3 live git commit --dry-run attempts

What shipped

  • A PreToolUse hook (.claude/hooks/gate-check.mjs) that mechanically blocks git commit/git push unless a fresh, substantive gate-evidence marker exists — wired into .claude/settings.json

  • Marker schema: .claude/gate-evidence.json (gitignored, session-scratch only — not the durable record)

  • Fixed crucible.mjs docs to mark interactive persona modes (pre/architect/customer/etc.) as terminal-only, pointing to crucible:council for programmatic use

  • Anvil + Strike entries capturing the process-vs-substance enforcement ceiling

“you have the ability to run this via the root level env that gives you API access to chat. last time you had no problem invoking this. why is this so inconsistent?”
— Zeb, after the crucible:architect crash — the push that led to actually reading the script instead of guessing