@remnic/core 9.69.30 → 9.69.32
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.
- package/dist/access-admin-ops-surface.d.ts +2 -2
- package/dist/access-admin-ops-surface.js +4 -4
- package/dist/access-authorization-probe.d.ts +2 -2
- package/dist/access-authorization-probe.js +5 -5
- package/dist/access-boundary.d.ts +2 -2
- package/dist/access-boundary.js +4 -4
- package/dist/access-cli.js +20 -20
- package/dist/access-extraction-force-flush.d.ts +2 -2
- package/dist/access-extraction-force-flush.js +4 -4
- package/dist/access-http-briefing.d.ts +2 -2
- package/dist/access-http-briefing.js +5 -5
- package/dist/access-http-lcm-compaction.d.ts +2 -2
- package/dist/access-http-lifecycle-flush.d.ts +2 -2
- package/dist/access-http-offline-stream.d.ts +2 -2
- package/dist/access-http-query.js +4 -4
- package/dist/access-http.d.ts +3 -3
- package/dist/access-http.js +14 -14
- package/dist/access-identity-continuity-surface.d.ts +1 -1
- package/dist/access-identity-continuity-surface.js +4 -4
- package/dist/access-lcm-surface.d.ts +2 -2
- package/dist/access-lcm-surface.js +4 -4
- package/dist/access-mcp.d.ts +2 -2
- package/dist/access-mcp.js +9 -9
- package/dist/access-namespace-preflight.js +4 -4
- package/dist/access-observe-transcript.d.ts +1 -1
- package/dist/access-observe-write-surface.d.ts +2 -2
- package/dist/access-observe-write-surface.js +4 -4
- package/dist/access-offline-manifest.d.ts +1 -1
- package/dist/access-operations-batch.js +5 -5
- package/dist/access-operations.d.ts +2 -2
- package/dist/access-operations.js +8 -8
- package/dist/access-recall-concurrency.d.ts +2 -2
- package/dist/access-recall-concurrency.js +4 -4
- package/dist/access-recall-response.d.ts +2 -2
- package/dist/access-recall-response.js +4 -4
- package/dist/access-recall-surface.d.ts +2 -2
- package/dist/access-recall-surface.js +4 -4
- package/dist/{access-service-DWdY9Mlk.d.ts → access-service-CCpOuS46.d.ts} +1 -1
- package/dist/access-service-helpers.d.ts +2 -2
- package/dist/access-service.d.ts +2 -2
- package/dist/access-service.js +4 -4
- package/dist/access-surface-catalog.d.ts +2 -2
- package/dist/access-surface-catalog.js +6 -6
- package/dist/bootstrap.d.ts +1 -1
- package/dist/briefing-window.d.ts +25 -5
- package/dist/briefing-window.js +4 -1
- package/dist/briefing.js +2 -2
- package/dist/buffer.js +2 -2
- package/dist/{chunk-SMOFBBPU.js → chunk-2GPE5UCR.js} +2 -2
- package/dist/{chunk-IA2YSHTX.js → chunk-42SDNZCU.js} +8 -8
- package/dist/{chunk-W64HKJJM.js → chunk-5N53UBH2.js} +2 -2
- package/dist/{chunk-T7CJQVRZ.js → chunk-6H5JYDOM.js} +2 -2
- package/dist/chunk-6JMQR72P.js +134 -0
- package/dist/chunk-6JMQR72P.js.map +1 -0
- package/dist/{chunk-X74UAWSI.js → chunk-C4OTC6WY.js} +2 -2
- package/dist/{chunk-PLBW64UM.js → chunk-CZYYJZB6.js} +10 -11
- package/dist/chunk-CZYYJZB6.js.map +1 -0
- package/dist/{chunk-JDDXXZWW.js → chunk-GQOMZ3MK.js} +2 -2
- package/dist/{chunk-SH2ZWEWB.js → chunk-HG6HXVHQ.js} +3 -3
- package/dist/{chunk-OGELWNYC.js → chunk-ITPS5DDH.js} +3 -3
- package/dist/{chunk-EYMOJ3J6.js → chunk-LPECRQO4.js} +2 -2
- package/dist/{chunk-666OOKB7.js → chunk-M75RYSHS.js} +2 -2
- package/dist/{chunk-5ABN4WVL.js → chunk-MYMNC6O5.js} +4 -4
- package/dist/{chunk-KLMESRPV.js → chunk-NAXDPKVM.js} +2 -2
- package/dist/{chunk-OXNU333D.js → chunk-Q3O3VKRB.js} +2 -2
- package/dist/{chunk-ENMTJRXA.js → chunk-QMGXMJ2O.js} +2 -2
- package/dist/{chunk-PEOTOFH5.js → chunk-TIT2C6WX.js} +2 -2
- package/dist/{chunk-U34EHBPL.js → chunk-VED2YHUD.js} +2 -2
- package/dist/{chunk-RAVRDTP7.js → chunk-XQ2Q43XD.js} +3 -1
- package/dist/chunk-XQ2Q43XD.js.map +1 -0
- package/dist/{chunk-7DUFJAOE.js → chunk-Z4PCVRTN.js} +3 -3
- package/dist/{cli-DD0P-lu8.d.ts → cli-NEEdq5Rt.d.ts} +2 -2
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +15 -15
- package/dist/deep-recall-http-glue.d.ts +2 -2
- package/dist/deep-recall-mcp-tools.d.ts +2 -2
- package/dist/explicit-capture.d.ts +1 -1
- package/dist/external-wiki-access.d.ts +2 -2
- package/dist/external-wiki-access.js +5 -5
- package/dist/external-wiki-mcp-tools.d.ts +2 -2
- package/dist/extraction.js +3 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +20 -20
- package/dist/mcp-memory-inspector-app.d.ts +2 -2
- package/dist/memory-subject-cli.d.ts +2 -2
- package/dist/memory-subject.d.ts +2 -2
- package/dist/{orchestrator-DgyvFfPR.d.ts → orchestrator-kqSzGv7e.d.ts} +48 -64
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.js +20 -20
- package/dist/{public-http-C4i8Opxc.d.ts → public-http-CW3l0g3P.d.ts} +1 -1
- package/dist/source-agent-qualifier.js +2 -2
- package/dist/support-passport/index.d.ts +5 -5
- package/dist/support-passport/index.js +7 -7
- package/dist/who-knows-cli.d.ts +2 -2
- package/dist/who-knows.d.ts +2 -2
- package/package.json +2 -2
- package/src/briefing-window.test.ts +554 -0
- package/src/briefing-window.ts +201 -12
- package/src/briefing.test.ts +2 -1
- package/src/orchestration/extraction-shutdown.ts +2 -10
- package/src/orchestration/graph-recall-coordinator.ts +19 -16
- package/src/orchestration/namespace-read-fanout.ts +2 -5
- package/src/orchestration/orchestrator-helpers.ts +2 -0
- package/src/orchestration/recall-internal-deps.ts +1 -5
- package/src/orchestration/recall-search-pipeline.ts +1 -4
- package/src/orchestrator.ts +1 -3
- package/dist/chunk-PLBW64UM.js.map +0 -1
- package/dist/chunk-RAVRDTP7.js.map +0 -1
- package/dist/chunk-UBCBDJOB.js +0 -22
- package/dist/chunk-UBCBDJOB.js.map +0 -1
- package/src/orchestration/graph-recall-seam.ts +0 -19
- /package/dist/{chunk-SMOFBBPU.js.map → chunk-2GPE5UCR.js.map} +0 -0
- /package/dist/{chunk-IA2YSHTX.js.map → chunk-42SDNZCU.js.map} +0 -0
- /package/dist/{chunk-W64HKJJM.js.map → chunk-5N53UBH2.js.map} +0 -0
- /package/dist/{chunk-T7CJQVRZ.js.map → chunk-6H5JYDOM.js.map} +0 -0
- /package/dist/{chunk-X74UAWSI.js.map → chunk-C4OTC6WY.js.map} +0 -0
- /package/dist/{chunk-JDDXXZWW.js.map → chunk-GQOMZ3MK.js.map} +0 -0
- /package/dist/{chunk-SH2ZWEWB.js.map → chunk-HG6HXVHQ.js.map} +0 -0
- /package/dist/{chunk-OGELWNYC.js.map → chunk-ITPS5DDH.js.map} +0 -0
- /package/dist/{chunk-EYMOJ3J6.js.map → chunk-LPECRQO4.js.map} +0 -0
- /package/dist/{chunk-666OOKB7.js.map → chunk-M75RYSHS.js.map} +0 -0
- /package/dist/{chunk-5ABN4WVL.js.map → chunk-MYMNC6O5.js.map} +0 -0
- /package/dist/{chunk-KLMESRPV.js.map → chunk-NAXDPKVM.js.map} +0 -0
- /package/dist/{chunk-OXNU333D.js.map → chunk-Q3O3VKRB.js.map} +0 -0
- /package/dist/{chunk-ENMTJRXA.js.map → chunk-QMGXMJ2O.js.map} +0 -0
- /package/dist/{chunk-PEOTOFH5.js.map → chunk-TIT2C6WX.js.map} +0 -0
- /package/dist/{chunk-U34EHBPL.js.map → chunk-VED2YHUD.js.map} +0 -0
- /package/dist/{chunk-7DUFJAOE.js.map → chunk-Z4PCVRTN.js.map} +0 -0
package/src/briefing-window.ts
CHANGED
|
@@ -1,27 +1,216 @@
|
|
|
1
1
|
import { log } from "./logger.js";
|
|
2
2
|
import type { MemoryFile } from "./types.js";
|
|
3
|
+
import { isAbortError } from "./abort-error.js";
|
|
4
|
+
import type { CorpusReadOptions } from "./corpus-read-cancellation.js";
|
|
5
|
+
import type { ParsedBriefingWindow } from "./briefing.js";
|
|
6
|
+
|
|
3
7
|
type BriefingMemoryReader = {
|
|
4
8
|
readMemoriesWindow?: (options: { updatedAfter?: Date }) => Promise<{ memories: MemoryFile[] }>;
|
|
5
|
-
readAllMemories: () => Promise<MemoryFile[]
|
|
9
|
+
readAllMemories: ((options?: CorpusReadOptions) => Promise<MemoryFile[]>) & {
|
|
10
|
+
supportsAbortSignal?: boolean;
|
|
11
|
+
};
|
|
12
|
+
supportsAbortSignal?: boolean;
|
|
13
|
+
supportsCancellation?: boolean;
|
|
14
|
+
cancellable?: boolean;
|
|
6
15
|
};
|
|
7
|
-
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Deadline for the legacy full-read fallback (issue #2779). Storage doubles
|
|
19
|
+
* that predate `readMemoriesWindow()` can only answer with a full-corpus
|
|
20
|
+
* `readAllMemories()`, which is unbounded work; on a large corpus that read
|
|
21
|
+
* alone can outlast the 60s MCP client timeout. Arm an AbortController with
|
|
22
|
+
* this budget (well under 60s, leaving room for entity reads and follow-ups)
|
|
23
|
+
* and fail open with an empty read. The deadline reaches the read as an
|
|
24
|
+
* abort signal (the #2307 corpus-read contract), so the scan stops at its
|
|
25
|
+
* next boundary instead of being abandoned to run on in the background.
|
|
26
|
+
*/
|
|
27
|
+
export const BRIEFING_FULL_READ_FALLBACK_MS = 30_000;
|
|
28
|
+
|
|
29
|
+
/** Options for {@link safeReadMemories}. */
|
|
30
|
+
export interface SafeReadMemoriesOptions {
|
|
31
|
+
/** Test seam overriding {@link BRIEFING_FULL_READ_FALLBACK_MS}. */
|
|
32
|
+
fallbackDeadlineMs?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type BriefingReadMode = "windowed" | "full-read-fallback";
|
|
36
|
+
type BriefingReadOutcome = "success" | "timeout" | "error";
|
|
37
|
+
|
|
38
|
+
/** Internal marker: the fallback deadline fired and the read was aborted. */
|
|
39
|
+
class BriefingReadTimedOut extends Error {
|
|
40
|
+
constructor(readonly deadlineMs: number) {
|
|
41
|
+
super("briefing full-read fallback timed out");
|
|
42
|
+
this.name = "BriefingReadTimedOut";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Internal marker: the adapter's readAllMemories predates the signal contract. */
|
|
47
|
+
class LegacyReadUnsupported extends Error {
|
|
48
|
+
constructor() {
|
|
49
|
+
super("readAllMemories does not accept an abort signal");
|
|
50
|
+
this.name = "LegacyReadUnsupported";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const SAFE_ERROR_CLASSES: Record<string, true> = {
|
|
55
|
+
Error: true,
|
|
56
|
+
TypeError: true,
|
|
57
|
+
RangeError: true,
|
|
58
|
+
ReferenceError: true,
|
|
59
|
+
SyntaxError: true,
|
|
60
|
+
URIError: true,
|
|
61
|
+
EvalError: true,
|
|
62
|
+
AggregateError: true,
|
|
63
|
+
AbortError: true,
|
|
64
|
+
TimeoutError: true,
|
|
65
|
+
SystemError: true,
|
|
66
|
+
BriefingReadTimedOut: true,
|
|
67
|
+
LegacyReadUnsupported: true,
|
|
68
|
+
StorageError: true,
|
|
69
|
+
EngramAccessInputError: true,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sanitize adapter-controlled Error.name before structured discriminator logs
|
|
74
|
+
* (issue #2827). Allow-lists known system/remnic error names and maps any
|
|
75
|
+
* unrecognized or backend-controlled names to a safe bounded class ("CustomError").
|
|
76
|
+
*/
|
|
77
|
+
function errorClass(err: unknown): string {
|
|
78
|
+
if (err instanceof Error) {
|
|
79
|
+
const name = err.name;
|
|
80
|
+
if (typeof name === "string" && SAFE_ERROR_CLASSES[name] === true) {
|
|
81
|
+
return name;
|
|
82
|
+
}
|
|
83
|
+
return "CustomError";
|
|
84
|
+
}
|
|
85
|
+
return typeof err === "string"
|
|
86
|
+
? "string"
|
|
87
|
+
: typeof err === "object" && err !== null
|
|
88
|
+
? "object"
|
|
89
|
+
: typeof err;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function bestEffortLog(level: "info" | "warn", message: string): void {
|
|
93
|
+
try {
|
|
94
|
+
log[level](message);
|
|
95
|
+
} catch {
|
|
96
|
+
// Diagnostics must never turn a successful or fail-open briefing read into
|
|
97
|
+
// a request failure when a host logger transport is unavailable.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* One structured, content-free discriminator per briefing memory read
|
|
103
|
+
* (issue #2779): `mode`, `durationMs`, `count` when known, `outcome`, and on
|
|
104
|
+
* failure a safe error class — never error messages or memory content.
|
|
105
|
+
*/
|
|
106
|
+
function logBriefingMemoryRead(
|
|
107
|
+
mode: BriefingReadMode,
|
|
108
|
+
outcome: BriefingReadOutcome,
|
|
109
|
+
durationMs: number,
|
|
110
|
+
resultCount: number | undefined,
|
|
111
|
+
errClass: string | undefined,
|
|
112
|
+
): void {
|
|
113
|
+
const fields = [
|
|
114
|
+
`mode=${mode}`,
|
|
115
|
+
`durationMs=${durationMs}`,
|
|
116
|
+
...(resultCount === undefined ? [] : [`count=${resultCount}`]),
|
|
117
|
+
`outcome=${outcome}`,
|
|
118
|
+
...(errClass === undefined ? [] : [`err=${errClass}`]),
|
|
119
|
+
];
|
|
120
|
+
bestEffortLog("info", `briefing: memory read ${fields.join(" ")}`);
|
|
121
|
+
}
|
|
8
122
|
|
|
9
123
|
/** Read only the memories needed by a briefing, with compatibility fallback. */
|
|
10
124
|
export async function safeReadMemories(
|
|
11
125
|
storage: BriefingMemoryReader,
|
|
12
|
-
window: ParsedBriefingWindow
|
|
126
|
+
window: ParsedBriefingWindow,
|
|
127
|
+
options: SafeReadMemoriesOptions = {},
|
|
13
128
|
): Promise<MemoryFile[]> {
|
|
129
|
+
const startedAt = Date.now();
|
|
130
|
+
const mode: BriefingReadMode =
|
|
131
|
+
typeof storage.readMemoriesWindow === "function" ? "windowed" : "full-read-fallback";
|
|
132
|
+
let outcome: BriefingReadOutcome = "error";
|
|
133
|
+
let resultCount: number | undefined;
|
|
134
|
+
let errClass: string | undefined;
|
|
14
135
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const result = await storage.readMemoriesWindow({ updatedAfter: window.from });
|
|
20
|
-
return result.memories;
|
|
21
|
-
}
|
|
22
|
-
return await storage.readAllMemories();
|
|
136
|
+
const memories = await readBriefingMemories(storage, window, mode, options);
|
|
137
|
+
outcome = "success";
|
|
138
|
+
resultCount = memories.length;
|
|
139
|
+
return memories;
|
|
23
140
|
} catch (err) {
|
|
24
|
-
|
|
141
|
+
if (err instanceof BriefingReadTimedOut) {
|
|
142
|
+
outcome = "timeout";
|
|
143
|
+
bestEffortLog(
|
|
144
|
+
"warn",
|
|
145
|
+
`briefing: memory read mode=full-read-fallback timed out after ${err.deadlineMs}ms — ` +
|
|
146
|
+
`returning no memories (storage adapter lacks readMemoriesWindow; upgrade it to ` +
|
|
147
|
+
`windowed or signal-aware reads)`,
|
|
148
|
+
);
|
|
149
|
+
} else if (err instanceof LegacyReadUnsupported) {
|
|
150
|
+
errClass = errorClass(err);
|
|
151
|
+
bestEffortLog(
|
|
152
|
+
"warn",
|
|
153
|
+
`briefing: memory read mode=full-read-fallback refused: readAllMemories() takes no abort ` +
|
|
154
|
+
`signal, so its scan could not be stopped at the deadline — returning no memories ` +
|
|
155
|
+
`(upgrade the storage adapter to readMemoriesWindow or a signal-aware readAllMemories)`,
|
|
156
|
+
);
|
|
157
|
+
} else {
|
|
158
|
+
errClass = errorClass(err);
|
|
159
|
+
bestEffortLog("warn", `briefing: read memories failed (${errClass}) — returning no memories`);
|
|
160
|
+
}
|
|
25
161
|
return [];
|
|
162
|
+
} finally {
|
|
163
|
+
logBriefingMemoryRead(mode, outcome, Date.now() - startedAt, resultCount, errClass);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function readBriefingMemories(
|
|
168
|
+
storage: BriefingMemoryReader,
|
|
169
|
+
window: ParsedBriefingWindow,
|
|
170
|
+
mode: BriefingReadMode,
|
|
171
|
+
options: SafeReadMemoriesOptions,
|
|
172
|
+
): Promise<MemoryFile[]> {
|
|
173
|
+
// A briefing only needs memories inside its lookback window. Avoid parsing
|
|
174
|
+
// the full corpus on cache misses; keep the full-read fallback for custom
|
|
175
|
+
// StorageManager-compatible callers that predate readMemoriesWindow().
|
|
176
|
+
if (mode === "windowed") {
|
|
177
|
+
const result = await storage.readMemoriesWindow!({ updatedAfter: window.from });
|
|
178
|
+
return result.memories;
|
|
179
|
+
}
|
|
180
|
+
// Refuse legacy adapters that do not explicitly declare cancellation support (#2827).
|
|
181
|
+
// Require affirmative cancellation support (`true` on one explicit marker) before fallback.
|
|
182
|
+
// Do not rely on Function.length, which is zero for default/rest/bound functions.
|
|
183
|
+
const isCancellable =
|
|
184
|
+
storage.supportsAbortSignal === true ||
|
|
185
|
+
storage.supportsCancellation === true ||
|
|
186
|
+
storage.cancellable === true ||
|
|
187
|
+
storage.readAllMemories?.supportsAbortSignal === true;
|
|
188
|
+
if (!isCancellable) {
|
|
189
|
+
throw new LegacyReadUnsupported();
|
|
190
|
+
}
|
|
191
|
+
const deadlineMs = options.fallbackDeadlineMs ?? BRIEFING_FULL_READ_FALLBACK_MS;
|
|
192
|
+
const controller = new AbortController();
|
|
193
|
+
let deadlineFired = false;
|
|
194
|
+
const timer = setTimeout(() => {
|
|
195
|
+
deadlineFired = true;
|
|
196
|
+
controller.abort();
|
|
197
|
+
}, deadlineMs);
|
|
198
|
+
try {
|
|
199
|
+
// Direct await, no Promise.race: the signal IS the deadline. A
|
|
200
|
+
// signal-aware read settles on abort (AbortError at its next scan
|
|
201
|
+
// boundary, #2307), so nothing is left scanning in the background once
|
|
202
|
+
// this function returns.
|
|
203
|
+
const memories = await storage.readAllMemories({ abortSignal: controller.signal });
|
|
204
|
+
if (deadlineFired) {
|
|
205
|
+
// A double that resolves partial rows instead of rejecting on abort
|
|
206
|
+
// must not have them served as a complete corpus.
|
|
207
|
+
throw new BriefingReadTimedOut(deadlineMs);
|
|
208
|
+
}
|
|
209
|
+
return memories;
|
|
210
|
+
} catch (err) {
|
|
211
|
+
if (isAbortError(err) && deadlineFired) throw new BriefingReadTimedOut(deadlineMs);
|
|
212
|
+
throw err;
|
|
213
|
+
} finally {
|
|
214
|
+
clearTimeout(timer);
|
|
26
215
|
}
|
|
27
216
|
}
|
package/src/briefing.test.ts
CHANGED
|
@@ -963,7 +963,8 @@ test("buildBriefing excludes support passport records from generated context", a
|
|
|
963
963
|
content: "Public project update",
|
|
964
964
|
};
|
|
965
965
|
const storage = {
|
|
966
|
-
|
|
966
|
+
supportsAbortSignal: true,
|
|
967
|
+
readAllMemories: async (_options?: { abortSignal?: AbortSignal }) => [privateMemory, publicMemory],
|
|
967
968
|
readAllEntityFiles: async () => [],
|
|
968
969
|
} as unknown as StorageManager;
|
|
969
970
|
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { log } from "../logger.js";
|
|
2
2
|
|
|
3
|
-
export interface ExtractionDrainPort {
|
|
4
|
-
pauseAndDrain(): Promise<boolean>;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface DependencyPropagationShutdownPort {
|
|
8
|
-
shutdown(): Promise<void>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
3
|
export async function drainExtractionAndShutdownDependencyPropagation(
|
|
12
|
-
extractionQueue:
|
|
13
|
-
dependencyPropagationDelivery:
|
|
4
|
+
extractionQueue: { pauseAndDrain(): Promise<boolean> },
|
|
5
|
+
dependencyPropagationDelivery: { shutdown(): Promise<void> } | undefined,
|
|
14
6
|
): Promise<unknown | undefined> {
|
|
15
7
|
let extractionDrainError: unknown;
|
|
16
8
|
try {
|
|
@@ -56,6 +56,24 @@ export interface GraphRecallShadowComparison {
|
|
|
56
56
|
averageOverlapDelta: number;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
export interface GraphRecallExpansionOptions {
|
|
60
|
+
memoryResults: QmdSearchResult[];
|
|
61
|
+
recallNamespaces: string[];
|
|
62
|
+
recallResultLimit: number;
|
|
63
|
+
/** Query-time instant used for graph-path invalidity checks. */
|
|
64
|
+
asOf?: string;
|
|
65
|
+
asOfMs?: number;
|
|
66
|
+
deadlineAtMs?: number | null;
|
|
67
|
+
/** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */
|
|
68
|
+
includeLowConfidence?: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface GraphRecallExpansionResult {
|
|
72
|
+
merged: QmdSearchResult[];
|
|
73
|
+
seedPaths: string[];
|
|
74
|
+
expandedPaths: GraphRecallExpandedEntry[];
|
|
75
|
+
seedResults: QmdSearchResult[];
|
|
76
|
+
}
|
|
59
77
|
// ---------------------------------------------------------------------------
|
|
60
78
|
// Utility functions (moved from orchestrator.ts; re-exported for callers)
|
|
61
79
|
// ---------------------------------------------------------------------------
|
|
@@ -193,22 +211,7 @@ export class GraphRecallCoordinator {
|
|
|
193
211
|
}
|
|
194
212
|
|
|
195
213
|
|
|
196
|
-
async expandResultsViaGraph(options: {
|
|
197
|
-
memoryResults: QmdSearchResult[];
|
|
198
|
-
recallNamespaces: string[];
|
|
199
|
-
recallResultLimit: number;
|
|
200
|
-
/** Query-time instant used for graph-path invalidity checks. */
|
|
201
|
-
asOf?: string;
|
|
202
|
-
asOfMs?: number;
|
|
203
|
-
deadlineAtMs?: number | null;
|
|
204
|
-
/** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */
|
|
205
|
-
includeLowConfidence?: boolean;
|
|
206
|
-
}): Promise<{
|
|
207
|
-
merged: QmdSearchResult[];
|
|
208
|
-
seedPaths: string[];
|
|
209
|
-
expandedPaths: GraphRecallExpandedEntry[];
|
|
210
|
-
seedResults: QmdSearchResult[];
|
|
211
|
-
}> {
|
|
214
|
+
async expandResultsViaGraph(options: GraphRecallExpansionOptions): Promise<GraphRecallExpansionResult> {
|
|
212
215
|
const config = this.getConfig();
|
|
213
216
|
const parsedAsOfMs =
|
|
214
217
|
typeof options.asOf === "string" ? Date.parse(options.asOf) : Number.NaN;
|
|
@@ -23,7 +23,7 @@ import { NamespaceCatalog } from "../namespaces/catalog.js";
|
|
|
23
23
|
import { namespaceIdentityFromToken, namespaceIdentityToken, normalizeNamespaceIdentity } from "../namespaces/identity.js";
|
|
24
24
|
import { NamespaceSearchRouter } from "../namespaces/search.js";
|
|
25
25
|
import { NamespaceStorageRouter } from "../namespaces/storage.js";
|
|
26
|
-
import { mergeArtifactRecallCandidates, tokenizeRecallQuery } from "./orchestrator-helpers.js";
|
|
26
|
+
import { ARTIFACT_STATUS_CACHE_TTL_MS, mergeArtifactRecallCandidates, tokenizeRecallQuery } from "./orchestrator-helpers.js";
|
|
27
27
|
import { qmdCollectionPathParts } from "./qmd-result-resolver.js";
|
|
28
28
|
import { qmdCollectionNamespaceFromPrefix as computeQmdCollectionNamespaceFromPrefix } from "./orchestrator-namespace-scope.js";
|
|
29
29
|
import { resolveNamespaceFromStorageDir } from "../scopes/scope-plan.js";
|
|
@@ -31,9 +31,6 @@ import { checkCorpusReadAbort, type CorpusReadOptions } from "../corpus-read-can
|
|
|
31
31
|
import type { ArtifactRecallOptions } from "./recall-search-prefilter.js";
|
|
32
32
|
import type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from "../search/port.js";
|
|
33
33
|
import type { MemoryFile, PluginConfig, QmdSearchResult } from "../types.js";
|
|
34
|
-
import {
|
|
35
|
-
Orchestrator,
|
|
36
|
-
} from "../orchestrator.js";
|
|
37
34
|
|
|
38
35
|
export interface NamespaceReadFanoutDeps {
|
|
39
36
|
readonly artifactSourceStatusCache: WeakMap<StorageManager, { loadedAtMs: number; statusVersion: number; statuses: Map<string, "active" | "superseded" | "archived" | "missing"> }>;
|
|
@@ -257,7 +254,7 @@ export class NamespaceReadFanoutCoordinator {
|
|
|
257
254
|
const isFresh =
|
|
258
255
|
snapshot !== undefined &&
|
|
259
256
|
Date.now() - snapshot.loadedAtMs <=
|
|
260
|
-
|
|
257
|
+
ARTIFACT_STATUS_CACHE_TTL_MS &&
|
|
261
258
|
snapshot.statusVersion === currentStatusVersion;
|
|
262
259
|
|
|
263
260
|
const rebuildSnapshot = async () => {
|
|
@@ -32,6 +32,8 @@ import { type BufferTurn, type MemoryActionEvent, type MemoryFile, type MemoryFr
|
|
|
32
32
|
import { categoryDirName } from "../utils/category-dir.js";
|
|
33
33
|
import { parseFlexibleIsoTimestamp } from "../utils/iso-timestamp.js";
|
|
34
34
|
|
|
35
|
+
/** Freshness window for the artifact source status cache read by NamespaceReadFanoutCoordinator. */
|
|
36
|
+
export const ARTIFACT_STATUS_CACHE_TTL_MS = 60_000;
|
|
35
37
|
export interface BulkImportBatchIngestResult {
|
|
36
38
|
attemptedTurnCount: number;
|
|
37
39
|
extractionCount: number;
|
|
@@ -35,11 +35,7 @@ import type { TrustZoneSearchResult } from "../trust-zones.js";
|
|
|
35
35
|
import type { CodingContext, EngramTraceEvent, IdentityInjectionMode, MemoryFile, MemoryIntent, PluginConfig, QmdSearchResult, RecallPlanMode, RecallSectionConfig } from "../types.js";
|
|
36
36
|
import type { VerifiedEpisodeResult } from "../verified-recall.js";
|
|
37
37
|
import type { WorkProductLedgerSearchResult } from "../work-product-ledger.js";
|
|
38
|
-
import type { GraphRecallRankedResult, GraphRecallShadowComparison } from "./graph-recall-coordinator.js";
|
|
39
|
-
import type {
|
|
40
|
-
GraphRecallExpansionOptions,
|
|
41
|
-
GraphRecallExpansionResult,
|
|
42
|
-
} from "./graph-recall-seam.js";
|
|
38
|
+
import type { GraphRecallExpansionOptions, GraphRecallExpansionResult, GraphRecallRankedResult, GraphRecallShadowComparison } from "./graph-recall-coordinator.js";
|
|
43
39
|
import type { RecallRerankCoordinator, RecallResultPartitionSink } from "./recall-rerank-coordinator.js";
|
|
44
40
|
import type { ArtifactRecallOptions } from "./recall-search-prefilter.js";
|
|
45
41
|
import type { RecallSectionAppendOptions, RecallSectionBuckets } from "./recall-section-coordinator.js";
|
|
@@ -28,10 +28,7 @@ import { NamespaceStorageRouter } from "../namespaces/storage.js";
|
|
|
28
28
|
import { NegativeExampleStore } from "../negative.js";
|
|
29
29
|
import { qmdCollectionPathParts } from "./qmd-result-resolver.js";
|
|
30
30
|
import type { RecallRerankCoordinator, RecallResultPartitionSink } from "./recall-rerank-coordinator.js";
|
|
31
|
-
import type {
|
|
32
|
-
GraphRecallExpansionOptions,
|
|
33
|
-
GraphRecallExpansionResult,
|
|
34
|
-
} from "./graph-recall-seam.js";
|
|
31
|
+
import type { GraphRecallExpansionOptions, GraphRecallExpansionResult } from "./graph-recall-coordinator.js";
|
|
35
32
|
import { RelevanceStore } from "../relevance.js";
|
|
36
33
|
import { RerankCache, rerankLocalOrNoop, reorderByRankedKeys } from "../rerank.js";
|
|
37
34
|
import type { SearchBackend, SearchDegradation, SearchExecutionOptions, SearchQueryOptions } from "../search/port.js";
|
package/src/orchestrator.ts
CHANGED
|
@@ -132,7 +132,7 @@ import { isDependencyPropagationEnabled } from "./orchestration/dependency-propa
|
|
|
132
132
|
import { createDependencyPropagationReplayReconciliation } from "./orchestration/dependency-propagation-replay-reconciliation.js";
|
|
133
133
|
import { RecallInternalCoordinator } from "./orchestration/recall-internal.js";
|
|
134
134
|
import { RecallSearchPipelineCoordinator } from "./orchestration/recall-search-pipeline.js";
|
|
135
|
-
import type { GraphRecallExpansionOptions, GraphRecallExpansionResult } from "./orchestration/graph-recall-
|
|
135
|
+
import type { GraphRecallExpansionOptions, GraphRecallExpansionResult } from "./orchestration/graph-recall-coordinator.js";
|
|
136
136
|
import type { ArtifactRecallOptions } from "./orchestration/recall-search-prefilter.js";
|
|
137
137
|
import type { CorpusReadOptions } from "./corpus-read-cancellation.js";
|
|
138
138
|
import { TurnIngestionCoordinator, type TurnIngestionOptions } from "./orchestration/turn-ingestion.js";
|
|
@@ -716,8 +716,6 @@ export class Orchestrator {
|
|
|
716
716
|
statuses: Map<string, "active" | "superseded" | "archived" | "missing">;
|
|
717
717
|
}
|
|
718
718
|
>();
|
|
719
|
-
/** Read by NamespaceReadFanoutCoordinator (seam 26), hence not `private`. */
|
|
720
|
-
static readonly ARTIFACT_STATUS_CACHE_TTL_MS = 60_000;
|
|
721
719
|
|
|
722
720
|
// Batched access-tracking counts and timestamps (Phase 1A).
|
|
723
721
|
private accessTrackingBuffer: Map<
|