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>
This commit is contained in:
Mikael Hugo 2026-05-10 18:03:13 +02:00
parent a3019e5402
commit 2a1309d127
4 changed files with 12 additions and 13 deletions

View file

@ -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;
}

View file

@ -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) => ({

View file

@ -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)",
};
}

View file

@ -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)",
});
});