chainlesschain 0.166.115 → 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 (207) hide show
  1. package/README.md +43 -5
  2. package/package.json +4 -4
  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-BsoSoDNb.js → AIOps-BGySwMIP.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-Dcx7Gm5t.js → ActionButton-Chn7fBLr.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-S1hsBIz3.js → Analytics-ORH7UkGa.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-B2j067qM.js → AppLayout-8xV4jWjP.js} +5 -5
  10. package/src/assets/web-panel/assets/{Artifacts-D5iGV9ic.js → Artifacts-26SBK-x-.js} +1 -1
  11. package/src/assets/web-panel/assets/{Audit-C8ChVvXu.js → Audit-CtXpqbXg.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-Cg97AAJS.js → BackgroundAgents-C5zLvQis.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-CyxU9IUg.js → Backup-C93xY4vO.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-CKlWjA8I.js → BaseInput-DpVCHfAn.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-C-EqZza6.js → Chat-DM0LblR2.js} +5 -5
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BRFiXKPX.js → ChatBubbleRenderer-unlQUF1T.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-kkI13tSJ.js → Checkbox-BsAt3cKR.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-NlqEDwHK.js → Codegen-E_kp4KFd.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-CfepEu79.js → Col-6msR3T6I.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-BRo0qLXM.js → Community-PyX9c5D-.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-BMu8TP0E.js → Compact-7G1bVDSH.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-B7Q3Moef.js → Compliance-DcHN7GlD.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-BVwt7Xmc.js → Cowork-WUIHJYDx.js} +3 -3
  24. package/src/assets/web-panel/assets/{Cron-CgBv20Qy.js → Cron-CWgCbptg.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-CwcSBJk2.js → Crosschain-BzKZ6roD.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-d20rCiIm.js → DID-r7zxeItn.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-PpZaUYpS.js → Dashboard-D3pBiN2H.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-DjsLdX_Z.js → Dropdown-C4otRJlZ.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-CaPkrtxn.js → EmailListRenderer-CzDTC8lm.js} +1 -1
  30. package/src/assets/web-panel/assets/{EvolutionSettings-DDY8cQnE.js → EvolutionSettings-DGkXiIs-.js} +1 -1
  31. package/src/assets/web-panel/assets/{FamilyGuardDashboard-VQavMjyj.js → FamilyGuardDashboard-BKdEyuiR.js} +1 -1
  32. package/src/assets/web-panel/assets/{Federation-D0GvKQgI.js → Federation-dsI-xcpf.js} +1 -1
  33. package/src/assets/web-panel/assets/{FormItemContext-Dl_TWHmb.js → FormItemContext-CEEb1fMR.js} +1 -1
  34. package/src/assets/web-panel/assets/{GenericCardRenderer-Bny2uagG.js → GenericCardRenderer-D_mfO3Ts.js} +1 -1
  35. package/src/assets/web-panel/assets/{Git-B01KXq47.js → Git-CBwr2ZI3.js} +2 -2
  36. package/src/assets/web-panel/assets/{Governance-F4c4Vwo1.js → Governance-D-Wy2Jjr.js} +1 -1
  37. package/src/assets/web-panel/assets/{Inference-_025Q-8K.js → Inference-B4Yk_IRx.js} +1 -1
  38. package/src/assets/web-panel/assets/{KnowledgeGraph-DwbTmQb1.js → KnowledgeGraph-DoI7bi6m.js} +1 -1
  39. package/src/assets/web-panel/assets/{Logs-CnNo0hCm.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-Dkz5bv7F.js → Marketplace-CsIEByzK.js} +1 -1
  42. package/src/assets/web-panel/assets/{McpTools-CBtRwDW_.js → McpTools-_DRzjcIn.js} +3 -3
  43. package/src/assets/web-panel/assets/{Memory-Y9jnyTb7.js → Memory-zvLpyi__.js} +2 -2
  44. package/src/assets/web-panel/assets/{MobileBridge-Br1urkOz.js → MobileBridge-DXd1ik2Z.js} +1 -1
  45. package/src/assets/web-panel/assets/{MobileProjects-DnsyuerX.js → MobileProjects-DKh2q-Y9.js} +1 -1
  46. package/src/assets/web-panel/assets/{Mtc-he3ZzieF.js → Mtc-Ct-fhtIx.js} +4 -4
  47. package/src/assets/web-panel/assets/{MtcAudit-BadphAuN.js → MtcAudit-J4zY3Oqk.js} +2 -2
  48. package/src/assets/web-panel/assets/{Multisig-3_pVLymK.js → Multisig-B2HJMCKe.js} +3 -3
  49. package/src/assets/web-panel/assets/{NLProgramming-DmtmHfsI.js → NLProgramming-CwcSmU4q.js} +1 -1
  50. package/src/assets/web-panel/assets/{Notes-CE4L2O55.js → Notes-Da53L6wb.js} +4 -4
  51. package/src/assets/web-panel/assets/{NotificationSettings-B7QmfJn9.js → NotificationSettings-BxhufdrA.js} +1 -1
  52. package/src/assets/web-panel/assets/{OrderTableRenderer-O0wRSyJ0.js → OrderTableRenderer-BoFwohAi.js} +1 -1
  53. package/src/assets/web-panel/assets/{Organization-BrlMSsyT.js → Organization-MIsMrUes.js} +4 -4
  54. package/src/assets/web-panel/assets/{Overflow-CY4ULPrZ.js → Overflow-Dy2P4v3q.js} +1 -1
  55. package/src/assets/web-panel/assets/{P2P-kIANZYKd.js → P2P-CD9Sxn2y.js} +2 -2
  56. package/src/assets/web-panel/assets/{PdhVaultBrowser-DEgB4rvF.js → PdhVaultBrowser-BvBWgfG0.js} +5 -5
  57. package/src/assets/web-panel/assets/{Permissions-CWxywRp5.js → Permissions-CwOlDRis.js} +4 -4
  58. package/src/assets/web-panel/assets/{PersonalDataHub-DAg7iCbr.js → PersonalDataHub-CZYaxEpv.js} +4 -4
  59. package/src/assets/web-panel/assets/{Pipeline-Brc6ONnR.js → Pipeline-kLU7PUbB.js} +1 -1
  60. package/src/assets/web-panel/assets/{Privacy-CcinYTL8.js → Privacy-BVRycSiI.js} +1 -1
  61. package/src/assets/web-panel/assets/{ProjectInit-Bz8XEsom.js → ProjectInit-DP3pr7uJ.js} +2 -2
  62. package/src/assets/web-panel/assets/{ProjectSettings-CsOMlSTZ.js → ProjectSettings-CACaDYjs.js} +2 -2
  63. package/src/assets/web-panel/assets/Projects-CB1k4zTC.js +1 -0
  64. package/src/assets/web-panel/assets/{Providers-CeunOQiH.js → Providers-D7Y9WHRE.js} +1 -1
  65. package/src/assets/web-panel/assets/{QrScannerModal-CN2a2_Fb.js → QrScannerModal-CeP8xzs1.js} +1 -1
  66. package/src/assets/web-panel/assets/{QuickAsk-CVeLif3e.js → QuickAsk-iJVFrhZ2.js} +1 -1
  67. package/src/assets/web-panel/assets/{Recommend-1k9WOEGM.js → Recommend-DmTpnagw.js} +1 -1
  68. package/src/assets/web-panel/assets/{RemoteSession-Q8UCqIMw.js → RemoteSession-C6ek8Uni.js} +2 -2
  69. package/src/assets/web-panel/assets/{Reputation-CkrCgXKM.js → Reputation-CPfwc9de.js} +1 -1
  70. package/src/assets/web-panel/assets/{Row-JFdvuTzi.js → Row-C1wwtSMJ.js} +1 -1
  71. package/src/assets/web-panel/assets/{RssFeed-C74JHCmk.js → RssFeed-BiDJsqaH.js} +3 -3
  72. package/src/assets/web-panel/assets/{Search-DrJiVO1T.js → Search-BF6Aon95.js} +1 -1
  73. package/src/assets/web-panel/assets/{Security-BJzNlSJq.js → Security-Bps0XnV4.js} +3 -3
  74. package/src/assets/web-panel/assets/{Services-D4TLMnJm.js → Services-uf92smGR.js} +2 -2
  75. package/src/assets/web-panel/assets/{Skeleton-cswTDqhh.js → Skeleton-DQd4eVWW.js} +1 -1
  76. package/src/assets/web-panel/assets/{Skills-Bv0rM1BS.js → Skills-DgamiYa5.js} +1 -1
  77. package/src/assets/web-panel/assets/{Sla-D9rE7hNh.js → Sla-CF1IVIrm.js} +1 -1
  78. package/src/assets/web-panel/assets/SpeechSettings-Bzxmjbpc.js +1 -0
  79. package/src/assets/web-panel/assets/{SyncSettings-BwnMG8kq.js → SyncSettings-B8zKauiq.js} +2 -2
  80. package/src/assets/web-panel/assets/{Tasks-wJvU24cB.js → Tasks-DPKV_xSt.js} +1 -1
  81. package/src/assets/web-panel/assets/{Templates-CZbRU3tN.js → Templates-BikeSZIF.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tenant-_jbpFJPZ.js → Tenant-CEaUaDkJ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Terminal-BzNm5WKZ.js → Terminal-ZPgOSQ_q.js} +3 -3
  84. package/src/assets/web-panel/assets/{TimelineRenderer-bmybWjuS.js → TimelineRenderer-DmyB4Udk.js} +1 -1
  85. package/src/assets/web-panel/assets/{Tokens-o1WDcqVQ.js → Tokens-g85Pm5TO.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trigger-BB1D6sIB.js → Trigger-D202hx9a.js} +1 -1
  87. package/src/assets/web-panel/assets/{Trust-CLxdCfy2.js → Trust-DzvQYVFy.js} +1 -1
  88. package/src/assets/web-panel/assets/{UkeySign-B9LS6vS0.js → UkeySign-KRzwddVg.js} +1 -1
  89. package/src/assets/web-panel/assets/{VideoEditing-Bg0-wxjz.js → VideoEditing-IRBXLO2z.js} +1 -1
  90. package/src/assets/web-panel/assets/{Wallet-Bw0G2F6P.js → Wallet-DSf5KPgQ.js} +4 -4
  91. package/src/assets/web-panel/assets/{WebAuthn-irEiNY9b.js → WebAuthn-DNPxLTCc.js} +5 -5
  92. package/src/assets/web-panel/assets/{WorkflowEditor-Bh08FbJs.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-De-FPjVT.js → chat-q3XXUtv2.js} +1 -1
  95. package/src/assets/web-panel/assets/{colors-ygdyvinU.js → colors-CF54SNei.js} +1 -1
  96. package/src/assets/web-panel/assets/{compact-item-BQ9jH9KV.js → compact-item-BaRkvZuT.js} +1 -1
  97. package/src/assets/web-panel/assets/{createContext-BFuVSyox.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-i19GtR1P.js → hasIn-DlC--S8R.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DS1IwwGL.js → index-B0Ptc7yu.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-B1IsP_JO.js → index-B0V9rgdu.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CWfgeaG4.js → index-BEiUlFKb.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DTY20pWu.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-IXkif6J_.js → index-BU5DJqk7.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BVhtukYX.js → index-BY-Tf3OM.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BKlU5VZy.js → index-BZrE0Go8.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bw5pTpnI.js → index-BizdX2X5.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BGMxK155.js → index-C87Yr3h1.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DVnFgasM.js → index-C9Wypz9e.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C61w3omz.js → index-CAoG_E-q.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-l5-J0jHx.js → index-CAxSyMrF.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-28DjsABm.js → index-CC5HjNM6.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BPUCvc8i.js → index-CNZQEZ9g.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CpdXhhMY.js → index-CPvIhha6.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DAboGZTw.js → index-CR_wqMGy.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DL7ewjD2.js → index-CSClXoB3.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Bhf-MuUh.js → index-CZ8azVgB.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-BaaydJcC.js → index-Ccc5z8eJ.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B2LieObB.js → index-CeiKbM3a.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-We2nK3ju.js → index-Cl6av3X7.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-m8waSAyv.js → index-CtGfeD7E.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-cDJsyAkI.js → index-Ctid12Gq.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DlwxUZQL.js → index-D0H-N0uG.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BBYiCI1d.js → index-D0vIgprF.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-_9tUBcLm.js → index-D4wUDFRg.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-4HoFz1MA.js → index-DJFipyK7.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Cq9k4-Ws.js → index-DX2REKNp.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DuuOX5u3.js → index-Dc3gD0cw.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DgjLaB7k.js → index-DiQzer2R.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CMNjaSir.js → index-DntKLOs9.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-vXtH3o6O.js → index-Dplhl6gh.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-BLMtCKAY.js → index-Dq8q_PWB.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CXrk8OYO.js → index-IVQdOBNN.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-CBVcGaxk.js → index-Kerduyao.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-BKblSCL9.js → index-W6cLGjpW.js} +1 -1
  138. package/src/assets/web-panel/assets/{index-CgoSgmjK.js → index-qZDNFll9.js} +1 -1
  139. package/src/assets/web-panel/assets/{initDefaultProps-B_EZHeqN.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-BrVb_Gy1.js → motion-BlCLpVDp.js} +1 -1
  143. package/src/assets/web-panel/assets/{move-CKxVRL_J.js → move-B80G7fLU.js} +1 -1
  144. package/src/assets/web-panel/assets/{mtc-parser-C80rvQ1J.js → mtc-parser-Djw08NJh.js} +1 -1
  145. package/src/assets/web-panel/assets/{omit-De5vD7BR.js → omit-Bg_G1eUr.js} +1 -1
  146. package/src/assets/web-panel/assets/{pickAttrs-BTyEDjth.js → pickAttrs-Df9zYUg2.js} +1 -1
  147. package/src/assets/web-panel/assets/{placementArrow-BWR94AjR.js → placementArrow-DjCDLhJ4.js} +1 -1
  148. package/src/assets/web-panel/assets/{responsiveObserve-1g-Vnibk.js → responsiveObserve--Naz7NgY.js} +1 -1
  149. package/src/assets/web-panel/assets/{slide-Dmg6dYuF.js → slide-CHn3ald-.js} +1 -1
  150. package/src/assets/web-panel/assets/{statusUtils-Ddj6rSab.js → statusUtils-BiGwoIK_.js} +1 -1
  151. package/src/assets/web-panel/assets/{styleChecker-DyP1mPDf.js → styleChecker-Zf2dQx1j.js} +1 -1
  152. package/src/assets/web-panel/assets/{useFlexGapSupport-D3d_0YuY.js → useFlexGapSupport-sLES8nyD.js} +1 -1
  153. package/src/assets/web-panel/assets/{useFs-M3vq-gE2.js → useFs-DV1Hl4qu.js} +1 -1
  154. package/src/assets/web-panel/assets/{usePersonalDataHub-GtP2TgtK.js → usePersonalDataHub-CZXr2Qxg.js} +1 -1
  155. package/src/assets/web-panel/assets/{vnode-BurE2ATQ.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-Ch-ViiDe.js → zoom-B8A6xKMF.js} +1 -1
  158. package/src/assets/web-panel/index.html +1 -1
  159. package/src/commands/compact.js +7 -2
  160. package/src/data/changelog.json +27 -1
  161. package/src/harness/jsonl-session-store.js +80 -74
  162. package/src/harness/prompt-compressor.js +57 -3
  163. package/src/lib/artifact-store.js +129 -20
  164. package/src/lib/bounded-artifact-file-read.js +128 -46
  165. package/src/lib/context-memory-kernel/context-image-transport.js +248 -0
  166. package/src/lib/context-memory-kernel/jsonl-session-context-port.js +4 -1
  167. package/src/lib/context-memory-kernel/live-compaction.js +40 -10
  168. package/src/lib/context-memory-kernel/message-adapter.js +80 -10
  169. package/src/lib/context-memory-kernel/message-bundle-store.js +1140 -0
  170. package/src/lib/context-memory-kernel/provider-context.js +23 -8
  171. package/src/lib/evolution/agent-evolution-ingress.js +103 -19
  172. package/src/lib/evolution/agent-evolution-runtime-composition.js +65 -27
  173. package/src/lib/evolution/agent-model-projection.js +90 -18
  174. package/src/lib/evolution/evidence-json-text.js +341 -42
  175. package/src/lib/evolution/evolution-artifact-ports.js +1005 -83
  176. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +59 -15
  177. package/src/lib/evolution/evolution-evidence-projector.js +153 -16
  178. package/src/lib/evolution/evolution-evidence-storage-layout.js +115 -0
  179. package/src/lib/evolution/evolution-file-witness.js +7 -3
  180. package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +6 -2
  181. package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +6 -2
  182. package/src/lib/evolution/evolution-ledger.js +226 -55
  183. package/src/lib/evolution/evolution-private-storage.js +20 -0
  184. package/src/lib/evolution/evolution-run-ledger-adapter.js +298 -11
  185. package/src/lib/evolution/evolution-windows-directory-durability.js +215 -32
  186. package/src/lib/evolution/local-ui-evolution-runtime.js +3 -38
  187. package/src/lib/evolution/local-ui-signing-authority.js +69 -0
  188. package/src/lib/image-token-estimate.js +59 -0
  189. package/src/lib/ollama-provider-fetch.js +33 -0
  190. package/src/lib/provider-stream.js +14 -13
  191. package/src/lib/read-file-loop-guard.js +7 -4
  192. package/src/lib/session-history-origins.js +94 -35
  193. package/src/lib/session-message-provenance.js +26 -2
  194. package/src/lib/session-runtime-retention.js +10 -1
  195. package/src/lib/session-transcript-history.js +5 -1
  196. package/src/lib/session-transcript-migration.js +67 -12
  197. package/src/lib/storage-failure-cause-codes.js +449 -0
  198. package/src/lib/tool-result-preview.js +276 -0
  199. package/src/runtime/agent-core.js +111 -92
  200. package/src/runtime/headless-stream.js +121 -27
  201. package/src/assets/web-panel/assets/MarkdownRenderer-D8_iZief.js +0 -1
  202. package/src/assets/web-panel/assets/Projects-BeSOM6wi.js +0 -1
  203. package/src/assets/web-panel/assets/SpeechSettings-Bfhvin8B.js +0 -1
  204. package/src/assets/web-panel/assets/devWarning-c2I2Rn4_.js +0 -1
  205. package/src/assets/web-panel/assets/index-CTs4dYcV.js +0 -1
  206. package/src/assets/web-panel/assets/index-DeuvaW15.js +0 -1
  207. package/src/assets/web-panel/assets/markdown-CsiA8-E5.js +0 -50
@@ -15,7 +15,9 @@ import {
15
15
  EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
16
16
  EVOLUTION_ARTIFACT_DEFAULT_TTL_MS,
17
17
  EVOLUTION_ARTIFACT_MAX_TTL_MS,
18
+ captureEvolutionArtifactStoreDirectoryBoundary,
18
19
  } from "./evolution-artifact-ports.js";
20
+ import { EVOLUTION_EVIDENCE_STORAGE_TYPES } from "./evolution-evidence-storage-layout.js";
19
21
  import { EVOLUTION_ARTIFACT_REF_SCHEMA } from "./evolution-ledger.js";
20
22
  import {
21
23
  EVOLUTION_RAW_STORAGE_RECEIPT_SCHEMA,
@@ -353,6 +355,7 @@ export class EvolutionEvidenceArtifactAdapter {
353
355
  projector,
354
356
  bundleVerifier,
355
357
  artifactPorts,
358
+ typedArtifactPorts,
356
359
  } = {}) {
357
360
  this.#tenantId = normalizeId(tenantId, "evidence adapter tenantId");
358
361
  this.#audience = normalizeId(audience, "evidence adapter audience");
@@ -374,11 +377,50 @@ export class EvolutionEvidenceArtifactAdapter {
374
377
  EvolutionEvidenceBundleVerifier.prototype,
375
378
  "bundleVerifier",
376
379
  );
377
- assertInstance(
378
- artifactPorts,
379
- EvolutionArtifactPorts.prototype,
380
- "artifactPorts",
381
- );
380
+ if (typedArtifactPorts !== undefined) {
381
+ if (artifactPorts !== undefined)
382
+ throw new TypeError(
383
+ "Evidence adapter requires exactly one storage layout",
384
+ );
385
+ assertPlainExact(
386
+ typedArtifactPorts,
387
+ new Set(EVOLUTION_EVIDENCE_STORAGE_TYPES),
388
+ "typedArtifactPorts",
389
+ );
390
+ const captured = {};
391
+ const identities = new Set();
392
+ for (const type of EVOLUTION_EVIDENCE_STORAGE_TYPES) {
393
+ const port = typedArtifactPorts[type];
394
+ const boundary =
395
+ captureEvolutionArtifactStoreDirectoryBoundary(port).descriptor;
396
+ if (
397
+ boundary.artifactTenantId !== this.#tenantId ||
398
+ boundary.audience !== this.#audience
399
+ )
400
+ throw new TypeError(
401
+ "Typed Evidence store scope does not match its adapter",
402
+ );
403
+ for (const directory of [boundary.root, boundary.files]) {
404
+ const identity = `${directory.identity.dev}:${directory.identity.ino}`;
405
+ if (identities.has(identity))
406
+ throw new TypeError("Typed Evidence stores must be distinct");
407
+ identities.add(identity);
408
+ }
409
+ captured[type] = port;
410
+ }
411
+ this.#ports = Object.freeze(captured);
412
+ } else {
413
+ assertInstance(
414
+ artifactPorts,
415
+ EvolutionArtifactPorts.prototype,
416
+ "artifactPorts",
417
+ );
418
+ this.#ports = Object.freeze(
419
+ Object.fromEntries(
420
+ EVOLUTION_EVIDENCE_STORAGE_TYPES.map((type) => [type, artifactPorts]),
421
+ ),
422
+ );
423
+ }
382
424
  this.#ttlMs = ttlMs;
383
425
  this.#project = captureMethod(projector, "project", "projector");
384
426
  this.#projectAgentModel = captureMethod(
@@ -392,16 +434,15 @@ export class EvolutionEvidenceArtifactAdapter {
392
434
  "projector",
393
435
  );
394
436
  this.#verify = captureMethod(bundleVerifier, "verify", "bundleVerifier");
395
- this.#ports = artifactPorts;
396
437
  this.#resolveManifestRef =
397
- artifactPorts.createEvolutionLedgerArtifactResolver({
438
+ this.#ports.evidence.createEvolutionLedgerArtifactResolver({
398
439
  purpose: this.#purpose,
399
440
  });
400
441
  Object.freeze(this);
401
442
  }
402
443
 
403
444
  #put(type, value) {
404
- return this.#ports.putCanonical(type, value, {
445
+ return this.#ports[type].putCanonical(type, value, {
405
446
  audience: this.#audience,
406
447
  purpose: this.#purpose,
407
448
  retention: "ttl",
@@ -479,12 +520,15 @@ export class EvolutionEvidenceArtifactAdapter {
479
520
  if (result.manifest.type !== "evidence") {
480
521
  throw new TypeError("evidence manifest descriptor type is invalid");
481
522
  }
482
- const manifestResolved = this.#ports.resolve(result.manifest.envelope, {
483
- expectedDigest: result.manifest.digest,
484
- expectedType: "evidence",
485
- purpose: this.#purpose,
486
- tenantId: this.#tenantId,
487
- });
523
+ const manifestResolved = this.#ports.evidence.resolve(
524
+ result.manifest.envelope,
525
+ {
526
+ expectedDigest: result.manifest.digest,
527
+ expectedType: "evidence",
528
+ purpose: this.#purpose,
529
+ tenantId: this.#tenantId,
530
+ },
531
+ );
488
532
  return this.#resolveManifest(manifestResolved.value, result.evidenceId);
489
533
  }
490
534
 
@@ -553,7 +597,7 @@ export class EvolutionEvidenceArtifactAdapter {
553
597
  if (!descriptor || descriptor.type !== type) {
554
598
  throw new Error("evidence derivation component type is invalid");
555
599
  }
556
- bundle[field] = this.#ports.resolve(descriptor.envelope, {
600
+ bundle[field] = this.#ports[type].resolve(descriptor.envelope, {
557
601
  expectedDigest: descriptor.digest,
558
602
  expectedType: type,
559
603
  purpose: this.#purpose,
@@ -11,12 +11,16 @@
11
11
 
12
12
  import { createHash, randomBytes } from "node:crypto";
13
13
  import {
14
+ AGENT_MODEL_REQUEST_LIMITS,
15
+ AGENT_MODEL_IMAGE_LIMITS,
14
16
  projectAgentOpaqueTransportBlock,
15
17
  snapshotAgentModelRequest,
16
18
  } from "./agent-model-projection.js";
17
19
  import { snapshotSkillDecisionPayload } from "./skill-decision-projection.js";
18
20
  import {
19
21
  createEvidenceJsonTextBoundary,
22
+ AGENT_FENCED_CODE_LANGUAGES,
23
+ AGENT_CODE_TEXT_RESULT_TOOLS,
20
24
  EVIDENCE_JSON_POLICY,
21
25
  isAgentToolArgumentsPath,
22
26
  } from "./evidence-json-text.js";
@@ -515,13 +519,56 @@ export const EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V2_DIGEST = `sha256:${crea
515
519
  "utf8",
516
520
  )
517
521
  .digest("hex")}`;
518
- const AGENT_MODEL_RULESET = Object.freeze({
522
+ const AGENT_MODEL_RULESET_V3 = Object.freeze({
519
523
  ...AGENT_MODEL_RULESET_V2,
520
524
  schema: "chainlesschain.evolution-agent-model-projection-rules/v3",
521
525
  version: 3,
522
526
  opaqueTransportPolicy:
523
527
  "digest-bound-base64-image-and-signed-thinking-no-plaintext-projection-v1",
524
528
  });
529
+ export const EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V3_DIGEST = `sha256:${createHash(
530
+ "sha256",
531
+ )
532
+ .update(
533
+ `${AGENT_MODEL_RULESET_V3.schema}\0${JSON.stringify(AGENT_MODEL_RULESET_V3)}`,
534
+ "utf8",
535
+ )
536
+ .digest("hex")}`;
537
+ const AGENT_MODEL_RULESET_V4 = Object.freeze({
538
+ ...AGENT_MODEL_RULESET_V3,
539
+ schema: "chainlesschain.evolution-agent-model-projection-rules/v4",
540
+ version: 4,
541
+ codeTextPolicy: "paired-code-source-and-result-literal-scan-v1",
542
+ codeTextResultTools: AGENT_CODE_TEXT_RESULT_TOOLS,
543
+ // ArtifactPorts caps the complete durable record at 1 MiB. Reserve room for
544
+ // provenance/findings and the record envelope; no storage limit is relaxed.
545
+ maxModelBytes: AGENT_MODEL_REQUEST_LIMITS.maxBytes - 128 * 1024,
546
+ maxStringChars: AGENT_MODEL_REQUEST_LIMITS.maxBytes - 128 * 1024,
547
+ maxNodes: AGENT_MODEL_REQUEST_LIMITS.maxNodes,
548
+ maxDepth: AGENT_MODEL_REQUEST_LIMITS.maxDepth,
549
+ decodedDepthPolicy: "independent-bounded-json-depth-v1",
550
+ imageBudget: AGENT_MODEL_IMAGE_LIMITS,
551
+ jsonTextPolicy: Object.freeze({
552
+ ...EVIDENCE_JSON_POLICY,
553
+ version: 2,
554
+ maxNodes: AGENT_MODEL_REQUEST_LIMITS.maxNodes,
555
+ }),
556
+ });
557
+ export const EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V4_DIGEST = `sha256:${createHash(
558
+ "sha256",
559
+ )
560
+ .update(
561
+ `${AGENT_MODEL_RULESET_V4.schema}\0${JSON.stringify(AGENT_MODEL_RULESET_V4)}`,
562
+ "utf8",
563
+ )
564
+ .digest("hex")}`;
565
+ const AGENT_MODEL_RULESET = Object.freeze({
566
+ ...AGENT_MODEL_RULESET_V4,
567
+ schema: "chainlesschain.evolution-agent-model-projection-rules/v5",
568
+ version: 5,
569
+ fencedCodePolicy: "closed-message-code-fence-literal-scan-v1",
570
+ fencedCodeLanguages: AGENT_FENCED_CODE_LANGUAGES,
571
+ });
525
572
  export const EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST = `sha256:${createHash(
526
573
  "sha256",
527
574
  )
@@ -552,6 +599,8 @@ const SUPPORTED_RULESETS = new Map([
552
599
  [RAW_RULESET_V3_DIGEST, RAW_RULESET_V3],
553
600
  [AGENT_MODEL_RULESET_V1_DIGEST, AGENT_MODEL_RULESET_V1],
554
601
  [EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V2_DIGEST, AGENT_MODEL_RULESET_V2],
602
+ [EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V3_DIGEST, AGENT_MODEL_RULESET_V3],
603
+ [EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V4_DIGEST, AGENT_MODEL_RULESET_V4],
555
604
  [EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST, AGENT_MODEL_RULESET],
556
605
  ]);
557
606
 
@@ -627,6 +676,8 @@ const AGENT_VALUE_PATTERNS = Object.freeze([
627
676
  function valuePatterns(ruleset) {
628
677
  return ruleset === SKILL_DECISION_RULESET ||
629
678
  ruleset === AGENT_MODEL_RULESET ||
679
+ ruleset === AGENT_MODEL_RULESET_V4 ||
680
+ ruleset === AGENT_MODEL_RULESET_V3 ||
630
681
  ruleset === AGENT_MODEL_RULESET_V2 ||
631
682
  ruleset === AGENT_MODEL_RULESET_V1
632
683
  ? AGENT_VALUE_PATTERNS
@@ -690,7 +741,12 @@ function assertExactRecord(
690
741
  }
691
742
  }
692
743
 
693
- function canonicalJson(value, seen = new Set(), depth = 0) {
744
+ function canonicalJson(
745
+ value,
746
+ seen = new Set(),
747
+ depth = 0,
748
+ maximumBytes = 2 * 1024 * 1024,
749
+ ) {
694
750
  if (depth > 32) {
695
751
  throw projectionError(
696
752
  EVOLUTION_PROJECTION_INVALID_CODE,
@@ -712,10 +768,12 @@ function canonicalJson(value, seen = new Set(), depth = 0) {
712
768
  output = JSON.stringify(value);
713
769
  }
714
770
  if (output !== undefined) {
715
- if (Buffer.byteLength(output, "utf8") > 2 * 1024 * 1024) {
771
+ if (Buffer.byteLength(output, "utf8") > maximumBytes) {
716
772
  throw projectionError(
717
773
  EVOLUTION_PROJECTION_INVALID_CODE,
718
- "projection exceeds the 2 MiB admission limit",
774
+ maximumBytes === 2 * 1024 * 1024
775
+ ? "projection exceeds the 2 MiB admission limit"
776
+ : "Agent image transport exceeds its canonical byte budget",
719
777
  );
720
778
  }
721
779
  return output;
@@ -757,7 +815,9 @@ function canonicalJson(value, seen = new Set(), depth = 0) {
757
815
  "projection arrays must use enumerable own data entries",
758
816
  );
759
817
  }
760
- entries.push(canonicalJson(descriptor.value, seen, depth + 1));
818
+ entries.push(
819
+ canonicalJson(descriptor.value, seen, depth + 1, maximumBytes),
820
+ );
761
821
  }
762
822
  output = `[${entries.join(",")}]`;
763
823
  } else {
@@ -784,24 +844,29 @@ function canonicalJson(value, seen = new Set(), depth = 0) {
784
844
  );
785
845
  }
786
846
  fields.push(
787
- `${JSON.stringify(key)}:${canonicalJson(descriptor.value, seen, depth + 1)}`,
847
+ `${JSON.stringify(key)}:${canonicalJson(descriptor.value, seen, depth + 1, maximumBytes)}`,
788
848
  );
789
849
  }
790
850
  output = `{${fields.join(",")}}`;
791
851
  }
792
852
  seen.delete(value);
793
- if (Buffer.byteLength(output, "utf8") > 2 * 1024 * 1024) {
853
+ if (Buffer.byteLength(output, "utf8") > maximumBytes) {
794
854
  throw projectionError(
795
855
  EVOLUTION_PROJECTION_INVALID_CODE,
796
- "projection exceeds the 2 MiB admission limit",
856
+ maximumBytes === 2 * 1024 * 1024
857
+ ? "projection exceeds the 2 MiB admission limit"
858
+ : "Agent image transport exceeds its canonical byte budget",
797
859
  );
798
860
  }
799
861
  return output;
800
862
  }
801
863
 
802
- function digest(value, domain) {
864
+ function digest(value, domain, maximumBytes) {
803
865
  return `sha256:${createHash("sha256")
804
- .update(`${domain}\0${canonicalJson(value)}`, "utf8")
866
+ .update(
867
+ `${domain}\0${canonicalJson(value, new Set(), 0, maximumBytes)}`,
868
+ "utf8",
869
+ )
805
870
  .digest("hex")}`;
806
871
  }
807
872
 
@@ -1296,6 +1361,43 @@ function sanitizeString(value, path, findings, injections, ruleset, patterns) {
1296
1361
  return output;
1297
1362
  }
1298
1363
 
1364
+ function isAgentCodeTextPath(payload, path, resultToolNames) {
1365
+ if (
1366
+ path[0] !== "messages" ||
1367
+ !/^\d+$/u.test(path[1] ?? "") ||
1368
+ !Array.isArray(payload?.messages)
1369
+ ) {
1370
+ return false;
1371
+ }
1372
+ const message = payload.messages[Number(path[1])];
1373
+ if (!message || typeof message !== "object") return false;
1374
+ if (
1375
+ path[2] === "tool_calls" &&
1376
+ /^\d+$/u.test(path[3] ?? "") &&
1377
+ path[4] === "function" &&
1378
+ path[5] === "arguments"
1379
+ ) {
1380
+ const call = message.tool_calls?.[Number(path[3])];
1381
+ const fields = path.slice(6);
1382
+ if (fields[0] === "$json") fields.shift();
1383
+ return call?.function?.name === "run_code" && fields[0] === "code";
1384
+ }
1385
+ if (path[2] === "content" && message.role === "tool") {
1386
+ const callId = message.tool_call_id;
1387
+ return payload.messages.some(
1388
+ (candidate) =>
1389
+ candidate?.role === "assistant" &&
1390
+ Array.isArray(candidate.tool_calls) &&
1391
+ candidate.tool_calls.some(
1392
+ (call) =>
1393
+ call?.id === callId &&
1394
+ resultToolNames.includes(call?.function?.name),
1395
+ ),
1396
+ );
1397
+ }
1398
+ return false;
1399
+ }
1400
+
1299
1401
  function sanitizePayload(
1300
1402
  payload,
1301
1403
  ruleset = RULESET,
@@ -1306,8 +1408,10 @@ function sanitizePayload(
1306
1408
  let nodes = 0;
1307
1409
  let truncated = false;
1308
1410
  const jsonText = ruleset.jsonTextPolicy
1309
- ? createEvidenceJsonTextBoundary((message) =>
1310
- projectionError(EVOLUTION_PROJECTION_INVALID_CODE, message),
1411
+ ? createEvidenceJsonTextBoundary(
1412
+ (message) =>
1413
+ projectionError(EVOLUTION_PROJECTION_INVALID_CODE, message),
1414
+ ruleset.jsonTextPolicy,
1311
1415
  )
1312
1416
  : null;
1313
1417
  const visit = (value, path, depth, layer = 0) => {
@@ -1323,7 +1427,9 @@ function sanitizePayload(
1323
1427
  }
1324
1428
  const toolArguments = jsonText && isAgentToolArgumentsPath(path);
1325
1429
  const opaqueTransportBlock =
1326
- ruleset === AGENT_MODEL_RULESET
1430
+ ruleset === AGENT_MODEL_RULESET ||
1431
+ ruleset === AGENT_MODEL_RULESET_V4 ||
1432
+ ruleset === AGENT_MODEL_RULESET_V3
1327
1433
  ? projectAgentOpaqueTransportBlock(value, path.join("."))
1328
1434
  : null;
1329
1435
  if (opaqueTransportBlock !== null) return opaqueTransportBlock;
@@ -1337,11 +1443,34 @@ function sanitizePayload(
1337
1443
  const plain = (text) =>
1338
1444
  sanitizeString(text, path, findings, injections, ruleset, patterns);
1339
1445
  if (!jsonText) return plain(value);
1446
+ const codeText =
1447
+ ruleset.codeTextPolicy ===
1448
+ "paired-code-source-and-result-literal-scan-v1" &&
1449
+ isAgentCodeTextPath(payload, path, ruleset.codeTextResultTools);
1340
1450
  const output = jsonText(value, {
1341
1451
  layer,
1342
1452
  objectOnly: toolArguments,
1453
+ codeText,
1454
+ // Only direct message text can contain Markdown code examples. Tool
1455
+ // arguments and recursively decoded strings keep their existing rules.
1456
+ fencedCodeLanguages:
1457
+ path[0] === "messages" &&
1458
+ /^\d+$/u.test(path[1] ?? "") &&
1459
+ path[2] === "content" &&
1460
+ (path.length === 3 || (path.length === 5 && path[4] === "text"))
1461
+ ? ruleset.fencedCodeLanguages
1462
+ : null,
1343
1463
  visit: (decoded, nextLayer) =>
1344
- visit(decoded, [...path, "$json"], depth + 1, nextLayer),
1464
+ visit(
1465
+ decoded,
1466
+ [...path, "$json"],
1467
+ // Serialized JSON has its own unchanged depth/layer limits. Its
1468
+ // traversal must not charge protocol nesting as decoded depth.
1469
+ ruleset.decodedDepthPolicy === "independent-bounded-json-depth-v1"
1470
+ ? 0
1471
+ : depth + 1,
1472
+ nextLayer,
1473
+ ),
1345
1474
  plain,
1346
1475
  equal: (left, right) => canonicalJson(left) === canonicalJson(right),
1347
1476
  });
@@ -3045,7 +3174,7 @@ function validateBundleIntegrity(bundle) {
3045
3174
  validateRedactionSummary(model.redactionSummary);
3046
3175
  if (
3047
3176
  !Array.isArray(model.injectionFindings) ||
3048
- model.injectionFindings.length > RULESET.maxNodes * 2
3177
+ model.injectionFindings.length > ruleset.maxNodes * 2
3049
3178
  ) {
3050
3179
  throw projectionError(
3051
3180
  EVOLUTION_PROJECTION_INVALID_CODE,
@@ -3187,12 +3316,17 @@ function validateBundleIntegrity(bundle) {
3187
3316
  }
3188
3317
  if (
3189
3318
  ruleset === AGENT_MODEL_RULESET ||
3319
+ ruleset === AGENT_MODEL_RULESET_V4 ||
3320
+ ruleset === AGENT_MODEL_RULESET_V3 ||
3190
3321
  ruleset === AGENT_MODEL_RULESET_V2 ||
3191
3322
  ruleset === AGENT_MODEL_RULESET_V1
3192
3323
  ) {
3193
3324
  snapshotAgentModelRequest(model.content, {
3194
3325
  allowStructuredArgumentText: ruleset !== AGENT_MODEL_RULESET_V1,
3195
- allowOpaqueTransportBlocks: ruleset === AGENT_MODEL_RULESET,
3326
+ allowOpaqueTransportBlocks:
3327
+ ruleset === AGENT_MODEL_RULESET ||
3328
+ ruleset === AGENT_MODEL_RULESET_V4 ||
3329
+ ruleset === AGENT_MODEL_RULESET_V3,
3196
3330
  });
3197
3331
  if (
3198
3332
  model.truncated ||
@@ -3477,6 +3611,9 @@ export class EvolutionEvidenceProjector {
3477
3611
  const sourceInputDigest = digest(
3478
3612
  payload,
3479
3613
  "chainlesschain.evolution-raw-plaintext/v2",
3614
+ ruleset === AGENT_MODEL_RULESET
3615
+ ? AGENT_MODEL_IMAGE_LIMITS.maxCanonicalRequestBytes
3616
+ : undefined,
3480
3617
  );
3481
3618
  const sourceEnvelopeDigest = digest(
3482
3619
  input.sourceEnvelope,
@@ -0,0 +1,115 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ import { ArtifactStore } from "../artifact-store.js";
5
+ import {
6
+ EvolutionArtifactPorts,
7
+ captureEvolutionArtifactStoreDirectoryBoundary,
8
+ captureEvolutionLedgerBatchReadWindow,
9
+ } from "./evolution-artifact-ports.js";
10
+
11
+ export const EVOLUTION_TYPED_EVIDENCE_LAYOUT = "typed-evidence-v1";
12
+ export const EVOLUTION_EVIDENCE_STORAGE_TYPES = Object.freeze([
13
+ "source-evidence",
14
+ "model-projection",
15
+ "trusted-projection",
16
+ "receipt",
17
+ "evidence",
18
+ ]);
19
+
20
+ export function validateEvidenceStorageLayout(value) {
21
+ if (value !== "legacy" && value !== EVOLUTION_TYPED_EVIDENCE_LAYOUT)
22
+ throw new TypeError("Unsupported Evidence storage layout");
23
+ return value;
24
+ }
25
+
26
+ // Callers must supply events freshly authenticated by the genuine Run adapter.
27
+ // A later event, projection, or sidecar is never a layout authority.
28
+ export function evidenceStorageLayoutForRun(events, emptyLayout = "legacy") {
29
+ validateEvidenceStorageLayout(emptyLayout);
30
+ if (events.length === 0) return emptyLayout;
31
+ const data = events[0].data;
32
+ if (!data || !Object.hasOwn(data, "evidenceStorageLayout")) return "legacy";
33
+ if (data.evidenceStorageLayout !== EVOLUTION_TYPED_EVIDENCE_LAYOUT)
34
+ throw new TypeError("Unsupported authenticated Evidence storage layout");
35
+ return EVOLUTION_TYPED_EVIDENCE_LAYOUT;
36
+ }
37
+
38
+ function physicalStore(directory) {
39
+ return [
40
+ directory,
41
+ path.join(directory, "files"),
42
+ path.join(directory, "index.jsonl"),
43
+ ].map((location, index) => {
44
+ const stat = fs.lstatSync(location, { bigint: true });
45
+ if (
46
+ stat.isSymbolicLink() ||
47
+ (index < 2 ? !stat.isDirectory() : !stat.isFile() || stat.nlink !== 1n)
48
+ )
49
+ throw new Error(
50
+ "Typed Evidence store must retain physical directories and a single-link index",
51
+ );
52
+ return {
53
+ location,
54
+ dev: stat.dev,
55
+ ino: stat.ino,
56
+ birthtimeNs: stat.birthtimeNs,
57
+ };
58
+ });
59
+ }
60
+
61
+ /** Separate genuine stores; no change to artifact locators or ledger authority. */
62
+ export function createTypedEvidenceArtifactPorts({
63
+ rootDir,
64
+ tenantId,
65
+ audience,
66
+ artifactAuthority,
67
+ now,
68
+ existingRun,
69
+ }) {
70
+ const directories = EVOLUTION_EVIDENCE_STORAGE_TYPES.map((type) =>
71
+ path.join(rootDir, type),
72
+ );
73
+ // Preflight every shard before any constructor can recreate a missing one.
74
+ const before = existingRun ? directories.map(physicalStore) : null;
75
+ const result = {};
76
+ const identities = new Set();
77
+ for (const [index, type] of EVOLUTION_EVIDENCE_STORAGE_TYPES.entries()) {
78
+ const port = new EvolutionArtifactPorts({
79
+ tenantId,
80
+ audience,
81
+ artifactStore: new ArtifactStore({ dir: directories[index], now }),
82
+ allowedTypes: [type],
83
+ envelopeSigner: artifactAuthority.envelopeSigner,
84
+ envelopeVerifier: artifactAuthority.envelopeVerifier,
85
+ currentAuthorityResolver: artifactAuthority.currentAuthorityResolver,
86
+ now,
87
+ });
88
+ const boundary = captureEvolutionArtifactStoreDirectoryBoundary(port);
89
+ const after = physicalStore(directories[index]);
90
+ for (const [entryIndex, entry] of after.entries()) {
91
+ const previous = before?.[index][entryIndex];
92
+ if (
93
+ previous &&
94
+ ["dev", "ino", "birthtimeNs"].some(
95
+ (key) => previous[key] !== entry[key],
96
+ )
97
+ )
98
+ throw new Error("Typed Evidence store identity changed during reopen");
99
+ const identity = `${entry.dev}:${entry.ino}`;
100
+ if (identities.has(identity))
101
+ throw new Error("Typed Evidence stores must be distinct");
102
+ identities.add(identity);
103
+ }
104
+ boundary.recheck();
105
+ // Authenticate bounded index structure through the original port reader.
106
+ // Payloads and current authority remain freshly checked on actual reads.
107
+ captureEvolutionLedgerBatchReadWindow(
108
+ port.createEvolutionLedgerArtifactResolver({
109
+ purpose: "evidence-projection",
110
+ }),
111
+ )(() => undefined);
112
+ result[type] = port;
113
+ }
114
+ return Object.freeze(result);
115
+ }
@@ -4,6 +4,7 @@ import path from "node:path";
4
4
  import { types } from "node:util";
5
5
  import { ensurePrivateDirectory, ensurePrivateFile } from "../secure-fs.js";
6
6
  import { withFileLock } from "../with-file-lock.js";
7
+ import { evolutionPrivateStorageOptions } from "./evolution-private-storage.js";
7
8
  import { createEvolutionPhysicalStateReader } from "./evolution-physical-state-reader.js";
8
9
  import {
9
10
  createEvolutionWitnessSegments,
@@ -246,7 +247,10 @@ export function createEvolutionFileWitness({
246
247
  "maximumHistoryBytes must be a safe integer of at least 4096",
247
248
  );
248
249
  }
249
- const secureOptions = { deps: { fs: fsImpl }, failIfUnavailable: true };
250
+ const secureOptions = evolutionPrivateStorageOptions(fsImpl);
251
+ const secureFileOptions = evolutionPrivateStorageOptions(fsImpl, {
252
+ file: true,
253
+ });
250
254
  ensurePrivateDirectory(directory, secureOptions);
251
255
  const readerOptions = {
252
256
  fsImpl,
@@ -651,7 +655,7 @@ export function createEvolutionFileWitness({
651
655
  const bytes = reader.read(file, {
652
656
  maximumBytes: byteLimit,
653
657
  allowAbsent,
654
- prepareFile: (name) => ensurePrivateFile(name, secureOptions),
658
+ prepareFile: (name) => ensurePrivateFile(name, secureFileOptions),
655
659
  });
656
660
  recheckStorage();
657
661
  return bytes;
@@ -723,7 +727,7 @@ export function createEvolutionFileWitness({
723
727
  fsImpl.closeSync(descriptor);
724
728
  descriptor = undefined;
725
729
  fsImpl.renameSync(temporary, file);
726
- ensurePrivateFile(file, secureOptions);
730
+ ensurePrivateFile(file, secureFileOptions);
727
731
  descriptor = fsImpl.openSync(file, "r+");
728
732
  fsImpl.fsyncSync(descriptor);
729
733
  fsImpl.closeSync(descriptor);
@@ -5,6 +5,7 @@ import { types as utilTypes } from "node:util";
5
5
 
6
6
  import { ensurePrivateDirectory, ensurePrivateFile } from "../secure-fs.js";
7
7
  import { withFileLock } from "../with-file-lock.js";
8
+ import { evolutionPrivateStorageOptions } from "./evolution-private-storage.js";
8
9
  import {
9
10
  createEvolutionManifestStateReader,
10
11
  captureEvolutionManifestStateReaderDirectoryBoundary,
@@ -76,7 +77,10 @@ export function createEvolutionLedgerFileManifestCatalogBackend({
76
77
  }
77
78
  const directory = path.resolve(directoryPath);
78
79
  const file = path.join(directory, "manifest-catalog.json");
79
- const secureOptions = { deps: { fs: fsImpl }, failIfUnavailable: true };
80
+ const secureOptions = evolutionPrivateStorageOptions(fsImpl);
81
+ const secureFileOptions = evolutionPrivateStorageOptions(fsImpl, {
82
+ file: true,
83
+ });
80
84
  ensurePrivateDirectory(directory, secureOptions);
81
85
 
82
86
  const stateReader = createEvolutionManifestStateReader({
@@ -131,7 +135,7 @@ export function createEvolutionLedgerFileManifestCatalogBackend({
131
135
  fsImpl.closeSync(descriptor);
132
136
  descriptor = undefined;
133
137
  fsImpl.renameSync(temporary, file);
134
- ensurePrivateFile(file, secureOptions);
138
+ ensurePrivateFile(file, secureFileOptions);
135
139
  descriptor = fsImpl.openSync(file, "r+");
136
140
  fsImpl.fsyncSync(descriptor);
137
141
  fsImpl.closeSync(descriptor);
@@ -5,6 +5,7 @@ import { types as utilTypes } from "node:util";
5
5
 
6
6
  import { ensurePrivateDirectory, ensurePrivateFile } from "../secure-fs.js";
7
7
  import { withFileLock } from "../with-file-lock.js";
8
+ import { evolutionPrivateStorageOptions } from "./evolution-private-storage.js";
8
9
  import {
9
10
  createEvolutionManifestStateReader,
10
11
  captureEvolutionManifestStateReaderDirectoryBoundary,
@@ -96,7 +97,10 @@ export function createEvolutionLedgerFileManifestHeadBackend({
96
97
  throw new TypeError("manifest head maximumBytes must be at least 4096");
97
98
  }
98
99
  const file = path.join(directory, "manifest-head.json");
99
- const secureOptions = { deps: { fs: fsImpl }, failIfUnavailable: true };
100
+ const secureOptions = evolutionPrivateStorageOptions(fsImpl);
101
+ const secureFileOptions = evolutionPrivateStorageOptions(fsImpl, {
102
+ file: true,
103
+ });
100
104
  ensurePrivateDirectory(directory, secureOptions);
101
105
 
102
106
  const invokeCrashHook = (phase, details) => {
@@ -158,7 +162,7 @@ export function createEvolutionLedgerFileManifestHeadBackend({
158
162
  descriptor = undefined;
159
163
  invokeCrashHook("after-stage", { file, temporary });
160
164
  fsImpl.renameSync(temporary, file);
161
- ensurePrivateFile(file, secureOptions);
165
+ ensurePrivateFile(file, secureFileOptions);
162
166
  descriptor = fsImpl.openSync(file, "r+");
163
167
  fsImpl.fsyncSync(descriptor);
164
168
  fsImpl.closeSync(descriptor);