chainlesschain 0.163.2 → 0.163.4

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 (222) hide show
  1. package/package.json +3 -2
  2. package/scripts/command-lifecycle-report.mjs +330 -38
  3. package/src/assets/web-panel/assets/{AIOps-DnGsmsqJ.js → AIOps-DB5X7qqV.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CrO6fcQ7.js → ActionButton-DxHRtKLk.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-DsBdOaP2.js → Analytics-DIH5QrxT.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-DmQslKUB.js → AppLayout-uu0oxVz7.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-BvyrT_QQ.js → Artifacts-BNSMiW9Y.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-prndoLiC.js → Audit-DcAzB4_x.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-DOTFyA55.js → BackgroundAgents-ClSsvjIc.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-9zOnPp_8.js → Backup-BMciY0js.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-C4PC6sAG.js → BaseInput-Hn3b57Sh.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-BBAF-W9v.js → Chat-CoSlC53V.js} +6 -6
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CWhvvloO.js → ChatBubbleRenderer-CFevJ3So.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-BI9iculd.js → Checkbox-B4L4Eu4w.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-3DP9BCKb.js → Codegen-C77FgRxF.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-df-2TnJX.js → Col-BrLtJLH3.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-CHs8gG_A.js → Community-Be7pXXhA.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-CDfF6q7V.js → Compact-DuGPecjo.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-CthrDnO7.js → Compliance-CzS66mjP.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-HjIqsWJw.js → Cowork-CEhjCoyK.js} +2 -2
  21. package/src/assets/web-panel/assets/{Cron-BKc196fb.js → Cron-D7ir8Vja.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CJnjdc8W.js → Crosschain-BcXmuLxf.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-BHUy-8Q2.js → DID-Cto1dtBy.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-QDB7sKeY.js → Dashboard-B7KjgwOX.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-DStcVK11.js → Dropdown-COMqxijg.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BwSUskMJ.js → EmailListRenderer-BZrya-nf.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgF_kurT.js → FamilyGuardDashboard-AmVeMq0J.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-k8wvv-wN.js → Federation-kZU8c-27.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-C11qoq2r.js → FormItemContext-sOV22v2-.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-BIIpr9kg.js → GenericCardRenderer-BUuLtGCz.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-BlA1exTe.js → Git-K-ZxsLsH.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CYa1ZYM4.js → Governance-D3OEnawI.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-6_kKVIt6.js → Inference-Bll0gRmP.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-CB4AwxYy.js → KnowledgeGraph-DBXwjr53.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-xf7nHFAe.js → Logs-CEzPwEfP.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-Bf3DEqP6.js → MarkdownRenderer-CLmCbHx6.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-aPg8e4Jt.js → Marketplace-BYyRyOPz.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-C-TNlVUf.js → McpTools-DVu8w_rM.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-DMTPIpGa.js → Memory-tenuZ_hO.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-BxyvveRq.js → MobileBridge-Bxgy4ozS.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-DyPCrAyQ.js → MobileProjects-Dgx1D6sc.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-BdhqNXp6.js → Mtc-CRfJ8r8j.js} +5 -5
  43. package/src/assets/web-panel/assets/{MtcAudit-Cz-HFxzW.js → MtcAudit-BBJq4Aiz.js} +5 -5
  44. package/src/assets/web-panel/assets/{Multisig-CIUaFNsx.js → Multisig-B3ii9lai.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-CWe6-J17.js → NLProgramming-FIi-Cubv.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-vYAKeviU.js → Notes-DIq8MPf1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-DQL9-2d7.js → NotificationSettings-BFOD9eGd.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-DnXj1jBn.js → OrderTableRenderer--41u7vre.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-B3spU8AN.js → Organization-B_0AWztW.js} +2 -2
  50. package/src/assets/web-panel/assets/{Overflow-DgEwo7vm.js → Overflow-B6I7TuXv.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-hujMRH8X.js → P2P-Cdf6qens.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-C_qhdg9h.js → PdhVaultBrowser-B_0FcQJY.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-vp7LMcSf.js → Permissions-6nFBjsQp.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-Dxr5Hgnq.js → PersonalDataHub-nQYV7xpn.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-DEPZqqH4.js → Pipeline-CBVod5jm.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-DTpDiKPe.js → Privacy-D52jW1Nt.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-jDJsRWmF.js → ProjectInit-Bdx3BYhf.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-Dhor5RWH.js → ProjectSettings-b7xr4DUa.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-DhfifCKx.js +1 -0
  60. package/src/assets/web-panel/assets/Providers-Dy_PgDMr.js +1 -0
  61. package/src/assets/web-panel/assets/{QrScannerModal-CjIw-wIb.js → QrScannerModal-FQKSmc3e.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-DX6jcqoi.js → QuickAsk-CSTrhzcF.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-DopXkhar.js → Recommend-CxMABOUh.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-BLvqJE9c.js → RemoteSession-Cv2T8yRa.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-DhRj2Me7.js → Reputation-CE1k4Vvu.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DQ53vuPq.js → Row-BNgNcAV_.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-BslvwiBD.js → RssFeed-5ZiBZ3ph.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-DJKBDNKZ.js → Search-mDOIF1UV.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-COhpxHER.js → Security-CtuCTC-e.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-dbulD6cI.js → Services-DxFO2Zg7.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-ciIVNfhC.js → Skeleton-CKmKkH9y.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-AiRTkTCk.js → Skills-Bmzl9qkk.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-DDMcWYBc.js → Sla-9RqaWHOC.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-BPxWbpXO.js → SpeechSettings-CGdzFIYw.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-BoEOXCyg.js → SyncSettings-CvNuCeBT.js} +2 -2
  76. package/src/assets/web-panel/assets/Tasks-B_sLdcnw.js +1 -0
  77. package/src/assets/web-panel/assets/{Templates-UowY8Ixe.js → Templates-D9_YijdK.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DauSLQXN.js → Tenant-Cuc7BUSP.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-DBj7Jneq.js → Terminal-6VYRnJgd.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-UMrPwoZC.js → TimelineRenderer-GtK8xd8Y.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-4ea96-bn.js → Tokens-BZ94Lt5W.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger--ISCqt4b.js → Trigger-DEcZgDaX.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-D4GVimRJ.js → Trust-CC3z9THe.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-Ci-nXRQc.js → UkeySign-Cvtw8cV3.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-Cjk7mKPw.js → VideoEditing-CL4e6Bn3.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BgOLOO3Z.js → Wallet-ycEemP27.js} +2 -2
  87. package/src/assets/web-panel/assets/{WebAuthn-CCX0K29i.js → WebAuthn-DgZ4X_aw.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-Ch3zgIsE.js → WorkflowEditor-D0qMhSv7.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-DKOU_2Vb.js → chat-DsAg01Zn.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-6OVo4u3C.js → colors-B0oqAhrQ.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BH78Hlsq.js → compact-item-CmX0Rabz.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-CFRpSbbC.js → createContext-Be4cn1Ub.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-CP2qzG6D.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DNQhgcVi.js → hasIn-D5v12kVq.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BkN3iTTp.js → index-0eWLkQKT.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CkNEMANR.js → index-301ogenv.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-D3RtTT4K.js → index-5LGY0JbG.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-dDkoL4Pe.js → index-7VKDn-t1.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BHa4WyTZ.js → index-8WvYGnON.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CaYqY35Z.js → index-B1YGjOWC.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-bKm3TUDp.js → index-B3mUHuVc.js} +1 -1
  102. package/src/assets/web-panel/assets/{index--rq90rL9.js → index-BA4oulaP.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DaDgdJYj.js → index-BBREnn1V.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-B_Z-YoxX.js → index-BBvyHguy.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CkqHgG-b.js → index-BKmsS2jj.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CrcLHN2F.js → index-BRIqLy1m.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BaVE6E8y.js → index-BXGSbelg.js} +3 -3
  108. package/src/assets/web-panel/assets/{index-BYrnm5Ob.js → index-BaE0Ui07.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BDSR7ecX.js → index-BoAIAZ5C.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CNuCHHQT.js → index-BqltWojQ.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Eag8e_mA.js → index-CGiIyTZw.js} +1 -1
  112. package/src/assets/web-panel/assets/index-CKB0vbJU.js +1 -0
  113. package/src/assets/web-panel/assets/{index-BepBTpa8.js → index-CZ2wUEgr.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-HNGGVF6o.js → index-CZpfzcuy.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-AuBhLqOm.js → index-Ckrk3pIV.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-7TC3S8SN.js → index-CqoCZ5vR.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CFPJ8yzF.js → index-CyWBir7N.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Bb6kDrUx.js → index-CyyGTMKd.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DKN2noIF.js → index-D0BSkxYQ.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Du0rnksC.js → index-D5YVopyr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BxRy5LPR.js → index-DKUBj36_.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-sm7W8AXy.js → index-DM724NgU.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BujsOZfc.js → index-DQRsQen0.js} +1 -1
  124. package/src/assets/web-panel/assets/index-DgoXmwqB.js +1 -0
  125. package/src/assets/web-panel/assets/{index-Y9MJv28e.js → index-DikJ0Qqe.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-caye7AOE.js → index-Dn2dSdXx.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-cdf7fd7d.js → index-DyUaFWEk.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BnnXQot_.js → index-Hfe_dEGx.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DvHGtNnF.js → index-_JjRLSD0.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-nbfHl1oV.js → index-frSojpHj.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Cu3L4r5l.js → index-jK3ax6Z6.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D84id2Y4.js → index-qMuZ-NRR.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-hPY0fFrd.js → index-q_fQ94SE.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-BZ9w6jPL.js → initDefaultProps-D4VdhJ9_.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BnwUiOho.js → motion-CZJA0MQW.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-ByUKJnNm.js → move-BqEs7Sb1.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-V7yK1KEl.js → mtc-parser-BpHEtsu1.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BEXBBt4j.js → omit-BW94tY9W.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-qDm_46Gi.js → pickAttrs-BnBjPWP9.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BIbhEo_0.js → placementArrow-uUkjQ_hu.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-NbPbDgA_.js → responsiveObserve-B-klUqXK.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-BnUWglZ0.js → slide-CvY1cNAs.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-BX8_wZI5.js → statusUtils-Ix5sEDT2.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-BV4OycQX.js → styleChecker-C8qcXOne.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-Od_H5llY.js → useFlexGapSupport-KNF6Kj8f.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-BWI-PyiX.js → useFs-DGJr345n.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-BqMuhG3g.js → usePersonalDataHub-BboN99rI.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DNd23z6f.js → vnode-Bgt8Vgte.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-Cjaxnm7l.js → zoom-BhJtErgt.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +2 -2
  152. package/src/commands/agenda.js +6 -5
  153. package/src/commands/agent.js +237 -75
  154. package/src/commands/agents.js +6 -0
  155. package/src/commands/artifacts.js +98 -0
  156. package/src/commands/background-session.js +11 -1
  157. package/src/commands/mcp.js +218 -31
  158. package/src/commands/review.js +221 -22
  159. package/src/commands/session-mcp-recovery.js +5 -5
  160. package/src/data/changelog.json +27 -1
  161. package/src/gateways/ws/ws-agent-handler.js +492 -14
  162. package/src/harness/jsonl-session-store.js +39 -1
  163. package/src/harness/mcp-client.js +414 -71
  164. package/src/harness/prompt-compressor.js +24 -0
  165. package/src/harness/provider-backed-compaction.js +205 -0
  166. package/src/harness/worktree-isolator.js +26 -3
  167. package/src/lib/agent-worktree.js +41 -2
  168. package/src/lib/app-preview.js +3 -0
  169. package/src/lib/background-agent-supervisor.js +790 -186
  170. package/src/lib/background-command-argv.js +318 -0
  171. package/src/lib/background-launch-profile.js +1 -0
  172. package/src/lib/background-phase-reporter.js +22 -2
  173. package/src/lib/background-worktree-policy.js +109 -0
  174. package/src/lib/command-lifecycle-report.js +1340 -145
  175. package/src/lib/cowork-mcp-tools.js +51 -6
  176. package/src/lib/cowork-task-runner.js +1 -0
  177. package/src/lib/delivery-coordinator.js +30 -5
  178. package/src/lib/delivery-production-adapter.js +1777 -0
  179. package/src/lib/delivery-production-runner.js +240 -0
  180. package/src/lib/durable-security-store.js +29 -17
  181. package/src/lib/execution-trace/trace-context.cjs +179 -0
  182. package/src/lib/execution-trace/trace-context.js +8 -175
  183. package/src/lib/mcp-call-ledger-store.js +58 -6
  184. package/src/lib/mcp-headers-helper.js +76 -8
  185. package/src/lib/mcp-host-recovery-runtime.js +2 -0
  186. package/src/lib/mcp-ledger-recovery-admission.js +39 -3
  187. package/src/lib/mcp-recovery-adjudication.js +256 -19
  188. package/src/lib/mcp-sandbox-policy.js +184 -0
  189. package/src/lib/mcp-stdio-capsule-builder-worker.cjs +495 -0
  190. package/src/lib/mcp-stdio-executable-identity.js +33 -2
  191. package/src/lib/mcp-stdio-execution-authority.js +163 -0
  192. package/src/lib/mcp-stdio-immutable-vfs-resolver.cjs +830 -0
  193. package/src/lib/mcp-stdio-package-materialization.js +721 -333
  194. package/src/lib/mcp-stdio-workspace-authority.js +252 -0
  195. package/src/lib/observability/index.js +2 -0
  196. package/src/lib/observability/otlp-exporter.js +2 -2
  197. package/src/lib/packer/pack-update-applier.js +8 -1
  198. package/src/lib/packer/pkg-config-generator.js +34 -0
  199. package/src/lib/plugin-runtime/sandbox-policy.js +42 -2
  200. package/src/lib/process-execution-broker/index.js +213 -109
  201. package/src/lib/process-execution-broker/platform-sandbox.js +1024 -169
  202. package/src/lib/process-tree-termination.js +17 -1
  203. package/src/lib/scheduler-kernel/contract.js +315 -0
  204. package/src/lib/scheduler-kernel/store.js +1345 -0
  205. package/src/lib/session-host-lease.js +403 -30
  206. package/src/lib/session-persistence-failure.js +4 -1
  207. package/src/lib/skill-mcp.js +65 -4
  208. package/src/lib/sub-agent-context.js +8 -0
  209. package/src/lib/web-fetch.js +4 -4
  210. package/src/repl/agent-repl.js +285 -38
  211. package/src/runtime/agent-core.js +1044 -90
  212. package/src/runtime/agent-runtime.js +61 -8
  213. package/src/runtime/headless-runner.js +260 -166
  214. package/src/runtime/headless-stream.js +254 -25
  215. package/src/runtime/mcp-config.js +235 -28
  216. package/src/workers/background-agent-worker.js +492 -71
  217. package/src/assets/web-panel/assets/Projects-08xUDZGt.js +0 -1
  218. package/src/assets/web-panel/assets/Providers-BGs47s1a.js +0 -1
  219. package/src/assets/web-panel/assets/Tasks-CEYFJwmr.js +0 -1
  220. package/src/assets/web-panel/assets/devWarning-DEMblAIm.js +0 -1
  221. package/src/assets/web-panel/assets/index-BTvq-36D.js +0 -1
  222. package/src/assets/web-panel/assets/index-hUpvk6Jl.js +0 -1
@@ -30,6 +30,7 @@ import {
30
30
  formatToolArgs,
31
31
  killAllBackgroundShellTasks,
32
32
  killAllBackgroundShellTasksSync,
33
+ normalizeExactFileMutationScope,
33
34
  } from "./agent-core.js";
34
35
  import {
35
36
  resolveAgentMcp,
@@ -151,6 +152,12 @@ const VALID_PERMISSION_MODES = Object.freeze([
151
152
  ]);
152
153
 
153
154
  const VALID_OUTPUT_FORMATS = Object.freeze(["text", "json", "stream-json"]);
155
+ const HERMETIC_SKILL_LOADER = Object.freeze({
156
+ getAutoActivatedPersonas: () => [],
157
+ getResolvedSkills: () => [],
158
+ getCacheLedger: () => null,
159
+ getLimits: () => null,
160
+ });
154
161
 
155
162
  // EPIPE guard for `cc agent -p … | head`. Lives in pipe-safety.js (shared with
156
163
  // the stream-json driver + REPL); re-exported here for existing importers.
@@ -658,50 +665,69 @@ async function runAgentHeadlessInWorkspace(
658
665
  const baseUrl = options.baseUrl || "http://localhost:11434";
659
666
  const apiKey = options.apiKey || null;
660
667
  const cwd = options.cwd || process.cwd();
668
+ const hermeticExecution = options.hermeticExecution === true;
669
+ if (
670
+ options.fileMutationScope != null &&
671
+ (options.exactToolNames !== true || !hermeticExecution)
672
+ ) {
673
+ throw new Error(
674
+ "exact file mutation scope requires exactToolNames=true and hermeticExecution=true",
675
+ );
676
+ }
677
+ const fileMutationScope = normalizeExactFileMutationScope(
678
+ options.fileMutationScope,
679
+ { cwd },
680
+ );
661
681
  // Extra workspace roots (--add-dir). Resolved/validated by the caller; we
662
682
  // just normalize to a clean string[] here.
663
- const additionalDirectories = Array.isArray(options.additionalDirectories)
664
- ? options.additionalDirectories.filter(Boolean)
665
- : [];
683
+ const additionalDirectories = hermeticExecution
684
+ ? []
685
+ : Array.isArray(options.additionalDirectories)
686
+ ? options.additionalDirectories.filter(Boolean)
687
+ : [];
666
688
 
667
689
  // .claude/settings.json permission rules (deny > ask > allow). A `deny` hard-
668
690
  // blocks, an `allow` pre-authorizes (so a safe op isn't fail-closed headless),
669
691
  // an `ask` falls closed (no human to confirm in headless). No file → null →
670
692
  // every existing risk-tier / shell-policy layer runs unchanged.
671
- let permissionRules = options.permissionRules || null;
693
+ let permissionRules = hermeticExecution
694
+ ? null
695
+ : options.permissionRules || null;
672
696
  let managedSettings = null;
673
697
  let settingsFiles = [];
674
- try {
675
- const { loadSettings, applyManagedPermissionPolicy } =
676
- await import("../lib/settings-loader.cjs");
677
- const loaded = loadSettings({
678
- cwd,
679
- settingsFile: options.settingsFile,
680
- managedSettingsFile: options.managedSettingsFile,
681
- });
682
- managedSettings = loaded.managed;
683
- settingsFiles = Array.isArray(loaded.files) ? loaded.files : [];
684
- if (!permissionRules) {
685
- const total =
686
- loaded.rules.allow.length +
687
- loaded.rules.ask.length +
688
- loaded.rules.deny.length;
689
- permissionRules = total > 0 ? loaded.rules : null;
690
- } else if (managedSettings) {
691
- permissionRules = applyManagedPermissionPolicy(
692
- permissionRules,
693
- managedSettings,
694
- );
698
+ if (!hermeticExecution) {
699
+ try {
700
+ const { loadSettings, applyManagedPermissionPolicy } =
701
+ await import("../lib/settings-loader.cjs");
702
+ const loaded = loadSettings({
703
+ cwd,
704
+ settingsFile: options.settingsFile,
705
+ managedSettingsFile: options.managedSettingsFile,
706
+ });
707
+ managedSettings = loaded.managed;
708
+ settingsFiles = Array.isArray(loaded.files) ? loaded.files : [];
709
+ if (!permissionRules) {
710
+ const total =
711
+ loaded.rules.allow.length +
712
+ loaded.rules.ask.length +
713
+ loaded.rules.deny.length;
714
+ permissionRules = total > 0 ? loaded.rules : null;
715
+ } else if (managedSettings) {
716
+ permissionRules = applyManagedPermissionPolicy(
717
+ permissionRules,
718
+ managedSettings,
719
+ );
720
+ }
721
+ } catch (error) {
722
+ if (error?.code === "CC_MANAGED_SETTINGS_INVALID") throw error;
723
+ // Preserve caller-provided rules; absent settings keep legacy behavior.
695
724
  }
696
- } catch (error) {
697
- if (error?.code === "CC_MANAGED_SETTINGS_INVALID") throw error;
698
- // Preserve caller-provided rules; absent settings keep legacy behavior.
699
725
  }
700
726
 
701
727
  // .claude/settings.json `hooks` block — decision-capable PreToolUse/
702
728
  // PostToolUse hooks (see settings-hooks/hook-runner). null = no hooks.
703
- let settingsHooks = options.settingsHooks || null;
704
- if (!settingsHooks) {
729
+ let settingsHooks = hermeticExecution ? null : options.settingsHooks || null;
730
+ if (!hermeticExecution && !settingsHooks) {
705
731
  try {
706
732
  const { loadHooks, projectHookTrustNotice, attachAuthorityErrors } =
707
733
  await import("../lib/settings-hooks.cjs");
@@ -748,28 +774,35 @@ async function runAgentHeadlessInWorkspace(
748
774
  // sandboxPolicy. Policy-bearing bins are excluded here and resolved as exact
749
775
  // direct Broker invocations by agent-core. The process exits at the end of
750
776
  // the run, so no explicit restore is needed.
751
- try {
752
- const { applyPluginBinPath } = await import("../lib/plugin-runtime/bin.js");
753
- applyPluginBinPath({ cwd });
754
- } catch {
755
- /* best-effort — plugin bin PATH never blocks a headless run */
777
+ if (!hermeticExecution) {
778
+ try {
779
+ const { applyPluginBinPath } =
780
+ await import("../lib/plugin-runtime/bin.js");
781
+ applyPluginBinPath({ cwd });
782
+ } catch {
783
+ /* best-effort — plugin bin PATH never blocks a headless run */
784
+ }
756
785
  }
757
786
 
758
787
  // Apply trusted plugins' default env vars for this run (Phase 3.3o) — only for
759
788
  // keys not already set; the process exits at the end so no restore is needed.
760
- try {
761
- const { applyPluginSettingsEnv } =
762
- await import("../lib/plugin-runtime/settings.js");
763
- applyPluginSettingsEnv({ cwd });
764
- } catch {
765
- /* best-effort — plugin settings never block a headless run */
789
+ if (!hermeticExecution) {
790
+ try {
791
+ const { applyPluginSettingsEnv } =
792
+ await import("../lib/plugin-runtime/settings.js");
793
+ applyPluginSettingsEnv({ cwd });
794
+ } catch {
795
+ /* best-effort — plugin settings never block a headless run */
796
+ }
766
797
  }
767
798
 
768
799
  // autoMode.classifyAllShell (Claude-Code 2.1.193): route the built-in
769
800
  // verification allowlist through the shell-policy classifier instead of
770
801
  // fast-pathing it. Explicit option wins; otherwise read settings.json.
771
- let classifyAllShell = options.classifyAllShell || false;
772
- if (!classifyAllShell) {
802
+ let classifyAllShell = hermeticExecution
803
+ ? false
804
+ : options.classifyAllShell || false;
805
+ if (!hermeticExecution && !classifyAllShell) {
773
806
  try {
774
807
  const { readBooleanSetting } = await import("../lib/settings-loader.cjs");
775
808
  classifyAllShell =
@@ -784,7 +817,14 @@ async function runAgentHeadlessInWorkspace(
784
817
 
785
818
  const runLoop = deps.agentLoop || coreAgentLoop;
786
819
  const doBootstrap = deps.bootstrap || bootstrap;
787
- const executeLifecycleHooks = deps.executeHooksV2Event || executeHooksV2Event;
820
+ const executeLifecycleHooks = hermeticExecution
821
+ ? async () => ({
822
+ success: true,
823
+ blocked: false,
824
+ decision: "continue",
825
+ results: [],
826
+ })
827
+ : deps.executeHooksV2Event || executeHooksV2Event;
788
828
  const getApprovalGate =
789
829
  deps.getApprovalGate ||
790
830
  (async () => {
@@ -918,7 +958,11 @@ async function runAgentHeadlessInWorkspace(
918
958
  // A matched command's `allowed-tools:` frontmatter scopes the run (parsed
919
959
  // below into enabledToolNames) the same way `cc command run` does.
920
960
  let macroAllowedTools = null;
921
- if (options.slashMacros !== false && prompt.startsWith("/")) {
961
+ if (
962
+ !hermeticExecution &&
963
+ options.slashMacros !== false &&
964
+ prompt.startsWith("/")
965
+ ) {
922
966
  try {
923
967
  const doMacro =
924
968
  deps.resolveSlashMacro ||
@@ -959,7 +1003,11 @@ async function runAgentHeadlessInWorkspace(
959
1003
  // a dir listing) so `cc agent -p "review @src/x.js"` works without a manual
960
1004
  // cat-pipe. Opt out with `--no-file-refs` (options.expandFileRefs === false).
961
1005
  // Skipped when a slash macro already expanded (expandCommand ran @refs).
962
- if (!slashExpanded && options.expandFileRefs !== false) {
1006
+ if (
1007
+ !hermeticExecution &&
1008
+ !slashExpanded &&
1009
+ options.expandFileRefs !== false
1010
+ ) {
963
1011
  const doExpand = deps.expandFileRefs || expandFileRefsAsync;
964
1012
  const expanded = await doExpand(prompt, { cwd });
965
1013
  userContent = expanded.prompt;
@@ -987,13 +1035,15 @@ async function runAgentHeadlessInWorkspace(
987
1035
 
988
1036
  // ── Best-effort runtime bootstrap (DB optional, like startAgentRepl) ───
989
1037
  let db = null;
990
- try {
991
- // Bootstrap logs db/config diagnostics via console.info (→ stdout); divert
992
- // to stderr so text/JSON/NDJSON stdout payloads stay clean.
993
- const ctx = await withQuietStdout(() => doBootstrap({ verbose: false }));
994
- db = ctx.db || null;
995
- } catch {
996
- // Continue without DB — static-prompt fallback.
1038
+ if (!hermeticExecution) {
1039
+ try {
1040
+ // Bootstrap logs db/config diagnostics via console.info (→ stdout); divert
1041
+ // to stderr so text/JSON/NDJSON stdout payloads stay clean.
1042
+ const ctx = await withQuietStdout(() => doBootstrap({ verbose: false }));
1043
+ db = ctx.db || null;
1044
+ } catch {
1045
+ // Continue without DB — static-prompt fallback.
1046
+ }
997
1047
  }
998
1048
 
999
1049
  const setupHooks = await executeLifecycleHooks(
@@ -1093,8 +1143,14 @@ async function runAgentHeadlessInWorkspace(
1093
1143
  // here — before the resume reconcile below — so an UNKNOWN-outcome side
1094
1144
  // effect found on resume can be reported too. For every non-background run
1095
1145
  // this is a disabled no-op.
1096
- const _bgPhase =
1097
- deps.backgroundPhaseReporter || createBackgroundPhaseReporter();
1146
+ const _bgPhase = hermeticExecution
1147
+ ? Object.freeze({
1148
+ enabled: false,
1149
+ reportUncertainSideEffects: () => {},
1150
+ reportQuestion: () => {},
1151
+ wrapConfirmer: (confirmer) => confirmer,
1152
+ })
1153
+ : deps.backgroundPhaseReporter || createBackgroundPhaseReporter();
1098
1154
 
1099
1155
  const sideEffectRunNonce = String(deps.now ? deps.now() : Date.now());
1100
1156
  const _backgroundPolicyDigest = _bgPhase.enabled
@@ -1339,40 +1395,42 @@ async function runAgentHeadlessInWorkspace(
1339
1395
  // ── Wire the persistent ApprovalGate with our non-interactive confirmer
1340
1396
  // and force the session-policy tier dictated by --permission-mode. ──────
1341
1397
  let approvalGate = null;
1342
- try {
1343
- approvalGate = await getApprovalGate();
1344
- if (approvalGate && (options.permissionMode || "default") === "auto") {
1345
- // autoMode.decisions: user-configured riskLevel → allow/ask/deny
1346
- // classifier. Only wrap when settings actually customize the map so the
1347
- // unconfigured auto path keeps the byte-identical trusted-tier mapping.
1348
- try {
1349
- const {
1350
- loadAutoModeConfig,
1351
- resolveAutoModeDecisions,
1352
- createAutoModeApprovalGate,
1353
- } = await import("../lib/auto-mode-config.js");
1354
- const autoConfig = loadAutoModeConfig({
1355
- cwd,
1356
- settingsFile: options.settingsFile,
1357
- });
1358
- const resolved = resolveAutoModeDecisions(autoConfig.effective);
1359
- if (resolved.customized) {
1360
- approvalGate = createAutoModeApprovalGate(approvalGate, resolved);
1398
+ if (!hermeticExecution) {
1399
+ try {
1400
+ approvalGate = await getApprovalGate();
1401
+ if (approvalGate && (options.permissionMode || "default") === "auto") {
1402
+ // autoMode.decisions: user-configured riskLevel → allow/ask/deny
1403
+ // classifier. Only wrap when settings actually customize the map so the
1404
+ // unconfigured auto path keeps the byte-identical trusted-tier mapping.
1405
+ try {
1406
+ const {
1407
+ loadAutoModeConfig,
1408
+ resolveAutoModeDecisions,
1409
+ createAutoModeApprovalGate,
1410
+ } = await import("../lib/auto-mode-config.js");
1411
+ const autoConfig = loadAutoModeConfig({
1412
+ cwd,
1413
+ settingsFile: options.settingsFile,
1414
+ });
1415
+ const resolved = resolveAutoModeDecisions(autoConfig.effective);
1416
+ if (resolved.customized) {
1417
+ approvalGate = createAutoModeApprovalGate(approvalGate, resolved);
1418
+ }
1419
+ } catch {
1420
+ // fail to the default trusted mapping — never block the run
1361
1421
  }
1362
- } catch {
1363
- // fail to the default trusted mapping — never block the run
1364
- }
1365
- }
1366
- if (approvalGate) {
1367
- if (typeof approvalGate.setSessionPolicy === "function") {
1368
- approvalGate.setSessionPolicy(sessionId, perm.sessionPolicy);
1369
1422
  }
1370
- if (typeof approvalGate.setConfirmer === "function") {
1371
- approvalGate.setConfirmer(perm.confirmer);
1423
+ if (approvalGate) {
1424
+ if (typeof approvalGate.setSessionPolicy === "function") {
1425
+ approvalGate.setSessionPolicy(sessionId, perm.sessionPolicy);
1426
+ }
1427
+ if (typeof approvalGate.setConfirmer === "function") {
1428
+ approvalGate.setConfirmer(perm.confirmer);
1429
+ }
1372
1430
  }
1431
+ } catch {
1432
+ approvalGate = null;
1373
1433
  }
1374
- } catch {
1375
- approvalGate = null;
1376
1434
  }
1377
1435
 
1378
1436
  const budget = Number.isFinite(options.maxTurns)
@@ -1386,26 +1444,29 @@ async function runAgentHeadlessInWorkspace(
1386
1444
  // --output-style (or settings.json `outputStyle`) → a persona appended to the
1387
1445
  // system prompt. Resolved best-effort; a missing style is ignored with a warn.
1388
1446
  let outputStyleBody = null;
1389
- try {
1390
- const { resolveOutputStyle } = await import("../lib/output-styles.js");
1391
- const st = resolveOutputStyle(options.outputStyle, cwd);
1392
- if (st && st.missing && options.outputStyle) {
1393
- writeErr(` output-style: unknown style "${options.outputStyle}"\n`);
1394
- } else if (st && st.body) {
1395
- outputStyleBody = st.body;
1447
+ if (!hermeticExecution) {
1448
+ try {
1449
+ const { resolveOutputStyle } = await import("../lib/output-styles.js");
1450
+ const st = resolveOutputStyle(options.outputStyle, cwd);
1451
+ if (st && st.missing && options.outputStyle) {
1452
+ writeErr(` output-style: unknown style "${options.outputStyle}"\n`);
1453
+ } else if (st && st.body) {
1454
+ outputStyleBody = st.body;
1455
+ }
1456
+ } catch {
1457
+ outputStyleBody = null;
1396
1458
  }
1397
- } catch {
1398
- outputStyleBody = null;
1399
1459
  }
1400
1460
 
1401
1461
  // Large-monorepo context lever: `instructionExcludes` (settings.json or an
1402
1462
  // explicit caller/SDK option) suppresses cc.md/CLAUDE.md/AGENTS.md, path-scoped
1403
1463
  // rules, and @imports that resolve into legacy/vendor/generated subtrees.
1404
1464
  // Explicit option wins; otherwise union across the layered settings files.
1405
- let instructionExcludes = Array.isArray(options.instructionExcludes)
1406
- ? options.instructionExcludes
1407
- : null;
1408
- if (!instructionExcludes) {
1465
+ let instructionExcludes =
1466
+ !hermeticExecution && Array.isArray(options.instructionExcludes)
1467
+ ? options.instructionExcludes
1468
+ : null;
1469
+ if (!hermeticExecution && !instructionExcludes) {
1409
1470
  try {
1410
1471
  const { readStringArraySetting } =
1411
1472
  await import("../lib/settings-loader.cjs");
@@ -1423,33 +1484,41 @@ async function runAgentHeadlessInWorkspace(
1423
1484
  // --no-project-memory (options.projectMemory === false): lean prompt — skip
1424
1485
  // rules.md (in buildSystemPrompt) + the cc.md/CLAUDE.md block. Absent flag
1425
1486
  // (undefined) leaves both paths byte-identical.
1426
- const _leanNoProjectMemory = options.projectMemory === false;
1487
+ const _leanNoProjectMemory =
1488
+ hermeticExecution || options.projectMemory === false;
1427
1489
  let _loadedInstructions = null;
1428
1490
  let _loadedPersonaSkills = [];
1429
1491
  let _skillCacheLedger = null;
1430
- const _runtimeSkillLoader = options.skillLoader || new CLISkillLoader();
1431
- const systemContent = composeSystemPrompt(
1432
- buildSystemPrompt(cwd, {
1433
- additionalDirectories,
1434
- projectMemory: options.projectMemory,
1435
- sessionId,
1436
- skillLoader: _runtimeSkillLoader,
1437
- onSkillsLoaded: (skills, cacheLedger) => {
1438
- _loadedPersonaSkills = Array.isArray(skills) ? skills : [];
1439
- _skillCacheLedger = cacheLedger || null;
1440
- },
1441
- }),
1442
- {
1443
- systemPrompt: options.systemPrompt,
1444
- appendSystemPrompt: options.appendSystemPrompt,
1445
- outputStyle: outputStyleBody,
1446
- instructionExcludes,
1447
- projectMemory: _leanNoProjectMemory ? false : undefined,
1448
- onInstructionsLoaded: (loaded) => {
1449
- _loadedInstructions = loaded;
1450
- },
1451
- },
1452
- );
1492
+ const _runtimeSkillLoader = hermeticExecution
1493
+ ? HERMETIC_SKILL_LOADER
1494
+ : options.skillLoader || new CLISkillLoader();
1495
+ const systemContent = hermeticExecution
1496
+ ? composeSystemPrompt(
1497
+ "You are a hermetic code fixer. Use only the exposed file tools, work only inside the current worktree, and mutate only the exact paths authorized in the user request. Do not invoke commands, plugins, hooks, IDE bridges, MCP servers, or sub-agents.",
1498
+ { projectMemory: false },
1499
+ )
1500
+ : composeSystemPrompt(
1501
+ buildSystemPrompt(cwd, {
1502
+ additionalDirectories,
1503
+ projectMemory: options.projectMemory,
1504
+ sessionId,
1505
+ skillLoader: _runtimeSkillLoader,
1506
+ onSkillsLoaded: (skills, cacheLedger) => {
1507
+ _loadedPersonaSkills = Array.isArray(skills) ? skills : [];
1508
+ _skillCacheLedger = cacheLedger || null;
1509
+ },
1510
+ }),
1511
+ {
1512
+ systemPrompt: options.systemPrompt,
1513
+ appendSystemPrompt: options.appendSystemPrompt,
1514
+ outputStyle: outputStyleBody,
1515
+ instructionExcludes,
1516
+ projectMemory: _leanNoProjectMemory ? false : undefined,
1517
+ onInstructionsLoaded: (loaded) => {
1518
+ _loadedInstructions = loaded;
1519
+ },
1520
+ },
1521
+ );
1453
1522
 
1454
1523
  // settings.json UserPromptSubmit hooks. block → abort the run; context → inject.
1455
1524
  if (settingsHooks) {
@@ -1654,7 +1723,13 @@ async function runAgentHeadlessInWorkspace(
1654
1723
  // tool to the LLM. A bad --mcp-config file fails fast; registered connects
1655
1724
  // are best-effort. --no-mcp disables the registered set (ad-hoc still loads).
1656
1725
  let mcp = null;
1657
- {
1726
+ const exactToolCeilingExcludesMcp =
1727
+ hermeticExecution ||
1728
+ (options.exactToolNames === true &&
1729
+ Array.isArray(enabledToolNames) &&
1730
+ !enabledToolNames.some((name) => String(name).startsWith("mcp__")) &&
1731
+ !options.permissionPromptTool);
1732
+ if (!exactToolCeilingExcludesMcp) {
1658
1733
  const doResolve = deps.resolveAgentMcp || resolveAgentMcp;
1659
1734
  try {
1660
1735
  mcp = await doResolve(
@@ -1727,6 +1802,7 @@ async function runAgentHeadlessInWorkspace(
1727
1802
  : null,
1728
1803
  recovery: resumeMcpRecovery,
1729
1804
  recoveryError: resumeMcpRecoveryError,
1805
+ dispatchAdmission: sessionHostLease?.admitMcpDispatch || null,
1730
1806
  });
1731
1807
  const hostMcp = mcp
1732
1808
  ? { ...mcp, mcpClient: mcpRecoveryRuntime.client || mcp.mcpClient }
@@ -1756,27 +1832,29 @@ async function runAgentHeadlessInWorkspace(
1756
1832
  // to the in-flight user message only — AFTER persistence — so a resumed
1757
1833
  // session replays the prompt, not a stale editor snapshot. Best-effort with
1758
1834
  // a short timeout; CC_IDE_CONTEXT=0 disables.
1759
- try {
1760
- const { buildIdePromptContext, appendTextToContent, expandIdeMentions } =
1761
- await import("../lib/ide-context.js");
1762
- const last = messages[messages.length - 1];
1763
- const ideCtx = await (deps.buildIdePromptContext || buildIdePromptContext)(
1764
- hostMcp,
1765
- );
1766
- if (ideCtx) {
1767
- last.content = appendTextToContent(last.content, ideCtx);
1768
- }
1769
- // Explicit @selection / @diagnostics mentions in the user's prompt
1770
- // (Claude-Code parity). Scan the ORIGINAL prompt so injected file-ref
1771
- // blocks can't spoof a mention; append the expansion to the in-flight
1772
- // message only (ephemeral, like the ambient block above).
1773
- const mentioned = await expandIdeMentions(prompt, hostMcp);
1774
- for (const w of mentioned.warnings) writeErr(` @ide: ${w}\n`);
1775
- if (mentioned.block) {
1776
- last.content = appendTextToContent(last.content, mentioned.block);
1835
+ if (!hermeticExecution) {
1836
+ try {
1837
+ const { buildIdePromptContext, appendTextToContent, expandIdeMentions } =
1838
+ await import("../lib/ide-context.js");
1839
+ const last = messages[messages.length - 1];
1840
+ const ideCtx = await (
1841
+ deps.buildIdePromptContext || buildIdePromptContext
1842
+ )(hostMcp);
1843
+ if (ideCtx) {
1844
+ last.content = appendTextToContent(last.content, ideCtx);
1845
+ }
1846
+ // Explicit @selection / @diagnostics mentions in the user's prompt
1847
+ // (Claude-Code parity). Scan the ORIGINAL prompt so injected file-ref
1848
+ // blocks can't spoof a mention; append the expansion to the in-flight
1849
+ // message only (ephemeral, like the ambient block above).
1850
+ const mentioned = await expandIdeMentions(prompt, hostMcp);
1851
+ for (const w of mentioned.warnings) writeErr(` @ide: ${w}\n`);
1852
+ if (mentioned.block) {
1853
+ last.content = appendTextToContent(last.content, mentioned.block);
1854
+ }
1855
+ } catch {
1856
+ // IDE context is optional polish — never fail the run over it.
1777
1857
  }
1778
- } catch {
1779
- // IDE context is optional polish — never fail the run over it.
1780
1858
  }
1781
1859
 
1782
1860
  // (`_bgPhase` — the background phase reporter — is created before the resume
@@ -1786,7 +1864,7 @@ async function runAgentHeadlessInWorkspace(
1786
1864
  // --permission-prompt-tool: route every CONFIRM-tier approval to an MCP tool
1787
1865
  // (loaded via --mcp-config) instead of headless fail-closed. Overrides the
1788
1866
  // permission-mode confirmer on the gate for this session.
1789
- if (options.permissionPromptTool) {
1867
+ if (!hermeticExecution && options.permissionPromptTool) {
1790
1868
  let ppt;
1791
1869
  try {
1792
1870
  ppt = resolvePermissionPromptTool(mcp, options.permissionPromptTool);
@@ -1829,7 +1907,11 @@ async function runAgentHeadlessInWorkspace(
1829
1907
  // --permission-prompt-tool; that flag wins when both are given since it is
1830
1908
  // installed above and this block skips). Fail-closed on timeout.
1831
1909
  let _remoteApproval = null;
1832
- if (options.remoteControl && !options.permissionPromptTool) {
1910
+ if (
1911
+ !hermeticExecution &&
1912
+ options.remoteControl &&
1913
+ !options.permissionPromptTool
1914
+ ) {
1833
1915
  try {
1834
1916
  const { startHeadlessRemoteApproval } =
1835
1917
  await import("../lib/remote-approval-bridge.js");
@@ -1858,14 +1940,16 @@ async function runAgentHeadlessInWorkspace(
1858
1940
  // same privacy-gated spans; the default path remains zero cost.
1859
1941
  let _otlpRecorder = null;
1860
1942
  let _collectorEnabled = false;
1861
- try {
1862
- const { isOtlpCollectorEnabled } =
1863
- await import("../lib/observability/index.js");
1864
- _collectorEnabled = isOtlpCollectorEnabled();
1865
- } catch {
1866
- _collectorEnabled = false;
1943
+ if (!hermeticExecution) {
1944
+ try {
1945
+ const { isOtlpCollectorEnabled } =
1946
+ await import("../lib/observability/index.js");
1947
+ _collectorEnabled = isOtlpCollectorEnabled();
1948
+ } catch {
1949
+ _collectorEnabled = false;
1950
+ }
1867
1951
  }
1868
- if (options.otlp || _collectorEnabled) {
1952
+ if (!hermeticExecution && (options.otlp || _collectorEnabled)) {
1869
1953
  try {
1870
1954
  const { TelemetryRecorder } =
1871
1955
  await import("../lib/telemetry/span-recorder.js");
@@ -1901,8 +1985,8 @@ async function runAgentHeadlessInWorkspace(
1901
1985
 
1902
1986
  // Resolve auto-pin (flag > env > config > default-on). Config read is
1903
1987
  // best-effort — a broken config file must not take headless down.
1904
- let _autoPinResolved;
1905
- {
1988
+ let _autoPinResolved = false;
1989
+ if (!hermeticExecution) {
1906
1990
  const { resolveAutoPinOption } = await import("./auto-pin.js");
1907
1991
  let _autoPinCfg;
1908
1992
  try {
@@ -1995,10 +2079,10 @@ async function runAgentHeadlessInWorkspace(
1995
2079
  managedCheckpoint: options.managedCheckpoint === true,
1996
2080
  managedCheckpointStateDir: options.managedCheckpointStateDir || null,
1997
2081
  managedCheckpointExclusions: options.managedCheckpointExclusions || [],
1998
- hookDb: db,
1999
- approvalGate,
2000
- permissionRules,
2001
- settingsHooks,
2082
+ hookDb: hermeticExecution ? null : db,
2083
+ approvalGate: hermeticExecution ? null : approvalGate,
2084
+ permissionRules: hermeticExecution ? null : permissionRules,
2085
+ settingsHooks: hermeticExecution ? null : settingsHooks,
2002
2086
  // Seed the subagent-contract CEILING with this run's permission mode so a
2003
2087
  // spawned sub-agent inherits/tightens from it (tighten-only): a
2004
2088
  // `--permission-mode bypassPermissions` run can hand a child bypass (→ allow
@@ -2009,8 +2093,11 @@ async function runAgentHeadlessInWorkspace(
2009
2093
  classifyAllShell,
2010
2094
  enabledToolNames,
2011
2095
  disabledTools,
2096
+ exactToolNames: options.exactToolNames === true,
2097
+ fileMutationScope,
2098
+ hermeticExecution,
2012
2099
  iterationBudget: budget,
2013
- toolAdmission: options.toolAdmission || null,
2100
+ toolAdmission: hermeticExecution ? null : options.toolAdmission || null,
2014
2101
  // `ask_user_question` in a BACKGROUND turn child: send a bound request to
2015
2102
  // the worker over Node IPC and await the answer here. `executeTool` remains
2016
2103
  // suspended, so the model continues the SAME turn/tool call after the user
@@ -2060,6 +2147,9 @@ async function runAgentHeadlessInWorkspace(
2060
2147
  // Keep the guarded in-memory ledger when persistence is disabled so an
2061
2148
  // outcome-unknown call still latches UNSAFE for the rest of this process.
2062
2149
  mcpCallLedger: mcpRecoveryRuntime.ledger,
2150
+ mcpDispatchAdmission: hermeticExecution
2151
+ ? null
2152
+ : sessionHostLease?.admitMcpDispatch || null,
2063
2153
  // chatFn passthrough lets tests drive the loop deterministically.
2064
2154
  chatFn: deps.chatFn || options.chatFn || undefined,
2065
2155
  signal: options.signal || undefined,
@@ -2414,10 +2504,12 @@ async function runAgentHeadlessInWorkspace(
2414
2504
  // race a competing handler. Removed in `finally` so a normal return leaves no
2415
2505
  // listener behind (runAgentHeadless can be called repeatedly in one process).
2416
2506
  const _onHardSignal = (sig) => {
2417
- try {
2418
- killAllBackgroundShellTasksSync();
2419
- } catch {
2420
- /* best-effort — never let cleanup throw during shutdown */
2507
+ if (!hermeticExecution) {
2508
+ try {
2509
+ killAllBackgroundShellTasksSync();
2510
+ } catch {
2511
+ /* best-effort — never let cleanup throw during shutdown */
2512
+ }
2421
2513
  }
2422
2514
  try {
2423
2515
  if (_hookSupervisor) _hookSupervisor.stopAll();
@@ -2927,9 +3019,11 @@ async function runAgentHeadlessInWorkspace(
2927
3019
  await cleanupDeadline.run("mcp", () => mcp?.mcpClient?.disconnectAll?.());
2928
3020
  // Kill any background run_shell tasks this run spawned so a backgrounded
2929
3021
  // command (e.g. a dev server) doesn't outlive the headless invocation.
2930
- await cleanupDeadline.run("background-shells", () =>
2931
- killAllBackgroundShellTasks(),
2932
- );
3022
+ if (!hermeticExecution) {
3023
+ await cleanupDeadline.run("background-shells", () =>
3024
+ killAllBackgroundShellTasks(),
3025
+ );
3026
+ }
2933
3027
  // Tear down the --remote-control approval bridge + its self-hosted WS
2934
3028
  // server so the run's port/socket never outlives the invocation.
2935
3029
  await cleanupDeadline.run("remote-approval", () =>