chainlesschain 0.162.176 → 0.162.177

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 (221) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-BDLu5Elz.js → AIOps-DT-VPWuN.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-DH5us-CK.js → ActionButton-DyOreOVN.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-BZ0u8IFG.js → Analytics-DslNsKux.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-Duu8xR14.js → AppLayout-BNJJAYME.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-Br2YBbh_.js → Artifacts-DoaAtEcY.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-C3C6a482.js → Audit-DPG3WdJ9.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-CzHvebcj.js → BackgroundAgents-C_JO6R5G.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DZNHYDFd.js → Backup-Cv3BooyX.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-VRiC4fIx.js → BaseInput-D2uQXWu-.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-Cm08WWAD.js → Chat-B4Vczyf3.js} +4 -4
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-DE6reP99.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-DtByk7d7.js → Checkbox-qTgk4VeP.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-CphXXOfD.js → Codegen-DlLWcIzj.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-Hz86TnLR.js → Col-DNO73qp7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-HP03ltpD.js → Community-vRDNpc4j.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-B_N1mqQz.js → Compact-CEWtIXni.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CVztRpi8.js → Compliance-KgYC9Fxi.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-wUVOyZih.js → Cowork-zj5wvkpT.js} +4 -4
  20. package/src/assets/web-panel/assets/{Cron-DW5TLJKw.js → Cron-BLDoCozU.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-CrAFGhWH.js → Crosschain-BYnff4VY.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-pA-oD8ke.js → DID-C75VFsVm.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-CXrd5gAw.js → Dashboard-C4Gutni2.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-EweJcsek.js → Dropdown-B5dbO4Kx.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-C9xVLPG4.js → EmailListRenderer-BDipZtHJ.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CDcEEqlu.js → FamilyGuardDashboard-DmIzt8jj.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-DtZda9A_.js → Federation-D9QOS-uW.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CiYdcVz3.js → FormItemContext-B47HRwAm.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-DA13uwA0.js → GenericCardRenderer-3R4mXmgV.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DzRhZD1O.js → Git-DrNXZf1C.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-D5RMgOSb.js → Governance-BGd7JR98.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BgrPfSNk.js → Inference-D-2he1ed.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DzjnD571.js → KnowledgeGraph-C0sHIbK5.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-BhWzVDtN.js → Logs-DiBQO-jL.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-BDape9cx.js → MarkdownRenderer-DL_5eV2D.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-DJtL5GV7.js → Marketplace-VR59OdrC.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-CZcQygI7.js → McpTools-DrPzwSd3.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-DUWSDUUu.js → Memory-CBgKALwQ.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BTwq2WKY.js → MobileBridge-pQ9Tn-Mn.js} +1 -1
  40. package/src/assets/web-panel/assets/MobileProjects-mASB6jyj.js +1 -0
  41. package/src/assets/web-panel/assets/{Mtc-BiGugEQm.js → Mtc-DTMgE7HC.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-DY7a6gUe.js → MtcAudit-CwTnCtiL.js} +2 -2
  43. package/src/assets/web-panel/assets/{Multisig-BQbDu_w7.js → Multisig-ngm6WU8f.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CM2wXTLv.js → NLProgramming-4YO4Qww9.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-DI6gGs1v.js → Notes-DP1k45mF.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-BsZOLWAB.js → NotificationSettings-r2H8yPKb.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-C48mu09U.js → OrderTableRenderer-CoM_Zw0J.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-Cds0_tXr.js → Organization-DrO7jRWS.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-WunYMD87.js → Overflow-Cnwu4i4t.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-Bo6j4DDv.js → P2P-zi-cDwA_.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Bh2XPD5f.js → PdhVaultBrowser-DBEryDv7.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-EMvMMC8N.js → Permissions-lqXK2C3x.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-AX3ypUDV.js → PersonalDataHub-b63T3HJM.js} +2 -2
  54. package/src/assets/web-panel/assets/{Pipeline-BOx8HOgL.js → Pipeline-Kep5KAGW.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-tBeTVQVM.js → Privacy-CHdvOAh1.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-CVYg1W4M.js → ProjectInit-BhKfdwe9.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-Dvt5I7y1.js → ProjectSettings-Yavk9K8A.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-Cc7FC9-e.js → Projects-CN8E_5Mq.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-Ct8xqY-E.js → Providers-Bfym6SQn.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-Cni8Ooja.js → QrScannerModal-CLSQcrlR.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-BJVLKdxr.js → QuickAsk-VPa2WKQN.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-DPG8Rbbm.js → Recommend-CGXR8jVU.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-DsdR7dCt.js → RemoteSession-C_20YfMB.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-Csg1YM-b.js → Reputation-awZh68UV.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-D9DoFoEf.js → Row-Ctb4oiYN.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-BsvKrXMS.js → RssFeed-D3sdjvUV.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-DFUStfgQ.js → Search-C-zfA4kT.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-ILg1zxdK.js → Security-D9XlmHA3.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-Dd41PCaY.js → Services-C3UKnr41.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-Bzo1cN80.js → Skeleton-BQxagZfF.js} +1 -1
  71. package/src/assets/web-panel/assets/Skills-q6eb6KPZ.js +1 -0
  72. package/src/assets/web-panel/assets/{Sla-jl7UTiRY.js → Sla-DveENvek.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-BePa-RF6.js → SpeechSettings-BFjXLNgF.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-DiqqDKGZ.js → SyncSettings-BpHgbaP9.js} +2 -2
  75. package/src/assets/web-panel/assets/Tasks-DvepRb8-.js +1 -0
  76. package/src/assets/web-panel/assets/{Templates-JiDeI06L.js → Templates-DEiaoyve.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-hhgI6zwS.js → Tenant-ITg774nY.js} +1 -1
  78. package/src/assets/web-panel/assets/Terminal-D3ZBcvnb.js +3 -0
  79. package/src/assets/web-panel/assets/{TimelineRenderer-B8uB5Llk.js → TimelineRenderer-BsLU6JjU.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-C3b_6r2z.js → Tokens-Cb5Pquc9.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-tIP7HKVe.js → Trigger-Dwfy-m9N.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-vjoc11vJ.js → Trust-CnlSRGG0.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-DUPBnGuH.js → UkeySign-Y4TlvKVo.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-CBvhUY5T.js → VideoEditing-BpKLtTTO.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-DUaQ0uA5.js → Wallet-LLBzIq8x.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-DllSivjE.js → WebAuthn-BeSRiusP.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-xc8D3uO6.js → WorkflowEditor-BK_l1tXO.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-BVicU7oA.js → chat-DYd-X7Wg.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-DJzLmhLm.js → colors-C9uip71j.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-BvYRfThE.js → compact-item-JBrfjUP6.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DGXxCBKR.js → createContext-D03fbuiq.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-B8LQ8leS.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-SBDJB1y4.js → hasIn-DLQOR6l-.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-MjC4G09d.js → index-5YN7F5bO.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-Dm_77jgR.js → index-6GuLRpBQ.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CtwqO5qo.js → index-B0X76LjX.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DRfiXB_p.js → index-B46YcgsV.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-VMfwIH5G.js → index-BNCdRmWf.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-hxTODbM1.js → index-BYv-LWdy.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DMarmfrv.js → index-Ba-Ps_AJ.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-xfluRkCT.js → index-BcBZwlnG.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BYqz4Wrr.js → index-BdH9l8wl.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BO1itZaY.js → index-BfOs_bmg.js} +3 -3
  104. package/src/assets/web-panel/assets/index-Bh8BPtqR.js +1 -0
  105. package/src/assets/web-panel/assets/{index-Cf-O_g_8.js → index-BnQgRjsm.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CKyEivf8.js → index-BpYKLrUT.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CoJAO1Lm.js → index-BuNFCZCx.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-1SdDS6lR.js → index-ByHO3SqZ.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DnjPdvR6.js → index-C2zmOsyD.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Bf-ctERC.js → index-CChQBM1d.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DCdRAgjy.js → index-CChaISMb.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Crk5NTb0.js → index-CILVyK3b.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-9gdI7uUW.js → index-CL0ixCxk.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BJZf9DhV.js → index-CS63r8h3.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DCqRS6da.js → index-CVZWiUE_.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DonCnfMr.js → index-Ce0Bf1YF.js} +1 -1
  117. package/src/assets/web-panel/assets/index-CeVrHLzZ.js +1 -0
  118. package/src/assets/web-panel/assets/{index-CloCgBUR.js → index-Ck17i0OD.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-wcCL-miV.js → index-Cpn19c9k.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BTrBGBJs.js → index-CqWk1FLG.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-e4fXH_WO.js → index-CwoDpKzW.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DvUTDYXX.js → index-D-1SqEpQ.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CdGY9P8a.js → index-D4UY5Z60.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DKrvvWm4.js → index-D8KvuDz0.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-lpaGoTH3.js → index-DNMAAUVk.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-YJkzy8ZF.js → index-DYLZY4uh.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-FxZzRyE1.js → index-DaokIHt3.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DHVLJ8q0.js → index-Q7mmL6w4.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Cs2rmLFt.js → index-SO6lgMg0.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-z1ZylsLq.js → index-iahNhZwm.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-d5BVd-cL.js → index-l08afIbV.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D7HimK0M.js → index-rIxxfdTN.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-C1zO1KnY.js → initDefaultProps-CG9z1c6w.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-CWLtEGmC.js → motion-B1Ky7Zff.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-DzD_C3Vm.js → move-DME8X2P1.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-D880PYJl.js → mtc-parser-cuJYSWB7.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-CFR_z2ov.js → omit-UI_EE0uZ.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-srIhgrSC.js → pickAttrs-BIoE_Z_V.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-C1rXpibP.js → placementArrow-B48-9HKN.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-C30gRcSS.js → responsiveObserve-D7x_GDgD.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-CvtKiMfV.js → slide-DjzC5_7m.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-DNHO7ITG.js → statusUtils-C6BIymhh.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-Dt_Sl-g4.js → styleChecker-B4dGrdD9.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Cjev42Gh.js → useFlexGapSupport-Bken4aNE.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-Baxglj2V.js → useFs-BMlqECqv.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-B4NkcLaP.js → usePersonalDataHub-DLdrfmMa.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-mIRkdT7o.js → vnode-CKJQmxa0.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-HzI5DlH_.js → zoom-CaZunuau.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/agenda.js +22 -6
  151. package/src/commands/agent.js +3 -3
  152. package/src/commands/background-session.js +11 -4
  153. package/src/commands/batch.js +79 -27
  154. package/src/commands/changelog.js +15 -4
  155. package/src/commands/eval.js +21 -6
  156. package/src/commands/hook.js +2 -2
  157. package/src/commands/loop.js +9 -2
  158. package/src/commands/skill.js +2 -0
  159. package/src/commands/statusline.js +3 -3
  160. package/src/data/changelog.json +293 -51
  161. package/src/harness/background-task-manager.js +18 -6
  162. package/src/harness/background-task-worker.js +11 -18
  163. package/src/harness/mcp-client.js +9 -15
  164. package/src/harness/worktree-isolator.js +18 -21
  165. package/src/lib/agent-core.js +5 -0
  166. package/src/lib/agent-ipc-bus.js +12 -3
  167. package/src/lib/agent-team/team-worktree.js +28 -6
  168. package/src/lib/agent-worktree.js +20 -19
  169. package/src/lib/async-hook-supervisor.cjs +134 -24
  170. package/src/lib/async-hook-supervisor.js +47 -0
  171. package/src/lib/background-agent-supervisor.js +35 -12
  172. package/src/lib/background-task-manager.js +5 -1
  173. package/src/lib/changelog.js +57 -0
  174. package/src/lib/chrome-connector.js +6 -2
  175. package/src/lib/claude-code-bridge.js +24 -8
  176. package/src/lib/cli-anything-bridge.js +82 -25
  177. package/src/lib/doctor-checkup.js +18 -6
  178. package/src/lib/eval/tasks.js +25 -31
  179. package/src/lib/hook-runner.cjs +71 -36
  180. package/src/lib/hook-runner.js +55 -0
  181. package/src/lib/host-adb-bridge.js +18 -3
  182. package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
  183. package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
  184. package/src/lib/lsp/benchmark.js +20 -4
  185. package/src/lib/lsp/lsp-client.js +6 -4
  186. package/src/lib/lsp/lsp-server-registry.js +0 -2
  187. package/src/lib/orchestrator.js +8 -2
  188. package/src/lib/packer/pack-update-applier.js +14 -2
  189. package/src/lib/packer/smoke-runner.js +18 -5
  190. package/src/lib/paths.js +1 -1
  191. package/src/lib/plugin-monitor-supervisor.js +20 -13
  192. package/src/lib/plugin-runtime/install.js +10 -3
  193. package/src/lib/repl-bang-memorize.js +10 -2
  194. package/src/lib/repl-goal.js +19 -2
  195. package/src/lib/settings-hook-events.cjs +13 -8
  196. package/src/lib/settings-hook-events.js +20 -0
  197. package/src/lib/skill-packs/generator.js +18 -9
  198. package/src/lib/skill-process-broker.js +71 -0
  199. package/src/lib/slash-commands.js +10 -2
  200. package/src/lib/status-line.cjs +28 -7
  201. package/src/lib/status-line.js +33 -0
  202. package/src/repl/agent-repl.js +48 -43
  203. package/src/runtime/agent-core.js +133 -49
  204. package/src/runtime/headless-runner.js +25 -10
  205. package/src/runtime/headless-stream.js +74 -4
  206. package/src/runtime/session-slash-commands.js +506 -0
  207. package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
  208. package/src/skills/video-editing/extractors/video-extractor.js +13 -3
  209. package/src/skills/video-editing/media-process.js +20 -0
  210. package/src/skills/video-editing/render/audio-mix.js +13 -3
  211. package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
  212. package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
  213. package/src/workers/background-agent-worker.js +6 -2
  214. package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +0 -1
  215. package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +0 -1
  216. package/src/assets/web-panel/assets/Skills-BDHh17P0.js +0 -1
  217. package/src/assets/web-panel/assets/Tasks-DYQ_6lxj.js +0 -1
  218. package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +0 -3
  219. package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +0 -1
  220. package/src/assets/web-panel/assets/index-B7nuIywP.js +0 -1
  221. package/src/assets/web-panel/assets/index-ycwAfC-i.js +0 -1
@@ -1,4 +1,3 @@
1
- import { spawn, spawnSync } from "node:child_process";
2
1
  import {
3
2
  closeSync,
4
3
  existsSync,
@@ -21,6 +20,7 @@ import {
21
20
  finishAgentWorktree,
22
21
  validateAgentWorktree,
23
22
  } from "./agent-worktree.js";
23
+ import executionBroker from "./process-execution-broker/index.js";
24
24
 
25
25
  export const DEFAULT_HEARTBEAT_INTERVAL_MS = 5000;
26
26
  export const DEFAULT_HEARTBEAT_STALE_MS = 120000;
@@ -42,6 +42,16 @@ export const PID_IDENTITY_TOLERANCE_MS = 60000;
42
42
  const START_TIME_CACHE_TTL_MS = 10000;
43
43
  const _startTimeCache = new Map();
44
44
 
45
+ function runSupervisorCommand(file, args, options, origin) {
46
+ return _deps.spawnSync(file, args, {
47
+ ...options,
48
+ origin,
49
+ policy: "allow",
50
+ scope: "background-agent",
51
+ shell: false,
52
+ });
53
+ }
54
+
45
55
  /** CIM_DATETIME (`20260711120000.500000+480`) → epoch ms, null when unparseable. */
46
56
  export function parseCimDateToMs(raw) {
47
57
  const m =
@@ -77,7 +87,7 @@ function defaultReadProcessStartTimeMs(pid) {
77
87
  // wmic first (fast, ~100-300ms); PowerShell CIM as fallback (wmic is
78
88
  // removed from recent Windows 11 builds).
79
89
  try {
80
- const r = spawnSync(
90
+ const r = runSupervisorCommand(
81
91
  "wmic",
82
92
  [
83
93
  "process",
@@ -88,6 +98,7 @@ function defaultReadProcessStartTimeMs(pid) {
88
98
  "/value",
89
99
  ],
90
100
  { windowsHide: true, encoding: "utf8", timeout: 5000 },
101
+ "background-agent:process-start-time",
91
102
  );
92
103
  if (!r.error && r.status === 0) {
93
104
  const m = /CreationDate=([^\r\n]+)/.exec(r.stdout || "");
@@ -101,10 +112,11 @@ function defaultReadProcessStartTimeMs(pid) {
101
112
  const script =
102
113
  `$p = Get-CimInstance Win32_Process -Filter 'ProcessId=${target}' -ErrorAction SilentlyContinue; ` +
103
114
  "if ($p -and $p.CreationDate) { [DateTimeOffset]::new($p.CreationDate).ToUnixTimeMilliseconds() }";
104
- const r = spawnSync(
115
+ const r = runSupervisorCommand(
105
116
  "powershell",
106
117
  ["-NoProfile", "-NonInteractive", "-Command", script],
107
118
  { windowsHide: true, encoding: "utf8", timeout: 10000 },
119
+ "background-agent:process-start-time",
108
120
  );
109
121
  if (!r.error && r.status === 0) {
110
122
  const n = Number(String(r.stdout || "").trim());
@@ -118,10 +130,15 @@ function defaultReadProcessStartTimeMs(pid) {
118
130
  // POSIX: `ps -o lstart=` gives an absolute start timestamp on Linux + macOS
119
131
  // (procps and BSD ps both support it; busybox ps does not → null → open).
120
132
  try {
121
- const r = spawnSync("ps", ["-o", "lstart=", "-p", String(target)], {
122
- encoding: "utf8",
123
- timeout: 5000,
124
- });
133
+ const r = runSupervisorCommand(
134
+ "ps",
135
+ ["-o", "lstart=", "-p", String(target)],
136
+ {
137
+ encoding: "utf8",
138
+ timeout: 5000,
139
+ },
140
+ "background-agent:process-start-time",
141
+ );
125
142
  if (!r.error && r.status === 0) {
126
143
  const t = Date.parse(String(r.stdout || "").trim());
127
144
  if (Number.isFinite(t) && t > 0) return t;
@@ -147,13 +164,14 @@ function defaultKillProcessTree(pid, signal = "SIGKILL") {
147
164
  if (target === process.pid) return false;
148
165
  try {
149
166
  if (process.platform === "win32") {
150
- const r = _deps.spawnSync(
167
+ const r = runSupervisorCommand(
151
168
  "taskkill",
152
169
  ["/PID", String(target), "/T", "/F"],
153
170
  {
154
171
  windowsHide: true,
155
172
  encoding: "utf8",
156
173
  },
174
+ "background-agent:process-tree-kill",
157
175
  );
158
176
  return !r.error && r.status === 0;
159
177
  }
@@ -170,8 +188,8 @@ function defaultKillProcessTree(pid, signal = "SIGKILL") {
170
188
  }
171
189
 
172
190
  export const _deps = {
173
- spawn,
174
- spawnSync,
191
+ spawn: executionBroker.spawn.bind(executionBroker),
192
+ spawnSync: executionBroker.spawnSync.bind(executionBroker),
175
193
  // Single POSIX signal seam: every kill this module issues goes through here
176
194
  // so tests can stub it — a bare `process.kill` is NOT interceptable and a
177
195
  // fixture recording a live pid would eat a REAL signal (the shard-2/4
@@ -741,7 +759,7 @@ export function resumeBackgroundAgent(id, prompt, options = {}) {
741
759
  }
742
760
 
743
761
  /**
744
- * Fail fast on an unusable cwd. Without this, spawn() surfaces a bad cwd as
762
+ * Fail fast on an unusable cwd. Without this, process launch surfaces a bad cwd as
745
763
  * an ASYNC 'error' event on the detached child — which nothing listened to
746
764
  * (uncaught exception with no context) — and the pre-written state/job files
747
765
  * stayed behind as a phantom "running" session. Deleted, file-replaced, and
@@ -826,6 +844,10 @@ export function launchBackgroundAgent({
826
844
  detached: true,
827
845
  stdio: "ignore",
828
846
  windowsHide: true,
847
+ origin: "background-agent:worker",
848
+ policy: "allow",
849
+ scope: "background-agent",
850
+ shell: false,
829
851
  });
830
852
  } catch (error) {
831
853
  rmSync(jobFile, { force: true });
@@ -922,13 +944,14 @@ export function stopBackgroundAgent(id) {
922
944
  return { ...lost, stopped: false };
923
945
  }
924
946
  if (process.platform === "win32") {
925
- const killed = _deps.spawnSync(
947
+ const killed = runSupervisorCommand(
926
948
  "taskkill",
927
949
  ["/PID", String(state.pid), "/T", "/F"],
928
950
  {
929
951
  windowsHide: true,
930
952
  encoding: "utf8",
931
953
  },
954
+ "background-agent:stop-tree",
932
955
  );
933
956
  if (killed.error || (killed.status !== 0 && isProcessAlive(state.pid))) {
934
957
  throw new Error(
@@ -1 +1,5 @@
1
- export { TaskStatus, BackgroundTaskManager } from "../harness/background-task-manager.js";
1
+ export {
2
+ _deps,
3
+ TaskStatus,
4
+ BackgroundTaskManager,
5
+ } from "../harness/background-task-manager.js";
@@ -91,6 +91,41 @@ export function compareSemver(a, b) {
91
91
  return 0;
92
92
  }
93
93
 
94
+ /**
95
+ * Whether a parsed changelog documents an exact CLI package version.
96
+ *
97
+ * A product block can cover more than one CLI release (notably the root
98
+ * `Unreleased` block), so check both its primary `cliVersion` and the complete
99
+ * `cliVersions` set. This is also the publish-time stale-artifact guard.
100
+ */
101
+ export function hasCliVersion(releases, version) {
102
+ if (!version || !Array.isArray(releases)) return false;
103
+ return releases.some(
104
+ (release) =>
105
+ release?.cliVersion === version ||
106
+ (Array.isArray(release?.cliVersions) &&
107
+ release.cliVersions.includes(version)),
108
+ );
109
+ }
110
+
111
+ /** Highest exact CLI version documented by the parsed release list. */
112
+ export function latestCliVersion(releases) {
113
+ if (!Array.isArray(releases)) return null;
114
+ const versions = releases.flatMap((release) => {
115
+ const covered = Array.isArray(release?.cliVersions)
116
+ ? release.cliVersions
117
+ : [];
118
+ return release?.cliVersion ? [...covered, release.cliVersion] : covered;
119
+ });
120
+ return versions.length === 0
121
+ ? null
122
+ : versions.reduce(
123
+ (latest, version) =>
124
+ compareSemver(version, latest) > 0 ? version : latest,
125
+ versions[0],
126
+ );
127
+ }
128
+
94
129
  /**
95
130
  * Parse a raw CHANGELOG.md string into CLI-focused release entries.
96
131
  *
@@ -135,6 +170,28 @@ export function parseChangelog(md) {
135
170
  const sections = extractCliSections(block.lines, block.header);
136
171
  if (!sections) continue;
137
172
 
173
+ // The root changelog keeps multiple still-unreleased CLI versions as
174
+ // sibling `###` sections. Treating the whole `## [Unreleased]` block as
175
+ // one record collapses many CLI releases into a single entry and makes
176
+ // `-n 5` mean five product blocks instead of five CLI versions.
177
+ if (parsed.version.toLowerCase() === "unreleased") {
178
+ for (const section of sections) {
179
+ const sectionText = `${section.heading}\n${section.body}`;
180
+ const sectionVersions = extractCliVersions(sectionText);
181
+ if (!sectionVersions.primary) continue;
182
+ const dateMatch = sectionText.match(/\b(\d{4}-\d{2}-\d{2})\b/);
183
+ releases.push({
184
+ productVersion: null,
185
+ cliVersion: sectionVersions.primary,
186
+ cliVersions: sectionVersions.all.sort(compareSemver),
187
+ date: dateMatch ? dateMatch[1] : null,
188
+ title: "",
189
+ sections: [section],
190
+ });
191
+ }
192
+ continue;
193
+ }
194
+
138
195
  releases.push({
139
196
  productVersion: parsed.version,
140
197
  cliVersion: primary,
@@ -26,11 +26,11 @@
26
26
  * Chrome when done. This is the same trade Claude-Code's Chrome connector
27
27
  * makes.
28
28
  */
29
- import { spawn } from "child_process";
30
29
  import fs from "fs";
31
30
  import os from "os";
32
31
  import path from "path";
33
32
  import http from "http";
33
+ import executionBroker from "./process-execution-broker/index.js";
34
34
 
35
35
  export const DEFAULT_CDP_PORT = 9222;
36
36
 
@@ -69,7 +69,7 @@ export const DEFAULT_DOM_CAP = 150000;
69
69
 
70
70
  const _deps = {
71
71
  fs,
72
- spawn,
72
+ spawn: executionBroker.spawn.bind(executionBroker),
73
73
  homedir: () => os.homedir(),
74
74
  platform: () => process.platform,
75
75
  env: () => process.env,
@@ -215,6 +215,10 @@ export function launchChrome(opts = {}) {
215
215
  detached: true,
216
216
  stdio: "ignore",
217
217
  windowsHide: false,
218
+ origin: "chrome-connector:launch",
219
+ policy: "allow",
220
+ scope: "browser",
221
+ shell: false,
218
222
  });
219
223
  child.unref();
220
224
  return { ok: true, executable, args, pid: child.pid };
@@ -13,11 +13,14 @@
13
13
  * ], { cwd: "/path/to/project" });
14
14
  */
15
15
 
16
- import { spawn, execSync } from "child_process";
17
16
  import { EventEmitter } from "events";
17
+ import executionBroker from "./process-execution-broker/index.js";
18
18
 
19
19
  /* ---------- _deps injection (Vitest CJS mock pattern) ---------- */
20
- export const _deps = { spawn, execSync };
20
+ export const _deps = {
21
+ spawn: executionBroker.spawn.bind(executionBroker),
22
+ execSync: executionBroker.execSync.bind(executionBroker),
23
+ };
21
24
 
22
25
  // ─── Agent status constants ───────────────────────────────────────
23
26
 
@@ -36,6 +39,19 @@ export const AGENT_STATUS = {
36
39
  // only thing _parseStreamJson needs — is at the end.
37
40
  export const MAX_AGENT_OUTPUT_BYTES = 32 * 1024 * 1024;
38
41
 
42
+ function detectCliVersion(command) {
43
+ return _deps
44
+ .execSync(`${command} --version`, {
45
+ encoding: "utf-8",
46
+ timeout: 5000,
47
+ origin: `claude-code-bridge:detect-${command}`,
48
+ policy: "allow",
49
+ scope: "orchestrator",
50
+ shell: true,
51
+ })
52
+ .trim();
53
+ }
54
+
39
55
  // ─── Detection ───────────────────────────────────────────────────
40
56
 
41
57
  /**
@@ -44,9 +60,7 @@ export const MAX_AGENT_OUTPUT_BYTES = 32 * 1024 * 1024;
44
60
  */
45
61
  export function detectClaudeCode() {
46
62
  try {
47
- const version = _deps
48
- .execSync("claude --version", { encoding: "utf-8", timeout: 5000 })
49
- .trim();
63
+ const version = detectCliVersion("claude");
50
64
  return { found: true, version };
51
65
  } catch (_err) {
52
66
  return { found: false };
@@ -59,9 +73,7 @@ export function detectClaudeCode() {
59
73
  */
60
74
  export function detectCodex() {
61
75
  try {
62
- const version = _deps
63
- .execSync("codex --version", { encoding: "utf-8", timeout: 5000 })
64
- .trim();
76
+ const version = detectCliVersion("codex");
65
77
  return { found: true, version };
66
78
  } catch (_err) {
67
79
  return { found: false };
@@ -152,6 +164,10 @@ export class ClaudeCodeAgent extends EventEmitter {
152
164
  cwd,
153
165
  env: { ...process.env },
154
166
  windowsHide: true,
167
+ origin: "claude-code-bridge:agent",
168
+ policy: "allow",
169
+ scope: "orchestrator",
170
+ shell: false,
155
171
  });
156
172
  this._proc = proc;
157
173
 
@@ -8,13 +8,27 @@
8
8
  * that the existing 4-layer skill-loader picks up automatically.
9
9
  */
10
10
 
11
- import { execSync } from "child_process";
12
11
  import fs from "fs";
13
12
  import path from "path";
14
13
  import { getElectronUserDataDir } from "./paths.js";
14
+ import executionBroker from "./process-execution-broker/index.js";
15
15
 
16
16
  /* ---------- _deps injection (Vitest CJS mock pattern) ---------- */
17
- export const _deps = { execSync, fs, path };
17
+ export const _deps = {
18
+ execFileSync: executionBroker.execFileSync.bind(executionBroker),
19
+ fs,
20
+ path,
21
+ };
22
+
23
+ function execCliAnything(file, args, options, origin) {
24
+ return _deps.execFileSync(file, args, {
25
+ ...options,
26
+ origin,
27
+ policy: "allow",
28
+ scope: "cli-anything",
29
+ shell: false,
30
+ });
31
+ }
18
32
 
19
33
  /* ----------------------------------------------------------------
20
34
  * Database helpers
@@ -55,13 +69,16 @@ export function detectPython() {
55
69
 
56
70
  for (const cmd of candidates) {
57
71
  try {
58
- const ver = _deps
59
- .execSync(`${cmd} --version`, {
72
+ const ver = execCliAnything(
73
+ cmd,
74
+ ["--version"],
75
+ {
60
76
  encoding: "utf-8",
61
77
  timeout: 10000,
62
78
  stdio: ["pipe", "pipe", "pipe"],
63
- })
64
- .trim();
79
+ },
80
+ "cli-anything:detect-python",
81
+ ).trim();
65
82
  const match = ver.match(/Python\s+([\d.]+)/i);
66
83
  if (match) {
67
84
  return { found: true, command: cmd, version: match[1] };
@@ -82,11 +99,16 @@ export function detectCliAnything() {
82
99
  if (!py.found) return { installed: false };
83
100
 
84
101
  try {
85
- const out = _deps.execSync(`${py.command} -m pip show cli-anything`, {
86
- encoding: "utf-8",
87
- timeout: 15000,
88
- stdio: ["pipe", "pipe", "pipe"],
89
- });
102
+ const out = execCliAnything(
103
+ py.command,
104
+ ["-m", "pip", "show", "cli-anything"],
105
+ {
106
+ encoding: "utf-8",
107
+ timeout: 15000,
108
+ stdio: ["pipe", "pipe", "pipe"],
109
+ },
110
+ "cli-anything:detect-package",
111
+ );
90
112
  const verMatch = out.match(/Version:\s*([\d.]+)/i);
91
113
  return {
92
114
  installed: true,
@@ -102,11 +124,16 @@ export function detectCliAnything() {
102
124
  * Install CLI-Anything via pip.
103
125
  */
104
126
  export function installCliAnything(pythonCmd) {
105
- _deps.execSync(`${pythonCmd} -m pip install cli-anything`, {
106
- encoding: "utf-8",
107
- timeout: 120000,
108
- stdio: "inherit",
109
- });
127
+ execCliAnything(
128
+ pythonCmd,
129
+ ["-m", "pip", "install", "cli-anything"],
130
+ {
131
+ encoding: "utf-8",
132
+ timeout: 120000,
133
+ stdio: "inherit",
134
+ },
135
+ "cli-anything:install",
136
+ );
110
137
  }
111
138
 
112
139
  /* ----------------------------------------------------------------
@@ -152,11 +179,16 @@ export function scanPathForTools() {
152
179
  export function parseToolHelp(command) {
153
180
  let helpText;
154
181
  try {
155
- helpText = _deps.execSync(`${command} --help`, {
156
- encoding: "utf-8",
157
- timeout: 15000,
158
- stdio: ["pipe", "pipe", "pipe"],
159
- });
182
+ helpText = execCliAnything(
183
+ command,
184
+ ["--help"],
185
+ {
186
+ encoding: "utf-8",
187
+ timeout: 15000,
188
+ stdio: ["pipe", "pipe", "pipe"],
189
+ },
190
+ "cli-anything:tool-help",
191
+ );
160
192
  } catch (err) {
161
193
  const raw = err.stdout || err.stderr || "";
162
194
  helpText = typeof raw === "string" ? raw : raw.toString("utf-8");
@@ -252,19 +284,44 @@ Pass the subcommand and arguments as plain text input:
252
284
  */
253
285
  export function _generateHandlerJs(name, command) {
254
286
  return `"use strict";
255
- const { execSync } = require("child_process");
287
+ const CLI_COMMAND = ${JSON.stringify(command)};
288
+
289
+ function parseArgs(input) {
290
+ const args = [];
291
+ let current = "";
292
+ let inSingle = false;
293
+ let inDouble = false;
294
+ for (const ch of input.trim()) {
295
+ if (ch === "'" && !inDouble) { inSingle = !inSingle; continue; }
296
+ if (ch === '"' && !inSingle) { inDouble = !inDouble; continue; }
297
+ if (/\\s/.test(ch) && !inSingle && !inDouble) {
298
+ if (current) { args.push(current); current = ""; }
299
+ continue;
300
+ }
301
+ current += ch;
302
+ }
303
+ if (inSingle || inDouble) return null;
304
+ if (current) args.push(current);
305
+ return args;
306
+ }
256
307
 
257
308
  module.exports = {
258
309
  async execute(task, context) {
259
310
  const input = (task?.params?.input || task?.action || "").trim();
260
311
  if (!input) return { success: false, error: "No input provided" };
261
- // Security: input is interpolated into a shell command, so reject shell
262
- // metacharacters to prevent command injection from untrusted skill input.
312
+ // Keep the historical shell-character guard for generated-handler
313
+ // compatibility even though the Broker now receives literal argv.
263
314
  if (/[;&|\`$<>()\\n\\r]/.test(input)) {
264
315
  return { success: false, error: "Input contains unsafe shell characters; refused." };
265
316
  }
317
+ const args = parseArgs(input);
318
+ if (!args) return { success: false, error: "Input contains an unmatched quote; refused." };
319
+ const processBroker = context?.processBroker;
320
+ if (!processBroker || typeof processBroker.runFileSync !== "function") {
321
+ return { success: false, error: "Process Broker unavailable for skill execution." };
322
+ }
266
323
  try {
267
- const output = execSync(\`${command} \${input}\`, {
324
+ const output = processBroker.runFileSync(CLI_COMMAND, args, {
268
325
  encoding: "utf-8",
269
326
  timeout: 60000,
270
327
  cwd: context?.projectRoot || process.cwd(),
@@ -23,9 +23,9 @@ import {
23
23
  statSync,
24
24
  rmSync,
25
25
  } from "node:fs";
26
- import { execSync, spawnSync } from "node:child_process";
27
26
  import { join, basename } from "node:path";
28
27
  import { getHomeDir, getConfigPath } from "./paths.js";
28
+ import executionBroker from "./process-execution-broker/index.js";
29
29
  import {
30
30
  languageIdForFile,
31
31
  resolveServer,
@@ -59,8 +59,8 @@ export const _deps = {
59
59
  readFileSync,
60
60
  statSync,
61
61
  rmSync,
62
- execSync,
63
- spawnSync,
62
+ execFileSync: (...args) => executionBroker.execFileSync(...args),
63
+ spawnSync: (...args) => executionBroker.spawnSync(...args),
64
64
  now: () => Date.now(),
65
65
  };
66
66
 
@@ -549,10 +549,14 @@ async function worktreeSection(opts, deps) {
549
549
  try {
550
550
  const inRepo = (() => {
551
551
  try {
552
- deps.execSync("git rev-parse --is-inside-work-tree", {
552
+ deps.execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
553
553
  cwd,
554
554
  encoding: "utf-8",
555
555
  stdio: ["ignore", "pipe", "ignore"],
556
+ origin: "doctor:git-worktree",
557
+ policy: "allow",
558
+ scope: "diagnostics",
559
+ shell: false,
556
560
  });
557
561
  return true;
558
562
  } catch {
@@ -570,10 +574,14 @@ async function worktreeSection(opts, deps) {
570
574
  );
571
575
  } else {
572
576
  const out =
573
- deps.execSync("git worktree prune --dry-run -v", {
577
+ deps.execFileSync("git", ["worktree", "prune", "--dry-run", "-v"], {
574
578
  cwd,
575
579
  encoding: "utf-8",
576
580
  stdio: ["ignore", "pipe", "ignore"],
581
+ origin: "doctor:git-worktree",
582
+ policy: "allow",
583
+ scope: "diagnostics",
584
+ shell: false,
577
585
  }) || "";
578
586
  const prunable = out.split("\n").filter((l) => l.trim()).length;
579
587
  if (prunable > 0) {
@@ -1138,10 +1146,14 @@ export async function runCheckupFixes(sections, opts = {}) {
1138
1146
  detail: `removed ${removed} file(s)`,
1139
1147
  });
1140
1148
  } else if (fix.id === "git-worktree-prune") {
1141
- deps.execSync("git worktree prune", {
1149
+ deps.execFileSync("git", ["worktree", "prune"], {
1142
1150
  cwd: opts.cwd || process.cwd(),
1143
1151
  encoding: "utf-8",
1144
1152
  stdio: ["ignore", "pipe", "ignore"],
1153
+ origin: "doctor:git-worktree-fix",
1154
+ policy: "allow",
1155
+ scope: "diagnostics",
1156
+ shell: false,
1145
1157
  });
1146
1158
  results.push({
1147
1159
  id: fix.id,
@@ -11,7 +11,24 @@
11
11
 
12
12
  import fs from "fs";
13
13
  import path from "path";
14
- import { execFileSync } from "node:child_process";
14
+ import executionBroker from "../process-execution-broker/index.js";
15
+
16
+ export const _deps = {
17
+ execFileSync: (...args) => executionBroker.execFileSync(...args),
18
+ };
19
+
20
+ function runTaskCheck(dir, script, options = {}) {
21
+ return _deps.execFileSync(process.execPath, [script], {
22
+ cwd: dir,
23
+ timeout: 10000,
24
+ stdio: ["ignore", "pipe", "pipe"],
25
+ ...options,
26
+ origin: "eval:task-check",
27
+ policy: "allow",
28
+ scope: "eval",
29
+ shell: false,
30
+ });
31
+ }
15
32
 
16
33
  function read(dir, rel) {
17
34
  try {
@@ -97,11 +114,8 @@ export const BUILTIN_TASKS = [
97
114
  // Objective check: it must parse AND print OK. Re-run in a child so we
98
115
  // score the actual behavior, not a heuristic on the source.
99
116
  try {
100
- const out = execFileSync(process.execPath, ["bug.js"], {
101
- cwd: dir,
117
+ const out = runTaskCheck(dir, "bug.js", {
102
118
  encoding: "utf8",
103
- timeout: 10000,
104
- stdio: ["ignore", "pipe", "pipe"], // capture stderr, don't inherit
105
119
  });
106
120
  return out.trim() === "OK"
107
121
  ? { pass: true, detail: "node bug.js prints OK" }
@@ -186,11 +200,8 @@ export const BUILTIN_TASKS = [
186
200
  };
187
201
  }
188
202
  try {
189
- const out = execFileSync(process.execPath, ["run-checks.mjs"], {
190
- cwd: dir,
203
+ const out = runTaskCheck(dir, "run-checks.mjs", {
191
204
  encoding: "utf8",
192
- timeout: 10000,
193
- stdio: ["ignore", "pipe", "pipe"],
194
205
  });
195
206
  return out.includes("ALL OK")
196
207
  ? { pass: true, detail: "test suite passes" }
@@ -243,11 +254,8 @@ export const BUILTIN_TASKS = [
243
254
  }
244
255
  // Behavior must be preserved: run main.js and check the output.
245
256
  try {
246
- const out = execFileSync(process.execPath, ["main.js"], {
247
- cwd: dir,
257
+ const out = runTaskCheck(dir, "main.js", {
248
258
  encoding: "utf8",
249
- timeout: 10000,
250
- stdio: ["ignore", "pipe", "pipe"],
251
259
  });
252
260
  return out.trim() === "6"
253
261
  ? { pass: true, detail: "renamed + behavior preserved" }
@@ -290,12 +298,7 @@ export const BUILTIN_TASKS = [
290
298
  if (read(dir, "verify.mjs") == null) {
291
299
  return { pass: false, detail: "verify.mjs not created" };
292
300
  }
293
- const run = () =>
294
- execFileSync(process.execPath, ["verify.mjs"], {
295
- cwd: dir,
296
- timeout: 10000,
297
- stdio: ["ignore", "pipe", "pipe"],
298
- });
301
+ const run = () => runTaskCheck(dir, "verify.mjs");
299
302
  // 1) The verifier must PASS against the correct implementation.
300
303
  try {
301
304
  run();
@@ -383,11 +386,8 @@ export const BUILTIN_TASKS = [
383
386
  };
384
387
  }
385
388
  try {
386
- const out = execFileSync(process.execPath, ["app.mjs"], {
387
- cwd: dir,
389
+ const out = runTaskCheck(dir, "app.mjs", {
388
390
  encoding: "utf8",
389
- timeout: 10000,
390
- stdio: ["ignore", "pipe", "pipe"],
391
391
  }).trim();
392
392
  return out === "Hello, Ada!\nHello, Bob!!!"
393
393
  ? { pass: true, detail: "signature migrated + callers updated" }
@@ -525,11 +525,8 @@ export const BUILTIN_TASKS = [
525
525
  };
526
526
  }
527
527
  try {
528
- const out = execFileSync(process.execPath, ["build.mjs"], {
529
- cwd: dir,
528
+ const out = runTaskCheck(dir, "build.mjs", {
530
529
  encoding: "utf8",
531
- timeout: 10000,
532
- stdio: ["ignore", "pipe", "pipe"],
533
530
  });
534
531
  return out.includes("BUILD OK")
535
532
  ? { pass: true, detail: "build links + passes" }
@@ -620,11 +617,8 @@ export const BUILTIN_TASKS = [
620
617
  return { pass: false, detail: "app.mjs does not use the new toTitle" };
621
618
  }
622
619
  try {
623
- const out = execFileSync(process.execPath, ["run.mjs"], {
624
- cwd: dir,
620
+ const out = runTaskCheck(dir, "run.mjs", {
625
621
  encoding: "utf8",
626
- timeout: 10000,
627
- stdio: ["ignore", "pipe", "pipe"],
628
622
  });
629
623
  return out.trim() === "OK"
630
624
  ? { pass: true, detail: "adapted to new API + manifest bumped" }