agent-recall-core 3.4.31 → 3.4.36

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 (270) hide show
  1. package/README.md +121 -441
  2. package/dist/digest/store.d.ts.map +1 -1
  3. package/dist/digest/store.js +4 -3
  4. package/dist/digest/store.js.map +1 -1
  5. package/dist/display/board-render.d.ts +61 -0
  6. package/dist/display/board-render.d.ts.map +1 -0
  7. package/dist/display/board-render.js +223 -0
  8. package/dist/display/board-render.js.map +1 -0
  9. package/dist/helpers/alignment-patterns.d.ts +10 -0
  10. package/dist/helpers/alignment-patterns.d.ts.map +1 -1
  11. package/dist/helpers/alignment-patterns.js +5 -1
  12. package/dist/helpers/alignment-patterns.js.map +1 -1
  13. package/dist/helpers/blind-spots.d.ts +86 -0
  14. package/dist/helpers/blind-spots.d.ts.map +1 -0
  15. package/dist/helpers/blind-spots.js +205 -0
  16. package/dist/helpers/blind-spots.js.map +1 -0
  17. package/dist/helpers/conflict-scan.d.ts +10 -0
  18. package/dist/helpers/conflict-scan.d.ts.map +1 -1
  19. package/dist/helpers/conflict-scan.js +3 -3
  20. package/dist/helpers/conflict-scan.js.map +1 -1
  21. package/dist/helpers/semantic-match.d.ts +82 -0
  22. package/dist/helpers/semantic-match.d.ts.map +1 -0
  23. package/dist/helpers/semantic-match.js +229 -0
  24. package/dist/helpers/semantic-match.js.map +1 -0
  25. package/dist/index.d.ts +57 -17
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +60 -14
  28. package/dist/index.js.map +1 -1
  29. package/dist/palace/awareness.d.ts +30 -0
  30. package/dist/palace/awareness.d.ts.map +1 -1
  31. package/dist/palace/awareness.js +65 -2
  32. package/dist/palace/awareness.js.map +1 -1
  33. package/dist/palace/consolidate.d.ts.map +1 -1
  34. package/dist/palace/consolidate.js +17 -0
  35. package/dist/palace/consolidate.js.map +1 -1
  36. package/dist/palace/decay-pass.d.ts +46 -0
  37. package/dist/palace/decay-pass.d.ts.map +1 -0
  38. package/dist/palace/decay-pass.js +87 -0
  39. package/dist/palace/decay-pass.js.map +1 -0
  40. package/dist/palace/insights-index.d.ts.map +1 -1
  41. package/dist/palace/insights-index.js +4 -2
  42. package/dist/palace/insights-index.js.map +1 -1
  43. package/dist/palace/skills.d.ts +41 -2
  44. package/dist/palace/skills.d.ts.map +1 -1
  45. package/dist/palace/skills.js +106 -4
  46. package/dist/palace/skills.js.map +1 -1
  47. package/dist/prompts/consolidation-prompt.d.ts +25 -0
  48. package/dist/prompts/consolidation-prompt.d.ts.map +1 -0
  49. package/dist/prompts/consolidation-prompt.js +91 -0
  50. package/dist/prompts/consolidation-prompt.js.map +1 -0
  51. package/dist/storage/ab-experiment.d.ts +184 -0
  52. package/dist/storage/ab-experiment.d.ts.map +1 -0
  53. package/dist/storage/ab-experiment.js +294 -0
  54. package/dist/storage/ab-experiment.js.map +1 -0
  55. package/dist/storage/archive-prune.d.ts +56 -0
  56. package/dist/storage/archive-prune.d.ts.map +1 -0
  57. package/dist/storage/archive-prune.js +118 -0
  58. package/dist/storage/archive-prune.js.map +1 -0
  59. package/dist/storage/archive-write.d.ts +38 -0
  60. package/dist/storage/archive-write.d.ts.map +1 -0
  61. package/dist/storage/archive-write.js +98 -0
  62. package/dist/storage/archive-write.js.map +1 -0
  63. package/dist/storage/blind-spots-store.d.ts +30 -0
  64. package/dist/storage/blind-spots-store.d.ts.map +1 -0
  65. package/dist/storage/blind-spots-store.js +91 -0
  66. package/dist/storage/blind-spots-store.js.map +1 -0
  67. package/dist/storage/capture-router.d.ts +60 -0
  68. package/dist/storage/capture-router.d.ts.map +1 -0
  69. package/dist/storage/capture-router.js +133 -0
  70. package/dist/storage/capture-router.js.map +1 -0
  71. package/dist/storage/classification.d.ts +36 -0
  72. package/dist/storage/classification.d.ts.map +1 -0
  73. package/dist/storage/classification.js +78 -0
  74. package/dist/storage/classification.js.map +1 -0
  75. package/dist/storage/consolidation-queue.d.ts +39 -0
  76. package/dist/storage/consolidation-queue.d.ts.map +1 -0
  77. package/dist/storage/consolidation-queue.js +120 -0
  78. package/dist/storage/consolidation-queue.js.map +1 -0
  79. package/dist/storage/content-guard.d.ts +74 -0
  80. package/dist/storage/content-guard.d.ts.map +1 -0
  81. package/dist/storage/content-guard.js +179 -0
  82. package/dist/storage/content-guard.js.map +1 -0
  83. package/dist/storage/corrections.d.ts +329 -22
  84. package/dist/storage/corrections.d.ts.map +1 -1
  85. package/dist/storage/corrections.js +788 -58
  86. package/dist/storage/corrections.js.map +1 -1
  87. package/dist/storage/durable-intent.d.ts +49 -0
  88. package/dist/storage/durable-intent.d.ts.map +1 -0
  89. package/dist/storage/durable-intent.js +124 -0
  90. package/dist/storage/durable-intent.js.map +1 -0
  91. package/dist/storage/filelock.d.ts +6 -0
  92. package/dist/storage/filelock.d.ts.map +1 -1
  93. package/dist/storage/filelock.js +6 -1
  94. package/dist/storage/filelock.js.map +1 -1
  95. package/dist/storage/memory-protocol.d.ts +19 -0
  96. package/dist/storage/memory-protocol.d.ts.map +1 -0
  97. package/dist/storage/memory-protocol.js +101 -0
  98. package/dist/storage/memory-protocol.js.map +1 -0
  99. package/dist/storage/paths.d.ts +23 -0
  100. package/dist/storage/paths.d.ts.map +1 -1
  101. package/dist/storage/paths.js +39 -0
  102. package/dist/storage/paths.js.map +1 -1
  103. package/dist/storage/retention.d.ts +23 -0
  104. package/dist/storage/retention.d.ts.map +1 -0
  105. package/dist/storage/retention.js +48 -0
  106. package/dist/storage/retention.js.map +1 -0
  107. package/dist/storage/session.d.ts +2 -2
  108. package/dist/storage/session.d.ts.map +1 -1
  109. package/dist/storage/session.js +11 -1
  110. package/dist/storage/session.js.map +1 -1
  111. package/dist/supabase/config.d.ts +26 -0
  112. package/dist/supabase/config.d.ts.map +1 -1
  113. package/dist/supabase/config.js +11 -0
  114. package/dist/supabase/config.js.map +1 -1
  115. package/dist/supabase/recall-backend.d.ts +1 -0
  116. package/dist/supabase/recall-backend.d.ts.map +1 -1
  117. package/dist/supabase/recall-backend.js +13 -13
  118. package/dist/supabase/recall-backend.js.map +1 -1
  119. package/dist/supabase/sync.d.ts +1 -1
  120. package/dist/supabase/sync.d.ts.map +1 -1
  121. package/dist/supabase/sync.js +85 -3
  122. package/dist/supabase/sync.js.map +1 -1
  123. package/dist/tools-logic/bootstrap.d.ts +15 -0
  124. package/dist/tools-logic/bootstrap.d.ts.map +1 -1
  125. package/dist/tools-logic/bootstrap.js +238 -47
  126. package/dist/tools-logic/bootstrap.js.map +1 -1
  127. package/dist/tools-logic/brief.d.ts +84 -0
  128. package/dist/tools-logic/brief.d.ts.map +1 -0
  129. package/dist/tools-logic/brief.js +193 -0
  130. package/dist/tools-logic/brief.js.map +1 -0
  131. package/dist/tools-logic/check-action.d.ts +9 -0
  132. package/dist/tools-logic/check-action.d.ts.map +1 -1
  133. package/dist/tools-logic/check-action.js +61 -3
  134. package/dist/tools-logic/check-action.js.map +1 -1
  135. package/dist/tools-logic/check.d.ts +7 -0
  136. package/dist/tools-logic/check.d.ts.map +1 -1
  137. package/dist/tools-logic/check.js +24 -2
  138. package/dist/tools-logic/check.js.map +1 -1
  139. package/dist/tools-logic/confidence.d.ts +50 -0
  140. package/dist/tools-logic/confidence.d.ts.map +1 -0
  141. package/dist/tools-logic/confidence.js +70 -0
  142. package/dist/tools-logic/confidence.js.map +1 -0
  143. package/dist/tools-logic/drill-down.d.ts +37 -0
  144. package/dist/tools-logic/drill-down.d.ts.map +1 -0
  145. package/dist/tools-logic/drill-down.js +63 -0
  146. package/dist/tools-logic/drill-down.js.map +1 -0
  147. package/dist/tools-logic/export-corrections.d.ts +63 -0
  148. package/dist/tools-logic/export-corrections.d.ts.map +1 -0
  149. package/dist/tools-logic/export-corrections.js +124 -0
  150. package/dist/tools-logic/export-corrections.js.map +1 -0
  151. package/dist/tools-logic/journal-capture.d.ts.map +1 -1
  152. package/dist/tools-logic/journal-capture.js +4 -1
  153. package/dist/tools-logic/journal-capture.js.map +1 -1
  154. package/dist/tools-logic/journal-write.d.ts.map +1 -1
  155. package/dist/tools-logic/journal-write.js +3 -2
  156. package/dist/tools-logic/journal-write.js.map +1 -1
  157. package/dist/tools-logic/local-archive-backend.d.ts +33 -0
  158. package/dist/tools-logic/local-archive-backend.d.ts.map +1 -0
  159. package/dist/tools-logic/local-archive-backend.js +124 -0
  160. package/dist/tools-logic/local-archive-backend.js.map +1 -0
  161. package/dist/tools-logic/memory-backend.d.ts +74 -0
  162. package/dist/tools-logic/memory-backend.d.ts.map +1 -0
  163. package/dist/tools-logic/memory-backend.js +172 -0
  164. package/dist/tools-logic/memory-backend.js.map +1 -0
  165. package/dist/tools-logic/memory-query.d.ts +10 -3
  166. package/dist/tools-logic/memory-query.d.ts.map +1 -1
  167. package/dist/tools-logic/memory-query.js +31 -7
  168. package/dist/tools-logic/memory-query.js.map +1 -1
  169. package/dist/tools-logic/mirror-builder.d.ts +115 -0
  170. package/dist/tools-logic/mirror-builder.d.ts.map +1 -0
  171. package/dist/tools-logic/mirror-builder.js +348 -0
  172. package/dist/tools-logic/mirror-builder.js.map +1 -0
  173. package/dist/tools-logic/palace-write.d.ts.map +1 -1
  174. package/dist/tools-logic/palace-write.js +3 -2
  175. package/dist/tools-logic/palace-write.js.map +1 -1
  176. package/dist/tools-logic/pipeline-close.d.ts.map +1 -1
  177. package/dist/tools-logic/pipeline-close.js +2 -1
  178. package/dist/tools-logic/pipeline-close.js.map +1 -1
  179. package/dist/tools-logic/pipeline-open.d.ts.map +1 -1
  180. package/dist/tools-logic/pipeline-open.js +2 -1
  181. package/dist/tools-logic/pipeline-open.js.map +1 -1
  182. package/dist/tools-logic/predict-correction.d.ts +47 -0
  183. package/dist/tools-logic/predict-correction.d.ts.map +1 -0
  184. package/dist/tools-logic/predict-correction.js +137 -0
  185. package/dist/tools-logic/predict-correction.js.map +1 -0
  186. package/dist/tools-logic/prior-builder.d.ts +27 -0
  187. package/dist/tools-logic/prior-builder.d.ts.map +1 -0
  188. package/dist/tools-logic/prior-builder.js +90 -0
  189. package/dist/tools-logic/prior-builder.js.map +1 -0
  190. package/dist/tools-logic/recognition-builder.d.ts +122 -0
  191. package/dist/tools-logic/recognition-builder.d.ts.map +1 -0
  192. package/dist/tools-logic/recognition-builder.js +289 -0
  193. package/dist/tools-logic/recognition-builder.js.map +1 -0
  194. package/dist/tools-logic/safety-consolidation.d.ts +104 -0
  195. package/dist/tools-logic/safety-consolidation.d.ts.map +1 -0
  196. package/dist/tools-logic/safety-consolidation.js +256 -0
  197. package/dist/tools-logic/safety-consolidation.js.map +1 -0
  198. package/dist/tools-logic/session-end-reflect.d.ts +18 -0
  199. package/dist/tools-logic/session-end-reflect.d.ts.map +1 -1
  200. package/dist/tools-logic/session-end-reflect.js +69 -30
  201. package/dist/tools-logic/session-end-reflect.js.map +1 -1
  202. package/dist/tools-logic/session-end.d.ts +18 -0
  203. package/dist/tools-logic/session-end.d.ts.map +1 -1
  204. package/dist/tools-logic/session-end.js +189 -34
  205. package/dist/tools-logic/session-end.js.map +1 -1
  206. package/dist/tools-logic/session-start-lite.d.ts +2 -0
  207. package/dist/tools-logic/session-start-lite.d.ts.map +1 -1
  208. package/dist/tools-logic/session-start-lite.js +11 -2
  209. package/dist/tools-logic/session-start-lite.js.map +1 -1
  210. package/dist/tools-logic/session-start.d.ts +81 -2
  211. package/dist/tools-logic/session-start.d.ts.map +1 -1
  212. package/dist/tools-logic/session-start.js +357 -40
  213. package/dist/tools-logic/session-start.js.map +1 -1
  214. package/dist/tools-logic/skill-propose.d.ts +27 -0
  215. package/dist/tools-logic/skill-propose.d.ts.map +1 -0
  216. package/dist/tools-logic/skill-propose.js +66 -0
  217. package/dist/tools-logic/skill-propose.js.map +1 -0
  218. package/dist/tools-logic/skill-recall.d.ts +5 -0
  219. package/dist/tools-logic/skill-recall.d.ts.map +1 -1
  220. package/dist/tools-logic/skill-recall.js +14 -1
  221. package/dist/tools-logic/skill-recall.js.map +1 -1
  222. package/dist/tools-logic/smart-recall.d.ts +17 -0
  223. package/dist/tools-logic/smart-recall.d.ts.map +1 -1
  224. package/dist/tools-logic/smart-recall.js +51 -16
  225. package/dist/tools-logic/smart-recall.js.map +1 -1
  226. package/dist/tools-logic/smart-remember.js +8 -9
  227. package/dist/tools-logic/smart-remember.js.map +1 -1
  228. package/dist/tools-logic/store-doctor.d.ts +71 -0
  229. package/dist/tools-logic/store-doctor.d.ts.map +1 -0
  230. package/dist/tools-logic/store-doctor.js +387 -0
  231. package/dist/tools-logic/store-doctor.js.map +1 -0
  232. package/dist/tools-logic/store-repair.d.ts +64 -0
  233. package/dist/tools-logic/store-repair.d.ts.map +1 -0
  234. package/dist/tools-logic/store-repair.js +243 -0
  235. package/dist/tools-logic/store-repair.js.map +1 -0
  236. package/dist/tools-logic/supersession.d.ts +34 -0
  237. package/dist/tools-logic/supersession.d.ts.map +1 -0
  238. package/dist/tools-logic/supersession.js +103 -0
  239. package/dist/tools-logic/supersession.js.map +1 -0
  240. package/dist/types.d.ts +7 -1
  241. package/dist/types.d.ts.map +1 -1
  242. package/dist/types.js +1 -1
  243. package/dist/vector/embedding.d.ts +8 -0
  244. package/dist/vector/embedding.d.ts.map +1 -1
  245. package/dist/vector/embedding.js +9 -1
  246. package/dist/vector/embedding.js.map +1 -1
  247. package/dist/vector/local-vector-backend.d.ts.map +1 -1
  248. package/dist/vector/local-vector-backend.js +14 -17
  249. package/dist/vector/local-vector-backend.js.map +1 -1
  250. package/package.json +2 -2
  251. package/dist/relevance/injector.d.ts +0 -51
  252. package/dist/relevance/injector.d.ts.map +0 -1
  253. package/dist/relevance/injector.js +0 -121
  254. package/dist/relevance/injector.js.map +0 -1
  255. package/dist/relevance/precision.d.ts +0 -109
  256. package/dist/relevance/precision.d.ts.map +0 -1
  257. package/dist/relevance/precision.js +0 -279
  258. package/dist/relevance/precision.js.map +0 -1
  259. package/dist/relevance/promoter.d.ts +0 -60
  260. package/dist/relevance/promoter.d.ts.map +0 -1
  261. package/dist/relevance/promoter.js +0 -336
  262. package/dist/relevance/promoter.js.map +0 -1
  263. package/dist/relevance/stager.d.ts +0 -61
  264. package/dist/relevance/stager.d.ts.map +0 -1
  265. package/dist/relevance/stager.js +0 -251
  266. package/dist/relevance/stager.js.map +0 -1
  267. package/dist/relevance/surfacer.d.ts +0 -34
  268. package/dist/relevance/surfacer.d.ts.map +0 -1
  269. package/dist/relevance/surfacer.js +0 -333
  270. package/dist/relevance/surfacer.js.map +0 -1
@@ -0,0 +1,124 @@
1
+ // packages/core/src/tools-logic/local-archive-backend.ts
2
+ //
3
+ // LocalArchiveMemoryBackend — the reference MemoryBackend implementation.
4
+ //
5
+ // Purpose (two roles):
6
+ // 1. TESTING: round-trip verification of the retain() contract without
7
+ // a live third-party service.
8
+ // 2. ADAPTER TEMPLATE: fork this file to build a real backend adapter.
9
+ // Replace the JSON write with a client.retain() call; keep the
10
+ // scrub-upstream assumption and the RetainResult shape unchanged.
11
+ //
12
+ // Storage layout:
13
+ // <root>/exports/<backend-name>/YYYY-MM-DD.json
14
+ //
15
+ // Each daily file is an array of CorrectionExport objects. A second call on
16
+ // the same day appends (unique by id — the seam is idempotent; a repeated
17
+ // `ar corrections export --to-backend` run on the same set does not create
18
+ // duplicate entries).
19
+ import * as fs from "node:fs";
20
+ import * as path from "node:path";
21
+ import { getRoot } from "../types.js";
22
+ /** Human-readable name surfaced in CLI output and log lines. */
23
+ const BACKEND_NAME = "local-archive";
24
+ /**
25
+ * Date string for today (YYYY-MM-DD) in the LOCAL timezone — injectable in
26
+ * tests via the fn arg.
27
+ *
28
+ * NOTE: uses local time, not UTC, so the archive file matches the operator's
29
+ * calendar day. toISOString() returns UTC and would produce the wrong date for
30
+ * operators running past midnight UTC in a positive-offset timezone.
31
+ */
32
+ export function todayDateString() {
33
+ const d = new Date();
34
+ const y = d.getFullYear();
35
+ const m = String(d.getMonth() + 1).padStart(2, "0");
36
+ const day = String(d.getDate()).padStart(2, "0");
37
+ return `${y}-${m}-${day}`;
38
+ }
39
+ /**
40
+ * LocalArchiveMemoryBackend — writes scrubbed CorrectionExport arrays to
41
+ * <root>/exports/local-archive/YYYY-MM-DD.json.
42
+ *
43
+ * CONTRACT:
44
+ * - Assumes records are already scrubbed (exportCorrections() upstream).
45
+ * - Idempotent: re-running with the same IDs does not duplicate entries.
46
+ * - Never throws into session flow — errors map to rejected entries.
47
+ */
48
+ export class LocalArchiveMemoryBackend {
49
+ /** Override in tests via the constructor to pin the date. */
50
+ _dateFn;
51
+ constructor(opts = {}) {
52
+ this._dateFn = opts.dateFn ?? todayDateString;
53
+ }
54
+ name() {
55
+ return BACKEND_NAME;
56
+ }
57
+ async available() {
58
+ // Always available — only needs a writable filesystem, same guarantee
59
+ // as the rest of the local store.
60
+ try {
61
+ const dir = this._archiveDir();
62
+ fs.mkdirSync(dir, { recursive: true });
63
+ return true;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ async retain(records) {
70
+ const accepted = [];
71
+ const rejected = [];
72
+ if (records.length === 0) {
73
+ return { accepted, rejected };
74
+ }
75
+ try {
76
+ const dir = this._archiveDir();
77
+ fs.mkdirSync(dir, { recursive: true });
78
+ const file = path.join(dir, `${this._dateFn()}.json`);
79
+ // Load existing entries (idempotency — deduplicate by id).
80
+ let existing = [];
81
+ try {
82
+ if (fs.existsSync(file)) {
83
+ const raw = fs.readFileSync(file, "utf-8");
84
+ const parsed = JSON.parse(raw);
85
+ if (Array.isArray(parsed)) {
86
+ existing = parsed;
87
+ }
88
+ }
89
+ }
90
+ catch {
91
+ // Malformed file — start fresh. A corrupt archive must not block new writes.
92
+ existing = [];
93
+ }
94
+ const existingIds = new Set(existing.map((e) => e.id));
95
+ const toWrite = [...existing];
96
+ for (const record of records) {
97
+ if (existingIds.has(record.id)) {
98
+ // Already present — idempotent accept (not a rejection).
99
+ accepted.push(record.id);
100
+ continue;
101
+ }
102
+ toWrite.push(record);
103
+ existingIds.add(record.id);
104
+ accepted.push(record.id);
105
+ }
106
+ fs.writeFileSync(file, JSON.stringify(toWrite, null, 2), "utf-8");
107
+ }
108
+ catch (err) {
109
+ // A filesystem failure rejects ALL records in this batch.
110
+ const reason = `write failed: ${String(err)}`;
111
+ for (const r of records) {
112
+ if (!accepted.includes(r.id)) {
113
+ rejected.push({ id: r.id, reason });
114
+ }
115
+ }
116
+ }
117
+ return { accepted, rejected };
118
+ }
119
+ /** Absolute path of the archive directory for this backend. */
120
+ _archiveDir() {
121
+ return path.join(getRoot(), "exports", BACKEND_NAME);
122
+ }
123
+ }
124
+ //# sourceMappingURL=local-archive-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-archive-backend.js","sourceRoot":"","sources":["../../src/tools-logic/local-archive-backend.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,0EAA0E;AAC1E,EAAE;AACF,uBAAuB;AACvB,yEAAyE;AACzE,mCAAmC;AACnC,yEAAyE;AACzE,oEAAoE;AACpE,uEAAuE;AACvE,EAAE;AACF,kBAAkB;AAClB,kDAAkD;AAClD,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAC1E,2EAA2E;AAC3E,sBAAsB;AAEtB,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAItC,gEAAgE;AAChE,MAAM,YAAY,GAAG,eAAe,CAAC;AAErC;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,yBAAyB;IACpC,6DAA6D;IAC5C,OAAO,CAAe;IAEvC,YAAY,OAAkC,EAAE;QAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC;IAChD,CAAC;IAED,IAAI;QACF,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,SAAS;QACb,sEAAsE;QACtE,kCAAkC;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAA2B;QACtC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAqC,EAAE,CAAC;QAEtD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAChC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAEtD,2DAA2D;YAC3D,IAAI,QAAQ,GAAuB,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxB,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;wBAC1B,QAAQ,GAAG,MAA4B,CAAC;oBAC1C,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,6EAA6E;gBAC7E,QAAQ,GAAG,EAAE,CAAC;YAChB,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACvD,MAAM,OAAO,GAAuB,CAAC,GAAG,QAAQ,CAAC,CAAC;YAElD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC/B,yDAAyD;oBACzD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBACzB,SAAS;gBACX,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrB,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC3B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3B,CAAC;YAED,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,0DAA0D;YAC1D,MAAM,MAAM,GAAG,iBAAiB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,+DAA+D;IACvD,WAAW;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -0,0 +1,74 @@
1
+ import type { CorrectionExport } from "./export-corrections.js";
2
+ /**
3
+ * RetainResult — structured response from a backend's retain() call.
4
+ * Mirrors the Hindsight `retain()` response shape so the local-archive
5
+ * reference backend and any third-party adapter speak the same dialect.
6
+ */
7
+ export interface RetainResult {
8
+ /** IDs successfully written to the backend. */
9
+ accepted: string[];
10
+ /** IDs the backend refused, each with a machine-readable reason. */
11
+ rejected: {
12
+ id: string;
13
+ reason: string;
14
+ }[];
15
+ }
16
+ /**
17
+ * MemoryBackend — write seam for external belief stores.
18
+ *
19
+ * CONTRACT:
20
+ * - retain() receives a CorrectionExport[] that has ALREADY been scrubbed by
21
+ * exportCorrections(). The backend may assume every string field is clean.
22
+ * Backends MUST NOT re-implement the scrub — that is a recipe for drift.
23
+ * - records MUST come from exportCorrections(); the type system cannot
24
+ * enforce this — which is exactly why the core barrel deliberately does
25
+ * NOT export concrete backends (only this interface + the factory). The
26
+ * sole supported path to a backend instance is getMemoryBackend(), and the
27
+ * sole supported record source is exportCorrections().
28
+ * - available() must never throw. Return false if the backend is misconfigured.
29
+ * - name() returns a stable human-readable label for logging.
30
+ * - Backend failure must be surfaced as a rejected entry or a thrown error that
31
+ * the CLI catches and prints as a warning — never as a process crash.
32
+ */
33
+ export interface MemoryBackend {
34
+ retain(records: CorrectionExport[]): Promise<RetainResult>;
35
+ available(): Promise<boolean>;
36
+ name(): string;
37
+ }
38
+ /**
39
+ * DisabledMemoryBackend — returned when AR_MEMORY_BACKEND is unset.
40
+ * available() is false so callers can gate on it cleanly.
41
+ */
42
+ export declare class DisabledMemoryBackend implements MemoryBackend {
43
+ name(): string;
44
+ available(): Promise<boolean>;
45
+ retain(_records: CorrectionExport[]): Promise<RetainResult>;
46
+ }
47
+ /**
48
+ * Get the configured MemoryBackend.
49
+ *
50
+ * Selection order:
51
+ * 1. AR_MEMORY_BACKEND=local-archive → LocalArchiveMemoryBackend (built-in)
52
+ * 2. AR_MEMORY_BACKEND=<module> → dynamic import of that module
53
+ * 3. (unset | "none" | "disabled") → DisabledMemoryBackend
54
+ *
55
+ * Case handling: built-in keywords (none/disabled/local-archive) match
56
+ * case-insensitively — pure operator convenience, nothing is imported.
57
+ * A third-party module specifier is used VERBATIM (npm names are
58
+ * case-sensitive on registry lookup and lowercase-only for new packages);
59
+ * uppercase input is rejected by SAFE_MODULE_RE with a clear message rather
60
+ * than silently normalized to a different package name.
61
+ *
62
+ * Dynamic import contract: the module must export a default class satisfying
63
+ * MemoryBackend. If the import fails, the specifier is invalid, a Node builtin,
64
+ * or the backend reports unavailable, the factory logs a warning to stderr and
65
+ * falls back to DisabledMemoryBackend — it NEVER crashes the session flow.
66
+ *
67
+ * @agent_instruction Returns DisabledMemoryBackend when no backend is configured.
68
+ * Check (await backend.available()) before calling retain(). If false, surface
69
+ * a clear "no backend configured" error to the operator.
70
+ */
71
+ export declare function getMemoryBackend(): Promise<MemoryBackend>;
72
+ /** Reset the cached backend instance (for testing). */
73
+ export declare function resetMemoryBackend(): void;
74
+ //# sourceMappingURL=memory-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-backend.d.ts","sourceRoot":"","sources":["../../src/tools-logic/memory-backend.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3D,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,IAAI,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,IAAI,IAAI,MAAM;IAIR,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAI7B,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CASlE;AAmCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CA+E/D;AAED,uDAAuD;AACvD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -0,0 +1,172 @@
1
+ // packages/core/src/tools-logic/memory-backend.ts
2
+ //
3
+ // MemoryBackend — symmetric WRITE seam for the RecallBackend READ abstraction.
4
+ //
5
+ // Design contract:
6
+ // - Records are ALWAYS the scrubbed CorrectionExport projection. The seam
7
+ // consumes exportCorrections() output (which runs fail-closed scrubForExport
8
+ // on every free-text field). Raw CorrectionRecord is NEVER passed through —
9
+ // the scrub guarantee is upstream by construction. Assert: callers must call
10
+ // exportCorrections() first; they MUST NOT build CorrectionExport manually
11
+ // and bypass the scrub.
12
+ // - Backend failure is a warning, not a session error. The seam is an explicit
13
+ // invocation path (ar corrections export --to-backend) — it never runs
14
+ // automatically on session_end in this version.
15
+ // - Zero-cloud default: the factory returns a DisabledMemoryBackend unless
16
+ // AR_MEMORY_BACKEND is set. No env var = no egress, unchanged.
17
+ //
18
+ // Environment selection (mirrors getRecallBackend()):
19
+ // AR_MEMORY_BACKEND=local-archive → LocalArchiveMemoryBackend (reference)
20
+ // AR_MEMORY_BACKEND=<npm-module> → dynamic import of third-party adapter
21
+ // (unset / "none" / "disabled") → DisabledMemoryBackend
22
+ //
23
+ // Third-party adapters (e.g. a future hindsight-adapter package) must export a
24
+ // default class that satisfies MemoryBackend via dynamic import.
25
+ import { builtinModules } from "node:module";
26
+ // ---------------------------------------------------------------------------
27
+ // Disabled (default / zero-cloud) backend
28
+ // ---------------------------------------------------------------------------
29
+ /**
30
+ * DisabledMemoryBackend — returned when AR_MEMORY_BACKEND is unset.
31
+ * available() is false so callers can gate on it cleanly.
32
+ */
33
+ export class DisabledMemoryBackend {
34
+ name() {
35
+ return "disabled";
36
+ }
37
+ async available() {
38
+ return false;
39
+ }
40
+ async retain(_records) {
41
+ return {
42
+ accepted: [],
43
+ rejected: _records.map((r) => ({
44
+ id: r.id,
45
+ reason: "no backend configured (AR_MEMORY_BACKEND not set)",
46
+ })),
47
+ };
48
+ }
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Factory
52
+ // ---------------------------------------------------------------------------
53
+ /** Cached backend instance. Reset via resetMemoryBackend() in tests. */
54
+ let _cachedBackend = null;
55
+ /**
56
+ * Allowlist for third-party module specifiers: bare npm package names only.
57
+ * - unscoped: [a-z0-9][a-z0-9._-]*
58
+ * - scoped: @[a-z0-9][a-z0-9._-]* / [a-z0-9][a-z0-9._-]*
59
+ * LOWERCASE ONLY — npm forbids uppercase in new package names, and we do NOT
60
+ * case-normalize the value before import: silently lowercasing "MyAdapter" to
61
+ * "myadapter" would import a DIFFERENT package than the operator named (a
62
+ * squat-redirect hazard). Uppercase input is rejected with a clear message.
63
+ * No path separators, no "..", no leading dots — a crafted value cannot reach
64
+ * import() as a file path.
65
+ */
66
+ const SAFE_MODULE_RE = /^(@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$/;
67
+ /**
68
+ * Denylist: Node builtin modules must never be import()ed as backends.
69
+ * They would fail the Ctor typecheck anyway (fail-safe), but the gate rejects
70
+ * them up front with a clear message instead of a confusing typecheck error.
71
+ * Explicit floor list + runtime builtinModules union for completeness across
72
+ * Node versions.
73
+ */
74
+ const BUILTIN_DENYLIST = new Set([
75
+ "fs", "path", "os", "http", "https", "child_process", "net",
76
+ "crypto", "module", "process", "vm", "worker_threads",
77
+ ...(Array.isArray(builtinModules) ? builtinModules : []),
78
+ ]);
79
+ /**
80
+ * Get the configured MemoryBackend.
81
+ *
82
+ * Selection order:
83
+ * 1. AR_MEMORY_BACKEND=local-archive → LocalArchiveMemoryBackend (built-in)
84
+ * 2. AR_MEMORY_BACKEND=<module> → dynamic import of that module
85
+ * 3. (unset | "none" | "disabled") → DisabledMemoryBackend
86
+ *
87
+ * Case handling: built-in keywords (none/disabled/local-archive) match
88
+ * case-insensitively — pure operator convenience, nothing is imported.
89
+ * A third-party module specifier is used VERBATIM (npm names are
90
+ * case-sensitive on registry lookup and lowercase-only for new packages);
91
+ * uppercase input is rejected by SAFE_MODULE_RE with a clear message rather
92
+ * than silently normalized to a different package name.
93
+ *
94
+ * Dynamic import contract: the module must export a default class satisfying
95
+ * MemoryBackend. If the import fails, the specifier is invalid, a Node builtin,
96
+ * or the backend reports unavailable, the factory logs a warning to stderr and
97
+ * falls back to DisabledMemoryBackend — it NEVER crashes the session flow.
98
+ *
99
+ * @agent_instruction Returns DisabledMemoryBackend when no backend is configured.
100
+ * Check (await backend.available()) before calling retain(). If false, surface
101
+ * a clear "no backend configured" error to the operator.
102
+ */
103
+ export async function getMemoryBackend() {
104
+ if (_cachedBackend)
105
+ return _cachedBackend;
106
+ const rawSpec = (process.env.AR_MEMORY_BACKEND ?? "").trim();
107
+ // Keywords only — the verbatim rawSpec is what reaches import() below.
108
+ const keyword = rawSpec.toLowerCase();
109
+ if (!keyword || keyword === "none" || keyword === "disabled") {
110
+ _cachedBackend = new DisabledMemoryBackend();
111
+ return _cachedBackend;
112
+ }
113
+ if (keyword === "local-archive") {
114
+ try {
115
+ const mod = await import("./local-archive-backend.js");
116
+ _cachedBackend = new mod.LocalArchiveMemoryBackend();
117
+ return _cachedBackend;
118
+ }
119
+ catch (err) {
120
+ process.stderr.write(`[agent-recall] memory-backend: failed to load local-archive backend: ${String(err)}\n`);
121
+ _cachedBackend = new DisabledMemoryBackend();
122
+ return _cachedBackend;
123
+ }
124
+ }
125
+ // Third-party module path — dynamic import.
126
+ // SECURITY: AR_MEMORY_BACKEND is operator-controlled env input; treat as
127
+ // untrusted. Gate 1: allowlist shape (bare/scoped npm package name, verbatim).
128
+ if (!SAFE_MODULE_RE.test(rawSpec)) {
129
+ process.stderr.write(`[agent-recall] memory-backend: AR_MEMORY_BACKEND="${rawSpec}" is not a valid npm package name — ` +
130
+ `only lowercase bare package names (e.g. "ar-mem0-adapter") or scoped packages (@org/pkg) are accepted. ` +
131
+ `Path specifiers and uppercase are not allowed. Falling back to disabled.\n`);
132
+ _cachedBackend = new DisabledMemoryBackend();
133
+ return _cachedBackend;
134
+ }
135
+ // Gate 2: Node builtins are never valid backends — reject before import().
136
+ if (BUILTIN_DENYLIST.has(rawSpec) || rawSpec.startsWith("node:")) {
137
+ process.stderr.write(`[agent-recall] memory-backend: AR_MEMORY_BACKEND="${rawSpec}" is a Node builtin module, ` +
138
+ `not a memory backend — refusing to load it. Falling back to disabled.\n`);
139
+ _cachedBackend = new DisabledMemoryBackend();
140
+ return _cachedBackend;
141
+ }
142
+ try {
143
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
144
+ const mod = await import(rawSpec);
145
+ // The module must export a default class or a named MemoryBackend class.
146
+ const Ctor = mod.default ?? mod.MemoryBackend;
147
+ if (typeof Ctor !== "function") {
148
+ throw new TypeError(`module "${rawSpec}" does not export a default class or MemoryBackend — got ${typeof Ctor}`);
149
+ }
150
+ const backend = new Ctor();
151
+ if (!(await backend.available())) {
152
+ // Contract: a loaded-but-unavailable backend falls back to Disabled.
153
+ // Caching and returning the unavailable instance would silently swallow
154
+ // all rejections for any caller that skips the available() check.
155
+ process.stderr.write(`[agent-recall] memory-backend: "${rawSpec}" loaded but reported unavailable — falling back to disabled\n`);
156
+ _cachedBackend = new DisabledMemoryBackend();
157
+ return _cachedBackend;
158
+ }
159
+ _cachedBackend = backend;
160
+ return backend;
161
+ }
162
+ catch (err) {
163
+ process.stderr.write(`[agent-recall] memory-backend: failed to load "${rawSpec}": ${String(err)} — falling back to disabled\n`);
164
+ _cachedBackend = new DisabledMemoryBackend();
165
+ return _cachedBackend;
166
+ }
167
+ }
168
+ /** Reset the cached backend instance (for testing). */
169
+ export function resetMemoryBackend() {
170
+ _cachedBackend = null;
171
+ }
172
+ //# sourceMappingURL=memory-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-backend.js","sourceRoot":"","sources":["../../src/tools-logic/memory-backend.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,+EAA+E;AAC/E,EAAE;AACF,mBAAmB;AACnB,4EAA4E;AAC5E,iFAAiF;AACjF,gFAAgF;AAChF,iFAAiF;AACjF,+EAA+E;AAC/E,4BAA4B;AAC5B,iFAAiF;AACjF,2EAA2E;AAC3E,oDAAoD;AACpD,6EAA6E;AAC7E,mEAAmE;AACnE,EAAE;AACF,sDAAsD;AACtD,6EAA6E;AAC7E,6EAA6E;AAC7E,6DAA6D;AAC7D,EAAE;AACF,+EAA+E;AAC/E,iEAAiE;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA0C7C,8EAA8E;AAC9E,0CAA0C;AAC1C,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IAChC,IAAI;QACF,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAA4B;QACvC,OAAO;YACL,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC7B,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,MAAM,EAAE,mDAAmD;aAC5D,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,wEAAwE;AACxE,IAAI,cAAc,GAAyB,IAAI,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,MAAM,cAAc,GAAG,sEAAsE,CAAC;AAE9F;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IACpD,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK;IAC3D,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB;IACrD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;CACzD,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAE1C,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7D,uEAAuE;IACvE,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEtC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC7D,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC7C,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;YACvD,cAAc,GAAG,IAAI,GAAG,CAAC,yBAAyB,EAAE,CAAC;YACrD,OAAO,cAAc,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wEAAwE,MAAM,CAAC,GAAG,CAAC,IAAI,CACxF,CAAC;YACF,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC;YAC7C,OAAO,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,yEAAyE;IACzE,+EAA+E;IAC/E,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qDAAqD,OAAO,sCAAsC;YAClG,yGAAyG;YACzG,4EAA4E,CAC7E,CAAC;QACF,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC7C,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,2EAA2E;IAC3E,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qDAAqD,OAAO,8BAA8B;YAC1F,yEAAyE,CAC1E,CAAC;QACF,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC7C,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,IAAI,CAAC;QACH,8DAA8D;QAC9D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAQ,CAAC;QACzC,yEAAyE;QACzE,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,aAAa,CAAC;QAC9C,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;YAC/B,MAAM,IAAI,SAAS,CACjB,WAAW,OAAO,4DAA4D,OAAO,IAAI,EAAE,CAC5F,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAmB,CAAC;QAC5C,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC;YACjC,qEAAqE;YACrE,wEAAwE;YACxE,kEAAkE;YAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mCAAmC,OAAO,gEAAgE,CAC3G,CAAC;YACF,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC;YAC7C,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,cAAc,GAAG,OAAO,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kDAAkD,OAAO,MAAM,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAC1G,CAAC;QACF,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC7C,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,kBAAkB;IAChC,cAAc,GAAG,IAAI,CAAC;AACxB,CAAC"}
@@ -4,9 +4,13 @@
4
4
  * Unlike `recall` (general search), this is called mid-task:
5
5
  * "I'm about to do X — what should I know?"
6
6
  *
7
- * Only returns high/medium confidence results. Designed for pull-on-demand
8
- * retrieval rather than push-on-start injection.
7
+ * Returns high/medium confidence results as the primary list. When the primary
8
+ * filter is empty (the match exists but is only low-confidence), the BRIDGE
9
+ * (Wave 4) attaches the verbatim drill-down source under `fallback` instead of
10
+ * silently suppressing it — so the agent gets the lossless source plus a
11
+ * "verify before relying" caution rather than a bare "nothing found" string.
9
12
  */
13
+ import { type BridgedSource } from "./smart-recall.js";
10
14
  export interface MemoryQueryInput {
11
15
  /** Describe what you're about to do or decide. e.g. "push to npm" or "modify auth middleware" */
12
16
  intent: string;
@@ -28,9 +32,12 @@ export interface MemoryQueryResult {
28
32
  intent: string;
29
33
  project: string;
30
34
  results: MemoryQueryItem[];
31
- /** True when no memory is relevant to this intent at the given confidence threshold. */
35
+ /** True when no memory passed the confidence threshold for the primary list. */
32
36
  empty: boolean;
33
37
  guidance?: string;
38
+ /** Verbatim drill-down source attached when the primary filter was empty but a
39
+ * low-confidence match exists (Wave 4 bridge). */
40
+ fallback?: BridgedSource[];
34
41
  }
35
42
  export declare function memoryQuery(input: MemoryQueryInput): Promise<MemoryQueryResult>;
36
43
  //# sourceMappingURL=memory-query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-query.d.ts","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3C,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,wFAAwF;IACxF,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAgBD,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgCrF"}
1
+ {"version":3,"file":"memory-query.d.ts","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOpE,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3C,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,gFAAgF;IAChF,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;uDACmD;IACnD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AAgBD,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuDrF"}
@@ -4,8 +4,11 @@
4
4
  * Unlike `recall` (general search), this is called mid-task:
5
5
  * "I'm about to do X — what should I know?"
6
6
  *
7
- * Only returns high/medium confidence results. Designed for pull-on-demand
8
- * retrieval rather than push-on-start injection.
7
+ * Returns high/medium confidence results as the primary list. When the primary
8
+ * filter is empty (the match exists but is only low-confidence), the BRIDGE
9
+ * (Wave 4) attaches the verbatim drill-down source under `fallback` instead of
10
+ * silently suppressing it — so the agent gets the lossless source plus a
11
+ * "verify before relying" caution rather than a bare "nothing found" string.
9
12
  */
10
13
  import { smartRecall } from "./smart-recall.js";
11
14
  import { resolveProject } from "../storage/project.js";
@@ -28,6 +31,7 @@ export async function memoryQuery(input) {
28
31
  query: input.intent,
29
32
  project,
30
33
  limit: limit * 2, // over-fetch then filter by confidence
34
+ drilldown: true, // bridge: attach verbatim source for low-confidence hits
31
35
  });
32
36
  const filtered = recalled.results
33
37
  .filter((r) => r.score >= minScore)
@@ -40,14 +44,34 @@ export async function memoryQuery(input) {
40
44
  confidence: r.confidence,
41
45
  room: r.room,
42
46
  }));
47
+ if (filtered.length > 0) {
48
+ return {
49
+ intent: input.intent,
50
+ project,
51
+ results: filtered,
52
+ empty: false,
53
+ };
54
+ }
55
+ // Primary filter empty — fall back to the bridged verbatim source if the
56
+ // model tier had a low-confidence match worth drilling into.
57
+ const fallback = recalled.bridged;
58
+ if (fallback && fallback.length > 0) {
59
+ return {
60
+ intent: input.intent,
61
+ project,
62
+ results: [],
63
+ empty: true,
64
+ fallback,
65
+ guidance: `Low-confidence match — verbatim source attached; verify before relying.`,
66
+ };
67
+ }
43
68
  return {
44
69
  intent: input.intent,
45
70
  project,
46
- results: filtered,
47
- empty: filtered.length === 0,
48
- guidance: filtered.length === 0
49
- ? `No memory found relevant to: "${input.intent}". This may be a new area — proceed with standard caution.`
50
- : undefined,
71
+ results: [],
72
+ empty: true,
73
+ fallback: [],
74
+ guidance: `No memory found relevant to: "${input.intent}". This may be a new area — proceed with standard caution.`,
51
75
  };
52
76
  }
53
77
  //# sourceMappingURL=memory-query.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-query.js","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAkCvD,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,MAAM,oBAAoB,GAA2B;IACnD,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,GAAG,EAAE,IAAI;CACV,CAAC;AAEF,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,cAAc,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC;IAChF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IAE/B,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC;QACjC,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,OAAO;QACP,KAAK,EAAE,KAAK,GAAG,CAAC,EAAG,uCAAuC;KAC3D,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC;SAClC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;IAEN,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO;QACP,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC5B,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;YAC7B,CAAC,CAAC,iCAAiC,KAAK,CAAC,MAAM,4DAA4D;YAC3G,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"memory-query.js","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAqCvD,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,MAAM,oBAAoB,GAA2B;IACnD,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,GAAG,EAAE,IAAI;CACV,CAAC;AAEF,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,cAAc,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC;IAChF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IAE/B,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC;QACjC,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,OAAO;QACP,KAAK,EAAE,KAAK,GAAG,CAAC,EAAG,uCAAuC;QAC1D,SAAS,EAAE,IAAI,EAAI,yDAAyD;KAC7E,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC;SAClC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;IAEN,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO;YACP,OAAO,EAAE,QAAQ;YACjB,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;IAClC,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO;YACP,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,QAAQ;YACR,QAAQ,EAAE,yEAAyE;SACpF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO;QACP,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,IAAI;QACX,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,iCAAiC,KAAK,CAAC,MAAM,4DAA4D;KACpH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * mirror.ts — "The Mirror" (Loop 9): a VISIBLE, CORRECTABLE self-model.
3
+ *
4
+ * For nine loops the system has accumulated a one-sided, HIDDEN model of the
5
+ * user (corrections, blind-spots, awareness insights). Loop 3 proved that model
6
+ * is weak at PREDICTION (0/13 keyword recall on a strict LOO). The Mirror flips
7
+ * the hidden model into a first-person reflection the human can READ and CORRECT:
8
+ *
9
+ * "You've corrected me 8 times about X."
10
+ * "I've noticed you tend to …" (with the corrections it's derived from)
11
+ *
12
+ * Each correction-OF-the-mirror is itself a high-value correction — the human
13
+ * pointing at the line and saying "no, that's not why" is exactly the signal the
14
+ * predict-the-correction loop needs.
15
+ *
16
+ * HARD RULES (enforced here and asserted in test/mirror.test.mjs):
17
+ * 1. NEVER fabricate a trait. Every rendered observation traces to ≥1 real
18
+ * stored record — its `cites` array is non-empty and lists real ids.
19
+ * 2. Carry an explicit fallibility caveat on every reflection (Loop 3: this
20
+ * model is NOT yet predictive — "what I've noticed", not "what's true").
21
+ * 3. Personal-tier, LOCAL-ONLY. Reads the same personal/ + awareness artifacts
22
+ * the rest of Wave 5 reads. No network, no LLM, fully deterministic.
23
+ *
24
+ * Pure assembly: this module reads stored data via injected readers (so tests
25
+ * can feed a known store) and renders. It performs NO IO of its own beyond the
26
+ * default readers, which are the existing disk-backed functions.
27
+ */
28
+ import { type CorrectionRecord } from "../storage/corrections.js";
29
+ import { type BlindSpotProfile } from "../helpers/blind-spots.js";
30
+ import { type AwarenessState } from "../palace/awareness.js";
31
+ /**
32
+ * One first-person observation in the mirror. `text` is the rendered line;
33
+ * `cites` lists the REAL stored record ids it was derived from — NEVER empty
34
+ * for a real line (the no-fabrication invariant). `kind` tags the source tier.
35
+ */
36
+ export interface MirrorObservation {
37
+ /** First-person line, e.g. "You've corrected me 8 times about: …". */
38
+ text: string;
39
+ /** Source tier this observation was assembled from. */
40
+ kind: "correction" | "tendency" | "insight" | "cross_project";
41
+ /** Real stored ids this line is grounded in (≥1; the anti-fabrication anchor). */
42
+ cites: string[];
43
+ /** Evidence weight — how many records back this line (for ordering / display). */
44
+ evidence_count: number;
45
+ }
46
+ export interface MirrorReflection {
47
+ /** ISO timestamp the reflection was assembled. */
48
+ generated_at: string;
49
+ /** Project this mirror reflects, or "_global" when assembled cross-project. */
50
+ project: string;
51
+ /** First-person observations, strongest-evidence first. Empty ⇒ empty mirror. */
52
+ observations: MirrorObservation[];
53
+ /**
54
+ * The fallibility caveat (Loop 3). ALWAYS present, even on an empty mirror —
55
+ * the mirror is "what I've noticed", explicitly NOT "what's true about you",
56
+ * and explicitly NOT yet predictive.
57
+ */
58
+ caveat: string;
59
+ /** True when there is no stored data to reflect — render an honest empty mirror. */
60
+ empty: boolean;
61
+ /** Headcount of the underlying corpus this was built from (for the header). */
62
+ basis: {
63
+ corrections: number;
64
+ tendencies: number;
65
+ insights: number;
66
+ cross_project_projects: number;
67
+ };
68
+ }
69
+ /** Injectable readers so tests can feed a known store; defaults read real disk. */
70
+ export interface MirrorReaders {
71
+ corrections: (project: string) => CorrectionRecord[];
72
+ blindSpots: (project: string) => BlindSpotProfile | null;
73
+ awareness: () => AwarenessState | null;
74
+ /** Returns [slug, corrections] for every project (cross-project pass). */
75
+ allProjectCorrections: () => Array<{
76
+ slug: string;
77
+ corrections: CorrectionRecord[];
78
+ }>;
79
+ }
80
+ /**
81
+ * Assemble the mirror for a project (or "_global" when project is omitted).
82
+ *
83
+ * DETERMINISTIC: given the same stored data the output is byte-identical except
84
+ * `generated_at`. Ordering is fully specified (evidence desc, then severity,
85
+ * then a stable text tiebreak) so there is no Set/Map iteration nondeterminism.
86
+ *
87
+ * @param project — project slug; when omitted, assembles a cross-project mirror
88
+ * keyed "_global" that also surfaces patterns recurring across ≥2 projects.
89
+ * @param readers — injectable for tests; defaults to the real disk-backed store.
90
+ */
91
+ export declare function buildMirror(project?: string, readers?: Partial<MirrorReaders>): MirrorReflection;
92
+ export interface CrossProjectPattern {
93
+ /** Representative topic (cleaned rule of the strongest member). */
94
+ topic: string;
95
+ /** Distinct project slugs the pattern spans (≥2). */
96
+ projects: string[];
97
+ /** Real correction ids backing the pattern. */
98
+ cites: string[];
99
+ }
100
+ /**
101
+ * Find correction clusters that recur across ≥2 projects. We tokenize each
102
+ * correction, greedily cluster by ≥2 shared content tokens, and keep clusters
103
+ * whose members span ≥2 distinct projects. Deterministic: corrections are
104
+ * pre-sorted by (date, id) before clustering.
105
+ */
106
+ export declare function deriveCrossProjectPatterns(perProject: Array<{
107
+ slug: string;
108
+ corrections: CorrectionRecord[];
109
+ }>): {
110
+ patterns: CrossProjectPattern[];
111
+ projectCount: number;
112
+ };
113
+ /** Render a reflection as first-person human-readable text (for `ar mirror`). */
114
+ export declare function renderMirror(m: MirrorReflection): string;
115
+ //# sourceMappingURL=mirror-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror-builder.d.ts","sourceRoot":"","sources":["../../src/tools-logic/mirror-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAsB,KAAK,cAAc,EAAgB,MAAM,wBAAwB,CAAC;AAQ/F;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,eAAe,CAAC;IAC9D,kFAAkF;IAClF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,kFAAkF;IAClF,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,KAAK,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,KAAK,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;IACrD,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC;IACzD,SAAS,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IACvC,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,gBAAgB,EAAE,CAAA;KAAE,CAAC,CAAC;CACvF;AAuDD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,gBAAgB,CAqIhG;AAiDD,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC,GACnE;IAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAmD3D;AAMD,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CA6BxD"}