@remnic/core 9.63.6 → 9.63.8

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 (304) hide show
  1. package/dist/access-admin-ops-surface.d.ts +3 -2
  2. package/dist/access-admin-ops-surface.js +31 -27
  3. package/dist/access-authorization-probe.d.ts +3 -2
  4. package/dist/access-authorization-probe.js +32 -28
  5. package/dist/access-boundary.d.ts +3 -2
  6. package/dist/access-boundary.js +31 -27
  7. package/dist/access-cli.js +98 -95
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +3 -2
  10. package/dist/access-extraction-force-flush.js +31 -27
  11. package/dist/access-http-lcm-compaction.d.ts +3 -2
  12. package/dist/access-http-lifecycle-flush.d.ts +3 -2
  13. package/dist/access-http-offline-stream.d.ts +3 -2
  14. package/dist/access-http-query.js +33 -29
  15. package/dist/access-http.d.ts +4 -3
  16. package/dist/access-http.js +47 -43
  17. package/dist/access-identity-continuity-surface.d.ts +2 -1
  18. package/dist/access-identity-continuity-surface.js +31 -27
  19. package/dist/access-lcm-surface.d.ts +3 -2
  20. package/dist/access-lcm-surface.js +31 -27
  21. package/dist/access-mcp-output-schemas.js +1 -1
  22. package/dist/access-mcp.d.ts +3 -2
  23. package/dist/access-mcp.js +38 -34
  24. package/dist/access-namespace-preflight.js +31 -27
  25. package/dist/access-observe-write-surface.d.ts +3 -2
  26. package/dist/access-observe-write-surface.js +31 -27
  27. package/dist/access-offline-manifest.d.ts +2 -1
  28. package/dist/access-offline-manifest.js +5 -4
  29. package/dist/access-operations-batch.js +32 -28
  30. package/dist/access-operations.d.ts +3 -2
  31. package/dist/access-operations.js +36 -32
  32. package/dist/access-recall-concurrency.d.ts +3 -2
  33. package/dist/access-recall-concurrency.js +31 -27
  34. package/dist/access-recall-response.d.ts +3 -2
  35. package/dist/access-recall-response.js +31 -27
  36. package/dist/access-recall-surface.d.ts +3 -2
  37. package/dist/access-recall-surface.js +31 -27
  38. package/dist/access-schema.js +6 -5
  39. package/dist/{access-service-cKQrte9Z.d.ts → access-service-BaPa_km6.d.ts} +1 -1
  40. package/dist/access-service-helpers.d.ts +3 -2
  41. package/dist/access-service.d.ts +3 -2
  42. package/dist/access-service.js +31 -27
  43. package/dist/access-surface-catalog.d.ts +3 -2
  44. package/dist/access-surface-catalog.js +33 -29
  45. package/dist/access-surface-catalog.js.map +1 -1
  46. package/dist/active-recall.js +4 -2
  47. package/dist/active-recall.js.map +1 -1
  48. package/dist/adapters/index.js +4 -4
  49. package/dist/adapters/registry.js +2 -2
  50. package/dist/{auto-sync-BKRJDMKX.js → auto-sync-3SHMZVQS.js} +5 -3
  51. package/dist/{auto-sync-BKRJDMKX.js.map → auto-sync-3SHMZVQS.js.map} +1 -1
  52. package/dist/bootstrap.d.ts +2 -1
  53. package/dist/briefing.js +10 -10
  54. package/dist/calibration.d.ts +2 -1
  55. package/dist/calibration.js +7 -0
  56. package/dist/calibration.js.map +1 -1
  57. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  58. package/dist/causal-consolidation.js +11 -11
  59. package/dist/census-validation.d.ts +19 -0
  60. package/dist/census-validation.js +14 -0
  61. package/dist/census-validation.js.map +1 -0
  62. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  63. package/dist/chunk-2YA5N2BY.js +65 -0
  64. package/dist/chunk-2YA5N2BY.js.map +1 -0
  65. package/dist/{chunk-PB4WVYGC.js → chunk-3IMYRX3W.js} +2 -2
  66. package/dist/{chunk-R6UMNP5C.js → chunk-3T6HIIKA.js} +2 -2
  67. package/dist/{chunk-77QZW2D6.js → chunk-3TDAA7VA.js} +2 -2
  68. package/dist/{chunk-TWTUGCTY.js → chunk-3YTTAGPB.js} +6 -1
  69. package/dist/chunk-3YTTAGPB.js.map +1 -0
  70. package/dist/{chunk-DXDAQZ2K.js → chunk-42TIIO2M.js} +2 -2
  71. package/dist/{chunk-Y7COCXY2.js → chunk-4F67JJPG.js} +2 -2
  72. package/dist/{chunk-OW7NVMGQ.js → chunk-5OOTHWGJ.js} +2 -2
  73. package/dist/{chunk-KYTRF64R.js → chunk-5SCFDQEJ.js} +2 -2
  74. package/dist/{chunk-DYZR3Z6D.js → chunk-5TF5STAV.js} +4 -4
  75. package/dist/{chunk-GG4DN63W.js → chunk-62Y5AGCM.js} +2 -2
  76. package/dist/{chunk-PMVPCZJZ.js → chunk-6433HV72.js} +2 -2
  77. package/dist/{chunk-KHCUVYCY.js → chunk-6UKSOXAO.js} +3 -3
  78. package/dist/{chunk-GF7RQWXC.js → chunk-AJRJDXYR.js} +2 -2
  79. package/dist/{chunk-YEQCMA5L.js → chunk-BOSIHHOH.js} +2 -2
  80. package/dist/{chunk-IVXVLDNT.js → chunk-BPQ7L27U.js} +77 -92
  81. package/dist/chunk-BPQ7L27U.js.map +1 -0
  82. package/dist/{chunk-7LF2OHIJ.js → chunk-BRHKW7GY.js} +2 -2
  83. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  84. package/dist/{chunk-LX4TNSAE.js → chunk-CBY54QYW.js} +4 -4
  85. package/dist/{chunk-CIAI24TQ.js → chunk-DGUVXXAU.js} +3 -3
  86. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  87. package/dist/{chunk-QI5RDDEL.js → chunk-EDZNW3HE.js} +3 -3
  88. package/dist/chunk-FEHIOYML.js +168 -0
  89. package/dist/chunk-FEHIOYML.js.map +1 -0
  90. package/dist/{chunk-Z4N7SVVF.js → chunk-FZEEWOI2.js} +9 -4
  91. package/dist/chunk-FZEEWOI2.js.map +1 -0
  92. package/dist/{chunk-6YMEU6OQ.js → chunk-G72IPMR7.js} +2 -2
  93. package/dist/{chunk-7AF243WZ.js → chunk-GBVRVYF4.js} +1 -1
  94. package/dist/{chunk-FPEZ74F7.js → chunk-I2HTKOOP.js} +3 -3
  95. package/dist/{chunk-R7TZ2HCS.js → chunk-JG22O53B.js} +58 -3
  96. package/dist/chunk-JG22O53B.js.map +1 -0
  97. package/dist/{chunk-VPHSMJ2E.js → chunk-JPWSYHLB.js} +2 -2
  98. package/dist/{chunk-X7LEDA74.js → chunk-KFB4YNXM.js} +2 -2
  99. package/dist/{chunk-I5FLIB2J.js → chunk-KXWE62IH.js} +2 -2
  100. package/dist/chunk-LQWOFU6L.js +17 -0
  101. package/dist/chunk-LQWOFU6L.js.map +1 -0
  102. package/dist/{chunk-TSTI6A3A.js → chunk-LTYH2L6E.js} +13 -13
  103. package/dist/{chunk-ZUPKNWRZ.js → chunk-MIUL6AUZ.js} +3 -3
  104. package/dist/{chunk-EJY3HJMT.js → chunk-MYI3RKI6.js} +2 -2
  105. package/dist/{chunk-UCLMKNHA.js → chunk-N7V3P4V5.js} +2 -2
  106. package/dist/{chunk-NA56NSKL.js → chunk-O52TB5SL.js} +2 -2
  107. package/dist/{chunk-7KQB4EBS.js → chunk-OPPBTPUU.js} +4 -4
  108. package/dist/{chunk-ERPBRXVZ.js → chunk-PHKU6BZ2.js} +2 -2
  109. package/dist/{chunk-GTD4Q62X.js → chunk-PQHNZ63P.js} +4 -4
  110. package/dist/{chunk-FHKXVTM5.js → chunk-Q5XKKDFQ.js} +16 -16
  111. package/dist/{chunk-QRWMS6SI.js → chunk-Q6OL23WM.js} +2 -2
  112. package/dist/{chunk-V3KIRICY.js → chunk-QQYHYW2N.js} +3 -3
  113. package/dist/{chunk-YFCEBB5P.js → chunk-QTXNS3HB.js} +2 -2
  114. package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
  115. package/dist/{chunk-E4KMY4KR.js → chunk-SNEUAZ6B.js} +2 -2
  116. package/dist/{chunk-F6JYBVL6.js → chunk-SY5JUJ2X.js} +52 -52
  117. package/dist/{chunk-EFKZT6AY.js → chunk-T42L3S6A.js} +6 -11
  118. package/dist/chunk-T42L3S6A.js.map +1 -0
  119. package/dist/{chunk-YXMHUBN2.js → chunk-TOP3FSDW.js} +25 -102
  120. package/dist/chunk-TOP3FSDW.js.map +1 -0
  121. package/dist/{chunk-PBRCYYO7.js → chunk-ULZFZL7K.js} +2 -2
  122. package/dist/{chunk-YYQAKIDJ.js → chunk-VD2OT77P.js} +2 -2
  123. package/dist/chunk-VD2OT77P.js.map +1 -0
  124. package/dist/{chunk-IPLYGWQF.js → chunk-VDX2J7OX.js} +6 -6
  125. package/dist/{chunk-UGHCZS6K.js → chunk-VFZQXYN5.js} +2 -2
  126. package/dist/{chunk-NKB43PGI.js → chunk-VYMICVRA.js} +2 -2
  127. package/dist/{chunk-OETHJBAL.js → chunk-WBPD6SBZ.js} +109 -116
  128. package/dist/chunk-WBPD6SBZ.js.map +1 -0
  129. package/dist/{chunk-2UM6WHME.js → chunk-XE2QCCT2.js} +2 -2
  130. package/dist/{chunk-SYVGVK4S.js → chunk-XTMYB2HY.js} +2 -2
  131. package/dist/{chunk-AYVCKGA6.js → chunk-YTXNDEUS.js} +2 -2
  132. package/dist/{chunk-3Z5TGRFA.js → chunk-ZOAAY2OE.js} +9 -9
  133. package/dist/{chunk-L3CHRBHE.js → chunk-ZRUEP4IK.js} +17 -11
  134. package/dist/chunk-ZRUEP4IK.js.map +1 -0
  135. package/dist/{chunk-PRDJMOST.js → chunk-ZVZHG7AI.js} +65 -15
  136. package/dist/chunk-ZVZHG7AI.js.map +1 -0
  137. package/dist/{chunk-RYST72N5.js → chunk-ZWYXSF2T.js} +4 -154
  138. package/dist/chunk-ZWYXSF2T.js.map +1 -0
  139. package/dist/{cli-BFBDYV0D.d.ts → cli-D0tV7eeU.d.ts} +2 -2
  140. package/dist/cli.d.ts +4 -3
  141. package/dist/cli.js +69 -65
  142. package/dist/compounding/engine.js +10 -10
  143. package/dist/config.js +4 -2
  144. package/dist/connectors/codex-materialize-runner.js +10 -10
  145. package/dist/connectors/index.js +10 -10
  146. package/dist/consolidation-provenance-check.js +2 -2
  147. package/dist/convergence-refresh.js +12 -12
  148. package/dist/conversation-index/backend.js +2 -2
  149. package/dist/corpus-watermark.js +12 -12
  150. package/dist/entity-retrieval.js +10 -10
  151. package/dist/explicit-capture.d.ts +2 -1
  152. package/dist/external-wiki-access.d.ts +3 -2
  153. package/dist/external-wiki-access.js +32 -28
  154. package/dist/external-wiki-mcp-tools.d.ts +3 -2
  155. package/dist/extraction-judge.d.ts +2 -1
  156. package/dist/extraction-judge.js +6 -1
  157. package/dist/extraction-normalization.js +2 -2
  158. package/dist/extraction-prompt.d.ts +20 -1
  159. package/dist/extraction-prompt.js +11 -1
  160. package/dist/extraction.js +13 -13
  161. package/dist/harmonic-retrieval.js +1 -1
  162. package/dist/included-memories.d.ts +11 -0
  163. package/dist/included-memories.js +14 -0
  164. package/dist/included-memories.js.map +1 -0
  165. package/dist/index.d.ts +6 -5
  166. package/dist/index.js +117 -114
  167. package/dist/lcm/index.js +3 -3
  168. package/dist/maintenance/memory-governance.js +10 -10
  169. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -10
  170. package/dist/maintenance/rebuild-memory-projection.js +11 -11
  171. package/dist/mcp-memory-inspector-app.d.ts +3 -2
  172. package/dist/namespaces/migrate.js +11 -11
  173. package/dist/namespaces/search.js +4 -4
  174. package/dist/namespaces/storage.js +10 -10
  175. package/dist/offline-sync.js +2 -1
  176. package/dist/operator-doctor-corpus.js +13 -13
  177. package/dist/operator-toolkit.js +23 -21
  178. package/dist/orchestration/maintenance.js +16 -16
  179. package/dist/{orchestrator-CSc9GfQv.d.ts → orchestrator-Bay_AofR.d.ts} +2 -3
  180. package/dist/orchestrator.d.ts +2 -1
  181. package/dist/orchestrator.js +100 -97
  182. package/dist/{public-http-8PcrDIYi.d.ts → public-http-BtjiyKah.d.ts} +1 -1
  183. package/dist/recall-explain-renderer.d.ts +1 -0
  184. package/dist/recall-state.d.ts +6 -2
  185. package/dist/recall-state.js +6 -2
  186. package/dist/reconcile/cursor.js +7 -3
  187. package/dist/reconcile/cursor.js.map +1 -1
  188. package/dist/reconcile/manifest.js +3 -7
  189. package/dist/reconcile/plan.d.ts +15 -1
  190. package/dist/reconcile/plan.js +6 -10
  191. package/dist/resume-bundles.js +5 -3
  192. package/dist/search/factory.js +3 -3
  193. package/dist/search/index.js +3 -3
  194. package/dist/semantic-consolidation.js +16 -16
  195. package/dist/semantic-rule-promotion.js +10 -10
  196. package/dist/semantic-rule-verifier.js +10 -10
  197. package/dist/source-agent-qualifier.js +10 -10
  198. package/dist/storage.js +9 -9
  199. package/dist/support-passport/index.d.ts +6 -5
  200. package/dist/support-passport/index.js +34 -30
  201. package/dist/transfer/autodetect.js +1 -1
  202. package/dist/transfer/backup.js +2 -2
  203. package/dist/transfer/capsule-export.js +3 -3
  204. package/dist/transfer/capsule-import.js +2 -2
  205. package/dist/verified-recall.js +10 -10
  206. package/package.json +2 -2
  207. package/src/access-mcp-output-schemas.ts +1 -1
  208. package/src/access-recall-response.ts +4 -2
  209. package/src/access-recall-surface.ts +9 -9
  210. package/src/access-service-namespace.test.ts +9 -9
  211. package/src/access-service-raw-excerpt-read-gate.test.ts +1 -1
  212. package/src/calibration.ts +3 -1
  213. package/src/census-validation.ts +25 -0
  214. package/src/coding/architecture-surfaces.test.ts +9 -10
  215. package/src/coding/architecture-surfaces.ts +2 -35
  216. package/src/coding/codegraph-runtime-loader.test.ts +228 -0
  217. package/src/coding/codegraph-runtime.ts +30 -50
  218. package/src/coding/codegraph-surfaces.ts +2 -2
  219. package/src/coding/coding-knowledge-config.ts +35 -1
  220. package/src/coding/decision-surfaces.test.ts +9 -10
  221. package/src/coding/decision-surfaces.ts +2 -40
  222. package/src/coding/session-delta-surfaces.test.ts +9 -10
  223. package/src/coding/session-delta-surfaces.ts +2 -33
  224. package/src/extraction-judge.ts +3 -1
  225. package/src/extraction-output-language.test.ts +116 -0
  226. package/src/extraction-prompt.ts +70 -1
  227. package/src/extraction.ts +23 -95
  228. package/src/included-memories.ts +88 -0
  229. package/src/offline-sync.ts +4 -4
  230. package/src/orchestration/recall-internal-deps.ts +2 -4
  231. package/src/orchestration/recall-internal.ts +9 -13
  232. package/src/orchestration/recall-result-formatter-display-safe.test.ts +13 -16
  233. package/src/orchestration/recall-result-formatter.ts +32 -45
  234. package/src/orchestration/recall-section-coordinator.ts +20 -26
  235. package/src/orchestrator.ts +2 -4
  236. package/src/recall-explain-renderer.test.ts +4 -0
  237. package/src/recall-state.test.ts +108 -5
  238. package/src/recall-state.ts +85 -23
  239. package/src/recall-token-budget.test.ts +1 -1
  240. package/src/reconcile/census-parity.test.ts +152 -0
  241. package/src/reconcile/cursor.ts +5 -5
  242. package/src/reconcile/manifest.ts +4 -11
  243. package/src/reconcile/plan.ts +18 -15
  244. package/dist/chunk-EFKZT6AY.js.map +0 -1
  245. package/dist/chunk-IVXVLDNT.js.map +0 -1
  246. package/dist/chunk-L3CHRBHE.js.map +0 -1
  247. package/dist/chunk-OETHJBAL.js.map +0 -1
  248. package/dist/chunk-PRDJMOST.js.map +0 -1
  249. package/dist/chunk-R7TZ2HCS.js.map +0 -1
  250. package/dist/chunk-RYST72N5.js.map +0 -1
  251. package/dist/chunk-TWTUGCTY.js.map +0 -1
  252. package/dist/chunk-YXMHUBN2.js.map +0 -1
  253. package/dist/chunk-YYQAKIDJ.js.map +0 -1
  254. package/dist/chunk-Z4N7SVVF.js.map +0 -1
  255. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  256. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  257. /package/dist/{chunk-PB4WVYGC.js.map → chunk-3IMYRX3W.js.map} +0 -0
  258. /package/dist/{chunk-R6UMNP5C.js.map → chunk-3T6HIIKA.js.map} +0 -0
  259. /package/dist/{chunk-77QZW2D6.js.map → chunk-3TDAA7VA.js.map} +0 -0
  260. /package/dist/{chunk-DXDAQZ2K.js.map → chunk-42TIIO2M.js.map} +0 -0
  261. /package/dist/{chunk-Y7COCXY2.js.map → chunk-4F67JJPG.js.map} +0 -0
  262. /package/dist/{chunk-OW7NVMGQ.js.map → chunk-5OOTHWGJ.js.map} +0 -0
  263. /package/dist/{chunk-KYTRF64R.js.map → chunk-5SCFDQEJ.js.map} +0 -0
  264. /package/dist/{chunk-DYZR3Z6D.js.map → chunk-5TF5STAV.js.map} +0 -0
  265. /package/dist/{chunk-GG4DN63W.js.map → chunk-62Y5AGCM.js.map} +0 -0
  266. /package/dist/{chunk-PMVPCZJZ.js.map → chunk-6433HV72.js.map} +0 -0
  267. /package/dist/{chunk-KHCUVYCY.js.map → chunk-6UKSOXAO.js.map} +0 -0
  268. /package/dist/{chunk-GF7RQWXC.js.map → chunk-AJRJDXYR.js.map} +0 -0
  269. /package/dist/{chunk-YEQCMA5L.js.map → chunk-BOSIHHOH.js.map} +0 -0
  270. /package/dist/{chunk-7LF2OHIJ.js.map → chunk-BRHKW7GY.js.map} +0 -0
  271. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  272. /package/dist/{chunk-LX4TNSAE.js.map → chunk-CBY54QYW.js.map} +0 -0
  273. /package/dist/{chunk-CIAI24TQ.js.map → chunk-DGUVXXAU.js.map} +0 -0
  274. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  275. /package/dist/{chunk-QI5RDDEL.js.map → chunk-EDZNW3HE.js.map} +0 -0
  276. /package/dist/{chunk-6YMEU6OQ.js.map → chunk-G72IPMR7.js.map} +0 -0
  277. /package/dist/{chunk-7AF243WZ.js.map → chunk-GBVRVYF4.js.map} +0 -0
  278. /package/dist/{chunk-FPEZ74F7.js.map → chunk-I2HTKOOP.js.map} +0 -0
  279. /package/dist/{chunk-VPHSMJ2E.js.map → chunk-JPWSYHLB.js.map} +0 -0
  280. /package/dist/{chunk-X7LEDA74.js.map → chunk-KFB4YNXM.js.map} +0 -0
  281. /package/dist/{chunk-I5FLIB2J.js.map → chunk-KXWE62IH.js.map} +0 -0
  282. /package/dist/{chunk-TSTI6A3A.js.map → chunk-LTYH2L6E.js.map} +0 -0
  283. /package/dist/{chunk-ZUPKNWRZ.js.map → chunk-MIUL6AUZ.js.map} +0 -0
  284. /package/dist/{chunk-EJY3HJMT.js.map → chunk-MYI3RKI6.js.map} +0 -0
  285. /package/dist/{chunk-UCLMKNHA.js.map → chunk-N7V3P4V5.js.map} +0 -0
  286. /package/dist/{chunk-NA56NSKL.js.map → chunk-O52TB5SL.js.map} +0 -0
  287. /package/dist/{chunk-7KQB4EBS.js.map → chunk-OPPBTPUU.js.map} +0 -0
  288. /package/dist/{chunk-ERPBRXVZ.js.map → chunk-PHKU6BZ2.js.map} +0 -0
  289. /package/dist/{chunk-GTD4Q62X.js.map → chunk-PQHNZ63P.js.map} +0 -0
  290. /package/dist/{chunk-FHKXVTM5.js.map → chunk-Q5XKKDFQ.js.map} +0 -0
  291. /package/dist/{chunk-QRWMS6SI.js.map → chunk-Q6OL23WM.js.map} +0 -0
  292. /package/dist/{chunk-V3KIRICY.js.map → chunk-QQYHYW2N.js.map} +0 -0
  293. /package/dist/{chunk-YFCEBB5P.js.map → chunk-QTXNS3HB.js.map} +0 -0
  294. /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
  295. /package/dist/{chunk-E4KMY4KR.js.map → chunk-SNEUAZ6B.js.map} +0 -0
  296. /package/dist/{chunk-F6JYBVL6.js.map → chunk-SY5JUJ2X.js.map} +0 -0
  297. /package/dist/{chunk-PBRCYYO7.js.map → chunk-ULZFZL7K.js.map} +0 -0
  298. /package/dist/{chunk-IPLYGWQF.js.map → chunk-VDX2J7OX.js.map} +0 -0
  299. /package/dist/{chunk-UGHCZS6K.js.map → chunk-VFZQXYN5.js.map} +0 -0
  300. /package/dist/{chunk-NKB43PGI.js.map → chunk-VYMICVRA.js.map} +0 -0
  301. /package/dist/{chunk-2UM6WHME.js.map → chunk-XE2QCCT2.js.map} +0 -0
  302. /package/dist/{chunk-SYVGVK4S.js.map → chunk-XTMYB2HY.js.map} +0 -0
  303. /package/dist/{chunk-AYVCKGA6.js.map → chunk-YTXNDEUS.js.map} +0 -0
  304. /package/dist/{chunk-3Z5TGRFA.js.map → chunk-ZOAAY2OE.js.map} +0 -0
@@ -12,6 +12,22 @@ import type {
12
12
  RecallPlanMode,
13
13
  RecallTierExplain,
14
14
  } from "./types.js";
15
+ import {
16
+ coerceIncludedMemories,
17
+ type IncludedMemory,
18
+ } from "./included-memories.js";
19
+
20
+ export type { IncludedMemory } from "./included-memories.js";
21
+ export { coerceIncludedMemories } from "./included-memories.js";
22
+
23
+ // Session keys are caller-supplied (host session IDs) and land in indexed
24
+ // assignments on plain-object state. A key matching one of these would
25
+ // pollute Object.prototype (or read junk off it), so every read/write
26
+ // through this module rejects them — same contract load() already enforced.
27
+ function isUnsafeStateKey(key: string): boolean {
28
+ return key === "__proto__" || key === "constructor" || key === "prototype";
29
+ }
30
+
15
31
 
16
32
  export interface LastRecallBudgetSummary {
17
33
  requestedTopK?: number;
@@ -36,6 +52,7 @@ export interface LastRecallSnapshot {
36
52
  queryHash: string;
37
53
  queryLen: number;
38
54
  memoryIds: string[];
55
+ includedMemories?: IncludedMemory[];
39
56
  namespace?: string;
40
57
  recallNamespaces?: string[];
41
58
  traceId?: string;
@@ -172,6 +189,13 @@ type StateFileWriter = (filePath: string, content: string) => Promise<void>;
172
189
  * recordedAt are compared. Extracted so every annotation surface applies
173
190
  * identical guards (CLAUDE.md rule 22).
174
191
  */
192
+ function cloneTierExplain(
193
+ tierExplain: RecallTierExplain | undefined,
194
+ ): RecallTierExplain | undefined {
195
+ if (!tierExplain) return undefined;
196
+ return structuredClone(tierExplain);
197
+ }
198
+
175
199
  function snapshotMatchesExpectedIdentity(
176
200
  current: LastRecallSnapshot,
177
201
  expected?: { writeNonce?: string; traceId?: string; recordedAt?: string },
@@ -182,34 +206,42 @@ function snapshotMatchesExpectedIdentity(
182
206
  }
183
207
  const hasExpectedTraceId =
184
208
  typeof expected.traceId === "string" && expected.traceId.length > 0;
185
- if (hasExpectedTraceId) {
186
- return current.traceId === expected.traceId;
187
- }
188
- if (expected.recordedAt !== undefined) {
209
+ if (hasExpectedTraceId && current.traceId !== expected.traceId) return false;
210
+ if (typeof expected.recordedAt === "string" && expected.recordedAt.length > 0) {
189
211
  return current.recordedAt === expected.recordedAt;
190
212
  }
191
213
  return true;
192
214
  }
193
215
 
194
- function cloneTierExplain(
195
- tierExplain: RecallTierExplain | undefined,
196
- ): RecallTierExplain | undefined {
197
- if (!tierExplain) return undefined;
198
- return structuredClone(tierExplain);
216
+ function hydrateLastRecallSnapshot(snapshot: LastRecallSnapshot): LastRecallSnapshot {
217
+ const includedMemories = coerceIncludedMemories(snapshot);
218
+ const budgets = snapshot.budgetsApplied
219
+ ? {
220
+ ...snapshot.budgetsApplied,
221
+ includedMemoryIds: includedMemories.map((memory) => memory.id),
222
+ includedMemoryPaths: includedMemories.map((memory) => memory.path),
223
+ includedMemoryNamespaces: includedMemories.map((memory) => memory.namespace),
224
+ }
225
+ : undefined;
226
+ return {
227
+ ...snapshot,
228
+ includedMemories,
229
+ memoryIds: includedMemories.map((memory) => memory.id),
230
+ resultPaths: includedMemories.map((memory) => memory.path),
231
+ resultNamespaces: includedMemories.map((memory) => memory.namespace),
232
+ ...(budgets ? { budgetsApplied: budgets } : {}),
233
+ };
199
234
  }
200
235
 
201
- /**
202
- * Deep-copy a LastRecallSnapshot so callers that receive it cannot
203
- * mutate the store's internal state through mutable array/object
204
- * fields. Same structuredClone rationale as cloneTierExplain above.
205
- */
206
236
  function cloneLastRecallSnapshot(
207
237
  snapshot: LastRecallSnapshot | null,
208
238
  ): LastRecallSnapshot | null {
209
239
  if (!snapshot) return null;
210
- return structuredClone(snapshot);
240
+ return structuredClone(hydrateLastRecallSnapshot(snapshot));
211
241
  }
212
242
 
243
+
244
+
213
245
  export interface TierMigrationCycleSummary {
214
246
  trigger: "extraction" | "maintenance" | "manual";
215
247
  scanned: number;
@@ -319,8 +351,22 @@ export class LastRecallStore {
319
351
  async load(): Promise<void> {
320
352
  try {
321
353
  const raw = await readFile(this.statePath, "utf-8");
322
- const parsed = JSON.parse(raw) as LastRecallState;
323
- if (parsed && typeof parsed === "object") this.state = parsed;
354
+ const parsed: unknown = JSON.parse(raw);
355
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
356
+ this.state = {};
357
+ return;
358
+ }
359
+ const next: LastRecallState = {};
360
+ for (const [sessionKey, snapshot] of Object.entries(parsed)) {
361
+ if (sessionKey === "__proto__" || sessionKey === "constructor" || sessionKey === "prototype") {
362
+ continue;
363
+ }
364
+ if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) {
365
+ continue;
366
+ }
367
+ next[sessionKey] = hydrateLastRecallSnapshot(snapshot as LastRecallSnapshot);
368
+ }
369
+ this.state = next;
324
370
  } catch {
325
371
  this.state = {};
326
372
  }
@@ -329,6 +375,7 @@ export class LastRecallStore {
329
375
  get(sessionKey: string): LastRecallSnapshot | null {
330
376
  // Defensive copy: callers must not be able to mutate internal state
331
377
  // by reaching into array/object fields on the returned snapshot.
378
+ if (isUnsafeStateKey(sessionKey)) return null;
332
379
  return cloneLastRecallSnapshot(this.state[sessionKey] ?? null);
333
380
  }
334
381
 
@@ -352,7 +399,8 @@ export class LastRecallStore {
352
399
  async record(opts: {
353
400
  sessionKey: string;
354
401
  query: string;
355
- memoryIds: string[];
402
+ memoryIds?: string[];
403
+ includedMemories?: IncludedMemory[];
356
404
  namespace?: string;
357
405
  recallNamespaces?: string[];
358
406
  traceId?: string;
@@ -386,6 +434,10 @@ export class LastRecallStore {
386
434
  */
387
435
  backendDegradations?: SearchDegradation[];
388
436
  }): Promise<void> {
437
+ if (isUnsafeStateKey(opts.sessionKey)) {
438
+ log.debug("last recall record skipped: unsafe session key");
439
+ return;
440
+ }
389
441
  const now = new Date().toISOString();
390
442
  const queryHash = createHash("sha256").update(opts.query).digest("hex");
391
443
 
@@ -393,13 +445,15 @@ export class LastRecallStore {
393
445
  // cloneLastRecallSnapshot so caller arrays/objects passed in
394
446
  // `opts` cannot retain a live reference to the persisted state and
395
447
  // tear it after `record()` returns.
448
+ const includedMemories = coerceIncludedMemories(opts);
396
449
  const liveSnapshot: LastRecallSnapshot = {
397
450
  sessionKey: opts.sessionKey,
398
451
  recordedAt: now,
399
452
  queryHash,
400
453
  writeNonce: randomUUID(),
401
454
  queryLen: opts.query.length,
402
- memoryIds: opts.memoryIds,
455
+ includedMemories,
456
+ memoryIds: includedMemories.map((memory) => memory.id),
403
457
  namespace: opts.namespace,
404
458
  recallNamespaces: opts.recallNamespaces,
405
459
  traceId: opts.traceId,
@@ -410,8 +464,6 @@ export class LastRecallStore {
410
464
  sourcesUsed: opts.sourcesUsed,
411
465
  budgetsApplied: opts.budgetsApplied,
412
466
  latencyMs: opts.latencyMs,
413
- resultPaths: opts.resultPaths,
414
- resultNamespaces: opts.resultNamespaces,
415
467
  policyVersion: opts.policyVersion,
416
468
  identityInjectionMode: opts.identityInjection?.mode,
417
469
  identityInjectedChars: opts.identityInjection?.injectedChars,
@@ -810,6 +862,7 @@ export class LastRecallStore {
810
862
  tierExplain: RecallTierExplain,
811
863
  expected?: { writeNonce?: string; traceId?: string; recordedAt?: string },
812
864
  ): Promise<void> {
865
+ if (isUnsafeStateKey(sessionKey)) return;
813
866
  const current = this.state[sessionKey];
814
867
  if (!current) return;
815
868
  if (!snapshotMatchesExpectedIdentity(current, expected)) return;
@@ -952,7 +1005,15 @@ export class RecallHandleHistoryStore {
952
1005
  try {
953
1006
  const raw = await readFile(this.statePath, "utf-8");
954
1007
  const parsed = JSON.parse(raw);
955
- if (parsed && typeof parsed === "object") this.state = parsed as typeof this.state;
1008
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1009
+ const next: Record<string, Array<{ at: string; ids: string[] }>> = {};
1010
+ for (const [sessionKey, entries] of Object.entries(parsed)) {
1011
+ if (isUnsafeStateKey(sessionKey)) continue;
1012
+ if (!Array.isArray(entries)) continue;
1013
+ next[sessionKey] = entries;
1014
+ }
1015
+ this.state = next;
1016
+ }
956
1017
  } catch {
957
1018
  this.state = {};
958
1019
  }
@@ -963,7 +1024,7 @@ export class RecallHandleHistoryStore {
963
1024
  * The ring is capped at {@link maxDepth}; older entries drop off the tail.
964
1025
  */
965
1026
  async record(sessionKey: string, memoryIds: readonly string[]): Promise<void> {
966
- if (!sessionKey) return;
1027
+ if (!sessionKey || isUnsafeStateKey(sessionKey)) return;
967
1028
  const ids = memoryIds.filter((id): id is string => typeof id === "string" && id.length > 0);
968
1029
  const entry = { at: new Date().toISOString(), ids };
969
1030
  const prior = this.state[sessionKey] ?? [];
@@ -982,6 +1043,7 @@ export class RecallHandleHistoryStore {
982
1043
  * Empty array when the session has no recorded history.
983
1044
  */
984
1045
  recent(sessionKey: string, depth: number = this.maxDepth): Array<readonly string[]> {
1046
+ if (isUnsafeStateKey(sessionKey)) return [];
985
1047
  const entries = this.state[sessionKey];
986
1048
  if (!entries || entries.length === 0) return [];
987
1049
  const limit = Math.max(0, Math.min(depth, entries.length));
@@ -46,6 +46,6 @@ test("recall reserves one memory chunk that fits both character and token budget
46
46
 
47
47
  const assembled = coordinator.assembleRecallSections(buckets);
48
48
 
49
- assert.deepEqual(assembled.includedMemoryIds, ["latin"]);
49
+ assert.deepEqual(assembled.includedMemories, [{ id: "latin", path: "memories/latin.md" }]);
50
50
  assert.ok(estimateTokenCount(assembled.sections.join("\n\n---\n\n")) <= 50);
51
51
  });
@@ -0,0 +1,152 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ OFFLINE_SYNC_MAX_MTIME_MS,
6
+ OFFLINE_SYNC_SNAPSHOT_FORMAT,
7
+ normalizeOfflineSyncSnapshot,
8
+ } from "../offline-sync.js";
9
+ import {
10
+ type ReconcilePlanEntry,
11
+ ReconcilePlanInputError,
12
+ compareReconcilePlanEntries,
13
+ planNamespaceReconciliation,
14
+ planReconciliation,
15
+ semanticAgreementKey,
16
+ } from "./plan.js";
17
+
18
+ /**
19
+ * Issue #2477: offline-sync and the reconcile planner validate the same peer
20
+ * census fields, and cursor/manifest order and key plan entries the same way.
21
+ * These tests fail the moment one surface drifts from the other, which was
22
+ * previously a silent convergence bug.
23
+ */
24
+
25
+ const PATH = "facts/2026-03-01/a.md";
26
+ const GOOD_SHA = "a".repeat(64);
27
+
28
+ type CensusOutcome = { accepted: boolean; digest?: string };
29
+
30
+ /** Validate one census file record through the offline-sync snapshot surface. */
31
+ function offlineSyncOutcome(overrides: Record<string, unknown>): CensusOutcome {
32
+ try {
33
+ const snapshot = normalizeOfflineSyncSnapshot({
34
+ format: OFFLINE_SYNC_SNAPSHOT_FORMAT,
35
+ schemaVersion: 1,
36
+ createdAt: "2026-08-17T00:00:00.000Z",
37
+ sourceId: "peer",
38
+ includeTranscripts: false,
39
+ files: [{ path: PATH, bytes: 1, mtimeMs: 0, sha256: GOOD_SHA, ...overrides }],
40
+ });
41
+ return { accepted: true, digest: snapshot.files[0]?.sha256 };
42
+ } catch {
43
+ return { accepted: false };
44
+ }
45
+ }
46
+
47
+ /** Validate the same record through the reconcile planner's census surface. */
48
+ function reconcileOutcome(overrides: Record<string, unknown>): CensusOutcome {
49
+ try {
50
+ const entries = planNamespaceReconciliation({
51
+ namespace: "default",
52
+ local: [{ path: PATH, sha256: GOOD_SHA, mtimeMs: 0, ...overrides }],
53
+ peer: [],
54
+ });
55
+ return { accepted: true, digest: entries.find((e) => e.path === PATH)?.localSha256 };
56
+ } catch (err) {
57
+ assert.ok(err instanceof ReconcilePlanInputError, "plan census rejects must stay ReconcilePlanInputError");
58
+ return { accepted: false };
59
+ }
60
+ }
61
+
62
+ const SHA256_FIXTURES: unknown[] = [
63
+ "b".repeat(64), // accepted, already canonical
64
+ "B".repeat(64), // accepted, canonicalized to lowercase
65
+ "b".repeat(63), // too short
66
+ "b".repeat(65), // too long
67
+ "z".repeat(64), // not hex
68
+ "",
69
+ 42,
70
+ null,
71
+ { length: 64 },
72
+ ];
73
+
74
+ const MTIME_FIXTURES: unknown[] = [
75
+ 0,
76
+ 1.25, // fractional mtimes are valid
77
+ OFFLINE_SYNC_MAX_MTIME_MS,
78
+ OFFLINE_SYNC_MAX_MTIME_MS + 1,
79
+ -1,
80
+ Number.NaN,
81
+ Number.POSITIVE_INFINITY,
82
+ "100",
83
+ null,
84
+ ];
85
+
86
+ test("sha256 census fixtures accept and canonicalize identically on both surfaces", () => {
87
+ const offline = SHA256_FIXTURES.map((sha256) => offlineSyncOutcome({ sha256 }));
88
+ const reconcile = SHA256_FIXTURES.map((sha256) => reconcileOutcome({ sha256 }));
89
+ assert.deepEqual(reconcile, offline);
90
+ assert.deepEqual(
91
+ offline.map((o) => o.accepted),
92
+ [true, true, false, false, false, false, false, false, false]
93
+ );
94
+ assert.equal(offline[1].digest, "b".repeat(64));
95
+ });
96
+
97
+ test("mtimeMs census fixtures accept and reject identically on both surfaces", () => {
98
+ const offline = MTIME_FIXTURES.map((mtimeMs) => offlineSyncOutcome({ mtimeMs }));
99
+ const reconcile = MTIME_FIXTURES.map((mtimeMs) => reconcileOutcome({ mtimeMs }));
100
+ assert.deepEqual(reconcile, offline);
101
+ assert.deepEqual(
102
+ offline.map((o) => o.accepted),
103
+ [true, true, true, false, false, false, false, false, false]
104
+ );
105
+ });
106
+
107
+ test("compareReconcilePlanEntries is the total order plan output itself uses", () => {
108
+ const entry = (namespace: string, path: string): ReconcilePlanEntry => ({
109
+ path,
110
+ namespace,
111
+ action: "identical",
112
+ reason: "same_content",
113
+ });
114
+ const a = entry("alpha", "facts/a.md");
115
+ const b = entry("beta", "facts/a.md");
116
+ const c = entry("beta", "facts/b.md");
117
+ const sorted = [c, { ...a }, b, a].sort(compareReconcilePlanEntries);
118
+ assert.deepEqual(
119
+ sorted.map((e) => [e.namespace, e.path]),
120
+ [
121
+ ["alpha", "facts/a.md"],
122
+ ["alpha", "facts/a.md"],
123
+ ["beta", "facts/a.md"],
124
+ ["beta", "facts/b.md"],
125
+ ]
126
+ );
127
+ assert.equal(compareReconcilePlanEntries(a, { ...a }), 0);
128
+
129
+ const plan = planReconciliation([
130
+ { namespace: "beta", local: [], peer: [] },
131
+ { namespace: "alpha", local: [{ path: "facts/z.md", sha256: GOOD_SHA }], peer: [] },
132
+ ]);
133
+ assert.ok(plan.entries.length > 0);
134
+ for (let i = 1; i < plan.entries.length; i += 1) {
135
+ assert.ok(compareReconcilePlanEntries(plan.entries[i - 1], plan.entries[i]) <= 0);
136
+ }
137
+ });
138
+
139
+ test("semanticAgreementKey pins the ordered path-pair identity shared by cursor and manifest", () => {
140
+ const localFirst = semanticAgreementKey({
141
+ local: { path: "facts/local.md", sha256: GOOD_SHA },
142
+ peer: { path: "facts/peer.md", sha256: GOOD_SHA },
143
+ });
144
+ assert.equal(localFirst, "facts/local.md\0facts/peer.md");
145
+ assert.notEqual(
146
+ localFirst,
147
+ semanticAgreementKey({
148
+ local: { path: "facts/peer.md", sha256: GOOD_SHA },
149
+ peer: { path: "facts/local.md", sha256: GOOD_SHA },
150
+ })
151
+ );
152
+ });
@@ -1,7 +1,11 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import * as fs from "node:fs/promises";
3
3
  import * as path from "node:path";
4
- import type { ReconcilePlanEntry, ReconcileSemanticAgreement } from "./plan.js";
4
+ import {
5
+ type ReconcilePlanEntry,
6
+ type ReconcileSemanticAgreement,
7
+ semanticAgreementKey,
8
+ } from "./plan.js";
5
9
 
6
10
  export type ConvergeRefreshTarget = "local" | "receiver";
7
11
 
@@ -76,10 +80,6 @@ function digestAfterReconcile(entry: ReconcilePlanEntry): string | undefined {
76
80
  return entry.localSha256 ?? entry.peerSha256;
77
81
  }
78
82
 
79
- function semanticAgreementKey(agreement: ReconcileSemanticAgreement): string {
80
- return `${agreement.local.path}\0${agreement.peer.path}`;
81
- }
82
-
83
83
  export function deriveConvergeCursorBase(
84
84
  entries: readonly ReconcilePlanEntry[],
85
85
  namespace: string,
@@ -12,6 +12,8 @@ import {
12
12
  type ReconcilePlanEntry,
13
13
  type ReconcileSemanticAgreement,
14
14
  type ReconcileSemanticChange,
15
+ compareReconcilePlanEntries,
16
+ semanticAgreementKey,
15
17
  summarizeReconcilePlan,
16
18
  } from "./plan.js";
17
19
 
@@ -218,15 +220,6 @@ function contentHashRows(
218
220
  return rows;
219
221
  }
220
222
 
221
- function comparePlanEntries(left: ReconcilePlanEntry, right: ReconcilePlanEntry): number {
222
- if (left.namespace !== right.namespace) return left.namespace < right.namespace ? -1 : 1;
223
- return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;
224
- }
225
-
226
- function semanticAgreementKey(agreement: ReconcileSemanticAgreement): string {
227
- return `${agreement.local.path}\0${agreement.peer.path}`;
228
- }
229
-
230
223
  function classifySemanticChange(
231
224
  current: ReconcileSemanticAgreement,
232
225
  prior: ReconcileSemanticAgreement | undefined
@@ -396,13 +389,13 @@ export function collapseActiveFactDuplicates(
396
389
  if (removed.size > 0 || replacements.length > 0) {
397
390
  entriesByNamespace.set(
398
391
  namespace,
399
- [...entries.filter((entry) => !removed.has(entry)), ...replacements].sort(comparePlanEntries)
392
+ [...entries.filter((entry) => !removed.has(entry)), ...replacements].sort(compareReconcilePlanEntries)
400
393
  );
401
394
  }
402
395
  }
403
396
 
404
397
  if (!changed) return plan;
405
- const entries = [...entriesByNamespace.values()].flat().sort(comparePlanEntries);
398
+ const entries = [...entriesByNamespace.values()].flat().sort(compareReconcilePlanEntries);
406
399
  return {
407
400
  entries,
408
401
  byNamespace: summarizeReconcilePlan(entries),
@@ -1,5 +1,5 @@
1
+ import { CENSUS_MAX_MTIME_MS, isCensusMtimeMs, isSha256Hex } from "../census-validation.js";
1
2
  import { normalizeNamespaceIdentity } from "../namespaces/identity.js";
2
- import { OFFLINE_SYNC_MAX_MTIME_MS } from "../offline-sync.js";
3
3
  import { validateArchiveRelativePath } from "../transfer/fs-utils.js";
4
4
  import type { OfflineSyncFileState } from "../offline-sync.js";
5
5
  import {
@@ -197,8 +197,7 @@ export class ReconcilePlanInputError extends Error {
197
197
  }
198
198
  }
199
199
 
200
- /** Matches `assertSha256` in offline-sync so both surfaces reject the same values (§40). */
201
- const SHA256_PATTERN = /^[a-f0-9]{64}$/i;
200
+ /** Shared with offline-sync's census validation (issue #2477): one acceptance set. */
202
201
 
203
202
  /**
204
203
  * Validate a census record's identity fields.
@@ -247,14 +246,9 @@ function assertCensusRecord(
247
246
  * deliberately does not require an integer.
248
247
  */
249
248
  function assertMtimeMs(value: unknown, context: string): number {
250
- if (
251
- typeof value !== "number"
252
- || !Number.isFinite(value)
253
- || value < 0
254
- || value > OFFLINE_SYNC_MAX_MTIME_MS
255
- ) {
249
+ if (!isCensusMtimeMs(value)) {
256
250
  throw new ReconcilePlanInputError(
257
- `reconcile: ${context} has an out-of-range mtimeMs; expected a finite value between 0 and ${OFFLINE_SYNC_MAX_MTIME_MS}`,
251
+ `reconcile: ${context} has an out-of-range mtimeMs; expected a finite value between 0 and ${CENSUS_MAX_MTIME_MS}`,
258
252
  );
259
253
  }
260
254
  return value;
@@ -267,7 +261,7 @@ function assertMtimeMs(value: unknown, context: string): number {
267
261
  * and tombstone lookups would silently miss.
268
262
  */
269
263
  function assertDigest(value: unknown, context: string): string {
270
- if (typeof value !== "string" || !SHA256_PATTERN.test(value)) {
264
+ if (!isSha256Hex(value)) {
271
265
  throw new ReconcilePlanInputError(
272
266
  `reconcile: ${context} must carry a 64-character sha256 hex digest`,
273
267
  );
@@ -503,14 +497,23 @@ function assertConflictPolicy(value: ConvergeConflictPolicy | undefined): Conver
503
497
  * Total ordering for plan entries (§12): namespace, then path. Both are unique
504
498
  * per entry, so equal keys are impossible and the comparator never has to
505
499
  * return 0 for distinct rows — the output is byte-identical across runs, which
506
- * is what makes a convergence report diffable.
500
+ * is what makes a convergence report diffable. Cursor and manifest sort with
501
+ * this same export; a local copy on either side is how ordering drifts (§2477).
507
502
  */
508
- function compareEntries(a: ReconcilePlanEntry, b: ReconcilePlanEntry): number {
503
+ export function compareReconcilePlanEntries(a: ReconcilePlanEntry, b: ReconcilePlanEntry): number {
509
504
  if (a.namespace !== b.namespace) return a.namespace < b.namespace ? -1 : 1;
510
505
  if (a.path !== b.path) return a.path < b.path ? -1 : 1;
511
506
  return 0;
512
507
  }
513
508
 
509
+ /**
510
+ * Identity of a semantic-duplicate pair: the ordered (local, peer) path pair.
511
+ * Cursor derivation and manifest collapse must key prior agreements with this
512
+ * same export or a stored cursor stops matching the plan that wrote it.
513
+ */
514
+ export function semanticAgreementKey(agreement: ReconcileSemanticAgreement): string {
515
+ return `${agreement.local.path}\0${agreement.peer.path}`;
516
+ }
514
517
 
515
518
  function resolveConflict(
516
519
  policy: ConvergeConflictPolicy,
@@ -795,7 +798,7 @@ export function planNamespaceReconciliation(
795
798
  });
796
799
  }
797
800
 
798
- return entries.sort(compareEntries);
801
+ return entries.sort(compareReconcilePlanEntries);
799
802
  }
800
803
 
801
804
  /** Aggregate entries into the per-namespace convergence report (#2150). */
@@ -852,7 +855,7 @@ export function planReconciliation(
852
855
  seenNamespaces.add(name);
853
856
  entries.push(...planNamespaceReconciliation(namespace, options));
854
857
  }
855
- entries.sort(compareEntries);
858
+ entries.sort(compareReconcilePlanEntries);
856
859
  return {
857
860
  entries,
858
861
  byNamespace: summarizeReconcilePlan(entries),
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/reconcile/manifest.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { computeLegacyContentHash, normalizeLegacyContent } from \"../content-hash.js\";\nimport { inferMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { ContentHashIndex, type ContentHashPathEntry } from \"../storage/content-hash-index.js\";\nimport { DEFAULT_CITATION_FORMAT, stripCitationForTemplate } from \"../source-attribution.js\";\nimport { storedContentIdentityCandidates } from \"../structured-attributes.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;\nconst CONTENT_HASH_NORMALIZER_VERSION = 4;\n/**\n * Version of the identity-resolution LOGIC (alias recovery, candidate\n * ordering), independent of the content normalizer: a cached manifest entry\n * written before an identity-resolution change carries an older value and is\n * reparsed even when its normalizerVersion still matches (issue #2367\n * review round 2). Bump when parsedMemoryIdentity's output shape or\n * semantics change.\n */\nconst IDENTITY_RESOLUTION_VERSION = 2;\n\nexport interface ReconcileMemoryIdentity {\n id: string;\n category: string;\n contentHash: string;\n /**\n * Recovered current-normalizer identities for a record whose persisted hash\n * is ambiguous under the legacy normalizer (issue #2367). The persisted\n * hash stays primary; these participate in duplicate bucketing so a\n * replica carrying the current form of the same fact still collapses.\n */\n contentHashAliases?: readonly string[];\n /** See IDENTITY_RESOLUTION_VERSION; absent on pre-versioning cache entries. */\n normalizerVersion?: number;\n identityResolutionVersion?: number;\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 type ReconcileMemoryParser = (\n raw: string,\n) => { frontmatter: MemoryFrontmatter; content: string } | null;\n\nexport interface BuildReconcileManifestOptions {\n files: Iterable<ReconcileFileState>;\n readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>;\n parseMemory: ReconcileMemoryParser;\n cachedFiles?: Iterable<ReconcileManifestFile>;\n citationTemplate?: string;\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\n\nfunction parsedMemoryIdentity(\n filePath: string,\n raw: Buffer | string,\n parseMemory: ReconcileMemoryParser,\n citationTemplate: string,\n): ReconcileMemoryIdentity | undefined {\n if (!isMemoryPath(filePath)) return undefined;\n const parsed = parseMemory(Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : raw);\n if (!parsed?.frontmatter.id) return undefined;\n\n const storedHash =\n parsed.frontmatter.contentHash &&\n SHA256_PATTERN.test(parsed.frontmatter.contentHash)\n ? parsed.frontmatter.contentHash.toLowerCase()\n : undefined;\n const candidates = storedContentIdentityCandidates(parsed.content, (content) =>\n stripCitationForTemplate(content, citationTemplate)\n );\n const bodyHash = ContentHashIndex.computeHash(candidates[0] ?? \"\");\n const currentMatch = candidates.find(\n (content) => ContentHashIndex.computeHash(content) === storedHash\n );\n const legacyMatch = [...candidates].reverse().find(\n (content) => computeLegacyContentHash(content) === storedHash\n );\n let contentHash: string;\n let contentHashAliases: string[] | undefined;\n if (currentMatch) {\n contentHash = ContentHashIndex.computeHash(currentMatch);\n } else if (legacyMatch && normalizeLegacyContent(legacyMatch).length > 0) {\n // A non-empty legacy equality is ambiguous (issue #2367): the persisted\n // hash may be an explicit contentHashSource identity that merely collides\n // with the body's ASCII skeleton under the lossy legacy normalizer, and\n // nothing in the record proves which it is. Keep the persisted hash as\n // the primary identity and expose the recovered current identity as an\n // alias so replicas carrying either form still collapse.\n contentHash = storedHash ?? bodyHash;\n const recovered = ContentHashIndex.computeHash(legacyMatch);\n if (recovered !== contentHash) contentHashAliases = [recovered];\n } else {\n // An EMPTY legacy skeleton identifies nothing (every non-ASCII body maps\n // to it), so preserving it would collapse unrelated records. Recovering\n // the current identity here is repair, not replacement.\n contentHash = legacyMatch ? ContentHashIndex.computeHash(legacyMatch) : storedHash ?? bodyHash;\n }\n\n return {\n id: parsed.frontmatter.id,\n category: parsed.frontmatter.category,\n contentHash,\n ...(contentHashAliases ? { contentHashAliases } : {}),\n normalizerVersion: CONTENT_HASH_NORMALIZER_VERSION,\n identityResolutionVersion: IDENTITY_RESOLUTION_VERSION,\n status: inferMemoryStatus(parsed.frontmatter, filePath),\n };\n}\n\nexport async function buildReconcileManifestFile(\n file: ReconcileFileState,\n readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>,\n parseMemory: ReconcileMemoryParser,\n citationTemplate = DEFAULT_CITATION_FORMAT,\n): Promise<ReconcileManifestFile> {\n let raw: Buffer | string | null = null;\n if (isMemoryPath(file.path)) {\n try {\n raw = await 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, parseMemory, citationTemplate);\n return { ...file, ...(memory ? { memory } : {}) };\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 (\n cached?.sha256.toLowerCase() === file.sha256.toLowerCase() &&\n (cached.memory === undefined ||\n (cached.memory.normalizerVersion === CONTENT_HASH_NORMALIZER_VERSION &&\n cached.memory.identityResolutionVersion === IDENTITY_RESOLUTION_VERSION))\n ) {\n files.push({ ...file, ...(cached.memory ? { memory: cached.memory } : {}) });\n continue;\n }\n\n files.push(await buildReconcileManifestFile(\n file,\n options.readFile,\n options.parseMemory,\n options.citationTemplate,\n ));\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 memoryIdentityHashes(memory: ReconcileMemoryIdentity): string[] {\n return [memory.contentHash, ...(memory.contentHashAliases ?? [])];\n}\n\nfunction contentHashRows(\n files: Iterable<ActiveFactManifestFile>,\n contentHash: string,\n): ContentHashPathEntry[] {\n const rows: ContentHashPathEntry[] = [];\n for (const file of files) {\n rows.push({ path: file.path, 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 for (const hash of memoryIdentityHashes(file.memory)) {\n const bucket = localByHash.get(hash) ?? [];\n bucket.push(file);\n localByHash.set(hash, bucket);\n }\n }\n for (const file of peerByPath.values()) {\n for (const hash of memoryIdentityHashes(file.memory)) {\n const bucket = peerByHash.get(hash) ?? [];\n bucket.push(file);\n peerByHash.set(hash, bucket);\n }\n }\n\n const removed = new Set<ReconcilePlanEntry>();\n const replacements: ReconcilePlanEntry[] = [];\n const processedPathPairs = new Set<string>();\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 || (\n activeOpposite !== undefined &&\n memoryIdentityHashes(activeOpposite.memory).includes(hash)\n );\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 || (\n activeOpposite !== undefined &&\n memoryIdentityHashes(activeOpposite.memory).includes(hash)\n );\n });\n const localPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(localCandidates, hash));\n const peerPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(peerCandidates, hash));\n\n if (localPath && peerPath && localPath !== peerPath) {\n const pathPair = `${localPath}\\0${peerPath}`;\n if (processedPathPairs.has(pathPair)) continue;\n processedPathPairs.add(pathPair);\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"]}