th-memory-mcp 1.2.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/ARCHITECTURE_v2.md +1582 -0
  2. package/README.md +214 -187
  3. package/README.th.md +28 -7
  4. package/dist/core/consolidation-engine.js +87 -0
  5. package/dist/core/context-engine.js +50 -0
  6. package/dist/core/graph-engine.js +67 -0
  7. package/dist/core/lifecycle-engine.js +76 -0
  8. package/dist/core/retrieval-engine.js +40 -0
  9. package/dist/core/temporal-engine.js +73 -0
  10. package/dist/db/index.js +111 -0
  11. package/dist/db/migrations.js +160 -0
  12. package/dist/db/repositories/memories.js +52 -0
  13. package/dist/db.js +3 -0
  14. package/dist/index.js +42 -0
  15. package/dist/lib/embed.js +8 -5
  16. package/dist/memory/conflict-resolver.js +125 -0
  17. package/dist/memory/decay.js +30 -0
  18. package/dist/memory/deduplicator.js +51 -0
  19. package/dist/memory/scorer.js +44 -0
  20. package/dist/memory/source-weights.js +13 -0
  21. package/dist/memory/types.js +41 -0
  22. package/dist/retrieval/fts.js +22 -0
  23. package/dist/retrieval/fusion.js +11 -0
  24. package/dist/retrieval/scorer.js +19 -0
  25. package/dist/retrieval/vector.js +29 -0
  26. package/dist/tools/consolidate.js +63 -0
  27. package/dist/tools/context.js +55 -0
  28. package/dist/tools/export_memory.js +1 -1
  29. package/dist/tools/extract_memories.js +90 -0
  30. package/dist/tools/forget.js +1 -1
  31. package/dist/tools/history.js +1 -1
  32. package/dist/tools/import_memory.js +95 -0
  33. package/dist/tools/lesson.js +1 -1
  34. package/dist/tools/link_memory.js +31 -0
  35. package/dist/tools/memory_stats.js +1 -1
  36. package/dist/tools/merge_memory.js +49 -0
  37. package/dist/tools/profile.js +1 -1
  38. package/dist/tools/recall.js +1 -1
  39. package/dist/tools/recent_interactions.js +1 -1
  40. package/dist/tools/remember.js +1 -1
  41. package/dist/tools/update_memory.js +98 -0
  42. package/package.json +46 -46
  43. package/design.md +0 -308
@@ -0,0 +1,1582 @@
1
+ # th-memory-mcp v2 — Architecture & Implementation Specification
2
+
3
+ **Status:** ✅ Released — `th-memory-mcp v2.0.0` is published (npm + Official MCP Registry + Glama).
4
+ **Baseline:** v1.2.2 → **Current:** v2.0.0
5
+ **Primary goal:** evolve th-memory-mcp from a structured local memory MCP into a durable, temporal, conflict-aware, hybrid-retrieval memory engine for AI agents.
6
+
7
+ > **Audience guide:** End users should read [README.md](README.md) (install, tools, usage). This document is the **canonical architecture & agent-rules spec** for developers and AI coding agents — the single source of truth for structure and behavior. The former `design.md` build log has been folded into §40 Implementation Status.
8
+
9
+ ---
10
+
11
+ ## 0. Executive Decision
12
+
13
+ v2 is a **refactor + controlled expansion**, not a rewrite and not a clone of Mem0, Zep/Graphiti, or Letta.
14
+
15
+ The project must retain these v1 properties:
16
+
17
+ - Local-first and offline by default.
18
+ - SQLite as the primary persistence layer.
19
+ - FTS5 and local semantic search.
20
+ - Thai/English support.
21
+ - Auto-capture and cross-harness compatibility.
22
+ - Secret filtering and safe export.
23
+ - Graceful degradation when memory is unavailable.
24
+ - Small MCP surface and bounded output.
25
+
26
+ v2 adds five core capabilities:
27
+
28
+ 1. Unified memory model.
29
+ 2. Temporal state and supersession.
30
+ 3. Duplicate/conflict resolution.
31
+ 4. Hybrid retrieval with ranking/fusion.
32
+ 5. Context assembly with token budgeting.
33
+
34
+ Optional AI-assisted extraction/consolidation must never make the core memory engine dependent on an external LLM API.
35
+
36
+ ---
37
+
38
+ # 1. Design Principles
39
+
40
+ ## 1.1 Memory is data, not instructions
41
+
42
+ Stored memory must never override the agent's system/developer instructions or become executable instructions merely because it contains imperative text.
43
+
44
+ ## 1.2 Event != memory
45
+
46
+ Raw interactions are evidence/feedstock. Long-term memories are derived, structured records.
47
+
48
+ ```text
49
+ Interaction/Event
50
+
51
+ Capture + filtering
52
+
53
+ Extraction/classification
54
+
55
+ Memory candidate
56
+
57
+ Dedup/conflict resolution
58
+
59
+ Persistent memory
60
+ ```
61
+
62
+ ## 1.3 Current truth and historical truth are both valuable
63
+
64
+ Old memories are not automatically deleted because they became stale. They can remain available for historical queries.
65
+
66
+ ## 1.4 Deterministic-first
67
+
68
+ Core operations must work without an LLM:
69
+
70
+ - persistence
71
+ - FTS search
72
+ - semantic search
73
+ - metadata filtering
74
+ - scoring
75
+ - RRF fusion
76
+ - lifecycle transitions
77
+ - basic duplicate detection
78
+ - basic conflict detection
79
+
80
+ LLM assistance is optional for:
81
+
82
+ - difficult extraction
83
+ - ambiguous conflict resolution
84
+ - consolidation
85
+ - summarization/compression
86
+
87
+ ## 1.5 Context is a projection of memory
88
+
89
+ The database is not the prompt. `get_context` selects a small, relevant, safe projection from persistent memory.
90
+
91
+ ## 1.6 Failure must be non-fatal
92
+
93
+ Memory failures must not crash the host agent. MCP operations should return bounded diagnostic text where appropriate and continue gracefully.
94
+
95
+ ---
96
+
97
+ # 2. High-Level Architecture
98
+
99
+ ```text
100
+ AI AGENT
101
+
102
+ MCP
103
+
104
+ ┌───────▼────────┐
105
+ │ MEMORY API │
106
+ └───────┬────────┘
107
+
108
+ ┌─────────────┼─────────────┐
109
+ │ │ │
110
+ ▼ ▼ ▼
111
+ CAPTURE ENGINE RETRIEVAL LIFECYCLE
112
+ │ ENGINE ENGINE
113
+ │ │ │
114
+ │ ┌──────┼──────┐ │
115
+ │ │ │ │ │
116
+ │ FTS VECTOR GRAPH │
117
+ │ │ │ │ │
118
+ │ └──────┼──────┘ │
119
+ │ │ │
120
+ └─────────────┼─────────────┘
121
+
122
+ MEMORY STORE
123
+ ┌─────────────────────┐
124
+ │ SQLite │
125
+ │ FTS5 │
126
+ │ local vectors │
127
+ │ entities/relations │
128
+ │ temporal metadata │
129
+ └──────────┬──────────┘
130
+
131
+ CONTEXT ENGINE
132
+
133
+
134
+ AI AGENT
135
+ ```
136
+
137
+ ---
138
+
139
+ # 3. Memory Taxonomy
140
+
141
+ Canonical memory types:
142
+
143
+ ```text
144
+ FACT
145
+ PREFERENCE
146
+ GOAL
147
+ DECISION
148
+ CONSTRAINT
149
+ LESSON
150
+ PROCEDURE
151
+ EPISODE
152
+ RELATION
153
+ PROFILE
154
+ ```
155
+
156
+ ### Semantics
157
+
158
+ | Type | Purpose |
159
+ |---|---|
160
+ | FACT | durable factual information |
161
+ | PREFERENCE | user/project preference |
162
+ | GOAL | desired future outcome |
163
+ | DECISION | chosen approach and rationale |
164
+ | CONSTRAINT | hard requirement or prohibition |
165
+ | LESSON | correction-derived knowledge |
166
+ | PROCEDURE | reusable method/workflow |
167
+ | EPISODE | meaningful historical event |
168
+ | RELATION | entity relationship information |
169
+ | PROFILE | high-value compact user/project summary |
170
+
171
+ Types must be extensible internally, but these ten are the stable v2 vocabulary.
172
+
173
+ ---
174
+
175
+ # 4. Memory Lifecycle
176
+
177
+ Every memory has a lifecycle state:
178
+
179
+ ```text
180
+ NEW → ACTIVE
181
+ ACTIVE → REINFORCED → ACTIVE
182
+ ACTIVE → STALE
183
+ ACTIVE → SUPERSEDED
184
+ STALE → ARCHIVED
185
+ SUPERSEDED → ARCHIVED
186
+ ACTIVE → DELETED
187
+ ARCHIVED → DELETED
188
+ ```
189
+
190
+ ### Rules
191
+
192
+ - `ACTIVE`: eligible for normal retrieval.
193
+ - `STALE`: low priority; eligible when historical context is useful.
194
+ - `SUPERSEDED`: replaced by another memory; normally excluded from current-context retrieval.
195
+ - `ARCHIVED`: retained but excluded from default retrieval.
196
+ - `DELETED`: logically deleted unless hard-delete is explicitly requested.
197
+
198
+ A superseded memory should retain a pointer to the replacement.
199
+
200
+ ---
201
+
202
+ # 5. Temporal Model
203
+
204
+ Each memory may have both record time and validity time:
205
+
206
+ ```text
207
+ created_at
208
+ updated_at
209
+ last_accessed_at
210
+ valid_from
211
+ valid_until
212
+ ```
213
+
214
+ `valid_until = NULL` means currently valid unless lifecycle state says otherwise.
215
+
216
+ Temporal questions must be supported conceptually:
217
+
218
+ - What is true now?
219
+ - What was true at time T?
220
+ - What changed?
221
+ - Which memory superseded this one?
222
+
223
+ Do not physically delete historical truth merely because it is no longer current.
224
+
225
+ ---
226
+
227
+ # 6. Database Schema
228
+
229
+ The following is the logical v2 schema. Migration SQL may implement equivalent SQLite details, but semantics must remain compatible.
230
+
231
+ ## 6.1 `memories`
232
+
233
+ ```sql
234
+ CREATE TABLE memories (
235
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
236
+ type TEXT NOT NULL,
237
+ content TEXT NOT NULL,
238
+ summary TEXT,
239
+ status TEXT NOT NULL DEFAULT 'active',
240
+ source TEXT NOT NULL DEFAULT 'explicit',
241
+ confidence REAL NOT NULL DEFAULT 0.5,
242
+ importance REAL NOT NULL DEFAULT 0.5,
243
+ salience REAL NOT NULL DEFAULT 0.5,
244
+ project_id TEXT,
245
+ session_id TEXT,
246
+ created_at TEXT NOT NULL,
247
+ updated_at TEXT NOT NULL,
248
+ last_accessed_at TEXT,
249
+ access_count INTEGER NOT NULL DEFAULT 0,
250
+ valid_from TEXT,
251
+ valid_until TEXT,
252
+ supersedes_id INTEGER,
253
+ metadata TEXT,
254
+ FOREIGN KEY (supersedes_id) REFERENCES memories(id)
255
+ );
256
+ ```
257
+
258
+ ### Required indexes
259
+
260
+ ```sql
261
+ CREATE INDEX idx_memories_type_status ON memories(type, status);
262
+ CREATE INDEX idx_memories_project_status ON memories(project_id, status);
263
+ CREATE INDEX idx_memories_updated ON memories(updated_at);
264
+ CREATE INDEX idx_memories_validity ON memories(valid_from, valid_until);
265
+ CREATE INDEX idx_memories_supersedes ON memories(supersedes_id);
266
+ ```
267
+
268
+ ## 6.2 `interactions`
269
+
270
+ Retain raw behavior/event storage:
271
+
272
+ ```sql
273
+ CREATE TABLE interactions (
274
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
275
+ ts TEXT NOT NULL,
276
+ session_id TEXT,
277
+ kind TEXT NOT NULL,
278
+ content TEXT NOT NULL,
279
+ meta TEXT
280
+ );
281
+ ```
282
+
283
+ Interactions are not automatically long-term memories.
284
+
285
+ ## 6.3 `entities`
286
+
287
+ ```sql
288
+ CREATE TABLE entities (
289
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
290
+ name TEXT NOT NULL,
291
+ canonical_name TEXT NOT NULL,
292
+ type TEXT,
293
+ metadata TEXT
294
+ );
295
+ CREATE UNIQUE INDEX idx_entities_canonical ON entities(canonical_name);
296
+ ```
297
+
298
+ ## 6.4 `relations`
299
+
300
+ ```sql
301
+ CREATE TABLE relations (
302
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
303
+ source_entity_id INTEGER NOT NULL,
304
+ relation TEXT NOT NULL,
305
+ target_entity_id INTEGER NOT NULL,
306
+ confidence REAL NOT NULL DEFAULT 0.5,
307
+ valid_from TEXT,
308
+ valid_until TEXT,
309
+ source_memory_id INTEGER,
310
+ metadata TEXT,
311
+ FOREIGN KEY (source_entity_id) REFERENCES entities(id),
312
+ FOREIGN KEY (target_entity_id) REFERENCES entities(id),
313
+ FOREIGN KEY (source_memory_id) REFERENCES memories(id)
314
+ );
315
+ ```
316
+
317
+ ## 6.5 `memory_links`
318
+
319
+ ```sql
320
+ CREATE TABLE memory_links (
321
+ source_memory_id INTEGER NOT NULL,
322
+ relation TEXT NOT NULL,
323
+ target_memory_id INTEGER NOT NULL,
324
+ confidence REAL NOT NULL DEFAULT 0.5,
325
+ created_at TEXT NOT NULL,
326
+ PRIMARY KEY (source_memory_id, relation, target_memory_id),
327
+ FOREIGN KEY (source_memory_id) REFERENCES memories(id),
328
+ FOREIGN KEY (target_memory_id) REFERENCES memories(id)
329
+ );
330
+ ```
331
+
332
+ Supported link relations:
333
+
334
+ ```text
335
+ supports
336
+ contradicts
337
+ supersedes
338
+ derived_from
339
+ related_to
340
+ caused_by
341
+ depends_on
342
+ ```
343
+
344
+ ## 6.6 `profile`
345
+
346
+ Retain compact profile sections for backward compatibility and fast injection:
347
+
348
+ ```sql
349
+ CREATE TABLE profile (
350
+ section TEXT PRIMARY KEY,
351
+ content TEXT NOT NULL,
352
+ updated_at TEXT NOT NULL
353
+ );
354
+ ```
355
+
356
+ In v2, profile is a projection/cache of important memories, not the canonical source of truth.
357
+
358
+ ---
359
+
360
+ # 7. Search Indexes
361
+
362
+ FTS5 remains mandatory.
363
+
364
+ Logical indexed fields:
365
+
366
+ ```text
367
+ memory id
368
+ memory type
369
+ content
370
+ summary
371
+ project_id
372
+ ```
373
+
374
+ The implementation may use a maintained FTS5 virtual table or separate indexes, but every mutation of searchable memory must keep indexes synchronized transactionally where possible.
375
+
376
+ Local semantic search remains supported. The implementation must preserve the dependency-light/offline property of v1.
377
+
378
+ ---
379
+
380
+ # 8. Memory Source Model
381
+
382
+ Canonical source values:
383
+
384
+ ```text
385
+ explicit
386
+ corrected
387
+ inferred
388
+ captured
389
+ consolidated
390
+ imported
391
+ system
392
+ ```
393
+
394
+ Recommended source weights for confidence calculation:
395
+
396
+ | Source | Weight |
397
+ |---|---:|
398
+ | explicit | 1.00 |
399
+ | corrected | 0.95 |
400
+ | captured | 0.30 |
401
+ | inferred | 0.50 |
402
+ | consolidated | 0.75 |
403
+ | imported | 0.70 |
404
+ | system | 0.80 |
405
+
406
+ These are defaults, not immutable constants.
407
+
408
+ ---
409
+
410
+ # 9. Confidence, Importance, Salience
411
+
412
+ All three values are normalized to `[0,1]`.
413
+
414
+ ## 9.1 Confidence
415
+
416
+ Confidence reflects how trustworthy the memory is.
417
+
418
+ Recommended conceptual model:
419
+
420
+ ```text
421
+ confidence = f(source_weight,
422
+ confirmation_count,
423
+ consistency,
424
+ conflict_penalty)
425
+ ```
426
+
427
+ Do not blindly increase confidence forever from duplicate saves. Repeated identical events should have diminishing returns.
428
+
429
+ ## 9.2 Importance
430
+
431
+ Importance is durable significance. It should not decay merely because the memory is old.
432
+
433
+ Examples:
434
+
435
+ - hard project constraint: high
436
+ - architectural decision: high
437
+ - temporary debugging detail: low
438
+
439
+ ## 9.3 Salience
440
+
441
+ Salience determines usefulness for a particular retrieval/context operation.
442
+
443
+ Recommended baseline:
444
+
445
+ ```text
446
+ salience =
447
+ 0.30 * semantic_relevance +
448
+ 0.20 * importance +
449
+ 0.15 * confidence +
450
+ 0.15 * recency +
451
+ 0.10 * access_frequency +
452
+ 0.10 * project_relevance
453
+ ```
454
+
455
+ Weights must be configurable and benchmarked.
456
+
457
+ ---
458
+
459
+ # 10. Recency and Decay
460
+
461
+ Use a bounded exponential recency factor:
462
+
463
+ ```text
464
+ recency = exp(-lambda * age_days)
465
+ ```
466
+
467
+ Decay policy must depend on memory type.
468
+
469
+ | Type | Default decay |
470
+ |---|---|
471
+ | CONSTRAINT | very low |
472
+ | DECISION | low |
473
+ | LESSON | low |
474
+ | PREFERENCE | low |
475
+ | FACT | low/medium |
476
+ | GOAL | medium |
477
+ | PROCEDURE | low/medium |
478
+ | EPISODE | medium |
479
+ | RELATION | low/medium |
480
+ | PROFILE | derived |
481
+
482
+ These are policy classes, not fixed numeric constants.
483
+
484
+ ---
485
+
486
+ # 11. Deduplication
487
+
488
+ Every `remember` candidate must pass duplicate detection before insertion.
489
+
490
+ Pipeline:
491
+
492
+ ```text
493
+ normalize
494
+
495
+ exact match
496
+
497
+ canonical/key match
498
+
499
+ FTS similarity
500
+
501
+ semantic similarity (if available)
502
+
503
+ DUPLICATE / UPDATE / DISTINCT
504
+ ```
505
+
506
+ Duplicate detection must avoid merging memories that are merely similar but semantically different.
507
+
508
+ ---
509
+
510
+ # 12. Conflict Resolution
511
+
512
+ This is a first-class v2 subsystem.
513
+
514
+ When a new candidate arrives:
515
+
516
+ ```text
517
+ candidate
518
+
519
+ find related active memories
520
+
521
+ classify relationship
522
+ ├── duplicate
523
+ ├── update
524
+ ├── contradiction
525
+ └── unrelated
526
+ ```
527
+
528
+ ### Update/supersession
529
+
530
+ For a direct change:
531
+
532
+ ```text
533
+ old memory: status = superseded
534
+ new memory: status = active
535
+ new memory.supersedes_id = old.id
536
+ ```
537
+
538
+ Create a `supersedes` memory link when useful.
539
+
540
+ ### Ambiguous conflict
541
+
542
+ If deterministic rules cannot safely decide, preserve both records and mark the relationship `contradicts`; do not silently destroy information.
543
+
544
+ Optional AI-assisted resolution may later select the current truth based on explicit user evidence.
545
+
546
+ ---
547
+
548
+ # 13. Hybrid Retrieval
549
+
550
+ `recall` and `get_context` must use more than one retrieval signal.
551
+
552
+ ```text
553
+ QUERY
554
+
555
+ ├── FTS5 keyword retrieval
556
+
557
+ ├── local semantic retrieval
558
+
559
+ ├── metadata/scope filtering
560
+
561
+ └── optional graph expansion
562
+
563
+
564
+ Candidate pool
565
+
566
+
567
+ RRF fusion
568
+
569
+
570
+ Scoring/reranking
571
+
572
+
573
+ Conflict/status filtering
574
+
575
+
576
+ Top K
577
+ ```
578
+
579
+ ## 13.1 Reciprocal Rank Fusion
580
+
581
+ Use RRF rather than directly mixing incompatible raw search scores:
582
+
583
+ ```text
584
+ RRF(m) = Σ 1 / (k + rank_i(m))
585
+ ```
586
+
587
+ Then apply memory-specific factors:
588
+
589
+ ```text
590
+ final_score =
591
+ RRF * confidence * importance_factor * recency_factor * scope_factor
592
+ ```
593
+
594
+ The exact formula must be benchmarked.
595
+
596
+ ---
597
+
598
+ # 14. Graph Retrieval
599
+
600
+ Graph is an augmentation, not the sole retrieval mechanism.
601
+
602
+ Default traversal should be shallow and bounded:
603
+
604
+ ```text
605
+ seed entities/memories
606
+
607
+ 1-hop related entities
608
+
609
+ related memories
610
+ ```
611
+
612
+ Do not perform unbounded graph traversal during normal `recall`.
613
+
614
+ Graph boost should improve relationship queries without allowing weak graph edges to dominate strong direct evidence.
615
+
616
+ ---
617
+
618
+ # 15. Context Engine
619
+
620
+ Introduce a first-class `get_context` operation.
621
+
622
+ Input concept:
623
+
624
+ ```json
625
+ {
626
+ "query": "current task",
627
+ "project": "optional-project-id",
628
+ "limit": 12,
629
+ "token_budget": 1500,
630
+ "include_history": false
631
+ }
632
+ ```
633
+
634
+ Pipeline:
635
+
636
+ ```text
637
+ query
638
+
639
+ retrieve candidate memories
640
+
641
+ filter stale/superseded records
642
+
643
+ deduplicate
644
+
645
+ resolve conflicts
646
+
647
+ rank
648
+
649
+ fit token budget
650
+
651
+ assemble structured context
652
+ ```
653
+
654
+ Output should be concise and machine-readable enough for agents to consume.
655
+
656
+ Recommended sections:
657
+
658
+ ```text
659
+ Current Profile
660
+ Relevant Preferences
661
+ Constraints
662
+ Decisions
663
+ Lessons
664
+ Relevant Facts
665
+ Historical Context (only when requested/useful)
666
+ ```
667
+
668
+ Default context should prioritize current project + active user constraints.
669
+
670
+ ---
671
+
672
+ # 16. Persistent vs Archival Memory
673
+
674
+ Two logical tiers:
675
+
676
+ ## Tier A — Persistent/Pinned
677
+
678
+ Small, high-value context that may be injected without retrieval:
679
+
680
+ - identity/profile essentials
681
+ - active goals
682
+ - critical constraints
683
+ - current project decisions
684
+
685
+ Target size: approximately 500–1500 tokens depending on host/context budget.
686
+
687
+ ## Tier B — Archival
688
+
689
+ Searchable persistent memory:
690
+
691
+ - facts
692
+ - episodes
693
+ - lessons
694
+ - procedures
695
+ - historical decisions
696
+ - relations
697
+
698
+ Tier A is a projection/cache; Tier B remains the source of truth.
699
+
700
+ ---
701
+
702
+ # 17. MCP Tool Surface
703
+
704
+ Do not expand to dozens of tools. v2.1.0 ships **16 tools** (the original spec targeted 14; the extra 2 are `consolidate` and `extract_memories`, which extend the v2 engine).
705
+
706
+ ## Shipped (16 tools)
707
+
708
+ ### Core / compatibility (carried from v1)
709
+ 1. `remember` — store a memory using the unified model (type + metadata)
710
+ 2. `recall` — hybrid FTS + semantic search (v1 behavior preserved)
711
+ 3. `forget` — soft delete by default
712
+ 4. `get_profile` — compact profile projection/cache
713
+ 5. `search_history` — search raw interactions
714
+ 6. `get_recent_interactions` — recent raw events
715
+ 7. `memory_stats` — lifecycle/retrieval/storage metrics
716
+ 8. `export_memory` — safe export confined to the allowed directory
717
+ 9. `save_lesson` — compatibility alias/wrapper over `remember(type=LESSON)`
718
+
719
+ ### v2 engine tools
720
+ 10. `get_context` — token-budgeted context assembly (preferred agent-facing retrieval)
721
+ 11. `consolidate` — cluster related memories + optional derived memory
722
+ 12. `link_memory` — typed relationship between two memories in the graph
723
+ 13. `merge_memory` — merge a duplicate into a canonical memory (source superseded, provenance in `metadata.merged_from`)
724
+ 14. `update_memory` — update mutable fields in place, or create a superseding memory when `content` changes
725
+ 15. `import_memory` — import memories from JSON (validates type, dedupes, dry-run by default)
726
+ 16. `extract_memories` — scan recent interactions for memory-intent and propose/create memories (deterministic, no LLM; dry-run by default)
727
+
728
+ All 16 are documented in README.md. The four tools originally marked "deferred" in this spec (`update_memory`, `merge_memory`, `link_memory`, `import_memory`) plus `extract_memories` were implemented in v2.1.0.
729
+
730
+ ---
731
+
732
+ # 18. Tool Contracts
733
+
734
+ ## `remember`
735
+
736
+ ```text
737
+ content: string
738
+ type?: MemoryType
739
+ importance?: 0..1
740
+ confidence?: 0..1
741
+ project_id?: string
742
+ session_id?: string
743
+ source?: SourceType
744
+ valid_from?: ISO timestamp
745
+ valid_until?: ISO timestamp
746
+ metadata?: object
747
+ ```
748
+
749
+ Returns:
750
+
751
+ ```text
752
+ created | reinforced | updated | superseded | duplicate | conflict
753
+ memory id
754
+ short summary
755
+ ```
756
+
757
+ ## `recall`
758
+
759
+ ```text
760
+ query: string
761
+ limit?: 1..50
762
+ project_id?: string
763
+ include_archived?: boolean
764
+ include_history?: boolean
765
+ ```
766
+
767
+ Uses hybrid retrieval.
768
+
769
+ ## `get_context`
770
+
771
+ ```text
772
+ query?: string
773
+ project_id?: string
774
+ token_budget?: integer
775
+ limit?: integer
776
+ include_history?: boolean
777
+ ```
778
+
779
+ This should be the preferred agent-facing retrieval operation for complex tasks.
780
+
781
+ ## `update_memory`
782
+
783
+ Updates mutable fields without silently changing identity/history.
784
+
785
+ Changes to factual content that represent a new truth should create a superseding memory where appropriate. (Implemented in v2.1.0 — see `src/tools/update_memory.ts`.)
786
+
787
+ ## `merge_memory`
788
+
789
+ Combines duplicate/near-duplicate memories while preserving provenance and source IDs. (Implemented in v2.1.0 — see `src/tools/merge_memory.ts`.)
790
+
791
+ ## `link_memory`
792
+
793
+ Creates a typed relationship between memories. (Implemented in v2.1.0 — see `src/tools/link_memory.ts`.)
794
+
795
+ ## `extract_memories`
796
+
797
+ Scans recent captured interactions for memory-intent phrases and proposes memory candidates. Deterministic (no LLM); dry-run by default, `apply=true` creates them (source=`captured`). Implemented in v2.1.0 — see `src/tools/extract_memories.ts`.
798
+
799
+ ## `forget`
800
+
801
+ Default behavior is soft delete. Hard delete must be explicit and documented.
802
+
803
+ ## `consolidate_memory`
804
+
805
+ Groups related memories and creates compact derived memories without automatically deleting source evidence.
806
+
807
+ ## `memory_stats`
808
+
809
+ Expose lifecycle, retrieval, quality, and storage metrics.
810
+
811
+ ## `export_memory` / `import_memory`
812
+
813
+ Must preserve IDs only when safe. Imports must validate schema/version and never overwrite active memory blindly.
814
+
815
+ ---
816
+
817
+ # 19. Auto-Capture v2
818
+
819
+ Retain the existing plugin architecture but make capture a pipeline.
820
+
821
+ ```text
822
+ Host event
823
+
824
+ Secret/PII filtering
825
+
826
+ Noise filter
827
+
828
+ Deduplication
829
+
830
+ Interaction event storage
831
+
832
+ Optional extraction
833
+
834
+ Memory candidate
835
+ ```
836
+
837
+ Capture must never turn every user prompt into long-term memory.
838
+
839
+ ### Existing v1 safeguards to retain
840
+
841
+ - secret filtering
842
+ - event deduplication
843
+ - truncation
844
+ - try/catch around every write
845
+ - shared `MEMORY_DB_PATH`
846
+ - WAL
847
+
848
+ ---
849
+
850
+ # 20. Security Requirements
851
+
852
+ Required:
853
+
854
+ - secret filtering before persistence
855
+ - safe export filenames
856
+ - export confined to allowed export directory
857
+ - metadata sanitization
858
+ - memory treated as untrusted data
859
+ - no memory-generated command execution
860
+ - no memory-generated system/developer instruction override
861
+ - no remote service required by default
862
+
863
+ Sensitive data must not be reintroduced merely because it was previously stored. Existing v1 filtering rules are the minimum baseline, not the maximum security boundary.
864
+
865
+ ---
866
+
867
+ # 21. Graceful Degradation
868
+
869
+ If any subsystem fails:
870
+
871
+ ```text
872
+ Graph unavailable → use FTS/vector
873
+ Vector unavailable → use FTS
874
+ FTS unavailable → use basic SQL filtering
875
+ Profile unavailable → continue without profile
876
+ DB unavailable → return bounded error and allow agent to continue
877
+ ```
878
+
879
+ No optional subsystem should become a single point of failure for the MCP server.
880
+
881
+ ---
882
+
883
+ # 22. Source Tree (as-built in v2.0.0)
884
+
885
+ ```text
886
+ src/
887
+ ├── index.ts # MCP server: registers 11 tools
888
+ ├── db/
889
+ │ ├── index.ts # db singleton (better-sqlite3, WAL) + runMigrations
890
+ │ ├── migrations.ts # ordered MIGRATIONS array (TS modules, idempotent)
891
+ │ └── repositories/
892
+ │ └── memories.ts # CRUD + searchMemories (delegates to hybrid retrieval)
893
+ ├── memory/
894
+ │ ├── types.ts # MemoryType, SourceType, LifecycleState, Scope, MemoryRecord
895
+ │ ├── decay.ts # recencyFactor + per-type DECAY_LAMBDA policy classes
896
+ │ ├── source-weights.ts # SOURCE_WEIGHTS
897
+ │ ├── scorer.ts # computeSalience / computeConfidence
898
+ │ ├── deduplicator.ts # normalize / exact / similar / deduplicate
899
+ │ └── conflict-resolver.ts # isContradiction / classifyRelationship / resolveConflict
900
+ ├── retrieval/
901
+ │ ├── fts.ts # FTS5 search
902
+ │ ├── vector.ts # cosine over embeddings
903
+ │ ├── fusion.ts # rrfFuse (k=60)
904
+ │ └── scorer.ts # finalScore (RRF × confidence × importance × recency × scope)
905
+ ├── core/
906
+ │ ├── lifecycle-engine.ts # transitions, reinforce, supersede, archive, softDelete
907
+ │ ├── temporal-engine.ts # validity intervals, point-in-time, supersession chains
908
+ │ ├── retrieval-engine.ts # retrieve(): FTS+vector → RRF → score → filter → topK
909
+ │ ├── graph-engine.ts # entities/relations, linkMemories, bounded traverse
910
+ │ ├── context-engine.ts # getContext(): retrieve → graph expand → temporal filter → budget
911
+ │ └── consolidation-engine.ts # clusterMemories, createDerivedMemory, getProvenance
912
+ ├── tools/
913
+ │ ├── context.ts # get_context tool
914
+ │ └── consolidate.ts # consolidate tool
915
+ ├── lib/
916
+ │ └── embed.ts # hashing-trick embed + DataView serialize/deserialize (fixed in v2)
917
+ └── plugin/
918
+ └── learning-capture.ts # Bun auto-capture plugin (OpenCode)
919
+ scripts/
920
+ └── claude-capture.mjs # Claude Code hook capture
921
+ test/
922
+ └── *.test.mjs # 12 suites (capture, distill, lifecycle, temporal, conflict,
923
+ # retrieval, graph, context, consolidation, benchmark, security, smoke)
924
+ ```
925
+
926
+ Compatibility wrappers keep the old `remember`/`recall`/etc. tool names; v2 internals live under `core/`, `memory/`, `retrieval/`.
927
+
928
+ ---
929
+
930
+ # 23. Migration Strategy v1 → v2
931
+
932
+ Migration must be non-destructive.
933
+
934
+ ## Phase M0 — Backup
935
+
936
+ Before any schema migration:
937
+
938
+ 1. Verify DB exists.
939
+ 2. Create timestamped backup.
940
+ 3. Verify SQLite integrity.
941
+ 4. Record current schema version.
942
+
943
+ ## Phase M1 — Introduce migration metadata
944
+
945
+ Create:
946
+
947
+ ```sql
948
+ CREATE TABLE schema_meta (
949
+ key TEXT PRIMARY KEY,
950
+ value TEXT NOT NULL
951
+ );
952
+ ```
953
+
954
+ Store `schema_version`.
955
+
956
+ ## Phase M2 — Preserve old tables
957
+
958
+ Do not immediately delete:
959
+
960
+ ```text
961
+ preferences
962
+ lessons
963
+ interactions
964
+ profile
965
+ ```
966
+
967
+ ## Phase M3 — Convert
968
+
969
+ Map:
970
+
971
+ ```text
972
+ preferences → memories(type=PREFERENCE)
973
+ lessons → memories(type=LESSON)
974
+ profile → profile projection/cache
975
+ interactions → interactions unchanged
976
+ ```
977
+
978
+ Preserve original IDs in metadata when IDs cannot be retained directly.
979
+
980
+ ## Phase M4 — Rebuild indexes
981
+
982
+ Recreate FTS and semantic indexes from canonical v2 memory records.
983
+
984
+ ## Phase M5 — Validate
985
+
986
+ Checks:
987
+
988
+ - row counts
989
+ - content hashes/sample comparisons
990
+ - FTS availability
991
+ - memory type mapping
992
+ - profile availability
993
+ - export availability
994
+
995
+ Only after validation may v2 consider old tables deprecated.
996
+
997
+ ---
998
+
999
+ # 24. Migration Files (as-built)
1000
+
1001
+ Migrations are **TypeScript modules** in `src/db/migrations.ts`, not `.sql` files. Each entry is an idempotent `up(db)` (`CREATE TABLE IF NOT EXISTS`) tracked in `schema_meta`. This avoids `.sql` file-copy issues under `tsc` while keeping deterministic order. The logical schema in §6 is the contract; the TS implementation realizes it.
1002
+
1003
+ Ordered migrations applied in v2.0.0:
1004
+
1005
+ 1. `schema_meta` table
1006
+ 2. `memories` + indexes
1007
+ 3. `entities` / `relations`
1008
+ 4. `memory_links`
1009
+ 5. v1 backfill (`preferences → PREFERENCE`, `lessons → LESSON`, sync FTS + embeddings; guarded by `v1_backfilled` flag, runs once)
1010
+
1011
+ The spec allowed implementation differences ("Exact SQL can differ if implementation constraints require it"); the TS approach is the chosen realization.
1012
+
1013
+ ---
1014
+
1015
+ # 25. Testing Strategy
1016
+
1017
+ Tests must be layered.
1018
+
1019
+ ## Unit tests
1020
+
1021
+ - classification
1022
+ - secret filtering
1023
+ - normalization
1024
+ - duplicate detection
1025
+ - conflict classification
1026
+ - confidence
1027
+ - decay
1028
+ - scoring
1029
+ - RRF
1030
+ - token budgeting
1031
+ - filename sanitization
1032
+
1033
+ ## Integration tests
1034
+
1035
+ - SQLite migration
1036
+ - FTS sync
1037
+ - semantic retrieval
1038
+ - graph relations
1039
+ - lifecycle transitions
1040
+ - import/export
1041
+
1042
+ ## MCP E2E
1043
+
1044
+ Run real JSON-RPC against the built server.
1045
+
1046
+ ## Plugin tests
1047
+
1048
+ - prompt capture
1049
+ - tool event capture
1050
+ - dedupe
1051
+ - secret filter
1052
+ - graceful DB failure
1053
+ - profile/context injection
1054
+
1055
+ ---
1056
+
1057
+ # 26. Retrieval Benchmark
1058
+
1059
+ Create:
1060
+
1061
+ ```text
1062
+ benchmark/
1063
+ ├── datasets/
1064
+ ├── retrieval/
1065
+ ├── conflict/
1066
+ ├── temporal/
1067
+ ├── lifecycle/
1068
+ └── performance/
1069
+ ```
1070
+
1071
+ Baseline dataset should contain:
1072
+
1073
+ - at least 500 memories
1074
+ - at least 100 distractors
1075
+ - at least 100 duplicates
1076
+ - at least 100 contradictions/updates
1077
+ - at least 100 temporal changes
1078
+
1079
+ Measure:
1080
+
1081
+ ```text
1082
+ Recall@1
1083
+ Recall@5
1084
+ Recall@10
1085
+ Precision@5
1086
+ MRR
1087
+ NDCG
1088
+ ```
1089
+
1090
+ Initial engineering targets:
1091
+
1092
+ ```text
1093
+ Recall@5 >= 0.90
1094
+ Precision@5 >= 0.85
1095
+ MRR >= 0.85
1096
+ ```
1097
+
1098
+ Targets are project acceptance goals, not claims about competitor performance.
1099
+
1100
+ ---
1101
+
1102
+ # 27. Conflict Benchmark
1103
+
1104
+ Target:
1105
+
1106
+ ```text
1107
+ >= 95% correct classification/resolution
1108
+ ```
1109
+
1110
+ Test cases must include:
1111
+
1112
+ - exact duplicate
1113
+ - paraphrase duplicate
1114
+ - preference update
1115
+ - direct contradiction
1116
+ - temporary exception
1117
+ - two valid but different scoped memories
1118
+ - ambiguous conflict
1119
+
1120
+ Ambiguous cases must prefer preservation over destructive guessing.
1121
+
1122
+ ---
1123
+
1124
+ # 28. Temporal Benchmark
1125
+
1126
+ Queries must test:
1127
+
1128
+ ```text
1129
+ current truth
1130
+ historical truth
1131
+ change detection
1132
+ supersession chain
1133
+ ```
1134
+
1135
+ No stale record may override an active current record in default current-context retrieval.
1136
+
1137
+ ---
1138
+
1139
+ # 29. Performance Targets
1140
+
1141
+ On a normal local development machine, initial targets are:
1142
+
1143
+ | Operation | Target |
1144
+ |---|---:|
1145
+ | remember | <20 ms typical |
1146
+ | recall | <50 ms typical |
1147
+ | get_context | <100 ms typical |
1148
+ | get_profile | <20 ms typical |
1149
+ | search_history | <30 ms typical |
1150
+
1151
+ These are engineering targets, not guaranteed SLAs.
1152
+
1153
+ Benchmark both cold-cache and warm-cache behavior where practical.
1154
+
1155
+ ---
1156
+
1157
+ # 30. Token Efficiency
1158
+
1159
+ Every retrieval operation must have a bounded output.
1160
+
1161
+ `get_context` must support an explicit token/character budget.
1162
+
1163
+ Do not return all matching memories merely because they match.
1164
+
1165
+ Target behavior:
1166
+
1167
+ ```text
1168
+ candidate pool: 50
1169
+
1170
+ rank: 20
1171
+
1172
+ filter: 12
1173
+
1174
+ budget: 5–15 useful memories
1175
+
1176
+ compact context
1177
+ ```
1178
+
1179
+ ---
1180
+
1181
+ # 31. Consolidation
1182
+
1183
+ Consolidation creates higher-level semantic memories from clusters of related evidence.
1184
+
1185
+ Example:
1186
+
1187
+ ```text
1188
+ User prefers TypeScript.
1189
+ User chooses TypeScript for projects.
1190
+ User corrected code examples from Python to TypeScript.
1191
+ ```
1192
+
1193
+ Can produce:
1194
+
1195
+ ```text
1196
+ User prefers TypeScript for software projects.
1197
+ ```
1198
+
1199
+ The derived memory must retain provenance:
1200
+
1201
+ ```text
1202
+ derived_from → source memories
1203
+ ```
1204
+
1205
+ Source evidence must not be deleted automatically.
1206
+
1207
+ ---
1208
+
1209
+ # 32. Decision Memory
1210
+
1211
+ `DECISION` should support optional rationale and alternatives in metadata.
1212
+
1213
+ Example:
1214
+
1215
+ ```json
1216
+ {
1217
+ "type": "DECISION",
1218
+ "content": "Use SQLite for local persistence",
1219
+ "metadata": {
1220
+ "reason": [
1221
+ "local-first",
1222
+ "simple deployment",
1223
+ "sufficient performance"
1224
+ ],
1225
+ "alternatives": ["PostgreSQL", "Neo4j"]
1226
+ }
1227
+ }
1228
+ ```
1229
+
1230
+ This prevents agents from repeatedly reopening already-settled architecture decisions.
1231
+
1232
+ ---
1233
+
1234
+ # 33. Scope Resolution
1235
+
1236
+ Supported scope hierarchy:
1237
+
1238
+ ```text
1239
+ GLOBAL
1240
+
1241
+ USER
1242
+
1243
+ PROJECT
1244
+
1245
+ SESSION
1246
+ ```
1247
+
1248
+ For current project queries, prefer:
1249
+
1250
+ ```text
1251
+ PROJECT > USER > GLOBAL > ARCHIVED
1252
+ ```
1253
+
1254
+ Session-specific temporary information should not silently become global memory.
1255
+
1256
+ ---
1257
+
1258
+ # 34. Compatibility Requirements
1259
+
1260
+ v2 must provide a migration/compatibility period where old workflows continue to work.
1261
+
1262
+ Minimum compatibility:
1263
+
1264
+ - existing `remember` usage
1265
+ - existing `recall` usage
1266
+ - existing `get_profile`
1267
+ - existing `save_lesson`
1268
+ - existing `search_history`
1269
+ - existing `forget`
1270
+ - existing `memory_stats`
1271
+ - existing `get_recent_interactions`
1272
+ - existing `export_memory`
1273
+ - existing OpenCode plugin DB path behavior
1274
+
1275
+ Where behavior changes, document it explicitly in `MIGRATION_v2.md`.
1276
+
1277
+ ---
1278
+
1279
+ # 35. Implementation Phases
1280
+
1281
+ ## Phase 0 — Freeze v1
1282
+
1283
+ - tag v1.2.2
1284
+ - backup database
1285
+ - record baseline benchmarks
1286
+ - do not modify production behavior
1287
+
1288
+ ## Phase 1 — Core abstraction
1289
+
1290
+ - repository layer
1291
+ - unified memory type
1292
+ - schema metadata
1293
+ - migration engine
1294
+ - v1 compatibility wrappers
1295
+
1296
+ ## Phase 2 — Lifecycle
1297
+
1298
+ - status
1299
+ - confidence
1300
+ - importance
1301
+ - salience
1302
+ - access tracking
1303
+ - decay
1304
+ - archive
1305
+ - supersession
1306
+
1307
+ ## Phase 3 — Temporal
1308
+
1309
+ - validity intervals
1310
+ - historical retrieval
1311
+ - change/supersession chains
1312
+
1313
+ ## Phase 4 — Conflict
1314
+
1315
+ - normalization
1316
+ - duplicate detection
1317
+ - contradiction detection
1318
+ - update/supersession
1319
+ - merge
1320
+
1321
+ ## Phase 5 — Retrieval
1322
+
1323
+ - FTS adapter
1324
+ - vector adapter
1325
+ - RRF
1326
+ - scoring
1327
+ - reranking
1328
+
1329
+ ## Phase 6 — Graph
1330
+
1331
+ - entities
1332
+ - relations
1333
+ - memory links
1334
+ - bounded traversal
1335
+ - graph boost
1336
+
1337
+ ## Phase 7 — Context
1338
+
1339
+ - `get_context`
1340
+ - token budgeting
1341
+ - context assembler
1342
+ - persistent/archival projection
1343
+
1344
+ ## Phase 8 — Consolidation
1345
+
1346
+ - clustering
1347
+ - derived memories
1348
+ - provenance
1349
+ - optional AI-assisted summarization
1350
+
1351
+ ## Phase 9 — Benchmark/security
1352
+
1353
+ - benchmark suite
1354
+ - migration tests
1355
+ - security tests
1356
+ - performance tests
1357
+
1358
+ ## Phase 10 — v2 release
1359
+
1360
+ - v2 documentation
1361
+ - migration guide
1362
+ - changelog
1363
+ - package version 2.0.0
1364
+
1365
+ ---
1366
+
1367
+ # 36. AI Coding Agent Rules
1368
+
1369
+ This section is normative.
1370
+
1371
+ ## MUST
1372
+
1373
+ - Read this document before modifying architecture.
1374
+ - Inspect current source before changing behavior.
1375
+ - Preserve v1 functionality unless explicitly superseded.
1376
+ - Add migrations instead of destructive schema replacement.
1377
+ - Add tests with every new subsystem.
1378
+ - Keep MCP stdio stdout clean; diagnostics belong on stderr.
1379
+ - Keep outputs bounded.
1380
+ - Preserve graceful failure.
1381
+ - Keep local/offline operation functional.
1382
+ - Treat stored memory as untrusted data.
1383
+ - Prefer deterministic logic over unnecessary LLM calls.
1384
+
1385
+ ## MUST NOT
1386
+
1387
+ - Rewrite the entire project without migration.
1388
+ - Delete the v1 database schema before successful migration.
1389
+ - Introduce a mandatory cloud dependency.
1390
+ - Introduce a mandatory external embedding API.
1391
+ - add dozens of MCP tools for internal implementation details.
1392
+ - Let stale/superseded memories silently override current truth.
1393
+ - Destroy contradictory evidence merely because it is inconvenient.
1394
+ - Put secrets into test fixtures, logs, or examples.
1395
+ - Make plugin failure crash the host.
1396
+ - Change public behavior without tests and migration notes.
1397
+
1398
+ ## SHOULD
1399
+
1400
+ - Keep modules small and independently testable.
1401
+ - Use interfaces/adapters for vector and graph implementations.
1402
+ - Prefer SQLite-native capabilities before adding dependencies.
1403
+ - Measure retrieval quality before tuning scoring constants.
1404
+
1405
+ ---
1406
+
1407
+ # 37. Acceptance Criteria for v2.0.0
1408
+
1409
+ The release is acceptable only when all are true:
1410
+
1411
+ ### Data
1412
+
1413
+ - [ ] v1 DB can be backed up and migrated.
1414
+ - [ ] preferences map correctly to PREFERENCE memories.
1415
+ - [ ] lessons map correctly to LESSON memories.
1416
+ - [ ] interactions remain queryable.
1417
+ - [ ] profile remains available as a projection.
1418
+
1419
+ ### Memory
1420
+
1421
+ - [ ] unified memory model works.
1422
+ - [ ] lifecycle states work.
1423
+ - [ ] temporal validity works.
1424
+ - [ ] supersession works.
1425
+ - [ ] duplicate detection works.
1426
+ - [ ] conflict handling preserves ambiguous evidence.
1427
+
1428
+ ### Retrieval
1429
+
1430
+ - [ ] FTS retrieval works.
1431
+ - [ ] local semantic retrieval works.
1432
+ - [ ] RRF fusion works.
1433
+ - [ ] metadata/project scope works.
1434
+ - [ ] stale/superseded filtering works.
1435
+ - [ ] bounded output works.
1436
+
1437
+ ### Context
1438
+
1439
+ - [ ] `get_context` works.
1440
+ - [ ] token/character budget is enforced.
1441
+ - [ ] current project context is prioritized.
1442
+ - [ ] critical constraints are prioritized.
1443
+
1444
+ ### Graph
1445
+
1446
+ - [ ] entity/relation persistence works.
1447
+ - [ ] memory links work.
1448
+ - [ ] graph traversal is bounded.
1449
+ - [ ] graph failure does not break retrieval.
1450
+
1451
+ ### Security
1452
+
1453
+ - [ ] secrets are filtered before storage.
1454
+ - [ ] exports are confined to the allowed directory.
1455
+ - [ ] memory cannot become executable instructions.
1456
+ - [ ] import validates schema/version.
1457
+
1458
+ ### Reliability
1459
+
1460
+ - [ ] DB errors do not crash the MCP server.
1461
+ - [ ] plugin errors do not crash the host.
1462
+ - [ ] stdout remains protocol-safe.
1463
+
1464
+ ### Quality
1465
+
1466
+ - [ ] retrieval benchmark passes project targets.
1467
+ - [ ] conflict benchmark meets >=95% target.
1468
+ - [ ] migration tests pass.
1469
+ - [ ] performance targets are measured and documented.
1470
+
1471
+ ---
1472
+
1473
+ # 38. Recommended v2 Positioning
1474
+
1475
+ Do not market v2 as "another Mem0".
1476
+
1477
+ Position it as:
1478
+
1479
+ > **A local-first, privacy-focused, temporal memory MCP for AI coding agents, with hybrid retrieval, conflict-aware memory, and token-efficient context assembly.**
1480
+
1481
+ The differentiators are:
1482
+
1483
+ 1. Local-first.
1484
+ 2. SQLite simplicity.
1485
+ 3. No mandatory API/cloud.
1486
+ 4. Thai/English friendliness.
1487
+ 5. Cross-harness portability.
1488
+ 6. Temporal + conflict-aware memory.
1489
+ 7. Small MCP interface.
1490
+ 8. Agent-oriented context assembly.
1491
+
1492
+ ---
1493
+
1494
+ # 39. Final Architecture Contract
1495
+
1496
+ The canonical v2 flow is:
1497
+
1498
+ ```text
1499
+ ┌──────────────────┐
1500
+ │ AI AGENT │
1501
+ └────────┬─────────┘
1502
+ │ MCP
1503
+ ┌────────▼─────────┐
1504
+ │ MEMORY API │
1505
+ └────────┬─────────┘
1506
+
1507
+ ┌──────────────────┼──────────────────┐
1508
+ │ │ │
1509
+ ▼ ▼ ▼
1510
+ CAPTURE RETRIEVAL LIFECYCLE
1511
+ │ │ │
1512
+ │ ┌─────────┼─────────┐ │
1513
+ │ │ │ │ │
1514
+ │ FTS VECTOR GRAPH │
1515
+ │ │ │ │ │
1516
+ │ └─────────┼─────────┘ │
1517
+ │ │ │
1518
+ └──────────────────┼──────────────────┘
1519
+
1520
+ ┌────────────────┐
1521
+ │ MEMORY STORE │
1522
+ │ SQLite + FTS5 │
1523
+ │ vectors + graph│
1524
+ │ temporal state │
1525
+ └───────┬────────┘
1526
+
1527
+ ┌───────▼────────┐
1528
+ │ CONTEXT ENGINE │
1529
+ │ rank/filter │
1530
+ │ dedupe/compress│
1531
+ │ token budget │
1532
+ └───────┬────────┘
1533
+
1534
+
1535
+ AI AGENT
1536
+ ```
1537
+
1538
+ **This document is the implementation source of truth for th-memory-mcp v2 unless a later version explicitly supersedes it.**
1539
+
1540
+ ---
1541
+
1542
+ # 40. Implementation Status (as-built, v2.1.0)
1543
+
1544
+ This section folds in the former `design.md` build log. All v2 engine phases are complete and tested. v2.1.0 adds the five previously-deferred tools.
1545
+
1546
+ ## What shipped (v2.0.0 + v2.1.0)
1547
+ - **16 MCP tools** (see §17). `save_lesson` retained as a compatibility wrapper. The four tools originally marked deferred (`update_memory`, `merge_memory`, `link_memory`, `import_memory`) plus `extract_memories` landed in v2.1.0.
1548
+ - **Non-destructive migration** from v1.2.2: v1 tables preserved; `memories`/`entities`/`relations`/`memory_links`/`schema_meta` added; one-time backfill of preferences + lessons.
1549
+ - **Hybrid retrieval**: FTS5 + local semantic (hashing-trick vectors) fused via RRF, then scored by confidence × importance × recency × scope.
1550
+ - **Temporal model**: validity intervals, point-in-time retrieval, supersession chains, change detection.
1551
+ - **Conflict/dedup**: normalize → exact → similar → classify (duplicate/update/contradiction/unrelated); ambiguous conflicts preserved, never silently destroyed.
1552
+ - **Graph**: entities/relations + bounded memory-link traversal (maxDepth 1–5); `link_memory` exposes it publicly.
1553
+ - **Context engine**: `get_context` with token budgeting, temporal filtering, optional graph expansion.
1554
+ - **Consolidation**: clustering + derived memories with `derived_from` provenance.
1555
+ - **Auto-extraction**: `extract_memories` scans recent interactions for memory-intent (deterministic, no LLM) and proposes/creates memories.
1556
+ - **Security**: secret filtering, parameterized SQL, FTS-injection quoting, memory treated as untrusted data, bounded output.
1557
+
1558
+ ## Phase checklist
1559
+ - [x] Phase 1 — Core abstraction (types, migrations, repository, index wiring)
1560
+ - [x] Phase 2 — Lifecycle engine (decay, source-weights, scorer, transitions)
1561
+ - [x] Phase 3 — Temporal model
1562
+ - [x] Phase 4 — Conflict & dedup (+ fixed v1 `embed.ts` DataView bug)
1563
+ - [x] Phase 5 — Hybrid retrieval (FTS/vector/fusion/scorer/engine)
1564
+ - [x] Phase 6 — Graph engine
1565
+ - [x] Phase 7 — Context engine (`get_context`)
1566
+ - [x] Phase 8 — Consolidation (`consolidate`)
1567
+ - [x] Phase 9 — Benchmark + security suites (13 test suites total)
1568
+ - [x] Phase 10 — Docs + v2.0.0 release (npm, GitHub Release, Official MCP Registry, Glama)
1569
+ - [x] v2.1.0 — `link_memory` / `merge_memory` / `update_memory` / `import_memory` / `extract_memories` (16 tools, 13 suites)
1570
+
1571
+ ## Test status
1572
+ All 13 test suites pass (capture, distill, lifecycle 17, temporal 7, conflict 14, retrieval 7, graph 7, context 7, consolidation 5, benchmark 2, security 5, tools_v21 21, smoke 16-tool).
1573
+
1574
+ ## Known gaps vs original spec (deferred, not regressions)
1575
+ - Retrieval/conflict benchmark quality targets (Recall@5 ≥ 0.90 etc., §26/§27) are **not yet measured** in-repo; only a performance benchmark (retrieve < 2000 ms over 300 memories) exists.
1576
+ - Perf targets in §29 are engineering goals, not yet benchmarked in CI.
1577
+ - `extract_memories` is a deterministic heuristic extractor (no LLM); AI-assisted extraction/summarization remains future work.
1578
+ - Auto entity extraction in consolidation is future work.
1579
+
1580
+ ## Release
1581
+ - v2.0.0: released — npm `th-memory-mcp@2.0.0` (latest), GitHub Release `v2.0.0`, Official MCP Registry `io.github.worakorn-prince/th-memory-mcp@2.0.0`, Glama listed.
1582
+ - v2.1.0: implemented and tested locally; **npm/GitHub/MCP Registry/Glama publish pending** because the publish token expired and requires the owner to re-authenticate (`npm login` / `mcp-publisher` GitHub OAuth).