th-memory-mcp 2.0.0 → 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.
- package/ARCHITECTURE_v2.md +1582 -0
- package/README.md +12 -7
- package/README.th.md +9 -4
- package/dist/index.js +30 -0
- package/dist/tools/extract_memories.js +90 -0
- package/dist/tools/import_memory.js +95 -0
- package/dist/tools/link_memory.js +31 -0
- package/dist/tools/merge_memory.js +49 -0
- package/dist/tools/update_memory.js +98 -0
- package/package.json +3 -3
- package/design.md +0 -98
|
@@ -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).
|