From 2a1309d127171f3d802c66c97d85d22b0b29a07a Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Sun, 10 May 2026 18:03:13 +0200 Subject: [PATCH] fix(memory): make SM opt-in (SM_ENABLED=true) instead of opt-out Local SQLite is the memory system. External Singularity Memory is an optional cross-project enhancement, not a dependency. Flip the default so SM is disabled unless explicitly opted in via SM_ENABLED=true: - sm-client.js: return disconnected early unless SM_ENABLED=true - memory-store.js: only pass smConnected=true when SM_ENABLED=true - doctor-config-checks.js: skip SM health check when not opted in - sm-client.test.ts: update test to reflect opt-in behaviour Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/resources/extensions/sf/doctor-config-checks.js | 5 ++--- src/resources/extensions/sf/memory-store.js | 4 ++-- src/resources/extensions/sf/sm-client.js | 12 ++++++------ src/resources/extensions/sf/tests/sm-client.test.ts | 4 ++-- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/resources/extensions/sf/doctor-config-checks.js b/src/resources/extensions/sf/doctor-config-checks.js index c94db46fb..12b69300a 100644 --- a/src/resources/extensions/sf/doctor-config-checks.js +++ b/src/resources/extensions/sf/doctor-config-checks.js @@ -389,9 +389,8 @@ export function checkVaultHealth(issues, _shouldFix) { */ export async function checkSmHealth(issues, _shouldFix) { try { - // Check if explicitly disabled - if (process.env.SM_ENABLED === "false") { - // Not an issue — explicit opt-out + // SM is opt-in — only check when explicitly enabled + if (process.env.SM_ENABLED !== "true") { return; } diff --git a/src/resources/extensions/sf/memory-store.js b/src/resources/extensions/sf/memory-store.js index 772de921a..50a4c1f09 100644 --- a/src/resources/extensions/sf/memory-store.js +++ b/src/resources/extensions/sf/memory-store.js @@ -124,8 +124,8 @@ export async function getRelevantMemoriesRanked(query, limit = 10) { let crossProjectMemories = []; try { const smResults = await querySmMemories(query, { - limit: Math.max(3, Math.ceil(limit * 0.3)), // Cross-project recall is 30% of local limit - smConnected: process.env.SM_ENABLED !== "false", + limit: Math.max(3, Math.ceil(limit * 0.3)), + smConnected: process.env.SM_ENABLED === "true", }); // Convert SM results to local format (all cross-project memories tagged as such) crossProjectMemories = (smResults || []).map((m) => ({ diff --git a/src/resources/extensions/sf/sm-client.js b/src/resources/extensions/sf/sm-client.js index bf8bb7f77..57f38a123 100644 --- a/src/resources/extensions/sf/sm-client.js +++ b/src/resources/extensions/sf/sm-client.js @@ -18,15 +18,15 @@ * Returns { connected: boolean, version: string | null, error?: string } * * Tries to connect to SM at SINGULARITY_MEMORY_ADDR (default: http://localhost:8080). - * Respects SM_ENABLED=false env var to explicitly disable. + * SM is opt-in: set SM_ENABLED=true to activate. Disabled by default. */ export async function initializeSmClient() { - // Check if explicitly disabled - if (process.env.SM_ENABLED === "false") { + // SM is opt-in — disabled unless explicitly enabled + if (process.env.SM_ENABLED !== "true") { return { connected: false, version: null, - reason: "disabled via SM_ENABLED=false", + reason: "disabled (set SM_ENABLED=true to enable)", }; } @@ -161,10 +161,10 @@ export async function querySmMemories(query, opts = {}) { * Get SM client status for doctor checks. */ export function getSmStatus() { - if (process.env.SM_ENABLED === "false") { + if (process.env.SM_ENABLED !== "true") { return { connected: false, - reason: "disabled via SM_ENABLED=false", + reason: "disabled (set SM_ENABLED=true to enable)", }; } diff --git a/src/resources/extensions/sf/tests/sm-client.test.ts b/src/resources/extensions/sf/tests/sm-client.test.ts index b8087fce6..36aeb33c6 100644 --- a/src/resources/extensions/sf/tests/sm-client.test.ts +++ b/src/resources/extensions/sf/tests/sm-client.test.ts @@ -197,7 +197,7 @@ describe("SM Client", () => { describe("getSmStatus", () => { it("when_sm_disabled_returns_disconnected_status", async () => { - process.env.SM_ENABLED = "false"; + delete process.env.SM_ENABLED; // SM is opt-in — absence means disabled const { getSmStatus } = await import("../sm-client.js"); @@ -205,7 +205,7 @@ describe("SM Client", () => { expect(status).toEqual({ connected: false, - reason: "disabled via SM_ENABLED=false", + reason: "disabled (set SM_ENABLED=true to enable)", }); });