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_CN.md CHANGED
@@ -10,13 +10,13 @@
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.md) | **简体中文** | [Roadmap](ROADMAP.md)
19
+ [English](README.md) | **简体中文** | [Roadmap](ROADMAP.md) | [项目主页](https://aliceljy.github.io/recallnest/)
20
20
 
21
21
  </div>
22
22
 
@@ -26,8 +26,133 @@
26
26
 
27
27
  编程 Agent 每开一个窗口就失忆。项目配置、调试决策、实体映射——散落在 Claude Code、Codex、Kimi、Antigravity 以及你打开的每一个终端里,互相不通。
28
28
 
29
- RecallNest 的解法:**一个 LanceDB 驱动的记忆层,供你的编程 Agent 共读共写**。一个窗口存入的上下文,另一个窗口自动召回。会话退出时 checkpoint,启动时 resume。记忆会衰减、演化、自组织——不是简单的日志堆积。
29
+ RecallNest 是**一个 LanceDB 驱动的记忆层,你所有的 Agent 共读共写**。一个窗口存入的上下文,另一个窗口能召回。会话退出时 checkpoint,启动时 resume。记忆会衰减、演化、自组织——它不是一堆等你 grep 的日志。
30
30
 
31
+ ### 一次召回长什么样
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
+ 这一小块里有三样东西,几乎就是整个设计:
45
+
46
+ - **`Source cc` · `Age 2d`** —— 它出自两天前的一个 Claude Code 窗口,而你正在另一个终端、
47
+ 甚至另一台机器上读它。整个项目就建在这个前提上。
48
+ - **`prov : evidence/…`** —— 每一行都标着自己待在哪一层。从对话里刮下来的碎片,永远没资格
49
+ 冒充你真正做过的决定;要变成稳定记忆,得另走一道带证据门槛的提升流程。
50
+ - **`imgs : …`** —— 那个 session 里有 52 张图,**一张都没进数据库**。这一行的存在只是让你知道
51
+ 那儿有东西可看,而产生它没花一次模型调用、没多一个向量、没占一份存储。
52
+
53
+ > 上面这一行来自「对话原文入库」。2026-10-06 起这一步默认关:`ingest` 不再把对话记录切块写进库,
54
+ > 默认配置下库里只有你存进去的记忆、提炼产物和记忆文件,原始对话交给专门的会话检索工具去查。
55
+ > 要让库里重新出现这样的行,见下文「索引已有对话」。
56
+
57
+ 最后这条就是整套做法的缩影:**只存"让一样东西能被找到"所需的部分,不存"将来可能被问到"的一切。**
58
+ 完整的推理——包括最显然的那种实现错在哪两个地方——在
59
+ [图片:可寻址,而不是被编码](#图片可寻址而不是被编码)。
60
+
61
+
62
+ ## 核心能力
63
+
64
+ ### 接入与安装
65
+
66
+ | 能力 | 说明 |
67
+ |---|---|
68
+ | **CC Plugin** | 一行命令装入 Claude Code,无需手动配置 MCP |
69
+ | **共享索引** | 所有客户端共用同一个 LanceDB 存储,跨机指向 `ssh` 即可共用真相源 |
70
+ | **双通道接入** | MCP(stdio)给 CLI agent 与能填 MCP 配置的 GUI app + HTTP API 给只会发请求的客户端 |
71
+ | **一键接入** | 集成脚本同时安装 MCP 和 continuity 规则 |
72
+
73
+ ### 检索与连续性
74
+
75
+ | 能力 | 说明 |
76
+ |---|---|
77
+ | **混合检索** | 6 通道:向量 + BM25 + L0/L1/L2 多向量 + KG 图(PPR)。默认只走向量(2026-06 起),BM25 融合与图扩展要在配置里打开 |
78
+ | **4 套检索策略** | default、writing、debug、fact-check —— 按任务类型调优 |
79
+ | **会话连续性** | `checkpoint_session` + `resume_context`(full/light/summary 三种模式)+ 仓库状态守卫 |
80
+ | **会话蒸馏** | 3 层对话压缩:微缩 → LLM 结构化摘要 → 知识提取 |
81
+ | **对话导入** | 支持 Claude Code、Claude.ai、ChatGPT、Slack、纯文本 |
82
+ | **Topic Tags** | scope 内 topic 分区,自动检测,搜索时可过滤 |
83
+ | **关联 scope 侧栏** | 显式传 `includeRelatedScopes` 时,按 `scopeRelations` 白名单额外检索,并和主 scope 排序分开展示 |
84
+
85
+ ### 记忆生命周期与治理
86
+
87
+ | 能力 | 说明 |
88
+ |---|---|
89
+ | **记忆演化** | Supersede 链、衰减评分、LLM 重要性、聚合、归档 |
90
+ | **显式升级** | Evidence → Durable Memory,带冲突守卫、合并决议、审计日志 |
91
+ | **隐私分级** | 4 级(`ephemeral` / `private` / `durable` / `shared`)+ 级联遗忘 |
92
+ | **准入控制** | 写入时门控:噪音过滤、重要性下限、去重、限流 |
93
+ | **Memory Lint** | 矛盾、重复、过期、孤儿检测 + 健康评分 |
94
+ | **离线整合** | `dream` 命令:聚类、合并、修剪积累的记忆 |
95
+
96
+ ### 推理与结构
97
+
98
+ | 能力 | 说明 |
99
+ |---|---|
100
+ | **Knowledge Graph** | 实体关系图 + PPR 算法,支持多跳问题 |
101
+ | **建构式检索** | 多源候选扩展 + 溯源锚定的上下文重建 |
102
+ | **叙事架构** | 三层自传式元数据(生命阶段 → 一般事件 → 具体事件) |
103
+ | **Skill Memory** | 存储、检索、自动提升来自重复模式的可执行技能 |
104
+ | **预测式提醒** | 行为信号预测引擎,主动浮现"你可能需要这个" |
105
+ | **6 类记忆** | profile、preferences、entities、events、cases、patterns —— 类别分化合并策略 |
106
+
107
+ ### 可视化与运维
108
+
109
+ | 能力 | 说明 |
110
+ |---|---|
111
+ | **Dashboard** | Web UI 首页:统计卡片、类别分布、增长趋势、健康概览 |
112
+ | **Workflow Observation** | 专门的 append-only 工作流观测层,不混入普通 memory |
113
+ | **结构化资产** | Pin、Brief、Distill —— 不只是原始日志 |
114
+ | **Data Checkup** | 记忆存储数据质量健康检查(含数据源健康) |
115
+ | **数据源心跳** | 按数据源自动追踪 ingest 健康状态,过期告警 |
116
+ | **导出图谱** | 导出交互式 HTML 知识图谱可视化 |
117
+ | **批量操作** | 单次调用存储最多 20 条记忆,自带去重 |
118
+ | **Connector 框架** | 标准 connector-v1 格式接入外部数据源,附带适配器示例 |
119
+
120
+ ---
121
+
122
+ ## 架构
123
+
124
+ ```
125
+ CLIENTS ACCESS CORE ENGINE STORAGE
126
+ ────────────────────── ─────────────────────── ──────────────────────────── ──────────────────────
127
+
128
+ Claude Code MCP over stdio Retriever LanceDB
129
+ Codex ───▶ 44 tools, 3 tiers ───▶ vector · hybrid opt-in ───▶ vector + columnar
130
+ Kimi · Antigravity Classifier · 6 categories
131
+ Doubao desktop Context composer
132
+ HTTP API :4318 resume_context Jina embeddings v5
133
+ your scripts · cron ───▶ 21 endpoints ───▶ Decay · Weibull half-life ─▶ 1024-dim, task-aware
134
+ Conflict · audit + merge
135
+ phone app ───▶ read-only gateway ───▶ Capture: evidence → durable
136
+ :8791, token-gated
137
+ ```
138
+
139
+ > 图内保留英文术语:等宽字体下中文占两格,混排会把对齐打乱。四段从左到右分别是
140
+ > 客户端、接入层(MCP / HTTP / 只读网关)、核心引擎、存储层。
141
+ >
142
+ > Retriever 一格:`retrieval.mode` 默认是 `"vector"`(纯向量检索);在 `config.json` 里改成 `"hybrid"`
143
+ > 后,会加上 BM25 全文检索,并与向量结果做加权分数融合(默认 `vectorWeight` 0.7 / `bm25Weight` 0.3)。
144
+
145
+ ### 内部设计
146
+
147
+ - **L0 / L1 / L2 动态折叠** —— 每条记忆存储 3 个粒度层(一句话 / 要点概要 / 完整内容);检索时根据相关性分数和 token 预算动态选择返回哪个层级
148
+ - **Weibull 衰减 + 情绪调制** —— 记忆沿参数化 Weibull 曲线衰减;情绪显著性可额外延长半衰期最高 30%
149
+ - **向量预筛 + LLM 去重** —— 90% 的去重决策用低成本余弦相似度(≥ 0.92);仅临界情况调用 LLM 判断
150
+ - **类别分化合并策略** —— `profile` 和 `preferences` 采用冲突合并(新版覆盖);`events` 和 `cases` 采用追加(保留历史)
151
+ - **展示分 vs 淘汰分双轨制** —— 检索使用双轨评分:tier floor 防止核心记忆被淘汰,decay boost 让新鲜记忆临时浮现而不永久挤掉稳定记忆
152
+
153
+ > 完整架构详解:[`docs/architecture.md`](docs/architecture.md)
154
+
155
+ ---
31
156
 
32
157
  ## 谁能接上
33
158
 
@@ -104,7 +229,7 @@ npm install -g recallnest # 全局安装
104
229
  recallnest doctor
105
230
  ```
106
231
 
107
- 支持 Node.js 22+(通过 tsx)或 Bun,无需 clone 仓库。
232
+ 需要 [Bun](https://bun.sh):RecallNest 不能在 Node.js 上运行。npm 装的启动脚本只负责转交给 Bun,找不到 `bun` 时会给出安装方法后退出。无需 clone 仓库。
108
233
 
109
234
  ### 方式 C:手动安装
110
235
 
@@ -159,267 +284,77 @@ bun run seed:continuity
159
284
  bun run src/cli.ts doctor
160
285
  ```
161
286
 
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 —— 总量、类别分布、健康评分、增长趋势一目了然。</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 —— 混合检索 + Topic Tag 过滤 + 4 套检索策略 + Skills 浏览 + 资产管理。</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 —— 交互式力导向图,语义桥接揭示跨域隐藏关联。</em>
179
- </p>
180
-
181
- ```bash
182
- bun run src/ui-server.ts
183
- # → http://localhost:4317
184
- ```
185
-
186
- ---
187
-
188
- ## 核心能力
189
-
190
- ### 接入与安装
191
-
192
- | 能力 | 说明 |
193
- |---|---|
194
- | **CC Plugin** | 一行命令装入 Claude Code,无需手动配置 MCP |
195
- | **共享索引** | 所有客户端共用同一个 LanceDB 存储,跨机指向 `ssh` 即可共用真相源 |
196
- | **双通道接入** | MCP(stdio)给 CLI agent 与能填 MCP 配置的 GUI app + HTTP API 给只会发请求的客户端 |
197
- | **一键接入** | 集成脚本同时安装 MCP 和 continuity 规则 |
198
-
199
- ### 检索与连续性
200
-
201
- | 能力 | 说明 |
202
- |---|---|
203
- | **混合检索** | 6 通道:向量 + BM25 + L0/L1/L2 多向量 + KG 图(PPR) |
204
- | **4 套检索策略** | default、writing、debug、fact-check —— 按任务类型调优 |
205
- | **会话连续性** | `checkpoint_session` + `resume_context`(full/light/summary 三种模式)+ 仓库状态守卫 |
206
- | **会话蒸馏** | 3 层对话压缩:微缩 → LLM 结构化摘要 → 知识提取 |
207
- | **对话导入** | 支持 Claude Code、Claude.ai、ChatGPT、Slack、纯文本 |
208
- | **Topic Tags** | scope 内 topic 分区,自动检测,搜索时可过滤 |
209
- | **关联 scope 侧栏** | 显式传 `includeRelatedScopes` 时,按 `scopeRelations` 白名单额外检索,并和主 scope 排序分开展示 |
210
-
211
- ### 记忆生命周期与治理
212
-
213
- | 能力 | 说明 |
214
- |---|---|
215
- | **记忆演化** | Supersede 链、衰减评分、LLM 重要性、聚合、归档 |
216
- | **显式升级** | Evidence → Durable Memory,带冲突守卫、合并决议、审计日志 |
217
- | **隐私分级** | 4 级(`ephemeral` / `private` / `durable` / `shared`)+ 级联遗忘 |
218
- | **准入控制** | 写入时门控:噪音过滤、重要性下限、去重、限流 |
219
- | **Memory Lint** | 矛盾、重复、过期、孤儿检测 + 健康评分 |
220
- | **离线整合** | `dream` 命令:聚类、合并、修剪积累的记忆 |
221
-
222
- ### 推理与结构
223
-
224
- | 能力 | 说明 |
225
- |---|---|
226
- | **Knowledge Graph** | 实体关系图 + PPR 算法,支持多跳问题 |
227
- | **建构式检索** | 多源候选扩展 + 溯源锚定的上下文重建 |
228
- | **叙事架构** | 三层自传式元数据(生命阶段 → 一般事件 → 具体事件) |
229
- | **Skill Memory** | 存储、检索、自动提升来自重复模式的可执行技能 |
230
- | **预测式提醒** | 行为信号预测引擎,主动浮现"你可能需要这个" |
231
- | **6 类记忆** | profile、preferences、entities、events、cases、patterns —— 类别分化合并策略 |
232
-
233
- ### 可视化与运维
234
-
235
- | 能力 | 说明 |
236
- |---|---|
237
- | **Dashboard** | Web UI 首页:统计卡片、类别分布、增长趋势、健康概览 |
238
- | **Workflow Observation** | 专门的 append-only 工作流观测层,不混入普通 memory |
239
- | **结构化资产** | Pin、Brief、Distill —— 不只是原始日志 |
240
- | **Data Checkup** | 记忆存储数据质量健康检查(含数据源健康) |
241
- | **数据源心跳** | 按数据源自动追踪 ingest 健康状态,过期告警 |
242
- | **导出图谱** | 导出交互式 HTML 知识图谱可视化 |
243
- | **批量操作** | 单次调用存储最多 20 条记忆,自带去重 |
244
- | **Connector 框架** | 标准 connector-v1 格式接入外部数据源,附带适配器示例 |
245
-
246
- ---
247
-
248
- ## v3.0 新增:一个受支持的运行时,和终于能被用起来的结论
249
-
250
- v3.0 是大版本,原因有两个:一个在安装时看得见,一个在记忆的行为里。
251
-
252
- **运行时边界提到了 Node 22。** RecallNest 一直带着 `openai@4`,它拽着
253
- `formdata-node` → `node-domexception` 这条弃用链。openai 从 v5 起每个版本都是零依赖,
254
- 所以升到哪一版这条链都会消失 —— 但 v7 自己声明 `engines.node >= 22.0.0`,于是
255
- 「抬 Node 边界」和「甩掉弃用依赖链」变成同一件事,而不是两件。`engines.node` 现在是
256
- `>=22`。这是本次大版本里唯一的破坏性改动。
257
-
258
- **合成出的结论终于能进稳定记忆。** `dream` 把 cluster insight 和 cross-memory pattern
259
- 写在 evidence 层是有意的 —— 模型对自己记忆的再加工是通往源头的线索,不是压过源头的
260
- 权威 —— 但稳定记忆的选取对 evidence 层一律拒收。后果是绝对的:一条合成结论无论证据
261
- 多充分,下游都没法靠它。`promote_synthesis`(MCP)与 `recallnest promote-synthesis`
262
- (CLI)给了它一条路,判据是这条结论自己那份经过校验的证据集,而不是「重复出现几次」
263
- —— 合成物本身就是跨条目聚合,要求它重复是把一件事数了几次。合成行本身一个字不改;
264
- 晋升写的是另一条 durable 记录,带 `promotedFrom` 指回去,走的是和其他晋升同一条通道、
265
- 同一套 `canonicalKey` 去重。
266
-
267
- 本次还有:
268
-
269
- - **retrieve 审计行会说清服务了什么。** 它以前只记查询词和命中数。而信念是就地修订的
270
- —— id 不变、版本号加一、旧正文作为 `superseded` 行留下 —— 所以「memory X 被检索了」
271
- 这句话跨过任何一次信念变更都是有歧义的。现在每条结果的 id、版本、生命周期状态和
272
- boundary 都记下来;列表有上限,而且**被截断时会说自己被截断了**。
273
- - **embeddings 与 chat completions 有了 HTTP 契约测试。** 此前所有测试都把 SDK client
274
- 换成桩函数,没有一条碰过 socket,传输层的回归会全绿着放过去。新测试驱动真的类、经真的
275
- SDK、打到本地回环服务器,覆盖成功 / 错误 / 超时三态,以及默认 OpenAI 形态加上 Jina、
276
- Qwen 兼容端点。零出网、零凭据。
277
- - **修复:被限流时反而会猛打对方。** 是上面那批测试当场查出来的。embedder 遇到
278
- context-length 错误会分块重试,而分块器对短文本原样返回,判定「这是 context 错误」的
279
- 那条正则又会命中限流措辞 —— 于是一个 429 会拿同一段文本无限重打。实测 5 秒 61,000 多
280
- 个请求,对着一个正在叫我们慢一点的端点。现在失败是有界的。
281
- - **一个已知的召回缺口变成了能跑的回归。** 一条又长、又旧、很少被读的记忆,可能用它自己
282
- 正文里的原话都召不回,而短的、新的、被频繁读的条目排在它前面。这是排序问题不是过滤
283
- 问题 —— 那条记忆过了所有阈值,然后排最后一名。复现已经进仓;排序的修复不在本次。
284
- - **MCP 工具 44 个**(三层),此前 43 个。
285
-
286
- ### 从 v2.6 升级
287
-
288
- - **需要 Node 22 或更新版本。** 用 Bun 的不受影响。这是本次唯一的破坏性改动。
289
- - 已有 LanceDB 数据原地打开,不需要导出导入。
290
- - `promote_synthesis` 默认 dry-run,不传 `dryRun=false` 不写任何东西。
291
- - `audit.jsonl` 里检索那类行变大了(它现在列出服务了哪几条)。轮转仍是手动的,接近
292
- 50 MB 时归档一下。
293
-
294
- ### 关于 npm 历史的一句说明
295
-
296
- npm 上的 `recallnest@2.6.1` 是一次维护发布,发布时这个包还没有配置 Trusted Publishing,
297
- 所以它不带构建 provenance。这是它当时怎么发的一个事实,不是包本身的缺陷,而且**无法追认**
298
- —— 同一个 npm 版本不能为了补 provenance 再发一次。
287
+ 2026-10-06 起,`ingest` 默认只做两件事:对账记忆文件(`sources.memory`),以及把 Minis 投递目录里的文件挪进
288
+ `data/minis-archive`。六个对话来源(cc / codex / kimi / gemini / desktop / minis)不切片、不嵌入、不写库。
289
+ 要把对话原文也索引进来,在运行 `ingest` 的环境里设 `RECALLNEST_TRANSCRIPT_INGEST=on`(只认 `on` 这一个写法)。
290
+ 关着期间挪进存档的 Minis 对话不会自动补进来,要补就把文件从 `data/minis-archive` 拷回投递目录再跑。
299
291
 
300
292
  ---
301
293
 
302
- ## v2.6 新增:跨进程一致性与可靠分发
303
-
304
- v2.6 把 v2.5.4 以来的开发整理成一版可升级、可安装、版本口径一致的正式候选:
305
-
306
- - **跨进程即时可见** —— LanceDB 默认每次读取都检查外部提交,常驻 MCP/API/UI 无需重启即可看见 CLI ingest 写入。可用 `RECALLNEST_READ_CONSISTENCY_INTERVAL=<秒>` 设置允许的延迟窗口,或设为 `off` 恢复旧版不检查行为。
307
- - **更安全的记忆演化** —— 信念变化不再原地覆盖,旧记录保留为 `superseded`;程序性记忆免于时间衰减;冷启动和长度归一化不再压低短实体查询与稳定记忆。
308
- - **更可靠的整合管线** —— `dream` 增加失败分型、总时长预算、聚类前向量回填,以及“成功必须真的产出结果”的断言。
309
- - **更完整的对话来源** —— Kimi、AGY/Antigravity 和 minis 已同步纳入 ingest、scope 边界与术语识别。
310
- - **一个公开版本号** —— npm 元数据、CLI `--version`、MCP 握手、HTTP 健康接口和 Claude Code marketplace 统一遵守 `2.6.0` 发布契约。
311
- - **真正可安装的 Claude Code 插件** —— 安装后自动注册 43 个 MCP 工具与连续性 skill,通过敏感插件配置接收 Jina key,并把配置与 LanceDB 数据放进 Claude Code 的持久插件数据目录。
294
+ ## 图片:可寻址,而不是被编码
312
295
 
313
- ### 从 v2.5.4 升级
314
-
315
- - 现有 LanceDB 数据原地打开;缺少新字段的旧表会自动迁移,空表也覆盖。
316
- - 插件数据位于版本缓存之外,更新插件不会清空;手动 clone 仍沿用现有 `config.json` 与数据库路径。
317
- - 检索操作现已写入审计日志。`audit.jsonl` 暂无自动轮转,接近 50 MB 时建议人工归档。
318
- - `RECALLNEST_LAYER_ADMISSION` 仍是显式开启项(`observe` 或 `on`),默认 `off`。
319
-
320
- ---
296
+ 对话里有图,而文本记忆层没有。通常的答案是上一个多模态 embedding 模型,把每张图编码进
297
+ 和文字同一个向量空间。那个答案对相册和商品库是对的,放在这里却是错的形状,理由很便宜:
298
+ **在对话里,一张图几乎从不孤零零地出现。** 它总被"你看这个报错"包着,而紧跟其后的回复
299
+ 通常已经描述了图里是什么。图周围的文字,本来就是这张图的索引。缺的从来不是对像素做语义
300
+ 检索,而是**知道那儿有一张图**。
321
301
 
322
- ## v2.1 新增:记忆哲学驱动的架构升级
302
+ 所以 RecallNest 不编码图片。它只记下**这条记忆所属的 session 里有几张图**,剩下的交给你判断
303
+ 要不要去翻原始对话。图的含义在需要的那一刻、由当时在问的那个模型现场解读。
323
304
 
324
- v2.0 建立了完整的记忆操作平台;v2.1 加入了记忆哲学驱动的记忆行为。
305
+ 代价值得说清楚:**不需要多模态模型,不重新 embedding,不存图片,不改动任何一个向量。**
306
+ 给存量的 21,319 条记忆补上这个标记,只动了 metadata。
325
307
 
326
- 来自 9 个记忆哲学研究维度的 5 项工程升级:
308
+ 这里面有两个不那么显然的选择,而且两次的第一版都是错的。
327
309
 
328
- - **情绪感知衰减** *(情感记忆理论)* —— 带有强烈情绪的记忆衰减慢 20-30%。基于关键词的情绪检测计算 `salience`(记忆显著性),注入 Weibull 半衰期公式和重新平衡的 4 因子演化评分。零 LLM 成本。
310
+ ### 粒度取 session,是故意的
329
311
 
330
- - **记忆伦理层** *(遗忘权 / GDPR 第 17 条)* —— 四级隐私:`ephemeral`(临时)/ `private`(私密)/ `durable`(持久)/ `shared`(共享)。级联遗忘引擎贯穿 KG 三元组、演化链、Pin 资产和摘要。完整审计日志。`forget_memory` MCP 工具支持 Agent 驱动的删除。
312
+ 标记数的是整个 session,不是单轮——比第一眼该有的粒度更粗,而粗正是重点。
331
313
 
332
- - **自传叙事架构** *(叙事身份理论 / Conway 三层模型)* —— 记忆标注 `生命阶段 → 一般事件 → 具体事件` 层级,正交于现有 6 类别。检索自动拉取叙事兄弟。上下文渲染按生命阶段分组。支持中英文的规则式标注器。
314
+ 一轮如果只有一张截图、几乎没有文字,它根本过不了长度闸,压根没进过库。在真实对话上实测,
315
+ **含用户贴图的轮次里有 12.5% 是整轮被丢掉的**——而且丢的恰恰是最值钱的那些:七张截图一个字
316
+ 没配,或者「操作步骤在这里」配一张图、而那张图**就是**步骤本身。轮次级的标记,对最该被找到的
317
+ 那批图**无处可挂**。session 级的标记会落到同一个 session 里**其他**进了库的记忆上,而那些才是
318
+ 搜索会捞出来的东西。
333
319
 
334
- - **建构式检索** *(模拟理论 / Michaelian)* —— 不再返回原始存储文本,而是从扩展候选集(KG 邻居 + 演化链 + 聚类成员 + 叙事兄弟)中重建上下文。Source-map 语义覆盖率替代词汇重叠。矛盾检测与标记。
320
+ 代价不加掩饰:同一个 session 的每条记忆都带同一个数字,所以那些图未必和你眼前这一条有关。
321
+ 输出里写的是 `in this session` 而不是 `in this memory`,就是为了这个。
335
322
 
336
- - **预测式前瞻记忆** *(精神时间旅行 / Tulving)* —— 启发式预测引擎从行为信号中浮现"你可能需要这个"提醒:过期的 checkpoint 待办事项、被纠正的工作流观察、高频休眠记忆和未覆盖的查询主题。零 LLM 成本。7 天未接受自动过期。
323
+ ### 分成两类,因为它们回答的不是同一个问题
337
324
 
338
- ---
339
-
340
- ## v2.2 新增:检索质量强化
341
-
342
- v2.1 加入了哲学记忆行为;v2.2 补齐前沿扫描(ACC、PI-LLM、TSM)发现的最后三个引擎层空白。
343
-
344
- - **记忆置信度元标签** *(ACC / 双过程不确定性量化)* —— 每条记忆携带结构化 `ConfidenceMetadata`(分数 + 可靠性层级:`direct` 用户亲述 / `inferred` LLM 推断 / `hearsay` 二手转述)。写入时根据 source 自动赋值(manual=0.9, agent=0.7, conversation_import=0.5)。检索评分加权置信度。`resume_context` 对低置信条目标注 `[低置信]`。
345
-
346
- - **干扰检测 + 主动遗忘门** *(PI-LLM / SleepGate)* —— 语义聚簇检测识别竞争检索的近重复记忆群。增强版 RIF 每簇仅保留 top-K(默认 3),多余的降权 50% 而非删除。写入时预警:scope 内累积 ≥5 条高相似活跃记忆时,最弱的标记 `pending_review`。`data_checkup` 报告干扰密度。
347
-
348
- - **时间有效性窗口** *(TSM / TiMem / Zep)* —— `store_memory` 接受 `validUntil`(过期时间)和 `eventTime`(事件发生时间)。`search_memory` 支持 `validAt`(时间点查询)和 `includeExpired`(降权 80% 而非隐藏)。auto-GC 对过期记忆施加 2 倍衰减加速。
349
-
350
- - **Usage-adjusted Auto-GC** *(默认关闭)* —— `RECALLNEST_USAGE_DECAY=true` 且建构式检索 use 信号开启时,GC 专用分支才会对 cold 记忆的 frequency 项打折;在线检索排序不读取这个分支。
351
-
352
- ---
353
-
354
- ## v2.3 新增:Connector 生态 + 数据源健康
355
-
356
- v2.2 强化了检索质量;v2.3 通过标准 Connector 框架和运维健康监控,把 RecallNest 开放给外部数据源。
357
-
358
- - **Connector-v1 标准** *(GB-2)* —— 一套 JSON 格式(`ConnectorOutputV1`),任何外部脚本都可以输出。Obsidian 笔记、邮件、RSS、日志文件——标准化一次,走完整的 dedup/embed/extract 管线入库。规范见 [`docs/connector-spec.md`](docs/connector-spec.md),适配器骨架见 [`connectors/examples/`](connectors/examples/)(email、logs、RSS)。
325
+ | 类别 | 是什么 | 回答什么问题 |
326
+ |---|---|---|
327
+ | user-pasted | 人贴进消息里的图 | *我发过的那张截图在哪?* |
328
+ | agent-made | 这个 session 产生的其余所有图 | *那个页面当时长什么样?我当时生成的图是哪张?* |
359
329
 
360
- - **Obsidian Vault 接入** *(GB-1)* —— 官方 Obsidian 连接器:扫描 `.md` 文件,提取 frontmatter + wikilink,文件夹结构映射为 tag。一条命令:`lm ingest --obsidian /path/to/vault`。
330
+ 只留第一类很诱人——人翻自己的记忆,想找的是自己的截图。但一个 agent 回溯自己干过的活,
331
+ 要的是第二类:它画的示意图、它截的渲染结果、它为一篇文章配的插图。**1,767 个带图 session 里,
332
+ 有 1,103 个一张人贴的图都没有。** 只留第一类,这些 session 就全哑了——而它们恰恰是 agent
333
+ 做了大量视觉工作的那些。
361
334
 
362
- - **数据源健康监控** *(GB-3)* —— 每次 connector ingest 写心跳到 `data/source-heartbeat.json`。`data_checkup` 标记过期数据源(>7 天 warning,>30 天 error)。`doctor --ci` 按数据源展示心跳摘要(如"obsidian: 2h ago")。
335
+ ### 第二类是补集,不是清单
363
336
 
364
- ---
337
+ 第一版的实现是靠**枚举**定义"AI 产的图":`tool_result` 里的、`payload.output` 里的、
338
+ `tool.result` 里的。每一个位置都真实存在,这份清单依然是错的,因为**图片可能出现的方式只会
339
+ 越来越多**,而枚举会悄无声息地漏掉它没预料到的那一种。
365
340
 
366
- ## 架构
341
+ 所以第二类改成了补集:数出这条记录里所有的图片信号,减去能明确认定为"人贴的",剩下的
342
+ 一律归入,不问它从哪儿来。在 9,619 份对话记录上:
367
343
 
368
- ```
369
- ┌──────────────────────────────────────────────────────────┐
370
- │ 客户端层 │
371
- ├──────────┬──────────┬──────────┬──────────────────────────┤
372
- │ Claude │ Gemini │ Codex │ 自定义 Agent / curl │
373
- │ Code │ CLI │ │ │
374
- └────┬─────┴────┬─────┴────┬─────┴──────┬──────────────────┘
375
- │ │ │ │
376
- └──── MCP (stdio) ───┘ HTTP API(端口 4318)
377
- │ │
378
- ▼ ▼
379
- ┌──────────────────────────────────────────────────────────┐
380
- │ 集成层 │
381
- │ ┌─────────────────────┐ ┌────────────────────────────┐ │
382
- │ │ MCP Server │ │ HTTP API Server │ │
383
- │ │ 44 个工具 │ │ 21 个端点 │ │
384
- │ └─────────┬───────────┘ └──────────┬─────────────────┘ │
385
- └────────────┼─────────────────────────┼───────────────────┘
386
- └──────────┬──────────────┘
387
- ▼
388
- ┌──────────────────────────────────────────────────────────┐
389
- │ 核心引擎 │
390
- │ │
391
- │ ┌────────────┐ ┌────────────┐ ┌─────────────────────┐ │
392
- │ │ 检索器 │ │ 分类器 │ │ 上下文编排器 │ │
393
- │ │(向量 + │ │(6 类分类) │ │(resume_context) │ │
394
- │ │ BM25 + RRF)│ │ │ │ │ │
395
- │ └────────────┘ └────────────┘ └──────────────────────┘ │
396
- │ ┌────────────┐ ┌────────────┐ ┌─────────────────────┐ │
397
- │ │ 衰减引擎 │ │ 冲突引擎 │ │ 捕获引擎 │ │
398
- │ │(Weibull) │ │(审计 + │ │(evidence → durable)│ │
399
- │ │ │ │ 合并) │ │ │ │
400
- │ └────────────┘ └────────────┘ └──────────────────────┘ │
401
- └──────────────────────────┬───────────────────────────────┘
402
- ▼
403
- ┌──────────────────────────────────────────────────────────┐
404
- │ 存储层 │
405
- │ ┌─────────────────────┐ ┌────────────────────────────┐ │
406
- │ │ LanceDB │ │ Jina Embeddings v5 │ │
407
- │ │(向量 + 列式存储) │ │(1024 维,任务感知) │ │
408
- │ └─────────────────────┘ └────────────────────────────┘ │
409
- └──────────────────────────────────────────────────────────┘
410
- ```
411
-
412
- ### 内部设计
413
-
414
- - **L0 / L1 / L2 动态折叠** —— 每条记忆存储 3 个粒度层(一句话 / 要点概要 / 完整内容);检索时根据相关性分数和 token 预算动态选择返回哪个层级
415
- - **Weibull 衰减 + 情绪调制** —— 记忆沿参数化 Weibull 曲线衰减;情绪显著性可额外延长半衰期最高 30%
416
- - **向量预筛 + LLM 去重** —— 90% 的去重决策用低成本余弦相似度(≥ 0.92);仅临界情况调用 LLM 判断
417
- - **类别分化合并策略** —— `profile` 和 `preferences` 采用冲突合并(新版覆盖);`events` 和 `cases` 采用追加(保留历史)
418
- - **展示分 vs 淘汰分双轨制** —— 检索使用双轨评分:tier floor 防止核心记忆被淘汰,decay boost 让新鲜记忆临时浮现而不永久挤掉稳定记忆
344
+ | | 枚举 | 补集 |
345
+ |---|---|---|
346
+ | AI 产的图 | 5,812 | **10,938** |
347
+ | 有图的 session | 1,507 | **1,767** |
348
+ | 人贴的图 | 1,629 | 1,629 |
419
349
 
420
- > 完整架构详解:[`docs/architecture.md`](docs/architecture.md)
350
+ **枚举漏掉了 5,126 张图和 376 个 session**,接近一半。漏得最多的是**生图**——它待在那份清单
351
+ 知道的两个容器之外。而人贴的图在两种口径下数字完全一致,这正是关键的校验点:放宽第二类
352
+ 没有污染精确的第一类。有一条回归测试钉住这件事:它喂给解析器一个源码里从未出现过的
353
+ `image_generation_call`,断言它落进第二类;在枚举式实现下那条测试必红。
421
354
 
422
- ---
355
+ 一点诚实的说明:补集数的是*信号*,不是确认过的图片张数。一次生图可能同时留下调用和完成
356
+ 两条记录,被数成两张。这个方向是刻意选的——它要回答的是"这儿有没有东西可看",而不是
357
+ "到底几张"。
423
358
 
424
359
  ## 接口
425
360
 
@@ -487,7 +422,7 @@ RecallNest 提供两种接口:
487
422
  | `data_checkup` | 运行数据质量健康检查 |
488
423
  | `dream` | 离线记忆整合(聚类、合并、修剪) |
489
424
  | `memory_lint` | 记忆质量检查:矛盾、重复、过期、孤儿 |
490
- | `forget_memory` | 级联删除记忆 + KG 清理 + Pin 归档 + 审计 |
425
+ | `forget_memory` | 删除记忆,连同它的 KG 三元组、trigger 行和由它生成的 pin 的索引副本,pin 文件归档,删后回读核对,写审计 |
491
426
  | `export_graph` | 导出交互式 HTML 知识图谱 |
492
427
 
493
428
  </details>
@@ -557,7 +492,7 @@ bun run src/cli.ts lint --scope project:myapp # 指定 scope
557
492
  bun run src/cli.ts graph --open # 导出并打开知识图谱
558
493
  bun run src/cli.ts graph --max-nodes 50 # 较小的图
559
494
 
560
- # 导入与诊断
495
+ # 导入与诊断(对话原文默认不入库,见「索引已有对话」)
561
496
  bun run src/cli.ts ingest --source all
562
497
  bun run src/cli.ts doctor
563
498
  ```
@@ -566,6 +501,50 @@ bun run src/cli.ts doctor
566
501
 
567
502
  ---
568
503
 
504
+ ## Web UI
505
+
506
+ <p align="center">
507
+ <img src="assets/dashboard.png" alt="RecallNest Dashboard" width="800" />
508
+ <br><em>Dashboard —— 总量、类别分布、健康评分、增长趋势一目了然。</em>
509
+ </p>
510
+
511
+ <p align="center">
512
+ <img src="assets/screenshots/ui-full.png" alt="RecallNest Search Workbench" width="800" />
513
+ <br><em>Search Workbench —— 混合检索 + Topic Tag 过滤 + 4 套检索策略 + Skills 浏览 + 资产管理。</em>
514
+ </p>
515
+
516
+ <p align="center">
517
+ <img src="assets/knowledge-graph.png" alt="RecallNest Knowledge Graph" width="800" />
518
+ <br><em>Knowledge Graph —— 交互式力导向图,语义桥接揭示跨域隐藏关联。</em>
519
+ </p>
520
+
521
+ ```bash
522
+ bun run src/ui-server.ts
523
+ # → http://localhost:4317
524
+ ```
525
+
526
+ ---
527
+
528
+ ## 最近更新
529
+
530
+ **v4.0** 只在 **Bun** 上运行,跨进程锁交给了内核。以前 RecallNest 靠锁文件里的
531
+ pid 和时间戳判断锁是不是过期了,判断过期就删掉重建——两个进程同时看到同一个过期锁,
532
+ 就可能都以为自己拿到了(八个进程抢一把锁,四十轮里最多有三十轮不止一个赢家)。
533
+ 现在用 `flock(2)`:进程退出或被杀,内核自动放锁;压力测试每 15 到 60 毫秒杀掉一个
534
+ 写入进程、连续六秒,临界区里从没出现过两个写方。
535
+
536
+ 这一版其余的修复,针对的都是会悄悄出错的数据:并发更新把刚删掉的记忆写回来、
537
+ 历史行指向不存在的记录、密钥留在 metadata 里还随 trigger 发给嵌入接口、
538
+ 搜 `git push 规则`、`#22` 这类查询直接返回空、写入被拒却在回执里报成已保存。
539
+
540
+ **升级:**先装 Bun,再停掉全部 RecallNest 进程后启动 v4——新旧两版的锁不能同时跑。
541
+ 有几处默认值和 HTTP 返回变了,清单在 CHANGELOG 的 v4.0.0 一节开头。
542
+ 已有的 LanceDB 数据原地打开。
543
+
544
+ **完整变更历史(v4.0 到 v1.0,含每个版本的升级说明)在
545
+ [CHANGELOG.md](CHANGELOG.md)。**
546
+
547
+
569
548
  ## 多语言支持
570
549
 
571
550
  RecallNest 开箱即用支持英文。如需多语言记忆(中文、日文、泰文及 20+ 种语言),安装 [babel-memory](https://github.com/AliceLJY/babel-memory) 及所需语言包:
package/assets/ui/app.js CHANGED
@@ -808,7 +808,12 @@ async function cleanDirtyBriefs() {
808
808
  await loadPins();
809
809
  await loadStats();
810
810
  renderMainSurface();
811
- statusLine.textContent = data.count > 0 ? 'Dirty briefs archived.' : 'No dirty briefs found.';
811
+ const unreadable = (data.readErrors || []).length;
812
+ if (unreadable > 0) {
813
+ statusLine.textContent = `${data.count > 0 ? 'Dirty briefs archived; ' : ''}${unreadable} brief file(s) could not be read.`;
814
+ } else {
815
+ statusLine.textContent = data.count > 0 ? 'Dirty briefs archived.' : 'No dirty briefs found.';
816
+ }
812
817
  } catch (error) {
813
818
  resultOutput.textContent = String(error.message || error);
814
819
  statusLine.textContent = 'Dirty brief cleanup failed.';
@@ -1,13 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * RecallNest CLI launcher — cross-runtime compatible
3
+ * RecallNest CLI launcher.
4
4
  *
5
- * Priority: bun (native TS, fastest) → node + tsx (fallback)
5
+ * RecallNest runs on Bun only: its cross-process lock calls flock(2) through bun:ffi
6
+ * (src/flock.ts), which Node cannot load. This launcher is plain JavaScript so that `npx` /
7
+ * a global npm install can start it under any runtime; it only ever hands off to Bun, and
8
+ * without Bun it exits with instructions instead of trying another runtime.
6
9
  */
7
10
  import { spawn, execFileSync } from "node:child_process";
8
11
  import { dirname, join } from "node:path";
9
12
  import { fileURLToPath } from "node:url";
10
- import { existsSync } from "node:fs";
11
13
 
12
14
  const __dirname = dirname(fileURLToPath(import.meta.url));
13
15
  const cli = join(__dirname, "..", "src", "cli.ts");
@@ -22,41 +24,22 @@ function hasBun() {
22
24
  }
23
25
  }
24
26
 
25
- function run(command, commandArgs) {
26
- const child = spawn(command, commandArgs, { stdio: "inherit" });
27
- child.on("close", (code) => process.exit(code || 0));
28
- child.on("error", (err) => {
29
- console.error(`Failed to start ${command}: ${err.message}`);
30
- process.exit(1);
31
- });
32
- }
33
-
34
- if (hasBun()) {
35
- // Native bun — fastest path
36
- run("bun", ["run", cli, ...args]);
37
- } else {
38
- // Fallback: node + tsx
39
- const tsxBin = join(__dirname, "..", "node_modules", ".bin", "tsx");
40
- if (existsSync(tsxBin)) {
41
- run(tsxBin, [cli, ...args]);
42
- } else {
43
- // tsx not found in local node_modules, try global
44
- try {
45
- execFileSync("tsx", ["--version"], { stdio: "ignore" });
46
- run("tsx", [cli, ...args]);
47
- } catch {
48
- console.error(`
49
- RecallNest requires either Bun or tsx to run TypeScript.
50
-
51
- Option A (recommended):
52
- curl -fsSL https://bun.sh/install | bash
27
+ if (!hasBun()) {
28
+ console.error(`
29
+ RecallNest requires Bun (https://bun.sh) — it does not run on Node.js.
53
30
 
54
- Option B:
55
- npm install -g tsx
31
+ Install Bun:
32
+ curl -fsSL https://bun.sh/install | bash # macOS / Linux
33
+ brew install oven-sh/bun/bun # or with Homebrew
56
34
 
57
- Then retry your command.
35
+ Then open a new shell (so \`bun\` is on PATH) and retry your command.
58
36
  `);
59
- process.exit(1);
60
- }
61
- }
37
+ process.exit(1);
62
38
  }
39
+
40
+ const child = spawn("bun", ["run", cli, ...args], { stdio: "inherit" });
41
+ child.on("close", (code) => process.exit(code || 0));
42
+ child.on("error", (err) => {
43
+ console.error(`Failed to start bun: ${err.message}`);
44
+ process.exit(1);
45
+ });