feat(FN-2087): finalize canonical memory path migration
- Remove legacy .fusion/memory.md fallback references and normalize prompts/docs to .fusion/memory/MEMORY.md - Stop legacy mirror writes and fallback reads in core memory backend and project memory flows - Update engine worktree boundary checks and tests for canonical memory file handling - Align dashboard memory/settings surfaces and route tests with canonical memory behavior - Add model-favorites persistence test coverage for mission interview and new agent dialogs
This commit is contained in:
@@ -236,13 +236,12 @@ From `packages/core/src/index.ts` exports (selected high-impact modules):
|
||||
|
||||
### Memory System
|
||||
|
||||
Fusion supports OpenClaw-style project memory with legacy fallback support:
|
||||
Fusion uses OpenClaw-style project memory files:
|
||||
|
||||
**Primary memory files:**
|
||||
- Long-term: `.fusion/memory/MEMORY.md`
|
||||
- Daily notes: `.fusion/memory/YYYY-MM-DD.md`
|
||||
- Dream processing: `.fusion/memory/DREAMS.md`
|
||||
- Legacy fallback (deprecated compatibility path): `.fusion/memory.md`
|
||||
|
||||
**Memory subsystems:**
|
||||
- `memory-backend.ts` — backend contracts + file/readonly/qmd implementations
|
||||
@@ -485,7 +484,7 @@ SQLite schema is initialized in `packages/core/src/db.ts` and uses:
|
||||
- `.fusion/memory/MEMORY.md`
|
||||
- `.fusion/memory/YYYY-MM-DD.md`
|
||||
- `.fusion/memory/DREAMS.md`
|
||||
- Legacy fallback (deprecated compatibility path): `.fusion/memory.md`
|
||||
- Upgrade migration may seed `MEMORY.md` from legacy `.fusion/memory.md` if present.
|
||||
|
||||
### File-based side stores
|
||||
Some data remains intentionally filesystem-based:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## 1. Scope & Methodology
|
||||
|
||||
### Files Examined
|
||||
- **Context files read:** `.fusion/memory.md`, `package.json`, `docs/architecture.md`, `improvements.md`, `docs/gap-analysis.md`, `docs/test-audit-report.md`
|
||||
- **Context files read:** `.fusion/memory/MEMORY.md`, `package.json`, `docs/architecture.md`, `improvements.md`, `docs/gap-analysis.md`, `docs/test-audit-report.md`
|
||||
- **Core hotspots:** `packages/core/src/store.ts` (3,895 LOC), `packages/engine/src/executor.ts` (3,355 LOC), `packages/dashboard/src/routes.ts` (12,480 LOC), `packages/cli/src/extension.ts` (1,741 LOC)
|
||||
- **Engine runtime:** `packages/engine/src/runtimes/child-process-runtime.ts`, `packages/engine/src/step-session-executor.ts`, `packages/engine/src/project-manager.ts`, `packages/engine/src/cron-runner.ts`
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
1. Re-checked each finding from prior audits against current code state
|
||||
2. Assessed whether issues are: **resolved**, **still open**, or **changed scope**
|
||||
3. Provided concrete evidence (file paths + line numbers)
|
||||
4. Incorporated memory-informed checks from `.fusion/memory.md`
|
||||
4. Incorporated memory-informed checks from `.fusion/memory/MEMORY.md`
|
||||
|
||||
---
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
## 3. Memory-Informed Checks
|
||||
|
||||
Based on `.fusion/memory.md` constraints and pitfalls:
|
||||
Based on `.fusion/memory/MEMORY.md` constraints and pitfalls:
|
||||
|
||||
| # | Constraint/Pitfall | Still a Concern? | Notes |
|
||||
|---|-------------------|------------------|-------|
|
||||
|
||||
@@ -104,12 +104,12 @@ Use task-ID-scoped conventional commits:
|
||||
|
||||
## Project Memory
|
||||
|
||||
When enabled, Fusion uses OpenClaw-style memory files as the canonical project memory workspace:
|
||||
When enabled, Fusion uses OpenClaw-style memory files:
|
||||
|
||||
- `.fusion/memory/MEMORY.md` — curated long-term memory for durable decisions, conventions, and pitfalls
|
||||
- `.fusion/memory/YYYY-MM-DD.md` — append-only daily running notes
|
||||
- `.fusion/memory/DREAMS.md` — synthesized patterns distilled from daily notes
|
||||
- `.fusion/memory.md` — deprecated legacy fallback path (kept for backward compatibility)
|
||||
- `.fusion/memory/MEMORY.md` — long-term project memory
|
||||
- `.fusion/memory/YYYY-MM-DD.md` — daily running notes
|
||||
- `.fusion/memory/DREAMS.md` — dream-processing memory file
|
||||
- Legacy `.fusion/memory.md` is only used as a one-time migration seed for upgrades
|
||||
|
||||
Use project memory for reusable patterns, constraints, and pitfalls that should persist across tasks.
|
||||
|
||||
@@ -117,11 +117,9 @@ Use project memory for reusable patterns, constraints, and pitfalls that should
|
||||
|
||||
Fusion can automatically extract insights from memory and prune transient content. Enable via `insightExtractionEnabled` setting:
|
||||
|
||||
- `.fusion/memory/MEMORY.md` — canonical long-term memory target for durable knowledge
|
||||
- `.fusion/memory/YYYY-MM-DD.md` — daily notes source used for ongoing synthesis
|
||||
- `.fusion/memory/DREAMS.md` — synthesized memory patterns
|
||||
- `.fusion/memory-insights.md` — legacy distilled insights artifact (still generated by the current extraction pipeline)
|
||||
- `.fusion/memory-audit.md` — legacy audit artifact for extraction runs
|
||||
- `.fusion/memory/MEMORY.md` — Working/long-term memory source compacted and pruned by extraction jobs
|
||||
- `.fusion/memory-insights.md` — Distilled insights output
|
||||
- `.fusion/memory-audit.md` — Audit report after each extraction (includes pruning outcome)
|
||||
|
||||
See [Settings Reference](./settings-reference.md#background-memory-summarization--audit) for configuration details.
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ readProjectMemory(rootDir: string): Promise<string> // Read current content
|
||||
```
|
||||
|
||||
**Key invariants:**
|
||||
- Canonical memory path is `.fusion/memory/MEMORY.md` (project-root relative, NOT worktree-local)
|
||||
- Legacy fallback `.fusion/memory.md` remains readable for backward compatibility
|
||||
- `MEMORY_FILE_PATH` is always `.fusion/memory/MEMORY.md` (project-root relative, NOT worktree-local)
|
||||
- `ensureMemoryFile` is idempotent: safe to call multiple times; never overwrites existing content
|
||||
- Bootstrap failure is non-fatal: `store.ts` wraps the call in try/catch
|
||||
|
||||
@@ -170,9 +169,9 @@ if (memoryEnabled && rootDir) {
|
||||
| Route | Method | Description |
|
||||
|-------|--------|-------------|
|
||||
| `/api/memory` | GET | Returns `{ content: string }` — empty string if file absent |
|
||||
| `/api/memory` | PUT | Body: `{ content: string }` — writes to canonical `.fusion/memory/MEMORY.md` (legacy fallback remains supported) |
|
||||
| `/api/memory` | PUT | Body: `{ content: string }` — writes to `.fusion/memory/MEMORY.md` |
|
||||
|
||||
Both routes use `readProjectFile` / `writeProjectFile` from `file-service.ts`, which enforces project-root path constraints (canonical memory path is `.fusion/memory/MEMORY.md`, with `.fusion/memory.md` treated as a compatibility fallback).
|
||||
Both routes use `readProjectFile` / `writeProjectFile` from `file-service.ts`, which enforces project-root path constraints (memory path is `.fusion/memory/MEMORY.md` — always within project scope).
|
||||
|
||||
### 1.6 Dashboard Settings UI
|
||||
|
||||
@@ -194,7 +193,7 @@ Both routes use `readProjectFile` / `writeProjectFile` from `file-service.ts`, w
|
||||
|
||||
### 1.8 Summary of Non-Negotiable Behaviors
|
||||
|
||||
1. **File path**: Canonical memory lives at `.fusion/memory/MEMORY.md` (project root, not worktree); legacy `.fusion/memory.md` remains a compatibility fallback
|
||||
1. **File path**: Memory always lives at `.fusion/memory/MEMORY.md` (project root, not worktree)
|
||||
2. **Toggle**: `memoryEnabled` controls all memory behavior — when `false`, no instructions injected, no reads/writes
|
||||
3. **Default**: `memoryEnabled: true` (backward-compatible default)
|
||||
4. **Idempotent bootstrap**: `ensureMemoryFile` never overwrites existing content
|
||||
@@ -270,7 +269,7 @@ OpenClaw backends fall back to a default (file-based) backend when:
|
||||
| Auto-flush | Manual writes via dashboard | Backend should handle internal buffering |
|
||||
| Search capability | Not implemented | Optional `search()` method in interface |
|
||||
| Fallback semantics | Always file-based | Need explicit fallback chain |
|
||||
| Path abstraction | Canonical `.fusion/memory/MEMORY.md` with legacy fallback support | Backend config includes `rootDir` |
|
||||
| Path abstraction | Hardcoded `.fusion/memory/MEMORY.md` | Backend config includes `rootDir` |
|
||||
|
||||
### 2.3 OpenClaw Memory Architecture Sources
|
||||
|
||||
@@ -527,7 +526,7 @@ export type MemoryBackendFactory = (
|
||||
```typescript
|
||||
/**
|
||||
* Default file-based memory backend.
|
||||
* Preserves canonical behavior: .fusion/memory/MEMORY.md on project root (with legacy .fusion/memory.md fallback).
|
||||
* Preserves exact current behavior: .fusion/memory/MEMORY.md on project root.
|
||||
*
|
||||
* This backend is always registered as the fallback when no other backend
|
||||
* is configured or when configured backend is unavailable.
|
||||
@@ -721,15 +720,13 @@ The following return shapes are **contractually guaranteed** by all backends and
|
||||
|
||||
**For the `"file"` backend (default):**
|
||||
- The file `.fusion/memory/MEMORY.md` IS the canonical source
|
||||
- Legacy `.fusion/memory.md` remains readable as a backward-compatible fallback
|
||||
- All reads/writes target canonical memory semantics
|
||||
- All reads/writes go directly to the file
|
||||
- No mirroring or sync required
|
||||
|
||||
**For alternative backends:**
|
||||
- The backend is the canonical source for memory content
|
||||
- **File mirroring is NOT required** — alternative backends need not maintain `.fusion/memory/MEMORY.md`
|
||||
- If a backend stores content externally (database, cloud), `.fusion/memory/MEMORY.md` may be stale or absent
|
||||
- Legacy `.fusion/memory.md` may exist but should be treated as compatibility-only data
|
||||
|
||||
#### 3.8.3 File Bridge Adapter (For Dashboard/Agent Compatibility)
|
||||
|
||||
@@ -782,7 +779,7 @@ Dashboard routes (`/api/memory`) use `readProjectFile`/`writeProjectFile` from `
|
||||
|
||||
| Constraint | Source | Requirement |
|
||||
|------------|--------|-------------|
|
||||
| Path validation | `file-service.ts:55` | Canonical memory path `.fusion/memory/MEMORY.md` (and legacy fallback `.fusion/memory.md`) must be within project scope |
|
||||
| Path validation | `file-service.ts:55` | Memory path `.fusion/memory/MEMORY.md` must be within project scope |
|
||||
| File size limit | `MAX_FILE_SIZE = 1MB` | Backend writes must not exceed 1MB |
|
||||
| Text encoding | `utf-8` | All content encoded as UTF-8 |
|
||||
|
||||
@@ -831,7 +828,7 @@ Prompt instructions branch based on the configured memory backend type via `reso
|
||||
|
||||
**Behavior details:**
|
||||
|
||||
- **File backend**: Instructions include `.fusion/memory/MEMORY.md` guidance and read/write directives (plus legacy `.fusion/memory.md` fallback context)
|
||||
- **File backend**: Instructions include `.fusion/memory/MEMORY.md` guidance and read/write directives
|
||||
- **Readonly backend**: Instructions include read-only wording but no write/update directives
|
||||
- **QMD/non-file backends**: Instructions are generic without assuming a file path; agents consult the project memory through backend-specific mechanisms
|
||||
- **Backward compatibility**: When `memoryBackendType` is omitted or unknown, defaults to file behavior
|
||||
@@ -894,10 +891,10 @@ Prompt instructions branch based on the configured memory backend type via `reso
|
||||
|
||||
### 4.3 Must-Not-Break Invariants
|
||||
|
||||
1. **File path invariant**: Canonical memory is always accessible at `.fusion/memory/MEMORY.md`, with `.fusion/memory.md` supported as legacy fallback
|
||||
1. **File path invariant**: Memory always accessible at `.fusion/memory/MEMORY.md` (file backend is always available as fallback)
|
||||
2. **Toggle invariant**: `memoryEnabled: false` always means zero memory **prompt** operations — agent instructions are NOT injected, but `GET /api/memory` remains readable and `PUT /api/memory` remains writable
|
||||
3. **Bootstrap invariant**: `ensureMemoryFile` is always called on init when `memoryEnabled !== false`
|
||||
4. **Prompt invariant**: Memory instructions always use project-root canonical paths (`.fusion/memory/MEMORY.md` and `.fusion/memory/*`), never worktree-local paths
|
||||
4. **Prompt invariant**: Memory instructions always use project-root path (`.fusion/memory/MEMORY.md`), never worktree-local
|
||||
5. **Non-fatal invariant**: Memory initialization/operation failures never block startup or settings updates
|
||||
6. **Insights null invariant**: `readInsightsMemory()` returns `null` when `.fusion/memory-insights.md` is absent (not `""`)
|
||||
7. **Insights write invariant**: `writeInsightsMemory()` creates `.fusion/` directory and `.fusion/memory-insights.md` if absent
|
||||
|
||||
@@ -390,8 +390,7 @@ Fusion can automatically extract insights from project memory and prune transien
|
||||
|
||||
1. **Scheduled Extraction**: When `insightExtractionEnabled` is `true`, a background automation runs on the configured `insightExtractionSchedule` (default: daily at 2 AM).
|
||||
|
||||
2. **AI-Powered Analysis**: The automation uses an AI agent to read canonical OpenClaw memory files (`.fusion/memory/MEMORY.md`, `.fusion/memory/YYYY-MM-DD.md`) plus compatibility insight artifacts (`.fusion/memory-insights.md`), then extract new insights and produce a pruned working memory candidate.
|
||||
- Legacy fallback note: `.fusion/memory.md` remains supported for backward compatibility in older projects.
|
||||
2. **AI-Powered Analysis**: The automation uses an AI agent to read `.fusion/memory/MEMORY.md` and `.fusion/memory-insights.md`, extract new insights, and produce a pruned working memory candidate.
|
||||
|
||||
3. **Insight Merging**: New insights are automatically merged into `.fusion/memory-insights.md` under the appropriate category (Patterns, Principles, Conventions, Pitfalls, Context). Duplicates are skipped.
|
||||
|
||||
@@ -411,11 +410,9 @@ Fusion can automatically extract insights from project memory and prune transien
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `.fusion/memory/MEMORY.md` | Canonical long-term memory file (updated with durable content) |
|
||||
| `.fusion/memory/YYYY-MM-DD.md` | Daily running notes used during synthesis/pruning workflows |
|
||||
| `.fusion/memory/DREAMS.md` | Dream synthesis output derived from daily notes |
|
||||
| `.fusion/memory-insights.md` | Legacy distilled-insights artifact kept for compatibility |
|
||||
| `.fusion/memory-audit.md` | Legacy human-readable audit report after each extraction |
|
||||
| `.fusion/memory/MEMORY.md` | Working memory (updated when pruning is applied and validated) |
|
||||
| `.fusion/memory-insights.md` | Long-term insights distilled from working memory |
|
||||
| `.fusion/memory-audit.md` | Human-readable audit report after each extraction |
|
||||
|
||||
### Settings Interaction
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ One prelisted item is no longer untested:
|
||||
|
||||
## 4.5 Memory pitfall cross-reference
|
||||
|
||||
From `.fusion/memory.md` testing pitfalls:
|
||||
From `.fusion/memory/MEMORY.md` testing pitfalls:
|
||||
|
||||
- **Engine pool setting must remain threads** — config currently reflects this (`packages/engine/vitest.config.ts:10`), but there is no dedicated regression test guarding accidental config drift.
|
||||
- **Dashboard 429 retry test requires 30s timeout** — still covered (`packages/dashboard/src/routes.test.ts:3992-4016`).
|
||||
|
||||
Reference in New Issue
Block a user