Fusion Memory Plugin Contract
May 4, 2026 · View on GitHub
This document is the source-of-truth contract for Fusion memory backend behavior after the FN-2087 migration series.
Table of Contents
- Current Fusion Memory Baseline
- OpenClaw Research Findings
- Fusion Memory Plugin Contract
- Migration Strategy + Compatibility Guardrails
- Downstream Task Alignment
1. Current Fusion Memory Baseline
1.1 Two Memory Systems (Distinct Responsibilities)
Fusion currently has two related but distinct memory systems:
- 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)
- 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
| Constant | Value | Source Module |
|---|---|---|
MEMORY_WORKSPACE_PATH | .fusion/memory | memory-backend.ts |
MEMORY_LONG_TERM_FILENAME | MEMORY.md | memory-backend.ts |
MEMORY_DREAMS_FILENAME | DREAMS.md | memory-backend.ts |
DEFAULT_MEMORY_BACKEND | qmd | memory-backend.ts |
MEMORY_WORKING_PATH | .fusion/memory/MEMORY.md | memory-insights.ts |
MEMORY_INSIGHTS_PATH | .fusion/memory/memory-insights.md | memory-insights.ts |
MEMORY_AUDIT_PATH | .fusion/memory/memory-audit.md | memory-insights.ts |
1.3 Exported Surface (Post-Migration)
project-memory.ts exports
| Export | Purpose |
|---|---|
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 builder | Planning 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
| Export | Purpose |
|---|---|
MemoryBackend, MemoryBackendCapabilities | Runtime backend contract |
MemoryBackendError, MemoryBackendErrorCode | Typed backend error model |
FileMemoryBackend, QmdMemoryBackend, ReadOnlyMemoryBackend | Built-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(defaulttrue)memoryBackendType?: string(default"qmd")insightExtractionEnabled?: boolean(defaultfalse)insightExtractionSchedule?: string(default"0 2 * * *")insightExtractionMinIntervalMs?: number(default86400000)
Runtime backend resolution uses an internal MemorySettings shape with memoryBackendType and optional additional keys.
1.5 Key Invariants
- Canonical layered long-term memory file is
.fusion/memory/MEMORY.md. - Runtime memory APIs only read/write canonical layered files under
.fusion/memory/. - Default backend is
qmd(DEFAULT_MEMORY_BACKEND). - Backend selection key is
memoryBackendType. - Prompt instruction context is backend-aware (
filepath hint vsqmd/readonlybehavior). - Dashboard
/api/memoryroutes 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 Concept | Fusion Current State | Contract Implication |
|---|---|---|
| Layered memory files | Implemented under .fusion/memory/ | Canonical source-of-truth is workspace-based, not single-file |
| Path abstraction | Implemented 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 backends | Implemented (file, qmd, readonly, custom) | Contract must document MemoryBackend exactly as shipped |
| Capability negotiation | Implemented via boolean-struct capabilities | No enum or lifecycle-based capability API |
| Search | Implemented through optional search(rootDir, options) hooks | Results are bounded snippets, not full-document dumps |
| Path migration completion | Legacy top-level path support removed from runtime APIs | Canonical 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 Class | Type | Current Behavior |
|---|---|---|
FileMemoryBackend | file | Reads/writes canonical .fusion/memory/MEMORY.md; supports exists/get/search; atomic writes via temp file rename |
QmdMemoryBackend | qmd | Delegates read/write to file backend; schedules qmd refresh; uses qmd search first, local layered search fallback |
ReadOnlyMemoryBackend | readonly | Read-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:
- Configured
memoryBackendType(if registered) 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:
| Condition | backendType | instructionPathHint | Behavior |
|---|---|---|---|
memoryEnabled === false | disabled | null | No memory instructions |
memoryBackendType === "file" | file | .fusion/memory/MEMORY.md | Explicit path-aware read/write instructions |
memoryBackendType === "readonly" | readonly | null | Read-only instruction set |
memoryBackendType === "qmd" or unknown | qmd | null | Backend-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/memoryuses backend-aware read/write (readMemory,writeMemory)/api/memory/fileuses 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
| Backend | Read behavior | Write behavior | Instruction style |
|---|---|---|---|
qmd (default) | Delegated file read | Delegated file write + qmd refresh schedule | Generic backend-aware instructions, no fixed path hint |
file | Direct canonical file read | Direct canonical file write | Explicit .fusion/memory/MEMORY.md path hint |
readonly | Empty/non-throw read semantics | Throws READ_ONLY | Read-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
| Phase | Task(s) | Status |
|---|---|---|
| Core backend contract + built-ins | FN-1418 | Complete |
| Engine backend-aware prompt integration | FN-1419 | Complete |
| Dashboard backend-aware memory integration | FN-1420 | Complete |
| Path/backend reconciliation umbrella | FN-2087 | Complete |
| Reconciliation implementation slices | FN-2131, FN-2132, FN-2133, FN-2134 | Complete |
4.2 Must-Not-Break Invariants
- Canonical long-term layered memory remains
.fusion/memory/MEMORY.md. - Legacy top-level memory requests are not part of the runtime API contract.
- Runtime backend selection remains keyed by
memoryBackendType. DEFAULT_MEMORY_BACKENDremains"qmd"unless explicitly changed in code + docs.- Prompt instruction behavior remains backend-dependent via
resolveMemoryInstructionContext(). - Missing working-memory reads degrade gracefully to empty string where contract requires.
4.3 Resolution Fallback Chain
- Use configured backend type if registered.
- Otherwise fall back to
DEFAULT_MEMORY_BACKEND("qmd"). - For
qmdsearch failures/unavailability, fall back to local layered file search.
4.4 Compatibility Matrix
| Concern | Required Behavior |
|---|---|
| Settings persistence | Unknown memoryBackendType may be persisted, but runtime still falls back safely |
| Read-only backend | Writes fail with typed READ_ONLY error |
| Legacy upgrades | Runtime memory APIs ignore legacy top-level paths and operate on layered files only |
| Memory file APIs | Must enforce workspace-relative path validation and project root boundaries |
| Prompt generation | Must 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)
- built-in backends (
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