Basic Memory v0.21.6 first sync over the live memory dir (steward-authorized live-dir trial, Option A 2026-06-06): adds permalink: to frontmatter, refolds long YAML description lines, strips final newlines. Bodies untouched — verified via full diff classification. From this commit forward, any diff in claude/memory shows only what Basic Memory or the session writes. Trial design: MemPalace untouched as incumbent; git status check on this dir at every wrap; end-of-day evaluation (recall quality, sync robustness, rebuild-from-files, malformed-file behavior). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.0 KiB
7.0 KiB
name, description, type, originSessionId, permalink
| name | description | type | originSessionId | permalink |
|---|---|---|---|---|
| Session 2026-04-13/14 — Storage layer trial and SQLite+LanceDB migration | Benchmarked three storage backends (NFCorpus/BEIR), chose SQLite+LanceDB, migrated all 13 modules. 40 infrastructure errors remain. | project | e02702fe-d3d4-4b0d-a71b-d83a06479fe2 | claude-memory/session-2026-04-13-storage-trial |
What we did
Storage Layer Trial (2026-04-13)
- Designed and executed three-branch evaluation of SurrealDB alternatives
- Branch A (
trial/storage-surrealdb-only): SurrealDB control - Branch B (
trial/storage-sqlite-lance): better-sqlite3 + LanceDB — SELECTED - Branch C (
trial/storage-sqlite-pure): better-sqlite3 + FTS5 + sqlite-vec - Built shared benchmark harness with NFCorpus (BEIR) dataset, real mxbai-embed-large embeddings (1024-dim), official relevance judgments
- Benchmark metrics: NDCG@10, recall@10 vs brute-force, ingest throughput, memory ceiling, cold start, read-under-write P95
Benchmark Results
| Metric | SurrealDB | SQLite+Lance | SQLite-Pure |
|---|---|---|---|
| Ingest (docs/min) | 4,441 | 8,079 | 173,207 |
| Hybrid NDCG@10 | 0.000 | 0.433 | 0.421 |
| Vector recall@10 | 0.000 | 0.984 | 0.984 |
| FTS NDCG@10 | 0.000 | 0.375 | 0.195 |
| RSS (MB) | 164 | 228 | 129 |
Migration (2026-04-13 evening → 2026-04-14 early morning)
- Built core storage layer:
src/core/storage/sqlite-lance.ts(getSqliteDb, getLanceDb, migrations, circuit breakers) - Created SQLite/LanceDB implementations for all 13 modules (8,517 lines total)
- Created compatibility bridges: each module's
storage.tsre-exports SQLite functions under original names - Wired all module
index.tsfiles to usegetSqliteDb()+initXStorage() - Changed all module pipeline/query files from
SurrealQueryBuildertoStorageDb = SqliteHandle - Converted inline SurrealQL in entity/pipeline.ts (resolution candidates, fuzzy match → SQLite + app-level Levenshtein)
- Rewrote training/model-registry.ts for SQLite
- Stubbed entity/temporal reconciliation (repair-only, not hot path)
wshobson/agents installed
- 41 agents + 40 skills installed from https://github.com/wshobson/agents to match Seb's setup
- Installed at
~/.claude/agents/(namespaced:plugin-agent.md) - Skills at
~/.claude/skills/
What we decided
Branch B (SQLite + LanceDB) chosen because:
- Recall quality is primary — memory system must find what it stored. Tantivy FTS (0.375 NDCG) > FTS5 (0.195)
- Scale-ready — LanceDB HNSW is O(log n), sqlite-vec brute-force is O(n). BMF is designed to grow
- Each tool does its job — better-sqlite3 (25 yrs, trillions of deployments) for relational; LanceDB (Rust, Arrow, Tantivy) for vectors+FTS
- David's instinct about dual-stack was right — the "single stack" burn was about maturity, not count
StorageDb = SqliteHandle (not any or unknown)
David explicitly rejected any as a type escape hatch. The prime directive applies: "Do things once, correctly." Using StorageDb = SqliteHandle gives proper type safety through the bridge layer.
Bridge pattern chosen over full signature rewrite
Instead of changing 86+ files' function signatures, bridge storage.ts files re-export SQLite functions under original names. Pipeline/query files change only their type import. This minimizes blast radius while maintaining type safety.
What's unresolved
40 compile errors in infrastructure layer
All in non-module files. Module layer is clean (zero errors).
Files with errors:
bootstrap.ts(15 errors) — inline SurrealQL for circle wiring, telemetry, invite codes, budget seeding, meld bootstraporchestrator.ts(8 errors) — cursor store, snapshot queries, IntLiteral usage- MCP tools/resources (10 errors) — budget resources, knowledge tools, training-pairs
- Knowledge services (4 errors) — circle-recall, clasp-knowledge, interaction-service, signal-receiver
- Inference/perception (3 errors) — teacher-enrichment, similarity-probe
These files have inline SurrealQL (db.execute(db.query\...`)`) that needs converting to SQLite SQL, same pattern as entity/pipeline.ts.
Factory, Meld, and Inference layers not yet touched
src/factory/— factory.ts, checkpoint.ts, dedup.ts, job-store.ts, migrations.ts all usegetSurrealDBand SurrealQLsrc/meld/— catalog.ts, bootstrap.ts, pulse.ts, discovery.ts, health.ts, identity.ts, slugs.ts, threats.ts, storage.ts, services/src/inference/— graduation-storage.ts, teacher-enrichment-storage.tssrc/core/reasonchain/— indexes.tssrc/core/lifecycle/— operations.ts, retrieval-tracker.tssrc/core/keystone/— telemetry-schema.ts, readiness/cursor-store.ts, readiness/replay-coordinator.ts, readiness/resource-monitor.ts
Reconciliation functions stubbed
entity/reconciliation.ts— reconcileEntityMentionCounts, reconcileCoOccurrenceEdges → return empty resultstemporal/reconciliation.ts— reconcileCausalChainConfidence, reconcileTemporalCoverage → return empty results These run duringctl repaironly. Need reimplementation before repair is usable.
SurrealDB not yet removed
- Dependencies
surrealdband@surrealdb/nodestill in package.json src/core/storage/surrealdb.ts(1,099 lines) still presentstorage-surreal.tsbackup files in every module- Tests still import from surrealdb.ts
Next actions (ordered)
- Convert remaining 40 infrastructure errors — bootstrap.ts, orchestrator.ts, MCP tools, knowledge services. Same bridge pattern: create storage functions, remove inline SurrealQL
- Wire factory layer — factory.ts, checkpoint.ts, dedup.ts, job-store.ts need SQLite storage bridges
- Run tests —
npm testto find test failures (tests usemem://SurrealDB, need SQLite:memory:equivalent) - End-to-end test — start BMF with
BM_STORAGE_BACKEND=sqlite-lance, observe/recall roundtrip - Run NFCorpus benchmark on wired system — verify recall quality matches benchmark adapter results
- Reimplement reconciliation — entity/temporal reconciliation for
ctl repair - Deprecate SurrealDB — remove deps, surrealdb.ts, storage-surreal.ts backups
Key files
| File | Status | Purpose |
|---|---|---|
src/core/storage/sqlite-lance.ts |
DONE | Core connection management |
src/modules/*/storage-sqlite.ts |
DONE | SQLite implementations (13 files, 8.5K lines) |
src/modules/vector/storage-lance.ts |
DONE | LanceDB vector+FTS implementation |
src/modules/*/storage.ts |
DONE | Bridge files (delegate to SQLite) |
src/modules/*/storage-surreal.ts |
PRESERVED | SurrealDB backups |
benchmarks/ |
DONE | NFCorpus harness, 3 adapters, dataset generator |
docs/thinking/David/l1-reliability/2026-04-13-storage-layer-trial.md |
DONE | Decision document |
Branch state
trial/storage-sqlite-lance— 17 commits ahead of main, all pushedtrial/storage-surrealdb-only— control branch (unchanged)trial/storage-sqlite-pure— comparison branch (unchanged)trial/storage-common— shared benchmark harness