Source: Source pull request number: 891 in rohitg00/agentmemory (URL omitted to avoid GitHub cross-reference)
Title: Hermes plugin: stable project scoping + close sessions on process exit
Author: zuevrs
State: open
Draft: no
Merged: no
Head: zuevrs/agentmemory:fix/hermes-plugin-project-scope-and-session-close @ 8966e05
Base: main @ 25e7701
Labels: (none)
Changed files: 0
Commits: 0
Created: 2026-06-10T20:51:27Z
Updated: 2026-06-11T07:55:17Z
Closed: (not closed)
Merged at: (not merged)
Original PR body:
What
Two independent fixes to the Hermes integration (integrations/hermes/__init__.py), found by running the plugin in production under a headless ACP-driven Hermes deployment that checks every task out into an ephemeral git worktree. Both are generic - any worktree/CI/orchestrator layout hits them.
1. Scope memory by git remote name, not the checkout path (commit 1)
Problem: initialize() used the session cwd as the agentmemory project id. A checkout path is not a stable repo identity: ephemeral checkouts (git worktrees, CI runners, agent-orchestrator workdirs) place the same repo under throwaway paths, and different repos often share one checkout basename (workdir, workspace, ...). In our deployment every task ran in .../<task-hash>/workdir - all projects collapsed into one shared workdir memory bucket, and recall started returning Go lessons inside TypeScript tasks.
Fix: resolve the project id as
AGENTMEMORY_PROJECT_NAME env var (explicit override),
- git
origin remote repo name - of the cwd or of a direct child checkout (covers sessions started one level above the repo),
- git toplevel basename,
- cwd basename (the previous behavior, as last resort).
The real cwd is still sent as cwd, and the resolved project is now passed explicitly on the search / remember / smart-search calls so recall and save stay inside the project bucket.
2. End the session on interpreter exit (commit 2)
Problem: Hermes' cli and gateway paths call on_session_end() / shutdown(), but the ACP adapter path (headless editors / daemons) tears the process down without either - every such run leaked its agentmemory session as permanently "active" on the server.
Fix: register an atexit hook at initialize() and route all teardown paths (on_session_end, shutdown, atexit) through an idempotent _close_session(), so session/end is POSTed exactly once on any graceful exit regardless of which host path ran. Hard kills (SIGKILL) can't be caught - that remains the server-side idle sweep's job.
How to verify
- Project scoping:
git worktree add /tmp/wt-a <repo-a> and start a Hermes session there, repeat with a second repo in /tmp/wt-b; with this patch session/start carries project: <repo-a-name> / project: <repo-b-name> instead of wt-a / wt-b (or one shared basename). A dir without any git remote falls back to its basename exactly as before.
- Session close: run a Hermes session through the ACP adapter (e.g. Zed), exit the editor, and check the server's active sessions - the session is now ended instead of dangling.
- Python-only change;
npm run build / npm test unaffected. python3 -m py_compile integrations/hermes/__init__.py passes; _resolve_project() exercised against the four layouts above (worktree-with-remote, parent-of-checkout, plain dir, env override).
Both commits are DCO signed-off. No issue filed for these - happy to split this into two issues/PRs if you prefer one logical change per PR taken strictly.
Summary by CodeRabbit
Release Notes
-
Bug Fixes
- Improved session lifecycle management to ensure graceful shutdowns are handled reliably with proper cleanup on interpreter exit
- Enhanced project identification logic using git remote metadata with intelligent fallback mechanisms
-
New Features
- Automatic preloading of environment configuration files at startup for consistent setup across sessions
- Better scoping of tool requests to include proper project and working directory context
Local branch:
Fork PR:
Fork decision:
Verification:
Notes:
Source: Source pull request number: 891 in rohitg00/agentmemory (URL omitted to avoid GitHub cross-reference)
Title: Hermes plugin: stable project scoping + close sessions on process exit
Author: zuevrs
State: open
Draft: no
Merged: no
Head: zuevrs/agentmemory:fix/hermes-plugin-project-scope-and-session-close @ 8966e05
Base: main @ 25e7701
Labels: (none)
Changed files: 0
Commits: 0
Created: 2026-06-10T20:51:27Z
Updated: 2026-06-11T07:55:17Z
Closed: (not closed)
Merged at: (not merged)
Original PR body:
What
Two independent fixes to the Hermes integration (
integrations/hermes/__init__.py), found by running the plugin in production under a headless ACP-driven Hermes deployment that checks every task out into an ephemeral git worktree. Both are generic - any worktree/CI/orchestrator layout hits them.1. Scope memory by git remote name, not the checkout path (commit 1)
Problem:
initialize()used the session cwd as the agentmemoryprojectid. A checkout path is not a stable repo identity: ephemeral checkouts (git worktrees, CI runners, agent-orchestrator workdirs) place the same repo under throwaway paths, and different repos often share one checkout basename (workdir,workspace, ...). In our deployment every task ran in.../<task-hash>/workdir- all projects collapsed into one sharedworkdirmemory bucket, and recall started returning Go lessons inside TypeScript tasks.Fix: resolve the project id as
AGENTMEMORY_PROJECT_NAMEenv var (explicit override),originremote repo name - of the cwd or of a direct child checkout (covers sessions started one level above the repo),The real cwd is still sent as
cwd, and the resolved project is now passed explicitly on thesearch/remember/smart-searchcalls so recall and save stay inside the project bucket.2. End the session on interpreter exit (commit 2)
Problem: Hermes' cli and gateway paths call
on_session_end()/shutdown(), but the ACP adapter path (headless editors / daemons) tears the process down without either - every such run leaked its agentmemory session as permanently "active" on the server.Fix: register an
atexithook atinitialize()and route all teardown paths (on_session_end,shutdown, atexit) through an idempotent_close_session(), sosession/endis POSTed exactly once on any graceful exit regardless of which host path ran. Hard kills (SIGKILL) can't be caught - that remains the server-side idle sweep's job.How to verify
git worktree add /tmp/wt-a <repo-a>and start a Hermes session there, repeat with a second repo in/tmp/wt-b; with this patchsession/startcarriesproject: <repo-a-name>/project: <repo-b-name>instead ofwt-a/wt-b(or one shared basename). A dir without any git remote falls back to its basename exactly as before.npm run build/npm testunaffected.python3 -m py_compile integrations/hermes/__init__.pypasses;_resolve_project()exercised against the four layouts above (worktree-with-remote, parent-of-checkout, plain dir, env override).Both commits are DCO signed-off. No issue filed for these - happy to split this into two issues/PRs if you prefer one logical change per PR taken strictly.
Summary by CodeRabbit
Release Notes
Bug Fixes
New Features
Local branch:
Fork PR:
Fork decision:
Verification:
Notes: