@miller-tech/uap 1.175.13 → 1.178.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/benchmarks/harness-card.d.ts +86 -0
  3. package/dist/benchmarks/harness-card.d.ts.map +1 -0
  4. package/dist/benchmarks/harness-card.js +153 -0
  5. package/dist/benchmarks/harness-card.js.map +1 -0
  6. package/dist/benchmarks/paired/report.d.ts +15 -0
  7. package/dist/benchmarks/paired/report.d.ts.map +1 -1
  8. package/dist/benchmarks/paired/report.js +12 -0
  9. package/dist/benchmarks/paired/report.js.map +1 -1
  10. package/dist/benchmarks/paired/types.d.ts +1 -1
  11. package/dist/bin/cli.js +27 -0
  12. package/dist/bin/cli.js.map +1 -1
  13. package/dist/cli/bench.d.ts.map +1 -1
  14. package/dist/cli/bench.js +64 -3
  15. package/dist/cli/bench.js.map +1 -1
  16. package/dist/cli/harness.d.ts +3 -2
  17. package/dist/cli/harness.d.ts.map +1 -1
  18. package/dist/cli/harness.js +81 -0
  19. package/dist/cli/harness.js.map +1 -1
  20. package/dist/cli/memory.d.ts +7 -1
  21. package/dist/cli/memory.d.ts.map +1 -1
  22. package/dist/cli/memory.js +165 -0
  23. package/dist/cli/memory.js.map +1 -1
  24. package/dist/delivery/agentic-executor.d.ts +76 -2
  25. package/dist/delivery/agentic-executor.d.ts.map +1 -1
  26. package/dist/delivery/agentic-executor.js +231 -29
  27. package/dist/delivery/agentic-executor.js.map +1 -1
  28. package/dist/delivery/edit-match.d.ts +134 -0
  29. package/dist/delivery/edit-match.d.ts.map +1 -0
  30. package/dist/delivery/edit-match.js +331 -0
  31. package/dist/delivery/edit-match.js.map +1 -0
  32. package/dist/memory/dynamic-retrieval.d.ts.map +1 -1
  33. package/dist/memory/dynamic-retrieval.js +57 -0
  34. package/dist/memory/dynamic-retrieval.js.map +1 -1
  35. package/dist/memory/reconstruct-ingest.d.ts +88 -0
  36. package/dist/memory/reconstruct-ingest.d.ts.map +1 -0
  37. package/dist/memory/reconstruct-ingest.js +165 -0
  38. package/dist/memory/reconstruct-ingest.js.map +1 -0
  39. package/dist/memory/reconstruct-store.d.ts +143 -0
  40. package/dist/memory/reconstruct-store.d.ts.map +1 -0
  41. package/dist/memory/reconstruct-store.js +312 -0
  42. package/dist/memory/reconstruct-store.js.map +1 -0
  43. package/dist/memory/reconstruct.d.ts +272 -0
  44. package/dist/memory/reconstruct.d.ts.map +1 -0
  45. package/dist/memory/reconstruct.js +552 -0
  46. package/dist/memory/reconstruct.js.map +1 -0
  47. package/dist/policies/schemas/policy.d.ts +2 -2
  48. package/dist/self-harness/evidence-proposer.d.ts +58 -0
  49. package/dist/self-harness/evidence-proposer.d.ts.map +1 -0
  50. package/dist/self-harness/evidence-proposer.js +132 -0
  51. package/dist/self-harness/evidence-proposer.js.map +1 -0
  52. package/dist/self-harness/manifest.d.ts +130 -0
  53. package/dist/self-harness/manifest.d.ts.map +1 -0
  54. package/dist/self-harness/manifest.js +247 -0
  55. package/dist/self-harness/manifest.js.map +1 -0
  56. package/dist/self-harness/mods.d.ts +57 -3
  57. package/dist/self-harness/mods.d.ts.map +1 -1
  58. package/dist/self-harness/mods.js +72 -0
  59. package/dist/self-harness/mods.js.map +1 -1
  60. package/dist/self-harness/orchestrator.d.ts +27 -0
  61. package/dist/self-harness/orchestrator.d.ts.map +1 -1
  62. package/dist/self-harness/orchestrator.js +47 -4
  63. package/dist/self-harness/orchestrator.js.map +1 -1
  64. package/dist/self-harness/pending.d.ts +17 -3
  65. package/dist/self-harness/pending.d.ts.map +1 -1
  66. package/dist/self-harness/pending.js +26 -4
  67. package/dist/self-harness/pending.js.map +1 -1
  68. package/dist/self-harness/profile.d.ts +17 -1
  69. package/dist/self-harness/profile.d.ts.map +1 -1
  70. package/dist/self-harness/profile.js +11 -4
  71. package/dist/self-harness/profile.js.map +1 -1
  72. package/dist/self-harness/run.d.ts +19 -0
  73. package/dist/self-harness/run.d.ts.map +1 -1
  74. package/dist/self-harness/run.js +43 -4
  75. package/dist/self-harness/run.js.map +1 -1
  76. package/dist/self-harness/transfer.d.ts.map +1 -1
  77. package/dist/self-harness/transfer.js +2 -0
  78. package/dist/self-harness/transfer.js.map +1 -1
  79. package/dist/self-harness/validate.d.ts +17 -6
  80. package/dist/self-harness/validate.d.ts.map +1 -1
  81. package/dist/self-harness/validate.js +73 -8
  82. package/dist/self-harness/validate.js.map +1 -1
  83. package/dist/telemetry/tool-calls.d.ts +82 -0
  84. package/dist/telemetry/tool-calls.d.ts.map +1 -0
  85. package/dist/telemetry/tool-calls.js +280 -0
  86. package/dist/telemetry/tool-calls.js.map +1 -0
  87. package/dist/telemetry/tool-failure.d.ts +71 -0
  88. package/dist/telemetry/tool-failure.d.ts.map +1 -0
  89. package/dist/telemetry/tool-failure.js +123 -0
  90. package/dist/telemetry/tool-failure.js.map +1 -0
  91. package/docs/plans/harness-engineering-uplift-2026-07-31.md +280 -0
  92. package/package.json +1 -1
  93. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  94. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  95. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Wiring active reconstruction to UAP's real memory stores (harness plan E3).
3
+ *
4
+ * Resolves where the graph lives, fills it from the stores UAP already writes
5
+ * (short-term SQLite AND the long-term semantic store), and exposes the entry
6
+ * point callers use: `recallActive`.
7
+ *
8
+ * The graph is a DERIVED index, never a source of truth: it can be deleted and
9
+ * rebuilt at any time. (It is not side-effect free, though — opening the
10
+ * short-term store runs `ensureShortTermSchema`, which creates indexes and can
11
+ * backfill FTS. That means a build needs a writable store.)
12
+ *
13
+ * COVERAGE IS THE CORRECTNESS PROPERTY HERE. The passive path queries short-term
14
+ * FTS *and* the long-term semantic store. If active recall indexed only the
15
+ * short-term store — a rolling ~50-entry window — then routing a query here
16
+ * would silently drop every durable memory the project has, which is a
17
+ * regression wearing a feature's clothes. So ingestion covers both tiers, and
18
+ * `recallActive` reports what it covered.
19
+ */
20
+ import { existsSync } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { loadUapConfig } from '../utils/config-loader.js';
23
+ import { MemoryGraph, reconstruct, heuristicPolicy, activeReconstructionEnabled, } from './reconstruct.js';
24
+ import { ingestItems, itemKey } from './reconstruct-ingest.js';
25
+ /** Where the derived graph lives, alongside the stores it indexes. */
26
+ export function memoryGraphPath(cwd) {
27
+ return join(cwd, 'agents', 'data', 'memory', 'memory-graph.db');
28
+ }
29
+ /**
30
+ * Resolve short-term store + project id the way `uap memory query` does.
31
+ *
32
+ * Reading these from the config rather than hardcoding defaults matters: a
33
+ * project with a configured store path, or any project not literally named
34
+ * "project", was otherwise indexing zero rows while reporting success — because
35
+ * `getRecent` filters on `project_id`.
36
+ */
37
+ export function resolveStoreConfig(cwd, opts = {}) {
38
+ const config = loadUapConfig(cwd);
39
+ return {
40
+ shortTermPath: opts.shortTermPath ||
41
+ config?.memory?.shortTerm?.path ||
42
+ join(cwd, 'agents', 'data', 'memory', 'short_term.db'),
43
+ projectId: opts.projectId ?? config?.project?.name ?? 'project',
44
+ };
45
+ }
46
+ export function openMemoryGraph(cwd) {
47
+ return new MemoryGraph(memoryGraphPath(cwd));
48
+ }
49
+ export function memoryGraphExists(cwd) {
50
+ return existsSync(memoryGraphPath(cwd));
51
+ }
52
+ /**
53
+ * Read UAP's short-term store into `IngestItem`s.
54
+ *
55
+ * Isolated and best-effort: a missing or unreadable store yields an empty list
56
+ * rather than failing the build, because the graph is derived and a partial
57
+ * index is more useful than none.
58
+ */
59
+ export async function itemsFromShortTerm(cwd, opts = {}) {
60
+ const { shortTermPath: dbPath, projectId } = resolveStoreConfig(cwd, opts);
61
+ if (!existsSync(dbPath))
62
+ return [];
63
+ const { SQLiteShortTermMemory } = await import('./short-term/sqlite.js');
64
+ let store = null;
65
+ try {
66
+ store = new SQLiteShortTermMemory({
67
+ dbPath,
68
+ projectId,
69
+ maxEntries: opts.limit ?? 2000,
70
+ });
71
+ const rows = (await store.getRecent(opts.limit ?? 2000)) ?? [];
72
+ return rows.map((r) => ({
73
+ id: `st:${r.id ?? itemKey({ text: r.content })}`,
74
+ text: r.content,
75
+ type: r.type,
76
+ occurredAt: r.timestamp,
77
+ }));
78
+ }
79
+ catch {
80
+ return [];
81
+ }
82
+ finally {
83
+ // A throw in getRecent used to skip close(), leaking the handle (plus WAL and
84
+ // SHM refs) once per query, since recall refreshes on every call.
85
+ try {
86
+ await store?.close();
87
+ }
88
+ catch {
89
+ /* ignore */
90
+ }
91
+ }
92
+ }
93
+ /**
94
+ * Read the LONG-TERM semantic store into ingest items.
95
+ *
96
+ * This tier holds everything durable — `memory store`, `sync-files`,
97
+ * `prepopulate`. Omitting it would make active recall a strict downgrade from
98
+ * the passive path it replaces. Best-effort: an unreachable Qdrant yields [] and
99
+ * the caller reports reduced coverage rather than failing.
100
+ */
101
+ export async function itemsFromLongTerm(cwd, limit = 2000) {
102
+ try {
103
+ const config = loadUapConfig(cwd);
104
+ const endpoint = config?.memory?.longTerm?.endpoint || 'localhost:6333';
105
+ const url = /^https?:\/\//.test(endpoint) ? endpoint : `http://${endpoint}`;
106
+ const collection = config?.memory?.longTerm?.collection || 'agent_memory';
107
+ const apiKey = config?.memory?.longTerm?.qdrantCloud?.apiKey || process.env.QDRANT_API_KEY;
108
+ const { getQdrantClientClass } = await import('../utils/lazy-imports.js');
109
+ const QdrantClientClass = await getQdrantClientClass();
110
+ // The client defaults to a 300_000ms timeout. On the AGENT path this call
111
+ // is awaited during context assembly, so a black-holed endpoint (firewall
112
+ // drop, not a fast ECONNREFUSED) would block a model turn for five minutes.
113
+ const timeout = Number(process.env.UAP_MEMORY_QDRANT_TIMEOUT_MS) || 3000;
114
+ const client = new QdrantClientClass({ url, apiKey, checkCompatibility: false, timeout });
115
+ const collections = await client.getCollections();
116
+ const names = [collection, `${collection}_prepopulated`].filter((c) => collections.collections.some((col) => col.name === c));
117
+ const items = [];
118
+ for (const name of names) {
119
+ // Scroll the payloads only — the graph indexes text, not vectors.
120
+ let offset = undefined;
121
+ while (items.length < limit) {
122
+ const page = await client.scroll(name, {
123
+ limit: Math.min(256, limit - items.length),
124
+ with_payload: true,
125
+ with_vector: false,
126
+ offset,
127
+ });
128
+ for (const point of page.points ?? []) {
129
+ const payload = (point.payload ?? {});
130
+ const text = String(payload.content ?? '');
131
+ if (!text)
132
+ continue;
133
+ items.push({
134
+ id: `lt:${name}:${String(point.id)}`,
135
+ text,
136
+ type: String(payload.type ?? 'knowledge'),
137
+ tags: Array.isArray(payload.tags) ? payload.tags : undefined,
138
+ occurredAt: typeof payload.timestamp === 'string' ? payload.timestamp : undefined,
139
+ });
140
+ }
141
+ offset = page.next_page_offset;
142
+ if (!offset)
143
+ break;
144
+ }
145
+ }
146
+ return items;
147
+ }
148
+ catch {
149
+ return [];
150
+ }
151
+ }
152
+ /**
153
+ * Build or refresh the graph from the stores.
154
+ *
155
+ * Incremental by default: source keys already ingested are skipped, so this is
156
+ * cheap to re-run and safe to call before a query.
157
+ */
158
+ export async function buildMemoryGraph(cwd, opts = {}) {
159
+ const graph = openMemoryGraph(cwd);
160
+ try {
161
+ if (!graph.acquireBuildLock(Date.now())) {
162
+ // Another process is building. Duplicating that work would insert every
163
+ // item a second time under fresh ids — permanent, since the ledger then
164
+ // reports them indexed.
165
+ return {
166
+ ingested: 0, skipped: 0, storedKeys: [], cues: 0, tags: 0, bridgingTags: 0,
167
+ considered: 0, graphPath: memoryGraphPath(cwd),
168
+ coverage: { shortTerm: 0, longTerm: 0 },
169
+ skippedConcurrentBuild: true,
170
+ };
171
+ }
172
+ const shortTerm = await itemsFromShortTerm(cwd, opts);
173
+ const longTerm = opts.includeLongTerm === false ? [] : await itemsFromLongTerm(cwd, opts.limit);
174
+ const items = [...shortTerm, ...longTerm, ...(opts.extra ?? [])];
175
+ if (opts.rebuild) {
176
+ // A real rebuild TRUNCATES. Clearing only the in-memory dedupe set left
177
+ // every row in place and re-inserted the whole corpus under fresh ids, so
178
+ // two rebuilds meant every memory twice — permanently, since the ledger
179
+ // then reported them as already indexed.
180
+ graph.clear();
181
+ }
182
+ const seen = opts.rebuild ? new Set() : graph.ingestedKeys();
183
+ const result = ingestItems(graph, items, { seen });
184
+ // Mark ONLY what was stored — see IngestResult.storedKeys.
185
+ graph.markIngested(result.storedKeys);
186
+ // Heartbeat REGARDLESS of whether anything was stored. Deriving staleness
187
+ // from stored keys means a refresh that finds nothing new never advances the
188
+ // clock, so the TTL never clears and the index rebuilds every retrieval.
189
+ graph.markRefreshed(new Date().toISOString());
190
+ return {
191
+ ...result,
192
+ considered: items.length,
193
+ graphPath: memoryGraphPath(cwd),
194
+ coverage: { shortTerm: shortTerm.length, longTerm: longTerm.length },
195
+ };
196
+ }
197
+ finally {
198
+ graph.releaseBuildLock();
199
+ graph.close();
200
+ }
201
+ }
202
+ /**
203
+ * Recall by ACTIVE RECONSTRUCTION: traverse the graph while reasoning, pruning
204
+ * weak paths before they cost context, instead of one passive top-k pull.
205
+ *
206
+ * This is the caller area E was missing. It is invoked by `uap memory query
207
+ * --active` and by anything that opts in; passive retrieval remains the default
208
+ * until the paired bench measures the lift on our own suite.
209
+ */
210
+ export async function recallActive(cwd, query, opts = {}) {
211
+ const build = (await shouldRefresh(cwd, opts))
212
+ ? await buildMemoryGraph(cwd, opts.buildOptions)
213
+ : undefined;
214
+ const graph = openMemoryGraph(cwd);
215
+ try {
216
+ if (graph.isEmpty()) {
217
+ return {
218
+ context: [],
219
+ steps: [],
220
+ converged: false,
221
+ stopReason: 'exhausted',
222
+ graphEmpty: true,
223
+ build,
224
+ };
225
+ }
226
+ const result = reconstruct(graph, query, {
227
+ policy: opts.policy ?? heuristicPolicy(),
228
+ maxSteps: opts.maxSteps,
229
+ maxContext: opts.maxContext,
230
+ });
231
+ return { ...result, graphEmpty: false, build };
232
+ }
233
+ finally {
234
+ graph.close();
235
+ }
236
+ }
237
+ /** Decide whether this recall should rebuild the index first. */
238
+ async function shouldRefresh(cwd, opts) {
239
+ if (opts.refresh === false)
240
+ return false;
241
+ if (opts.refresh !== 'if-stale')
242
+ return true;
243
+ if (!memoryGraphExists(cwd))
244
+ return true;
245
+ const graph = openMemoryGraph(cwd);
246
+ try {
247
+ const last = graph.lastRefreshedAt() ?? graph.lastIngestedAt();
248
+ if (!last)
249
+ return true;
250
+ // SQLite datetime('now') is UTC without a zone marker; parse it as such.
251
+ const lastMs = Date.parse(last.endsWith('Z') ? last : `${last.replace(' ', 'T')}Z`);
252
+ if (!Number.isFinite(lastMs))
253
+ return true;
254
+ const ttlMs = (opts.staleAfterSeconds ?? 900) * 1000;
255
+ return Date.now() - lastMs > ttlMs;
256
+ }
257
+ catch {
258
+ return false;
259
+ }
260
+ finally {
261
+ graph.close();
262
+ }
263
+ }
264
+ /**
265
+ * Should a caller use active reconstruction?
266
+ *
267
+ * Both conditions must hold: the operator opted in AND the graph actually has
268
+ * content. Routing to an empty graph would silently return nothing where
269
+ * passive retrieval would have answered — a regression dressed as a feature.
270
+ */
271
+ export function shouldUseActiveRecall(cwd, graph) {
272
+ if (!activeReconstructionEnabled())
273
+ return false;
274
+ if (!memoryGraphExists(cwd))
275
+ return false;
276
+ if (graph) {
277
+ try {
278
+ return !graph.isEmpty();
279
+ }
280
+ catch {
281
+ return false;
282
+ }
283
+ }
284
+ const owned = openMemoryGraph(cwd);
285
+ const graphRef = owned;
286
+ try {
287
+ // Cheap probe, not stats(): this runs on EVERY `uap memory query` and every
288
+ // harness-card render, and stats() is five aggregates over the triples table.
289
+ return !graphRef.isEmpty();
290
+ }
291
+ catch {
292
+ return false;
293
+ }
294
+ finally {
295
+ owned.close();
296
+ }
297
+ }
298
+ /**
299
+ * The retrieval mode actually in force, for the harness disclosure card.
300
+ *
301
+ * One implementation so the bench card and `uap harness card` cannot disagree —
302
+ * two call sites computing this independently is how a card starts lying.
303
+ */
304
+ export function describeMemoryMode(cwd) {
305
+ try {
306
+ return shouldUseActiveRecall(cwd) ? 'active reconstruction' : 'semantic retrieval';
307
+ }
308
+ catch {
309
+ return 'semantic retrieval';
310
+ }
311
+ }
312
+ //# sourceMappingURL=reconstruct-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconstruct-store.js","sourceRoot":"","sources":["../../src/memory/reconstruct-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Active memory reconstruction over a Cue–Tag–Content graph
3
+ * (harness plan area E, 2026-07-31).
4
+ *
5
+ * UAP's memory retrieval is passive: embed the query, pull the top-k, reason
6
+ * once. "Memory is Reconstructed, Not Retrieved" (arXiv 2606.06036) shows that
7
+ * paradigm is strictly less expressive than letting the model traverse memory
8
+ * WHILE it reasons — it proves active policies solve a binary-tree
9
+ * needle-in-a-haystack with zero error where passive policies need an
10
+ * exponential budget — and measures the practical gap at up to +23% on LoCoMo
11
+ * with 118k tokens per query against A-Mem's 632k and LangMem's 3.26M.
12
+ *
13
+ * THE TAG LAYER IS THE CONTRIBUTION. Their ablation: cue -> content direct
14
+ * indexing recalls ~65%; cue -> TAG -> content with multi-turn reasoning recalls
15
+ * ~90%. A "graph memory" that skips the associative tag bridge gets none of the
16
+ * benefit, so the schema here makes tags mandatory rather than an optimisation.
17
+ *
18
+ * Off by default. The literature's numbers are theirs, not ours: this ships
19
+ * behind `UAP_MEMORY_ACTIVE=1` until `uap bench paired` measures the lift on our
20
+ * own suite (harness plan constraint 3).
21
+ */
22
+ /** Which memory layer a content node lives in (MRAgent's three granularities). */
23
+ export type MemoryLayer =
24
+ /** Event-specific, temporally ordered. */
25
+ 'episodic'
26
+ /** Stable facts: preferences, attributes, decisions. */
27
+ | 'semantic'
28
+ /** Topic nodes summarising recurring patterns — the top-down entry point. */
29
+ | 'abstraction';
30
+ export interface ContentNode {
31
+ id: number;
32
+ layer: MemoryLayer;
33
+ text: string;
34
+ /** ISO timestamp of the source episode, when known. */
35
+ occurredAt?: string;
36
+ }
37
+ /** One (cue, tag, content) triple — the graph's only edge type. */
38
+ export interface Triple {
39
+ cue: string;
40
+ tag: string;
41
+ contentId: number;
42
+ }
43
+ export interface ReconstructionStep {
44
+ /** 1-based step index. */
45
+ step: number;
46
+ /** Cues the model chose to expand this step. */
47
+ expandedCues: string[];
48
+ /** Tags reached from those cues. */
49
+ tags: string[];
50
+ /** Content ids admitted into the reconstructed context. */
51
+ kept: number[];
52
+ /** Content ids reached but judged IRRELEVANT. */
53
+ pruned: number[];
54
+ /**
55
+ * Content ids the policy kept but that did not fit the context budget.
56
+ * Separate from `pruned`: "judged irrelevant" and "budget full" are different
57
+ * outcomes and want different remedies.
58
+ */
59
+ dropped: number[];
60
+ /** Whether the model declared the evidence sufficient after this step. */
61
+ sufficient: boolean;
62
+ }
63
+ export interface ReconstructionResult {
64
+ /** Content, in the order it was admitted — this is what goes to the model. */
65
+ context: ContentNode[];
66
+ steps: ReconstructionStep[];
67
+ /** True when the loop stopped because evidence sufficed, not because it ran out of steps. */
68
+ converged: boolean;
69
+ /** Why the traversal stopped, so callers can give accurate advice. */
70
+ stopReason: 'sufficient' | 'context-full' | 'exhausted' | 'step-budget';
71
+ }
72
+ /**
73
+ * The reasoning seam. Injected so the traversal policy is testable without a
74
+ * model, and so the same graph can be driven by a local or a frontier model.
75
+ */
76
+ export interface ReconstructionPolicy {
77
+ /**
78
+ * Choose which of the currently-active cues to expand next. Returning [] ends
79
+ * the traversal.
80
+ */
81
+ selectCues(query: string, activeCues: string[], context: ContentNode[]): string[];
82
+ /**
83
+ * Semantic routing: which reached contents are worth keeping, and is the
84
+ * accumulated evidence now enough to answer?
85
+ *
86
+ * `hops` carries how each candidate was reached. A router that ignores it can
87
+ * only judge lexical similarity to the query — and then the tag bridge, which
88
+ * is the whole point of the structure, buys nothing: the traversal reaches the
89
+ * associated memory and the router throws it away for sharing no words with
90
+ * the question.
91
+ */
92
+ route(query: string, candidates: ContentNode[], context: ContentNode[], hops?: HopContext): RouteDecision;
93
+ }
94
+ export interface RouteDecision {
95
+ keep: number[];
96
+ sufficient: boolean;
97
+ /**
98
+ * Candidates declined ONLY because a per-step cap was reached, not on the
99
+ * merits. The traversal keeps these reachable by a later, stronger bridge
100
+ * instead of blacklisting them like a genuine rejection.
101
+ */
102
+ deferred?: number[];
103
+ }
104
+ /** How the traversal reached this step's candidates. */
105
+ export interface HopContext {
106
+ /** Candidate id -> the tags it was reached through. */
107
+ tagsFor: Map<number, string[]>;
108
+ /**
109
+ * Tags that have produced admitted evidence in ANY prior step — accumulated,
110
+ * not per-step. A bridge proves itself once; requiring it to re-prove itself
111
+ * every step is what stops a second hop from ever landing, since by
112
+ * definition the far side of a bridge does not resemble the query.
113
+ */
114
+ productiveTags: ReadonlySet<string>;
115
+ /**
116
+ * How many contents each tag links. Specificity is the honest discriminator
117
+ * for an associative admission: a tag on 3 memories asserts a real relation, a
118
+ * tag on 300 asserts almost nothing. Lexical overlap cannot serve here — the
119
+ * far side of a bridge shares no words with the query by construction.
120
+ */
121
+ tagSize: (tag: string) => number;
122
+ }
123
+ /**
124
+ * Zero-LLM policy: lexical overlap for routing, breadth-first for expansion.
125
+ *
126
+ * Not a toy — it is the honest default. An active traversal driven by a cheap
127
+ * heuristic is still active (it prunes on accumulated evidence, which is the
128
+ * mechanism the paper isolates); wiring an LLM in raises the ceiling but is not
129
+ * required for the structure to pay off, and a deterministic policy is what
130
+ * makes the loop unit-testable.
131
+ */
132
+ export declare function heuristicPolicy(opts?: {
133
+ keepThreshold?: number;
134
+ sufficientAt?: number;
135
+ maxExpandPerStep?: number;
136
+ /** Max tag-bridged admissions per step. 0 disables associative recall. */
137
+ maxAssociativePerStep?: number;
138
+ /**
139
+ * A tag linking more contents than this is too broad to justify admitting a
140
+ * candidate that has no lexical relation to the query at all.
141
+ */
142
+ maxBridgeTagSize?: number;
143
+ }): ReconstructionPolicy;
144
+ /**
145
+ * The Cue–Tag–Content graph.
146
+ *
147
+ * Its own SQLite file rather than a table in the semantic store: the traversal
148
+ * is a different access pattern (many small keyed hops, no vector math) and
149
+ * keeping it separate means enabling the feature cannot slow the existing
150
+ * retrieval path.
151
+ */
152
+ export declare class MemoryGraph {
153
+ private db;
154
+ constructor(dbPath: string);
155
+ /**
156
+ * Add one memory item and its (cue, tag) index entries.
157
+ *
158
+ * Tags are REQUIRED: an item indexed by cue alone is the ~65%-recall
159
+ * configuration the paper ablates away. Callers with no tags should supply a
160
+ * coarse one (the layer name) rather than none.
161
+ */
162
+ addContent(params: {
163
+ layer: MemoryLayer;
164
+ text: string;
165
+ occurredAt?: string;
166
+ cues: string[];
167
+ tags: string[];
168
+ }): number;
169
+ /** φ_{c→g}: the associative tags a cue activates. */
170
+ tagsForCue(cue: string): string[];
171
+ /** φ_{(c,g)→v}: contents reachable from a cue THROUGH a specific tag. */
172
+ contentsFor(cue: string, tag: string): ContentNode[];
173
+ /**
174
+ * Tags too broad to be bridges: attached to >= 60% of all content. Reuses the
175
+ * discriminativeness rule `stats()` already applies, because a tag that links
176
+ * everything relates nothing — and on the short-term tier EVERY item is tagged
177
+ * with one of ~6 type values, so without this the "bridge" is the whole store.
178
+ */
179
+ hubTags(): Set<string>;
180
+ private tagSizeCache;
181
+ /** How many distinct contents a tag links. Cached — hot in the route loop. */
182
+ tagSize(tag: string): number;
183
+ /** Cues that co-occur with a tag — how traversal discovers NEW clues. */
184
+ cuesForTag(tag: string): string[];
185
+ /** Source keys already ingested, for incremental rebuilds. */
186
+ ingestedKeys(): Set<string>;
187
+ /** Record that a refresh COMPLETED, whether or not it stored anything. */
188
+ markRefreshed(nowIso: string): void;
189
+ /** ISO timestamp of the last completed refresh, or null if never refreshed. */
190
+ lastRefreshedAt(): string | null;
191
+ /**
192
+ * Best-effort single-flight guard around a build.
193
+ *
194
+ * Two agents retrieving at once both see a stale graph, both build, and both
195
+ * insert the same items under fresh ids — permanent duplicates, since the
196
+ * ledger then reports them indexed. Returns false when another build holds the
197
+ * lock; a lock older than `staleMs` is taken over so a crashed build cannot
198
+ * wedge refreshes forever.
199
+ */
200
+ acquireBuildLock(nowMs: number, staleMs?: number): boolean;
201
+ releaseBuildLock(): void;
202
+ /** ISO timestamp of the most recent ingest, or null if never built. */
203
+ lastIngestedAt(): string | null;
204
+ /** Mark source keys as ingested. */
205
+ markIngested(keys: Iterable<string>): void;
206
+ /**
207
+ * Cheap emptiness probe. `stats()` runs five aggregates including two
208
+ * COUNT(DISTINCT) and a GROUP BY — far too expensive for the "should I route
209
+ * here" check that runs on every single query.
210
+ */
211
+ isEmpty(): boolean;
212
+ /** Delete everything — the truncate half of a real rebuild. */
213
+ clear(): void;
214
+ /** Shape of the graph, for `uap memory graph status` and honest reporting. */
215
+ stats(): {
216
+ contents: number;
217
+ cues: number;
218
+ tags: number;
219
+ triples: number;
220
+ bridgingTags: number;
221
+ };
222
+ /** Every cue in the graph — the seed set when the query matches nothing. */
223
+ allCues(): string[];
224
+ close(): void;
225
+ }
226
+ export interface ReconstructOptions {
227
+ /** Hard step cap. The paper's runs converge in 3–4; 5 leaves headroom. */
228
+ maxSteps?: number;
229
+ policy?: ReconstructionPolicy;
230
+ /** Seed cues. Omitted -> derived from the query's own tokens. */
231
+ seedCues?: string[];
232
+ /**
233
+ * Hard ceiling on admitted context. `sufficient` only stops FURTHER steps —
234
+ * everything kept in the current step is already in context — so without this
235
+ * one step over a well-connected graph can admit thousands of nodes and blow
236
+ * the token budget this whole approach exists to protect.
237
+ */
238
+ maxContext?: number;
239
+ /** Seed cues to draw when the query matches nothing. Default 32. */
240
+ maxSeeds?: number;
241
+ /**
242
+ * Hard cap on cues expanded per step, enforced HERE rather than trusted to the
243
+ * policy. The policy seam exists for an LLM to plug into, and an LLM will
244
+ * happily return 200 cues (or cues that were never active), reproducing the
245
+ * full-scan this bound was added to prevent.
246
+ */
247
+ maxExpandPerStep?: number;
248
+ }
249
+ /**
250
+ * Reconstruct an answer context by traversing the graph while reasoning.
251
+ *
252
+ * The loop is the paper's three-step iteration: select actions over the active
253
+ * set, traverse (cue -> tags -> contents), then route/prune and update state.
254
+ * The essential difference from retrieval is that step N+1's expansion depends
255
+ * on what step N actually found — cues discovered mid-traversal become new
256
+ * entry points, and weak paths are killed before they consume context.
257
+ */
258
+ export declare function reconstruct(graph: MemoryGraph, query: string, options?: ReconstructOptions): ReconstructionResult;
259
+ /**
260
+ * Seed cues = query tokens present in the graph.
261
+ *
262
+ * When nothing matches we fall back to a BOUNDED sample rather than every cue
263
+ * in the graph: an off-topic query would otherwise load the entire content
264
+ * table on step 1, which is the opposite of what this is for.
265
+ */
266
+ export declare function seedCuesFromQuery(graph: MemoryGraph, query: string, maxSeeds?: number): string[];
267
+ /**
268
+ * Is active reconstruction enabled? Off by default — the lift is measured on our
269
+ * own suite before it becomes the default retrieval path.
270
+ */
271
+ export declare function activeReconstructionEnabled(): boolean;
272
+ //# sourceMappingURL=reconstruct.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconstruct.d.ts","sourceRoot":"","sources":["../../src/memory/reconstruct.ts"],"names":[],"mappings":"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"}