@remnic/core 9.3.650 → 9.3.652
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-cli.js +39 -38
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +3 -2
- package/dist/access-http.js +19 -19
- package/dist/access-mcp.d.ts +3 -2
- package/dist/access-mcp.js +18 -18
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-DIZRHQ7Q.d.ts → access-service-CdJFd3_b.d.ts} +23 -2
- package/dist/access-service.d.ts +3 -2
- package/dist/access-service.js +16 -16
- package/dist/{auto-sync-54QQHOG5.js → auto-sync-5CJBJMPZ.js} +5 -5
- package/dist/bootstrap.d.ts +2 -1
- package/dist/briefing.js +3 -3
- package/dist/calibration.js +2 -2
- package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/causal-consolidation.js +6 -6
- package/dist/{chunk-QT4THOLT.js → chunk-2DGQLOOM.js} +1 -1
- package/dist/chunk-2DGQLOOM.js.map +1 -0
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-OAZ5MFUB.js → chunk-3XGWCZ63.js} +45 -28
- package/dist/chunk-3XGWCZ63.js.map +1 -0
- package/dist/{chunk-QKE4LHNR.js → chunk-4HYSMH7D.js} +2 -2
- package/dist/{chunk-DDRNDPX4.js → chunk-4SKKVWLQ.js} +2 -2
- package/dist/chunk-5FOCXX5E.js +34 -0
- package/dist/chunk-5FOCXX5E.js.map +1 -0
- package/dist/{chunk-YAFSTKTH.js → chunk-5V3TAB7D.js} +184 -12
- package/dist/chunk-5V3TAB7D.js.map +1 -0
- package/dist/{chunk-DB5A3NHS.js → chunk-7LWRCOP7.js} +9 -2
- package/dist/chunk-7LWRCOP7.js.map +1 -0
- package/dist/{chunk-FOVPSMGI.js → chunk-7WEB3FLJ.js} +2 -2
- package/dist/{chunk-APJQ6UEA.js → chunk-AGNBY3VG.js} +4 -4
- package/dist/{chunk-4BISW7RX.js → chunk-AJE7FJVE.js} +2 -2
- package/dist/{chunk-ZXWAQFDE.js → chunk-CFOCZPIQ.js} +2 -2
- package/dist/{chunk-NT5TINK5.js → chunk-DHGSZ3UD.js} +2 -2
- package/dist/{chunk-OTC2KOZ2.js → chunk-EHQLDFSH.js} +2 -2
- package/dist/{chunk-RRRCNIPK.js → chunk-GI45G4BK.js} +4 -4
- package/dist/{chunk-AMACWKM4.js → chunk-IJHLC5CH.js} +2 -2
- package/dist/{chunk-OR7R6M5Z.js → chunk-IVYSVAC6.js} +2 -2
- package/dist/{chunk-76QTEJ2Q.js → chunk-JBHXMCYN.js} +2 -2
- package/dist/{chunk-UMKPSD35.js → chunk-JF7SFXTG.js} +2 -2
- package/dist/{chunk-NMIOW7XG.js → chunk-JVRPJ7D4.js} +126 -26
- package/dist/chunk-JVRPJ7D4.js.map +1 -0
- package/dist/{chunk-TQUWNX7C.js → chunk-JX2RINDR.js} +2 -2
- package/dist/{chunk-MCYT2RNT.js → chunk-KJDKZVF3.js} +3 -3
- package/dist/{chunk-BUKK5SWA.js → chunk-KQAFEZQX.js} +2 -2
- package/dist/{chunk-PQFUUXWK.js → chunk-KWM33SPU.js} +2 -2
- package/dist/{chunk-A3BS64GV.js → chunk-LCC5EZTT.js} +4 -4
- package/dist/{chunk-TVOPSKOK.js → chunk-MGGNV3H2.js} +4 -4
- package/dist/{chunk-D6WVJIS3.js → chunk-ORGWWNJG.js} +2 -2
- package/dist/{chunk-Z3PZRDLW.js → chunk-PRQXUSQV.js} +2 -2
- package/dist/{chunk-VWT3F4IV.js → chunk-PS3SYNHP.js} +12 -4
- package/dist/chunk-PS3SYNHP.js.map +1 -0
- package/dist/{chunk-I4COC5XW.js → chunk-PYWNNF2I.js} +47 -9
- package/dist/chunk-PYWNNF2I.js.map +1 -0
- package/dist/{chunk-IMWFHBG2.js → chunk-QWRC7GIO.js} +2 -2
- package/dist/{chunk-U3GQ33JC.js → chunk-SLTKP5WJ.js} +2 -2
- package/dist/{chunk-23RYLGYA.js → chunk-TCX4WLKK.js} +104 -112
- package/dist/chunk-TCX4WLKK.js.map +1 -0
- package/dist/{chunk-6NKAQ74D.js → chunk-UU6MVCJ6.js} +1 -1
- package/dist/chunk-UU6MVCJ6.js.map +1 -0
- package/dist/{chunk-WEPMT6SC.js → chunk-V25ZAOSB.js} +5 -5
- package/dist/{chunk-UMTG2BN2.js → chunk-V4UDXYGG.js} +2 -2
- package/dist/{chunk-TUMH6EDV.js → chunk-WSFNYPAT.js} +26 -26
- package/dist/{chunk-ZT6R3WR3.js → chunk-WTI35CVJ.js} +4 -4
- package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-OZKZ2TRP.js → chunk-XBIACVCO.js} +9 -2
- package/dist/chunk-XBIACVCO.js.map +1 -0
- package/dist/{chunk-ALUZN7BE.js → chunk-XMN6MMTU.js} +2 -2
- package/dist/{chunk-A4BTPHIN.js → chunk-Y7NWBBHV.js} +6 -6
- package/dist/{chunk-WPCCNSWO.js → chunk-YM3LR4LS.js} +7 -7
- package/dist/{chunk-3IJEQWQX.js → chunk-YOVKPOMD.js} +4 -4
- package/dist/{chunk-M75TBFKQ.js → chunk-Z2OXSMZK.js} +2 -2
- package/dist/{cli-BG4ybtJr.d.ts → cli-DDo7Qgs-.d.ts} +2 -2
- package/dist/cli.d.ts +4 -3
- package/dist/cli.js +34 -34
- package/dist/compounding/engine.js +3 -3
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/index.js +3 -3
- package/dist/entity-retrieval.js +3 -3
- package/dist/event-order-recall.js +1 -1
- package/dist/explicit-capture.d.ts +2 -1
- package/dist/explicit-cue-recall.d.ts +7 -0
- package/dist/explicit-cue-recall.js +2 -1
- package/dist/extraction-judge.js +3 -3
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.js +2 -2
- package/dist/focused-list-recall.d.ts +6 -0
- package/dist/focused-list-recall.js +2 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +87 -86
- package/dist/index.js.map +1 -1
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +5 -5
- package/dist/lcm-fallback-read.d.ts +71 -0
- package/dist/lcm-fallback-read.js +10 -0
- package/dist/lcm-fallback-read.js.map +1 -0
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +3 -2
- package/dist/namespaces/migrate.js +11 -11
- package/dist/namespaces/search.d.ts +18 -1
- package/dist/namespaces/search.js +7 -7
- package/dist/namespaces/storage.js +3 -3
- package/dist/operator-toolkit.js +13 -13
- package/dist/{orchestrator-CX-oqwJq.d.ts → orchestrator-8fTZsa0y.d.ts} +2 -0
- package/dist/orchestrator.d.ts +2 -1
- package/dist/orchestrator.js +33 -32
- package/dist/qmd.d.ts +2 -1
- package/dist/qmd.js +2 -2
- package/dist/recall-planner-llm.js +2 -2
- package/dist/response-guidance-recall.d.ts +6 -0
- package/dist/response-guidance-recall.js +2 -1
- package/dist/search/factory.js +6 -6
- package/dist/search/index.js +8 -8
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/orama-backend.js +2 -2
- package/dist/search/port.d.ts +6 -0
- package/dist/search/port.js +1 -1
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/storage.js +2 -2
- package/dist/summarizer.js +3 -3
- package/dist/targeted-fact-recall.d.ts +6 -0
- package/dist/targeted-fact-recall.js +2 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/verified-recall.js +3 -3
- package/package.json +1 -1
- package/src/access-service-health.test.ts +402 -0
- package/src/access-service.ts +274 -2
- package/src/event-order-recall.ts +8 -0
- package/src/explicit-cue-recall.ts +70 -29
- package/src/focused-list-recall.ts +23 -1
- package/src/lcm-fallback-read.ts +113 -0
- package/src/namespaces/search.test.ts +258 -3
- package/src/namespaces/search.ts +184 -30
- package/src/orchestrator.ts +179 -122
- package/src/qmd.test.ts +102 -0
- package/src/qmd.ts +54 -7
- package/src/response-guidance-recall.ts +21 -1
- package/src/search/port.ts +6 -0
- package/src/targeted-fact-recall.ts +24 -3
- package/dist/chunk-23RYLGYA.js.map +0 -1
- package/dist/chunk-6NKAQ74D.js.map +0 -1
- package/dist/chunk-DB5A3NHS.js.map +0 -1
- package/dist/chunk-I4COC5XW.js.map +0 -1
- package/dist/chunk-NMIOW7XG.js.map +0 -1
- package/dist/chunk-OAZ5MFUB.js.map +0 -1
- package/dist/chunk-OZKZ2TRP.js.map +0 -1
- package/dist/chunk-QT4THOLT.js.map +0 -1
- package/dist/chunk-VWT3F4IV.js.map +0 -1
- package/dist/chunk-YAFSTKTH.js.map +0 -1
- /package/dist/{auto-sync-54QQHOG5.js.map → auto-sync-5CJBJMPZ.js.map} +0 -0
- /package/dist/{capsule-crypto-GWVG7LGC.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-QKE4LHNR.js.map → chunk-4HYSMH7D.js.map} +0 -0
- /package/dist/{chunk-DDRNDPX4.js.map → chunk-4SKKVWLQ.js.map} +0 -0
- /package/dist/{chunk-FOVPSMGI.js.map → chunk-7WEB3FLJ.js.map} +0 -0
- /package/dist/{chunk-APJQ6UEA.js.map → chunk-AGNBY3VG.js.map} +0 -0
- /package/dist/{chunk-4BISW7RX.js.map → chunk-AJE7FJVE.js.map} +0 -0
- /package/dist/{chunk-ZXWAQFDE.js.map → chunk-CFOCZPIQ.js.map} +0 -0
- /package/dist/{chunk-NT5TINK5.js.map → chunk-DHGSZ3UD.js.map} +0 -0
- /package/dist/{chunk-OTC2KOZ2.js.map → chunk-EHQLDFSH.js.map} +0 -0
- /package/dist/{chunk-RRRCNIPK.js.map → chunk-GI45G4BK.js.map} +0 -0
- /package/dist/{chunk-AMACWKM4.js.map → chunk-IJHLC5CH.js.map} +0 -0
- /package/dist/{chunk-OR7R6M5Z.js.map → chunk-IVYSVAC6.js.map} +0 -0
- /package/dist/{chunk-76QTEJ2Q.js.map → chunk-JBHXMCYN.js.map} +0 -0
- /package/dist/{chunk-UMKPSD35.js.map → chunk-JF7SFXTG.js.map} +0 -0
- /package/dist/{chunk-TQUWNX7C.js.map → chunk-JX2RINDR.js.map} +0 -0
- /package/dist/{chunk-MCYT2RNT.js.map → chunk-KJDKZVF3.js.map} +0 -0
- /package/dist/{chunk-BUKK5SWA.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-PQFUUXWK.js.map → chunk-KWM33SPU.js.map} +0 -0
- /package/dist/{chunk-A3BS64GV.js.map → chunk-LCC5EZTT.js.map} +0 -0
- /package/dist/{chunk-TVOPSKOK.js.map → chunk-MGGNV3H2.js.map} +0 -0
- /package/dist/{chunk-D6WVJIS3.js.map → chunk-ORGWWNJG.js.map} +0 -0
- /package/dist/{chunk-Z3PZRDLW.js.map → chunk-PRQXUSQV.js.map} +0 -0
- /package/dist/{chunk-IMWFHBG2.js.map → chunk-QWRC7GIO.js.map} +0 -0
- /package/dist/{chunk-U3GQ33JC.js.map → chunk-SLTKP5WJ.js.map} +0 -0
- /package/dist/{chunk-WEPMT6SC.js.map → chunk-V25ZAOSB.js.map} +0 -0
- /package/dist/{chunk-UMTG2BN2.js.map → chunk-V4UDXYGG.js.map} +0 -0
- /package/dist/{chunk-TUMH6EDV.js.map → chunk-WSFNYPAT.js.map} +0 -0
- /package/dist/{chunk-ZT6R3WR3.js.map → chunk-WTI35CVJ.js.map} +0 -0
- /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-ALUZN7BE.js.map → chunk-XMN6MMTU.js.map} +0 -0
- /package/dist/{chunk-A4BTPHIN.js.map → chunk-Y7NWBBHV.js.map} +0 -0
- /package/dist/{chunk-WPCCNSWO.js.map → chunk-YM3LR4LS.js.map} +0 -0
- /package/dist/{chunk-3IJEQWQX.js.map → chunk-YOVKPOMD.js.map} +0 -0
- /package/dist/{chunk-M75TBFKQ.js.map → chunk-Z2OXSMZK.js.map} +0 -0
package/src/qmd.test.ts
CHANGED
|
@@ -183,6 +183,108 @@ test("QmdClient preserves configured qmdPath diagnostics when all probes fail",
|
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
+
test("QmdClient read-only availability failures preserve operational state", async () => {
|
|
187
|
+
const { QmdClient } = await import("./qmd.js");
|
|
188
|
+
const originalPath = process.env.PATH;
|
|
189
|
+
const originalWindowsPath = process.env.Path;
|
|
190
|
+
const missingQmdPath = path.join(
|
|
191
|
+
os.tmpdir(),
|
|
192
|
+
`remnic-missing-readonly-qmd-${process.pid}-${Date.now()}`,
|
|
193
|
+
"qmd.cmd",
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
process.env.PATH = "";
|
|
197
|
+
process.env.Path = "";
|
|
198
|
+
try {
|
|
199
|
+
const client = new QmdClient("test-collection", 10, {
|
|
200
|
+
qmdPath: missingQmdPath,
|
|
201
|
+
qmdFallbackPaths: [],
|
|
202
|
+
});
|
|
203
|
+
(client as any).available = true;
|
|
204
|
+
(client as any).qmdPath = "qmd";
|
|
205
|
+
(client as any).qmdPathSource = "auto-path";
|
|
206
|
+
(client as any).cliVersion = "qmd 2.5.3";
|
|
207
|
+
(client as any).qmdCapabilities = resolveQmdCapabilities("qmd 2.5.3");
|
|
208
|
+
(client as any).lastCliProbeError = null;
|
|
209
|
+
|
|
210
|
+
assert.equal(await client.checkAvailability(), false);
|
|
211
|
+
|
|
212
|
+
assert.equal(client.isAvailable(), true);
|
|
213
|
+
assert.equal((client as any).qmdPath, "qmd");
|
|
214
|
+
assert.equal((client as any).qmdPathSource, "auto-path");
|
|
215
|
+
assert.equal((client as any).cliVersion, "qmd 2.5.3");
|
|
216
|
+
assert.equal((client as any).lastCliProbeError, null);
|
|
217
|
+
} finally {
|
|
218
|
+
if (originalPath === undefined) delete process.env.PATH;
|
|
219
|
+
else process.env.PATH = originalPath;
|
|
220
|
+
if (originalWindowsPath === undefined) delete process.env.Path;
|
|
221
|
+
else process.env.Path = originalWindowsPath;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("QmdClient read-only availability preserves live daemon availability", async () => {
|
|
226
|
+
const { QmdClient } = await import("./qmd.js");
|
|
227
|
+
const originalPath = process.env.PATH;
|
|
228
|
+
const originalWindowsPath = process.env.Path;
|
|
229
|
+
const missingQmdPath = path.join(
|
|
230
|
+
os.tmpdir(),
|
|
231
|
+
`remnic-missing-daemon-qmd-${process.pid}-${Date.now()}`,
|
|
232
|
+
"qmd.cmd",
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
process.env.PATH = "";
|
|
236
|
+
process.env.Path = "";
|
|
237
|
+
try {
|
|
238
|
+
const client = new QmdClient("test-collection", 10, {
|
|
239
|
+
qmdPath: missingQmdPath,
|
|
240
|
+
qmdFallbackPaths: [],
|
|
241
|
+
});
|
|
242
|
+
(client as any).daemonAvailable = true;
|
|
243
|
+
(client as any).daemonSession = { isActive: () => true };
|
|
244
|
+
|
|
245
|
+
assert.equal(await client.checkAvailability(), true);
|
|
246
|
+
assert.equal(client.isAvailable(), true);
|
|
247
|
+
} finally {
|
|
248
|
+
if (originalPath === undefined) delete process.env.PATH;
|
|
249
|
+
else process.env.PATH = originalPath;
|
|
250
|
+
if (originalWindowsPath === undefined) delete process.env.Path;
|
|
251
|
+
else process.env.Path = originalWindowsPath;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test("QmdClient read-only availability clears stale daemon availability", async () => {
|
|
256
|
+
const { QmdClient } = await import("./qmd.js");
|
|
257
|
+
const originalPath = process.env.PATH;
|
|
258
|
+
const originalWindowsPath = process.env.Path;
|
|
259
|
+
const missingQmdPath = path.join(
|
|
260
|
+
os.tmpdir(),
|
|
261
|
+
`remnic-missing-stale-daemon-qmd-${process.pid}-${Date.now()}`,
|
|
262
|
+
"qmd.cmd",
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
process.env.PATH = "";
|
|
266
|
+
process.env.Path = "";
|
|
267
|
+
try {
|
|
268
|
+
const client = new QmdClient("test-collection", 10, {
|
|
269
|
+
qmdPath: missingQmdPath,
|
|
270
|
+
qmdFallbackPaths: [],
|
|
271
|
+
});
|
|
272
|
+
(client as any).daemonAvailable = true;
|
|
273
|
+
(client as any).daemonSession = { isActive: () => false };
|
|
274
|
+
(client as any).lastDaemonCheckAtMs = Date.now();
|
|
275
|
+
|
|
276
|
+
assert.equal(await client.checkAvailability(), false);
|
|
277
|
+
assert.equal(client.isAvailable(), false);
|
|
278
|
+
assert.equal((client as any).daemonAvailable, false);
|
|
279
|
+
assert.equal((client as any).lastDaemonCheckAtMs, 0);
|
|
280
|
+
} finally {
|
|
281
|
+
if (originalPath === undefined) delete process.env.PATH;
|
|
282
|
+
else process.env.PATH = originalPath;
|
|
283
|
+
if (originalWindowsPath === undefined) delete process.env.Path;
|
|
284
|
+
else process.env.Path = originalWindowsPath;
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
186
288
|
test("QmdClient applies chunk strategy to normal and forced embed args", async () => {
|
|
187
289
|
const { QmdClient } = await import("./qmd.js");
|
|
188
290
|
const client = new QmdClient("test", 5, {
|
package/src/qmd.ts
CHANGED
|
@@ -1362,6 +1362,22 @@ export class QmdClient implements SearchBackend {
|
|
|
1362
1362
|
return cliOk || this.daemonAvailable;
|
|
1363
1363
|
}
|
|
1364
1364
|
|
|
1365
|
+
async checkAvailability(execution?: SearchExecutionOptions): Promise<boolean> {
|
|
1366
|
+
const cliAvailable = await this.probeCli({
|
|
1367
|
+
allowAutoUpgrade: false,
|
|
1368
|
+
preserveStateOnFailure: true,
|
|
1369
|
+
signal: execution?.signal,
|
|
1370
|
+
});
|
|
1371
|
+
if (this.daemonAvailable && this.daemonSession?.isActive()) {
|
|
1372
|
+
return true;
|
|
1373
|
+
}
|
|
1374
|
+
if (this.daemonAvailable) {
|
|
1375
|
+
this.daemonAvailable = false;
|
|
1376
|
+
this.lastDaemonCheckAtMs = 0;
|
|
1377
|
+
}
|
|
1378
|
+
return cliAvailable;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1365
1381
|
private async probeDaemon(): Promise<boolean> {
|
|
1366
1382
|
this.lastDaemonCheckAtMs = Date.now();
|
|
1367
1383
|
const normalizedPath = this.qmdPath.trim() || "qmd";
|
|
@@ -1409,7 +1425,32 @@ export class QmdClient implements SearchBackend {
|
|
|
1409
1425
|
}
|
|
1410
1426
|
}
|
|
1411
1427
|
|
|
1412
|
-
private async probeCli(
|
|
1428
|
+
private async probeCli(
|
|
1429
|
+
options: {
|
|
1430
|
+
allowAutoUpgrade?: boolean;
|
|
1431
|
+
preserveStateOnFailure?: boolean;
|
|
1432
|
+
signal?: AbortSignal;
|
|
1433
|
+
} = {},
|
|
1434
|
+
): Promise<boolean> {
|
|
1435
|
+
const priorState = options.preserveStateOnFailure === true
|
|
1436
|
+
? {
|
|
1437
|
+
available: this.available,
|
|
1438
|
+
qmdPath: this.qmdPath,
|
|
1439
|
+
qmdPathSource: this.qmdPathSource,
|
|
1440
|
+
cliVersion: this.cliVersion,
|
|
1441
|
+
lastCliProbeError: this.lastCliProbeError,
|
|
1442
|
+
qmdCapabilities: this.qmdCapabilities,
|
|
1443
|
+
}
|
|
1444
|
+
: null;
|
|
1445
|
+
const restorePriorState = (): void => {
|
|
1446
|
+
if (!priorState) return;
|
|
1447
|
+
this.available = priorState.available;
|
|
1448
|
+
this.qmdPath = priorState.qmdPath;
|
|
1449
|
+
this.qmdPathSource = priorState.qmdPathSource;
|
|
1450
|
+
this.cliVersion = priorState.cliVersion;
|
|
1451
|
+
this.lastCliProbeError = priorState.lastCliProbeError;
|
|
1452
|
+
this.qmdCapabilities = priorState.qmdCapabilities;
|
|
1453
|
+
};
|
|
1413
1454
|
let configuredProbeFailure: string | null = null;
|
|
1414
1455
|
const markProbeFailure = (err: unknown): void => {
|
|
1415
1456
|
this.lastCliProbeError = err instanceof Error ? err.message : String(err);
|
|
@@ -1431,12 +1472,14 @@ export class QmdClient implements SearchBackend {
|
|
|
1431
1472
|
this.cliVersion = parseQmdVersionOutput(result.stdout, result.stderr);
|
|
1432
1473
|
this.qmdCapabilities = resolveQmdCapabilities(this.cliVersion);
|
|
1433
1474
|
this.lastCliProbeError = null;
|
|
1434
|
-
|
|
1475
|
+
if (options.allowAutoUpgrade !== false) {
|
|
1476
|
+
await this.maybeAutoUpgradeQmd();
|
|
1477
|
+
}
|
|
1435
1478
|
};
|
|
1436
1479
|
|
|
1437
1480
|
if (this.configuredQmdPath) {
|
|
1438
1481
|
try {
|
|
1439
|
-
const result = await runQmd(["--version"], QMD_PROBE_TIMEOUT_MS, this.configuredQmdPath,
|
|
1482
|
+
const result = await runQmd(["--version"], QMD_PROBE_TIMEOUT_MS, this.configuredQmdPath, options.signal, this.qmdRuntimeEnv);
|
|
1440
1483
|
await recordProbeSuccess(result, this.configuredQmdPath, "configured");
|
|
1441
1484
|
return true;
|
|
1442
1485
|
} catch (err) {
|
|
@@ -1452,7 +1495,7 @@ export class QmdClient implements SearchBackend {
|
|
|
1452
1495
|
|
|
1453
1496
|
// Try PATH first
|
|
1454
1497
|
try {
|
|
1455
|
-
const result = await runQmd(["--version"], QMD_PROBE_TIMEOUT_MS, "qmd",
|
|
1498
|
+
const result = await runQmd(["--version"], QMD_PROBE_TIMEOUT_MS, "qmd", options.signal, this.qmdRuntimeEnv);
|
|
1456
1499
|
await recordProbeSuccess(result, "qmd", "auto-path");
|
|
1457
1500
|
return true;
|
|
1458
1501
|
} catch (err) {
|
|
@@ -1460,7 +1503,7 @@ export class QmdClient implements SearchBackend {
|
|
|
1460
1503
|
// Try fallback paths
|
|
1461
1504
|
for (const fallbackPath of this.qmdFallbackPaths) {
|
|
1462
1505
|
try {
|
|
1463
|
-
const result = await runQmd(["--version"], QMD_PROBE_TIMEOUT_MS, fallbackPath,
|
|
1506
|
+
const result = await runQmd(["--version"], QMD_PROBE_TIMEOUT_MS, fallbackPath, options.signal, this.qmdRuntimeEnv);
|
|
1464
1507
|
await recordProbeSuccess(result, fallbackPath, "auto-fallback");
|
|
1465
1508
|
log.info(`QMD: found at ${fallbackPath}`);
|
|
1466
1509
|
return true;
|
|
@@ -1469,8 +1512,12 @@ export class QmdClient implements SearchBackend {
|
|
|
1469
1512
|
// Continue to next fallback
|
|
1470
1513
|
}
|
|
1471
1514
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1515
|
+
if (priorState) {
|
|
1516
|
+
restorePriorState();
|
|
1517
|
+
} else {
|
|
1518
|
+
this.available = false;
|
|
1519
|
+
restoreConfiguredProbeFailure();
|
|
1520
|
+
}
|
|
1474
1521
|
return false;
|
|
1475
1522
|
}
|
|
1476
1523
|
}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { buildEvidencePack, type EvidencePackItem } from "./evidence-pack.js";
|
|
2
2
|
import type { ExplicitCueRecallEngine } from "./explicit-cue-recall.js";
|
|
3
|
+
import {
|
|
4
|
+
gatherAcrossReadSessions,
|
|
5
|
+
resolveLcmReadSessionIds,
|
|
6
|
+
} from "./lcm-fallback-read.js";
|
|
3
7
|
|
|
4
8
|
export interface ResponseGuidanceRecallOptions {
|
|
5
9
|
engine: ExplicitCueRecallEngine | null | undefined;
|
|
6
10
|
sessionId?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Ordered, read-authorized LCM read key set (primary overlay → project/root
|
|
13
|
+
* fallbacks). When present, evidence is gathered across EVERY key and merged
|
|
14
|
+
* under this section's budget (#1505 codex P2). Falls back to `sessionId`.
|
|
15
|
+
*/
|
|
16
|
+
sessionIds?: readonly (string | undefined)[];
|
|
7
17
|
query: string;
|
|
8
18
|
maxChars: number;
|
|
9
19
|
maxItemChars?: number;
|
|
@@ -157,7 +167,17 @@ export async function buildResponseGuidanceRecallSection(
|
|
|
157
167
|
) {
|
|
158
168
|
return "";
|
|
159
169
|
}
|
|
160
|
-
|
|
170
|
+
// #1505 codex P2: gather candidates across the ordered LCM read key set
|
|
171
|
+
// (primary overlay → project/root fallbacks) and UNION them into the existing
|
|
172
|
+
// rank/dedupe/budget pass, so stronger project-fallback guidance is not masked
|
|
173
|
+
// by a weak primary-key hit. `gatherAcrossReadSessions` isolates a per-key read
|
|
174
|
+
// failure so a corrupt/locked fallback index can't discard the primary key's
|
|
175
|
+
// guidance; the single-key path collects exactly once and propagates a failure
|
|
176
|
+
// as before — byte-for-byte the pre-#1505 behavior.
|
|
177
|
+
const items: EvidencePackItem[] = [];
|
|
178
|
+
await gatherAcrossReadSessions(resolveLcmReadSessionIds(options), async (sessionId) => {
|
|
179
|
+
items.push(...(await collectGuidanceItems({ ...options, sessionId }, intents)));
|
|
180
|
+
});
|
|
161
181
|
const ranked = rankAndDedupeGuidanceItems(items, options.query, intents)
|
|
162
182
|
.slice(0, maxResults);
|
|
163
183
|
if (ranked.length === 0) {
|
package/src/search/port.ts
CHANGED
|
@@ -42,6 +42,12 @@ export function resolveEnsureCollectionArgs(
|
|
|
42
42
|
export interface SearchBackend {
|
|
43
43
|
// ── Lifecycle ──
|
|
44
44
|
probe(): Promise<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* Optional non-mutating availability probe for health/readiness checks.
|
|
47
|
+
* Implementations must avoid auto-upgrades, collection creation, daemon
|
|
48
|
+
* startup, or any other runtime-modifying side effects.
|
|
49
|
+
*/
|
|
50
|
+
checkAvailability?(execution?: SearchExecutionOptions): Promise<boolean>;
|
|
45
51
|
isAvailable(): boolean;
|
|
46
52
|
debugStatus(): string;
|
|
47
53
|
|
|
@@ -4,10 +4,20 @@ import {
|
|
|
4
4
|
type EvidencePackItem,
|
|
5
5
|
} from "./evidence-pack.js";
|
|
6
6
|
import type { ExplicitCueRecallEngine } from "./explicit-cue-recall.js";
|
|
7
|
+
import {
|
|
8
|
+
gatherAcrossReadSessions,
|
|
9
|
+
resolveLcmReadSessionIds,
|
|
10
|
+
} from "./lcm-fallback-read.js";
|
|
7
11
|
|
|
8
12
|
export interface TargetedFactRecallOptions {
|
|
9
13
|
engine: ExplicitCueRecallEngine | null | undefined;
|
|
10
14
|
sessionId?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Ordered, read-authorized LCM read key set (primary overlay → project/root
|
|
17
|
+
* fallbacks). When present, evidence is gathered across EVERY key and merged
|
|
18
|
+
* under this section's budget (#1505 codex P2). Falls back to `sessionId`.
|
|
19
|
+
*/
|
|
20
|
+
sessionIds?: readonly (string | undefined)[];
|
|
11
21
|
query: string;
|
|
12
22
|
maxChars: number;
|
|
13
23
|
maxItemChars?: number;
|
|
@@ -43,10 +53,21 @@ export async function buildTargetedFactRecallSection(
|
|
|
43
53
|
return "";
|
|
44
54
|
}
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
// #1505 codex P2: gather candidates across the ordered LCM read key set
|
|
57
|
+
// (primary overlay → project/root fallbacks) and UNION them into the existing
|
|
58
|
+
// rank/dedupe/budget pass, so stronger project-fallback evidence is not masked
|
|
59
|
+
// by a weak primary-key hit. `gatherAcrossReadSessions` isolates a per-key read
|
|
60
|
+
// failure so a corrupt/locked fallback index can't discard the primary key's
|
|
61
|
+
// evidence; the single-key path collects exactly one search+scan pair and
|
|
62
|
+
// propagates a failure as before — byte-for-byte the pre-#1505 behavior.
|
|
63
|
+
const collected: EvidencePackItem[] = [];
|
|
64
|
+
await gatherAcrossReadSessions(resolveLcmReadSessionIds(options), async (sessionId) => {
|
|
65
|
+
const scoped = { ...options, sessionId };
|
|
66
|
+
collected.push(...(await collectTargetedFactSearchItems(scoped)));
|
|
67
|
+
collected.push(...(await collectTargetedFactScanItems(scoped)));
|
|
68
|
+
});
|
|
48
69
|
const ranked = rankAndDedupeTargetedFactItems(
|
|
49
|
-
|
|
70
|
+
collected,
|
|
50
71
|
options.query,
|
|
51
72
|
).slice(0, maxResults);
|
|
52
73
|
|