fix(hooks): stop heredoc bodies false-blocking the commit gate (H-09b)#139
Merged
Conversation
COMMIT_RE captures git-commit args greedily across newlines, so a `git commit -F - <<EOF ... EOF` heredoc body was parsed as pathspecs; `git diff HEAD -- <body tokens>` then errored and the H-09b/H-10b/H-14 gate failed CLOSED - false-blocking the recommended multi-line-commit form (which surfaced landing this very branch). Add _strip_heredoc_bodies(): join `\`-newline continuations, then remove only the heredoc operator+body+delimiter, re-emitting the operator-line tail. Skip redirect-operator tokens in commit_pathspecs. Applied at both gate sites. The --cached staged scan and the worktree-union OVER-include for real pathspecs are untouched, so the v2.rev.0015 pathspec-bypass guard is preserved. Adversarial security review caught two ways an earlier cut weakened the gate, both now closed and locked by tests: (1) bounding to the first newline truncated at the literal newline inside a quoted `-m "subject\n\nbody"` message and dropped a trailing pathspec; (2) the heredoc strip swallowed a pathspec sitting on the operator line after `<<WORD`. Both shifted BLOCK->ALLOW vs baseline; the shipped form strips only the heredoc body. Tests: test_hook_guards.py gains unit assertions for _strip_heredoc_ bodies / commit_pathspecs (multi-line-message + pathspec, and the operator-line pathspec, both non-weakening) and integration 6l (benign heredoc allows), 6m (staged-crypto heredoc blocks), 6n (unstaged crypto via a multi-line `-m` pathspec commit still blocks). 102 guard assertions + migration suite green. CHANGELOG: the commit gate no longer false-blocks multi-line `git commit -F - <<EOF` commit messages. Claude-Session: https://claude.ai/code/session_011nnQYBPd5Dt1rmtf9CHNfU
SUaDtL
added a commit
that referenced
this pull request
Jun 27, 2026
* docs(changelog): roll the 2.6.0 release notes Reconcile the [2.6.0] CHANGELOG section for the release: broaden the intro beyond the farm work, add context-drift provenance (#145) and file-scoped context injection (#146) under Added, note the MIT to AGPLv3 relicense (#147, ADR-0009) under Changed, and add a Fixed section for #143, #139, and #138. Dated 2026-06-27. Also flips v2.feature.0001 to done now that file-scoped context injection has shipped and merged; the flip rides this release commit per ADR-0008. No version bump: plugin.json is already 2.6.0 and the ca-scoped commit window is unchanged. The relicense and docs commits touch no plugins/ca/ payload. Claude-Session: https://claude.ai/code/session_01QaLw7nTrRbHwygFar2R6zu * docs(license): reserve the dual-licensing right without offering it yet Soften the README "Commercial licensing" wording. The prior text implied proprietary licenses were actively on offer; the intent is narrower: the owner retains sole ownership and reserves the right to dual-license, but is not offering commercial licenses at this time. Inquiries may still be sent through GitHub and will be considered if and when a commercial path is established. The legal substance is unchanged. AGPLv3 plus sole copyright already secures the right; this only corrects the public statement so it does not overstate an active commercial offering. ADR-0009, the CLA, and the CHANGELOG already use the reserves-the-right framing, so no other file changes. Claude-Session: https://claude.ai/code/session_01QaLw7nTrRbHwygFar2R6zu --------- Co-authored-by: SUaDtL <SUaDtL@users.noreply.github.com>
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.
What
Fixes a false-positive in the H-09b/H-10b/H-14 commit gate discovered while landing #138: a
git commit -F - <<EOF … EOF(the recommended multi-line-commit form) was blocked.COMMIT_REcaptures git-commit args greedily across newlines, so the heredoc body was parsed as pathspecs;git diff HEAD -- <body tokens>then errored and the gate failed closed.Fix
_strip_heredoc_bodies(args)— join\-newline continuations, then remove only the heredoc operator+body+delimiter, re-emitting the operator-line tail (a pathspec after<<WORDis a real git arg).commit_pathspecsskips redirect-operator tokens.--cachedstaged scan and the worktree-union over-include for real pathspecs are untouched, so the v2.rev.0015 pathspec-bypass guard is preserved.Why this was risky — and how the review earned its keep
This touches the load-bearing security commit gate, so it went through adversarial security review, which caught two ways an earlier cut silently weakened the gate (both shifted BLOCK→ALLOW vs. baseline, both now closed and locked by tests):
split("\n",1)[0]also truncated at the literal newline inside a quoted-m "subject\n\nbody"message and dropped a trailing pathspec — reopening the worktree-union bypass.<<WORD.The shipped form strips only the heredoc body.
Tests
test_hook_guards.py:_strip_heredoc_bodies/commit_pathspecs, including the two non-weakening cases above (multi-line message + pathspec, and operator-line pathspec).-mpathspec commit still blocks).Known residual (not introduced here, errs closed)
COMMIT_RE's[^|;&]*truncates the captured args at a|/;/&inside a heredoc body, so a body line containing those chars can leave an unterminated heredoc that survives the strip and can still false-block. This errs closed (fail-safe), so it is not a weakening — noted for a future follow-up.https://claude.ai/code/session_011nnQYBPd5Dt1rmtf9CHNfU