Skip to content

fix(v2): scope runtime ownership per project directory - #99

Open
BobbyNooby wants to merge 2 commits into
supermemoryai:mainfrom
BobbyNooby:fix/v2-owner-scoped-per-directory
Open

BobbyNooby wants to merge 2 commits into
supermemoryai:mainfrom
BobbyNooby:fix/v2-owner-scoped-per-directory

Conversation

@BobbyNooby

@BobbyNooby BobbyNooby commented Sep 27, 2026 •

Copy link
Copy Markdown

TL;DR

On OpenCode 2, loading a new project directory silently disposes the supermemory plugin instance of every previously loaded directory. The supermemory tools vanish and auto-capture stops working in all but the most recently loaded project — with no error anywhere. Fix: scope runtime ownership per project directory instead of per process.

Impact

  • supermemory / supermemory_recall tool calls fail in every directory except the last-loaded one (the tool is no longer registered).
  • The session.context, session.compaction, and event hooks that inject memories and auto-capture transcripts are disposed too, so recall and capture silently stop for those projects.

Steps to reproduce (2.0.15)

  1. Start OpenCode in project A and start a session — the supermemory tools work.
  2. While the background service is still running, open OpenCode in project B and start a session — tools work there too, and the server logs a second v2 plugin init.
  3. Back in project A, start a new session — the tools are gone and memory injection/capture no longer happen. Nothing is logged; the plugin just does nothing.

Easy to miss because with a single project directory (the common case) everything works — and even with several, the directory you're currently using tends to be the surviving one.

Root cause

The V2 plugin assumes one instance per process — the old comment says so verbatim: "Only one instance is active per process, so a hot-reloaded plugin replaces (and cleans up) the previous generation."

But the OpenCode server instantiates the plugin once per project directory in the same process. Since ownership was keyed by a single process-wide symbol:

const OWNER_KEY = Symbol.for("opencode-supermemory.v2.owner");

every new directory's setupV2() saw the previous instance as its "previous" and disposed it (previous?.cleanup() → #active = false + disposal of all tracked registrations). Only the last-loaded directory kept a living runtime.

Fix

Scope the owner key per directory (+9/−3):

function ownerKeyFor(directory: string | undefined): symbol {
  return Symbol.for(`opencode-supermemory.v2.owner:${directory ?? "global"}`);
}
  • Same-directory hot reloads still replace and clean up the previous generation — the guard's original purpose is unchanged.
  • Different directories coexist; each keeps its own runtime.
  • The registry entry is removed on cleanup, so shutdown semantics are unchanged.

Verification

  • bun run typecheck and bun test (34 pass) — including a new regression test added in this PR (test(v2): cover per-directory runtime ownership) that pins the per-directory ownership contract: two directories stay active, a same-directory reload bumps only that directory's generation, and cleanups remove their registry entries. The test fails against the pre-fix code and passes with the fix.
  • Also verified against the published 2.0.15 bundle with a live OpenCode service: after the patch, two directories each log generation: 1 and both keep working; a fresh-session supermemory add succeeds where it previously reported the tool as missing.

@ishaanxgupta

ishaanxgupta commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

hi @BobbyNooby thanks for this PR, will have a look

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.

2 participants