Skip to content

fix: scope git worktrees to shared project id#929

Closed
wbugitlab1 wants to merge 2 commits into
rohitg00:mainfrom
wbugitlab1:fix/worktree-project-scope
Closed

fix: scope git worktrees to shared project id#929
wbugitlab1 wants to merge 2 commits into
rohitg00:mainfrom
wbugitlab1:fix/worktree-project-scope

Conversation

@wbugitlab1

@wbugitlab1 wbugitlab1 commented Jun 14, 2026

Copy link
Copy Markdown

Summary

  • resolve project scope through a canonical git project id instead of raw cwd path
  • make linked worktrees for the same repository share the same git:<hash> project scope
  • preserve explicit AGENTMEMORY_PROJECT_ID / AGENTMEMORY_PROJECT_NAME overrides and non-git basename fallback
  • expose optional project arguments through MCP/REST memory operations

Verification

  • npm run build passed
  • npm run skills:check passed
  • npx vitest run test/worktree-project-scope.test.ts test/hook-project.test.ts test/api-memories-project.test.ts test/mcp-project-scope.test.ts test/pre-tool-use-project.test.ts test/remember-project-scope.test.ts test/mcp-standalone.test.ts test/mcp-standalone-proxy.test.ts passed: 8 files, 72 tests
  • gitleaks protect --staged --redact passed
  • gitleaks detect --source . --log-opts 'origin/main..HEAD' --redact passed
  • git diff --name-only origin/main..HEAD | xargs semgrep scan --config p/default --error --metrics=off passed: 30 files, 0 findings
  • git diff --check origin/main..HEAD passed

Notes

  • Full npm test currently has unrelated local failures in test/fs-watcher.test.ts; this file is not touched by this PR. Other first-run timeout failures passed when rerun in isolation.
  • Full repo semgrep scan --config p/default --error --metrics=off . reports existing findings outside this PR diff.
  • Full history gitleaks detect --source . --redact reports one historical finding; the PR commit itself is clean.

Manual smoke

A local build of this change was tested with two linked worktrees for the same repo. Hook-generated sessions from both worktrees resolved to the same project id:

/Users/A1538552/_projects/_tools/agentmemory              -> git:c578c496c2ba2535ab6a51797c014666
/Users/A1538552/.codex/worktrees/aba6/agentmemory         -> git:c578c496c2ba2535ab6a51797c014666

Summary by CodeRabbit

Release Notes

  • New Features

    • Memories can be scoped to projects via AGENTMEMORY_PROJECT_ID (preferred) or AGENTMEMORY_PROJECT_NAME.
    • Added optional project parameter to memory_recall and smart search tools.
    • The memories API now supports project filtering with includeUnscoped.
  • Improvements

    • Project scoping is now more consistent across Git worktrees; cwd is normalized in event payloads.
    • Project info is no longer exposed in “Memory saved” logging.
  • Documentation

    • Updated environment and tool references to include AGENTMEMORY_PROJECT_ID and the new project parameter.
  • Tests

    • Added/expanded coverage for project scoping, filtering, and worktree behavior.

Signed-off-by: Willi Budzinski <w.budzinski@telekom.de>
@vercel

vercel Bot commented Jun 14, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 18f969c7-d20a-4cd4-96d1-1872ca6998d7

📥 Commits

Reviewing files that changed from the base of the PR and between feeb504 and c234cbd.

📒 Files selected for processing (23)
  • plugin/scripts/notification.mjs
  • plugin/scripts/post-tool-failure.mjs
  • plugin/scripts/post-tool-use.mjs
  • plugin/scripts/pre-compact.mjs
  • plugin/scripts/pre-tool-use.mjs
  • plugin/scripts/prompt-submit.mjs
  • plugin/scripts/session-start.mjs
  • plugin/scripts/subagent-start.mjs
  • plugin/scripts/subagent-stop.mjs
  • plugin/scripts/task-completed.mjs
  • src/hooks/_project.ts
  • src/hooks/notification.ts
  • src/hooks/post-tool-failure.ts
  • src/hooks/post-tool-use.ts
  • src/hooks/pre-compact.ts
  • src/hooks/pre-tool-use.ts
  • src/hooks/prompt-submit.ts
  • src/hooks/session-start.ts
  • src/hooks/subagent-start.ts
  • src/hooks/subagent-stop.ts
  • src/hooks/task-completed.ts
  • test/hook-project.test.ts
  • test/pre-tool-use-project.test.ts
✅ Files skipped from review due to trivial changes (2)
  • src/hooks/notification.ts
  • src/hooks/pre-compact.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • src/hooks/post-tool-use.ts
  • src/hooks/session-start.ts
  • src/hooks/prompt-submit.ts
  • src/hooks/task-completed.ts
  • src/hooks/subagent-start.ts
  • plugin/scripts/post-tool-use.mjs
  • src/hooks/subagent-stop.ts
  • src/hooks/_project.ts
  • plugin/scripts/pre-compact.mjs
  • plugin/scripts/subagent-start.mjs
  • src/hooks/pre-tool-use.ts
  • plugin/scripts/subagent-stop.mjs
  • test/pre-tool-use-project.test.ts
  • plugin/scripts/session-start.mjs
  • test/hook-project.test.ts
  • plugin/scripts/notification.mjs
  • plugin/scripts/post-tool-failure.mjs
  • plugin/scripts/prompt-submit.mjs

📝 Walkthrough

Walkthrough

Replaces basename-based project IDs with stable git:<sha256> hashes derived from the git common directory, adds AGENTMEMORY_PROJECT_ID env override, propagates project through MCP tools and API memories endpoint, redacts raw project values from logs, and updates docs and tests.

Changes

Canonical Git Project Scoping and MCP Project Filtering

Layer / File(s) Summary
resolveProject: canonical git common-dir hash
src/hooks/_project.ts
Adds helpers (cleanEnv, gitOutput, realPath, gitCommonDir, canonicalGitProject, resolveCwd) to compute opaque git:<sha256> IDs from git common-dir root. Exports new resolveCwd helper. Resolution order: AGENTMEMORY_PROJECT_IDAGENTMEMORY_PROJECT_NAMEgit:<hash>basename(cwd).
Hook integration: project and cwd normalization
src/hooks/notification.ts, src/hooks/post-tool-failure.ts, src/hooks/post-tool-use.ts, src/hooks/pre-compact.ts, src/hooks/pre-tool-use.ts, src/hooks/prompt-submit.ts, src/hooks/session-start.ts, src/hooks/subagent-start.ts, src/hooks/subagent-stop.ts, src/hooks/task-completed.ts
All hook TypeScript sources import resolveProject and resolveCwd from _project.ts and use them to derive project and cwd payload fields instead of inline casting and process.cwd() fallbacks.
Plugin scripts: inlined resolver propagation
plugin/scripts/notification.mjs, plugin/scripts/post-tool-failure.mjs, plugin/scripts/post-tool-use.mjs, plugin/scripts/pre-compact.mjs, plugin/scripts/pre-tool-use.mjs, plugin/scripts/prompt-submit.mjs, plugin/scripts/session-start.mjs, plugin/scripts/subagent-start.mjs, plugin/scripts/subagent-stop.mjs, plugin/scripts/task-completed.mjs, plugin/scripts/post-commit.mjs, plugin/scripts/session-end.mjs, plugin/scripts/stop.mjs
Propagates the canonical resolver rewrite to all bundled hook scripts. Scripts without resolver changes receive normalized export {}; footers and region markers.
MCP tools: project field in schema, server, and standalone
src/mcp/tools-registry.ts, src/mcp/server.ts, src/mcp/standalone.ts
Adds optional project to memory_recall schema. Server handler forwards project to mem::search. Standalone tool handler parses and forwards project in proxy mode for memory_save, memory_recall, and memory_smart_search; filters by project in local fallback.
API memories endpoint: project filtering
src/triggers/api.ts
Parses project and includeUnscoped query parameters; filters memories by projectFilter before pagination, optionally including unscoped legacy memories.
remember.ts: project field handling and log redaction
src/functions/remember.ts
Changes logger.info("Memory saved", ...) to log hasProject boolean instead of raw project string.
Documentation: env var and tool references
plugin/skills/agentmemory-config/REFERENCE.md, plugin/skills/agentmemory-mcp-tools/REFERENCE.md
Adds AGENTMEMORY_PROJECT_ID to env var reference (35 total) and documents new project: string parameter on memory_recall.
Tests: resolver, worktrees, MCP, API, logging
test/hook-project.test.ts, test/worktree-project-scope.test.ts, test/mcp-project-scope.test.ts, test/mcp-standalone.test.ts, test/mcp-standalone-proxy.test.ts, test/api-memories-project.test.ts, test/pre-tool-use-project.test.ts, test/remember-project-scope.test.ts
Adds and updates suites covering resolver precedence, linked worktree scoping, same-basename collision avoidance, MCP project forwarding, API filtering with pagination, end-to-end hook project injection, and log redaction.

Sequence Diagram(s)

sequenceDiagram
  participant Hook as Hook (pre-tool-use)
  participant Resolve as resolveProject
  participant Git as git rev-parse
  participant Hash as sha256
  participant Enrich as /agentmemory/enrich

  Hook->>Resolve: resolveProject(data.cwd)
  alt AGENTMEMORY_PROJECT_ID set
    Resolve-->>Hook: return trimmed PROJECT_ID
  else AGENTMEMORY_PROJECT_NAME set
    Resolve-->>Hook: return trimmed PROJECT_NAME
  else
    Resolve->>Git: --git-common-dir in cwd
    Git-->>Resolve: common-dir path
    Resolve->>Hash: sha256(realpath(parent))
    Hash-->>Resolve: hex digest
    Resolve-->>Hook: return "git:<hash>"
  end
  Hook->>Enrich: POST {project, cwd, ...}
  Enrich-->>Hook: response
Loading
sequenceDiagram
  participant Client as MCP Client
  participant Tools as tools-registry
  participant Server as mcp::tools::call
  participant Search as mem::search
  participant API as /agentmemory/search

  Client->>Tools: memory_recall(query, project?)
  Tools-->>Client: schema with project field
  Client->>Server: call memory_recall
  Server->>Search: {query, project, limit, format}
  alt Proxy mode
    Search->>API: POST + project parameter
    API-->>Search: filtered results
  else Local fallback
    Search->>Search: filter InMemoryKV by project
  end
  Search-->>Server: results
  Server-->>Client: results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related issues

Possibly related PRs

  • rohitg00/agentmemory#687: Modifies the same resolveProject pathway and plugin hook scripts; this PR supersedes its approach with git:<sha256> strategy and AGENTMEMORY_PROJECT_ID priority.
  • rohitg00/agentmemory#662: Touches the project field propagation in mem::remember write path and memory API scoping, overlapping with log-redaction and project storage changes in this PR.
  • rohitg00/agentmemory#648: The main PR updates hook payloads to compute project/cwd via resolveProject/resolveCwd, which directly supports PR #648's change to mem::observe that implicitly creates sessions only when project and cwd are provided.

Suggested reviewers

  • rohitg00

Poem

🐇 Hoppity-hash, no more basename collision,
Git common-dir guides each decision!
git:<sha256> stable and true,
Worktrees share memory through and through.
No tricks, just opaque precision—
This rabbit codes with crypto vision! 🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and specifically summarizes the main objective: fixing git worktree scoping to use a shared project ID instead of raw filesystem paths.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wbugitlab1

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@plugin/scripts/notification.mjs`:
- Around line 58-59: The issue is that cwd.trim() can crash at runtime when cwd
contains a non-string truthy value (since it comes from parsed stdin JSON). The
current guard at cwd && cwd.trim() only checks truthiness, not the string type.
Add a typeof check to ensure cwd is a string before calling trim() on it in all
affected locations. Apply this same guard to the identical resolver blocks in
plugin/scripts/notification.mjs (lines 58-59),
plugin/scripts/post-tool-failure.mjs, plugin/scripts/post-tool-use.mjs, and
plugin/scripts/pre-compact.mjs. Change the condition from cwd && cwd.trim() to
typeof cwd === 'string' && cwd.trim() so that non-string values safely fall
through to the fallback process.cwd() call.

In `@src/hooks/pre-tool-use.ts`:
- Line 98: The code passes data.cwd directly to resolveProject without
validating its type, which can cause runtime errors if cwd is not a string (the
resolveProject function likely accesses string methods like trim). Add a runtime
typeof check to validate that data.cwd is actually a string before calling
resolveProject, and handle the case where it is not a string appropriately.
After fixing src/hooks/pre-tool-use.ts, regenerate
plugin/scripts/pre-tool-use.mjs to keep the bundled hook in sync with the
source.

In `@test/pre-tool-use-project.test.ts`:
- Around line 26-30: The test is not hermetic because AGENTMEMORY_PROJECT_ID and
AGENTMEMORY_PROJECT_NAME environment variables from the runner environment can
affect the test behavior, causing it to validate override behavior instead of
cwd-based resolution. Remove or explicitly exclude these two variables from the
env object configuration (where you spread process.env) in both locations
mentioned in the comment to ensure the test environment is isolated and only
tests the intended cwd-based resolution path.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26627530-2927-4f23-85ee-7a71f2b6ff07

📥 Commits

Reviewing files that changed from the base of the PR and between f6f9e3c and 52d3153.

📒 Files selected for processing (30)
  • plugin/scripts/notification.mjs
  • plugin/scripts/post-commit.mjs
  • plugin/scripts/post-tool-failure.mjs
  • plugin/scripts/post-tool-use.mjs
  • plugin/scripts/pre-compact.mjs
  • plugin/scripts/pre-tool-use.mjs
  • plugin/scripts/prompt-submit.mjs
  • plugin/scripts/session-end.mjs
  • plugin/scripts/session-start.mjs
  • plugin/scripts/stop.mjs
  • plugin/scripts/subagent-start.mjs
  • plugin/scripts/subagent-stop.mjs
  • plugin/scripts/task-completed.mjs
  • plugin/skills/agentmemory-config/REFERENCE.md
  • plugin/skills/agentmemory-mcp-tools/REFERENCE.md
  • src/functions/remember.ts
  • src/hooks/_project.ts
  • src/hooks/pre-tool-use.ts
  • src/mcp/server.ts
  • src/mcp/standalone.ts
  • src/mcp/tools-registry.ts
  • src/triggers/api.ts
  • test/api-memories-project.test.ts
  • test/hook-project.test.ts
  • test/mcp-project-scope.test.ts
  • test/mcp-standalone-proxy.test.ts
  • test/mcp-standalone.test.ts
  • test/pre-tool-use-project.test.ts
  • test/remember-project-scope.test.ts
  • test/worktree-project-scope.test.ts

Comment thread plugin/scripts/notification.mjs Outdated
Comment thread src/hooks/pre-tool-use.ts Outdated
typeof data.project === "string" && data.project.trim().length > 0
? data.project.trim()
: undefined;
const project = resolveProject(data.cwd as string | undefined);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate data.cwd before calling resolveProject.

A non-string cwd from hook payload can throw at runtime (trim access), causing this hook to exit unexpectedly. Parse cwd with a runtime typeof check first.

Suggested fix
-  const project = resolveProject(data.cwd as string | undefined);
+  const cwd = typeof data.cwd === "string" ? data.cwd : undefined;
+  const project = resolveProject(cwd);

Please regenerate plugin/scripts/pre-tool-use.mjs after fixing this source file so the bundled hook stays in sync.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const project = resolveProject(data.cwd as string | undefined);
const cwd = typeof data.cwd === "string" ? data.cwd : undefined;
const project = resolveProject(cwd);
🤖 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 `@src/hooks/pre-tool-use.ts` at line 98, The code passes data.cwd directly to
resolveProject without validating its type, which can cause runtime errors if
cwd is not a string (the resolveProject function likely accesses string methods
like trim). Add a runtime typeof check to validate that data.cwd is actually a
string before calling resolveProject, and handle the case where it is not a
string appropriately. After fixing src/hooks/pre-tool-use.ts, regenerate
plugin/scripts/pre-tool-use.mjs to keep the bundled hook in sync with the
source.

Comment thread test/pre-tool-use-project.test.ts Outdated
@wbugitlab1

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@plugin/scripts/subagent-start.mjs`:
- Around line 53-56: The resolveCwd function validates the cwd parameter by
checking cwd.trim().length but returns the untrimmed cwd value, allowing
whitespace-padded strings to propagate into downstream operations like project
hashing. Modify the return statement in resolveCwd to return cwd.trim() instead
of cwd when the trimmed length is greater than zero, ensuring whitespace is
consistently removed before the value is used.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: e6dbcfcf-3dee-4876-a9c3-33927cb2e8aa

📥 Commits

Reviewing files that changed from the base of the PR and between 52d3153 and feeb504.

📒 Files selected for processing (23)
  • plugin/scripts/notification.mjs
  • plugin/scripts/post-tool-failure.mjs
  • plugin/scripts/post-tool-use.mjs
  • plugin/scripts/pre-compact.mjs
  • plugin/scripts/pre-tool-use.mjs
  • plugin/scripts/prompt-submit.mjs
  • plugin/scripts/session-start.mjs
  • plugin/scripts/subagent-start.mjs
  • plugin/scripts/subagent-stop.mjs
  • plugin/scripts/task-completed.mjs
  • src/hooks/_project.ts
  • src/hooks/notification.ts
  • src/hooks/post-tool-failure.ts
  • src/hooks/post-tool-use.ts
  • src/hooks/pre-compact.ts
  • src/hooks/pre-tool-use.ts
  • src/hooks/prompt-submit.ts
  • src/hooks/session-start.ts
  • src/hooks/subagent-start.ts
  • src/hooks/subagent-stop.ts
  • src/hooks/task-completed.ts
  • test/hook-project.test.ts
  • test/pre-tool-use-project.test.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • plugin/scripts/task-completed.mjs
  • plugin/scripts/pre-tool-use.mjs
  • plugin/scripts/notification.mjs
  • plugin/scripts/post-tool-failure.mjs
  • plugin/scripts/prompt-submit.mjs
  • plugin/scripts/post-tool-use.mjs
  • plugin/scripts/session-start.mjs
  • plugin/scripts/subagent-stop.mjs
  • test/hook-project.test.ts
  • plugin/scripts/pre-compact.mjs

Comment thread plugin/scripts/subagent-start.mjs
Signed-off-by: wbu <wbu@live.de>
@wbugitlab1 wbugitlab1 force-pushed the fix/worktree-project-scope branch from feeb504 to c234cbd Compare June 14, 2026 14:38
@wbugitlab1 wbugitlab1 marked this pull request as ready for review June 14, 2026 14:41
@wbugitlab1 wbugitlab1 closed this Jun 14, 2026
@wbugitlab1 wbugitlab1 deleted the fix/worktree-project-scope branch June 17, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant