Skip to content

fix(hooks): stop the guard from blocking heredocs and unindexed sessions (v2.1.2) - #31

Merged
denfry merged 2 commits into
mainfrom
fix/hook-guard-false-positives
Sep 25, 2026
Merged

denfry merged 2 commits into
mainfrom
fix/hook-guard-false-positives

Conversation

@denfry

@denfry denfry commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Problem

The PreToolUse guard from 2.1.1 blocked calls it should have let through. In a real session it:

  • kept intercepting after the agent had already run codebase-index search, because that search was the one that built the index: the guard saw no index, returned early, and never recorded that the index was used;
  • denied a Bash call that only wrote a PowerShell script via cat > x.ps1 <<'EOF', because ; Select-String "BUILD FAILED" inside the heredoc body looked like a code search;
  • denied the retry too, since the retry was keyed by the full tool input (description included) and the regenerated command differed by a few characters;
  • cut grep "a\|b" at the \|, producing a broken suggested query.

Solution

  • Session state moves to the system temp directory (CBX_HOOK_STATE overrides it) and is written before the index lookup, so the first index command always turns the guard off.
  • Heredoc bodies are stripped before scanning; newlines separate commands.
  • Retries are matched by the normalised search term.
  • Quoted arguments are parsed whole.

Verification

  • 6 new tests in tests/test_hooks_guard.py, all failing before the fix; full suite passes (coverage 86%), ruff and mypy clean.
  • Replayed every Bash call of the affected session through the new guard: none denied. In a fresh session a real grep --include=*.java is nudged once and its retry passes; the heredoc scripts pass.

Compatibility

Sessions started before the upgrade keep their old state inside the index, so they may be nudged once more. No settings changes needed.

Also bumps the version to 2.1.2 with every mirror synced.

The guard kept denying calls in a session that had already used the index:
the first codebase-index command ran before the index existed, so the guard
returned early and never recorded it. Session state now lives in the temp
directory and is written before the index lookup.

Heredoc bodies are stripped before scanning, retries are keyed by search
term instead of the full tool input, quoted alternations are parsed whole,
and newlines separate commands.
Version bump with every mirror synced (plugin.json, requirements.lock, skill stamps) and the 2.1.2 release notes.
@denfry
denfry merged commit b5c4940 into main Sep 25, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant