chainlesschain 0.166.117 → 0.166.118

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 (192) hide show
  1. package/README.md +26 -4
  2. package/package.json +3 -3
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/.build-hash +1 -1
  6. package/src/assets/web-panel/assets/{AIOps-C9tSCImB.js → AIOps-BGySwMIP.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-CXKExmT_.js → ActionButton-Chn7fBLr.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-DE8WBWHo.js → Analytics-ORH7UkGa.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-BdpwNM08.js → AppLayout-8xV4jWjP.js} +4 -4
  10. package/src/assets/web-panel/assets/{Artifacts-94TQpe38.js → Artifacts-26SBK-x-.js} +1 -1
  11. package/src/assets/web-panel/assets/{Audit-DdDEv5Ej.js → Audit-CtXpqbXg.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-TU9nlV7j.js → BackgroundAgents-C5zLvQis.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-C0GPoUUq.js → Backup-C93xY4vO.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-iyrVn2I6.js → BaseInput-DpVCHfAn.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-Dqo8spwp.js → Chat-DM0LblR2.js} +5 -5
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CDqHSzc4.js → ChatBubbleRenderer-unlQUF1T.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-BF_XJvQi.js → Checkbox-BsAt3cKR.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-5tUWoOa9.js → Codegen-E_kp4KFd.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-BQxSeRvG.js → Col-6msR3T6I.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-B2Ra7w-J.js → Community-PyX9c5D-.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-GjxJwlr0.js → Compact-7G1bVDSH.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-BTUP6RTA.js → Compliance-DcHN7GlD.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-DiwfL16s.js → Cowork-WUIHJYDx.js} +2 -2
  24. package/src/assets/web-panel/assets/{Cron-1ceOo5ux.js → Cron-CWgCbptg.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-aHYxLu0u.js → Crosschain-BzKZ6roD.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-eeTjzOLV.js → DID-r7zxeItn.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-CT3fpkvX.js → Dashboard-D3pBiN2H.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-B3UpOy-N.js → Dropdown-C4otRJlZ.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-Ba2Rvoru.js → EmailListRenderer-CzDTC8lm.js} +1 -1
  30. package/src/assets/web-panel/assets/{EvolutionSettings-CGtn93on.js → EvolutionSettings-DGkXiIs-.js} +1 -1
  31. package/src/assets/web-panel/assets/{FamilyGuardDashboard-C0IUdHQt.js → FamilyGuardDashboard-BKdEyuiR.js} +1 -1
  32. package/src/assets/web-panel/assets/{Federation-1QIDwemn.js → Federation-dsI-xcpf.js} +1 -1
  33. package/src/assets/web-panel/assets/{FormItemContext-NGbSsdje.js → FormItemContext-CEEb1fMR.js} +1 -1
  34. package/src/assets/web-panel/assets/{GenericCardRenderer-DzVZc2Ba.js → GenericCardRenderer-D_mfO3Ts.js} +1 -1
  35. package/src/assets/web-panel/assets/{Git-B_1TDbSr.js → Git-CBwr2ZI3.js} +2 -2
  36. package/src/assets/web-panel/assets/{Governance-BDl_ySyI.js → Governance-D-Wy2Jjr.js} +1 -1
  37. package/src/assets/web-panel/assets/{Inference-CAp-wcCK.js → Inference-B4Yk_IRx.js} +1 -1
  38. package/src/assets/web-panel/assets/{KnowledgeGraph-DRjRcxul.js → KnowledgeGraph-DoI7bi6m.js} +1 -1
  39. package/src/assets/web-panel/assets/{Logs-qSuwMwk7.js → Logs-Ce1IiKAj.js} +2 -2
  40. package/src/assets/web-panel/assets/MarkdownRenderer-GND_8y0V.js +1 -0
  41. package/src/assets/web-panel/assets/{Marketplace-DfiXL6UO.js → Marketplace-CsIEByzK.js} +1 -1
  42. package/src/assets/web-panel/assets/{McpTools-D9rIvFjN.js → McpTools-_DRzjcIn.js} +2 -2
  43. package/src/assets/web-panel/assets/{Memory-D-p7yDzj.js → Memory-zvLpyi__.js} +2 -2
  44. package/src/assets/web-panel/assets/{MobileBridge-D0XT5B6m.js → MobileBridge-DXd1ik2Z.js} +1 -1
  45. package/src/assets/web-panel/assets/{MobileProjects-CL9cHVIk.js → MobileProjects-DKh2q-Y9.js} +1 -1
  46. package/src/assets/web-panel/assets/{Mtc-CME4kDmC.js → Mtc-Ct-fhtIx.js} +2 -2
  47. package/src/assets/web-panel/assets/{MtcAudit-BjGOXFnn.js → MtcAudit-J4zY3Oqk.js} +2 -2
  48. package/src/assets/web-panel/assets/{Multisig-CSzc53e0.js → Multisig-B2HJMCKe.js} +3 -3
  49. package/src/assets/web-panel/assets/{NLProgramming-BYjZnaH8.js → NLProgramming-CwcSmU4q.js} +1 -1
  50. package/src/assets/web-panel/assets/{Notes-BUPOYE0C.js → Notes-Da53L6wb.js} +3 -3
  51. package/src/assets/web-panel/assets/{NotificationSettings-BK8YADru.js → NotificationSettings-BxhufdrA.js} +1 -1
  52. package/src/assets/web-panel/assets/{OrderTableRenderer-B5F8bnWt.js → OrderTableRenderer-BoFwohAi.js} +1 -1
  53. package/src/assets/web-panel/assets/{Organization-B0WNlhMd.js → Organization-MIsMrUes.js} +4 -4
  54. package/src/assets/web-panel/assets/{Overflow-CED6ZO87.js → Overflow-Dy2P4v3q.js} +1 -1
  55. package/src/assets/web-panel/assets/{P2P-CBdc8fkP.js → P2P-CD9Sxn2y.js} +2 -2
  56. package/src/assets/web-panel/assets/{PdhVaultBrowser-DuauYi03.js → PdhVaultBrowser-BvBWgfG0.js} +3 -3
  57. package/src/assets/web-panel/assets/{Permissions-kfgY0ukN.js → Permissions-CwOlDRis.js} +4 -4
  58. package/src/assets/web-panel/assets/{PersonalDataHub-CDY3I1Do.js → PersonalDataHub-CZYaxEpv.js} +3 -3
  59. package/src/assets/web-panel/assets/{Pipeline-B9x0wKSK.js → Pipeline-kLU7PUbB.js} +1 -1
  60. package/src/assets/web-panel/assets/{Privacy-Cqhcr_Qv.js → Privacy-BVRycSiI.js} +1 -1
  61. package/src/assets/web-panel/assets/{ProjectInit-CFhoyo57.js → ProjectInit-DP3pr7uJ.js} +2 -2
  62. package/src/assets/web-panel/assets/{ProjectSettings-DCBjV2Hm.js → ProjectSettings-CACaDYjs.js} +2 -2
  63. package/src/assets/web-panel/assets/{Projects-C51w0LnM.js → Projects-CB1k4zTC.js} +1 -1
  64. package/src/assets/web-panel/assets/{Providers-BuCIWZY1.js → Providers-D7Y9WHRE.js} +1 -1
  65. package/src/assets/web-panel/assets/{QrScannerModal-CEXNL5CB.js → QrScannerModal-CeP8xzs1.js} +1 -1
  66. package/src/assets/web-panel/assets/{QuickAsk-DgK8aLAU.js → QuickAsk-iJVFrhZ2.js} +1 -1
  67. package/src/assets/web-panel/assets/{Recommend-BxEYQRAs.js → Recommend-DmTpnagw.js} +1 -1
  68. package/src/assets/web-panel/assets/{RemoteSession-PRsxNsYU.js → RemoteSession-C6ek8Uni.js} +2 -2
  69. package/src/assets/web-panel/assets/{Reputation-S-tQH70r.js → Reputation-CPfwc9de.js} +1 -1
  70. package/src/assets/web-panel/assets/{Row-U1Ws3CJl.js → Row-C1wwtSMJ.js} +1 -1
  71. package/src/assets/web-panel/assets/{RssFeed-BftCyeii.js → RssFeed-BiDJsqaH.js} +3 -3
  72. package/src/assets/web-panel/assets/{Search-o4gK0cPy.js → Search-BF6Aon95.js} +1 -1
  73. package/src/assets/web-panel/assets/{Security-U2ZRpsbA.js → Security-Bps0XnV4.js} +3 -3
  74. package/src/assets/web-panel/assets/{Services-D0tRjWl_.js → Services-uf92smGR.js} +2 -2
  75. package/src/assets/web-panel/assets/{Skeleton-DzZ8TFsB.js → Skeleton-DQd4eVWW.js} +1 -1
  76. package/src/assets/web-panel/assets/{Skills-B1cC7rju.js → Skills-DgamiYa5.js} +1 -1
  77. package/src/assets/web-panel/assets/{Sla-CtIHOR0J.js → Sla-CF1IVIrm.js} +1 -1
  78. package/src/assets/web-panel/assets/{SpeechSettings-CD8ZlQpW.js → SpeechSettings-Bzxmjbpc.js} +1 -1
  79. package/src/assets/web-panel/assets/{SyncSettings-BilFQWQk.js → SyncSettings-B8zKauiq.js} +2 -2
  80. package/src/assets/web-panel/assets/{Tasks-Bmg2qLXl.js → Tasks-DPKV_xSt.js} +1 -1
  81. package/src/assets/web-panel/assets/{Templates-D6yofyC1.js → Templates-BikeSZIF.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tenant-BzttD-Gp.js → Tenant-CEaUaDkJ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Terminal-DyRXeYuH.js → Terminal-ZPgOSQ_q.js} +3 -3
  84. package/src/assets/web-panel/assets/{TimelineRenderer-Bdmkx-Tr.js → TimelineRenderer-DmyB4Udk.js} +1 -1
  85. package/src/assets/web-panel/assets/{Tokens-10RcVAVJ.js → Tokens-g85Pm5TO.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trigger-CKV-9DdV.js → Trigger-D202hx9a.js} +1 -1
  87. package/src/assets/web-panel/assets/{Trust-BEc-sW1q.js → Trust-DzvQYVFy.js} +1 -1
  88. package/src/assets/web-panel/assets/{UkeySign-BSql8piX.js → UkeySign-KRzwddVg.js} +1 -1
  89. package/src/assets/web-panel/assets/{VideoEditing-C4OH2f4s.js → VideoEditing-IRBXLO2z.js} +1 -1
  90. package/src/assets/web-panel/assets/{Wallet-BSSvWKmv.js → Wallet-DSf5KPgQ.js} +4 -4
  91. package/src/assets/web-panel/assets/{WebAuthn-LxIzXo9d.js → WebAuthn-DNPxLTCc.js} +5 -5
  92. package/src/assets/web-panel/assets/{WorkflowEditor-DWwdfcte.js → WorkflowEditor-C3wAtVcK.js} +1 -1
  93. package/src/assets/web-panel/assets/{addon-fit-CK6X9sAG.js → addon-fit-CbkjSUJl.js} +1 -1
  94. package/src/assets/web-panel/assets/{chat-DWxYYLD5.js → chat-q3XXUtv2.js} +1 -1
  95. package/src/assets/web-panel/assets/{colors-BxEcQqtg.js → colors-CF54SNei.js} +1 -1
  96. package/src/assets/web-panel/assets/{compact-item-DNbezFOJ.js → compact-item-BaRkvZuT.js} +1 -1
  97. package/src/assets/web-panel/assets/{createContext-DaJXc5nx.js → createContext-CDR9hsfs.js} +1 -1
  98. package/src/assets/web-panel/assets/devWarning-1LO-NplX.js +1 -0
  99. package/src/assets/web-panel/assets/{hasIn-BMrw3sg3.js → hasIn-DlC--S8R.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DpSp97J8.js → index-B0Ptc7yu.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DzZHBzCb.js → index-B0V9rgdu.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DEvdSKT4.js → index-BEiUlFKb.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-pzYLf5qu.js → index-BJO0n1LQ.js} +1 -1
  104. package/src/assets/web-panel/assets/index-BLaJsev4.js +1 -0
  105. package/src/assets/web-panel/assets/index-BLmviChG.js +1 -0
  106. package/src/assets/web-panel/assets/{index-2c0bL3SE.js → index-BU5DJqk7.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Dr18agDl.js → index-BY-Tf3OM.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-T4T84G6X.js → index-BZrE0Go8.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-LRb0QX6S.js → index-BizdX2X5.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-B9b6UaZl.js → index-C87Yr3h1.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BAV07GDK.js → index-C9Wypz9e.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-B_b9_6wQ.js → index-CAoG_E-q.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-NEW5EN2w.js → index-CAxSyMrF.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Dwg38xTG.js → index-CC5HjNM6.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Bs2QyMPQ.js → index-CNZQEZ9g.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BR4nWOmR.js → index-CPvIhha6.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-hPy_f08G.js → index-CR_wqMGy.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-IX0g0s2t.js → index-CSClXoB3.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-cCqCEa9X.js → index-CZ8azVgB.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-C25ig6EV.js → index-Ccc5z8eJ.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-7zzLqfvI.js → index-CeiKbM3a.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CpwgF7vh.js → index-Cl6av3X7.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BNZDGV2q.js → index-CtGfeD7E.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-6W0V5G2t.js → index-Ctid12Gq.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BaByEdBj.js → index-D0H-N0uG.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BCCd8Rj6.js → index-D0vIgprF.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CL-36X3A.js → index-D4wUDFRg.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DL0k35f0.js → index-DJFipyK7.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BcuytRTa.js → index-DX2REKNp.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Cm9DYzhC.js → index-Dc3gD0cw.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Bum_aSyd.js → index-DiQzer2R.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CaxzeSIM.js → index-DntKLOs9.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-cKBpcInt.js → index-Dplhl6gh.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Ca2hwPMo.js → index-Dq8q_PWB.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DarVV5yG.js → index-IVQdOBNN.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-rFaCnjXi.js → index-Kerduyao.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-VD-dTYQE.js → index-W6cLGjpW.js} +1 -1
  138. package/src/assets/web-panel/assets/{index-CiEdfbB9.js → index-qZDNFll9.js} +1 -1
  139. package/src/assets/web-panel/assets/{initDefaultProps-BWVLgWhF.js → initDefaultProps-Ccz7v71u.js} +1 -1
  140. package/src/assets/web-panel/assets/{markdown-Yo_c6Krv.js → markdown-Bq2x0XsR.js} +1 -1
  141. package/src/assets/web-panel/assets/markdown-DUKxbhE4.js +51 -0
  142. package/src/assets/web-panel/assets/{motion-KJZ1xfDE.js → motion-BlCLpVDp.js} +1 -1
  143. package/src/assets/web-panel/assets/{move-DGqU6H7M.js → move-B80G7fLU.js} +1 -1
  144. package/src/assets/web-panel/assets/{mtc-parser-Dg0xkI5J.js → mtc-parser-Djw08NJh.js} +1 -1
  145. package/src/assets/web-panel/assets/{omit-B6RnMJAQ.js → omit-Bg_G1eUr.js} +1 -1
  146. package/src/assets/web-panel/assets/{pickAttrs-Ctw2i3jb.js → pickAttrs-Df9zYUg2.js} +1 -1
  147. package/src/assets/web-panel/assets/{placementArrow-D3F3x8Jm.js → placementArrow-DjCDLhJ4.js} +1 -1
  148. package/src/assets/web-panel/assets/{responsiveObserve-W6eHE0nM.js → responsiveObserve--Naz7NgY.js} +1 -1
  149. package/src/assets/web-panel/assets/{slide-BlFf8sY5.js → slide-CHn3ald-.js} +1 -1
  150. package/src/assets/web-panel/assets/{statusUtils-Cd6LMwmy.js → statusUtils-BiGwoIK_.js} +1 -1
  151. package/src/assets/web-panel/assets/{styleChecker-Bg5-U4Y1.js → styleChecker-Zf2dQx1j.js} +1 -1
  152. package/src/assets/web-panel/assets/{useFlexGapSupport-DTkLS3tn.js → useFlexGapSupport-sLES8nyD.js} +1 -1
  153. package/src/assets/web-panel/assets/{useFs-CwYGzoBt.js → useFs-DV1Hl4qu.js} +1 -1
  154. package/src/assets/web-panel/assets/{usePersonalDataHub-PCgFQXZP.js → usePersonalDataHub-CZXr2Qxg.js} +1 -1
  155. package/src/assets/web-panel/assets/{vnode-CJM7MkrB.js → vnode-e8Eo3Oyl.js} +1 -1
  156. package/src/assets/web-panel/assets/{xterm-BZcWGsqw.js → xterm-zbskxxGA.js} +1 -1
  157. package/src/assets/web-panel/assets/{zoom-CP0mgaFi.js → zoom-B8A6xKMF.js} +1 -1
  158. package/src/assets/web-panel/index.html +1 -1
  159. package/src/data/changelog.json +15 -2
  160. package/src/harness/jsonl-session-store.js +2 -1
  161. package/src/lib/artifact-store.js +129 -20
  162. package/src/lib/bounded-artifact-file-read.js +128 -46
  163. package/src/lib/evolution/agent-evolution-ingress.js +41 -7
  164. package/src/lib/evolution/agent-evolution-runtime-composition.js +65 -27
  165. package/src/lib/evolution/evidence-json-text.js +65 -3
  166. package/src/lib/evolution/evolution-artifact-ports.js +1005 -83
  167. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +59 -15
  168. package/src/lib/evolution/evolution-evidence-projector.js +35 -3
  169. package/src/lib/evolution/evolution-evidence-storage-layout.js +115 -0
  170. package/src/lib/evolution/evolution-file-witness.js +7 -3
  171. package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +6 -2
  172. package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +6 -2
  173. package/src/lib/evolution/evolution-ledger.js +226 -55
  174. package/src/lib/evolution/evolution-private-storage.js +20 -0
  175. package/src/lib/evolution/evolution-run-ledger-adapter.js +298 -11
  176. package/src/lib/evolution/evolution-windows-directory-durability.js +215 -32
  177. package/src/lib/evolution/local-ui-evolution-runtime.js +3 -38
  178. package/src/lib/evolution/local-ui-signing-authority.js +69 -0
  179. package/src/lib/ollama-provider-fetch.js +33 -0
  180. package/src/lib/provider-stream.js +14 -13
  181. package/src/lib/session-history-origins.js +71 -32
  182. package/src/lib/session-message-provenance.js +26 -2
  183. package/src/lib/session-runtime-retention.js +10 -1
  184. package/src/lib/session-transcript-migration.js +67 -12
  185. package/src/lib/storage-failure-cause-codes.js +449 -0
  186. package/src/runtime/agent-core.js +54 -33
  187. package/src/runtime/headless-stream.js +89 -10
  188. package/src/assets/web-panel/assets/MarkdownRenderer-BgnYTegK.js +0 -1
  189. package/src/assets/web-panel/assets/devWarning-CRyXoGo9.js +0 -1
  190. package/src/assets/web-panel/assets/index-C-W0Ntk_.js +0 -1
  191. package/src/assets/web-panel/assets/index-CCk_qhBx.js +0 -1
  192. package/src/assets/web-panel/assets/markdown-CsiA8-E5.js +0 -50
@@ -8,6 +8,7 @@ import {
8
8
  } from "./context-memory-kernel/message-adapter.js";
9
9
  import {
10
10
  decodeVerifiedPersistedMessage,
11
+ decodeVerifiedRawPersistedMessage,
11
12
  encodePersistedMessage,
12
13
  getDurableSystemMessageProvenance,
13
14
  DURABLE_SYSTEM_MESSAGE_KINDS,
@@ -34,8 +35,15 @@ const historyBearing = (entry) =>
34
35
  derivedSystemKinds.has(
35
36
  getDurableSystemMessageProvenance(entry.message)?.kind,
36
37
  );
38
+ // Compare conversation identity without dropping system messages, their private
39
+ // provenance, or unknown metadata. Raw receipt fields remain available below
40
+ // for authenticating historical ContextItem source digests.
41
+ const conversationMessages = (messages) =>
42
+ messages.map((message) =>
43
+ decodeVerifiedPersistedMessage(encodePersistedMessage(message)),
44
+ );
37
45
  const fingerprint = (messages) =>
38
- canonicalDigest(messages.map(encodePersistedMessage));
46
+ canonicalDigest(conversationMessages(messages).map(encodePersistedMessage));
39
47
  const sameContextItemContent = (left, right) => {
40
48
  if (typeof left?.content === "string" || typeof right?.content === "string") {
41
49
  return (
@@ -91,12 +99,12 @@ export function createSessionHistoryOrigins() {
91
99
  appendPersisted(message, ordinal) {
92
100
  if (!context) return;
93
101
  append(
94
- decodeVerifiedPersistedMessage(message),
102
+ decodeVerifiedRawPersistedMessage(message),
95
103
  displayable(message) ? { first: ordinal, last: ordinal } : null,
96
104
  );
97
105
  },
98
106
  appendMappedPersisted(message, origin) {
99
- append(decodeVerifiedPersistedMessage(message), origin);
107
+ append(decodeVerifiedRawPersistedMessage(message), origin);
100
108
  },
101
109
  branchPrefix(messages, head, count) {
102
110
  if (!context) return null;
@@ -130,7 +138,7 @@ export function createSessionHistoryOrigins() {
130
138
  let ordinal = 0;
131
139
  replace(
132
140
  messages.map((message) => ({
133
- message: decodeVerifiedPersistedMessage(message),
141
+ message: decodeVerifiedRawPersistedMessage(message),
134
142
  origin: displayable(message)
135
143
  ? { first: ordinal, last: ordinal++ }
136
144
  : null,
@@ -142,16 +150,34 @@ export function createSessionHistoryOrigins() {
142
150
  let entries = null;
143
151
  try {
144
152
  if (context) {
145
- const originals = messagesToContextItems(
146
- context.map((entry) => entry.message),
147
- { sessionId: canonical.sessionId, allowExternalization: true },
148
- );
149
- const byDigest = new Map(
150
- originals.map((item) => [item.digest, item]),
151
- );
152
- const bySequence = new Map(
153
- originals.map((item) => [item.sourceRef.eventSequence, item]),
154
- );
153
+ const rawMessages = context.map((entry) => entry.message);
154
+ // Old compactions hashed raw receipt-bearing bundles; new ones hash
155
+ // conversation projections. Derive exactly these two representations
156
+ // from the same bounded verified context, never from output claims.
157
+ const representations = [rawMessages];
158
+ if (
159
+ rawMessages.some(
160
+ (message) =>
161
+ message.role === "user" &&
162
+ (Object.hasOwn(message, "clientMessageId") ||
163
+ Object.hasOwn(message, "inputDigest")),
164
+ )
165
+ ) {
166
+ representations.push(conversationMessages(rawMessages));
167
+ }
168
+ const sources = representations.map((messages) => {
169
+ const items = messagesToContextItems(messages, {
170
+ sessionId: canonical.sessionId,
171
+ allowExternalization: true,
172
+ });
173
+ return {
174
+ items,
175
+ byDigest: new Map(items.map((item) => [item.digest, item])),
176
+ bySequence: new Map(
177
+ items.map((item) => [item.sourceRef.eventSequence, item]),
178
+ ),
179
+ };
180
+ });
155
181
  const itemEntries = (item) =>
156
182
  context.slice(
157
183
  item.sourceRef.eventSequence,
@@ -171,12 +197,16 @@ export function createSessionHistoryOrigins() {
171
197
  const messages = contextItemsToMessages([item], {
172
198
  sessionId: canonical.sessionId,
173
199
  });
174
- const source = bySequence.get(item.sourceRef.eventSequence);
175
- if (
176
- item.sourceRef.store === "cli-jsonl-session" &&
177
- source?.sourceRef.digest === item.sourceRef.digest &&
178
- sameContextItemContent(source, item)
179
- ) {
200
+ const source = sources
201
+ .map(({ bySequence }) =>
202
+ bySequence.get(item.sourceRef.eventSequence),
203
+ )
204
+ .find(
205
+ (candidate) =>
206
+ candidate?.sourceRef.digest === item.sourceRef.digest &&
207
+ sameContextItemContent(candidate, item),
208
+ );
209
+ if (item.sourceRef.store === "cli-jsonl-session" && source) {
180
210
  return itemEntries(source);
181
211
  }
182
212
  let origin = null;
@@ -185,18 +215,26 @@ export function createSessionHistoryOrigins() {
185
215
  item.provenance?.parentDigests?.length > 0
186
216
  ) {
187
217
  const digests = item.provenance.parentDigests;
188
- if (
189
- digests.length <= originals.length &&
190
- new Set(digests).size === digests.length
191
- ) {
192
- const parents = digests.map((digest) => byDigest.get(digest));
193
- if (parents.every(Boolean))
194
- origin = span(parents.flatMap(itemEntries));
218
+ if (new Set(digests).size === digests.length) {
219
+ // A summary must name one complete representation. Mixing
220
+ // raw and projected aliases cannot manufacture extra parents.
221
+ for (const { items, byDigest } of sources) {
222
+ if (digests.length > items.length) continue;
223
+ const parents = digests.map((digest) =>
224
+ byDigest.get(digest),
225
+ );
226
+ if (parents.every(Boolean)) {
227
+ origin = span(parents.flatMap(itemEntries));
228
+ break;
229
+ }
230
+ }
195
231
  }
196
232
  }
197
233
  return messages.map((message) => ({ message, origin }));
198
234
  });
199
- const persisted = data.messages.map(decodeVerifiedPersistedMessage);
235
+ const persisted = data.messages.map(
236
+ decodeVerifiedRawPersistedMessage,
237
+ );
200
238
  if (
201
239
  fingerprint(entries.map((entry) => entry.message)) !==
202
240
  fingerprint(persisted)
@@ -209,7 +247,7 @@ export function createSessionHistoryOrigins() {
209
247
  replace(
210
248
  entries ||
211
249
  data.messages.map((message) => ({
212
- message: decodeVerifiedPersistedMessage(message),
250
+ message: decodeVerifiedRawPersistedMessage(message),
213
251
  origin: null,
214
252
  })),
215
253
  );
@@ -233,13 +271,14 @@ export function createSessionHistoryOrigins() {
233
271
  start: certificate.start,
234
272
  end: certificate.end,
235
273
  });
274
+ const persisted = data.messages.map(decodeVerifiedRawPersistedMessage);
236
275
  if (
237
276
  fingerprint(projected.map((entry) => entry.message)) !==
238
- fingerprint(data.messages.map(decodeVerifiedPersistedMessage))
277
+ fingerprint(persisted)
239
278
  )
240
279
  return false;
241
- const entries = projected.map(({ message, sourceIndexes }) => ({
242
- message,
280
+ const entries = projected.map(({ sourceIndexes }, index) => ({
281
+ message: persisted[index],
243
282
  origin: span(sourceIndexes.map((index) => context[index])),
244
283
  }));
245
284
  replace(entries);
@@ -214,6 +214,18 @@ function cloneWithoutWireTag(snapshot) {
214
214
  return clean;
215
215
  }
216
216
 
217
+ // Input acceptance belongs to the authenticated event, not the provider's
218
+ // conversation message. Keep encodePersistedMessage unchanged so receipt
219
+ // lookup/deduplication still verifies the original event and digest. Apply this
220
+ // only after the full JSON-safe clone, including for historical checkpoints.
221
+ function conversationMessage(clean) {
222
+ if (clean?.role === "user") {
223
+ delete clean.clientMessageId;
224
+ delete clean.inputDigest;
225
+ }
226
+ return clean;
227
+ }
228
+
217
229
  function canonicalTag(kind) {
218
230
  if (!DURABLE_KINDS.has(kind)) {
219
231
  throw new TypeError(`Unsupported durable system message kind: ${kind}`);
@@ -314,7 +326,7 @@ export function encodePersistedMessage(message) {
314
326
  * Decode provenance only after the caller has verified the JSONL hash chain
315
327
  * and its independent head/count anchor while holding the session lock.
316
328
  */
317
- export function decodeVerifiedPersistedMessage(message) {
329
+ export function decodeVerifiedRawPersistedMessage(message) {
318
330
  if (!message || typeof message !== "object") return message;
319
331
  if (!isObjectMessage(message)) return null;
320
332
  const snapshot = plainDataSnapshot(message);
@@ -332,6 +344,12 @@ export function decodeVerifiedPersistedMessage(message) {
332
344
  return clean;
333
345
  }
334
346
 
347
+ /** Verified message replay has a conversation projection distinct from the
348
+ * exact historical payload used to authenticate migration and lineage. */
349
+ export function decodeVerifiedPersistedMessage(message) {
350
+ return conversationMessage(decodeVerifiedRawPersistedMessage(message));
351
+ }
352
+
335
353
  /** Strip an untrusted wire field without granting runtime replay authority. */
336
354
  export function sanitizePersistedMessage(message) {
337
355
  if (!message || typeof message !== "object") return message;
@@ -340,6 +358,12 @@ export function sanitizePersistedMessage(message) {
340
358
  return snapshot ? cloneWithoutWireTag(snapshot) : null;
341
359
  }
342
360
 
361
+ /** Conversation replay excludes receipt metadata; generic data sanitation and
362
+ * historical migration digests retain their original representation. */
363
+ export function sanitizeConversationMessage(message) {
364
+ return conversationMessage(sanitizePersistedMessage(message));
365
+ }
366
+
343
367
  /** Deep-sanitize an untrusted persisted message array without granting replay. */
344
368
  export function sanitizePersistedMessages(messages, options = {}) {
345
369
  const strict = options?.strict === true;
@@ -442,7 +466,7 @@ export function projectCanonicalResumeMessages(messages, options = {}) {
442
466
  }
443
467
  if (isRuntimeOnlySessionMessage(raw)) continue;
444
468
  if (role !== "system") {
445
- projected.push(clean);
469
+ projected.push(conversationMessage(clean));
446
470
  } else if (runtimeTag) {
447
471
  projected.push(attachRuntimeTag(clean, canonicalTag(runtimeTag.kind)));
448
472
  }
@@ -1,6 +1,10 @@
1
1
  /** Bounded live-state retention for long-running agent conversations. */
2
2
 
3
3
  import { createHash } from "node:crypto";
4
+ import {
5
+ isRuntimeOnlySessionMessage,
6
+ markRuntimeOnlySessionMessage,
7
+ } from "./session-message-provenance.js";
4
8
 
5
9
  export const SESSION_RUNTIME_RETENTION_LIMITS = Object.freeze({
6
10
  recentResults: 32,
@@ -136,7 +140,12 @@ export function releaseOldLiveSessionResults(messages, configured = {}) {
136
140
  originalChars: content.length,
137
141
  retainedChars: projection.content.length,
138
142
  });
139
- return { ...message, content: projection.content };
143
+ const retained = { ...message, content: projection.content };
144
+ // This is a trusted host clone. Preserve only authority already attached
145
+ // to its source; matching background-result text grants no authority.
146
+ return isRuntimeOnlySessionMessage(message)
147
+ ? markRuntimeOnlySessionMessage(retained)
148
+ : retained;
140
149
  });
141
150
  return {
142
151
  messages: output,
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
 
3
3
  import {
4
4
  appendEvent,
5
+ appendAuthorityEventWithVerifiedProjection,
5
6
  findLatestEvent,
6
7
  listSessionAuthoritySummaries,
7
8
  readVerifiedMessages,
@@ -12,7 +13,10 @@ import {
12
13
  getSession as getDatabaseSession,
13
14
  listSessions as listDatabaseSessions,
14
15
  } from "./session-manager.js";
15
- import { sanitizePersistedMessages } from "./session-message-provenance.js";
16
+ import {
17
+ sanitizeConversationMessage,
18
+ sanitizePersistedMessages,
19
+ } from "./session-message-provenance.js";
16
20
 
17
21
  export const SESSION_STORE_MIGRATION_EVENT = "session_store_migrated";
18
22
  export const SESSION_STORE_MIGRATION_SCHEMA =
@@ -71,6 +75,7 @@ export function ensureCanonicalSessionTranscript(
71
75
  ) {
72
76
  const deps = {
73
77
  appendEvent,
78
+ appendAuthorityEventWithVerifiedProjection,
74
79
  findLatestEvent,
75
80
  readVerifiedMessages,
76
81
  sessionHasPersistedEvidence,
@@ -113,14 +118,67 @@ export function ensureCanonicalSessionTranscript(
113
118
  });
114
119
  }
115
120
 
121
+ const migration = {
122
+ schema: SESSION_STORE_MIGRATION_SCHEMA,
123
+ source,
124
+ messagesDigest: digest,
125
+ messageCount: importedMessages.length,
126
+ };
127
+ const conflict = () =>
128
+ migrationError(
129
+ "CC_SESSION_MIGRATION_CONFLICT",
130
+ `canonical transcript already contains different messages: ${id}`,
131
+ { sessionId: id },
132
+ );
116
133
  const currentMessages = deps.readVerifiedMessages(id);
134
+ let recoveredImport = false;
117
135
  if (currentMessages.length > 0) {
118
- if (messagesDigest(currentMessages) !== digest) {
119
- throw migrationError(
120
- "CC_SESSION_MIGRATION_CONFLICT",
121
- `canonical transcript already contains different messages: ${id}`,
122
- { sessionId: id },
136
+ const snapshot = deps.findLatestEvent(id, "compact");
137
+ if (snapshot?.data?.reason === "physical-store-import") {
138
+ // Conversation replay omits input receipt metadata. Recover an interrupted
139
+ // import only from the exact raw snapshot, never normalized equality alone.
140
+ // Recheck both evidence and live replay under the marker's writer lock.
141
+ deps.appendAuthorityEventWithVerifiedProjection(
142
+ id,
143
+ SESSION_STORE_MIGRATION_EVENT,
144
+ migration,
145
+ {
146
+ createProjection: () => {
147
+ let latest = null;
148
+ let completed = false;
149
+ return {
150
+ accept(event) {
151
+ if (event.type === "compact") latest = event.data;
152
+ if (event.type === SESSION_STORE_MIGRATION_EVENT)
153
+ completed = true;
154
+ },
155
+ finish: () => ({ latest, completed }),
156
+ };
157
+ },
158
+ validateProjection({ latest, completed }, authority) {
159
+ if (
160
+ completed ||
161
+ latest?.reason !== "physical-store-import" ||
162
+ !Array.isArray(latest.messages) ||
163
+ messagesDigest(latest.messages) !== digest ||
164
+ // Old snapshots did not record a source label. Their exact raw
165
+ // source bytes remain the only available import identity proof.
166
+ (Object.hasOwn(latest, "migration") &&
167
+ (latest.migration?.schema !== migration.schema ||
168
+ latest.migration.source !== source ||
169
+ latest.migration.messagesDigest !== digest)) ||
170
+ messagesDigest(authority.readMessages()) !==
171
+ messagesDigest(
172
+ importedMessages.map(sanitizeConversationMessage),
173
+ )
174
+ )
175
+ throw conflict();
176
+ },
177
+ },
123
178
  );
179
+ recoveredImport = true;
180
+ } else if (messagesDigest(currentMessages) !== digest) {
181
+ throw conflict();
124
182
  }
125
183
  } else if (importedMessages.length > 0) {
126
184
  deps.appendEvent(id, "compact", {
@@ -128,15 +186,12 @@ export function ensureCanonicalSessionTranscript(
128
186
  originalMessages: importedMessages.length,
129
187
  compressedMessages: importedMessages.length,
130
188
  reason: "physical-store-import",
189
+ migration,
131
190
  });
132
191
  }
133
192
 
134
- deps.appendEvent(id, SESSION_STORE_MIGRATION_EVENT, {
135
- schema: SESSION_STORE_MIGRATION_SCHEMA,
136
- source,
137
- messagesDigest: digest,
138
- messageCount: importedMessages.length,
139
- });
193
+ if (!recoveredImport)
194
+ deps.appendEvent(id, SESSION_STORE_MIGRATION_EVENT, migration);
140
195
  return Object.freeze({
141
196
  sessionId: id,
142
197
  migrated: true,