Destructive bash gate previously denied every invocation with no
isChecked call, creating an infinite deny loop. Now gates per-command
on first attempt and allows retry after the model presents the required
facts (targets, rollback plan, user instruction).
Addresses greptile P1: "Destructive bash gate permanently blocks"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GATEGUARD_STATE_DIR env var for test isolation (hook + tests)
- Exit code assertions on all 9 tests (no vacuous passes)
- Non-vacuous allow-path assertions (verify pass-through preserves input)
- Robust newline-injection assertion
- clearState() now reports errors instead of swallowing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Use run-with-flags.js wrapper (supports ECC_HOOK_PROFILE, ECC_DISABLED_HOOKS)
2. Add session timeout (30min inactivity = state reset, fixes "once ever" bug)
3. Add 9 integration tests (deny/allow/timeout/sanitize/disable)
Refactored hook to module.exports.run() pattern for direct require() by
run-with-flags.js (~50-100ms faster per invocation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A PreToolUse hook that forces Claude to investigate before editing.
Instead of self-evaluation ("are you sure?"), it demands concrete facts:
importers, public API, data schemas, user instruction.
A/B tested: +2.25 quality points (9.0 vs 6.75) across two independent tasks.
- scripts/hooks/gateguard-fact-force.js — standalone Node.js hook
- skills/gateguard/SKILL.md — skill documentation
- hooks/hooks.json — PreToolUse entries for Edit|Write and Bash
Full package with config: pip install gateguard-ai
Repo: https://github.com/zunoworks/gateguard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>