@tokenfactory/acc-runner 0.44.0 → 0.44.2

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 (197) hide show
  1. package/README.md +43 -1
  2. package/dist/bin-resolve.d.ts +39 -3
  3. package/dist/bin-resolve.d.ts.map +1 -1
  4. package/dist/bin-resolve.js +176 -12
  5. package/dist/bin-resolve.js.map +1 -1
  6. package/dist/build-fingerprint.d.ts +66 -0
  7. package/dist/build-fingerprint.d.ts.map +1 -0
  8. package/dist/build-fingerprint.js +70 -0
  9. package/dist/build-fingerprint.js.map +1 -0
  10. package/dist/build-info.generated.d.ts +3 -0
  11. package/dist/build-info.generated.d.ts.map +1 -0
  12. package/dist/build-info.generated.js +3 -0
  13. package/dist/build-info.generated.js.map +1 -0
  14. package/dist/capacity/resume-controller.d.ts +5 -3
  15. package/dist/capacity/resume-controller.d.ts.map +1 -1
  16. package/dist/capacity/resume-controller.js +9 -0
  17. package/dist/capacity/resume-controller.js.map +1 -1
  18. package/dist/chat-delegation-guard.d.ts +23 -0
  19. package/dist/chat-delegation-guard.d.ts.map +1 -0
  20. package/dist/chat-delegation-guard.js +62 -0
  21. package/dist/chat-delegation-guard.js.map +1 -0
  22. package/dist/chat-lane.d.ts +17 -6
  23. package/dist/chat-lane.d.ts.map +1 -1
  24. package/dist/chat-lane.js +29 -8
  25. package/dist/chat-lane.js.map +1 -1
  26. package/dist/companion-identity.d.ts +37 -0
  27. package/dist/companion-identity.d.ts.map +1 -1
  28. package/dist/companion-identity.js +98 -29
  29. package/dist/companion-identity.js.map +1 -1
  30. package/dist/companion-run.d.ts +1 -50
  31. package/dist/companion-run.d.ts.map +1 -1
  32. package/dist/companion-run.js +48 -105
  33. package/dist/companion-run.js.map +1 -1
  34. package/dist/config.d.ts +1 -0
  35. package/dist/config.d.ts.map +1 -1
  36. package/dist/config.js +14 -3
  37. package/dist/config.js.map +1 -1
  38. package/dist/conformance.d.ts +49 -0
  39. package/dist/conformance.d.ts.map +1 -0
  40. package/dist/conformance.js +121 -0
  41. package/dist/conformance.js.map +1 -0
  42. package/dist/cost-pricing.d.ts +91 -0
  43. package/dist/cost-pricing.d.ts.map +1 -1
  44. package/dist/cost-pricing.js +115 -1
  45. package/dist/cost-pricing.js.map +1 -1
  46. package/dist/credential-identity.d.ts +70 -0
  47. package/dist/credential-identity.d.ts.map +1 -0
  48. package/dist/credential-identity.js +128 -0
  49. package/dist/credential-identity.js.map +1 -0
  50. package/dist/doctor.d.ts +37 -1
  51. package/dist/doctor.d.ts.map +1 -1
  52. package/dist/doctor.js +300 -41
  53. package/dist/doctor.js.map +1 -1
  54. package/dist/engines/chat-stream.d.ts +71 -1
  55. package/dist/engines/chat-stream.d.ts.map +1 -1
  56. package/dist/engines/chat-stream.js +126 -8
  57. package/dist/engines/chat-stream.js.map +1 -1
  58. package/dist/engines/claude-code-chat.d.ts +11 -1
  59. package/dist/engines/claude-code-chat.d.ts.map +1 -1
  60. package/dist/engines/claude-code-chat.js +69 -5
  61. package/dist/engines/claude-code-chat.js.map +1 -1
  62. package/dist/engines/claude-code.d.ts.map +1 -1
  63. package/dist/engines/claude-code.js +30 -6
  64. package/dist/engines/claude-code.js.map +1 -1
  65. package/dist/engines/codex.d.ts.map +1 -1
  66. package/dist/engines/codex.js +18 -5
  67. package/dist/engines/codex.js.map +1 -1
  68. package/dist/engines/registry.d.ts +26 -0
  69. package/dist/engines/registry.d.ts.map +1 -1
  70. package/dist/engines/registry.js +37 -0
  71. package/dist/engines/registry.js.map +1 -1
  72. package/dist/engines/types.d.ts +5 -0
  73. package/dist/engines/types.d.ts.map +1 -1
  74. package/dist/failure-classifier.d.ts +1 -1
  75. package/dist/failure-classifier.d.ts.map +1 -1
  76. package/dist/failure-classifier.js +65 -12
  77. package/dist/failure-classifier.js.map +1 -1
  78. package/dist/gh.d.ts +15 -0
  79. package/dist/gh.d.ts.map +1 -1
  80. package/dist/gh.js +18 -0
  81. package/dist/gh.js.map +1 -1
  82. package/dist/git.d.ts +6 -0
  83. package/dist/git.d.ts.map +1 -1
  84. package/dist/git.js +27 -1
  85. package/dist/git.js.map +1 -1
  86. package/dist/instance.d.ts +30 -0
  87. package/dist/instance.d.ts.map +1 -0
  88. package/dist/instance.js +51 -0
  89. package/dist/instance.js.map +1 -0
  90. package/dist/keychain.d.ts +20 -7
  91. package/dist/keychain.d.ts.map +1 -1
  92. package/dist/keychain.js +40 -4
  93. package/dist/keychain.js.map +1 -1
  94. package/dist/loc-advisory.d.ts +70 -0
  95. package/dist/loc-advisory.d.ts.map +1 -0
  96. package/dist/loc-advisory.js +196 -0
  97. package/dist/loc-advisory.js.map +1 -0
  98. package/dist/locks/claim-lock-policy.d.ts +67 -0
  99. package/dist/locks/claim-lock-policy.d.ts.map +1 -0
  100. package/dist/locks/claim-lock-policy.js +132 -0
  101. package/dist/locks/claim-lock-policy.js.map +1 -0
  102. package/dist/login.d.ts +63 -2
  103. package/dist/login.d.ts.map +1 -1
  104. package/dist/login.js +93 -8
  105. package/dist/login.js.map +1 -1
  106. package/dist/mcp-spawn.d.ts +54 -0
  107. package/dist/mcp-spawn.d.ts.map +1 -1
  108. package/dist/mcp-spawn.js +88 -4
  109. package/dist/mcp-spawn.js.map +1 -1
  110. package/dist/memory-context.d.ts +106 -0
  111. package/dist/memory-context.d.ts.map +1 -0
  112. package/dist/memory-context.js +220 -0
  113. package/dist/memory-context.js.map +1 -0
  114. package/dist/memory-curation.d.ts +172 -0
  115. package/dist/memory-curation.d.ts.map +1 -0
  116. package/dist/memory-curation.js +277 -0
  117. package/dist/memory-curation.js.map +1 -0
  118. package/dist/migration-seq-guard.d.ts +28 -1
  119. package/dist/migration-seq-guard.d.ts.map +1 -1
  120. package/dist/migration-seq-guard.js +111 -6
  121. package/dist/migration-seq-guard.js.map +1 -1
  122. package/dist/output-diagnostics.d.ts +15 -0
  123. package/dist/output-diagnostics.d.ts.map +1 -0
  124. package/dist/output-diagnostics.js +95 -0
  125. package/dist/output-diagnostics.js.map +1 -0
  126. package/dist/pr-open-guard.d.ts +67 -0
  127. package/dist/pr-open-guard.d.ts.map +1 -0
  128. package/dist/pr-open-guard.js +79 -0
  129. package/dist/pr-open-guard.js.map +1 -0
  130. package/dist/prepr-gate.d.ts +229 -1
  131. package/dist/prepr-gate.d.ts.map +1 -1
  132. package/dist/prepr-gate.js +406 -3
  133. package/dist/prepr-gate.js.map +1 -1
  134. package/dist/program.d.ts.map +1 -1
  135. package/dist/program.js +43 -5
  136. package/dist/program.js.map +1 -1
  137. package/dist/provider-auth.d.ts +27 -0
  138. package/dist/provider-auth.d.ts.map +1 -1
  139. package/dist/provider-auth.js +33 -0
  140. package/dist/provider-auth.js.map +1 -1
  141. package/dist/runtime/cache-dir.d.ts.map +1 -1
  142. package/dist/runtime/cache-dir.js +8 -3
  143. package/dist/runtime/cache-dir.js.map +1 -1
  144. package/dist/runtime/decision-provenance.d.ts +63 -0
  145. package/dist/runtime/decision-provenance.d.ts.map +1 -0
  146. package/dist/runtime/decision-provenance.js +107 -0
  147. package/dist/runtime/decision-provenance.js.map +1 -0
  148. package/dist/runtime/prompt-substitute.d.ts +100 -0
  149. package/dist/runtime/prompt-substitute.d.ts.map +1 -0
  150. package/dist/runtime/prompt-substitute.js +124 -0
  151. package/dist/runtime/prompt-substitute.js.map +1 -0
  152. package/dist/runtime/quarantine.d.ts +11 -0
  153. package/dist/runtime/quarantine.d.ts.map +1 -1
  154. package/dist/runtime/quarantine.js +16 -1
  155. package/dist/runtime/quarantine.js.map +1 -1
  156. package/dist/runtime/review-cost-cap.d.ts +167 -0
  157. package/dist/runtime/review-cost-cap.d.ts.map +1 -0
  158. package/dist/runtime/review-cost-cap.js +182 -0
  159. package/dist/runtime/review-cost-cap.js.map +1 -0
  160. package/dist/runtime/reviewer-abstain.d.ts +101 -0
  161. package/dist/runtime/reviewer-abstain.d.ts.map +1 -0
  162. package/dist/runtime/reviewer-abstain.js +138 -0
  163. package/dist/runtime/reviewer-abstain.js.map +1 -0
  164. package/dist/runtime/reviewer.d.ts +165 -2
  165. package/dist/runtime/reviewer.d.ts.map +1 -1
  166. package/dist/runtime/reviewer.js +752 -111
  167. package/dist/runtime/reviewer.js.map +1 -1
  168. package/dist/runtime/running-build.d.ts +24 -0
  169. package/dist/runtime/running-build.d.ts.map +1 -0
  170. package/dist/runtime/running-build.js +62 -0
  171. package/dist/runtime/running-build.js.map +1 -0
  172. package/dist/runtime/singleton.d.ts.map +1 -1
  173. package/dist/runtime/singleton.js +9 -1
  174. package/dist/runtime/singleton.js.map +1 -1
  175. package/dist/runtime/worktree.d.ts +45 -0
  176. package/dist/runtime/worktree.d.ts.map +1 -1
  177. package/dist/runtime/worktree.js +174 -5
  178. package/dist/runtime/worktree.js.map +1 -1
  179. package/dist/serving-auth/index.d.ts +79 -0
  180. package/dist/serving-auth/index.d.ts.map +1 -0
  181. package/dist/serving-auth/index.js +169 -0
  182. package/dist/serving-auth/index.js.map +1 -0
  183. package/dist/task-runner.d.ts +134 -5
  184. package/dist/task-runner.d.ts.map +1 -1
  185. package/dist/task-runner.js +1255 -129
  186. package/dist/task-runner.js.map +1 -1
  187. package/dist/types.d.ts +8 -0
  188. package/dist/types.d.ts.map +1 -1
  189. package/dist/watch-chat/wire.d.ts +80 -0
  190. package/dist/watch-chat/wire.d.ts.map +1 -1
  191. package/dist/watch-chat/wire.js +203 -43
  192. package/dist/watch-chat/wire.js.map +1 -1
  193. package/dist/watch.d.ts +70 -16
  194. package/dist/watch.d.ts.map +1 -1
  195. package/dist/watch.js +548 -108
  196. package/dist/watch.js.map +1 -1
  197. package/package.json +4 -3
@@ -0,0 +1,220 @@
1
+ /**
2
+ * MEMORY-2 (Curation) — operational memory injection on the TASK/RUNNER path.
3
+ *
4
+ * MEMORY-1 established the read half of the loop here: `renderTaskPrompt` built
5
+ * a prompt from the task row alone, so an agent started every run with no
6
+ * recollection of what earlier runs had learned, and this module closed that.
7
+ * Its four founding properties are UNCHANGED and every one of them is still
8
+ * enforced below:
9
+ *
10
+ * • OPERATIONAL ONLY. `p_data_class` is the module constant {@link OPERATIONAL}
11
+ * at the single RPC call site, and {@link selectOperationalMemories} drops
12
+ * any row that comes back with another class anyway. docs/acc/
13
+ * AGENT_MEMORY_PRIVACY.md attaches GDPR export/erasure duties to
14
+ * `personal_data` and `sensitive`; neither may ever reach a prompt from
15
+ * here, and no argument to any function below could put one there.
16
+ * • BOUNDED. See the budget section.
17
+ * • NO-OP ON EMPTY. No rows, no agent id, nothing relevant, or any error at
18
+ * all ⇒ the empty string, and the prompt is byte-identical to what it was
19
+ * before. An unavailable memory store must never fail a task.
20
+ * • LABELLED. The section says what it is and where it came from, so the
21
+ * agent treats it as prior belief rather than as instruction.
22
+ *
23
+ * ── WHAT MEMORY-2 CHANGES ──────────────────────────────────────────────────
24
+ *
25
+ * MEMORY-1's own docblock named its two compromises, and this is the phase that
26
+ * pays them off.
27
+ *
28
+ * RANKING. "Most relevant" used to mean the RPC's own `is_pinned desc,
29
+ * created_at desc`, because the only other signal `acc.read_agent_memory`
30
+ * offers is a substring ILIKE. It now means the weighted score in
31
+ * ./memory-curation.ts — pinned ≫ recency-decay > confidence > read/merge
32
+ * signal — computed against an INJECTED clock, over a candidate window
33
+ * ({@link MAX_MEMORY_CANDIDATES}) wider than the injection itself, with
34
+ * near-identical rows collapsed. Still no embeddings: `p_query` stays the RPC's
35
+ * ILIKE parameter and nothing here computes or stores a vector.
36
+ *
37
+ * BUDGET. The bound was a row count plus a character cap. It is now a TOKEN
38
+ * budget ({@link MAX_INJECTED_TOKENS}) — the unit the thing being bounded is
39
+ * actually denominated in — with the row count and the character cap retained
40
+ * underneath as belt-and-braces ceilings.
41
+ *
42
+ * RELEVANCE GATE. Injection used to be unconditional: whatever the agent's five
43
+ * most recent notes happened to be, they went into every prompt. A memory now
44
+ * has to share a topical term with the task (or be PINNED, which is an operator
45
+ * saying "this applies regardless") to be injected at all. When nothing
46
+ * qualifies, the section is empty and the prompt is untouched — a task about the
47
+ * webhook no longer carries five notes about the visual-regression suite.
48
+ *
49
+ * When the caller supplies NO task text, the gate is inert and every memory is
50
+ * relevant. That is deliberate: a gate that emptied the injection whenever it
51
+ * had nothing to match against would be a regression wearing a feature's name.
52
+ */
53
+ import { dropNearDuplicates, estimateTokens, isRelevantMemory, rankMemories, relevanceTerms, } from "./memory-curation.js";
54
+ /** The ONLY `acc.memory_data_class` value this module will read. */
55
+ export const OPERATIONAL = "operational";
56
+ /** Hard ceiling on injected rows. */
57
+ export const MAX_INJECTED_MEMORIES = 5;
58
+ /**
59
+ * How many rows to ASK the RPC for. Wider than the injection because ranking,
60
+ * dedup and the relevance gate all run after the fetch: gating a 5-row window
61
+ * would usually leave 0-1 rows, which reads as "memory does nothing".
62
+ */
63
+ export const MAX_MEMORY_CANDIDATES = 30;
64
+ /** Longest single memory rendered; longer bodies are cut with an ellipsis. */
65
+ export const MAX_MEMORY_CHARS = 400;
66
+ /** Longest whole section, in characters. The secondary ceiling under the budget. */
67
+ export const MAX_SECTION_CHARS = 2_000;
68
+ /**
69
+ * The PRIMARY bound: estimated tokens of the rendered section, heading and
70
+ * preamble included. A prompt budget is denominated in tokens, so this is what
71
+ * the cap has to be expressed in; ~500 tokens is a few percent of a task prompt.
72
+ */
73
+ export const MAX_INJECTED_TOKENS = 500;
74
+ /** The heading the section is emitted under — the label the agent reads. */
75
+ export const MEMORY_SECTION_HEADING = "## Prior operational memory (from earlier runs)";
76
+ function intOr0(v) {
77
+ const n = Number(v);
78
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
79
+ }
80
+ /**
81
+ * Keep only genuinely operational rows, rank them, collapse near-identical
82
+ * ones, and bound the count.
83
+ *
84
+ * Pure. Re-applies the class filter the RPC argument already made because this
85
+ * is the last gate before a row reaches a model's context: if the definer RPC
86
+ * ever changes under us, the failure mode must be "nothing is injected", never
87
+ * "a sensitive row is".
88
+ *
89
+ * `nowMs` is a parameter and never `Date.now()` read inline — the ranking is a
90
+ * pure function of (rows, clock), which is what makes it testable without a
91
+ * fixture that expires (the SWEEP-FIX-1 lesson).
92
+ */
93
+ export function selectOperationalMemories(rows, limit = MAX_INJECTED_MEMORIES, nowMs = Date.now()) {
94
+ const list = Array.isArray(rows) ? rows : [];
95
+ const kept = [];
96
+ for (const raw of list) {
97
+ if (!raw || typeof raw !== "object")
98
+ continue;
99
+ const rec = raw;
100
+ if (rec.data_class !== OPERATIONAL)
101
+ continue;
102
+ const content = typeof rec.content === "string" ? rec.content.trim() : "";
103
+ if (content.length === 0)
104
+ continue;
105
+ kept.push({
106
+ id: typeof rec.id === "string" ? rec.id : "",
107
+ data_class: OPERATIONAL,
108
+ content,
109
+ is_pinned: rec.is_pinned === true,
110
+ created_at: typeof rec.created_at === "string" ? rec.created_at : "",
111
+ updated_at: typeof rec.updated_at === "string" ? rec.updated_at : null,
112
+ confidence: typeof rec.confidence === "number" ? rec.confidence : null,
113
+ read_count: intOr0(rec.read_count),
114
+ merge_count: intOr0(rec.merge_count),
115
+ source_task_id: typeof rec.source_task_id === "string" ? rec.source_task_id : null,
116
+ });
117
+ }
118
+ return dropNearDuplicates(rankMemories(kept, nowMs)).slice(0, Math.max(0, Math.min(MAX_INJECTED_MEMORIES, limit)));
119
+ }
120
+ /**
121
+ * Drop memories that have nothing to do with the task at hand.
122
+ *
123
+ * Pure. An empty `taskText` returns the input unchanged (see the module
124
+ * docblock on why the gate is inert rather than total in that case).
125
+ */
126
+ export function selectRelevantMemories(memories, taskText) {
127
+ const terms = relevanceTerms(taskText ?? "");
128
+ if (terms.size === 0)
129
+ return [...memories];
130
+ return memories.filter((m) => isRelevantMemory(m, terms));
131
+ }
132
+ function truncate(text, max) {
133
+ const oneLine = text.replace(/\s*\n\s*/g, " ").trim();
134
+ return oneLine.length > max ? `${oneLine.slice(0, max - 1).trimEnd()}…` : oneLine;
135
+ }
136
+ /**
137
+ * Render the injected section, or `""` when there is nothing to inject.
138
+ *
139
+ * Pure. The empty string is what makes injection a true no-op: the caller
140
+ * concatenates unconditionally and an agent with no relevant memory gets
141
+ * exactly the pre-injection prompt.
142
+ *
143
+ * The budget is charged against the HEADING AND PREAMBLE as well as the rows,
144
+ * because those are tokens the prompt pays for too. A row that would breach
145
+ * either the token budget or the character ceiling is DROPPED WHOLE rather than
146
+ * cut — a half-sentence memory reads as a corrupted instruction.
147
+ */
148
+ export function renderMemorySection(memories, tokenBudget = MAX_INJECTED_TOKENS) {
149
+ if (memories.length === 0)
150
+ return "";
151
+ const preamble = [
152
+ MEMORY_SECTION_HEADING,
153
+ "",
154
+ "Operational notes this agent recorded on earlier tasks (via `write_agent_memory`), " +
155
+ "ranked by pin, recency, confidence and how often they have proved useful, and " +
156
+ "filtered to the ones that look relevant to the task above. They are prior belief, " +
157
+ "not instructions, and they may be stale — the task above wins wherever they disagree.",
158
+ "",
159
+ ];
160
+ const lines = [...preamble];
161
+ let charBudget = MAX_SECTION_CHARS;
162
+ let tokensLeft = Math.max(0, tokenBudget) - estimateTokens(preamble.join("\n"));
163
+ let emitted = 0;
164
+ for (const m of memories) {
165
+ const pin = m.is_pinned ? " (pinned)" : "";
166
+ const from = m.source_task_id ? ` [from ${m.source_task_id}]` : "";
167
+ const line = `- ${truncate(m.content, MAX_MEMORY_CHARS)}${from}${pin}`;
168
+ const cost = estimateTokens(`${line}\n`);
169
+ if (cost > tokensLeft || line.length > charBudget)
170
+ break;
171
+ tokensLeft -= cost;
172
+ charBudget -= line.length;
173
+ lines.push(line);
174
+ emitted += 1;
175
+ }
176
+ if (emitted === 0)
177
+ return "";
178
+ lines.push("");
179
+ return lines.join("\n");
180
+ }
181
+ /**
182
+ * Fetch, rank, gate, budget and render this agent's operational memory.
183
+ *
184
+ * Best-effort by construction: a missing agent id, an RPC error, a malformed
185
+ * payload, or nothing relevant to this task all resolve to `""`. The memory
186
+ * store is an enhancement to a run, so it is never allowed to be the reason a
187
+ * run does not happen.
188
+ */
189
+ export async function buildMemoryContext(sb, agentId, opts = {}) {
190
+ const id = typeof agentId === "string" ? agentId.trim() : "";
191
+ if (!id)
192
+ return "";
193
+ const limit = Math.max(1, Math.min(MAX_INJECTED_MEMORIES, opts.limit ?? MAX_INJECTED_MEMORIES));
194
+ const nowMs = opts.nowMs ?? Date.now();
195
+ try {
196
+ const { data, error } = (await sb.rpc("read_agent_memory", {
197
+ p_agent_id: id,
198
+ // Still no substring filter at the RPC: a task title is not a substring
199
+ // of a memory body, so ILIKE-ing on it would FILTER almost everything out
200
+ // rather than rank it. The relevance gate below does the topical work, in
201
+ // TypeScript, over whole tokens.
202
+ p_query: null,
203
+ // The pin. A literal, never a parameter — this module cannot be asked
204
+ // for any other class.
205
+ p_data_class: OPERATIONAL,
206
+ p_pinned_only: false,
207
+ p_limit: MAX_MEMORY_CANDIDATES,
208
+ p_offset: 0,
209
+ }));
210
+ if (error)
211
+ return "";
212
+ const ranked = selectOperationalMemories(data, MAX_INJECTED_MEMORIES, nowMs);
213
+ const relevant = selectRelevantMemories(ranked, opts.taskText).slice(0, limit);
214
+ return renderMemorySection(relevant, opts.tokenBudget ?? MAX_INJECTED_TOKENS);
215
+ }
216
+ catch {
217
+ return "";
218
+ }
219
+ }
220
+ //# sourceMappingURL=memory-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-context.js","sourceRoot":"","sources":["../src/memory-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * MEMORY-2 (Curation) — the pure ranking / dedup / budget primitives for
3
+ * operational agent memory.
4
+ *
5
+ * ── THIS FILE IS THE MIRROR ────────────────────────────────────────────────
6
+ * The canonical copy is api/_lib/memory-curation.ts. This one exists because
7
+ * the runner is published to npm and builds with `include: ["src/**"]`, so it
8
+ * cannot import out of `api/_lib`. Keep the two byte-compatible: any change
9
+ * here must land in the canonical copy too, and
10
+ * tests/unit/memory2-agent-memory-curation.test.ts imports BOTH and fails if
11
+ * they disagree on any exported constant or on any fixture.
12
+ *
13
+ * MEMORY-1 shipped the loop (write tool, read tool, prompt injection) but no
14
+ * curation: `acc.record_agent_memory` is a plain INSERT, so an agent that
15
+ * learns the same thing on ten tasks writes ten near-identical rows; and both
16
+ * read paths took the RPC's own `is_pinned desc, created_at desc` order, which
17
+ * knows nothing about how confident the agent was or how often the note has
18
+ * actually proved useful. This module is the arithmetic that fixes both halves.
19
+ * It is deliberately ALL PURE — no client, no clock, no I/O — because every
20
+ * caller needs to test it against a fixed clock (the SWEEP-FIX-1 lesson: a
21
+ * suite that reads the real `Date.now()` is a time bomb, not a test).
22
+ *
23
+ * ── MIRRORED, ON PURPOSE ───────────────────────────────────────────────────
24
+ *
25
+ * `packages/acc-runner/src/memory-curation.ts` is a verbatim mirror of this
26
+ * file. The runner is published to npm as `@tokenfactory/acc-runner` and builds
27
+ * from `packages/acc-runner/tsconfig.build.json` with `include: ["src/**"]`, so
28
+ * it CANNOT import out of `api/_lib` — the same constraint that already makes
29
+ * `api/_lib/alerts-git-auth.ts` a documented mirror of
30
+ * `packages/acc-runner/src/git-auth`. The drift guard is a real test, not a
31
+ * comment: tests/unit/memory2-agent-memory-curation.test.ts imports BOTH copies
32
+ * and asserts every exported constant and every function output agrees over a
33
+ * shared fixture corpus. Change one, change the other, or that test fails.
34
+ *
35
+ * A THIRD copy of the normalisation lives in SQL
36
+ * (`acc._normalize_memory_content` / `acc._memory_similarity`, migration 0335),
37
+ * because the write-time dedup has to happen inside the RPC that does the merge.
38
+ * That is why {@link normalizeMemoryContent} uses the ASCII class `[^a-z0-9]+`
39
+ * rather than a Unicode property escape: `[:alnum:]` in Postgres is
40
+ * collation-dependent, and for a dedup KEY, "the two sides disagree on this
41
+ * input" means "sometimes merges, sometimes duplicates". The documented cost is
42
+ * that a body with no ASCII alphanumerics normalises to `""`, which every caller
43
+ * treats as NOT COMPARABLE (never as a match).
44
+ *
45
+ * Nothing here reads or writes a `data_class`. Class enforcement is the pin at
46
+ * the RPC call sites in api/_lib/agent-memory-tools.ts and the row filters in
47
+ * that module and in the runner's memory-context.ts; a scoring function that
48
+ * could not see the class also cannot widen it.
49
+ */
50
+ /**
51
+ * The canonical dedup normalisation: lowercase, every run of non-`[a-z0-9]`
52
+ * collapsed to a single space, trimmed. Mirror of SQL
53
+ * `acc._normalize_memory_content` (0335 §1).
54
+ */
55
+ export declare function normalizeMemoryContent(text: unknown): string;
56
+ /** The DISTINCT normalized tokens of a body. Empty for an uncomparable body. */
57
+ export declare function memoryTokenSet(text: unknown): Set<string>;
58
+ /**
59
+ * Dice coefficient over the distinct normalized token sets: `2|A∩B| / (|A|+|B|)`.
60
+ * Mirror of SQL `acc._memory_similarity` (0335 §2).
61
+ *
62
+ * Returns 0 when either side has no tokens — the "not comparable" rule. 0 can
63
+ * never clear a threshold, so an unnormalisable body is never a duplicate.
64
+ */
65
+ export declare function memorySimilarity(a: unknown, b: unknown): number;
66
+ /** The Dice threshold at which two operational memories count as the same one. */
67
+ export declare const NEAR_DUPLICATE_SIMILARITY = 0.9;
68
+ /**
69
+ * Are these two bodies the SAME memory?
70
+ *
71
+ * Exact normalized equality first — that is the overwhelmingly common duplicate
72
+ * (the same note re-emitted with different capitalisation or punctuation) and it
73
+ * is the case SQL can answer from `content_hash` alone. Then the Dice gate.
74
+ */
75
+ export declare function isNearDuplicate(a: unknown, b: unknown, threshold?: number): boolean;
76
+ /**
77
+ * The signals a memory carries into the ranking. Every field but `content` is
78
+ * optional and nullable, because a row read back through a definer RPC may be
79
+ * missing any of them (and rows written before 0335 have no `updated_at` or
80
+ * `merge_count` at all).
81
+ */
82
+ export interface CurationSignals {
83
+ content: string;
84
+ is_pinned?: boolean | null;
85
+ created_at?: string | null;
86
+ updated_at?: string | null;
87
+ confidence?: number | null;
88
+ read_count?: number | null;
89
+ merge_count?: number | null;
90
+ }
91
+ /** Half-life of the recency term, in days. */
92
+ export declare const RECENCY_HALF_LIFE_DAYS = 14;
93
+ /**
94
+ * Component weights. They are SEPARATED BY AN ORDER OF MAGNITUDE on purpose,
95
+ * which is what makes one weighted sum express the priority the task asks for
96
+ * — pinned, then recency, then confidence, then the read/merge signal. Each
97
+ * component is normalised into [0,1] first, so `W_PINNED` (1000) exceeds the
98
+ * largest possible sum of the other three (111): a pinned memory is ALWAYS
99
+ * ranked above an unpinned one, never merely usually.
100
+ */
101
+ export declare const W_PINNED = 1000;
102
+ export declare const W_RECENCY = 100;
103
+ export declare const W_CONFIDENCE = 10;
104
+ export declare const W_READ = 1;
105
+ /** Read+merge count at which the usefulness signal is considered saturated. */
106
+ export declare const READ_SIGNAL_SATURATION = 20;
107
+ /**
108
+ * When this memory was last ASSERTED: `updated_at` when a merge refreshed it,
109
+ * else `created_at`. `0` for a row with no parseable timestamp, which scores as
110
+ * maximally stale rather than as "now".
111
+ */
112
+ export declare function memoryTimestampMs(m: CurationSignals): number;
113
+ /** Exponential recency decay in (0,1]. `nowMs` is always injected — never read. */
114
+ export declare function recencyDecay(m: CurationSignals, nowMs: number): number;
115
+ /** Log-saturating usefulness signal in [0,1] over `read_count + merge_count`. */
116
+ export declare function readSignal(m: CurationSignals): number;
117
+ /** The weighted relevance score. Higher ranks first. */
118
+ export declare function memoryScore(m: CurationSignals, nowMs: number): number;
119
+ /**
120
+ * Rank a batch, highest score first.
121
+ *
122
+ * The tie-breaks are the point of the `sort` comparator, not an afterthought:
123
+ * newest-first, then content order. Without them, two memories whose recency
124
+ * terms have both decayed to ~0 would compare equal and the resulting order
125
+ * would depend on `nowMs` and on input order — exactly the drift that makes a
126
+ * suite pass in August and fail in September. With them the order is TOTAL and
127
+ * the ranking is a pure function of the rows plus the injected clock.
128
+ */
129
+ export declare function rankMemories<T extends CurationSignals>(rows: readonly T[], nowMs: number): T[];
130
+ /**
131
+ * Collapse near-identical hits, keeping the FIRST occurrence of each cluster.
132
+ *
133
+ * Call it on an already-ranked list: "first" then means "the highest-scoring
134
+ * member of the cluster survives". Read-time dedup is needed even with
135
+ * write-time dedup in place, because rows written before 0335, rows written by
136
+ * the Memory tab, and rows belonging to two different agents in an org fan-out
137
+ * were never routed through the merging RPC.
138
+ *
139
+ * O(n²) against the KEPT list only, and every caller bounds n at <= 50.
140
+ */
141
+ export declare function dropNearDuplicates<T extends CurationSignals>(ranked: readonly T[], threshold?: number): T[];
142
+ /** Characters per token for the budget estimate. */
143
+ export declare const CHARS_PER_TOKEN = 4;
144
+ /**
145
+ * Estimated tokens in a string.
146
+ *
147
+ * A deliberate over-approximation of a real tokeniser: the runner must not ship
148
+ * a tokenizer dependency, and a budget that guesses HIGH spends less of the
149
+ * prompt than it promised, which is the safe direction to be wrong in.
150
+ */
151
+ export declare function estimateTokens(text: string): number;
152
+ /** Shortest token that can carry topical signal in the relevance gate. */
153
+ export declare const RELEVANCE_MIN_TERM_CHARS = 4;
154
+ /**
155
+ * The topical terms of a task (or a query): normalized tokens of at least
156
+ * {@link RELEVANCE_MIN_TERM_CHARS} characters that are not stopwords.
157
+ *
158
+ * An empty set means "no task context supplied", and every caller treats that
159
+ * as "everything is relevant" rather than as "nothing is" — a gate that
160
+ * silently emptied the injection whenever the caller had no query would be a
161
+ * regression dressed as a feature.
162
+ */
163
+ export declare function relevanceTerms(text: unknown): Set<string>;
164
+ /**
165
+ * Is this memory relevant to the current task?
166
+ *
167
+ * Pinned memories are ALWAYS relevant: an operator pinned the row precisely to
168
+ * say "this applies regardless of what the agent happens to be doing", and the
169
+ * gate must not override that.
170
+ */
171
+ export declare function isRelevantMemory(m: CurationSignals, terms: ReadonlySet<string>): boolean;
172
+ //# sourceMappingURL=memory-curation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-curation.d.ts","sourceRoot":"","sources":["../src/memory-curation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAMH;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAG5D;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAIzD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAO/D;AAED,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,CAAC,EAAE,OAAO,EACV,CAAC,EAAE,OAAO,EACV,SAAS,GAAE,MAAkC,GAC5C,OAAO,CAMT;AAMD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,8CAA8C;AAC9C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,OAAQ,CAAC;AAC9B,eAAO,MAAM,SAAS,MAAM,CAAC;AAC7B,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,MAAM,IAAI,CAAC;AACxB,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAUzC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,CAO5D;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,CAOrD;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAQ9F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,eAAe,EAC1D,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,SAAS,GAAE,MAAkC,GAC5C,CAAC,EAAE,CAOL;AAMD,oDAAoD;AACpD,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAgB1C;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAQzD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAKxF"}