@remnic/core 9.45.0 → 9.45.2

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 (387) hide show
  1. package/dist/access-admin-ops-surface.d.ts +10 -10
  2. package/dist/access-admin-ops-surface.js +25 -25
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +10 -10
  5. package/dist/access-authorization-probe.js +26 -26
  6. package/dist/access-boundary.d.ts +10 -10
  7. package/dist/access-boundary.js +25 -25
  8. package/dist/access-cli.js +69 -68
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +10 -10
  11. package/dist/access-extraction-force-flush.js +25 -25
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +10 -10
  14. package/dist/access-http-lifecycle-flush.d.ts +10 -10
  15. package/dist/access-http-query.js +25 -25
  16. package/dist/access-http.d.ts +10 -10
  17. package/dist/access-http.js +34 -34
  18. package/dist/access-identity-continuity-surface.d.ts +8 -8
  19. package/dist/access-identity-continuity-surface.js +25 -25
  20. package/dist/access-lcm-surface.d.ts +10 -10
  21. package/dist/access-lcm-surface.js +25 -25
  22. package/dist/access-mcp.d.ts +10 -10
  23. package/dist/access-mcp.js +30 -30
  24. package/dist/access-memory-search-fanout.d.ts +2 -2
  25. package/dist/{access-namespace-preflight-47dOyty9.d.ts → access-namespace-preflight-5yZ4g6F8.d.ts} +1 -1
  26. package/dist/access-namespace-preflight.d.ts +3 -3
  27. package/dist/access-namespace-preflight.js +25 -25
  28. package/dist/access-observe-write-surface.d.ts +10 -10
  29. package/dist/access-observe-write-surface.js +25 -25
  30. package/dist/access-operations-batch.js +27 -27
  31. package/dist/access-operations.d.ts +10 -10
  32. package/dist/access-operations.js +29 -29
  33. package/dist/access-recall-concurrency.d.ts +10 -10
  34. package/dist/access-recall-concurrency.js +25 -25
  35. package/dist/access-recall-response.d.ts +10 -10
  36. package/dist/access-recall-response.js +25 -25
  37. package/dist/access-recall-surface.d.ts +10 -10
  38. package/dist/access-recall-surface.js +25 -25
  39. package/dist/access-schema.js +3 -3
  40. package/dist/{access-service-DBo88Dmm.d.ts → access-service-CiJRsgAB.d.ts} +7 -7
  41. package/dist/access-service-helpers.d.ts +10 -10
  42. package/dist/access-service.d.ts +10 -10
  43. package/dist/access-service.js +25 -25
  44. package/dist/access-surface-catalog.d.ts +10 -10
  45. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  46. package/dist/action-confidence.d.ts +1 -1
  47. package/dist/active-memory-bridge.d.ts +1 -1
  48. package/dist/active-recall.d.ts +1 -1
  49. package/dist/active-recall.js +3 -2
  50. package/dist/active-recall.js.map +1 -1
  51. package/dist/adapters/index.js +4 -4
  52. package/dist/adapters/registry.js +2 -2
  53. package/dist/behavior-learner.d.ts +1 -1
  54. package/dist/behavior-signals.d.ts +1 -1
  55. package/dist/bootstrap.d.ts +8 -8
  56. package/dist/briefing.d.ts +2 -2
  57. package/dist/briefing.js +8 -8
  58. package/dist/buffer-surprise-report.d.ts +1 -1
  59. package/dist/buffer-turn-helpers.d.ts +1 -1
  60. package/dist/buffer.d.ts +2 -2
  61. package/dist/bulk-import/index.d.ts +3 -3
  62. package/dist/calibration.d.ts +1 -1
  63. package/dist/capabilities.d.ts +1 -1
  64. package/dist/{catalog-DPQynQZG.d.ts → catalog-scBmy0sO.d.ts} +1 -1
  65. package/dist/causal-behavior.d.ts +1 -1
  66. package/dist/causal-behavior.js +2 -2
  67. package/dist/causal-chain.js +2 -2
  68. package/dist/causal-consolidation.d.ts +1 -1
  69. package/dist/causal-consolidation.js +11 -11
  70. package/dist/causal-retrieval.js +2 -2
  71. package/dist/causal-trajectory-graph.d.ts +1 -1
  72. package/dist/causal-trajectory-graph.js +2 -2
  73. package/dist/causal-trajectory.js +1 -1
  74. package/dist/{chunk-GBJJUPNV.js → chunk-33PLLLL7.js} +2 -2
  75. package/dist/{chunk-ZAB5PG65.js → chunk-3F2LKUMU.js} +2 -2
  76. package/dist/{chunk-TXBU7YDV.js → chunk-3TBLDMJA.js} +2 -2
  77. package/dist/{chunk-6UWB5PTR.js → chunk-4L6HUREQ.js} +54 -24
  78. package/dist/chunk-4L6HUREQ.js.map +1 -0
  79. package/dist/{chunk-FLBPATMZ.js → chunk-4UH4BTGK.js} +33 -33
  80. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  81. package/dist/{chunk-K6OTW3TP.js → chunk-A5OJCXZL.js} +2 -2
  82. package/dist/{chunk-QQ3NDJOM.js → chunk-AAIUERNB.js} +2 -2
  83. package/dist/{chunk-C7EI7CA6.js → chunk-BJKPPZ6Z.js} +2 -2
  84. package/dist/{chunk-65V4K4MT.js → chunk-CJ2ZR7UA.js} +17 -17
  85. package/dist/{chunk-TM72UOX2.js → chunk-CUM2BBPN.js} +5 -1
  86. package/dist/chunk-CUM2BBPN.js.map +1 -0
  87. package/dist/{chunk-GQBZ7EVF.js → chunk-D3J5SLQK.js} +2 -2
  88. package/dist/{chunk-3HLCRYBV.js → chunk-DL7ZD3JH.js} +3 -3
  89. package/dist/{chunk-ZPJJE7MF.js → chunk-DNWXFTLD.js} +2 -2
  90. package/dist/{chunk-YQQK7W7T.js → chunk-E53DSZEN.js} +2 -2
  91. package/dist/{chunk-6OLQJJYE.js → chunk-E5UK4VPE.js} +2 -2
  92. package/dist/{chunk-3HKQOFOV.js → chunk-E6PNLPGJ.js} +19 -19
  93. package/dist/{chunk-Z54EM5YZ.js → chunk-GF22HWS2.js} +4 -4
  94. package/dist/chunk-HBVPYRDW.js +39 -0
  95. package/dist/chunk-HBVPYRDW.js.map +1 -0
  96. package/dist/{chunk-W6ROK2KU.js → chunk-HNZKVLAN.js} +2 -2
  97. package/dist/{chunk-GDC4INBF.js → chunk-HO3QBJEY.js} +2 -2
  98. package/dist/{chunk-U5G66ORD.js → chunk-HREE4JHI.js} +48 -48
  99. package/dist/{chunk-GSL47NPM.js → chunk-J7VGGECD.js} +1 -1
  100. package/dist/chunk-J7VGGECD.js.map +1 -0
  101. package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
  102. package/dist/{chunk-7PVFOFPJ.js → chunk-JE7EK33X.js} +2 -2
  103. package/dist/{chunk-WG2PI44B.js → chunk-JVLCVFQ4.js} +2 -2
  104. package/dist/{chunk-UZGJFIIG.js → chunk-JYIFGGEM.js} +2 -2
  105. package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
  106. package/dist/{chunk-3SHB4YAW.js → chunk-L2DPF4DF.js} +4 -4
  107. package/dist/{chunk-VRYJSKOM.js → chunk-LZ4LDKHZ.js} +2 -2
  108. package/dist/{chunk-PO5LSKQO.js → chunk-MU7ZHSZE.js} +2 -2
  109. package/dist/{chunk-CAGPP5NB.js → chunk-NRV4Y3PM.js} +1 -1
  110. package/dist/{chunk-SS7YWVPF.js → chunk-OAEQLRCY.js} +2 -2
  111. package/dist/{chunk-FVGQ5LIS.js → chunk-OQ5PRDDS.js} +2 -2
  112. package/dist/{chunk-5YGO5VEH.js → chunk-P4DRWEYC.js} +2 -2
  113. package/dist/{chunk-XMZV27S5.js → chunk-PDLBLTOK.js} +2 -2
  114. package/dist/{chunk-VCGPO2VD.js → chunk-PKNLM44P.js} +4 -4
  115. package/dist/{chunk-XFQRFWVS.js → chunk-QN25OCUF.js} +2 -2
  116. package/dist/{chunk-J4OKD6QX.js → chunk-RN7DY3FC.js} +5 -5
  117. package/dist/{chunk-7JO6RVBI.js → chunk-S2NCTZGJ.js} +4 -4
  118. package/dist/{chunk-R4Q7CQGZ.js → chunk-TDHTVMPG.js} +2 -2
  119. package/dist/{chunk-FXGLFGIG.js → chunk-TIHMZFIV.js} +3 -3
  120. package/dist/{chunk-ZS5UZU5M.js → chunk-U7GW7NE7.js} +7 -7
  121. package/dist/{chunk-WC4SPYHX.js → chunk-UVIKWC7M.js} +10 -10
  122. package/dist/{chunk-2QR2RRH6.js → chunk-UYLMNVY6.js} +4 -4
  123. package/dist/{chunk-G24XIK6H.js → chunk-VUPTKTDV.js} +2 -2
  124. package/dist/{chunk-GOPWZYZH.js → chunk-VWAXN2BN.js} +8 -8
  125. package/dist/{chunk-JZ7SSAQ5.js → chunk-XYTOI63Z.js} +3 -3
  126. package/dist/{cli-DQ4VhjqX.d.ts → cli-BUGN3d6_.d.ts} +5 -5
  127. package/dist/cli.d.ts +12 -12
  128. package/dist/cli.js +52 -51
  129. package/dist/compounding/engine.d.ts +2 -2
  130. package/dist/compounding/engine.js +8 -8
  131. package/dist/compounding/preference-consolidator.d.ts +1 -1
  132. package/dist/compression-optimizer.d.ts +1 -1
  133. package/dist/config.d.ts +1 -1
  134. package/dist/config.js +3 -2
  135. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  136. package/dist/connectors/codex-materialize-runner.js +8 -8
  137. package/dist/connectors/codex-materialize.d.ts +1 -1
  138. package/dist/connectors/index.d.ts +1 -1
  139. package/dist/connectors/index.js +8 -8
  140. package/dist/consolidation-provenance-check.d.ts +2 -2
  141. package/dist/consolidation-undo.d.ts +2 -2
  142. package/dist/contradiction/index.d.ts +2 -2
  143. package/dist/converge-config.d.ts +11 -0
  144. package/dist/converge-config.js +12 -0
  145. package/dist/convergence-refresh.d.ts +2 -2
  146. package/dist/convergence-refresh.js +10 -10
  147. package/dist/conversation-index/backend.d.ts +1 -1
  148. package/dist/conversation-index/chunker.d.ts +1 -1
  149. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  150. package/dist/conversation-index/indexer.d.ts +1 -1
  151. package/dist/conversation-index/search.d.ts +1 -1
  152. package/dist/corpus-watermark.d.ts +1 -1
  153. package/dist/corpus-watermark.js +10 -10
  154. package/dist/day-summary.d.ts +1 -1
  155. package/dist/delinearize.d.ts +1 -1
  156. package/dist/direct-answer-wiring.d.ts +1 -1
  157. package/dist/direct-answer.d.ts +1 -1
  158. package/dist/embedding-fallback.d.ts +1 -1
  159. package/dist/enrichment/index.d.ts +1 -1
  160. package/dist/entity-retrieval.d.ts +2 -2
  161. package/dist/entity-retrieval.js +8 -8
  162. package/dist/entity-schema.d.ts +1 -1
  163. package/dist/explicit-capture.d.ts +8 -8
  164. package/dist/extraction-error-classification.d.ts +1 -1
  165. package/dist/extraction-faithfulness.d.ts +1 -1
  166. package/dist/extraction-judge-telemetry.d.ts +1 -1
  167. package/dist/extraction-judge-training.d.ts +1 -1
  168. package/dist/extraction-judge.d.ts +1 -1
  169. package/dist/extraction-liveness.d.ts +1 -1
  170. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  171. package/dist/extraction-source-grounding.d.ts +1 -1
  172. package/dist/extraction.d.ts +1 -1
  173. package/dist/extraction.js +10 -10
  174. package/dist/fallback-llm.d.ts +1 -1
  175. package/dist/graph-dashboard-diff.d.ts +1 -1
  176. package/dist/graph-dashboard-key.d.ts +1 -1
  177. package/dist/graph-dashboard-parser.d.ts +1 -1
  178. package/dist/{graph-edge-decay-GF3ZSGSP.js → graph-edge-decay-Z6ENALU2.js} +4 -4
  179. package/dist/graph-edge-decay-Z6ENALU2.js.map +1 -0
  180. package/dist/graph-edge-reinforcement.d.ts +1 -1
  181. package/dist/graph-snapshot.d.ts +1 -1
  182. package/dist/graph-snapshot.js +3 -3
  183. package/dist/graph.d.ts +1 -1
  184. package/dist/graph.js +2 -2
  185. package/dist/importance.d.ts +1 -1
  186. package/dist/importers/index.d.ts +1 -1
  187. package/dist/in-flight-reads.d.ts +1 -1
  188. package/dist/index.d.ts +20 -19
  189. package/dist/index.js +77 -71
  190. package/dist/intent.d.ts +1 -1
  191. package/dist/lcm/engine.d.ts +1 -1
  192. package/dist/lcm/engine.js +2 -2
  193. package/dist/lcm/index.d.ts +1 -1
  194. package/dist/lcm/index.js +4 -4
  195. package/dist/lcm/tools.d.ts +1 -1
  196. package/dist/lifecycle.d.ts +1 -1
  197. package/dist/live-connectors-runner.d.ts +1 -1
  198. package/dist/local-llm.d.ts +1 -1
  199. package/dist/local-model-endpoint.d.ts +1 -1
  200. package/dist/maintenance/memory-governance.d.ts +1 -1
  201. package/dist/maintenance/memory-governance.js +8 -8
  202. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  203. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -8
  204. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  205. package/dist/maintenance/rebuild-memory-projection.js +9 -9
  206. package/dist/{maintenance-_RV38GlE.d.ts → maintenance-LbuS2rUA.d.ts} +3 -3
  207. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  208. package/dist/memory-action-policy.d.ts +1 -1
  209. package/dist/memory-cache.d.ts +1 -1
  210. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  211. package/dist/memory-projection-store.d.ts +1 -1
  212. package/dist/memory-provenance.d.ts +1 -1
  213. package/dist/memory-worth-outcomes.d.ts +2 -2
  214. package/dist/models-json.d.ts +1 -1
  215. package/dist/namespaces/migrate.d.ts +3 -3
  216. package/dist/namespaces/migrate.js +9 -9
  217. package/dist/namespaces/principal.d.ts +1 -1
  218. package/dist/namespaces/search.d.ts +1 -1
  219. package/dist/namespaces/storage.d.ts +3 -3
  220. package/dist/namespaces/storage.js +8 -8
  221. package/dist/native-knowledge.d.ts +1 -1
  222. package/dist/offline-sync-impression-drain.d.ts +1 -1
  223. package/dist/operator-doctor-corpus.d.ts +1 -1
  224. package/dist/operator-doctor-corpus.js +11 -11
  225. package/dist/operator-doctor-replica.d.ts +1 -1
  226. package/dist/operator-toolkit.d.ts +3 -3
  227. package/dist/operator-toolkit.js +19 -18
  228. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  229. package/dist/orchestration/maintenance.d.ts +4 -4
  230. package/dist/orchestration/maintenance.js +13 -13
  231. package/dist/{orchestrator-B2ecFpRO.d.ts → orchestrator-rHiWt32X.d.ts} +7 -7
  232. package/dist/orchestrator.d.ts +8 -8
  233. package/dist/orchestrator.js +69 -68
  234. package/dist/patterns-cli.d.ts +1 -1
  235. package/dist/{pipeline-Cs76XC-p.d.ts → pipeline-W_97O8BV.d.ts} +1 -1
  236. package/dist/policy-runtime.d.ts +1 -1
  237. package/dist/proactive-contention.d.ts +1 -1
  238. package/dist/provenance.d.ts +1 -1
  239. package/dist/{qmd-WJwvBgiF.d.ts → qmd-LWtMofAf.d.ts} +1 -1
  240. package/dist/qmd-preflight.d.ts +2 -2
  241. package/dist/qmd-recall-cache.d.ts +1 -1
  242. package/dist/qmd.d.ts +2 -2
  243. package/dist/recall-concurrency-config.d.ts +1 -1
  244. package/dist/recall-disclosure-escalation.d.ts +1 -1
  245. package/dist/recall-explain-renderer.d.ts +1 -1
  246. package/dist/recall-explain-renderer.js +3 -3
  247. package/dist/recall-memory-map.d.ts +1 -1
  248. package/dist/recall-planner-llm.d.ts +1 -1
  249. package/dist/recall-state.d.ts +1 -1
  250. package/dist/recall-tag-filter.d.ts +1 -1
  251. package/dist/recall-timings.d.ts +1 -1
  252. package/dist/recall-xray-cli.d.ts +1 -1
  253. package/dist/recall-xray-cli.js +4 -4
  254. package/dist/recall-xray-renderer.d.ts +1 -1
  255. package/dist/recall-xray-renderer.js +3 -3
  256. package/dist/recall-xray.d.ts +1 -1
  257. package/dist/recall-xray.js +2 -2
  258. package/dist/reconcile/cursor.d.ts +11 -1
  259. package/dist/reconcile/cursor.js +54 -0
  260. package/dist/reconcile/cursor.js.map +1 -1
  261. package/dist/reconcile/manifest.d.ts +3 -3
  262. package/dist/reconcile/manifest.js +42 -4
  263. package/dist/reconcile/manifest.js.map +1 -1
  264. package/dist/reconcile/plan.d.ts +32 -21
  265. package/dist/reconcile/plan.js +2 -1
  266. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  267. package/dist/replay/normalizers/claude.d.ts +1 -1
  268. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  269. package/dist/replay/normalizers/shared.d.ts +1 -1
  270. package/dist/replay/runner.d.ts +1 -1
  271. package/dist/replay/types.d.ts +1 -1
  272. package/dist/replica-divergence.d.ts +1 -1
  273. package/dist/replica-peers-config.d.ts +1 -1
  274. package/dist/resolve-auth-token.d.ts +1 -1
  275. package/dist/resume-bundles.js +4 -3
  276. package/dist/retrieval-agents.d.ts +2 -2
  277. package/dist/retrieval-tiers.d.ts +1 -1
  278. package/dist/routing/engine.d.ts +1 -1
  279. package/dist/routing/store.d.ts +1 -1
  280. package/dist/salvage-envelope.d.ts +1 -1
  281. package/dist/{scope-profiles-CQ0NAleS.d.ts → scope-profiles-BiQKOE-p.d.ts} +1 -1
  282. package/dist/search/embed-helper.d.ts +1 -1
  283. package/dist/search/factory.d.ts +1 -1
  284. package/dist/search/index.d.ts +1 -1
  285. package/dist/search/lancedb-backend.d.ts +1 -1
  286. package/dist/search/meilisearch-backend.d.ts +1 -1
  287. package/dist/search/noop-backend.d.ts +1 -1
  288. package/dist/search/orama-backend.d.ts +1 -1
  289. package/dist/search/port.d.ts +1 -1
  290. package/dist/search/remote-backend.d.ts +1 -1
  291. package/dist/{semantic-consolidation-BWxOBMtz.d.ts → semantic-consolidation-dHYCyqgh.d.ts} +1 -1
  292. package/dist/semantic-consolidation.d.ts +2 -2
  293. package/dist/semantic-consolidation.js +9 -9
  294. package/dist/semantic-rule-promotion.js +8 -8
  295. package/dist/semantic-rule-verifier.d.ts +1 -1
  296. package/dist/semantic-rule-verifier.js +8 -8
  297. package/dist/{service-DW06sY3P.d.ts → service-DJG3KCQ4.d.ts} +2 -2
  298. package/dist/session-observer-bands.d.ts +1 -1
  299. package/dist/session-observer-state.d.ts +1 -1
  300. package/dist/shared-context/manager.d.ts +1 -1
  301. package/dist/signal.d.ts +1 -1
  302. package/dist/source-agent-qualifier.d.ts +1 -1
  303. package/dist/source-agent-qualifier.js +8 -8
  304. package/dist/{storage-qRIQPA6F.d.ts → storage-F9FVh-w9.d.ts} +1 -1
  305. package/dist/storage.d.ts +2 -2
  306. package/dist/storage.js +7 -7
  307. package/dist/summarizer.d.ts +1 -1
  308. package/dist/summary-snapshot.d.ts +1 -1
  309. package/dist/temporal-supersession.d.ts +2 -2
  310. package/dist/temporal-timeline-recall.d.ts +1 -1
  311. package/dist/temporal-validity.d.ts +1 -1
  312. package/dist/threading.d.ts +1 -1
  313. package/dist/tier-migration.d.ts +2 -2
  314. package/dist/tier-routing.d.ts +1 -1
  315. package/dist/topics.d.ts +1 -1
  316. package/dist/transcript.d.ts +1 -1
  317. package/dist/transfer/autodetect.js +1 -1
  318. package/dist/transfer/backup.js +1 -1
  319. package/dist/transfer/capsule-export.js +2 -2
  320. package/dist/trust-score-stage.d.ts +1 -1
  321. package/dist/trust-score.d.ts +1 -1
  322. package/dist/{types-CqWwMPr_.d.ts → types-rEwubvim.d.ts} +6 -1
  323. package/dist/types.d.ts +1 -1
  324. package/dist/types.js +1 -1
  325. package/dist/utility-runtime.d.ts +1 -1
  326. package/dist/verified-recall.js +8 -8
  327. package/dist/write-envelope.d.ts +1 -1
  328. package/package.json +2 -2
  329. package/src/config.test.ts +24 -0
  330. package/src/config.ts +3 -0
  331. package/src/converge-config.ts +39 -0
  332. package/src/index.ts +1 -2
  333. package/src/reconcile/cursor.test.ts +30 -0
  334. package/src/reconcile/cursor.ts +63 -0
  335. package/src/reconcile/manifest.test.ts +93 -2
  336. package/src/reconcile/manifest.ts +56 -3
  337. package/src/reconcile/plan.test.ts +40 -52
  338. package/src/reconcile/plan.ts +95 -61
  339. package/src/types.ts +5 -0
  340. package/dist/chunk-6UWB5PTR.js.map +0 -1
  341. package/dist/chunk-GSL47NPM.js.map +0 -1
  342. package/dist/chunk-TM72UOX2.js.map +0 -1
  343. /package/dist/{chunk-GBJJUPNV.js.map → chunk-33PLLLL7.js.map} +0 -0
  344. /package/dist/{chunk-ZAB5PG65.js.map → chunk-3F2LKUMU.js.map} +0 -0
  345. /package/dist/{chunk-TXBU7YDV.js.map → chunk-3TBLDMJA.js.map} +0 -0
  346. /package/dist/{chunk-FLBPATMZ.js.map → chunk-4UH4BTGK.js.map} +0 -0
  347. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  348. /package/dist/{chunk-K6OTW3TP.js.map → chunk-A5OJCXZL.js.map} +0 -0
  349. /package/dist/{chunk-QQ3NDJOM.js.map → chunk-AAIUERNB.js.map} +0 -0
  350. /package/dist/{chunk-C7EI7CA6.js.map → chunk-BJKPPZ6Z.js.map} +0 -0
  351. /package/dist/{chunk-65V4K4MT.js.map → chunk-CJ2ZR7UA.js.map} +0 -0
  352. /package/dist/{chunk-GQBZ7EVF.js.map → chunk-D3J5SLQK.js.map} +0 -0
  353. /package/dist/{chunk-3HLCRYBV.js.map → chunk-DL7ZD3JH.js.map} +0 -0
  354. /package/dist/{chunk-ZPJJE7MF.js.map → chunk-DNWXFTLD.js.map} +0 -0
  355. /package/dist/{chunk-YQQK7W7T.js.map → chunk-E53DSZEN.js.map} +0 -0
  356. /package/dist/{chunk-6OLQJJYE.js.map → chunk-E5UK4VPE.js.map} +0 -0
  357. /package/dist/{chunk-3HKQOFOV.js.map → chunk-E6PNLPGJ.js.map} +0 -0
  358. /package/dist/{chunk-Z54EM5YZ.js.map → chunk-GF22HWS2.js.map} +0 -0
  359. /package/dist/{chunk-W6ROK2KU.js.map → chunk-HNZKVLAN.js.map} +0 -0
  360. /package/dist/{chunk-GDC4INBF.js.map → chunk-HO3QBJEY.js.map} +0 -0
  361. /package/dist/{chunk-U5G66ORD.js.map → chunk-HREE4JHI.js.map} +0 -0
  362. /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
  363. /package/dist/{chunk-7PVFOFPJ.js.map → chunk-JE7EK33X.js.map} +0 -0
  364. /package/dist/{chunk-WG2PI44B.js.map → chunk-JVLCVFQ4.js.map} +0 -0
  365. /package/dist/{chunk-UZGJFIIG.js.map → chunk-JYIFGGEM.js.map} +0 -0
  366. /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
  367. /package/dist/{chunk-3SHB4YAW.js.map → chunk-L2DPF4DF.js.map} +0 -0
  368. /package/dist/{chunk-VRYJSKOM.js.map → chunk-LZ4LDKHZ.js.map} +0 -0
  369. /package/dist/{chunk-PO5LSKQO.js.map → chunk-MU7ZHSZE.js.map} +0 -0
  370. /package/dist/{chunk-CAGPP5NB.js.map → chunk-NRV4Y3PM.js.map} +0 -0
  371. /package/dist/{chunk-SS7YWVPF.js.map → chunk-OAEQLRCY.js.map} +0 -0
  372. /package/dist/{chunk-FVGQ5LIS.js.map → chunk-OQ5PRDDS.js.map} +0 -0
  373. /package/dist/{chunk-5YGO5VEH.js.map → chunk-P4DRWEYC.js.map} +0 -0
  374. /package/dist/{chunk-XMZV27S5.js.map → chunk-PDLBLTOK.js.map} +0 -0
  375. /package/dist/{chunk-VCGPO2VD.js.map → chunk-PKNLM44P.js.map} +0 -0
  376. /package/dist/{chunk-XFQRFWVS.js.map → chunk-QN25OCUF.js.map} +0 -0
  377. /package/dist/{chunk-J4OKD6QX.js.map → chunk-RN7DY3FC.js.map} +0 -0
  378. /package/dist/{chunk-7JO6RVBI.js.map → chunk-S2NCTZGJ.js.map} +0 -0
  379. /package/dist/{chunk-R4Q7CQGZ.js.map → chunk-TDHTVMPG.js.map} +0 -0
  380. /package/dist/{chunk-FXGLFGIG.js.map → chunk-TIHMZFIV.js.map} +0 -0
  381. /package/dist/{chunk-ZS5UZU5M.js.map → chunk-U7GW7NE7.js.map} +0 -0
  382. /package/dist/{chunk-WC4SPYHX.js.map → chunk-UVIKWC7M.js.map} +0 -0
  383. /package/dist/{chunk-2QR2RRH6.js.map → chunk-UYLMNVY6.js.map} +0 -0
  384. /package/dist/{chunk-G24XIK6H.js.map → chunk-VUPTKTDV.js.map} +0 -0
  385. /package/dist/{chunk-GOPWZYZH.js.map → chunk-VWAXN2BN.js.map} +0 -0
  386. /package/dist/{chunk-JZ7SSAQ5.js.map → chunk-XYTOI63Z.js.map} +0 -0
  387. /package/dist/{graph-edge-decay-GF3ZSGSP.js.map → converge-config.js.map} +0 -0
@@ -20,6 +20,48 @@ function defaultConvergeCursorPath(memoryDir, peerUrl, namespace) {
20
20
  const key = hashPeerNamespace(peerUrl, namespace);
21
21
  return path.join(path.resolve(memoryDir), ".remnic", "state", "converge-cursors", `${key}.json`);
22
22
  }
23
+ function normalizeSemanticFileState(input) {
24
+ if (!input || typeof input !== "object" || Array.isArray(input)) return void 0;
25
+ const file = input;
26
+ if (typeof file.path !== "string" || typeof file.sha256 !== "string") return void 0;
27
+ return { path: file.path, sha256: file.sha256 };
28
+ }
29
+ function digestAfterReconcile(entry) {
30
+ if (entry.action === "push") return entry.localSha256;
31
+ if (entry.action === "pull") return entry.peerSha256;
32
+ if (entry.action === "conflict") {
33
+ if (entry.resolution === "local-wins") return entry.localSha256;
34
+ if (entry.resolution === "peer-wins") return entry.peerSha256;
35
+ return void 0;
36
+ }
37
+ if (entry.action !== "identical") return void 0;
38
+ if (entry.localSha256 && entry.peerSha256 && entry.localSha256 !== entry.peerSha256) return void 0;
39
+ return entry.localSha256 ?? entry.peerSha256;
40
+ }
41
+ function semanticAgreementKey(agreement) {
42
+ return `${agreement.local.path}\0${agreement.peer.path}`;
43
+ }
44
+ function deriveConvergeCursorBase(entries, namespace, priorSemanticAgreements = []) {
45
+ const baseFiles = [];
46
+ const semanticAgreementsByPathPair = new Map(
47
+ priorSemanticAgreements.map((agreement) => [semanticAgreementKey(agreement), agreement])
48
+ );
49
+ for (const entry of entries) {
50
+ if (entry.namespace !== namespace) continue;
51
+ if (entry.semanticAgreement) {
52
+ semanticAgreementsByPathPair.set(semanticAgreementKey(entry.semanticAgreement), entry.semanticAgreement);
53
+ continue;
54
+ }
55
+ const sha256 = digestAfterReconcile(entry);
56
+ if (sha256) baseFiles.push({ path: entry.path, sha256 });
57
+ }
58
+ baseFiles.sort((left, right) => left.path.localeCompare(right.path));
59
+ const semanticAgreements = [...semanticAgreementsByPathPair.values()];
60
+ semanticAgreements.sort(
61
+ (left, right) => left.local.path.localeCompare(right.local.path) || left.peer.path.localeCompare(right.peer.path)
62
+ );
63
+ return { baseFiles, semanticAgreements };
64
+ }
23
65
  function normalizeConvergeCursor(input) {
24
66
  if (!input || typeof input !== "object" || Array.isArray(input)) {
25
67
  throw new Error("converge cursor must be an object");
@@ -50,6 +92,16 @@ function normalizeConvergeCursor(input) {
50
92
  }
51
93
  }
52
94
  }
95
+ const semanticAgreements = [];
96
+ if (Array.isArray(obj.semanticAgreements)) {
97
+ for (const item of obj.semanticAgreements) {
98
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
99
+ const agreement = item;
100
+ const local = normalizeSemanticFileState(agreement.local);
101
+ const peer = normalizeSemanticFileState(agreement.peer);
102
+ if (local && peer) semanticAgreements.push({ local, peer });
103
+ }
104
+ }
53
105
  const completedPaths = [];
54
106
  if (Array.isArray(obj.completedPaths)) {
55
107
  for (const item of obj.completedPaths) {
@@ -64,6 +116,7 @@ function normalizeConvergeCursor(input) {
64
116
  namespace: obj.namespace.trim(),
65
117
  lastConvergedAt: typeof obj.lastConvergedAt === "string" ? obj.lastConvergedAt : void 0,
66
118
  baseFiles,
119
+ semanticAgreements,
67
120
  completedPaths
68
121
  };
69
122
  }
@@ -96,6 +149,7 @@ async function writeConvergeCursor(cursorPath, cursor) {
96
149
  }
97
150
  export {
98
151
  defaultConvergeCursorPath,
152
+ deriveConvergeCursorBase,
99
153
  hashPeerNamespace,
100
154
  normalizeConvergeCursor,
101
155
  readConvergeCursor,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/reconcile/cursor.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nexport interface ConvergeCursorFileState {\n path: string;\n sha256: string;\n mtimeMs?: number;\n bytes?: number;\n}\n\nexport interface ConvergeCursorState {\n version: 1;\n peerUrl: string;\n namespace: string;\n lastConvergedAt?: string;\n baseFiles: ConvergeCursorFileState[];\n completedPaths?: string[];\n}\n\nexport function hashPeerNamespace(peerUrl: string, namespace: string): string {\n let normalizedUrl: string;\n try {\n const url = new URL(peerUrl);\n const credentials =\n url.username || url.password\n ? `${url.username}${url.password ? `:${url.password}` : \"\"}@`\n : \"\";\n normalizedUrl =\n `${url.protocol.toLowerCase()}//${credentials}${url.hostname.toLowerCase()}` +\n `${url.port ? `:${url.port}` : \"\"}${url.pathname.replace(/\\/+$/, \"\")}${url.search}${url.hash}`;\n } catch {\n normalizedUrl = peerUrl.trim().replace(/\\/+$/, \"\").toLowerCase();\n }\n const normalizedNs = namespace.trim().toLowerCase();\n return createHash(\"sha256\")\n .update(`${normalizedUrl}\\0${normalizedNs}`)\n .digest(\"hex\")\n .slice(0, 16);\n}\n\nexport function defaultConvergeCursorPath(\n memoryDir: string,\n peerUrl: string,\n namespace: string,\n): string {\n const key = hashPeerNamespace(peerUrl, namespace);\n return path.join(path.resolve(memoryDir), \".remnic\", \"state\", \"converge-cursors\", `${key}.json`);\n}\n\nexport function normalizeConvergeCursor(input: unknown): ConvergeCursorState {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new Error(\"converge cursor must be an object\");\n }\n const obj = input as Record<string, unknown>;\n if (obj.version !== 1) {\n throw new Error(\"converge cursor version must be 1\");\n }\n if (typeof obj.peerUrl !== \"string\" || !obj.peerUrl.trim()) {\n throw new Error(\"converge cursor missing peerUrl\");\n }\n if (typeof obj.namespace !== \"string\" || !obj.namespace.trim()) {\n throw new Error(\"converge cursor missing namespace\");\n }\n const baseFiles: ConvergeCursorFileState[] = [];\n if (Array.isArray(obj.baseFiles)) {\n for (const item of obj.baseFiles) {\n if (item && typeof item === \"object\") {\n const fileItem = item as Record<string, unknown>;\n if (typeof fileItem.path === \"string\" && typeof fileItem.sha256 === \"string\") {\n baseFiles.push({\n path: fileItem.path,\n sha256: fileItem.sha256,\n mtimeMs: typeof fileItem.mtimeMs === \"number\" ? fileItem.mtimeMs : undefined,\n bytes: typeof fileItem.bytes === \"number\" ? fileItem.bytes : undefined,\n });\n }\n }\n }\n }\n const completedPaths: string[] = [];\n if (Array.isArray(obj.completedPaths)) {\n for (const item of obj.completedPaths) {\n if (typeof item === \"string\") {\n completedPaths.push(item);\n }\n }\n }\n return {\n version: 1,\n peerUrl: obj.peerUrl.trim(),\n namespace: obj.namespace.trim(),\n lastConvergedAt: typeof obj.lastConvergedAt === \"string\" ? obj.lastConvergedAt : undefined,\n baseFiles,\n completedPaths,\n };\n}\n\nexport async function readConvergeCursor(\n cursorPath: string,\n): Promise<ConvergeCursorState | null> {\n try {\n const raw = await fs.readFile(path.resolve(cursorPath), \"utf-8\");\n const parsed = JSON.parse(raw);\n return normalizeConvergeCursor(parsed);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n return null;\n }\n}\n\nexport async function writeConvergeCursor(\n cursorPath: string,\n cursor: ConvergeCursorState,\n): Promise<void> {\n const normalized = normalizeConvergeCursor(cursor);\n const target = path.resolve(cursorPath);\n await fs.mkdir(path.dirname(target), { recursive: true });\n const tmp = path.join(\n path.dirname(target),\n `.converge-cursor.${process.pid}.${randomUUID()}.tmp`,\n );\n await fs.writeFile(tmp, JSON.stringify(normalized, null, 2) + \"\\n\", \"utf-8\");\n try {\n await fs.rename(tmp, target);\n } catch (error) {\n await fs.unlink(tmp).catch(() => {});\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/reconcile/cursor.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { ReconcilePlanEntry, ReconcileSemanticAgreement } from \"./plan.js\";\n\nexport interface ConvergeCursorFileState {\n path: string;\n sha256: string;\n mtimeMs?: number;\n bytes?: number;\n}\n\nexport interface ConvergeCursorState {\n version: 1;\n peerUrl: string;\n namespace: string;\n lastConvergedAt?: string;\n baseFiles: ConvergeCursorFileState[];\n semanticAgreements?: ReconcileSemanticAgreement[];\n completedPaths?: string[];\n}\n\nexport function hashPeerNamespace(peerUrl: string, namespace: string): string {\n let normalizedUrl: string;\n try {\n const url = new URL(peerUrl);\n const credentials =\n url.username || url.password\n ? `${url.username}${url.password ? `:${url.password}` : \"\"}@`\n : \"\";\n normalizedUrl =\n `${url.protocol.toLowerCase()}//${credentials}${url.hostname.toLowerCase()}` +\n `${url.port ? `:${url.port}` : \"\"}${url.pathname.replace(/\\/+$/, \"\")}${url.search}${url.hash}`;\n } catch {\n normalizedUrl = peerUrl.trim().replace(/\\/+$/, \"\").toLowerCase();\n }\n const normalizedNs = namespace.trim().toLowerCase();\n return createHash(\"sha256\")\n .update(`${normalizedUrl}\\0${normalizedNs}`)\n .digest(\"hex\")\n .slice(0, 16);\n}\n\nexport function defaultConvergeCursorPath(\n memoryDir: string,\n peerUrl: string,\n namespace: string,\n): string {\n const key = hashPeerNamespace(peerUrl, namespace);\n return path.join(path.resolve(memoryDir), \".remnic\", \"state\", \"converge-cursors\", `${key}.json`);\n}\n\nfunction normalizeSemanticFileState(input: unknown): { path: string; sha256: string } | undefined {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return undefined;\n const file = input as Record<string, unknown>;\n if (typeof file.path !== \"string\" || typeof file.sha256 !== \"string\") return undefined;\n return { path: file.path, sha256: file.sha256 };\n}\n\nfunction digestAfterReconcile(entry: ReconcilePlanEntry): string | undefined {\n if (entry.action === \"push\") return entry.localSha256;\n if (entry.action === \"pull\") return entry.peerSha256;\n if (entry.action === \"conflict\") {\n if (entry.resolution === \"local-wins\") return entry.localSha256;\n if (entry.resolution === \"peer-wins\") return entry.peerSha256;\n return undefined;\n }\n if (entry.action !== \"identical\") return undefined;\n if (entry.localSha256 && entry.peerSha256 && entry.localSha256 !== entry.peerSha256) return undefined;\n return entry.localSha256 ?? entry.peerSha256;\n}\n\nfunction semanticAgreementKey(agreement: ReconcileSemanticAgreement): string {\n return `${agreement.local.path}\\0${agreement.peer.path}`;\n}\n\nexport function deriveConvergeCursorBase(\n entries: readonly ReconcilePlanEntry[],\n namespace: string,\n priorSemanticAgreements: readonly ReconcileSemanticAgreement[] = [],\n): Pick<ConvergeCursorState, \"baseFiles\" | \"semanticAgreements\"> {\n const baseFiles: ConvergeCursorFileState[] = [];\n const semanticAgreementsByPathPair = new Map(\n priorSemanticAgreements.map((agreement) => [semanticAgreementKey(agreement), agreement])\n );\n for (const entry of entries) {\n if (entry.namespace !== namespace) continue;\n if (entry.semanticAgreement) {\n semanticAgreementsByPathPair.set(semanticAgreementKey(entry.semanticAgreement), entry.semanticAgreement);\n continue;\n }\n const sha256 = digestAfterReconcile(entry);\n if (sha256) baseFiles.push({ path: entry.path, sha256 });\n }\n baseFiles.sort((left, right) => left.path.localeCompare(right.path));\n const semanticAgreements = [...semanticAgreementsByPathPair.values()];\n semanticAgreements.sort((left, right) =>\n left.local.path.localeCompare(right.local.path) || left.peer.path.localeCompare(right.peer.path)\n );\n return { baseFiles, semanticAgreements };\n}\n\nexport function normalizeConvergeCursor(input: unknown): ConvergeCursorState {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new Error(\"converge cursor must be an object\");\n }\n const obj = input as Record<string, unknown>;\n if (obj.version !== 1) {\n throw new Error(\"converge cursor version must be 1\");\n }\n if (typeof obj.peerUrl !== \"string\" || !obj.peerUrl.trim()) {\n throw new Error(\"converge cursor missing peerUrl\");\n }\n if (typeof obj.namespace !== \"string\" || !obj.namespace.trim()) {\n throw new Error(\"converge cursor missing namespace\");\n }\n const baseFiles: ConvergeCursorFileState[] = [];\n if (Array.isArray(obj.baseFiles)) {\n for (const item of obj.baseFiles) {\n if (item && typeof item === \"object\") {\n const fileItem = item as Record<string, unknown>;\n if (typeof fileItem.path === \"string\" && typeof fileItem.sha256 === \"string\") {\n baseFiles.push({\n path: fileItem.path,\n sha256: fileItem.sha256,\n mtimeMs: typeof fileItem.mtimeMs === \"number\" ? fileItem.mtimeMs : undefined,\n bytes: typeof fileItem.bytes === \"number\" ? fileItem.bytes : undefined,\n });\n }\n }\n }\n }\n const semanticAgreements: ReconcileSemanticAgreement[] = [];\n if (Array.isArray(obj.semanticAgreements)) {\n for (const item of obj.semanticAgreements) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n const agreement = item as Record<string, unknown>;\n const local = normalizeSemanticFileState(agreement.local);\n const peer = normalizeSemanticFileState(agreement.peer);\n if (local && peer) semanticAgreements.push({ local, peer });\n }\n }\n const completedPaths: string[] = [];\n if (Array.isArray(obj.completedPaths)) {\n for (const item of obj.completedPaths) {\n if (typeof item === \"string\") {\n completedPaths.push(item);\n }\n }\n }\n return {\n version: 1,\n peerUrl: obj.peerUrl.trim(),\n namespace: obj.namespace.trim(),\n lastConvergedAt: typeof obj.lastConvergedAt === \"string\" ? obj.lastConvergedAt : undefined,\n baseFiles,\n semanticAgreements,\n completedPaths,\n };\n}\n\nexport async function readConvergeCursor(\n cursorPath: string,\n): Promise<ConvergeCursorState | null> {\n try {\n const raw = await fs.readFile(path.resolve(cursorPath), \"utf-8\");\n const parsed = JSON.parse(raw);\n return normalizeConvergeCursor(parsed);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n return null;\n }\n}\n\nexport async function writeConvergeCursor(\n cursorPath: string,\n cursor: ConvergeCursorState,\n): Promise<void> {\n const normalized = normalizeConvergeCursor(cursor);\n const target = path.resolve(cursorPath);\n await fs.mkdir(path.dirname(target), { recursive: true });\n const tmp = path.join(\n path.dirname(target),\n `.converge-cursor.${process.pid}.${randomUUID()}.tmp`,\n );\n await fs.writeFile(tmp, JSON.stringify(normalized, null, 2) + \"\\n\", \"utf-8\");\n try {\n await fs.rename(tmp, target);\n } catch (error) {\n await fs.unlink(tmp).catch(() => {});\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
- import { x as MemoryStatus } from '../types-CqWwMPr_.js';
2
- import { ReconcileFileState, ReconcilePlan } from './plan.js';
1
+ import { x as MemoryStatus } from '../types-rEwubvim.js';
2
+ import { ReconcileFileState, ReconcilePlan, ReconcileSemanticAgreement } from './plan.js';
3
3
  import '../message-parts/index.js';
4
4
  import '../bounded-jsonl-state.js';
5
5
  import '../operator-doctor-types.js';
@@ -28,6 +28,6 @@ interface BuildReconcileManifestOptions {
28
28
  cachedFiles?: Iterable<ReconcileManifestFile>;
29
29
  }
30
30
  declare function buildReconcileManifest(options: BuildReconcileManifestOptions): Promise<ReconcileManifest>;
31
- declare function collapseActiveFactDuplicates(plan: ReconcilePlan, localManifests: ReadonlyMap<string, ReconcileManifest>, peerManifests: ReadonlyMap<string, ReconcileManifest>): ReconcilePlan;
31
+ declare function collapseActiveFactDuplicates(plan: ReconcilePlan, localManifests: ReadonlyMap<string, ReconcileManifest>, peerManifests: ReadonlyMap<string, ReconcileManifest>, priorSemanticAgreements?: ReadonlyMap<string, readonly ReconcileSemanticAgreement[]>): ReconcilePlan;
32
32
 
33
33
  export { type BuildReconcileManifestOptions, RECONCILE_MANIFEST_FORMAT, RECONCILE_MANIFEST_SCHEMA_VERSION, type ReconcileManifest, type ReconcileManifestFile, type ReconcileMemoryIdentity, buildReconcileManifest, collapseActiveFactDuplicates };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  summarizeReconcilePlan
3
- } from "../chunk-6UWB5PTR.js";
3
+ } from "../chunk-4L6HUREQ.js";
4
+ import "../chunk-HBVPYRDW.js";
4
5
  import "../chunk-EGGE52UU.js";
5
6
  import {
6
7
  inferMemoryStatus
@@ -130,7 +131,19 @@ function comparePlanEntries(left, right) {
130
131
  if (left.namespace !== right.namespace) return left.namespace < right.namespace ? -1 : 1;
131
132
  return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;
132
133
  }
133
- function collapseActiveFactDuplicates(plan, localManifests, peerManifests) {
134
+ function semanticAgreementKey(agreement) {
135
+ return `${agreement.local.path}\0${agreement.peer.path}`;
136
+ }
137
+ function classifySemanticChange(current, prior) {
138
+ if (!prior) return "unchanged";
139
+ const localChanged = current.local.sha256 !== prior.local.sha256;
140
+ const peerChanged = current.peer.sha256 !== prior.peer.sha256;
141
+ if (localChanged && peerChanged) return "both_modified";
142
+ if (localChanged) return "local_changed";
143
+ if (peerChanged) return "peer_changed";
144
+ return "unchanged";
145
+ }
146
+ function collapseActiveFactDuplicates(plan, localManifests, peerManifests, priorSemanticAgreements) {
134
147
  const entriesByNamespace = /* @__PURE__ */ new Map();
135
148
  for (const entry of plan.entries) {
136
149
  const entries2 = entriesByNamespace.get(entry.namespace) ?? [];
@@ -146,6 +159,12 @@ function collapseActiveFactDuplicates(plan, localManifests, peerManifests) {
146
159
  const peerByPath = activeFactByPath(peerManifest);
147
160
  const localFilesByPath = new Map((localManifest?.files ?? []).map((file) => [file.path, file]));
148
161
  const peerFilesByPath = new Map((peerManifest?.files ?? []).map((file) => [file.path, file]));
162
+ const priorSemanticByPathPair = new Map(
163
+ (priorSemanticAgreements?.get(namespace) ?? []).map((agreement) => [
164
+ semanticAgreementKey(agreement),
165
+ agreement
166
+ ])
167
+ );
149
168
  const localByHash = /* @__PURE__ */ new Map();
150
169
  const peerByHash = /* @__PURE__ */ new Map();
151
170
  for (const file of localByPath.values()) {
@@ -183,6 +202,18 @@ function collapseActiveFactDuplicates(plan, localManifests, peerManifests) {
183
202
  ...localCandidates.map((file) => file.path),
184
203
  ...peerCandidates.map((file) => file.path)
185
204
  ]);
205
+ const authoritativeSamePathEntries = new Set(entries2.filter(
206
+ (entry) => duplicatePaths.has(entry.path) && localFilesByPath.has(entry.path) && peerFilesByPath.has(entry.path) && entry.action !== "identical"
207
+ ));
208
+ if (authoritativeSamePathEntries.size > 0) {
209
+ for (const entry of entries2) {
210
+ if (duplicatePaths.has(entry.path) && !authoritativeSamePathEntries.has(entry) && (entry.action === "pull" || entry.action === "push" || entry.action === "identical")) {
211
+ removed.add(entry);
212
+ changed = true;
213
+ }
214
+ }
215
+ continue;
216
+ }
186
217
  const unsafeEntry = entries2.some(
187
218
  (entry) => duplicatePaths.has(entry.path) && (entry.action === "suppress" || entry.action === "conflict")
188
219
  );
@@ -192,13 +223,20 @@ function collapseActiveFactDuplicates(plan, localManifests, peerManifests) {
192
223
  removed.add(entry);
193
224
  }
194
225
  }
226
+ const semanticAgreement = {
227
+ local: { path: localPath, sha256: localFile.sha256 },
228
+ peer: { path: peerPath, sha256: peerFile.sha256 }
229
+ };
195
230
  replacements.push({
196
231
  path: localPath < peerPath ? localPath : peerPath,
197
232
  namespace,
198
233
  action: "identical",
199
234
  reason: "semantic_duplicate",
200
- localSha256: localFile.sha256,
201
- peerSha256: peerFile.sha256
235
+ semanticAgreement,
236
+ semanticChange: classifySemanticChange(
237
+ semanticAgreement,
238
+ priorSemanticByPathPair.get(semanticAgreementKey(semanticAgreement))
239
+ )
202
240
  });
203
241
  changed = true;
204
242
  continue;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/reconcile/manifest.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { inferMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { ContentHashIndex, type ContentHashPathEntry } from \"../storage/content-hash-index.js\";\nimport type { MemoryFrontmatter, MemoryStatus } from \"../types.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport {\n type ReconcileFileState,\n type ReconcilePlan,\n type ReconcilePlanEntry,\n summarizeReconcilePlan,\n} from \"./plan.js\";\n\nexport const RECONCILE_MANIFEST_FORMAT = \"remnic-reconcile-manifest\";\nexport const RECONCILE_MANIFEST_SCHEMA_VERSION = 1;\n\nexport interface ReconcileMemoryIdentity {\n id: string;\n category: string;\n contentHash: string;\n status: MemoryStatus;\n}\n\nexport interface ReconcileManifestFile extends ReconcileFileState {\n memory?: ReconcileMemoryIdentity;\n}\n\ntype ActiveFactManifestFile = ReconcileManifestFile & { memory: ReconcileMemoryIdentity };\n\nexport interface ReconcileManifest {\n format: typeof RECONCILE_MANIFEST_FORMAT;\n schemaVersion: typeof RECONCILE_MANIFEST_SCHEMA_VERSION;\n files: ReconcileManifestFile[];\n}\n\nexport interface BuildReconcileManifestOptions {\n files: Iterable<ReconcileFileState>;\n readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>;\n cachedFiles?: Iterable<ReconcileManifestFile>;\n}\n\nconst SHA256_PATTERN = /^[a-f0-9]{64}$/i;\nconst MEMORY_DIRS = new Set(RECALL_FALLBACK_DIRS);\n\nfunction isMemoryPath(filePath: string): boolean {\n if (!filePath.endsWith(\".md\")) return false;\n const segments = filePath.split(\"/\");\n let index = 0;\n if (segments[index] === \"cold\" || segments[index] === \"archive\") index += 1;\n return MEMORY_DIRS.has(segments[index] ?? \"\");\n}\n\nfunction parseScalar(value: string | undefined): string | undefined {\n if (value === undefined) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n return typeof parsed === \"string\" ? parsed : trimmed;\n } catch {\n return trimmed.slice(1, -1).replace(/\\\\\"/g, '\"');\n }\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1).replace(/''/g, \"'\");\n }\n return trimmed;\n}\n\nfunction parsedMemoryIdentity(filePath: string, raw: Buffer | string): ReconcileMemoryIdentity | undefined {\n if (!isMemoryPath(filePath)) return undefined;\n const match = (Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : raw).match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n if (!match) return undefined;\n const fields = new Map<string, string>();\n for (const line of match[1].split(\"\\n\")) {\n const separator = line.indexOf(\":\");\n if (separator > 0) fields.set(line.slice(0, separator).trim(), line.slice(separator + 1).trim());\n }\n const id = parseScalar(fields.get(\"id\"));\n if (!id) return undefined;\n const category = parseScalar(fields.get(\"category\")) ?? \"fact\";\n const storedHash = parseScalar(fields.get(\"contentHash\"));\n const contentHash =\n storedHash && SHA256_PATTERN.test(storedHash)\n ? storedHash.toLowerCase()\n : ContentHashIndex.computeHash(match[2].trim());\n const status = inferMemoryStatus(\n {\n status: parseScalar(fields.get(\"status\")) as MemoryStatus | undefined,\n archivedAt: parseScalar(fields.get(\"archivedAt\")),\n } as MemoryFrontmatter,\n filePath\n );\n return { id, category, contentHash, status };\n}\n\nexport async function buildReconcileManifest(options: BuildReconcileManifestOptions): Promise<ReconcileManifest> {\n const cachedByPath = new Map<string, ReconcileManifestFile>();\n for (const cached of options.cachedFiles ?? []) {\n cachedByPath.set(cached.path, cached);\n }\n\n const files: ReconcileManifestFile[] = [];\n for (const file of options.files) {\n const cached = cachedByPath.get(file.path);\n if (cached?.sha256.toLowerCase() === file.sha256.toLowerCase()) {\n files.push({ ...file, ...(cached.memory ? { memory: cached.memory } : {}) });\n continue;\n }\n\n let raw: Buffer | string | null = null;\n if (isMemoryPath(file.path)) {\n try {\n raw = await options.readFile(file);\n } catch {\n raw = null;\n }\n }\n if (raw !== null && createHash(\"sha256\").update(raw).digest(\"hex\") !== file.sha256.toLowerCase()) {\n raw = null;\n }\n const memory = raw === null ? undefined : parsedMemoryIdentity(file.path, raw);\n files.push({ ...file, ...(memory ? { memory } : {}) });\n }\n files.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));\n return {\n format: RECONCILE_MANIFEST_FORMAT,\n schemaVersion: RECONCILE_MANIFEST_SCHEMA_VERSION,\n files,\n };\n}\n\nfunction activeFactByPath(manifest: ReconcileManifest | undefined): Map<string, ActiveFactManifestFile> {\n const result = new Map<string, ActiveFactManifestFile>();\n for (const file of manifest?.files ?? []) {\n if (file.memory?.category === \"fact\" && file.memory.status === \"active\") {\n result.set(file.path, file as ActiveFactManifestFile);\n }\n }\n return result;\n}\n\nfunction contentHashRows(files: Iterable<ActiveFactManifestFile>): ContentHashPathEntry[] {\n const rows: ContentHashPathEntry[] = [];\n for (const file of files) {\n rows.push({ path: file.path, contentHash: file.memory.contentHash });\n }\n return rows;\n}\n\nfunction comparePlanEntries(left: ReconcilePlanEntry, right: ReconcilePlanEntry): number {\n if (left.namespace !== right.namespace) return left.namespace < right.namespace ? -1 : 1;\n return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;\n}\n\nexport function collapseActiveFactDuplicates(\n plan: ReconcilePlan,\n localManifests: ReadonlyMap<string, ReconcileManifest>,\n peerManifests: ReadonlyMap<string, ReconcileManifest>\n): ReconcilePlan {\n const entriesByNamespace = new Map<string, ReconcilePlanEntry[]>();\n for (const entry of plan.entries) {\n const entries = entriesByNamespace.get(entry.namespace) ?? [];\n entries.push({ ...entry });\n entriesByNamespace.set(entry.namespace, entries);\n }\n\n let changed = false;\n for (const namespace of new Set([...localManifests.keys(), ...peerManifests.keys()])) {\n const entries = entriesByNamespace.get(namespace) ?? [];\n const localManifest = localManifests.get(namespace);\n const peerManifest = peerManifests.get(namespace);\n const localByPath = activeFactByPath(localManifest);\n const peerByPath = activeFactByPath(peerManifest);\n const localFilesByPath = new Map((localManifest?.files ?? []).map((file) => [file.path, file]));\n const peerFilesByPath = new Map((peerManifest?.files ?? []).map((file) => [file.path, file]));\n const localByHash = new Map<string, ActiveFactManifestFile[]>();\n const peerByHash = new Map<string, ActiveFactManifestFile[]>();\n\n for (const file of localByPath.values()) {\n const hash = file.memory.contentHash;\n const bucket = localByHash.get(hash) ?? [];\n bucket.push(file);\n localByHash.set(hash, bucket);\n }\n for (const file of peerByPath.values()) {\n const hash = file.memory.contentHash;\n const bucket = peerByHash.get(hash) ?? [];\n bucket.push(file);\n peerByHash.set(hash, bucket);\n }\n\n const removed = new Set<ReconcilePlanEntry>();\n const replacements: ReconcilePlanEntry[] = [];\n for (const hash of new Set([...localByHash.keys(), ...peerByHash.keys()])) {\n const localCandidates = (localByHash.get(hash) ?? []).filter((file) => {\n const opposite = peerFilesByPath.get(file.path);\n const activeOpposite = peerByPath.get(file.path);\n return opposite === undefined || activeOpposite?.memory.contentHash === hash;\n });\n const peerCandidates = (peerByHash.get(hash) ?? []).filter((file) => {\n const opposite = localFilesByPath.get(file.path);\n const activeOpposite = localByPath.get(file.path);\n return opposite === undefined || activeOpposite?.memory.contentHash === hash;\n });\n const localPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(localCandidates));\n const peerPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(peerCandidates));\n\n if (localPath && peerPath && localPath !== peerPath) {\n const localFile = localByPath.get(localPath);\n const peerFile = peerByPath.get(peerPath);\n if (!localFile || !peerFile) continue;\n const duplicatePaths = new Set([\n ...localCandidates.map((file) => file.path),\n ...peerCandidates.map((file) => file.path),\n ]);\n const unsafeEntry = entries.some(\n (entry) => duplicatePaths.has(entry.path) && (entry.action === \"suppress\" || entry.action === \"conflict\")\n );\n if (unsafeEntry) continue;\n for (const entry of entries) {\n if (\n duplicatePaths.has(entry.path) &&\n (entry.action === \"pull\" || entry.action === \"push\" || entry.action === \"identical\")\n ) {\n removed.add(entry);\n }\n }\n replacements.push({\n path: localPath < peerPath ? localPath : peerPath,\n namespace,\n action: \"identical\",\n reason: \"semantic_duplicate\",\n localSha256: localFile.sha256,\n peerSha256: peerFile.sha256,\n });\n changed = true;\n continue;\n }\n\n const sameSideEntries = entries.filter((entry) => {\n if (localPath && entry.reason === \"local_only\") {\n return localCandidates.some((file) => file.path === entry.path);\n }\n if (peerPath && entry.reason === \"peer_only\") {\n return peerCandidates.some((file) => file.path === entry.path);\n }\n return false;\n });\n const canonicalPath = localPath ?? peerPath;\n const hasSharedCanonical = localPath !== undefined && localPath === peerPath;\n if (!canonicalPath || sameSideEntries.length === 0 || (!hasSharedCanonical && sameSideEntries.length < 2)) {\n continue;\n }\n for (const entry of sameSideEntries) {\n if (entry.path !== canonicalPath) {\n removed.add(entry);\n changed = true;\n }\n }\n }\n\n if (removed.size > 0 || replacements.length > 0) {\n entriesByNamespace.set(\n namespace,\n [...entries.filter((entry) => !removed.has(entry)), ...replacements].sort(comparePlanEntries)\n );\n }\n }\n\n if (!changed) return plan;\n const entries = [...entriesByNamespace.values()].flat().sort(comparePlanEntries);\n return {\n entries,\n byNamespace: summarizeReconcilePlan(entries),\n converged: entries.every((entry) => entry.action === \"identical\"),\n };\n}\n"],"mappings":"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","names":["entries"]}
1
+ {"version":3,"sources":["../../src/reconcile/manifest.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { inferMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { ContentHashIndex, type ContentHashPathEntry } from \"../storage/content-hash-index.js\";\nimport type { MemoryFrontmatter, MemoryStatus } from \"../types.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport {\n type ReconcileFileState,\n type ReconcilePlan,\n type ReconcilePlanEntry,\n type ReconcileSemanticAgreement,\n type ReconcileSemanticChange,\n summarizeReconcilePlan,\n} from \"./plan.js\";\n\nexport const RECONCILE_MANIFEST_FORMAT = \"remnic-reconcile-manifest\";\nexport const RECONCILE_MANIFEST_SCHEMA_VERSION = 1;\n\nexport interface ReconcileMemoryIdentity {\n id: string;\n category: string;\n contentHash: string;\n status: MemoryStatus;\n}\n\nexport interface ReconcileManifestFile extends ReconcileFileState {\n memory?: ReconcileMemoryIdentity;\n}\n\ntype ActiveFactManifestFile = ReconcileManifestFile & { memory: ReconcileMemoryIdentity };\n\nexport interface ReconcileManifest {\n format: typeof RECONCILE_MANIFEST_FORMAT;\n schemaVersion: typeof RECONCILE_MANIFEST_SCHEMA_VERSION;\n files: ReconcileManifestFile[];\n}\n\nexport interface BuildReconcileManifestOptions {\n files: Iterable<ReconcileFileState>;\n readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>;\n cachedFiles?: Iterable<ReconcileManifestFile>;\n}\n\nconst SHA256_PATTERN = /^[a-f0-9]{64}$/i;\nconst MEMORY_DIRS = new Set(RECALL_FALLBACK_DIRS);\n\nfunction isMemoryPath(filePath: string): boolean {\n if (!filePath.endsWith(\".md\")) return false;\n const segments = filePath.split(\"/\");\n let index = 0;\n if (segments[index] === \"cold\" || segments[index] === \"archive\") index += 1;\n return MEMORY_DIRS.has(segments[index] ?? \"\");\n}\n\nfunction parseScalar(value: string | undefined): string | undefined {\n if (value === undefined) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n return typeof parsed === \"string\" ? parsed : trimmed;\n } catch {\n return trimmed.slice(1, -1).replace(/\\\\\"/g, '\"');\n }\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1).replace(/''/g, \"'\");\n }\n return trimmed;\n}\n\nfunction parsedMemoryIdentity(filePath: string, raw: Buffer | string): ReconcileMemoryIdentity | undefined {\n if (!isMemoryPath(filePath)) return undefined;\n const match = (Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : raw).match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n if (!match) return undefined;\n const fields = new Map<string, string>();\n for (const line of match[1].split(\"\\n\")) {\n const separator = line.indexOf(\":\");\n if (separator > 0) fields.set(line.slice(0, separator).trim(), line.slice(separator + 1).trim());\n }\n const id = parseScalar(fields.get(\"id\"));\n if (!id) return undefined;\n const category = parseScalar(fields.get(\"category\")) ?? \"fact\";\n const storedHash = parseScalar(fields.get(\"contentHash\"));\n const contentHash =\n storedHash && SHA256_PATTERN.test(storedHash)\n ? storedHash.toLowerCase()\n : ContentHashIndex.computeHash(match[2].trim());\n const status = inferMemoryStatus(\n {\n status: parseScalar(fields.get(\"status\")) as MemoryStatus | undefined,\n archivedAt: parseScalar(fields.get(\"archivedAt\")),\n } as MemoryFrontmatter,\n filePath\n );\n return { id, category, contentHash, status };\n}\n\nexport async function buildReconcileManifest(options: BuildReconcileManifestOptions): Promise<ReconcileManifest> {\n const cachedByPath = new Map<string, ReconcileManifestFile>();\n for (const cached of options.cachedFiles ?? []) {\n cachedByPath.set(cached.path, cached);\n }\n\n const files: ReconcileManifestFile[] = [];\n for (const file of options.files) {\n const cached = cachedByPath.get(file.path);\n if (cached?.sha256.toLowerCase() === file.sha256.toLowerCase()) {\n files.push({ ...file, ...(cached.memory ? { memory: cached.memory } : {}) });\n continue;\n }\n\n let raw: Buffer | string | null = null;\n if (isMemoryPath(file.path)) {\n try {\n raw = await options.readFile(file);\n } catch {\n raw = null;\n }\n }\n if (raw !== null && createHash(\"sha256\").update(raw).digest(\"hex\") !== file.sha256.toLowerCase()) {\n raw = null;\n }\n const memory = raw === null ? undefined : parsedMemoryIdentity(file.path, raw);\n files.push({ ...file, ...(memory ? { memory } : {}) });\n }\n files.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));\n return {\n format: RECONCILE_MANIFEST_FORMAT,\n schemaVersion: RECONCILE_MANIFEST_SCHEMA_VERSION,\n files,\n };\n}\n\nfunction activeFactByPath(manifest: ReconcileManifest | undefined): Map<string, ActiveFactManifestFile> {\n const result = new Map<string, ActiveFactManifestFile>();\n for (const file of manifest?.files ?? []) {\n if (file.memory?.category === \"fact\" && file.memory.status === \"active\") {\n result.set(file.path, file as ActiveFactManifestFile);\n }\n }\n return result;\n}\n\nfunction contentHashRows(files: Iterable<ActiveFactManifestFile>): ContentHashPathEntry[] {\n const rows: ContentHashPathEntry[] = [];\n for (const file of files) {\n rows.push({ path: file.path, contentHash: file.memory.contentHash });\n }\n return rows;\n}\n\nfunction comparePlanEntries(left: ReconcilePlanEntry, right: ReconcilePlanEntry): number {\n if (left.namespace !== right.namespace) return left.namespace < right.namespace ? -1 : 1;\n return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;\n}\n\nfunction semanticAgreementKey(agreement: ReconcileSemanticAgreement): string {\n return `${agreement.local.path}\\0${agreement.peer.path}`;\n}\n\nfunction classifySemanticChange(\n current: ReconcileSemanticAgreement,\n prior: ReconcileSemanticAgreement | undefined\n): ReconcileSemanticChange {\n if (!prior) return \"unchanged\";\n const localChanged = current.local.sha256 !== prior.local.sha256;\n const peerChanged = current.peer.sha256 !== prior.peer.sha256;\n if (localChanged && peerChanged) return \"both_modified\";\n if (localChanged) return \"local_changed\";\n if (peerChanged) return \"peer_changed\";\n return \"unchanged\";\n}\n\nexport function collapseActiveFactDuplicates(\n plan: ReconcilePlan,\n localManifests: ReadonlyMap<string, ReconcileManifest>,\n peerManifests: ReadonlyMap<string, ReconcileManifest>,\n priorSemanticAgreements?: ReadonlyMap<string, readonly ReconcileSemanticAgreement[]>,\n): ReconcilePlan {\n const entriesByNamespace = new Map<string, ReconcilePlanEntry[]>();\n for (const entry of plan.entries) {\n const entries = entriesByNamespace.get(entry.namespace) ?? [];\n entries.push({ ...entry });\n entriesByNamespace.set(entry.namespace, entries);\n }\n\n let changed = false;\n for (const namespace of new Set([...localManifests.keys(), ...peerManifests.keys()])) {\n const entries = entriesByNamespace.get(namespace) ?? [];\n const localManifest = localManifests.get(namespace);\n const peerManifest = peerManifests.get(namespace);\n const localByPath = activeFactByPath(localManifest);\n const peerByPath = activeFactByPath(peerManifest);\n const localFilesByPath = new Map((localManifest?.files ?? []).map((file) => [file.path, file]));\n const peerFilesByPath = new Map((peerManifest?.files ?? []).map((file) => [file.path, file]));\n const priorSemanticByPathPair = new Map(\n (priorSemanticAgreements?.get(namespace) ?? []).map((agreement) => [\n semanticAgreementKey(agreement),\n agreement,\n ])\n );\n const localByHash = new Map<string, ActiveFactManifestFile[]>();\n const peerByHash = new Map<string, ActiveFactManifestFile[]>();\n\n for (const file of localByPath.values()) {\n const hash = file.memory.contentHash;\n const bucket = localByHash.get(hash) ?? [];\n bucket.push(file);\n localByHash.set(hash, bucket);\n }\n for (const file of peerByPath.values()) {\n const hash = file.memory.contentHash;\n const bucket = peerByHash.get(hash) ?? [];\n bucket.push(file);\n peerByHash.set(hash, bucket);\n }\n\n const removed = new Set<ReconcilePlanEntry>();\n const replacements: ReconcilePlanEntry[] = [];\n for (const hash of new Set([...localByHash.keys(), ...peerByHash.keys()])) {\n const localCandidates = (localByHash.get(hash) ?? []).filter((file) => {\n const opposite = peerFilesByPath.get(file.path);\n const activeOpposite = peerByPath.get(file.path);\n return opposite === undefined || activeOpposite?.memory.contentHash === hash;\n });\n const peerCandidates = (peerByHash.get(hash) ?? []).filter((file) => {\n const opposite = localFilesByPath.get(file.path);\n const activeOpposite = localByPath.get(file.path);\n return opposite === undefined || activeOpposite?.memory.contentHash === hash;\n });\n const localPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(localCandidates));\n const peerPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(peerCandidates));\n\n if (localPath && peerPath && localPath !== peerPath) {\n const localFile = localByPath.get(localPath);\n const peerFile = peerByPath.get(peerPath);\n if (!localFile || !peerFile) continue;\n const duplicatePaths = new Set([\n ...localCandidates.map((file) => file.path),\n ...peerCandidates.map((file) => file.path),\n ]);\n const authoritativeSamePathEntries = new Set(entries.filter(\n (entry) =>\n duplicatePaths.has(entry.path)\n && localFilesByPath.has(entry.path)\n && peerFilesByPath.has(entry.path)\n && entry.action !== \"identical\"\n ));\n if (authoritativeSamePathEntries.size > 0) {\n for (const entry of entries) {\n if (\n duplicatePaths.has(entry.path)\n && !authoritativeSamePathEntries.has(entry)\n && (entry.action === \"pull\" || entry.action === \"push\" || entry.action === \"identical\")\n ) {\n removed.add(entry);\n changed = true;\n }\n }\n continue;\n }\n const unsafeEntry = entries.some(\n (entry) => duplicatePaths.has(entry.path) && (entry.action === \"suppress\" || entry.action === \"conflict\")\n );\n if (unsafeEntry) continue;\n for (const entry of entries) {\n if (\n duplicatePaths.has(entry.path) &&\n (entry.action === \"pull\" || entry.action === \"push\" || entry.action === \"identical\")\n ) {\n removed.add(entry);\n }\n }\n const semanticAgreement: ReconcileSemanticAgreement = {\n local: { path: localPath, sha256: localFile.sha256 },\n peer: { path: peerPath, sha256: peerFile.sha256 },\n };\n replacements.push({\n path: localPath < peerPath ? localPath : peerPath,\n namespace,\n action: \"identical\",\n reason: \"semantic_duplicate\",\n semanticAgreement,\n semanticChange: classifySemanticChange(\n semanticAgreement,\n priorSemanticByPathPair.get(semanticAgreementKey(semanticAgreement))\n ),\n });\n changed = true;\n continue;\n }\n\n const sameSideEntries = entries.filter((entry) => {\n if (localPath && entry.reason === \"local_only\") {\n return localCandidates.some((file) => file.path === entry.path);\n }\n if (peerPath && entry.reason === \"peer_only\") {\n return peerCandidates.some((file) => file.path === entry.path);\n }\n return false;\n });\n const canonicalPath = localPath ?? peerPath;\n const hasSharedCanonical = localPath !== undefined && localPath === peerPath;\n if (!canonicalPath || sameSideEntries.length === 0 || (!hasSharedCanonical && sameSideEntries.length < 2)) {\n continue;\n }\n for (const entry of sameSideEntries) {\n if (entry.path !== canonicalPath) {\n removed.add(entry);\n changed = true;\n }\n }\n }\n\n if (removed.size > 0 || replacements.length > 0) {\n entriesByNamespace.set(\n namespace,\n [...entries.filter((entry) => !removed.has(entry)), ...replacements].sort(comparePlanEntries)\n );\n }\n }\n\n if (!changed) return plan;\n const entries = [...entriesByNamespace.values()].flat().sort(comparePlanEntries);\n return {\n entries,\n byNamespace: summarizeReconcilePlan(entries),\n converged: entries.every((entry) => entry.action === \"identical\"),\n };\n}\n"],"mappings":"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","names":["entries"]}
@@ -1,4 +1,9 @@
1
1
  import { OfflineSyncFileState } from '../offline-sync.js';
2
+ import { ai as ConvergeConflictPolicy } from '../types-rEwubvim.js';
3
+ import '../message-parts/index.js';
4
+ import '../bounded-jsonl-state.js';
5
+ import '../operator-doctor-types.js';
6
+ import '../types-continuity.js';
2
7
 
3
8
  /**
4
9
  * Bootstrap reconciliation planner for two peer daemons whose corpora have
@@ -19,22 +24,22 @@ import { OfflineSyncFileState } from '../offline-sync.js';
19
24
  */
20
25
  /** Which way a path must move for the two corpora to agree. */
21
26
  type ReconcileAction = "pull" | "push" | "identical" | "conflict" | "suppress";
22
- /**
23
- * How a path present on BOTH sides with different content is settled.
24
- *
25
- * `manual` is the safe default: on a bootstrap merge the two sides are equally
26
- * authoritative, so silently picking one is data loss with extra steps. An
27
- * operator opts into an automatic rule once they know the shape of their split.
28
- */
29
- type ReconcileConflictPolicy = "manual" | "newest-wins" | "keep-both";
30
27
  /**
31
28
  * What the planner decided for a conflicting path.
32
- *
33
- * `keep-both` never overwrites: the older side is retained and linked as
34
- * superseded by the newer one, which is the only resolution that cannot lose a
35
- * fact neither corpus has seen.
29
+ * `supersede-link` records that both revisions need durable preservation when
30
+ * timestamps cannot safely select a winner. Apply must stop until transport
31
+ * can assign distinct durable identities to both revisions.
36
32
  */
37
33
  type ReconcileResolution = "local-wins" | "peer-wins" | "supersede-link" | "unresolved";
34
+ interface ReconcileSemanticFileState {
35
+ path: string;
36
+ sha256: string;
37
+ }
38
+ interface ReconcileSemanticAgreement {
39
+ local: ReconcileSemanticFileState;
40
+ peer: ReconcileSemanticFileState;
41
+ }
42
+ type ReconcileSemanticChange = "unchanged" | "local_changed" | "peer_changed" | "both_modified";
38
43
  interface ReconcilePlanEntry {
39
44
  path: string;
40
45
  namespace: string;
@@ -55,14 +60,12 @@ interface ReconcilePlanEntry {
55
60
  */
56
61
  suppressSide?: "local" | "peer" | "both";
57
62
  /**
58
- * Which revision is newer, set only for a `supersede-link` resolution.
59
- *
60
- * The contract is that the older revision is linked as superseded by the
61
- * newer one, so transport needs the direction. Absent when the timestamps
62
- * cannot order the two - which is exactly when `newest-wins` degrades to
63
- * `supersede-link` - and the link direction is then an operator decision.
63
+ * Real per-side identities for a cross-path semantic agreement. Synthetic
64
+ * rows omit the top-level side digests because `path` cannot name both files.
64
65
  */
65
- newerSide?: "local" | "peer";
66
+ semanticAgreement?: ReconcileSemanticAgreement;
67
+ /** Each side's current digest compared with its own prior semantic digest. */
68
+ semanticChange?: ReconcileSemanticChange;
66
69
  }
67
70
  type ReconcileReason = "peer_only" | "local_only"
68
71
  /** Cursor showed only that side moved since agreement; both still hold the path. */
@@ -108,6 +111,14 @@ interface ReconcileNamespaceInput {
108
111
  * read as "never seen" rather than "deleted".
109
112
  */
110
113
  base?: Iterable<ReconcileFileState>;
114
+ /**
115
+ * Revision timestamps for paths deleted locally since the base cursor.
116
+ * A deletion is a revision and must carry a comparable time for
117
+ * `newest-wins`; absence alone has no timestamp.
118
+ */
119
+ localDeletionMtimeMs?: ReadonlyMap<string, number>;
120
+ /** Revision timestamps for paths deleted by the peer since the base cursor. */
121
+ peerDeletionMtimeMs?: ReadonlyMap<string, number>;
111
122
  /**
112
123
  * Digests of FILES this side has retracted, in the same form as
113
124
  * `ReconcileFileState.sha256` — a hash of the serialized file.
@@ -139,7 +150,7 @@ interface ReconcileNamespaceInput {
139
150
  peerTombstonedFileSha256?: Iterable<string>;
140
151
  }
141
152
  interface ReconcileOptions {
142
- conflictPolicy?: ReconcileConflictPolicy;
153
+ conflictPolicy?: ConvergeConflictPolicy;
143
154
  }
144
155
  /**
145
156
  * A census the planner refuses to reason about.
@@ -172,4 +183,4 @@ declare function summarizeReconcilePlan(entries: readonly ReconcilePlanEntry[]):
172
183
  */
173
184
  declare function planReconciliation(namespaces: readonly ReconcileNamespaceInput[], options?: ReconcileOptions): ReconcilePlan;
174
185
 
175
- export { type ReconcileAction, type ReconcileConflictPolicy, type ReconcileFileState, type ReconcileNamespaceInput, type ReconcileNamespaceReport, type ReconcileOptions, type ReconcilePlan, type ReconcilePlanEntry, ReconcilePlanInputError, type ReconcileReason, type ReconcileResolution, planNamespaceReconciliation, planReconciliation, summarizeReconcilePlan };
186
+ export { type ReconcileAction, type ReconcileFileState, type ReconcileNamespaceInput, type ReconcileNamespaceReport, type ReconcileOptions, type ReconcilePlan, type ReconcilePlanEntry, ReconcilePlanInputError, type ReconcileReason, type ReconcileResolution, type ReconcileSemanticAgreement, type ReconcileSemanticChange, type ReconcileSemanticFileState, planNamespaceReconciliation, planReconciliation, summarizeReconcilePlan };
@@ -3,7 +3,8 @@ import {
3
3
  planNamespaceReconciliation,
4
4
  planReconciliation,
5
5
  summarizeReconcilePlan
6
- } from "../chunk-6UWB5PTR.js";
6
+ } from "../chunk-4L6HUREQ.js";
7
+ import "../chunk-HBVPYRDW.js";
7
8
  import "../chunk-EGGE52UU.js";
8
9
  import "../chunk-7XC2HX75.js";
9
10
  import "../chunk-UI3NYK34.js";
@@ -1,6 +1,6 @@
1
1
  import { ReplayNormalizer } from '../types.js';
2
2
  import '../../message-parts/index.js';
3
- import '../../types-CqWwMPr_.js';
3
+ import '../../types-rEwubvim.js';
4
4
  import '../../bounded-jsonl-state.js';
5
5
  import '../../operator-doctor-types.js';
6
6
  import '../../types-continuity.js';
@@ -1,6 +1,6 @@
1
1
  import { ReplayNormalizer } from '../types.js';
2
2
  import '../../message-parts/index.js';
3
- import '../../types-CqWwMPr_.js';
3
+ import '../../types-rEwubvim.js';
4
4
  import '../../bounded-jsonl-state.js';
5
5
  import '../../operator-doctor-types.js';
6
6
  import '../../types-continuity.js';
@@ -1,6 +1,6 @@
1
1
  import { ReplayNormalizer } from '../types.js';
2
2
  import '../../message-parts/index.js';
3
- import '../../types-CqWwMPr_.js';
3
+ import '../../types-rEwubvim.js';
4
4
  import '../../bounded-jsonl-state.js';
5
5
  import '../../operator-doctor-types.js';
6
6
  import '../../types-continuity.js';
@@ -1,6 +1,6 @@
1
1
  import { ReplayRole } from '../types.js';
2
2
  import '../../message-parts/index.js';
3
- import '../../types-CqWwMPr_.js';
3
+ import '../../types-rEwubvim.js';
4
4
  import '../../bounded-jsonl-state.js';
5
5
  import '../../operator-doctor-types.js';
6
6
  import '../../types-continuity.js';
@@ -1,6 +1,6 @@
1
1
  import { ReplaySource, ReplayWarning, ReplayNormalizer, ReplayTurn, ReplayParseOptions } from './types.js';
2
2
  import '../message-parts/index.js';
3
- import '../types-CqWwMPr_.js';
3
+ import '../types-rEwubvim.js';
4
4
  import '../bounded-jsonl-state.js';
5
5
  import '../operator-doctor-types.js';
6
6
  import '../types-continuity.js';
@@ -1,5 +1,5 @@
1
1
  import { LcmMessagePartInput, MessagePartSourceFormat } from '../message-parts/index.js';
2
- import { n as SourceConnectorProvenance } from '../types-CqWwMPr_.js';
2
+ import { n as SourceConnectorProvenance } from '../types-rEwubvim.js';
3
3
  import '../bounded-jsonl-state.js';
4
4
  import '../operator-doctor-types.js';
5
5
  import '../types-continuity.js';
@@ -1,6 +1,6 @@
1
1
  import { TokenCapabilities } from './access-token-capabilities.js';
2
2
  import { CorpusWatermark } from './corpus-watermark.js';
3
- import { Z as ReplicaPeersConfig, _ as ReplicaPeerConfig } from './types-CqWwMPr_.js';
3
+ import { Z as ReplicaPeersConfig, _ as ReplicaPeerConfig } from './types-rEwubvim.js';
4
4
  import { ResolveSecretRefFn } from './resolve-auth-token.js';
5
5
  import 'node:async_hooks';
6
6
  import './message-parts/index.js';
@@ -1,4 +1,4 @@
1
- export { _ as ReplicaPeerConfig, Z as ReplicaPeersConfig, cc as parseReplicaPeersConfig, cd as resolveReplicaPeersConfig } from './types-CqWwMPr_.js';
1
+ export { _ as ReplicaPeerConfig, Z as ReplicaPeersConfig, ce as parseReplicaPeersConfig, cf as resolveReplicaPeersConfig } from './types-rEwubvim.js';
2
2
  import './message-parts/index.js';
3
3
  import './bounded-jsonl-state.js';
4
4
  import './operator-doctor-types.js';
@@ -1,4 +1,4 @@
1
- import { s as SecretRef, t as AgentAccessAuthToken } from './types-CqWwMPr_.js';
1
+ import { s as SecretRef, t as AgentAccessAuthToken } from './types-rEwubvim.js';
2
2
  import './message-parts/index.js';
3
3
  import './bounded-jsonl-state.js';
4
4
  import './operator-doctor-types.js';
@@ -4,18 +4,19 @@ import {
4
4
  recordResumeBundle,
5
5
  resolveResumeBundleDir,
6
6
  validateResumeBundle
7
- } from "./chunk-GDC4INBF.js";
7
+ } from "./chunk-HO3QBJEY.js";
8
8
  import "./chunk-ZRWB5D4H.js";
9
9
  import "./chunk-HYQJQGD3.js";
10
10
  import "./chunk-KFY3SGN7.js";
11
11
  import "./chunk-LMDRGRJ2.js";
12
- import "./chunk-TM72UOX2.js";
12
+ import "./chunk-CUM2BBPN.js";
13
13
  import "./chunk-NDAH7BJ5.js";
14
14
  import "./chunk-7RAJ3GXO.js";
15
15
  import "./chunk-Z5LAYHGJ.js";
16
16
  import "./chunk-6ZMAMSHS.js";
17
17
  import "./chunk-H4WG3UQZ.js";
18
18
  import "./chunk-OO42R444.js";
19
+ import "./chunk-HBVPYRDW.js";
19
20
  import "./chunk-PIG4WJFQ.js";
20
21
  import "./chunk-KFZY2OFH.js";
21
22
  import "./chunk-S4DDLTPX.js";
@@ -27,8 +28,8 @@ import "./chunk-IJ6WHMFB.js";
27
28
  import "./chunk-3SG4FGDV.js";
28
29
  import "./chunk-K6MV3TRQ.js";
29
30
  import "./chunk-5I4M26Q7.js";
30
- import "./chunk-5GKPFL3S.js";
31
31
  import "./chunk-ZIKENA2C.js";
32
+ import "./chunk-5GKPFL3S.js";
32
33
  import "./chunk-PQVCH2AE.js";
33
34
  import "./chunk-EYIEWJNI.js";
34
35
  import "./chunk-JUC24CTX.js";
@@ -1,5 +1,5 @@
1
- import { Q as QmdSearchResult } from './types-CqWwMPr_.js';
2
- import { Q as QmdClient } from './qmd-WJwvBgiF.js';
1
+ import { Q as QmdSearchResult } from './types-rEwubvim.js';
2
+ import { Q as QmdClient } from './qmd-LWtMofAf.js';
3
3
  import './message-parts/index.js';
4
4
  import './bounded-jsonl-state.js';
5
5
  import './operator-doctor-types.js';
@@ -1,4 +1,4 @@
1
- import { ay as RetrievalTier } from './types-CqWwMPr_.js';
1
+ import { aA as RetrievalTier } from './types-rEwubvim.js';
2
2
  import './message-parts/index.js';
3
3
  import './bounded-jsonl-state.js';
4
4
  import './operator-doctor-types.js';
@@ -1,4 +1,4 @@
1
- import { v as MemoryCategory } from '../types-CqWwMPr_.js';
1
+ import { v as MemoryCategory } from '../types-rEwubvim.js';
2
2
  import '../message-parts/index.js';
3
3
  import '../bounded-jsonl-state.js';
4
4
  import '../operator-doctor-types.js';
@@ -1,5 +1,5 @@
1
1
  import { RoutingEngineOptions, RouteRule } from './engine.js';
2
- import '../types-CqWwMPr_.js';
2
+ import '../types-rEwubvim.js';
3
3
  import '../message-parts/index.js';
4
4
  import '../bounded-jsonl-state.js';
5
5
  import '../operator-doctor-types.js';
@@ -1,5 +1,5 @@
1
1
  import { MemoryWriteInput, WriteContext, SealedMemoryEnvelope } from './write-envelope.js';
2
- import './types-CqWwMPr_.js';
2
+ import './types-rEwubvim.js';
3
3
  import './message-parts/index.js';
4
4
  import './bounded-jsonl-state.js';
5
5
  import './operator-doctor-types.js';
@@ -1,4 +1,4 @@
1
- import { o as ScopeProfileConfig, p as ScopeProfileLayerId, q as ScopeProfilePromotionTarget } from './types-CqWwMPr_.js';
1
+ import { o as ScopeProfileConfig, p as ScopeProfileLayerId, q as ScopeProfilePromotionTarget } from './types-rEwubvim.js';
2
2
 
3
3
  interface ScopeProfileLayerResolution {
4
4
  id: ScopeProfileLayerId;
@@ -1,4 +1,4 @@
1
- import { P as PluginConfig } from '../types-CqWwMPr_.js';
1
+ import { P as PluginConfig } from '../types-rEwubvim.js';
2
2
  import { HostEmbeddingProvider } from '../host-embedding-provider.js';
3
3
  import '../message-parts/index.js';
4
4
  import '../bounded-jsonl-state.js';
@@ -1,4 +1,4 @@
1
- import { P as PluginConfig } from '../types-CqWwMPr_.js';
1
+ import { P as PluginConfig } from '../types-rEwubvim.js';
2
2
  import { SearchBackend } from './port.js';
3
3
  import { F as FaissConversationIndexAdapter } from '../faiss-adapter-BHecI1fF.js';
4
4
  import { ConversationQmdRuntime, ConversationIndexBackend } from '../conversation-index/backend.js';
@@ -7,7 +7,7 @@ export { OramaBackend } from './orama-backend.js';
7
7
  export { EmbedHelper } from './embed-helper.js';
8
8
  export { IndexableDocument, scanMemoryDir } from './document-scanner.js';
9
9
  export { createConversationIndexRuntime, createConversationSearchBackend, createSearchBackend } from './factory.js';
10
- import '../types-CqWwMPr_.js';
10
+ import '../types-rEwubvim.js';
11
11
  import '../message-parts/index.js';
12
12
  import '../bounded-jsonl-state.js';
13
13
  import '../operator-doctor-types.js';
@@ -1,6 +1,6 @@
1
1
  import { SearchBackend, SearchQueryOptions, SearchExecutionOptions, SearchResult } from './port.js';
2
2
  import { EmbedHelper } from './embed-helper.js';
3
- import '../types-CqWwMPr_.js';
3
+ import '../types-rEwubvim.js';
4
4
  import '../message-parts/index.js';
5
5
  import '../bounded-jsonl-state.js';
6
6
  import '../operator-doctor-types.js';