@remnic/core 9.3.734 → 9.3.736
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-service-rjFfmfKB.d.ts → access-service-CdC0q4pr.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-D2NLDg4S.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-Z7J3OAPR.js → chunk-AE2HPUP7.js} +726 -645
- package/dist/chunk-AE2HPUP7.js.map +1 -0
- 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-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-BHy6Bo6u.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-C-xp_rtZ.d.ts} +141 -18
- package/dist/orchestrator.d.ts +7 -5
- package/dist/orchestrator.js +19 -21
- 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/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-COdwU-me.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 +1 -1
- 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/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CpFz51Pv.d.ts → types-w3Y232yi.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/entity-synthesis-coordinator.ts +319 -0
- package/src/orchestration/lifecycle-policy-coordinator.ts +504 -0
- package/src/orchestrator.ts +40 -618
- 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
|
@@ -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
|
+
}
|