@remnic/core 9.51.1 → 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.
Files changed (234) hide show
  1. package/dist/access-admin-ops-surface.d.ts +6 -5
  2. package/dist/access-admin-ops-surface.js +16 -16
  3. package/dist/access-authorization-probe.d.ts +6 -5
  4. package/dist/access-authorization-probe.js +17 -17
  5. package/dist/access-boundary.d.ts +6 -5
  6. package/dist/access-boundary.js +16 -16
  7. package/dist/access-cli.js +39 -39
  8. package/dist/access-extraction-force-flush.d.ts +6 -5
  9. package/dist/access-extraction-force-flush.js +16 -16
  10. package/dist/access-http-lcm-compaction.d.ts +6 -5
  11. package/dist/access-http-lifecycle-flush.d.ts +6 -5
  12. package/dist/access-http-offline-stream.d.ts +6 -5
  13. package/dist/access-http-query.js +16 -16
  14. package/dist/access-http.d.ts +6 -5
  15. package/dist/access-http.js +22 -22
  16. package/dist/access-identity-continuity-surface.d.ts +5 -4
  17. package/dist/access-identity-continuity-surface.js +16 -16
  18. package/dist/access-lcm-surface.d.ts +6 -5
  19. package/dist/access-lcm-surface.js +16 -16
  20. package/dist/access-mcp.d.ts +6 -5
  21. package/dist/access-mcp.js +20 -20
  22. package/dist/access-namespace-preflight.js +16 -16
  23. package/dist/access-observe-write-surface.d.ts +6 -5
  24. package/dist/access-observe-write-surface.js +16 -16
  25. package/dist/access-offline-manifest.d.ts +5 -4
  26. package/dist/access-operations-batch.js +17 -17
  27. package/dist/access-operations.d.ts +9 -8
  28. package/dist/access-operations.js +19 -19
  29. package/dist/access-recall-concurrency.d.ts +6 -5
  30. package/dist/access-recall-concurrency.js +16 -16
  31. package/dist/access-recall-response.d.ts +6 -5
  32. package/dist/access-recall-response.js +16 -16
  33. package/dist/access-recall-surface.d.ts +6 -5
  34. package/dist/access-recall-surface.js +16 -16
  35. package/dist/access-schema.d.ts +88 -88
  36. package/dist/{access-service-BY0KJ44c.d.ts → access-service-Cbk3bNbD.d.ts} +3 -3
  37. package/dist/access-service-helpers.d.ts +6 -5
  38. package/dist/access-service.d.ts +6 -5
  39. package/dist/access-service.js +16 -16
  40. package/dist/access-surface-catalog.d.ts +6 -5
  41. package/dist/access-wearables-meetings-surface.d.ts +2 -2
  42. package/dist/bootstrap.d.ts +5 -4
  43. package/dist/briefing.d.ts +1 -1
  44. package/dist/briefing.js +7 -7
  45. package/dist/buffer.d.ts +1 -1
  46. package/dist/{capsule-merge-XMFBXVDP.js → capsule-merge-HCJJMLPS.js} +4 -4
  47. package/dist/causal-consolidation.js +8 -8
  48. package/dist/{chunk-PWN32TAG.js → chunk-2ASAS3CQ.js} +2 -2
  49. package/dist/{chunk-WQM326GS.js → chunk-2LY6GIIE.js} +2 -2
  50. package/dist/{chunk-JL43BVDE.js → chunk-2OIQDTDC.js} +2 -2
  51. package/dist/{chunk-33SV3E43.js → chunk-3OY7KXHM.js} +3 -3
  52. package/dist/{chunk-AIUBBHSF.js → chunk-5UZ6UCOZ.js} +3 -3
  53. package/dist/chunk-5WITETWU.js +591 -0
  54. package/dist/chunk-5WITETWU.js.map +1 -0
  55. package/dist/{chunk-UT5BV5OG.js → chunk-7HXZJAID.js} +2 -2
  56. package/dist/{chunk-M7BXDKPR.js → chunk-7M6NYQWB.js} +3 -3
  57. package/dist/{chunk-TPTECFWR.js → chunk-B6LZ4IBH.js} +3 -3
  58. package/dist/{chunk-J5LLX6IL.js → chunk-BF6SXNQJ.js} +10 -10
  59. package/dist/{chunk-4PC4PRJE.js → chunk-BKIFTXHR.js} +2 -2
  60. package/dist/{chunk-VVG2BOKA.js → chunk-BMEYMKWX.js} +2 -2
  61. package/dist/{chunk-DCZBSE4F.js → chunk-D5YOZ66N.js} +18 -18
  62. package/dist/{chunk-BHXYAVUM.js → chunk-DLG5V6ND.js} +2 -2
  63. package/dist/{chunk-52UKFTUK.js → chunk-F4EU6VUC.js} +2 -2
  64. package/dist/{chunk-M4A44LUA.js → chunk-GSTIBXBW.js} +2 -2
  65. package/dist/{chunk-W5XVQFLM.js → chunk-GXFSQ6SD.js} +2 -2
  66. package/dist/{chunk-XADV5IZ3.js → chunk-HDIUYMSB.js} +5 -5
  67. package/dist/{chunk-FXTYIA46.js → chunk-J272WKX2.js} +2 -2
  68. package/dist/{chunk-ENTCVTQR.js → chunk-JJRVPWFY.js} +11 -1
  69. package/dist/chunk-JJRVPWFY.js.map +1 -0
  70. package/dist/{chunk-JYL3BVVZ.js → chunk-JSEJH2YQ.js} +2 -2
  71. package/dist/{chunk-5UDMFE3Q.js → chunk-MLXZD4WM.js} +2 -2
  72. package/dist/{chunk-PUSLMZBQ.js → chunk-NOEMGE56.js} +2 -2
  73. package/dist/{chunk-C5QLI33R.js → chunk-QINJITDS.js} +2 -2
  74. package/dist/{chunk-45BRYON6.js → chunk-QPOHMO6M.js} +2 -2
  75. package/dist/{chunk-ZQOCRIGA.js → chunk-QYN5PXDZ.js} +3 -3
  76. package/dist/{chunk-PA45XCUD.js → chunk-RANKJI5T.js} +2 -2
  77. package/dist/{chunk-ZHY5TMJG.js → chunk-RMHMUUBW.js} +2392 -628
  78. package/dist/chunk-RMHMUUBW.js.map +1 -0
  79. package/dist/{chunk-37ZO6LLJ.js → chunk-RYLEDKQ2.js} +2 -2
  80. package/dist/{chunk-CV6BBVYV.js → chunk-TEMSWHQD.js} +2 -2
  81. package/dist/{chunk-QGR6OVGT.js → chunk-VFSAWRMZ.js} +2 -2
  82. package/dist/{chunk-NLK2VZYZ.js → chunk-VXCNQYTC.js} +2 -2
  83. package/dist/{chunk-AZ2QBGYB.js → chunk-W7Y5JDVB.js} +1 -1
  84. package/dist/{chunk-VBHPOWBJ.js → chunk-WD5B5AIE.js} +1051 -591
  85. package/dist/chunk-WD5B5AIE.js.map +1 -0
  86. package/dist/{chunk-OYESWJ43.js → chunk-WLRD2TXF.js} +15 -10
  87. package/dist/chunk-WLRD2TXF.js.map +1 -0
  88. package/dist/{chunk-4F6X3RXW.js → chunk-X57M2Q4I.js} +2 -2
  89. package/dist/{chunk-6MTSFX7A.js → chunk-X7XEDOSL.js} +8 -8
  90. package/dist/{chunk-UEVLYVNW.js → chunk-YXKVLYXU.js} +2 -2
  91. package/dist/{chunk-OQAL6SIR.js → chunk-ZMSZVISA.js} +2 -2
  92. package/dist/{cli-CnOkH9hA.d.ts → cli-DMAFI0qt.d.ts} +3 -3
  93. package/dist/cli.d.ts +7 -6
  94. package/dist/cli.js +33 -33
  95. package/dist/compounding/engine.d.ts +1 -1
  96. package/dist/compounding/engine.js +7 -7
  97. package/dist/connectors/codex-materialize-runner.js +7 -7
  98. package/dist/connectors/index.js +7 -7
  99. package/dist/consolidation-provenance-check.d.ts +1 -1
  100. package/dist/consolidation-provenance-check.js +4 -4
  101. package/dist/consolidation-undo.d.ts +1 -1
  102. package/dist/consolidation-undo.js +3 -3
  103. package/dist/contradiction/index.d.ts +1 -1
  104. package/dist/convergence-refresh.d.ts +1 -1
  105. package/dist/convergence-refresh.js +9 -9
  106. package/dist/corpus-watermark.js +9 -9
  107. package/dist/dependency-propagation-delivery-D63r24pH.d.ts +41 -0
  108. package/dist/entity-retrieval.d.ts +1 -1
  109. package/dist/entity-retrieval.js +7 -7
  110. package/dist/explicit-capture.d.ts +5 -4
  111. package/dist/explicit-capture.js +4 -4
  112. package/dist/external-wiki-access.d.ts +6 -5
  113. package/dist/external-wiki-access.js +17 -17
  114. package/dist/external-wiki-mcp-tools.d.ts +6 -5
  115. package/dist/extraction.js +7 -7
  116. package/dist/{forget-UJDJHG6R.js → forget-HDS4N6CG.js} +3 -3
  117. package/dist/harmonic-retrieval.js +1 -1
  118. package/dist/index.d.ts +687 -686
  119. package/dist/index.js +39 -39
  120. package/dist/maintenance/memory-governance.js +7 -7
  121. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
  122. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +7 -7
  123. package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
  124. package/dist/maintenance/rebuild-memory-projection.js +8 -8
  125. package/dist/{maintenance-CKwxpdRx.d.ts → maintenance-kBII2qUI.d.ts} +3 -2
  126. package/dist/mcp-memory-inspector-app.d.ts +6 -5
  127. package/dist/memory-worth-outcomes.d.ts +1 -1
  128. package/dist/namespaces/migrate.d.ts +1 -1
  129. package/dist/namespaces/migrate.js +8 -8
  130. package/dist/namespaces/storage.d.ts +1 -1
  131. package/dist/namespaces/storage.js +7 -7
  132. package/dist/operator-doctor-corpus.js +10 -10
  133. package/dist/operator-toolkit.d.ts +1 -1
  134. package/dist/operator-toolkit.js +15 -15
  135. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  136. package/dist/orchestration/maintenance.d.ts +2 -2
  137. package/dist/orchestration/maintenance.js +12 -12
  138. package/dist/{orchestrator-BshGam-o.d.ts → orchestrator-DHy5LtTy.d.ts} +20 -35
  139. package/dist/orchestrator.d.ts +5 -4
  140. package/dist/orchestrator.js +39 -39
  141. package/dist/page-versioning.js +3 -3
  142. package/dist/schemas.d.ts +138 -138
  143. package/dist/semantic-consolidation.js +8 -8
  144. package/dist/semantic-rule-promotion.js +7 -7
  145. package/dist/semantic-rule-verifier.js +7 -7
  146. package/dist/{service-BIgVM7fL.d.ts → service-PT2_z7xm.d.ts} +1 -1
  147. package/dist/shared-context/manager.d.ts +8 -8
  148. package/dist/source-agent-qualifier.js +7 -7
  149. package/dist/{storage-CVfGWqCI.d.ts → storage-BmVudhk4.d.ts} +46 -27
  150. package/dist/storage.d.ts +1 -1
  151. package/dist/storage.js +6 -6
  152. package/dist/temporal-supersession.d.ts +51 -26
  153. package/dist/temporal-supersession.js +3 -1
  154. package/dist/tier-migration.d.ts +1 -1
  155. package/dist/transfer/capsule-import.js +4 -4
  156. package/dist/transfer/types.d.ts +66 -66
  157. package/dist/verified-recall.js +7 -7
  158. package/package.json +2 -2
  159. package/src/lifecycle/tombstones.ts +30 -0
  160. package/src/orchestration/consolidation-run.ts +324 -106
  161. package/src/orchestration/contradiction-linking-coordinator.ts +237 -64
  162. package/src/orchestration/dependency-propagation-delivery.test.ts +2353 -0
  163. package/src/orchestration/dependency-propagation-delivery.ts +1143 -0
  164. package/src/orchestration/dependency-propagation-queue-state.ts +220 -0
  165. package/src/orchestration/dependency-propagation-recovery-replay.ts +237 -0
  166. package/src/orchestration/dependency-propagation-replay-reconciliation.ts +73 -0
  167. package/src/orchestration/dependency-propagation-triggers.test.ts +1069 -11
  168. package/src/orchestration/dependency-propagation.test.ts +82 -31
  169. package/src/orchestration/dependency-propagation.ts +55 -17
  170. package/src/orchestration/extraction-persist-deps.ts +2 -2
  171. package/src/orchestration/extraction-persist.ts +14 -15
  172. package/src/orchestration/extraction-queue-coordinator.ts +23 -1
  173. package/src/orchestration/extraction-shutdown.ts +29 -0
  174. package/src/orchestration/maintenance.ts +13 -7
  175. package/src/orchestration/turn-ingestion.ts +5 -1
  176. package/src/orchestrator-background-writes.test.ts +265 -1
  177. package/src/orchestrator-extraction-queue.test.ts +39 -0
  178. package/src/orchestrator.ts +59 -58
  179. package/src/storage/committed-invalidation.ts +34 -0
  180. package/src/storage/deletion-revision-store.ts +529 -0
  181. package/src/storage/supersession-audit.ts +41 -0
  182. package/src/storage/supersession-side-effects.ts +52 -25
  183. package/src/storage-contract/failure-semantics.test.ts +12 -0
  184. package/src/storage-contract/round-trip.test.ts +184 -2
  185. package/src/storage-deletion-revisions.test.ts +213 -1
  186. package/src/storage-frontmatter-cas.test.ts +141 -0
  187. package/src/storage-memory-lifecycle-ledger.test.ts +372 -0
  188. package/src/storage-replay.test.ts +149 -0
  189. package/src/storage.ts +345 -358
  190. package/src/temporal-supersession.test.ts +431 -2
  191. package/src/temporal-supersession.ts +567 -107
  192. package/src/testing/subjects/dependency-propagation.test.ts +179 -38
  193. package/dist/chunk-ENTCVTQR.js.map +0 -1
  194. package/dist/chunk-EWMTOVMY.js +0 -484
  195. package/dist/chunk-EWMTOVMY.js.map +0 -1
  196. package/dist/chunk-OYESWJ43.js.map +0 -1
  197. package/dist/chunk-VBHPOWBJ.js.map +0 -1
  198. package/dist/chunk-ZHY5TMJG.js.map +0 -1
  199. /package/dist/{capsule-merge-XMFBXVDP.js.map → capsule-merge-HCJJMLPS.js.map} +0 -0
  200. /package/dist/{chunk-PWN32TAG.js.map → chunk-2ASAS3CQ.js.map} +0 -0
  201. /package/dist/{chunk-WQM326GS.js.map → chunk-2LY6GIIE.js.map} +0 -0
  202. /package/dist/{chunk-JL43BVDE.js.map → chunk-2OIQDTDC.js.map} +0 -0
  203. /package/dist/{chunk-33SV3E43.js.map → chunk-3OY7KXHM.js.map} +0 -0
  204. /package/dist/{chunk-AIUBBHSF.js.map → chunk-5UZ6UCOZ.js.map} +0 -0
  205. /package/dist/{chunk-UT5BV5OG.js.map → chunk-7HXZJAID.js.map} +0 -0
  206. /package/dist/{chunk-M7BXDKPR.js.map → chunk-7M6NYQWB.js.map} +0 -0
  207. /package/dist/{chunk-TPTECFWR.js.map → chunk-B6LZ4IBH.js.map} +0 -0
  208. /package/dist/{chunk-J5LLX6IL.js.map → chunk-BF6SXNQJ.js.map} +0 -0
  209. /package/dist/{chunk-4PC4PRJE.js.map → chunk-BKIFTXHR.js.map} +0 -0
  210. /package/dist/{chunk-VVG2BOKA.js.map → chunk-BMEYMKWX.js.map} +0 -0
  211. /package/dist/{chunk-DCZBSE4F.js.map → chunk-D5YOZ66N.js.map} +0 -0
  212. /package/dist/{chunk-BHXYAVUM.js.map → chunk-DLG5V6ND.js.map} +0 -0
  213. /package/dist/{chunk-52UKFTUK.js.map → chunk-F4EU6VUC.js.map} +0 -0
  214. /package/dist/{chunk-M4A44LUA.js.map → chunk-GSTIBXBW.js.map} +0 -0
  215. /package/dist/{chunk-W5XVQFLM.js.map → chunk-GXFSQ6SD.js.map} +0 -0
  216. /package/dist/{chunk-XADV5IZ3.js.map → chunk-HDIUYMSB.js.map} +0 -0
  217. /package/dist/{chunk-FXTYIA46.js.map → chunk-J272WKX2.js.map} +0 -0
  218. /package/dist/{chunk-JYL3BVVZ.js.map → chunk-JSEJH2YQ.js.map} +0 -0
  219. /package/dist/{chunk-5UDMFE3Q.js.map → chunk-MLXZD4WM.js.map} +0 -0
  220. /package/dist/{chunk-PUSLMZBQ.js.map → chunk-NOEMGE56.js.map} +0 -0
  221. /package/dist/{chunk-C5QLI33R.js.map → chunk-QINJITDS.js.map} +0 -0
  222. /package/dist/{chunk-45BRYON6.js.map → chunk-QPOHMO6M.js.map} +0 -0
  223. /package/dist/{chunk-ZQOCRIGA.js.map → chunk-QYN5PXDZ.js.map} +0 -0
  224. /package/dist/{chunk-PA45XCUD.js.map → chunk-RANKJI5T.js.map} +0 -0
  225. /package/dist/{chunk-37ZO6LLJ.js.map → chunk-RYLEDKQ2.js.map} +0 -0
  226. /package/dist/{chunk-CV6BBVYV.js.map → chunk-TEMSWHQD.js.map} +0 -0
  227. /package/dist/{chunk-QGR6OVGT.js.map → chunk-VFSAWRMZ.js.map} +0 -0
  228. /package/dist/{chunk-NLK2VZYZ.js.map → chunk-VXCNQYTC.js.map} +0 -0
  229. /package/dist/{chunk-AZ2QBGYB.js.map → chunk-W7Y5JDVB.js.map} +0 -0
  230. /package/dist/{chunk-4F6X3RXW.js.map → chunk-X57M2Q4I.js.map} +0 -0
  231. /package/dist/{chunk-6MTSFX7A.js.map → chunk-X7XEDOSL.js.map} +0 -0
  232. /package/dist/{chunk-UEVLYVNW.js.map → chunk-YXKVLYXU.js.map} +0 -0
  233. /package/dist/{chunk-OQAL6SIR.js.map → chunk-ZMSZVISA.js.map} +0 -0
  234. /package/dist/{forget-UJDJHG6R.js.map → forget-HDS4N6CG.js.map} +0 -0
@@ -34,7 +34,15 @@ import {
34
34
  localizeUpdateCandidates,
35
35
  mergeMemorySnapshots,
36
36
  } from "./update-localization.js";
37
- import { propagateInvalidation } from "./dependency-propagation.js";
37
+ import {
38
+ isDependencyPropagationEnabled,
39
+ propagateInvalidation,
40
+ type PropagationEvent,
41
+ } from "./dependency-propagation.js";
42
+ import type {
43
+ DependencyPropagationDeliveryPort,
44
+ DependencyPropagationPreparationToken,
45
+ } from "./dependency-propagation-delivery.js";
38
46
 
39
47
  /** Result type of {@link ContradictionLinkingCoordinator.checkForContradiction}. */
40
48
  export interface ContradictionResult {
@@ -93,6 +101,8 @@ export class ContradictionLinkingCoordinator {
93
101
  namespace: string,
94
102
  ) => Promise<StorageManager>;
95
103
  private readonly getExtraction: () => ExtractionEngine;
104
+ private readonly storageDirNamespace: (storageDir: string) => string;
105
+ private readonly getDependencyPropagationDelivery: () => DependencyPropagationDeliveryPort;
96
106
 
97
107
  constructor(options: {
98
108
  getConfig: () => PluginConfig;
@@ -107,6 +117,8 @@ export class ContradictionLinkingCoordinator {
107
117
  namespaceFromPath: (p: string) => string;
108
118
  storageForNamespace: (namespace: string) => Promise<StorageManager>;
109
119
  getExtraction: () => ExtractionEngine;
120
+ storageDirNamespace?: (storageDir: string) => string;
121
+ getDependencyPropagationDelivery?: () => DependencyPropagationDeliveryPort;
110
122
  }) {
111
123
  this.getConfig = options.getConfig;
112
124
  this.isSearchAvailable = options.isSearchAvailable;
@@ -115,6 +127,12 @@ export class ContradictionLinkingCoordinator {
115
127
  this.namespaceFromPath = options.namespaceFromPath;
116
128
  this.storageForNamespace = options.storageForNamespace;
117
129
  this.getExtraction = options.getExtraction;
130
+ this.storageDirNamespace = options.storageDirNamespace ?? (() => "default");
131
+ this.getDependencyPropagationDelivery =
132
+ options.getDependencyPropagationDelivery ??
133
+ (() => {
134
+ throw new Error("dependency propagation delivery is unavailable");
135
+ });
118
136
  }
119
137
 
120
138
  /**
@@ -346,35 +364,188 @@ export class ContradictionLinkingCoordinator {
346
364
  return postWriteGuard ? "blocked" : "not_attempted";
347
365
  }
348
366
 
349
- // Capture links before the primary supersession. The propagation hook is
350
- // orchestration-owned, so its own supersessions cannot recurse.
351
- let oldMemory: MemoryFile | null = null;
352
- if (coerceBool(config.dependencyPropagation?.enabled) === true) {
367
+ // Capture propagation inputs before the primary supersession. The
368
+ // propagation hook is orchestration-owned, so its own supersessions cannot
369
+ // recurse.
370
+ let oldMemory: PropagationEvent["oldMemory"] | null = null;
371
+ let replacementContent: string | null = null;
372
+ let propagationEvent: PropagationEvent | null = null;
373
+ try {
374
+ const [hot, cold] = await Promise.all([
375
+ typeof storage.readAllMemories === "function"
376
+ ? storage.readAllMemories()
377
+ : Promise.resolve([]),
378
+ typeof storage.readAllColdMemories === "function"
379
+ ? storage.readAllColdMemories()
380
+ : Promise.resolve([]),
381
+ ]);
382
+ const memories = mergeMemorySnapshots(hot, cold, storage.dir);
383
+ const captured = memories.find(
384
+ (memory) =>
385
+ memory.frontmatter.id === contradiction.supersededId &&
386
+ inferLocalizationMemoryStatus(memory, storage.dir) === "active",
387
+ );
388
+ if (captured) {
389
+ oldMemory = {
390
+ content: captured.content,
391
+ frontmatter: {
392
+ ...captured.frontmatter,
393
+ ...(captured.frontmatter.tags
394
+ ? { tags: [...captured.frontmatter.tags] }
395
+ : {}),
396
+ ...(captured.frontmatter.links
397
+ ? { links: captured.frontmatter.links.map((link) => ({ ...link })) }
398
+ : {}),
399
+ },
400
+ path: captured.path,
401
+ };
402
+ }
403
+ replacementContent =
404
+ memories.find((memory) => memory.frontmatter.id === newMemoryId)?.content ??
405
+ (await storage.getMemoryById(newMemoryId))?.content ??
406
+ null;
407
+ } catch (err) {
408
+ log.warn(
409
+ `contradiction propagation snapshot failed for ${contradiction.supersededId}: ${err}`,
410
+ );
411
+ }
412
+
413
+ if (oldMemory && replacementContent !== null) {
353
414
  try {
354
- const [hot, cold] = await Promise.all([
355
- typeof storage.readAllMemories === "function"
356
- ? storage.readAllMemories()
357
- : storage.getMemoryById(contradiction.supersededId).then((memory) =>
358
- memory ? [memory] : [],
359
- ),
360
- typeof storage.readAllColdMemories === "function"
361
- ? storage.readAllColdMemories()
362
- : Promise.resolve([]),
363
- ]);
364
- oldMemory = mergeMemorySnapshots(hot, cold, storage.dir).find(
365
- (memory) => memory.frontmatter.id === contradiction.supersededId,
366
- ) ?? null;
415
+ propagationEvent = {
416
+ oldMemory,
417
+ replacementId: newMemoryId,
418
+ replacementContent,
419
+ cause: "contradiction",
420
+ namespaceScope: this.storageDirNamespace(storage.dir),
421
+ };
422
+ } catch (err) {
423
+ log.warn(
424
+ `contradiction dependency propagation event failed for ${contradiction.supersededId}: ${err}`,
425
+ );
426
+ }
427
+ } else if (oldMemory) {
428
+ log.warn(
429
+ `contradiction dependency propagation skipped for ${contradiction.supersededId}: replacement content was not captured`,
430
+ );
431
+ }
432
+ const propagationEnabled = isDependencyPropagationEnabled(config);
433
+ let delivery: DependencyPropagationDeliveryPort | null = null;
434
+ if (propagationEvent && propagationEnabled) {
435
+ try {
436
+ delivery = this.getDependencyPropagationDelivery();
437
+ } catch (err) {
438
+ log.warn(
439
+ `contradiction dependency propagation delivery unavailable for ${contradiction.supersededId}: ${err}`,
440
+ );
441
+ }
442
+ }
443
+ let preparation: DependencyPropagationPreparationToken | null = null;
444
+ if (delivery && propagationEvent) {
445
+ try {
446
+ preparation = await delivery.prepare(propagationEvent);
367
447
  } catch (err) {
368
- log.warn(`contradiction propagation snapshot failed for ${contradiction.supersededId}: ${err}`);
448
+ log.warn(
449
+ `contradiction dependency propagation prepare failed for ${contradiction.supersededId}: ${err}`,
450
+ );
369
451
  }
370
452
  }
453
+ const supersessionCommitted = async (): Promise<boolean | null> => {
454
+ try {
455
+ const current = await storage.getMemoryById(contradiction.supersededId);
456
+ if (!current) return null;
457
+ return (
458
+ current.frontmatter.status === "superseded" &&
459
+ current.frontmatter.supersededBy === newMemoryId
460
+ );
461
+ } catch (err) {
462
+ log.warn(
463
+ `contradiction supersession state read failed for ${contradiction.supersededId}: ${err}`,
464
+ );
465
+ return null;
466
+ }
467
+ };
468
+
469
+ const settleFailedPropagation = async (commitState: boolean | null): Promise<void> => {
470
+ let token = preparation;
471
+ if (commitState === false) {
472
+ if (token !== null) {
473
+ try {
474
+ await delivery?.cancel(token);
475
+ } catch (err) {
476
+ log.warn(
477
+ `contradiction dependency propagation cancel failed for ${contradiction.supersededId}: ${err}`,
478
+ );
479
+ }
480
+ }
481
+ return;
482
+ }
483
+ if (commitState === null && token === null && delivery && propagationEvent) {
484
+ try {
485
+ token = await delivery.prepare(propagationEvent);
486
+ } catch (err) {
487
+ log.warn(
488
+ `contradiction dependency propagation recovery prepare failed for ${contradiction.supersededId}: ${err}`,
489
+ );
490
+ }
491
+ }
492
+ if (token !== null) {
493
+ try {
494
+ await delivery?.deferPrepared(token);
495
+ } catch (err) {
496
+ log.warn(
497
+ `contradiction dependency propagation defer failed for ${contradiction.supersededId}: ${err}`,
498
+ );
499
+ }
500
+ return;
501
+ }
502
+ if (commitState === true && delivery && propagationEvent) {
503
+ try {
504
+ await delivery.afterMutation(null, propagationEvent);
505
+ } catch (err) {
506
+ log.warn(
507
+ `contradiction dependency propagation fallback failed for ${contradiction.supersededId}: ${err}`,
508
+ );
509
+ }
510
+ }
511
+ };
512
+ const readyPreparedPropagation = async (): Promise<void> => {
513
+ if (!propagationEvent || !propagationEnabled) return;
514
+ if (!delivery) {
515
+ await propagateInvalidation(
516
+ { storage, extraction: this.getExtraction(), config },
517
+ propagationEvent,
518
+ );
519
+ return;
520
+ }
521
+ let token = preparation;
522
+ if (token === null) {
523
+ try {
524
+ token = await delivery.prepare(propagationEvent);
525
+ } catch (err) {
526
+ log.warn(
527
+ `contradiction dependency propagation recovery prepare failed for ${contradiction.supersededId}: ${err}`,
528
+ );
529
+ }
530
+ }
531
+ try {
532
+ await delivery.afterMutation(token, propagationEvent);
533
+ } catch (err) {
534
+ log.warn(
535
+ `contradiction dependency propagation failed for ${contradiction.supersededId}: ${err}`,
536
+ );
537
+ }
538
+ };
539
+
540
+ let commitState: boolean | null = false;
371
541
  try {
372
- const superseded = await storage.supersedeMemory(
542
+ const committed = await storage.supersedeMemory(
373
543
  contradiction.supersededId,
374
544
  newMemoryId,
375
545
  contradiction.reason,
376
546
  );
377
- if (!superseded) {
547
+ commitState = committed ? true : await supersessionCommitted();
548
+ if (!committed || commitState !== true) {
378
549
  let mergedSnapshot: MemoryFile[];
379
550
  try {
380
551
  const [hot, cold] = await Promise.all([
@@ -395,80 +566,82 @@ export class ContradictionLinkingCoordinator {
395
566
  log.warn(
396
567
  `contradiction auto-resolve race check failed for ${contradiction.supersededId}: ${err}`,
397
568
  );
569
+ await settleFailedPropagation(commitState);
398
570
  return "supersede_failed";
399
571
  }
400
572
  const target = mergedSnapshot.find(
401
573
  (memory) => memory.frontmatter.id === contradiction.supersededId,
402
574
  );
403
- if (!target) return "supersede_failed";
575
+ if (!target) {
576
+ await settleFailedPropagation(commitState);
577
+ return "supersede_failed";
578
+ }
404
579
  const losingMemory = mergedSnapshot.find(
405
580
  (memory) =>
406
581
  memory.frontmatter.id === newMemoryId &&
407
582
  inferLocalizationMemoryStatus(memory, storage.dir) === "active",
408
583
  );
409
- if (!losingMemory) return "supersede_failed";
584
+ if (!losingMemory) {
585
+ await settleFailedPropagation(commitState);
586
+ return "supersede_failed";
587
+ }
410
588
  try {
411
589
  if (losingMemory.frontmatter.supersedes === contradiction.supersededId) {
412
590
  const cleared = await storage.writeMemoryFrontmatter(losingMemory, {
413
591
  supersedes: undefined,
414
592
  });
415
- if (cleared === false) return "supersedes_clear_failed";
593
+ if (cleared === false) {
594
+ await settleFailedPropagation(commitState);
595
+ return "supersedes_clear_failed";
596
+ }
416
597
  }
417
598
  } catch (err) {
418
599
  log.warn(
419
600
  `contradiction auto-resolve losing supersedes clear failed for ${newMemoryId}: ${err}`,
420
601
  );
602
+ await settleFailedPropagation(commitState);
421
603
  return "supersedes_clear_failed";
422
604
  }
423
- return inferLocalizationMemoryStatus(target, storage.dir) === "active"
605
+ const outcome = inferLocalizationMemoryStatus(target, storage.dir) === "active"
424
606
  ? "supersede_failed"
425
607
  : "lost_race";
426
- }
427
- if (oldMemory) {
428
- try {
429
- await propagateInvalidation(
430
- {
431
- storage,
432
- extraction: this.getExtraction(),
433
- config,
434
- },
435
- {
436
- oldMemory,
437
- replacementId: newMemoryId,
438
- replacementContent: (await storage.getMemoryById(newMemoryId))?.content ?? null,
439
- cause: "contradiction",
440
- namespaceScope: this.namespaceFromPath(storage.dir),
441
- },
442
- );
443
- } catch (err) {
444
- log.warn(`contradiction dependency propagation failed for ${contradiction.supersededId}: ${err}`);
608
+ if (commitState === true) {
609
+ await readyPreparedPropagation();
610
+ } else {
611
+ await settleFailedPropagation(commitState);
445
612
  }
613
+ return outcome;
446
614
  }
447
-
448
- if (
449
- resolveIndexingCapabilities(config).queryAwareIndexing &&
450
- contradiction.supersededPath
451
- ) {
452
- try {
453
- await deindexMemoryAsync(
454
- config.memoryDir,
455
- contradiction.supersededPath,
456
- contradiction.supersededCreated,
457
- contradiction.supersededTags,
458
- );
459
- } catch (err) {
460
- log.warn(
461
- `contradiction auto-resolve deindex failed for ${contradiction.supersededId}: ${err}`,
462
- );
463
- }
464
- }
465
- return "resolved";
466
615
  } catch (err) {
616
+ commitState = await supersessionCommitted();
467
617
  log.warn(
468
618
  `contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`,
469
619
  );
470
- return "supersede_failed";
620
+ if (commitState !== true) {
621
+ await settleFailedPropagation(commitState);
622
+ return "supersede_failed";
623
+ }
624
+ }
625
+ await readyPreparedPropagation();
626
+
627
+ if (
628
+ resolveIndexingCapabilities(config).queryAwareIndexing &&
629
+ contradiction.supersededPath
630
+ ) {
631
+ try {
632
+ await deindexMemoryAsync(
633
+ config.memoryDir,
634
+ contradiction.supersededPath,
635
+ contradiction.supersededCreated,
636
+ contradiction.supersededTags,
637
+ );
638
+ } catch (err) {
639
+ log.warn(
640
+ `contradiction auto-resolve deindex failed for ${contradiction.supersededId}: ${err}`,
641
+ );
642
+ }
471
643
  }
644
+ return "resolved";
472
645
  }
473
646
 
474
647
  // ---------------------------------------------------------------------------