chainlesschain 0.166.103 → 0.166.105

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 (183) hide show
  1. package/README.md +14 -2
  2. package/package.json +2 -1
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-BLrXpdnP.js → AIOps-CcD-AVDw.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-C0xy9uFy.js → ActionButton-CYy-g36A.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-C6EephQP.js → Analytics-DPFDNaBL.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-ZCXdOD9y.js → AppLayout-PVIuRdgN.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-D4MfZ-pl.js → Artifacts-BXGD3bM-.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-BQ8c3bBu.js → Audit-Bu5s_4tu.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-BOA7_ljM.js → BackgroundAgents-BHmgpnzo.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-60uiQjGT.js → Backup-C872jURx.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-BDvEbGs_.js → BaseInput-Bh7xO30H.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-B3IkAuFQ.js → Chat-DaacK53T.js} +6 -6
  15. package/src/assets/web-panel/assets/ChatBubbleRenderer-PYrSKMM_.js +1 -0
  16. package/src/assets/web-panel/assets/{Checkbox-njGbfJWq.js → Checkbox-Cnt7_8I2.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-CF7DtdxC.js → Codegen-AZRz6kmW.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-C_3Zix40.js → Col-BtOXzMFt.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-CzU-ZC2d.js → Community-BFmFygS7.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-BgeqsPRh.js → Compact-2z5CfKpR.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-6l7cwiqp.js → Compliance-B5hKrPVF.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-D4s905fI.js → Cowork-CxEyp2ww.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-CGTYSxRS.js → Cron-B-8f9_qF.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BnSo-Yt3.js → Crosschain-XARMOcc4.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Dm4vk2X1.js → DID-DwLtEKAe.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-D7H-PZ_N.js → Dashboard-Cjw0L_iA.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-COslkgxn.js → Dropdown-BBGWIP7l.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CJWEetmk.js → EmailListRenderer-DG4kZFkm.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-BbzebAWe.js → EvolutionSettings-D8vuNDde.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BsoTOXwk.js → FamilyGuardDashboard-COXCzDXI.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-Ck5kM_5H.js → Federation-Btb-aMhW.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-gShxCqtF.js → FormItemContext-TO-E6l6e.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-DarN1G-z.js → GenericCardRenderer-BWXdJCT0.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-CJfpLyP5.js → Git-B6icGhEv.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-CVcJmpQz.js → Governance-C5Y__K6S.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-ComU_ig8.js → Inference-DZGEKnbN.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-35hprFJy.js → KnowledgeGraph--Kga5yvm.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-BQDqBTz0.js → Logs-BXs3EPKj.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-BsSiyE-A.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-B9O9OKnn.js → Marketplace-JSEAu0su.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-VMKxA4Wc.js → McpTools-BUBifkKP.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CcBbf3Bc.js → Memory-Cb7sE4a-.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-D7myz46N.js → MobileBridge-BOzmmNV2.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-Da5KBXyx.js → MobileProjects-ClRlavdF.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-x3NPZfuL.js → Mtc-DmMWErG1.js} +5 -5
  46. package/src/assets/web-panel/assets/{MtcAudit-CwnzptEC.js → MtcAudit-DnGkRVXF.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-CCAxf4Ye.js → Multisig-C3mzascL.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-CptHKz-Q.js → NLProgramming-CrmMZZ1t.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-0uEp4DCJ.js → Notes-4S6uts9Q.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-DthvrOLd.js → NotificationSettings-gn3UrWwW.js} +1 -1
  51. package/src/assets/web-panel/assets/OrderTableRenderer-CDVAlBUf.js +1 -0
  52. package/src/assets/web-panel/assets/{Organization-BWf2tmQQ.js → Organization-fMlkdgpW.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-BbvAtEth.js → Overflow-DGwCUPU1.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-zBo6enit.js → P2P-BDGcpPmf.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-D_LMQ4A4.js → PdhVaultBrowser-CccRPAB9.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-C1ucb2ck.js → Permissions-C33dNECx.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-Bz64RddJ.js → PersonalDataHub-BeqbCStc.js} +5 -5
  58. package/src/assets/web-panel/assets/{Pipeline-DXJt3y3_.js → Pipeline-CTmasgbQ.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-DiZ8b_ut.js → Privacy-ktd37BSp.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-DfLKKrJ4.js → ProjectInit-KOGvQtBX.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-Ct6kJuIY.js → ProjectSettings-CUvH_hC6.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-BBUMlZ3m.js → Projects-BvP_Os-1.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-DYVQPHvc.js → Providers-C-hmLXlO.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-23Il7iPp.js → QrScannerModal-DzG_rbSL.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-WgOZKrv1.js → QuickAsk-ShwiATg4.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-CRIka6xT.js → Recommend-DkV8Ruep.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-DOy3GjVZ.js → RemoteSession-Ca2dOx_G.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-BXyi6xeR.js → Reputation-DYA5BJ6A.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-CoMxuIcR.js → Row-DvGDgxLS.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-87hPkoM6.js → RssFeed-DbwTBSPw.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-B1EqFCO4.js → Search-C5XAMQ9T.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-HcC41eGs.js → Security-CKWT60Qt.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-BqLwmvCM.js → Services-CZvASlWL.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-CIMmjW4r.js → Skeleton-DFkMVqws.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-CgurezJU.js → Skills-hslZ_GyP.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-CJuRuqPE.js → Sla-BLW5rmZ5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-BUwsbd1o.js → SpeechSettings-Cn4ffCi5.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-qo04TOX-.js → SyncSettings-D1K0nJuo.js} +2 -2
  79. package/src/assets/web-panel/assets/Tasks-CCRu0xoN.js +1 -0
  80. package/src/assets/web-panel/assets/{Templates-D1PTczPW.js → Templates-L19GYuS4.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-Bi0FkEPR.js → Tenant-CZ6HE3PF.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-DfSt3bIF.js → Terminal-BiAwzaBT.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-B7bIVs4R.js → TimelineRenderer-DRHSWQT5.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-B6w5XrMb.js → Tokens-Cm-XATgh.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-XXVSDWiF.js → Trigger-BVXtx3kn.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-DYvlgcK-.js → Trust-Bb0TmkLJ.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-XyYwJMBM.js → UkeySign-Dbt9R7l0.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-C47WbtHH.js → VideoEditing-z0-Ti8eJ.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-CYfqTj_C.js → Wallet-BZh31tI-.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-3AduFn1l.js → WebAuthn-DQ0yIr5K.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-DHYEHjMJ.js → WorkflowEditor-DCt_yuWG.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-AeehErSw.js → chat-BLgtmFeS.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-DKXJ8paX.js → colors-xU4UH8M1.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-BOlCiomD.js → compact-item-C4w4v16T.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BAP6U85b.js → createContext-CZM9hAaj.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-BZUZgMkO.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-BLmeL1Xe.js → hasIn-DvHqEpE7.js} +1 -1
  98. package/src/assets/web-panel/assets/index--_-pNhk0.js +1 -0
  99. package/src/assets/web-panel/assets/{index-wyKpTsGM.js → index-55Rkd1KA.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CaHhfpBi.js → index-B0IvKEVO.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-EKNODw4P.js → index-B4jIcYSv.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-C5AKY6bJ.js → index-B64Vf-8H.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-C8qi53Ki.js → index-B6AQ2b5U.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-FPXLIXoy.js → index-BHK3CQHq.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CRa4pAaM.js → index-BHg9NoJ5.js} +3 -3
  106. package/src/assets/web-panel/assets/{index-Bn54FU3i.js → index-BIWumeQl.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CdNSmvog.js → index-BRhD9RMV.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-De2fPxdb.js → index-BTxhDCtg.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CgtaOzMo.js → index-BaQZvM4m.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CFKzWIo8.js → index-Bf8Wm4ks.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-OLKhib9T.js → index-Bh14b1k0.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-B0IjlB9m.js → index-BkTKWAgq.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-PEe9OWEQ.js → index-BlN5KPq6.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DpZqbc4w.js → index-C6ZrTSw5.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Bpx54vfs.js → index-C9YnZFv2.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DsQ38fVY.js → index-CExiTobS.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BTnp4Nt3.js → index-CF9ebAIB.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BuUwKmEI.js → index-CKugxsw3.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-IlzfIRNh.js → index-CPC7OGCe.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BSOenF5s.js → index-CPDw21XY.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-T28naovw.js → index-CQEzxnYS.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DWYqOI1A.js → index-CRLP56-W.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-ZMbXl5lo.js → index-CYrQnkqA.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DQLQuwpA.js → index-Cm00787d.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Co7pjF53.js → index-CpiuuIww.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-urPvyUVk.js → index-CqDiY-jl.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BhcpWl5z.js → index-CyV8fNBg.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BAS2QqLn.js → index-DGdLkss8.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BRcJlKSa.js → index-DifMvnMQ.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Dv8-g1pY.js → index-Ds1tM734.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DE7cbDDe.js → index-Ds6wKTMh.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Bt-FCVzh.js → index-QHmhwgfc.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-Bs2O3f81.js → index-SNV95Zen.js} +1 -1
  134. package/src/assets/web-panel/assets/index-ftwO31cp.js +1 -0
  135. package/src/assets/web-panel/assets/{index-ClpwxOXo.js → index-n6SAUmmI.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-CiqeF0Pf.js → index-wYRjvvbl.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-CDWa1rnn.js → initDefaultProps-C44ZER6c.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-CX2Cnsd5.js → motion-DbNzzScd.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-Bfe1NcEF.js → move-BrRrDH2u.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-DbdqleHE.js → mtc-parser-DZ_T_Pw8.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-CE2K7NVv.js → omit-5QHHk_V3.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-y_bZgxWG.js → pickAttrs-BdxEl0G2.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BOHR4zwr.js → placementArrow-CGyD615D.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-B8Jwq05-.js → responsiveObserve-QqcWAQmN.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-BD7RJ3Kn.js → slide-BumQrJ5R.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-BuxDJeDx.js → statusUtils-Pf64olM7.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DgYQ2Q0o.js → styleChecker-DNwm5SQZ.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-DAHF0Fwi.js → useFlexGapSupport-c3gLKs6e.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-D4kDyLFp.js → useFs-TzTd6NDM.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BHtSxW4A.js → usePersonalDataHub-BP5E_0Fe.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-CHKtdqW0.js → vnode-CVEkRfZU.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-CIZAMma9.js → zoom-C18X_8TJ.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/commands/agent.js +56 -20
  155. package/src/commands/batch.js +17 -12
  156. package/src/commands/eval.js +24 -8
  157. package/src/data/changelog.json +26 -0
  158. package/src/harness/mcp-client.js +187 -26
  159. package/src/lib/background-session-transport.js +21 -5
  160. package/src/lib/coding-task-guidance.js +13 -0
  161. package/src/lib/decision-layer/runtime.js +180 -10
  162. package/src/lib/direct-model-usage.js +34 -0
  163. package/src/lib/evolution/agent-evolution-ingress.js +63 -7
  164. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +10 -0
  165. package/src/lib/evolution/evolution-evidence-projector.js +46 -7
  166. package/src/lib/evolution/skill-decision-projection.js +211 -0
  167. package/src/lib/evolution/skill-retrieval-revocation-authority.js +17 -2
  168. package/src/lib/file-import-diagnostics.js +246 -0
  169. package/src/lib/skill-loader.js +16 -0
  170. package/src/lib/transport-error-details.js +83 -0
  171. package/src/repl/agent-repl.js +86 -7
  172. package/src/runtime/agent-core.js +248 -15
  173. package/src/runtime/headless-runner.js +295 -71
  174. package/src/runtime/headless-stream.js +197 -27
  175. package/src/runtime/mcp-config.js +26 -17
  176. package/src/runtime/mcp-tool-search.js +44 -14
  177. package/src/assets/web-panel/assets/ChatBubbleRenderer-n6BVStHf.js +0 -1
  178. package/src/assets/web-panel/assets/MarkdownRenderer-BpdGAVCC.js +0 -1
  179. package/src/assets/web-panel/assets/OrderTableRenderer-CxXuPzZg.js +0 -1
  180. package/src/assets/web-panel/assets/Tasks-QEFENVsp.js +0 -1
  181. package/src/assets/web-panel/assets/devWarning-rGldFhxo.js +0 -1
  182. package/src/assets/web-panel/assets/index-Cw-lfvvV.js +0 -1
  183. package/src/assets/web-panel/assets/index-QBXRSyoZ.js +0 -1
@@ -23,7 +23,9 @@
23
23
  */
24
24
 
25
25
  import { randomUUID } from "node:crypto";
26
+ import { transportErrorDetails } from "../lib/transport-error-details.js";
26
27
  import { captureAgentExecutionPolicy } from "../lib/agent-execution-policy.js";
28
+ import { HERMETIC_CODING_SYSTEM_PROMPT } from "../lib/coding-task-guidance.js";
27
29
  import { bootstrap } from "./bootstrap.js";
28
30
  import {
29
31
  buildSystemPrompt,
@@ -57,6 +59,7 @@ import {
57
59
  appendAuthorityEvent as jsonlAppendAuthorityEvent,
58
60
  readEvents as jsonlReadEvents,
59
61
  readVerifiedEvents as jsonlReadVerifiedEvents,
62
+ readVerifiedProjection as jsonlReadVerifiedProjection,
60
63
  findLatestEvent as jsonlFindLatestEvent,
61
64
  rebuildMessages as jsonlRebuildMessages,
62
65
  sessionExists as jsonlSessionExists,
@@ -137,7 +140,9 @@ import executionBroker from "../lib/process-execution-broker/index.js";
137
140
  import { extractPluginUsageAttribution } from "../lib/plugin-usage-attribution.js";
138
141
  import { formatManagedCheckpointEvent } from "../lib/managed-checkpoint-render.js";
139
142
  import {
143
+ normalizeSessionBudgetRootConfig,
140
144
  openProductionSessionBudgetRoot,
145
+ readProductionSessionBudget,
141
146
  sessionBudgetAdmissionError,
142
147
  } from "../lib/session-budget-production-root.js";
143
148
  import {
@@ -288,6 +293,74 @@ export function resolveHeadlessSkillDecisionOptions(options = {}) {
288
293
  });
289
294
  }
290
295
 
296
+ function createDecisionUsageRecoveryProjection() {
297
+ const started = new Map();
298
+ const seenCallIds = new Set();
299
+ let blocked = false;
300
+ return {
301
+ accept(event) {
302
+ if (blocked) return;
303
+ const data = event?.data;
304
+ const callId = data?.callId;
305
+ const isDecision =
306
+ typeof data?.operationId === "string" &&
307
+ data.operationId.startsWith("decision:");
308
+ if (event?.type === "model_usage_started" && isDecision) {
309
+ if (typeof callId !== "string" || !callId || seenCallIds.has(callId)) {
310
+ blocked = true;
311
+ return;
312
+ }
313
+ let boundary;
314
+ try {
315
+ boundary = projectRuntimeUsageBoundary(data, "started");
316
+ } catch {
317
+ blocked = true;
318
+ return;
319
+ }
320
+ seenCallIds.add(callId);
321
+ started.set(callId, boundary);
322
+ } else if (
323
+ event?.type === "model_usage_unknown" &&
324
+ (isDecision || started.has(callId))
325
+ ) {
326
+ blocked = true;
327
+ } else if (event?.type === "token_usage" && started.has(callId)) {
328
+ let settlement;
329
+ try {
330
+ settlement = projectRuntimeTokenUsage(data);
331
+ } catch {
332
+ blocked = true;
333
+ return;
334
+ }
335
+ const boundary = started.get(callId);
336
+ if (
337
+ settlement.callId !== boundary.callId ||
338
+ settlement.operationId !== boundary.operationId ||
339
+ settlement.provider !== boundary.provider ||
340
+ settlement.model !== boundary.model ||
341
+ settlement.source !== boundary.source
342
+ ) {
343
+ blocked = true;
344
+ return;
345
+ }
346
+ started.delete(callId);
347
+ }
348
+ },
349
+ finish() {
350
+ return blocked || started.size > 0;
351
+ },
352
+ };
353
+ }
354
+
355
+ function hasUnreconciledDecisionUsage(events) {
356
+ if (!Array.isArray(events)) return true;
357
+ const projection = createDecisionUsageRecoveryProjection();
358
+ for (const event of events) {
359
+ projection.accept(event);
360
+ }
361
+ return projection.finish();
362
+ }
363
+
291
364
  /**
292
365
  * Resolve a --permission-mode string into the session-policy tier + a
293
366
  * non-interactive confirmer + whether to clamp tools to the read-only set.
@@ -500,6 +573,7 @@ export function applyForkSession(opts = {}, store = {}) {
500
573
  */
501
574
  const HEADLESS_SESSION_RESOLUTION = Symbol("headlessSessionResolution");
502
575
  const HEADLESS_SESSION_HOST_LEASE = Symbol("headlessSessionHostLease");
576
+ const HEADLESS_CANONICAL_ADMISSION = Symbol("headlessCanonicalAdmission");
503
577
  const HEADLESS_HOOK_EVENT_CLEANUP = Symbol("headlessHookEventCleanup");
504
578
  const HOST_EVENT_BACKLOG_CODE = "CC_HOST_EVENT_BACKLOG_EXHAUSTED";
505
579
  const HOST_EVENT_BACKLOG_ERROR =
@@ -528,6 +602,7 @@ async function withHeadlessSessionHostLease(options, deps, task) {
528
602
  let lease = null;
529
603
  let budgetRoot = null;
530
604
  let scopedOptions = options;
605
+ let preflightAdmission;
531
606
  try {
532
607
  // Session authority/lease/budget setup can lazily initialize AppConfig and
533
608
  // DatabaseManager. Those legacy diagnostics use console.info (stdout), and
@@ -589,13 +664,101 @@ async function withHeadlessSessionHostLease(options, deps, task) {
589
664
  : lease.signal,
590
665
  }
591
666
  : options;
667
+ const canReadCanonical =
668
+ !hasInjectedSessionStore ||
669
+ typeof deps.readVerifiedEvents === "function";
670
+ if (
671
+ authoritySessionId &&
672
+ !canReadCanonical &&
673
+ (deps.sessionBudgetStore || options.sessionBudgetRoot?.enabled) &&
674
+ (resolution.resumeId ||
675
+ deps.sessionExists?.(authoritySessionId) !== false)
676
+ ) {
677
+ throw Object.assign(
678
+ new Error("budgeted resume requires verified session events"),
679
+ { code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
680
+ );
681
+ }
682
+ if (authoritySessionId && canReadCanonical) {
683
+ preflightAdmission = readSessionHostResumeState(authoritySessionId, {
684
+ sessionHasPersistedEvidence:
685
+ deps.sessionHasPersistedEvidence ||
686
+ (!hasInjectedSessionStore
687
+ ? jsonlSessionHasPersistedEvidence
688
+ : undefined),
689
+ sessionExists: deps.sessionExists || jsonlSessionExists,
690
+ readVerifiedEvents:
691
+ deps.readVerifiedEvents || jsonlReadVerifiedEvents,
692
+ });
693
+ }
694
+ if (preflightAdmission && !preflightAdmission.snapshot.verified) {
695
+ // The inner runner reports the canonical failure without opening or
696
+ // mutating a budget sidecar for an unverified transcript.
697
+ return;
698
+ }
699
+ const sidecar =
700
+ authoritySessionId &&
701
+ (process.platform === "linux" || deps.sessionBudgetStore)
702
+ ? readProductionSessionBudget(authoritySessionId, {
703
+ store: deps.sessionBudgetStore,
704
+ })
705
+ : null;
706
+ if (!preflightAdmission && !hasInjectedSessionStore && sidecar) {
707
+ throw Object.assign(
708
+ new Error("budget sidecar has no canonical JSONL session"),
709
+ { code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
710
+ );
711
+ }
712
+ let effectiveBudgetConfig = options.sessionBudgetRoot;
713
+ if (preflightAdmission) {
714
+ const canonicalConfig = preflightAdmission.sessionBudgetRoot;
715
+ const requestedConfig = options.sessionBudgetRoot?.enabled
716
+ ? normalizeSessionBudgetRootConfig(options.sessionBudgetRoot)
717
+ : null;
718
+ if (canonicalConfig?.enabled) {
719
+ if (!sidecar) {
720
+ throw Object.assign(
721
+ new Error(
722
+ "budgeted session is missing its durable budget sidecar",
723
+ ),
724
+ { code: "CC_SESSION_BUDGET_SIDECAR_REQUIRED" },
725
+ );
726
+ }
727
+ if (requestedConfig) {
728
+ if (
729
+ JSON.stringify(requestedConfig) !==
730
+ JSON.stringify(canonicalConfig)
731
+ ) {
732
+ throw Object.assign(
733
+ new Error(
734
+ "session budget does not match its JSONL declaration",
735
+ ),
736
+ { code: "CC_SESSION_BUDGET_CONFIG_MISMATCH" },
737
+ );
738
+ }
739
+ } else {
740
+ effectiveBudgetConfig = canonicalConfig;
741
+ }
742
+ } else if (requestedConfig || sidecar) {
743
+ throw Object.assign(
744
+ new Error(
745
+ "existing session has no canonical JSONL budget declaration",
746
+ ),
747
+ { code: "CC_SESSION_BUDGET_JSONL_REQUIRED" },
748
+ );
749
+ }
750
+ }
751
+ scopedOptions = {
752
+ ...scopedOptions,
753
+ sessionBudgetRoot: effectiveBudgetConfig,
754
+ };
592
755
  budgetRoot = openProductionSessionBudgetRoot(
593
756
  authoritySessionId,
594
- options.sessionBudgetRoot,
757
+ effectiveBudgetConfig,
595
758
  {
596
759
  persist: resolution.persist,
597
760
  signal: scopedOptions.signal || null,
598
- table: options.sessionBudgetRoot?.table,
761
+ table: effectiveBudgetConfig?.table || options.priceTable,
599
762
  open: deps.openSessionBudget,
600
763
  store: deps.sessionBudgetStore,
601
764
  registry: deps.sessionBudgetRegistry,
@@ -609,6 +772,7 @@ async function withHeadlessSessionHostLease(options, deps, task) {
609
772
  ...deps,
610
773
  [HEADLESS_SESSION_RESOLUTION]: resolution,
611
774
  [HEADLESS_SESSION_HOST_LEASE]: lease,
775
+ [HEADLESS_CANONICAL_ADMISSION]: preflightAdmission,
612
776
  });
613
777
  } finally {
614
778
  // Cleanup can touch the same lazy stores. Keep late diagnostics out of a
@@ -939,18 +1103,20 @@ async function runAgentHeadlessInWorkspace(
939
1103
  !hasInjectedSessionStore || typeof deps.readVerifiedEvents === "function";
940
1104
  const canonicalAdmissionId = resumeId || (persist ? sessionId : null);
941
1105
  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;
1106
+ deps[HEADLESS_CANONICAL_ADMISSION] !== undefined
1107
+ ? deps[HEADLESS_CANONICAL_ADMISSION]
1108
+ : canonicalAdmissionId && canReadCanonicalResume
1109
+ ? readSessionHostResumeState(canonicalAdmissionId, {
1110
+ sessionHasPersistedEvidence:
1111
+ deps.sessionHasPersistedEvidence ||
1112
+ (!hasInjectedSessionStore
1113
+ ? jsonlSessionHasPersistedEvidence
1114
+ : undefined),
1115
+ sessionExists: deps.sessionExists || jsonlSessionExists,
1116
+ readVerifiedEvents:
1117
+ deps.readVerifiedEvents || jsonlReadVerifiedEvents,
1118
+ })
1119
+ : null;
954
1120
  if (canonicalAdmission && !canonicalAdmission.snapshot.verified) {
955
1121
  const message =
956
1122
  "CC_SESSION_HOST_SNAPSHOT_UNVERIFIED: canonical JSONL session is not " +
@@ -1059,8 +1225,9 @@ async function runAgentHeadlessInWorkspace(
1059
1225
  const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
1060
1226
  // Fold in installed plugins' hooks/hooks.json (Phase 3.3c) — plugins ADD
1061
1227
  // to the user's settings hooks, never replace them.
1062
- const { mergePluginHooks } =
1063
- await import("../lib/plugin-runtime/hooks.js");
1228
+ const { mergePluginHooks } = await import(
1229
+ "../lib/plugin-runtime/hooks.js"
1230
+ );
1064
1231
  const effectiveHooks = mergePluginHooks(
1065
1232
  attachAuthorityErrors(loaded.hooks, loaded.authorityErrors),
1066
1233
  { cwd },
@@ -1101,8 +1268,9 @@ async function runAgentHeadlessInWorkspace(
1101
1268
  // the run, so no explicit restore is needed.
1102
1269
  if (!hermeticExecution) {
1103
1270
  try {
1104
- const { applyPluginBinPath } =
1105
- await import("../lib/plugin-runtime/bin.js");
1271
+ const { applyPluginBinPath } = await import(
1272
+ "../lib/plugin-runtime/bin.js"
1273
+ );
1106
1274
  applyPluginBinPath({ cwd });
1107
1275
  } catch {
1108
1276
  /* best-effort — plugin bin PATH never blocks a headless run */
@@ -1113,8 +1281,9 @@ async function runAgentHeadlessInWorkspace(
1113
1281
  // keys not already set; the process exits at the end so no restore is needed.
1114
1282
  if (!hermeticExecution) {
1115
1283
  try {
1116
- const { applyPluginSettingsEnv } =
1117
- await import("../lib/plugin-runtime/settings.js");
1284
+ const { applyPluginSettingsEnv } = await import(
1285
+ "../lib/plugin-runtime/settings.js"
1286
+ );
1118
1287
  applyPluginSettingsEnv({ cwd });
1119
1288
  } catch {
1120
1289
  /* best-effort — plugin settings never block a headless run */
@@ -1248,8 +1417,9 @@ async function runAgentHeadlessInWorkspace(
1248
1417
  if (isHeadlessConfigCommand(prompt)) {
1249
1418
  const cm = await import("../lib/config-manager.js");
1250
1419
  const { getConfigPath } = await import("../lib/paths.js");
1251
- const { runConfigDirective } =
1252
- await import("../lib/headless-config-command.js");
1420
+ const { runConfigDirective } = await import(
1421
+ "../lib/headless-config-command.js"
1422
+ );
1253
1423
  const { text, isError } = runConfigDirective(prompt, {
1254
1424
  configManager: cm,
1255
1425
  getConfigPath,
@@ -1325,8 +1495,9 @@ async function runAgentHeadlessInWorkspace(
1325
1495
  model = macro.model;
1326
1496
  writeErr(` command: model → ${model}\n`);
1327
1497
  try {
1328
- const { maybeWarnDeprecatedModel } =
1329
- await import("../lib/model-deprecation.js");
1498
+ const { maybeWarnDeprecatedModel } = await import(
1499
+ "../lib/model-deprecation.js"
1500
+ );
1330
1501
  maybeWarnDeprecatedModel({ model });
1331
1502
  } catch {
1332
1503
  // deprecation notice is best-effort
@@ -1363,8 +1534,9 @@ async function runAgentHeadlessInWorkspace(
1363
1534
 
1364
1535
  // ── Permission + tool resolution ──────────────────────────────────────
1365
1536
  if (managedSettings) {
1366
- const { assertManagedPermissionMode } =
1367
- await import("../lib/settings-loader.cjs");
1537
+ const { assertManagedPermissionMode } = await import(
1538
+ "../lib/settings-loader.cjs"
1539
+ );
1368
1540
  assertManagedPermissionMode(options.permissionMode, managedSettings);
1369
1541
  }
1370
1542
  const perm = resolvePermissionMode(options.permissionMode);
@@ -1824,8 +1996,9 @@ async function runAgentHeadlessInWorkspace(
1824
1996
  : null;
1825
1997
  if (!hermeticExecution && !instructionExcludes) {
1826
1998
  try {
1827
- const { readStringArraySetting } =
1828
- await import("../lib/settings-loader.cjs");
1999
+ const { readStringArraySetting } = await import(
2000
+ "../lib/settings-loader.cjs"
2001
+ );
1829
2002
  const fromSettings = readStringArraySetting("instructionExcludes", {
1830
2003
  cwd,
1831
2004
  settingsFile: options.settingsFile,
@@ -1850,10 +2023,9 @@ async function runAgentHeadlessInWorkspace(
1850
2023
  : options.skillLoader ||
1851
2024
  new CLISkillLoader(captureSkillRuntimeDependencies(options));
1852
2025
  const systemContent = hermeticExecution
1853
- ? composeSystemPrompt(
1854
- "You are a hermetic code fixer. The exposed file tools are the complete tool surface. Inspect and mutate only the exact paths authorized in the user request, then return a concise completion message.",
1855
- { projectMemory: false },
1856
- )
2026
+ ? composeSystemPrompt(HERMETIC_CODING_SYSTEM_PROMPT, {
2027
+ projectMemory: false,
2028
+ })
1857
2029
  : composeSystemPrompt(
1858
2030
  buildSystemPrompt(cwd, {
1859
2031
  additionalDirectories,
@@ -1880,8 +2052,9 @@ async function runAgentHeadlessInWorkspace(
1880
2052
  // settings.json UserPromptSubmit hooks. block → abort the run; context → inject.
1881
2053
  if (settingsHooks) {
1882
2054
  try {
1883
- const { runUserPromptSubmitHooks } =
1884
- await import("../lib/settings-hook-events.js");
2055
+ const { runUserPromptSubmitHooks } = await import(
2056
+ "../lib/settings-hook-events.js"
2057
+ );
1885
2058
  const ups = await runUserPromptSubmitHooks(settingsHooks, {
1886
2059
  prompt: userContent,
1887
2060
  cwd,
@@ -1911,8 +2084,9 @@ async function runAgentHeadlessInWorkspace(
1911
2084
  let instructionsLoadedContext = null;
1912
2085
  if (settingsHooks && _loadedInstructions) {
1913
2086
  try {
1914
- const { runInstructionsLoadedHooks } =
1915
- await import("../lib/settings-hook-events.js");
2087
+ const { runInstructionsLoadedHooks } = await import(
2088
+ "../lib/settings-hook-events.js"
2089
+ );
1916
2090
  instructionsLoadedContext = (
1917
2091
  await runInstructionsLoadedHooks(settingsHooks, {
1918
2092
  files: _loadedInstructions.files,
@@ -1929,8 +2103,9 @@ async function runAgentHeadlessInWorkspace(
1929
2103
  let sessionStartContext = null;
1930
2104
  if (settingsHooks) {
1931
2105
  try {
1932
- const { runSessionStartHooks } =
1933
- await import("../lib/settings-hook-events.js");
2106
+ const { runSessionStartHooks } = await import(
2107
+ "../lib/settings-hook-events.js"
2108
+ );
1934
2109
  sessionStartContext = (
1935
2110
  await runSessionStartHooks(settingsHooks, {
1936
2111
  source: resumeId ? "resume" : "startup",
@@ -1950,8 +2125,9 @@ async function runAgentHeadlessInWorkspace(
1950
2125
  // back up" — e.g. re-run a workspace sanity check. Observe-only, best-effort.
1951
2126
  if (settingsHooks && resumeId && history.length > 0) {
1952
2127
  try {
1953
- const { runObserveHooks } =
1954
- await import("../lib/settings-hook-events.js");
2128
+ const { runObserveHooks } = await import(
2129
+ "../lib/settings-hook-events.js"
2130
+ );
1955
2131
  await runObserveHooks(
1956
2132
  settingsHooks,
1957
2133
  "SessionResume",
@@ -2012,6 +2188,9 @@ async function runAgentHeadlessInWorkspace(
2012
2188
  provider,
2013
2189
  model,
2014
2190
  observabilityScope: options.observabilityScope,
2191
+ ...(options.sessionBudgetRoot?.enabled === true
2192
+ ? { sessionBudgetRoot: options.sessionBudgetRoot }
2193
+ : {}),
2015
2194
  executionLocation: captureAmbientExecutionLocation({
2016
2195
  provider,
2017
2196
  model,
@@ -2200,8 +2379,9 @@ async function runAgentHeadlessInWorkspace(
2200
2379
  // --add-dir → workspaceRootDirs = [cwd] and this is a no-op. Best-effort.
2201
2380
  if (hostMcp?.mcpClient && additionalDirectories.length > 0) {
2202
2381
  try {
2203
- const { notifyMcpRootsChanged, workspaceRootDirs } =
2204
- await import("../repl/add-dir.js");
2382
+ const { notifyMcpRootsChanged, workspaceRootDirs } = await import(
2383
+ "../repl/add-dir.js"
2384
+ );
2205
2385
  notifyMcpRootsChanged(
2206
2386
  [hostMcp.mcpClient],
2207
2387
  workspaceRootDirs(options.cwd || process.cwd(), additionalDirectories),
@@ -2309,8 +2489,9 @@ async function runAgentHeadlessInWorkspace(
2309
2489
  error.code = "CC_REMOTE_APPROVAL_GATE_UNAVAILABLE";
2310
2490
  throw error;
2311
2491
  }
2312
- const { startHeadlessRemoteApproval } =
2313
- await import("../lib/remote-approval-bridge.js");
2492
+ const { startHeadlessRemoteApproval } = await import(
2493
+ "../lib/remote-approval-bridge.js"
2494
+ );
2314
2495
  _remoteApproval = await (
2315
2496
  deps.startHeadlessRemoteApproval || startHeadlessRemoteApproval
2316
2497
  )({
@@ -2341,8 +2522,9 @@ async function runAgentHeadlessInWorkspace(
2341
2522
  let _collectorEnabled = false;
2342
2523
  if (!hermeticExecution) {
2343
2524
  try {
2344
- const { isOtlpCollectorEnabled } =
2345
- await import("../lib/observability/index.js");
2525
+ const { isOtlpCollectorEnabled } = await import(
2526
+ "../lib/observability/index.js"
2527
+ );
2346
2528
  _collectorEnabled = isOtlpCollectorEnabled();
2347
2529
  } catch {
2348
2530
  _collectorEnabled = false;
@@ -2350,8 +2532,9 @@ async function runAgentHeadlessInWorkspace(
2350
2532
  }
2351
2533
  if (!hermeticExecution && (options.otlp || _collectorEnabled)) {
2352
2534
  try {
2353
- const { TelemetryRecorder } =
2354
- await import("../lib/telemetry/span-recorder.js");
2535
+ const { TelemetryRecorder } = await import(
2536
+ "../lib/telemetry/span-recorder.js"
2537
+ );
2355
2538
  _otlpRecorder = new TelemetryRecorder({ serviceName: "cc-agent" });
2356
2539
  } catch {
2357
2540
  _otlpRecorder = null; // telemetry is best-effort, never blocks the run
@@ -2365,8 +2548,9 @@ async function runAgentHeadlessInWorkspace(
2365
2548
  let _hookSupervisor = null;
2366
2549
  if (settingsHooks) {
2367
2550
  try {
2368
- const { AsyncHookSupervisor } =
2369
- await import("../lib/async-hook-supervisor.js");
2551
+ const { AsyncHookSupervisor } = await import(
2552
+ "../lib/async-hook-supervisor.js"
2553
+ );
2370
2554
  _hookSupervisor = new AsyncHookSupervisor({
2371
2555
  persistStats: true,
2372
2556
  // Durably park failed-rewake signals keyed by session so a crash before
@@ -2458,13 +2642,35 @@ async function runAgentHeadlessInWorkspace(
2458
2642
  const skillDecisionOptions = resolveHeadlessSkillDecisionOptions(options);
2459
2643
  let skillDecisionRuntime = null;
2460
2644
  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
- );
2645
+ let previousUnreconciledDecisionUsage;
2646
+ if (
2647
+ !hasInjectedSessionStore ||
2648
+ typeof deps.readVerifiedEvents === "function"
2649
+ ) {
2650
+ try {
2651
+ previousUnreconciledDecisionUsage = hasInjectedSessionStore
2652
+ ? hasUnreconciledDecisionUsage(store.readVerifiedEvents(sessionId))
2653
+ : jsonlReadVerifiedProjection(
2654
+ sessionId,
2655
+ createDecisionUsageRecoveryProjection,
2656
+ );
2657
+ } catch {
2658
+ // Without a verified settlement, a resumed provider call could be paid twice.
2659
+ previousUnreconciledDecisionUsage = true;
2660
+ }
2661
+ } else {
2662
+ // Legacy injected stores cannot prove a prior call was settled. Their
2663
+ // explicit no-session answer still permits a fresh test/embedding run.
2664
+ previousUnreconciledDecisionUsage =
2665
+ store.sessionExists(sessionId) ||
2666
+ store.findLatestEvent(
2667
+ sessionId,
2668
+ "model_usage_unknown",
2669
+ (event) =>
2670
+ typeof event?.data?.operationId === "string" &&
2671
+ event.data.operationId.startsWith("decision:"),
2672
+ ) != null;
2673
+ }
2468
2674
  const decisionProvider =
2469
2675
  deps.decisionProvider ||
2470
2676
  createDecisionProvider({
@@ -2487,11 +2693,12 @@ async function runAgentHeadlessInWorkspace(
2487
2693
  options.decisionTenantId || evolutionIngress?.tenantId || "cli-local",
2488
2694
  sessionId,
2489
2695
  provider: decisionProvider,
2696
+ evolutionIngress,
2490
2697
  persist: persistDecisionEvent,
2491
2698
  observe: (observation) =>
2492
2699
  persistDecisionEvent("skill_decision_observation", observation),
2493
2700
  sessionBudget: options.sessionBudget || null,
2494
- initialUsageUnknown: previousUnknownDecisionUsage != null,
2701
+ initialUsageUnknown: previousUnreconciledDecisionUsage,
2495
2702
  timeoutMs: skillDecisionOptions.timeoutMs,
2496
2703
  });
2497
2704
  }
@@ -2837,8 +3044,9 @@ async function runAgentHeadlessInWorkspace(
2837
3044
  if (options.goal !== undefined && options.goal !== false) {
2838
3045
  try {
2839
3046
  const explicitId = typeof options.goal === "string" ? options.goal : null;
2840
- const { resolveActiveGoal, linkSession } =
2841
- await import("../lib/goal-store.js");
3047
+ const { resolveActiveGoal, linkSession } = await import(
3048
+ "../lib/goal-store.js"
3049
+ );
2842
3050
  const goal = (deps.resolveActiveGoal || resolveActiveGoal)({
2843
3051
  explicitId,
2844
3052
  sessionId,
@@ -3642,6 +3850,7 @@ async function runAgentHeadlessInWorkspace(
3642
3850
  autoRewake &&
3643
3851
  _hookSupervisor &&
3644
3852
  !stopForCost &&
3853
+ endReason !== "deferred-mutation-unresolved" &&
3645
3854
  endReason !== "max_turns" &&
3646
3855
  endReason !== "cost-budget-exhausted"
3647
3856
  ) {
@@ -3696,7 +3905,8 @@ async function runAgentHeadlessInWorkspace(
3696
3905
  !goalEngine.done &&
3697
3906
  !stopForCost &&
3698
3907
  endReason !== "cost-budget-exhausted" &&
3699
- endReason !== "max_turns"
3908
+ endReason !== "max_turns" &&
3909
+ endReason !== "deferred-mutation-unresolved"
3700
3910
  ) {
3701
3911
  // Feed this turn's usage DELTA so the engine's totals equal the run's
3702
3912
  // cumulative usage (recordTurnUsage accumulates).
@@ -3814,17 +4024,23 @@ async function runAgentHeadlessInWorkspace(
3814
4024
  : sessionBudgetFailed
3815
4025
  ? "error_session_budget"
3816
4026
  : "error";
4027
+ const transportDetails =
4028
+ errorSubtype === "error" ? transportErrorDetails(err) : undefined;
4029
+ const diagnosticFields = transportDetails
4030
+ ? { error_details: transportDetails }
4031
+ : {};
3817
4032
  if (isStream) {
3818
4033
  emitStream({
3819
4034
  type: "result",
3820
4035
  subtype: errorSubtype,
3821
4036
  is_error: true,
3822
4037
  error: message,
4038
+ ...diagnosticFields,
3823
4039
  });
3824
4040
  } else if (isJson) {
3825
4041
  writeOut(
3826
- JSON.stringify(
3827
- buildResultEnvelope({
4042
+ JSON.stringify({
4043
+ ...buildResultEnvelope({
3828
4044
  subtype: errorSubtype,
3829
4045
  isError: true,
3830
4046
  result: message,
@@ -3836,7 +4052,8 @@ async function runAgentHeadlessInWorkspace(
3836
4052
  denials,
3837
4053
  compactionDegradations,
3838
4054
  }),
3839
- ) + "\n",
4055
+ ...diagnosticFields,
4056
+ }) + "\n",
3840
4057
  );
3841
4058
  } else {
3842
4059
  writeErr(`Error: ${message}\n`);
@@ -3887,8 +4104,9 @@ async function runAgentHeadlessInWorkspace(
3887
4104
  await cleanupDeadline.run("settings-hooks", async () => {
3888
4105
  if (settingsHooks) {
3889
4106
  try {
3890
- const { runObserveHooks } =
3891
- await import("../lib/settings-hook-events.js");
4107
+ const { runObserveHooks } = await import(
4108
+ "../lib/settings-hook-events.js"
4109
+ );
3892
4110
  const stopPayload = {
3893
4111
  reason: pipeState.closed ? "pipe_closed" : endReason,
3894
4112
  cwd,
@@ -4018,7 +4236,11 @@ async function runAgentHeadlessInWorkspace(
4018
4236
  const exhausted =
4019
4237
  endReason === "budget-exhausted" || endReason === "max_turns";
4020
4238
  const costStopped = endReason === "cost-budget-exhausted";
4021
- let isError = exhausted || costStopped || endReason === "no-response";
4239
+ let isError =
4240
+ exhausted ||
4241
+ costStopped ||
4242
+ endReason === "no-response" ||
4243
+ endReason === "deferred-mutation-unresolved";
4022
4244
  let subtype = exhausted
4023
4245
  ? "error_max_turns"
4024
4246
  : costStopped
@@ -4165,8 +4387,9 @@ async function runAgentHeadlessInWorkspace(
4165
4387
  emitStream({ type: "denials_summary", count: denials.length, denials });
4166
4388
  }
4167
4389
  try {
4168
- const { appendRecentDenials } =
4169
- await import("../lib/permission-denial-store.js");
4390
+ const { appendRecentDenials } = await import(
4391
+ "../lib/permission-denial-store.js"
4392
+ );
4170
4393
  appendRecentDenials(denials, {
4171
4394
  sessionId,
4172
4395
  permissionMode: options.permissionMode || "default",
@@ -4239,8 +4462,9 @@ async function runAgentHeadlessInWorkspace(
4239
4462
  }
4240
4463
  if (_collectorEnabled) {
4241
4464
  try {
4242
- const { exportTelemetryRecorder } =
4243
- await import("../lib/observability/index.js");
4465
+ const { exportTelemetryRecorder } = await import(
4466
+ "../lib/observability/index.js"
4467
+ );
4244
4468
  exportTelemetryRecorder(_otlpRecorder);
4245
4469
  } catch {
4246
4470
  // Telemetry is observational only and never changes the agent result.