fix(init): update v1 workflows and harden hook recording#71
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughBump documented workflow examples to wasabeef/AgentNote@v1; add tokenizer-based isAgentNoteHookCommand and apply it across agent adapters, CLI init/commit/record/status, core record evidence checks and fallback, and expanded tests. ChangesVersion Upgrade to wasabeef/AgentNote@v1
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI (dist/cli.js)
participant HookMatcher as isAgentNoteHookCommand
participant AgentAdapter as AgentAdapter (claude/codex/cursor/gemini)
participant GitHooks as prepare/post-commit hooks
participant Recorder as recordCommitEntry / recordHeadFallback
CLI->>HookMatcher: parse configured hook commands
HookMatcher->>AgentAdapter: identify managed agent hooks
GitHooks->>Recorder: trigger recording or write fallback marker
Recorder->>CLI: invoke `agent-note record` or `--fallback-head` flow
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/cli/src/commands/init.test.ts`:
- Line 408: The test's internal-package-path guard currently checks for the
exact string "packages/dashboard@v1" which is version-specific; update the
assertion that references dashboardWorkflow (e.g., the expression using
dashboardWorkflow.includes("packages/dashboard@v1")) to instead detect any
dashboard package prefix by checking elements with
startsWith("packages/dashboard") or a regex match (e.g., items.some(p =>
p.startsWith("packages/dashboard"))), so the guard is version-agnostic and
rejects dashboard packages regardless of version suffix.
In `@website/src/content/docs/fr/dashboard.mdx`:
- Line 48: Replace the straight ASCII apostrophe in the French text (currently
written as "l'artefact" around the Dashboard workflow paragraph) with the
typographic right single quotation mark (’), ensuring consistency with other
French typography on the page; search for other occurrences of ASCII apostrophes
in website/src/content/docs/fr/dashboard.mdx (e.g., "l'artefact") and replace
them with the typographic apostrophe to match the locale style.
🪄 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: ca1e1592-5520-4217-8d7a-c8f81730cb8f
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (41)
README.de.mdREADME.es.mdREADME.fr.mdREADME.id.mdREADME.it.mdREADME.ja.mdREADME.ko.mdREADME.mdREADME.pt-br.mdREADME.ru.mdREADME.zh-cn.mdREADME.zh-tw.mddocs/architecture.mddocs/knowledge/agent-skill.mdpackages/cli/src/commands/init.test.tspackages/cli/src/commands/init.tspackages/dashboard/workflow/resolve-pages-target.test.mjswebsite/src/content/docs/dashboard.mdxwebsite/src/content/docs/de/dashboard.mdxwebsite/src/content/docs/de/github-action.mdxwebsite/src/content/docs/es/dashboard.mdxwebsite/src/content/docs/es/github-action.mdxwebsite/src/content/docs/fr/dashboard.mdxwebsite/src/content/docs/fr/github-action.mdxwebsite/src/content/docs/github-action.mdxwebsite/src/content/docs/id/dashboard.mdxwebsite/src/content/docs/id/github-action.mdxwebsite/src/content/docs/it/dashboard.mdxwebsite/src/content/docs/it/github-action.mdxwebsite/src/content/docs/ja/dashboard.mdxwebsite/src/content/docs/ja/github-action.mdxwebsite/src/content/docs/ko/dashboard.mdxwebsite/src/content/docs/ko/github-action.mdxwebsite/src/content/docs/pt-br/dashboard.mdxwebsite/src/content/docs/pt-br/github-action.mdxwebsite/src/content/docs/ru/dashboard.mdxwebsite/src/content/docs/ru/github-action.mdxwebsite/src/content/docs/zh-cn/dashboard.mdxwebsite/src/content/docs/zh-cn/github-action.mdxwebsite/src/content/docs/zh-tw/dashboard.mdxwebsite/src/content/docs/zh-tw/github-action.mdx
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/cli/src/agents/claude.ts (1)
149-176:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDo not filter Claude hooks at group level; filter nested
hooks[]entries instead.Current logic serializes each group and removes the entire group if any managed command is present. That can delete unrelated custom hooks living in the same group.
💡 Proposed fix (apply in both installHooks and removeHooks paths)
for (const [event, entries] of Object.entries(hooks)) { - hooks[event] = entries.filter((entry) => { - const text = JSON.stringify(entry); - return !isAgentNoteHookCommand(text, AGENT_NAMES.claude, { allowMissingAgent: true }); - }); + hooks[event] = entries + .map((entry) => { + const group = entry as { hooks?: Array<{ command?: string }> }; + if (!Array.isArray(group.hooks)) return entry; + return { + ...group, + hooks: group.hooks.filter( + (hook) => + !( + typeof hook.command === "string" && + isAgentNoteHookCommand(hook.command, AGENT_NAMES.claude, { + allowMissingAgent: true, + }) + ), + ), + }; + }) + .filter((entry) => { + const group = entry as { hooks?: unknown[] }; + return !Array.isArray(group.hooks) || group.hooks.length > 0; + }); if (hooks[event].length === 0) delete hooks[event]; }As per coding guidelines: ensure enablement/removal operates safely without breaking the coding session flow.
🤖 Prompt for 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. In `@packages/cli/src/agents/claude.ts` around lines 149 - 176, The current code is removing entire hook groups when any managed Claude command appears because it JSON.serializes the group instead of filtering the group's entries; update both the install-hooks block (where hooks is built/merged using HOOKS_CONFIG) and removeHooks to iterate each group's entries and replace settings.hooks[event] with a filtered array: settings.hooks[event] = (entries as unknown[]).filter(e => !isAgentNoteHookCommand(JSON.stringify(e), AGENT_NAMES.claude, { allowMissingAgent: true })); then only delete the group if its filtered length is 0. Ensure you reference the same filtering logic in both the code that merges HOOKS_CONFIG into hooks and in removeHooks so unrelated custom hooks in the same group are preserved.
🤖 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/cli/src/agents/claude.test.ts`:
- Around line 561-585: Add a new test alongside the existing legacy SessionStart
detection that writes the same .claude/settings.json fixture, then invokes the
hook removal routine and asserts the feature is disabled; specifically, create a
test that uses the same settingsDir/setup as the "returns true for legacy
repo-local dist hooks" case, calls removeHooks(repoRoot) (the public helper
under test), and then asserts await claude.isEnabled(repoRoot) === false to
verify legacy hooks were removed; reference the existing test’s setup and the
functions removeHooks and claude.isEnabled when adding this paired regression.
In `@packages/cli/src/agents/hook-command.ts`:
- Around line 18-19: Replace the current substring check with exact token
matching for the --agent argument: instead of command.includes(`--agent
${agentName}`) test for a tokenized or regex match that only accepts --agent as
a flag whose value equals agentName (handle both “--agent value” and
“--agent=value” and ensure the match is bounded by whitespace or end-of-string);
when checking options.allowMissingAgent, detect the absence of any --agent token
(not the absence of the agentName substring) by looking for the --agent flag
token. Use variables command, agentName and options.allowMissingAgent to
implement this change so managed hook detection is precise across adapters.
---
Outside diff comments:
In `@packages/cli/src/agents/claude.ts`:
- Around line 149-176: The current code is removing entire hook groups when any
managed Claude command appears because it JSON.serializes the group instead of
filtering the group's entries; update both the install-hooks block (where hooks
is built/merged using HOOKS_CONFIG) and removeHooks to iterate each group's
entries and replace settings.hooks[event] with a filtered array:
settings.hooks[event] = (entries as unknown[]).filter(e =>
!isAgentNoteHookCommand(JSON.stringify(e), AGENT_NAMES.claude, {
allowMissingAgent: true })); then only delete the group if its filtered length
is 0. Ensure you reference the same filtering logic in both the code that merges
HOOKS_CONFIG into hooks and in removeHooks so unrelated custom hooks in the same
group are preserved.
🪄 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: 1a6252f3-7592-4bec-8849-5a748a539f76
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (9)
packages/cli/src/agents/claude.test.tspackages/cli/src/agents/claude.tspackages/cli/src/agents/codex.test.tspackages/cli/src/agents/codex.tspackages/cli/src/agents/cursor.test.tspackages/cli/src/agents/cursor.tspackages/cli/src/agents/gemini.test.tspackages/cli/src/agents/gemini.tspackages/cli/src/agents/hook-command.ts
Agentnote-Session: 89e518cc-e1cc-46d7-bdd0-86525a708263
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/cli/src/agents/claude.test.ts (1)
566-590:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd a paired legacy hook removal test.
The new test confirms that
isEnableddetects the legacy repo-local dist hook format, but doesn't verify thatremoveHookscan successfully clean up that same fixture. Add a companion case that:
- Sets up the legacy SessionStart fixture (lines 572-585),
- Calls
await claude.removeHooks(repoRoot),- Asserts
await claude.isEnabled(repoRoot) === false.This closes the behavior loop and ensures the new structured detection correctly removes legacy formats.
🧪 Suggested test addition
it("removes legacy repo-local dist hooks", async () => { const settingsDir = join(repoRoot, ".claude"); mkdirSync(settingsDir, { recursive: true }); writeFileSync( join(settingsDir, "settings.json"), `${JSON.stringify({ hooks: { SessionStart: [ { hooks: [ { type: "command", command: "node packages/cli/dist/cli.js hook --agent claude", async: true, }, ], }, ], }, })}\n`, ); await claude.removeHooks(repoRoot); const enabled = await claude.isEnabled(repoRoot); assert.equal(enabled, false, "legacy hooks should be removed"); });As per coding guidelines: when changing persistent-storage behavior (hook detection affects which hooks are kept/removed), ensure tests cover the full lifecycle.
🤖 Prompt for 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. In `@packages/cli/src/agents/claude.test.ts` around lines 566 - 590, Add a paired test that verifies removal of the legacy repo-local dist hook: reuse the legacy SessionStart fixture setup used for the "returns true for legacy repo-local dist hooks" case (create .claude/settings.json with the legacy hooks payload), then call await claude.removeHooks(repoRoot) and assert that await claude.isEnabled(repoRoot) === false; this test should reference the same fixture creation logic and call the claude.removeHooks and claude.isEnabled functions to confirm the legacy hooks are cleaned up.
🤖 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/cli/src/agents/hook-command.ts`:
- Around line 55-62: Add a one-line comment inside hasHookTokenSequence
explaining the basename special-case: clarify that when sequence[0] equals
CLI_JS_HOOK_TOKENS[0] we compare tokenBasename(token) to allow repo-local paths
like "packages/cli/dist/cli.js" to match the hook token; reference the
CLI_JS_HOOK_TOKENS constant and tokenBasename function so future readers
understand why we check basename instead of full token.
---
Duplicate comments:
In `@packages/cli/src/agents/claude.test.ts`:
- Around line 566-590: Add a paired test that verifies removal of the legacy
repo-local dist hook: reuse the legacy SessionStart fixture setup used for the
"returns true for legacy repo-local dist hooks" case (create
.claude/settings.json with the legacy hooks payload), then call await
claude.removeHooks(repoRoot) and assert that await claude.isEnabled(repoRoot)
=== false; this test should reference the same fixture creation logic and call
the claude.removeHooks and claude.isEnabled functions to confirm the legacy
hooks are cleaned up.
🪄 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: c096c8ec-0e8a-43c0-9c3d-719750a48ed1
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (4)
packages/cli/src/agents/claude.test.tspackages/cli/src/agents/claude.tspackages/cli/src/agents/hook-command.test.tspackages/cli/src/agents/hook-command.ts
Agentnote-Session: 89e518cc-e1cc-46d7-bdd0-86525a708263
Agentnote-Session: 89e518cc-e1cc-46d7-bdd0-86525a708263
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/cli/src/commands/status.test.ts`:
- Around line 129-132: Test code is invoking the CLI via shell-interpolated
execSync which risks shell-parsing bugs; replace those calls with node's
execFileSync using the cliPath variable as the executable and an argument array
(e.g., ["status"] or ["init","--agent",...]) and import execFileSync from
child_process, updating all occurrences of execSync in these tests (search for
execSync and cliPath) to use execFileSync(cliPath, args, {cwd, encoding}) to
avoid shell interpolation.
🪄 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: 86307508-7d68-4f92-9d03-4b5c5719cb7b
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (5)
AGENTS.mdCLAUDE.mddocs/architecture.mdpackages/cli/src/commands/status.test.tspackages/cli/src/commands/status.ts
Agentnote-Session: 89e518cc-e1cc-46d7-bdd0-86525a708263
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
website/src/content/docs/fr/dashboard.mdx (1)
48-48:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTypographic apostrophe issue reintroduced.
This line update reintroduced the straight apostrophe in "l'artefact" (appears 3 times) that was previously fixed. French typography requires the typographic apostrophe (').
✏️ Proposed fix
-Le workflow Dashboard généré utilise `wasabeef/AgentNote@v1` avec `dashboard: true` pour restaurer, synchroniser, builder, uploader l'artefact et persister les notes, puis publie la vue partagée sous `/dashboard/`. Si le même job uploade déjà un artefact GitHub Pages, Agent Note ajoute le Dashboard dans le répertoire `dashboard/` de cet artefact au lieu de remplacer le site existant. Si un autre job ou workflow publie déjà Pages, Agent Note saute la publication standalone; placez Agent Note dans le même job avant `actions/upload-pages-artifact` pour combiner un site de docs et le Dashboard. +Le workflow Dashboard généré utilise `wasabeef/AgentNote@v1` avec `dashboard: true` pour restaurer, synchroniser, builder, uploader l'artefact et persister les notes, puis publie la vue partagée sous `/dashboard/`. Si le même job uploade déjà un artefact GitHub Pages, Agent Note ajoute le Dashboard dans le répertoire `dashboard/` de cet artefact au lieu de remplacer le site existant. Si un autre job ou workflow publie déjà Pages, Agent Note saute la publication standalone; placez Agent Note dans le même job avant `actions/upload-pages-artifact` pour combiner un site de docs et le Dashboard.As per coding guidelines: Review documentation for natural language and locale parity.
🤖 Prompt for 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. In `@website/src/content/docs/fr/dashboard.mdx` at line 48, Replace the three straight apostrophes in the French text occurrences of "l'artefact" with the typographic apostrophe (’ U+2019); locate the sentence containing "wasabeef/AgentNote@v1" and "dashboard: true" and update each "l'artefact" -> "l’artefact", and scan the rest of website content in the same Markdown file for any other straight apostrophes to normalize to typographic ones.packages/cli/src/commands/status.test.ts (1)
66-69: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winUse argument-array execution for the new
gitsetup calls as well.This block adds new shell-string
execSync("git ...")calls. PreferexecFileSync("git", [...])here too, to keep command execution consistent and avoid shell-dependent behavior.Suggested diff
- execSync("git init", { cwd: repo }); - execSync("git config user.email test@test.com", { cwd: repo }); - execSync("git config user.name Test", { cwd: repo }); - execSync("git commit --allow-empty -m 'init'", { cwd: repo }); + execFileSync("git", ["init"], { cwd: repo }); + execFileSync("git", ["config", "user.email", "test@test.com"], { cwd: repo }); + execFileSync("git", ["config", "user.name", "Test"], { cwd: repo }); + execFileSync("git", ["commit", "--allow-empty", "-m", "init"], { cwd: repo });#!/bin/bash # Verify remaining shell-string git execSync calls in this file. rg -nP 'execSync\("git [^"]*"' packages/cli/src/commands/status.test.ts🤖 Prompt for 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. In `@packages/cli/src/commands/status.test.ts` around lines 66 - 69, Replace the shell-string execSync calls used to run git in the status.test.ts setup with argument-array execution: for each execSync("git ...", { cwd: repo }) invocation, use execFileSync("git", [...args], { cwd: repo }) instead (e.g., transform execSync("git init", ...) → execFileSync("git", ["init"], ...); similarly for the user.email, user.name and commit commands). Update the four calls in the test setup that call execSync so they use execFileSync with an args array to avoid shell-dependent behavior.
🤖 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/cli/src/agents/claude.test.ts`:
- Around line 620-649: Add a new unit test that mirrors the existing case but
uses a single command string containing both fragments (e.g., "echo agent-note
hook --agent claude") to ensure claude.isEnabled(repoRoot) returns false; update
the test suite near the existing "does not infer enabled state from unrelated
hook command fragments" test by creating the same .claude/settings.json with a
single command entry under SessionStart hooks and assert that
claude.isEnabled(repoRoot) === false so the parser doesn't false-positive on
tokens within one command string.
In `@packages/cli/src/agents/hook-command.ts`:
- Around line 55-63: hasHookTokenSequence only checks sequence[0] and
sequence[1], which can produce false positives; update hasHookTokenSequence to
ensure the entire sequence matches by checking that for a given index tokens has
enough remaining elements and that every element of sequence matches the
corresponding token (use tokenBasename(token) for the first token when comparing
against CLI_JS_HOOK_TOKENS[0] as the current code intended). In short: iterate
possible start indexes, verify index + sequence.length <= tokens.length, and
compare each sequence[i] to tokens[index + i] (with the basename special-case
for the first token) so the full hook token sequence must match.
---
Duplicate comments:
In `@packages/cli/src/commands/status.test.ts`:
- Around line 66-69: Replace the shell-string execSync calls used to run git in
the status.test.ts setup with argument-array execution: for each execSync("git
...", { cwd: repo }) invocation, use execFileSync("git", [...args], { cwd: repo
}) instead (e.g., transform execSync("git init", ...) → execFileSync("git",
["init"], ...); similarly for the user.email, user.name and commit commands).
Update the four calls in the test setup that call execSync so they use
execFileSync with an args array to avoid shell-dependent behavior.
In `@website/src/content/docs/fr/dashboard.mdx`:
- Line 48: Replace the three straight apostrophes in the French text occurrences
of "l'artefact" with the typographic apostrophe (’ U+2019); locate the sentence
containing "wasabeef/AgentNote@v1" and "dashboard: true" and update each
"l'artefact" -> "l’artefact", and scan the rest of website content in the same
Markdown file for any other straight apostrophes to normalize to typographic
ones.
🪄 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: 9b10ed0b-0dc0-4afb-a0ff-bd2ee9964928
📒 Files selected for processing (5)
packages/cli/src/agents/claude.test.tspackages/cli/src/agents/hook-command.tspackages/cli/src/commands/init.test.tspackages/cli/src/commands/status.test.tswebsite/src/content/docs/fr/dashboard.mdx
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/cli/src/commands/init.ts`:
- Around line 158-163: The current logic in the SESSION_ID fallback treats any
missing Agentnote-Session trailer as a stale-heartbeat signal and can
incorrectly allow amended commits (which intentionally skip trailers) to be
routed through recovery; change the fallback to use a distinct sentinel (e.g.,
"--stale-heartbeat") instead of "--fallback-head", and ensure the
prepare-commit-msg hook (prepare-commit-msg) explicitly writes that sentinel
only when it attempted to inject a trailer but skipped due to a stale heartbeat
(heartbeat older than 1 hour) while continuing to skip amend/ -c/ -C commits
without emitting the stale sentinel; update the code that reads SESSION_ID (the
SESSION_ID/TRAILE R_KEY handling) to branch on the new sentinel so amend-only
commits don't trigger recovery behavior.
In `@packages/cli/src/commands/record.ts`:
- Around line 40-47: The current fallback uses only filename overlap from
readHeadCommitFiles + hasSessionCommitFileEvidence which is too weak; change the
logic so recordCommitEntry is only called when stronger proof exists: update or
replace hasSessionCommitFileEvidence to verify blob/diff intersection with HEAD
blobs when session blob evidence is present, and/or verify transcript evidence
is tied to the current HEAD (e.g., matching commit hash or diff hunk IDs), then
call recordCommitEntry({agentnoteDirPath, sessionId,
requireAiFileEvidence:true}) only if those stronger checks pass; search for
readHeadCommitFiles, hasSessionCommitFileEvidence and recordCommitEntry to
implement and wire the stronger validations.
- Around line 58-60: readHeadCommitFiles currently calls git(["diff-tree",
"--no-commit-id", "--name-only", "-r", "HEAD"]) which returns an empty list for
the initial (root) commit; update the args passed in readHeadCommitFiles to
include the "--root" flag (matching the pattern used in core/record.ts) so the
initial commit's files are returned and the file-evidence gate (used earlier
around the record flow) works for root commits.
🪄 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: af66cec2-d1aa-4fe8-934d-ae66c6d77dcf
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (12)
AGENTS.mdCLAUDE.mddocs/architecture.mddocs/knowledge/investigations.mdpackages/cli/src/cli.tspackages/cli/src/commands/commit.test.tspackages/cli/src/commands/commit.tspackages/cli/src/commands/init.test.tspackages/cli/src/commands/init.tspackages/cli/src/commands/record.tspackages/cli/src/core/record.test.tspackages/cli/src/core/record.ts
Agentnote-Session: 89e518cc-e1cc-46d7-bdd0-86525a708263
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@docs/knowledge/investigations.md`:
- Around line 29-33: The long regression-coverage sentence in
docs/knowledge/investigations.md should be split into a concise bulleted list
for readability: find the sentence that lists the tests (mentions
packages/cli/src/commands/hook.test.ts, packages/cli/src/commands/init.test.ts,
packages/cli/src/core/record.test.ts, packages/cli/src/commands/commit.test.ts,
packages/pr-report/src/report.test.ts) and break each described test/expectation
into its own bullet (preserve all existing details and ordering, keep Japanese
text), ensuring line breaks and punctuation remain correct and meaning
unchanged.
In `@packages/cli/src/commands/commit.ts`:
- Line 18: AMEND_LIKE_COMMIT_ARGS currently only lists short flags; add the
long-form flags "--reuse-message" and "--reedit-message" to that Set and
implement a helper function (e.g., isAmendLikeArg or isAmendLikeCommitArg) that
returns true for exact matches and for "--name=value" forms or when the next
argv token is the value (covers both "--reuse-message=<commit>" and
"--reuse-message <commit>"). Replace the direct AMEND_LIKE_COMMIT_ARGS.has(...)
call at the usage site (previously line 30) with this helper so both
space-separated and equals-syntax long-form flags are recognized and skipped.
Ensure the helper checks both the Set entries (AMEND_LIKE_COMMIT_ARGS) and
prefix matching for "--xxx=" patterns.
🪄 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: c544eb8e-1938-4069-a61b-c48a2b2b34d4
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (13)
AGENTS.mdCLAUDE.mddocs/architecture.mddocs/knowledge/investigations.mdpackages/cli/src/commands/commit.test.tspackages/cli/src/commands/commit.tspackages/cli/src/commands/init.test.tspackages/cli/src/commands/init.tspackages/cli/src/commands/record.tspackages/cli/src/core/constants.tspackages/cli/src/core/record.test.tspackages/cli/src/core/record.tsskills/agent-note/SKILL.md
Agentnote-Session: 89e518cc-e1cc-46d7-bdd0-86525a708263
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/cli/src/commands/commit.test.ts`:
- Line 131: Replace unsafe shell execution calls that use execSync with
argv-based execFileSync to avoid shell quoting issues: locate uses of execSync
(e.g., the call execSync(`node ${cliPath} commit -m "feat: stale commit
fallback"`, { cwd: testDir })) in commit.test.ts and change them to
execFileSync("node", [cliPath, "commit", "-m", "feat: stale commit fallback"], {
cwd: testDir }); update all other occurrences in the file (the other execSync
calls at the noted lines) to the same pattern, keeping the same cliPath,
testDir, and argument strings but passing arguments as an array to execFileSync.
In `@packages/cli/src/commands/commit.ts`:
- Around line 103-108: The empty catch around recordHeadFallback() swallows
errors; preserve non-fatal behavior but log the error for diagnosability by
catching the exception from recordHeadFallback() and calling the same warning
logger used in the primary recording path (e.g., processLogger.warn or
logger.warn as used elsewhere) with a short message plus the error details; keep
the rest of the control flow unchanged and do not rethrow so the commit still
succeeds.
🪄 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: e6b70cdf-e15f-414e-9b04-ef9163a2c3ae
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (3)
docs/knowledge/investigations.mdpackages/cli/src/commands/commit.test.tspackages/cli/src/commands/commit.ts
Why Plain git hooks could attach an Agentnote-Session trailer from a fresh prompt-only active pointer even when that session had no file evidence for the commit. recordCommitEntry then skipped the empty note, leaving PR Report with trailer-backed commits that still had no Agent Note data. User impact Plain terminal commits no longer get hijacked by a stale or foreign prompt-only session pointer. Stale-heartbeat fallback still records when post-edit blob evidence matches HEAD, including paths that Git would quote in raw diff output. Verification npm run build; focused post-commit fallback and prompt-only session tests; npm run typecheck; npm run lint; npm test; npm run build --prefix website; git diff --check. Release note: fix dangling Agent Note trailers for prompt-only active sessions and quoted fallback paths
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 `@website/src/content/docs/fr/how-it-works.mdx`:
- Line 170: The sentence "dont la commande a été observée" is ambiguous—update
the French text to explicitly name the commit command (e.g., "dont la commande
`commit` a été observée") so it matches the implemented rule; locate the phrase
"dont la commande a été observée" in the how-it-works.mdx content and replace it
with wording that explicitly mentions the `commit` command.
🪄 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: e9717af2-1314-4b16-a386-551b00d41269
⛔ Files ignored due to path filters (1)
packages/cli/dist/cli.jsis excluded by!**/dist/**,!**/dist/**
📒 Files selected for processing (23)
AGENTS.mdCLAUDE.mddocs/architecture.mddocs/knowledge/investigations.mdpackages/cli/src/commands/commit.test.tspackages/cli/src/commands/commit.tspackages/cli/src/commands/init.test.tspackages/cli/src/commands/init.tspackages/cli/src/commands/record.tspackages/cli/src/core/constants.tspackages/cli/src/core/record.tswebsite/src/content/docs/de/how-it-works.mdxwebsite/src/content/docs/es/how-it-works.mdxwebsite/src/content/docs/fr/how-it-works.mdxwebsite/src/content/docs/how-it-works.mdxwebsite/src/content/docs/id/how-it-works.mdxwebsite/src/content/docs/it/how-it-works.mdxwebsite/src/content/docs/ja/how-it-works.mdxwebsite/src/content/docs/ko/how-it-works.mdxwebsite/src/content/docs/pt-br/how-it-works.mdxwebsite/src/content/docs/ru/how-it-works.mdxwebsite/src/content/docs/zh-cn/how-it-works.mdxwebsite/src/content/docs/zh-tw/how-it-works.mdx
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 `@docs/knowledge/investigations.md`:
- Line 28: Update the sentence to match the PR `#71` spec: state that
prepare-commit-msg (plain git path) appends the Agentnote-Session trailer only
when there is file-evidence present (changes.jsonl or pre_blobs.jsonl), that
prompts.jsonl alone or transcript_path (as auxiliary metadata) do not qualify as
recordable data, and that prompt-only rescue/injection is limited to cases where
the Agent observed a PreToolUse "git commit" (i.e., Agent-note commit), so do
not allow prompt-only injection for plain prepare-commit-msg paths.
🪄 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: 9228d0e6-6b87-47a8-8074-95e3c2b69183
📒 Files selected for processing (1)
docs/knowledge/investigations.md
Summary
wasabeef/AgentNote@v0to the public@v1floating major tag.node packages/cli/dist/cli.js hook --agent ...commands are recognized, removed, and upgraded consistently across Claude, Codex, Cursor, and Gemini.agent-note hook/ repo-localcli.js hookcommands with the exact requested--agentvalue are treated as managed Agent Note hooks.git commit.Problem Details
PR #71 exposed multiple independent recording issues while moving the public examples to
@v1.First, this repository still had older repo-local hook commands such as
node packages/cli/dist/cli.js hook --agent codex. Those commands are local development compatibility paths for this repository, not the public user path. Adapter management only recognized the publicagent-note hookform, so existing local configs could look unmanaged.Second, hook command matching was too string-based. A command that merely mentioned
agent-note hookor contained a similar--agentvalue could be misclassified as managed Agent Note configuration.Third, a legitimate Agent session can exceed the 1 hour heartbeat window before commit.
prepare-commit-msgcorrectly skips trailer injection in that case, but the session may still contain reliable post-edit blob evidence for HEAD. Before this PR,post-commithad no strict recovery path when the trailer was missing.Fourth, the most recent missing-prompt commits were not a long-running-session problem. They were short commits where
.git/agentnote/sessionpointed at a fresh active session that had prompt data but no file evidence for the commit. Plaingit commitinjected a trailer from that active pointer, thenrecordCommitEntry()safely skipped the empty note, producingtrailer present / git note absent. This can happen even if the user is actually working in Codex: the bug is the active session pointer and evidence contract, not the Agent brand.This was not caused by the repository becoming public or by the
v1tag itself.Fix Details
--agent nameand--agent=namemust match the requested Agent exactly.cli.js hookcommands are recognized by executable basename, while unrelated command fragments are ignored.agent-note statususes the same managed-hook detector when reporting Codex / Cursor / Gemini capture capabilities.prepare-commit-msgwrites a one-shot fallback marker only when a brand-new commit is skipped because heartbeat is stale. Amend / reuse commits clear the marker and never opt into fallback.post-commitcallsagent-note record --fallback-headonly when HEAD has no trailer and the one-shot stale-heartbeat marker exists.changes.jsonlpost-edit blob matches a committed HEAD blob.git diff-tree -z --raw, andrecordCommitEntry()reads commit file names withdiff-tree -z --name-only, so non-ASCII / space-containing paths are not broken by Gitcore.quotePathoutput.changes.jsonlorpre_blobs.jsonl) before injecting a trailer. Prompt-only active sessions are skipped for plain terminal commits to avoid hijacking unrelated work.PreToolUse git committrailer injection still allows prompt-only rescue because the commit command itself was observed inside the Agent session.Dashboard Note
A related Dashboard gap was also observed: after git notes are backfilled manually, the Dashboard workflow does not rerun just because
refs/notes/agentnotechanged. That is a separate Dashboard sync limitation and is not fixed by this PR.Verification
npm run build(packages/cli)agent-note commitnpm run typecheck(packages/cli)npm run lint(packages/cli)npm test(packages/cli, 441 tests)npm run build --prefix websitechanges/pre_blobs, matching / unrelated / empty evidence, and prompt-only noise@v0repository sweep: no remainingAgentNote@v0references in README, website, docs, or skillsgit diff --checkSummary by CodeRabbit
New Features
Documentation
🧑💬🤖 Agent Note
Total AI Ratio: ████████ 100%
Model:
gpt-5.411ba038fix(init): generate v1 action workflow referencesc889da4fix(agents): recognize repo-local hook commandsabd820bfix(agents): tighten hook command detectionc578590fix(status): recognize repo-local hook capabilitiesbf69f7btest(agents): cover legacy hook cleanup319c679test(status): avoid shell-interpolated cli callsf1a3e13fix(agents): reject inert hook command fragments2537467fix(hooks): recover stale session notes after commitbf7bbe9fix(hooks): tighten stale session fallbacke09500dfix(commit): skip long-form reuse recording76acadefix(hooks): avoid dangling prompt-only trailers2a21f2fdocs: clarify active session investigation17c2d1ddocs: clarify trailer evidence paths💬 Prompts & Responses (9 total)
11ba038fix(init): generate v1 action workflow referencesc889da4fix(agents): recognize repo-local hook commands