recallnest 1.4.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 (261) hide show
  1. package/.claude-plugin/CLAUDE.md +29 -0
  2. package/.claude-plugin/marketplace.json +18 -0
  3. package/.env.example +3 -0
  4. package/.github/workflows/ci.yml +28 -0
  5. package/.mcp.json +9 -0
  6. package/CHANGELOG.md +51 -0
  7. package/CLAUDE.md +42 -0
  8. package/DEMO.md +94 -0
  9. package/EVAL.md +89 -0
  10. package/FAILURES.md +75 -0
  11. package/LICENSE +21 -0
  12. package/OPERATIONS.md +59 -0
  13. package/README.md +427 -0
  14. package/README_CN.md +425 -0
  15. package/ROADMAP.md +198 -0
  16. package/assets/recallnest-workbench.png +0 -0
  17. package/assets/ui/app.js +807 -0
  18. package/assets/ui/index.html +154 -0
  19. package/assets/ui/styles.css +605 -0
  20. package/assets/wechat-qr.jpg +0 -0
  21. package/config.json.example +38 -0
  22. package/daily-recall.sh +87 -0
  23. package/daily-reflections/2026-03-05.md +15 -0
  24. package/daily-reflections/2026-03-06.md +15 -0
  25. package/daily-reflections/2026-03-07.md +7 -0
  26. package/daily-reflections/2026-03-08.md +34 -0
  27. package/daily-reflections/2026-03-09.md +35 -0
  28. package/daily-reflections/2026-03-10.md +36 -0
  29. package/daily-reflections/2026-03-11.md +35 -0
  30. package/daily-reflections/2026-03-12.md +36 -0
  31. package/daily-reflections/2026-03-13.md +35 -0
  32. package/daily-reflections/2026-03-14.md +35 -0
  33. package/daily-reflections/2026-03-15.md +35 -0
  34. package/daily-reflections/2026-03-16.md +41 -0
  35. package/daily-reflections/2026-03-17.md +10 -0
  36. package/daily-reflections/2026-03-18.md +10 -0
  37. package/daily-reflections/2026-03-19.md +10 -0
  38. package/daily-reflections/2026-03-20.md +10 -0
  39. package/daily-reflections/2026-03-21.md +10 -0
  40. package/daily-reflections/2026-03-22.md +10 -0
  41. package/daily-reflections/2026-03-23.md +10 -0
  42. package/daily-reflections/2026-03-24.md +10 -0
  43. package/daily-reflections/2026-03-25.md +32 -0
  44. package/daily-reflections/2026-03-26.md +37 -0
  45. package/daily-reflections/2026-03-27.md +35 -0
  46. package/daily-reflections/2026-03-28.md +35 -0
  47. package/daily-reflections/2026-03-29.md +35 -0
  48. package/daily-reflections/2026-03-30.md +36 -0
  49. package/daily-reflections/2026-03-31.md +35 -0
  50. package/daily-reflections/2026-04-01.md +35 -0
  51. package/docs/api-reference.md +1291 -0
  52. package/docs/architecture.md +168 -0
  53. package/docs/memory-boundary-contract.md +226 -0
  54. package/docs/memory-categories.md +119 -0
  55. package/docs/pipeline-audit-ultramemory.md +177 -0
  56. package/docs/plans/2026-03-08-query-expansion.md +270 -0
  57. package/docs/plans/2026-03-16-continuity-layer.md +196 -0
  58. package/docs/plans/mcp-tiering-plan.md +126 -0
  59. package/docs/research/recall-quality-audit-2026-03-22.md +153 -0
  60. package/docs/self-evolution.md +198 -0
  61. package/docs/superpowers/plans/2026-03-19-ingest-pipeline-upgrade.md +782 -0
  62. package/docs/superpowers/specs/2026-03-19-ingest-pipeline-upgrade-design.md +77 -0
  63. package/docs/superpowers/specs/2026-03-23-pull-claude-desktop-design.md +95 -0
  64. package/eval/cases.json +85 -0
  65. package/eval/continuity/case-seeds.json +90 -0
  66. package/eval/continuity/cases.json +302 -0
  67. package/eval/continuity/memory-seeds.json +26 -0
  68. package/eval/continuity/pattern-seeds.json +100 -0
  69. package/eval/continuity/results-2026-03-16.md +117 -0
  70. package/eval/continuity/results-2026-03-19.md +453 -0
  71. package/eval/continuity/runbook.md +110 -0
  72. package/eval/continuity/seed-cases.md +54 -0
  73. package/eval/reports/2026-03-06-abstract-query-baseline.md +96 -0
  74. package/eval/reports/2026-03-06-aws-ssh-baseline.md +82 -0
  75. package/eval/reports/2026-03-06-baseline.md +82 -0
  76. package/eval/reports/query-expansion.md +138 -0
  77. package/integrations/README.md +57 -0
  78. package/integrations/claude-code/README.md +133 -0
  79. package/integrations/claude-code/claude-md-snippet.md +31 -0
  80. package/integrations/claude-code/setup.sh +66 -0
  81. package/integrations/claude-code/smoke-continuity.sh +452 -0
  82. package/integrations/codex/README.md +49 -0
  83. package/integrations/codex/agents-md-snippet.md +31 -0
  84. package/integrations/codex/setup.sh +58 -0
  85. package/integrations/examples/claude-agent-sdk/memory-agent.ts +182 -0
  86. package/integrations/examples/langchain/memory-chain.py +111 -0
  87. package/integrations/examples/openai-agents-sdk/memory-agent.py +109 -0
  88. package/integrations/gemini-cli/README.md +57 -0
  89. package/integrations/gemini-cli/gemini-md-snippet.md +31 -0
  90. package/integrations/gemini-cli/setup.sh +64 -0
  91. package/integrations/shared/install-managed-block.sh +51 -0
  92. package/lm +19 -0
  93. package/package.json +50 -0
  94. package/plan-v1.2-distributable.md +105 -0
  95. package/scripts/archive-distilled-junk.ts +116 -0
  96. package/scripts/backfill-l0l1l2.ts +98 -0
  97. package/scripts/blind-scan.ts +588 -0
  98. package/scripts/cleanup-step1-exact-dups.ts +117 -0
  99. package/scripts/cleanup-step2-template-dups.ts +113 -0
  100. package/scripts/cleanup-step3-stale-content.ts +149 -0
  101. package/scripts/cleanup-step4-orphan-scopes.ts +131 -0
  102. package/scripts/delete-distilled-junk.ts +88 -0
  103. package/scripts/distill-facts.ts +305 -0
  104. package/scripts/health-check.ts +343 -0
  105. package/scripts/incremental-ingest.sh +71 -0
  106. package/scripts/mlp-health-check.ts +382 -0
  107. package/scripts/pull-claude-desktop.ts +515 -0
  108. package/scripts/re-ingest-cc.sh +66 -0
  109. package/scripts/rebalance-memory-health.ts +181 -0
  110. package/scripts/run-desktop-ingest.sh +11 -0
  111. package/scripts/start-server.sh +12 -0
  112. package/scripts/viz-dashboard.html +423 -0
  113. package/scripts/viz-export.ts +703 -0
  114. package/src/__tests__/access-tracker-novelty.test.ts +228 -0
  115. package/src/__tests__/auto-consolidation.test.ts +168 -0
  116. package/src/__tests__/auto-recall.test.ts +131 -0
  117. package/src/__tests__/batch-dedup.test.ts +65 -0
  118. package/src/__tests__/capture-engine.test.ts +1142 -0
  119. package/src/__tests__/capture-heuristic.test.ts +171 -0
  120. package/src/__tests__/cascade-forget.test.ts +210 -0
  121. package/src/__tests__/category-min-scores.test.ts +33 -0
  122. package/src/__tests__/confidence-tracker.test.ts +196 -0
  123. package/src/__tests__/conflict-advisor.test.ts +206 -0
  124. package/src/__tests__/conflict-escalation.test.ts +149 -0
  125. package/src/__tests__/conflict-lifecycle.test.ts +83 -0
  126. package/src/__tests__/conflict-output.test.ts +85 -0
  127. package/src/__tests__/conflict-store.test.ts +374 -0
  128. package/src/__tests__/consolidation-engine.test.ts +181 -0
  129. package/src/__tests__/context-composer-pins.test.ts +64 -0
  130. package/src/__tests__/context-composer-task-selection.test.ts +24 -0
  131. package/src/__tests__/context-renderer.test.ts +91 -0
  132. package/src/__tests__/continuity-eval.test.ts +275 -0
  133. package/src/__tests__/continuity-schema.test.ts +97 -0
  134. package/src/__tests__/core-recall-eval.test.ts +235 -0
  135. package/src/__tests__/core-summary.test.ts +109 -0
  136. package/src/__tests__/dedup-actions.test.ts +58 -0
  137. package/src/__tests__/deterministic-id.test.ts +39 -0
  138. package/src/__tests__/doctor.test.ts +303 -0
  139. package/src/__tests__/drill-down.test.ts +108 -0
  140. package/src/__tests__/embedder.test.ts +122 -0
  141. package/src/__tests__/entity-resolver.test.ts +58 -0
  142. package/src/__tests__/event-segmenter.test.ts +153 -0
  143. package/src/__tests__/hotness-blend.test.ts +76 -0
  144. package/src/__tests__/ingest.test.ts +360 -0
  145. package/src/__tests__/kg-extractor.test.ts +184 -0
  146. package/src/__tests__/kg-store.test.ts +198 -0
  147. package/src/__tests__/llm-consolidation.test.ts +226 -0
  148. package/src/__tests__/memory-boundaries.test.ts +237 -0
  149. package/src/__tests__/memory-health-rebalance.test.ts +144 -0
  150. package/src/__tests__/memory-output.test.ts +215 -0
  151. package/src/__tests__/multi-vector.test.ts +242 -0
  152. package/src/__tests__/ppr-traversal.test.ts +256 -0
  153. package/src/__tests__/preference-guard-smoke.test.ts +211 -0
  154. package/src/__tests__/preference-matcher.test.ts +230 -0
  155. package/src/__tests__/preference-slots.test.ts +106 -0
  156. package/src/__tests__/prospective-memory.test.ts +283 -0
  157. package/src/__tests__/query-entity-detector.test.ts +171 -0
  158. package/src/__tests__/query-expander.test.ts +34 -0
  159. package/src/__tests__/recall-mode.test.ts +64 -0
  160. package/src/__tests__/result-synthesizer.test.ts +198 -0
  161. package/src/__tests__/resume-context.test.ts +4743 -0
  162. package/src/__tests__/retrieval-trace.test.ts +213 -0
  163. package/src/__tests__/retriever-boundary-weight.test.ts +136 -0
  164. package/src/__tests__/retroactive-boost.test.ts +223 -0
  165. package/src/__tests__/scope-inventory.test.ts +200 -0
  166. package/src/__tests__/scope-policy.test.ts +69 -0
  167. package/src/__tests__/session-checkpoint.test.ts +259 -0
  168. package/src/__tests__/session-gc.test.ts +215 -0
  169. package/src/__tests__/store-scope-audit.test.ts +81 -0
  170. package/src/__tests__/temporal-parser.test.ts +241 -0
  171. package/src/__tests__/term-registry.test.ts +121 -0
  172. package/src/__tests__/tool-output-compressor.test.ts +133 -0
  173. package/src/__tests__/version-manager.test.ts +213 -0
  174. package/src/__tests__/workflow-observation.test.ts +400 -0
  175. package/src/access-tracker.ts +316 -0
  176. package/src/adaptive-retrieval.ts +64 -0
  177. package/src/api-server.ts +667 -0
  178. package/src/asset-sync.ts +79 -0
  179. package/src/auto-consolidation.ts +133 -0
  180. package/src/auto-gc.ts +124 -0
  181. package/src/auto-recall.ts +95 -0
  182. package/src/capture-engine.ts +931 -0
  183. package/src/capture-heuristic.ts +177 -0
  184. package/src/cascade-forget.ts +135 -0
  185. package/src/chunker.ts +253 -0
  186. package/src/cli.ts +1917 -0
  187. package/src/confidence-tracker.ts +166 -0
  188. package/src/conflict-advisor.ts +433 -0
  189. package/src/conflict-engine.ts +181 -0
  190. package/src/conflict-escalation.ts +138 -0
  191. package/src/conflict-lifecycle.ts +67 -0
  192. package/src/conflict-output.ts +218 -0
  193. package/src/conflict-schema.ts +130 -0
  194. package/src/conflict-store.ts +127 -0
  195. package/src/consolidation-engine.ts +256 -0
  196. package/src/context-composer-pins.ts +183 -0
  197. package/src/context-composer-queries.ts +121 -0
  198. package/src/context-composer-scope.ts +56 -0
  199. package/src/context-composer-stable-selection.ts +200 -0
  200. package/src/context-composer-stable.ts +217 -0
  201. package/src/context-composer-task-fallbacks.ts +36 -0
  202. package/src/context-composer-task-ranking.ts +197 -0
  203. package/src/context-composer-task-results.ts +137 -0
  204. package/src/context-composer-task-selection.ts +342 -0
  205. package/src/context-composer-text.ts +57 -0
  206. package/src/context-composer.ts +300 -0
  207. package/src/context-renderer.ts +179 -0
  208. package/src/decay-engine.ts +189 -0
  209. package/src/doctor.ts +543 -0
  210. package/src/embedder.ts +557 -0
  211. package/src/entity-resolver.ts +131 -0
  212. package/src/eval.ts +632 -0
  213. package/src/event-segmenter.ts +216 -0
  214. package/src/ingest.ts +1822 -0
  215. package/src/kg-extractor.ts +217 -0
  216. package/src/kg-store.ts +353 -0
  217. package/src/legacy-scope-review.ts +53 -0
  218. package/src/llm-client.ts +629 -0
  219. package/src/llm-consolidation.ts +168 -0
  220. package/src/mcp-server.ts +1337 -0
  221. package/src/memory-assets.ts +475 -0
  222. package/src/memory-boundaries.ts +354 -0
  223. package/src/memory-health-rebalance.ts +220 -0
  224. package/src/memory-output.ts +474 -0
  225. package/src/memory-schema.ts +184 -0
  226. package/src/multi-vector.ts +234 -0
  227. package/src/noise-filter.ts +155 -0
  228. package/src/ppr-traversal.ts +279 -0
  229. package/src/preference-matcher.ts +174 -0
  230. package/src/preference-slots.ts +259 -0
  231. package/src/prospective-memory.ts +198 -0
  232. package/src/query-entity-detector.ts +207 -0
  233. package/src/query-expander.ts +98 -0
  234. package/src/result-synthesizer.ts +114 -0
  235. package/src/retrieval-profiles.ts +101 -0
  236. package/src/retrieval-trace.ts +94 -0
  237. package/src/retriever.ts +1338 -0
  238. package/src/retroactive-boost.ts +154 -0
  239. package/src/rif.ts +73 -0
  240. package/src/runtime-config.ts +172 -0
  241. package/src/schema-utils.ts +56 -0
  242. package/src/scope-inventory.ts +310 -0
  243. package/src/scope-policy.ts +142 -0
  244. package/src/session-engine.ts +168 -0
  245. package/src/session-output.ts +96 -0
  246. package/src/session-schema.ts +60 -0
  247. package/src/session-store.ts +293 -0
  248. package/src/stderr-log.ts +16 -0
  249. package/src/store.ts +903 -0
  250. package/src/temporal-parser.ts +318 -0
  251. package/src/term-registry.ts +791 -0
  252. package/src/tool-output-compressor.ts +115 -0
  253. package/src/tracker.ts +57 -0
  254. package/src/ui-server.ts +430 -0
  255. package/src/version-manager.ts +172 -0
  256. package/src/workflow-observation-engine.ts +316 -0
  257. package/src/workflow-observation-managed.ts +83 -0
  258. package/src/workflow-observation-output.ts +86 -0
  259. package/src/workflow-observation-schema.ts +87 -0
  260. package/src/workflow-observation-scope-review.ts +409 -0
  261. package/src/workflow-observation-store.ts +69 -0
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env bash
2
+ # RecallNest — Claude Code MCP setup (idempotent)
3
+ # Usage: bash integrations/claude-code/setup.sh
4
+
5
+ set -euo pipefail
6
+
7
+ CLAUDE_JSON="$HOME/.claude.json"
8
+ CLAUDE_MD="$HOME/.claude/CLAUDE.md"
9
+ RECALLNEST_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
10
+ MCP_ENTRY="$RECALLNEST_DIR/src/mcp-server.ts"
11
+ RULES_SNIPPET="$RECALLNEST_DIR/integrations/claude-code/claude-md-snippet.md"
12
+ RULES_HELPER="$RECALLNEST_DIR/integrations/shared/install-managed-block.sh"
13
+
14
+ # Verify mcp-server.ts exists
15
+ if [[ ! -f "$MCP_ENTRY" ]]; then
16
+ echo "ERROR: $MCP_ENTRY not found. Run this from the recallnest repo root."
17
+ exit 1
18
+ fi
19
+
20
+ if [[ ! -f "$RULES_HELPER" ]]; then
21
+ echo "ERROR: $RULES_HELPER not found."
22
+ exit 1
23
+ fi
24
+
25
+ mkdir -p "$HOME/.claude"
26
+
27
+ # Create ~/.claude.json if missing
28
+ if [[ ! -f "$CLAUDE_JSON" ]]; then
29
+ echo '{}' > "$CLAUDE_JSON"
30
+ echo "Created $CLAUDE_JSON"
31
+ fi
32
+
33
+ # Check if recallnest MCP is already configured
34
+ if bun -e "
35
+ const c = JSON.parse(require('fs').readFileSync('$CLAUDE_JSON','utf8'));
36
+ process.exit(c.mcpServers?.recallnest ? 0 : 1);
37
+ " 2>/dev/null; then
38
+ echo "RecallNest MCP already configured in $CLAUDE_JSON — skipping."
39
+ else
40
+ # Add recallnest to mcpServers using bun for safe JSON manipulation
41
+ bun -e "
42
+ const fs = require('fs');
43
+ const c = JSON.parse(fs.readFileSync('$CLAUDE_JSON','utf8'));
44
+ if (!c.mcpServers) c.mcpServers = {};
45
+ c.mcpServers.recallnest = {
46
+ command: 'bun',
47
+ args: ['run', '$MCP_ENTRY'],
48
+ env: {}
49
+ };
50
+ fs.writeFileSync('$CLAUDE_JSON', JSON.stringify(c, null, 2) + '\n');
51
+ "
52
+ echo "Added RecallNest MCP to $CLAUDE_JSON"
53
+ fi
54
+
55
+ . "$RULES_HELPER"
56
+ install_managed_markdown_block "$RULES_SNIPPET" "$CLAUDE_MD" "recallnest-continuity"
57
+ echo "Installed RecallNest continuity rules in $CLAUDE_MD"
58
+
59
+ echo ""
60
+ echo "Setup complete. Restart Claude Code to activate."
61
+ echo ""
62
+ echo "Continuity baseline seed:"
63
+ echo " (cd \"$RECALLNEST_DIR\" && bun run seed:continuity)"
64
+ echo ""
65
+ echo "Managed snippet source:"
66
+ echo " $RULES_SNIPPET"
@@ -0,0 +1,452 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
6
+ CLAUDE_BIN="${CLAUDE_BIN:-claude}"
7
+ OUT_DIR="${RECALLNEST_CC_SMOKE_OUT_DIR:-/tmp/recallnest-claude-smoke-$(date +%Y%m%d-%H%M%S)}"
8
+ OBSERVATION_SCOPE="${RECALLNEST_CC_SMOKE_SCOPE:-project:recallnest}"
9
+ OBSERVATION_SOURCE="${RECALLNEST_CC_SMOKE_SOURCE:-smoke}"
10
+ RECORD_OBSERVATIONS="${RECALLNEST_RECORD_WORKFLOW_OBSERVATIONS:-1}"
11
+
12
+ CONTINUE_PROMPT="继续 RecallNest,不要让我重复前情。这个请求是 recall-only smoke:只调用 RecallNest continuity tools 恢复上下文,不要读 repo、不要运行 Bash、不要开始实际工作;如果当前 repo 状态未验证,就明确说 unknown,不要提 git status、未跟踪文件或修改文件名。恢复后只用一句话说明你接下来会做什么。"
13
+ CHECKPOINT_PROMPT="继续 RecallNest,不要让我重复前情。这个请求是 recall-only smoke:只调用 RecallNest continuity tools 恢复上下文,不要读 repo、不要运行 Bash、不要开始实际工作;如果当前 repo 状态未验证,就明确说 unknown,不要提 git status、未跟踪文件或修改文件名;然后在结束前保存 checkpoint_session,并用两句话告诉我你保存了什么。"
14
+ TASK_PIVOT_PROMPT="回到 RecallNest 项目,处理 task-pivot recall regression。这个请求是 recall-only smoke:只调用 RecallNest continuity tools 恢复相关记忆,不要读 repo、不要运行 Bash、不要开始实际工作;如果当前 repo 状态未验证,就明确说 unknown,不要提 git status、未跟踪文件或修改文件名。恢复后只用一句话说明你接下来会做什么。"
15
+ REPO_TOOL_PATTERN='"name":"(Read|Bash|Grep|Glob)"'
16
+ SEARCH_TOOL_PATTERN='"name":"mcp__recallnest__search_memory"'
17
+ RESUME_TOOL_PATTERN='"name":"mcp__recallnest__resume_context"'
18
+ RECALL_TOOL_PATTERN='"name":"mcp__recallnest__(resume_context|search_memory)"'
19
+ REPO_STATE_PATTERN='git status|未提交|staged|uncommitted|已修改文件|modified files|untracked|新增文件|dirty repo|dirty worktree'
20
+ REPO_STATE_CLAIM_PATTERN='git status (里|shows|showed)|未提交|staged|uncommitted|已修改文件|modified files|untracked|新增文件|dirty repo|dirty worktree|未跟踪'
21
+
22
+ need_cmd() {
23
+ local cmd="$1"
24
+ if ! command -v "$cmd" >/dev/null 2>&1; then
25
+ echo "Missing required command: $cmd" >&2
26
+ exit 1
27
+ fi
28
+ }
29
+
30
+ log_step() {
31
+ local message="$1"
32
+ printf '[smoke] %s\n' "$message" >&2
33
+ }
34
+
35
+ record_workflow_observation() {
36
+ local workflow_id="$1"
37
+ local outcome="$2"
38
+ local summary="$3"
39
+ local signal="${4:-}"
40
+ local task="${5:-}"
41
+ local tools="${6:-}"
42
+
43
+ if [[ "$RECORD_OBSERVATIONS" == "0" ]]; then
44
+ return 0
45
+ fi
46
+
47
+ local cmd=(
48
+ bun run src/cli.ts workflow-observe
49
+ "$workflow_id"
50
+ "$summary"
51
+ --outcome "$outcome"
52
+ --scope "$OBSERVATION_SCOPE"
53
+ --source "$OBSERVATION_SOURCE"
54
+ --tags "continuity,claude-smoke"
55
+ )
56
+
57
+ if [[ -n "$signal" ]]; then
58
+ cmd+=(--signal "$signal")
59
+ fi
60
+ if [[ -n "$task" ]]; then
61
+ cmd+=(--task "$task")
62
+ fi
63
+ if [[ -n "$tools" ]]; then
64
+ cmd+=(--tools "$tools")
65
+ fi
66
+
67
+ (
68
+ cd "$ROOT_DIR"
69
+ "${cmd[@]}"
70
+ ) >/dev/null
71
+ }
72
+
73
+ record_and_fail() {
74
+ local workflow_id="$1"
75
+ local outcome="$2"
76
+ local summary="$3"
77
+ local signal="${4:-}"
78
+ local task="${5:-}"
79
+ local tools="${6:-}"
80
+
81
+ record_workflow_observation "$workflow_id" "$outcome" "$summary" "$signal" "$task" "$tools"
82
+ echo "FAIL: $summary" >&2
83
+ exit 1
84
+ }
85
+
86
+ first_match_line() {
87
+ local pattern="$1"
88
+ local file="$2"
89
+ rg -n --max-count 1 "$pattern" "$file" | cut -d: -f1 || true
90
+ }
91
+
92
+ run_case() {
93
+ local name="$1"
94
+ local allowed_tools="$2"
95
+ local prompt="$3"
96
+ local output_file="$OUT_DIR/$name.jsonl"
97
+
98
+ "$CLAUDE_BIN" \
99
+ -p \
100
+ --verbose \
101
+ --output-format stream-json \
102
+ --permission-mode dontAsk \
103
+ --allowedTools="$allowed_tools" \
104
+ "$prompt" >"$output_file"
105
+
106
+ echo "$output_file"
107
+ }
108
+
109
+ assert_no_permission_denials() {
110
+ local file="$1"
111
+ local workflow_id="$2"
112
+ local task="$3"
113
+ local tools="$4"
114
+ if rg -q '"permission_denials":\[\{' "$file"; then
115
+ record_and_fail \
116
+ "$workflow_id" \
117
+ "failure" \
118
+ "Claude Code smoke ${task} hit a permission denial before completing the RecallNest flow." \
119
+ "permission-denied" \
120
+ "$task" \
121
+ "$tools"
122
+ fi
123
+ }
124
+
125
+ assert_resume_before_repo_tools() {
126
+ local file="$1"
127
+ local task="$2"
128
+ local resume_line repo_tool_line
129
+
130
+ resume_line="$(first_match_line "$RESUME_TOOL_PATTERN" "$file")"
131
+ repo_tool_line="$(first_match_line "$REPO_TOOL_PATTERN" "$file")"
132
+
133
+ if [[ -z "$resume_line" ]]; then
134
+ record_and_fail \
135
+ "resume_context" \
136
+ "missed" \
137
+ "Claude Code smoke ${task} never called resume_context." \
138
+ "missing-resume-context" \
139
+ "$task" \
140
+ "resume_context"
141
+ fi
142
+
143
+ if [[ -n "$repo_tool_line" && "$repo_tool_line" -lt "$resume_line" ]]; then
144
+ record_and_fail \
145
+ "resume_context" \
146
+ "missed" \
147
+ "Claude Code smoke ${task} explored the repo before resume_context." \
148
+ "resume-after-repo-tool" \
149
+ "$task" \
150
+ "resume_context"
151
+ fi
152
+ }
153
+
154
+ assert_no_repo_tools() {
155
+ local file="$1"
156
+ local task="$2"
157
+
158
+ if rg -q "$REPO_TOOL_PATTERN" "$file"; then
159
+ record_and_fail \
160
+ "resume_context" \
161
+ "failure" \
162
+ "Claude Code smoke ${task} used repo tools during a recall-only flow." \
163
+ "repo-tool-in-recall-only" \
164
+ "$task" \
165
+ "resume_context,search_memory,checkpoint_session"
166
+ fi
167
+ }
168
+
169
+ assert_recall_before_repo_tools() {
170
+ local file="$1"
171
+ local task="$2"
172
+ local recall_line repo_tool_line
173
+
174
+ recall_line="$(first_match_line "$RECALL_TOOL_PATTERN" "$file")"
175
+ repo_tool_line="$(first_match_line "$REPO_TOOL_PATTERN" "$file")"
176
+
177
+ if [[ -z "$recall_line" ]]; then
178
+ record_and_fail \
179
+ "search_memory" \
180
+ "missed" \
181
+ "Claude Code smoke ${task} never called resume_context or search_memory." \
182
+ "missing-recall-tool" \
183
+ "$task" \
184
+ "resume_context,search_memory"
185
+ fi
186
+
187
+ if [[ -n "$repo_tool_line" && "$repo_tool_line" -lt "$recall_line" ]]; then
188
+ record_and_fail \
189
+ "search_memory" \
190
+ "missed" \
191
+ "Claude Code smoke ${task} explored the repo before any RecallNest recovery tool." \
192
+ "recall-after-repo-tool" \
193
+ "$task" \
194
+ "resume_context,search_memory"
195
+ fi
196
+ }
197
+
198
+ assert_resume_before_search_if_present() {
199
+ local file="$1"
200
+ local task="$2"
201
+ local resume_line search_line
202
+
203
+ resume_line="$(first_match_line "$RESUME_TOOL_PATTERN" "$file")"
204
+ search_line="$(first_match_line "$SEARCH_TOOL_PATTERN" "$file")"
205
+
206
+ if [[ -z "$search_line" ]]; then
207
+ return 0
208
+ fi
209
+
210
+ if [[ -z "$resume_line" ]]; then
211
+ record_and_fail \
212
+ "resume_context" \
213
+ "missed" \
214
+ "Claude Code smoke ${task} called search_memory without resume_context." \
215
+ "search-without-resume" \
216
+ "$task" \
217
+ "resume_context,search_memory"
218
+ fi
219
+
220
+ if [[ "$search_line" -lt "$resume_line" ]]; then
221
+ record_and_fail \
222
+ "resume_context" \
223
+ "failure" \
224
+ "Claude Code smoke ${task} called search_memory before resume_context." \
225
+ "search-before-resume" \
226
+ "$task" \
227
+ "resume_context,search_memory"
228
+ fi
229
+ }
230
+
231
+ first_recall_tool() {
232
+ local file="$1"
233
+ local resume_line search_line
234
+
235
+ resume_line="$(first_match_line "$RESUME_TOOL_PATTERN" "$file")"
236
+ search_line="$(first_match_line "$SEARCH_TOOL_PATTERN" "$file")"
237
+
238
+ if [[ -n "$resume_line" && ( -z "$search_line" || "$resume_line" -le "$search_line" ) ]]; then
239
+ echo "resume_context"
240
+ return
241
+ fi
242
+ if [[ -n "$search_line" ]]; then
243
+ echo "search_memory"
244
+ return
245
+ fi
246
+ echo "recall"
247
+ }
248
+
249
+ describe_unverified_repo_state_claim_sources() {
250
+ local file="$1"
251
+ local repo_tool_line assistant_line checkpoint_request_line checkpoint_saved_line
252
+ local sources=()
253
+
254
+ repo_tool_line="$(first_match_line "$REPO_TOOL_PATTERN" "$file")"
255
+ if [[ -n "$repo_tool_line" ]]; then
256
+ return 0
257
+ fi
258
+
259
+ assistant_line="$(first_match_line "\"type\":\"assistant\".*\"type\":\"text\".*($REPO_STATE_CLAIM_PATTERN)" "$file")"
260
+ checkpoint_request_line="$(first_match_line "\"name\":\"mcp__recallnest__checkpoint_session\".*($REPO_STATE_CLAIM_PATTERN)" "$file")"
261
+ checkpoint_saved_line="$(first_match_line "Checkpoint [0-9a-f]+.*($REPO_STATE_CLAIM_PATTERN)" "$file")"
262
+ if [[ -n "$assistant_line" ]]; then
263
+ sources+=("assistant:$assistant_line")
264
+ fi
265
+ if [[ -n "$checkpoint_request_line" ]]; then
266
+ sources+=("checkpoint_request:$checkpoint_request_line")
267
+ fi
268
+ if [[ -n "$checkpoint_saved_line" ]]; then
269
+ sources+=("checkpoint_saved:$checkpoint_saved_line")
270
+ fi
271
+
272
+ if [[ ${#sources[@]} -gt 0 ]]; then
273
+ printf '%s\n' "${sources[*]}"
274
+ fi
275
+ }
276
+
277
+ assert_no_unverified_repo_state_claims() {
278
+ local file="$1"
279
+ local task="$2"
280
+ local sources
281
+
282
+ sources="$(describe_unverified_repo_state_claim_sources "$file")"
283
+ if [[ -n "$sources" ]]; then
284
+ record_and_fail \
285
+ "resume_context" \
286
+ "failure" \
287
+ "Claude Code smoke ${task} restated unverified repo-state details during a recall-only flow." \
288
+ "unverified-repo-state-claim" \
289
+ "$task" \
290
+ "resume_context,search_memory,checkpoint_session"
291
+ fi
292
+ }
293
+
294
+ assert_checkpoint_repo_state_claims_are_verified() {
295
+ local file="$1"
296
+ local task="$2"
297
+ local checkpoint_saved_line
298
+
299
+ checkpoint_saved_line="$(first_match_line "Checkpoint [0-9a-f]+.*($REPO_STATE_PATTERN)" "$file")"
300
+ if [[ -n "$checkpoint_saved_line" ]] && ! rg -q "$REPO_TOOL_PATTERN" "$file"; then
301
+ record_and_fail \
302
+ "checkpoint_session" \
303
+ "failure" \
304
+ "Claude Code smoke ${task} saved repo-state text into checkpoint_session without visible repo verification." \
305
+ "repo-state-contamination" \
306
+ "$task" \
307
+ "resume_context,checkpoint_session"
308
+ fi
309
+ }
310
+
311
+ extract_checkpoint_id() {
312
+ local file="$1"
313
+ rg -o --max-count 1 'Checkpoint [0-9a-f]{8,}' "$file" | awk '{print $2}' || true
314
+ }
315
+
316
+ summarize_case() {
317
+ local label="$1"
318
+ local file="$2"
319
+ local resume_line recall_line checkpoint_line repo_tool_line checkpoint_id repo_state_sources
320
+
321
+ resume_line="$(first_match_line "$RESUME_TOOL_PATTERN" "$file")"
322
+ recall_line="$(first_match_line "$RECALL_TOOL_PATTERN" "$file")"
323
+ checkpoint_line="$(first_match_line '"name":"mcp__recallnest__checkpoint_session"' "$file")"
324
+ repo_tool_line="$(first_match_line "$REPO_TOOL_PATTERN" "$file")"
325
+ checkpoint_id="$(extract_checkpoint_id "$file")"
326
+ repo_state_sources="$(describe_unverified_repo_state_claim_sources "$file")"
327
+
328
+ echo "$label"
329
+ echo " log: $file"
330
+ echo " resume_context line: ${resume_line:-missing}"
331
+ echo " first recall tool line: ${recall_line:-missing}"
332
+ if [[ -n "$repo_tool_line" ]]; then
333
+ echo " first repo tool line: $repo_tool_line"
334
+ else
335
+ echo " first repo tool line: none"
336
+ fi
337
+ if [[ -n "$checkpoint_line" ]]; then
338
+ echo " checkpoint_session line: $checkpoint_line"
339
+ fi
340
+ if [[ -n "$checkpoint_id" ]]; then
341
+ echo " checkpoint id: $checkpoint_id"
342
+ fi
343
+ if [[ -n "$repo_state_sources" ]]; then
344
+ echo " unverified repo-state sources: $repo_state_sources"
345
+ fi
346
+ }
347
+
348
+ need_cmd "$CLAUDE_BIN"
349
+ need_cmd rg
350
+ need_cmd bun
351
+
352
+ mkdir -p "$OUT_DIR"
353
+
354
+ continue_log="$(
355
+ cd "$ROOT_DIR" && \
356
+ log_step "Running continue case..."
357
+ run_case \
358
+ "continue" \
359
+ "ToolSearch,mcp__recallnest__resume_context,mcp__recallnest__search_memory" \
360
+ "$CONTINUE_PROMPT"
361
+ )"
362
+
363
+ assert_no_permission_denials "$continue_log" "resume_context" "claude-code smoke continue" "resume_context,search_memory"
364
+ assert_resume_before_repo_tools "$continue_log" "claude-code smoke continue"
365
+ assert_resume_before_search_if_present "$continue_log" "claude-code smoke continue"
366
+ assert_no_repo_tools "$continue_log" "claude-code smoke continue"
367
+ assert_no_unverified_repo_state_claims "$continue_log" "claude-code smoke continue"
368
+ record_workflow_observation \
369
+ "resume_context" \
370
+ "success" \
371
+ "Claude Code smoke continue case recovered continuity before any visible repo tools." \
372
+ "startup-recovered" \
373
+ "claude-code smoke continue" \
374
+ "resume_context,search_memory"
375
+
376
+ checkpoint_log="$(
377
+ cd "$ROOT_DIR" && \
378
+ log_step "Running checkpoint case..."
379
+ run_case \
380
+ "checkpoint" \
381
+ "ToolSearch,mcp__recallnest__resume_context,mcp__recallnest__search_memory,mcp__recallnest__checkpoint_session" \
382
+ "$CHECKPOINT_PROMPT"
383
+ )"
384
+
385
+ assert_no_permission_denials "$checkpoint_log" "resume_context" "claude-code smoke checkpoint" "resume_context,search_memory,checkpoint_session"
386
+ assert_resume_before_repo_tools "$checkpoint_log" "claude-code smoke checkpoint"
387
+ assert_resume_before_search_if_present "$checkpoint_log" "claude-code smoke checkpoint"
388
+ assert_no_repo_tools "$checkpoint_log" "claude-code smoke checkpoint"
389
+ assert_no_unverified_repo_state_claims "$checkpoint_log" "claude-code smoke checkpoint"
390
+
391
+ resume_line="$(first_match_line '"name":"mcp__recallnest__resume_context"' "$checkpoint_log")"
392
+ checkpoint_line="$(first_match_line '"name":"mcp__recallnest__checkpoint_session"' "$checkpoint_log")"
393
+
394
+ if [[ -z "$checkpoint_line" ]]; then
395
+ record_and_fail \
396
+ "checkpoint_session" \
397
+ "missed" \
398
+ "Claude Code smoke checkpoint case never called checkpoint_session." \
399
+ "missing-checkpoint-session" \
400
+ "claude-code smoke checkpoint" \
401
+ "resume_context,search_memory,checkpoint_session"
402
+ fi
403
+
404
+ if [[ "$checkpoint_line" -lt "$resume_line" ]]; then
405
+ record_and_fail \
406
+ "checkpoint_session" \
407
+ "failure" \
408
+ "Claude Code smoke checkpoint case called checkpoint_session before resume_context." \
409
+ "checkpoint-before-resume" \
410
+ "claude-code smoke checkpoint" \
411
+ "resume_context,search_memory,checkpoint_session"
412
+ fi
413
+
414
+ assert_checkpoint_repo_state_claims_are_verified "$checkpoint_log" "claude-code smoke checkpoint"
415
+ record_workflow_observation \
416
+ "checkpoint_session" \
417
+ "success" \
418
+ "Claude Code smoke checkpoint case saved a clean checkpoint after continuity recovery." \
419
+ "checkpoint-saved-cleanly" \
420
+ "claude-code smoke checkpoint" \
421
+ "resume_context,search_memory,checkpoint_session"
422
+
423
+ task_pivot_log="$(
424
+ cd "$ROOT_DIR" && \
425
+ log_step "Running task-pivot case..."
426
+ run_case \
427
+ "task-pivot" \
428
+ "ToolSearch,mcp__recallnest__resume_context,mcp__recallnest__search_memory" \
429
+ "$TASK_PIVOT_PROMPT"
430
+ )"
431
+
432
+ assert_no_permission_denials "$task_pivot_log" "search_memory" "claude-code smoke task-pivot" "resume_context,search_memory"
433
+ assert_recall_before_repo_tools "$task_pivot_log" "claude-code smoke task-pivot"
434
+ assert_resume_before_search_if_present "$task_pivot_log" "claude-code smoke task-pivot"
435
+ assert_no_repo_tools "$task_pivot_log" "claude-code smoke task-pivot"
436
+ assert_no_unverified_repo_state_claims "$task_pivot_log" "claude-code smoke task-pivot"
437
+ record_workflow_observation \
438
+ "$(first_recall_tool "$task_pivot_log")" \
439
+ "success" \
440
+ "Claude Code smoke task-pivot case recovered RecallNest context before any visible repo tools." \
441
+ "task-pivot-recovered" \
442
+ "claude-code smoke task-pivot" \
443
+ "resume_context,search_memory"
444
+
445
+ echo "Claude Code continuity smoke passed."
446
+ echo "Artifacts saved under: $OUT_DIR"
447
+ if [[ "$RECORD_OBSERVATIONS" != "0" ]]; then
448
+ echo "Workflow observations stored under scope: $OBSERVATION_SCOPE"
449
+ fi
450
+ summarize_case "Continue case:" "$continue_log"
451
+ summarize_case "Checkpoint case:" "$checkpoint_log"
452
+ summarize_case "Task-pivot case:" "$task_pivot_log"
@@ -0,0 +1,49 @@
1
+ # Codex Integration
2
+
3
+ > Codex 接入指南:一键配 MCP + continuity 规则,让 Codex 在新窗口里主动恢复稳定上下文。
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ bash integrations/codex/setup.sh
9
+ ```
10
+
11
+ ## What It Does
12
+
13
+ - Adds RecallNest as an MCP server in `~/.codex/config.toml`
14
+ - Installs a managed RecallNest block in `~/.codex/AGENTS.md`
15
+
16
+ ## Continuity Rules
17
+
18
+ The managed block comes from [agents-md-snippet.md](agents-md-snippet.md) and tells Codex to:
19
+
20
+ - call `resume_context` at the start of fresh windows or continuity-sensitive tasks
21
+ - run lightweight `search_memory` on task pivots inside the same project before repo exploration drifts
22
+ - reuse known `scope` / `sessionId` and the resolved scope returned by `resume_context` in follow-up recall calls
23
+ - treat recalled or startup-hook repo state as unverified until this window explicitly checks the repo
24
+ - save `checkpoint_session` before leaving resumable work
25
+ - do not inspect repo state just to enrich a close-window checkpoint unless the user explicitly asked for repo state
26
+ - do not write unverified repo-state claims into `checkpoint_session`
27
+ - capture durable facts with `store_memory` and reusable workflows with `store_workflow_pattern`
28
+
29
+ ## Manual Setup
30
+
31
+ Add to `~/.codex/config.toml`:
32
+
33
+ ```toml
34
+ [mcp_servers.recallnest]
35
+ command = "bun"
36
+ args = ["run", "RECALLNEST_PATH/src/mcp-server.ts"]
37
+ ```
38
+
39
+ Replace `RECALLNEST_PATH` with your actual path.
40
+
41
+ Then copy [agents-md-snippet.md](agents-md-snippet.md) into `~/.codex/AGENTS.md` or your repo-level `AGENTS.md`.
42
+
43
+ ## Shared Index
44
+
45
+ Same LanceDB index as Claude Code and Gemini CLI — all three share memories.
46
+
47
+ ## Verify
48
+
49
+ Start Codex and ask: "resume my context for RecallNest continuity work"
@@ -0,0 +1,31 @@
1
+ ## RecallNest Continuity
2
+
3
+ - These continuity rules override later generic writing, skill, and local-memory instructions whenever the user's intent is continuity recovery or memory recall.
4
+ - If the user says `continue`, `继续`, `接着`, `刚才`, `上个窗口`, `不要让我重复前情`, `之前讨论过`, or asks what the project is solving / where it stopped / what to do next, call `resume_context` before any Bash, Read, or repo exploration.
5
+ - If the user starts a concrete task in an active project, shifts back to a named project, or asks for prior implementation detail, do lightweight RecallNest recovery before repo exploration even without an explicit `continue`: call `resume_context` when you need broad continuity, or `search_memory` when you just need a focused fact/pattern recall.
6
+ - Do not substitute `git status`, `git log`, or reading local docs for `resume_context`. Local inspection can validate current code state only after continuity has been recovered.
7
+ - Use `resume_context` to recover stable background such as active projects, durable preferences, recent cases, reusable patterns, and the latest checkpoint.
8
+ - When `scope`, shared project scope, or `sessionId` is known, pass it into `resume_context` / `search_memory` / related recall tools instead of relying on global recall.
9
+ - If `resume_context` returns a resolved scope or latest checkpoint scope, reuse that same scope in follow-up `search_memory`, `brief_memory`, `pin_memory`, and other recall calls.
10
+ - If `resume_context` or a recalled checkpoint mentions repo state such as `git status`, modified files, untracked files, commits, or pending push, treat that as handoff context only. Do not restate it as the current repo state unless you verify it in this window with repo tools.
11
+ - If current repo state has not been verified in this window, say it is unknown or omit it. Do not infer dirty/clean state, staged files, commit readiness, or specific modified files from recalled context alone.
12
+ - In recall-only continuity recovery, do not mention `git status`, modified/untracked filenames, or repo cleanliness just to sound specific. If the next step would need repo inspection, say you would inspect the repo after the user asks you to proceed.
13
+ - Treat startup hooks, restored checkpoints, and recalled notes the same way: unless this window explicitly inspected the repo, they are not evidence for current file lists or worktree state.
14
+ - If the user is asking what you remember about preferences, style, tone, identity, or current project background, answer from `resume_context` and recalled memory first. Do not read repo files or local docs unless the user explicitly asks for file inspection or the recovered context is insufficient.
15
+ - If the message mentions writing, articles, or the public account but the actual intent is recall-only (for example: "what style do you remember", "哪些表达方式要避免", "回忆偏好"), do not activate article-writing workflows, writing-persona files, or content-alchemy style skills. Treat it as a memory recall question unless the user explicitly asks you to draft, edit, or research.
16
+ - Normal writing requests are unchanged: if the user explicitly asks you to draft an article, revise copy, research a topic, or continue the writing pipeline, you should use the existing writing workflows and skills as usual.
17
+ - For recall-only writing/style questions, do not supplement the answer with local memory indexes, quick-reference blocks, `writing-persona.md`, `writing-rules.md`, or similar local style docs. If RecallNest recalled only one preference, answer from that one preference.
18
+ - For recall-only preference questions, prefer a plain `resume_context` call over writing-specific profiles or broader rulesets unless the user explicitly asks for the full writing system.
19
+ - If `resume_context` returns `Response mode: recall-only` or a recall-only guidance line, follow it literally. Restate the recalled stable context briefly and do not add extra examples, banned words, or inferred style rules unless they were also recalled.
20
+ - If `resume_context` already returns a relevant durable preference for the current task, keep the answer narrow. Do not pad it with older pins, briefs, or local rule files unless the user asks for a broader ruleset.
21
+ - For recall-only questions, stay constrained to the recalled items. Do not expand one recalled preference into a full doctrine, banned-word list, or writing system unless those details were also recalled or the user explicitly asks for expansion.
22
+ - If recalled context is sparse, say what you do remember and what is still uncertain. Do not invent extra rules to sound complete.
23
+ - For task pivots or fresh implementation work inside the same project, run a lightweight `search_memory` using 2-3 key nouns or verbs from the user's request before repo exploration drifts.
24
+ - If `resume_context` is not enough and you need a specific fact, follow up with `search_memory` using 2-3 key nouns or verbs instead of full sentences.
25
+ - If the user explicitly corrects a continuity miss, such as saying you should have resumed context first or should have saved a checkpoint before stopping, fix the workflow first and then call `workflow_observe` with outcome `corrected` so the miss is tracked outside durable memory.
26
+ - Before leaving a window with unfinished or resumable work, call `checkpoint_session` and capture the current summary, decisions, open loops, next actions, and relevant entities.
27
+ - Do not inspect repo state just to make `checkpoint_session` more complete unless the user explicitly asked for repo state in this window. A close-window handoff should prefer an incomplete but verified checkpoint over speculative or freshly-probed repo details.
28
+ - Do not write repo-state claims into `checkpoint_session` unless you actually inspected the repo in this window. A recalled checkpoint mentioning dirty files or pending push is not enough evidence to repeat or persist it.
29
+ - Do not copy or paraphrase unverified repo-state text into `checkpoint_session`, even with caveats like `未在本窗口验证`, `上次看到`, or `according to the earlier checkpoint`. If this window never inspected the repo, omit repo state entirely from the checkpoint.
30
+ - Use `store_memory` when you learn durable profile, preference, entity, or case knowledge that should survive across future windows.
31
+ - Use `store_workflow_pattern` when you discover a reusable multi-step workflow that should become durable `patterns` memory.
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env bash
2
+ # RecallNest — Codex MCP setup (idempotent)
3
+ # Usage: bash integrations/codex/setup.sh
4
+
5
+ set -euo pipefail
6
+
7
+ CODEX_CONFIG="$HOME/.codex/config.toml"
8
+ CODEX_AGENTS="$HOME/.codex/AGENTS.md"
9
+ CODEX_DIR="$HOME/.codex"
10
+ RECALLNEST_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
11
+ MCP_ENTRY="$RECALLNEST_DIR/src/mcp-server.ts"
12
+ RULES_SNIPPET="$RECALLNEST_DIR/integrations/codex/agents-md-snippet.md"
13
+ RULES_HELPER="$RECALLNEST_DIR/integrations/shared/install-managed-block.sh"
14
+
15
+ if [[ ! -f "$MCP_ENTRY" ]]; then
16
+ echo "ERROR: $MCP_ENTRY not found. Run this from the recallnest repo root."
17
+ exit 1
18
+ fi
19
+
20
+ if [[ ! -f "$RULES_HELPER" ]]; then
21
+ echo "ERROR: $RULES_HELPER not found."
22
+ exit 1
23
+ fi
24
+
25
+ # Create ~/.codex/ if missing
26
+ mkdir -p "$CODEX_DIR"
27
+
28
+ # Create config.toml if missing
29
+ if [[ ! -f "$CODEX_CONFIG" ]]; then
30
+ touch "$CODEX_CONFIG"
31
+ echo "Created $CODEX_CONFIG"
32
+ fi
33
+
34
+ # Check if already configured
35
+ if grep -q '\[mcp_servers\.recallnest\]' "$CODEX_CONFIG" 2>/dev/null; then
36
+ echo "RecallNest MCP already configured in $CODEX_CONFIG — skipping."
37
+ else
38
+ cat >> "$CODEX_CONFIG" <<EOF
39
+
40
+ [mcp_servers.recallnest]
41
+ command = "bun"
42
+ args = ["run", "$MCP_ENTRY"]
43
+ EOF
44
+ echo "Added RecallNest MCP to $CODEX_CONFIG"
45
+ fi
46
+
47
+ . "$RULES_HELPER"
48
+ install_managed_markdown_block "$RULES_SNIPPET" "$CODEX_AGENTS" "recallnest-continuity"
49
+ echo "Installed RecallNest continuity rules in $CODEX_AGENTS"
50
+
51
+ echo ""
52
+ echo "Setup complete. Restart Codex to activate."
53
+ echo ""
54
+ echo "Continuity baseline seed:"
55
+ echo " (cd \"$RECALLNEST_DIR\" && bun run seed:continuity)"
56
+ echo ""
57
+ echo "Managed snippet source:"
58
+ echo " $RULES_SNIPPET"