recallnest 2.6.0 → 3.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 (74) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +131 -14
  3. package/README_CN.md +121 -17
  4. package/config.json.example +8 -1
  5. package/docs/api-reference.md +1 -1
  6. package/integrations/README.md +1 -1
  7. package/integrations/agy/README.md +73 -0
  8. package/integrations/agy/setup.sh +75 -0
  9. package/integrations/setup-all.sh +1 -1
  10. package/package.json +7 -5
  11. package/src/__tests__/access-tracker-novelty.test.ts +22 -2
  12. package/src/__tests__/activity-counter.test.ts +38 -38
  13. package/src/__tests__/age-label.test.ts +33 -0
  14. package/src/__tests__/cluster-consolidation.test.ts +313 -22
  15. package/src/__tests__/consolidation-engine.test.ts +90 -0
  16. package/src/__tests__/contracts.test.ts +2 -2
  17. package/src/__tests__/data-checkup.test.ts +31 -3
  18. package/src/__tests__/dream-pipeline.test.ts +41 -1
  19. package/src/__tests__/dream-scope-isolation.test.ts +386 -0
  20. package/src/__tests__/dream-write-batching.test.ts +211 -0
  21. package/src/__tests__/env-config-invariant.test.ts +80 -0
  22. package/src/__tests__/env-config.test.ts +60 -0
  23. package/src/__tests__/ingest-scope-prefix.test.ts +69 -0
  24. package/src/__tests__/maintenance-locks.test.ts +8 -0
  25. package/src/__tests__/memory-evolution-b2-b3-e1.test.ts +17 -0
  26. package/src/__tests__/memory-output.test.ts +9 -0
  27. package/src/__tests__/memory-utility.test.ts +256 -0
  28. package/src/__tests__/openai-contract.test.ts +513 -0
  29. package/src/__tests__/promotion-distinct-sources.test.ts +162 -0
  30. package/src/__tests__/retrieve-audit-revision.test.ts +255 -0
  31. package/src/__tests__/source-heartbeat.test.ts +6 -2
  32. package/src/__tests__/store-patch-metadata.test.ts +30 -0
  33. package/src/__tests__/synthesis-contract.test.ts +252 -0
  34. package/src/__tests__/synthesis-promotion.test.ts +369 -0
  35. package/src/__tests__/trusted-memory.test.ts +28 -0
  36. package/src/__tests__/utility-weight.test.ts +57 -0
  37. package/src/__tests__/verbatim-self-recall.test.ts +279 -0
  38. package/src/__tests__/version-manager.test.ts +35 -0
  39. package/src/access-tracker.ts +10 -1
  40. package/src/activity-counter.ts +69 -11
  41. package/src/age-label.ts +29 -0
  42. package/src/audit-log.ts +35 -0
  43. package/src/auto-gc.ts +97 -30
  44. package/src/cli.ts +224 -10
  45. package/src/consolidation-engine.ts +317 -123
  46. package/src/data-checkup.ts +17 -3
  47. package/src/dream-pipeline.ts +90 -12
  48. package/src/embedder.ts +20 -5
  49. package/src/env-config.ts +53 -0
  50. package/src/forget-engine.ts +8 -2
  51. package/src/gateway-server.ts +272 -0
  52. package/src/ingest.ts +23 -5
  53. package/src/llm-client.ts +86 -25
  54. package/src/mcp-server.ts +2 -1
  55. package/src/mcp-tools-advanced.ts +7 -2
  56. package/src/mcp-tools-core.ts +11 -1
  57. package/src/mcp-tools-governance.ts +45 -3
  58. package/src/memory-evolution.ts +16 -0
  59. package/src/memory-output.ts +12 -8
  60. package/src/memory-promotion.ts +280 -0
  61. package/src/memory-store-port.ts +32 -3
  62. package/src/memory-utility.ts +314 -0
  63. package/src/recall-ledger.ts +76 -0
  64. package/src/retriever.ts +82 -9
  65. package/src/scope-policy.ts +22 -1
  66. package/src/session-output.ts +4 -3
  67. package/src/skill-promotion.ts +152 -1
  68. package/src/store.ts +231 -71
  69. package/src/synthesis-contract.ts +286 -0
  70. package/src/version-manager.ts +83 -0
  71. package/src/workflow-observation-schema.ts +26 -0
  72. package/integrations/gemini-cli/README.md +0 -57
  73. package/integrations/gemini-cli/setup.sh +0 -64
  74. /package/integrations/{gemini-cli/gemini-md-snippet.md → agy/agy-md-snippet.md} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,196 @@
1
1
  # Changelog
2
2
 
3
+ ## v3.0.0 — Node 22, and conclusions that can be used (2026-08-24)
4
+
5
+ Two things make this a major release: the runtime floor moves, and a synthesized
6
+ conclusion can finally reach stable memory. Everything else here is either in service of
7
+ those or was found while doing them.
8
+
9
+ ### Changed
10
+
11
+ - **`engines.node` is now `>=22`** (was `>=18.14.1`). This is the only breaking change in
12
+ the release; Bun users are unaffected.
13
+ - **`openai` migrated from `^4.0.0` to `^7.5.0`**, which removes the
14
+ `openai@4 → formdata-node@4.4.1 → node-domexception@1.0.0` deprecated chain from the
15
+ dependency tree. Every `openai` release since v5 has zero dependencies, so the chain
16
+ disappears on any upgrade — v7 was chosen because it declares `engines.node >= 22.0.0`,
17
+ making the Node floor and the dependency cleanup one decision instead of two. Verified
18
+ against the SDK rather than its migration guide: the guide documents the `httpAgent`
19
+ removal, the move to built-in `fetch`, and the Node 22 floor, but says nothing about the
20
+ three things this codebase actually depends on — `embeddings.create`, the second
21
+ `RequestOptions` argument on `chat.completions.create`, and the error classes exposed as
22
+ statics on the default export. All three hold.
23
+ - **MCP tool count is 44**, up from 43 (`promote_synthesis`, governance tier).
24
+
25
+ ### Added
26
+
27
+ - **`promote_synthesis` (MCP) and `recallnest promote-synthesis` (CLI)** — a promotion road
28
+ for dream-synthesized conclusions. `buildDerivedBoundary` marks every cluster insight and
29
+ cross-memory pattern `layer: "evidence"` on purpose, and `shouldUseStableMemoryResult`
30
+ refuses the evidence layer, so a synthesized conclusion could never take part in stable
31
+ memory regardless of how well supported it was. Eligibility comes from the conclusion's
32
+ own validated evidence set — `synthesis_contract >= 2`, at least two distinct still-active
33
+ evidence memories — rather than from repetition, because a synthesis is already a
34
+ cross-entry aggregate. It abstains when the evidence cannot be resolved, counts every
35
+ rejection reason, defaults to dry-run, never modifies the synthesized row, and writes
36
+ through the existing `promoteMemory` path so `canonicalKey` dedup makes a re-run a
37
+ revision instead of a duplicate.
38
+ - **Retrieve audit rows carry revision and provenance.** `retrieved[]` records each served
39
+ result's id, `evolution.version`, lifecycle status, and boundary layer/authority;
40
+ `retrievedTotal` appears when the capped list is shorter than the truth. Beliefs are
41
+ revised in place — the canonical id survives, the version increments, the old text
42
+ remains as a `superseded` row — so a row saying only `hits=N` could not distinguish a
43
+ current answer from a stale one after the fact.
44
+ - **HTTP contract tests for embeddings and chat completions** (`openai-contract.test.ts`).
45
+ Every prior embedder/LLM test stubbed the SDK client, so none of them touched a socket
46
+ and a transport-level regression would have passed all of them. These drive the real
47
+ `Embedder` and `LLMClient` through the real SDK against a loopback `node:http` server,
48
+ covering success, error, and timeout for the default OpenAI request shape plus the Jina
49
+ (`task`/`normalized`/`dimensions`) and Qwen-compatible profiles. No network egress, no
50
+ vendor credentials, no paid calls.
51
+ - **A repeatable regression for verbatim self-recall** (`verbatim-self-recall.test.ts`).
52
+ A long, older, rarely-read entry can fail to be recalled by words copied out of its own
53
+ body while short, fresh, frequently-read entries outrank it. The reproduction pins the
54
+ mechanism: the entry is *not* filtered — `hard_min_score`, `layer_admission` and
55
+ `noise_filter` each drop zero rows and its score clears the threshold — it is admitted
56
+ and then ranked last. The ranking fix is deliberately not in this release.
57
+ - **`scripts/tier-exemption-snapshot.ts`** — captures tier and decay-exemption distribution
58
+ so "we did not change tiers" becomes checkable later rather than asserted.
59
+
60
+ ### Added — synthesis quality (generation side)
61
+
62
+ Six changes to what `dream` produces, from a full diagnostic on 2026-08-22 whose core
63
+ finding was that **derived memories had a lower conclusion density than their own input**:
64
+ over the same 40–160 character band, with a deterministic regex and no LLM judge,
65
+ hand-written pivots scored 40.4%, raw transcripts 25.1%, insights 14.4%, patterns 12.1%.
66
+ Synthesis was subtracting.
67
+
68
+ - **`cluster_insight` no longer routes through `generateL0`.** That prompt is a chunk
69
+ summariser — it asks for a one-line summary for retrieval and explicitly preserves ports,
70
+ IPs, URLs and file paths verbatim; it never asks for a conclusion, a cause, or a decision.
71
+ The new `synthesizeClusterInsight` goes through `synthesis-contract.ts`, asks for a
72
+ reusable conclusion, and **may abstain**. The old path's `if (!insight)` only fired when
73
+ the LLM call itself failed, so "this cluster is not worth keeping" had no way to be
74
+ expressed and all 2,427 rows were episode summaries by construction.
75
+ - **`extractPattern` changed target concept and now requires evidence.** The old prompt
76
+ asked for recurring preferences, behavioural tendencies and values — a personality-profile
77
+ frame, which produced dispositional attribution in 56.1% of outputs against 1.4% in the
78
+ source material. The old prompt also claimed to want "at least 2 memories as supporting
79
+ evidence" while the implementation neither received nor checked any numbering, making the
80
+ sentence free. Two pieces of evidence is now a hard gate.
81
+ - **`validateSynthesis` runs before anything is written.** The old path checked only
82
+ `response.length < 5`, which is how 28 memories ended up holding their own system prompt
83
+ as their body. `has` must be a boolean, length must be in range, the text must not echo
84
+ the prompt, and evidence numbers must refer to real, distinct cluster members. Failures
85
+ are counted by reason instead of collapsing into one `null`.
86
+ - **Pattern and insight are decoupled.** `if (!insight) { continue; }` bound two different
87
+ target concepts to one fate: an abstaining insight meant pattern extraction never ran.
88
+ They now fail and abstain independently, and "this round produced nothing" is judged on
89
+ whether the cluster had any effect at all rather than on whether an insight existed.
90
+ - **Derived rows carry an explicit `boundary`.** All 4,749 historical derivatives had none;
91
+ the retriever's `isEvidenceLayer` fell back to scope matching, so 96.4% were classified
92
+ correctly only because they happened to sit in a `cc:`/`codex:` scope — by luck of naming,
93
+ not by design. The remaining 173 sat in `memory`/`project:*` scopes and silently held
94
+ durable authority. Derived rows are `layer: "evidence"`, `authority: "distillation"`.
95
+ - **`synthesis_contract` version stamp**, so "which code produced this output" stops being
96
+ a guess from timestamps. v2 adds a single-JSON-object constraint: v1 emitted multiple JSON
97
+ objects on 3.3% of calls (all with `finish_reason: stop`, unrelated to truncation), which
98
+ made the whole response unparsable; the same measurement after the constraint is 0.0%.
99
+
100
+ ### Added — memory utility (MemOS value backtracking)
101
+
102
+ - **Value-backtracking join key (P0).** `workflow_observe` now records `readerId` and
103
+ `recalledIds`, supplying the `(memory_id, outcome)` pairing the database never had: one
104
+ side had outcomes without participants (observations did not record memories), the other
105
+ had participants without outcomes (the access tracker recorded hits but not task success).
106
+ New `src/recall-ledger.ts` keeps process-level reader identity and a retrieval-hit ledger;
107
+ managed observations from `resume_context` / `checkpoint_session` carry it automatically.
108
+ New CLI `memory-utility <id>` reports the success rate of tasks a memory took part in.
109
+ - **`utility` column (P1).** `src/memory-utility.ts` weights outcomes (success +0.8 /
110
+ corrected +0.2 / missed −0.3 / failure −0.8) with a 30-day half-life; **it can be
111
+ negative**. It lands in `metadata.utility` and deliberately not in `importance`, which is
112
+ threshold-valued (≥0.95 grants permanent decay exemption) and already written by structured
113
+ memory. Retrieval gained `utilityWeight`, default 0 (off), feeding ranking only — not tier,
114
+ not decay exemption.
115
+ - **Cross-source criterion for promotion (P2).** `scanForPromotions` gained
116
+ `minDistinctSources` (default 2). Counting "how many similar cases" and "how many distinct
117
+ episodes" differ in dimension, not degree — hitting the same problem three times is one
118
+ experience repeated, which belongs on the failure-burst path instead. It **abstains** when
119
+ source pointers are unavailable: only 1.2% of cases across the database carry a `src:` tag,
120
+ so judging strictly would mostly punish three different problems solved on one day.
121
+
122
+ ### Fixed
123
+
124
+ - **A rate-limit reply could trigger an unbounded request storm.** Found by the new contract
125
+ tests. `embedSingle` retried a context-length error by chunking, and each chunk recursed
126
+ back into `embedSingle`, able to re-enter the same branch. Two facts made that
127
+ non-terminating: `smartChunk` returns short text unchanged, so the recursion re-embedded
128
+ the identical string and reproduced the identical error; and the gate
129
+ `/context|too long|exceed|length/i` also matches rate-limit wording — both
130
+ `"Rate limit exceeded"` and `"429 quota exceeded"` trigger chunking. Measured before the
131
+ fix: **61,724 requests in five seconds** against an endpoint asking us to slow down. The
132
+ batch path had the same shape. The missing terminating condition is now present: chunking
133
+ that cannot produce anything smaller than its input throws instead of recursing, and a
134
+ chunk's own embed call cannot re-enter the branch. After: 4 ms, one request, correct error.
135
+ - **Multiple `AccessTracker` instances in one process no longer invent separate readers.**
136
+ `createComponentResolver` caches components per profile, so one session opening two
137
+ profiles produced a phantom second reader, inflating `distinctReaderCount` and the
138
+ skill-promotion read boost. The implementation now matches what `access-tracker.ts` says
139
+ about itself ("one stdio MCP server process ≈ one CC session").
140
+
141
+ ### Documentation
142
+
143
+ - `docs/memory-boundary-contract.md` documents both promotion scans, why their eligibility
144
+ gates differ, and the abstention rule.
145
+ - `retriever.ts` records that `candidatePoolSize` above 20 has never had any effect — both
146
+ candidate legs land in `store.ts`'s `clampInt(limit, 1, 20)`. The clamp has been there
147
+ since the first commit while the 2026-07-16 tuning only touched the retriever, so that
148
+ `30` was inert from the day it landed. Left alone deliberately: raising it means widening
149
+ the candidate pool, which was measured and rejected on 2026-08-22.
150
+
151
+ ### Upgrade notes
152
+
153
+ - **Node 22 or newer is required.** This is the release's only breaking change.
154
+ - Existing LanceDB data opens in place; no export/import step.
155
+ - `promote_synthesis` defaults to dry-run and writes nothing until `dryRun=false`.
156
+ - `audit.jsonl` retrieve rows are larger now that they list what was served. The list is
157
+ capped at 10 entries with `retrievedTotal` marking truncation. Rotation is still manual;
158
+ archive it if it approaches 50 MB.
159
+ - `utilityWeight` defaults to 0 and `metadata.utility` is written only by an explicit
160
+ `memory-utility --apply` run, so the MemOS work above is **available but not yet acting on
161
+ anything**. The resident MCP server was restarted on 2026-08-24, so `readerId` is now being
162
+ written (verified end-to-end on a fresh server: a `workflow_observe` call landed an
163
+ observation carrying `readerId`); `recalledIds` only gets a value when a retrieval hit
164
+ actually occurs, and no row carries `metadata.utility` yet because `--apply` has not been
165
+ run. Real data therefore starts accumulating from this release forward, not before it.
166
+ This is the intended shadow period, not a defect.
167
+
168
+ ### Verification
169
+
170
+ - 2,324 tests pass across 165 files, 0 fail (2,281 at the 3.0 gate → +14 contract, +6 audit
171
+ revision, +8 verbatim self-recall, +15 synthesis promotion). Verified under three
172
+ feature-flag combinations, including the CI default, after CI caught one assertion
173
+ that had been reading the developer's local `.env` rather than product behaviour.
174
+ - The deprecated chain is absent from `npm ls`, `node_modules/`, `bun.lock` and
175
+ `package-lock.json`; installed `openai@7.5.0` reports zero dependencies and
176
+ `engines.node >= 22.0.0`.
177
+ - SDK compatibility was measured, not assumed: 20 sandbox probes against v7.5.0 (9 API
178
+ surface, 11 loopback-HTTP runtime) plus a `tsc --strict` check of all five call sites,
179
+ with a deliberately-broken control run to confirm the type check actually reports errors.
180
+ - `promote_synthesis` was exercised read-only against the live database: 52 contract-stamped
181
+ derivatives exist; `project:codex-self-evolution` yielded 10 candidates from 10 examined,
182
+ `project:antigravity-cli` 4 from 9 (5 below importance), `learnings` 3 from 4 (1 with too
183
+ few distinct sources). Nothing was written.
184
+ - The verbatim self-recall and synthesis-promotion suites were both reverse-verified —
185
+ removing the behaviour each asserts turns the relevant tests red and no others.
186
+
187
+ ### A note on npm history
188
+
189
+ `recallnest@2.6.1` was a maintenance release published before Trusted Publishing was
190
+ configured for this package and therefore carries no build provenance. That describes how it
191
+ was published; it is not retroactively fixable, since the same npm version cannot be
192
+ republished to add provenance.
193
+
3
194
  ## v2.6.0 — Cross-process consistency and reliable distribution (2026-08-13)
4
195
 
5
196
  ### Added
package/README.md CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  # RecallNest
4
4
 
5
- **Shared Memory Layer for Any MCP Client — Claude Code, Codex, Kimi, Antigravity, Gemini CLI**
5
+ **Shared Memory Layer for Every AI Client — CLI agents, desktop apps, your own scripts**
6
6
 
7
- *One memory. Every terminal. Context that survives across windows.*
7
+ *One memory. Every client. Context that survives across windows — and across machines.*
8
8
 
9
9
  A local-first memory system backed by LanceDB that turns scattered conversation history into reusable knowledge — shared across your coding agents, recalled automatically.
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_18+-f9f1e1?logo=bun)](https://bun.sh)
13
+ [![Runtime](https://img.shields.io/badge/Runtime-Bun_|_Node.js_22+-f9f1e1?logo=bun)](https://bun.sh)
14
14
  [![LanceDB](https://img.shields.io/badge/LanceDB-Vector+FTS-orange)](https://lancedb.com)
15
- [![MCP](https://img.shields.io/badge/MCP-43_tools-blue)](https://modelcontextprotocol.io)
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
 
@@ -29,6 +29,55 @@ Coding agents forget everything between windows. Your context — project config
29
29
  RecallNest solves this: **a single LanceDB-backed memory layer that your coding agents read and write**. Context stored in one window is auto-recalled in another. Sessions checkpoint on exit and resume on start. Memory decays, evolves, and self-organizes — not just raw log storage.
30
30
 
31
31
 
32
+ ## Who Can Connect
33
+
34
+ **The data layer does not know what your client looks like.** RecallNest exposes the same LanceDB store through three outlets, so the right one is picked per client — not per protocol.
35
+
36
+ | What your client can do | Route | Verified with |
37
+ |---|---|---|
38
+ | Run a local command (CLI agent) | **MCP over stdio** | Claude Code, Codex, Kimi, Antigravity |
39
+ | Run a local command (GUI app, MCP config filled by hand) | **MCP over stdio** | Doubao desktop — same shape as Cherry Studio / ChatBox |
40
+ | Only speak HTTP | **HTTP API** | custom agents, scripts, cron |
41
+ | Run on another machine | swap the stdio command for `ssh <host> recallnest-mcp` | four clients on a laptop reading one store on a home server |
42
+
43
+ Two consequences worth stating plainly:
44
+
45
+ - **Not tied to one protocol.** A GUI chat app that supports MCP config connects the same way a terminal agent does. A client that can only issue HTTP requests still reads the same memory.
46
+ - **Not tied to one machine.** Because the MCP transport is stdio, the launch command is yours to define — point it at `ssh` and every client on every machine shares a single source of truth instead of each host growing its own database.
47
+
48
+ Adding a client does not mean changing RecallNest. A capable client writes one config line; a limited one gets a thin gateway in front of the HTTP API.
49
+
50
+ ### AI apps on a phone: the read-only gateway
51
+
52
+ The HTTP API (`:4318`) binds to `127.0.0.1` and rejects any request whose Host header is not local. That is **deliberate** — it also exposes write routes (`/v1/store`, `/v1/checkpoint`), so putting it on a public address would hand out write access.
53
+
54
+ To let an AI app on your phone read the same memory, put a read-only gateway in front:
55
+
56
+ ```bash
57
+ openssl rand -hex 32 > ~/.config/recallnest/gateway-token
58
+ chmod 600 ~/.config/recallnest/gateway-token
59
+
60
+ bun run api # local API on :4318
61
+ bun run gateway # read-only gateway on :8791 → forwards to :4318
62
+ ```
63
+
64
+ The gateway allows read routes only (`/recall`, `/search`, `/stats`, `/health`); **every write route is a 404**. Bearer token compared in constant time, per-minute rate limit, hard caps on request and response size. Put it behind a tunnel (Tailscale Serve/Funnel, Cloudflare Tunnel, …) to reach it from a phone.
65
+
66
+ ```bash
67
+ curl -X POST https://<your-tunnel>/recall \
68
+ -H "Authorization: Bearer $(cat ~/.config/recallnest/gateway-token)" \
69
+ -H 'content-type: application/json' \
70
+ -d '{"query":"how did we fix that deploy issue","limit":3,"allScopes":true}'
71
+ ```
72
+
73
+ Optional: set `RECALLNEST_GATEWAY_FILE_ROOTS="notes=/abs/path,wiki=/abs/path"` to add `GET /files/search`, a read-only ripgrep search over markdown directories you name (the query is passed as an argv element, never through a shell). Leave it unset and the route does not exist.
74
+
75
+ > The gateway also binds to `127.0.0.1` by default — exposing it is the tunnel's job. Evaluate that risk yourself.
76
+
77
+ This is how the author connected [OpenMinis](https://github.com/OpenMinis/OpenMinis) on an iPhone: the phone app reaches the gateway over a Tailscale Funnel and queries the same memory store. The interesting part is what it reads back — its own history. Those conversations get exported, flow back, and are indexed, so a phone agent that cold-starts every time ends up with memory that survives its sessions.
78
+
79
+
80
+
32
81
  ## Quick Start
33
82
 
34
83
  ### Option A: Claude Code Plugin (recommended)
@@ -55,7 +104,7 @@ npm install -g recallnest # install globally
55
104
  recallnest doctor
56
105
  ```
57
106
 
58
- Works with Node.js 18+ (via tsx) or Bun. No git clone needed.
107
+ Works with Node.js 22+ (via tsx) or Bun. No git clone needed.
59
108
 
60
109
  ### Option C: Manual setup
61
110
 
@@ -96,7 +145,7 @@ curl http://localhost:4318/v1/stats
96
145
 
97
146
  ```bash
98
147
  bash integrations/claude-code/setup.sh
99
- bash integrations/gemini-cli/setup.sh
148
+ bash integrations/agy/setup.sh
100
149
  bash integrations/codex/setup.sh
101
150
  ```
102
151
 
@@ -196,6 +245,71 @@ bun run src/ui-server.ts
196
245
 
197
246
  ---
198
247
 
248
+ ## New in v3.0: A Supported Runtime, and Conclusions That Can Be Used
249
+
250
+ v3.0 is a major release for one reason that shows up on install and one that shows up in
251
+ how memory behaves.
252
+
253
+ **The runtime boundary moved to Node 22.** RecallNest had been carrying `openai@4`, which
254
+ pulls in the deprecated `formdata-node` → `node-domexception` chain. Every `openai` release
255
+ since v5 has zero dependencies, so the chain disappears on any upgrade — but v7 declares
256
+ `engines.node >= 22.0.0`, which makes "raise the Node floor" and "move off a deprecated
257
+ dependency chain" the same piece of work rather than two. `engines.node` is now `>=22`.
258
+ This is the breaking part of the major.
259
+
260
+ **A synthesized conclusion can now reach stable memory.** `dream` writes cluster insights
261
+ and cross-memory patterns on the evidence layer deliberately — a model re-reading its own
262
+ memories is a lead to its sources, not authority over them — but stable-memory selection
263
+ refuses the evidence layer outright. The consequence was absolute: no matter how well
264
+ supported a synthesized conclusion was, nothing downstream could lean on it. `promote_synthesis`
265
+ (MCP) and `recallnest promote-synthesis` (CLI) give it a road, gated on the conclusion's own
266
+ validated evidence set rather than on repetition, because a synthesis is already a
267
+ cross-entry aggregate. The synthesized row is never modified; promotion writes a separate
268
+ durable entry carrying `promotedFrom` back to it, through the same path and the same
269
+ `canonicalKey` dedup as every other promotion.
270
+
271
+ Also in this release:
272
+
273
+ - **Retrieve audit rows say what was served.** They used to record the query and a hit
274
+ count. Because beliefs are revised in place — the id stays, the version increments, the
275
+ old text survives as a `superseded` row — "memory X was retrieved" was ambiguous across
276
+ every belief change. Rows now carry each result's id, revision, lifecycle status, and
277
+ boundary. The list is capped, and a capped list says so.
278
+ - **HTTP contract tests for embeddings and chat completions.** Every previous test stubbed
279
+ the SDK client, so nothing exercised a socket, and a transport-level regression would
280
+ have passed all of them. These drive the real classes through the real SDK against a
281
+ loopback server, covering success, error, and timeout for the default OpenAI shape plus
282
+ the Jina and Qwen-compatible profiles. No network egress, no vendor credentials.
283
+ - **Fixed: a rate-limit reply could trigger an unbounded request storm.** Found by those
284
+ tests. The embedder retried a context-length error by chunking, the chunker returns short
285
+ text unchanged, and the gate that decided "this is a context error" also matched
286
+ rate-limit wording — so a 429 re-embedded the same text forever. Measured at over 61,000
287
+ requests in five seconds against an endpoint asking us to slow down. Failure is bounded now.
288
+ - **A known recall gap is now a runnable regression.** A memory that is long, older, and
289
+ rarely read can fail to be recalled by words copied out of its own body, while short,
290
+ fresh, frequently-read entries outrank it. It is a ranking problem, not a filtering one —
291
+ the entry clears every threshold and then places last. The reproduction is checked in; the
292
+ ranking fix is not in this release.
293
+ - **44 MCP tools** across three tiers, up from 43.
294
+
295
+ ### Upgrading from v2.6
296
+
297
+ - **Node 22 or newer is required.** Bun users are unaffected. This is the only breaking
298
+ change in the release.
299
+ - Existing LanceDB data is opened in place. No export or import step.
300
+ - `promote_synthesis` defaults to dry-run and writes nothing until `dryRun=false`.
301
+ - `audit.jsonl` rows for retrievals are larger now that they list what was served. Rotation
302
+ is still manual; archive it if it approaches 50 MB.
303
+
304
+ ### A note on npm history
305
+
306
+ `recallnest@2.6.1` on npm was a maintenance release published before Trusted Publishing was
307
+ configured for this package, so it carries no build provenance. That is a fact about how it
308
+ was published, not a defect in the package, and it is not retroactively fixable — the same
309
+ npm version cannot be republished to add provenance.
310
+
311
+ ---
312
+
199
313
  ## New in v2.6: Reliable Cross-Process Memory and Distribution
200
314
 
201
315
  v2.6 turns the development since v2.5.4 into a release-ready upgrade:
@@ -266,8 +380,8 @@ v2.2 hardened retrieval quality; v2.3 opens RecallNest to external data sources
266
380
  ┌──────────────────────────────────────────────────────────┐
267
381
  │ Client Layer │
268
382
  ├──────────┬──────────┬──────────┬──────────────────────────┤
269
- │ Claude │ Gemini │ Codex │ Custom Agents / curl │
270
- │ Code │ CLI │ │ │
383
+ │ Claude │ Anti- │ Codex │ Custom Agents / curl │
384
+ │ Code │ gravity │ │ │
271
385
  └────┬─────┴────┬─────┴────┬─────┴──────┬──────────────────┘
272
386
  │ │ │ │
273
387
  └──── MCP (stdio) ───┘ HTTP API (port 4318)
@@ -277,7 +391,7 @@ v2.2 hardened retrieval quality; v2.3 opens RecallNest to external data sources
277
391
  │ Integration Layer │
278
392
  │ ┌─────────────────────┐ ┌────────────────────────────┐ │
279
393
  │ │ MCP Server │ │ HTTP API Server │ │
280
- │ │ 43 tools │ │ 21 endpoints │ │
394
+ │ │ 44 tools │ │ 21 endpoints │ │
281
395
  │ └─────────┬───────────┘ └──────────┬─────────────────┘ │
282
396
  └────────────┼─────────────────────────┼───────────────────┘
283
397
  └──────────┬──────────────┘
@@ -323,7 +437,7 @@ v2.2 hardened retrieval quality; v2.3 opens RecallNest to external data sources
323
437
 
324
438
  RecallNest serves two interfaces:
325
439
 
326
- - **MCP** — for any MCP client: Claude Code, Codex, Kimi, Antigravity, Gemini CLI (native tool access)
440
+ - **MCP (stdio)** — for any client that can launch a command: CLI agents (Claude Code, Codex, Kimi, Antigravity) and GUI apps that accept an MCP config (Doubao, Cherry Studio, ChatBox)
327
441
  - **HTTP API** — for custom agents, SDK-based apps, and any HTTP client
328
442
 
329
443
  ### Agent framework examples
@@ -339,7 +453,7 @@ Examples live in [`integrations/examples/`](integrations/examples/):
339
453
  ---
340
454
 
341
455
  <details>
342
- <summary><strong>MCP Tools (43 tools)</strong></summary>
456
+ <summary><strong>MCP Tools (44 tools)</strong></summary>
343
457
 
344
458
  | Tool | Description |
345
459
  |------|-------------|
@@ -351,6 +465,7 @@ Examples live in [`integrations/examples/`](integrations/examples/):
351
465
  | `store_case` | Store a reusable problem-solution pair as durable `cases` memory |
352
466
  | `promote_memory` | Explicitly promote evidence into durable memory |
353
467
  | `promote_scan` | Scan recent evidence and auto-promote qualifying memories into durable storage |
468
+ | `promote_synthesis` | Scan dream-synthesized conclusions and promote the ones their own evidence set supports |
354
469
  | `list_conflicts` | List or inspect promotion conflict candidates |
355
470
  | `audit_conflicts` | Summarize stale/escalated conflict priorities |
356
471
  | `escalate_conflicts` | Preview or apply conflict escalation metadata |
@@ -492,6 +607,8 @@ RecallNest auto-detects babel-memory at startup — no configuration needed. Wit
492
607
 
493
608
  RecallNest is actively maintained. All major architecture phases are complete — see the full [Roadmap](ROADMAP.md) for current priorities and future plans.
494
609
 
610
+ Maintainers: see [Publishing RecallNest](https://github.com/AliceLJY/recallnest/blob/main/docs/releasing.md) for the npm Trusted Publishing, validation, and recovery process.
611
+
495
612
  ---
496
613
 
497
614
  ## Relationship to memory-lancedb-pro
@@ -499,7 +616,7 @@ RecallNest is actively maintained. All major architecture phases are complete
499
616
  RecallNest started as a fork of [memory-lancedb-pro](https://github.com/CortexReach/memory-lancedb-pro) and shares its core ideas around hybrid retrieval, decay modeling, and memory-as-engineering-system. The key difference:
500
617
 
501
618
  - **memory-lancedb-pro** is an OpenClaw plugin — it adds long-term memory to a single OpenClaw agent.
502
- - **RecallNest** is a standalone memory layer — it serves any MCP client (Claude Code, Codex, Kimi, Antigravity, Gemini CLI) simultaneously through MCP + HTTP API, with session continuity, structured assets, and conflict management built in.
619
+ - **RecallNest** is a standalone memory layer — it serves CLI agents, GUI chat apps and plain HTTP callers simultaneously through MCP + HTTP API, with session continuity, structured assets, and conflict management built in.
503
620
 
504
621
  ## Credit
505
622
 
@@ -520,9 +637,9 @@ Part of the **小试AI** open-source AI workflow:
520
637
  |---------|-------------|
521
638
  | [babel-memory](https://github.com/AliceLJY/babel-memory) | Multilingual preprocessing for BM25 — 27+ languages, zero deps |
522
639
  | cc-empire *(private)* | Hooks/rules/methodology — the connective tissue of the whole ecosystem |
523
- | [telegram-ai-bridge](https://github.com/AliceLJY/telegram-ai-bridge) | Telegram bots for Claude, Codex, and Gemini |
640
+ | [telegram-ai-bridge](https://github.com/AliceLJY/telegram-ai-bridge) | Telegram bots for Claude, Codex, Agy, and Kimi |
524
641
  | [tg-bridge-channel](https://github.com/AliceLJY/tg-bridge-channel) | Sister Telegram bridge using Claude Agent View background sessions |
525
- | [wechat-ai-bridge](https://github.com/AliceLJY/wechat-ai-bridge) | Run Claude Code / Codex / Gemini in WeChat with session management |
642
+ | [wechat-ai-bridge](https://github.com/AliceLJY/wechat-ai-bridge) | Run Claude Code / Codex in WeChat with session management |
526
643
  | [openclaw-tunnel](https://github.com/AliceLJY/openclaw-tunnel) | Docker ↔ host CLI bridge (maintenance mode — LanceDB test only) |
527
644
  | [digital-clone-skill](https://github.com/AliceLJY/digital-clone-skill) | Build digital clones from corpus data |
528
645
  | [claude-code-studio](https://github.com/AliceLJY/claude-code-studio) | Multi-session collaboration platform for Claude Code |