@remnic/core 9.3.727 → 9.3.729
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-boundary.d.ts +2 -2
- package/dist/access-boundary.js +6 -6
- package/dist/access-cli.js +11 -11
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +10 -10
- package/dist/access-mcp.d.ts +2 -2
- package/dist/access-mcp.js +9 -9
- package/dist/access-operations-batch.js +7 -7
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +8 -8
- package/dist/access-schema.d.ts +46 -46
- package/dist/{access-service-Bgpjxo4f.d.ts → access-service-BXMJqkTA.d.ts} +1 -1
- package/dist/access-service.d.ts +2 -2
- package/dist/access-service.js +5 -5
- package/dist/access-surface-catalog.d.ts +2 -2
- package/dist/bootstrap.d.ts +1 -1
- package/dist/capabilities.d.ts +43 -1
- package/dist/capabilities.js +5 -3
- package/dist/{chunk-DVRHLN2O.js → chunk-3RCBIOOJ.js} +18 -2
- package/dist/{chunk-DVRHLN2O.js.map → chunk-3RCBIOOJ.js.map} +1 -1
- package/dist/{chunk-R7IYU5DZ.js → chunk-4ESAR77N.js} +2 -2
- package/dist/{chunk-SNKPUJHR.js → chunk-76NHR6ZL.js} +3 -3
- package/dist/{chunk-6PY5YJAV.js → chunk-BQCHEV7O.js} +8 -3
- package/dist/{chunk-6PY5YJAV.js.map → chunk-BQCHEV7O.js.map} +1 -1
- package/dist/{chunk-ZA2S2VLL.js → chunk-C2PG7IEH.js} +5 -2
- package/dist/chunk-C2PG7IEH.js.map +1 -0
- package/dist/{chunk-MJIHJ7OG.js → chunk-H5BWGCRZ.js} +11 -10
- package/dist/chunk-H5BWGCRZ.js.map +1 -0
- package/dist/{chunk-XPHVAOBT.js → chunk-HEDZUSCS.js} +180 -101
- package/dist/chunk-HEDZUSCS.js.map +1 -0
- package/dist/{chunk-N3VNUM4Z.js → chunk-HGNOCPZX.js} +4 -4
- package/dist/{chunk-CSRXQ6NB.js → chunk-I5REUWLH.js} +10 -4
- package/dist/chunk-I5REUWLH.js.map +1 -0
- package/dist/{chunk-NSA5ZRUL.js → chunk-M4AYVEWS.js} +3 -3
- package/dist/{chunk-OEEW4KJA.js → chunk-O6YH5F47.js} +3 -3
- package/dist/{chunk-27QQC7ZX.js → chunk-UM5AWJNQ.js} +6 -5
- package/dist/chunk-UM5AWJNQ.js.map +1 -0
- package/dist/{chunk-2KAYTPPT.js → chunk-UTHQPSRC.js} +2 -2
- package/dist/{chunk-CTOQEZSN.js → chunk-V4GNSDFH.js} +2 -2
- package/dist/{chunk-EHISUJFN.js → chunk-WAS3NV46.js} +6 -3
- package/dist/chunk-WAS3NV46.js.map +1 -0
- package/dist/{chunk-DKJCRGWM.js → chunk-YGIQORJ3.js} +2 -2
- package/dist/{cli-BLME420h.d.ts → cli-DmAiDd8A.d.ts} +2 -2
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +13 -13
- package/dist/embedding-fallback.js +2 -1
- package/dist/explicit-capture.d.ts +1 -1
- package/dist/extraction.js +2 -1
- package/dist/{first-start-migration-PG5HBC3K.js → first-start-migration-22LPFHD5.js} +6 -2
- package/dist/first-start-migration-22LPFHD5.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +16 -16
- package/dist/mcp-memory-inspector-app.d.ts +2 -2
- package/dist/namespaces/migrate.js +5 -4
- package/dist/namespaces/search.js +4 -3
- package/dist/operator-toolkit.js +6 -6
- package/dist/{orchestrator-DqPAz8ot.d.ts → orchestrator-BR0sGsME.d.ts} +104 -26
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.js +7 -7
- package/dist/schemas.d.ts +74 -74
- package/dist/search/embed-helper.js +2 -1
- package/dist/search/factory.js +3 -2
- package/dist/search/index.js +3 -2
- package/dist/shared-context/manager.d.ts +2 -2
- package/dist/transfer/types.d.ts +12 -12
- package/package.json +2 -2
- package/src/access-service.ts +2 -1
- package/src/capabilities.test.ts +155 -0
- package/src/capabilities.ts +91 -0
- package/src/chat/chat-engine.test.ts +39 -1
- package/src/chat/chat-session.ts +25 -2
- package/src/cli.ts +3 -2
- package/src/embedding-fallback.ts +2 -1
- package/src/extraction.ts +7 -3
- package/src/maintenance/first-start-migration.ts +3 -1
- package/src/orchestration/extraction-queue-coordinator.ts +175 -0
- package/src/orchestrator-extraction-queue.test.ts +26 -38
- package/src/orchestrator-flush.test.ts +10 -15
- package/src/orchestrator.ts +52 -104
- package/src/search/embed-helper.ts +3 -2
- package/dist/chunk-27QQC7ZX.js.map +0 -1
- package/dist/chunk-CSRXQ6NB.js.map +0 -1
- package/dist/chunk-EHISUJFN.js.map +0 -1
- package/dist/chunk-MJIHJ7OG.js.map +0 -1
- package/dist/chunk-XPHVAOBT.js.map +0 -1
- package/dist/chunk-ZA2S2VLL.js.map +0 -1
- package/dist/first-start-migration-PG5HBC3K.js.map +0 -1
- /package/dist/{chunk-R7IYU5DZ.js.map → chunk-4ESAR77N.js.map} +0 -0
- /package/dist/{chunk-SNKPUJHR.js.map → chunk-76NHR6ZL.js.map} +0 -0
- /package/dist/{chunk-N3VNUM4Z.js.map → chunk-HGNOCPZX.js.map} +0 -0
- /package/dist/{chunk-NSA5ZRUL.js.map → chunk-M4AYVEWS.js.map} +0 -0
- /package/dist/{chunk-OEEW4KJA.js.map → chunk-O6YH5F47.js.map} +0 -0
- /package/dist/{chunk-2KAYTPPT.js.map → chunk-UTHQPSRC.js.map} +0 -0
- /package/dist/{chunk-CTOQEZSN.js.map → chunk-V4GNSDFH.js.map} +0 -0
- /package/dist/{chunk-DKJCRGWM.js.map → chunk-YGIQORJ3.js.map} +0 -0
package/src/orchestrator.ts
CHANGED
|
@@ -99,6 +99,7 @@ import {
|
|
|
99
99
|
} from "./fallback-llm.js";
|
|
100
100
|
import { MaintenanceScheduler } from "./orchestration/maintenance.js";
|
|
101
101
|
import { TierMigrationCoordinator } from "./orchestration/tier-migration-coordinator.js";
|
|
102
|
+
import { ExtractionQueueCoordinator } from "./orchestration/extraction-queue-coordinator.js";
|
|
102
103
|
import {
|
|
103
104
|
runLiveConnectorsOnce,
|
|
104
105
|
type LiveConnectorsRunSummary,
|
|
@@ -171,7 +172,6 @@ import {
|
|
|
171
172
|
import { SessionObserverState } from "./session-observer-state.js";
|
|
172
173
|
import {
|
|
173
174
|
abortError as sharedAbortError,
|
|
174
|
-
isAbortError,
|
|
175
175
|
throwIfAborted as sharedThrowIfAborted,
|
|
176
176
|
} from "./abort-error.js";
|
|
177
177
|
import { CODEX_THREAD_KEY_PREFIX } from "./thread-key.js";
|
|
@@ -269,8 +269,10 @@ import { tryDirectAnswer, type DirectAnswerSources } from "./direct-answer-wirin
|
|
|
269
269
|
import {
|
|
270
270
|
resolveCapabilities,
|
|
271
271
|
resolveGraphConstructionCapabilities,
|
|
272
|
+
resolveMemoryLifecycleCapabilities,
|
|
272
273
|
type CapabilitySet,
|
|
273
274
|
type GraphConstructionCapabilitySet,
|
|
275
|
+
type MemoryLifecycleCapabilitySet,
|
|
274
276
|
} from "./capabilities.js";
|
|
275
277
|
import { DEFAULT_TAXONOMY } from "./taxonomy/index.js";
|
|
276
278
|
import {
|
|
@@ -2019,10 +2021,14 @@ export class Orchestrator {
|
|
|
2019
2021
|
suppressedReasonCounts: Record<string, number>;
|
|
2020
2022
|
} = { detected: 0, queued: 0, autoApplied: 0, suppressedReasonCounts: {} };
|
|
2021
2023
|
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2024
|
+
/**
|
|
2025
|
+
* Background serial extraction queue coordinator (issue #1526 — moved
|
|
2026
|
+
* from inline `extractionQueue`/`queueProcessing` fields). Owns queue
|
|
2027
|
+
* state + scheduling + the serial drain + failure classification; the
|
|
2028
|
+
* orchestrator builds each task closure in `queueBufferedExtraction` and
|
|
2029
|
+
* hands it to `enqueue`.
|
|
2030
|
+
*/
|
|
2031
|
+
readonly extractionQueueCoordinator: ExtractionQueueCoordinator;
|
|
2026
2032
|
private heartbeatObserverChains = new Map<string, Promise<void>>();
|
|
2027
2033
|
private recentExtractionFingerprints = new Map<string, number>();
|
|
2028
2034
|
private readonly consolidationObservers = new Set<
|
|
@@ -2989,6 +2995,8 @@ export class Orchestrator {
|
|
|
2989
2995
|
namespaceSearchRouter: this.namespaceSearchRouter,
|
|
2990
2996
|
namespaceCatalog: this.namespaceCatalog,
|
|
2991
2997
|
});
|
|
2998
|
+
// Issue #1526: background extraction queue lives on its own coordinator.
|
|
2999
|
+
this.extractionQueueCoordinator = new ExtractionQueueCoordinator();
|
|
2992
3000
|
const conversationIndexRuntime = createConversationIndexRuntime(config, {
|
|
2993
3001
|
getQmd: () => this.conversationQmd,
|
|
2994
3002
|
getFaiss: () => this.conversationFaiss,
|
|
@@ -3094,9 +3102,10 @@ export class Orchestrator {
|
|
|
3094
3102
|
);
|
|
3095
3103
|
// BoxBuilders are created per-namespace on first use in runExtraction().
|
|
3096
3104
|
|
|
3105
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
|
|
3097
3106
|
// Temporal Memory Tree (v8.2) — lazy build during consolidation
|
|
3098
3107
|
this.tmtBuilder = new TmtBuilder(config.memoryDir, {
|
|
3099
|
-
temporalMemoryTreeEnabled:
|
|
3108
|
+
temporalMemoryTreeEnabled: lifecycleCaps.temporalMemoryTree,
|
|
3100
3109
|
tmtHourlyMinMemories: config.tmtHourlyMinMemories,
|
|
3101
3110
|
tmtSummaryMaxTokens: config.tmtSummaryMaxTokens,
|
|
3102
3111
|
});
|
|
@@ -3654,6 +3663,7 @@ export class Orchestrator {
|
|
|
3654
3663
|
}
|
|
3655
3664
|
|
|
3656
3665
|
private async deferredInitialize(signal: AbortSignal): Promise<void> {
|
|
3666
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
3657
3667
|
|
|
3658
3668
|
// Sync QMD index with current disk state so recall finds recently-written
|
|
3659
3669
|
// facts. Without this, the index stays stale from the last extraction-
|
|
@@ -3707,7 +3717,7 @@ export class Orchestrator {
|
|
|
3707
3717
|
}),
|
|
3708
3718
|
);
|
|
3709
3719
|
}
|
|
3710
|
-
if (this.config.
|
|
3720
|
+
if (resolveMemoryLifecycleCapabilities(this.config).embeddingFallback) {
|
|
3711
3721
|
warmupPromises.push(
|
|
3712
3722
|
this.embeddingFallback
|
|
3713
3723
|
.isAvailable()
|
|
@@ -3792,7 +3802,7 @@ export class Orchestrator {
|
|
|
3792
3802
|
// sweep (capped at 50 demotions) so the hot tier isn't flooded on the
|
|
3793
3803
|
// first real cron pass. Non-fatal — a failure here must not break init.
|
|
3794
3804
|
if (signal.aborted) return;
|
|
3795
|
-
if (
|
|
3805
|
+
if (lifecycleCaps.lifecyclePolicy && this.config.qmdTierMigrationEnabled) {
|
|
3796
3806
|
try {
|
|
3797
3807
|
const { runFirstStartMigration } = await import(
|
|
3798
3808
|
"./maintenance/first-start-migration.js"
|
|
@@ -4117,6 +4127,7 @@ export class Orchestrator {
|
|
|
4117
4127
|
* default storage.
|
|
4118
4128
|
*/
|
|
4119
4129
|
async runLifecyclePolicyFanout(): Promise<NamespaceMaintenanceSummary> {
|
|
4130
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
4120
4131
|
return this.runNamespaceMaintenanceFanoutForJob(
|
|
4121
4132
|
"lifecycle",
|
|
4122
4133
|
async (ctx) => {
|
|
@@ -4125,7 +4136,7 @@ export class Orchestrator {
|
|
|
4125
4136
|
const assessed = await this.runLifecyclePolicyPass(corpus, storage);
|
|
4126
4137
|
return { itemCount: assessed };
|
|
4127
4138
|
},
|
|
4128
|
-
{ enabled:
|
|
4139
|
+
{ enabled: lifecycleCaps.lifecyclePolicy },
|
|
4129
4140
|
);
|
|
4130
4141
|
}
|
|
4131
4142
|
|
|
@@ -4715,15 +4726,8 @@ export class Orchestrator {
|
|
|
4715
4726
|
}
|
|
4716
4727
|
|
|
4717
4728
|
async waitForExtractionIdle(timeoutMs: number = 60_000): Promise<boolean> {
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
if (Date.now() - started > timeoutMs) {
|
|
4721
|
-
log.warn(`waitForExtractionIdle timed out after ${timeoutMs}ms`);
|
|
4722
|
-
return false;
|
|
4723
|
-
}
|
|
4724
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
4725
|
-
}
|
|
4726
|
-
return true;
|
|
4729
|
+
// Issue #1526: queue state + idle wait moved to ExtractionQueueCoordinator.
|
|
4730
|
+
return this.extractionQueueCoordinator.waitForIdle(timeoutMs);
|
|
4727
4731
|
}
|
|
4728
4732
|
|
|
4729
4733
|
async waitForConsolidationIdle(timeoutMs: number = 60_000): Promise<boolean> {
|
|
@@ -7438,6 +7442,7 @@ export class Orchestrator {
|
|
|
7438
7442
|
options: RecallInvocationOptions = {},
|
|
7439
7443
|
caps: CapabilitySet = resolveCapabilities(this.config),
|
|
7440
7444
|
graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.config),
|
|
7445
|
+
lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.config),
|
|
7441
7446
|
): Promise<string> {
|
|
7442
7447
|
const recallStart = Date.now();
|
|
7443
7448
|
// Backend degradations observed by this recall's QMD searches (#1536):
|
|
@@ -10845,9 +10850,9 @@ export class Orchestrator {
|
|
|
10845
10850
|
if (
|
|
10846
10851
|
this.isRecallSectionEnabled(
|
|
10847
10852
|
"temporal-memory-tree",
|
|
10848
|
-
|
|
10853
|
+
lifecycleCaps.temporalMemoryTree,
|
|
10849
10854
|
) &&
|
|
10850
|
-
|
|
10855
|
+
lifecycleCaps.temporalMemoryTree &&
|
|
10851
10856
|
recallMode !== "minimal" &&
|
|
10852
10857
|
(recallMode as RecallPlanMode) !== "no_recall"
|
|
10853
10858
|
) {
|
|
@@ -11707,7 +11712,7 @@ export class Orchestrator {
|
|
|
11707
11712
|
// Using the shared gate fixes both Finding 2 and Finding 3 from
|
|
11708
11713
|
// PR #402 (round 6).
|
|
11709
11714
|
const supersessionOptions = {
|
|
11710
|
-
enabled:
|
|
11715
|
+
enabled: lifecycleCaps.temporalSupersession,
|
|
11711
11716
|
includeInRecall: this.config.temporalSupersessionIncludeInRecall,
|
|
11712
11717
|
};
|
|
11713
11718
|
// Cursor Medium on PR #713: when `as_of` is active, the
|
|
@@ -13159,7 +13164,7 @@ export class Orchestrator {
|
|
|
13159
13164
|
}, remainingMs);
|
|
13160
13165
|
}
|
|
13161
13166
|
|
|
13162
|
-
this.
|
|
13167
|
+
this.extractionQueueCoordinator.enqueue(async () => {
|
|
13163
13168
|
if (settled) return;
|
|
13164
13169
|
if (
|
|
13165
13170
|
typeof extractionDeadlineMs === "number" &&
|
|
@@ -13190,13 +13195,6 @@ export class Orchestrator {
|
|
|
13190
13195
|
}
|
|
13191
13196
|
});
|
|
13192
13197
|
|
|
13193
|
-
if (!this.queueProcessing) {
|
|
13194
|
-
this.queueProcessing = true;
|
|
13195
|
-
this.processQueue().catch((err) => {
|
|
13196
|
-
this.logExtractionQueueFailure(err, "processor");
|
|
13197
|
-
this.queueProcessing = false;
|
|
13198
|
-
});
|
|
13199
|
-
}
|
|
13200
13198
|
log.debug(`queued extraction from ${reason}`);
|
|
13201
13199
|
}
|
|
13202
13200
|
|
|
@@ -13231,7 +13229,8 @@ export class Orchestrator {
|
|
|
13231
13229
|
turns: BufferTurn[],
|
|
13232
13230
|
options: { commit?: boolean; bufferKey?: string } = {},
|
|
13233
13231
|
): boolean {
|
|
13234
|
-
|
|
13232
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
13233
|
+
if (!lifecycleCaps.extractionDedupe) return true;
|
|
13235
13234
|
if (!Array.isArray(turns) || turns.length === 0) return false;
|
|
13236
13235
|
|
|
13237
13236
|
const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? "default";
|
|
@@ -13263,62 +13262,6 @@ export class Orchestrator {
|
|
|
13263
13262
|
return true;
|
|
13264
13263
|
}
|
|
13265
13264
|
|
|
13266
|
-
/**
|
|
13267
|
-
* Background serial queue processor.
|
|
13268
|
-
* Processes extractions one at a time to avoid race conditions.
|
|
13269
|
-
* Called automatically when items are queued.
|
|
13270
|
-
*/
|
|
13271
|
-
private async processQueue(): Promise<void> {
|
|
13272
|
-
while (this.extractionQueue.length > 0) {
|
|
13273
|
-
const task = this.extractionQueue.shift();
|
|
13274
|
-
if (task) {
|
|
13275
|
-
try {
|
|
13276
|
-
await task();
|
|
13277
|
-
} catch (err) {
|
|
13278
|
-
this.logExtractionQueueFailure(err, "task");
|
|
13279
|
-
}
|
|
13280
|
-
}
|
|
13281
|
-
}
|
|
13282
|
-
|
|
13283
|
-
this.queueProcessing = false;
|
|
13284
|
-
}
|
|
13285
|
-
|
|
13286
|
-
/**
|
|
13287
|
-
* Classify + log a failure from either the per-task catch inside
|
|
13288
|
-
* `processQueue()` or the outer `processQueue().catch(...)` in
|
|
13289
|
-
* `queueBufferedExtraction()`. Issue #549: `throwIfRecallAborted`
|
|
13290
|
-
* (used throughout `runExtraction`) raises an Error whose `name` is
|
|
13291
|
-
* `"AbortError"`. That path fires when `before_reset` aborts a
|
|
13292
|
-
* queued task to avoid duplicate extraction — it is intentional
|
|
13293
|
-
* cancellation, not a failure. Downgrading the log to debug
|
|
13294
|
-
* prevents spurious `error`-level lines that routinely appear
|
|
13295
|
-
* right next to a successful `persisted: N facts, M entities` log
|
|
13296
|
-
* and that confuse operators into thinking extraction is broken.
|
|
13297
|
-
* Genuine extraction failures (network, parse, I/O) still log at
|
|
13298
|
-
* `error`.
|
|
13299
|
-
*
|
|
13300
|
-
* Source differentiates the two call sites so the log message
|
|
13301
|
-
* names the right layer (`task` vs `processor`).
|
|
13302
|
-
*/
|
|
13303
|
-
private logExtractionQueueFailure(
|
|
13304
|
-
err: unknown,
|
|
13305
|
-
source: "task" | "processor",
|
|
13306
|
-
): void {
|
|
13307
|
-
const aborted =
|
|
13308
|
-
source === "task"
|
|
13309
|
-
? "background extraction task aborted (session transition)"
|
|
13310
|
-
: "background extraction queue processor aborted (session transition)";
|
|
13311
|
-
const failed =
|
|
13312
|
-
source === "task"
|
|
13313
|
-
? "background extraction task failed"
|
|
13314
|
-
: "background extraction queue processor failed";
|
|
13315
|
-
if (isAbortError(err)) {
|
|
13316
|
-
log.debug(aborted);
|
|
13317
|
-
} else {
|
|
13318
|
-
log.error(failed, err);
|
|
13319
|
-
}
|
|
13320
|
-
}
|
|
13321
|
-
|
|
13322
13265
|
/**
|
|
13323
13266
|
* Passive correction capture (issue #1581) — detects corrections expressed
|
|
13324
13267
|
* passively in conversation turns and routes them to the Correction Contract
|
|
@@ -14090,6 +14033,7 @@ export class Orchestrator {
|
|
|
14090
14033
|
/** Verbatim source turn text the facts were extracted from (faithfulness gate #1576). */
|
|
14091
14034
|
sourceText?: string,
|
|
14092
14035
|
graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.config),
|
|
14036
|
+
lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.config),
|
|
14093
14037
|
): Promise<string[]> {
|
|
14094
14038
|
// Inline source attribution (issue #369). When enabled, every extracted
|
|
14095
14039
|
// fact is rewritten to carry a compact provenance tag inside its body so
|
|
@@ -14388,7 +14332,7 @@ export class Orchestrator {
|
|
|
14388
14332
|
},
|
|
14389
14333
|
);
|
|
14390
14334
|
if (
|
|
14391
|
-
|
|
14335
|
+
lifecycleCaps.temporalSupersession &&
|
|
14392
14336
|
options.category === "fact" &&
|
|
14393
14337
|
options.entityRef &&
|
|
14394
14338
|
options.structuredAttributes &&
|
|
@@ -14552,7 +14496,7 @@ export class Orchestrator {
|
|
|
14552
14496
|
// would have run post-writeMemory. This is a best-effort / fail-open
|
|
14553
14497
|
// step — if the lookup fails we skip silently (same as the normal path).
|
|
14554
14498
|
if (
|
|
14555
|
-
|
|
14499
|
+
lifecycleCaps.temporalSupersession &&
|
|
14556
14500
|
options.entityRef &&
|
|
14557
14501
|
options.structuredAttributes &&
|
|
14558
14502
|
Object.keys(options.structuredAttributes).length > 0
|
|
@@ -14714,7 +14658,7 @@ export class Orchestrator {
|
|
|
14714
14658
|
// shared recall continues returning the stale state. Reuses the same
|
|
14715
14659
|
// applyTemporalSupersession helper — no logic duplication.
|
|
14716
14660
|
if (
|
|
14717
|
-
|
|
14661
|
+
lifecycleCaps.temporalSupersession &&
|
|
14718
14662
|
options.entityRef &&
|
|
14719
14663
|
options.structuredAttributes &&
|
|
14720
14664
|
Object.keys(options.structuredAttributes).length > 0
|
|
@@ -15024,7 +14968,7 @@ export class Orchestrator {
|
|
|
15024
14968
|
// persistExtraction call so stale state from a prior call cannot leak
|
|
15025
14969
|
// into the caller's buffer-retention decision.
|
|
15026
14970
|
this.lastPersistExtractionDeferredCount = 0;
|
|
15027
|
-
if (
|
|
14971
|
+
if (lifecycleCaps.extractionJudge) {
|
|
15028
14972
|
// #1669 P1: pre-filter redacted facts from judge candidates so never-store
|
|
15029
14973
|
// content is not persisted as judge training data.
|
|
15030
14974
|
let preJudgeRedactionRules: CompiledRedactionRule[] = [];
|
|
@@ -15090,7 +15034,7 @@ export class Orchestrator {
|
|
|
15090
15034
|
// off; the combined callback itself is undefined when both are
|
|
15091
15035
|
// disabled so there is zero overhead in the default configuration.
|
|
15092
15036
|
const judgeTelemetryOpts = {
|
|
15093
|
-
enabled:
|
|
15037
|
+
enabled: lifecycleCaps.extractionJudgeTelemetry,
|
|
15094
15038
|
memoryDir: this.config.memoryDir,
|
|
15095
15039
|
};
|
|
15096
15040
|
const judgeTrainingOpts = {
|
|
@@ -15301,7 +15245,7 @@ export class Orchestrator {
|
|
|
15301
15245
|
// do not block scope routing). Rule 30: gated by
|
|
15302
15246
|
// extractionScopeClassificationEnabled.
|
|
15303
15247
|
if (
|
|
15304
|
-
|
|
15248
|
+
lifecycleCaps.extractionScopeClassification &&
|
|
15305
15249
|
this.config.namespacesEnabled &&
|
|
15306
15250
|
fact.scope === "global" &&
|
|
15307
15251
|
!routedNamespaceExplicit
|
|
@@ -15954,7 +15898,7 @@ export class Orchestrator {
|
|
|
15954
15898
|
// #1578 r3: an extracted end-only bound (validFrom absent) is
|
|
15955
15899
|
// historical, not a new authoritative state — never let it
|
|
15956
15900
|
// supersede a later active fact (codex P1 on :15534).
|
|
15957
|
-
enabled:
|
|
15901
|
+
enabled: lifecycleCaps.temporalSupersession &&
|
|
15958
15902
|
!(biTemporal && !biTemporal.validFrom),
|
|
15959
15903
|
});
|
|
15960
15904
|
} catch (err) {
|
|
@@ -16190,7 +16134,7 @@ export class Orchestrator {
|
|
|
16190
16134
|
entityRef: supersessionEntityRef,
|
|
16191
16135
|
structuredAttributes: fact.structuredAttributes,
|
|
16192
16136
|
createdAt: supersessionOrderingAt(biTemporal?.validFrom ?? sourceContext?.validAt),
|
|
16193
|
-
enabled:
|
|
16137
|
+
enabled: lifecycleCaps.temporalSupersession &&
|
|
16194
16138
|
!(biTemporal && !biTemporal.validFrom),
|
|
16195
16139
|
});
|
|
16196
16140
|
} catch (err) {
|
|
@@ -16557,7 +16501,7 @@ export class Orchestrator {
|
|
|
16557
16501
|
storage: StorageManager,
|
|
16558
16502
|
memoryId: string,
|
|
16559
16503
|
): Promise<void> {
|
|
16560
|
-
if (!this.config.
|
|
16504
|
+
if (!resolveMemoryLifecycleCapabilities(this.config).embeddingFallback) return;
|
|
16561
16505
|
if (!(await this.embeddingFallback.isAvailable())) return;
|
|
16562
16506
|
const memory = await storage.getMemoryById(memoryId);
|
|
16563
16507
|
if (!memory) return;
|
|
@@ -16749,6 +16693,7 @@ export class Orchestrator {
|
|
|
16749
16693
|
merged: number;
|
|
16750
16694
|
invalidated: number;
|
|
16751
16695
|
}> {
|
|
16696
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
16752
16697
|
log.info("running consolidation pass");
|
|
16753
16698
|
let merged = 0;
|
|
16754
16699
|
let invalidated = 0;
|
|
@@ -16985,7 +16930,7 @@ export class Orchestrator {
|
|
|
16985
16930
|
}
|
|
16986
16931
|
|
|
16987
16932
|
// v8.3 Lifecycle policy pass — deterministic promotion/decay metadata
|
|
16988
|
-
if (
|
|
16933
|
+
if (lifecycleCaps.lifecyclePolicy) {
|
|
16989
16934
|
try {
|
|
16990
16935
|
const lightSleepStartedAt = new Date().toISOString();
|
|
16991
16936
|
const lifecycleCorpus = await this.storage.readAllMemories();
|
|
@@ -17173,7 +17118,7 @@ export class Orchestrator {
|
|
|
17173
17118
|
await this.storage.saveMeta(meta);
|
|
17174
17119
|
|
|
17175
17120
|
// Temporal Memory Tree (v8.2) — rebuild nodes from all memories, fail-open
|
|
17176
|
-
if (
|
|
17121
|
+
if (lifecycleCaps.temporalMemoryTree) {
|
|
17177
17122
|
try {
|
|
17178
17123
|
const tmtEntries = allMemories
|
|
17179
17124
|
.filter(
|
|
@@ -17715,6 +17660,7 @@ export class Orchestrator {
|
|
|
17715
17660
|
let updatedCount = 0;
|
|
17716
17661
|
let disputedCount = 0;
|
|
17717
17662
|
let evaluatedCount = 0;
|
|
17663
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
17718
17664
|
|
|
17719
17665
|
const thresholds = this.effectiveLifecycleThresholds();
|
|
17720
17666
|
const policy = {
|
|
@@ -17780,7 +17726,7 @@ export class Orchestrator {
|
|
|
17780
17726
|
|
|
17781
17727
|
// Report how many memories had frontmatter rewritten so callers can record a
|
|
17782
17728
|
// catalog write touch for lifecycle-only passes (codex NR-tS).
|
|
17783
|
-
if (!
|
|
17729
|
+
if (!lifecycleCaps.lifecycleMetrics) return updatedCount;
|
|
17784
17730
|
|
|
17785
17731
|
const total = evaluatedCount;
|
|
17786
17732
|
const metrics = {
|
|
@@ -19226,7 +19172,7 @@ export class Orchestrator {
|
|
|
19226
19172
|
// • search() throws → re-throw (network/provider error).
|
|
19227
19173
|
// • search() returns [] → return [] (empty index, not a
|
|
19228
19174
|
// backend failure; decideSemanticDedup reports no_candidates).
|
|
19229
|
-
if (!this.config.
|
|
19175
|
+
if (!resolveMemoryLifecycleCapabilities(this.config).embeddingFallback) {
|
|
19230
19176
|
throw new Error("semantic dedup: embedding backend not configured");
|
|
19231
19177
|
}
|
|
19232
19178
|
if (!(await this.embeddingFallback.isAvailable())) {
|
|
@@ -19300,7 +19246,7 @@ export class Orchestrator {
|
|
|
19300
19246
|
query: string,
|
|
19301
19247
|
limit: number,
|
|
19302
19248
|
): Promise<QmdSearchResult[]> {
|
|
19303
|
-
if (!this.config.
|
|
19249
|
+
if (!resolveMemoryLifecycleCapabilities(this.config).embeddingFallback) return [];
|
|
19304
19250
|
if (!(await this.embeddingFallback.isAvailable())) return [];
|
|
19305
19251
|
const hits = await this.embeddingFallback.search(query, limit);
|
|
19306
19252
|
if (hits.length === 0) return [];
|
|
@@ -20010,6 +19956,7 @@ export class Orchestrator {
|
|
|
20010
19956
|
blockedPaths?: Set<string>;
|
|
20011
19957
|
},
|
|
20012
19958
|
): QmdSearchResult[] {
|
|
19959
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
20013
19960
|
let lifecycleFilteredCount = 0;
|
|
20014
19961
|
let temporalSupersededFilteredCount = 0;
|
|
20015
19962
|
let biTemporalExpiredFilteredCount = 0;
|
|
@@ -20043,9 +19990,9 @@ export class Orchestrator {
|
|
|
20043
19990
|
if (
|
|
20044
19991
|
options?.allowLifecycleFiltered !== true &&
|
|
20045
19992
|
shouldFilterLifecycleRecallCandidate(memory.frontmatter, {
|
|
20046
|
-
lifecyclePolicyEnabled:
|
|
19993
|
+
lifecyclePolicyEnabled: lifecycleCaps.lifecyclePolicy,
|
|
20047
19994
|
lifecycleFilterStaleEnabled:
|
|
20048
|
-
|
|
19995
|
+
lifecycleCaps.lifecycleFilterStale,
|
|
20049
19996
|
})
|
|
20050
19997
|
) {
|
|
20051
19998
|
lifecycleFilteredCount += 1;
|
|
@@ -20079,7 +20026,7 @@ export class Orchestrator {
|
|
|
20079
20026
|
// half-open `[valid_at, invalid_at)` evaluation in isValidAsOf
|
|
20080
20027
|
// is the authoritative gate for historical recall.
|
|
20081
20028
|
shouldFilterSupersededFromRecall(memory.frontmatter, {
|
|
20082
|
-
enabled:
|
|
20029
|
+
enabled: lifecycleCaps.temporalSupersession,
|
|
20083
20030
|
includeInRecall: this.config.temporalSupersessionIncludeInRecall,
|
|
20084
20031
|
})
|
|
20085
20032
|
) {
|
|
@@ -20223,6 +20170,7 @@ export class Orchestrator {
|
|
|
20223
20170
|
asOfMs?: number;
|
|
20224
20171
|
},
|
|
20225
20172
|
): Promise<QmdSearchResult[]> {
|
|
20173
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
20226
20174
|
if (results.length === 0) return results;
|
|
20227
20175
|
|
|
20228
20176
|
const safety = await this.filterSearchResultsForRecall(
|
|
@@ -20397,7 +20345,7 @@ export class Orchestrator {
|
|
|
20397
20345
|
const lifecycleDelta = lifecycleRecallScoreAdjustment(
|
|
20398
20346
|
memory.frontmatter,
|
|
20399
20347
|
{
|
|
20400
|
-
lifecyclePolicyEnabled:
|
|
20348
|
+
lifecyclePolicyEnabled: lifecycleCaps.lifecyclePolicy,
|
|
20401
20349
|
},
|
|
20402
20350
|
);
|
|
20403
20351
|
score += applyUtilityRankingRuntimeDelta(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { log } from "../logger.js";
|
|
2
|
+
import { resolveMemoryLifecycleCapabilities } from "../capabilities.js";
|
|
2
3
|
import type { PluginConfig } from "../types.js";
|
|
3
4
|
import { isAbortError } from "../abort-error.js";
|
|
4
5
|
import { withTimeoutSignal } from "./abort.js";
|
|
@@ -209,7 +210,7 @@ export class EmbedHelper {
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
private resolveProvider(options: { includeHost?: boolean } = {}): ProviderConfig | null {
|
|
212
|
-
if (!this.config.
|
|
213
|
+
if (!resolveMemoryLifecycleCapabilities(this.config).embeddingFallback) return null;
|
|
213
214
|
|
|
214
215
|
if (
|
|
215
216
|
options.includeHost !== false &&
|
|
@@ -244,7 +245,7 @@ export class EmbedHelper {
|
|
|
244
245
|
}
|
|
245
246
|
|
|
246
247
|
private resolveFallbackProviderForIdentity(identity: EmbedProviderIdentity): ProviderConfig | null {
|
|
247
|
-
if (!this.config.
|
|
248
|
+
if (!resolveMemoryLifecycleCapabilities(this.config).embeddingFallback) return null;
|
|
248
249
|
const separator = identity.indexOf(":");
|
|
249
250
|
if (separator <= 0 || separator === identity.length - 1) return null;
|
|
250
251
|
const type = identity.slice(0, separator);
|