Repository navigation
fix: never resume a session of another project (GIT-86) - #37
Merged
2 commits merged intoSep 22, 2026
Merged
2 commits merged into
2 commits merged into
Conversation
… (GIT-86) One desktop process serves every chat, so hostname+pid does not name a session. session_start(Y) found the open X session by hostname+pid, replaced the caller's project with X's (stderr only) and carried on in X. - findSessionByHostPid and findResumableSessionOnDisk take the requested project and only return a session of that project. - params.project set and no match: a new session. The registry slot is now hostname+pid+project, so registerSession no longer displaces X, X is not marked superseded, and pruneOrphanedDirs no longer sees X as unregistered. - params.project absent: the most recent session is resumed, and the display names its project (project_from_resumed_session). - force:true carries startedAt, surfaced scars, confirmations, observations and children forward only from a session of the same project. Confirmations were never carried before, and the free tier dropped the carried startedAt. - session_close's registry fallback looks the session up by id. +9 unit tests (4 registry, 5 through session_start); 8 fail on origin/main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…GIT-86)
session_start(X), session_start(Y), session_start(X), session_start({}),
session_start(X, force) through one server over stdio, as the desktop app
does. Checks the stored rows, close_compliance, the registry and the session
directories. Exits 1 on 1.10.0 (Y resumes X); exits 0 with the fix.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 22, 2026
neoneye
pushed a commit
to agent-memory-atlas-archive/gitmem-dev--gitmem
that referenced
this pull request
Sep 22, 2026
…itmem-dev#37) GIT-86 (gitmem-dev#37) made session_close's registry fallback look the session up by id. Four mocks of active-sessions.js exported only findSessionByHostPid — session-close-validation (named in the stack plan), session-close-payload-path (gitmem-dev#39, whose mock header was copied from it), session-close-supabase and session-close-bridge. No test reached that fallback, so nothing failed; any future one would have thrown on the missing export. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
What
session_startnever resumes, displaces or supersedes a session of another project (GIT-86).findSessionByHostPidandfindResumableSessionOnDisktake the requested project and only return a session of that project.projectpassed, no match: a new session starts. The registry slot is now hostname + pid + project, so the other project's session stays registered, is not markedsuperseded, andpruneOrphanedDirsno longer treats its directory as unregistered.projectabsent: the most recent session is resumed, and the display says which project it is in:Resumed project: <p> (no project was passed — pass project to start a session in another). The result also carriesproject_from_resumed_session: true.force: true:startedAt, surfaced scars, scar confirmations, observations and children carry forward only from a session of the same project. A session of another project is left open.session_close's registry fallback now looks the session up by id instead of by pid.Why
One desktop process serves every chat, so hostname + pid doesn't identify a session. Before this change,
session_start(Y)found the open X session by pid, replaced the caller's project with X's (logged to stderr only) and carried on in X. Reported twice.The obvious fix (filter the two lookups) isn't enough on its own.
registerSessionwould still displace X from the registry and mark it superseded in Supabase, and X's directory would then be deleted as an orphan an hour later. So X wouldn't actually be resumable.Found along the way (same code path, fixed here)
force: true:setCurrentSessionalways reset them. So surfaced scars came across without their confirmations.startedAtbut only used it when resuming, so a forced free-tier session restarted its duration clock.How to test
Standing rule: the venue runs the v1.8.0
setup.sqlfirst. The venuevujndhcumgroztfkkduswas reset and provisioned fromv1.8.0:schema/setup.sql(byte-identical to the tag) before any run. Production was not touched.projects(new mode)origin/main1.10.0session_start(Y)resumed X (f7c06c8b) and every call after it continued X. 6 checks failed, including "Y is a new session" and "Y never superseded".projects5ddc4fc4; Y →6a15ba33(new); X again →5ddc4fc4resumed; no project →6a15ba33resumed, namingblank-venue-y; X with force → new. Y is never superseded; X is superseded only by the same-project force.flowUnit tests: 1283/1283 pass (+9: 4 registry, 5 through the real
session_starton the free tier). 8 of the 9 fail onorigin/main. The 9th is a same-project resume guard, which passes on both.Existing tests
None needed changing, and nothing was deleted. One test states the old invariant in its name:
findResumableSessionOnDisk > adopts at most one session — never leaves two rows sharing hostname+pid. It still passes, because both of its sessions are in projectdefault. The invariant is now "never two rows sharing hostname + pid + project". I left the name as it is; a rename is a one-line follow-up if wanted.Checklist
npm run test:unitpasses (1283)npm run test:e2e: not run; the venue driver above is the e2e check for this changesetup.sqlstore as-is.Breaking changes
A process can now hold one open session per project instead of one in total. A caller that relied on
session_start(project: Y)continuing its X session now gets a new Y session. That's the fix.🤖 Generated with Claude Code