Fusion Memory Plugin Contract

May 4, 2026 · View on GitHub

← Docs index

This document is the source-of-truth contract for Fusion memory backend behavior after the FN-2087 migration series.


Table of Contents

  1. Current Fusion Memory Baseline
  2. OpenClaw Research Findings
  3. Fusion Memory Plugin Contract
  4. Migration Strategy + Compatibility Guardrails
  5. Downstream Task Alignment

1. Current Fusion Memory Baseline

1.1 Two Memory Systems (Distinct Responsibilities)

Fusion currently has two related but distinct memory systems:

  1. Layered memory backend system (memory-backend.ts + project-memory.ts)
    • Handles agent-facing read/write/get/search for project memory
    • Canonical layered workspace under .fusion/memory/
    • Uses pluggable backends (file, qmd, readonly, custom)
  2. Insight extraction system (memory-insights.ts)
    • Runs scheduled extraction and pruning workflows
    • Reads working memory and writes extracted insights/audit artifacts
    • Independent automation lifecycle and settings

1.2 Canonical Constants and Paths

ConstantValueSource Module
MEMORY_WORKSPACE_PATH.fusion/memorymemory-backend.ts
MEMORY_LONG_TERM_FILENAMEMEMORY.mdmemory-backend.ts
MEMORY_DREAMS_FILENAMEDREAMS.mdmemory-backend.ts
DEFAULT_MEMORY_BACKENDqmdmemory-backend.ts
MEMORY_WORKING_PATH.fusion/memory/MEMORY.mdmemory-insights.ts
MEMORY_INSIGHTS_PATH.fusion/memory/memory-insights.mdmemory-insights.ts
MEMORY_AUDIT_PATH.fusion/memory/memory-audit.mdmemory-insights.ts

1.3 Exported Surface (Post-Migration)

project-memory.ts exports

ExportPurpose
getDefaultMemoryScaffold()Default long-term scaffold content
ensureMemoryFile()Filesystem bootstrap for canonical memory
ensureMemoryFileWithBackend()Backend-aware bootstrap
readProjectMemoryWithBackend()Backend-aware read helper
searchProjectMemory(), getProjectMemory()Backend-aware search/get wrappers
resolveMemoryInstructionContext()Backend-aware instruction context
Planning instruction builderPlanning prompt memory instructions
buildExecutionMemoryInstructions()Executor prompt memory instructions
buildReviewerMemoryInstructions()Reviewer prompt memory instructions
readProjectMemory()Direct canonical long-term file read

memory-backend.ts key exports

ExportPurpose
MemoryBackend, MemoryBackendCapabilitiesRuntime backend contract
MemoryBackendError, MemoryBackendErrorCodeTyped backend error model
FileMemoryBackend, QmdMemoryBackend, ReadOnlyMemoryBackendBuilt-in backend implementations
registerMemoryBackend(), getMemoryBackend(), listMemoryBackendTypes()Function-based registry API
resolveMemoryBackend()Backend resolution from settings
memoryWorkspacePath(), memoryLongTermPath(), dailyMemoryPath(), memoryDreamsPath()Canonical layered path helpers
ensureOpenClawMemoryFiles()Layered file bootstrap
listProjectMemoryFiles(), readProjectMemoryFile(), writeProjectMemoryFile()Validated layered file operations

1.4 Settings Baseline

ProjectSettings fields that govern memory behavior:

  • memoryEnabled?: boolean (default true)
  • memoryBackendType?: string (default "qmd")
  • insightExtractionEnabled?: boolean (default false)
  • insightExtractionSchedule?: string (default "0 2 * * *")
  • insightExtractionMinIntervalMs?: number (default 86400000)

Runtime backend resolution uses an internal MemorySettings shape with memoryBackendType and optional additional keys.

1.5 Key Invariants

  1. Canonical layered long-term memory file is .fusion/memory/MEMORY.md.
  2. Runtime memory APIs only read/write canonical layered files under .fusion/memory/.
  3. Default backend is qmd (DEFAULT_MEMORY_BACKEND).
  4. Backend selection key is memoryBackendType.
  5. Prompt instruction context is backend-aware (file path hint vs qmd/readonly behavior).
  6. Dashboard /api/memory routes are backend-aware; layered file routes validate requests against allowed memory workspace files.

2. OpenClaw Research Findings

Fusion adopted OpenClaw-style layered memory while keeping a concrete TypeScript runtime contract.

2.1 What Was Adopted

  • Layered workspace (MEMORY.md, daily files, DREAMS.md)
  • Backend abstraction with explicit capability declarations
  • Search over layered files with bounded snippets
  • Migration safety via strict canonical path validation for layered files

2.2 Implications Table

OpenClaw ConceptFusion Current StateContract Implication
Layered memory filesImplemented under .fusion/memory/Canonical source-of-truth is workspace-based, not single-file
Path abstractionImplemented via backend methods that receive rootDir (read(rootDir), write(rootDir, ...), etc.)Backends must resolve paths relative to project root; no global hardcoded absolute paths
Pluggable backendsImplemented (file, qmd, readonly, custom)Contract must document MemoryBackend exactly as shipped
Capability negotiationImplemented via boolean-struct capabilitiesNo enum or lifecycle-based capability API
SearchImplemented through optional search(rootDir, options) hooksResults are bounded snippets, not full-document dumps
Path migration completionLegacy top-level path support removed from runtime APIsCanonical source-of-truth is .fusion/memory/ only

3. Fusion Memory Plugin Contract

3.1 Runtime Interface (Canonical)

export interface MemoryBackendCapabilities {
  readable: boolean;
  writable: boolean;
  supportsAtomicWrite: boolean;
  hasConflictResolution: boolean;
  persistent: boolean;
}

export interface MemoryBackend {
  readonly type: string;
  readonly name: string;
  readonly capabilities: MemoryBackendCapabilities;
  read(rootDir: string): Promise<MemoryReadResult>;
  write(rootDir: string, content: string): Promise<MemoryWriteResult>;
  get?(rootDir: string, options: MemoryGetOptions): Promise<MemoryGetResult>;
  search?(rootDir: string, options: MemorySearchOptions): Promise<MemorySearchResult[]>;
  exists?(rootDir: string): Promise<boolean>;
}

export interface MemoryBackendConfig {
  type: string;
  options?: Record<string, unknown>;
}

This is the active contract. The following are not part of current runtime semantics: initialize(), hasCapability(), flush(), shutdown(), class-based registry APIs, or lifecycle interfaces.

3.2 Error Contract

export type MemoryBackendErrorCode =
  | "NOT_FOUND"
  | "READ_ONLY"
  | "READ_FAILED"
  | "WRITE_FAILED"
  | "UNSUPPORTED"
  | "CONFLICT"
  | "QUOTA_EXCEEDED"
  | "BACKEND_UNAVAILABLE";

export class MemoryBackendError extends Error {
  readonly code: MemoryBackendErrorCode;
  readonly backend: string;
}

3.3 Built-In Backends

Backend ClassTypeCurrent Behavior
FileMemoryBackendfileReads/writes canonical .fusion/memory/MEMORY.md; supports exists/get/search; atomic writes via temp file rename
QmdMemoryBackendqmdDelegates read/write to file backend; schedules qmd refresh; uses qmd search first, local layered search fallback
ReadOnlyMemoryBackendreadonlyRead-only; write() throws MemoryBackendError("READ_ONLY", ...); search() returns empty

3.4 Registry Contract (Function-Based)

registerMemoryBackend(backend: MemoryBackend): void
getMemoryBackend(type: string): MemoryBackend | undefined
listMemoryBackendTypes(): string[]

Backends are stored in a module-level Map<string, MemoryBackend>. Built-ins are registered at module load.

3.5 Resolution Contract

export const MEMORY_BACKEND_SETTINGS_KEYS = {
  MEMORY_BACKEND_TYPE: "memoryBackendType",
} as const;

export const DEFAULT_MEMORY_BACKEND = "qmd";

export function resolveMemoryBackend(settings?: { memoryBackendType?: string }): MemoryBackend

Resolution chain:

  1. Configured memoryBackendType (if registered)
  2. DEFAULT_MEMORY_BACKEND ("qmd")

3.6 Layered Memory Operations

The layered memory workspace helpers in memory-backend.ts provide:

  • Workspace bootstrap: ensureOpenClawMemoryFiles()
  • File listing: listProjectMemoryFiles()
  • Validated file access: readProjectMemoryFile(), writeProjectMemoryFile()
  • Path helpers: memoryLongTermPath(), dailyMemoryPath(), memoryDreamsPath()

Allowed workspace files are constrained to:

  • .fusion/memory/MEMORY.md
  • .fusion/memory/DREAMS.md
  • .fusion/memory/YYYY-MM-DD.md

3.7 Prompt Instruction Context Contract

resolveMemoryInstructionContext(settings?) in project-memory.ts currently resolves as:

ConditionbackendTypeinstructionPathHintBehavior
memoryEnabled === falsedisablednullNo memory instructions
memoryBackendType === "file"file.fusion/memory/MEMORY.mdExplicit path-aware read/write instructions
memoryBackendType === "readonly"readonlynullRead-only instruction set
memoryBackendType === "qmd" or unknownqmdnullBackend-aware generic instructions

3.8 File Compatibility & Source-of-Truth Semantics

3.8.1 Canonical source-of-truth

  • Canonical layered workspace: .fusion/memory/
  • Canonical long-term file: .fusion/memory/MEMORY.md
  • Runtime path validation rejects non-layered legacy requests

3.8.2 QMD stale-index normalization scope

QMD search result normalization may remap stale indexed paths to canonical layered paths so search results remain consumable. This normalization does not re-enable legacy read/write APIs.

3.8.3 Dashboard and API path constraints

Dashboard memory routes must remain rooted in project-scoped memory APIs:

  • /api/memory uses backend-aware read/write (readMemory, writeMemory)
  • /api/memory/file uses validated layered file operations (MEMORY.md, DREAMS.md, daily files)
  • Read-only backends must reject writes with READ_ONLY

3.8.4 Prompt compatibility matrix

BackendRead behaviorWrite behaviorInstruction style
qmd (default)Delegated file readDelegated file write + qmd refresh scheduleGeneric backend-aware instructions, no fixed path hint
fileDirect canonical file readDirect canonical file writeExplicit .fusion/memory/MEMORY.md path hint
readonlyEmpty/non-throw read semanticsThrows READ_ONLYRead-only instructions only

3.8.5 Insight extraction relationship

Insight extraction is a separate subsystem that currently uses:

  • Working source: .fusion/memory/MEMORY.md
  • Insight output: .fusion/memory/memory-insights.md
  • Audit output: .fusion/memory/memory-audit.md

It is related to, but not equivalent to, backend selection and prompt instruction logic.


4. Migration Strategy + Compatibility Guardrails

4.1 Migration Phase Status

PhaseTask(s)Status
Core backend contract + built-insFN-1418Complete
Engine backend-aware prompt integrationFN-1419Complete
Dashboard backend-aware memory integrationFN-1420Complete
Path/backend reconciliation umbrellaFN-2087Complete
Reconciliation implementation slicesFN-2131, FN-2132, FN-2133, FN-2134Complete

4.2 Must-Not-Break Invariants

  1. Canonical long-term layered memory remains .fusion/memory/MEMORY.md.
  2. Legacy top-level memory requests are not part of the runtime API contract.
  3. Runtime backend selection remains keyed by memoryBackendType.
  4. DEFAULT_MEMORY_BACKEND remains "qmd" unless explicitly changed in code + docs.
  5. Prompt instruction behavior remains backend-dependent via resolveMemoryInstructionContext().
  6. Missing working-memory reads degrade gracefully to empty string where contract requires.

4.3 Resolution Fallback Chain

  1. Use configured backend type if registered.
  2. Otherwise fall back to DEFAULT_MEMORY_BACKEND ("qmd").
  3. For qmd search failures/unavailability, fall back to local layered file search.

4.4 Compatibility Matrix

ConcernRequired Behavior
Settings persistenceUnknown memoryBackendType may be persisted, but runtime still falls back safely
Read-only backendWrites fail with typed READ_ONLY error
Legacy upgradesRuntime memory APIs ignore legacy top-level paths and operate on layered files only
Memory file APIsMust enforce workspace-relative path validation and project root boundaries
Prompt generationMust honor memoryEnabled toggle and backend-aware instruction context

4.5 Test Coverage Verification Checklist

Contract-critical behavior is covered by:

  • packages/core/src/memory-backend.test.ts
    • built-in backends (file, qmd, readonly)
    • registry helpers and resolveMemoryBackend() default/fallback behavior
    • layered workspace helpers (ensureOpenClawMemoryFiles, list/get/write, path validation)
  • packages/core/src/project-memory.test.ts
    • canonical long-term path bootstrap/read behavior
    • resolveMemoryInstructionContext() branching
    • planning/execution/reviewer instruction generation per backend
  • packages/core/src/store.test.ts
    • memory bootstrap behavior when memory is enabled/disabled and toggled
  • Engine planning and executor tests
    • memory instruction injection behavior by settings/backend

5. Downstream Task Alignment

This contract should remain aligned with:

If backend contract behavior changes in source, update these docs in the same change.


Last updated: 2026-04-19