@remnic/core 9.51.0 → 9.52.0
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-admin-ops-surface.d.ts +6 -5
- package/dist/access-admin-ops-surface.js +16 -16
- package/dist/access-authorization-probe.d.ts +6 -5
- package/dist/access-authorization-probe.js +17 -17
- package/dist/access-boundary.d.ts +6 -5
- package/dist/access-boundary.js +16 -16
- package/dist/access-cli.js +39 -39
- package/dist/access-extraction-force-flush.d.ts +6 -5
- package/dist/access-extraction-force-flush.js +16 -16
- package/dist/access-http-lcm-compaction.d.ts +6 -5
- package/dist/access-http-lifecycle-flush.d.ts +6 -5
- package/dist/access-http-offline-stream.d.ts +6 -5
- package/dist/access-http-query.js +16 -16
- package/dist/access-http.d.ts +6 -5
- package/dist/access-http.js +22 -22
- package/dist/access-identity-continuity-surface.d.ts +5 -4
- package/dist/access-identity-continuity-surface.js +16 -16
- package/dist/access-lcm-surface.d.ts +6 -5
- package/dist/access-lcm-surface.js +16 -16
- package/dist/access-mcp.d.ts +6 -5
- package/dist/access-mcp.js +20 -20
- package/dist/access-namespace-preflight.js +16 -16
- package/dist/access-observe-write-surface.d.ts +6 -5
- package/dist/access-observe-write-surface.js +16 -16
- package/dist/access-offline-manifest.d.ts +5 -4
- package/dist/access-operations-batch.js +17 -17
- package/dist/access-operations.d.ts +9 -8
- package/dist/access-operations.js +19 -19
- package/dist/access-recall-concurrency.d.ts +6 -5
- package/dist/access-recall-concurrency.js +16 -16
- package/dist/access-recall-response.d.ts +6 -5
- package/dist/access-recall-response.js +16 -16
- package/dist/access-recall-surface.d.ts +6 -5
- package/dist/access-recall-surface.js +16 -16
- package/dist/access-schema.d.ts +88 -88
- package/dist/{access-service-BY0KJ44c.d.ts → access-service-Cbk3bNbD.d.ts} +3 -3
- package/dist/access-service-helpers.d.ts +6 -5
- package/dist/access-service.d.ts +6 -5
- package/dist/access-service.js +16 -16
- package/dist/access-surface-catalog.d.ts +6 -5
- package/dist/access-wearables-meetings-surface.d.ts +2 -2
- package/dist/bootstrap.d.ts +5 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +7 -7
- package/dist/buffer.d.ts +1 -1
- package/dist/{capsule-merge-XMFBXVDP.js → capsule-merge-HCJJMLPS.js} +4 -4
- package/dist/causal-consolidation.js +8 -8
- package/dist/{chunk-PWN32TAG.js → chunk-2ASAS3CQ.js} +2 -2
- package/dist/{chunk-WQM326GS.js → chunk-2LY6GIIE.js} +2 -2
- package/dist/{chunk-JL43BVDE.js → chunk-2OIQDTDC.js} +2 -2
- package/dist/{chunk-33SV3E43.js → chunk-3OY7KXHM.js} +3 -3
- package/dist/{chunk-AIUBBHSF.js → chunk-5UZ6UCOZ.js} +3 -3
- package/dist/chunk-5WITETWU.js +591 -0
- package/dist/chunk-5WITETWU.js.map +1 -0
- package/dist/{chunk-UT5BV5OG.js → chunk-7HXZJAID.js} +2 -2
- package/dist/{chunk-M7BXDKPR.js → chunk-7M6NYQWB.js} +3 -3
- package/dist/{chunk-TPTECFWR.js → chunk-B6LZ4IBH.js} +3 -3
- package/dist/{chunk-J5LLX6IL.js → chunk-BF6SXNQJ.js} +10 -10
- package/dist/{chunk-4PC4PRJE.js → chunk-BKIFTXHR.js} +2 -2
- package/dist/{chunk-VVG2BOKA.js → chunk-BMEYMKWX.js} +2 -2
- package/dist/{chunk-DCZBSE4F.js → chunk-D5YOZ66N.js} +18 -18
- package/dist/{chunk-BHXYAVUM.js → chunk-DLG5V6ND.js} +2 -2
- package/dist/{chunk-52UKFTUK.js → chunk-F4EU6VUC.js} +2 -2
- package/dist/{chunk-M4A44LUA.js → chunk-GSTIBXBW.js} +2 -2
- package/dist/{chunk-W5XVQFLM.js → chunk-GXFSQ6SD.js} +2 -2
- package/dist/{chunk-XADV5IZ3.js → chunk-HDIUYMSB.js} +5 -5
- package/dist/{chunk-FXTYIA46.js → chunk-J272WKX2.js} +2 -2
- package/dist/{chunk-ENTCVTQR.js → chunk-JJRVPWFY.js} +11 -1
- package/dist/chunk-JJRVPWFY.js.map +1 -0
- package/dist/{chunk-JYL3BVVZ.js → chunk-JSEJH2YQ.js} +2 -2
- package/dist/{chunk-5UDMFE3Q.js → chunk-MLXZD4WM.js} +2 -2
- package/dist/{chunk-PUSLMZBQ.js → chunk-NOEMGE56.js} +2 -2
- package/dist/{chunk-C5QLI33R.js → chunk-QINJITDS.js} +2 -2
- package/dist/{chunk-45BRYON6.js → chunk-QPOHMO6M.js} +2 -2
- package/dist/{chunk-ZQOCRIGA.js → chunk-QYN5PXDZ.js} +3 -3
- package/dist/{chunk-PA45XCUD.js → chunk-RANKJI5T.js} +2 -2
- package/dist/{chunk-ZHY5TMJG.js → chunk-RMHMUUBW.js} +2392 -628
- package/dist/chunk-RMHMUUBW.js.map +1 -0
- package/dist/{chunk-37ZO6LLJ.js → chunk-RYLEDKQ2.js} +2 -2
- package/dist/{chunk-CV6BBVYV.js → chunk-TEMSWHQD.js} +2 -2
- package/dist/{chunk-QGR6OVGT.js → chunk-VFSAWRMZ.js} +2 -2
- package/dist/{chunk-NLK2VZYZ.js → chunk-VXCNQYTC.js} +2 -2
- package/dist/{chunk-AZ2QBGYB.js → chunk-W7Y5JDVB.js} +1 -1
- package/dist/{chunk-VBHPOWBJ.js → chunk-WD5B5AIE.js} +1051 -591
- package/dist/chunk-WD5B5AIE.js.map +1 -0
- package/dist/{chunk-OYESWJ43.js → chunk-WLRD2TXF.js} +15 -10
- package/dist/chunk-WLRD2TXF.js.map +1 -0
- package/dist/{chunk-4F6X3RXW.js → chunk-X57M2Q4I.js} +2 -2
- package/dist/{chunk-6MTSFX7A.js → chunk-X7XEDOSL.js} +8 -8
- package/dist/{chunk-UEVLYVNW.js → chunk-YXKVLYXU.js} +2 -2
- package/dist/{chunk-OQAL6SIR.js → chunk-ZMSZVISA.js} +2 -2
- package/dist/{cli-CnOkH9hA.d.ts → cli-DMAFI0qt.d.ts} +3 -3
- package/dist/cli.d.ts +7 -6
- package/dist/cli.js +33 -33
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +7 -7
- package/dist/connectors/codex-materialize-runner.js +7 -7
- package/dist/connectors/index.js +7 -7
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-provenance-check.js +4 -4
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/consolidation-undo.js +3 -3
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +1 -1
- package/dist/convergence-refresh.js +9 -9
- package/dist/corpus-watermark.js +9 -9
- package/dist/dependency-propagation-delivery-D63r24pH.d.ts +41 -0
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +7 -7
- package/dist/explicit-capture.d.ts +5 -4
- package/dist/explicit-capture.js +4 -4
- package/dist/external-wiki-access.d.ts +6 -5
- package/dist/external-wiki-access.js +17 -17
- package/dist/external-wiki-mcp-tools.d.ts +6 -5
- package/dist/extraction.js +7 -7
- package/dist/{forget-UJDJHG6R.js → forget-HDS4N6CG.js} +3 -3
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/index.d.ts +687 -686
- package/dist/index.js +39 -39
- package/dist/maintenance/memory-governance.js +7 -7
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +7 -7
- package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-projection.js +8 -8
- package/dist/{maintenance-CKwxpdRx.d.ts → maintenance-kBII2qUI.d.ts} +3 -2
- package/dist/mcp-memory-inspector-app.d.ts +6 -5
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +8 -8
- package/dist/namespaces/storage.d.ts +1 -1
- package/dist/namespaces/storage.js +7 -7
- package/dist/operator-doctor-corpus.js +10 -10
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +15 -15
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +12 -12
- package/dist/{orchestrator-BshGam-o.d.ts → orchestrator-DHy5LtTy.d.ts} +20 -35
- package/dist/orchestrator.d.ts +5 -4
- package/dist/orchestrator.js +39 -39
- package/dist/page-versioning.js +3 -3
- package/dist/schemas.d.ts +138 -138
- package/dist/semantic-consolidation.js +8 -8
- package/dist/semantic-rule-promotion.js +7 -7
- package/dist/semantic-rule-verifier.js +7 -7
- package/dist/{service-BIgVM7fL.d.ts → service-PT2_z7xm.d.ts} +1 -1
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/source-agent-qualifier.js +7 -7
- package/dist/{storage-CVfGWqCI.d.ts → storage-BmVudhk4.d.ts} +46 -27
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +6 -6
- package/dist/temporal-supersession.d.ts +51 -26
- package/dist/temporal-supersession.js +3 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/transfer/capsule-import.js +4 -4
- package/dist/transfer/types.d.ts +66 -66
- package/dist/verified-recall.js +7 -7
- package/package.json +2 -2
- package/src/lifecycle/tombstones.ts +30 -0
- package/src/orchestration/consolidation-run.ts +324 -106
- package/src/orchestration/contradiction-linking-coordinator.ts +237 -64
- package/src/orchestration/dependency-propagation-delivery.test.ts +2353 -0
- package/src/orchestration/dependency-propagation-delivery.ts +1143 -0
- package/src/orchestration/dependency-propagation-queue-state.ts +220 -0
- package/src/orchestration/dependency-propagation-recovery-replay.ts +237 -0
- package/src/orchestration/dependency-propagation-replay-reconciliation.ts +73 -0
- package/src/orchestration/dependency-propagation-triggers.test.ts +1069 -11
- package/src/orchestration/dependency-propagation.test.ts +82 -31
- package/src/orchestration/dependency-propagation.ts +55 -17
- package/src/orchestration/extraction-persist-deps.ts +2 -2
- package/src/orchestration/extraction-persist.ts +14 -15
- package/src/orchestration/extraction-queue-coordinator.ts +23 -1
- package/src/orchestration/extraction-shutdown.ts +29 -0
- package/src/orchestration/maintenance.ts +13 -7
- package/src/orchestration/turn-ingestion.ts +5 -1
- package/src/orchestrator-background-writes.test.ts +265 -1
- package/src/orchestrator-extraction-queue.test.ts +39 -0
- package/src/orchestrator.ts +59 -58
- package/src/storage/committed-invalidation.ts +34 -0
- package/src/storage/deletion-revision-store.ts +529 -0
- package/src/storage/supersession-audit.ts +41 -0
- package/src/storage/supersession-side-effects.ts +52 -25
- package/src/storage-contract/failure-semantics.test.ts +12 -0
- package/src/storage-contract/round-trip.test.ts +184 -2
- package/src/storage-deletion-revisions.test.ts +213 -1
- package/src/storage-frontmatter-cas.test.ts +141 -0
- package/src/storage-memory-lifecycle-ledger.test.ts +372 -0
- package/src/storage-replay.test.ts +149 -0
- package/src/storage.ts +345 -358
- package/src/temporal-supersession.test.ts +431 -2
- package/src/temporal-supersession.ts +567 -107
- package/src/testing/subjects/dependency-propagation.test.ts +179 -38
- package/dist/chunk-ENTCVTQR.js.map +0 -1
- package/dist/chunk-EWMTOVMY.js +0 -484
- package/dist/chunk-EWMTOVMY.js.map +0 -1
- package/dist/chunk-OYESWJ43.js.map +0 -1
- package/dist/chunk-VBHPOWBJ.js.map +0 -1
- package/dist/chunk-ZHY5TMJG.js.map +0 -1
- /package/dist/{capsule-merge-XMFBXVDP.js.map → capsule-merge-HCJJMLPS.js.map} +0 -0
- /package/dist/{chunk-PWN32TAG.js.map → chunk-2ASAS3CQ.js.map} +0 -0
- /package/dist/{chunk-WQM326GS.js.map → chunk-2LY6GIIE.js.map} +0 -0
- /package/dist/{chunk-JL43BVDE.js.map → chunk-2OIQDTDC.js.map} +0 -0
- /package/dist/{chunk-33SV3E43.js.map → chunk-3OY7KXHM.js.map} +0 -0
- /package/dist/{chunk-AIUBBHSF.js.map → chunk-5UZ6UCOZ.js.map} +0 -0
- /package/dist/{chunk-UT5BV5OG.js.map → chunk-7HXZJAID.js.map} +0 -0
- /package/dist/{chunk-M7BXDKPR.js.map → chunk-7M6NYQWB.js.map} +0 -0
- /package/dist/{chunk-TPTECFWR.js.map → chunk-B6LZ4IBH.js.map} +0 -0
- /package/dist/{chunk-J5LLX6IL.js.map → chunk-BF6SXNQJ.js.map} +0 -0
- /package/dist/{chunk-4PC4PRJE.js.map → chunk-BKIFTXHR.js.map} +0 -0
- /package/dist/{chunk-VVG2BOKA.js.map → chunk-BMEYMKWX.js.map} +0 -0
- /package/dist/{chunk-DCZBSE4F.js.map → chunk-D5YOZ66N.js.map} +0 -0
- /package/dist/{chunk-BHXYAVUM.js.map → chunk-DLG5V6ND.js.map} +0 -0
- /package/dist/{chunk-52UKFTUK.js.map → chunk-F4EU6VUC.js.map} +0 -0
- /package/dist/{chunk-M4A44LUA.js.map → chunk-GSTIBXBW.js.map} +0 -0
- /package/dist/{chunk-W5XVQFLM.js.map → chunk-GXFSQ6SD.js.map} +0 -0
- /package/dist/{chunk-XADV5IZ3.js.map → chunk-HDIUYMSB.js.map} +0 -0
- /package/dist/{chunk-FXTYIA46.js.map → chunk-J272WKX2.js.map} +0 -0
- /package/dist/{chunk-JYL3BVVZ.js.map → chunk-JSEJH2YQ.js.map} +0 -0
- /package/dist/{chunk-5UDMFE3Q.js.map → chunk-MLXZD4WM.js.map} +0 -0
- /package/dist/{chunk-PUSLMZBQ.js.map → chunk-NOEMGE56.js.map} +0 -0
- /package/dist/{chunk-C5QLI33R.js.map → chunk-QINJITDS.js.map} +0 -0
- /package/dist/{chunk-45BRYON6.js.map → chunk-QPOHMO6M.js.map} +0 -0
- /package/dist/{chunk-ZQOCRIGA.js.map → chunk-QYN5PXDZ.js.map} +0 -0
- /package/dist/{chunk-PA45XCUD.js.map → chunk-RANKJI5T.js.map} +0 -0
- /package/dist/{chunk-37ZO6LLJ.js.map → chunk-RYLEDKQ2.js.map} +0 -0
- /package/dist/{chunk-CV6BBVYV.js.map → chunk-TEMSWHQD.js.map} +0 -0
- /package/dist/{chunk-QGR6OVGT.js.map → chunk-VFSAWRMZ.js.map} +0 -0
- /package/dist/{chunk-NLK2VZYZ.js.map → chunk-VXCNQYTC.js.map} +0 -0
- /package/dist/{chunk-AZ2QBGYB.js.map → chunk-W7Y5JDVB.js.map} +0 -0
- /package/dist/{chunk-4F6X3RXW.js.map → chunk-X57M2Q4I.js.map} +0 -0
- /package/dist/{chunk-6MTSFX7A.js.map → chunk-X7XEDOSL.js.map} +0 -0
- /package/dist/{chunk-UEVLYVNW.js.map → chunk-YXKVLYXU.js.map} +0 -0
- /package/dist/{chunk-OQAL6SIR.js.map → chunk-ZMSZVISA.js.map} +0 -0
- /package/dist/{forget-UJDJHG6R.js.map → forget-HDS4N6CG.js.map} +0 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
import {
|
|
2
|
+
effectiveValidAt
|
|
3
|
+
} from "./chunk-6CIAGZ6X.js";
|
|
4
|
+
import {
|
|
5
|
+
log
|
|
6
|
+
} from "./chunk-3WCASNQZ.js";
|
|
7
|
+
|
|
8
|
+
// src/temporal-supersession.ts
|
|
9
|
+
import { createHash } from "crypto";
|
|
10
|
+
function normalizeSupersessionKey(raw) {
|
|
11
|
+
return raw.trim().toLowerCase().replace(/[\s\-]+/g, "-").replace(/^-|-$/g, "");
|
|
12
|
+
}
|
|
13
|
+
function computeSupersessionKey(entityRef, attributeName) {
|
|
14
|
+
if (!entityRef || typeof entityRef !== "string") return null;
|
|
15
|
+
if (!attributeName || typeof attributeName !== "string") return null;
|
|
16
|
+
const entity = normalizeSupersessionKey(entityRef);
|
|
17
|
+
const attr = normalizeSupersessionKey(attributeName);
|
|
18
|
+
if (entity.length === 0 || attr.length === 0) return null;
|
|
19
|
+
return `${entity}::${attr}`;
|
|
20
|
+
}
|
|
21
|
+
function supersessionKeysForFact(spec) {
|
|
22
|
+
if (!spec.entityRef) return [];
|
|
23
|
+
if (!spec.structuredAttributes) return [];
|
|
24
|
+
const keys = [];
|
|
25
|
+
for (const attrName of Object.keys(spec.structuredAttributes)) {
|
|
26
|
+
const key = computeSupersessionKey(spec.entityRef, attrName);
|
|
27
|
+
if (key) keys.push(key);
|
|
28
|
+
}
|
|
29
|
+
return keys;
|
|
30
|
+
}
|
|
31
|
+
function lookupAttributeByNormalizedKey(attributes, rawKey) {
|
|
32
|
+
const normalizedTarget = normalizeSupersessionKey(rawKey);
|
|
33
|
+
for (const [k, v] of Object.entries(attributes)) {
|
|
34
|
+
if (normalizeSupersessionKey(k) === normalizedTarget) return v;
|
|
35
|
+
}
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
38
|
+
function shouldSupersedeExisting(args) {
|
|
39
|
+
const { candidate, newEntityRef, newAttributes, newCreatedAt, newMemoryId } = args;
|
|
40
|
+
if (candidate.id === newMemoryId) return null;
|
|
41
|
+
if (candidate.status && candidate.status !== "active") return null;
|
|
42
|
+
if (!candidate.entityRef) return null;
|
|
43
|
+
if (!candidate.structuredAttributes) return null;
|
|
44
|
+
const candidateEntityNorm = normalizeSupersessionKey(candidate.entityRef);
|
|
45
|
+
const newEntityNorm = normalizeSupersessionKey(newEntityRef);
|
|
46
|
+
if (candidateEntityNorm !== newEntityNorm) return null;
|
|
47
|
+
const candidateCreated = Date.parse(effectiveValidAt(candidate));
|
|
48
|
+
const newCreated = Date.parse(newCreatedAt);
|
|
49
|
+
if (!Number.isFinite(candidateCreated) || !Number.isFinite(newCreated)) return null;
|
|
50
|
+
if (candidateCreated >= newCreated) return null;
|
|
51
|
+
const matchedKeys = [];
|
|
52
|
+
for (const [attrName, newValue] of Object.entries(newAttributes)) {
|
|
53
|
+
const candidateValue = lookupAttributeByNormalizedKey(
|
|
54
|
+
candidate.structuredAttributes,
|
|
55
|
+
attrName
|
|
56
|
+
);
|
|
57
|
+
if (candidateValue === void 0) continue;
|
|
58
|
+
if (normalizeValue(String(candidateValue)) === normalizeValue(newValue)) continue;
|
|
59
|
+
const key = computeSupersessionKey(newEntityRef, attrName);
|
|
60
|
+
if (key) matchedKeys.push(key);
|
|
61
|
+
}
|
|
62
|
+
return matchedKeys.length > 0 ? { matchedKeys } : null;
|
|
63
|
+
}
|
|
64
|
+
function normalizeValue(v) {
|
|
65
|
+
return v.trim().toLowerCase();
|
|
66
|
+
}
|
|
67
|
+
function temporalSupersessionOperationKey(sourceMemoryId, replacementId, mutation) {
|
|
68
|
+
return createHash("sha256").update(
|
|
69
|
+
JSON.stringify({
|
|
70
|
+
sourceMemoryId,
|
|
71
|
+
replacementId,
|
|
72
|
+
cause: "temporal_supersession",
|
|
73
|
+
supersededAt: mutation.supersededAt,
|
|
74
|
+
invalidAt: mutation.invalidAt ?? null,
|
|
75
|
+
matchedKeys: [...mutation.matchedKeys].sort(compareByteStable)
|
|
76
|
+
})
|
|
77
|
+
).digest("hex");
|
|
78
|
+
}
|
|
79
|
+
function compareByteStable(left, right) {
|
|
80
|
+
return Buffer.from(left, "utf8").compare(Buffer.from(right, "utf8"));
|
|
81
|
+
}
|
|
82
|
+
function canonicalTemporalValue(value) {
|
|
83
|
+
if (Array.isArray(value)) return value.map((entry) => canonicalTemporalValue(entry));
|
|
84
|
+
if (value && typeof value === "object") {
|
|
85
|
+
return Object.fromEntries(
|
|
86
|
+
Object.entries(value).sort(([left], [right]) => compareByteStable(left, right)).map(([key, entry]) => [key, canonicalTemporalValue(entry)])
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
function temporalSnapshotKey(memory) {
|
|
92
|
+
return JSON.stringify(
|
|
93
|
+
canonicalTemporalValue({
|
|
94
|
+
content: memory.content,
|
|
95
|
+
frontmatter: memory.frontmatter
|
|
96
|
+
})
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
function temporalMutationPatch(replacementId, mutation) {
|
|
100
|
+
return {
|
|
101
|
+
status: "superseded",
|
|
102
|
+
supersededBy: replacementId,
|
|
103
|
+
supersededAt: mutation.supersededAt,
|
|
104
|
+
updated: mutation.supersededAt,
|
|
105
|
+
...mutation.invalidAt ? { invalid_at: mutation.invalidAt } : {}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
async function classifyTemporalPrimaryMutation(args) {
|
|
109
|
+
let current;
|
|
110
|
+
try {
|
|
111
|
+
current = await args.storage.readMemoryByPath(args.path);
|
|
112
|
+
} catch {
|
|
113
|
+
return "unknown";
|
|
114
|
+
}
|
|
115
|
+
if (!current) return "unknown";
|
|
116
|
+
const beforeKey = temporalSnapshotKey(args.before);
|
|
117
|
+
const committedKey = temporalSnapshotKey({
|
|
118
|
+
content: args.before.content,
|
|
119
|
+
frontmatter: { ...args.before.frontmatter, ...args.patch }
|
|
120
|
+
});
|
|
121
|
+
const currentKey = temporalSnapshotKey(current);
|
|
122
|
+
if (currentKey === committedKey) return "committed";
|
|
123
|
+
if (currentKey === beforeKey) return "not-committed";
|
|
124
|
+
return "unknown";
|
|
125
|
+
}
|
|
126
|
+
async function settleTemporalPropagationAfterPrimaryFailure(pending, commitState, memoryId) {
|
|
127
|
+
let token = pending.token;
|
|
128
|
+
if (commitState === "not-committed") {
|
|
129
|
+
if (token !== null) {
|
|
130
|
+
try {
|
|
131
|
+
await pending.delivery.cancel(token);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
log.warn(
|
|
134
|
+
`temporal-supersession: dependency propagation cancellation failed for ${memoryId}: ${error}`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (token === null && (commitState === "committed" || commitState === "unknown")) {
|
|
141
|
+
try {
|
|
142
|
+
token = await pending.delivery.prepare(pending.event);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
log.warn(
|
|
145
|
+
`temporal-supersession: dependency propagation recovery preparation failed for ${memoryId}: ${error}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (token !== null) {
|
|
150
|
+
try {
|
|
151
|
+
await pending.delivery.deferPrepared(token);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
log.warn(`temporal-supersession: dependency propagation defer failed for ${memoryId}: ${error}`);
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (commitState === "committed") {
|
|
158
|
+
try {
|
|
159
|
+
await pending.delivery.afterMutation(null, pending.event);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
log.warn(`temporal-supersession: dependency propagation fallback failed for ${memoryId}: ${error}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function hasTemporalLifecycleEffect(args) {
|
|
166
|
+
const events = await args.storage.getMemoryTimeline(args.memoryId, 200);
|
|
167
|
+
return events.some((event) => {
|
|
168
|
+
if (event.memoryId !== args.memoryId || event.eventType !== "superseded" && event.eventType !== "updated" || event.timestamp !== args.timestamp || event.after?.status !== "superseded") {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
if (event.correlationId !== void 0) return event.correlationId === args.operationKey;
|
|
172
|
+
return event.reasonCode === args.reasonCode && Array.isArray(event.relatedMemoryIds) && event.relatedMemoryIds.length === args.relatedMemoryIds.length && event.relatedMemoryIds.every((memoryId, index) => memoryId === args.relatedMemoryIds[index]);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async function hasTemporalTombstoneEffect(args) {
|
|
176
|
+
if (!args.storage.hasExactTombstone) return false;
|
|
177
|
+
return args.storage.hasExactTombstone({
|
|
178
|
+
sourceMemoryId: args.oldMemory.frontmatter.id,
|
|
179
|
+
...args.oldMemory.frontmatter.contentHash ? { contentHash: args.oldMemory.frontmatter.contentHash } : {},
|
|
180
|
+
...args.oldMemory.frontmatter.entityRef ? { entityRef: args.oldMemory.frontmatter.entityRef } : {},
|
|
181
|
+
...args.supersessionKey ? { supersessionKey: args.supersessionKey } : {},
|
|
182
|
+
createdAt: args.createdAt,
|
|
183
|
+
operationKey: args.operationKey
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
async function ensureTemporalLifecycleEffect(args) {
|
|
187
|
+
const reasonCode = args.child ? "structured-attribute-update-child-chunk" : "structured-attribute-update";
|
|
188
|
+
const relatedMemoryIds = args.child ? [args.replacementId, args.memory.frontmatter.parentId ?? ""].filter(Boolean) : [args.replacementId];
|
|
189
|
+
const lifecycleEffect = await hasTemporalLifecycleEffect({
|
|
190
|
+
storage: args.storage,
|
|
191
|
+
memoryId: args.memory.frontmatter.id,
|
|
192
|
+
timestamp: args.mutation.supersededAt,
|
|
193
|
+
operationKey: args.operationKey,
|
|
194
|
+
reasonCode,
|
|
195
|
+
relatedMemoryIds
|
|
196
|
+
});
|
|
197
|
+
if (lifecycleEffect === void 0) return false;
|
|
198
|
+
if (lifecycleEffect === true) return true;
|
|
199
|
+
if (lifecycleEffect === false || args.memory.frontmatter.status !== "superseded") {
|
|
200
|
+
if (!args.storage.writeMemoryFrontmatterIfUnchanged) return false;
|
|
201
|
+
const wrote = await args.storage.writeMemoryFrontmatterIfUnchanged(
|
|
202
|
+
args.memory,
|
|
203
|
+
{
|
|
204
|
+
status: "superseded",
|
|
205
|
+
supersededBy: args.replacementId,
|
|
206
|
+
supersededAt: args.mutation.supersededAt,
|
|
207
|
+
updated: args.mutation.supersededAt,
|
|
208
|
+
...args.mutation.invalidAt && !args.memory.frontmatter.invalid_at ? { invalid_at: args.mutation.invalidAt } : {}
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
actor: "temporal-supersession",
|
|
212
|
+
reasonCode: args.child ? "structured-attribute-update-child-chunk" : "structured-attribute-update",
|
|
213
|
+
relatedMemoryIds: args.child ? [args.replacementId, args.memory.frontmatter.parentId ?? ""].filter(Boolean) : [args.replacementId],
|
|
214
|
+
correlationId: args.operationKey
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
return wrote;
|
|
218
|
+
}
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
async function expireChildChunksForSupersededParent(args) {
|
|
222
|
+
const processedChunkIds = /* @__PURE__ */ new Set();
|
|
223
|
+
const chunks = args.allCandidates.filter(
|
|
224
|
+
(candidate) => candidate.frontmatter.parentId === args.parentId
|
|
225
|
+
);
|
|
226
|
+
for (const chunk of chunks) {
|
|
227
|
+
const chunkKey = chunk.frontmatter.id ?? chunk.path;
|
|
228
|
+
if (processedChunkIds.has(chunkKey)) continue;
|
|
229
|
+
try {
|
|
230
|
+
const freshChunk = await args.storage.readMemoryByPath(chunk.path);
|
|
231
|
+
if (!freshChunk) continue;
|
|
232
|
+
processedChunkIds.add(chunkKey);
|
|
233
|
+
const freshStatus = freshChunk.frontmatter.status ?? "active";
|
|
234
|
+
if (freshStatus !== "active" && !(freshStatus === "superseded" && freshChunk.frontmatter.supersededBy === args.newMemoryId)) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const completed = await ensureTemporalLifecycleEffect({
|
|
238
|
+
storage: args.storage,
|
|
239
|
+
memory: freshChunk,
|
|
240
|
+
replacementId: args.newMemoryId,
|
|
241
|
+
mutation: {
|
|
242
|
+
supersededAt: args.supersededAt,
|
|
243
|
+
...args.invalidAt ? { invalidAt: args.invalidAt } : {},
|
|
244
|
+
matchedKeys: []
|
|
245
|
+
},
|
|
246
|
+
operationKey: `${args.operationKey}:child:${freshChunk.frontmatter.id}`,
|
|
247
|
+
child: true
|
|
248
|
+
});
|
|
249
|
+
if (!completed) return false;
|
|
250
|
+
} catch (err) {
|
|
251
|
+
log.warn(
|
|
252
|
+
`temporal-supersession: failed to expire child chunk ${chunk.frontmatter.id} for parent ${args.parentId}: ${err}`
|
|
253
|
+
);
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
async function applyTemporalSupersessionPrimaryMutation(args) {
|
|
260
|
+
const { storage, oldMemory, replacementId, mutation } = args;
|
|
261
|
+
if (typeof storage.getMemoryTimeline !== "function") {
|
|
262
|
+
log.warn("temporal-supersession: required memory timeline adapter is missing");
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
const operationKey = temporalSupersessionOperationKey(
|
|
266
|
+
oldMemory.frontmatter.id,
|
|
267
|
+
replacementId,
|
|
268
|
+
mutation
|
|
269
|
+
);
|
|
270
|
+
const alreadyApplied = oldMemory.frontmatter.status === "superseded" && oldMemory.frontmatter.supersededBy === replacementId && oldMemory.frontmatter.supersededAt === mutation.supersededAt && (mutation.invalidAt === void 0 || oldMemory.frontmatter.invalid_at === mutation.invalidAt);
|
|
271
|
+
const lifecycleEffect = alreadyApplied ? await hasTemporalLifecycleEffect({
|
|
272
|
+
storage,
|
|
273
|
+
memoryId: oldMemory.frontmatter.id,
|
|
274
|
+
timestamp: mutation.supersededAt,
|
|
275
|
+
operationKey,
|
|
276
|
+
reasonCode: "structured-attribute-update",
|
|
277
|
+
relatedMemoryIds: [replacementId]
|
|
278
|
+
}) : void 0;
|
|
279
|
+
if (alreadyApplied && lifecycleEffect === void 0) return false;
|
|
280
|
+
if (!alreadyApplied || lifecycleEffect === false) {
|
|
281
|
+
if (!storage.writeMemoryFrontmatterIfUnchanged) return false;
|
|
282
|
+
const wrote = await storage.writeMemoryFrontmatterIfUnchanged(
|
|
283
|
+
oldMemory,
|
|
284
|
+
temporalMutationPatch(replacementId, mutation),
|
|
285
|
+
{
|
|
286
|
+
actor: "temporal-supersession",
|
|
287
|
+
reasonCode: "structured-attribute-update",
|
|
288
|
+
relatedMemoryIds: [replacementId],
|
|
289
|
+
correlationId: operationKey
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
if (!wrote) return false;
|
|
293
|
+
}
|
|
294
|
+
let allCandidates = args.allCandidates;
|
|
295
|
+
if (!allCandidates) {
|
|
296
|
+
let hotMemories;
|
|
297
|
+
let coldMemories;
|
|
298
|
+
try {
|
|
299
|
+
hotMemories = await storage.readAllMemories();
|
|
300
|
+
} catch (error) {
|
|
301
|
+
log.warn(`temporal-supersession: recovery hot-memory scan failed: ${error}`);
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
try {
|
|
305
|
+
coldMemories = await storage.readAllColdMemories();
|
|
306
|
+
} catch (error) {
|
|
307
|
+
log.warn(`temporal-supersession: recovery cold-memory scan failed: ${error}`);
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
allCandidates = [...hotMemories, ...coldMemories];
|
|
311
|
+
}
|
|
312
|
+
const childrenCompleted = await expireChildChunksForSupersededParent({
|
|
313
|
+
storage,
|
|
314
|
+
allCandidates,
|
|
315
|
+
parentId: oldMemory.frontmatter.id,
|
|
316
|
+
newMemoryId: replacementId,
|
|
317
|
+
supersededAt: mutation.supersededAt,
|
|
318
|
+
invalidAt: mutation.invalidAt ?? oldMemory.frontmatter.invalid_at,
|
|
319
|
+
operationKey
|
|
320
|
+
});
|
|
321
|
+
if (!childrenCompleted) return false;
|
|
322
|
+
const keysToTombstone = mutation.matchedKeys.length > 0 ? mutation.matchedKeys : [void 0];
|
|
323
|
+
for (const key of keysToTombstone) {
|
|
324
|
+
const tombstoneOperationKey = `${operationKey}:tombstone:${key ?? "content"}`;
|
|
325
|
+
if (await hasTemporalTombstoneEffect({
|
|
326
|
+
storage,
|
|
327
|
+
oldMemory,
|
|
328
|
+
supersessionKey: key,
|
|
329
|
+
operationKey: tombstoneOperationKey,
|
|
330
|
+
createdAt: mutation.supersededAt
|
|
331
|
+
})) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
try {
|
|
335
|
+
const tombstoneId = await storage.appendTombstone({
|
|
336
|
+
reason: "supersession",
|
|
337
|
+
createdBy: "supersession",
|
|
338
|
+
sourceMemoryId: oldMemory.frontmatter.id,
|
|
339
|
+
...oldMemory.frontmatter.contentHash ? { contentHash: oldMemory.frontmatter.contentHash } : {},
|
|
340
|
+
rawContent: oldMemory.content,
|
|
341
|
+
...oldMemory.frontmatter.entityRef ? { entityRef: oldMemory.frontmatter.entityRef } : {},
|
|
342
|
+
...key ? { supersessionKey: key } : {},
|
|
343
|
+
createdAt: mutation.supersededAt,
|
|
344
|
+
operationKey: tombstoneOperationKey
|
|
345
|
+
});
|
|
346
|
+
if (tombstoneId === null && storage.isTombstonesEnabled?.() !== false) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
} catch (error) {
|
|
350
|
+
log.warn(
|
|
351
|
+
`temporal-supersession: tombstone emit failed for ${oldMemory.frontmatter.id}${key ? ` (key=${key})` : ""} : ${error}`
|
|
352
|
+
);
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
async function applyTemporalSupersession(args) {
|
|
359
|
+
const empty = { supersededIds: [], matchedKeys: [] };
|
|
360
|
+
const createdAtMs = typeof args.createdAt === "string" ? Date.parse(args.createdAt) : Number.NaN;
|
|
361
|
+
if (!Number.isFinite(createdAtMs)) {
|
|
362
|
+
log.warn(`temporal-supersession: refusing mutation with invalid createdAt: ${String(args.createdAt)}`);
|
|
363
|
+
return empty;
|
|
364
|
+
}
|
|
365
|
+
if (!args.enabled) return empty;
|
|
366
|
+
if (!args.entityRef) return empty;
|
|
367
|
+
if (!args.structuredAttributes) return empty;
|
|
368
|
+
if (Object.keys(args.structuredAttributes).length === 0) return empty;
|
|
369
|
+
if (typeof args.storage.getMemoryTimeline !== "function") {
|
|
370
|
+
log.warn("temporal-supersession: required memory timeline adapter is missing");
|
|
371
|
+
return empty;
|
|
372
|
+
}
|
|
373
|
+
const newKeys = supersessionKeysForFact({
|
|
374
|
+
entityRef: args.entityRef,
|
|
375
|
+
structuredAttributes: args.structuredAttributes
|
|
376
|
+
});
|
|
377
|
+
if (newKeys.length === 0) return empty;
|
|
378
|
+
let hotMemories;
|
|
379
|
+
try {
|
|
380
|
+
hotMemories = await args.storage.readAllMemories();
|
|
381
|
+
} catch (err) {
|
|
382
|
+
log.warn(`temporal-supersession: readAllMemories failed: ${err}`);
|
|
383
|
+
return empty;
|
|
384
|
+
}
|
|
385
|
+
const newMemoryFile = hotMemories.find((m) => m.frontmatter.id === args.newMemoryId);
|
|
386
|
+
const persistedCreatedAt = args.useCallerTimestamp ? args.createdAt : newMemoryFile ? effectiveValidAt(newMemoryFile.frontmatter) : args.createdAt;
|
|
387
|
+
const supersededIds = [];
|
|
388
|
+
const matchedKeys = /* @__PURE__ */ new Set();
|
|
389
|
+
const processedIds = /* @__PURE__ */ new Set();
|
|
390
|
+
let coldMemories;
|
|
391
|
+
try {
|
|
392
|
+
coldMemories = await args.storage.readAllColdMemories();
|
|
393
|
+
} catch (err) {
|
|
394
|
+
log.warn(`temporal-supersession: readAllColdMemories failed: ${err}`);
|
|
395
|
+
coldMemories = [];
|
|
396
|
+
}
|
|
397
|
+
const allCandidates = [...hotMemories, ...coldMemories];
|
|
398
|
+
const replacementMemory = allCandidates.find((memory) => memory.frontmatter.id === args.newMemoryId) ?? newMemoryFile;
|
|
399
|
+
for (const memory of allCandidates) {
|
|
400
|
+
if (memory.frontmatter.id === args.newMemoryId) continue;
|
|
401
|
+
const dedupeKey = memory.frontmatter.id ?? memory.path;
|
|
402
|
+
if (processedIds.has(dedupeKey)) continue;
|
|
403
|
+
const snapshotStatus = memory.frontmatter.status ?? "active";
|
|
404
|
+
if (snapshotStatus !== "active") {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
const decision = shouldSupersedeExisting({
|
|
408
|
+
candidate: memory.frontmatter,
|
|
409
|
+
newEntityRef: args.entityRef,
|
|
410
|
+
newAttributes: args.structuredAttributes,
|
|
411
|
+
newCreatedAt: persistedCreatedAt,
|
|
412
|
+
newMemoryId: args.newMemoryId
|
|
413
|
+
});
|
|
414
|
+
if (!decision) {
|
|
415
|
+
processedIds.add(dedupeKey);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
let preparedPropagation = null;
|
|
419
|
+
let primaryPath = null;
|
|
420
|
+
let primaryBefore = null;
|
|
421
|
+
let primaryPatch = null;
|
|
422
|
+
try {
|
|
423
|
+
const fresh = await args.storage.readMemoryByPath(memory.path);
|
|
424
|
+
if (!fresh) {
|
|
425
|
+
log.debug(
|
|
426
|
+
`[engram] temporal supersession skipped candidate ${memory.frontmatter.id}: no longer readable at ${memory.path} \u2014 leaving id available for alternate tier`
|
|
427
|
+
);
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
processedIds.add(dedupeKey);
|
|
431
|
+
const freshStatus = fresh.frontmatter.status ?? "active";
|
|
432
|
+
if (freshStatus !== "active" || fresh.frontmatter.supersededBy) {
|
|
433
|
+
log.debug(
|
|
434
|
+
`[engram] temporal supersession skipped candidate ${memory.frontmatter.id}: already superseded by concurrent writer`
|
|
435
|
+
);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
primaryPath = fresh.path;
|
|
439
|
+
primaryBefore = {
|
|
440
|
+
content: fresh.content,
|
|
441
|
+
frontmatter: { ...fresh.frontmatter }
|
|
442
|
+
};
|
|
443
|
+
const oldCreatedMs = new Date(fresh.frontmatter.created).getTime();
|
|
444
|
+
const newCreatedMs = new Date(persistedCreatedAt).getTime();
|
|
445
|
+
const argCreatedMs = new Date(args.createdAt).getTime();
|
|
446
|
+
const maxMs = Math.max(
|
|
447
|
+
Number.isFinite(oldCreatedMs) ? oldCreatedMs : 0,
|
|
448
|
+
Number.isFinite(newCreatedMs) ? newCreatedMs : 0,
|
|
449
|
+
Number.isFinite(argCreatedMs) ? argCreatedMs : 0
|
|
450
|
+
);
|
|
451
|
+
const supersededAt = new Date(maxMs).toISOString();
|
|
452
|
+
let invalidAtPatch;
|
|
453
|
+
if (!fresh.frontmatter.invalid_at) {
|
|
454
|
+
if (args.useCallerTimestamp) {
|
|
455
|
+
invalidAtPatch = persistedCreatedAt;
|
|
456
|
+
} else {
|
|
457
|
+
const newValidAt = replacementMemory?.frontmatter.valid_at?.trim();
|
|
458
|
+
invalidAtPatch = newValidAt && newValidAt.length > 0 ? newValidAt : persistedCreatedAt;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
const mutation = {
|
|
462
|
+
supersededAt,
|
|
463
|
+
...invalidAtPatch ? { invalidAt: invalidAtPatch } : {},
|
|
464
|
+
matchedKeys: decision.matchedKeys
|
|
465
|
+
};
|
|
466
|
+
primaryPatch = temporalMutationPatch(args.newMemoryId, mutation);
|
|
467
|
+
const propagationEvent = args.dependencyPropagationDelivery && args.namespaceScope ? {
|
|
468
|
+
oldMemory: {
|
|
469
|
+
content: fresh.content,
|
|
470
|
+
frontmatter: {
|
|
471
|
+
...fresh.frontmatter,
|
|
472
|
+
...fresh.frontmatter.links ? { links: fresh.frontmatter.links.map((link) => ({ ...link })) } : {}
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
replacementId: args.newMemoryId,
|
|
476
|
+
replacementContent: replacementMemory?.content ?? null,
|
|
477
|
+
cause: "temporal_supersession",
|
|
478
|
+
namespaceScope: args.namespaceScope,
|
|
479
|
+
temporalMutation: mutation
|
|
480
|
+
} : null;
|
|
481
|
+
if (propagationEvent && args.dependencyPropagationDelivery) {
|
|
482
|
+
preparedPropagation = {
|
|
483
|
+
delivery: args.dependencyPropagationDelivery,
|
|
484
|
+
event: propagationEvent,
|
|
485
|
+
token: null
|
|
486
|
+
};
|
|
487
|
+
try {
|
|
488
|
+
preparedPropagation.token = await args.dependencyPropagationDelivery.prepare(propagationEvent);
|
|
489
|
+
} catch (prepareErr) {
|
|
490
|
+
log.warn(
|
|
491
|
+
`temporal-supersession: dependency propagation preparation failed for ${fresh.frontmatter.id}: ${prepareErr}`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
const wrote = await applyTemporalSupersessionPrimaryMutation({
|
|
496
|
+
storage: args.storage,
|
|
497
|
+
oldMemory: fresh,
|
|
498
|
+
replacementId: args.newMemoryId,
|
|
499
|
+
mutation,
|
|
500
|
+
allCandidates
|
|
501
|
+
});
|
|
502
|
+
if (!wrote) {
|
|
503
|
+
const commitState = await classifyTemporalPrimaryMutation({
|
|
504
|
+
storage: args.storage,
|
|
505
|
+
path: fresh.path,
|
|
506
|
+
before: primaryBefore,
|
|
507
|
+
patch: primaryPatch
|
|
508
|
+
});
|
|
509
|
+
if (preparedPropagation) {
|
|
510
|
+
await settleTemporalPropagationAfterPrimaryFailure(
|
|
511
|
+
preparedPropagation,
|
|
512
|
+
commitState,
|
|
513
|
+
fresh.frontmatter.id
|
|
514
|
+
);
|
|
515
|
+
if (commitState !== "not-committed") {
|
|
516
|
+
log.warn(
|
|
517
|
+
`temporal-supersession: retaining dependency propagation recovery for ${fresh.frontmatter.id} after ${commitState} primary mutation`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
preparedPropagation = null;
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
if (preparedPropagation) {
|
|
525
|
+
const completedPropagation = preparedPropagation;
|
|
526
|
+
preparedPropagation = null;
|
|
527
|
+
try {
|
|
528
|
+
await completedPropagation.delivery.afterMutation(
|
|
529
|
+
completedPropagation.token,
|
|
530
|
+
completedPropagation.event
|
|
531
|
+
);
|
|
532
|
+
} catch (afterMutationErr) {
|
|
533
|
+
log.warn(
|
|
534
|
+
`temporal-supersession: dependency propagation delivery failed for ${memory.frontmatter.id}: ${afterMutationErr}`
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
supersededIds.push(memory.frontmatter.id);
|
|
539
|
+
for (const key of decision.matchedKeys) matchedKeys.add(key);
|
|
540
|
+
} catch (err) {
|
|
541
|
+
let commitState = "unknown";
|
|
542
|
+
if (primaryPath && primaryBefore && primaryPatch) {
|
|
543
|
+
commitState = await classifyTemporalPrimaryMutation({
|
|
544
|
+
storage: args.storage,
|
|
545
|
+
path: primaryPath,
|
|
546
|
+
before: primaryBefore,
|
|
547
|
+
patch: primaryPatch
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
if (preparedPropagation) {
|
|
551
|
+
await settleTemporalPropagationAfterPrimaryFailure(
|
|
552
|
+
preparedPropagation,
|
|
553
|
+
commitState,
|
|
554
|
+
memory.frontmatter.id
|
|
555
|
+
);
|
|
556
|
+
if (commitState !== "not-committed") {
|
|
557
|
+
log.warn(
|
|
558
|
+
`temporal-supersession: retaining dependency propagation recovery for ${memory.frontmatter.id} after ${commitState} primary mutation`
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
preparedPropagation = null;
|
|
563
|
+
log.warn(
|
|
564
|
+
`temporal-supersession: failed to mark ${memory.frontmatter.id} superseded: ${err}`
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (supersededIds.length > 0) {
|
|
569
|
+
log.debug(
|
|
570
|
+
`temporal-supersession: marked ${supersededIds.length} memories superseded by ${args.newMemoryId} (keys=${Array.from(matchedKeys).join(",")})`
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
return { supersededIds, matchedKeys: Array.from(matchedKeys) };
|
|
574
|
+
}
|
|
575
|
+
function shouldFilterSupersededFromRecall(frontmatter, options) {
|
|
576
|
+
if (!options.enabled) return false;
|
|
577
|
+
if (options.includeInRecall) return false;
|
|
578
|
+
return frontmatter.status === "superseded";
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export {
|
|
582
|
+
normalizeSupersessionKey,
|
|
583
|
+
computeSupersessionKey,
|
|
584
|
+
supersessionKeysForFact,
|
|
585
|
+
lookupAttributeByNormalizedKey,
|
|
586
|
+
shouldSupersedeExisting,
|
|
587
|
+
applyTemporalSupersessionPrimaryMutation,
|
|
588
|
+
applyTemporalSupersession,
|
|
589
|
+
shouldFilterSupersededFromRecall
|
|
590
|
+
};
|
|
591
|
+
//# sourceMappingURL=chunk-5WITETWU.js.map
|