diff --git a/packages/coding-agent/README.md b/packages/coding-agent/README.md index 8e4fe40c3..9a0e3a275 100644 --- a/packages/coding-agent/README.md +++ b/packages/coding-agent/README.md @@ -17,11 +17,9 @@ Package-specific references: The agent supports three mutually-exclusive memory backends, selected via the `memory.backend` setting (Settings → Memory tab, or `~/.omp/config.yml`): -|Backend|Behaviour| ----|---| -`off`|No memory subsystem runs.| -`local` (default)|Existing rollout-summarisation pipeline. Writes `memory_summary.md` and consolidated artifacts under the agent dir. Additionally gated by the legacy `memories.enabled` boolean — set it to `true` to actually run.| -`hindsight`|Talks to a [Hindsight](https://hindsight.vectorize.io) server (Cloud or self-hosted Docker). Retains transcripts every Nth user turn, recalls memories on the first turn of a session, and exposes three tools: `hindsight_retain`, `hindsight_recall`, `hindsight_reflect`.| +- `off` (default) — no memory subsystem runs. +- `local` — existing rollout-summarisation pipeline; writes `memory_summary.md` and consolidated artifacts under the agent dir. +- `hindsight` — talks to a [Hindsight](https://hindsight.vectorize.io) server (Cloud or self-hosted Docker), retains transcripts every Nth user turn, recalls memories on the first turn of a session, and exposes `hindsight_retain`, `hindsight_recall`, and `hindsight_reflect`. ### Hindsight quickstart diff --git a/packages/coding-agent/src/config/settings-schema.ts b/packages/coding-agent/src/config/settings-schema.ts index e8e93e129..90834e48d 100644 --- a/packages/coding-agent/src/config/settings-schema.ts +++ b/packages/coding-agent/src/config/settings-schema.ts @@ -879,14 +879,11 @@ export const SETTINGS_SCHEMA = { "branchSummary.reserveTokens": { type: "number", default: 16384 }, // Memories + // Legacy local-memory enable flag kept only for back-compat migration. + // Hidden from UI — users should use `memory.backend` instead. "memories.enabled": { type: "boolean", default: false, - ui: { - tab: "memory", - label: "Memories", - description: "Enable autonomous memory extraction and consolidation", - }, }, "memories.maxRolloutsPerStartup": { type: "number", default: 64 }, @@ -925,11 +922,11 @@ export const SETTINGS_SCHEMA = { "memory.backend": { type: "enum", values: ["off", "local", "hindsight"] as const, - default: "local", + default: "off", ui: { tab: "memory", label: "Memory Backend", - description: "Local memory pipeline, Hindsight remote memory, or off", + description: "Off, local memory pipeline, or Hindsight remote memory", submenu: true, }, }, diff --git a/packages/coding-agent/src/memories/index.ts b/packages/coding-agent/src/memories/index.ts index 9de84a260..00660e422 100644 --- a/packages/coding-agent/src/memories/index.ts +++ b/packages/coding-agent/src/memories/index.ts @@ -1077,7 +1077,7 @@ async function resolveMemoryModel(options: { function loadMemoryConfig(settings: Settings): MemoryRuntimeConfig { return { - enabled: settings.get("memories.enabled") ?? DEFAULTS.enabled, + enabled: settings.get("memory.backend") === "local" || settings.get("memories.enabled") === true, maxRolloutsPerStartup: settings.get("memories.maxRolloutsPerStartup") ?? DEFAULTS.maxRolloutsPerStartup, maxRolloutAgeDays: settings.get("memories.maxRolloutAgeDays") ?? DEFAULTS.maxRolloutAgeDays, minRolloutIdleHours: settings.get("memories.minRolloutIdleHours") ?? DEFAULTS.minRolloutIdleHours, diff --git a/packages/coding-agent/src/memory-backend/off-backend.ts b/packages/coding-agent/src/memory-backend/off-backend.ts index b5583890c..28eb14053 100644 --- a/packages/coding-agent/src/memory-backend/off-backend.ts +++ b/packages/coding-agent/src/memory-backend/off-backend.ts @@ -3,9 +3,7 @@ import type { MemoryBackend } from "./types"; /** * No-op memory backend. * - * Selected when `memory.backend` is `"off"`, or when `"local"` is selected but - * `memories.enabled` is false (preserves the historical "memories disabled by - * default" behaviour without forcing users to flip both switches). + * Selected when `memory.backend` is `"off"`. */ export const offBackend: MemoryBackend = { id: "off", diff --git a/packages/coding-agent/src/memory-backend/resolve.ts b/packages/coding-agent/src/memory-backend/resolve.ts index 7dc5c47dc..33719a8d0 100644 --- a/packages/coding-agent/src/memory-backend/resolve.ts +++ b/packages/coding-agent/src/memory-backend/resolve.ts @@ -10,16 +10,15 @@ import type { MemoryBackend } from "./types"; * Selection rules (single source of truth — every memory consumer routes * through this): * - `memory.backend === "hindsight"` → Hindsight remote memory - * - `memory.backend === "local"` and `memories.enabled === true` → local pipeline - * - everything else → no-op + * - `memory.backend === "local"` → local pipeline + * - everything else → no-op * - * The legacy `memories.enabled` boolean still gates the local backend so users - * who have it set to `false` keep getting silence, even after the new enum - * defaults to `"local"`. + * `memories.enabled` remains accepted only as a legacy migration input. Once + * a config is loaded, `memory.backend` is the sole runtime selector. */ export function resolveMemoryBackend(settings: Settings): MemoryBackend { const id = settings.get("memory.backend"); if (id === "hindsight") return hindsightBackend; - if (id === "local" && settings.get("memories.enabled")) return localBackend; + if (id === "local") return localBackend; return offBackend; } diff --git a/packages/coding-agent/test/memories-runtime.test.ts b/packages/coding-agent/test/memories-runtime.test.ts index ebe492940..1bf6d7010 100644 --- a/packages/coding-agent/test/memories-runtime.test.ts +++ b/packages/coding-agent/test/memories-runtime.test.ts @@ -349,7 +349,7 @@ describe("buildMemoryToolDeveloperInstructions", () => { test("returns undefined for missing or empty summaries", async () => { const agentDir = await makeTempDir("memories-runtime-instructions"); - const settings = Settings.isolated({ "memories.enabled": true }); + const settings = Settings.isolated({ "memory.backend": "local" }); expect(await buildMemoryToolDeveloperInstructions(agentDir, settings)).toBeUndefined(); @@ -362,7 +362,7 @@ describe("buildMemoryToolDeveloperInstructions", () => { test("renders payload with truncation for non-empty summary", async () => { const agentDir = await makeTempDir("memories-runtime-instructions"); const settings = Settings.isolated({ - "memories.enabled": true, + "memory.backend": "local", "memories.summaryInjectionTokenLimit": 8, }); const memoryRoot = getMemoryRoot(agentDir, settings.getCwd()); diff --git a/packages/coding-agent/test/memory-backend-resolve.test.ts b/packages/coding-agent/test/memory-backend-resolve.test.ts index 590a6584b..68cdc8aa9 100644 --- a/packages/coding-agent/test/memory-backend-resolve.test.ts +++ b/packages/coding-agent/test/memory-backend-resolve.test.ts @@ -16,18 +16,12 @@ describe("resolveMemoryBackend", () => { expect(resolveMemoryBackend(settings).id).toBe("off"); }); - it("returns the local backend when memory.backend is local AND memories.enabled is true", () => { - const settings = Settings.isolated({ "memory.backend": "local", "memories.enabled": true }); + it("returns the local backend when memory.backend is local", () => { + const settings = Settings.isolated({ "memory.backend": "local", "memories.enabled": false }); expect(resolveMemoryBackend(settings).id).toBe("local"); }); - it("returns the off backend when memory.backend is local but memories.enabled is false", () => { - const settings = Settings.isolated({ "memory.backend": "local", "memories.enabled": false }); - // Falls back to off so existing users with memories.enabled=false keep silence. - expect(resolveMemoryBackend(settings).id).toBe("off"); - }); - - it("returns the hindsight backend when memory.backend is hindsight, regardless of memories.enabled", () => { + it("returns the hindsight backend when memory.backend is hindsight, regardless of legacy memories.enabled", () => { const a = Settings.isolated({ "memory.backend": "hindsight", "memories.enabled": false }); const b = Settings.isolated({ "memory.backend": "hindsight", "memories.enabled": true }); expect(resolveMemoryBackend(a).id).toBe("hindsight");