fix(hooks): commit guards match `git commit-tree` as `git commit` (unanchored substring)

Open Beginner friendly
#1,665 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
83/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
git, github, typescript
Domain
devtools, tooling

Research direction

Start in hooks/pre-tool.sh, where the issue identifies the seg_match callers and raw_commit_segment as matching git commit too broadly. Read those checks and the related hook tests, then reproduce with the supplied git commit-tree command. Add a regression case showing plumbing commands pass through while porcelain git commit guards still work.

Written by the indexing model from the issue text.

Description

bug
Bug Description

The commit guards in hooks/pre-tool.sh match git commit as an unanchored substring, so they also fire on the plumbing command git commit-tree, which doesn't commit staged files at all.

  • The no-changes guard (seg_match 'git commit', about line 1222 in 2.20.0) runs git status --porcelain, sees a clean tree (which is normal for commit-tree, since it builds a commit from an existing tree object), and blocks with HOOK_BLOCKED: No changes to commit. Stage files with 'git add' first.
  • raw_commit_segment selects segments that contain the literal substring "git commit", so a git commit-tree … -m "<msg>" would also have its message checked by the conventional-commit validator.

Seen on 2026-11-08 in a downstream graph repo. Under Claude Code auto mode, force-push is denied. To update a PR branch with a verified rebase, the runner tried to publish the rebased tree as a merge commit: git commit-tree HEAD^{tree} -p <pr-head> -p <main> -m …, then a normal push. The hook blocked it, so the runner fell back to git merge --no-commit plus git checkout <sha> -- ., which took two extra calls.

Steps to Reproduce
  1. In a clean checkout with the hook installed, run: git commit-tree HEAD^{tree} -p HEAD -m "chore: test"
  2. The hook blocks with HOOK_BLOCKED: No changes to commit.
Expected Behavior

The commit guards match git commit only as a whole word, for example git commit([[:space:]]|$), so commit-tree and commit-graph pass through. Other git commit-* plumbing is never a porcelain commit of staged changes.

Related

#1663: the same guard checks the tree before a compound command runs. That issue is about when the guard checks; this one is about what it matches.

Complexity

Small. It's a regex anchor in seg_match callers and raw_commit_segment, plus a test case.

Area

hooks

Environment

sequant 2.20.0, Claude Code VS Code extension, macOS, zsh.

Dominant language
TypeScript
Stars
1
Forks
1
Avg merge
10h 12m
Merged PRs (30d)
78

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from sequant-io/sequant

All issues in sequant-io/sequant

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.