From ec0f6be4e83fd08706ad4a11d14524f76f48876c Mon Sep 17 00:00:00 2001 From: jlin53882 Date: Sat, 25 Apr 2026 01:16:56 +0800 Subject: [PATCH 1/2] fix: isOwnedByAgent fail-closed for malformed itemKind (#448) --- src/reflection-store.ts | Bin 21129 -> 45086 bytes test/isOwnedByAgent.test.mjs | 65 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 test/isOwnedByAgent.test.mjs diff --git a/src/reflection-store.ts b/src/reflection-store.ts index 38da5ce791e7693e568bd3870ef8b94650f15454..577a6b36c6da236a7e6189059667150a0b733ef0 100644 GIT binary patch literal 45086 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 literal 21129 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 diff --git a/test/isOwnedByAgent.test.mjs b/test/isOwnedByAgent.test.mjs new file mode 100644 index 00000000..b23e4c4b --- /dev/null +++ b/test/isOwnedByAgent.test.mjs @@ -0,0 +1,65 @@ +// isOwnedByAgent unit tests — Issue #448 fix verification +import { describe, it } from "node:test"; +import assert from "node:assert"; + +// From reflection-store.ts: isOwnedByAgent function for isolated testing +function isOwnedByAgent(metadata, agentId) { + const owner = typeof metadata.agentId === "string" ? metadata.agentId.trim() : ""; + + const itemKind = metadata.itemKind; + + // derived: no main fallback, empty owner -> completely invisible + if (itemKind === "derived") { + if (!owner) return false; + return owner === agentId; + } + + // invariant / legacy / mapped: maintain original main fallback + if (!owner) return true; + return owner === agentId || owner === "main"; +} + +describe("isOwnedByAgent — derived ownership fix (Issue #448)", () => { + describe("itemKind === 'derived'", () => { + it("main's derived -> main visible", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "derived", agentId: "main" }, "main"), true); + }); + it("main's derived -> sub-agent invisible (core bug fix)", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "derived", agentId: "main" }, "sub-agent-A"), false); + }); + it("agent-x's derived -> agent-x visible", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "derived", agentId: "agent-x" }, "agent-x"), true); + }); + it("agent-x's derived -> agent-y invisible", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "derived", agentId: "agent-x" }, "agent-y"), false); + }); + it("derived + empty owner -> completely invisible (guard)", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "derived", agentId: "" }, "main"), false); + assert.strictEqual(isOwnedByAgent({ itemKind: "derived", agentId: "" }, "sub-agent"), false); + }); + }); + + describe("itemKind === 'invariant' (maintain fallback)", () => { + it("main's invariant -> sub-agent visible", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "invariant", agentId: "main" }, "sub-agent-A"), true); + }); + it("agent-x's invariant -> agent-x visible", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "invariant", agentId: "agent-x" }, "agent-x"), true); + }); + it("agent-x's invariant -> agent-y invisible", () => { + assert.strictEqual(isOwnedByAgent({ itemKind: "invariant", agentId: "agent-x" }, "agent-y"), false); + }); + }); + + describe("legacy / mapped (no itemKind, maintain fallback)", () => { + it("main legacy -> sub-agent visible", () => { + assert.strictEqual(isOwnedByAgent({ agentId: "main" }, "sub-agent-A"), true); + }); + it("agent-x legacy -> agent-x visible", () => { + assert.strictEqual(isOwnedByAgent({ agentId: "agent-x" }, "agent-x"), true); + }); + it("agent-x legacy -> agent-y invisible", () => { + assert.strictEqual(isOwnedByAgent({ agentId: "agent-x" }, "agent-y"), false); + }); + }); +}); \ No newline at end of file From 7249252fa709542e8e32dda687d9da05d3cbc1af Mon Sep 17 00:00:00 2001 From: jlin53882 Date: Mon, 27 Apr 2026 00:49:31 +0800 Subject: [PATCH 2/2] fix(register): move _registeredApis.add after successful _initPluginState Resolves reviewer Must-Fix #1 from PR #522: - _registeredApis.add(api) was called BEFORE _initPluginState. If _initPluginState threw, the api was already in the WeakSet, permanently blocking any retry from the same api instance. - Fix: wrap _initPluginState in try-catch; add api to WeakSet only after successful init. If init fails, api stays out of WeakSet, allowing subsequent register() calls with the same api to retry. Fixes CortexReach/memory-lancedb-pro#448 --- index.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/index.ts b/index.ts index 25b2012f..28829715 100644 --- a/index.ts +++ b/index.ts @@ -1899,7 +1899,6 @@ const memoryLanceDBProPlugin = { api.logger.debug?.("memory-lancedb-pro: register() called again — skipping re-init (idempotent)"); return; } - _registeredApis.add(api); // Parse and validate configuration // ======================================================================== @@ -1908,8 +1907,22 @@ const memoryLanceDBProPlugin = { // the same singleton via destructuring. This prevents: // - Memory heap growth from repeated resource creation (~9 calls/process) // - Accumulated session Maps being lost on re-registration + // + // IMPORTANT: _registeredApis.add(api) is called AFTER successful init. + // This ensures that if _initPluginState throws, the api is NOT in the + // WeakSet, allowing a subsequent register() call with the same api to retry. + // (The old placement — before init — caused permanent breakage on init failure.) // ======================================================================== - if (!_singletonState) { _singletonState = _initPluginState(api); } + let singleton: typeof _singletonState; + try { + if (!_singletonState) { _singletonState = _initPluginState(api); } + singleton = _singletonState; + } catch (err) { + api.logger.error(`memory-lancedb-pro: _initPluginState failed — ${String(err)}`); + throw err; + } + _registeredApis.add(api); + const { config, resolvedDbPath, @@ -1930,7 +1943,7 @@ const memoryLanceDBProPlugin = { autoCaptureSeenTextCount, autoCapturePendingIngressTexts, autoCaptureRecentTexts, - } = _singletonState; + } = singleton; async function sleep(ms: number): Promise {