agent-recall-core 3.4.30 → 3.4.35

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 (251) 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 +52 -11
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +48 -9
  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/archive-prune.d.ts +56 -0
  52. package/dist/storage/archive-prune.d.ts.map +1 -0
  53. package/dist/storage/archive-prune.js +118 -0
  54. package/dist/storage/archive-prune.js.map +1 -0
  55. package/dist/storage/archive-write.d.ts +38 -0
  56. package/dist/storage/archive-write.d.ts.map +1 -0
  57. package/dist/storage/archive-write.js +98 -0
  58. package/dist/storage/archive-write.js.map +1 -0
  59. package/dist/storage/blind-spots-store.d.ts +30 -0
  60. package/dist/storage/blind-spots-store.d.ts.map +1 -0
  61. package/dist/storage/blind-spots-store.js +91 -0
  62. package/dist/storage/blind-spots-store.js.map +1 -0
  63. package/dist/storage/capture-router.d.ts +60 -0
  64. package/dist/storage/capture-router.d.ts.map +1 -0
  65. package/dist/storage/capture-router.js +133 -0
  66. package/dist/storage/capture-router.js.map +1 -0
  67. package/dist/storage/classification.d.ts +32 -0
  68. package/dist/storage/classification.d.ts.map +1 -0
  69. package/dist/storage/classification.js +74 -0
  70. package/dist/storage/classification.js.map +1 -0
  71. package/dist/storage/consolidation-queue.d.ts +39 -0
  72. package/dist/storage/consolidation-queue.d.ts.map +1 -0
  73. package/dist/storage/consolidation-queue.js +120 -0
  74. package/dist/storage/consolidation-queue.js.map +1 -0
  75. package/dist/storage/content-guard.d.ts +74 -0
  76. package/dist/storage/content-guard.d.ts.map +1 -0
  77. package/dist/storage/content-guard.js +179 -0
  78. package/dist/storage/content-guard.js.map +1 -0
  79. package/dist/storage/corrections.d.ts +246 -21
  80. package/dist/storage/corrections.d.ts.map +1 -1
  81. package/dist/storage/corrections.js +605 -56
  82. package/dist/storage/corrections.js.map +1 -1
  83. package/dist/storage/durable-intent.d.ts +49 -0
  84. package/dist/storage/durable-intent.d.ts.map +1 -0
  85. package/dist/storage/durable-intent.js +124 -0
  86. package/dist/storage/durable-intent.js.map +1 -0
  87. package/dist/storage/filelock.d.ts +6 -0
  88. package/dist/storage/filelock.d.ts.map +1 -1
  89. package/dist/storage/filelock.js +6 -1
  90. package/dist/storage/filelock.js.map +1 -1
  91. package/dist/storage/memory-protocol.d.ts +19 -0
  92. package/dist/storage/memory-protocol.d.ts.map +1 -0
  93. package/dist/storage/memory-protocol.js +101 -0
  94. package/dist/storage/memory-protocol.js.map +1 -0
  95. package/dist/storage/paths.d.ts +23 -0
  96. package/dist/storage/paths.d.ts.map +1 -1
  97. package/dist/storage/paths.js +39 -0
  98. package/dist/storage/paths.js.map +1 -1
  99. package/dist/storage/retention.d.ts +23 -0
  100. package/dist/storage/retention.d.ts.map +1 -0
  101. package/dist/storage/retention.js +48 -0
  102. package/dist/storage/retention.js.map +1 -0
  103. package/dist/storage/session.d.ts +2 -2
  104. package/dist/storage/session.d.ts.map +1 -1
  105. package/dist/storage/session.js +11 -1
  106. package/dist/storage/session.js.map +1 -1
  107. package/dist/supabase/config.d.ts +8 -0
  108. package/dist/supabase/config.d.ts.map +1 -1
  109. package/dist/supabase/config.js +5 -0
  110. package/dist/supabase/config.js.map +1 -1
  111. package/dist/supabase/recall-backend.d.ts +1 -0
  112. package/dist/supabase/recall-backend.d.ts.map +1 -1
  113. package/dist/supabase/recall-backend.js +13 -13
  114. package/dist/supabase/recall-backend.js.map +1 -1
  115. package/dist/supabase/sync.d.ts.map +1 -1
  116. package/dist/supabase/sync.js +30 -3
  117. package/dist/supabase/sync.js.map +1 -1
  118. package/dist/tools-logic/bootstrap.d.ts +15 -0
  119. package/dist/tools-logic/bootstrap.d.ts.map +1 -1
  120. package/dist/tools-logic/bootstrap.js +238 -47
  121. package/dist/tools-logic/bootstrap.js.map +1 -1
  122. package/dist/tools-logic/brief.d.ts +84 -0
  123. package/dist/tools-logic/brief.d.ts.map +1 -0
  124. package/dist/tools-logic/brief.js +193 -0
  125. package/dist/tools-logic/brief.js.map +1 -0
  126. package/dist/tools-logic/check-action.d.ts +9 -0
  127. package/dist/tools-logic/check-action.d.ts.map +1 -1
  128. package/dist/tools-logic/check-action.js +31 -2
  129. package/dist/tools-logic/check-action.js.map +1 -1
  130. package/dist/tools-logic/check.d.ts +7 -0
  131. package/dist/tools-logic/check.d.ts.map +1 -1
  132. package/dist/tools-logic/check.js +24 -2
  133. package/dist/tools-logic/check.js.map +1 -1
  134. package/dist/tools-logic/confidence.d.ts +50 -0
  135. package/dist/tools-logic/confidence.d.ts.map +1 -0
  136. package/dist/tools-logic/confidence.js +70 -0
  137. package/dist/tools-logic/confidence.js.map +1 -0
  138. package/dist/tools-logic/drill-down.d.ts +37 -0
  139. package/dist/tools-logic/drill-down.d.ts.map +1 -0
  140. package/dist/tools-logic/drill-down.js +63 -0
  141. package/dist/tools-logic/drill-down.js.map +1 -0
  142. package/dist/tools-logic/export-corrections.d.ts +63 -0
  143. package/dist/tools-logic/export-corrections.d.ts.map +1 -0
  144. package/dist/tools-logic/export-corrections.js +124 -0
  145. package/dist/tools-logic/export-corrections.js.map +1 -0
  146. package/dist/tools-logic/journal-capture.d.ts.map +1 -1
  147. package/dist/tools-logic/journal-capture.js +4 -1
  148. package/dist/tools-logic/journal-capture.js.map +1 -1
  149. package/dist/tools-logic/journal-write.d.ts.map +1 -1
  150. package/dist/tools-logic/journal-write.js +3 -2
  151. package/dist/tools-logic/journal-write.js.map +1 -1
  152. package/dist/tools-logic/memory-query.d.ts +10 -3
  153. package/dist/tools-logic/memory-query.d.ts.map +1 -1
  154. package/dist/tools-logic/memory-query.js +31 -7
  155. package/dist/tools-logic/memory-query.js.map +1 -1
  156. package/dist/tools-logic/mirror-builder.d.ts +115 -0
  157. package/dist/tools-logic/mirror-builder.d.ts.map +1 -0
  158. package/dist/tools-logic/mirror-builder.js +348 -0
  159. package/dist/tools-logic/mirror-builder.js.map +1 -0
  160. package/dist/tools-logic/palace-write.d.ts.map +1 -1
  161. package/dist/tools-logic/palace-write.js +3 -2
  162. package/dist/tools-logic/palace-write.js.map +1 -1
  163. package/dist/tools-logic/pipeline-close.d.ts.map +1 -1
  164. package/dist/tools-logic/pipeline-close.js +2 -1
  165. package/dist/tools-logic/pipeline-close.js.map +1 -1
  166. package/dist/tools-logic/pipeline-open.d.ts.map +1 -1
  167. package/dist/tools-logic/pipeline-open.js +2 -1
  168. package/dist/tools-logic/pipeline-open.js.map +1 -1
  169. package/dist/tools-logic/predict-correction.d.ts +47 -0
  170. package/dist/tools-logic/predict-correction.d.ts.map +1 -0
  171. package/dist/tools-logic/predict-correction.js +137 -0
  172. package/dist/tools-logic/predict-correction.js.map +1 -0
  173. package/dist/tools-logic/prior-builder.d.ts +27 -0
  174. package/dist/tools-logic/prior-builder.d.ts.map +1 -0
  175. package/dist/tools-logic/prior-builder.js +57 -0
  176. package/dist/tools-logic/prior-builder.js.map +1 -0
  177. package/dist/tools-logic/recognition-builder.d.ts +116 -0
  178. package/dist/tools-logic/recognition-builder.d.ts.map +1 -0
  179. package/dist/tools-logic/recognition-builder.js +289 -0
  180. package/dist/tools-logic/recognition-builder.js.map +1 -0
  181. package/dist/tools-logic/safety-consolidation.d.ts +104 -0
  182. package/dist/tools-logic/safety-consolidation.d.ts.map +1 -0
  183. package/dist/tools-logic/safety-consolidation.js +256 -0
  184. package/dist/tools-logic/safety-consolidation.js.map +1 -0
  185. package/dist/tools-logic/session-end-reflect.d.ts +18 -0
  186. package/dist/tools-logic/session-end-reflect.d.ts.map +1 -1
  187. package/dist/tools-logic/session-end-reflect.js +68 -29
  188. package/dist/tools-logic/session-end-reflect.js.map +1 -1
  189. package/dist/tools-logic/session-end.d.ts +9 -0
  190. package/dist/tools-logic/session-end.d.ts.map +1 -1
  191. package/dist/tools-logic/session-end.js +111 -13
  192. package/dist/tools-logic/session-end.js.map +1 -1
  193. package/dist/tools-logic/session-start-lite.d.ts +2 -0
  194. package/dist/tools-logic/session-start-lite.d.ts.map +1 -1
  195. package/dist/tools-logic/session-start-lite.js +10 -0
  196. package/dist/tools-logic/session-start-lite.js.map +1 -1
  197. package/dist/tools-logic/session-start.d.ts +46 -0
  198. package/dist/tools-logic/session-start.d.ts.map +1 -1
  199. package/dist/tools-logic/session-start.js +96 -3
  200. package/dist/tools-logic/session-start.js.map +1 -1
  201. package/dist/tools-logic/skill-propose.d.ts +27 -0
  202. package/dist/tools-logic/skill-propose.d.ts.map +1 -0
  203. package/dist/tools-logic/skill-propose.js +66 -0
  204. package/dist/tools-logic/skill-propose.js.map +1 -0
  205. package/dist/tools-logic/skill-recall.d.ts +5 -0
  206. package/dist/tools-logic/skill-recall.d.ts.map +1 -1
  207. package/dist/tools-logic/skill-recall.js +14 -1
  208. package/dist/tools-logic/skill-recall.js.map +1 -1
  209. package/dist/tools-logic/smart-recall.d.ts +17 -0
  210. package/dist/tools-logic/smart-recall.d.ts.map +1 -1
  211. package/dist/tools-logic/smart-recall.js +51 -16
  212. package/dist/tools-logic/smart-recall.js.map +1 -1
  213. package/dist/tools-logic/store-doctor.d.ts +71 -0
  214. package/dist/tools-logic/store-doctor.d.ts.map +1 -0
  215. package/dist/tools-logic/store-doctor.js +387 -0
  216. package/dist/tools-logic/store-doctor.js.map +1 -0
  217. package/dist/tools-logic/store-repair.d.ts +64 -0
  218. package/dist/tools-logic/store-repair.d.ts.map +1 -0
  219. package/dist/tools-logic/store-repair.js +243 -0
  220. package/dist/tools-logic/store-repair.js.map +1 -0
  221. package/dist/tools-logic/supersession.d.ts +34 -0
  222. package/dist/tools-logic/supersession.d.ts.map +1 -0
  223. package/dist/tools-logic/supersession.js +103 -0
  224. package/dist/tools-logic/supersession.js.map +1 -0
  225. package/dist/types.d.ts +7 -1
  226. package/dist/types.d.ts.map +1 -1
  227. package/dist/types.js +1 -1
  228. package/dist/vector/local-vector-backend.d.ts.map +1 -1
  229. package/dist/vector/local-vector-backend.js +14 -17
  230. package/dist/vector/local-vector-backend.js.map +1 -1
  231. package/package.json +9 -1
  232. package/dist/relevance/injector.d.ts +0 -51
  233. package/dist/relevance/injector.d.ts.map +0 -1
  234. package/dist/relevance/injector.js +0 -121
  235. package/dist/relevance/injector.js.map +0 -1
  236. package/dist/relevance/precision.d.ts +0 -109
  237. package/dist/relevance/precision.d.ts.map +0 -1
  238. package/dist/relevance/precision.js +0 -279
  239. package/dist/relevance/precision.js.map +0 -1
  240. package/dist/relevance/promoter.d.ts +0 -60
  241. package/dist/relevance/promoter.d.ts.map +0 -1
  242. package/dist/relevance/promoter.js +0 -336
  243. package/dist/relevance/promoter.js.map +0 -1
  244. package/dist/relevance/stager.d.ts +0 -61
  245. package/dist/relevance/stager.d.ts.map +0 -1
  246. package/dist/relevance/stager.js +0 -251
  247. package/dist/relevance/stager.js.map +0 -1
  248. package/dist/relevance/surfacer.d.ts +0 -34
  249. package/dist/relevance/surfacer.d.ts.map +0 -1
  250. package/dist/relevance/surfacer.js +0 -333
  251. package/dist/relevance/surfacer.js.map +0 -1
@@ -1,121 +0,0 @@
1
- /**
2
- * Injector — formats Surfacer Candidates as an "added context" block the host
3
- * hook can echo into the agent's context (v3.5.0 P-B, spec §4 "Judge" + §5).
4
- *
5
- * Contract:
6
- * • Pure function. Zero fs, zero network — Surfacer already did the I/O.
7
- * • Empty candidates → returns "" (silence is precision; the hook MUST emit
8
- * nothing in this case so the agent's context stays clean — see spec §6).
9
- * • One bullet per candidate, capped at ~140 chars total per line so the
10
- * injected block never blows past a few hundred tokens even at K=3.
11
- * • Title-render uses [source] (palace shows palace/<room>) and includes
12
- * the Surfacer's `why` clause so the model knows WHY this surfaced and
13
- * can decide whether to act on it.
14
- *
15
- * Output shape (verbatim — host hook copy-pastes this into stdout):
16
- *
17
- * <agent-recall-context>
18
- * Possibly relevant prior memory (use if it helps, ignore otherwise):
19
- * • [palace/goals] Rate limiting in Stripe — must use idempotency keys (why: matches palace/goals)
20
- * • [journal] 2026-06-12 — Stripe webhook signature verification gotcha (why: matched recent journal 2026-06-12)
21
- * </agent-recall-context>
22
- *
23
- * Worker done-definition self-check:
24
- * (1) Error path: candidates is null/undefined → coerce to [] before any
25
- * work. Each candidate field is `?? ""` so undefined never throws.
26
- * (2) No global binaries — pure node, no shell-outs, no deps.
27
- * (3) Threshold/ternary ordering — only branch is `length === 0 ? '' : block`,
28
- * short-circuit-on-empty first.
29
- * (4) No time-of-day logic; nothing TZ-sensitive.
30
- */
31
- /** Hard cap per bullet line. ~140 chars keeps the K=3 block under ~500 chars. */
32
- const LINE_MAX_CHARS = 140;
33
- /** Width budget left over for the title+why after the "• [tag] " prefix. */
34
- const TITLE_MAX_CHARS = 80;
35
- const WHY_MAX_CHARS = 60;
36
- /**
37
- * Build the bracket-tag prefix shown at the head of each bullet.
38
- * palace candidates carry their room (`palace/goals`); others fall back to
39
- * just the source kind.
40
- */
41
- function tagOf(c) {
42
- if (c.source === "palace" && c.room)
43
- return `palace/${c.room}`;
44
- return c.source;
45
- }
46
- /**
47
- * Truncate without splitting mid-codepoint. We only handle BMP here; the
48
- * Surfacer's snippets are already char-capped, so this is the second-line
49
- * defense (Injector's caller could in theory pass a fresh Candidate with a
50
- * longer title — be tolerant).
51
- */
52
- function truncate(s, n) {
53
- if (!s)
54
- return "";
55
- if (s.length <= n)
56
- return s;
57
- return s.slice(0, n);
58
- }
59
- /**
60
- * Render one Candidate as a single bullet line, capped to LINE_MAX_CHARS.
61
- *
62
- * Format: `• [<tag>] <title> (why: <why>)`
63
- *
64
- * If the assembled line exceeds LINE_MAX_CHARS we re-trim the title (the
65
- * most variable field) until the whole line fits. The `[tag]` prefix and
66
- * the `why:` clause are short and information-dense, so they survive
67
- * intact at the expense of the title's tail.
68
- */
69
- export function formatCandidate(c) {
70
- const tag = tagOf(c);
71
- const why = truncate((c.why ?? "").trim(), WHY_MAX_CHARS);
72
- let title = truncate((c.title ?? "").trim(), TITLE_MAX_CHARS);
73
- // Static parts of the line. `• [tag] ` + ` (why: <why>)` is fixed once
74
- // tag/why are known; only the title is elastic.
75
- const prefix = `• [${tag}] `;
76
- const suffix = why ? ` (why: ${why})` : "";
77
- const budget = LINE_MAX_CHARS - prefix.length - suffix.length;
78
- if (budget <= 0) {
79
- // Pathological case: tag + why already > LINE_MAX_CHARS. Drop the why
80
- // clause to recover space; the bracket-tag is the more important signal.
81
- return truncate(`${prefix}${title}`, LINE_MAX_CHARS);
82
- }
83
- if (title.length > budget) {
84
- title = title.slice(0, Math.max(0, budget - 1)) + "…";
85
- }
86
- const line = `${prefix}${title}${suffix}`;
87
- // Final guard — the budget math above should make this a no-op, but a
88
- // bug in the truncate path must NEVER produce a line that breaks the
89
- // host's stdout framing. Cap unconditionally.
90
- return truncate(line, LINE_MAX_CHARS);
91
- }
92
- /**
93
- * Format a list of Candidates for the host hook to inject.
94
- *
95
- * Empty input → empty string. This is load-bearing — the hook in the host
96
- * is wired to echo our stdout verbatim, so an empty string keeps the
97
- * agent's context clean (silence is precision, spec §6).
98
- */
99
- export function formatForHook(candidates) {
100
- // Error path #1: null/undefined input — coerce, do not throw.
101
- const list = Array.isArray(candidates) ? candidates : [];
102
- if (list.length === 0)
103
- return "";
104
- const lines = [];
105
- for (const c of list) {
106
- // Skip malformed candidates rather than throwing — Surfacer's contract is
107
- // strict but defensive code here costs nothing.
108
- if (!c || typeof c !== "object")
109
- continue;
110
- lines.push(formatCandidate(c));
111
- }
112
- if (lines.length === 0)
113
- return "";
114
- return [
115
- "<agent-recall-context>",
116
- "Possibly relevant prior memory (use if it helps, ignore otherwise):",
117
- ...lines,
118
- "</agent-recall-context>",
119
- ].join("\n");
120
- }
121
- //# sourceMappingURL=injector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injector.js","sourceRoot":"","sources":["../../src/relevance/injector.ts"],"names":[],"mappings":"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"}
@@ -1,109 +0,0 @@
1
- /**
2
- * Precision meter — `injection_precision = used / injected`
3
- * (v3.5.0 P-C, Ambient Relevance Loop, spec §5 + §6 "Precision guardrail").
4
- *
5
- * Purpose: this is the north-star metric that proves "intelligence, not
6
- * storage." Of the memories AgentRecall surfaces (`injected`), how many
7
- * does the agent actually act on (`used`)? A falling number is the
8
- * early-warning that the Surfacer threshold is mis-tuned (noise > signal).
9
- *
10
- * Storage shape — append-only JSONL, one file per kind, per project:
11
- *
12
- * ~/.agent-recall/projects/<slug>/_precision/injections.jsonl
13
- * ~/.agent-recall/projects/<slug>/_precision/usages.jsonl
14
- *
15
- * Design contract:
16
- * • `recordInjection`/`recordUsage` are fire-and-forget — they NEVER
17
- * throw. Losing a measurement line is acceptable; killing a user turn
18
- * is not. Errors are swallowed silently (mirrors stager.ts).
19
- * • `getPrecisionKPI` is tolerant of malformed lines (skipped, not
20
- * fatal), missing files (treated as empty), and missing fields.
21
- * • `precision` is **null** (not NaN) when `injected === 0` — the
22
- * dashboard can render "—" instead of "NaN%".
23
- * • `precision` is clamped to `[0, 1]` via `Math.min(1, used / injected)`
24
- * (matches the existing pattern in storage/corrections.ts:373 — under
25
- * data corruption / duplicate-usage events, the raw ratio can exceed
26
- * 1.0, which is nonsense as a "precision" metric).
27
- * • `per_source` groups by the prefix of `candidate_id` before ':'
28
- * (e.g. `palace:room:slug` → bucket `palace`). Unprefixed ids land in
29
- * the `unknown` bucket so they're still visible.
30
- *
31
- * Worker done-definition self-check:
32
- * (1) error paths: `readJsonl` returns [] on read failure, JSON.parse
33
- * wrapped in try/catch per line; recordInjection/Usage's outer
34
- * try/catch swallows fs errors.
35
- * (2) no global binaries — pure node:fs/path/crypto, no shell-outs.
36
- * (3) ternary ordering — only branch is `injected > 0 ? clamp : null`,
37
- * null is the explicit zero-denominator case.
38
- * (4) time logic — `cutoff` is computed in ms-since-epoch from `Date.now()`
39
- * which is TZ-agnostic; `ts` strings are ISO-8601 (also TZ-agnostic).
40
- * No local-date filename is used here so no TZ bug surface.
41
- */
42
- export interface InjectionEvent {
43
- /** ISO-8601 timestamp of when the candidates were surfaced. */
44
- ts: string;
45
- /** Candidate ids that the Surfacer pushed into the agent's context this turn. */
46
- candidate_ids: string[];
47
- /** sha256(user_message + assistant_response) — links to UsageEvent.turn_hash. */
48
- turn_hash: string;
49
- }
50
- export interface UsageEvent {
51
- /** ISO-8601 timestamp of when the usage was detected. */
52
- ts: string;
53
- /** The id of the candidate that the agent acted on. */
54
- candidate_id: string;
55
- /** Turn this candidate was used in — joins back to InjectionEvent.turn_hash. */
56
- turn_hash: string;
57
- /** Brief reason (e.g. "title appeared in assistant output"). */
58
- evidence: string;
59
- }
60
- export interface PrecisionKPI {
61
- /** Window the KPI was computed over (days). */
62
- window_days: number;
63
- /** Total candidates surfaced (sum of candidate_ids.length across injections). */
64
- injected: number;
65
- /** Total candidates the agent used (one row per used candidate). */
66
- used: number;
67
- /**
68
- * `used / injected`, clamped to `[0, 1]`. **null** when `injected === 0`
69
- * (NaN MUST NOT appear — the dashboard treats null as "no data yet").
70
- */
71
- precision: number | null;
72
- /** Breakdown by candidate-id source prefix (palace / journal / …). */
73
- per_source: Record<string, {
74
- injected: number;
75
- used: number;
76
- }>;
77
- }
78
- /**
79
- * Append one injection event to `_precision/injections.jsonl`.
80
- *
81
- * NEVER THROWS. Mirrors `stage()` — the read/write loop continues
82
- * regardless of fs errors. Losing a measurement is acceptable; killing a
83
- * user turn is not.
84
- */
85
- export declare function recordInjection(project: string, ev: InjectionEvent): void;
86
- /**
87
- * Append one usage event to `_precision/usages.jsonl`.
88
- *
89
- * NEVER THROWS. One row per used candidate; the caller is expected to
90
- * dedupe at the detection layer (one usage row per (turn_hash, candidate_id)).
91
- */
92
- export declare function recordUsage(project: string, ev: UsageEvent): void;
93
- /**
94
- * Compute the precision KPI over the trailing `windowDays` (default 14).
95
- *
96
- * Algorithm (spec §6):
97
- * • cutoff = now - windowDays * 86400_000 ms
98
- * • injected = Σ ev.candidate_ids.length over injections with ts ≥ cutoff
99
- * • used = count of usage rows with ts ≥ cutoff
100
- * • precision = injected > 0 ? Math.min(1, used / injected) : null
101
- * • per_source = { <prefix>: { injected, used } } grouped by id-prefix
102
- *
103
- * Invariants:
104
- * • `precision` is never NaN; it is either a finite number in [0, 1] or null.
105
- * • Malformed jsonl lines are tolerated (skipped by `readJsonl`).
106
- * • Empty project → injected=0, used=0, precision=null, per_source={}.
107
- */
108
- export declare function getPrecisionKPI(project: string, windowDays?: number): PrecisionKPI;
109
- //# sourceMappingURL=precision.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"precision.d.ts","sourceRoot":"","sources":["../../src/relevance/precision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAaH,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,yDAAyD;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChE;AAoGD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,CAiBzE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,CAiBjE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CA+DlF"}
@@ -1,279 +0,0 @@
1
- /**
2
- * Precision meter — `injection_precision = used / injected`
3
- * (v3.5.0 P-C, Ambient Relevance Loop, spec §5 + §6 "Precision guardrail").
4
- *
5
- * Purpose: this is the north-star metric that proves "intelligence, not
6
- * storage." Of the memories AgentRecall surfaces (`injected`), how many
7
- * does the agent actually act on (`used`)? A falling number is the
8
- * early-warning that the Surfacer threshold is mis-tuned (noise > signal).
9
- *
10
- * Storage shape — append-only JSONL, one file per kind, per project:
11
- *
12
- * ~/.agent-recall/projects/<slug>/_precision/injections.jsonl
13
- * ~/.agent-recall/projects/<slug>/_precision/usages.jsonl
14
- *
15
- * Design contract:
16
- * • `recordInjection`/`recordUsage` are fire-and-forget — they NEVER
17
- * throw. Losing a measurement line is acceptable; killing a user turn
18
- * is not. Errors are swallowed silently (mirrors stager.ts).
19
- * • `getPrecisionKPI` is tolerant of malformed lines (skipped, not
20
- * fatal), missing files (treated as empty), and missing fields.
21
- * • `precision` is **null** (not NaN) when `injected === 0` — the
22
- * dashboard can render "—" instead of "NaN%".
23
- * • `precision` is clamped to `[0, 1]` via `Math.min(1, used / injected)`
24
- * (matches the existing pattern in storage/corrections.ts:373 — under
25
- * data corruption / duplicate-usage events, the raw ratio can exceed
26
- * 1.0, which is nonsense as a "precision" metric).
27
- * • `per_source` groups by the prefix of `candidate_id` before ':'
28
- * (e.g. `palace:room:slug` → bucket `palace`). Unprefixed ids land in
29
- * the `unknown` bucket so they're still visible.
30
- *
31
- * Worker done-definition self-check:
32
- * (1) error paths: `readJsonl` returns [] on read failure, JSON.parse
33
- * wrapped in try/catch per line; recordInjection/Usage's outer
34
- * try/catch swallows fs errors.
35
- * (2) no global binaries — pure node:fs/path/crypto, no shell-outs.
36
- * (3) ternary ordering — only branch is `injected > 0 ? clamp : null`,
37
- * null is the explicit zero-denominator case.
38
- * (4) time logic — `cutoff` is computed in ms-since-epoch from `Date.now()`
39
- * which is TZ-agnostic; `ts` strings are ISO-8601 (also TZ-agnostic).
40
- * No local-date filename is used here so no TZ bug surface.
41
- */
42
- import * as fs from "node:fs";
43
- import * as path from "node:path";
44
- import { sanitizeProject } from "../storage/paths.js";
45
- import { ensureDir } from "../storage/fs-utils.js";
46
- import { getRoot } from "../types.js";
47
- // ---------------------------------------------------------------------------
48
- // Internal helpers
49
- // ---------------------------------------------------------------------------
50
- /** Resolve the per-project precision directory. Mirrors stager's `_staging/` convention. */
51
- function precisionDir(project) {
52
- const safe = sanitizeProject(project);
53
- return path.join(getRoot(), "projects", safe, "_precision");
54
- }
55
- function injectionsPath(project) {
56
- return path.join(precisionDir(project), "injections.jsonl");
57
- }
58
- function usagesPath(project) {
59
- return path.join(precisionDir(project), "usages.jsonl");
60
- }
61
- /**
62
- * Parse a JSONL file. Bad lines (truncated writes, manual edits) are
63
- * silently skipped — never throws. Missing file → empty array.
64
- *
65
- * Generic over the row shape; caller is responsible for narrowing.
66
- */
67
- function readJsonl(filePath) {
68
- if (!fs.existsSync(filePath))
69
- return [];
70
- let raw;
71
- try {
72
- raw = fs.readFileSync(filePath, "utf-8");
73
- }
74
- catch {
75
- return [];
76
- }
77
- const out = [];
78
- const lines = raw.split("\n");
79
- for (const line of lines) {
80
- const trimmed = line.trim();
81
- if (!trimmed)
82
- continue;
83
- try {
84
- out.push(JSON.parse(trimmed));
85
- }
86
- catch {
87
- // Malformed line — skip, never throw.
88
- }
89
- }
90
- return out;
91
- }
92
- /**
93
- * Append one row to a JSONL file. Wraps the `fs.appendFileSync` call so
94
- * the public recorders can swallow fs errors at the boundary.
95
- */
96
- function appendJsonl(filePath, row) {
97
- ensureDir(path.dirname(filePath));
98
- fs.appendFileSync(filePath, JSON.stringify(row) + "\n", "utf-8");
99
- }
100
- /**
101
- * Extract the source prefix from a candidate id.
102
- * `palace:room:slug` → `palace`. Unprefixed → `unknown`.
103
- */
104
- function sourceOf(candidateId) {
105
- if (typeof candidateId !== "string" || candidateId.length === 0)
106
- return "unknown";
107
- const idx = candidateId.indexOf(":");
108
- if (idx <= 0)
109
- return "unknown";
110
- return candidateId.slice(0, idx);
111
- }
112
- /**
113
- * Narrow an unknown value to `InjectionEvent` shape (defensive — JSONL may
114
- * have been edited by hand). Returns null on miss.
115
- */
116
- function asInjectionEvent(v) {
117
- if (!v || typeof v !== "object")
118
- return null;
119
- const o = v;
120
- if (typeof o.ts !== "string")
121
- return null;
122
- if (!Array.isArray(o.candidate_ids))
123
- return null;
124
- if (typeof o.turn_hash !== "string")
125
- return null;
126
- const cids = o.candidate_ids.filter((c) => typeof c === "string");
127
- return { ts: o.ts, candidate_ids: cids, turn_hash: o.turn_hash };
128
- }
129
- function asUsageEvent(v) {
130
- if (!v || typeof v !== "object")
131
- return null;
132
- const o = v;
133
- if (typeof o.ts !== "string")
134
- return null;
135
- if (typeof o.candidate_id !== "string")
136
- return null;
137
- if (typeof o.turn_hash !== "string")
138
- return null;
139
- return {
140
- ts: o.ts,
141
- candidate_id: o.candidate_id,
142
- turn_hash: o.turn_hash,
143
- evidence: typeof o.evidence === "string" ? o.evidence : "",
144
- };
145
- }
146
- // ---------------------------------------------------------------------------
147
- // Public API
148
- // ---------------------------------------------------------------------------
149
- /**
150
- * Append one injection event to `_precision/injections.jsonl`.
151
- *
152
- * NEVER THROWS. Mirrors `stage()` — the read/write loop continues
153
- * regardless of fs errors. Losing a measurement is acceptable; killing a
154
- * user turn is not.
155
- */
156
- export function recordInjection(project, ev) {
157
- try {
158
- if (!ev || typeof ev !== "object")
159
- return;
160
- const safe = {
161
- ts: typeof ev.ts === "string" && ev.ts.length > 0
162
- ? ev.ts
163
- : new Date().toISOString(),
164
- candidate_ids: Array.isArray(ev.candidate_ids)
165
- ? ev.candidate_ids.filter((c) => typeof c === "string")
166
- : [],
167
- turn_hash: typeof ev.turn_hash === "string" ? ev.turn_hash : "",
168
- };
169
- appendJsonl(injectionsPath(project), safe);
170
- }
171
- catch {
172
- // Swallow — see contract above.
173
- }
174
- }
175
- /**
176
- * Append one usage event to `_precision/usages.jsonl`.
177
- *
178
- * NEVER THROWS. One row per used candidate; the caller is expected to
179
- * dedupe at the detection layer (one usage row per (turn_hash, candidate_id)).
180
- */
181
- export function recordUsage(project, ev) {
182
- try {
183
- if (!ev || typeof ev !== "object")
184
- return;
185
- const safe = {
186
- ts: typeof ev.ts === "string" && ev.ts.length > 0
187
- ? ev.ts
188
- : new Date().toISOString(),
189
- candidate_id: typeof ev.candidate_id === "string" ? ev.candidate_id : "",
190
- turn_hash: typeof ev.turn_hash === "string" ? ev.turn_hash : "",
191
- evidence: typeof ev.evidence === "string" ? ev.evidence : "",
192
- };
193
- if (!safe.candidate_id)
194
- return; // can't bucket without an id
195
- appendJsonl(usagesPath(project), safe);
196
- }
197
- catch {
198
- // Swallow.
199
- }
200
- }
201
- /**
202
- * Compute the precision KPI over the trailing `windowDays` (default 14).
203
- *
204
- * Algorithm (spec §6):
205
- * • cutoff = now - windowDays * 86400_000 ms
206
- * • injected = Σ ev.candidate_ids.length over injections with ts ≥ cutoff
207
- * • used = count of usage rows with ts ≥ cutoff
208
- * • precision = injected > 0 ? Math.min(1, used / injected) : null
209
- * • per_source = { <prefix>: { injected, used } } grouped by id-prefix
210
- *
211
- * Invariants:
212
- * • `precision` is never NaN; it is either a finite number in [0, 1] or null.
213
- * • Malformed jsonl lines are tolerated (skipped by `readJsonl`).
214
- * • Empty project → injected=0, used=0, precision=null, per_source={}.
215
- */
216
- export function getPrecisionKPI(project, windowDays) {
217
- const days = typeof windowDays === "number" && Number.isFinite(windowDays) && windowDays > 0
218
- ? windowDays
219
- : 14;
220
- const cutoffMs = Date.now() - days * 86400_000;
221
- const rawInjections = readJsonl(injectionsPath(project));
222
- const rawUsages = readJsonl(usagesPath(project));
223
- const injections = [];
224
- for (const r of rawInjections) {
225
- const ev = asInjectionEvent(r);
226
- if (!ev)
227
- continue;
228
- const t = Date.parse(ev.ts);
229
- if (!Number.isFinite(t))
230
- continue; // unparseable ts → skip
231
- if (t < cutoffMs)
232
- continue;
233
- injections.push(ev);
234
- }
235
- const usages = [];
236
- for (const r of rawUsages) {
237
- const ev = asUsageEvent(r);
238
- if (!ev)
239
- continue;
240
- const t = Date.parse(ev.ts);
241
- if (!Number.isFinite(t))
242
- continue;
243
- if (t < cutoffMs)
244
- continue;
245
- usages.push(ev);
246
- }
247
- let injected = 0;
248
- const perSource = {};
249
- for (const ev of injections) {
250
- for (const cid of ev.candidate_ids) {
251
- injected++;
252
- const src = sourceOf(cid);
253
- if (!perSource[src])
254
- perSource[src] = { injected: 0, used: 0 };
255
- perSource[src].injected++;
256
- }
257
- }
258
- const used = usages.length;
259
- for (const ev of usages) {
260
- const src = sourceOf(ev.candidate_id);
261
- if (!perSource[src])
262
- perSource[src] = { injected: 0, used: 0 };
263
- perSource[src].used++;
264
- }
265
- // Clamp [0, 1]: data corruption (duplicate usages, late-arriving rows after
266
- // injections were rotated out, etc.) can push raw used/injected above 1.0.
267
- // Matches storage/corrections.ts:373 — "150% precision" is nonsense.
268
- // null (not NaN) is the explicit zero-denominator case so the dashboard
269
- // can render "—" rather than "NaN%".
270
- const precision = injected > 0 ? Math.min(1, used / injected) : null;
271
- return {
272
- window_days: days,
273
- injected,
274
- used,
275
- precision,
276
- per_source: perSource,
277
- };
278
- }
279
- //# sourceMappingURL=precision.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"precision.js","sourceRoot":"","sources":["../../src/relevance/precision.ts"],"names":[],"mappings":"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"}
@@ -1,60 +0,0 @@
1
- /**
2
- * Promoter — curates the staging buffer into the palace/journal at session
3
- * boundaries (v3.5.0 P-A, spec §4 "Promote", §5).
4
- *
5
- * Flow:
6
- * 1. Read up to N most-recent staged exchanges via `readStaging`.
7
- * 2. Apply a pure-function durability heuristic — `isDurableSignal` — to
8
- * drop chitchat, single-word turns, tool-only exchanges.
9
- * 3. Dedupe survivors against the project's recent journal titles
10
- * (`tooSimilarToExistingJournal`, threshold 0.7).
11
- * 4. Write the survivors via the existing `journalWrite` tool, then clear
12
- * the staging file up to the newest promoted timestamp.
13
- *
14
- * Design notes:
15
- * • The heuristic is intentionally cheap and pure. It is the FIRST pass —
16
- * the in-room model (called separately by `sessionEndReflect`) is the
17
- * true fine-grain judge. Here we just trim the obvious noise.
18
- * • `opts.dryRun` runs the whole pipeline without writing the journal or
19
- * clearing staging — used by tests and the dashboard preview.
20
- * • Threshold ordering inside `isDurableSignal` is high-confidence first
21
- * (explicit markers) then weaker signals (length + lexical proxy)
22
- * (worker done-def rule 3).
23
- */
24
- import { type StagedExchange } from "./stager.js";
25
- export interface PromoteResult {
26
- promoted: number;
27
- skipped: number;
28
- /** Counters keyed by reason for downstream dashboards and tests. */
29
- reasons: Record<string, number>;
30
- }
31
- export interface PromoteOptions {
32
- /** When true, runs the heuristic + dedup but writes nothing. */
33
- dryRun?: boolean;
34
- }
35
- /**
36
- * Decide whether a staged exchange carries a durable signal.
37
- *
38
- * Returns TRUE on any of:
39
- * 1. Explicit marker (`decision`, `bug`, `gotcha`, …).
40
- * 2. Correction shape (`no … wrong`, `actually`, `correction`, `the right way`).
41
- * 3. Contains a wikilink or fenced code block (durable artifact).
42
- * 4. Length ≥ 120 chars AND has both an "important word" and an action verb
43
- * (noun-verb proxy — catches substantive sentences).
44
- *
45
- * Returns FALSE for chitchat ("ok", "thanks"), single-sentence questions,
46
- * and tool-only turns (no user/assistant text).
47
- */
48
- export declare function isDurableSignal(e: StagedExchange): boolean;
49
- /**
50
- * Promote durable staged exchanges into the journal.
51
- *
52
- * Idempotent within a session: once promoted, the corresponding staging
53
- * entries are cleared (only the newest-promoted timestamp is used as the
54
- * `beforeTs` cursor, so any post-promote stage() calls survive).
55
- *
56
- * `opts.dryRun = true` runs the full pipeline (incl. dedup) but writes
57
- * nothing and clears nothing. Useful for tests and dashboard previews.
58
- */
59
- export declare function promote(project: string, opts?: PromoteOptions): Promise<PromoteResult>;
60
- //# sourceMappingURL=promoter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"promoter.d.ts","sourceRoot":"","sources":["../../src/relevance/promoter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAoC5E,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAmB1D;AAqFD;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,CA+JxB"}