chainlesschain 0.166.10 → 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 (230) hide show
  1. package/README.md +33 -0
  2. package/bin/chainlesschain.js +5 -0
  3. package/package.json +4 -2
  4. package/src/assets/web-panel/assets/{AIOps-CLYBDAGv.js → AIOps-BN25cNOD.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-CpeSttcu.js → ActionButton-Da9IP-m5.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-Ba1TNLG0.js → Analytics-D7hkEvQm.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-xBy8EOeg.js → AppLayout-CCV4Xnbc.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CJ_3TFb8.js → Artifacts-CVSnVJeA.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DUATFCG3.js → Audit-CuYdw5Ag.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-BRXYPIGp.js → BackgroundAgents-DZCnK-Tf.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-D8auLx7y.js → Backup-cV9FdpTy.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-CBgdslQ3.js → BaseInput-BRnv6YSp.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-B32LvAiE.js → Chat-Bw5w87P4.js} +5 -5
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CVfvAy-n.js → ChatBubbleRenderer-C0GjtUAw.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-BwzBxOpC.js → Checkbox-DaoTqcdt.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-0U5vrg1H.js → Codegen-B4dYcEIi.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-dZ2i4aAj.js → Col-mAhuOeuD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-UVvpLr8c.js → Community-BK6KEdBk.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-BDNEb1Bd.js → Compact-CCglmNu5.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-BrzQPxyS.js → Compliance-Cm8S4of7.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-BbgGsu-9.js → Cowork-Dhs1QLMe.js} +2 -2
  22. package/src/assets/web-panel/assets/{Cron-G321XPhp.js → Cron-CLlhmXWk.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-CgLNUyMn.js → Crosschain-BnHVbaNs.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-BAfRj18q.js → DID-UzQP9-0O.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-BNIxA4TK.js → Dashboard-CBdlPClz.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-BLAUmCAN.js → Dropdown-axIRPdq1.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-CsnhTW22.js → EmailListRenderer-DUalW5rx.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-zcQ7Ip1n.js → FamilyGuardDashboard-Bl4W9luY.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-KFwxodNU.js → Federation-C1yP-uEu.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-3CYRLEHG.js → FormItemContext-Xh6Ig5q8.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-D3d9D8L9.js → GenericCardRenderer-C2cz3bt2.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-BJ202nJY.js → Git-C_z63ixg.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-ClnnXVQ-.js → Governance-BYqB33_3.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-DNU-PTkc.js → Inference-CEULuArm.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-DJuinbuY.js → KnowledgeGraph-fgMsu-0H.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-D4No-46s.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-Ba-KqRN3.js → Marketplace-B8zyLiFe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-DVoxnPgE.js → McpTools-BLAN2mWW.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-D_C8gzAZ.js → Memory-CrQcFM7u.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-DnzTPcDH.js → MobileBridge-DVnyiiU-.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-qjCME5OD.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-CvEHmHId.js → Mtc-4JE3C3It.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-VNJmWqmv.js → MtcAudit-CjBuak9I.js} +5 -5
  45. package/src/assets/web-panel/assets/{Multisig-BO0x_Vsa.js → Multisig-BtPcYQcC.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-CM2gI1UY.js → NLProgramming-Cx653_Ba.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-CMc1HsML.js → Notes-CkuD3YzS.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-DGNmSKGM.js → NotificationSettings-BgNgU7HH.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-Du-Kct3p.js → OrderTableRenderer-BTC8W0a-.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-DRtRZjas.js → Organization-Dmd4Hjxz.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-Dp4OeWsn.js → Overflow-C_5DA-G0.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-DXMJVls8.js → P2P-uwslV4XC.js} +2 -2
  53. package/src/assets/web-panel/assets/PdhVaultBrowser-CuNgwVnX.js +7 -0
  54. package/src/assets/web-panel/assets/{Permissions-D1Hbb51o.js → Permissions-CJayVX9H.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-BridiDhr.js → PersonalDataHub-Cb05H5go.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-B4bUNCm1.js → Pipeline-BZlGKapZ.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-BTu_HEqK.js → Privacy-BIzZWYzd.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-SVtL2hnt.js → ProjectInit-vEYYyQXQ.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-B2Sh7JZ2.js → ProjectSettings-MZqTy5CC.js} +2 -2
  60. package/src/assets/web-panel/assets/{Projects-BwU1xalW.js → Projects-CRARUOl8.js} +1 -1
  61. package/src/assets/web-panel/assets/{Providers-BWdWQSDw.js → Providers-80VAK8PX.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-Brzc-Sxb.js → QrScannerModal-CzRSoIwK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-DIBz7FCe.js → QuickAsk-BpwQ2n4C.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-CZ8RriIJ.js → Recommend-BC03TZ79.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-CM0KJQ3t.js → RemoteSession-DE59-jaa.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-D_wo8H0O.js → Reputation-DOHmeWyA.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-D1G1fD7N.js → Row-hc5RZl1D.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-dKCVtA0K.js → RssFeed-Cv5uMP7E.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-Be1D61xo.js → Search-qohu7Ug0.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-IbNiR6OC.js → Security-drCPFWV5.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-nuHK8y8p.js → Services-BAEgUeRy.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DnM5jdnC.js → Skeleton-CkJkKBlo.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-DCTdoq_q.js → Skills-bMuKEpez.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-DlWun-Ui.js → Sla-DxWQVHRC.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-C19kv2sd.js → SpeechSettings-BpS8idmV.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-CkQIR_Hu.js → SyncSettings-BPBLlW5v.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-DdbqOEbs.js → Tasks-C4SLEeUh.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-B7GpIXeo.js → Templates-r-wfU39U.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-ByEstFhY.js → Tenant-C7vjRmLN.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-BKRVID1a.js → Terminal-DdzeFCV2.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-CNS3dHNv.js → TimelineRenderer-CYyWN2KD.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-BykqylCL.js → Tokens-D8A9osUg.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-ByNxq51W.js → Trigger-DBvrNlyS.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-BlrFsdaS.js → Trust-DBVAGc7o.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-Dg26A-sd.js → UkeySign-C1vQUCRJ.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-C1wUxNn0.js → VideoEditing-BKs4dah4.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-OphEUzI4.js → Wallet-ByIuj3lD.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-_8lL08hF.js → WebAuthn-DYlAFCm9.js} +3 -3
  89. package/src/assets/web-panel/assets/{WorkflowEditor-BnTuIvnP.js → WorkflowEditor-Dwyadd0c.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-3N3VLQYr.js → chat-Bm2f3s08.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-Bo_G96gg.js → colors-C8ORSh7V.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-DjubfjI_.js → compact-item-1iVlnsM-.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-Cx_HSLCk.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-D5OjAOlA.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-Bj7S5IJw.js → index-B53c3diB.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-C-_Cy0k_.js → index-B59OWAs7.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DaU60K3A.js → index-B8BrB0Ls.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-UnpsQ6A0.js → index-BC32_0xT.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BScGr1BY.js → index-BC8Wb6cy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CC7RnaPP.js → index-BCOhTILd.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DXJqa1-I.js → index-BFniLMn9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-C-4sfa0l.js → index-BIvM-uAX.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C8dPFFhy.js → index-BK-RY0-7.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CVPDhmVH.js → index-BQL9r73Y.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CqZq3zWr.js → index-BVtnizyC.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C5IwN9q3.js → index-Bf1PlIHp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Cz5tQ5PY.js → index-Bgw4Y2rU.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CmLwI-Y8.js → index-BgwLNxmr.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Y-H7j25u.js → index-C-J5-pGH.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-ydnEPOzZ.js → index-C-ZIHi42.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-HioDjvUF.js → index-C3B1S-mW.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CRKk1JPX.js → index-C5RfRciU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-x7o-2T3S.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-BvYo09C0.js → index-CTfEmKK0.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CCjq3g32.js → index-CfiHyVyl.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-3_CEBEEf.js → index-CkFvuAex.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-EZr3bvz2.js → index-D98FXb0w.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-C4MAnkl5.js → index-DDHk911Q.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BgPb37tI.js → index-DJxtPFOh.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CNmsP0Xf.js → index-DVJ1uKf4.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DBvZhdCb.js → index-Dcck8QfW.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B905-Mcs.js → index-DgUE51Pz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DrVjatPe.js → index-Dsve5Gkv.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-uAcJUJkx.js → index-DvedhJeM.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DD1zSPZH.js → index-DwMdWKiF.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BxgIE4PD.js → index-OcbzdRpT.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Ce8EWU6r.js → index-fPK6GFEg.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DlcbE0sX.js → index-geQinnns.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Dbdr8tVi.js → index-pHWA7bmM.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DE4XtzMl.js → index-reUHhuz8.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Q_vn0t8d.js → index-tqTx5wXo.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-DurpENJY.js → initDefaultProps-CuA-cpkL.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-CIh-z-gR.js → motion-CimmE_9b.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-Uc_yI2NA.js → move-DlGlrltz.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-DUevj5wz.js → mtc-parser-CK6BJQ07.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-85eMYyur.js → omit-BKjBfZfB.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-AuxDD20F.js → pickAttrs-B2chVYw9.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-DOWn8dd1.js → placementArrow-BW8aLJJ3.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-CPxTWodH.js → responsiveObserve-dXlPl66S.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-BqvbGPjx.js → slide-hSa89S4G.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-BzXKkV8d.js → statusUtils-DM6KLt-s.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-B2O7yRk3.js → styleChecker-C9MQAK15.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-DRWp7px1.js → useFlexGapSupport-BpQDpP0z.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-Dp0V7sjM.js → useFs-C7rtRViA.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-CyCrG3ql.js → usePersonalDataHub-Dm15xafq.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-CXhoFpFo.js → vnode-mEiEytw4.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-0z3mtwEg.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 +28 -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/migration-saga.js +2 -2
  195. package/src/lib/graph-kernel/production-cutover-evidence.js +8 -1
  196. package/src/lib/hierarchical-memory.js +22 -0
  197. package/src/lib/hook-audit-store.js +170 -0
  198. package/src/lib/hook-event-bus.cjs +0 -0
  199. package/src/lib/hook-manager.js +25 -83
  200. package/src/lib/hook-runtime-adapters.js +233 -0
  201. package/src/lib/hook-runtime-contract.cjs +291 -0
  202. package/src/lib/hook-runtime-contract.js +21 -0
  203. package/src/lib/hook-trust.js +210 -0
  204. package/src/lib/hooks-v2-producers.js +52 -6
  205. package/src/lib/hooks-v2-runtime.js +443 -178
  206. package/src/lib/llm-pricing.js +10 -0
  207. package/src/lib/memory-manager.js +29 -4
  208. package/src/lib/model-context-window.js +52 -0
  209. package/src/lib/permanent-memory.js +17 -0
  210. package/src/lib/plan-mode.js +8 -4
  211. package/src/lib/process-execution-broker/index.js +208 -16
  212. package/src/lib/runtime-usage-ledger.js +20 -0
  213. package/src/lib/session-consolidator.js +59 -0
  214. package/src/lib/session-core-singletons.js +17 -4
  215. package/src/lib/session-hooks.js +29 -2
  216. package/src/lib/session-transcript-migration.js +188 -0
  217. package/src/lib/settings-hook-events.cjs +37 -401
  218. package/src/lib/settings-hook-events.js +210 -8
  219. package/src/lib/settings-hooks.cjs +42 -83
  220. package/src/lib/ws-session-manager.js +4 -1
  221. package/src/repl/agent-repl.js +186 -53
  222. package/src/runtime/agent-core.js +376 -350
  223. package/src/runtime/headless-runner.js +40 -33
  224. package/src/runtime/headless-stream.js +131 -30
  225. package/src/assets/web-panel/assets/MarkdownRenderer-Dt8hH_qA.js +0 -1
  226. package/src/assets/web-panel/assets/MobileProjects-Jg2dVUc-.js +0 -1
  227. package/src/assets/web-panel/assets/PdhVaultBrowser-0jYeVmyY.js +0 -7
  228. package/src/assets/web-panel/assets/devWarning-BX944k9E.js +0 -1
  229. package/src/assets/web-panel/assets/index-C_9Jt_SR.js +0 -1
  230. package/src/assets/web-panel/assets/index-DL2EFx7m.js +0 -1
@@ -24,7 +24,6 @@ import sharedCodingAgentPolicy from "./coding-agent-policy.cjs";
24
24
  import sharedShellPolicy from "./coding-agent-shell-policy.cjs";
25
25
  import sharedPermissionRules from "../lib/permission-rules.cjs";
26
26
  import sharedSettingsHooks from "../lib/settings-hooks.cjs";
27
- import sharedHookRunner from "../lib/hook-runner.js";
28
27
  import sharedHookEvents from "../lib/settings-hook-events.js";
29
28
  import { mergeProviderOptions } from "../lib/provider-options.js";
30
29
  import { applyCredentialProxy } from "../lib/credential-proxy.js";
@@ -48,7 +47,6 @@ import {
48
47
  debitSkillPromptBudget,
49
48
  resolveSkillLimits,
50
49
  } from "../lib/skill-budget.js";
51
- import { executeHooks, HookEvents } from "../lib/hook-manager.js";
52
50
  import { detectPython } from "../lib/cli-anything-bridge.js";
53
51
  import { findProjectRoot, loadProjectConfig } from "../lib/project-detector.js";
54
52
  import { SubAgentContext } from "../lib/sub-agent-context.js";
@@ -179,14 +177,8 @@ const { isDangerousGitCommand, isReadOnlyGitCommand, normalizeGitCommand } =
179
177
  sharedCodingAgentPolicy;
180
178
  const { evaluateShellCommandPolicy } = sharedShellPolicy;
181
179
  const { evaluatePermissionRules } = sharedPermissionRules;
182
- const { collectHooks, umbrellaFor } = sharedSettingsHooks;
183
- const { runHooks: runCommandHooks } = sharedHookRunner;
184
- const {
185
- runObserveHooks,
186
- aggregateContext,
187
- partitionAsyncHooks,
188
- withDeliveryId,
189
- } = sharedHookEvents;
180
+ const { umbrellaFor } = sharedSettingsHooks;
181
+ const { runObserveHooks, aggregateContext } = sharedHookEvents;
190
182
 
191
183
  const searchProcessRunner = broker.execSync.bind(broker);
192
184
  const runCodeProcessRunner = broker.execFileSync.bind(broker);
@@ -764,156 +756,6 @@ function _resolveShellTimeout(raw) {
764
756
  return Math.min(Math.floor(n), MAX_SHELL_TIMEOUT_MS);
765
757
  }
766
758
 
767
- /**
768
- * Run settings.json `PreToolUse` hooks (decision-capable). DB hooks are handled
769
- * separately + stay observe-only. A `block` decision stops the tool; an `ask`
770
- * routes to the confirmer (headless without one falls closed). spawnSync is
771
- * synchronous but each hook is timeout-capped.
772
- * @returns {Promise<{blocked:boolean, reason?:string, hook?:string}>}
773
- */
774
- async function runSettingsPreToolUseHooks(name, args, context, cwd) {
775
- const matched = collectHooks(context.settingsHooks, "PreToolUse", name);
776
- if (!matched || matched.length === 0) return { blocked: false };
777
- // Unified-bus envelope (P2): stamps event_id + threads trace_id (this run) /
778
- // parent_id (spawning run) from the loop context. Additive fields — a hook
779
- // that ignores them is unaffected; absent context omits them entirely.
780
- const payload = withDeliveryId(
781
- "PreToolUse",
782
- {
783
- hook_event_name: "PreToolUse",
784
- tool_name: umbrellaFor(name),
785
- raw_tool_name: name,
786
- tool_input: args,
787
- cwd,
788
- session_id: context.sessionId || null,
789
- },
790
- {
791
- sessionId: context.sessionId || null,
792
- traceId: context.hookTraceId || null,
793
- parentId: context.hookParentId || null,
794
- },
795
- );
796
- // Run every matching authority-bearing hook in configured order, then merge
797
- // the outcomes with block > ask > allow > continue. Sequential execution
798
- // preserves the documented hook side-effect order while preventing an early
799
- // ask/allow from masking a later block. Environment variables cannot weaken
800
- // this permission boundary.
801
- const outcome = runCommandHooks(matched, payload, {
802
- cwd,
803
- event: "PreToolUse",
804
- mergeStrict: true,
805
- failClosed: true,
806
- broker,
807
- });
808
- if (outcome.decision === "block") {
809
- return { blocked: true, reason: outcome.reason, hook: outcome.hook };
810
- }
811
- if (outcome.decision === "ask") {
812
- // File edits in an interactive session with an IDE bridge: route the ask
813
- // through the editor's openDiff review (same machinery as settings ask —
814
- // accepted means the IDE wrote the file, so the caller must skip
815
- // execution; see tryIdeDiffApprovalForEdit).
816
- const ide = await tryIdeDiffApprovalForEdit(name, args, context, cwd, {
817
- rule: `hook:${outcome.hook}`,
818
- source: "PreToolUse hook",
819
- });
820
- if (ide?.outcome === "accepted") {
821
- return { blocked: false, ideApplied: ide.result };
822
- }
823
- // Both rejected and changes-requested mean "not applied + feed the
824
- // verdict's message back" — same control flow, different message body.
825
- if (ide?.outcome === "rejected" || ide?.outcome === "changes-requested") {
826
- return {
827
- blocked: true,
828
- reason: ide.result.error,
829
- hook: outcome.hook,
830
- ideResult: ide.result,
831
- };
832
- }
833
- const ok = await requestInteractivePermission(name, args, context, cwd, {
834
- tool: name,
835
- args,
836
- rule: `hook:${outcome.hook}`,
837
- reason: outcome.reason || "a PreToolUse hook requests confirmation",
838
- });
839
- return ok
840
- ? { blocked: false }
841
- : {
842
- blocked: true,
843
- reason: outcome.reason || "PreToolUse hook ask denied",
844
- hook: outcome.hook,
845
- };
846
- }
847
- return { blocked: false };
848
- }
849
-
850
- /**
851
- * Run settings.json `PermissionRequest` hooks (Claude-Code parity). Fires at the
852
- * exact moment a tool call would prompt the user for approval — BEFORE the
853
- * prompt — so a policy hook can auto-approve (`allow`/`approve`), auto-reject
854
- * (`deny`/`block`), or defer (`ask` / no decision) to the normal prompt.
855
- * Returns `{ decision: "allow" | "deny" | null }`. No matching hook (or no
856
- * `settingsHooks`) → `{ decision: null }` and the caller prompts exactly as
857
- * before (default behaviour is byte-for-byte unchanged).
858
- * @returns {{decision:("allow"|"deny"|null), reason?:string, hook?:string}}
859
- */
860
- function runSettingsPermissionRequestHooks(name, args, context, cwd, reason) {
861
- // Command hooks are arbitrary processes. Until a host-enforced read-only
862
- // hook sandbox exists, no command hook may execute inside the planning-only
863
- // capability fence (even when the underlying tool is read-only).
864
- if (context.planReadOnlyFenceActive === true) return { decision: null };
865
- const matched = collectHooks(
866
- context.settingsHooks,
867
- "PermissionRequest",
868
- name,
869
- );
870
- if (!matched || matched.length === 0) return { decision: null };
871
- const payload = withDeliveryId(
872
- "PermissionRequest",
873
- {
874
- hook_event_name: "PermissionRequest",
875
- tool_name: umbrellaFor(name),
876
- raw_tool_name: name,
877
- tool_input: args,
878
- permission_reason: reason || null,
879
- cwd,
880
- session_id: context.sessionId || null,
881
- },
882
- {
883
- sessionId: context.sessionId || null,
884
- traceId: context.hookTraceId || null,
885
- parentId: context.hookParentId || null,
886
- },
887
- );
888
- const outcome = runCommandHooks(matched, payload, {
889
- cwd,
890
- event: "PermissionRequest",
891
- mergeStrict: true,
892
- failClosed: true,
893
- broker,
894
- });
895
- // Precedence: deny > ask > allow > defer. The runner normalizes deny/block →
896
- // "block" and short-circuits block/ask, but it COLLAPSES an "allow" into the
897
- // aggregate "continue" (it only short-circuits block/ask) — so an explicit
898
- // auto-approve must be recovered from the per-hook `results`. A deny or ask
899
- // by any hook still wins over an allow (safety: never let an allow override a
900
- // gate that another hook wanted to block or prompt for).
901
- if (outcome.decision === "block") {
902
- return { decision: "deny", reason: outcome.reason, hook: outcome.hook };
903
- }
904
- if (outcome.decision === "ask") {
905
- return { decision: null }; // a hook asked → defer to the confirmer
906
- }
907
- const allowHook =
908
- outcome.decision === "allow"
909
- ? { command: outcome.hook }
910
- : (outcome.results || []).find((r) => r && r.decision === "allow");
911
- if (allowHook) {
912
- return { decision: "allow", hook: allowHook.command || null };
913
- }
914
- return { decision: null }; // no actionable decision → defer to the confirmer
915
- }
916
-
917
759
  /**
918
760
  * Resolve an interactive permission gate. Gives `PermissionRequest` hooks first
919
761
  * say (auto-allow → true without prompting, auto-deny → false without
@@ -946,6 +788,12 @@ async function requestInteractivePermission(
946
788
  ? Boolean(await confirm(confirmArgs))
947
789
  : false;
948
790
  }
791
+ if (context.planReadOnlyFenceActive === true) {
792
+ const confirm = context.permissionConfirm || context.shellConfirm || null;
793
+ return typeof confirm === "function"
794
+ ? Boolean(await confirm(confirmArgs))
795
+ : false;
796
+ }
949
797
  const hooksV2 = await executeHooksV2Event(
950
798
  "PermissionRequest",
951
799
  {
@@ -954,14 +802,21 @@ async function requestInteractivePermission(
954
802
  turn_id: context.turnId || null,
955
803
  tool_use_id: context.toolCallId || null,
956
804
  tool_name: name,
805
+ raw_tool_name: name,
806
+ tool_input: args,
957
807
  input_keys:
958
808
  args && typeof args === "object" ? Object.keys(args).sort() : [],
959
809
  reason: confirmArgs?.reason || null,
960
810
  cwd,
961
- trace_id: context.hookTraceId || null,
962
- parent_id: context.hookParentId || null,
811
+ ...(context.hookTraceId ? { trace_id: context.hookTraceId } : {}),
812
+ ...(context.hookParentId ? { parent_id: context.hookParentId } : {}),
813
+ },
814
+ {
815
+ failClosed: true,
816
+ settingsHooks: context.settingsHooks,
817
+ matchTarget: name,
818
+ cwd,
963
819
  },
964
- { failClosed: true },
965
820
  );
966
821
  if (hooksV2.decision === "allow") return true;
967
822
  if (hooksV2.blocked || hooksV2.decision === "block") {
@@ -975,25 +830,6 @@ async function requestInteractivePermission(
975
830
  });
976
831
  return false;
977
832
  }
978
- const verdict = runSettingsPermissionRequestHooks(
979
- name,
980
- args,
981
- context,
982
- cwd,
983
- confirmArgs?.reason,
984
- );
985
- if (verdict.decision === "allow") return true;
986
- if (verdict.decision === "deny") {
987
- emitHooksV2Event("PermissionDenied", {
988
- schema_version: 1,
989
- session_id: context.sessionId || null,
990
- turn_id: context.turnId || null,
991
- tool_use_id: context.toolCallId || null,
992
- tool_name: name,
993
- source: "settings-hook",
994
- });
995
- return false;
996
- }
997
833
  const confirm = context.permissionConfirm || context.shellConfirm || null;
998
834
  const approved =
999
835
  typeof confirm === "function" ? await confirm(confirmArgs) : false;
@@ -2750,6 +2586,25 @@ export async function executeTool(name, args, context = {}) {
2750
2586
  typeof context.externalToolExecutors === "object"
2751
2587
  ? context.externalToolExecutors[name] || null
2752
2588
  : null;
2589
+ // Bind MCP arguments to one strict immutable JSON snapshot before any
2590
+ // asynchronous permission or Hook boundary. This prevents accessors,
2591
+ // functions, or later caller mutation from changing the request that was
2592
+ // approved, recorded in the ledger, and sent over the wire.
2593
+ if (localToolExecutor?.kind === "mcp") {
2594
+ try {
2595
+ args = snapshotMcpJsonRpcInput(args || {});
2596
+ } catch (error) {
2597
+ return {
2598
+ error:
2599
+ "MCP tool blocked because its input is not strict immutable JSON data",
2600
+ policy: {
2601
+ decision: "blocked",
2602
+ via: "mcp-wire-input",
2603
+ code: safeMcpErrorCode(error, "CC_MCP_WIRE_INPUT_INVALID"),
2604
+ },
2605
+ };
2606
+ }
2607
+ }
2753
2608
  const runtimeDescriptor =
2754
2609
  getRuntimeToolDescriptor(name) || localToolDescriptor;
2755
2610
  let admittedToolAdmissionDigest = null;
@@ -2852,6 +2707,8 @@ export async function executeTool(name, args, context = {}) {
2852
2707
  turn_id: context.turnId || null,
2853
2708
  tool_use_id: context.toolCallId || null,
2854
2709
  tool_name: name,
2710
+ raw_tool_name: name,
2711
+ tool_input: args,
2855
2712
  hook_event_name: event,
2856
2713
  hook_source: source,
2857
2714
  incident_code: incident.code,
@@ -3553,6 +3410,7 @@ export async function executeTool(name, args, context = {}) {
3553
3410
  "PreToolUse",
3554
3411
  {
3555
3412
  schema_version: 1,
3413
+ event_id: `evt_${randomUUID().replaceAll("-", "").slice(0, 16)}`,
3556
3414
  session_id: context.sessionId || null,
3557
3415
  turn_id: context.turnId || null,
3558
3416
  tool_use_id: context.toolCallId || null,
@@ -3560,28 +3418,69 @@ export async function executeTool(name, args, context = {}) {
3560
3418
  input_keys:
3561
3419
  args && typeof args === "object" ? Object.keys(args).sort() : [],
3562
3420
  cwd,
3563
- trace_id: context.hookTraceId || null,
3564
- parent_id: context.hookParentId || null,
3421
+ ...(context.hookTraceId ? { trace_id: context.hookTraceId } : {}),
3422
+ ...(context.hookParentId ? { parent_id: context.hookParentId } : {}),
3423
+ },
3424
+ {
3425
+ failClosed: true,
3426
+ settingsHooks: context.settingsHooks,
3427
+ hookDb,
3428
+ matchTarget: name,
3429
+ cwd,
3565
3430
  },
3566
- { failClosed: true },
3567
3431
  );
3568
3432
  if (hooksV2Pre.blocked || hooksV2Pre.decision === "block") {
3433
+ const blockingHook = hooksV2Pre.results?.find(
3434
+ (entry) => entry.decision === "block",
3435
+ );
3436
+ const blockingReason =
3437
+ blockingHook?.result?.reason ||
3438
+ hooksV2Pre.blockingResult?.reason ||
3439
+ blockingHook?.error ||
3440
+ null;
3569
3441
  return {
3570
- error: `[Hook v2] PreToolUse blocked "${name}".`,
3571
- policy: { decision: "block", via: "hooks-v2" },
3442
+ error: `[Hook] PreToolUse blocked "${name}"${blockingReason ? `: ${blockingReason}` : ""}`,
3443
+ policy: {
3444
+ decision: "block",
3445
+ via: "hook",
3446
+ hook: blockingHook?.hookId || null,
3447
+ code:
3448
+ hooksV2Pre.errorCode ||
3449
+ hooksV2Pre.auditError ||
3450
+ hooksV2Pre.blockingResult?.code ||
3451
+ null,
3452
+ },
3572
3453
  };
3573
3454
  }
3574
3455
  if (hooksV2Pre.requiresApproval || hooksV2Pre.decision === "ask") {
3575
- const confirm = context.permissionConfirm || context.shellConfirm || null;
3576
- const approved =
3577
- typeof confirm === "function"
3578
- ? await confirm({
3579
- tool: name,
3580
- args,
3581
- reason: "Hooks v2 PreToolUse requested confirmation",
3582
- source: "hooks-v2",
3583
- })
3584
- : false;
3456
+ const askingHook = hooksV2Pre.results?.find(
3457
+ (entry) => entry.decision === "ask",
3458
+ );
3459
+ const reason =
3460
+ askingHook?.result?.reason ||
3461
+ hooksV2Pre.blockingResult?.reason ||
3462
+ "A PreToolUse Hook requests confirmation";
3463
+ const ide = await tryIdeDiffApprovalForEdit(name, args, context, cwd, {
3464
+ rule: `hook:${askingHook?.hookId || "canonical"}`,
3465
+ source: "PreToolUse Hook",
3466
+ });
3467
+ if (ide?.outcome === "accepted") return ide.result;
3468
+ if (ide?.outcome === "rejected" || ide?.outcome === "changes-requested") {
3469
+ return ide.result;
3470
+ }
3471
+ const approved = await requestInteractivePermission(
3472
+ name,
3473
+ args,
3474
+ context,
3475
+ cwd,
3476
+ {
3477
+ tool: name,
3478
+ args,
3479
+ rule: `hook:${askingHook?.hookId || "canonical"}`,
3480
+ reason,
3481
+ source: "hooks-v2",
3482
+ },
3483
+ );
3585
3484
  if (!approved) {
3586
3485
  emitHooksV2Event("PermissionDenied", {
3587
3486
  schema_version: 1,
@@ -3592,35 +3491,8 @@ export async function executeTool(name, args, context = {}) {
3592
3491
  source: "hooks-v2",
3593
3492
  });
3594
3493
  return {
3595
- error: `[Hook v2] PreToolUse confirmation denied for "${name}".`,
3596
- policy: { decision: "deny", via: "hooks-v2" },
3597
- };
3598
- }
3599
- }
3600
- if (hookDb) {
3601
- try {
3602
- await executeHooks(hookDb, HookEvents.PreToolUse, {
3603
- tool: name,
3604
- args,
3605
- timestamp: new Date().toISOString(),
3606
- descriptor: runtimeDescriptor,
3607
- context: toolContext,
3608
- });
3609
- } catch (error) {
3610
- recordObserveHookIncident("PreToolUse", "database", error);
3611
- }
3612
- }
3613
- if (context.settingsHooks) {
3614
- const pre = await runSettingsPreToolUseHooks(name, args, context, cwd);
3615
- // A hook `ask` resolved by the IDE diff review: accepted → the IDE
3616
- // already wrote the file, return the synthetic result and skip the tool;
3617
- // rejected → the ide-diff deny shape (via:"ide-diff", not via:"hook").
3618
- if (pre.ideApplied) return pre.ideApplied;
3619
- if (pre.blocked) {
3620
- if (pre.ideResult) return pre.ideResult;
3621
- return {
3622
- error: `[Hook] PreToolUse blocked "${name}"${pre.reason ? ": " + pre.reason : ""}`,
3623
- policy: { decision: "block", via: "hook", hook: pre.hook || null },
3494
+ error: `[Hook] PreToolUse blocked "${name}": confirmation denied`,
3495
+ policy: { decision: "deny", via: "hook" },
3624
3496
  };
3625
3497
  }
3626
3498
  }
@@ -3741,19 +3613,26 @@ export async function executeTool(name, args, context = {}) {
3741
3613
  context.browserReplayAllowCredentials === true,
3742
3614
  });
3743
3615
  } catch (err) {
3744
- if (
3745
- hookDb &&
3746
- !planReadOnlyFenceActive &&
3747
- context.hermeticExecution !== true
3748
- ) {
3616
+ if (!planReadOnlyFenceActive && context.hermeticExecution !== true) {
3749
3617
  try {
3750
- await executeHooks(hookDb, HookEvents.ToolError, {
3751
- tool: name,
3752
- args,
3753
- error: err.message,
3754
- });
3618
+ await executeHooksV2Event(
3619
+ "ToolError",
3620
+ {
3621
+ tool: name,
3622
+ tool_name: name,
3623
+ tool_input: args,
3624
+ error: err.message,
3625
+ cwd,
3626
+ },
3627
+ {
3628
+ hookDb,
3629
+ settingsHooks: context.settingsHooks,
3630
+ matchTarget: name,
3631
+ cwd,
3632
+ },
3633
+ );
3755
3634
  } catch (error) {
3756
- recordObserveHookIncident("ToolError", "database", error);
3635
+ recordObserveHookIncident("ToolError", "canonical", error);
3757
3636
  }
3758
3637
  }
3759
3638
  throw err;
@@ -3777,96 +3656,76 @@ export async function executeTool(name, args, context = {}) {
3777
3656
  }
3778
3657
  }
3779
3658
 
3780
- // PostToolUse hook
3781
- if (
3782
- hookDb &&
3783
- !planReadOnlyFenceActive &&
3784
- context.hermeticExecution !== true
3785
- ) {
3786
- try {
3787
- await executeHooks(hookDb, HookEvents.PostToolUse, {
3788
- tool: name,
3789
- args,
3790
- result:
3791
- typeof toolResult === "object"
3792
- ? JSON.stringify(toolResult).substring(0, 500)
3793
- : String(toolResult).substring(0, 500),
3794
- descriptor: runtimeDescriptor,
3795
- context: toolContext,
3796
- });
3797
- } catch (error) {
3798
- recordObserveHookIncident("PostToolUse", "database", error);
3799
- }
3800
- }
3801
- // settings.json PostToolUse hooks: can't un-run the tool, but a `block`
3802
- // reason is attached as `hookFeedback` to be surfaced back to the model.
3659
+ // Canonical PostToolUse dispatch. SQLite and settings definitions are input
3660
+ // adapters; Hooks v2 is the only scheduler/decision/audit runtime.
3803
3661
  if (
3804
3662
  !planReadOnlyFenceActive &&
3805
3663
  context.hermeticExecution !== true &&
3806
- context.settingsHooks &&
3807
3664
  toolResult &&
3808
3665
  typeof toolResult === "object"
3809
3666
  ) {
3810
3667
  try {
3811
- const matched = collectHooks(context.settingsHooks, "PostToolUse", name);
3812
- if (matched && matched.length > 0) {
3813
- // `async:true` PostToolUse hooks must NOT block the tool loop — split
3814
- // them off the synchronous decision path. Without this an async hook
3815
- // ran synchronously here, defeating fire-and-forget (a background lint /
3816
- // test after each edit would stall the turn).
3817
- const { sync, async: asyncHooks } = partitionAsyncHooks(matched);
3818
- const payload = withDeliveryId(
3819
- "PostToolUse",
3820
- {
3821
- hook_event_name: "PostToolUse",
3822
- tool_name: umbrellaFor(name),
3823
- raw_tool_name: name,
3824
- tool_input: args,
3825
- tool_response:
3826
- typeof toolResult === "object"
3827
- ? JSON.stringify(toolResult).substring(0, 2000)
3828
- : String(toolResult).substring(0, 2000),
3829
- cwd,
3830
- session_id: context.sessionId || null,
3831
- },
3832
- {
3833
- sessionId: context.sessionId || null,
3834
- traceId: context.hookTraceId || null,
3835
- parentId: context.hookParentId || null,
3836
- },
3837
- );
3838
- if (sync.length > 0) {
3839
- const outcome = runCommandHooks(sync, payload, {
3840
- cwd,
3841
- event: "PostToolUse",
3842
- broker,
3843
- });
3844
- for (const hookResult of outcome.results || []) {
3845
- if (
3846
- hookResult?.nonBlockingError === true ||
3847
- hookResult?.breakerOpen === true ||
3848
- hookResult?.malformedDecision === true ||
3849
- hookResult?.unsupportedDecision === true
3850
- ) {
3851
- recordObserveHookIncident(
3852
- "PostToolUse",
3853
- "settings-command",
3854
- hookResult.reason || hookResult.error || "hook command failed",
3855
- );
3856
- }
3857
- }
3858
- if (outcome.decision === "block" && outcome.reason) {
3859
- toolResult.hookFeedback = outcome.reason;
3860
- }
3861
- }
3862
- // Fire-and-forget the async hooks onto the REPL-owned supervisor when
3863
- // one is wired; results/rewakes drain into the next turn's context.
3864
- if (asyncHooks.length > 0 && context.hookSupervisor) {
3865
- context.hookSupervisor.dispatch(asyncHooks, payload, { cwd, broker });
3668
+ const outcome = await executeHooksV2Event(
3669
+ "PostToolUse",
3670
+ {
3671
+ schema_version: 1,
3672
+ event_id: `evt_${randomUUID().replaceAll("-", "").slice(0, 16)}`,
3673
+ hook_event_name: "PostToolUse",
3674
+ tool_name: umbrellaFor(name),
3675
+ raw_tool_name: name,
3676
+ tool_input: args,
3677
+ tool_response: JSON.stringify(toolResult).substring(0, 2000),
3678
+ cwd,
3679
+ session_id: context.sessionId || null,
3680
+ ...(context.hookTraceId ? { trace_id: context.hookTraceId } : {}),
3681
+ ...(context.hookParentId ? { parent_id: context.hookParentId } : {}),
3682
+ },
3683
+ {
3684
+ settingsHooks: context.settingsHooks,
3685
+ hookDb,
3686
+ matchTarget: name,
3687
+ cwd,
3688
+ asyncDispatcher:
3689
+ context.hookSupervisor &&
3690
+ typeof context.hookSupervisor.dispatch === "function"
3691
+ ? (hook, payload) =>
3692
+ context.hookSupervisor.dispatch(
3693
+ [hook.legacyHook || hook],
3694
+ payload,
3695
+ { cwd, broker },
3696
+ )
3697
+ : null,
3698
+ },
3699
+ );
3700
+ for (const hookResult of outcome.results || []) {
3701
+ if (
3702
+ hookResult?.status === "error" &&
3703
+ String(hookResult.hookId || "").startsWith("settings:")
3704
+ ) {
3705
+ recordObserveHookIncident(
3706
+ "PostToolUse",
3707
+ "settings-command",
3708
+ hookResult.error || "hook command failed",
3709
+ );
3866
3710
  }
3867
3711
  }
3712
+ const feedback = outcome.results?.find(
3713
+ (entry) =>
3714
+ entry.status === "success" &&
3715
+ entry.result &&
3716
+ ["block", "deny"].includes(
3717
+ String(
3718
+ entry.result.decision ||
3719
+ entry.result.permissionDecision ||
3720
+ entry.result.hookSpecificOutput?.permissionDecision ||
3721
+ "",
3722
+ ).toLowerCase(),
3723
+ ),
3724
+ );
3725
+ const reason = feedback?.result?.reason;
3726
+ if (reason) toolResult.hookFeedback = reason;
3868
3727
  } catch (error) {
3869
- recordObserveHookIncident("PostToolUse", "settings-command", error);
3728
+ recordObserveHookIncident("PostToolUse", "canonical", error);
3870
3729
  }
3871
3730
  }
3872
3731
 
@@ -3885,7 +3744,7 @@ export async function executeTool(name, args, context = {}) {
3885
3744
  !(toolResult.background === true && toolResult.status === "running")
3886
3745
  ) {
3887
3746
  try {
3888
- const outcome = runObserveHooks(
3747
+ const outcome = await runObserveHooks(
3889
3748
  context.settingsHooks,
3890
3749
  "SubagentStop",
3891
3750
  {
@@ -5813,7 +5672,7 @@ async function executeToolInner(
5813
5672
  // below so an allow rule can never re-enable a blocked unsafe command.
5814
5673
  const requestShellApproval = async (operationArgs) => {
5815
5674
  await shellDispatchPolicyAuthority?.revalidate?.();
5816
- if (approvalGate && !ruleAllowed) {
5675
+ if (!ruleAllowed) {
5817
5676
  const approvalPolicyVersion = `${shellDispatchPolicyAuthority?.policyVersion || "cc-shell-policy-authority/v1:unobserved"}:shell:${shellPolicy.decision}:${shellPolicy.ruleId || "none"}`;
5818
5677
  const gated = await evaluateShellCommandWithApproval({
5819
5678
  command: args.command,
@@ -6209,6 +6068,43 @@ async function executeToolInner(
6209
6068
  );
6210
6069
  if (approvalDenial) return approvalDenial;
6211
6070
 
6071
+ const createShellProcessAuditContext = () => {
6072
+ const authorization = approvalOutcome || {
6073
+ decision: "allow",
6074
+ via: ruleAllowed ? "settings-rule" : "shell-policy",
6075
+ riskLevel: null,
6076
+ policy: null,
6077
+ };
6078
+ const policyDigest = createHash("sha256")
6079
+ .update(
6080
+ JSON.stringify({
6081
+ authorityVersion:
6082
+ shellDispatchPolicyAuthority?.policyVersion || null,
6083
+ shellDecision: shellPolicy.decision || null,
6084
+ shellRuleId: shellPolicy.ruleId || null,
6085
+ authorization,
6086
+ }),
6087
+ "utf8",
6088
+ )
6089
+ .digest("hex");
6090
+ return Object.freeze({
6091
+ actor: "agent",
6092
+ sessionId: sessionId ? String(sessionId) : null,
6093
+ authorization: Object.freeze({ ...authorization }),
6094
+ policyDigest,
6095
+ });
6096
+ };
6097
+ const shellProcessAuditRedactArgIndexes = () => {
6098
+ const auditArgs = pluginBinInvocation
6099
+ ? executionPlugin?.argv
6100
+ : shellInv.useDefaultShell
6101
+ ? []
6102
+ : shellInv.argv;
6103
+ return Array.isArray(auditArgs)
6104
+ ? auditArgs.map((_, index) => index)
6105
+ : [];
6106
+ };
6107
+
6212
6108
  let shellDispatchAdmitted = false;
6213
6109
  const admitShellDispatch = async () => {
6214
6110
  if (shellDispatchAdmitted) {
@@ -6337,6 +6233,10 @@ async function executeToolInner(
6337
6233
  policy: "allow",
6338
6234
  scope: "agent",
6339
6235
  sandboxPolicy: pluginBinSandboxPolicy,
6236
+ requirePersistentAudit: true,
6237
+ auditRedactCommand: true,
6238
+ auditRedactArgIndexes: [launchArgs.length - 1],
6239
+ auditContext: createShellProcessAuditContext(),
6340
6240
  };
6341
6241
  const issuer =
6342
6242
  _backgroundProcessDeps.issueLinuxWorkspaceSandboxExecutionContract;
@@ -6447,6 +6347,10 @@ async function executeToolInner(
6447
6347
  origin: processOrigin,
6448
6348
  policy: "allow",
6449
6349
  scope: "agent",
6350
+ requirePersistentAudit: true,
6351
+ auditRedactCommand: true,
6352
+ auditRedactArgIndexes: shellProcessAuditRedactArgIndexes(),
6353
+ auditContext: createShellProcessAuditContext(),
6450
6354
  ...processProvenance,
6451
6355
  }
6452
6356
  : null;
@@ -6638,6 +6542,7 @@ async function executeToolInner(
6638
6542
  maxBuffer: 1024 * 1024,
6639
6543
  egressProxy,
6640
6544
  env: sandboxChildEnvironment,
6545
+ auditContext: createShellProcessAuditContext(),
6641
6546
  });
6642
6547
  } finally {
6643
6548
  if (proxyHandle) {
@@ -6697,6 +6602,10 @@ async function executeToolInner(
6697
6602
  origin: processOrigin,
6698
6603
  policy: "allow",
6699
6604
  scope: "agent",
6605
+ requirePersistentAudit: true,
6606
+ auditRedactCommand: true,
6607
+ auditRedactArgIndexes: shellProcessAuditRedactArgIndexes(),
6608
+ auditContext: createShellProcessAuditContext(),
6700
6609
  ...processProvenance,
6701
6610
  };
6702
6611
  if (pluginBinInvocation) {
@@ -8358,20 +8267,9 @@ async function executeToolInner(
8358
8267
  return attachDescriptor(deferredGate);
8359
8268
  }
8360
8269
 
8361
- let mcpWireInput;
8362
- try {
8363
- mcpWireInput = snapshotMcpJsonRpcInput(args || {});
8364
- } catch (error) {
8365
- return attachDescriptor({
8366
- error:
8367
- "MCP tool blocked because its input is not strict immutable JSON data",
8368
- policy: {
8369
- decision: "blocked",
8370
- via: "mcp-wire-input",
8371
- code: safeMcpErrorCode(error, "CC_MCP_WIRE_INPUT_INVALID"),
8372
- },
8373
- });
8374
- }
8270
+ // executeTool admitted this immutable snapshot before permission and
8271
+ // Hook processing; reuse the exact object for ledger and transport.
8272
+ const mcpWireInput = args;
8375
8273
 
8376
8274
  if (
8377
8275
  mcpDispatchAdmission !== null &&
@@ -9885,7 +9783,7 @@ async function _executeSpawnSubAgent(args, ctx) {
9885
9783
  // returns). Best-effort — a hook error never blocks the spawn.
9886
9784
  if (ctx.settingsHooks) {
9887
9785
  try {
9888
- const startOutcome = runObserveHooks(
9786
+ const startOutcome = await runObserveHooks(
9889
9787
  ctx.settingsHooks,
9890
9788
  "SubagentStart",
9891
9789
  {
@@ -10650,14 +10548,40 @@ export async function chatWithTools(rawMessages, options) {
10650
10548
  options.providerRequestId,
10651
10549
  );
10652
10550
 
10653
- const tools = getEffectiveToolDefinitions(options);
10551
+ let tools = getEffectiveToolDefinitions(options);
10552
+ if (Array.isArray(options.contextMemorySelectedToolNames)) {
10553
+ const selected = new Set(options.contextMemorySelectedToolNames);
10554
+ tools = tools.filter((tool) => selected.has(tool?.function?.name));
10555
+ }
10654
10556
 
10655
- const lastUserMsg = [...rawMessages].reverse().find((m) => m.role === "user");
10656
- const messages = ce
10657
- ? ce.buildOptimizedMessages(rawMessages, {
10658
- userQuery: lastUserMsg?.content,
10659
- })
10660
- : rawMessages;
10557
+ let providerMessages = rawMessages;
10558
+ let canonicalPlan = null;
10559
+ if (
10560
+ options.contextMemoryPreplanned !== true &&
10561
+ options.contextMemorySkipPlanning !== true
10562
+ ) {
10563
+ const { prepareCanonicalProviderContext } =
10564
+ await import("../lib/context-memory-kernel/provider-context.js");
10565
+ const prepared = await prepareCanonicalProviderContext(rawMessages, {
10566
+ ...options,
10567
+ contextMemoryToolDefinitions: tools,
10568
+ });
10569
+ providerMessages = prepared.messages;
10570
+ canonicalPlan = prepared.plan;
10571
+ if (canonicalPlan) {
10572
+ const selected = new Set(prepared.selectedToolNames);
10573
+ tools = tools.filter((tool) => selected.has(tool?.function?.name));
10574
+ }
10575
+ }
10576
+ const lastUserMsg = [...providerMessages]
10577
+ .reverse()
10578
+ .find((m) => m.role === "user");
10579
+ const messages =
10580
+ ce && !canonicalPlan
10581
+ ? ce.buildOptimizedMessages(providerMessages, {
10582
+ userQuery: lastUserMsg?.content,
10583
+ })
10584
+ : providerMessages;
10661
10585
 
10662
10586
  throwIfAborted(signal);
10663
10587
 
@@ -12775,9 +12699,19 @@ async function _getAutoCompactor(options) {
12775
12699
  return _instrumentAutoCompactorUsage(options._autoCompactor, options);
12776
12700
  }
12777
12701
  let compressor = null;
12702
+ let canonicalRequired = false;
12778
12703
  try {
12779
12704
  const { feature } = await import("../lib/feature-flags.js");
12780
- if (feature("PROMPT_COMPRESSOR")) {
12705
+ const { resolveCliContextMemoryCutover } =
12706
+ await import("../lib/context-memory-kernel/authority.js");
12707
+ const cutover = resolveCliContextMemoryCutover({
12708
+ env: options.contextMemoryEnv || process.env,
12709
+ scopeKey: options.sessionId
12710
+ ? `cli:session:${options.sessionId}`
12711
+ : "cli:live-session",
12712
+ });
12713
+ canonicalRequired = cutover.canonical;
12714
+ if (feature("PROMPT_COMPRESSOR") || cutover.canonical) {
12781
12715
  const { PromptCompressor } =
12782
12716
  await import("../harness/prompt-compressor.js");
12783
12717
  const llmQuery =
@@ -12798,6 +12732,7 @@ async function _getAutoCompactor(options) {
12798
12732
  {
12799
12733
  ...options,
12800
12734
  contextEngine: null,
12735
+ contextMemorySkipPlanning: true,
12801
12736
  enabledToolNames: [],
12802
12737
  extraToolDefinitions: [],
12803
12738
  hostManagedToolPolicy: null,
@@ -12824,8 +12759,35 @@ async function _getAutoCompactor(options) {
12824
12759
  summaryInputMaxChars: options.compactionInputMaxChars,
12825
12760
  });
12826
12761
  compressor = _instrumentAutoCompactorUsage(compressor, options);
12762
+ if (cutover.canonical) {
12763
+ const compatibilitySummarizer = compressor;
12764
+ const { compactLiveMessagesCanonical } =
12765
+ await import("../lib/context-memory-kernel/live-compaction.js");
12766
+ compressor = {
12767
+ canonicalKernel: true,
12768
+ shouldAutoCompact: (messages) =>
12769
+ compatibilitySummarizer.shouldAutoCompact(messages),
12770
+ compress: async (messages, compressOptions = {}) => {
12771
+ return compactLiveMessagesCanonical(messages, {
12772
+ compressor: compatibilitySummarizer,
12773
+ compressOptions,
12774
+ sessionId: options.sessionId,
12775
+ operationId: `auto-${randomUUID()}`,
12776
+ provider: options.provider,
12777
+ model: options.model,
12778
+ env: options.contextMemoryEnv || process.env,
12779
+ persist: options.persistCompaction !== false,
12780
+ trigger: "auto",
12781
+ ...(typeof options.onCompaction === "function"
12782
+ ? { commit: options.onCompaction }
12783
+ : {}),
12784
+ });
12785
+ },
12786
+ };
12787
+ }
12827
12788
  }
12828
- } catch {
12789
+ } catch (error) {
12790
+ if (canonicalRequired) throw error;
12829
12791
  compressor = null;
12830
12792
  }
12831
12793
  try {
@@ -12906,7 +12868,9 @@ async function _settleAutomaticCompaction({
12906
12868
  }
12907
12869
 
12908
12870
  let settlement = null;
12909
- if (typeof options.onCompaction === "function") {
12871
+ if (stats?.canonicalAlreadySettled === true) {
12872
+ settlement = stats.canonicalReceipt || null;
12873
+ } else if (typeof options.onCompaction === "function") {
12910
12874
  if (options.onCompaction.constructor?.name === "AsyncFunction") {
12911
12875
  throw _compactionSettlementError(
12912
12876
  "CC_COMPACTION_SETTLEMENT_ASYNC",
@@ -13597,7 +13561,10 @@ export async function* agentLoop(messages, options) {
13597
13561
  // the full compaction below is skipped this round — so heavy-tool
13598
13562
  // conversations rarely hit a full summarize. Opt out:
13599
13563
  // autoMicroCompact: false.
13600
- if (options.autoMicroCompact !== false) {
13564
+ if (
13565
+ options.autoMicroCompact !== false &&
13566
+ compactor.canonicalKernel !== true
13567
+ ) {
13601
13568
  try {
13602
13569
  const { microCompact } = await import("../lib/micro-compact.js");
13603
13570
  const mc = microCompact(messages);
@@ -13623,7 +13590,7 @@ export async function* agentLoop(messages, options) {
13623
13590
  let preCompactReason = null;
13624
13591
  if (!hermeticExecution && needFull && options.settingsHooks) {
13625
13592
  try {
13626
- const pc = runObserveHooks(
13593
+ const pc = await runObserveHooks(
13627
13594
  options.settingsHooks,
13628
13595
  "PreCompact",
13629
13596
  {
@@ -13670,6 +13637,31 @@ export async function* agentLoop(messages, options) {
13670
13637
  preserveToolPairs: true,
13671
13638
  ...pinOpts,
13672
13639
  });
13640
+ if (
13641
+ stats?.canonicalReceipt &&
13642
+ !["committed", "degraded"].includes(stats.canonicalReceipt.status)
13643
+ ) {
13644
+ automaticCompactionSettlementBlocked = true;
13645
+ yield {
13646
+ type: "compaction-degraded",
13647
+ runId,
13648
+ reason:
13649
+ stats.canonicalReceipt.status === "stale"
13650
+ ? "session_messages_changed_during_compaction"
13651
+ : "canonical_compaction_reconciliation_required",
13652
+ summaryMode: "none",
13653
+ code:
13654
+ stats.canonicalReceipt.status === "stale"
13655
+ ? "SESSION_REVISION_STALE"
13656
+ : "CC_COMPACTION_RECONCILIATION_REQUIRED",
13657
+ receipt: stats.canonicalReceipt,
13658
+ };
13659
+ await _awaitBackgroundUsageSettlement(
13660
+ backgroundSubAgents,
13661
+ backgroundUsageFailureState,
13662
+ );
13663
+ return;
13664
+ }
13673
13665
  const observerFailure = compactionUsageState.calls.find(
13674
13666
  (call) => call.observerFailed,
13675
13667
  );
@@ -13937,7 +13929,7 @@ export async function* agentLoop(messages, options) {
13937
13929
  // spawn-time handle skips it); a block reason rides along as feedback.
13938
13930
  if (!hermeticExecution && options.settingsHooks) {
13939
13931
  try {
13940
- const outcome = runObserveHooks(
13932
+ const outcome = await runObserveHooks(
13941
13933
  options.settingsHooks,
13942
13934
  "SubagentStop",
13943
13935
  {
@@ -13982,6 +13974,7 @@ export async function* agentLoop(messages, options) {
13982
13974
  // prepareCall runs fresh each iteration and returns an ephemeral
13983
13975
  // system-message supplement that is NOT persisted to messages history.
13984
13976
  let callMessages = messages;
13977
+ const contextMemoryTrustedSystemIndexes = [];
13985
13978
  if (!hermeticExecution && typeof options.prepareCall === "function") {
13986
13979
  try {
13987
13980
  const hook = await options.prepareCall({
@@ -13998,6 +13991,7 @@ export async function* agentLoop(messages, options) {
13998
13991
  ...messages,
13999
13992
  { role: "system", content: hook.systemSuffix },
14000
13993
  ];
13994
+ contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
14001
13995
  }
14002
13996
  } catch (_e) {
14003
13997
  // prepareCall failures are non-critical — proceed with original messages
@@ -14010,6 +14004,29 @@ export async function* agentLoop(messages, options) {
14010
14004
  // model request within that turn. Normalized through buildTelemetryAttributes
14011
14005
  // so they get the same charset-sanitized + cardinality-bounded treatment as
14012
14006
  // the run-level ids (turn.id correlates with the agent.iteration counter).
14007
+ let canonicalProviderContext = null;
14008
+ if (options.contextMemorySkipPlanning !== true) {
14009
+ const { prepareCanonicalProviderContext } =
14010
+ await import("../lib/context-memory-kernel/provider-context.js");
14011
+ canonicalProviderContext = await prepareCanonicalProviderContext(
14012
+ callMessages,
14013
+ {
14014
+ ...options,
14015
+ contextMemoryToolDefinitions:
14016
+ getEffectiveToolDefinitions(effectiveToolOptions),
14017
+ contextMemoryTrustedSystemIndexes,
14018
+ },
14019
+ );
14020
+ if (canonicalProviderContext.plan) {
14021
+ callMessages = canonicalProviderContext.messages;
14022
+ yield {
14023
+ type: "context.plan.created",
14024
+ plan: canonicalProviderContext.plan,
14025
+ recallDigest: canonicalProviderContext.recall?.digest || null,
14026
+ };
14027
+ }
14028
+ }
14029
+
14013
14030
  const modelIdAttrs = recorder
14014
14031
  ? buildTelemetryAttributes({
14015
14032
  turnId: `${runId}:t${budget.consumed}`,
@@ -14024,9 +14041,18 @@ export async function* agentLoop(messages, options) {
14024
14041
  "model",
14025
14042
  budget.consumed,
14026
14043
  );
14027
- const providerCallOptions = providerRequestId
14028
- ? { ...effectiveToolOptions, providerRequestId }
14044
+ const plannedProviderOptions = canonicalProviderContext?.plan
14045
+ ? {
14046
+ ...effectiveToolOptions,
14047
+ contextEngine: null,
14048
+ contextMemoryPreplanned: true,
14049
+ contextMemorySelectedToolNames:
14050
+ canonicalProviderContext.selectedToolNames,
14051
+ }
14029
14052
  : effectiveToolOptions;
14053
+ const providerCallOptions = providerRequestId
14054
+ ? { ...plannedProviderOptions, providerRequestId }
14055
+ : plannedProviderOptions;
14030
14056
  const modelUsageCall = {
14031
14057
  type: "model-usage-started",
14032
14058
  callId: _newModelUsageCallId("model"),
@@ -14275,7 +14301,7 @@ export async function* agentLoop(messages, options) {
14275
14301
  if (!hermeticExecution && options.settingsHooks) {
14276
14302
  let stopOutcome = null;
14277
14303
  try {
14278
- stopOutcome = runObserveHooks(
14304
+ stopOutcome = await runObserveHooks(
14279
14305
  options.settingsHooks,
14280
14306
  "Stop",
14281
14307
  {