fix(hooks): parse Stryker commands instead of scanning for the tool name - #2194
Merged
Merged
Conversation
Both C# mutation PreToolUse gates decided "is this a Stryker run?" with a bare regex search over the whole command string, with no notion of argument position or quoting — any command merely mentioning the tool name in prose (a --body, a grep, an echo, a Python comment) was treated as an invocation and blocked. Extract a shared hooks/lib/stryker_invocation.py predicate: tokenize with shlex (punctuation_chars mode, so &&/||/;/| are recognised as their own tokens while quoted text stays one token), split into operator-separated segments, and match the tool only in program position of a segment. Heredoc bodies are stripped before tokenizing. Falls back to the old permissive regex only when shlex can't tokenize the command at all, so a malformed command still fails closed. Both mutation_testing_smoke_gate.py and stryker_xunit_shim_guard.py now delegate to the shared predicate instead of keeping their own drifting copy, with the old regex kept only as each hook's degraded-import fallback. Closes #2185 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016uBnw1i52qEik2k9LSHa4n
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mutation_testing_smoke_gate.py,stryker_xunit_shim_guard.py) decided "is this a Stryker run?" with a barere.searchover the whole command string — any command merely mentioning the tool name in prose (a--body, agrep, anecho, a Python comment) was treated as an invocation and blocked.hooks/lib/stryker_invocation.py::is_stryker_invocation()predicate: tokenize withshlex(punctuation_charsmode, so&&/||/;/|are recognised as their own tokens while quoted text stays one token), split into operator-separated segments, and match the tool only in program position of a segment. Heredoc bodies are stripped before tokenizing. Falls back to the old permissive regex only whenshlexcan't tokenize the command at all, so a malformed command still fails closed.hooks/libunreachable).Test Plan
-t mtpmatch) — proving the bug — before writing the fix.python3 -m pytest plugins/dev-team/tests/hooks/test_stryker_invocation.py plugins/dev-team/tests/hooks/test_mutation_testing_smoke_gate.py plugins/dev-team/tests/hooks/test_stryker_xunit_shim_guard.py -q— 106 passed, including all pre-existing trigger cases (cd <dir> && dotnet stryker ...,dotnet-stryker, the wrapper script) unchangedpython3 plugins/dev-team/skills/code-review/scripts/repo_invariants.pyandinternal_double_detector.pystatic pre-passes — cleanpython3 scripts/check_md_references.py— cleanplugins/dev-team/tests tests/repo tests/agents tests/commands tests/docs tests/knowledge tests/stack_aware tests/skills tests/scripts tests/hooks) — 10786 passed, 48 skippedpre-pushhook's own local CI — all checks passedCloses #2185
🤖 Generated with Claude Code
https://claude.ai/code/session_016uBnw1i52qEik2k9LSHa4n
Generated by Claude Code