chainlesschain 0.166.9 → 0.166.13

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 (232) hide show
  1. package/README.md +33 -0
  2. package/bin/chainlesschain.js +5 -0
  3. package/package.json +5 -2
  4. package/src/assets/web-panel/assets/{AIOps-DJvpifGx.js → AIOps-BN25cNOD.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-D2UhuF_A.js → ActionButton-Da9IP-m5.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-C9ho9obu.js → Analytics-D7hkEvQm.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-BvRCpFK3.js → AppLayout-CCV4Xnbc.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-jxrySvpk.js → Artifacts-CVSnVJeA.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-ovEw0ZYl.js → Audit-CuYdw5Ag.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-D7H5z6zS.js → BackgroundAgents-DZCnK-Tf.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-BuXob8za.js → Backup-cV9FdpTy.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-CtnszuQ2.js → BaseInput-BRnv6YSp.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-B_mYE8fJ.js → Chat-Bw5w87P4.js} +6 -6
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-C0GjtUAw.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-ierdtcJD.js → Checkbox-DaoTqcdt.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-3VKPJD_B.js → Codegen-B4dYcEIi.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-1EdMyf5P.js → Col-mAhuOeuD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-D6H7UA8K.js → Community-BK6KEdBk.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-BBAZvYIm.js → Compact-CCglmNu5.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-CgsTrAoj.js → Compliance-Cm8S4of7.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-tnZgLoTE.js → Cowork-Dhs1QLMe.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-CPpZw2Nh.js → Cron-CLlhmXWk.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-BymBcp5z.js → Crosschain-BnHVbaNs.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-DKPxS_K1.js → DID-UzQP9-0O.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-DvJhEmH9.js → Dashboard-CBdlPClz.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-b8iQyQIZ.js → Dropdown-axIRPdq1.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer--0-A-zKb.js → EmailListRenderer-DUalW5rx.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-C12iDN06.js → FamilyGuardDashboard-Bl4W9luY.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-BRhaE2Z8.js → Federation-C1yP-uEu.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-C4dnq7yf.js → FormItemContext-Xh6Ig5q8.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-CGAdbR5n.js → GenericCardRenderer-C2cz3bt2.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-4eA2fYzL.js → Git-C_z63ixg.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-BJuY9Y-9.js → Governance-BYqB33_3.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-DZ5Dy4up.js → Inference-CEULuArm.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-BMTjRs4A.js → KnowledgeGraph-fgMsu-0H.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-BKEeQEfJ.js → Logs-DO9Hdcec.js} +2 -2
  37. package/src/assets/web-panel/assets/MarkdownRenderer-BkrK04xW.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-Dhho4fEg.js → Marketplace-B8zyLiFe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-BW6xxSlU.js → McpTools-BLAN2mWW.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-mPqlpSkq.js → Memory-CrQcFM7u.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-Cb9N_DQI.js → MobileBridge-DVnyiiU-.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-BNs8tah_.js → MobileProjects-qjCME5OD.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-CaxBt8tn.js → Mtc-4JE3C3It.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-DRPQbp3t.js → MtcAudit-CjBuak9I.js} +5 -5
  45. package/src/assets/web-panel/assets/{Multisig-CRm-d8bK.js → Multisig-BtPcYQcC.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-BCCk3LPs.js → NLProgramming-Cx653_Ba.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-Cv8SN8gN.js → Notes-CkuD3YzS.js} +4 -4
  48. package/src/assets/web-panel/assets/{NotificationSettings-CggIvTh5.js → NotificationSettings-BgNgU7HH.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-BW3_bV12.js → OrderTableRenderer-BTC8W0a-.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-BuRE-VCO.js → Organization-Dmd4Hjxz.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-DBrm1gju.js → Overflow-C_5DA-G0.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-CWVnDYgS.js → P2P-uwslV4XC.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-8RKUIpte.js → PdhVaultBrowser-CuNgwVnX.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-tDUAxogW.js → Permissions-CJayVX9H.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-Dv2-CFis.js → PersonalDataHub-Cb05H5go.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-DM6kvFni.js → Pipeline-BZlGKapZ.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-DzK-yL0d.js → Privacy-BIzZWYzd.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-B5UrNpkj.js → ProjectInit-vEYYyQXQ.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-CxJD43oW.js → ProjectSettings-MZqTy5CC.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-CRARUOl8.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-CYl4jRYK.js → Providers-80VAK8PX.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-DeH2T0fH.js → QrScannerModal-CzRSoIwK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-Bw9k_kTk.js → QuickAsk-BpwQ2n4C.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-Bl_jGwoi.js → Recommend-BC03TZ79.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-d6u01Kq0.js → RemoteSession-DE59-jaa.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-Ds_Dfr-k.js → Reputation-DOHmeWyA.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-BpQUQTNj.js → Row-hc5RZl1D.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-BatpZBGt.js → RssFeed-Cv5uMP7E.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-D7hOObzi.js → Search-qohu7Ug0.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-dXQ4FKNt.js → Security-drCPFWV5.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-D8wInGPa.js → Services-BAEgUeRy.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DXQCoYpM.js → Skeleton-CkJkKBlo.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-D3oLRIVn.js → Skills-bMuKEpez.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-BmP4-LnJ.js → Sla-DxWQVHRC.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-DLj-xzro.js → SpeechSettings-BpS8idmV.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-8KKaaRMr.js → SyncSettings-BPBLlW5v.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-GyK42I7C.js → Tasks-C4SLEeUh.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-n1y_8UBG.js → Templates-r-wfU39U.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-B39nBph8.js → Tenant-C7vjRmLN.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-DCQoOKXe.js → Terminal-DdzeFCV2.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-BkhbDfXk.js → TimelineRenderer-CYyWN2KD.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-BeHIIU8D.js → Tokens-D8A9osUg.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-BHvWXVOb.js → Trigger-DBvrNlyS.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-y2WaOSto.js → Trust-DBVAGc7o.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DBFeJBzt.js → UkeySign-C1vQUCRJ.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-BEOWitC-.js → VideoEditing-BKs4dah4.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-BITedTe6.js → Wallet-ByIuj3lD.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-DMwlJVin.js → WebAuthn-DYlAFCm9.js} +3 -3
  89. package/src/assets/web-panel/assets/{WorkflowEditor-CKfGFEu1.js → WorkflowEditor-Dwyadd0c.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-DR6gnBGF.js → chat-Bm2f3s08.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-C_Hw5NCn.js → colors-C8ORSh7V.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-B8IPwsEu.js → compact-item-1iVlnsM-.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-D-u4JVnJ.js → createContext-CmqNyUSL.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-B69RCDDH.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-CZubdS4D.js → hasIn-rUMaX3Ul.js} +1 -1
  96. package/src/assets/web-panel/assets/index-9biMQ-tw.js +1 -0
  97. package/src/assets/web-panel/assets/{index-C25rOz7O.js → index-B53c3diB.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CfniPP5p.js → index-B59OWAs7.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-11ASqx-A.js → index-B8BrB0Ls.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-auyNYjLo.js → index-BC32_0xT.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Ctje8Vl3.js → index-BC8Wb6cy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cg2bCeol.js → index-BCOhTILd.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-D1w96gg9.js → index-BFniLMn9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-k1Xa5iw1.js → index-BIvM-uAX.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DuOU5apg.js → index-BK-RY0-7.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-D47jt8ET.js → index-BQL9r73Y.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-C2VmtNaQ.js → index-BVtnizyC.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Bizm87cX.js → index-Bf1PlIHp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dt-w3xQ7.js → index-Bgw4Y2rU.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-ffe7bvqP.js → index-BgwLNxmr.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Cl5RpreD.js → index-C-J5-pGH.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-idZKyADQ.js → index-C-ZIHi42.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-LvjAKDSl.js → index-C3B1S-mW.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DmRcgiYT.js → index-C5RfRciU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-rYBHSDcJ.js → index-CCEyz58d.js} +1 -1
  116. package/src/assets/web-panel/assets/index-COie87kl.js +1 -0
  117. package/src/assets/web-panel/assets/{index-DcFjRT-K.js → index-CTfEmKK0.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DjRrqooR.js → index-CfiHyVyl.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DpjHpRoq.js → index-CkFvuAex.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-BzoFanEQ.js → index-D98FXb0w.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cbm8F0M2.js → index-DDHk911Q.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BXS6wYJZ.js → index-DJxtPFOh.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DY6MHo9D.js → index-DVJ1uKf4.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CiXkhOkY.js → index-Dcck8QfW.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-mYZJxGH6.js → index-DgUE51Pz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CqmLw8cs.js → index-Dsve5Gkv.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-xoNssgz_.js → index-DvedhJeM.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DfnzrUxU.js → index-DwMdWKiF.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Bi21Etg4.js → index-OcbzdRpT.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DJ6pG79m.js → index-fPK6GFEg.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-_nL79NT8.js → index-geQinnns.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DTosx2Wu.js → index-pHWA7bmM.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-cVqbas5C.js → index-reUHhuz8.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Bv2132PO.js → index-tqTx5wXo.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-lcU_dT2r.js → initDefaultProps-CuA-cpkL.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-Dc7UNXZ1.js → motion-CimmE_9b.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-Cll8ZXaL.js → move-DlGlrltz.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-CAb_yLIM.js → mtc-parser-CK6BJQ07.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-DurYMyTe.js → omit-BKjBfZfB.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-BITQyOlw.js → pickAttrs-B2chVYw9.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-Dg1rH91i.js → placementArrow-BW8aLJJ3.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-D_EWIeac.js → responsiveObserve-dXlPl66S.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-lK4d3zsh.js → slide-hSa89S4G.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-Bflq-Git.js → statusUtils-DM6KLt-s.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Ccp0I-wt.js → styleChecker-C9MQAK15.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-CYZbByYA.js → useFlexGapSupport-BpQDpP0z.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-B_x0nxFD.js → useFs-C7rtRViA.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-DW55rL85.js → usePersonalDataHub-Dm15xafq.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-Ca6MH3W8.js → vnode-mEiEytw4.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-NdHelOog.js → zoom-DzPxflhY.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +5 -5
  153. package/src/commands/agent.js +51 -20
  154. package/src/commands/compact.js +349 -3
  155. package/src/commands/context.js +72 -1
  156. package/src/commands/graph.js +26 -15
  157. package/src/commands/hmemory.js +21 -0
  158. package/src/commands/hook.js +256 -28
  159. package/src/commands/memory.js +209 -42
  160. package/src/commands/promcomp.js +17 -0
  161. package/src/commands/serve.js +94 -10
  162. package/src/commands/session.js +2 -3
  163. package/src/commands/team.js +7 -1
  164. package/src/data/changelog.json +41 -2
  165. package/src/gateways/ws/session-core-protocol.js +62 -3
  166. package/src/gateways/ws/session-protocol.js +123 -15
  167. package/src/gateways/ws/ws-agent-handler.js +157 -9
  168. package/src/gateways/ws/ws-session-gateway.js +204 -30
  169. package/src/generated/cc-agent-protocol.schema.json +2094 -4
  170. package/src/harness/prompt-compressor.js +5 -55
  171. package/src/lib/agent-sandbox.js +14 -4
  172. package/src/lib/agent-team/team-distributed-graph-bridge.js +3 -3
  173. package/src/lib/app-server/context-memory-notifications.js +54 -0
  174. package/src/lib/app-server/rollout-store-factory.js +115 -0
  175. package/src/lib/app-server/rollout-store.js +310 -23
  176. package/src/lib/app-server/server.js +184 -7
  177. package/src/lib/app-server/sqlite-rollout-store.js +59 -16
  178. package/src/lib/auto-mode-config.js +26 -0
  179. package/src/lib/causal-observability.js +13 -1
  180. package/src/lib/context-memory-kernel/authority.js +95 -0
  181. package/src/lib/context-memory-kernel/durable-memory-port.js +296 -0
  182. package/src/lib/context-memory-kernel/index.js +8 -0
  183. package/src/lib/context-memory-kernel/jsonl-session-context-port.js +232 -0
  184. package/src/lib/context-memory-kernel/live-compaction.js +375 -0
  185. package/src/lib/context-memory-kernel/memory-service.js +667 -0
  186. package/src/lib/context-memory-kernel/message-adapter.js +451 -0
  187. package/src/lib/context-memory-kernel/privacy-purge-port.js +244 -0
  188. package/src/lib/context-memory-kernel/provider-context.js +192 -0
  189. package/src/lib/context-memory-kernel/runtime.js +61 -0
  190. package/src/lib/direct-model-usage.js +22 -18
  191. package/src/lib/graph-kernel/cutover-authority-resolver.js +4 -5
  192. package/src/lib/graph-kernel/cutover-ledger.js +2 -2
  193. package/src/lib/graph-kernel/event-store.js +3 -5
  194. package/src/lib/graph-kernel/index.js +2 -0
  195. package/src/lib/graph-kernel/migration-saga.js +2 -2
  196. package/src/lib/graph-kernel/production-cutover-evidence.js +976 -0
  197. package/src/lib/graph-kernel/retirement-evidence.js +12 -4
  198. package/src/lib/hierarchical-memory.js +22 -0
  199. package/src/lib/hook-audit-store.js +170 -0
  200. package/src/lib/hook-event-bus.cjs +0 -0
  201. package/src/lib/hook-manager.js +25 -83
  202. package/src/lib/hook-runtime-adapters.js +233 -0
  203. package/src/lib/hook-runtime-contract.cjs +291 -0
  204. package/src/lib/hook-runtime-contract.js +21 -0
  205. package/src/lib/hook-trust.js +210 -0
  206. package/src/lib/hooks-v2-producers.js +52 -6
  207. package/src/lib/hooks-v2-runtime.js +443 -178
  208. package/src/lib/llm-pricing.js +10 -0
  209. package/src/lib/memory-manager.js +29 -4
  210. package/src/lib/model-context-window.js +52 -0
  211. package/src/lib/permanent-memory.js +17 -0
  212. package/src/lib/plan-mode.js +8 -4
  213. package/src/lib/process-execution-broker/index.js +208 -16
  214. package/src/lib/runtime-usage-ledger.js +20 -0
  215. package/src/lib/session-consolidator.js +59 -0
  216. package/src/lib/session-core-singletons.js +17 -4
  217. package/src/lib/session-hooks.js +29 -2
  218. package/src/lib/session-transcript-migration.js +188 -0
  219. package/src/lib/settings-hook-events.cjs +37 -401
  220. package/src/lib/settings-hook-events.js +210 -8
  221. package/src/lib/settings-hooks.cjs +42 -83
  222. package/src/lib/ws-session-manager.js +4 -1
  223. package/src/repl/agent-repl.js +186 -53
  224. package/src/runtime/agent-core.js +376 -350
  225. package/src/runtime/headless-runner.js +40 -33
  226. package/src/runtime/headless-stream.js +131 -30
  227. package/src/assets/web-panel/assets/ChatBubbleRenderer-DaiA6CsX.js +0 -1
  228. package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +0 -1
  229. package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +0 -1
  230. package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +0 -1
  231. package/src/assets/web-panel/assets/index-BQ3213fz.js +0 -1
  232. package/src/assets/web-panel/assets/index-vJagfET2.js +0 -1
@@ -65,11 +65,21 @@ export const PRICE_TABLE = Object.freeze({
65
65
  { match: "o1", in: 15, out: 60 },
66
66
  ],
67
67
  deepseek: [
68
+ // DeepSeek V4 launch-list rates for the versioned 2026-04 model ids.
69
+ // Keep these ahead of the legacy aliases so formal budget gates never
70
+ // treat the current V4 models as unpriced remote usage.
71
+ { match: "deepseek-v4-pro", in: 0.435, out: 0.87 },
72
+ { match: "deepseek-v4-flash", in: 0.14, out: 0.28 },
68
73
  { match: "reasoner", in: 0.55, out: 2.19 },
69
74
  { match: "chat", in: 0.27, out: 1.1 },
70
75
  ],
71
76
  // Volcengine Doubao — rough USD conversion of public RMB list pricing.
72
77
  volcengine: [
78
+ // Third-party DeepSeek V4 ids exposed by Ark use the same token-accounting
79
+ // shape. Pricing them explicitly is required by USD-capped Agent/Team runs;
80
+ // falling through to the Doubao patterns would fail closed as unpriced.
81
+ { match: "deepseek-v4-pro", in: 0.435, out: 0.87 },
82
+ { match: "deepseek-v4-flash", in: 0.14, out: 0.28 },
73
83
  // Doubao Seed 2.0 family (2026, e.g. doubao-seed-2-0-lite-260215) is
74
84
  // natively multimodal. Rates ≈ official CNY ÷ ~7.2 (lite ≤32k is 0.6/3.6
75
85
  // CNY → $0.08/$0.50); the generic "seed" rate below underprices 2.0 output.
@@ -8,6 +8,18 @@
8
8
  import fs from "fs";
9
9
  import path from "path";
10
10
  import { likePrefix, escapeLike } from "./sql-like.js";
11
+ import {
12
+ assertLegacyMutationAllowed,
13
+ resolveCliContextMemoryCutover,
14
+ } from "./context-memory-kernel/authority.js";
15
+
16
+ function assertLegacyMemoryManagerMutationAllowed(operation) {
17
+ assertLegacyMutationAllowed(
18
+ resolveCliContextMemoryCutover({
19
+ scopeKey: `cli:legacy-memory-manager:${operation}`,
20
+ }),
21
+ );
22
+ }
11
23
 
12
24
  /**
13
25
  * Atomically write a UTF-8 file: a crash mid-write must not truncate MEMORY.md
@@ -57,6 +69,15 @@ function ensureMemoryTable(db) {
57
69
  `);
58
70
  }
59
71
 
72
+ function memoryTableExists(db) {
73
+ const row = db
74
+ .prepare(
75
+ "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_entries'",
76
+ )
77
+ .get();
78
+ return Boolean(row);
79
+ }
80
+
60
81
  /**
61
82
  * Get the memory directory path
62
83
  */
@@ -68,6 +89,7 @@ export function getMemoryDir(dataDir) {
68
89
  * Add an entry to memory (stored in DB)
69
90
  */
70
91
  export function addMemory(db, content, options = {}) {
92
+ assertLegacyMemoryManagerMutationAllowed("add");
71
93
  ensureMemoryTable(db);
72
94
 
73
95
  if (!content || !content.trim()) {
@@ -142,7 +164,9 @@ export function listMemory(db, options = {}) {
142
164
  * ordered deterministically so the same DB exports identically.
143
165
  */
144
166
  export function exportMemory(db) {
145
- ensureMemoryTable(db);
167
+ // Canonical cutover calls this as a one-time read-only importer. Do not
168
+ // create a legacy table merely because no legacy data exists.
169
+ if (!memoryTableExists(db)) return [];
146
170
  return db
147
171
  .prepare(
148
172
  `SELECT id, content, category, importance, source, created_at, updated_at
@@ -162,6 +186,7 @@ function _nowSqlite() {
162
186
  * updated_at. Never aborts mid-batch; returns {ok, imported, failed, errors}.
163
187
  */
164
188
  export function importMemory(db, entries) {
189
+ assertLegacyMemoryManagerMutationAllowed("import");
165
190
  ensureMemoryTable(db);
166
191
  if (!Array.isArray(entries)) {
167
192
  throw new Error("importMemory: entries must be a JSON array");
@@ -208,6 +233,7 @@ export function importMemory(db, entries) {
208
233
  * Delete a memory entry
209
234
  */
210
235
  export function deleteMemory(db, id) {
236
+ assertLegacyMemoryManagerMutationAllowed("delete");
211
237
  ensureMemoryTable(db);
212
238
 
213
239
  // Try exact match first, then prefix match
@@ -228,6 +254,7 @@ export function deleteMemory(db, id) {
228
254
  * Append to today's daily note
229
255
  */
230
256
  export function appendDailyNote(memoryDir, content) {
257
+ assertLegacyMemoryManagerMutationAllowed("append-daily-note");
231
258
  ensureMemoryDirs(memoryDir);
232
259
 
233
260
  const today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
@@ -260,8 +287,6 @@ export function getDailyNote(memoryDir, date) {
260
287
  * List available daily notes
261
288
  */
262
289
  export function listDailyNotes(memoryDir, options = {}) {
263
- ensureMemoryDirs(memoryDir);
264
-
265
290
  const dailyDir = path.join(memoryDir, "daily");
266
291
  const limit = Math.max(1, parseInt(options.limit) || 30);
267
292
 
@@ -291,13 +316,13 @@ export function listDailyNotes(memoryDir, options = {}) {
291
316
  * Read or update the MEMORY.md file (long-term knowledge)
292
317
  */
293
318
  export function getMemoryFile(memoryDir) {
294
- ensureMemoryDirs(memoryDir);
295
319
  const filePath = path.join(memoryDir, "MEMORY.md");
296
320
  if (!fs.existsSync(filePath)) return "";
297
321
  return fs.readFileSync(filePath, "utf8");
298
322
  }
299
323
 
300
324
  export function updateMemoryFile(memoryDir, content) {
325
+ assertLegacyMemoryManagerMutationAllowed("update-memory-file");
301
326
  ensureMemoryDirs(memoryDir);
302
327
  const filePath = path.join(memoryDir, "MEMORY.md");
303
328
  atomicWriteFileSync(filePath, content);
@@ -0,0 +1,52 @@
1
+ export const CONTEXT_WINDOWS = Object.freeze({
2
+ "qwen2.5:7b": 32768,
3
+ "qwen2.5:14b": 32768,
4
+ "qwen2.5-coder:14b": 32768,
5
+ "qwen2:7b": 32768,
6
+ "llama3:8b": 8192,
7
+ "mistral:7b": 32768,
8
+ "codellama:7b": 16384,
9
+ "gpt-4o": 128000,
10
+ "gpt-4o-mini": 128000,
11
+ "gpt-4-turbo": 128000,
12
+ "gpt-3.5-turbo": 16385,
13
+ o1: 200000,
14
+ "claude-opus-4-6": 200000,
15
+ "claude-sonnet-4-6": 200000,
16
+ "claude-haiku-4-5-20251001": 200000,
17
+ "deepseek-chat": 64000,
18
+ "deepseek-coder": 64000,
19
+ "deepseek-reasoner": 64000,
20
+ "qwen-turbo": 131072,
21
+ "qwen-plus": 131072,
22
+ "qwen-max": 32768,
23
+ "gemini-2.0-flash": 1048576,
24
+ "gemini-2.0-pro": 1048576,
25
+ "gemini-1.5-flash": 1048576,
26
+ "moonshot-v1-auto": 131072,
27
+ "moonshot-v1-8k": 8192,
28
+ "moonshot-v1-32k": 32768,
29
+ "moonshot-v1-128k": 131072,
30
+ "doubao-seed-1-6-251015": 32768,
31
+ "doubao-seed-2-1-pro-260628": 32768,
32
+ _provider_defaults: Object.freeze({
33
+ ollama: 32768,
34
+ openai: 128000,
35
+ anthropic: 200000,
36
+ deepseek: 64000,
37
+ dashscope: 131072,
38
+ gemini: 1048576,
39
+ kimi: 131072,
40
+ volcengine: 32768,
41
+ minimax: 32768,
42
+ mistral: 32768,
43
+ }),
44
+ });
45
+
46
+ export function getContextWindow(model, provider) {
47
+ if (model && CONTEXT_WINDOWS[model]) return CONTEXT_WINDOWS[model];
48
+ if (provider && CONTEXT_WINDOWS._provider_defaults[provider]) {
49
+ return CONTEXT_WINDOWS._provider_defaults[provider];
50
+ }
51
+ return 32768;
52
+ }
@@ -9,6 +9,18 @@
9
9
  import fs from "fs";
10
10
  import path from "path";
11
11
  import { BM25Search } from "./bm25-search.js";
12
+ import {
13
+ assertLegacyMutationAllowed,
14
+ resolveCliContextMemoryCutover,
15
+ } from "./context-memory-kernel/authority.js";
16
+
17
+ function assertLegacyPermanentMemoryMutationAllowed(operation) {
18
+ assertLegacyMutationAllowed(
19
+ resolveCliContextMemoryCutover({
20
+ scopeKey: `cli:legacy-permanent-memory:${operation}`,
21
+ }),
22
+ );
23
+ }
12
24
 
13
25
  // Exported for test injection
14
26
  export const _deps = {
@@ -66,6 +78,7 @@ export class CLIPermanentMemory {
66
78
  */
67
79
  initialize() {
68
80
  if (this._initialized) return;
81
+ assertLegacyPermanentMemoryMutationAllowed("initialize");
69
82
  this._initialized = true;
70
83
 
71
84
  // Ensure directories
@@ -120,6 +133,7 @@ export class CLIPermanentMemory {
120
133
  */
121
134
  appendDailyNote(content) {
122
135
  if (!this.memoryDir || !content) return null;
136
+ assertLegacyPermanentMemoryMutationAllowed("append-daily-note");
123
137
 
124
138
  try {
125
139
  const today = new Date().toISOString().slice(0, 10);
@@ -154,6 +168,7 @@ export class CLIPermanentMemory {
154
168
  */
155
169
  updateMemoryFile(section, content) {
156
170
  if (!this.memoryDir) return null;
171
+ assertLegacyPermanentMemoryMutationAllowed("update-memory-file");
157
172
 
158
173
  try {
159
174
  const filePath = _deps.path.join(this.memoryDir, "MEMORY.md");
@@ -228,6 +243,7 @@ export class CLIPermanentMemory {
228
243
  */
229
244
  autoSummarize(sessionMessages) {
230
245
  if (!sessionMessages || sessionMessages.length < 4) return [];
246
+ assertLegacyPermanentMemoryMutationAllowed("auto-summarize");
231
247
 
232
248
  const facts = [];
233
249
 
@@ -281,6 +297,7 @@ export class CLIPermanentMemory {
281
297
  */
282
298
  _storeEntry(content, source = "auto", importance = 0.5) {
283
299
  if (!this.db) return null;
300
+ assertLegacyPermanentMemoryMutationAllowed("store-entry");
284
301
  try {
285
302
  const id = `pm-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
286
303
  this.db
@@ -1530,10 +1530,14 @@ export class PlanModeManager extends EventEmitter {
1530
1530
  */
1531
1531
  _fireHook(eventName, context) {
1532
1532
  if (!this._hookDb) return;
1533
- // Dynamic import to avoid circular deps
1534
- import("./hook-manager.js")
1535
- .then(({ executeHooks }) => {
1536
- executeHooks(this._hookDb, eventName, context).catch(() => {});
1533
+ // Dynamic import avoids a constructor-time dependency while keeping the
1534
+ // legacy SQLite registry behind the canonical Hooks v2 adapter.
1535
+ import("./hooks-v2-producers.js")
1536
+ .then(({ executeHooksV2Event }) => {
1537
+ executeHooksV2Event(eventName, context, {
1538
+ hookDb: this._hookDb,
1539
+ matchTarget: context?.target || eventName,
1540
+ }).catch(() => {});
1537
1541
  })
1538
1542
  .catch(() => {});
1539
1543
  }
@@ -964,12 +964,19 @@ class ProcessExecutionBroker extends EventEmitter {
964
964
  sandboxed: 0,
965
965
  credFiltered: 0,
966
966
  };
967
- this._logPath = path.join(
968
- os.homedir(),
969
- ".chainlesschain",
970
- "logs",
971
- "process-audit.log",
972
- );
967
+ this._logPath =
968
+ process.env.NODE_ENV === "test"
969
+ ? path.join(
970
+ os.tmpdir(),
971
+ "chainlesschain-process-audit-tests",
972
+ `${process.pid}.log`,
973
+ )
974
+ : path.join(
975
+ os.homedir(),
976
+ ".chainlesschain",
977
+ "logs",
978
+ "process-audit.log",
979
+ );
973
980
 
974
981
  // P0-1: Platform sandbox functions (applySandbox/postSpawnSandbox imported above)
975
982
  // No instance needed — stateless functional API per platform
@@ -998,7 +1005,8 @@ class ProcessExecutionBroker extends EventEmitter {
998
1005
  try {
999
1006
  fs.mkdirSync(path.dirname(this._logPath), { recursive: true });
1000
1007
  } catch {
1001
- // Audit persistence is best-effort; in-memory audit remains available.
1008
+ // Legacy callers may retain in-memory audit. Required-audit executions
1009
+ // independently prove appendability before native spawn and fail closed.
1002
1010
  }
1003
1011
  }
1004
1012
 
@@ -1033,6 +1041,14 @@ class ProcessExecutionBroker extends EventEmitter {
1033
1041
  }
1034
1042
 
1035
1043
  _recordAudit(entry) {
1044
+ try {
1045
+ fs.appendFileSync(this._logPath, JSON.stringify(entry) + "\n");
1046
+ } catch (cause) {
1047
+ if (entry.persistentAuditRequired === true) {
1048
+ throw this._persistentAuditError(cause, entry);
1049
+ }
1050
+ // Non-sensitive legacy callers retain best-effort persistence.
1051
+ }
1036
1052
  this._auditLog.push(entry);
1037
1053
  if (this._auditLog.length > 10000) this._auditLog.shift();
1038
1054
  this._stats.totalSpawned++;
@@ -1046,12 +1062,54 @@ class ProcessExecutionBroker extends EventEmitter {
1046
1062
  }
1047
1063
  this._stats.byOrigin[entry.origin] =
1048
1064
  (this._stats.byOrigin[entry.origin] || 0) + 1;
1065
+ this.emit("spawn", entry);
1066
+ }
1067
+
1068
+ _persistentAuditError(cause, entry) {
1069
+ const error = new Error(
1070
+ `Persistent process audit is unavailable: ${cause.message}`,
1071
+ );
1072
+ error.code = "ERR_PROCESS_AUDIT_UNAVAILABLE";
1073
+ error.auditFailClosed = true;
1074
+ error.cause = cause;
1075
+ error.auditEntry = entry;
1076
+ return error;
1077
+ }
1078
+
1079
+ _requirePersistentAuditAdmission(entry) {
1080
+ const admission = {
1081
+ ...entry,
1082
+ auditPhase: "admission",
1083
+ persistentAuditRequired: true,
1084
+ admittedAt: Date.now(),
1085
+ };
1049
1086
  try {
1050
- fs.appendFileSync(this._logPath, JSON.stringify(entry) + "\n");
1051
- } catch {
1052
- // Audit persistence is best-effort; the in-memory entry is retained.
1087
+ fs.appendFileSync(this._logPath, JSON.stringify(admission) + "\n");
1088
+ } catch (cause) {
1089
+ throw this._persistentAuditError(cause, entry);
1090
+ }
1091
+ entry.persistentAuditRequired = true;
1092
+ entry.persistentAuditAdmitted = true;
1093
+ }
1094
+
1095
+ _recordRequiredAuditOutcome(entry, auditPhase) {
1096
+ if (entry.persistentAuditRequired !== true) return;
1097
+ try {
1098
+ fs.appendFileSync(
1099
+ this._logPath,
1100
+ JSON.stringify({ ...entry, auditPhase }) + "\n",
1101
+ );
1102
+ } catch (cause) {
1103
+ const error = this._persistentAuditError(cause, entry);
1104
+ entry.persistentAuditFailure = error.message;
1105
+ if (this.listenerCount("audit-error") > 0) {
1106
+ this.emit("audit-error", { auditEntry: entry, error });
1107
+ }
1108
+ process.emitWarning(error.message, {
1109
+ code: error.code,
1110
+ detail: `executionId=${entry.executionId}`,
1111
+ });
1053
1112
  }
1054
- this.emit("spawn", entry);
1055
1113
  }
1056
1114
 
1057
1115
  _sanitizeOptions(options) {
@@ -3965,8 +4023,68 @@ class ProcessExecutionBroker extends EventEmitter {
3965
4023
  return sanitized;
3966
4024
  }
3967
4025
 
4026
+ _auditCommand(command, redact = false) {
4027
+ if (!redact) return command;
4028
+ const digest = crypto
4029
+ .createHash("sha256")
4030
+ .update(String(command ?? ""), "utf8")
4031
+ .digest("hex");
4032
+ return `[REDACTED sha256:${digest}]`;
4033
+ }
4034
+
4035
+ _normalizeAuditContext(value, origin) {
4036
+ if (value === undefined || value === null) {
4037
+ return {
4038
+ actor: origin,
4039
+ sessionId: null,
4040
+ authorization: null,
4041
+ policyDigest: null,
4042
+ };
4043
+ }
4044
+ if (typeof value !== "object" || Array.isArray(value)) {
4045
+ throw new TypeError("auditContext must be an object");
4046
+ }
4047
+ const snapshot = ownDataObjectSnapshot(value);
4048
+ if (!snapshot)
4049
+ throw new TypeError("auditContext must contain data properties");
4050
+ const authorization = snapshot.authorization;
4051
+ if (
4052
+ authorization !== undefined &&
4053
+ authorization !== null &&
4054
+ (typeof authorization !== "object" || Array.isArray(authorization))
4055
+ ) {
4056
+ throw new TypeError("auditContext.authorization must be an object");
4057
+ }
4058
+ const authorizationSnapshot = authorization
4059
+ ? ownDataObjectSnapshot(authorization)
4060
+ : null;
4061
+ if (authorization && !authorizationSnapshot) {
4062
+ throw new TypeError(
4063
+ "auditContext.authorization must contain data properties",
4064
+ );
4065
+ }
4066
+ const text = (input, fallback = null) =>
4067
+ typeof input === "string" && input ? input.slice(0, 512) : fallback;
4068
+ return {
4069
+ actor: text(snapshot.actor, origin),
4070
+ sessionId: text(snapshot.sessionId),
4071
+ authorization: authorizationSnapshot
4072
+ ? {
4073
+ decision: text(authorizationSnapshot.decision, "unknown"),
4074
+ via: text(authorizationSnapshot.via, "unknown"),
4075
+ riskLevel: text(authorizationSnapshot.riskLevel),
4076
+ policy: text(authorizationSnapshot.policy),
4077
+ }
4078
+ : null,
4079
+ policyDigest: text(snapshot.policyDigest),
4080
+ };
4081
+ }
4082
+
3968
4083
  _stripAuditControlOptions(options) {
3969
4084
  delete options.auditRedactArgIndexes;
4085
+ delete options.auditRedactCommand;
4086
+ delete options.auditContext;
4087
+ delete options.requirePersistentAudit;
3970
4088
  }
3971
4089
 
3972
4090
  _applyCredentialBoundary(command, args, spawnOptions, origin) {
@@ -4380,12 +4498,20 @@ class ProcessExecutionBroker extends EventEmitter {
4380
4498
  );
4381
4499
 
4382
4500
  const traceCtx = this._getTraceContext();
4501
+ const auditContext = this._normalizeAuditContext(
4502
+ options.auditContext,
4503
+ origin,
4504
+ );
4383
4505
  const auditEntry = {
4384
4506
  executionId,
4385
4507
  traceId: traceCtx?.traceId || null,
4386
4508
  origin,
4387
4509
  scope,
4388
- command,
4510
+ actor: auditContext.actor,
4511
+ sessionId: auditContext.sessionId,
4512
+ authorization: auditContext.authorization,
4513
+ approvalPolicyDigest: auditContext.policyDigest,
4514
+ command: this._auditCommand(command, options.auditRedactCommand === true),
4389
4515
  args: this._auditArgs(args, auditRedactArgIndexes),
4390
4516
  cwd,
4391
4517
  startTime,
@@ -4533,6 +4659,16 @@ class ProcessExecutionBroker extends EventEmitter {
4533
4659
  throw transactionError;
4534
4660
  }
4535
4661
 
4662
+ if (options.requirePersistentAudit === true) {
4663
+ try {
4664
+ this._requirePersistentAuditAdmission(auditEntry);
4665
+ } catch (auditError) {
4666
+ sandboxPlan.cleanup?.();
4667
+ auditError.auditEntry = auditEntry;
4668
+ throw auditError;
4669
+ }
4670
+ }
4671
+
4536
4672
  // Use native spawn from _native (set by patch-child-process.js)
4537
4673
  const nativeSpawnFn = this._native?.spawn || nativeSpawn;
4538
4674
  let proc;
@@ -4680,6 +4816,7 @@ class ProcessExecutionBroker extends EventEmitter {
4680
4816
  auditEntry.signal = signal;
4681
4817
  auditEntry.endTime = endTime;
4682
4818
  auditEntry.durationMs = endTime - startTime;
4819
+ this._recordRequiredAuditOutcome(auditEntry, "completed");
4683
4820
  this._writeRplEntry(auditEntry, "completed");
4684
4821
  this._emitHooksEvent("tool:end", {
4685
4822
  executionId,
@@ -4695,6 +4832,7 @@ class ProcessExecutionBroker extends EventEmitter {
4695
4832
  auditEntry.error = err.message;
4696
4833
  auditEntry.endTime = Date.now();
4697
4834
  auditEntry.durationMs = auditEntry.endTime - startTime;
4835
+ this._recordRequiredAuditOutcome(auditEntry, "error");
4698
4836
  this._writeRplEntry(auditEntry, "error", err);
4699
4837
  this._emitHooksEvent("tool:end", {
4700
4838
  executionId,
@@ -4743,12 +4881,20 @@ class ProcessExecutionBroker extends EventEmitter {
4743
4881
  );
4744
4882
 
4745
4883
  const traceCtx = this._getTraceContext();
4884
+ const auditContext = this._normalizeAuditContext(
4885
+ options.auditContext,
4886
+ origin,
4887
+ );
4746
4888
  const auditEntry = {
4747
4889
  executionId,
4748
4890
  traceId: traceCtx?.traceId || null,
4749
4891
  origin,
4750
4892
  scope,
4751
- command,
4893
+ actor: auditContext.actor,
4894
+ sessionId: auditContext.sessionId,
4895
+ authorization: auditContext.authorization,
4896
+ approvalPolicyDigest: auditContext.policyDigest,
4897
+ command: this._auditCommand(command, options.auditRedactCommand === true),
4752
4898
  args: this._auditArgs(args, auditRedactArgIndexes),
4753
4899
  cwd,
4754
4900
  startTime,
@@ -4880,6 +5026,16 @@ class ProcessExecutionBroker extends EventEmitter {
4880
5026
  throw transactionError;
4881
5027
  }
4882
5028
 
5029
+ if (options.requirePersistentAudit === true) {
5030
+ try {
5031
+ this._requirePersistentAuditAdmission(auditEntry);
5032
+ } catch (auditError) {
5033
+ sandboxPlan.cleanup?.();
5034
+ auditError.auditEntry = auditEntry;
5035
+ throw auditError;
5036
+ }
5037
+ }
5038
+
4883
5039
  const nativeSpawnSyncFn = this._native?.spawnSync || nativeSpawnSync;
4884
5040
  try {
4885
5041
  const macPlanBindingDeclared =
@@ -4957,12 +5113,20 @@ class ProcessExecutionBroker extends EventEmitter {
4957
5113
  options.auditRedactArgIndexes,
4958
5114
  Array.isArray(args) ? args.length : 0,
4959
5115
  );
5116
+ const auditContext = this._normalizeAuditContext(
5117
+ options.auditContext,
5118
+ origin,
5119
+ );
4960
5120
  const auditEntry = {
4961
5121
  executionId,
4962
5122
  traceId: this._getTraceContext()?.traceId || null,
4963
5123
  origin,
4964
5124
  scope,
4965
- command,
5125
+ actor: auditContext.actor,
5126
+ sessionId: auditContext.sessionId,
5127
+ authorization: auditContext.authorization,
5128
+ approvalPolicyDigest: auditContext.policyDigest,
5129
+ command: this._auditCommand(command, options.auditRedactCommand === true),
4966
5130
  args: this._auditArgs(args, auditRedactArgIndexes),
4967
5131
  cwd: options.cwd || process.cwd(),
4968
5132
  startTime,
@@ -5051,6 +5215,9 @@ class ProcessExecutionBroker extends EventEmitter {
5051
5215
  const filteredArgs = spawnOptions.args || [];
5052
5216
  delete spawnOptions.args;
5053
5217
  this._prepareWorkspaceTransactionAudit(auditEntry);
5218
+ if (options.requirePersistentAudit === true) {
5219
+ this._requirePersistentAuditAdmission(auditEntry);
5220
+ }
5054
5221
 
5055
5222
  if (sandboxPolicy.requiredBoundaries.length === 0) {
5056
5223
  delete spawnOptions.origin;
@@ -5070,7 +5237,18 @@ class ProcessExecutionBroker extends EventEmitter {
5070
5237
  auditEntry.pid = proc?.pid ?? null;
5071
5238
  auditEntry.endTime = Date.now();
5072
5239
  auditEntry.durationMs = auditEntry.endTime - startTime;
5073
- this._recordAudit(auditEntry);
5240
+ try {
5241
+ this._recordAudit(auditEntry);
5242
+ } catch (auditError) {
5243
+ try {
5244
+ proc.kill?.();
5245
+ } catch {
5246
+ // Preserve the required-audit failure after requesting teardown.
5247
+ }
5248
+ auditError.spawnedProcess = proc;
5249
+ auditError.processTerminationRequested = true;
5250
+ throw auditError;
5251
+ }
5074
5252
  this._writeRplEntry(auditEntry, "started");
5075
5253
  return proc;
5076
5254
  }
@@ -5216,6 +5394,7 @@ class ProcessExecutionBroker extends EventEmitter {
5216
5394
  auditEntry.signal = signal;
5217
5395
  auditEntry.endTime = Date.now();
5218
5396
  auditEntry.durationMs = auditEntry.endTime - startTime;
5397
+ this._recordRequiredAuditOutcome(auditEntry, "completed");
5219
5398
  this._writeRplEntry(auditEntry, "completed");
5220
5399
  this.emit("exit", auditEntry);
5221
5400
  });
@@ -5224,13 +5403,26 @@ class ProcessExecutionBroker extends EventEmitter {
5224
5403
  auditEntry.error = error.message;
5225
5404
  auditEntry.endTime = Date.now();
5226
5405
  auditEntry.durationMs = auditEntry.endTime - startTime;
5406
+ this._recordRequiredAuditOutcome(auditEntry, "error");
5227
5407
  this._writeRplEntry(auditEntry, "error", error);
5228
5408
  if (this.listenerCount("error") > 0) this.emit("error", auditEntry);
5229
5409
  });
5230
5410
  auditEntry.pid = proc?.pid ?? null;
5231
5411
  auditEntry.endTime = Date.now();
5232
5412
  auditEntry.durationMs = auditEntry.endTime - startTime;
5233
- this._recordAudit(auditEntry);
5413
+ try {
5414
+ this._recordAudit(auditEntry);
5415
+ } catch (auditError) {
5416
+ try {
5417
+ child.kill?.();
5418
+ } catch {
5419
+ // Preserve the required-audit failure after requesting teardown.
5420
+ }
5421
+ releaseTerminal();
5422
+ auditError.spawnedProcess = proc;
5423
+ auditError.processTerminationRequested = true;
5424
+ throw auditError;
5425
+ }
5234
5426
  this._writeRplEntry(auditEntry, "started");
5235
5427
  return proc;
5236
5428
  } catch (error) {
@@ -1,5 +1,6 @@
1
1
  const MAX_LABEL_LENGTH = 160;
2
2
  const MAX_CALL_ID_LENGTH = 128;
3
+ const MAX_OPERATION_ID_LENGTH = 160;
3
4
  const MAX_ATTRIBUTION_ID_LENGTH = 256;
4
5
  let fallbackToolSequence = 0;
5
6
  const USAGE_FIELDS = Object.freeze([
@@ -65,6 +66,21 @@ function callId(value, { required = false } = {}) {
65
66
  return value.trim();
66
67
  }
67
68
 
69
+ function operationId(value) {
70
+ if (value === undefined) return null;
71
+ if (
72
+ typeof value !== "string" ||
73
+ !value.trim() ||
74
+ value.length > MAX_OPERATION_ID_LENGTH ||
75
+ /\p{Cc}/u.test(value)
76
+ ) {
77
+ throw new TypeError(
78
+ "runtime usage boundary requires a bounded operation id",
79
+ );
80
+ }
81
+ return value.trim();
82
+ }
83
+
68
84
  function projectAttribution(value) {
69
85
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
70
86
  const projected = {};
@@ -120,12 +136,14 @@ export function projectRuntimeTokenUsage(event = {}) {
120
136
  }
121
137
  }
122
138
  const projectedCallId = callId(event.callId);
139
+ const projectedOperationId = operationId(event.operationId);
123
140
  const attribution = projectAttribution(event.attribution);
124
141
  return {
125
142
  provider: cleanLabel(event.provider),
126
143
  model: cleanLabel(event.model),
127
144
  usage,
128
145
  ...(projectedCallId ? { callId: projectedCallId } : {}),
146
+ ...(projectedOperationId ? { operationId: projectedOperationId } : {}),
129
147
  ...(event.source ? { source: source(event.source) } : {}),
130
148
  ...(attribution ? { attribution } : {}),
131
149
  };
@@ -138,11 +156,13 @@ export function projectRuntimeUsageBoundary(event = {}, outcome) {
138
156
  "runtime usage boundary outcome must be started or unknown",
139
157
  );
140
158
  }
159
+ const projectedOperationId = operationId(event.operationId);
141
160
  const projected = {
142
161
  callId: callId(event.callId, { required: true }),
143
162
  provider: cleanLabel(event.provider),
144
163
  model: cleanLabel(event.model),
145
164
  source: source(event.source),
165
+ ...(projectedOperationId ? { operationId: projectedOperationId } : {}),
146
166
  };
147
167
  const attribution = projectAttribution(event.attribution);
148
168
  if (attribution) projected.attribution = attribution;