@remnic/core 9.3.734 → 9.3.735
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 +8 -6
- package/dist/access-boundary.js +9 -9
- package/dist/access-cli.js +24 -24
- package/dist/access-http.d.ts +8 -6
- package/dist/access-http.js +14 -14
- package/dist/access-mcp.d.ts +8 -6
- package/dist/access-mcp.js +13 -13
- package/dist/access-operations-batch.js +11 -11
- package/dist/access-operations.d.ts +8 -6
- package/dist/access-operations.js +12 -12
- package/dist/access-schema.d.ts +4 -4
- package/dist/{access-service-rjFfmfKB.d.ts → access-service-CVx7mmvK.d.ts} +3 -3
- package/dist/access-service.d.ts +8 -6
- package/dist/access-service.js +8 -8
- package/dist/access-surface-catalog.d.ts +8 -6
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-memory-bridge.js +3 -3
- package/dist/active-recall.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +7 -5
- package/dist/briefing.d.ts +1 -1
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +101 -2
- package/dist/capabilities.js +13 -3
- package/dist/{catalog-DHYXzM4-.d.ts → catalog-BVhDEUhT.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-IWMGBNXY.js → chunk-2T2N7ISV.js} +3 -3
- package/dist/{chunk-K7PAILHO.js → chunk-5BOQNB2K.js} +3 -3
- package/dist/{chunk-Q5LGXWNG.js → chunk-AAIHDIMD.js} +6 -6
- package/dist/{chunk-WHQ2JB35.js → chunk-AB2E5DCN.js} +2 -2
- package/dist/{chunk-FAGERSH2.js → chunk-AE7NTZ75.js} +3 -3
- package/dist/{chunk-V5OVSGB6.js → chunk-AESC5OQJ.js} +2 -2
- package/dist/{chunk-7FPJFCXL.js → chunk-BXPG5AVX.js} +4 -4
- package/dist/{chunk-UH3NYOHN.js → chunk-CHJIWG2H.js} +2 -2
- package/dist/{chunk-IDIXGGDN.js → chunk-E4LYJ7PY.js} +6 -6
- package/dist/{chunk-WTTVFSCO.js → chunk-FF36YNKY.js} +3 -3
- package/dist/{chunk-Z7J3OAPR.js → chunk-FLCYY5JX.js} +456 -398
- package/dist/chunk-FLCYY5JX.js.map +1 -0
- package/dist/{chunk-TJSQHO4Q.js → chunk-FLPKEMSO.js} +2 -2
- package/dist/{chunk-UF3N7IRP.js → chunk-G54IDCD3.js} +45 -41
- package/dist/chunk-G54IDCD3.js.map +1 -0
- package/dist/{chunk-UK6U5C3N.js → chunk-GB2FZOWB.js} +3 -3
- package/dist/{chunk-5OYHJIJN.js → chunk-GYICIICQ.js} +3 -3
- package/dist/{chunk-PEF2XOIV.js → chunk-HFXZIF3V.js} +3 -3
- package/dist/{chunk-PKO5NJ65.js → chunk-HLPYL6LC.js} +27 -24
- package/dist/chunk-HLPYL6LC.js.map +1 -0
- package/dist/{chunk-ET5HXSQL.js → chunk-IPI45Q4S.js} +2 -2
- package/dist/{chunk-2L5RTVMO.js → chunk-IX4L7E5G.js} +2 -2
- package/dist/{chunk-SYX73XD7.js → chunk-IXGXALRV.js} +10 -7
- package/dist/chunk-IXGXALRV.js.map +1 -0
- package/dist/{chunk-SHJGBAIW.js → chunk-JWDE7OVJ.js} +44 -2
- package/dist/{chunk-SHJGBAIW.js.map → chunk-JWDE7OVJ.js.map} +1 -1
- package/dist/{chunk-IZLTOS5L.js → chunk-K3Y2SJTN.js} +4 -4
- package/dist/{chunk-CILX2XW7.js → chunk-NDKW67ER.js} +2 -2
- package/dist/{chunk-54RCE5Z3.js → chunk-NNJKEAP2.js} +2 -2
- package/dist/{chunk-LV32K4OP.js → chunk-OYHYBHHI.js} +2 -2
- package/dist/{chunk-5DIKZKOD.js → chunk-P6VLG7KE.js} +2 -2
- package/dist/{chunk-T7CGPTFU.js → chunk-QNTLWH3T.js} +3 -3
- package/dist/{chunk-6U7TES2M.js → chunk-UO6MPN77.js} +13 -12
- package/dist/chunk-UO6MPN77.js.map +1 -0
- package/dist/{chunk-NDYQIN6C.js → chunk-VOEVVIP3.js} +3 -3
- package/dist/{chunk-3QETM5NG.js → chunk-ZBZ4XULO.js} +3 -3
- package/dist/{cli-XVpmSoQs.d.ts → cli-Cx5Mxwk7.d.ts} +3 -3
- package/dist/cli.d.ts +9 -7
- package/dist/cli.js +20 -20
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +2 -2
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/contradiction/index.js +2 -2
- package/dist/{contradiction-scan-OUHMCUBT.js → contradiction-scan-2B4AE4TI.js} +3 -3
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +2 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +7 -5
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{first-start-migration-W4U6XDKI.js → first-start-migration-2RQYDIZ7.js} +6 -5
- package/dist/first-start-migration-2RQYDIZ7.js.map +1 -0
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +30 -30
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +8 -6
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +6 -6
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/principal.js +2 -2
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +2 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +11 -11
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/compression-guideline-coordinator.js +2 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +6 -6
- package/dist/{orchestrator-BXi-gadS.d.ts → orchestrator-oF0cceBX.d.ts} +80 -16
- package/dist/orchestrator.d.ts +7 -5
- package/dist/orchestrator.js +19 -19
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +24 -24
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/embed-helper.js +2 -2
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +3 -3
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +3 -3
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DeL5grLx.d.ts → semantic-consolidation-DKGbufYO.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +3 -3
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/{tier-stats-LSM35HZY.js → tier-stats-KPDIISG7.js} +6 -5
- package/dist/tier-stats-KPDIISG7.js.map +1 -0
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +42 -42
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CpFz51Pv.d.ts → types-C7UCxpuO.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-service.ts +20 -20
- package/src/capabilities.test.ts +197 -0
- package/src/capabilities.ts +206 -0
- package/src/cli/creation-ledger-commands.ts +2 -2
- package/src/cli/research-status-commands.ts +13 -13
- package/src/cli.ts +17 -17
- package/src/maintenance/first-start-migration.ts +3 -3
- package/src/maintenance/tier-stats.ts +3 -3
- package/src/operator-toolkit.ts +8 -8
- package/src/orchestration/compression-guideline-coordinator.ts +7 -6
- package/src/orchestration/lifecycle-policy-coordinator.ts +504 -0
- package/src/orchestrator.ts +28 -383
- package/dist/chunk-6U7TES2M.js.map +0 -1
- package/dist/chunk-PKO5NJ65.js.map +0 -1
- package/dist/chunk-SYX73XD7.js.map +0 -1
- package/dist/chunk-UF3N7IRP.js.map +0 -1
- package/dist/chunk-Z7J3OAPR.js.map +0 -1
- package/dist/first-start-migration-W4U6XDKI.js.map +0 -1
- package/dist/tier-stats-LSM35HZY.js.map +0 -1
- /package/dist/{chunk-IWMGBNXY.js.map → chunk-2T2N7ISV.js.map} +0 -0
- /package/dist/{chunk-K7PAILHO.js.map → chunk-5BOQNB2K.js.map} +0 -0
- /package/dist/{chunk-Q5LGXWNG.js.map → chunk-AAIHDIMD.js.map} +0 -0
- /package/dist/{chunk-WHQ2JB35.js.map → chunk-AB2E5DCN.js.map} +0 -0
- /package/dist/{chunk-FAGERSH2.js.map → chunk-AE7NTZ75.js.map} +0 -0
- /package/dist/{chunk-V5OVSGB6.js.map → chunk-AESC5OQJ.js.map} +0 -0
- /package/dist/{chunk-7FPJFCXL.js.map → chunk-BXPG5AVX.js.map} +0 -0
- /package/dist/{chunk-UH3NYOHN.js.map → chunk-CHJIWG2H.js.map} +0 -0
- /package/dist/{chunk-IDIXGGDN.js.map → chunk-E4LYJ7PY.js.map} +0 -0
- /package/dist/{chunk-WTTVFSCO.js.map → chunk-FF36YNKY.js.map} +0 -0
- /package/dist/{chunk-TJSQHO4Q.js.map → chunk-FLPKEMSO.js.map} +0 -0
- /package/dist/{chunk-UK6U5C3N.js.map → chunk-GB2FZOWB.js.map} +0 -0
- /package/dist/{chunk-5OYHJIJN.js.map → chunk-GYICIICQ.js.map} +0 -0
- /package/dist/{chunk-PEF2XOIV.js.map → chunk-HFXZIF3V.js.map} +0 -0
- /package/dist/{chunk-ET5HXSQL.js.map → chunk-IPI45Q4S.js.map} +0 -0
- /package/dist/{chunk-2L5RTVMO.js.map → chunk-IX4L7E5G.js.map} +0 -0
- /package/dist/{chunk-IZLTOS5L.js.map → chunk-K3Y2SJTN.js.map} +0 -0
- /package/dist/{chunk-CILX2XW7.js.map → chunk-NDKW67ER.js.map} +0 -0
- /package/dist/{chunk-54RCE5Z3.js.map → chunk-NNJKEAP2.js.map} +0 -0
- /package/dist/{chunk-LV32K4OP.js.map → chunk-OYHYBHHI.js.map} +0 -0
- /package/dist/{chunk-5DIKZKOD.js.map → chunk-P6VLG7KE.js.map} +0 -0
- /package/dist/{chunk-T7CGPTFU.js.map → chunk-QNTLWH3T.js.map} +0 -0
- /package/dist/{chunk-NDYQIN6C.js.map → chunk-VOEVVIP3.js.map} +0 -0
- /package/dist/{chunk-3QETM5NG.js.map → chunk-ZBZ4XULO.js.map} +0 -0
- /package/dist/{contradiction-scan-OUHMCUBT.js.map → contradiction-scan-2B4AE4TI.js.map} +0 -0
package/src/operator-toolkit.ts
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
resolveCapabilities,
|
|
30
30
|
resolveGraphConstructionCapabilities,
|
|
31
31
|
resolveQmdCapabilities,
|
|
32
|
-
} from "./capabilities.js";
|
|
32
|
+
resolveEvalCapabilities} from "./capabilities.js";
|
|
33
33
|
import {
|
|
34
34
|
analyzeSessionIntegrity,
|
|
35
35
|
applySessionRepair,
|
|
@@ -2263,17 +2263,17 @@ export async function runBenchmarkRecall(options: BenchmarkRecallOptions): Promi
|
|
|
2263
2263
|
const status = await getEvalHarnessStatus({
|
|
2264
2264
|
memoryDir: options.config.memoryDir,
|
|
2265
2265
|
evalStoreDir: options.config.evalStoreDir,
|
|
2266
|
-
enabled: options.config.
|
|
2267
|
-
shadowModeEnabled: options.config.
|
|
2268
|
-
baselineSnapshotsEnabled: options.config.
|
|
2269
|
-
memoryRedTeamBenchEnabled: options.config.
|
|
2266
|
+
enabled: resolveEvalCapabilities(options.config).evalHarness,
|
|
2267
|
+
shadowModeEnabled: resolveEvalCapabilities(options.config).evalShadowMode,
|
|
2268
|
+
baselineSnapshotsEnabled: resolveEvalCapabilities(options.config).benchmarkBaselineSnapshots,
|
|
2269
|
+
memoryRedTeamBenchEnabled: resolveEvalCapabilities(options.config).memoryRedTeamBench,
|
|
2270
2270
|
});
|
|
2271
2271
|
|
|
2272
2272
|
if (options.createSnapshot && options.snapshotId) {
|
|
2273
2273
|
const snapshot = await createEvalBaselineSnapshot({
|
|
2274
2274
|
memoryDir: options.config.memoryDir,
|
|
2275
2275
|
evalStoreDir: options.config.evalStoreDir,
|
|
2276
|
-
baselineSnapshotsEnabled: options.config.
|
|
2276
|
+
baselineSnapshotsEnabled: resolveEvalCapabilities(options.config).benchmarkBaselineSnapshots,
|
|
2277
2277
|
snapshotId: options.snapshotId,
|
|
2278
2278
|
notes: options.snapshotNotes,
|
|
2279
2279
|
gitRef: options.gitRef,
|
|
@@ -2309,7 +2309,7 @@ export async function runBenchmarkRecall(options: BenchmarkRecallOptions): Promi
|
|
|
2309
2309
|
const baselineReport = await runEvalBaselineDeltaReport({
|
|
2310
2310
|
memoryDir: options.config.memoryDir,
|
|
2311
2311
|
evalStoreDir: options.config.evalStoreDir,
|
|
2312
|
-
benchmarkDeltaReporterEnabled: options.config.
|
|
2312
|
+
benchmarkDeltaReporterEnabled: resolveEvalCapabilities(options.config).benchmarkDeltaReporter,
|
|
2313
2313
|
snapshotId: options.snapshotId,
|
|
2314
2314
|
});
|
|
2315
2315
|
return {
|
|
@@ -2323,7 +2323,7 @@ export async function runBenchmarkRecall(options: BenchmarkRecallOptions): Promi
|
|
|
2323
2323
|
|
|
2324
2324
|
if (options.validatePath) {
|
|
2325
2325
|
const validate = await validateEvalBenchmarkPack(options.validatePath, {
|
|
2326
|
-
memoryRedTeamBenchEnabled: options.config.
|
|
2326
|
+
memoryRedTeamBenchEnabled: resolveEvalCapabilities(options.config).memoryRedTeamBench,
|
|
2327
2327
|
});
|
|
2328
2328
|
return {
|
|
2329
2329
|
schemaVersion: 1,
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { createHash } from "node:crypto";
|
|
27
|
+
import { resolveCompressionCapabilities } from "../capabilities.js";
|
|
27
28
|
|
|
28
29
|
// StorageManager type comes from the package barrel (type-only) so this
|
|
29
30
|
// module does not add a direct storage.ts import (#1533 ratchet).
|
|
@@ -103,7 +104,7 @@ export class CompressionGuidelineCoordinator {
|
|
|
103
104
|
? draftState
|
|
104
105
|
: activeState;
|
|
105
106
|
|
|
106
|
-
if (!this.config.
|
|
107
|
+
if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) {
|
|
107
108
|
return {
|
|
108
109
|
enabled: false,
|
|
109
110
|
dryRun,
|
|
@@ -152,7 +153,7 @@ export class CompressionGuidelineCoordinator {
|
|
|
152
153
|
}
|
|
153
154
|
const refinedCandidate =
|
|
154
155
|
await refineCompressionGuidelineCandidateSemantically(candidate, {
|
|
155
|
-
enabled: this.config.
|
|
156
|
+
enabled: resolveCompressionCapabilities(this.config).compressionGuidelineSemanticRefinement,
|
|
156
157
|
timeoutMs: this.config.compressionGuidelineSemanticTimeoutMs,
|
|
157
158
|
runRefinement: async (baseline) => {
|
|
158
159
|
const prompt = [
|
|
@@ -241,7 +242,7 @@ export class CompressionGuidelineCoordinator {
|
|
|
241
242
|
| "guideline_version_mismatch"
|
|
242
243
|
| "draft_changed";
|
|
243
244
|
}> {
|
|
244
|
-
if (!this.config.
|
|
245
|
+
if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) {
|
|
245
246
|
return {
|
|
246
247
|
enabled: false,
|
|
247
248
|
activated: false,
|
|
@@ -312,7 +313,7 @@ export class CompressionGuidelineCoordinator {
|
|
|
312
313
|
|
|
313
314
|
/** Consolidation-time hook: recompute the draft from recent events. */
|
|
314
315
|
async runCompressionGuidelineLearningPass(): Promise<void> {
|
|
315
|
-
if (!this.config.
|
|
316
|
+
if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) return;
|
|
316
317
|
try {
|
|
317
318
|
const result = await this.optimizeCompressionGuidelines({
|
|
318
319
|
dryRun: false,
|
|
@@ -328,8 +329,8 @@ export class CompressionGuidelineCoordinator {
|
|
|
328
329
|
|
|
329
330
|
/** Recall-time hook: surface active guidelines as a recall section. */
|
|
330
331
|
async buildCompressionGuidelineRecallSection(): Promise<string | null> {
|
|
331
|
-
if (!this.config.
|
|
332
|
-
if (!this.config.
|
|
332
|
+
if (!resolveCompressionCapabilities(this.config).contextCompressionActions) return null;
|
|
333
|
+
if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) return null;
|
|
333
334
|
|
|
334
335
|
const state = await this.storage
|
|
335
336
|
.readCompressionGuidelineOptimizerState()
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle-policy coordinator — extracted from the orchestrator
|
|
3
|
+
* (issue #1526, seam 6).
|
|
4
|
+
*
|
|
5
|
+
* Owns the deterministic memory-lifecycle pipeline: heat/decay scoring
|
|
6
|
+
* (`runLifecyclePolicyPass`), fact archival (`runFactArchival`),
|
|
7
|
+
* summarization (`runSummarization`), and topic extraction
|
|
8
|
+
* (`runTopicExtraction`). Also owns the action-outcome prior builder
|
|
9
|
+
* (`buildLifecycleActionPriors` / `actionOutcomePriorDelta`) that feeds
|
|
10
|
+
* the lifecycle transition decider.
|
|
11
|
+
*
|
|
12
|
+
* The orchestrator constructs one instance and delegates the internal
|
|
13
|
+
* entrypoints to it. The public wrapper (`runLifecyclePolicyNow`)
|
|
14
|
+
* remains on the orchestrator as a thin pass-through. Storage is the
|
|
15
|
+
* orchestrator's stable `this.storage` (or a per-namespace override
|
|
16
|
+
* passed via options); the extraction engine, embedding-fallback, and
|
|
17
|
+
* content-hash callbacks arrive as deps so the orchestrator keeps
|
|
18
|
+
* ownership of gateway routing and cross-subsystem persistence.
|
|
19
|
+
*
|
|
20
|
+
* Behavior-preserving move from orchestrator.ts. No logic changes — the
|
|
21
|
+
* orchestrator keeps thin delegating methods so existing call sites
|
|
22
|
+
* and tests that exercise the public API continue to work.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
decideLifecycleTransition,
|
|
27
|
+
resolveLifecycleState,
|
|
28
|
+
type LifecycleSignals,
|
|
29
|
+
} from "../lifecycle.js";
|
|
30
|
+
import type { LifecycleState } from "../types.js";
|
|
31
|
+
import {
|
|
32
|
+
resolveIndexingCapabilities,
|
|
33
|
+
resolveMemoryLifecycleCapabilities,
|
|
34
|
+
resolveCreationMemoryCapabilities,
|
|
35
|
+
} from "../capabilities.js";
|
|
36
|
+
import { isActiveMemoryStatus } from "../memory-lifecycle-ledger-utils.js";
|
|
37
|
+
import { deindexMemory } from "../temporal-index.js";
|
|
38
|
+
import { extractTopics } from "../topics.js";
|
|
39
|
+
import { log } from "../logger.js";
|
|
40
|
+
import path from "node:path";
|
|
41
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
42
|
+
import type { StorageManager } from "../index.js";
|
|
43
|
+
import type { ExtractionEngine } from "../extraction.js";
|
|
44
|
+
import type { EmbeddingFallback } from "../embedding-fallback.js";
|
|
45
|
+
import type {
|
|
46
|
+
PluginConfig,
|
|
47
|
+
MemoryFile,
|
|
48
|
+
MemoryActionEvent,
|
|
49
|
+
MemorySummary,
|
|
50
|
+
} from "../types.js";
|
|
51
|
+
|
|
52
|
+
/** Dependencies injected by the orchestrator. All stable references or
|
|
53
|
+
* live accessors. */
|
|
54
|
+
export interface LifecyclePolicyCoordinatorDeps {
|
|
55
|
+
config: PluginConfig;
|
|
56
|
+
/** Live accessor: the orchestrator's storage manager (stable post-ctor). */
|
|
57
|
+
getStorage: () => StorageManager;
|
|
58
|
+
/** The extraction engine — used for summarization. */
|
|
59
|
+
extraction: ExtractionEngine;
|
|
60
|
+
/** The embedding-fallback manager used for index cleanup on archival. */
|
|
61
|
+
embeddingFallback: EmbeddingFallback;
|
|
62
|
+
/** Effective lifecycle thresholds (promote/stale/archive). Delegated to
|
|
63
|
+
* the orchestrator which owns runtime-policy-values overlay. */
|
|
64
|
+
getEffectiveLifecycleThresholds: () => {
|
|
65
|
+
promoteHeatThreshold: number;
|
|
66
|
+
staleDecayThreshold: number;
|
|
67
|
+
archiveDecayThreshold: number;
|
|
68
|
+
};
|
|
69
|
+
/** Remove a memory's content-hash entry from the storage-scoped index.
|
|
70
|
+
* Delegated to the orchestrator which owns the per-storage index map. */
|
|
71
|
+
removeContentHashForMemory: (
|
|
72
|
+
targetStorage: StorageManager,
|
|
73
|
+
memory: MemoryFile,
|
|
74
|
+
context: string,
|
|
75
|
+
) => Promise<void>;
|
|
76
|
+
/** Persist all dirty content-hash indexes to disk. */
|
|
77
|
+
saveContentHashIndexes: () => Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Coordinates the memory-lifecycle policy pipeline. Holds no mutable
|
|
82
|
+
* state of its own — all persistence flows through the injected storage
|
|
83
|
+
* managers and callbacks.
|
|
84
|
+
*/
|
|
85
|
+
export class LifecyclePolicyCoordinator {
|
|
86
|
+
constructor(
|
|
87
|
+
private readonly deps: LifecyclePolicyCoordinatorDeps,
|
|
88
|
+
) {}
|
|
89
|
+
|
|
90
|
+
private get config(): PluginConfig {
|
|
91
|
+
return this.deps.config;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// -------------------------------------------------------------------------
|
|
95
|
+
// Action-outcome priors (feeds lifecycle transition decisions)
|
|
96
|
+
// -------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
actionOutcomePriorDelta(event: MemoryActionEvent): number {
|
|
99
|
+
if (event.outcome === "failed") return -0.3;
|
|
100
|
+
if (event.policyDecision === "deny") return -0.22;
|
|
101
|
+
if (event.policyDecision === "defer") return -0.14;
|
|
102
|
+
if (event.outcome === "skipped") return -0.1;
|
|
103
|
+
|
|
104
|
+
if (event.outcome !== "applied") return 0;
|
|
105
|
+
switch (event.action) {
|
|
106
|
+
case "store_episode":
|
|
107
|
+
case "store_note":
|
|
108
|
+
case "update_note":
|
|
109
|
+
return 0.08;
|
|
110
|
+
case "create_artifact":
|
|
111
|
+
case "summarize_node":
|
|
112
|
+
case "link_graph":
|
|
113
|
+
return 0.04;
|
|
114
|
+
case "discard":
|
|
115
|
+
return -0.03;
|
|
116
|
+
default:
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async buildLifecycleActionPriors(
|
|
122
|
+
storage: StorageManager = this.deps.getStorage(),
|
|
123
|
+
): Promise<Map<string, number>> {
|
|
124
|
+
const events = await storage.readMemoryActionEvents(1200);
|
|
125
|
+
if (events.length === 0) return new Map<string, number>();
|
|
126
|
+
|
|
127
|
+
const nowMs = Date.now();
|
|
128
|
+
const windowMs = 14 * 24 * 60 * 60 * 1000;
|
|
129
|
+
const byMemory = new Map<
|
|
130
|
+
string,
|
|
131
|
+
Array<{ weightedDelta: number; weight: number }>
|
|
132
|
+
>();
|
|
133
|
+
|
|
134
|
+
for (const event of events) {
|
|
135
|
+
if (
|
|
136
|
+
typeof event.memoryId !== "string" ||
|
|
137
|
+
event.memoryId.trim().length === 0
|
|
138
|
+
)
|
|
139
|
+
continue;
|
|
140
|
+
const ts = Date.parse(event.timestamp);
|
|
141
|
+
if (!Number.isFinite(ts)) continue;
|
|
142
|
+
const ageMs = nowMs - ts;
|
|
143
|
+
if (ageMs < 0 || ageMs > windowMs) continue;
|
|
144
|
+
|
|
145
|
+
const delta = this.actionOutcomePriorDelta(event);
|
|
146
|
+
if (delta === 0) continue;
|
|
147
|
+
|
|
148
|
+
const recencyWeight = Math.max(0.2, 1 - ageMs / windowMs);
|
|
149
|
+
const list = byMemory.get(event.memoryId) ?? [];
|
|
150
|
+
if (list.length >= 8) list.shift();
|
|
151
|
+
list.push({
|
|
152
|
+
weightedDelta: delta * recencyWeight,
|
|
153
|
+
weight: recencyWeight,
|
|
154
|
+
});
|
|
155
|
+
byMemory.set(event.memoryId, list);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const out = new Map<string, number>();
|
|
159
|
+
for (const [memoryId, deltas] of byMemory.entries()) {
|
|
160
|
+
if (deltas.length === 0) continue;
|
|
161
|
+
const weightedSum = deltas.reduce(
|
|
162
|
+
(sum, item) => sum + item.weightedDelta,
|
|
163
|
+
0,
|
|
164
|
+
);
|
|
165
|
+
const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);
|
|
166
|
+
if (weightTotal <= 0) continue;
|
|
167
|
+
const score = weightedSum / weightTotal;
|
|
168
|
+
out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// -------------------------------------------------------------------------
|
|
174
|
+
// Lifecycle policy pass (heat/decay scoring + transition)
|
|
175
|
+
// -------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
async runLifecyclePolicyPass(
|
|
178
|
+
allMemories: MemoryFile[],
|
|
179
|
+
storage: StorageManager = this.deps.getStorage(),
|
|
180
|
+
): Promise<number> {
|
|
181
|
+
const now = new Date();
|
|
182
|
+
const nowIso = now.toISOString();
|
|
183
|
+
const countsByState: Record<LifecycleState, number> = {
|
|
184
|
+
candidate: 0,
|
|
185
|
+
validated: 0,
|
|
186
|
+
active: 0,
|
|
187
|
+
stale: 0,
|
|
188
|
+
archived: 0,
|
|
189
|
+
};
|
|
190
|
+
const transitionCounts: Record<string, number> = {};
|
|
191
|
+
let updatedCount = 0;
|
|
192
|
+
let disputedCount = 0;
|
|
193
|
+
let evaluatedCount = 0;
|
|
194
|
+
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
195
|
+
|
|
196
|
+
const thresholds = this.deps.getEffectiveLifecycleThresholds();
|
|
197
|
+
const policy = {
|
|
198
|
+
promoteHeatThreshold: thresholds.promoteHeatThreshold,
|
|
199
|
+
staleDecayThreshold: thresholds.staleDecayThreshold,
|
|
200
|
+
archiveDecayThreshold: thresholds.archiveDecayThreshold,
|
|
201
|
+
protectedCategories: this.config.lifecycleProtectedCategories,
|
|
202
|
+
};
|
|
203
|
+
const actionPriors = await this.buildLifecycleActionPriors(storage);
|
|
204
|
+
|
|
205
|
+
for (const memory of allMemories) {
|
|
206
|
+
if (
|
|
207
|
+
memory.frontmatter.status === "superseded" ||
|
|
208
|
+
memory.frontmatter.status === "forgotten"
|
|
209
|
+
) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
evaluatedCount += 1;
|
|
213
|
+
const currentState = resolveLifecycleState(memory.frontmatter);
|
|
214
|
+
const actionPriorScore = actionPriors.get(memory.frontmatter.id);
|
|
215
|
+
const signals: LifecycleSignals | undefined =
|
|
216
|
+
typeof actionPriorScore === "number" &&
|
|
217
|
+
Number.isFinite(actionPriorScore)
|
|
218
|
+
? { actionPriorScore }
|
|
219
|
+
: undefined;
|
|
220
|
+
const decision = decideLifecycleTransition(memory, policy, now, signals);
|
|
221
|
+
const nextState: LifecycleState =
|
|
222
|
+
memory.frontmatter.status === "archived"
|
|
223
|
+
? "archived"
|
|
224
|
+
: decision.nextState;
|
|
225
|
+
|
|
226
|
+
countsByState[nextState] += 1;
|
|
227
|
+
if (memory.frontmatter.verificationState === "disputed") {
|
|
228
|
+
disputedCount += 1;
|
|
229
|
+
}
|
|
230
|
+
if (nextState !== currentState) {
|
|
231
|
+
const key = `${currentState}->${nextState}`;
|
|
232
|
+
transitionCounts[key] = (transitionCounts[key] ?? 0) + 1;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const prevHeat = memory.frontmatter.heatScore;
|
|
236
|
+
const prevDecay = memory.frontmatter.decayScore;
|
|
237
|
+
const scoreDelta =
|
|
238
|
+
Math.abs((prevHeat ?? -1) - decision.heatScore) +
|
|
239
|
+
Math.abs((prevDecay ?? -1) - decision.decayScore);
|
|
240
|
+
const shouldPersist =
|
|
241
|
+
memory.frontmatter.lifecycleState !== nextState ||
|
|
242
|
+
memory.frontmatter.heatScore === undefined ||
|
|
243
|
+
memory.frontmatter.decayScore === undefined ||
|
|
244
|
+
memory.frontmatter.lastValidatedAt === undefined ||
|
|
245
|
+
scoreDelta >= 0.01;
|
|
246
|
+
|
|
247
|
+
if (!shouldPersist) continue;
|
|
248
|
+
|
|
249
|
+
const wrote = await storage.writeMemoryFrontmatter(memory, {
|
|
250
|
+
lifecycleState: nextState,
|
|
251
|
+
heatScore: decision.heatScore,
|
|
252
|
+
decayScore: decision.decayScore,
|
|
253
|
+
lastValidatedAt: nowIso,
|
|
254
|
+
});
|
|
255
|
+
if (wrote) updatedCount += 1;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Report how many memories had frontmatter rewritten so callers can record a
|
|
259
|
+
// catalog write touch for lifecycle-only passes (codex NR-tS).
|
|
260
|
+
if (!lifecycleCaps.lifecycleMetrics) return updatedCount;
|
|
261
|
+
|
|
262
|
+
const total = evaluatedCount;
|
|
263
|
+
const metrics = {
|
|
264
|
+
generatedAt: nowIso,
|
|
265
|
+
memoriesEvaluated: total,
|
|
266
|
+
memoriesUpdated: updatedCount,
|
|
267
|
+
countsByLifecycleState: countsByState,
|
|
268
|
+
transitionCounts,
|
|
269
|
+
staleRatio: total > 0 ? countsByState.stale / total : 0,
|
|
270
|
+
disputedRatio: total > 0 ? disputedCount / total : 0,
|
|
271
|
+
policy: {
|
|
272
|
+
promoteHeatThreshold: thresholds.promoteHeatThreshold,
|
|
273
|
+
staleDecayThreshold: thresholds.staleDecayThreshold,
|
|
274
|
+
archiveDecayThreshold: thresholds.archiveDecayThreshold,
|
|
275
|
+
protectedCategories: this.config.lifecycleProtectedCategories,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
const metricsPath = path.join(
|
|
279
|
+
storage.dir,
|
|
280
|
+
"state",
|
|
281
|
+
"lifecycle-metrics.json",
|
|
282
|
+
);
|
|
283
|
+
await mkdir(path.dirname(metricsPath), { recursive: true });
|
|
284
|
+
await writeFile(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
|
|
285
|
+
return updatedCount;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// -------------------------------------------------------------------------
|
|
289
|
+
// Fact archival
|
|
290
|
+
// -------------------------------------------------------------------------
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Archive old, low-importance, rarely-accessed facts (v6.0).
|
|
294
|
+
* Moves eligible facts from facts/ to archive/YYYY-MM-DD/.
|
|
295
|
+
* Returns the number of archived facts.
|
|
296
|
+
*/
|
|
297
|
+
async runFactArchival(
|
|
298
|
+
allMemories: MemoryFile[],
|
|
299
|
+
): Promise<number> {
|
|
300
|
+
const storage = this.deps.getStorage();
|
|
301
|
+
const now = Date.now();
|
|
302
|
+
const ageCutoffMs = this.config.factArchivalAgeDays * 24 * 60 * 60 * 1000;
|
|
303
|
+
const protectedCategories = new Set(
|
|
304
|
+
this.config.factArchivalProtectedCategories,
|
|
305
|
+
);
|
|
306
|
+
let archivedCount = 0;
|
|
307
|
+
|
|
308
|
+
for (const memory of allMemories) {
|
|
309
|
+
const fm = memory.frontmatter;
|
|
310
|
+
|
|
311
|
+
// Skip already-archived or superseded
|
|
312
|
+
if (fm.status && fm.status !== "active") continue;
|
|
313
|
+
|
|
314
|
+
// Skip protected categories
|
|
315
|
+
if (protectedCategories.has(fm.category)) continue;
|
|
316
|
+
|
|
317
|
+
// Skip corrections (always keep)
|
|
318
|
+
if (fm.category === "correction") continue;
|
|
319
|
+
|
|
320
|
+
// Check age requirement
|
|
321
|
+
const createdMs = new Date(fm.created).getTime();
|
|
322
|
+
if (now - createdMs < ageCutoffMs) continue;
|
|
323
|
+
|
|
324
|
+
// Check importance (only archive low-importance facts)
|
|
325
|
+
const importanceScore = fm.importance?.score ?? 0.5;
|
|
326
|
+
if (importanceScore >= this.config.factArchivalMaxImportance) continue;
|
|
327
|
+
|
|
328
|
+
// Check access count
|
|
329
|
+
const accessCount = fm.accessCount ?? 0;
|
|
330
|
+
if (accessCount > this.config.factArchivalMaxAccessCount) continue;
|
|
331
|
+
|
|
332
|
+
// All criteria met — archive
|
|
333
|
+
const result = await storage.archiveMemory(memory);
|
|
334
|
+
if (result) {
|
|
335
|
+
// Remove from the same storage-scoped content-hash index since it is
|
|
336
|
+
// no longer in hot search.
|
|
337
|
+
await this.deps.removeContentHashForMemory(
|
|
338
|
+
storage,
|
|
339
|
+
memory,
|
|
340
|
+
"fact-archival",
|
|
341
|
+
);
|
|
342
|
+
await this.deps.embeddingFallback.removeFromIndex(memory.frontmatter.id);
|
|
343
|
+
if (
|
|
344
|
+
resolveIndexingCapabilities(this.config).queryAwareIndexing &&
|
|
345
|
+
memory.path &&
|
|
346
|
+
memory.frontmatter?.created
|
|
347
|
+
) {
|
|
348
|
+
deindexMemory(
|
|
349
|
+
this.config.memoryDir,
|
|
350
|
+
memory.path,
|
|
351
|
+
memory.frontmatter.created,
|
|
352
|
+
memory.frontmatter.tags ?? [],
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
archivedCount++;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Save hash indexes if we removed any entries.
|
|
360
|
+
if (archivedCount > 0) {
|
|
361
|
+
await this.deps.saveContentHashIndexes().catch((err) =>
|
|
362
|
+
log.warn(`content-hash index save failed during archival: ${err}`),
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return archivedCount;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// -------------------------------------------------------------------------
|
|
370
|
+
// Summarization (Phase 4A)
|
|
371
|
+
// -------------------------------------------------------------------------
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Run memory summarization if memory count exceeds threshold (Phase 4A).
|
|
375
|
+
*/
|
|
376
|
+
async runSummarization(
|
|
377
|
+
allMemories: MemoryFile[],
|
|
378
|
+
): Promise<void> {
|
|
379
|
+
const storage = this.deps.getStorage();
|
|
380
|
+
// Only active memories count toward the threshold
|
|
381
|
+
const activeMemories = allMemories.filter(
|
|
382
|
+
(m) => isActiveMemoryStatus(m.frontmatter.status),
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
if (activeMemories.length < this.config.summarizationTriggerCount) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
log.info(
|
|
390
|
+
`memory count (${activeMemories.length}) exceeds threshold (${this.config.summarizationTriggerCount}) — running summarization`,
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// Sort by creation date, oldest first
|
|
394
|
+
const sorted = activeMemories.sort(
|
|
395
|
+
(a, b) =>
|
|
396
|
+
new Date(a.frontmatter.created).getTime() -
|
|
397
|
+
new Date(b.frontmatter.created).getTime(),
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
// Keep recent memories, with explicit zero handling so `slice(-0)` does not
|
|
401
|
+
// accidentally keep every memory out of the summarization candidate set.
|
|
402
|
+
const recentToKeep = Math.max(0, this.config.summarizationRecentToKeep);
|
|
403
|
+
const toSummarize = recentToKeep > 0 ? sorted.slice(0, -recentToKeep) : sorted;
|
|
404
|
+
|
|
405
|
+
// Filter candidates for summarization
|
|
406
|
+
const candidates = toSummarize.filter((m) => {
|
|
407
|
+
// Skip if protected by entity reference
|
|
408
|
+
if (m.frontmatter.entityRef) return false;
|
|
409
|
+
|
|
410
|
+
// Skip if protected by tag
|
|
411
|
+
const protectedTags = this.config.summarizationProtectedTags;
|
|
412
|
+
if (m.frontmatter.tags.some((t) => protectedTags.includes(t)))
|
|
413
|
+
return false;
|
|
414
|
+
|
|
415
|
+
// Skip if importance is above threshold
|
|
416
|
+
const importance = m.frontmatter.importance?.score ?? 0.5;
|
|
417
|
+
if (importance >= this.config.summarizationImportanceThreshold)
|
|
418
|
+
return false;
|
|
419
|
+
|
|
420
|
+
return true;
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
if (candidates.length < 50) {
|
|
424
|
+
log.debug(
|
|
425
|
+
`only ${candidates.length} candidates for summarization — skipping`,
|
|
426
|
+
);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Summarize in batches of 50
|
|
431
|
+
const batchSize = 50;
|
|
432
|
+
for (let i = 0; i < candidates.length; i += batchSize) {
|
|
433
|
+
const batch = candidates.slice(i, i + batchSize);
|
|
434
|
+
const batchData = batch.map((m) => ({
|
|
435
|
+
id: m.frontmatter.id,
|
|
436
|
+
content: m.content,
|
|
437
|
+
category: m.frontmatter.category,
|
|
438
|
+
created: m.frontmatter.created,
|
|
439
|
+
}));
|
|
440
|
+
|
|
441
|
+
const result = await this.deps.extraction.summarizeMemories(batchData);
|
|
442
|
+
if (!result) continue;
|
|
443
|
+
|
|
444
|
+
// Create summary
|
|
445
|
+
const summary: MemorySummary = {
|
|
446
|
+
id: `summary-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
|
447
|
+
createdAt: new Date().toISOString(),
|
|
448
|
+
timeRangeStart: batch[0].frontmatter.created,
|
|
449
|
+
timeRangeEnd: batch[batch.length - 1].frontmatter.created,
|
|
450
|
+
summaryText: result.summaryText,
|
|
451
|
+
keyFacts: result.keyFacts,
|
|
452
|
+
keyEntities: result.keyEntities,
|
|
453
|
+
sourceEpisodeIds: batch.map((m) => m.frontmatter.id),
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
await storage.writeSummary(summary);
|
|
457
|
+
|
|
458
|
+
// Archive source memories
|
|
459
|
+
const archived = await storage.archiveMemories(
|
|
460
|
+
batch.map((m) => m.frontmatter.id),
|
|
461
|
+
summary.id,
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
// Catalog write touch (issue #1499 sweep): summarization writes a durable
|
|
465
|
+
// summary and then rewrites source-memory archive status, bypassing the
|
|
466
|
+
// extraction write path. Record the touch after both mutations complete so
|
|
467
|
+
// `lastWriteAt` covers the final archived-state write.
|
|
468
|
+
// #1522: catalog touch handled at the storage chokepoint.
|
|
469
|
+
|
|
470
|
+
log.info(
|
|
471
|
+
`created summary ${summary.id} from ${batch.length} memories, archived ${archived}`,
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// -------------------------------------------------------------------------
|
|
477
|
+
// Topic extraction (Phase 4B)
|
|
478
|
+
// -------------------------------------------------------------------------
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Run topic extraction on all memories (Phase 4B).
|
|
482
|
+
*/
|
|
483
|
+
async runTopicExtraction(
|
|
484
|
+
allMemories: MemoryFile[],
|
|
485
|
+
): Promise<void> {
|
|
486
|
+
const storage = this.deps.getStorage();
|
|
487
|
+
// Only extract from active memories
|
|
488
|
+
const activeMemories = allMemories.filter(
|
|
489
|
+
(m) => isActiveMemoryStatus(m.frontmatter.status),
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
if (activeMemories.length === 0) return;
|
|
493
|
+
|
|
494
|
+
const topics = extractTopics(
|
|
495
|
+
activeMemories,
|
|
496
|
+
this.config.topicExtractionTopN,
|
|
497
|
+
);
|
|
498
|
+
await storage.saveTopics(topics);
|
|
499
|
+
|
|
500
|
+
log.debug(
|
|
501
|
+
`extracted ${topics.length} topics from ${activeMemories.length} memories`,
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|