hippo-memory 1.61.0 → 1.63.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 (377) hide show
  1. package/README.md +37 -53
  2. package/dist/agent-memories/apply.d.ts +3 -1
  3. package/dist/agent-memories/apply.js +23 -1
  4. package/dist/agent-memories/claude-code.d.ts +4 -1
  5. package/dist/agent-memories/claude-code.js +53 -9
  6. package/dist/agent-memories/report.d.ts +1 -0
  7. package/dist/agent-memories/report.js +2 -2
  8. package/dist/agent-memories/sync.d.ts +3 -3
  9. package/dist/agent-memories/sync.js +46 -24
  10. package/dist/agent-memories/types.d.ts +0 -2
  11. package/dist/ambient-store.d.ts +4 -4
  12. package/dist/ambient-store.js +4 -3
  13. package/dist/api/assemble.d.ts +7 -10
  14. package/dist/api/assemble.js +62 -66
  15. package/dist/api/audit.d.ts +2 -2
  16. package/dist/api/audit.js +2 -2
  17. package/dist/api/auth.d.ts +6 -6
  18. package/dist/api/auth.js +5 -7
  19. package/dist/api/context-select.d.ts +50 -0
  20. package/dist/api/context-select.js +342 -0
  21. package/dist/api/context-types.d.ts +12 -17
  22. package/dist/api/context.d.ts +5 -4
  23. package/dist/api/context.js +208 -535
  24. package/dist/api/dormant.js +1 -1
  25. package/dist/api/drill-down.d.ts +4 -4
  26. package/dist/api/drill-down.js +56 -41
  27. package/dist/api/outcome.d.ts +8 -13
  28. package/dist/api/outcome.js +13 -17
  29. package/dist/api/promote.d.ts +5 -8
  30. package/dist/api/promote.js +55 -66
  31. package/dist/api/quarantine.js +3 -2
  32. package/dist/api/recall-types.d.ts +43 -55
  33. package/dist/api/recall.d.ts +3 -3
  34. package/dist/api/recall.js +310 -456
  35. package/dist/api/remember.d.ts +2 -2
  36. package/dist/api/sleep.d.ts +7 -35
  37. package/dist/api/sleep.js +206 -220
  38. package/dist/api/tokens.d.ts +2 -2
  39. package/dist/api/tokens.js +2 -2
  40. package/dist/api/types.d.ts +6 -10
  41. package/dist/api/types.js +2 -4
  42. package/dist/audit-prune.d.ts +4 -6
  43. package/dist/audit-prune.js +3 -5
  44. package/dist/audit.js +11 -33
  45. package/dist/auth.d.ts +8 -9
  46. package/dist/auth.js +5 -7
  47. package/dist/autolearn.d.ts +1 -1
  48. package/dist/autolearn.js +1 -1
  49. package/dist/availability.js +3 -5
  50. package/dist/capture/command.d.ts +5 -4
  51. package/dist/capture/command.js +8 -22
  52. package/dist/capture/compact.d.ts +2 -2
  53. package/dist/capture/compact.js +11 -15
  54. package/dist/capture/extract.js +37 -115
  55. package/dist/capture-error.d.ts +1 -1
  56. package/dist/capture-error.js +1 -1
  57. package/dist/churn-git.d.ts +1 -1
  58. package/dist/churn-git.js +1 -1
  59. package/dist/cli/audit.js +3 -4
  60. package/dist/cli/auth.js +3 -6
  61. package/dist/cli/briefs.js +324 -306
  62. package/dist/cli/context.js +44 -34
  63. package/dist/cli/continuity.js +283 -271
  64. package/dist/cli/curate.d.ts +1 -1
  65. package/dist/cli/curate.js +43 -58
  66. package/dist/cli/dag.js +5 -9
  67. package/dist/cli/decisions.js +334 -345
  68. package/dist/cli/explain.js +68 -61
  69. package/dist/cli/goals.js +1 -1
  70. package/dist/cli/init.js +1 -1
  71. package/dist/cli/maintenance.js +62 -51
  72. package/dist/cli/playbooks.js +391 -379
  73. package/dist/cli/projects.js +11 -6
  74. package/dist/cli/recall.js +30 -44
  75. package/dist/cli/remember.js +118 -87
  76. package/dist/cli/session-hooks.js +106 -115
  77. package/dist/cli/setup.d.ts +1 -1
  78. package/dist/cli/setup.js +267 -250
  79. package/dist/cli/shared.js +3 -3
  80. package/dist/cli/slack.js +1 -1
  81. package/dist/cli/sleep.js +27 -1
  82. package/dist/cli/status.d.ts +4 -4
  83. package/dist/cli/status.js +80 -76
  84. package/dist/cli/transfer.js +88 -107
  85. package/dist/cli/usage.js +9 -6
  86. package/dist/cli.d.ts +1 -1
  87. package/dist/cli.js +4 -9
  88. package/dist/compaction-record.d.ts +2 -2
  89. package/dist/compaction-record.js +89 -68
  90. package/dist/compare.d.ts +11 -16
  91. package/dist/compare.js +11 -16
  92. package/dist/config.d.ts +19 -18
  93. package/dist/config.js +90 -67
  94. package/dist/connectors/github/backfill.d.ts +2 -2
  95. package/dist/connectors/github/backfill.js +8 -15
  96. package/dist/connectors/github/cli-impl.js +3 -8
  97. package/dist/connectors/github/deletion.d.ts +5 -12
  98. package/dist/connectors/github/deletion.js +5 -12
  99. package/dist/connectors/github/dlq.d.ts +6 -9
  100. package/dist/connectors/github/dlq.js +2 -3
  101. package/dist/connectors/github/ingest.d.ts +5 -7
  102. package/dist/connectors/github/ingest.js +8 -12
  103. package/dist/connectors/github/octokit-client.d.ts +3 -5
  104. package/dist/connectors/github/octokit-client.js +5 -6
  105. package/dist/connectors/github/signature.d.ts +9 -39
  106. package/dist/connectors/github/signature.js +9 -39
  107. package/dist/connectors/github/tenant-routing.d.ts +1 -1
  108. package/dist/connectors/github/tenant-routing.js +1 -1
  109. package/dist/connectors/github/transform.js +2 -2
  110. package/dist/connectors/github/types.d.ts +2 -10
  111. package/dist/connectors/github/types.js +1 -3
  112. package/dist/connectors/slack/deletion.d.ts +3 -8
  113. package/dist/connectors/slack/deletion.js +3 -8
  114. package/dist/connectors/slack/dlq.d.ts +1 -1
  115. package/dist/connectors/slack/ingest.d.ts +1 -1
  116. package/dist/connectors/slack/ingest.js +7 -16
  117. package/dist/connectors/slack/signature.d.ts +1 -1
  118. package/dist/connectors/slack/tenant-routing.d.ts +3 -5
  119. package/dist/connectors/slack/tenant-routing.js +3 -5
  120. package/dist/connectors/slack/transform.d.ts +5 -6
  121. package/dist/connectors/slack/transform.js +5 -6
  122. package/dist/connectors/slack/types.d.ts +2 -6
  123. package/dist/connectors/slack/types.js +1 -3
  124. package/dist/connectors/slack/web-client.js +10 -3
  125. package/dist/connectors/slack/workspaces.d.ts +3 -5
  126. package/dist/connectors/slack/workspaces.js +3 -5
  127. package/dist/consolidate/conflicts.js +3 -14
  128. package/dist/consolidate/decay.js +9 -29
  129. package/dist/consolidate/llm-passes.js +4 -5
  130. package/dist/consolidate/merge.js +8 -23
  131. package/dist/consolidate/run.d.ts +1 -8
  132. package/dist/consolidate/run.js +3 -25
  133. package/dist/consolidate/sleep.js +5 -17
  134. package/dist/consolidate/traces.js +9 -21
  135. package/dist/customer-notes.d.ts +5 -7
  136. package/dist/customer-notes.js +82 -76
  137. package/dist/dag.d.ts +10 -21
  138. package/dist/dag.js +189 -203
  139. package/dist/db/continuity.js +2 -2
  140. package/dist/db/migrations/v14.js +1 -1
  141. package/dist/db/migrations/v15.js +1 -2
  142. package/dist/db/migrations/v16.js +3 -4
  143. package/dist/db/migrations/v17.js +2 -3
  144. package/dist/db/migrations/v19.js +1 -1
  145. package/dist/db/migrations/v20.js +1 -1
  146. package/dist/db/migrations/v21.js +2 -6
  147. package/dist/db/migrations/v22.js +2 -4
  148. package/dist/db/migrations/v23.js +1 -1
  149. package/dist/db/migrations/v24.js +4 -6
  150. package/dist/db/migrations/v25.js +2 -3
  151. package/dist/db/migrations/v26.js +3 -3
  152. package/dist/db/migrations/v27.js +2 -10
  153. package/dist/db/migrations/v28.js +5 -8
  154. package/dist/db/migrations/v29.js +3 -4
  155. package/dist/db/migrations/v30.js +2 -2
  156. package/dist/db/migrations/v31.js +1 -1
  157. package/dist/db/migrations/v32.js +1 -1
  158. package/dist/db/migrations/v33.js +3 -3
  159. package/dist/db/migrations/v34.js +1 -1
  160. package/dist/db/migrations/v35.js +3 -4
  161. package/dist/db/migrations/v36.js +3 -4
  162. package/dist/db/migrations/v37.js +5 -5
  163. package/dist/db/migrations/v38.js +7 -8
  164. package/dist/db/migrations/v39.js +1 -1
  165. package/dist/db/migrations/v40.js +4 -16
  166. package/dist/db/migrations/v41.js +3 -4
  167. package/dist/db/migrations/v42.js +3 -4
  168. package/dist/db/migrations/v45.js +1 -1
  169. package/dist/db/migrations/v46.js +1 -1
  170. package/dist/db/migrations/v47.js +1 -1
  171. package/dist/db/migrations/v48.js +1 -1
  172. package/dist/decisions.d.ts +2 -2
  173. package/dist/decisions.js +97 -80
  174. package/dist/dedupe.js +86 -61
  175. package/dist/delivery-recorder.js +154 -135
  176. package/dist/doctor.js +129 -110
  177. package/dist/dormant.js +1 -4
  178. package/dist/embedding-provider.d.ts +4 -8
  179. package/dist/embedding-provider.js +4 -8
  180. package/dist/embeddings.js +55 -47
  181. package/dist/env.d.ts +1 -1
  182. package/dist/env.js +12 -12
  183. package/dist/escape.d.ts +5 -0
  184. package/dist/escape.js +10 -0
  185. package/dist/eval-stats.d.ts +1 -2
  186. package/dist/eval-stats.js +1 -2
  187. package/dist/eval-suite.js +27 -21
  188. package/dist/extract.js +4 -9
  189. package/dist/failure-log.d.ts +3 -3
  190. package/dist/failure-log.js +1 -1
  191. package/dist/forward-claim-detector.d.ts +2 -4
  192. package/dist/forward-claim-detector.js +6 -11
  193. package/dist/goals.d.ts +3 -3
  194. package/dist/goals.js +103 -91
  195. package/dist/graph/read.d.ts +2 -2
  196. package/dist/graph/read.js +5 -6
  197. package/dist/graph/types.d.ts +8 -8
  198. package/dist/graph/write.d.ts +7 -14
  199. package/dist/graph/write.js +16 -23
  200. package/dist/graph-extract.d.ts +7 -8
  201. package/dist/graph-extract.js +62 -72
  202. package/dist/graph-recall.d.ts +2 -2
  203. package/dist/graph-recall.js +55 -49
  204. package/dist/graph-stream.d.ts +5 -6
  205. package/dist/graph-stream.js +66 -57
  206. package/dist/graph-view.d.ts +2 -2
  207. package/dist/graph-view.js +7 -7
  208. package/dist/half-life-migration.d.ts +1 -2
  209. package/dist/half-life-migration.js +2 -3
  210. package/dist/hooks/codex-session.js +1 -1
  211. package/dist/hooks/codex-wrapper.d.ts +1 -1
  212. package/dist/hooks/codex-wrapper.js +3 -2
  213. package/dist/hooks/json-hooks.d.ts +2 -2
  214. package/dist/hooks/json-hooks.js +5 -4
  215. package/dist/hooks/opencode.d.ts +1 -1
  216. package/dist/hooks/opencode.js +5 -4
  217. package/dist/hooks/shared.d.ts +3 -7
  218. package/dist/hooks/shared.js +1 -8
  219. package/dist/http-util.d.ts +2 -3
  220. package/dist/http-util.js +3 -0
  221. package/dist/importers/core.d.ts +2 -9
  222. package/dist/importers/core.js +15 -30
  223. package/dist/importers/sources.js +2 -1
  224. package/dist/importers/vault.js +2 -20
  225. package/dist/incidents.d.ts +1 -1
  226. package/dist/incidents.js +46 -39
  227. package/dist/instruction-detect.d.ts +1 -1
  228. package/dist/instruction-detect.js +1 -1
  229. package/dist/invalidation.d.ts +3 -0
  230. package/dist/invalidation.js +160 -114
  231. package/dist/json.d.ts +5 -0
  232. package/dist/json.js +4 -0
  233. package/dist/judgment.js +1 -2
  234. package/dist/local-embedding.js +1 -1
  235. package/dist/mcp/admin-tools.js +7 -17
  236. package/dist/mcp/format.js +1 -1
  237. package/dist/mcp/framing.js +3 -6
  238. package/dist/mcp/protocol.d.ts +2 -5
  239. package/dist/mcp/protocol.js +1 -3
  240. package/dist/mcp/recall-tools.js +12 -15
  241. package/dist/mcp/request.js +4 -3
  242. package/dist/mcp/session-state.js +2 -3
  243. package/dist/mcp/stdio.js +2 -1
  244. package/dist/mcp/tools.js +9 -6
  245. package/dist/memory-value-weights.d.ts +5 -8
  246. package/dist/memory-value-weights.js +5 -8
  247. package/dist/memory-value.d.ts +13 -13
  248. package/dist/memory-value.js +26 -37
  249. package/dist/memory.d.ts +20 -22
  250. package/dist/memory.js +24 -48
  251. package/dist/multihop.d.ts +1 -1
  252. package/dist/multihop.js +3 -2
  253. package/dist/owner-validation.d.ts +4 -5
  254. package/dist/owner-validation.js +4 -5
  255. package/dist/physics.d.ts +4 -4
  256. package/dist/physics.js +7 -9
  257. package/dist/policies.d.ts +9 -10
  258. package/dist/policies.js +96 -81
  259. package/dist/postinstall.js +3 -6
  260. package/dist/predictions/planning-fallacy.d.ts +9 -14
  261. package/dist/predictions/planning-fallacy.js +10 -16
  262. package/dist/predictions/store.d.ts +15 -23
  263. package/dist/predictions/store.js +36 -33
  264. package/dist/processes.d.ts +2 -7
  265. package/dist/processes.js +88 -72
  266. package/dist/project-briefs.d.ts +2 -3
  267. package/dist/project-briefs.js +141 -118
  268. package/dist/project-identity.d.ts +22 -9
  269. package/dist/project-identity.js +47 -12
  270. package/dist/project-merge.d.ts +28 -5
  271. package/dist/project-merge.js +213 -46
  272. package/dist/project-remote.d.ts +12 -0
  273. package/dist/project-remote.js +138 -0
  274. package/dist/prompt-recall.js +1 -2
  275. package/dist/rate-limit.d.ts +1 -1
  276. package/dist/rate-limit.js +1 -1
  277. package/dist/raw-archive.d.ts +9 -0
  278. package/dist/raw-archive.js +70 -53
  279. package/dist/recall-history.d.ts +19 -20
  280. package/dist/recall-history.js +24 -42
  281. package/dist/recall-pipeline.js +4 -28
  282. package/dist/recall-scope.d.ts +7 -8
  283. package/dist/recall-scope.js +7 -8
  284. package/dist/recall-trace.d.ts +5 -9
  285. package/dist/recall-trace.js +6 -10
  286. package/dist/refine-llm.d.ts +1 -1
  287. package/dist/refine-llm.js +2 -2
  288. package/dist/reject-flow.d.ts +3 -4
  289. package/dist/reject-flow.js +122 -117
  290. package/dist/rejection.d.ts +5 -6
  291. package/dist/rejection.js +7 -15
  292. package/dist/rerankers/clef.d.ts +1 -1
  293. package/dist/rerankers/jev.d.ts +1 -2
  294. package/dist/rerankers/jev.js +4 -5
  295. package/dist/rerankers/llm.d.ts +1 -2
  296. package/dist/rerankers/llm.js +1 -2
  297. package/dist/rerankers/types.d.ts +1 -2
  298. package/dist/rrf.d.ts +2 -2
  299. package/dist/rrf.js +2 -2
  300. package/dist/search/bm25-search.d.ts +1 -1
  301. package/dist/search/bm25-search.js +2 -1
  302. package/dist/search/boosts.js +2 -1
  303. package/dist/search/hybrid.d.ts +1 -1
  304. package/dist/search/hybrid.js +2 -1
  305. package/dist/search/physics-search.d.ts +1 -1
  306. package/dist/search/physics-search.js +2 -1
  307. package/dist/search/types.d.ts +2 -0
  308. package/dist/search/types.js +3 -1
  309. package/dist/secret-detect.d.ts +4 -5
  310. package/dist/secret-detect.js +6 -10
  311. package/dist/server/auth.js +5 -5
  312. package/dist/server/client-ip.js +1 -1
  313. package/dist/server/cursor.js +2 -1
  314. package/dist/server/mcp-http.js +4 -4
  315. package/dist/server/request.d.ts +3 -6
  316. package/dist/server/request.js +6 -7
  317. package/dist/server/routes/admin.js +5 -4
  318. package/dist/server/routes/customer-notes.js +6 -5
  319. package/dist/server/routes/decisions.js +4 -3
  320. package/dist/server/routes/incidents.js +7 -5
  321. package/dist/server/routes/memories.js +7 -7
  322. package/dist/server/routes/policies.js +3 -2
  323. package/dist/server/routes/predictions.js +12 -15
  324. package/dist/server/routes/processes.js +3 -2
  325. package/dist/server/routes/project-briefs.js +8 -7
  326. package/dist/server/routes/recall.js +95 -93
  327. package/dist/server/routes/skills.js +6 -5
  328. package/dist/server/types.d.ts +1 -1
  329. package/dist/server/validation.d.ts +1 -2
  330. package/dist/server/validation.js +7 -14
  331. package/dist/server-detect.js +72 -58
  332. package/dist/server.d.ts +2 -2
  333. package/dist/server.js +131 -117
  334. package/dist/shared.d.ts +26 -17
  335. package/dist/shared.js +102 -104
  336. package/dist/skills.d.ts +3 -3
  337. package/dist/skills.js +88 -72
  338. package/dist/store/audit-event.d.ts +2 -2
  339. package/dist/store/audit-event.js +1 -1
  340. package/dist/store/candidates.d.ts +2 -2
  341. package/dist/store/candidates.js +4 -3
  342. package/dist/store/conflicts.js +30 -22
  343. package/dist/store/delete-and-batch.d.ts +11 -14
  344. package/dist/store/delete-and-batch.js +40 -91
  345. package/dist/store/entry-reads.d.ts +17 -25
  346. package/dist/store/entry-reads.js +59 -40
  347. package/dist/store/entry-row.d.ts +6 -24
  348. package/dist/store/entry-row.js +6 -24
  349. package/dist/store/entry-writes.d.ts +6 -7
  350. package/dist/store/entry-writes.js +13 -11
  351. package/dist/store/handoffs.d.ts +1 -1
  352. package/dist/store/handoffs.js +7 -10
  353. package/dist/store/index-and-stats.d.ts +2 -6
  354. package/dist/store/index-and-stats.js +4 -10
  355. package/dist/store/mirrors.d.ts +6 -19
  356. package/dist/store/mirrors.js +14 -39
  357. package/dist/store/open.js +9 -31
  358. package/dist/store/rows.d.ts +5 -11
  359. package/dist/store/rows.js +6 -11
  360. package/dist/store/search-rows.d.ts +17 -34
  361. package/dist/store/search-rows.js +34 -56
  362. package/dist/store/sessions.d.ts +4 -5
  363. package/dist/store/sessions.js +5 -6
  364. package/dist/store/summaries.d.ts +13 -17
  365. package/dist/store/summaries.js +26 -70
  366. package/dist/support-bundle.js +4 -8
  367. package/dist/tenant.d.ts +1 -5
  368. package/dist/token-ledger.d.ts +1 -1
  369. package/dist/token-ledger.js +3 -5
  370. package/dist/trace.js +1 -3
  371. package/dist/version.d.ts +1 -1
  372. package/dist/version.js +1 -1
  373. package/dist/working-memory.d.ts +1 -1
  374. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  375. package/extensions/openclaw-plugin/package.json +1 -1
  376. package/openclaw.plugin.json +1 -1
  377. package/package.json +1 -1
@@ -1,21 +1,20 @@
1
1
  /**
2
- * J1 anchoring detector (recall-recurrence) — pure module.
2
+ * Anchoring detector (recall-recurrence), pure module.
3
3
  *
4
- * Implements two detection rules from ROADMAP-RESEARCH.md L546:
5
- * R1 query_repeat: same queryHash within recentRepeatWindow returned
4
+ * Implements two detection rules:
5
+ * query_repeat: same queryHash within recentRepeatWindow returned
6
6
  * same topMemoryId (caller is re-asking the same question).
7
- * R2 memory_dominance: same topMemoryId across >= minDominance distinct
7
+ * memory_dominance: same topMemoryId across >= minDominance distinct
8
8
  * queryHashes (memory acts as a fixed-point anchor regardless of what
9
9
  * the agent asks).
10
10
  *
11
- * Per the plan v3 architectural decision: each pipeline (api.recall via
11
+ * Each pipeline (api.recall via
12
12
  * HTTP, cmdRecall, MCP hippo_recall) owns its OWN ring buffer Map keyed
13
13
  * by (tenant, session). No cross-pipeline sharing (the typical multi-
14
14
  * process deployment makes IPC ring-sharing impractical; per-pipeline
15
15
  * is correct because each pipeline has its own top-1 ranking anyway).
16
16
  *
17
- * Plan: docs/plans/2026-05-26-j1-anchoring-detector.md.
18
- * Composes with J3.2: AnchoringHint + PlanningFallacyHint are independent
17
+ * AnchoringHint + PlanningFallacyHint are independent
19
18
  * signals; both can fire on the same recall.
20
19
  */
21
20
  export type AnchoringReason = 'query_repeat' | 'memory_dominance';
@@ -36,20 +35,20 @@ export interface RecallHistoryEntry {
36
35
  queryHash: number;
37
36
  /** Top-1 memory id this recall surfaced; null if zero results. */
38
37
  topMemoryId: string | null;
39
- /** ISO-8601 timestamp; advisory, not used by R1/R2 logic. */
38
+ /** ISO-8601 timestamp; advisory, not used by the detection rules. */
40
39
  ts: string;
41
40
  /** Memory id of the AnchoringHint that fired on this recall, if any.
42
- * Used by R1/R2 cooldown logic to prevent re-emitting the same hint on
41
+ * Used by the cooldown logic to prevent re-emitting the same hint on
43
42
  * consecutive recalls within the dominance window. Caller-written
44
43
  * AFTER detectAnchoring returns; reads next time detectAnchoring runs. */
45
44
  anchoredOn?: string;
46
45
  }
47
46
  export type RecallHistorySnapshot = readonly RecallHistoryEntry[];
48
47
  export interface DetectAnchoringOpts {
49
- /** R2 threshold: number of distinct queryHashes that must have returned
48
+ /** memory_dominance threshold: number of distinct queryHashes that must have returned
50
49
  * the same topMemoryId. Default 3. */
51
50
  minDominance?: number;
52
- /** R1 window: how many recent history entries to scan for query repeat.
51
+ /** query_repeat window: how many recent history entries to scan for query repeat.
53
52
  * Default 5. */
54
53
  recentRepeatWindow?: number;
55
54
  /** Cooldown: if the immediately-prior fire (per `anchoredOn`) was for
@@ -63,8 +62,8 @@ export interface DetectAnchoringOpts {
63
62
  * sort tokens → join → FNV-1a 32-bit.
64
63
  *
65
64
  * Token sort + dedup means semantically-equivalent queries with reordered
66
- * words collide intentionally (the roadmap's "semantically-distinct" v1
67
- * uses textual normalization; embedding-based distinctness is J1-v2).
65
+ * words collide intentionally ("semantically-distinct" is approximated by
66
+ * textual normalization, not embeddings).
68
67
  *
69
68
  * Deterministic across processes; stable across Node + V8 versions.
70
69
  */
@@ -73,17 +72,17 @@ export declare function hashQueryText(query: string): number;
73
72
  * Detect anchoring patterns in the recall history against the current
74
73
  * recall's (queryHash, topMemoryId).
75
74
  *
76
- * Rule precedence: R2 (memory_dominance) wins on tie. When both R1 and R2
77
- * fire on the same recall, return only the R2 hint — R2's signal is the
78
- * cognitively stronger one (a memory dominating multiple DIFFERENT queries
79
- * is a fixed-point anchor; R1 alone is just a literal re-ask).
75
+ * Rule precedence: memory_dominance wins on tie. When both rules fire on the
76
+ * same recall, return only memory_dominance, the stronger signal (a memory
77
+ * dominating multiple DIFFERENT queries is a fixed-point anchor; query_repeat
78
+ * alone is just a literal re-ask).
80
79
  *
81
80
  * Cooldown: if the immediately-prior recall fired a hint on the SAME
82
81
  * topMemoryId within `cooldown=3` history entries, suppress. Prevents
83
82
  * spam when the agent repeatedly recalls within the dominance window.
84
- * Cooldown is per-memory, not per-rule: if R2 fired on M (cooldown
85
- * engaged for M), and the next recall has top=N + repeated query →
86
- * R1 fires on N (different memory, not in cooldown).
83
+ * Cooldown is per-memory, not per-rule: if memory_dominance fired on M
84
+ * (cooldown engaged for M), and the next recall has top=N + repeated query,
85
+ * query_repeat fires on N (different memory, not in cooldown).
87
86
  *
88
87
  * @returns AnchoringHint when a pattern fires; null otherwise.
89
88
  */
@@ -1,21 +1,20 @@
1
1
  /**
2
- * J1 anchoring detector (recall-recurrence) — pure module.
2
+ * Anchoring detector (recall-recurrence), pure module.
3
3
  *
4
- * Implements two detection rules from ROADMAP-RESEARCH.md L546:
5
- * R1 query_repeat: same queryHash within recentRepeatWindow returned
4
+ * Implements two detection rules:
5
+ * query_repeat: same queryHash within recentRepeatWindow returned
6
6
  * same topMemoryId (caller is re-asking the same question).
7
- * R2 memory_dominance: same topMemoryId across >= minDominance distinct
7
+ * memory_dominance: same topMemoryId across >= minDominance distinct
8
8
  * queryHashes (memory acts as a fixed-point anchor regardless of what
9
9
  * the agent asks).
10
10
  *
11
- * Per the plan v3 architectural decision: each pipeline (api.recall via
11
+ * Each pipeline (api.recall via
12
12
  * HTTP, cmdRecall, MCP hippo_recall) owns its OWN ring buffer Map keyed
13
13
  * by (tenant, session). No cross-pipeline sharing (the typical multi-
14
14
  * process deployment makes IPC ring-sharing impractical; per-pipeline
15
15
  * is correct because each pipeline has its own top-1 ranking anyway).
16
16
  *
17
- * Plan: docs/plans/2026-05-26-j1-anchoring-detector.md.
18
- * Composes with J3.2: AnchoringHint + PlanningFallacyHint are independent
17
+ * AnchoringHint + PlanningFallacyHint are independent
19
18
  * signals; both can fire on the same recall.
20
19
  */
21
20
  import { envAnchoringOff, envAvailabilityOff } from './env.js';
@@ -31,44 +30,27 @@ const DEFAULT_COOLDOWN = 3;
31
30
  * sort tokens → join → FNV-1a 32-bit.
32
31
  *
33
32
  * Token sort + dedup means semantically-equivalent queries with reordered
34
- * words collide intentionally (the roadmap's "semantically-distinct" v1
35
- * uses textual normalization; embedding-based distinctness is J1-v2).
33
+ * words collide intentionally ("semantically-distinct" is approximated by
34
+ * textual normalization, not embeddings).
36
35
  *
37
36
  * Deterministic across processes; stable across Node + V8 versions.
38
37
  */
39
38
  export function hashQueryText(query) {
40
39
  if (!query)
41
40
  return 0;
42
- // Token dedup before join: the R2 contract says "distinct queries"
43
- // means semantically distinct, so `foo bar` and `foo foo bar` should
44
- // collapse to the same hash. Without dedup, simple phrasing
45
- // variations (typos, doubled tokens, intensifiers) would inflate
46
- // distinct-query counts and trip R2 on essentially the same question.
47
- // Codex round-1 catch.
48
- // Unicode-aware tokenization (codex round-3 P2 catch): the prior
49
- // ASCII-only [^a-z0-9\s] pattern stripped every non-Latin letter, so
50
- // Japanese, Arabic, Cyrillic, accented-Latin etc. queries collapsed
51
- // to empty token set -> hash 0 -> false R1 collisions across distinct
52
- // non-English queries. \p{L} = any Unicode letter, \p{N} = any Unicode
53
- // number, \p{M} = combining marks (preserve composed accented chars).
54
- // Requires the /u flag and Node >= 12.
41
+ // Tokens are deduped before join so `foo foo bar` and `foo bar` count as one query for memory_dominance.
42
+ // Unicode classes (\p{L} letter, \p{N} number, \p{M} combining mark; needs /u) keep
43
+ // non-Latin queries from collapsing to an empty token set and colliding at hash 0.
55
44
  const normalized = query
56
45
  .toLowerCase()
57
46
  .replace(/[^\p{L}\p{N}\p{M}\s]/gu, ' ')
58
47
  .split(/\s+/)
59
48
  .filter((t) => t.length > 0);
60
- // Drop tokens shorter than 3 chars to match the normalizer contract
61
- // (filler / stop words). Without this, `a login bug` vs `login bug`
62
- // hash differently and inflate R2 distinct-query counts, firing
63
- // memory_dominance on repeated phrasings of the same question.
64
- // Codex round-4 P2 catch. Matches the same >=3 filter in
65
- // src/forward-claim-detector.ts for class-resolver tokens.
49
+ // Drop tokens under 3 chars (filler words) so `a login bug` and `login bug` hash
50
+ // alike; matches the >=3 filter in src/forward-claim-detector.ts.
66
51
  const filtered = normalized.filter((t) => t.length >= 3);
67
- // Fallback when the >=3 filter would collapse the entire query to
68
- // empty: CJK queries like `测试` / `环境` are 2-char tokens; English
69
- // acronyms like `AI` / `UI` are 2 chars. Without this fallback they
70
- // all hash to fnv1a32(''), producing false R1 collisions across
71
- // distinct short-token queries. Codex round-5 P2 catch.
52
+ // Fall back to all tokens when the filter empties the query (CJK 2-char words,
53
+ // acronyms like `AI`) so distinct short queries do not all hash to fnv1a32('').
72
54
  const tokens = filtered.length > 0 ? filtered : normalized;
73
55
  const deduped = Array.from(new Set(tokens)).sort();
74
56
  return fnv1a32(deduped.join(' '));
@@ -91,17 +73,17 @@ function fnv1a32(text) {
91
73
  * Detect anchoring patterns in the recall history against the current
92
74
  * recall's (queryHash, topMemoryId).
93
75
  *
94
- * Rule precedence: R2 (memory_dominance) wins on tie. When both R1 and R2
95
- * fire on the same recall, return only the R2 hint — R2's signal is the
96
- * cognitively stronger one (a memory dominating multiple DIFFERENT queries
97
- * is a fixed-point anchor; R1 alone is just a literal re-ask).
76
+ * Rule precedence: memory_dominance wins on tie. When both rules fire on the
77
+ * same recall, return only memory_dominance, the stronger signal (a memory
78
+ * dominating multiple DIFFERENT queries is a fixed-point anchor; query_repeat
79
+ * alone is just a literal re-ask).
98
80
  *
99
81
  * Cooldown: if the immediately-prior recall fired a hint on the SAME
100
82
  * topMemoryId within `cooldown=3` history entries, suppress. Prevents
101
83
  * spam when the agent repeatedly recalls within the dominance window.
102
- * Cooldown is per-memory, not per-rule: if R2 fired on M (cooldown
103
- * engaged for M), and the next recall has top=N + repeated query →
104
- * R1 fires on N (different memory, not in cooldown).
84
+ * Cooldown is per-memory, not per-rule: if memory_dominance fired on M
85
+ * (cooldown engaged for M), and the next recall has top=N + repeated query,
86
+ * query_repeat fires on N (different memory, not in cooldown).
105
87
  *
106
88
  * @returns AnchoringHint when a pattern fires; null otherwise.
107
89
  */
@@ -119,7 +101,7 @@ export function detectAnchoring(history, currentQueryHash, currentTopMemoryId, o
119
101
  return null;
120
102
  }
121
103
  }
122
- // R2 check FIRST (wins on tie). Count distinct queryHashes in history
104
+ // memory_dominance check FIRST (wins on tie). Count distinct queryHashes in history
123
105
  // where topMemoryId === currentTopMemoryId (excluding null tops).
124
106
  const matchingQueryHashes = new Set();
125
107
  for (const entry of history) {
@@ -139,7 +121,7 @@ export function detectAnchoring(history, currentQueryHash, currentTopMemoryId, o
139
121
  source: 'j1-recurrence',
140
122
  };
141
123
  }
142
- // R1 check: is currentQueryHash present in the last `recentRepeatWindow`
124
+ // query_repeat check: is currentQueryHash present in the last `recentRepeatWindow`
143
125
  // entries AND was that entry's topMemoryId === currentTopMemoryId?
144
126
  const r1Slice = history.slice(-recentRepeatWindow);
145
127
  for (const entry of r1Slice) {
@@ -11,6 +11,7 @@ import { DEFAULT_GRAPH_STREAM_WEIGHT } from './graph-stream.js';
11
11
  import { Layer } from './memory.js';
12
12
  import { multihopSearch } from './multihop.js';
13
13
  import { passesCliRecallScopeFilter } from './recall-scope.js';
14
+ import { currentEntries } from './search/as-of.js';
14
15
  import { hybridSearch } from './search/hybrid.js';
15
16
  import { physicsSearch } from './search/physics-search.js';
16
17
  import { searchBothHybrid } from './shared.js';
@@ -72,36 +73,11 @@ function loadRecallPool(ctx, opts) {
72
73
  const passes = (e) => passesCliRecallScopeFilter(e.scope ?? null, requested);
73
74
  local = local.filter(passes);
74
75
  global = global.filter(passes);
75
- if (opts.asOf) {
76
- local = currentAsOf(local, opts.asOf);
77
- global = currentAsOf(global, opts.asOf);
78
- }
79
- else if (!opts.includeSuperseded) {
80
- local = local.filter((e) => !e.superseded_by);
81
- global = global.filter((e) => !e.superseded_by);
82
- }
76
+ const currentness = { asOf: opts.asOf, includeSuperseded: opts.includeSuperseded };
77
+ local = currentEntries(local, currentness);
78
+ global = currentEntries(global, currentness);
83
79
  return { local, global, total, dropped: total - (local.length + global.length) };
84
80
  }
85
- /** Rows that were true at `asOf`: valid by then, and not yet replaced by a successor in the same pool. */
86
- function currentAsOf(entries, asOf) {
87
- const asOfDate = new Date(asOf);
88
- const successorValidFrom = new Map();
89
- for (const e of entries) {
90
- if (e.superseded_by) {
91
- const successor = entries.find(s => s.id === e.superseded_by);
92
- if (successor)
93
- successorValidFrom.set(e.id, successor.valid_from);
94
- }
95
- }
96
- return entries.filter(e => {
97
- if (new Date(e.valid_from) > asOfDate)
98
- return false;
99
- if (!e.superseded_by)
100
- return true;
101
- const succVf = successorValidFrom.get(e.id);
102
- return succVf ? new Date(succVf) > asOfDate : true;
103
- });
104
- }
105
81
  async function searchPool(ctx, opts, pool) {
106
82
  const { query, budget, cost, includeSuperseded, asOf, activeScope: scope, search } = opts;
107
83
  const { mmr, mmrLambda, minResults, explain } = search;
@@ -1,8 +1,7 @@
1
1
  /**
2
- * v1.25.0 — recall-side scope predicates, extracted from api.ts into a leaf
3
- * module so shared.ts (which api.ts imports) can apply the same default-deny
4
- * rule to searchBothHybrid's internal candidate loads without an import
5
- * cycle. Mirrors the v39 `project-identity.ts` precedent. api.ts imports
2
+ * Recall-side scope predicates, in a leaf module so shared.ts (which api.ts
3
+ * imports) can apply the same default-deny rule to searchBothHybrid's internal
4
+ * candidate loads without an import cycle. api.ts imports
6
5
  * these for its own call sites AND re-exports them for back-compat
7
6
  * (`api.isPrivateScope`, test imports of `passesScopeFilterForRecall`).
8
7
  */
@@ -30,7 +29,7 @@ export declare const RECALL_DEFAULT_DENY_SCOPES: readonly ["unknown:legacy"];
30
29
  */
31
30
  export declare function assertNonEmpty<T>(arr: readonly T[], name: string): void;
32
31
  /**
33
- * v1.2.1: source-agnostic private-scope detector. A scope string is treated
32
+ * Source-agnostic private-scope detector. A scope string is treated
34
33
  * as private when it has the shape `<lowercase-source>:private:<rest>`.
35
34
  *
36
35
  * Examples that match:
@@ -56,14 +55,14 @@ export declare function isPrivateScope(scope: string | null | undefined): boolea
56
55
  * `<source>:private:*` scope and on the `RECALL_DEFAULT_DENY_SCOPES`
57
56
  * quarantine buckets. `null` and public scopes pass.
58
57
  *
59
- * @internal v1.7.2 — exported for test parity with
58
+ * @internal Exported for test parity with
60
59
  * `RECALL_DEFAULT_DENY_SCOPES` (single-source-of-truth verification). NOT part
61
60
  * of the public API surface; not re-exported from `src/index.ts`. Subject to
62
61
  * change without semver bump.
63
62
  */
64
63
  export declare function passesScopeFilterForRecall(scope: string | null, requested: string | undefined): boolean;
65
64
  /**
66
- * v1.25.0 — the CLI `--scope` variant of the recall filter (JS half of the
65
+ * The CLI `--scope` variant of the recall filter (JS half of the
67
66
  * SQL 'default-deny-or-exact' mode in loadSearchRows).
68
67
  *
69
68
  * The CLI flag predates the envelope column as a TAG-boost ranking hint
@@ -101,7 +100,7 @@ export interface ScopeActor {
101
100
  }
102
101
  /** True when `actor` may read `scope`: admin always; member needs an exact grant on a restricted scope. */
103
102
  export declare function canReadScope(actor: ScopeActor, scope: string): boolean;
104
- /** Authorize an explicitly requested scope before any read honours it (ROADMAP Part VIII EI2: member scope grants). */
103
+ /** Authorize an explicitly requested scope before any read honours it (member scope grants). */
105
104
  export declare function assertScopeRequestAllowed(actor: ScopeActor, requested: string | undefined): void;
106
105
  /** Scope a derived row keeps from one source: the restricted scope itself, else null. */
107
106
  export declare function derivationScope(scope: string | null | undefined): string | null;
@@ -1,8 +1,7 @@
1
1
  /**
2
- * v1.25.0 — recall-side scope predicates, extracted from api.ts into a leaf
3
- * module so shared.ts (which api.ts imports) can apply the same default-deny
4
- * rule to searchBothHybrid's internal candidate loads without an import
5
- * cycle. Mirrors the v39 `project-identity.ts` precedent. api.ts imports
2
+ * Recall-side scope predicates, in a leaf module so shared.ts (which api.ts
3
+ * imports) can apply the same default-deny rule to searchBothHybrid's internal
4
+ * candidate loads without an import cycle. api.ts imports
6
5
  * these for its own call sites AND re-exports them for back-compat
7
6
  * (`api.isPrivateScope`, test imports of `passesScopeFilterForRecall`).
8
7
  */
@@ -35,7 +34,7 @@ export function assertNonEmpty(arr, name) {
35
34
  }
36
35
  assertNonEmpty(RECALL_DEFAULT_DENY_SCOPES, 'RECALL_DEFAULT_DENY_SCOPES');
37
36
  /**
38
- * v1.2.1: source-agnostic private-scope detector. A scope string is treated
37
+ * Source-agnostic private-scope detector. A scope string is treated
39
38
  * as private when it has the shape `<lowercase-source>:private:<rest>`.
40
39
  *
41
40
  * Examples that match:
@@ -68,7 +67,7 @@ export function isPrivateScope(scope) {
68
67
  * `<source>:private:*` scope and on the `RECALL_DEFAULT_DENY_SCOPES`
69
68
  * quarantine buckets. `null` and public scopes pass.
70
69
  *
71
- * @internal v1.7.2 — exported for test parity with
70
+ * @internal Exported for test parity with
72
71
  * `RECALL_DEFAULT_DENY_SCOPES` (single-source-of-truth verification). NOT part
73
72
  * of the public API surface; not re-exported from `src/index.ts`. Subject to
74
73
  * change without semver bump.
@@ -80,7 +79,7 @@ export function passesScopeFilterForRecall(scope, requested) {
80
79
  return !isRestrictedScope(scope);
81
80
  }
82
81
  /**
83
- * v1.25.0 — the CLI `--scope` variant of the recall filter (JS half of the
82
+ * The CLI `--scope` variant of the recall filter (JS half of the
84
83
  * SQL 'default-deny-or-exact' mode in loadSearchRows).
85
84
  *
86
85
  * The CLI flag predates the envelope column as a TAG-boost ranking hint
@@ -135,7 +134,7 @@ export function canReadScope(actor, scope) {
135
134
  return true;
136
135
  return (actor.scopes ?? []).includes(scope);
137
136
  }
138
- /** Authorize an explicitly requested scope before any read honours it (ROADMAP Part VIII EI2: member scope grants). */
137
+ /** Authorize an explicitly requested scope before any read honours it (member scope grants). */
139
138
  export function assertScopeRequestAllowed(actor, requested) {
140
139
  if (requested === undefined || requested === '')
141
140
  return;
@@ -1,6 +1,5 @@
1
1
  /**
2
- * LC1 — retrieval-trace persistence
3
- * (docs/plans/2026-08-02-lc1-recall-trace-persistence.md).
2
+ * Retrieval-trace persistence.
4
3
  *
5
4
  * Single producer for the `recall_traces` / `recall_trace_results` /
6
5
  * `recall_trace_outcomes` tables (schema v40). Every recall on the three
@@ -59,14 +58,11 @@ export declare function writeRecallTrace(db: DatabaseSyncLike, input: RecallTrac
59
58
  * Used at api.getContext and CLI cmdRecall — sites where the block's own
60
59
  * convention is per-call handles (writeEntry, saveIndex) and the earlier
61
60
  * audit handles are already closed. NOT used by api.recall, which must
62
- * reuse the caller's open handle (v1.11.5 no-side-effects contract,
61
+ * reuse the caller's open handle (no-side-effects contract,
63
62
  * tests/api-recall-no-side-effects.test.ts).
64
63
  *
65
- * F1 structural fix (replaces the earlier stamp-then-clear design): this
66
- * function does NOT touch the `last_trace_id` meta key. Stamping lived here
67
- * originally, on its own connection, separate from the `last_retrieval_ids`
68
- * write in `saveIndex` — two connections meant two commits, so a crash or
69
- * a failed second write could advance one without the other. LOCKSTEP
64
+ * This function does NOT touch the `last_trace_id` meta key: its own connection
65
+ * would commit apart from `saveIndex`, so a crash could advance one key alone. LOCKSTEP
70
66
  * INVARIANT: `last_trace_id` must only ever advance in the SAME write as
71
67
  * `last_retrieval_ids`. The caller now does: call this function FIRST, set
72
68
  * `localIndex.last_trace_id` from the returned id, THEN call `saveIndex`
@@ -98,7 +94,7 @@ export interface RecordTraceOutcomeInput {
98
94
  * Lives in its own append-only table, not audit_log metadata: audit_log is
99
95
  * pruned by `pruneAuditLog`, and pruning must never erase training data.
100
96
  *
101
- * F4 validation (codex cross-model finding): `traceId`/`memoryIds` reach
97
+ * Validation: `traceId`/`memoryIds` reach
102
98
  * this function from caller-side state (`last_trace_id` / applied outcome
103
99
  * ids) that can go stale relative to the trace it names — a forgotten
104
100
  * memory, a tenant switch mid-session, or a race between two callers. Two
@@ -1,6 +1,5 @@
1
1
  /**
2
- * LC1 — retrieval-trace persistence
3
- * (docs/plans/2026-08-02-lc1-recall-trace-persistence.md).
2
+ * Retrieval-trace persistence.
4
3
  *
5
4
  * Single producer for the `recall_traces` / `recall_trace_results` /
6
5
  * `recall_trace_outcomes` tables (schema v40). Every recall on the three
@@ -21,7 +20,7 @@ import { DELIVERY_LEDGER_VERSION } from './delivery-recorder.js';
21
20
  import { log } from './log.js';
22
21
  /**
23
22
  * Strip a RerankStep down to {stage, multiplier, scoreBefore, scoreAfter}
24
- * before persisting (F3 privacy fix, codex cross-model finding). `note` is
23
+ * before persisting. `note` is
25
24
  * free-form human text — the CLI's goal-boost step embeds matched goal tag
26
25
  * text there, so persisting it verbatim would leak raw user content into
27
26
  * training data via `rerank_json`. Only the four structured fields survive;
@@ -89,14 +88,11 @@ export function writeRecallTrace(db, input) {
89
88
  * Used at api.getContext and CLI cmdRecall — sites where the block's own
90
89
  * convention is per-call handles (writeEntry, saveIndex) and the earlier
91
90
  * audit handles are already closed. NOT used by api.recall, which must
92
- * reuse the caller's open handle (v1.11.5 no-side-effects contract,
91
+ * reuse the caller's open handle (no-side-effects contract,
93
92
  * tests/api-recall-no-side-effects.test.ts).
94
93
  *
95
- * F1 structural fix (replaces the earlier stamp-then-clear design): this
96
- * function does NOT touch the `last_trace_id` meta key. Stamping lived here
97
- * originally, on its own connection, separate from the `last_retrieval_ids`
98
- * write in `saveIndex` — two connections meant two commits, so a crash or
99
- * a failed second write could advance one without the other. LOCKSTEP
94
+ * This function does NOT touch the `last_trace_id` meta key: its own connection
95
+ * would commit apart from `saveIndex`, so a crash could advance one key alone. LOCKSTEP
100
96
  * INVARIANT: `last_trace_id` must only ever advance in the SAME write as
101
97
  * `last_retrieval_ids`. The caller now does: call this function FIRST, set
102
98
  * `localIndex.last_trace_id` from the returned id, THEN call `saveIndex`
@@ -135,7 +131,7 @@ export function writeRecallTraceAtRoot(root, input) {
135
131
  * Lives in its own append-only table, not audit_log metadata: audit_log is
136
132
  * pruned by `pruneAuditLog`, and pruning must never erase training data.
137
133
  *
138
- * F4 validation (codex cross-model finding): `traceId`/`memoryIds` reach
134
+ * Validation: `traceId`/`memoryIds` reach
139
135
  * this function from caller-side state (`last_trace_id` / applied outcome
140
136
  * ids) that can go stale relative to the trace it names — a forgotten
141
137
  * memory, a tenant switch mid-session, or a race between two callers. Two
@@ -23,7 +23,7 @@ export interface RefineOptions {
23
23
  /** Injected for testing — defaults to the real fetch. */
24
24
  fetcher?: typeof fetch;
25
25
  /**
26
- * L9: tenant scope. When provided, refineStore only scans consolidated
26
+ * Tenant scope. When provided, refineStore only scans consolidated
27
27
  * entries belonging to this tenant, and parent lookups are scoped to the
28
28
  * same tenant. Cross-tenant parents return null from readEntry and are
29
29
  * silently skipped (refine still produces output from merged content).
@@ -109,7 +109,7 @@ export async function refineStore(hippoRoot, opts) {
109
109
  failed: 0,
110
110
  details: [],
111
111
  };
112
- // L9: when opts.tenantId is provided, scope the top-level scan to this
112
+ // When opts.tenantId is provided, scope the top-level scan to this
113
113
  // tenant's consolidated entries.
114
114
  const entries = loadAllEntries(hippoRoot, opts.tenantId);
115
115
  let processed = 0;
@@ -130,7 +130,7 @@ export async function refineStore(hippoRoot, opts) {
130
130
  const sources = [];
131
131
  const parentIds = Array.isArray(entry.parents) ? entry.parents : [];
132
132
  for (const pid of parentIds) {
133
- // L9: parent lookup scoped by opts.tenantId when provided.
133
+ // Parent lookup scoped by opts.tenantId when provided.
134
134
  // Cross-tenant parents return null and are silently skipped — refine
135
135
  // still produces output from the merged content alone (graceful
136
136
  // degradation rather than refuse-to-refine).
@@ -1,6 +1,5 @@
1
1
  /**
2
- * AT1 rejected-value tombstone — shared reject/unreject/list flow.
3
- * docs/plans/2026-08-15-at1-rejected-value-tombstone.md (T2, plan §4).
2
+ * Rejected-value tombstone: shared reject/unreject/list flow.
4
3
  *
5
4
  * The CLI (`hippo reject`/`rejections`/`unreject`) and the Context-based
6
5
  * `api.reject`/`api.unreject`/`api.listRejections` surfaces both need the
@@ -24,12 +23,12 @@ export interface RejectFlowOpts {
24
23
  }
25
24
  export interface RejectFlowResult {
26
25
  digest: string;
27
- /** The rejected content, for the CLI's at-reject-time echo (plan §2: the
26
+ /** The rejected content, for the CLI's at-reject-time echo (the
28
27
  * tombstone itself stores no content — this is the only place it's seen
29
28
  * again after this call returns). */
30
29
  content: string;
31
30
  /** Every row removed this call, live or dormant: all whose normalized digest matched (not just the id
32
- * passed, per the K1/R7 duplicate lesson), and each sleep-merged row holding the value, whose other
31
+ * passed, since duplicates share a digest), and each sleep-merged row holding the value, whose other
33
32
  * texts move to a new row: listed in successorIds when it was live, dormantSuccessorIds when dormant. */
34
33
  removedIds: string[];
35
34
  /** Subset of removedIds that were kind='raw' (archived, not deleted). */