recallnest 3.0.0 → 4.0.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 (246) hide show
  1. package/CHANGELOG.md +304 -0
  2. package/README.md +251 -258
  3. package/README_CN.md +226 -247
  4. package/assets/ui/app.js +6 -1
  5. package/bin/recallnest.mjs +20 -37
  6. package/docs/api-reference.md +8 -0
  7. package/docs/architecture.md +18 -13
  8. package/eval/cases-canary.json +107 -9
  9. package/integrations/examples/claude-agent-sdk/memory-agent.ts +2 -0
  10. package/integrations/examples/langchain/memory-chain.py +4 -0
  11. package/integrations/examples/openai-agents-sdk/memory-agent.py +4 -0
  12. package/package.json +12 -3
  13. package/src/activity-counter.ts +1 -0
  14. package/src/adaptive-retrieval.ts +23 -0
  15. package/src/api-server.ts +13 -11
  16. package/src/asset-sync.ts +26 -2
  17. package/src/audit-log.ts +2 -0
  18. package/src/auto-gc.ts +4 -3
  19. package/src/belief-history.ts +137 -31
  20. package/src/capture-engine.ts +459 -71
  21. package/src/cascade-forget.ts +7 -3
  22. package/src/checkpoint-mirror.ts +417 -0
  23. package/src/cli.ts +574 -54
  24. package/src/conflict-engine.ts +43 -15
  25. package/src/consolidation-engine.ts +24 -3
  26. package/src/context-collapse-renderer.ts +8 -1
  27. package/src/context-composer-stable.ts +5 -1
  28. package/src/context-composer.ts +11 -2
  29. package/src/distill-lock.ts +246 -74
  30. package/src/dream-pipeline.ts +3 -1
  31. package/src/embedder.ts +24 -0
  32. package/src/env-config.ts +136 -0
  33. package/src/flock.ts +97 -0
  34. package/src/forget-engine.ts +342 -58
  35. package/src/gateway-server.ts +4 -0
  36. package/src/ingest-plan.ts +56 -0
  37. package/src/ingest.ts +294 -121
  38. package/src/kg-contradiction.ts +753 -0
  39. package/src/kg-extractor.ts +17 -0
  40. package/src/kg-store.ts +1 -1
  41. package/src/known-item-eval.ts +455 -0
  42. package/src/llm-client.ts +13 -26
  43. package/src/llm-consolidation.ts +2 -2
  44. package/src/mcp-tool-deps.ts +6 -0
  45. package/src/mcp-tools-advanced.ts +80 -45
  46. package/src/mcp-tools-core.ts +23 -17
  47. package/src/mcp-tools-governance.ts +13 -7
  48. package/src/memory-assets.ts +144 -8
  49. package/src/memory-boundaries.ts +19 -0
  50. package/src/memory-evolution.ts +9 -0
  51. package/src/memory-lint.ts +1 -1
  52. package/src/memory-output.ts +311 -14
  53. package/src/memory-reconcile.ts +1437 -0
  54. package/src/memory-schema.ts +11 -0
  55. package/src/memory-store-port.ts +1 -0
  56. package/src/minis-archive.ts +151 -0
  57. package/src/noise-filter.ts +15 -2
  58. package/src/pii-detector.ts +31 -1
  59. package/src/pivot-apply.ts +55 -5
  60. package/src/pivot-evidence.ts +128 -0
  61. package/src/ppr-traversal.ts +25 -1
  62. package/src/preference-matcher.ts +40 -28
  63. package/src/prospective-memory.ts +7 -4
  64. package/src/retriever.ts +297 -57
  65. package/src/retroactive-boost.ts +3 -2
  66. package/src/runtime-config.ts +15 -1
  67. package/src/scope-policy.ts +1 -0
  68. package/src/session-distiller.ts +6 -2
  69. package/src/session-engine.ts +11 -4
  70. package/src/session-output.ts +20 -1
  71. package/src/session-schema.ts +5 -2
  72. package/src/session-store.ts +59 -12
  73. package/src/skill-promotion.ts +67 -1
  74. package/src/store-receipts.ts +109 -0
  75. package/src/store-write-budget.ts +37 -0
  76. package/src/store.ts +298 -57
  77. package/src/text-fingerprint.ts +25 -0
  78. package/src/trigger-store.ts +443 -0
  79. package/src/ui-server.ts +22 -21
  80. package/src/version-manager.ts +19 -5
  81. package/src/write-verifier.ts +16 -11
  82. package/src/__tests__/access-tracker-novelty.test.ts +0 -324
  83. package/src/__tests__/activity-counter.test.ts +0 -125
  84. package/src/__tests__/adaptive-fidelity.test.ts +0 -102
  85. package/src/__tests__/admission-control.test.ts +0 -206
  86. package/src/__tests__/age-label.test.ts +0 -33
  87. package/src/__tests__/anchor-generator.test.ts +0 -67
  88. package/src/__tests__/api-server-security.test.ts +0 -102
  89. package/src/__tests__/auto-consolidation.test.ts +0 -168
  90. package/src/__tests__/auto-recall.test.ts +0 -131
  91. package/src/__tests__/babel-integration.test.ts +0 -144
  92. package/src/__tests__/batch-dedup.test.ts +0 -65
  93. package/src/__tests__/belief-history.test.ts +0 -220
  94. package/src/__tests__/canary-eval.test.ts +0 -114
  95. package/src/__tests__/capture-engine.test.ts +0 -1328
  96. package/src/__tests__/capture-heuristic.test.ts +0 -171
  97. package/src/__tests__/cascade-forget.test.ts +0 -210
  98. package/src/__tests__/category-min-scores.test.ts +0 -116
  99. package/src/__tests__/cc8-cc1-essential-context.test.ts +0 -298
  100. package/src/__tests__/circuit-breaker.test.ts +0 -99
  101. package/src/__tests__/cluster-consolidation.test.ts +0 -1236
  102. package/src/__tests__/confidence-metadata.test.ts +0 -125
  103. package/src/__tests__/confidence-tracker.test.ts +0 -261
  104. package/src/__tests__/conflict-advisor.test.ts +0 -206
  105. package/src/__tests__/conflict-escalation.test.ts +0 -149
  106. package/src/__tests__/conflict-lifecycle.test.ts +0 -83
  107. package/src/__tests__/conflict-output.test.ts +0 -85
  108. package/src/__tests__/conflict-store.test.ts +0 -418
  109. package/src/__tests__/connector-v1.test.ts +0 -181
  110. package/src/__tests__/consolidation-engine.test.ts +0 -520
  111. package/src/__tests__/constructive-retrieval.test.ts +0 -509
  112. package/src/__tests__/context-collapse-renderer.test.ts +0 -214
  113. package/src/__tests__/context-composer-pins.test.ts +0 -64
  114. package/src/__tests__/context-composer-task-selection.test.ts +0 -24
  115. package/src/__tests__/context-reconstructor.test.ts +0 -65
  116. package/src/__tests__/context-renderer.test.ts +0 -91
  117. package/src/__tests__/continuity-eval.test.ts +0 -275
  118. package/src/__tests__/continuity-schema.test.ts +0 -97
  119. package/src/__tests__/contracts.test.ts +0 -262
  120. package/src/__tests__/conversation-importer.test.ts +0 -692
  121. package/src/__tests__/core-recall-eval.test.ts +0 -235
  122. package/src/__tests__/core-summary.test.ts +0 -109
  123. package/src/__tests__/data-checkup.test.ts +0 -304
  124. package/src/__tests__/decay-exemption.test.ts +0 -129
  125. package/src/__tests__/dedup-actions.test.ts +0 -58
  126. package/src/__tests__/dedup-guard.test.ts +0 -39
  127. package/src/__tests__/deterministic-id.test.ts +0 -39
  128. package/src/__tests__/distill-lock.test.ts +0 -305
  129. package/src/__tests__/distill-session-argshape.test.ts +0 -79
  130. package/src/__tests__/doctor.test.ts +0 -319
  131. package/src/__tests__/dream-pipeline.test.ts +0 -820
  132. package/src/__tests__/dream-scope-isolation.test.ts +0 -386
  133. package/src/__tests__/dream-write-batching.test.ts +0 -211
  134. package/src/__tests__/drill-down.test.ts +0 -108
  135. package/src/__tests__/embedder.test.ts +0 -122
  136. package/src/__tests__/emotion-decay.test.ts +0 -46
  137. package/src/__tests__/emotion-detector.test.ts +0 -56
  138. package/src/__tests__/emotion-phase1-integration.test.ts +0 -153
  139. package/src/__tests__/emotion-retrieval.test.ts +0 -56
  140. package/src/__tests__/entity-resolver.test.ts +0 -58
  141. package/src/__tests__/env-config-invariant.test.ts +0 -80
  142. package/src/__tests__/env-config.test.ts +0 -211
  143. package/src/__tests__/error-signature-boost.test.ts +0 -87
  144. package/src/__tests__/error-signature.test.ts +0 -95
  145. package/src/__tests__/error-taxonomy.test.ts +0 -129
  146. package/src/__tests__/ethics-layer.test.ts +0 -476
  147. package/src/__tests__/event-segmenter.test.ts +0 -153
  148. package/src/__tests__/feature-flags-integration.test.ts +0 -54
  149. package/src/__tests__/frequency-tracker.test.ts +0 -113
  150. package/src/__tests__/freshness.test.ts +0 -186
  151. package/src/__tests__/graph-export.test.ts +0 -489
  152. package/src/__tests__/hotness-blend.test.ts +0 -283
  153. package/src/__tests__/ingest-chunking.test.ts +0 -44
  154. package/src/__tests__/ingest-scope-prefix.test.ts +0 -69
  155. package/src/__tests__/ingest.test.ts +0 -360
  156. package/src/__tests__/interference-detector.test.ts +0 -203
  157. package/src/__tests__/kg-extractor.test.ts +0 -192
  158. package/src/__tests__/kg-store.test.ts +0 -300
  159. package/src/__tests__/llm-client-pivot.test.ts +0 -628
  160. package/src/__tests__/llm-consolidation.test.ts +0 -226
  161. package/src/__tests__/maintenance-locks.test.ts +0 -197
  162. package/src/__tests__/mcp-efficiency.test.ts +0 -288
  163. package/src/__tests__/mcp-related-scopes.test.ts +0 -151
  164. package/src/__tests__/memory-boundaries.test.ts +0 -282
  165. package/src/__tests__/memory-evolution-b2-b3-e1.test.ts +0 -362
  166. package/src/__tests__/memory-evolution.test.ts +0 -271
  167. package/src/__tests__/memory-health-rebalance.test.ts +0 -144
  168. package/src/__tests__/memory-lint.test.ts +0 -421
  169. package/src/__tests__/memory-output.test.ts +0 -224
  170. package/src/__tests__/memory-promotion.test.ts +0 -315
  171. package/src/__tests__/memory-utility.test.ts +0 -256
  172. package/src/__tests__/migrate-dedup-ids.test.ts +0 -65
  173. package/src/__tests__/multi-vector.test.ts +0 -242
  174. package/src/__tests__/narrative-architecture.test.ts +0 -456
  175. package/src/__tests__/noise-filter.test.ts +0 -205
  176. package/src/__tests__/noise-prototype-bank.test.ts +0 -280
  177. package/src/__tests__/obsidian-connector.test.ts +0 -363
  178. package/src/__tests__/omitted-reporting.test.ts +0 -98
  179. package/src/__tests__/openai-contract.test.ts +0 -513
  180. package/src/__tests__/pending-review.test.ts +0 -77
  181. package/src/__tests__/pii-redact.test.ts +0 -333
  182. package/src/__tests__/pivot-apply.test.ts +0 -373
  183. package/src/__tests__/pivot-distill-supervisor.test.ts +0 -457
  184. package/src/__tests__/pivot-distill.test.ts +0 -1178
  185. package/src/__tests__/post-retrieval-filter.test.ts +0 -178
  186. package/src/__tests__/ppr-traversal.test.ts +0 -256
  187. package/src/__tests__/prediction-engine.test.ts +0 -349
  188. package/src/__tests__/predictive-prospective-memory.test.ts +0 -416
  189. package/src/__tests__/preference-guard-smoke.test.ts +0 -211
  190. package/src/__tests__/preference-matcher.test.ts +0 -282
  191. package/src/__tests__/preference-slots.test.ts +0 -205
  192. package/src/__tests__/promotion-distinct-sources.test.ts +0 -162
  193. package/src/__tests__/prospective-memory.test.ts +0 -283
  194. package/src/__tests__/pull-from-macbook-sync-only.test.ts +0 -679
  195. package/src/__tests__/query-entity-detector.test.ts +0 -171
  196. package/src/__tests__/query-expander-alias.test.ts +0 -146
  197. package/src/__tests__/query-expander.test.ts +0 -34
  198. package/src/__tests__/recall-gate.test.ts +0 -266
  199. package/src/__tests__/recall-governor.test.ts +0 -227
  200. package/src/__tests__/recall-mode.test.ts +0 -64
  201. package/src/__tests__/resolve-db-path.test.ts +0 -130
  202. package/src/__tests__/resolve-tier.test.ts +0 -64
  203. package/src/__tests__/result-synthesizer.test.ts +0 -198
  204. package/src/__tests__/resume-context.test.ts +0 -4898
  205. package/src/__tests__/retrieval-eval.test.ts +0 -163
  206. package/src/__tests__/retrieval-trace.test.ts +0 -213
  207. package/src/__tests__/retrieve-audit-revision.test.ts +0 -255
  208. package/src/__tests__/retriever-boundary-weight.test.ts +0 -136
  209. package/src/__tests__/retriever-lazy-init-dispatch.test.ts +0 -123
  210. package/src/__tests__/retroactive-boost.test.ts +0 -223
  211. package/src/__tests__/salience-scoring.test.ts +0 -106
  212. package/src/__tests__/scope-inventory.test.ts +0 -200
  213. package/src/__tests__/scope-policy.test.ts +0 -69
  214. package/src/__tests__/scope-suggester.test.ts +0 -80
  215. package/src/__tests__/session-checkpoint.test.ts +0 -291
  216. package/src/__tests__/session-distiller.test.ts +0 -640
  217. package/src/__tests__/session-gc.test.ts +0 -215
  218. package/src/__tests__/skill-engine.test.ts +0 -552
  219. package/src/__tests__/skill-promotion.test.ts +0 -654
  220. package/src/__tests__/skill-verifier.test.ts +0 -122
  221. package/src/__tests__/source-heartbeat.test.ts +0 -254
  222. package/src/__tests__/stable-context-length-contract.test.ts +0 -62
  223. package/src/__tests__/store-patch-metadata.test.ts +0 -235
  224. package/src/__tests__/store-read-consistency.test.ts +0 -122
  225. package/src/__tests__/store-schema-migration.test.ts +0 -87
  226. package/src/__tests__/store-scope-audit.test.ts +0 -81
  227. package/src/__tests__/store-upsert.test.ts +0 -201
  228. package/src/__tests__/supersede-chain.test.ts +0 -154
  229. package/src/__tests__/synthesis-contract.test.ts +0 -252
  230. package/src/__tests__/synthesis-promotion.test.ts +0 -369
  231. package/src/__tests__/temporal-parser.test.ts +0 -241
  232. package/src/__tests__/temporal-validity.test.ts +0 -160
  233. package/src/__tests__/term-registry-terminal-roster.test.ts +0 -127
  234. package/src/__tests__/term-registry.test.ts +0 -121
  235. package/src/__tests__/tool-error-surfacing.test.ts +0 -98
  236. package/src/__tests__/tool-output-compressor.test.ts +0 -160
  237. package/src/__tests__/topic-tag.test.ts +0 -113
  238. package/src/__tests__/trusted-memory.test.ts +0 -867
  239. package/src/__tests__/ui-server-security.test.ts +0 -93
  240. package/src/__tests__/usage-tracker.test.ts +0 -287
  241. package/src/__tests__/utility-weight.test.ts +0 -57
  242. package/src/__tests__/verbatim-self-recall.test.ts +0 -279
  243. package/src/__tests__/version-manager.test.ts +0 -248
  244. package/src/__tests__/workflow-observation-skill-outcome.test.ts +0 -352
  245. package/src/__tests__/workflow-observation.test.ts +0 -433
  246. package/src/__tests__/write-verifier.test.ts +0 -122
package/README.md CHANGED
@@ -10,13 +10,13 @@ A local-first memory system backed by LanceDB that turns scattered conversation
10
10
 
11
11
  [![GitHub](https://img.shields.io/github/stars/AliceLJY/recallnest?style=social)](https://github.com/AliceLJY/recallnest)
12
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
13
- [![Runtime](https://img.shields.io/badge/Runtime-Bun_|_Node.js_22+-f9f1e1?logo=bun)](https://bun.sh)
13
+ [![Runtime](https://img.shields.io/badge/Runtime-Bun-f9f1e1?logo=bun)](https://bun.sh)
14
14
  [![LanceDB](https://img.shields.io/badge/LanceDB-Vector+FTS-orange)](https://lancedb.com)
15
15
  [![MCP](https://img.shields.io/badge/MCP-44_tools-blue)](https://modelcontextprotocol.io)
16
16
  [![CI](https://github.com/AliceLJY/recallnest/actions/workflows/ci.yml/badge.svg)](https://github.com/AliceLJY/recallnest/actions/workflows/ci.yml)
17
17
  [![CC Plugin](https://img.shields.io/badge/Claude_Code-Plugin-blueviolet)](https://github.com/AliceLJY/recallnest)
18
18
 
19
- **English** | [简体中文](README_CN.md) | [Roadmap](ROADMAP.md)
19
+ **English** | [简体中文](README_CN.md) | [Roadmap](ROADMAP.md) | [Website](https://aliceljy.github.io/recallnest/)
20
20
 
21
21
  </div>
22
22
 
@@ -26,8 +26,139 @@ A local-first memory system backed by LanceDB that turns scattered conversation
26
26
 
27
27
  Coding agents forget everything between windows. Your context — project configs, debugging decisions, entity mappings — is scattered across Claude Code, Codex, Kimi, Antigravity — and every other terminal you open — with no shared memory.
28
28
 
29
- RecallNest solves this: **a single LanceDB-backed memory layer that your coding agents read and write**. Context stored in one window is auto-recalled in another. Sessions checkpoint on exit and resume on start. Memory decays, evolves, and self-organizes — not just raw log storage.
29
+ RecallNest is **one LanceDB-backed memory layer that all of them read and write**. Context stored in one window is recalled in another. Sessions checkpoint on exit and resume on start. Memory decays, evolves, and self-organizes — it is not a log you grep.
30
30
 
31
+ ### What a recall actually looks like
32
+
33
+ ```text
34
+ Query : deploy rollback
35
+ Hits : 5
36
+
37
+ # ID Score Category Tier Source Date Age Retrieval Path
38
+ 1 ee79037a 46.1% cases peripheral cc 2026-08-25 2d vector
39
+ [assistant] Rolled back to the previous image and pinned the digest so the next…
40
+ prov : evidence/transcript-ingest
41
+ imgs : 52 agent-made in this session · read sess=dca70d4a
42
+ ```
43
+
44
+ Three things in that block carry most of the design:
45
+
46
+ - **`Source cc` · `Age 2d`** — this came out of a Claude Code window two days ago and you
47
+ are reading it from a different terminal, possibly on a different machine. That is the
48
+ premise the whole project is built on.
49
+ - **`prov : evidence/…`** — every row states which layer it sits on. A fragment scraped out
50
+ of a transcript never gets to pose as a decision you actually made; moving to durable
51
+ memory is a separate, gated step with its own evidence requirement.
52
+ - **`imgs : …`** — that session contained 52 images. **Not one of them is in the database.**
53
+ The line exists so you know there is something to go look at, and producing it cost no
54
+ model call, no vector, and no storage.
55
+
56
+ > The row above comes from transcript ingest. Since 2026-10-06 that step is off by default:
57
+ > `ingest` no longer chunks conversation records into the store, so a default setup holds only
58
+ > the memories you stored, distilled entries and memory files, and raw sessions are left to a
59
+ > dedicated session-search tool. To get rows like this one back, see "Index existing
60
+ > conversations" below.
61
+
62
+ That last one is the approach in miniature: **store what makes a thing findable, not
63
+ everything that could ever be asked about it.** The full reasoning — including the two
64
+ places where the obvious implementation was wrong — is in
65
+ [Images: addressable, not embedded](#images-addressable-not-embedded).
66
+
67
+
68
+ ## Core Capabilities
69
+
70
+ ### Access & Setup
71
+
72
+ | Capability | Description |
73
+ |---|---|
74
+ | **CC Plugin** | Install in Claude Code with one command — no manual config |
75
+ | **Shared Index** | One LanceDB store shared by every terminal that speaks MCP |
76
+ | **Dual Interface** | MCP (stdio) for CLI tools + HTTP API for custom agents |
77
+ | **One-Click Setup** | Integration scripts install MCP access and continuity rules |
78
+
79
+ ### Recall & Continuity
80
+
81
+ | Capability | Description |
82
+ |---|---|
83
+ | **Hybrid Retrieval** | 6-channel: vector + BM25 + L0/L1/L2 multi-vector + KG graph (PPR). The default mode is vector-only (since 2026-06); BM25 fusion and graph expansion are opt-in |
84
+ | **Write-time Triggers** | Each memory can carry 2–6 "how will this be asked about later" phrasings (`triggers`), embedded separately and used only for recall — never rendered as evidence. Borrowed from Tencent T-Mem (EMNLP 2026). |
85
+ | **4 Retrieval Profiles** | default, writing, debug, fact-check — tuned for different tasks |
86
+ | **Session Continuity** | `checkpoint_session` + `resume_context` (full/light/summary modes) with repo-state guard |
87
+ | **Session Distiller** | 3-layer conversation compression: microcompact → LLM summary → knowledge extraction |
88
+ | **Conversation Import** | Import from Claude Code, Claude.ai, ChatGPT, Slack, and plaintext |
89
+ | **Topic Tags** | Intra-scope topic partitioning — auto-detected, filterable in search |
90
+ | **Related Scope Sidecar** | Opt-in `includeRelatedScopes` search over configured `scopeRelations`, shown separately from the main scoped ranking |
91
+
92
+ ### Memory Lifecycle & Governance
93
+
94
+ | Capability | Description |
95
+ |---|---|
96
+ | **Memory Evolution** | Supersede chains, decay scoring, LLM importance, consolidation, archival |
97
+ | **Smart Promotion** | Evidence → durable memory with conflict guards, merge resolution, and audit trail |
98
+ | **Privacy Tiers** | 4-tier (`ephemeral` / `private` / `durable` / `shared`) with cascade forgetting |
99
+ | **Admission Control** | Write-time gating: noise filter, importance floor, dedup, rate limiting |
100
+ | **Memory Lint** | Contradiction, duplicate, stale, and orphan detection with health score |
101
+ | **Offline Consolidation** | `dream` command: clustering, merging, pruning of accumulated memories |
102
+
103
+ ### Reasoning & Structure
104
+
105
+ | Capability | Description |
106
+ |---|---|
107
+ | **Knowledge Graph** | Entity relation graph with PPR algorithm for multi-hop questions |
108
+ | **Constructive Retrieval** | Multi-source candidate expansion + grounded context reconstruction |
109
+ | **Narrative Architecture** | 3-layer autobiographical metadata (life-period → general-event → specific-event) |
110
+ | **Skill Memory** | Store, retrieve, and promote executable skills from recurring patterns |
111
+ | **Predictive Reminders** | Behavioral-signal prediction engine surfaces "you might need this" suggestions |
112
+ | **6 Categories** | profile, preferences, entities, events, cases, patterns — with category-aware merge strategies |
113
+
114
+ ### Visibility & Operations
115
+
116
+ | Capability | Description |
117
+ |---|---|
118
+ | **Dashboard** | Web UI with stats, category distribution, growth trends, and health |
119
+ | **Workflow Observation** | Dedicated append-only workflow health records, outside regular memory |
120
+ | **Structured Assets** | Pins, briefs, and distilled summaries — not just raw logs |
121
+ | **Data Checkup** | Data quality health checks on the memory store (including source health) |
122
+ | **Source Heartbeats** | Automatic ingest health tracking per data source with staleness alerts |
123
+ | **Export Graph** | Export interactive HTML knowledge graph visualization |
124
+ | **Batch Operations** | Store up to 20 memories in a single call with dedup |
125
+ | **Connector Framework** | Standard connector-v1 format for external data sources with example adapters |
126
+
127
+ ---
128
+
129
+ ## Architecture
130
+
131
+ ```
132
+ CLIENTS ACCESS CORE ENGINE STORAGE
133
+ ────────────────────── ─────────────────────── ──────────────────────────── ──────────────────────
134
+
135
+ Claude Code MCP over stdio Retriever LanceDB
136
+ Codex ───▶ 44 tools, 3 tiers ───▶ vector · hybrid opt-in ───▶ vector + columnar
137
+ Kimi · Antigravity Classifier · 6 categories
138
+ Doubao desktop Context composer
139
+ HTTP API :4318 resume_context Jina embeddings v5
140
+ your scripts · cron ───▶ 21 endpoints ───▶ Decay · Weibull half-life ─▶ 1024-dim, task-aware
141
+ Conflict · audit + merge
142
+ phone app ───▶ read-only gateway ───▶ Capture: evidence → durable
143
+ :8791, token-gated
144
+ ```
145
+
146
+ > Retriever: `retrieval.mode` defaults to `"vector"` (vector-only search). Setting it to `"hybrid"` in
147
+ > `config.json` adds BM25 full-text search, merged with the vector results by weighted score fusion
148
+ > (`vectorWeight` 0.7 / `bm25Weight` 0.3 by default).
149
+
150
+ ### Internal Design
151
+
152
+ - **L0 / L1 / L2 Dynamic Folding** — every memory stores 3 granularity layers (one-liner / bullet summary / full content); retrieval dynamically selects which layer to return based on relevance score and token budget
153
+ - **Weibull Decay + Emotion Modulation** — memories decay along a parametric Weibull curve; importance scores modulate the half-life, and emotional salience extends it further (up to 30%)
154
+ - **Vector Pre-filter + LLM Dedup** — 90% of dedup decisions use cheap cosine similarity (>= 0.92); only borderline cases invoke LLM judgment, keeping costs low without sacrificing accuracy
155
+ - **Category-Aware Merge Strategies** — `profile` and `preferences` use merge-on-conflict (latest wins); `events` and `cases` use append-only (history preserved)
156
+ - **Write-time Rehearsal (Triggers)** — a memory stored with `triggers: ["别人的榜我们要不要也去排个名", ...]` gets each phrasing embedded on the query side into a side table (`memory_triggers`); at recall time the query is matched against triggers, the best-matching trigger pulls its host memory into the candidate pool (max-over-triggers attribution, cosine hard gate + lexical soft gate), and the host then goes through the normal scoring chain. Triggers never appear in results — they are an entry point, not evidence. `RECALLNEST_TRIGGER_RECALL=false` turns it off; `triggers-backfill` / `triggers-calibrate` CLI manage existing data
157
+ - **Display Score vs Elimination Score** — dual-track retrieval: tier floor prevents core memories from ever dropping out, while decay boost lets fresh memories surface temporarily without permanently displacing stable ones
158
+
159
+ > Full architecture deep-dive: [`docs/architecture.md`](docs/architecture.md)
160
+
161
+ ---
31
162
 
32
163
  ## Who Can Connect
33
164
 
@@ -104,7 +235,7 @@ npm install -g recallnest # install globally
104
235
  recallnest doctor
105
236
  ```
106
237
 
107
- Works with Node.js 22+ (via tsx) or Bun. No git clone needed.
238
+ Requires [Bun](https://bun.sh): RecallNest does not run on Node.js. The npm launcher only hands off to Bun, and exits with install instructions if `bun` is not on your PATH. No git clone needed.
108
239
 
109
240
  ### Option C: Manual setup
110
241
 
@@ -159,279 +290,94 @@ bun run seed:continuity
159
290
  bun run src/cli.ts doctor
160
291
  ```
161
292
 
162
- ---
163
-
164
- ## Web UI
165
-
166
- <p align="center">
167
- <img src="assets/dashboard.png" alt="RecallNest Dashboard" width="800" />
168
- <br><em>Dashboard — total count, category distribution, health score, and growth trends at a glance.</em>
169
- </p>
170
-
171
- <p align="center">
172
- <img src="assets/screenshots/ui-full.png" alt="RecallNest Search Workbench" width="800" />
173
- <br><em>Search Workbench — hybrid search with topic tag filtering, 4 retrieval profiles, Skills browser, and asset management.</em>
174
- </p>
175
-
176
- <p align="center">
177
- <img src="assets/knowledge-graph.png" alt="RecallNest Knowledge Graph" width="800" />
178
- <br><em>Knowledge Graph — interactive force-directed visualization with semantic bridges revealing cross-domain connections.</em>
179
- </p>
180
-
181
- ```bash
182
- bun run src/ui-server.ts
183
- # → http://localhost:4317
184
- ```
185
-
186
- ---
187
-
188
- ## Core Capabilities
189
-
190
- ### Access & Setup
191
-
192
- | Capability | Description |
193
- |---|---|
194
- | **CC Plugin** | Install in Claude Code with one command — no manual config |
195
- | **Shared Index** | One LanceDB store shared by every terminal that speaks MCP |
196
- | **Dual Interface** | MCP (stdio) for CLI tools + HTTP API for custom agents |
197
- | **One-Click Setup** | Integration scripts install MCP access and continuity rules |
198
-
199
- ### Recall & Continuity
200
-
201
- | Capability | Description |
202
- |---|---|
203
- | **Hybrid Retrieval** | 6-channel: vector + BM25 + L0/L1/L2 multi-vector + KG graph (PPR) |
204
- | **4 Retrieval Profiles** | default, writing, debug, fact-check — tuned for different tasks |
205
- | **Session Continuity** | `checkpoint_session` + `resume_context` (full/light/summary modes) with repo-state guard |
206
- | **Session Distiller** | 3-layer conversation compression: microcompact → LLM summary → knowledge extraction |
207
- | **Conversation Import** | Import from Claude Code, Claude.ai, ChatGPT, Slack, and plaintext |
208
- | **Topic Tags** | Intra-scope topic partitioning — auto-detected, filterable in search |
209
- | **Related Scope Sidecar** | Opt-in `includeRelatedScopes` search over configured `scopeRelations`, shown separately from the main scoped ranking |
210
-
211
- ### Memory Lifecycle & Governance
212
-
213
- | Capability | Description |
214
- |---|---|
215
- | **Memory Evolution** | Supersede chains, decay scoring, LLM importance, consolidation, archival |
216
- | **Smart Promotion** | Evidence → durable memory with conflict guards, merge resolution, and audit trail |
217
- | **Privacy Tiers** | 4-tier (`ephemeral` / `private` / `durable` / `shared`) with cascade forgetting |
218
- | **Admission Control** | Write-time gating: noise filter, importance floor, dedup, rate limiting |
219
- | **Memory Lint** | Contradiction, duplicate, stale, and orphan detection with health score |
220
- | **Offline Consolidation** | `dream` command: clustering, merging, pruning of accumulated memories |
221
-
222
- ### Reasoning & Structure
223
-
224
- | Capability | Description |
225
- |---|---|
226
- | **Knowledge Graph** | Entity relation graph with PPR algorithm for multi-hop questions |
227
- | **Constructive Retrieval** | Multi-source candidate expansion + grounded context reconstruction |
228
- | **Narrative Architecture** | 3-layer autobiographical metadata (life-period → general-event → specific-event) |
229
- | **Skill Memory** | Store, retrieve, and promote executable skills from recurring patterns |
230
- | **Predictive Reminders** | Behavioral-signal prediction engine surfaces "you might need this" suggestions |
231
- | **6 Categories** | profile, preferences, entities, events, cases, patterns — with category-aware merge strategies |
232
-
233
- ### Visibility & Operations
234
-
235
- | Capability | Description |
236
- |---|---|
237
- | **Dashboard** | Web UI with stats, category distribution, growth trends, and health |
238
- | **Workflow Observation** | Dedicated append-only workflow health records, outside regular memory |
239
- | **Structured Assets** | Pins, briefs, and distilled summaries — not just raw logs |
240
- | **Data Checkup** | Data quality health checks on the memory store (including source health) |
241
- | **Source Heartbeats** | Automatic ingest health tracking per data source with staleness alerts |
242
- | **Export Graph** | Export interactive HTML knowledge graph visualization |
243
- | **Batch Operations** | Store up to 20 memories in a single call with dedup |
244
- | **Connector Framework** | Standard connector-v1 format for external data sources with example adapters |
245
-
246
- ---
247
-
248
- ## New in v3.0: A Supported Runtime, and Conclusions That Can Be Used
249
-
250
- v3.0 is a major release for one reason that shows up on install and one that shows up in
251
- how memory behaves.
252
-
253
- **The runtime boundary moved to Node 22.** RecallNest had been carrying `openai@4`, which
254
- pulls in the deprecated `formdata-node` → `node-domexception` chain. Every `openai` release
255
- since v5 has zero dependencies, so the chain disappears on any upgrade — but v7 declares
256
- `engines.node >= 22.0.0`, which makes "raise the Node floor" and "move off a deprecated
257
- dependency chain" the same piece of work rather than two. `engines.node` is now `>=22`.
258
- This is the breaking part of the major.
259
-
260
- **A synthesized conclusion can now reach stable memory.** `dream` writes cluster insights
261
- and cross-memory patterns on the evidence layer deliberately — a model re-reading its own
262
- memories is a lead to its sources, not authority over them — but stable-memory selection
263
- refuses the evidence layer outright. The consequence was absolute: no matter how well
264
- supported a synthesized conclusion was, nothing downstream could lean on it. `promote_synthesis`
265
- (MCP) and `recallnest promote-synthesis` (CLI) give it a road, gated on the conclusion's own
266
- validated evidence set rather than on repetition, because a synthesis is already a
267
- cross-entry aggregate. The synthesized row is never modified; promotion writes a separate
268
- durable entry carrying `promotedFrom` back to it, through the same path and the same
269
- `canonicalKey` dedup as every other promotion.
270
-
271
- Also in this release:
272
-
273
- - **Retrieve audit rows say what was served.** They used to record the query and a hit
274
- count. Because beliefs are revised in place — the id stays, the version increments, the
275
- old text survives as a `superseded` row — "memory X was retrieved" was ambiguous across
276
- every belief change. Rows now carry each result's id, revision, lifecycle status, and
277
- boundary. The list is capped, and a capped list says so.
278
- - **HTTP contract tests for embeddings and chat completions.** Every previous test stubbed
279
- the SDK client, so nothing exercised a socket, and a transport-level regression would
280
- have passed all of them. These drive the real classes through the real SDK against a
281
- loopback server, covering success, error, and timeout for the default OpenAI shape plus
282
- the Jina and Qwen-compatible profiles. No network egress, no vendor credentials.
283
- - **Fixed: a rate-limit reply could trigger an unbounded request storm.** Found by those
284
- tests. The embedder retried a context-length error by chunking, the chunker returns short
285
- text unchanged, and the gate that decided "this is a context error" also matched
286
- rate-limit wording — so a 429 re-embedded the same text forever. Measured at over 61,000
287
- requests in five seconds against an endpoint asking us to slow down. Failure is bounded now.
288
- - **A known recall gap is now a runnable regression.** A memory that is long, older, and
289
- rarely read can fail to be recalled by words copied out of its own body, while short,
290
- fresh, frequently-read entries outrank it. It is a ranking problem, not a filtering one —
291
- the entry clears every threshold and then places last. The reproduction is checked in; the
292
- ranking fix is not in this release.
293
- - **44 MCP tools** across three tiers, up from 43.
294
-
295
- ### Upgrading from v2.6
296
-
297
- - **Node 22 or newer is required.** Bun users are unaffected. This is the only breaking
298
- change in the release.
299
- - Existing LanceDB data is opened in place. No export or import step.
300
- - `promote_synthesis` defaults to dry-run and writes nothing until `dryRun=false`.
301
- - `audit.jsonl` rows for retrievals are larger now that they list what was served. Rotation
302
- is still manual; archive it if it approaches 50 MB.
303
-
304
- ### A note on npm history
305
-
306
- `recallnest@2.6.1` on npm was a maintenance release published before Trusted Publishing was
307
- configured for this package, so it carries no build provenance. That is a fact about how it
308
- was published, not a defect in the package, and it is not retroactively fixable — the same
309
- npm version cannot be republished to add provenance.
310
-
311
- ---
312
-
313
- ## New in v2.6: Reliable Cross-Process Memory and Distribution
314
-
315
- v2.6 turns the development since v2.5.4 into a release-ready upgrade:
316
-
317
- - **Cross-process visibility** — LanceDB now checks for external commits on every read by default, so resident MCP/API/UI processes see writes from CLI ingestion without a restart. Set `RECALLNEST_READ_CONSISTENCY_INTERVAL=<seconds>` for bounded staleness or `off` for the legacy unchecked behavior.
318
- - **Safer memory evolution** — belief changes preserve the old row as `superseded`; procedural memories avoid time decay; cold-start and length-normalization behavior no longer suppress short entity queries or stable memories.
319
- - **More reliable consolidation** — `dream` now distinguishes failure classes, honors wall-clock budgets, refills vectors before semantic clustering, and asserts that successful runs actually produced work.
320
- - **Broader conversation coverage** — Kimi, AGY/Antigravity, and minis sources are recognized across ingestion, scope boundaries, and term resolution.
321
- - **One public version** — npm metadata, CLI `--version`, MCP handshakes, HTTP health responses, and the Claude Code marketplace all follow the `2.6.0` release contract.
322
- - **Installable Claude Code plugin** — installation now registers the 43-tool MCP server and continuity skill, asks for the Jina key through sensitive plugin configuration, and keeps config plus LanceDB data in Claude Code's persistent plugin data directory.
323
-
324
- ### Upgrading from v2.5.4
325
-
326
- - Existing LanceDB data is opened in place. Legacy tables missing newer fields are migrated automatically, including empty tables.
327
- - Plugin data survives plugin updates because it is stored outside the versioned cache. A manual clone continues to use its existing `config.json` and database path.
328
- - Retrieval auditing now includes read operations. `audit.jsonl` has no automatic rotation yet; consider archiving it if it approaches 50 MB.
329
- - `RECALLNEST_LAYER_ADMISSION` remains opt-in (`observe` or `on`); the default is `off`.
293
+ Since 2026-10-06, `ingest` does two things by default: it reconciles memory files
294
+ (`sources.memory`) and moves files from the Minis drop folder into `data/minis-archive`. The six
295
+ conversation sources (cc / codex / kimi / gemini / desktop / minis) are not chunked, embedded or
296
+ written. To index transcripts as well, set `RECALLNEST_TRANSCRIPT_INGEST=on` in the environment
297
+ that runs `ingest` (only the exact value `on` counts). Minis conversations archived while the
298
+ switch was off are not picked up automatically; copy them from `data/minis-archive` back into
299
+ the drop folder and run `ingest` again.
330
300
 
331
301
  ---
332
302
 
333
- ## New in v2.1: Philosophy-Informed Memory
334
-
335
- v2.0 built the operational memory platform; v2.1 added philosophy-informed memory behavior.
303
+ ## Images: addressable, not embedded
336
304
 
337
- Five upgrades derived from 9 research dimensions in philosophy of memory, each mapped to concrete engineering:
305
+ Conversations contain images. A text memory layer does not. The usual answer is a
306
+ multimodal embedding model — encode every image into the same space as the text. That is
307
+ right for photo libraries. It is the wrong shape here, for a cheap reason: **in a
308
+ conversation an image almost never arrives alone.** It comes wrapped in "look at this
309
+ error", and the reply right after it usually describes what was in the picture. The words
310
+ around the image are already an index of it. What was missing was never semantic search
311
+ over pixels — it was knowing a picture is sitting there at all.
338
312
 
339
- - **Emotion-Aware Decay** *(Affective Memory Theory)* — Memories with strong emotional content decay 20-30% slower. Keyword-based emotion detection computes `salience` (mnemonic significance), which feeds into the Weibull half-life formula and a rebalanced 4-factor evolution score. Zero LLM cost.
313
+ So RecallNest does not encode images. It records **how many images are in the session a
314
+ memory came from**, and lets you decide whether to open the original transcript. Meaning
315
+ is resolved on demand, by whatever model is asking, at the moment it matters.
340
316
 
341
- - **Memory Ethics Layer** *(Right to Be Forgotten / GDPR Art. 17)* — Four privacy tiers (`ephemeral` / `private` / `durable` / `shared`). Cascade forgetting engine that propagates deletion through KG triples, evolution chains, pin assets, and briefs. Full audit trail. `forget_memory` MCP tool for agent-driven deletion.
317
+ The cost is worth stating plainly: **no multimodal model, no re-embedding, no image
318
+ storage, no change to any vector.** Backfilling 21,319 existing memories touched metadata
319
+ only.
342
320
 
343
- - **Autobiographical Narrative** *(Narrative Identity Theory / Conway's 3-layer model)* — Memories are tagged with `lifePeriod → generalEvent → specificEvent` hierarchy, orthogonal to existing 6 categories. Retrieval pulls narrative siblings. Context rendering groups by life period. Rule-based tagger with EN+CN support.
344
-
345
- - **Constructive Retrieval** *(Simulation Theory / Michaelian)* — Instead of returning raw stored text, RecallNest now reconstructs context from an expanded candidate set: KG neighbors + evolution chains + cluster members + narrative siblings. Source-map grounded coverage replaces lexical overlap. Contradictions are detected and flagged.
346
-
347
- - **Predictive Prospective Memory** *(Mental Time Travel / Tulving)* — Heuristic prediction engine that surfaces "you might need this" reminders from behavioral signals: stale checkpoint open loops, corrected workflow observations, high-frequency dormant memories, and uncovered query topics. Zero LLM cost. Auto-expire in 7 days if unaccepted.
348
-
349
- ---
321
+ Two design choices in it were not obvious, and both were wrong on the first attempt.
350
322
 
351
- ## New in v2.2: Retrieval Quality Hardening
323
+ ### Session-level, on purpose
352
324
 
353
- v2.1 added philosophy-informed behavior; v2.2 closes the last three engine-layer gaps identified by a frontier research scan (ACC, PI-LLM, TSM).
325
+ The marker counts the whole session, not the turn — coarser than it first looks like it
326
+ should be, and the coarseness is the point.
354
327
 
355
- - **Memory Confidence Meta-tags** *(ACC / Dual-Process UQ)* — Each memory now carries structured `ConfidenceMetadata` (score, reliability tier: `direct` / `inferred` / `hearsay`). Auto-assigned from source on write (`manual` = 0.9, `agent` = 0.7, `conversation_import` = 0.5). Retrieval scores are weighted by confidence. `resume_context` tags low-confidence items with `[低置信]`.
328
+ A turn that is nothing but a pasted screenshot has almost no text, so it never cleared the
329
+ length gate and never entered the store. Measured on real transcripts, **12.5% of turns
330
+ containing a pasted image were dropped whole** — including the ones worth the most, like
331
+ seven screenshots with no caption, or "here are the steps" attached to a picture that *is*
332
+ the steps. A turn-level marker has nothing to attach to for exactly those. A session-level
333
+ marker lands on that session's *other* memories, which did get stored, and those are what
334
+ a search surfaces.
356
335
 
357
- - **Interference Detection + Active Forgetting Gate** *(PI-LLM / SleepGate)* — Semantic cluster detection identifies groups of near-duplicate memories competing for retrieval. Enhanced RIF keeps only top-K (default 3) per cluster; extras are demoted 50% instead of removed. Write-time pre-warning: when a scope accumulates ≥5 high-similarity active memories, the weakest is flagged `pending_review`. `data_checkup` reports interference density.
336
+ The trade-off is undisguised: every memory from a session carries the same count, so the
337
+ images may have nothing to do with the row you are looking at. The line says
338
+ `in this session`, not `in this memory`, for that reason.
358
339
 
359
- - **Temporal Validity Windows** *(TSM / TiMem / Zep)* — `store_memory` accepts `validUntil` (expiration) and `eventTime` (when the event actually happened). `search_memory` supports `validAt` (point-in-time query) and `includeExpired` (demote 80% instead of hide). Auto-GC applies 2× decay acceleration to expired memories.
340
+ ### Two classes, because they answer different questions
360
341
 
361
- - **Usage-Adjusted Auto-GC** *(off by default)* — `RECALLNEST_USAGE_DECAY=true` enables a GC-only cold-memory penalty when constructive retrieval is also active. Cold memories discount the frequency component instead of changing online retrieval ranking.
362
-
363
- ---
364
-
365
- ## New in v2.3: Connector Ecosystem + Source Health
366
-
367
- v2.2 hardened retrieval quality; v2.3 opens RecallNest to external data sources with a standard connector framework and operational health monitoring.
342
+ | Bucket | What it is | The question it answers |
343
+ |---|---|---|
344
+ | user-pasted | Pictures a human put into a message | *Where is that screenshot I sent?* |
345
+ | agent-made | Everything else the session produced | *What did the page look like? What did I generate?* |
368
346
 
369
- - **Connector-v1 Standard** *(GB-2)* — A JSON format (`ConnectorOutputV1`) that any external script can produce. Obsidian vaults, emails, RSS feeds, log files — normalize once, ingest through the full dedup/embed/extract pipeline. See [`docs/connector-spec.md`](docs/connector-spec.md) for the specification and [`connectors/examples/`](connectors/examples/) for adapter skeletons (email, logs, RSS).
347
+ Keeping only the first is tempting — a person searching their own memory wants their own
348
+ screenshots. But an agent reconstructing its past work wants the other: the diagram it
349
+ drew, the rendering it captured, the illustration it made for a post. **Of 1,767 sessions
350
+ carrying images, 1,103 contain no human-pasted image at all.** Keep one bucket and those
351
+ sessions go silent — precisely the ones where the agent did visual work.
370
352
 
371
- - **Obsidian Vault Ingestion** *(GB-1)* — First-party Obsidian connector: scans `.md` files, extracts frontmatter + wikilinks, maps folder structure to tags. One command: `lm ingest --obsidian /path/to/vault`.
353
+ ### The second bucket is a complement, not a list
372
354
 
373
- - **Source Health Monitoring** *(GB-3)* — Every connector ingest writes a heartbeat to `data/source-heartbeat.json`. `data_checkup` flags stale sources (>7d warning, >30d error). `doctor --ci` shows a per-source heartbeat summary with human-readable age.
355
+ The first implementation defined agent-made images by enumeration: inside `tool_result`,
356
+ inside `payload.output`, inside `tool.result`. Every location was real. The list was still
357
+ wrong, because **the set of ways an image can appear only grows**, and an enumeration
358
+ silently drops whatever it did not anticipate.
374
359
 
375
- ---
360
+ So the second bucket is a complement: count every image signal in the record, subtract the
361
+ ones positively identified as human-pasted, attribute the rest without asking where it came
362
+ from. Across 9,619 transcripts:
376
363
 
377
- ## Architecture
378
-
379
- ```
380
- ┌──────────────────────────────────────────────────────────┐
381
- │ Client Layer │
382
- ├──────────┬──────────┬──────────┬──────────────────────────┤
383
- │ Claude │ Anti- │ Codex │ Custom Agents / curl │
384
- │ Code │ gravity │ │ │
385
- └────┬─────┴────┬─────┴────┬─────┴──────┬──────────────────┘
386
- │ │ │ │
387
- └──── MCP (stdio) ───┘ HTTP API (port 4318)
388
- │ │
389
- ▼ ▼
390
- ┌──────────────────────────────────────────────────────────┐
391
- │ Integration Layer │
392
- │ ┌─────────────────────┐ ┌────────────────────────────┐ │
393
- │ │ MCP Server │ │ HTTP API Server │ │
394
- │ │ 44 tools │ │ 21 endpoints │ │
395
- │ └─────────┬───────────┘ └──────────┬─────────────────┘ │
396
- └────────────┼─────────────────────────┼───────────────────┘
397
- └──────────┬──────────────┘
398
- ▼
399
- ┌──────────────────────────────────────────────────────────┐
400
- │ Core Engine │
401
- │ │
402
- │ ┌────────────┐ ┌────────────┐ ┌─────────────────────┐ │
403
- │ │ Retriever │ │ Classifier │ │ Context Composer │ │
404
- │ │ (vector + │ │ (6 cats) │ │ (resume_context) │ │
405
- │ │ BM25 + RRF)│ │ │ │ │ │
406
- │ └────────────┘ └────────────┘ └──────────────────────┘ │
407
- │ ┌────────────┐ ┌────────────┐ ┌─────────────────────┐ │
408
- │ │ Decay │ │ Conflict │ │ Capture Engine │ │
409
- │ │ Engine │ │ Engine │ │ (evidence → durable) │ │
410
- │ │ (Weibull) │ │ (audit + │ │ │ │
411
- │ │ │ │ merge) │ │ │ │
412
- │ └────────────┘ └────────────┘ └──────────────────────┘ │
413
- └──────────────────────────┬───────────────────────────────┘
414
- ▼
415
- ┌──────────────────────────────────────────────────────────┐
416
- │ Storage Layer │
417
- │ ┌─────────────────────┐ ┌────────────────────────────┐ │
418
- │ │ LanceDB │ │ Jina Embeddings v5 │ │
419
- │ │ (vector + columnar) │ │ (1024-dim, task-aware) │ │
420
- │ └─────────────────────┘ └────────────────────────────┘ │
421
- └──────────────────────────────────────────────────────────┘
422
- ```
423
-
424
- ### Internal Design
364
+ | | Enumerated | Complement |
365
+ |---|---|---|
366
+ | Agent-made images | 5,812 | **10,938** |
367
+ | Sessions with any image | 1,507 | **1,767** |
368
+ | Human-pasted images | 1,629 | 1,629 |
425
369
 
426
- - **L0 / L1 / L2 Dynamic Folding** — every memory stores 3 granularity layers (one-liner / bullet summary / full content); retrieval dynamically selects which layer to return based on relevance score and token budget
427
- - **Weibull Decay + Emotion Modulation** — memories decay along a parametric Weibull curve; importance scores modulate the half-life, and emotional salience extends it further (up to 30%)
428
- - **Vector Pre-filter + LLM Dedup** — 90% of dedup decisions use cheap cosine similarity (>= 0.92); only borderline cases invoke LLM judgment, keeping costs low without sacrificing accuracy
429
- - **Category-Aware Merge Strategies** — `profile` and `preferences` use merge-on-conflict (latest wins); `events` and `cases` use append-only (history preserved)
430
- - **Display Score vs Elimination Score** — dual-track retrieval: tier floor prevents core memories from ever dropping out, while decay boost lets fresh memories surface temporarily without permanently displacing stable ones
370
+ **The enumeration missed 5,126 images and 376 sessions** — nearly half. The largest class
371
+ it dropped was image *generation*, which lives in neither container the list knew about.
372
+ Human-pasted counts are identical under both definitions, which is the check that matters:
373
+ widening the second bucket did not contaminate the precise one. A regression test feeds the
374
+ parser an `image_generation_call` — a shape the source never names — and asserts it lands
375
+ in the second bucket; under the enumerated implementation that test fails.
431
376
 
432
- > Full architecture deep-dive: [`docs/architecture.md`](docs/architecture.md)
377
+ One caveat: the complement counts *signals*, not certified pictures. A single generation can
378
+ leave both a call and a completion record and be counted twice. That direction was chosen
379
+ deliberately — the question is "is there anything here to look at", not "exactly how many".
433
380
 
434
- ---
435
381
 
436
382
  ## Interfaces
437
383
 
@@ -499,7 +445,7 @@ Examples live in [`integrations/examples/`](integrations/examples/):
499
445
  | `data_checkup` | Run data quality health checks on the memory store |
500
446
  | `dream` | Run offline memory consolidation (clustering, merging, pruning) |
501
447
  | `memory_lint` | Run memory quality checks: contradictions, duplicates, stale entries, orphans |
502
- | `forget_memory` | Cascade-delete a memory with KG cleanup, pin archival, and audit trail |
448
+ | `forget_memory` | Delete a memory together with its KG triples, trigger rows and the indexed copies of pins made from it, archive the pin files, read back to confirm, and write an audit entry |
503
449
  | `export_graph` | Export memories as an interactive HTML knowledge graph |
504
450
 
505
451
  </details>
@@ -569,7 +515,7 @@ bun run src/cli.ts lint --scope project:myapp # lint a specific scope
569
515
  bun run src/cli.ts graph --open # export & open knowledge graph
570
516
  bun run src/cli.ts graph --max-nodes 50 # smaller graph
571
517
 
572
- # Ingestion & diagnostics
518
+ # Ingestion & diagnostics (transcripts are not ingested by default; see "Index existing conversations")
573
519
  bun run src/cli.ts ingest --source all
574
520
  bun run src/cli.ts doctor
575
521
  ```
@@ -578,6 +524,53 @@ bun run src/cli.ts doctor
578
524
 
579
525
  ---
580
526
 
527
+ ## Web UI
528
+
529
+ <p align="center">
530
+ <img src="assets/dashboard.png" alt="RecallNest Dashboard" width="800" />
531
+ <br><em>Dashboard — total count, category distribution, health score, and growth trends at a glance.</em>
532
+ </p>
533
+
534
+ <p align="center">
535
+ <img src="assets/screenshots/ui-full.png" alt="RecallNest Search Workbench" width="800" />
536
+ <br><em>Search Workbench — hybrid search with topic tag filtering, 4 retrieval profiles, Skills browser, and asset management.</em>
537
+ </p>
538
+
539
+ <p align="center">
540
+ <img src="assets/knowledge-graph.png" alt="RecallNest Knowledge Graph" width="800" />
541
+ <br><em>Knowledge Graph — interactive force-directed visualization with semantic bridges revealing cross-domain connections.</em>
542
+ </p>
543
+
544
+ ```bash
545
+ bun run src/ui-server.ts
546
+ # → http://localhost:4317
547
+ ```
548
+
549
+ ---
550
+
551
+ ## What's new
552
+
553
+ **v4.0** runs on **Bun only** and hands its cross-process locks to the kernel. RecallNest
554
+ used to decide a lock file was stale from its pid and timestamp and then delete it — two
555
+ processes that saw the same stale file could both end up holding the lock (more than one
556
+ winner in up to 30 of 40 rounds of an eight-process race). Locks are now `flock(2)`: the
557
+ kernel releases them when a process exits or is killed, and a stress test that kills a
558
+ writer every 15–60 ms for six seconds never sees two writers inside.
559
+
560
+ The rest of the release fixes data that could go wrong quietly: a deleted memory written
561
+ back by a concurrent update, history rows left pointing at nothing, secrets kept in
562
+ metadata and sent to the embedding API inside triggers, explicit searches such as
563
+ `git push rules` or `#22` returning nothing, and write receipts that reported rejected
564
+ writes as stored.
565
+
566
+ **Upgrading:** install Bun, then stop every RecallNest process before starting v4 — old and
567
+ new lock code must not run together. A few defaults and HTTP replies changed; the list is
568
+ at the top of the v4.0.0 entry in the changelog. Existing LanceDB data opens in place.
569
+
570
+ **Full history — v4.0 through v1.0, with the upgrade notes for each — is in
571
+ [CHANGELOG.md](CHANGELOG.md).**
572
+
573
+
581
574
  ## Multilingual Support
582
575
 
583
576
  RecallNest works out of the box with English. For multilingual memory (Chinese, Japanese, Thai, and 20+ more), install [babel-memory](https://github.com/AliceLJY/babel-memory) with the language packs you need: