chainlesschain 0.166.102 → 0.166.104

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 (213) hide show
  1. package/package.json +1 -1
  2. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  3. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-CyHIMEd8.js → AIOps-Bah3HREy.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-vuNxDpHm.js → ActionButton-DY2aeZMc.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-D0quEM0q.js → Analytics-BFly8Xaa.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-xRSVpbCs.js → AppLayout-dp0Zz-JM.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-ktfVAZBC.js → Artifacts-DcIg09ai.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-UJW6maH4.js → Audit-DkN-lsjZ.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-BYrfdCoT.js → BackgroundAgents-BjzgusLx.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-IBgsJ7BK.js → Backup-CU8S6qu9.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-BmP8_zxy.js → BaseInput-B1pC2gjL.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-urkw8_BF.js → Chat-B6xFp6gD.js} +6 -6
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Cw44zZbh.js → ChatBubbleRenderer-DxNCLZ_X.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-CYboo-__.js → Checkbox-QHw7Vc4U.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-DaqR_Ay8.js → Codegen-gdecsfjg.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-04BSIj_z.js → Col-B0_JmAmc.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-DxFk7Trv.js → Community-DRCcP5xR.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-mjgWlMCB.js → Compact-DZtoGzhX.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-CC5ee7QV.js → Compliance-BfNTvEnT.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-BK4BhHZd.js → Cowork-CDXTLm84.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-CP6jAxq0.js → Cron-Big35CbN.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-DJPaViZS.js → Crosschain-C8ArrAVr.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-BTLxkuOj.js → DID-D_77BI2O.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-Djkiqh3d.js → Dashboard-D2SxTzEp.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-t_eUhqom.js → Dropdown-mR1-b9ud.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-7w6USx_J.js → EmailListRenderer-DPl7TE1c.js} +1 -1
  28. package/src/assets/web-panel/assets/{EvolutionSettings-mU5IHEk5.js → EvolutionSettings-BxRYLRSH.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BCh-VBBC.js → FamilyGuardDashboard-rnGtXJ5Z.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-Be_VpjI2.js → Federation-BpxenYK8.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-D_lzQ7PI.js → FormItemContext-Cz1kDf6l.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-LYu3KapV.js → GenericCardRenderer-CGV3KN6U.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-BBeF-PP4.js → Git-CIRP4UTx.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-CoF8Kzg7.js → Governance-DX4r8Vmt.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-C4DLMnXS.js → Inference-DQKk02Hl.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-B2mlNewk.js → KnowledgeGraph-DdD6J-By.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-DMZ_44Ya.js → Logs-DA2w-1_m.js} +2 -2
  38. package/src/assets/web-panel/assets/{MarkdownRenderer-Ck7Iv_9e.js → MarkdownRenderer-C9aSGETh.js} +1 -1
  39. package/src/assets/web-panel/assets/{Marketplace-BqDzTew_.js → Marketplace-BsJ6_6KW.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-BbwSbDN9.js → McpTools-_6k30z6u.js} +2 -2
  41. package/src/assets/web-panel/assets/{Memory-DAaTWgrm.js → Memory-C0_dYY0A.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-BjbTGxoR.js → MobileBridge-CCTnVqiC.js} +1 -1
  43. package/src/assets/web-panel/assets/{MobileProjects-DMODOBr-.js → MobileProjects-RZdxDSwC.js} +1 -1
  44. package/src/assets/web-panel/assets/{Mtc-DT9N2rCs.js → Mtc-D4Ys8lvX.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-DagMfUVv.js → MtcAudit-BKTC--a2.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-C1BKP6nM.js → Multisig-CGR1qOe1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-B5LFh72i.js → NLProgramming-hKKD4qWb.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-Q77V3ltW.js → Notes-pCn7Ec40.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-HxdpNIBs.js → NotificationSettings-B9eEJXEs.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-Dc0DpvBH.js → OrderTableRenderer-CmJuhaT2.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-QL3NZ7uW.js → Organization-CcQbrnwW.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-B_gqOKho.js → Overflow-HmD4Mn72.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-BBJubU8Z.js → P2P-B7LIgx5H.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-CFnGd-2E.js → PdhVaultBrowser-CXiHnBfX.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-BKkznIUM.js → Permissions-CQRI3y_l.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-DYK7ZAcd.js → PersonalDataHub-1EeHmsy5.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-CoeKpjoN.js → Pipeline-BFyoIdn8.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-Diw4G-92.js → Privacy-BxWthXMF.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-CHBOFkma.js → ProjectInit-DfigBilu.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-BJIsgdOf.js → ProjectSettings-CFmIcVc-.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-CR7H59v3.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-o8QCimor.js → Providers-2ulom-76.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-z2W-zvhW.js → QrScannerModal-BwhO07b_.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-_yubhsna.js → QuickAsk-_Wg34OwF.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-CucgJwih.js → Recommend-D_jq6Svg.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-EzfIIRg1.js → RemoteSession-BlzvEfsa.js} +2 -2
  67. package/src/assets/web-panel/assets/{Reputation-_shttE67.js → Reputation-9CTXHfL4.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-DQA_S8-9.js → Row-DlCYCN-t.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-BOqWawXT.js → RssFeed-BvlInFCH.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-Dx1v2xOq.js → Search-CfaUzKuL.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-Bt4HHsT4.js → Security-bAWgLyve.js} +4 -4
  72. package/src/assets/web-panel/assets/{Services-sruHiQ-r.js → Services-C4LOGACW.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-CiBxvmOJ.js → Skeleton-Dd0Uwh3_.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-De9qKODU.js → Skills-ZYF1kYCU.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-B_6yn8Wp.js → Sla-DpsmIaEo.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-C2CafExS.js → SpeechSettings-BBXoJ4yc.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-Dhh3Qmb0.js → SyncSettings-SOnROi2Y.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-Mvo5mTWm.js → Tasks-HFA_ZlDk.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-D7WVTQQy.js → Templates-fsK-RCEc.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-7ur9Yfxd.js → Tenant-CuqYxamb.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-BgzrOA6k.js → Terminal-GKlI2R5F.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-Dco20pT1.js → TimelineRenderer-DMDMHLeY.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-hN6qBPag.js → Tokens-BoV60rh3.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-C4f_twAM.js → Trigger-CE344-Ws.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-Wf1SMypp.js → Trust-DENwgkVc.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-DUXSyg3N.js → UkeySign-FrcM7yfm.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-BvqsJaL0.js → VideoEditing-DAY9WaC2.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-CgAbcjKl.js → Wallet-BuUR5i82.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-DaLT0W3s.js → WebAuthn-nfSQuq85.js} +2 -2
  90. package/src/assets/web-panel/assets/{WorkflowEditor-CQqAXoaS.js → WorkflowEditor-DHhPOp9l.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-BhlohFTB.js → chat-C4nsLzYy.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-D7HqXIL8.js → colors-BwXH0Wjn.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-Bqk4FCLY.js → compact-item-uApFG30S.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-CEmWrWf0.js → createContext-BpyYs4fe.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-Bk6HGn3N.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-CDY0pFi2.js → hasIn-MXCLi00p.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-e9oCy7_4.js → index-1LxX2IwJ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DEzL7s7P.js → index-61CBBrHE.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D0nfNmbq.js → index-B0P1Z_oa.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BiLu-ImR.js → index-B7jojVc7.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CqK0J4Sj.js → index-BEGMfaOo.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-aBHlgMrq.js → index-BOhjapd5.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DPBoWNwq.js → index-BaBwXpAp.js} +1 -1
  104. package/src/assets/web-panel/assets/index-Bb1LPYdi.js +1 -0
  105. package/src/assets/web-panel/assets/{index-BxXFRLTZ.js → index-Btv--Nnt.js} +1 -1
  106. package/src/assets/web-panel/assets/index-C-FsTuFG.js +1 -0
  107. package/src/assets/web-panel/assets/{index-BxYO6nde.js → index-CF0bUOP4.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DGKRAO61.js → index-CNjUPfJP.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CkjgSHVz.js → index-CRmNdEk_.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CrsM-oiD.js → index-C_oOpXhP.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BNrvBWDS.js → index-ChUTKrOq.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CYcjOnDX.js → index-CiIpIYhs.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-C02yDu4f.js → index-CwVvk2i7.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DmKdCWq1.js → index-D3_tj06B.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CkqBoCiu.js → index-DE4W4vLO.js} +3 -3
  116. package/src/assets/web-panel/assets/{index-B8L3_-sG.js → index-DLxKx5_J.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Dwob5XoD.js → index-DTXi_gQh.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DuMt3ewl.js → index-Daco83me.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DpI1LqJX.js → index-DffWVpZv.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-lBAbMOzg.js → index-Dkncxel3.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DRcDWMwP.js → index-Dn12gJJU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CVrwozwH.js → index-Dt-nq2eF.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-C3opQg47.js → index-Du01X9N9.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-o_lc3eww.js → index-DucLR6YX.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Cur88hoN.js → index-Gz2rGWef.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-XErJQ1yF.js → index-IvgszJ3C.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BuKGuH_y.js → index-S80LLjdx.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Chxt0t-A.js → index-WKbnwbKa.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-1HBam9t1.js → index-XHBXtvqp.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BXRooi-O.js → index-nn22NSDK.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BHGOdvOQ.js → index-pCIAE2yS.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Cf1ha8l0.js → index-pRpMLhMt.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-6f6n0KFR.js → index-pgHGBAoF.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-BPmRkxeX.js → index-ugIUt5TL.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-C9mvnSii.js → index-xLGf7f9K.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-CIeEUxIN.js → initDefaultProps-C58CkKEo.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-IPIj1ZtP.js → motion-BLWPO2NV.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-BfSeXZ-f.js → move-BgrFMwYp.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-DX03-Xp4.js → mtc-parser-Cq2AuGzl.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-z9EannfX.js → omit-Bb-9L7if.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-DXKmRkqZ.js → pickAttrs-vLmOxYr1.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-k2HV7cIU.js → placementArrow-BNySU_dJ.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-bX7CsyWy.js → responsiveObserve-xnbwagnm.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-NskjQLbJ.js → slide-BccbY5Cn.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-B3IoG-Er.js → statusUtils-DOp9d2-w.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-DHv_UilX.js → styleChecker-Bu1w6ho9.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-DEqGB5Ng.js → useFlexGapSupport-ZsUOrVdL.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-Bl9CbrqZ.js → useFs-C0zpzKtO.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-O-Ukv93M.js → usePersonalDataHub-DO1OdgXK.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-hGCHTaZt.js → vnode-jTIRyhR5.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-BWhIVeKQ.js → zoom-DKvS7-Qs.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/commands/agent.js +56 -20
  154. package/src/commands/ask.js +6 -4
  155. package/src/commands/batch.js +17 -12
  156. package/src/commands/eval.js +24 -8
  157. package/src/commands/team.js +28 -19
  158. package/src/data/changelog.json +26 -0
  159. package/src/harness/mcp-client.js +187 -26
  160. package/src/harness/prompt-compressor.js +2 -0
  161. package/src/lib/advisor-runtime.js +4 -2
  162. package/src/lib/agent-ipc-bus.js +2 -0
  163. package/src/lib/background-agent-keeper-client.js +3 -0
  164. package/src/lib/background-session-transport.js +21 -5
  165. package/src/lib/browser-automation.js +4 -0
  166. package/src/lib/cc-android-bridge.js +4 -0
  167. package/src/lib/chat-core.js +11 -9
  168. package/src/lib/cloud/cloud-client.js +10 -1
  169. package/src/lib/cowork-adapter.js +4 -3
  170. package/src/lib/decision-layer/providers.js +16 -11
  171. package/src/lib/decision-layer/runtime.js +180 -10
  172. package/src/lib/direct-model-usage.js +34 -0
  173. package/src/lib/evolution/agent-evolution-ingress.js +63 -7
  174. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +10 -0
  175. package/src/lib/evolution/evolution-evidence-projector.js +46 -7
  176. package/src/lib/evolution/governed-hub-llm.js +31 -16
  177. package/src/lib/evolution/governed-hub-resolver.js +4 -0
  178. package/src/lib/evolution/governed-skill-synthesis-process-grader.js +4 -0
  179. package/src/lib/evolution/skill-decision-projection.js +211 -0
  180. package/src/lib/evolution/skill-retrieval-revocation-authority.js +17 -2
  181. package/src/lib/evomap-client.js +14 -2
  182. package/src/lib/formal-budget-authority.js +191 -59
  183. package/src/lib/formal-budget-contract.js +7 -13
  184. package/src/lib/formal-budget-errors.js +31 -0
  185. package/src/lib/formal-budget-lineage-registry.js +612 -0
  186. package/src/lib/formal-budget-provider-scope.js +143 -0
  187. package/src/lib/formal-budget-transport.js +235 -100
  188. package/src/lib/gateway-client-resilience.js +5 -0
  189. package/src/lib/hub-llm-client.js +25 -16
  190. package/src/lib/llm-connection-probe.js +17 -10
  191. package/src/lib/llm-providers.js +4 -1
  192. package/src/lib/model-failure-policy.js +2 -0
  193. package/src/lib/plugin-runtime/marketplace-network.js +9 -5
  194. package/src/lib/process-execution-broker/credential-agent.js +7 -2
  195. package/src/lib/process-execution-broker/credential-transport.js +4 -0
  196. package/src/lib/process-execution-broker/index.js +8 -0
  197. package/src/lib/provider-stream.js +28 -13
  198. package/src/lib/sandbox-egress-worker.js +3 -0
  199. package/src/lib/skill-loader.js +16 -0
  200. package/src/lib/stream-retry.js +2 -0
  201. package/src/lib/sub-agent-context.js +6 -3
  202. package/src/lib/web-fetch.js +2 -0
  203. package/src/lib/web-search.js +5 -0
  204. package/src/repl/agent-repl.js +86 -7
  205. package/src/runtime/agent-core.js +141 -22
  206. package/src/runtime/headless-runner.js +212 -22
  207. package/src/runtime/headless-stream.js +189 -25
  208. package/src/runtime/mcp-config.js +26 -17
  209. package/src/runtime/mcp-tool-search.js +44 -14
  210. package/src/assets/web-panel/assets/Projects-GJjItXIk.js +0 -1
  211. package/src/assets/web-panel/assets/devWarning-YPX_TU7w.js +0 -1
  212. package/src/assets/web-panel/assets/index-D53szVZQ.js +0 -1
  213. package/src/assets/web-panel/assets/index-Ub2nJbV2.js +0 -1
@@ -1,3 +1,8 @@
1
+ import {
2
+ providerFetch,
3
+ requireUnscopedToolExecution,
4
+ } from "../lib/formal-budget-provider-scope.js";
5
+ import { isFormalBudgetError } from "../lib/formal-budget-errors.js";
1
6
  /**
2
7
  * Agent Core — transport-independent agentic logic
3
8
  *
@@ -2613,6 +2618,7 @@ function snapshotApprovalPolicyAuthority(approvalGate, sessionId) {
2613
2618
  * @returns {Promise<object>} tool result
2614
2619
  */
2615
2620
  export async function executeTool(name, args, context = {}) {
2621
+ requireUnscopedToolExecution();
2616
2622
  const liveExecutionContext = context;
2617
2623
  try {
2618
2624
  const executionPolicy = captureAgentExecutionPolicy(context);
@@ -7851,6 +7857,7 @@ async function executeToolInner(
7851
7857
  });
7852
7858
  return attachDescriptor(result);
7853
7859
  } catch (err) {
7860
+ if (isFormalBudgetError(err)) throw err;
7854
7861
  return attachDescriptor({ error: `web_search failed: ${err.message}` });
7855
7862
  }
7856
7863
  }
@@ -9172,6 +9179,7 @@ async function executeToolInner(
9172
9179
  } catch (err) {
9173
9180
  if (
9174
9181
  isEvolutionIngressFailure(err) ||
9182
+ isFormalBudgetError(err) ||
9175
9183
  err?.runtimeLedgerPersistence === true ||
9176
9184
  err?.workflowEffectOutcomeUnknown === true
9177
9185
  ) {
@@ -9281,24 +9289,122 @@ async function executeToolInner(
9281
9289
  ? null
9282
9290
  : captureSkillDecisionRuntime(skillDecisionRuntime);
9283
9291
  if (decisionRuntime !== null && routing.candidates.length > 0) {
9284
- const decision = await decisionRuntime.suggest({
9285
- query: args.query,
9286
- candidates: routing.candidates.slice(0, 5).map((candidate) => {
9287
- const descriptor = byDigest.get(candidate.digest);
9292
+ const decisionInputsFor = (result, descriptors) => {
9293
+ const descriptorsByDigest = new Map(
9294
+ descriptors.map((skill) => [
9295
+ skill.executionIdentity?.contentDigest,
9296
+ skill,
9297
+ ]),
9298
+ );
9299
+ return result.candidates.slice(0, 5).map((candidate) => {
9300
+ const descriptor = descriptorsByDigest.get(candidate.digest);
9288
9301
  return {
9289
- id: candidate.id,
9290
- displayName: candidate.displayName,
9291
- description: descriptor?.description || candidate.displayName,
9292
- category: candidate.category,
9293
- digest: candidate.digest,
9294
- tags: Array.isArray(descriptor?.tags) ? descriptor.tags : [],
9302
+ candidate: {
9303
+ id: candidate.id,
9304
+ displayName: candidate.displayName,
9305
+ description: descriptor?.description || candidate.displayName,
9306
+ category: candidate.category,
9307
+ digest: candidate.digest,
9308
+ tags: Array.isArray(descriptor?.tags)
9309
+ ? [...descriptor.tags]
9310
+ : [],
9311
+ },
9312
+ // Scope and compatibility are local routing inputs. They never
9313
+ // leave the process, but changes invalidate the old advice.
9314
+ identity: {
9315
+ namespace: candidate.namespace,
9316
+ version: candidate.version,
9317
+ paths: descriptor?.paths ?? null,
9318
+ os: descriptor?.os ?? null,
9319
+ capabilities: descriptor?.capabilities ?? null,
9320
+ },
9295
9321
  };
9296
- }),
9322
+ });
9323
+ };
9324
+ const decisionInputs = decisionInputsFor(routing, skills);
9325
+ const snapshotFor = (result, inputs) =>
9326
+ JSON.stringify({
9327
+ candidates: inputs,
9328
+ selectedDigest: result.selected?.digest ?? null,
9329
+ conflicts: result.conflicts,
9330
+ });
9331
+ const decisionSnapshot = snapshotFor(routing, decisionInputs);
9332
+ const contextRevision = `routing-${createHash("sha256")
9333
+ .update(
9334
+ JSON.stringify({
9335
+ query: args.query,
9336
+ category: args.category ?? null,
9337
+ cwd,
9338
+ turnId: turnId || toolCallId || "list-skills",
9339
+ toolCallId: toolCallId ?? null,
9340
+ decisionSnapshot,
9341
+ }),
9342
+ )
9343
+ .digest("hex")}`;
9344
+ const decision = await decisionRuntime.suggest({
9345
+ query: args.query,
9346
+ candidates: decisionInputs.map(({ candidate }) => candidate),
9297
9347
  turnId: turnId || toolCallId || "list-skills",
9298
- contextRevision: "skill-routing-v1",
9348
+ contextRevision,
9299
9349
  signal,
9300
9350
  });
9301
- if (decision.visible) {
9351
+ signal?.throwIfAborted();
9352
+ // The provider result belongs to the captured candidate set. Recheck
9353
+ // the persisted revocations and live loader before exposing advice.
9354
+ await skillRetrievalRevocationReader?.refresh();
9355
+ signal?.throwIfAborted();
9356
+ const refreshedSkills =
9357
+ typeof skillLoader.refreshResolvedSkills === "function"
9358
+ ? await skillLoader.refreshResolvedSkills()
9359
+ : skillLoader.getResolvedSkills();
9360
+ signal?.throwIfAborted();
9361
+ let currentSkills = await filterSkillsByCwd(
9362
+ refreshedSkills.filter(skillAllowed),
9363
+ cwd,
9364
+ );
9365
+ if (args.category) {
9366
+ currentSkills = currentSkills.filter(
9367
+ (s) => s.category.toLowerCase() === args.category.toLowerCase(),
9368
+ );
9369
+ }
9370
+ // The vector index can change while the decision provider is in
9371
+ // flight. Score the refreshed corpus again before comparing routing.
9372
+ vector =
9373
+ vectorAuthority === null
9374
+ ? null
9375
+ : await vectorAuthority.score({
9376
+ query: args.query,
9377
+ skills: currentSkills,
9378
+ });
9379
+ signal?.throwIfAborted();
9380
+ const currentRouting = routeSkillDescriptors({
9381
+ skills: currentSkills,
9382
+ query: args.query,
9383
+ target: { os: process.platform },
9384
+ vectorScores: vector?.scores ?? null,
9385
+ outcomeMetrics: outcomeAuthority.metrics,
9386
+ revocationReader: skillRetrievalRevocationReader ?? null,
9387
+ topK: Math.min(64, Math.max(1, currentSkills.length)),
9388
+ });
9389
+ const currentByDigest = new Map(
9390
+ currentSkills.map((skill) => [
9391
+ skill.executionIdentity?.contentDigest,
9392
+ skill,
9393
+ ]),
9394
+ );
9395
+ const currentDecisionSnapshot = snapshotFor(
9396
+ currentRouting,
9397
+ decisionInputsFor(currentRouting, currentSkills),
9398
+ );
9399
+ routing = currentRouting;
9400
+ skills = routing.candidates
9401
+ .map(({ digest }) => currentByDigest.get(digest))
9402
+ .filter(Boolean);
9403
+ signal?.throwIfAborted();
9404
+ if (
9405
+ decision.visible &&
9406
+ currentDecisionSnapshot === decisionSnapshot
9407
+ ) {
9302
9408
  routing = Object.freeze({
9303
9409
  ...routing,
9304
9410
  decisionSuggestion: Object.freeze({
@@ -10643,6 +10749,7 @@ function _throwBackgroundSubAgentUsageFailure(entry) {
10643
10749
  const error = entry?.outcome?.fatalError;
10644
10750
  if (
10645
10751
  isEvolutionIngressFailure(error) ||
10752
+ isFormalBudgetError(error) ||
10646
10753
  error?.runtimeLedgerPersistence === true ||
10647
10754
  error?.workflowEffectOutcomeUnknown === true
10648
10755
  ) {
@@ -11621,6 +11728,7 @@ async function _executeSpawnSubAgent(args, ctx) {
11621
11728
  result: subCtx.result,
11622
11729
  error: err.message,
11623
11730
  ...(isEvolutionIngressFailure(err) ||
11731
+ isFormalBudgetError(err) ||
11624
11732
  err?.runtimeLedgerPersistence === true ||
11625
11733
  err?.workflowEffectOutcomeUnknown === true
11626
11734
  ? { fatalError: err }
@@ -11757,6 +11865,7 @@ async function _executeSpawnSubAgent(args, ctx) {
11757
11865
 
11758
11866
  if (
11759
11867
  isEvolutionIngressFailure(err) ||
11868
+ isFormalBudgetError(err) ||
11760
11869
  err?.runtimeLedgerPersistence === true ||
11761
11870
  err?.workflowEffectOutcomeUnknown === true
11762
11871
  ) {
@@ -12000,7 +12109,7 @@ export async function chatWithTools(rawMessages, options) {
12000
12109
  },
12001
12110
  );
12002
12111
  }
12003
- const response = await fetch(apiUrl, {
12112
+ const response = await providerFetch(apiUrl, {
12004
12113
  method: "POST",
12005
12114
  headers: { "Content-Type": "application/json" },
12006
12115
  signal,
@@ -12156,7 +12265,7 @@ export async function chatWithTools(rawMessages, options) {
12156
12265
  );
12157
12266
  }
12158
12267
 
12159
- const response = await fetch(`${url}/messages`, {
12268
+ const response = await providerFetch(`${url}/messages`, {
12160
12269
  method: "POST",
12161
12270
  headers: {
12162
12271
  "Content-Type": "application/json",
@@ -12312,7 +12421,7 @@ export async function chatWithTools(rawMessages, options) {
12312
12421
  );
12313
12422
  }
12314
12423
 
12315
- const response = await fetch(`${url}/responses`, {
12424
+ const response = await providerFetch(`${url}/responses`, {
12316
12425
  method: "POST",
12317
12426
  headers: {
12318
12427
  "Content-Type": "application/json",
@@ -12390,7 +12499,7 @@ export async function chatWithTools(rawMessages, options) {
12390
12499
  );
12391
12500
  }
12392
12501
 
12393
- const response = await fetch(`${url}/chat/completions`, {
12502
+ const response = await providerFetch(`${url}/chat/completions`, {
12394
12503
  method: "POST",
12395
12504
  headers: {
12396
12505
  "Content-Type": "application/json",
@@ -12627,6 +12736,7 @@ export function _streamErrorDisposition(
12627
12736
  partialText,
12628
12737
  visible = false,
12629
12738
  ) {
12739
+ if (isFormalBudgetError(err)) return "rethrow";
12630
12740
  if (err?.isOutputBackpressureFailure === true) return "rethrow";
12631
12741
  if (isAbortError(err)) return "rethrow";
12632
12742
  if (signal && signal.aborted) return "rethrow";
@@ -12871,7 +12981,7 @@ async function _chatOllamaStreaming(
12871
12981
  stallMs,
12872
12982
  stallTimeoutMs,
12873
12983
  ) {
12874
- const response = await fetch(apiUrl, {
12984
+ const response = await providerFetch(apiUrl, {
12875
12985
  method: "POST",
12876
12986
  headers: { "Content-Type": "application/json" },
12877
12987
  signal,
@@ -12933,7 +13043,7 @@ async function _chatAnthropicStreaming(
12933
13043
  stallMs,
12934
13044
  stallTimeoutMs,
12935
13045
  ) {
12936
- const response = await fetch(apiUrl, {
13046
+ const response = await providerFetch(apiUrl, {
12937
13047
  method: "POST",
12938
13048
  headers: { "Content-Type": "application/json", ...extraHeaders },
12939
13049
  signal,
@@ -13000,7 +13110,7 @@ async function _chatOpenAIStreaming(
13000
13110
  stallTimeoutMs,
13001
13111
  providerRequestId = null,
13002
13112
  ) {
13003
- const response = await fetch(apiUrl, {
13113
+ const response = await providerFetch(apiUrl, {
13004
13114
  method: "POST",
13005
13115
  headers: {
13006
13116
  "Content-Type": "application/json",
@@ -13083,7 +13193,7 @@ async function _chatOpenAIResponsesStreaming(
13083
13193
  stallTimeoutMs,
13084
13194
  providerRequestId = null,
13085
13195
  ) {
13086
- const response = await fetch(apiUrl, {
13196
+ const response = await providerFetch(apiUrl, {
13087
13197
  method: "POST",
13088
13198
  headers: {
13089
13199
  "Content-Type": "application/json",
@@ -15479,6 +15589,7 @@ export async function* agentLoop(messages, options) {
15479
15589
  }
15480
15590
  } catch (_e) {
15481
15591
  if (isAbortError(_e) || signal?.aborted) throw _e;
15592
+ if (isFormalBudgetError(_e)) throw _e;
15482
15593
  if (_e?.runtimeLedgerPersistence === true) throw _e;
15483
15594
  if (_e?.code === "CC_AGENT_EVOLUTION_INGRESS_FAILED") throw _e;
15484
15595
  if (
@@ -15911,6 +16022,7 @@ export async function* agentLoop(messages, options) {
15911
16022
  ];
15912
16023
  }
15913
16024
  } catch (_e) {
16025
+ if (isFormalBudgetError(_e)) throw _e;
15914
16026
  // prepareCall failures are non-critical — proceed with original messages
15915
16027
  }
15916
16028
  }
@@ -16511,6 +16623,7 @@ export async function* agentLoop(messages, options) {
16511
16623
  : {}),
16512
16624
  },
16513
16625
  error: err.message,
16626
+ fatalError: isFormalBudgetError(err) ? err : null,
16514
16627
  }),
16515
16628
  );
16516
16629
  return { call, toolArgs, workflowBinding, promise };
@@ -16518,7 +16631,12 @@ export async function* agentLoop(messages, options) {
16518
16631
  for (const { call, toolArgs, workflowBinding, promise } of inflight) {
16519
16632
  throwIfAborted(signal);
16520
16633
  _throwBackgroundUsageFailureState(backgroundUsageFailureState);
16521
- const { result: toolResult, error: toolError } = await promise;
16634
+ const {
16635
+ result: toolResult,
16636
+ error: toolError,
16637
+ fatalError,
16638
+ } = await promise;
16639
+ if (fatalError) throw fatalError;
16522
16640
  throwIfAborted(signal);
16523
16641
  const taskAdvanced = taskProgressTracker.record(
16524
16642
  call.function.name,
@@ -16961,6 +17079,7 @@ export async function* agentLoop(messages, options) {
16961
17079
  } catch (err) {
16962
17080
  if (
16963
17081
  isEvolutionIngressFailure(err) ||
17082
+ isFormalBudgetError(err) ||
16964
17083
  err?.runtimeLedgerPersistence === true
16965
17084
  )
16966
17085
  throw err;
@@ -57,6 +57,7 @@ import {
57
57
  appendAuthorityEvent as jsonlAppendAuthorityEvent,
58
58
  readEvents as jsonlReadEvents,
59
59
  readVerifiedEvents as jsonlReadVerifiedEvents,
60
+ readVerifiedProjection as jsonlReadVerifiedProjection,
60
61
  findLatestEvent as jsonlFindLatestEvent,
61
62
  rebuildMessages as jsonlRebuildMessages,
62
63
  sessionExists as jsonlSessionExists,
@@ -137,7 +138,9 @@ import executionBroker from "../lib/process-execution-broker/index.js";
137
138
  import { extractPluginUsageAttribution } from "../lib/plugin-usage-attribution.js";
138
139
  import { formatManagedCheckpointEvent } from "../lib/managed-checkpoint-render.js";
139
140
  import {
141
+ normalizeSessionBudgetRootConfig,
140
142
  openProductionSessionBudgetRoot,
143
+ readProductionSessionBudget,
141
144
  sessionBudgetAdmissionError,
142
145
  } from "../lib/session-budget-production-root.js";
143
146
  import {
@@ -288,6 +291,74 @@ export function resolveHeadlessSkillDecisionOptions(options = {}) {
288
291
  });
289
292
  }
290
293
 
294
+ function createDecisionUsageRecoveryProjection() {
295
+ const started = new Map();
296
+ const seenCallIds = new Set();
297
+ let blocked = false;
298
+ return {
299
+ accept(event) {
300
+ if (blocked) return;
301
+ const data = event?.data;
302
+ const callId = data?.callId;
303
+ const isDecision =
304
+ typeof data?.operationId === "string" &&
305
+ data.operationId.startsWith("decision:");
306
+ if (event?.type === "model_usage_started" && isDecision) {
307
+ if (typeof callId !== "string" || !callId || seenCallIds.has(callId)) {
308
+ blocked = true;
309
+ return;
310
+ }
311
+ let boundary;
312
+ try {
313
+ boundary = projectRuntimeUsageBoundary(data, "started");
314
+ } catch {
315
+ blocked = true;
316
+ return;
317
+ }
318
+ seenCallIds.add(callId);
319
+ started.set(callId, boundary);
320
+ } else if (
321
+ event?.type === "model_usage_unknown" &&
322
+ (isDecision || started.has(callId))
323
+ ) {
324
+ blocked = true;
325
+ } else if (event?.type === "token_usage" && started.has(callId)) {
326
+ let settlement;
327
+ try {
328
+ settlement = projectRuntimeTokenUsage(data);
329
+ } catch {
330
+ blocked = true;
331
+ return;
332
+ }
333
+ const boundary = started.get(callId);
334
+ if (
335
+ settlement.callId !== boundary.callId ||
336
+ settlement.operationId !== boundary.operationId ||
337
+ settlement.provider !== boundary.provider ||
338
+ settlement.model !== boundary.model ||
339
+ settlement.source !== boundary.source
340
+ ) {
341
+ blocked = true;
342
+ return;
343
+ }
344
+ started.delete(callId);
345
+ }
346
+ },
347
+ finish() {
348
+ return blocked || started.size > 0;
349
+ },
350
+ };
351
+ }
352
+
353
+ function hasUnreconciledDecisionUsage(events) {
354
+ if (!Array.isArray(events)) return true;
355
+ const projection = createDecisionUsageRecoveryProjection();
356
+ for (const event of events) {
357
+ projection.accept(event);
358
+ }
359
+ return projection.finish();
360
+ }
361
+
291
362
  /**
292
363
  * Resolve a --permission-mode string into the session-policy tier + a
293
364
  * non-interactive confirmer + whether to clamp tools to the read-only set.
@@ -500,6 +571,7 @@ export function applyForkSession(opts = {}, store = {}) {
500
571
  */
501
572
  const HEADLESS_SESSION_RESOLUTION = Symbol("headlessSessionResolution");
502
573
  const HEADLESS_SESSION_HOST_LEASE = Symbol("headlessSessionHostLease");
574
+ const HEADLESS_CANONICAL_ADMISSION = Symbol("headlessCanonicalAdmission");
503
575
  const HEADLESS_HOOK_EVENT_CLEANUP = Symbol("headlessHookEventCleanup");
504
576
  const HOST_EVENT_BACKLOG_CODE = "CC_HOST_EVENT_BACKLOG_EXHAUSTED";
505
577
  const HOST_EVENT_BACKLOG_ERROR =
@@ -528,6 +600,7 @@ async function withHeadlessSessionHostLease(options, deps, task) {
528
600
  let lease = null;
529
601
  let budgetRoot = null;
530
602
  let scopedOptions = options;
603
+ let preflightAdmission;
531
604
  try {
532
605
  // Session authority/lease/budget setup can lazily initialize AppConfig and
533
606
  // DatabaseManager. Those legacy diagnostics use console.info (stdout), and
@@ -589,13 +662,101 @@ async function withHeadlessSessionHostLease(options, deps, task) {
589
662
  : lease.signal,
590
663
  }
591
664
  : options;
665
+ const canReadCanonical =
666
+ !hasInjectedSessionStore ||
667
+ typeof deps.readVerifiedEvents === "function";
668
+ if (
669
+ authoritySessionId &&
670
+ !canReadCanonical &&
671
+ (deps.sessionBudgetStore || options.sessionBudgetRoot?.enabled) &&
672
+ (resolution.resumeId ||
673
+ deps.sessionExists?.(authoritySessionId) !== false)
674
+ ) {
675
+ throw Object.assign(
676
+ new Error("budgeted resume requires verified session events"),
677
+ { code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
678
+ );
679
+ }
680
+ if (authoritySessionId && canReadCanonical) {
681
+ preflightAdmission = readSessionHostResumeState(authoritySessionId, {
682
+ sessionHasPersistedEvidence:
683
+ deps.sessionHasPersistedEvidence ||
684
+ (!hasInjectedSessionStore
685
+ ? jsonlSessionHasPersistedEvidence
686
+ : undefined),
687
+ sessionExists: deps.sessionExists || jsonlSessionExists,
688
+ readVerifiedEvents:
689
+ deps.readVerifiedEvents || jsonlReadVerifiedEvents,
690
+ });
691
+ }
692
+ if (preflightAdmission && !preflightAdmission.snapshot.verified) {
693
+ // The inner runner reports the canonical failure without opening or
694
+ // mutating a budget sidecar for an unverified transcript.
695
+ return;
696
+ }
697
+ const sidecar =
698
+ authoritySessionId &&
699
+ (process.platform === "linux" || deps.sessionBudgetStore)
700
+ ? readProductionSessionBudget(authoritySessionId, {
701
+ store: deps.sessionBudgetStore,
702
+ })
703
+ : null;
704
+ if (!preflightAdmission && !hasInjectedSessionStore && sidecar) {
705
+ throw Object.assign(
706
+ new Error("budget sidecar has no canonical JSONL session"),
707
+ { code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
708
+ );
709
+ }
710
+ let effectiveBudgetConfig = options.sessionBudgetRoot;
711
+ if (preflightAdmission) {
712
+ const canonicalConfig = preflightAdmission.sessionBudgetRoot;
713
+ const requestedConfig = options.sessionBudgetRoot?.enabled
714
+ ? normalizeSessionBudgetRootConfig(options.sessionBudgetRoot)
715
+ : null;
716
+ if (canonicalConfig?.enabled) {
717
+ if (!sidecar) {
718
+ throw Object.assign(
719
+ new Error(
720
+ "budgeted session is missing its durable budget sidecar",
721
+ ),
722
+ { code: "CC_SESSION_BUDGET_SIDECAR_REQUIRED" },
723
+ );
724
+ }
725
+ if (requestedConfig) {
726
+ if (
727
+ JSON.stringify(requestedConfig) !==
728
+ JSON.stringify(canonicalConfig)
729
+ ) {
730
+ throw Object.assign(
731
+ new Error(
732
+ "session budget does not match its JSONL declaration",
733
+ ),
734
+ { code: "CC_SESSION_BUDGET_CONFIG_MISMATCH" },
735
+ );
736
+ }
737
+ } else {
738
+ effectiveBudgetConfig = canonicalConfig;
739
+ }
740
+ } else if (requestedConfig || sidecar) {
741
+ throw Object.assign(
742
+ new Error(
743
+ "existing session has no canonical JSONL budget declaration",
744
+ ),
745
+ { code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
746
+ );
747
+ }
748
+ }
749
+ scopedOptions = {
750
+ ...scopedOptions,
751
+ sessionBudgetRoot: effectiveBudgetConfig,
752
+ };
592
753
  budgetRoot = openProductionSessionBudgetRoot(
593
754
  authoritySessionId,
594
- options.sessionBudgetRoot,
755
+ effectiveBudgetConfig,
595
756
  {
596
757
  persist: resolution.persist,
597
758
  signal: scopedOptions.signal || null,
598
- table: options.sessionBudgetRoot?.table,
759
+ table: effectiveBudgetConfig?.table || options.priceTable,
599
760
  open: deps.openSessionBudget,
600
761
  store: deps.sessionBudgetStore,
601
762
  registry: deps.sessionBudgetRegistry,
@@ -609,6 +770,7 @@ async function withHeadlessSessionHostLease(options, deps, task) {
609
770
  ...deps,
610
771
  [HEADLESS_SESSION_RESOLUTION]: resolution,
611
772
  [HEADLESS_SESSION_HOST_LEASE]: lease,
773
+ [HEADLESS_CANONICAL_ADMISSION]: preflightAdmission,
612
774
  });
613
775
  } finally {
614
776
  // Cleanup can touch the same lazy stores. Keep late diagnostics out of a
@@ -939,18 +1101,20 @@ async function runAgentHeadlessInWorkspace(
939
1101
  !hasInjectedSessionStore || typeof deps.readVerifiedEvents === "function";
940
1102
  const canonicalAdmissionId = resumeId || (persist ? sessionId : null);
941
1103
  const canonicalAdmission =
942
- canonicalAdmissionId && canReadCanonicalResume
943
- ? readSessionHostResumeState(canonicalAdmissionId, {
944
- sessionHasPersistedEvidence:
945
- deps.sessionHasPersistedEvidence ||
946
- (!hasInjectedSessionStore
947
- ? jsonlSessionHasPersistedEvidence
948
- : undefined),
949
- sessionExists: deps.sessionExists || jsonlSessionExists,
950
- readVerifiedEvents:
951
- deps.readVerifiedEvents || jsonlReadVerifiedEvents,
952
- })
953
- : null;
1104
+ deps[HEADLESS_CANONICAL_ADMISSION] !== undefined
1105
+ ? deps[HEADLESS_CANONICAL_ADMISSION]
1106
+ : canonicalAdmissionId && canReadCanonicalResume
1107
+ ? readSessionHostResumeState(canonicalAdmissionId, {
1108
+ sessionHasPersistedEvidence:
1109
+ deps.sessionHasPersistedEvidence ||
1110
+ (!hasInjectedSessionStore
1111
+ ? jsonlSessionHasPersistedEvidence
1112
+ : undefined),
1113
+ sessionExists: deps.sessionExists || jsonlSessionExists,
1114
+ readVerifiedEvents:
1115
+ deps.readVerifiedEvents || jsonlReadVerifiedEvents,
1116
+ })
1117
+ : null;
954
1118
  if (canonicalAdmission && !canonicalAdmission.snapshot.verified) {
955
1119
  const message =
956
1120
  "CC_SESSION_HOST_SNAPSHOT_UNVERIFIED: canonical JSONL session is not " +
@@ -2012,6 +2176,9 @@ async function runAgentHeadlessInWorkspace(
2012
2176
  provider,
2013
2177
  model,
2014
2178
  observabilityScope: options.observabilityScope,
2179
+ ...(options.sessionBudgetRoot?.enabled === true
2180
+ ? { sessionBudgetRoot: options.sessionBudgetRoot }
2181
+ : {}),
2015
2182
  executionLocation: captureAmbientExecutionLocation({
2016
2183
  provider,
2017
2184
  model,
@@ -2458,13 +2625,35 @@ async function runAgentHeadlessInWorkspace(
2458
2625
  const skillDecisionOptions = resolveHeadlessSkillDecisionOptions(options);
2459
2626
  let skillDecisionRuntime = null;
2460
2627
  if (skillDecisionOptions.mode !== "off") {
2461
- const previousUnknownDecisionUsage = store.findLatestEvent(
2462
- sessionId,
2463
- "model_usage_unknown",
2464
- (event) =>
2465
- typeof event?.data?.operationId === "string" &&
2466
- event.data.operationId.startsWith("decision:"),
2467
- );
2628
+ let previousUnreconciledDecisionUsage;
2629
+ if (
2630
+ !hasInjectedSessionStore ||
2631
+ typeof deps.readVerifiedEvents === "function"
2632
+ ) {
2633
+ try {
2634
+ previousUnreconciledDecisionUsage = hasInjectedSessionStore
2635
+ ? hasUnreconciledDecisionUsage(store.readVerifiedEvents(sessionId))
2636
+ : jsonlReadVerifiedProjection(
2637
+ sessionId,
2638
+ createDecisionUsageRecoveryProjection,
2639
+ );
2640
+ } catch {
2641
+ // Without a verified settlement, a resumed provider call could be paid twice.
2642
+ previousUnreconciledDecisionUsage = true;
2643
+ }
2644
+ } else {
2645
+ // Legacy injected stores cannot prove a prior call was settled. Their
2646
+ // explicit no-session answer still permits a fresh test/embedding run.
2647
+ previousUnreconciledDecisionUsage =
2648
+ store.sessionExists(sessionId) ||
2649
+ store.findLatestEvent(
2650
+ sessionId,
2651
+ "model_usage_unknown",
2652
+ (event) =>
2653
+ typeof event?.data?.operationId === "string" &&
2654
+ event.data.operationId.startsWith("decision:"),
2655
+ ) != null;
2656
+ }
2468
2657
  const decisionProvider =
2469
2658
  deps.decisionProvider ||
2470
2659
  createDecisionProvider({
@@ -2487,11 +2676,12 @@ async function runAgentHeadlessInWorkspace(
2487
2676
  options.decisionTenantId || evolutionIngress?.tenantId || "cli-local",
2488
2677
  sessionId,
2489
2678
  provider: decisionProvider,
2679
+ evolutionIngress,
2490
2680
  persist: persistDecisionEvent,
2491
2681
  observe: (observation) =>
2492
2682
  persistDecisionEvent("skill_decision_observation", observation),
2493
2683
  sessionBudget: options.sessionBudget || null,
2494
- initialUsageUnknown: previousUnknownDecisionUsage != null,
2684
+ initialUsageUnknown: previousUnreconciledDecisionUsage,
2495
2685
  timeoutMs: skillDecisionOptions.timeoutMs,
2496
2686
  });
2497
2687
  }