chainlesschain 0.162.159 → 0.162.161

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 (199) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-ByIiF5bT.js → AIOps-DMn528q-.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-NlgSFZq5.js → ActionButton-D9ZcDCJL.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D17cOUcb.js → Analytics-A_K-8PX0.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-B4mEZcbl.js → AppLayout-D4pFW3X6.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-CASsmyQw.js → Artifacts-Dz46COAd.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-DYAia2e2.js → Audit-cbMjbyg0.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-C1lvYUSu.js → BackgroundAgents-Dtf88GAj.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-B6agK6bA.js → Backup-C5KRxn52.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DM43R2vy.js → BaseInput-Dd2UK3BN.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-Dtdp3eXp.js → Chat-lptKTFdG.js} +6 -6
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BL5c_OQ1.js → ChatBubbleRenderer-C2KLtwHz.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-D2xf7uZt.js → Checkbox-_yspG6rG.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-D3j45jJL.js → Codegen-BGq_GAha.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-voPJ9fUZ.js → Col-CePor71g.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-DEsyTESF.js → Community-CLOWhIT7.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-OHV_QXLD.js → Compact-CivJt2vT.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-eDTJWC-J.js → Compliance-Btmo1GGE.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-BBvy-6d1.js → Cowork-Ct35OlG4.js} +2 -2
  21. package/src/assets/web-panel/assets/{Cron-Dw2eoJxu.js → Cron-CTc2GmhB.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DQHms_Bh.js → Crosschain-ZtiBETk1.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-Cyu7Id1c.js → DID-BNqMQQXw.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-sIDzkG92.js → Dashboard-BmzZd-9V.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-DUW3T2ey.js → Dropdown-CMVgvP2M.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-CECELXW8.js → EmailListRenderer-CcqQFAfT.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BIZR37ov.js → FamilyGuardDashboard-CTqB1_4V.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BEZIQX84.js → Federation-CiKOOzlb.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BcdUMznL.js → FormItemContext-Wk-OT0gr.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-DsN_fr5H.js → GenericCardRenderer-DbEQT6ue.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-63LhjBx2.js → Git-0ZvCPSD9.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CYtQtIcH.js → Governance-CmVuKkPb.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BwR6UUox.js → Inference-CTWE3Jwg.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-D9lVNTUA.js → KnowledgeGraph-CBEIF00L.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-C4q5h7Ut.js → Logs-DLhxDwVG.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-DxywvhTU.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-Plksliuw.js → Marketplace-BgsCBrnc.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DZUFfeuG.js → McpTools-ClBUGDS2.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-NoDYt29V.js → Memory-CnG_ZnYw.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CEXGTkdh.js → MobileBridge-BUOAbR1Z.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-DnbJkbZo.js → MobileProjects-Dnt_9-WB.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-DTAa0cwy.js → Mtc-CLjt4kCD.js} +5 -5
  43. package/src/assets/web-panel/assets/{MtcAudit-CVV7LnNS.js → MtcAudit-f24U9Aes.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-BqqGrjt_.js → Multisig-GrmGQbSq.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-C4WP8DRp.js → NLProgramming-DADaWn-n.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-Zo4DJUVI.js → Notes-xtf5RX6C.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-DBcjRaz2.js → NotificationSettings-Cd27Rgtx.js} +1 -1
  48. package/src/assets/web-panel/assets/OrderTableRenderer-fXRxlDjl.js +1 -0
  49. package/src/assets/web-panel/assets/{Organization-BT9WPBOX.js → Organization-joCFlNB0.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-D6b4bZ3q.js → Overflow-B1HoURq0.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-Cw3OsYx-.js → P2P-DiwsKbT7.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-C0nyiK2b.js → PdhVaultBrowser-Xe-BsW6S.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-zVBZEB_C.js → Permissions-C23qi8kl.js} +3 -3
  54. package/src/assets/web-panel/assets/{PersonalDataHub-BOspsFew.js → PersonalDataHub-BS1syX2f.js} +2 -2
  55. package/src/assets/web-panel/assets/{Pipeline-CQWfZ4XH.js → Pipeline-DRYwwDyh.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-C2oGJ_WL.js → Privacy-BQKaDHPH.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BZMR4qY1.js → ProjectInit-BC6F9xiG.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-DAujoP63.js → ProjectSettings-ClFPc1Nd.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-Dn-f5aYe.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-D_RGHM-v.js → Providers-CLWuOUNt.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-Mf6KfL2J.js → QrScannerModal-DiqULTxb.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-5D8URoI_.js → QuickAsk-9A03P-E_.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-Df4kC8Gy.js → Recommend-CJZAnbq_.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DGi3f3vO.js → RemoteSession-C9A1R77h.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-jmkGFNWb.js → Reputation-BIZc6Rky.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DP6Pcu3m.js → Row-DfIPNtuG.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-D60hSuPO.js → RssFeed-C5znFcQ1.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-0mf1BQUK.js → Search-DSs2z3OX.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-CfZtLFYV.js → Security-CV6LcrLY.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-D9zpZLWz.js → Services-cmhoX0Xj.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-D1_44eMD.js → Skeleton-tCsg2po7.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-cVFa8zkz.js → Skills-BK1KUDiy.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-Cinpzc3L.js → Sla-yRgyeA82.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-bqdiJE_P.js → SpeechSettings-c1mo1mlp.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-Dgl_SLgj.js → SyncSettings-koIAfuT3.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-DawWAEhy.js → Tasks-DkkreAaB.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-Ca0nY651.js → Templates-fy5Ctf9M.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-CgaGEhLm.js → Tenant-Bw70Jf6S.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-D-9EnpRx.js → Terminal-BKh6Rx-4.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-CSOxDHZ6.js → TimelineRenderer-Dg54WP0c.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-BpwLZpL3.js → Tokens-BvvD5SxJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DgowwBK5.js → Trigger-B7Ug9x4e.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-BZutapjE.js → Trust-BjvuMORY.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-QZPt8_Sp.js → UkeySign-CZqhkx8p.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DlQx5UDJ.js → VideoEditing-ClR50lhX.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-ZfdTgtWA.js → Wallet-DlfppYjx.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-CAp0y_Cr.js → WebAuthn-BirgVr8B.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BVITZEmr.js → WorkflowEditor-B8DP_bax.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-CC2tPaNg.js → chat-DA8AUZzL.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-31brc9CA.js → colors-C38pLGp1.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-DLMkC9C-.js → compact-item-81rtr98o.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BMtveI6F.js → createContext-D34ixq8t.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-CHDIEOeN.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DbD6WHW2.js → hasIn-D4bzqTrZ.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BoO4WEJB.js → index-9qoVpPt6.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CJhREOlG.js → index-B0QArPQt.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BnFLzejT.js → index-B8mkLM4x.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Bbc2JeQG.js → index-BIP62a6r.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CFXKbOek.js → index-BP-zkXK8.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-C-cGlCDW.js → index-BS3M5H9V.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-AaIKG60c.js → index-BXd2_LmH.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CEXa-4zd.js → index-BlxEphl7.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DZl-UXB6.js → index-BqIhLAbA.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BOM-VFlv.js → index-BtGxuQrO.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CcVszn2b.js → index-BvD7b2IK.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-C21pdBqs.js → index-BvL_3J_n.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DJvxFyIz.js → index-COe_cOLJ.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-ALvoNTRF.js → index-CP5alL4t.js} +1 -1
  109. package/src/assets/web-panel/assets/index-CY1NURWZ.js +1 -0
  110. package/src/assets/web-panel/assets/{index-Dm0byjm1.js → index-CbhE3j5j.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-WQUO2vvK.js → index-Cd3KuNK5.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-bdaJwTXJ.js → index-CoVgZw_b.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-COHHQ9cU.js → index-CuS-UPoj.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-C7LHNw_N.js → index-D0Ih7Hwn.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Cod97Urs.js → index-D3zCCZRS.js} +3 -3
  116. package/src/assets/web-panel/assets/{index-Cwbqh0KZ.js → index-D6GfvEQG.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BKAB6-6V.js → index-DBFSo1NF.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CEwjBA9q.js → index-DFHa1HIg.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DndNnYc0.js → index-DFyWKOBD.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-3oBsXZmF.js → index-DMgnRwrK.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-C_eUKGYP.js → index-DUQLXLQM.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CUmLMFsy.js → index-D_2VYPr1.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BPpS-lGb.js → index-DakfFZ-k.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ep6JchNG.js → index-Ddk0e_Pi.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D7cV0tu0.js → index-DkHqMnn3.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-jG6h22Qg.js → index-Dmo3dFHb.js} +1 -1
  127. package/src/assets/web-panel/assets/index-DokUYqpq.js +1 -0
  128. package/src/assets/web-panel/assets/{index-C1PfeI88.js → index-DvfCEJG-.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-ntVQqSML.js → index-E1OJRXs4.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CWgfipcC.js → index-F76w1NiL.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BiRQUoyE.js → index-ZRJRItm0.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BFRLmCR3.js → index-fI5sXMLg.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-D67kIagl.js → index-tKiC8T-4.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-D5UoBRhN.js → initDefaultProps-ByyvflIR.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-DltOw0CR.js → motion-B3FQm2By.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-_oPkk5zj.js → move-BSfns6Ef.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-EES8ROCS.js → mtc-parser-CTG1Ieri.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-B-_39x_M.js → omit-DObM_2j6.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-l6D0yJHz.js → pickAttrs-DOfelQ1t.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-DIeUK31L.js → placementArrow-CHZILds_.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-dG4EzUQo.js → responsiveObserve-REbucKSx.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DWFzYGdH.js → slide-C6EZzD7o.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-CECdTA5H.js → statusUtils-BxkWS-g3.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-D6kP-mMK.js → styleChecker-Chklyoq6.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-BWfna_rd.js → useFlexGapSupport-CRVwKrrI.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-Bb-j6rzo.js → useFs-DV24ik_J.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-D5OIsYM4.js → usePersonalDataHub-C7vIo4Pg.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DNpwzFTM.js → vnode-By-v5GlF.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-vNLpFQBW.js → zoom-B1w9Am3r.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/agenda.js +15 -1
  152. package/src/commands/agent.js +72 -6
  153. package/src/commands/background-session.js +46 -2
  154. package/src/commands/mcp.js +46 -0
  155. package/src/commands/session.js +70 -0
  156. package/src/data/changelog.json +12 -2
  157. package/src/gateways/ws/background-agent-protocol.js +88 -14
  158. package/src/harness/jsonl-session-store.js +70 -1
  159. package/src/harness/mcp-client.js +50 -0
  160. package/src/lib/agent-authority.js +251 -0
  161. package/src/lib/agent-sandbox.js +68 -0
  162. package/src/lib/agents.js +12 -4
  163. package/src/lib/api-key-helper.js +62 -0
  164. package/src/lib/background-agent-phase.js +100 -0
  165. package/src/lib/background-agent-supervisor.js +320 -8
  166. package/src/lib/backpressure-policy.js +105 -0
  167. package/src/lib/capability-negotiation.js +212 -0
  168. package/src/lib/credential-guard.js +11 -0
  169. package/src/lib/credential-proxy.js +182 -0
  170. package/src/lib/dependency-install-policy.js +130 -0
  171. package/src/lib/event-seq-replay.js +167 -0
  172. package/src/lib/exit-codes.cjs +77 -0
  173. package/src/lib/goal-condition-engine.js +369 -0
  174. package/src/lib/headless-manifest.js +188 -0
  175. package/src/lib/hook-runner.cjs +70 -4
  176. package/src/lib/ide-context-redaction.js +130 -0
  177. package/src/lib/ide-context.js +128 -13
  178. package/src/lib/jsonl-session-store.js +2 -0
  179. package/src/lib/llm-config-defaults.js +24 -8
  180. package/src/lib/project-instructions.js +98 -1
  181. package/src/lib/project-mcp-trust.js +87 -0
  182. package/src/lib/remote-path-mapping.js +229 -0
  183. package/src/lib/schedule-planner.js +136 -0
  184. package/src/lib/sensitive-file-guard.js +51 -0
  185. package/src/lib/sub-agent-context.js +7 -3
  186. package/src/repl/bg-dashboard.js +13 -12
  187. package/src/runtime/agent-core.js +113 -10
  188. package/src/runtime/coding-agent-contract-shared.cjs +19 -2
  189. package/src/runtime/headless-runner.js +66 -7
  190. package/src/runtime/headless-stream.js +224 -12
  191. package/src/runtime/mcp-config.js +32 -1
  192. package/src/runtime/system-prompt.js +3 -0
  193. package/src/workers/background-agent-worker.js +37 -2
  194. package/src/assets/web-panel/assets/MarkdownRenderer-DexLlXfN.js +0 -1
  195. package/src/assets/web-panel/assets/OrderTableRenderer-BCQel9bD.js +0 -1
  196. package/src/assets/web-panel/assets/Projects-DvH_P2Uq.js +0 -1
  197. package/src/assets/web-panel/assets/devWarning-CB8pPOtd.js +0 -1
  198. package/src/assets/web-panel/assets/index-BhXiaiev.js +0 -1
  199. package/src/assets/web-panel/assets/index-WpaYaE3D.js +0 -1
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Background-agent dashboard — the interactive agent view behind
3
3
  * `cc daemon view` (no id). Claude-Code `claude agents` parity: one live panel
4
- * over every background session with grouping (Needs input / Working /
4
+ * over every background session with grouping (Needs input / Working / Idle /
5
5
  * Completed / Failed / Stopped), peek + reply, attach hand-off, stop, rename,
6
- * pin, filter, and new-task dispatch.
6
+ * pin, filter, and new-task dispatch. Phase→group classification is the shared
7
+ * `background-agent-phase.js` contract, so `idle` (parked, nothing blocking)
8
+ * is kept distinct from a genuine `needs-input` (a human decision blocks it).
7
9
  *
8
10
  * Design:
9
11
  * - Pure model/render layer (`groupKey`, `buildDashboardModel`,
@@ -17,10 +19,12 @@
17
19
  */
18
20
 
19
21
  import chalk from "chalk";
22
+ import { phaseGroupKey } from "../lib/background-agent-phase.js";
20
23
 
21
24
  export const GROUP_ORDER = [
22
25
  "needs-input",
23
26
  "working",
27
+ "idle",
24
28
  "completed",
25
29
  "failed",
26
30
  "stopped",
@@ -29,24 +33,21 @@ export const GROUP_ORDER = [
29
33
  export const GROUP_TITLES = {
30
34
  "needs-input": "Needs input",
31
35
  working: "Working",
36
+ idle: "Idle",
32
37
  completed: "Completed",
33
38
  failed: "Failed",
34
39
  stopped: "Stopped",
35
40
  };
36
41
 
37
42
  /**
38
- * Group a session: running+idle phase = waiting for a follow-up (the closest
39
- * analog of "needs input" — the worker finished a turn and a client can
40
- * reply); running+turn = working; lost workers count as failed.
43
+ * Group a session into a dashboard bucket. Delegates to the shared
44
+ * `background-agent-phase.js` contract so the worker/supervisor and this panel
45
+ * agree on phase semantics: running + pending approval / blocking phase →
46
+ * "needs-input"; running + idle (parked, nothing blocking) → "idle"; running +
47
+ * working/turn/starting → "working"; lost/unknown → "failed".
41
48
  */
42
49
  export function groupKey(session) {
43
- const status = session?.status;
44
- if (status === "running") {
45
- return session.phase === "idle" ? "needs-input" : "working";
46
- }
47
- if (status === "completed") return "completed";
48
- if (status === "stopped") return "stopped";
49
- return "failed"; // failed | lost | unknown
50
+ return phaseGroupKey(session);
50
51
  }
51
52
 
52
53
  function formatAge(ms) {
@@ -25,6 +25,7 @@ import sharedSettingsHooks from "../lib/settings-hooks.cjs";
25
25
  import sharedHookRunner from "../lib/hook-runner.cjs";
26
26
  import sharedHookEvents from "../lib/settings-hook-events.cjs";
27
27
  import { mergeProviderOptions } from "../lib/provider-options.js";
28
+ import { applyCredentialProxy } from "../lib/credential-proxy.js";
28
29
  import { getPlanModeManager } from "../lib/plan-mode.js";
29
30
  import { CLISkillLoader } from "../lib/skill-loader.js";
30
31
  import { executeHooks, HookEvents } from "../lib/hook-manager.js";
@@ -673,8 +674,8 @@ Key behaviors:
673
674
  When the user's problem involves data processing, calculations, file operations, text parsing, API calls, web scraping, or any task that can be solved programmatically:
674
675
  - Proactively write and execute code using run_code tool
675
676
  - Choose the best language: Python for data/math/scraping, Node.js for JSON/API, Bash for system tasks
676
- - Missing Python packages are auto-installed via pip when import errors are detected
677
- - Scripts are persisted in .chainlesschain/agent-scripts/ for reference
677
+ - Missing Python packages are NOT auto-installed by default; the tool result tells you (and the user) how to opt in (settings runCode.autoInstall)
678
+ - Scripts run from a temp file by default; pass persist:true to keep one in .chainlesschain/agent-scripts/ for reference
678
679
  - Show the results and explain them clearly
679
680
  - If the first attempt fails, debug and retry with a different approach
680
681
 
@@ -1263,6 +1264,8 @@ export async function executeTool(name, args, context = {}) {
1263
1264
  // Sensitive-file write guard (Claude-Code 2.1.160 parity): shell startup
1264
1265
  // files / PowerShell profiles / git+husky hooks execute code on the user's
1265
1266
  // next shell or commit — even otherwise-permitted edit flows confirm first.
1267
+ // Auto-exec configs (.vscode/tasks.json, .mcp.json, .idea run configs, …)
1268
+ // ride the same gate via autoExecConfigReason.
1266
1269
  // An explicit settings `allow` rule is the only bypass (exact user
1267
1270
  // pre-authorization); headless without a confirmer fails closed.
1268
1271
  if (
@@ -1272,9 +1275,10 @@ export async function executeTool(name, args, context = {}) {
1272
1275
  settingsVerdict.decision !== "allow" &&
1273
1276
  args?.path
1274
1277
  ) {
1275
- const { sensitiveFileReason } =
1278
+ const { sensitiveFileReason, autoExecConfigReason } =
1276
1279
  await import("../lib/sensitive-file-guard.js");
1277
- const sensReason = sensitiveFileReason(args.path);
1280
+ const sensReason =
1281
+ sensitiveFileReason(args.path) || autoExecConfigReason(args.path);
1278
1282
  if (sensReason) {
1279
1283
  const ok = await requestInteractivePermission(name, args, context, cwd, {
1280
1284
  tool: name,
@@ -2537,7 +2541,10 @@ async function executeToolInner(
2537
2541
  // Same agent-identity env as the foreground path: CLAUDECODE marks
2538
2542
  // "running under the agent"; the session id correlates work to the
2539
2543
  // run (CC_SESSION_ID + CLAUDE_CODE_SESSION_ID for Claude-Code parity).
2540
- env: {
2544
+ // Credential proxy (opt-in, CC_CREDENTIAL_PROXY): keeps the agent's
2545
+ // real long-lived secrets out of the spawned command's env — a
2546
+ // no-op (same object) when disabled. See credential-proxy.js.
2547
+ env: applyCredentialProxy({
2541
2548
  ...process.env,
2542
2549
  CLAUDECODE: "1",
2543
2550
  ...(sessionId
@@ -2546,7 +2553,7 @@ async function executeToolInner(
2546
2553
  CLAUDE_CODE_SESSION_ID: String(sessionId),
2547
2554
  }
2548
2555
  : {}),
2549
- },
2556
+ }).env,
2550
2557
  // POSIX: own process group so check_shell{kill}/teardown can signal
2551
2558
  // the whole tree (shell + its grandchild command). No-op on Windows
2552
2559
  // where the tree is killed via taskkill /T instead.
@@ -2712,7 +2719,10 @@ async function executeToolInner(
2712
2719
  // parity): CLAUDECODE=1 marks "running under the agent"; CC_SESSION_ID
2713
2720
  // + its CLAUDE_CODE_SESSION_ID mirror let scripts/hooks correlate work
2714
2721
  // to the agent session (the mirror is what CC-targeting tools expect).
2715
- env: {
2722
+ // Credential proxy (opt-in, CC_CREDENTIAL_PROXY): keeps the agent's
2723
+ // real long-lived secrets out of the shell's env — a no-op (same
2724
+ // object) when disabled. See credential-proxy.js.
2725
+ env: applyCredentialProxy({
2716
2726
  ...process.env,
2717
2727
  CLAUDECODE: "1",
2718
2728
  ...(sessionId
@@ -2721,7 +2731,7 @@ async function executeToolInner(
2721
2731
  CLAUDE_CODE_SESSION_ID: String(sessionId),
2722
2732
  }
2723
2733
  : {}),
2724
- },
2734
+ }).env,
2725
2735
  };
2726
2736
  let output;
2727
2737
  if (shellInv.useDefaultShell) {
@@ -3908,7 +3918,10 @@ async function _executeRunCode(args, cwd) {
3908
3918
  const lang = args.language;
3909
3919
  const code = args.code;
3910
3920
  const timeoutSec = Math.min(Math.max(args.timeout || 60, 1), 300);
3911
- const persist = args.persist !== false; // default true
3921
+ // gap-analysis 2026-07-11 P0 "依赖安装与凭据": agent-generated scripts
3922
+ // default to the OS temp dir; only an explicit persist:true lands them in
3923
+ // the project (.chainlesschain/agent-scripts/).
3924
+ const persist = args.persist === true; // default false (temp dir)
3912
3925
 
3913
3926
  const extMap = { python: ".py", node: ".js", bash: ".sh" };
3914
3927
  const ext = extMap[lang];
@@ -3978,6 +3991,51 @@ async function _executeRunCode(args, cwd) {
3978
3991
  };
3979
3992
  }
3980
3993
 
3994
+ // Auto-install is OPT-IN (settings runCode.autoInstall / env
3995
+ // CC_RUN_CODE_AUTO_INSTALL=1) with an optional package allowlist;
3996
+ // every attempt — including refused ones — is audited.
3997
+ const {
3998
+ resolveAutoInstallPolicy,
3999
+ isPackageAllowed,
4000
+ autoInstallDisabledHint,
4001
+ recordInstallAudit,
4002
+ } = await import("../lib/dependency-install-policy.js");
4003
+ const installPolicy = resolveAutoInstallPolicy({ cwd });
4004
+ if (!installPolicy.enabled) {
4005
+ recordInstallAudit({
4006
+ package: packageName,
4007
+ interpreter,
4008
+ cwd,
4009
+ outcome: "disabled",
4010
+ });
4011
+ return {
4012
+ error: (stderr || message).substring(0, 5000),
4013
+ stderr: stderr.substring(0, 5000),
4014
+ exitCode: err.status,
4015
+ language: lang,
4016
+ ...classified,
4017
+ hint: autoInstallDisabledHint(packageName),
4018
+ scriptPath: persist ? scriptPath : undefined,
4019
+ };
4020
+ }
4021
+ if (!isPackageAllowed(packageName, installPolicy.allowlist)) {
4022
+ recordInstallAudit({
4023
+ package: packageName,
4024
+ interpreter,
4025
+ cwd,
4026
+ outcome: "blocked",
4027
+ });
4028
+ return {
4029
+ error: (stderr || message).substring(0, 5000),
4030
+ stderr: stderr.substring(0, 5000),
4031
+ exitCode: err.status,
4032
+ language: lang,
4033
+ ...classified,
4034
+ hint: `Package "${packageName}" is not in runCode.installAllowlist — install it manually or add it to the allowlist.`,
4035
+ scriptPath: persist ? scriptPath : undefined,
4036
+ };
4037
+ }
4038
+
3981
4039
  // Attempt pip install
3982
4040
  try {
3983
4041
  execSync(`${interpreter} -m pip install ${packageName}`, {
@@ -3986,6 +4044,12 @@ async function _executeRunCode(args, cwd) {
3986
4044
  maxBuffer: 2 * 1024 * 1024,
3987
4045
  stdio: ["pipe", "pipe", "pipe"],
3988
4046
  });
4047
+ recordInstallAudit({
4048
+ package: packageName,
4049
+ interpreter,
4050
+ cwd,
4051
+ outcome: "installed",
4052
+ });
3989
4053
 
3990
4054
  // Retry execution
3991
4055
  const retryStart = Date.now();
@@ -4006,6 +4070,13 @@ async function _executeRunCode(args, cwd) {
4006
4070
  scriptPath: persist ? scriptPath : undefined,
4007
4071
  };
4008
4072
  } catch (pipErr) {
4073
+ recordInstallAudit({
4074
+ package: packageName,
4075
+ interpreter,
4076
+ cwd,
4077
+ outcome: "failed",
4078
+ detail: (pipErr.stderr || pipErr.message || "").substring(0, 200),
4079
+ });
4009
4080
  return {
4010
4081
  error: (stderr || message).substring(0, 5000),
4011
4082
  stderr: stderr.substring(0, 5000),
@@ -4233,6 +4304,17 @@ async function _executeSpawnSubAgent(args, ctx) {
4233
4304
  tools: explicitTools,
4234
4305
  profile: profileName,
4235
4306
  } = args;
4307
+ // Extended sub-agent contract (gap 2026-07-11 P1): per-spawn deny-list,
4308
+ // iteration cap and worktree isolation — spawn args win over the agent
4309
+ // file's frontmatter defaults.
4310
+ let disallowedTools = Array.isArray(args.disallowedTools)
4311
+ ? args.disallowedTools.filter(Boolean)
4312
+ : null;
4313
+ let subMaxTurns =
4314
+ Number.isFinite(Number(args.maxTurns)) && Number(args.maxTurns) > 0
4315
+ ? Math.floor(Number(args.maxTurns))
4316
+ : null;
4317
+ let subIsolation = args.isolation === "worktree" ? "worktree" : null;
4236
4318
 
4237
4319
  // Named subagent delegation (cc agents / .chainlesschain|.claude/agents/*.md):
4238
4320
  // load the agent's persona (its body = system prompt) + tool allow-list.
@@ -4250,6 +4332,13 @@ async function _executeSpawnSubAgent(args, ctx) {
4250
4332
  }
4251
4333
  role = role || md.name;
4252
4334
  if (!explicitTools && Array.isArray(md.tools)) explicitTools = md.tools;
4335
+ if (!disallowedTools && Array.isArray(md.disallowedTools)) {
4336
+ disallowedTools = md.disallowedTools;
4337
+ }
4338
+ if (!subMaxTurns && md.maxTurns) subMaxTurns = md.maxTurns;
4339
+ if (!subIsolation && md.isolation === "worktree") {
4340
+ subIsolation = "worktree";
4341
+ }
4253
4342
  if (md.model) mdModel = md.model;
4254
4343
  if (md.systemPrompt) {
4255
4344
  mdProfile = { name: md.name, systemPrompt: md.systemPrompt };
@@ -4289,9 +4378,19 @@ async function _executeSpawnSubAgent(args, ctx) {
4289
4378
  // profile.systemPrompt seam) when no declarative profile was requested.
4290
4379
  if (!profile && mdProfile) profile = mdProfile;
4291
4380
 
4292
- const allowedTools = Array.isArray(explicitTools)
4381
+ let allowedTools = Array.isArray(explicitTools)
4293
4382
  ? explicitTools
4294
4383
  : profile?.toolAllowlist || null;
4384
+ // Deny-list: subtract from the resolved allow-list; with no allow-list
4385
+ // ("all tools"), subtract from the full built-in contract set. spawn itself
4386
+ // is always denied downstream by depth/breadth caps, so no special-casing.
4387
+ if (Array.isArray(disallowedTools) && disallowedTools.length > 0) {
4388
+ const deny = new Set(disallowedTools.map((t) => String(t).trim()));
4389
+ const base = Array.isArray(allowedTools)
4390
+ ? allowedTools
4391
+ : listCodingAgentToolNames();
4392
+ allowedTools = base.filter((t) => !deny.has(t));
4393
+ }
4295
4394
 
4296
4395
  // Auto-condense parent context if caller didn't provide explicit context
4297
4396
  let resolvedContext = inheritedContext || null;
@@ -4399,6 +4498,10 @@ async function _executeSpawnSubAgent(args, ctx) {
4399
4498
  // single total-sub-agent pool (breadth cap spans the whole tree).
4400
4499
  subAgentBudget: ctx.subAgentBudget || null,
4401
4500
  onUsage,
4501
+ // Extended contract (gap 2026-07-11): per-agent iteration cap + opt-in
4502
+ // worktree isolation. undefined keeps the profile/flag defaults intact.
4503
+ ...(subMaxTurns ? { maxIterations: subMaxTurns } : {}),
4504
+ ...(subIsolation === "worktree" ? { useWorktree: true } : {}),
4402
4505
  });
4403
4506
  subCtxRef = subCtx;
4404
4507
 
@@ -521,7 +521,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
521
521
  kind: "code",
522
522
  tier: "extension",
523
523
  description:
524
- "Write and execute code in Python, Node.js, or Bash. Use this when the user needs data processing, calculations, file batch operations, API calls, or any task best solved with a script. Scripts are saved for reference. Missing Python packages are auto-installed.",
524
+ "Write and execute code in Python, Node.js, or Bash. Use this when the user needs data processing, calculations, file batch operations, API calls, or any task best solved with a script. Scripts run from a temp file unless persist:true. Missing Python packages are NOT auto-installed unless the user opted in (settings runCode.autoInstall).",
525
525
  inputSchema: {
526
526
  type: "object",
527
527
  properties: {
@@ -538,7 +538,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
538
538
  persist: {
539
539
  type: "boolean",
540
540
  description:
541
- "If true (default), save script in .chainlesschain/agent-scripts/. If false, use temp file and clean up.",
541
+ "If true, save the script in .chainlesschain/agent-scripts/ for reference. Default false: run from a temp file outside the project.",
542
542
  },
543
543
  },
544
544
  required: ["language", "code"],
@@ -599,6 +599,23 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
599
599
  description:
600
600
  "Run the sub-agent in the BACKGROUND: the call returns immediately with a running handle and you continue working; the sub-agent's result is delivered to you automatically in a later turn (the run waits for stragglers before finishing). Use for independent subtasks you don't need before your next step.",
601
601
  },
602
+ disallowedTools: {
603
+ type: "array",
604
+ items: { type: "string" },
605
+ description:
606
+ "Optional tool DENY-list for the sub-agent: these are removed from whatever tool set it would otherwise get (explicit `tools`, agent-file allowlist, or all).",
607
+ },
608
+ maxTurns: {
609
+ type: "number",
610
+ description:
611
+ "Optional iteration cap for the sub-agent's own loop (positive integer; default 8 or the profile's cap).",
612
+ },
613
+ isolation: {
614
+ type: "string",
615
+ enum: ["worktree"],
616
+ description:
617
+ "Optional isolation mode: \"worktree\" runs the sub-agent in a fresh git worktree so its file edits land on an isolated branch (diff/merge summary comes back with the result).",
618
+ },
602
619
  },
603
620
  required: ["task"],
604
621
  },
@@ -54,6 +54,18 @@ import { composeSystemPrompt } from "./system-prompt.js";
54
54
  import { buildUserContent } from "../lib/image-input.js";
55
55
  import { mergeConsecutiveMessages } from "./message-roles.js";
56
56
  import { isHeadlessConfigCommand } from "../lib/headless-config-command.js";
57
+ import {
58
+ STREAM_PROTOCOL_VERSION,
59
+ computePolicyDigest,
60
+ computeToolsHash,
61
+ buildLoadedSources,
62
+ } from "../lib/headless-manifest.js";
63
+ import {
64
+ HEADLESS_EXIT_CODES,
65
+ classifyLoopError,
66
+ exitCodeForEndReason,
67
+ } from "../lib/exit-codes.cjs";
68
+ import { isolationLevel } from "../lib/agent-sandbox.js";
57
69
  import { withQuietStdout } from "./quiet-stdout.js";
58
70
  import { CostBudget } from "../lib/cost-budget.js";
59
71
  import {
@@ -200,13 +212,18 @@ export function parseToolList(value) {
200
212
  * Persistence is intentionally OFF unless a resume/continue/persist intent is
201
213
  * present, so a plain one-shot `cc agent -p "..."` writes nothing to disk.
202
214
  *
203
- * @param {object} options { resume, continueSession, sessionId, persistSession }
215
+ * `--ephemeral` forces persistence OFF regardless of the above: a resume id
216
+ * still REPLAYS prior history into context, but nothing new is written — the
217
+ * deterministic-CI shape ("read context, leave no trace").
218
+ *
219
+ * @param {object} options { resume, continueSession, sessionId, persistSession, ephemeral }
204
220
  * @param {object} store { getLastSessionId } (injection seam)
205
221
  * @param {string} fallbackId used when nothing is being resumed
206
222
  * @returns {{ sessionId:string, resumeId:string|null, persist:boolean, wantLatest:boolean }}
207
223
  */
208
224
  export function resolveHeadlessSession(options = {}, store = {}, fallbackId) {
209
- const { resume, continueSession, sessionId, persistSession } = options;
225
+ const { resume, continueSession, sessionId, persistSession, ephemeral } =
226
+ options;
210
227
  const wantLatest = continueSession === true || resume === true;
211
228
  let resumeId = null;
212
229
  if (wantLatest) {
@@ -217,7 +234,10 @@ export function resolveHeadlessSession(options = {}, store = {}, fallbackId) {
217
234
  } else if (typeof resume === "string" && resume.trim()) {
218
235
  resumeId = resume.trim();
219
236
  }
220
- const persist = persistSession === true || resumeId != null || wantLatest;
237
+ const persist =
238
+ ephemeral === true
239
+ ? false
240
+ : persistSession === true || resumeId != null || wantLatest;
221
241
  const id = resumeId || sessionId || fallbackId;
222
242
  return { sessionId: id, resumeId, persist, wantLatest };
223
243
  }
@@ -900,7 +920,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
900
920
  } catch (err) {
901
921
  writeErr(`Error: ${err.message}\n`);
902
922
  emitHeadlessError(err.message);
903
- return { exitCode: 1, result: err.message, isError: true };
923
+ // Bad --mcp-config / MCP wiring is a CONFIG error, not a run failure.
924
+ return {
925
+ exitCode: HEADLESS_EXIT_CODES.CONFIG_ERROR,
926
+ result: err.message,
927
+ isError: true,
928
+ };
904
929
  }
905
930
  }
906
931
 
@@ -943,7 +968,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
943
968
  writeErr(`Error: ${err.message}\n`);
944
969
  if (mcp?.mcpClient) await mcp.mcpClient.disconnectAll().catch(() => {});
945
970
  emitHeadlessError(err.message);
946
- return { exitCode: 1, result: err.message, isError: true };
971
+ // A bad --permission-prompt-tool reference is a CONFIG error.
972
+ return {
973
+ exitCode: HEADLESS_EXIT_CODES.CONFIG_ERROR,
974
+ result: err.message,
975
+ isError: true,
976
+ };
947
977
  }
948
978
  if (approvalGate && typeof approvalGate.setConfirmer === "function") {
949
979
  approvalGate.setConfirmer(
@@ -1175,11 +1205,32 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1175
1205
  emitStream({
1176
1206
  type: "system",
1177
1207
  subtype: "init",
1208
+ // Deterministic-headless manifest (gap-analysis 2026-07-11): protocol
1209
+ // version + persistence + live sources + policy/tool digests so CI can
1210
+ // assert the run shape. Mirrors agent-sdk PROTOCOL_VERSION.
1211
+ protocol_version: STREAM_PROTOCOL_VERSION,
1178
1212
  session_id: sessionId,
1213
+ session_persistence: persist,
1179
1214
  model,
1180
1215
  provider,
1181
1216
  permission_mode: options.permissionMode || "default",
1182
1217
  tools: enabledToolNames,
1218
+ tools_hash: computeToolsHash(enabledToolNames),
1219
+ policy_digest: computePolicyDigest({
1220
+ permissionMode: options.permissionMode,
1221
+ allowedTools: options.allowedTools,
1222
+ disallowedTools: options.disallowedTools,
1223
+ permissionRules,
1224
+ }),
1225
+ loaded_sources: buildLoadedSources({
1226
+ permissionRules,
1227
+ settingsHooks,
1228
+ mcp: Boolean(mcp),
1229
+ enabledToolNames,
1230
+ }),
1231
+ // True isolation level for tool subprocesses: os-sandbox (bwrap) /
1232
+ // container (docker) / policy-only (no sandbox — rules are pre-execution).
1233
+ isolation_level: isolationLevel(options.sandbox),
1183
1234
  max_turns: budget.limit,
1184
1235
  resumed_from: resumeId,
1185
1236
  history_messages: history.length,
@@ -1471,7 +1522,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1471
1522
  } else {
1472
1523
  writeErr(`Error: ${message}\n`);
1473
1524
  }
1474
- return { exitCode: 1, result: message, isError: true };
1525
+ // Provider/transport failures get their own exit code (5) so CI can tell
1526
+ // "the model call failed" from "the run itself errored" (1).
1527
+ return { exitCode: classifyLoopError(err), result: message, isError: true };
1475
1528
  } finally {
1476
1529
  // Drop the signal handlers first — a normal return must not leave a
1477
1530
  // process-wide SIGINT/SIGTERM listener behind (a later Ctrl-C would wrongly
@@ -1739,7 +1792,13 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1739
1792
  }
1740
1793
  }
1741
1794
 
1742
- return { exitCode: isError ? 1 : 0, result: finalText, isError };
1795
+ // Exit-code taxonomy: max-turns → 3, cost cap → 4 (both still non-zero, so
1796
+ // "any failure" checks keep working; scripts can now tell exhaustion apart).
1797
+ return {
1798
+ exitCode: exitCodeForEndReason(endReason, isError),
1799
+ result: finalText,
1800
+ isError,
1801
+ };
1743
1802
  }
1744
1803
 
1745
1804
  function buildResultEnvelope({