fix: git hooks self-heal when the init-time CLI shim breaks#89
Merged
Conversation
Why The repo-local shim baked the node binary and CLI entry paths captured at init time. When the checkout that ran init was deleted or the node version changed, the shim kept existing and stayed executable, so the hook fallback chain short-circuited on it, swallowed the failure, and notes silently stopped being recorded and pushed while git kept succeeding. The shim now resolves the repository's current CLI install at runtime (node_modules, then PATH) and keeps the init-time paths only as the last resort for restricted hook environments such as GUI git clients. Hook scripts gate each resolver on success — the CLI exits zero even for internal no-ops and failures, so a non-zero exit precisely means the CLI could not start — and fall through instead of stopping. When no resolver can run the CLI, the hooks emit a one-line stderr warning while still exiting zero, and the PR report action emits a notice when a PR has commits but no tracked data. User impact Deleting the worktree that ran init, upgrading node, or pruning the npx cache no longer silently disables Agent Note in checkouts that have a local or global CLI install, and the remaining failure modes are visible instead of silent. Commits and pushes are never blocked. Existing repositories pick up the new hooks and shim by re-running agent-note init. Verification npm -w packages/cli run build npm -w packages/cli run typecheck npm -w packages/cli run lint npm -w packages/cli test (495 passed, 4 new hook fallback tests) npm -w packages/pr-report run build npm -w packages/pr-report test (51 passed) Release note: Git hooks now recover automatically when the repo-local CLI shim breaks, and failures emit a visible warning instead of silently skipping Agent Note recording. Agentnote-Session: 4a6d322d-5afe-45e3-a11b-cf15d0e740a9
📝 WalkthroughWalkthroughChangesGit hook and reporting resilience
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Git
participant Hook
participant AgentNoteShim
participant AgentNoteCli
participant GitNotes
Git->>Hook: run post-commit or pre-push hook
Hook->>AgentNoteShim: try repo-local shim
AgentNoteShim->>AgentNoteCli: resolve current CLI or PATH CLI
AgentNoteCli->>GitNotes: record or push notes
Hook-->>Git: warn and exit zero if no resolver works
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/pr-report/src/index.ts`:
- Around line 261-268: Add tests in index.test.ts covering the report flow
around shouldRetryNotesFetch: assert that after retries, a report with
total_commits > 0 and tracked_commits === 0 emits the repair message through
core.notice, and assert that a null report returns early without triggering the
notice path. Reuse existing test setup and mocks for the index entry point.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e0ebede4-7ec6-4c9e-803b-736f5a16b38e
⛔ Files ignored due to path filters (2)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**packages/pr-report/dist/index.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (5)
CLAUDE.mddocs/architecture.mdpackages/cli/src/commands/init.test.tspackages/cli/src/commands/init.tspackages/pr-report/src/index.ts
…ilures Run the shim's node_modules and PATH resolvers without exec so a CLI launch that fails at runtime (for example an incompatible node found on a restricted PATH) still reaches the init-time absolute paths instead of consuming the attempt. Also assert in tests that the pre-push warning fires only when notes really were not pushed, and extract the PR report repair notice into buildMissingNotesNotice with unit tests. Addresses self-review and CodeRabbit feedback on PR #89. Release note: skip Agentnote-Session: 4a6d322d-5afe-45e3-a11b-cf15d0e740a9
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
All four fixes proposed in the issue, hardened for every install path (npx, bun, local node_modules, global, worktrees, bare repos, GUI git clients, husky/lefthook chains):
pre-push,post-commit): a shim that exists but cannot start the CLI no longer consumes the attempt withexit 0— the hook falls through to the common-dir shim,node_modules/.bin, and PATH. Gating is precise because the CLI deliberately exits zero for internal no-ops and failures (push-notesandrecordnever propagate errors), so a non-zero exit means exactly "the CLI could not start".node_modules/.bin/agent-note, then a PATH install, and keeps the init-time absolute paths as the last resort. Thecommand -v nodegate and the retained baked paths protect restricted hook environments (GUI git clients without the user's PATH) that today rely on the absolute node path — no regression for those users.refs/notes/agentnoteref so checkouts that never use Agent Note stay quiet, and the post-commit warning is deduplicated across the trailer and env-fallback record attempts.::notice(notwarning, since human-only PRs legitimately have no tracked data) when a PR has commits but zero tracked commits.The contradictory hook comments ("exact CLI version that generated these hooks" vs "tracks the current CLI implementation after upgrades") are unified on the latter, which the shim now actually implements.
prepare-commit-msgis untouched — it never invokes the CLI, so the issue's mention of it did not apply.Root cause
installLocalCliShimbakedprocess.execPathandresolve(process.argv[1])at init time. Deleting the checkout that ran init (worktree flows), upgrading node (mise/nvm), or pruning the npx cache left a broken-but-executable shim; the hooks'-xtest passed,|| trueswallowed the failure, and an unconditionalexit 0prevented the remaining resolvers from running. Notes silently stopped recording and pushing while git kept succeeding.User impact
Checkouts with any working CLI install self-heal immediately with the new hooks. Environments with no working install now see a one-line stderr warning instead of silent data loss, and PR reports flag suspicious zero-tracked results. Commits and pushes are never blocked. Existing repositories pick up the fix by re-running
npx agent-note init(managed hooks and the shim are upgraded in place).Validation
node_modulesfallback records the commit note; broken shim + fallback pushes notes to the remote; push with no usable resolver emits the warning once while the main push succeeds; commit with no usable resolver emits the warning exactly once and writes no noteCloses #88
🧑💬🤖 Agent Note
Total AI Ratio: ████████ 100%
Model:
claude-fable-5c191b04fix(init): self-heal git hooks when the init-time CLI shim breaks9febe29fix(init): let the shim fall through to init-time paths on runtime failures💬 Prompts & Responses (2 shown / 3 total)
c191b04fix(init): self-heal git hooks when the init-time CLI shim breaks🧑 Prompt
9febe29fix(init): let the shim fall through to init-time paths on runtime failures🧑 Prompt
Summary by CodeRabbit
Bug Fixes
Improvements
Documentation