recallnest 1.4.1 → 2.2.1

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 (233) hide show
  1. package/.env +4 -0
  2. package/CLAUDE.md +7 -3
  3. package/README.md +202 -130
  4. package/README_CN.md +263 -190
  5. package/bin/recallnest.mjs +62 -0
  6. package/config.json +55 -0
  7. package/daily-recall.sh +23 -0
  8. package/integrations/setup-all.sh +31 -0
  9. package/logs/daily-recall.error.log +0 -0
  10. package/logs/daily-recall.log +30 -0
  11. package/logs/ingest-2026-04-11.log +110 -0
  12. package/logs/ingest-2026-04-12.log +90 -0
  13. package/logs/launchagent-stderr.log +0 -0
  14. package/logs/launchagent-stdout.log +0 -0
  15. package/package.json +10 -3
  16. package/src/access-tracker.ts +3 -2
  17. package/src/activity-counter.ts +109 -0
  18. package/src/adaptive-retrieval.ts +6 -5
  19. package/src/admission-control.ts +163 -0
  20. package/src/anchor-generator.ts +80 -0
  21. package/src/api-server.ts +10 -0
  22. package/src/audit-log.ts +122 -0
  23. package/src/auto-gc.ts +98 -29
  24. package/src/auto-recall.ts +33 -4
  25. package/src/capture-engine.ts +372 -23
  26. package/src/cascade-forget.ts +3 -2
  27. package/src/cli.ts +107 -5
  28. package/src/compat.ts +22 -0
  29. package/src/confidence-tracker.ts +210 -47
  30. package/src/conflict-store.ts +12 -3
  31. package/src/consolidation-engine.ts +296 -8
  32. package/src/context-collapse-renderer.ts +222 -0
  33. package/src/context-composer-stable-selection.ts +5 -1
  34. package/src/context-composer.ts +239 -4
  35. package/src/context-reconstructor.ts +404 -0
  36. package/src/conversation-importer.ts +441 -0
  37. package/src/data-checkup.ts +232 -0
  38. package/src/decay-engine.ts +84 -0
  39. package/src/distill-lock.ts +122 -0
  40. package/src/doctor.ts +8 -10
  41. package/src/dream-pipeline.ts +227 -0
  42. package/src/emotion-detector.ts +90 -0
  43. package/src/eval.ts +3 -2
  44. package/src/forget-engine.ts +269 -0
  45. package/src/frequency-tracker.ts +175 -0
  46. package/src/graph-export.ts +644 -0
  47. package/src/ingest.ts +36 -6
  48. package/src/interference-detector.ts +187 -0
  49. package/src/kg-extractor.ts +15 -24
  50. package/src/kg-store.ts +2 -1
  51. package/src/language-hook.ts +67 -0
  52. package/src/llm-client.ts +289 -6
  53. package/src/mcp-server.ts +707 -80
  54. package/src/memory-assets.ts +22 -5
  55. package/src/memory-evolution.ts +365 -0
  56. package/src/memory-lint.ts +429 -0
  57. package/src/memory-output.ts +69 -0
  58. package/src/memory-schema.ts +74 -2
  59. package/src/narrative-schema.ts +79 -0
  60. package/src/narrative-tagger.ts +164 -0
  61. package/src/pii-detector.ts +98 -0
  62. package/src/post-retrieval-filter.ts +76 -0
  63. package/src/prediction-engine.ts +253 -0
  64. package/src/preference-slots.ts +65 -2
  65. package/src/prospective-memory.ts +215 -0
  66. package/src/query-expander.ts +67 -0
  67. package/src/recall-governor.ts +183 -0
  68. package/src/retention-policy.ts +90 -0
  69. package/src/retriever.ts +828 -55
  70. package/src/rif.ts +34 -8
  71. package/src/runtime-config.ts +23 -8
  72. package/src/scope-inventory.ts +4 -3
  73. package/src/scope-policy.ts +4 -0
  74. package/src/session-distiller.ts +307 -0
  75. package/src/session-output.ts +40 -0
  76. package/src/session-schema.ts +37 -0
  77. package/src/session-store.ts +7 -2
  78. package/src/skill-engine.ts +208 -0
  79. package/src/skill-promotion.ts +293 -0
  80. package/src/skill-schema.ts +39 -0
  81. package/src/store.ts +96 -10
  82. package/src/topic-tag.ts +66 -0
  83. package/src/tracker.ts +3 -1
  84. package/src/ui-server.ts +80 -8
  85. package/src/workflow-observation-scope-review.ts +2 -1
  86. package/src/workflow-observation-store.ts +2 -1
  87. package/src/write-verifier.ts +126 -0
  88. package/.claude-plugin/CLAUDE.md +0 -29
  89. package/.claude-plugin/marketplace.json +0 -18
  90. package/.github/workflows/ci.yml +0 -28
  91. package/.mcp.json +0 -9
  92. package/CHANGELOG.md +0 -51
  93. package/DEMO.md +0 -94
  94. package/EVAL.md +0 -89
  95. package/FAILURES.md +0 -75
  96. package/OPERATIONS.md +0 -59
  97. package/ROADMAP.md +0 -198
  98. package/assets/recallnest-workbench.png +0 -0
  99. package/assets/ui/app.js +0 -807
  100. package/assets/ui/index.html +0 -154
  101. package/assets/ui/styles.css +0 -605
  102. package/assets/wechat-qr.jpg +0 -0
  103. package/daily-reflections/2026-03-05.md +0 -15
  104. package/daily-reflections/2026-03-06.md +0 -15
  105. package/daily-reflections/2026-03-07.md +0 -7
  106. package/daily-reflections/2026-03-08.md +0 -34
  107. package/daily-reflections/2026-03-09.md +0 -35
  108. package/daily-reflections/2026-03-10.md +0 -36
  109. package/daily-reflections/2026-03-11.md +0 -35
  110. package/daily-reflections/2026-03-12.md +0 -36
  111. package/daily-reflections/2026-03-13.md +0 -35
  112. package/daily-reflections/2026-03-14.md +0 -35
  113. package/daily-reflections/2026-03-15.md +0 -35
  114. package/daily-reflections/2026-03-16.md +0 -41
  115. package/daily-reflections/2026-03-17.md +0 -10
  116. package/daily-reflections/2026-03-18.md +0 -10
  117. package/daily-reflections/2026-03-19.md +0 -10
  118. package/daily-reflections/2026-03-20.md +0 -10
  119. package/daily-reflections/2026-03-21.md +0 -10
  120. package/daily-reflections/2026-03-22.md +0 -10
  121. package/daily-reflections/2026-03-23.md +0 -10
  122. package/daily-reflections/2026-03-24.md +0 -10
  123. package/daily-reflections/2026-03-25.md +0 -32
  124. package/daily-reflections/2026-03-26.md +0 -37
  125. package/daily-reflections/2026-03-27.md +0 -35
  126. package/daily-reflections/2026-03-28.md +0 -35
  127. package/daily-reflections/2026-03-29.md +0 -35
  128. package/daily-reflections/2026-03-30.md +0 -36
  129. package/daily-reflections/2026-03-31.md +0 -35
  130. package/daily-reflections/2026-04-01.md +0 -35
  131. package/docs/api-reference.md +0 -1291
  132. package/docs/architecture.md +0 -168
  133. package/docs/memory-boundary-contract.md +0 -226
  134. package/docs/memory-categories.md +0 -119
  135. package/docs/pipeline-audit-ultramemory.md +0 -177
  136. package/docs/plans/2026-03-08-query-expansion.md +0 -270
  137. package/docs/plans/2026-03-16-continuity-layer.md +0 -196
  138. package/docs/plans/mcp-tiering-plan.md +0 -126
  139. package/docs/research/recall-quality-audit-2026-03-22.md +0 -153
  140. package/docs/self-evolution.md +0 -198
  141. package/docs/superpowers/plans/2026-03-19-ingest-pipeline-upgrade.md +0 -782
  142. package/docs/superpowers/specs/2026-03-19-ingest-pipeline-upgrade-design.md +0 -77
  143. package/docs/superpowers/specs/2026-03-23-pull-claude-desktop-design.md +0 -95
  144. package/eval/continuity/results-2026-03-16.md +0 -117
  145. package/eval/continuity/results-2026-03-19.md +0 -453
  146. package/eval/continuity/runbook.md +0 -110
  147. package/eval/continuity/seed-cases.md +0 -54
  148. package/eval/reports/2026-03-06-abstract-query-baseline.md +0 -96
  149. package/eval/reports/2026-03-06-aws-ssh-baseline.md +0 -82
  150. package/eval/reports/2026-03-06-baseline.md +0 -82
  151. package/eval/reports/query-expansion.md +0 -138
  152. package/lm +0 -19
  153. package/plan-v1.2-distributable.md +0 -105
  154. package/scripts/archive-distilled-junk.ts +0 -116
  155. package/scripts/backfill-l0l1l2.ts +0 -98
  156. package/scripts/blind-scan.ts +0 -588
  157. package/scripts/cleanup-step1-exact-dups.ts +0 -117
  158. package/scripts/cleanup-step2-template-dups.ts +0 -113
  159. package/scripts/cleanup-step3-stale-content.ts +0 -149
  160. package/scripts/cleanup-step4-orphan-scopes.ts +0 -131
  161. package/scripts/delete-distilled-junk.ts +0 -88
  162. package/scripts/distill-facts.ts +0 -305
  163. package/scripts/health-check.ts +0 -343
  164. package/scripts/incremental-ingest.sh +0 -71
  165. package/scripts/mlp-health-check.ts +0 -382
  166. package/scripts/pull-claude-desktop.ts +0 -515
  167. package/scripts/re-ingest-cc.sh +0 -66
  168. package/scripts/rebalance-memory-health.ts +0 -181
  169. package/scripts/run-desktop-ingest.sh +0 -11
  170. package/scripts/start-server.sh +0 -12
  171. package/scripts/viz-dashboard.html +0 -423
  172. package/scripts/viz-export.ts +0 -703
  173. package/src/__tests__/access-tracker-novelty.test.ts +0 -228
  174. package/src/__tests__/auto-consolidation.test.ts +0 -168
  175. package/src/__tests__/auto-recall.test.ts +0 -131
  176. package/src/__tests__/batch-dedup.test.ts +0 -65
  177. package/src/__tests__/capture-engine.test.ts +0 -1142
  178. package/src/__tests__/capture-heuristic.test.ts +0 -171
  179. package/src/__tests__/cascade-forget.test.ts +0 -210
  180. package/src/__tests__/category-min-scores.test.ts +0 -33
  181. package/src/__tests__/confidence-tracker.test.ts +0 -196
  182. package/src/__tests__/conflict-advisor.test.ts +0 -206
  183. package/src/__tests__/conflict-escalation.test.ts +0 -149
  184. package/src/__tests__/conflict-lifecycle.test.ts +0 -83
  185. package/src/__tests__/conflict-output.test.ts +0 -85
  186. package/src/__tests__/conflict-store.test.ts +0 -374
  187. package/src/__tests__/consolidation-engine.test.ts +0 -181
  188. package/src/__tests__/context-composer-pins.test.ts +0 -64
  189. package/src/__tests__/context-composer-task-selection.test.ts +0 -24
  190. package/src/__tests__/context-renderer.test.ts +0 -91
  191. package/src/__tests__/continuity-eval.test.ts +0 -275
  192. package/src/__tests__/continuity-schema.test.ts +0 -97
  193. package/src/__tests__/core-recall-eval.test.ts +0 -235
  194. package/src/__tests__/core-summary.test.ts +0 -109
  195. package/src/__tests__/dedup-actions.test.ts +0 -58
  196. package/src/__tests__/deterministic-id.test.ts +0 -39
  197. package/src/__tests__/doctor.test.ts +0 -303
  198. package/src/__tests__/drill-down.test.ts +0 -108
  199. package/src/__tests__/embedder.test.ts +0 -122
  200. package/src/__tests__/entity-resolver.test.ts +0 -58
  201. package/src/__tests__/event-segmenter.test.ts +0 -153
  202. package/src/__tests__/hotness-blend.test.ts +0 -76
  203. package/src/__tests__/ingest.test.ts +0 -360
  204. package/src/__tests__/kg-extractor.test.ts +0 -184
  205. package/src/__tests__/kg-store.test.ts +0 -198
  206. package/src/__tests__/llm-consolidation.test.ts +0 -226
  207. package/src/__tests__/memory-boundaries.test.ts +0 -237
  208. package/src/__tests__/memory-health-rebalance.test.ts +0 -144
  209. package/src/__tests__/memory-output.test.ts +0 -215
  210. package/src/__tests__/multi-vector.test.ts +0 -242
  211. package/src/__tests__/ppr-traversal.test.ts +0 -256
  212. package/src/__tests__/preference-guard-smoke.test.ts +0 -211
  213. package/src/__tests__/preference-matcher.test.ts +0 -230
  214. package/src/__tests__/preference-slots.test.ts +0 -106
  215. package/src/__tests__/prospective-memory.test.ts +0 -283
  216. package/src/__tests__/query-entity-detector.test.ts +0 -171
  217. package/src/__tests__/query-expander.test.ts +0 -34
  218. package/src/__tests__/recall-mode.test.ts +0 -64
  219. package/src/__tests__/result-synthesizer.test.ts +0 -198
  220. package/src/__tests__/resume-context.test.ts +0 -4743
  221. package/src/__tests__/retrieval-trace.test.ts +0 -213
  222. package/src/__tests__/retriever-boundary-weight.test.ts +0 -136
  223. package/src/__tests__/retroactive-boost.test.ts +0 -223
  224. package/src/__tests__/scope-inventory.test.ts +0 -200
  225. package/src/__tests__/scope-policy.test.ts +0 -69
  226. package/src/__tests__/session-checkpoint.test.ts +0 -259
  227. package/src/__tests__/session-gc.test.ts +0 -215
  228. package/src/__tests__/store-scope-audit.test.ts +0 -81
  229. package/src/__tests__/temporal-parser.test.ts +0 -241
  230. package/src/__tests__/term-registry.test.ts +0 -121
  231. package/src/__tests__/tool-output-compressor.test.ts +0 -133
  232. package/src/__tests__/version-manager.test.ts +0 -213
  233. package/src/__tests__/workflow-observation.test.ts +0 -400
package/config.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "dbPath": "./data/lancedb",
3
+ "recallMode": "full",
4
+ "embedding": {
5
+ "provider": "jina",
6
+ "apiKey": "${JINA_API_KEY}",
7
+ "model": "jina-embeddings-v5-text-small",
8
+ "baseURL": "https://api.jina.ai/v1",
9
+ "dimensions": 1024,
10
+ "taskQuery": "retrieval.query",
11
+ "taskPassage": "retrieval.passage"
12
+ },
13
+ "llm": {
14
+ "apiKey": "${QWEN_API_KEY}",
15
+ "model": "qwen-turbo",
16
+ "baseURL": "https://dashscope.aliyuncs.com/compatible-mode/v1"
17
+ },
18
+ "sources": {
19
+ "cc": {
20
+ "path": "auto",
21
+ "glob": "*.jsonl",
22
+ "description": "Claude Code transcripts"
23
+ },
24
+ "codex": {
25
+ "path": "~/.codex/sessions",
26
+ "glob": "*.jsonl",
27
+ "description": "Codex sessions"
28
+ },
29
+ "memory": {
30
+ "path": "auto",
31
+ "glob": "*.md",
32
+ "description": "Claude Code memory files"
33
+ },
34
+ "gemini": {
35
+ "path": "~/.gemini/tmp",
36
+ "glob": "session-*.json",
37
+ "description": "Gemini CLI sessions"
38
+ },
39
+ "desktop": {
40
+ "path": "./data/desktop-import",
41
+ "glob": "*.jsonl",
42
+ "description": "Claude Desktop / claude.ai web conversations"
43
+ }
44
+ },
45
+ "retrieval": {
46
+ "mode": "hybrid",
47
+ "vectorWeight": 0.6,
48
+ "bm25Weight": 0.4,
49
+ "recencyHalfLifeDays": 30,
50
+ "timeDecayHalfLifeDays": 60,
51
+ "hardMinScore": 0.38,
52
+ "hotnessWeight": 0.15
53
+ },
54
+ "recallDepthDefault": "l1"
55
+ }
package/daily-recall.sh CHANGED
@@ -48,6 +48,25 @@ TODAY_QUERY="${QUERIES[$IDX]}"
48
48
 
49
49
  echo " 今日主题 (#$((IDX+1))): $TODAY_QUERY" | tee -a "$LOG_FILE"
50
50
 
51
+ # ── CC-6 + HP-3: Distill gate — lock + session gate + activity gate ─────
52
+ echo " 检查 distill gate..." | tee -a "$LOG_FILE"
53
+ GATE_RESULT=$(bun -e "
54
+ const { acquireLock, shouldDistill } = require('./src/distill-lock.ts');
55
+ const { getDistillTier } = require('./src/activity-counter.ts');
56
+ const cp = parseInt(process.argv[1] || '0', 10);
57
+ const tier = getDistillTier();
58
+ const sessionReady = shouldDistill(cp);
59
+ if (tier === 'none' && !sessionReady) { console.log('SKIP:no_activity'); process.exit(0); }
60
+ if (!acquireLock()) { console.log('SKIP:lock_held'); process.exit(0); }
61
+ console.log('OK:' + tier);
62
+ " "$(bun run "$SCRIPT_DIR/src/cli.ts" checkpoint-count 2>/dev/null || echo 5)" 2>&1 || echo "OK:standard")
63
+
64
+ if [[ "$GATE_RESULT" == SKIP:* ]]; then
65
+ echo " [跳过] distill gate: $GATE_RESULT" | tee -a "$LOG_FILE"
66
+ else
67
+ echo " distill gate: $GATE_RESULT" | tee -a "$LOG_FILE"
68
+ fi
69
+
51
70
  # ── 用 lm distill 提取结构化洞察 ──────────────────────────────
52
71
  echo " 执行 distill..." | tee -a "$LOG_FILE"
53
72
  DISTILL_OUTPUT=$("$LM" distill "$TODAY_QUERY" --profile writing --limit 8 --all-scopes 2>&1 || true)
@@ -64,6 +83,10 @@ fi
64
83
 
65
84
  echo " distill 完成,$(echo "$DISTILL_OUTPUT" | wc -l | tr -d ' ') 行" | tee -a "$LOG_FILE"
66
85
 
86
+ # CC-6: Release lock on success + HP-3: Reset activity counter
87
+ bun -e "try { require('./src/distill-lock.ts').releaseLock(); } catch {}" 2>/dev/null || true
88
+ bun -e "try { require('./src/activity-counter.ts').resetWriteCount(); } catch {}" 2>/dev/null || true
89
+
67
90
  # ── 写入输出文件 ──────────────────────────────────────────────
68
91
  cat > "$OUTPUT_FILE" << EOF
69
92
  # 每日回顾 · $DATE
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env bash
2
+ # RecallNest — setup all three terminals at once (idempotent)
3
+ # Usage: bash integrations/setup-all.sh
4
+
5
+ set -euo pipefail
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+
9
+ echo "RecallNest — setting up all terminals"
10
+ echo "======================================"
11
+ echo ""
12
+
13
+ echo "--- Claude Code ---"
14
+ bash "$SCRIPT_DIR/claude-code/setup.sh"
15
+ echo ""
16
+
17
+ echo "--- Codex ---"
18
+ bash "$SCRIPT_DIR/codex/setup.sh"
19
+ echo ""
20
+
21
+ echo "--- Gemini CLI ---"
22
+ bash "$SCRIPT_DIR/gemini-cli/setup.sh"
23
+ echo ""
24
+
25
+ echo "======================================"
26
+ echo "All terminals configured."
27
+ echo ""
28
+ echo "Next steps:"
29
+ echo " 1. Restart each terminal"
30
+ echo " 2. Run: bun run seed:continuity"
31
+ echo " 3. Run: bun run src/cli.ts doctor"
File without changes
@@ -0,0 +1,30 @@
1
+ === 2026-04-12 08:00:01 daily-recall 开始 ===
2
+ === 2026-04-12 08:00:01 daily-recall 开始 ===
3
+ 今日主题 (#7): 踩坑 修复 经验总结
4
+ 今日主题 (#7): 踩坑 修复 经验总结
5
+ 检查 distill gate...
6
+ 检查 distill gate...
7
+ distill gate:
8
+ distill gate:
9
+ 执行 distill...
10
+ 执行 distill...
11
+ distill 完成,27 行
12
+ distill 完成,27 行
13
+ [完成] 回顾已写入: /Users/anxianjingya/recallnest/daily-reflections/2026-04-12.md
14
+ [完成] 回顾已写入: /Users/anxianjingya/recallnest/daily-reflections/2026-04-12.md
15
+ 执行 checkpoint-gc...
16
+ 执行 checkpoint-gc...
17
+ checkpoint-gc: === Checkpoint GC ===
18
+
19
+ Kept : 217
20
+ Archived : 0
21
+ Deleted : 0
22
+ Errors : 0
23
+ checkpoint-gc: === Checkpoint GC ===
24
+
25
+ Kept : 217
26
+ Archived : 0
27
+ Deleted : 0
28
+ Errors : 0
29
+ === 2026-04-12 08:00:13 daily-recall 结束 ===
30
+ === 2026-04-12 08:00:13 daily-recall 结束 ===
@@ -0,0 +1,110 @@
1
+ === 2026-04-11 19:22:04 增量更新开始 ===
2
+ [INFO] LLM client initialized: qwen-turbo @ https://dashscope.aliyuncs.com/compatible-mode/v1
3
+
4
+ 🔑 验证 Embedding API...
5
+ ✅ jina-embeddings-v5-text-small (1024d)
6
+ ✅ LLM: qwen-turbo (L0 摘要 + 语义去重)
7
+ ✅ 两阶段去重: vector + LLM 语义判断
8
+
9
+ 🔄 开始导入记忆 (source: all)...
10
+
11
+ 📝 导入 Claude Code 对话...
12
+ CC: 230/962 files, 120 chunks ingested
13
+ CC: 470/962 files, 186 chunks ingested
14
+ [INFO] noise-filter: denial pattern matched: "**Phase 5: Predictive Prospective Memory — DONE** ✅
15
+
16
+ 总结一下做了什..."
17
+ ✅ CC: 24 files, 528 ingested, 474 deduped (hard:17, exact:160, llm-skip:150, llm-merge:147), 0 errors
18
+ 🤖 导入 Codex 对话...
19
+ [INFO] noise-filter: meta-question filtered: "# AGENTS.md instructions for /Users/anxianjingya/Projects/re..."
20
+ [INFO] noise-filter: meta-question filtered: "# AGENTS.md instructions for /Users/anxianjingya
21
+
22
+ <INSTRUCTI..."
23
+ Codex: 294/294 files, 39 chunks ingested
24
+ ✅ Codex: 2 files, 39 ingested, 22 deduped (hard:6, exact:0, llm-skip:8, llm-merge:8), 0 errors
25
+ 💎 导入 Gemini 对话...
26
+ ✅ Gemini: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
27
+ 🖥️ 导入 Claude Desktop 对话...
28
+ CC: 10/349 files, 43 chunks ingested
29
+ [INFO] noise-filter: denial pattern matched: "好的!我来手把手教你!别担心,超简单! 😊
30
+
31
+ ---
32
+
33
+ ## 📍 **Step 1: 找到文件在哪**
34
+
35
+ 我刚才给你..."
36
+ CC: 20/349 files, 70 chunks ingested
37
+ CC: 30/349 files, 73 chunks ingested
38
+ [INFO] noise-filter: short boilerplate filtered: "好的,我来帮你截图。"
39
+ CC: 40/349 files, 160 chunks ingested
40
+ CC: 50/349 files, 180 chunks ingested
41
+ CC: 60/349 files, 226 chunks ingested
42
+ CC: 70/349 files, 256 chunks ingested
43
+ [INFO] noise-filter: meta-question filtered: "你记不记得我让你帮我弄孩子们的简历..."
44
+ [INFO] noise-filter: denial pattern matched: "我查找一下我们之前关于孩子们简历的对话...
45
+
46
+ 让我搜索一下相关内容。
47
+
48
+ 我没有找到我们之前讨论过帮孩子们制作简历的记录..."
49
+ CC: 80/349 files, 316 chunks ingested
50
+ CC: 90/349 files, 335 chunks ingested
51
+ CC: 100/349 files, 412 chunks ingested
52
+ CC: 110/349 files, 501 chunks ingested
53
+ CC: 120/349 files, 520 chunks ingested
54
+ [INFO] noise-filter: boilerplate filtered: "Hello! How can I help you today?..."
55
+ [INFO] noise-filter: denial pattern matched: "不能。我无法访问你本地电脑上的文件或 Claude Code 的 session 记录。
56
+
57
+ 我能访问的是:
58
+ 1. **我..."
59
+ [INFO] noise-filter: denial pattern matched: "这个我不太确定,因为 Claude Desktop 的会话索引存在 `~/Library/Application Sup..."
60
+ [INFO] noise-filter: boilerplate filtered: "Hi Alice,
61
+ I understand you're looking for a way to rebuild t..."
62
+ CC: 130/349 files, 547 chunks ingested
63
+ CC: 140/349 files, 585 chunks ingested
64
+ [INFO] noise-filter: denial pattern matched: "啊,你说得对!我理解错了。
65
+
66
+ 让我重新想想这个问题...
67
+
68
+ Antigravity 确实也是通过 Claude in C..."
69
+ CC: 150/349 files, 618 chunks ingested
70
+ [INFO] noise-filter: denial pattern matched: "我来帮你查看workspace里的PPT相关文件,分析其逻辑是否与截图中描述的一致。
71
+
72
+ 让我先看看目录结构:
73
+ 我看到wo..."
74
+ CC: 160/349 files, 659 chunks ingested
75
+ CC: 170/349 files, 681 chunks ingested
76
+ [INFO] noise-filter: denial pattern matched: "我不确定Claude Opus 4.5的具体知识截止日期是否与我的相同。
77
+
78
+ 让我搜索一下Anthropic官方文档来确认..."
79
+ CC: 180/349 files, 685 chunks ingested
80
+ CC: 190/349 files, 694 chunks ingested
81
+ CC: 210/349 files, 919 chunks ingested
82
+ CC: 220/349 files, 927 chunks ingested
83
+ CC: 230/349 files, 956 chunks ingested
84
+ CC: 240/349 files, 977 chunks ingested
85
+ CC: 250/349 files, 1018 chunks ingested
86
+ CC: 260/349 files, 1030 chunks ingested
87
+ CC: 270/349 files, 1048 chunks ingested
88
+ CC: 280/349 files, 1185 chunks ingested
89
+ CC: 290/349 files, 1196 chunks ingested
90
+ [INFO] noise-filter: boilerplate filtered: "Hi Alice! Here's what I've learned about you from our past c..."
91
+ CC: 300/349 files, 1211 chunks ingested
92
+ CC: 310/349 files, 1243 chunks ingested
93
+ CC: 320/349 files, 1276 chunks ingested
94
+ [INFO] noise-filter: denial pattern matched: "我想不起来给你的这些提示词和视觉skill是哪里来的..."
95
+ [INFO] noise-filter: denial pattern matched: "* 全网AI集体翻车?为了读一篇公众号文章,我扒开了Grok的“谎言”
96
+ * Gemini、Claude、元宝全试了,竟..."
97
+ [INFO] noise-filter: denial pattern matched: "让我先查看歌舞剧院的总结,提取人才相关数据:
98
+ 好的,我现在已经了解了录音中领导的修改意见和两家院团的总结内容。根据领导的..."
99
+ CC: 330/349 files, 1331 chunks ingested
100
+ CC: 340/349 files, 1348 chunks ingested
101
+ CC: 349/349 files, 1372 chunks ingested
102
+ ✅ Desktop: 343 files, 1372 ingested, 3805 deduped (hard:440, exact:1721, llm-skip:1045, llm-merge:599), 0 errors
103
+ 📚 导入记忆文件...
104
+ ✅ Memory: 8 files, 11 ingested, 279 deduped (hard:0, exact:257, llm-skip:15, llm-merge:7), 0 errors
105
+
106
+ 📊 导入汇总:
107
+ 总计: 1950 chunks 已索引, 4580 chunks 去重 (hard:463, exact:2138, llm-skip:1218, llm-merge:761), 0 errors
108
+
109
+ === 2026-04-11 20:37:10 增量更新完成 ===
110
+
@@ -0,0 +1,90 @@
1
+ === 2026-04-12 03:00:01 增量更新开始 ===
2
+ [INFO] LLM client initialized: qwen-turbo @ https://dashscope.aliyuncs.com/compatible-mode/v1
3
+
4
+ 🔑 验证 Embedding API...
5
+ ✅ jina-embeddings-v5-text-small (1024d)
6
+ ✅ LLM: qwen-turbo (L0 摘要 + 语义去重)
7
+ ✅ 两阶段去重: vector + LLM 语义判断
8
+
9
+ 🔄 开始导入记忆 (source: all)...
10
+
11
+ 📝 导入 Claude Code 对话...
12
+ [INFO] noise-filter: denial pattern matched: "<task-notification>
13
+ <task-id>ac1e8c3a46f90bcc6</task-id>
14
+ <to..."
15
+ CC: 400/976 files, 269 chunks ingested
16
+ [INFO] noise-filter: denial pattern matched: "完全破案了。
17
+
18
+ **根因:4月10日 22:55(新加坡时间)发生了一次批量仓库可见性修改**
19
+
20
+ 时间线还原:
21
+
22
+ | U..."
23
+ CC: 770/976 files, 541 chunks ingested
24
+ ✅ CC: 19 files, 563 ingested, 505 deduped (hard:24, exact:228, llm-skip:114, llm-merge:139), 0 errors
25
+ 🤖 导入 Codex 对话...
26
+ ✅ Codex: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
27
+ 💎 导入 Gemini 对话...
28
+ ✅ Gemini: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
29
+ 🖥️ 导入 Claude Desktop 对话...
30
+ ✅ Desktop: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
31
+ 📚 导入记忆文件...
32
+ ✅ Memory: 5 files, 4 ingested, 188 deduped (hard:0, exact:172, llm-skip:13, llm-merge:3), 0 errors
33
+
34
+ 📊 导入汇总:
35
+ 总计: 567 chunks 已索引, 693 chunks 去重 (hard:24, exact:400, llm-skip:127, llm-merge:142), 0 errors
36
+
37
+ === 2026-04-12 03:16:02 增量更新完成 ===
38
+
39
+ === 2026-04-12 11:16:02 增量更新开始 ===
40
+ [INFO] LLM client initialized: qwen-turbo @ https://dashscope.aliyuncs.com/compatible-mode/v1
41
+
42
+ 🔑 验证 Embedding API...
43
+ ✅ jina-embeddings-v5-text-small (1024d)
44
+ ✅ LLM: qwen-turbo (L0 摘要 + 语义去重)
45
+ ✅ 两阶段去重: vector + LLM 语义判断
46
+
47
+ 🔄 开始导入记忆 (source: all)...
48
+
49
+ 📝 导入 Claude Code 对话...
50
+ ✅ CC: 5 files, 141 ingested, 90 deduped (hard:4, exact:24, llm-skip:30, llm-merge:32), 0 errors
51
+ 🤖 导入 Codex 对话...
52
+ ✅ Codex: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
53
+ 💎 导入 Gemini 对话...
54
+ ✅ Gemini: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
55
+ 🖥️ 导入 Claude Desktop 对话...
56
+ ✅ Desktop: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
57
+ 📚 导入记忆文件...
58
+ ✅ Memory: 1 files, 0 ingested, 182 deduped (hard:0, exact:171, llm-skip:11, llm-merge:0), 0 errors
59
+
60
+ 📊 导入汇总:
61
+ 总计: 141 chunks 已索引, 272 chunks 去重 (hard:4, exact:195, llm-skip:41, llm-merge:32), 0 errors
62
+
63
+ === 2026-04-12 11:21:02 增量更新完成 ===
64
+
65
+ === 2026-04-12 19:21:02 增量更新开始 ===
66
+ [INFO] LLM client initialized: qwen-turbo @ https://dashscope.aliyuncs.com/compatible-mode/v1
67
+
68
+ 🔑 验证 Embedding API...
69
+ ✅ jina-embeddings-v5-text-small (1024d)
70
+ ✅ LLM: qwen-turbo (L0 摘要 + 语义去重)
71
+ ✅ 两阶段去重: vector + LLM 语义判断
72
+
73
+ 🔄 开始导入记忆 (source: all)...
74
+
75
+ 📝 导入 Claude Code 对话...
76
+ ✅ CC: 3 files, 55 ingested, 188 deduped (hard:2, exact:134, llm-skip:33, llm-merge:19), 0 errors
77
+ 🤖 导入 Codex 对话...
78
+ ✅ Codex: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
79
+ 💎 导入 Gemini 对话...
80
+ ✅ Gemini: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
81
+ 🖥️ 导入 Claude Desktop 对话...
82
+ ✅ Desktop: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
83
+ 📚 导入记忆文件...
84
+ ✅ Memory: 1 files, 0 ingested, 182 deduped (hard:0, exact:171, llm-skip:11, llm-merge:0), 0 errors
85
+
86
+ 📊 导入汇总:
87
+ 总计: 55 chunks 已索引, 370 chunks 去重 (hard:2, exact:305, llm-skip:44, llm-merge:19), 0 errors
88
+
89
+ === 2026-04-12 19:25:03 增量更新完成 ===
90
+
File without changes
File without changes
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "recallnest",
3
- "version": "1.4.1",
3
+ "version": "2.2.1",
4
4
  "description": "RecallNest \u2014 MCP-native, local-first memory search and distillation for AI conversations",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
8
- "recallnest": "src/cli.ts",
9
- "local-memory": "src/cli.ts"
8
+ "recallnest": "bin/recallnest.mjs",
9
+ "local-memory": "bin/recallnest.mjs"
10
10
  },
11
11
  "scripts": {
12
12
  "search": "bun run src/cli.ts search",
@@ -35,13 +35,20 @@
35
35
  "ui": "bun run src/ui-server.ts",
36
36
  "api": "bun run src/api-server.ts"
37
37
  },
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
38
41
  "dependencies": {
39
42
  "@lancedb/lancedb": "^0.26.0",
40
43
  "@modelcontextprotocol/sdk": "^1.27.1",
41
44
  "commander": "^12.0.0",
42
45
  "openai": "^4.0.0",
46
+ "tsx": "^4.19.0",
43
47
  "zod": "^3.25.76"
44
48
  },
49
+ "optionalDependencies": {
50
+ "babel-memory": ">=1.0.0"
51
+ },
45
52
  "repository": {
46
53
  "type": "git",
47
54
  "url": "git+https://github.com/AliceLJY/recallnest.git"
@@ -95,10 +95,11 @@ export class AccessTracker {
95
95
  * Accumulates deltas in memory; flushed to store after debounce.
96
96
  *
97
97
  * @param ids Memory entry IDs to record access for
98
- * @param scores Optional parallel array of similarity scores for novelty gating.
98
+ * @param scores Optional parallel array of raw similarity scores for novelty gating.
99
+ * Entries with an undefined score skip novelty gating.
99
100
  * When provided, only entries passing shouldReinforce() are recorded.
100
101
  */
101
- recordAccess(ids: string[], scores?: number[]): void {
102
+ recordAccess(ids: string[], scores?: Array<number | undefined>): void {
102
103
  if (ids.length === 0) return;
103
104
 
104
105
  const now = Date.now();
@@ -0,0 +1,109 @@
1
+ /**
2
+ * HP-3: Activity-driven distill frequency.
3
+ * Tracks write operations since last distill, exposes tier-based thresholds.
4
+ * Complements CC-6 distill-lock: HP-3 decides "when to trigger", CC-6 decides "whether to allow".
5
+ */
6
+
7
+ import {
8
+ existsSync,
9
+ readFileSync,
10
+ writeFileSync,
11
+ mkdirSync,
12
+ } from "node:fs";
13
+ import { join, dirname } from "node:path";
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Config
17
+ // ---------------------------------------------------------------------------
18
+
19
+ export interface ActivityCounterConfig {
20
+ /** Path to the stats file (default: data/activity-stats.json) */
21
+ statsPath: string;
22
+ /** Writes needed for light scoring/tagging pass */
23
+ lightThreshold: number;
24
+ /** Writes needed for standard distill */
25
+ standardThreshold: number;
26
+ /** Writes needed for deep checkpoint */
27
+ deepThreshold: number;
28
+ }
29
+
30
+ export const DEFAULT_ACTIVITY_CONFIG: ActivityCounterConfig = {
31
+ statsPath: join(
32
+ process.env.RECALLNEST_DATA_DIR || "data",
33
+ "activity-stats.json",
34
+ ),
35
+ lightThreshold: 15,
36
+ standardThreshold: 50,
37
+ deepThreshold: 200,
38
+ };
39
+
40
+ export type DistillTier = "none" | "light" | "standard" | "deep";
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Internal
44
+ // ---------------------------------------------------------------------------
45
+
46
+ interface ActivityStats {
47
+ writesSinceLastDistill: number;
48
+ lastResetAt: number;
49
+ }
50
+
51
+ function resolveConfig(
52
+ cfg?: Partial<ActivityCounterConfig>,
53
+ ): ActivityCounterConfig {
54
+ return { ...DEFAULT_ACTIVITY_CONFIG, ...cfg };
55
+ }
56
+
57
+ function readStats(statsPath: string): ActivityStats {
58
+ if (!existsSync(statsPath)) {
59
+ return { writesSinceLastDistill: 0, lastResetAt: Date.now() };
60
+ }
61
+ try {
62
+ return JSON.parse(readFileSync(statsPath, "utf-8"));
63
+ } catch {
64
+ return { writesSinceLastDistill: 0, lastResetAt: Date.now() };
65
+ }
66
+ }
67
+
68
+ function writeStats(statsPath: string, stats: ActivityStats): void {
69
+ mkdirSync(dirname(statsPath), { recursive: true });
70
+ writeFileSync(statsPath, JSON.stringify(stats, null, 2), "utf-8");
71
+ }
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Public API
75
+ // ---------------------------------------------------------------------------
76
+
77
+ /** Increment write counter by n (default 1). Returns new count. */
78
+ export function incrementWriteCount(
79
+ n = 1,
80
+ cfg?: Partial<ActivityCounterConfig>,
81
+ ): number {
82
+ const { statsPath } = resolveConfig(cfg);
83
+ const stats = readStats(statsPath);
84
+ stats.writesSinceLastDistill += n;
85
+ writeStats(statsPath, stats);
86
+ return stats.writesSinceLastDistill;
87
+ }
88
+
89
+ /** Read current write count without modifying. */
90
+ export function getWriteCount(cfg?: Partial<ActivityCounterConfig>): number {
91
+ const { statsPath } = resolveConfig(cfg);
92
+ return readStats(statsPath).writesSinceLastDistill;
93
+ }
94
+
95
+ /** Reset counter after successful distill. */
96
+ export function resetWriteCount(cfg?: Partial<ActivityCounterConfig>): void {
97
+ const { statsPath } = resolveConfig(cfg);
98
+ writeStats(statsPath, { writesSinceLastDistill: 0, lastResetAt: Date.now() });
99
+ }
100
+
101
+ /** Determine which distill tier the current write count warrants. */
102
+ export function getDistillTier(cfg?: Partial<ActivityCounterConfig>): DistillTier {
103
+ const config = resolveConfig(cfg);
104
+ const count = getWriteCount(cfg);
105
+ if (count >= config.deepThreshold) return "deep";
106
+ if (count >= config.standardThreshold) return "standard";
107
+ if (count >= config.lightThreshold) return "light";
108
+ return "none";
109
+ }
@@ -44,15 +44,16 @@ export function shouldSkipRetrieval(query: string, minLength?: number): boolean
44
44
  // Force retrieve if query has memory-related intent (BEFORE length check)
45
45
  if (FORCE_RETRIEVE_PATTERNS.some(p => p.test(trimmed))) return false;
46
46
 
47
- // Very short = skip
48
- if (trimmed.length < 4) return true;
47
+ // CJK-aware: Chinese chars carry much more semantic density than ASCII.
48
+ // 2 Chinese chars ("轮巡") is a meaningful query equivalent to "daily patrol".
49
+ const hasCJK = /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff]/.test(trimmed);
50
+ const absoluteMin = hasCJK ? 2 : 4;
51
+ if (trimmed.length < absoluteMin) return true;
49
52
 
50
53
  // Pattern-based skip
51
54
  if (SKIP_PATTERNS.some(p => p.test(trimmed))) return true;
52
55
 
53
- // CJK-aware minimum length: Chinese chars carry more semantic density
54
- const hasCJK = /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff]/.test(trimmed);
55
- const effectiveMinLength = minLength ?? (hasCJK ? 6 : 15);
56
+ const effectiveMinLength = minLength ?? (hasCJK ? 2 : 15);
56
57
 
57
58
  // Short non-question messages are skipped; questions (? ?) are always worth checking
58
59
  if (trimmed.length < effectiveMinLength &&