@remnic/core 9.25.6 → 9.25.7

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 (45) hide show
  1. package/dist/access-admin-ops-surface.d.ts +2 -2
  2. package/dist/access-authorization-probe.d.ts +2 -2
  3. package/dist/access-boundary.d.ts +2 -2
  4. package/dist/access-cli.js +1 -1
  5. package/dist/access-http.d.ts +2 -2
  6. package/dist/access-identity-continuity-surface.d.ts +1 -1
  7. package/dist/access-lcm-surface.d.ts +2 -2
  8. package/dist/access-mcp.d.ts +2 -2
  9. package/dist/access-observe-write-surface.d.ts +2 -2
  10. package/dist/access-operations.d.ts +5 -5
  11. package/dist/access-recall-concurrency.d.ts +2 -2
  12. package/dist/access-recall-response.d.ts +2 -2
  13. package/dist/access-recall-surface.d.ts +2 -2
  14. package/dist/access-schema.d.ts +76 -76
  15. package/dist/{access-service-BJQ22URi.d.ts → access-service-CIdWkP6J.d.ts} +1 -1
  16. package/dist/access-service.d.ts +2 -2
  17. package/dist/access-surface-catalog.d.ts +2 -2
  18. package/dist/bootstrap.d.ts +1 -1
  19. package/dist/{chunk-FR75B4UU.js → chunk-KZVPTJNZ.js} +334 -647
  20. package/dist/chunk-KZVPTJNZ.js.map +1 -0
  21. package/dist/{cli-1W7cNjJJ.d.ts → cli-Da5kesWC.d.ts} +2 -2
  22. package/dist/cli.d.ts +3 -3
  23. package/dist/explicit-capture.d.ts +1 -1
  24. package/dist/index.d.ts +392 -392
  25. package/dist/index.js +1 -1
  26. package/dist/mcp-memory-inspector-app.d.ts +2 -2
  27. package/dist/{orchestrator-BtA1wC5K.d.ts → orchestrator-CFJ_TG6D.d.ts} +15 -10
  28. package/dist/orchestrator.d.ts +1 -1
  29. package/dist/orchestrator.js +1 -1
  30. package/dist/schemas.d.ts +76 -76
  31. package/dist/shared-context/manager.d.ts +8 -8
  32. package/dist/transfer/types.d.ts +66 -66
  33. package/package.json +2 -2
  34. package/src/meetings/recall-exclusion.test.ts +4 -2
  35. package/src/orchestration/generic-recall-paths.ts +119 -0
  36. package/src/orchestration/namespace-read-fanout.ts +0 -12
  37. package/src/orchestration/orchestrator-helpers.ts +0 -35
  38. package/src/orchestration/recall-internal.ts +6 -6
  39. package/src/orchestration/recall-search-pipeline.test.ts +194 -28
  40. package/src/orchestration/recall-search-pipeline.ts +39 -89
  41. package/src/orchestrator.ts +5 -17
  42. package/src/recall-cold-deadline.test.ts +11 -13
  43. package/src/testing/subjects/generic-recall-paths.test.ts +157 -0
  44. package/dist/chunk-FR75B4UU.js.map +0 -1
  45. package/src/recall/archive-scoring.ts +0 -544
@@ -4,7 +4,7 @@
4
4
  * Pins the task-level cancellation contract of runColdStepWithinDeadline
5
5
  * inside RecallSearchPipelineCoordinator.applyColdFallbackPipeline:
6
6
  * - when the per-step deadline wins, the losing cold task's INJECTED signal
7
- * is aborted (so an orphaned archive scan stops cooperatively) and the
7
+ * is aborted so an orphaned query-aware fallback stops cooperatively; the
8
8
  * step returns its fallback (fail-open);
9
9
  * - a task-level deadline must NOT abort the request-level signal;
10
10
  * - a task that completes normally (no deadline) never aborts the injected
@@ -37,24 +37,22 @@ async function coldConfig() {
37
37
  }
38
38
 
39
39
  /**
40
- * Minimal deps for the archive-scan branch. qmd.isAvailable() === false forces
41
- * the cold-qmd block to be skipped, so control reaches the archive-scan step;
42
- * an empty archive result returns [] before any namespace/storage-router work,
43
- * keeping the stub surface tight. The cast is a deliberate test double.
40
+ * Minimal dependencies for the query-aware fallback. QMD is unavailable, so
41
+ * the cold-QMD branch is skipped and the injected fallback step is observed.
44
42
  */
45
43
  function coldDeps(
46
44
  config: PluginConfig,
47
- searchLongTermArchiveFallback: RecallSearchPipelineDeps["searchLongTermArchiveFallback"],
45
+ searchQueryAwareFallback: RecallSearchPipelineDeps["searchQueryAwareFallback"],
48
46
  ): RecallSearchPipelineDeps {
49
47
  return {
50
48
  config,
51
49
  qmd: { isAvailable: () => false },
52
50
  namespaceFromPath: () => "default",
53
- searchLongTermArchiveFallback,
51
+ searchQueryAwareFallback,
54
52
  } as unknown as RecallSearchPipelineDeps;
55
53
  }
56
54
 
57
- test("#1907: cold archive-scan deadline aborts the injected step signal, returns fallback, leaves the request signal intact", async () => {
55
+ test("#1907: query-aware fallback deadline aborts the injected step signal, returns fallback, leaves the request signal intact", async () => {
58
56
  const { memoryDir, config } = await coldConfig();
59
57
  try {
60
58
  const stuck = Promise.withResolvers<QmdSearchResult[]>();
@@ -65,7 +63,7 @@ test("#1907: cold archive-scan deadline aborts the injected step signal, returns
65
63
  // so the late completion leaks "late" here and the assertion below fails.
66
64
  const lateWrites: string[] = [];
67
65
  const abandonedTaskSettled = Promise.withResolvers<void>();
68
- const deps = coldDeps(config, async (_prompt, _ns, _limit, _prefilter, abortSignal) => {
66
+ const deps = coldDeps(config, async (_prompt, _limit, _prefilter, abortSignal) => {
69
67
  capturedStepSignal = abortSignal;
70
68
  const late = await stuck.promise; // does not settle before the deadline wins
71
69
  if (!abortSignal?.aborted) {
@@ -87,7 +85,7 @@ test("#1907: cold archive-scan deadline aborts the injected step signal, returns
87
85
  });
88
86
 
89
87
  assert.deepEqual(result, [], "the step returns its fallback when the deadline wins");
90
- assert.ok(capturedStepSignal, "archive scan received an injected step signal");
88
+ assert.ok(capturedStepSignal, "query-aware fallback received an injected step signal");
91
89
  assert.equal(
92
90
  capturedStepSignal!.aborted,
93
91
  true,
@@ -119,7 +117,7 @@ test("#1907: a cold step that completes before its deadline never aborts the inj
119
117
  const { memoryDir, config } = await coldConfig();
120
118
  try {
121
119
  let capturedStepSignal: AbortSignal | undefined;
122
- const deps = coldDeps(config, async (_prompt, _ns, _limit, _prefilter, abortSignal) => {
120
+ const deps = coldDeps(config, async (_prompt, _limit, _prefilter, abortSignal) => {
123
121
  capturedStepSignal = abortSignal;
124
122
  return []; // resolves immediately, well within the deadline
125
123
  });
@@ -135,8 +133,8 @@ test("#1907: a cold step that completes before its deadline never aborts the inj
135
133
  abortSignal: requestController.signal,
136
134
  });
137
135
 
138
- assert.deepEqual(result, [], "empty archive returns []");
139
- assert.ok(capturedStepSignal, "archive scan received an injected step signal");
136
+ assert.deepEqual(result, [], "empty query-aware fallback returns []");
137
+ assert.ok(capturedStepSignal, "query-aware fallback received an injected step signal");
140
138
  assert.equal(
141
139
  capturedStepSignal!.aborted,
142
140
  false,
@@ -0,0 +1,157 @@
1
+ import assert from "node:assert/strict";
2
+
3
+ import { Orchestrator } from "../../orchestrator.js";
4
+ import type { SearchBackend } from "../../search/port.js";
5
+ import type { MemoryFile, PluginConfig, QmdSearchResult } from "../../types.js";
6
+ import {
7
+ cleanupDir,
8
+ makeLifecycleConfig,
9
+ mkTempMemoryDir,
10
+ singleFactResult,
11
+ stubExtraction,
12
+ } from "../orchestrator-lite.js";
13
+ import {
14
+ type LifecycleSubject,
15
+ type MatrixRow,
16
+ runLifecycleMatrix,
17
+ } from "../lifecycle-matrix.js";
18
+
19
+ interface QmdSeam {
20
+ qmd: SearchBackend;
21
+ }
22
+
23
+ interface GenericRecallPathState {
24
+ readonly memoryDir: string;
25
+ orchestrator: Orchestrator;
26
+ readonly config: PluginConfig;
27
+ readonly archivePath: string;
28
+ readonly activePath: string;
29
+ readonly candidates: QmdSearchResult[];
30
+ recalled?: string;
31
+ }
32
+
33
+ function installQmd(orchestrator: Orchestrator, candidates: QmdSearchResult[]): void {
34
+ const seam = orchestrator as unknown as QmdSeam;
35
+ seam.qmd = {
36
+ isAvailable: () => true,
37
+ debugStatus: () => "lifecycle-test-qmd",
38
+ search: async () => candidates,
39
+ hybridSearch: async () => candidates,
40
+ } as unknown as SearchBackend;
41
+ }
42
+
43
+ function result(memory: MemoryFile, score: number): QmdSearchResult {
44
+ return {
45
+ docid: memory.frontmatter.id,
46
+ path: memory.path,
47
+ score,
48
+ snippet: memory.content,
49
+ };
50
+ }
51
+
52
+ const subject: LifecycleSubject<GenericRecallPathState> = {
53
+ async setup(row: MatrixRow): Promise<GenericRecallPathState> {
54
+ const memoryDir = await mkTempMemoryDir(`generic-recall-${row.id}`);
55
+ let orchestrator: Orchestrator | undefined;
56
+ try {
57
+ const config = makeLifecycleConfig(memoryDir, {
58
+ qmdEnabled: true,
59
+ qmdSearchStrategy: "lex",
60
+ });
61
+ orchestrator = new Orchestrator(config);
62
+ stubExtraction(orchestrator, () => singleFactResult(`replay-${row.id}`));
63
+ const storage = await orchestrator.getStorage();
64
+ const archivedWrite = await storage.writeMemory(
65
+ "fact",
66
+ `archived candidate for ${row.id}`,
67
+ );
68
+ const archivedMemory = await storage.getMemoryById(archivedWrite.id);
69
+ assert.ok(archivedMemory);
70
+ const archivePath = await storage.archiveMemory(archivedMemory);
71
+ assert.ok(archivePath);
72
+
73
+ const activeWrite = await storage.writeMemory(
74
+ "fact",
75
+ `active candidate for ${row.id}`,
76
+ );
77
+ const activeMemory = await storage.getMemoryById(activeWrite.id);
78
+ assert.ok(activeMemory);
79
+ const candidates = [
80
+ result({ ...archivedMemory, path: archivePath }, 1),
81
+ result(activeMemory, 0.9),
82
+ ];
83
+ installQmd(orchestrator, candidates);
84
+ return {
85
+ memoryDir,
86
+ orchestrator,
87
+ config,
88
+ archivePath,
89
+ activePath: activeMemory.path,
90
+ candidates,
91
+ };
92
+ } catch (error) {
93
+ await orchestrator?.destroy().catch(() => undefined);
94
+ await cleanupDir(memoryDir);
95
+ throw error;
96
+ }
97
+ },
98
+
99
+ async exercise(state, row): Promise<void> {
100
+ const sessionKey = `generic-recall-${row.id}`;
101
+ if (row.dimensions.flush !== "none") {
102
+ await state.orchestrator.flushSession(sessionKey, {
103
+ reason: row.dimensions.flush,
104
+ });
105
+ }
106
+ if (row.dimensions.restart) {
107
+ await state.orchestrator.destroy();
108
+ state.orchestrator = new Orchestrator(state.config);
109
+ installQmd(state.orchestrator, state.candidates);
110
+ }
111
+ if (
112
+ row.dimensions.providerIdentity === "explicit" ||
113
+ (row.dimensions.providerIdentity === "sparse" && row.dimensions.rememberedBinding)
114
+ ) {
115
+ state.orchestrator.setPeerIdForSession(sessionKey, "remembered-provider");
116
+ } else if (row.dimensions.providerIdentity === "rebound") {
117
+ state.orchestrator.setPeerIdForSession(sessionKey, "provider-a");
118
+ state.orchestrator.setPeerIdForSession(sessionKey, "provider-b");
119
+ }
120
+ if (row.dimensions.dedupeOrReplay) {
121
+ const replayTurn = {
122
+ source: "openclaw" as const,
123
+ sessionKey,
124
+ role: "user" as const,
125
+ content: "replayed candidate",
126
+ timestamp: "2026-07-25T00:00:00.000Z",
127
+ };
128
+ await state.orchestrator.ingestReplayBatch(
129
+ [replayTurn, { ...replayTurn }],
130
+ { archiveLcm: false },
131
+ );
132
+ }
133
+ state.recalled = await state.orchestrator.recall("candidate", sessionKey);
134
+ },
135
+
136
+ async invariants(state): Promise<void> {
137
+ assert.match(state.recalled ?? "", /active candidate/);
138
+ assert.doesNotMatch(state.recalled ?? "", /archived candidate/);
139
+ assert.equal(
140
+ state.candidates[0]?.path,
141
+ state.archivePath,
142
+ "the QMD fixture must put the archived memory ahead of the active hit",
143
+ );
144
+ assert.equal(
145
+ state.candidates[1]?.path,
146
+ state.activePath,
147
+ "the QMD fixture must include the persisted active memory",
148
+ );
149
+ },
150
+
151
+ async teardown(state): Promise<void> {
152
+ await state.orchestrator.destroy();
153
+ await cleanupDir(state.memoryDir);
154
+ },
155
+ };
156
+
157
+ runLifecycleMatrix("generic-recall-paths", subject);