@iowarp/clio-coder 0.4.3 → 0.4.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 (340) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +1 -1
  3. package/dist/{acp-H2NGRPWO.js → acp-WNAYYF4F.js} +4 -5
  4. package/dist/{agents-TL5LLUQP.js → agents-3OKXHLOI.js} +33 -31
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-E5SW4HMS.js → auth-VKNNMGPU.js} +10 -11
  7. package/dist/{builtins-IA7V7FUC.js → builtins-WGALA46I.js} +4 -4
  8. package/dist/{chunk-F5JHEYZM.js → chunk-23L32XTI.js} +10 -7
  9. package/dist/{chunk-DWUOQKRU.js → chunk-25QBEXRS.js} +2 -2
  10. package/dist/{chunk-LLDJM5XK.js → chunk-26QSH3EJ.js} +2 -2
  11. package/dist/{chunk-N2Z7HLVY.js → chunk-2ASED4PZ.js} +10 -10
  12. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  13. package/dist/chunk-2DSOYNFC.js +108 -0
  14. package/dist/{chunk-LDJG7DW3.js → chunk-2ZSONWVL.js} +4 -4
  15. package/dist/{chunk-GI7YYQ3F.js → chunk-36CT5VVL.js} +324 -41
  16. package/dist/{chunk-4UVU7BJ5.js → chunk-3GY4F45V.js} +2 -2
  17. package/dist/{chunk-PUVDKJ2Y.js → chunk-3ODX73FK.js} +3 -5
  18. package/dist/{chunk-IUE3Y34X.js → chunk-3UNOLWNZ.js} +2 -2
  19. package/dist/{chunk-6PTFB5VS.js → chunk-3UUXNFEX.js} +8 -4
  20. package/dist/{chunk-2APPQIER.js → chunk-4M6Z5QVF.js} +4 -4
  21. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  22. package/dist/{chunk-JGRC33J2.js → chunk-54X7T7DK.js} +12 -3
  23. package/dist/{chunk-YQWYVTMC.js → chunk-5636DCO5.js} +4 -4
  24. package/dist/{chunk-7E7I3WLS.js → chunk-57XXR6DR.js} +23 -22
  25. package/dist/{chunk-7ZYNNDKC.js → chunk-5TUB6SLS.js} +2 -2
  26. package/dist/{chunk-VW6DOEDG.js → chunk-6OSVSQL5.js} +11 -2
  27. package/dist/{chunk-L47TF46W.js → chunk-6PAZTBPA.js} +14 -2
  28. package/dist/{chunk-XIVNBFZS.js → chunk-6Q3CYFD3.js} +34 -16
  29. package/dist/{chunk-RSJ25QSL.js → chunk-6QOTUPRG.js} +155 -36
  30. package/dist/{chunk-JKKCYP3C.js → chunk-6UINWWS6.js} +10 -4
  31. package/dist/{chunk-WBKFA554.js → chunk-72YIHOZQ.js} +2 -2
  32. package/dist/{chunk-PAJQJ7BS.js → chunk-75W7L2E2.js} +246 -697
  33. package/dist/{chunk-RRNP2ANY.js → chunk-7UGL4MB5.js} +4 -4
  34. package/dist/{chunk-EKCHAPYA.js → chunk-AUPNRN7C.js} +2 -2
  35. package/dist/{chunk-ZDN3Y73Y.js → chunk-BJVFZO5U.js} +6 -48
  36. package/dist/{chunk-IWT4SF4R.js → chunk-CUSRQKPU.js} +64 -2
  37. package/dist/{chunk-SKHCAU7K.js → chunk-DQOVN6KV.js} +3 -2
  38. package/dist/{chunk-ZWPRK62N.js → chunk-DT3LWJOB.js} +4 -4
  39. package/dist/chunk-DXKJURES.js +671 -0
  40. package/dist/{chunk-BEPZRGGU.js → chunk-EL24TAU4.js} +2 -2
  41. package/dist/{chunk-OML5D5V5.js → chunk-ELWDPP3Y.js} +5 -5
  42. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  43. package/dist/chunk-EXLD33WO.js +381 -0
  44. package/dist/{chunk-IJNZMHLA.js → chunk-FEAXX7B6.js} +2 -2
  45. package/dist/{chunk-TM6LQDI3.js → chunk-FFUPXJC4.js} +74 -323
  46. package/dist/chunk-GX5WYQO4.js +59 -0
  47. package/dist/chunk-I2DWJ4GM.js +390 -0
  48. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  49. package/dist/chunk-IRXAATOX.js +539 -0
  50. package/dist/chunk-IXIY2H4R.js +44 -0
  51. package/dist/{chunk-KK4JZPBQ.js → chunk-IZXGRF7P.js} +76 -10
  52. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  53. package/dist/{chunk-INY6HTFL.js → chunk-JEIYHLOR.js} +2 -2
  54. package/dist/{chunk-MUW2BDDH.js → chunk-JQLNNIKT.js} +2 -2
  55. package/dist/{chunk-XPWWI35G.js → chunk-JSD46VO2.js} +19 -8
  56. package/dist/{chunk-VA5FNYMT.js → chunk-JT2RFCC5.js} +39 -2
  57. package/dist/{chunk-V2ANDPVT.js → chunk-K6T2ZAMZ.js} +168 -6
  58. package/dist/{chunk-B4OAX3SI.js → chunk-KFV5L5SK.js} +13 -6
  59. package/dist/{chunk-JEQ3XTHC.js → chunk-LLXSDWXS.js} +2 -2
  60. package/dist/{chunk-E3TPLWFX.js → chunk-LTIKRKFL.js} +3 -3
  61. package/dist/{chunk-NIQJ66N4.js → chunk-N56KALIC.js} +17 -17
  62. package/dist/{chunk-JDAY6FIL.js → chunk-NAI6ZFCY.js} +13 -9
  63. package/dist/{chunk-AF4YM7Z4.js → chunk-NRO2BJRH.js} +2490 -2182
  64. package/dist/{chunk-WRBAGUNF.js → chunk-NXIMQY5W.js} +2 -2
  65. package/dist/{chunk-I7ZPNEJM.js → chunk-NXYCB2VD.js} +5 -5
  66. package/dist/chunk-ODGTEFFI.js +50 -0
  67. package/dist/{chunk-2VIKGWFZ.js → chunk-OEJSLEPW.js} +2 -2
  68. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  69. package/dist/{chunk-54CBCGIR.js → chunk-Q4WO54TA.js} +132 -77
  70. package/dist/{chunk-B4VEBZKF.js → chunk-QUFRYSWI.js} +12 -6
  71. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  72. package/dist/{chunk-HEQY7ZFI.js → chunk-RAY4OVGZ.js} +2 -2
  73. package/dist/{chunk-G76U63X4.js → chunk-RQCKCSRL.js} +7 -7
  74. package/dist/{chunk-64I3JVYM.js → chunk-RXTN6AKH.js} +2 -2
  75. package/dist/{chunk-UPZU6GE4.js → chunk-RZDWV63N.js} +3 -3
  76. package/dist/{chunk-2UH2KFUP.js → chunk-S6PYF2XF.js} +2 -2
  77. package/dist/{chunk-JSC3U7TI.js → chunk-TOIVGRUX.js} +2 -2
  78. package/dist/{chunk-7DRAWPTZ.js → chunk-TQAHXW6Y.js} +1 -1
  79. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  80. package/dist/{chunk-AX2THNSA.js → chunk-UEPWCCTY.js} +4 -4
  81. package/dist/{chunk-QWGDJJYJ.js → chunk-USR47QNF.js} +4 -4
  82. package/dist/{chunk-Y3CBHOR6.js → chunk-V6HJFQZE.js} +2 -2
  83. package/dist/chunk-V76WTFTW.js +318 -0
  84. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  85. package/dist/{chunk-2UG5F4C5.js → chunk-XULDXHTN.js} +24 -12
  86. package/dist/chunk-XXYSBZIQ.js +283 -0
  87. package/dist/{chunk-MWUZBSAQ.js → chunk-Y55JBDO5.js} +331 -51
  88. package/dist/{chunk-W6RRQCPQ.js → chunk-YD5GIKET.js} +4 -4
  89. package/dist/{chunk-CE5AX47J.js → chunk-YECAMM3D.js} +2 -2
  90. package/dist/{chunk-WCXUNS7U.js → chunk-YNFKXPEC.js} +6 -6
  91. package/dist/cli/index.js +36 -35
  92. package/dist/{clio-CMMK4KRR.js → clio-QLICPCF5.js} +2 -2
  93. package/dist/{code-nav-MDZNQS33.js → code-nav-IJR2DBPR.js} +6 -6
  94. package/dist/{components-UCUQ4QXW.js → components-2TGAI2RC.js} +3 -4
  95. package/dist/{config-SVM5P5YI.js → config-IUA6OYNS.js} +52 -47
  96. package/dist/{configure-LE3IK2TJ.js → configure-VEPX4NMX.js} +14 -15
  97. package/dist/{context-VNCR7KAG.js → context-2DKHWH2T.js} +23 -23
  98. package/dist/{context-2OHRKS42.js → context-4MPR7WKB.js} +48 -42
  99. package/dist/{context-E3VC7RX5.js → context-BOYF5EJM.js} +11 -11
  100. package/dist/{context-clear-BW4O37TG.js → context-clear-S4ZJCQUX.js} +48 -42
  101. package/dist/{context-working-set-VDS25HXZ.js → context-working-set-3I3FYX6Y.js} +8 -8
  102. package/dist/detail-A7JAVSIG.js +98 -0
  103. package/dist/{dispatch-runner-5AHT53RF.js → dispatch-runner-RJ5I2F2O.js} +71 -58
  104. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  105. package/dist/{doctor-WNNVO6FY.js → doctor-DKICC2SN.js} +54 -31
  106. package/dist/{eval-7G7SGAYO.js → eval-OQOQUDHK.js} +47 -56
  107. package/dist/{evidence-VD6736FQ.js → evidence-4DQ25GUQ.js} +53 -150
  108. package/dist/evidence-4F5USFKH.js +208 -0
  109. package/dist/{evolve-AL3NGVRL.js → evolve-GSS52E5J.js} +44 -41
  110. package/dist/{extensions-MOVJ32NM.js → extensions-G7MFLYHT.js} +4 -5
  111. package/dist/{fleet-QZHUMAGI.js → fleet-Q37YHHAQ.js} +74 -68
  112. package/dist/{fleet-commands-BAYT5FJZ.js → fleet-commands-G7E4N7SM.js} +14 -11
  113. package/dist/{fleet-decisions-IREVMRU4.js → fleet-decisions-O7M6QBA2.js} +6 -6
  114. package/dist/{fleet-graph-YCTT3HTI.js → fleet-graph-TOUBW6OW.js} +13 -13
  115. package/dist/{fleet-inspect-QVJTDAVB.js → fleet-inspect-SW33JJNI.js} +43 -39
  116. package/dist/{fleet-preflight-25QAFPK4.js → fleet-preflight-CV2655TW.js} +2 -3
  117. package/dist/{fleet-validate-5O57AAJ7.js → fleet-validate-KESZX2YH.js} +16 -16
  118. package/dist/{fleet-verify-CPH2W2T6.js → fleet-verify-UQPMTVE3.js} +42 -38
  119. package/dist/{fleet-view-SWBR3VGQ.js → fleet-view-MN2VG4MR.js} +43 -39
  120. package/dist/{init-J477LKZH.js → init-PXEXQSBF.js} +60 -54
  121. package/dist/{interop-3FCM6XLG.js → interop-ZG5T62U3.js} +6 -7
  122. package/dist/inventory-C26CFDRR.js +101 -0
  123. package/dist/{library-QUQEIUG6.js → library-B2W4N74O.js} +16 -17
  124. package/dist/{memory-SGGSEP65.js → memory-YCANYS5A.js} +45 -42
  125. package/dist/{models-HEKUAXXK.js → models-GERTU3YI.js} +20 -22
  126. package/dist/{monitor-HKU57TYQ.js → monitor-CPNIUULB.js} +50 -44
  127. package/dist/{orchestrator-VDFAEFAI.js → orchestrator-J4BSH4WQ.js} +491 -1182
  128. package/dist/{panes-DN2SSFOH.js → panes-BOHAEGYC.js} +3 -3
  129. package/dist/{panes-TALGNPZT.js → panes-NXSLDQZ2.js} +5 -6
  130. package/dist/{paths-NBMFAIEZ.js → paths-VSUWNC22.js} +3 -4
  131. package/dist/{reset-EAJFFJVB.js → reset-TNWTB5LU.js} +5 -6
  132. package/dist/{resources-OVKSEFVE.js → resources-4PXNMD5G.js} +14 -14
  133. package/dist/{run-7DP7ZF2J.js → run-D6XJ34CN.js} +79 -83
  134. package/dist/{share-WML67FT3.js → share-2NWMJJEE.js} +14 -15
  135. package/dist/{skills-SG662R2K.js → skills-KR7WON5G.js} +18 -19
  136. package/dist/{skills-eval-VVZEUU46.js → skills-eval-O2ZNOLDS.js} +49 -46
  137. package/dist/{skills-inventory-I2E23GET.js → skills-inventory-ZZOUBK7O.js} +14 -14
  138. package/dist/{slash-commands-S7MBJDQK.js → slash-commands-ZXPJD64J.js} +32 -23
  139. package/dist/{steer-2LQOMCPB.js → steer-XA25PSCS.js} +3 -3
  140. package/dist/{support-CC2UJBJ6.js → support-7EMVWYG2.js} +2 -2
  141. package/dist/{targets-4QC3HIEW.js → targets-OMH2XCSN.js} +25 -27
  142. package/dist/tasks-IPAGMEIX.js +36 -0
  143. package/dist/{terminal-lease-TUHIJ6Y2.js → terminal-lease-C2J3JYRE.js} +4 -4
  144. package/dist/{tools-TFGJICCU.js → tools-EFFEAIDP.js} +5 -6
  145. package/dist/{uninstall-5PEVOE5B.js → uninstall-HALS6BLF.js} +7 -8
  146. package/dist/{upgrade-M4WXY6KN.js → upgrade-MS72RJEP.js} +14 -11
  147. package/dist/{usage-N7ZNVLEM.js → usage-NHG6MCJM.js} +60 -51
  148. package/dist/{verifiers-DJTP4XX6.js → verifiers-7AUNVXDY.js} +150 -17
  149. package/dist/{verify-RWE4PPEK.js → verify-FWYGPKMR.js} +12 -10
  150. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  151. package/dist/{wiki-generate-C7IQOXSP.js → wiki-generate-743CIGJW.js} +63 -56
  152. package/dist/{with-panes-4GCGSL7J.js → with-panes-BDQEWBRT.js} +2 -2
  153. package/dist/worker/entry.js +36 -33
  154. package/docs/README.md +3 -2
  155. package/docs/architecture/acp.md +17 -0
  156. package/docs/architecture/artifact-versions.md +1 -1
  157. package/docs/architecture/dispatch-typed-intent.md +1 -1
  158. package/docs/architecture/evidence-and-memory.md +1 -1
  159. package/docs/architecture/observability.md +7 -1
  160. package/docs/architecture/prompt-envelope-and-tools.md +15 -5
  161. package/docs/architecture/safety-model.md +10 -17
  162. package/docs/architecture/tui-design.md +1 -1
  163. package/docs/guide/built-in-agents.md +8 -8
  164. package/docs/guide/commands-and-modes.md +17 -2
  165. package/docs/guide/configuration-and-targets.md +3 -1
  166. package/docs/guide/configuration-reference.md +10 -5
  167. package/docs/guide/environment-variables.md +2 -2
  168. package/docs/guide/tool-usage.md +78 -3
  169. package/docs/history/config-knobs-audit.md +2 -2
  170. package/docs/process/development-pipeline.md +6 -1
  171. package/docs/process/git-commit-provenance.md +15 -0
  172. package/docs/process/release-cut-checklist.md +207 -0
  173. package/docs/process/scientific-validation.md +18 -17
  174. package/evals/behavioral-machinery-support.ts +1 -0
  175. package/evals/behavioral-machinery.yaml +1 -1
  176. package/package.json +1 -1
  177. package/skills/coding/coding-standards/SKILL.md +14 -4
  178. package/skills/context/context-handoff/SKILL.md +3 -3
  179. package/skills/context/context-prime/SKILL.md +3 -3
  180. package/skills/planning/architecture/SKILL.md +5 -5
  181. package/skills/planning/backlog/SKILL.md +4 -4
  182. package/skills/planning/prd/SKILL.md +4 -3
  183. package/skills/planning/product-intent/SKILL.md +8 -8
  184. package/skills/planning/tech-spec/SKILL.md +4 -4
  185. package/skills/registry.yaml +32 -32
  186. package/skills/research/arxiv-literature/SKILL.md +3 -3
  187. package/skills/research/experiment-protocol/SKILL.md +3 -3
  188. package/skills/research/scientific-debugging/SKILL.md +3 -2
  189. package/skills/research/scientific-modernization/SKILL.md +3 -3
  190. package/skills/skill-marketplace.json +16 -16
  191. package/skills/workflow/cut-it/SKILL.md +3 -4
  192. package/skills/workflow/design-council/SKILL.md +5 -10
  193. package/skills/workflow/grill-me/SKILL.md +14 -15
  194. package/skills/workflow/workflow-distiller/SKILL.md +4 -4
  195. package/src/cli/args.ts +0 -8
  196. package/src/cli/configure.ts +2 -1
  197. package/src/cli/doctor-state-size.ts +1 -12
  198. package/src/cli/doctor-validation-contract.ts +28 -0
  199. package/src/cli/doctor.ts +5 -0
  200. package/src/cli/evidence-detail.ts +1 -75
  201. package/src/cli/evidence-inventory.ts +1 -167
  202. package/src/cli/index.ts +2 -0
  203. package/src/cli/run.ts +0 -2
  204. package/src/cli/targets.ts +1 -1
  205. package/src/cli/tasks.ts +84 -0
  206. package/src/cli/upgrade.ts +10 -5
  207. package/src/cli/usage.ts +6 -0
  208. package/src/cli/verifiers.ts +147 -1
  209. package/src/cli/wiki-generate.ts +1 -0
  210. package/src/core/commit-attribution.ts +41 -1
  211. package/src/core/git-commit-attribution.ts +46 -3
  212. package/src/core/run-overrides.ts +0 -5
  213. package/src/core/skill-activation.ts +3 -0
  214. package/src/core/tool-names.ts +5 -2
  215. package/src/domains/agents/builtins/architect.md +1 -1
  216. package/src/domains/agents/builtins/coder.md +1 -1
  217. package/src/domains/agents/builtins/documenter.md +1 -1
  218. package/src/domains/agents/builtins/git-master.md +1 -1
  219. package/src/domains/agents/builtins/provenance.md +7 -7
  220. package/src/domains/agents/builtins/tester.md +1 -1
  221. package/src/domains/agents/builtins/verifier.md +2 -2
  222. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  223. package/src/domains/context/extension.ts +31 -7
  224. package/src/domains/context/refresh.ts +3 -0
  225. package/src/domains/context/wiki/frontmatter.ts +5 -2
  226. package/src/domains/context/wiki/generate.ts +6 -0
  227. package/src/domains/context/wiki/prompts.ts +43 -0
  228. package/src/domains/dispatch/active-route-planner.ts +4 -0
  229. package/src/domains/dispatch/code-step.ts +11 -4
  230. package/src/domains/dispatch/contract.ts +31 -7
  231. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  232. package/src/domains/dispatch/extension.ts +50 -27
  233. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  234. package/src/domains/dispatch/fleet-run.ts +1 -0
  235. package/src/domains/dispatch/host-verification.ts +114 -13
  236. package/src/domains/dispatch/intent.ts +28 -18
  237. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  238. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  239. package/src/domains/dispatch/reservation-store.ts +5 -3
  240. package/src/domains/dispatch/state.ts +15 -2
  241. package/src/domains/dispatch/types.ts +17 -2
  242. package/src/domains/eval/runners/clio-run.ts +12 -9
  243. package/src/domains/eval/runners/context-index.ts +2 -7
  244. package/src/domains/eval/runners/context-init.ts +3 -6
  245. package/src/domains/eval/runners/external-command.ts +29 -11
  246. package/src/domains/evidence/build.ts +102 -15
  247. package/src/domains/evidence/detail.ts +69 -0
  248. package/src/domains/evidence/eval.ts +13 -1
  249. package/src/domains/evidence/finish-contract-map.ts +5 -1
  250. package/src/domains/evidence/inventory.ts +167 -0
  251. package/src/domains/evidence/store.ts +16 -0
  252. package/src/domains/evidence/types.ts +12 -0
  253. package/src/domains/extensions/resources.ts +7 -0
  254. package/src/domains/middleware/marketplace-offer.ts +20 -1
  255. package/src/domains/middleware/runtime.ts +7 -3
  256. package/src/domains/mux/detect.ts +3 -6
  257. package/src/domains/observability/accountability.ts +15 -1
  258. package/src/domains/observability/contract.ts +52 -7
  259. package/src/domains/observability/evidence-index.ts +10 -0
  260. package/src/domains/observability/extension.ts +9 -5
  261. package/src/domains/observability/projection.ts +394 -45
  262. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  263. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  264. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  265. package/src/domains/providers/model-discovery.ts +1 -4
  266. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +16 -14
  267. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  268. package/src/domains/providers/support.ts +1 -1
  269. package/src/domains/providers/types/runtime-descriptor.ts +1 -1
  270. package/src/domains/safety/action-classifier.ts +7 -0
  271. package/src/domains/safety/default-path-policy.ts +2 -0
  272. package/src/domains/safety/finish-contract-registration.ts +29 -14
  273. package/src/domains/safety/finish-contract.ts +252 -40
  274. package/src/domains/safety/index.ts +20 -1
  275. package/src/domains/safety/policy-engine.ts +26 -6
  276. package/src/domains/safety/rigor.ts +53 -39
  277. package/src/domains/safety/validation-contract.ts +388 -0
  278. package/src/domains/session/archive-readers.ts +10 -1
  279. package/src/domains/session/decision-board.ts +101 -2
  280. package/src/domains/session/entries.ts +44 -7
  281. package/src/domains/session/extension.ts +4 -4
  282. package/src/domains/session/handoff.ts +2 -1
  283. package/src/domains/session/manager.ts +2 -3
  284. package/src/domains/session/task-board.ts +14 -1
  285. package/src/domains/session/tree/fork.ts +1 -2
  286. package/src/domains/session/tree/navigator.ts +1 -1
  287. package/src/domains/user-tasks/acceptance.ts +56 -0
  288. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  289. package/src/domains/user-tasks/store.ts +34 -3
  290. package/src/engine/acp/adapter.ts +24 -6
  291. package/src/engine/acp/server.ts +21 -4
  292. package/src/engine/acp/transport.ts +53 -8
  293. package/src/engine/acp/types.ts +4 -0
  294. package/src/engine/apis/ollama-native.ts +15 -0
  295. package/src/engine/claude/subprocess-runtime.ts +107 -60
  296. package/src/engine/external-subprocess.ts +12 -4
  297. package/src/entry/orchestrator.ts +11 -2
  298. package/src/interactive/dispatch-board.ts +46 -717
  299. package/src/interactive/fleet-run-preview.ts +2 -1
  300. package/src/interactive/interactive-application.ts +3 -2
  301. package/src/interactive/interactive-presentation.ts +55 -12
  302. package/src/interactive/interactive-slash-runtime.ts +2 -1
  303. package/src/interactive/oracle.ts +5 -2
  304. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  305. package/src/interactive/overlays/message-picker.ts +2 -2
  306. package/src/interactive/overlays/settings.ts +2 -2
  307. package/src/interactive/overlays/tree-selector.ts +2 -2
  308. package/src/interactive/renderers/branch-summary.ts +1 -1
  309. package/src/interactive/slash-autocomplete.ts +4 -6
  310. package/src/interactive/slash-commands.ts +25 -39
  311. package/src/interactive/slash-spec.ts +28 -0
  312. package/src/interactive/view/artifacts.ts +2 -0
  313. package/src/interactive/worker-stream.ts +7 -3
  314. package/src/tools/bootstrap.ts +4 -0
  315. package/src/tools/builtin-tool-catalog.ts +31 -0
  316. package/src/tools/compete-worktrees.ts +7 -1
  317. package/src/tools/core-bootstrap.ts +16 -0
  318. package/src/tools/decide.ts +136 -0
  319. package/src/tools/dispatch-admission.ts +21 -0
  320. package/src/tools/dispatch-plan.ts +5 -2
  321. package/src/tools/dispatch-runner.ts +15 -1
  322. package/src/tools/dispatch-types.ts +6 -0
  323. package/src/tools/evidence.ts +96 -0
  324. package/src/tools/limitation.ts +76 -0
  325. package/src/tools/policy.ts +9 -0
  326. package/src/tools/presentation.ts +3 -0
  327. package/src/tools/registry.ts +1 -1
  328. package/src/tools/result-shaping.ts +17 -5
  329. package/src/tools/task-worktree.ts +13 -3
  330. package/src/tools/tasks.ts +10 -1
  331. package/src/tools/verify/authoring.ts +170 -83
  332. package/src/tools/verify/catalog.ts +122 -5
  333. package/src/tools/verify/index.ts +2 -1
  334. package/src/tools/verify/numeric.ts +298 -0
  335. package/src/tools/verify/perf.ts +143 -0
  336. package/src/tools/verify/scripts.ts +229 -2
  337. package/dist/chunk-7DICMOS6.js +0 -313
  338. package/dist/chunk-RVG5JXAL.js +0 -41
  339. package/dist/chunk-T56WDKA5.js +0 -183
  340. package/dist/chunk-VPKWYKEY.js +0 -169
@@ -1,4 +1,8 @@
1
1
  import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
+ import {
3
+ hashToolCall,
4
+ typedValidationSummary
5
+ } from "./chunk-6QOTUPRG.js";
2
6
  import {
3
7
  ROUTE_POLICY_VERSION,
4
8
  isRouteDecisionAgentSelection,
@@ -6,50 +10,14 @@ import {
6
10
  parseRoutingIntent,
7
11
  routePriorForLatencyClass,
8
12
  sameRouteIdentity
9
- } from "./chunk-EKCHAPYA.js";
10
- import {
11
- hashToolCall,
12
- typedValidationSummary
13
- } from "./chunk-RSJ25QSL.js";
13
+ } from "./chunk-AUPNRN7C.js";
14
14
  import {
15
15
  describeCallAction
16
16
  } from "./chunk-NEDJ26B5.js";
17
- import {
18
- TOOL_PROFILE_NAMES,
19
- assertToolProfileEnforceable,
20
- isToolProfileName
21
- } from "./chunk-42FMPA75.js";
22
- import {
23
- deriveExecutionRole,
24
- isExecutionRole,
25
- requestExecutionRole
26
- } from "./chunk-H7IXIC72.js";
27
17
  import {
28
18
  expandPath,
29
19
  resolveReadPath
30
20
  } from "./chunk-OQE5J4C6.js";
31
- import {
32
- PATH_BOUNDARY_MAX_ENTRIES,
33
- PathBoundaryError,
34
- asDirectoryPathBoundary,
35
- normalizePathBoundaryEntry,
36
- pathBoundaryCovers,
37
- resolvePathBoundary
38
- } from "./chunk-HHV2GANA.js";
39
- import {
40
- AGENT_AUTOMATION_AUTHORITIES,
41
- COUNCIL_BALLOT_SHAPE,
42
- COUNCIL_BALLOT_VERDICT_MAX_BYTES,
43
- agentSpecFingerprint,
44
- classify
45
- } from "./chunk-B4OAX3SI.js";
46
- import {
47
- commandArgumentSegments,
48
- detectValidationCommand,
49
- extractCommandDeleteTargets,
50
- extractCommandWriteTargets,
51
- toolMutationPaths
52
- } from "./chunk-I7ZPNEJM.js";
53
21
  import {
54
22
  DEFAULT_MAX_LINES,
55
23
  DEFAULT_TOOL_RESULT_MAX_BYTES,
@@ -65,14 +33,43 @@ import {
65
33
  toolResultDigestFor,
66
34
  truncateHead,
67
35
  truncateTail
68
- } from "./chunk-JDAY6FIL.js";
36
+ } from "./chunk-NAI6ZFCY.js";
69
37
  import {
70
38
  formatSize
71
39
  } from "./chunk-OZNBF4L3.js";
72
40
  import {
73
- byteLength,
74
- truncateUtf8
75
- } from "./chunk-6XLNIQDB.js";
41
+ TOOL_PROFILE_NAMES,
42
+ assertToolProfileEnforceable,
43
+ isToolProfileName
44
+ } from "./chunk-QZWQA4DE.js";
45
+ import {
46
+ deriveExecutionRole,
47
+ isExecutionRole,
48
+ requestExecutionRole
49
+ } from "./chunk-H7IXIC72.js";
50
+ import {
51
+ AGENT_AUTOMATION_AUTHORITIES,
52
+ COUNCIL_BALLOT_SHAPE,
53
+ COUNCIL_BALLOT_VERDICT_MAX_BYTES,
54
+ agentSpecFingerprint,
55
+ classify
56
+ } from "./chunk-KFV5L5SK.js";
57
+ import {
58
+ commandArgumentSegments,
59
+ detectValidationCommand,
60
+ extractCommandDeleteTargets,
61
+ extractCommandWriteTargets,
62
+ toolMutationPaths
63
+ } from "./chunk-NXYCB2VD.js";
64
+ import {
65
+ isDispatchIntent,
66
+ resolveDispatchPathScope
67
+ } from "./chunk-IRXAATOX.js";
68
+ import {
69
+ asDirectoryPathBoundary,
70
+ pathBoundaryCovers,
71
+ resolvePathBoundary
72
+ } from "./chunk-HHV2GANA.js";
76
73
  import {
77
74
  typebox_exports
78
75
  } from "./chunk-5B2AEOW5.js";
@@ -84,30 +81,34 @@ import {
84
81
  evaluateSkillToolSurface,
85
82
  isAutonomyLevel,
86
83
  mapAutonomy
87
- } from "./chunk-JGRC33J2.js";
84
+ } from "./chunk-54X7T7DK.js";
85
+ import {
86
+ byteLength,
87
+ truncateUtf8
88
+ } from "./chunk-6XLNIQDB.js";
88
89
  import {
89
90
  ToolNames
90
- } from "./chunk-K6BSR66V.js";
91
+ } from "./chunk-4NSRCOYP.js";
91
92
  import {
92
93
  BASH_HARD_CAP_BYTES,
93
94
  combineBashOutput,
94
95
  runBashCommand
95
- } from "./chunk-NMJXSHBJ.js";
96
+ } from "./chunk-W54I7H25.js";
96
97
  import {
97
98
  boundedExternalDiagnostic
98
- } from "./chunk-VW6DOEDG.js";
99
+ } from "./chunk-6OSVSQL5.js";
99
100
  import {
100
101
  THINKING_LEVELS
101
102
  } from "./chunk-UXCU4E3T.js";
102
- import {
103
- buildSafeToolEnv,
104
- resolveSafeCwd
105
- } from "./chunk-JSC3U7TI.js";
106
103
  import {
107
104
  GUARDRAIL_DEFAULTS,
108
105
  isWorkerToolCallCapExceededReason,
109
106
  resolveGuardrail
110
107
  } from "./chunk-S66XZJOF.js";
108
+ import {
109
+ buildSafeToolEnv,
110
+ resolveSafeCwd
111
+ } from "./chunk-TOIVGRUX.js";
111
112
  import {
112
113
  StringEnum
113
114
  } from "./chunk-YPC6ZR5L.js";
@@ -821,513 +822,6 @@ function createAskUserTool(deps = {}) {
821
822
  };
822
823
  }
823
824
 
824
- // src/domains/dispatch/intent.ts
825
- init_esm_shims();
826
- import path2 from "node:path";
827
-
828
- // src/domains/dispatch/path-scope.ts
829
- init_esm_shims();
830
- import { existsSync } from "node:fs";
831
- var DISPATCH_PATH_TOKEN_RE = /(?:[\w.-]+\/)+[\w.-]+|\b[\w-]+\.[A-Za-z0-9]{1,8}\b/g;
832
- var HTTP_URL_RE = /\bhttps?:\/\/\S+/gu;
833
- var POSIX_ABSOLUTE_TOKEN_RE = /(?:^|[\s("'])((?:\/[\w.~+-]+)+)/gu;
834
- var WINDOWS_ABSOLUTE_TOKEN_RE = /(?:^|[\s("'])([A-Za-z]:[\\/][^\s"']+)/gu;
835
- var BACKSLASH_PATH_RE = /\b[A-Za-z_.-][\w.-]*\\(?:(?:[\w.-]+\\)+[\w.-]+|[\w-]+\.[A-Za-z0-9]{1,8})\b/gu;
836
- var DOUBLE_SEPARATOR_PATH_RE = /\b[\w.-]+\/\/[\w./-]+/gu;
837
- var PARENT_PREFIX_RE = /^(?:\.\.\/)+/u;
838
- var DispatchPathScopeInferenceError = class extends Error {
839
- code;
840
- source;
841
- token;
842
- constructor(code, source, token, detail) {
843
- super(`${code}: ${source} contains ${detail} '${token}'; declare intent explicitly`);
844
- this.name = "DispatchPathScopeInferenceError";
845
- this.code = code;
846
- this.source = source;
847
- this.token = token;
848
- }
849
- };
850
- var DECLARED_EVIDENCE = {
851
- readRoots: {
852
- provenance: "declared",
853
- source: "intent.read_roots",
854
- confidence: "certain",
855
- reason: "explicit_intent"
856
- },
857
- writeRoots: {
858
- provenance: "declared",
859
- source: "intent.write_roots",
860
- confidence: "certain",
861
- reason: "explicit_intent"
862
- },
863
- relevantPaths: {
864
- provenance: "declared",
865
- source: "intent.relevant_paths",
866
- confidence: "certain",
867
- reason: "explicit_intent"
868
- }
869
- };
870
- function cloneEvidence(evidence) {
871
- return { ...evidence };
872
- }
873
- function addProvenance(entries, path5, evidence) {
874
- const current = entries.get(path5);
875
- if (current === void 0) {
876
- entries.set(path5, { path: path5, evidence: [cloneEvidence(evidence)] });
877
- return;
878
- }
879
- if (!current.evidence.some((entry) => entry.source === evidence.source)) {
880
- current.evidence.push(cloneEvidence(evidence));
881
- }
882
- }
883
- function sortedEntries(entries) {
884
- return [...entries.values()].sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0).map((entry) => ({ path: entry.path, evidence: entry.evidence.map(cloneEvidence) }));
885
- }
886
- function declaredIntentPathProvenance(input) {
887
- const entries = /* @__PURE__ */ new Map();
888
- for (const path5 of input.readRoots) addProvenance(entries, path5, DECLARED_EVIDENCE.readRoots);
889
- for (const path5 of input.writeRoots) addProvenance(entries, path5, DECLARED_EVIDENCE.writeRoots);
890
- for (const path5 of input.relevantPaths) addProvenance(entries, path5, DECLARED_EVIDENCE.relevantPaths);
891
- return sortedEntries(entries);
892
- }
893
- function inferredPaths(req, root) {
894
- const paths = /* @__PURE__ */ new Set();
895
- const droppedTokens = /* @__PURE__ */ new Set();
896
- const text = `${req.task}
897
- ${req.briefing ?? ""}`;
898
- for (const match of text.matchAll(DISPATCH_PATH_TOKEN_RE)) {
899
- const inferred = inferredPathToken(match[0], root);
900
- if (inferred.kind === "dropped") {
901
- droppedTokens.add(inferred.token);
902
- continue;
903
- }
904
- const token = inferred.kind === "anchored" ? inferred.resolved : inferred.token;
905
- if (token.startsWith("http://") || token.startsWith("https://")) continue;
906
- paths.add(token);
907
- }
908
- return { paths: [...paths], droppedTokens: [...droppedTokens] };
909
- }
910
- function inferredPathToken(raw, root) {
911
- const token = raw.replace(/^\.\//u, "").replace(/\.+$/u, "");
912
- const parents = PARENT_PREFIX_RE.exec(token)?.[0];
913
- if (parents === void 0) return { kind: "token", token };
914
- const rest = token.slice(parents.length);
915
- const segments = rest.split("/");
916
- if (rest.length === 0 || segments.includes("..") || segments.includes(".")) return { kind: "token", token };
917
- return existsSync(resolvePathBoundary(root, rest)) ? { kind: "anchored", token, resolved: rest } : { kind: "dropped", token };
918
- }
919
- function failMalformedText(text, source) {
920
- const withoutUrls = text.replace(HTTP_URL_RE, (url) => " ".repeat(url.length));
921
- const absolute = POSIX_ABSOLUTE_TOKEN_RE.exec(withoutUrls)?.[1];
922
- POSIX_ABSOLUTE_TOKEN_RE.lastIndex = 0;
923
- if (absolute !== void 0) {
924
- throw new DispatchPathScopeInferenceError("legacy_scope_path_absolute", source, absolute, "an absolute path token");
925
- }
926
- const windowsAbsolute = WINDOWS_ABSOLUTE_TOKEN_RE.exec(withoutUrls)?.[1];
927
- WINDOWS_ABSOLUTE_TOKEN_RE.lastIndex = 0;
928
- if (windowsAbsolute !== void 0) {
929
- throw new DispatchPathScopeInferenceError(
930
- "legacy_scope_path_absolute",
931
- source,
932
- windowsAbsolute,
933
- "an absolute path token"
934
- );
935
- }
936
- for (const pattern of [BACKSLASH_PATH_RE, DOUBLE_SEPARATOR_PATH_RE]) {
937
- const malformed = pattern.exec(withoutUrls)?.[0];
938
- pattern.lastIndex = 0;
939
- if (malformed !== void 0) {
940
- throw new DispatchPathScopeInferenceError(
941
- "legacy_scope_path_malformed",
942
- source,
943
- malformed,
944
- "a malformed path token"
945
- );
946
- }
947
- }
948
- }
949
- function strictInferredPaths(text, source, root) {
950
- failMalformedText(text, source);
951
- const withoutUrls = text.replace(HTTP_URL_RE, (url) => " ".repeat(url.length));
952
- const evidence = source === "task" ? { provenance: "inferred", source, confidence: "medium", reason: "task_path_token" } : { provenance: "inferred", source, confidence: "low", reason: "briefing_path_token" };
953
- const paths = [];
954
- const parentTokens = [];
955
- for (const match of withoutUrls.matchAll(DISPATCH_PATH_TOKEN_RE)) {
956
- const inferred = inferredPathToken(match[0], root);
957
- if (inferred.kind === "dropped") {
958
- parentTokens.push({ token: inferred.token, resolved: null, source });
959
- continue;
960
- }
961
- if (inferred.kind === "anchored") {
962
- parentTokens.push({ token: inferred.token, resolved: inferred.resolved, source });
963
- }
964
- const token = inferred.kind === "anchored" ? inferred.resolved : inferred.token;
965
- try {
966
- paths.push({ path: normalizePathBoundaryEntry(token), evidence });
967
- } catch (error) {
968
- const code = error instanceof PathBoundaryError && error.code === "absolute" ? "legacy_scope_path_absolute" : "legacy_scope_path_malformed";
969
- throw new DispatchPathScopeInferenceError(
970
- code,
971
- source,
972
- token,
973
- code === "legacy_scope_path_absolute" ? "an absolute path token" : "a malformed path token"
974
- );
975
- }
976
- }
977
- return { paths, parentTokens };
978
- }
979
- function legacyPathScope(req, cwd) {
980
- const workingEntries = /* @__PURE__ */ new Map();
981
- const writeEntries = /* @__PURE__ */ new Map();
982
- const writeEvidence = {
983
- provenance: "derived",
984
- source: "writeRoots",
985
- confidence: "high",
986
- reason: "legacy_write_roots"
987
- };
988
- for (const root of req.writeRoots ?? []) {
989
- addProvenance(workingEntries, root, writeEvidence);
990
- addProvenance(writeEntries, asDirectoryPathBoundary(resolvePathBoundary(cwd, root)), writeEvidence);
991
- }
992
- const parentTokens = /* @__PURE__ */ new Map();
993
- const recordParentTokens = (entries) => {
994
- for (const entry of entries) if (!parentTokens.has(entry.token)) parentTokens.set(entry.token, entry);
995
- };
996
- const taskScope = strictInferredPaths(req.task, "task", cwd);
997
- for (const candidate of taskScope.paths) addProvenance(workingEntries, candidate.path, candidate.evidence);
998
- recordParentTokens(taskScope.parentTokens);
999
- if (req.briefing !== void 0) {
1000
- const briefingScope = strictInferredPaths(req.briefing, "briefing", cwd);
1001
- for (const candidate of briefingScope.paths) addProvenance(workingEntries, candidate.path, candidate.evidence);
1002
- recordParentTokens(briefingScope.parentTokens);
1003
- }
1004
- const workingContext = [...workingEntries.values()].map((entry) => ({
1005
- path: entry.path,
1006
- evidence: entry.evidence.map(cloneEvidence)
1007
- }));
1008
- const writeBoundaries = [...writeEntries.values()].map((entry) => ({
1009
- path: entry.path,
1010
- evidence: entry.evidence.map(cloneEvidence)
1011
- }));
1012
- return {
1013
- source: "inferred",
1014
- workingContextPaths: workingContext.map((entry) => entry.path),
1015
- writeBoundaries: writeBoundaries.map((entry) => entry.path),
1016
- inferredOnlyPaths: [],
1017
- parentTokens: [...parentTokens.values()],
1018
- provenance: {
1019
- version: 1,
1020
- mode: "legacy-inferred",
1021
- workingContextPaths: workingContext,
1022
- writeBoundaries
1023
- }
1024
- };
1025
- }
1026
- function resolveDispatchPathScope(req) {
1027
- const cwd = req.cwd ?? process.cwd();
1028
- if (req.intent === void 0) return legacyPathScope(req, cwd);
1029
- const declaredProvenance = declaredIntentPathProvenance(req.intent);
1030
- const declaredPaths = declaredProvenance.map((entry) => entry.path);
1031
- const inferred = inferredPaths(req, cwd);
1032
- const inferredOnlyPaths = [
1033
- ...inferred.paths.filter((candidate) => !pathBoundaryCovers(declaredPaths, candidate)),
1034
- ...inferred.droppedTokens
1035
- ];
1036
- const writeEvidence = DECLARED_EVIDENCE.writeRoots;
1037
- const writeBoundaries = req.intent.writeRoots.map((root) => ({
1038
- path: resolvePathBoundary(cwd, root),
1039
- evidence: [cloneEvidence(writeEvidence)]
1040
- }));
1041
- return {
1042
- source: "declared",
1043
- workingContextPaths: declaredPaths,
1044
- writeBoundaries: writeBoundaries.map((entry) => entry.path),
1045
- inferredOnlyPaths,
1046
- // Empty on purpose: the declaration is the scope here, so no "../" token
1047
- // changed what the worker sees and there is nothing for the legacy notice
1048
- // to report. A dropped one still reaches the operator through
1049
- // inferredOnlyPaths above.
1050
- parentTokens: [],
1051
- provenance: {
1052
- version: 1,
1053
- mode: "declared",
1054
- workingContextPaths: declaredProvenance,
1055
- writeBoundaries
1056
- }
1057
- };
1058
- }
1059
- var REPORTABLE_OMITTED_PATH_RE = /\.(?:[cm]?[jt]sx?|json|ya?ml|md|txt|py|go|rs|c|h|cc|cpp|hpp|java|rb|sh|toml|css|html|sql|lock)(?:\/|$)|\/$/u;
1060
- var OMITTED_PATH_REPORT_CAP = 12;
1061
- function reportableOmittedPaths(scope) {
1062
- return scope.inferredOnlyPaths.filter((path5) => REPORTABLE_OMITTED_PATH_RE.test(path5));
1063
- }
1064
- function renderOmittedPaths(paths) {
1065
- if (paths.length <= OMITTED_PATH_REPORT_CAP) return paths.join(", ");
1066
- return `${paths.slice(0, OMITTED_PATH_REPORT_CAP).join(", ")} and ${paths.length - OMITTED_PATH_REPORT_CAP} more`;
1067
- }
1068
- function declaredScopeReplacementDiagnostic(scope) {
1069
- if (scope.source !== "declared") return null;
1070
- const omitted = reportableOmittedPaths(scope);
1071
- if (omitted.length === 0) return null;
1072
- return `typed_scope_replaced_inferred_paths: typed intent omitted prose-inferred paths ${renderOmittedPaths(
1073
- omitted
1074
- )}; those paths did not select project rules or expand worker authority`;
1075
- }
1076
- function declaredScopeReplacementNotice(scope) {
1077
- if (scope.source !== "declared") return null;
1078
- const omittedPaths = reportableOmittedPaths(scope);
1079
- if (omittedPaths.length === 0) return null;
1080
- return {
1081
- code: "typed_scope_replaced_inferred_paths",
1082
- level: "warning",
1083
- omittedPaths,
1084
- message: `[dispatch scope] typed intent replaced prose path inference; omitted paths: ${renderOmittedPaths(
1085
- omittedPaths
1086
- )}. Those paths did not select project rules or expand worker authority.`
1087
- };
1088
- }
1089
- function renderParentTokens(tokens) {
1090
- return renderOmittedPaths(tokens.map((entry) => `${entry.token} -> ${entry.resolved ?? "dropped"}`));
1091
- }
1092
- function inferredScopeParentTokenDiagnostic(scope) {
1093
- const tokens = scope.parentTokens;
1094
- if (tokens.length === 0) return null;
1095
- return `legacy_scope_inferred: prose inference resolved path tokens carrying a leading '../' run against the dispatch root ${renderParentTokens(
1096
- tokens
1097
- )}; an anchored token selects project rules without expanding worker authority and a dropped one took no part in scope`;
1098
- }
1099
- function inferredScopeParentTokenNotice(scope) {
1100
- const tokens = scope.parentTokens;
1101
- if (tokens.length === 0) return null;
1102
- return {
1103
- code: "legacy_scope_inferred",
1104
- level: "warning",
1105
- // Every entry names the raw prose token, the one spelling both outcomes
1106
- // share; the message carries what each one resolved to.
1107
- paths: tokens.map((entry) => ({
1108
- path: entry.token,
1109
- policy: "working-context",
1110
- provenance: "inferred",
1111
- source: entry.source,
1112
- confidence: "low"
1113
- })),
1114
- message: `[dispatch scope] prose inference resolved path tokens carrying a leading '../' run against the dispatch root: ${renderParentTokens(
1115
- tokens
1116
- )}. An anchored token selects project rules without expanding worker authority; a dropped one took no part in scope.`
1117
- };
1118
- }
1119
-
1120
- // src/domains/dispatch/intent.ts
1121
- var DISPATCH_INTENT_PATH_LIST_CAP = PATH_BOUNDARY_MAX_ENTRIES;
1122
- var DISPATCH_INTENT_PATH_ENTRY_BYTES_CAP = 512;
1123
- var DISPATCH_INTENT_VERIFICATION_CAP = 8;
1124
- var DISPATCH_INTENT_TIMEOUT_MIN_MS = 1e3;
1125
- var RAW_FIELDS = /* @__PURE__ */ new Set([
1126
- "version",
1127
- "read_roots",
1128
- "write_roots",
1129
- "relevant_paths",
1130
- "expected_outputs",
1131
- "verification"
1132
- ]);
1133
- function isRecord2(value) {
1134
- return value !== null && typeof value === "object" && !Array.isArray(value);
1135
- }
1136
- function compareCodepoints(left, right) {
1137
- return left < right ? -1 : left > right ? 1 : 0;
1138
- }
1139
- function fail(reason, message) {
1140
- return { ok: false, reason, message };
1141
- }
1142
- function checkedPathText(value, field, index) {
1143
- if (typeof value !== "string" || value.trim().length === 0) {
1144
- return fail("intent_path_malformed", `${field}[${index}] must be a non-empty repository-relative POSIX path`);
1145
- }
1146
- const trimmed = value.trim();
1147
- if (Buffer.byteLength(trimmed, "utf8") > DISPATCH_INTENT_PATH_ENTRY_BYTES_CAP) {
1148
- return fail(
1149
- "intent_path_over_cap",
1150
- `${field}[${index}] exceeds the ${DISPATCH_INTENT_PATH_ENTRY_BYTES_CAP}-byte cap`
1151
- );
1152
- }
1153
- return trimmed;
1154
- }
1155
- function normalizeScopePathEntry(value, field, index) {
1156
- const checked = checkedPathText(value, field, index);
1157
- if (typeof checked !== "string") return checked;
1158
- try {
1159
- return normalizePathBoundaryEntry(checked);
1160
- } catch (error) {
1161
- if (error instanceof PathBoundaryError) {
1162
- if (error.code === "absolute") {
1163
- return fail("intent_path_absolute", `${field}[${index}] must be a repository-relative POSIX path`);
1164
- }
1165
- if (error.code === "parent") {
1166
- return fail("intent_path_escapes_root", `${field}[${index}] escapes the repository root`);
1167
- }
1168
- }
1169
- return fail(
1170
- "intent_path_malformed",
1171
- `${field}[${index}] does not follow the repository path boundary grammar: ${error instanceof Error ? error.message : String(error)}`
1172
- );
1173
- }
1174
- }
1175
- function normalizeExpectedOutputEntry(value, field, index) {
1176
- const checked = checkedPathText(value, field, index);
1177
- if (typeof checked !== "string") return checked;
1178
- const trimmed = checked;
1179
- if (trimmed.includes("\\") || path2.posix.isAbsolute(trimmed) || path2.win32.isAbsolute(trimmed)) {
1180
- return fail("intent_path_absolute", `${field}[${index}] must be a repository-relative POSIX path`);
1181
- }
1182
- const normalized = path2.posix.normalize(trimmed.replace(/^\.\//u, "").replace(/\/{2,}/gu, "/"));
1183
- if (normalized === "." || normalized.length === 0) {
1184
- return fail("intent_path_malformed", `${field}[${index}] must not normalize to an empty path`);
1185
- }
1186
- if (normalized === ".." || normalized.startsWith("../") || normalized.split("/").includes("..")) {
1187
- return fail("intent_path_escapes_root", `${field}[${index}] escapes the repository root`);
1188
- }
1189
- return normalized;
1190
- }
1191
- function normalizePathList(value, field, normalizeEntry = normalizeScopePathEntry) {
1192
- if (value === void 0) return [];
1193
- if (!Array.isArray(value)) return fail("intent_path_malformed", `${field} must be an array`);
1194
- if (value.length > DISPATCH_INTENT_PATH_LIST_CAP) {
1195
- return fail("intent_path_over_cap", `${field} exceeds the ${DISPATCH_INTENT_PATH_LIST_CAP}-entry cap`);
1196
- }
1197
- const normalized = [];
1198
- for (const [index, entry] of value.entries()) {
1199
- if (normalizeEntry === normalizeScopePathEntry && typeof entry === "string" && /^\.\/?$/u.test(entry.trim())) {
1200
- continue;
1201
- }
1202
- const result = normalizeEntry(entry, field, index);
1203
- if (typeof result !== "string") return result;
1204
- normalized.push(result);
1205
- }
1206
- return [...new Set(normalized)].sort(compareCodepoints);
1207
- }
1208
- function declaredScopeIntent(input) {
1209
- const readRoots = normalizePathList(input.readRoots, "intent.read_roots");
1210
- if (!Array.isArray(readRoots)) return readRoots;
1211
- const writeRoots = normalizePathList(input.writeRoots, "intent.write_roots");
1212
- if (!Array.isArray(writeRoots)) return writeRoots;
1213
- const relevantPaths = normalizePathList(input.relevantPaths, "intent.relevant_paths");
1214
- if (!Array.isArray(relevantPaths)) return relevantPaths;
1215
- return {
1216
- ok: true,
1217
- intent: {
1218
- version: 2,
1219
- readRoots,
1220
- writeRoots,
1221
- relevantPaths,
1222
- pathProvenance: declaredIntentPathProvenance({ readRoots, writeRoots, relevantPaths }),
1223
- expectedOutputs: [],
1224
- verification: []
1225
- }
1226
- };
1227
- }
1228
- function isDispatchIntent(value) {
1229
- if (!isRecord2(value) || value.version !== 2) return false;
1230
- for (const field of ["readRoots", "writeRoots", "relevantPaths", "expectedOutputs"]) {
1231
- if (!Array.isArray(value[field]) || !value[field].every((entry) => typeof entry === "string")) return false;
1232
- }
1233
- const readRoots = value.readRoots;
1234
- const writeRoots = value.writeRoots;
1235
- const relevantPaths = value.relevantPaths;
1236
- if (!Array.isArray(value.pathProvenance) || JSON.stringify(value.pathProvenance) !== JSON.stringify(
1237
- declaredIntentPathProvenance({
1238
- readRoots,
1239
- writeRoots,
1240
- relevantPaths
1241
- })
1242
- )) {
1243
- return false;
1244
- }
1245
- return Array.isArray(value.verification) && value.verification.every(
1246
- (entry) => isRecord2(entry) && typeof entry.check === "string" && entry.check.length > 0 && typeof entry.timeoutMs === "number" && Number.isInteger(entry.timeoutMs) && entry.timeoutMs >= DISPATCH_INTENT_TIMEOUT_MIN_MS
1247
- );
1248
- }
1249
- function narrowDispatchIntentToReadOnly(intent) {
1250
- if (intent.writeRoots.length === 0) return intent;
1251
- const readRoots = [.../* @__PURE__ */ new Set([...intent.readRoots, ...intent.writeRoots])].sort(compareCodepoints);
1252
- return {
1253
- version: 2,
1254
- readRoots,
1255
- writeRoots: [],
1256
- relevantPaths: [...intent.relevantPaths],
1257
- pathProvenance: declaredIntentPathProvenance({ readRoots, writeRoots: [], relevantPaths: intent.relevantPaths }),
1258
- expectedOutputs: [...intent.expectedOutputs],
1259
- verification: intent.verification.map((entry) => ({ ...entry }))
1260
- };
1261
- }
1262
- function normalizeDispatchIntent(raw, checks) {
1263
- if (!isRecord2(raw)) return fail("intent_malformed", "intent must be an object");
1264
- const unknown = Object.keys(raw).filter((key) => !RAW_FIELDS.has(key)).sort(compareCodepoints);
1265
- if (unknown.length > 0) return fail("intent_malformed", `intent contains unknown field '${unknown[0]}'`);
1266
- if (raw.version !== void 0 && raw.version !== 2) {
1267
- return fail(
1268
- "intent_version_unsupported",
1269
- `intent declares version ${JSON.stringify(raw.version)}; this build speaks dispatch intent version 2. A declaration at another version is refused rather than migrated: restate read_roots, write_roots, relevant_paths, expected_outputs, and verification under version 2`
1270
- );
1271
- }
1272
- const readRoots = normalizePathList(raw.read_roots, "intent.read_roots");
1273
- if (!Array.isArray(readRoots)) return readRoots;
1274
- const writeRoots = normalizePathList(raw.write_roots, "intent.write_roots");
1275
- if (!Array.isArray(writeRoots)) return writeRoots;
1276
- const relevantPaths = normalizePathList(raw.relevant_paths, "intent.relevant_paths");
1277
- if (!Array.isArray(relevantPaths)) return relevantPaths;
1278
- const expectedOutputs = normalizePathList(
1279
- raw.expected_outputs,
1280
- "intent.expected_outputs",
1281
- normalizeExpectedOutputEntry
1282
- );
1283
- if (!Array.isArray(expectedOutputs)) return expectedOutputs;
1284
- const rawVerification = raw.verification ?? [];
1285
- if (!Array.isArray(rawVerification)) {
1286
- return fail("verification_malformed", "intent.verification must be an array");
1287
- }
1288
- if (rawVerification.length > DISPATCH_INTENT_VERIFICATION_CAP) {
1289
- return fail("verification_over_cap", `intent.verification exceeds the ${DISPATCH_INTENT_VERIFICATION_CAP}-entry cap`);
1290
- }
1291
- const verification = [];
1292
- for (const [index, entry] of rawVerification.entries()) {
1293
- if (!isRecord2(entry) || Object.keys(entry).some((key) => key !== "check" && key !== "timeout_ms")) {
1294
- return fail("verification_malformed", `intent.verification[${index}] must contain check and optional timeout_ms`);
1295
- }
1296
- if (typeof entry.check !== "string" || entry.check.trim().length === 0) {
1297
- return fail("verification_malformed", `intent.verification[${index}].check must be a non-empty declared id`);
1298
- }
1299
- const check = entry.check.trim();
1300
- const declared = checks.get(check);
1301
- if (declared === void 0 && check.toLowerCase() === "none") continue;
1302
- if (declared === void 0) {
1303
- return fail(
1304
- "verification_check_undeclared",
1305
- `verification check '${check}' is undeclared: intent.verification takes only check ids that verify() lists (package.json verification scripts or .clio-coder/verifiers.yaml entries), never a shell command; omit verification and run the check yourself after the receipt, or declare the check first`
1306
- );
1307
- }
1308
- if (entry.timeout_ms !== void 0 && (typeof entry.timeout_ms !== "number" || !Number.isInteger(entry.timeout_ms) || entry.timeout_ms <= 0)) {
1309
- return fail("verification_malformed", `intent.verification[${index}].timeout_ms must be a positive integer`);
1310
- }
1311
- const requested = typeof entry.timeout_ms === "number" ? entry.timeout_ms : declared.timeoutMs;
1312
- verification.push({
1313
- check,
1314
- timeoutMs: Math.min(declared.timeoutMs, Math.max(DISPATCH_INTENT_TIMEOUT_MIN_MS, requested))
1315
- });
1316
- }
1317
- return {
1318
- ok: true,
1319
- intent: {
1320
- version: 2,
1321
- readRoots,
1322
- writeRoots,
1323
- relevantPaths,
1324
- pathProvenance: declaredIntentPathProvenance({ readRoots, writeRoots, relevantPaths }),
1325
- expectedOutputs,
1326
- verification
1327
- }
1328
- };
1329
- }
1330
-
1331
825
  // src/domains/dispatch/budget-envelope.ts
1332
826
  init_esm_shims();
1333
827
  var NATIVE_CLIO_CONTROLS = ["tool-calls", "read-reserve", "synthesis", "attempt-cap"];
@@ -1346,11 +840,11 @@ var BudgetAdmissionError = class extends Error {
1346
840
  this.code = code;
1347
841
  }
1348
842
  };
1349
- function isRecord3(value) {
843
+ function isRecord2(value) {
1350
844
  return typeof value === "object" && value !== null && !Array.isArray(value);
1351
845
  }
1352
846
  function clonePhase(value, prefix) {
1353
- if (!isRecord3(value)) throw new Error(`${prefix} must be an object`);
847
+ if (!isRecord2(value)) throw new Error(`${prefix} must be an object`);
1354
848
  for (const key of Object.keys(value)) {
1355
849
  if (key !== "toolCalls" && key !== "readReserve") throw new Error(`${prefix}.${key} is unknown`);
1356
850
  }
@@ -1369,7 +863,7 @@ function clonePhase(value, prefix) {
1369
863
  return { toolCalls, readReserve };
1370
864
  }
1371
865
  function cloneDispatchBudgetRequest(value, prefix = "budget") {
1372
- if (!isRecord3(value)) throw new Error(`${prefix} must be an object`);
866
+ if (!isRecord2(value)) throw new Error(`${prefix} must be an object`);
1373
867
  for (const key of Object.keys(value)) {
1374
868
  if (key !== "toolCalls" && key !== "readReserve" && key !== "retryRevision") {
1375
869
  throw new Error(`${prefix}.${key} is unknown`);
@@ -1584,14 +1078,14 @@ function isExactStringArray(value, expected) {
1584
1078
  }
1585
1079
  function cloneRunToolBudgetEnvelope(value) {
1586
1080
  try {
1587
- if (!isRecord3(value) || value.version !== 1 || !isRecord3(value.policy) || !isRecord3(value.effective)) {
1081
+ if (!isRecord2(value) || value.version !== 1 || !isRecord2(value.policy) || !isRecord2(value.effective)) {
1588
1082
  return void 0;
1589
1083
  }
1590
1084
  const recipeId = value.policy.recipeId;
1591
1085
  if (typeof recipeId !== "string" || recipeId.length === 0 || typeof value.policy.exact !== "boolean") {
1592
1086
  return void 0;
1593
1087
  }
1594
- if (!isRecord3(value.policy.default) || typeof value.policy.default.synthesis !== "boolean") return void 0;
1088
+ if (!isRecord2(value.policy.default) || typeof value.policy.default.synthesis !== "boolean") return void 0;
1595
1089
  const defaultPhase = clonePhase(
1596
1090
  { toolCalls: value.policy.default.toolCalls, readReserve: value.policy.default.readReserve },
1597
1091
  "budget.policy.default"
@@ -1611,7 +1105,7 @@ function cloneRunToolBudgetEnvelope(value) {
1611
1105
  }
1612
1106
  const reasons = [];
1613
1107
  for (const reason of value.reasons) {
1614
- if (!isRecord3(reason) || typeof reason.code !== "string" || !BUDGET_REASON_CODES.has(reason.code) || typeof reason.detail !== "string") {
1108
+ if (!isRecord2(reason) || typeof reason.code !== "string" || !BUDGET_REASON_CODES.has(reason.code) || typeof reason.detail !== "string") {
1615
1109
  return void 0;
1616
1110
  }
1617
1111
  reasons.push({ code: reason.code, detail: reason.detail });
@@ -1624,7 +1118,7 @@ function cloneRunToolBudgetEnvelope(value) {
1624
1118
  clioControls: [...NATIVE_CLIO_CONTROLS]
1625
1119
  };
1626
1120
  }
1627
- if (!isRecord3(value.enforcement) || !Array.isArray(value.enforcement.clioControls)) return null;
1121
+ if (!isRecord2(value.enforcement) || !Array.isArray(value.enforcement.clioControls)) return null;
1628
1122
  if (Object.keys(value.enforcement).some(
1629
1123
  (key) => key !== "classification" && key !== "perTool" && key !== "clioControls"
1630
1124
  )) {
@@ -2028,14 +1522,14 @@ var DISPATCH_INTENT_SUPPORTED_VERSIONS = [DISPATCH_INTENT_VERSION];
2028
1522
  function finding(code, decision, detail) {
2029
1523
  return { code, decision, message: `${code}: ${detail}` };
2030
1524
  }
2031
- function isRecord4(value) {
1525
+ function isRecord3(value) {
2032
1526
  return typeof value === "object" && value !== null && !Array.isArray(value);
2033
1527
  }
2034
1528
  function declaredVersion(value) {
2035
1529
  return typeof value.version === "number" && Number.isInteger(value.version) ? value.version : null;
2036
1530
  }
2037
1531
  function isSupportedDispatchIntentVersion(value) {
2038
- if (!isRecord4(value)) return false;
1532
+ if (!isRecord3(value)) return false;
2039
1533
  const version = declaredVersion(value);
2040
1534
  return version !== null && DISPATCH_INTENT_SUPPORTED_VERSIONS.includes(version);
2041
1535
  }
@@ -2099,7 +1593,7 @@ function classifyDispatchIntentCompatibility(input) {
2099
1593
  );
2100
1594
  return findings;
2101
1595
  }
2102
- if (!isRecord4(input.intent)) {
1596
+ if (!isRecord3(input.intent)) {
2103
1597
  findings.push(
2104
1598
  finding(
2105
1599
  "intent_malformed",
@@ -2168,7 +1662,7 @@ function dispatchIntentScopeWidening(ceiling, narrowed) {
2168
1662
 
2169
1663
  // src/domains/dispatch/validation.ts
2170
1664
  init_esm_shims();
2171
- import path3 from "node:path";
1665
+ import path2 from "node:path";
2172
1666
 
2173
1667
  // src/core/response-schema.ts
2174
1668
  init_esm_shims();
@@ -2280,49 +1774,49 @@ function schemaSyntaxError(value) {
2280
1774
  while (stack.length > 0) {
2281
1775
  const frame = stack.pop();
2282
1776
  if (!frame) break;
2283
- const { schema, path: path5 } = frame;
1777
+ const { schema, path: path4 } = frame;
2284
1778
  for (const key of Object.keys(schema)) {
2285
- if (!SUPPORTED_SCHEMA_KEYS.has(key)) return `${path5}.${key} is not supported by the llama.cpp schema subset`;
1779
+ if (!SUPPORTED_SCHEMA_KEYS.has(key)) return `${path4}.${key} is not supported by the llama.cpp schema subset`;
2286
1780
  }
2287
1781
  if (typeof schema.type !== "string" || !SUPPORTED_SCHEMA_TYPES.has(schema.type)) {
2288
- return `${path5}.type must be one of ${[...SUPPORTED_SCHEMA_TYPES].join(", ")}`;
1782
+ return `${path4}.type must be one of ${[...SUPPORTED_SCHEMA_TYPES].join(", ")}`;
2289
1783
  }
2290
1784
  if (schema.type === "object") {
2291
- if (schema.items !== void 0) return `${path5}.items is only valid for array schemas`;
1785
+ if (schema.items !== void 0) return `${path4}.items is only valid for array schemas`;
2292
1786
  if (schema.properties !== void 0 && !isPlainObject(schema.properties)) {
2293
- return `${path5}.properties must be a plain object`;
1787
+ return `${path4}.properties must be a plain object`;
2294
1788
  }
2295
1789
  const properties = schema.properties ?? {};
2296
1790
  for (const [name, child] of Object.entries(properties)) {
2297
- if (!isPlainObject(child)) return `${path5}.properties.${name} must be a schema object`;
2298
- stack.push({ schema: child, path: `${path5}.properties.${name}` });
1791
+ if (!isPlainObject(child)) return `${path4}.properties.${name} must be a schema object`;
1792
+ stack.push({ schema: child, path: `${path4}.properties.${name}` });
2299
1793
  }
2300
1794
  if (schema.required !== void 0) {
2301
1795
  if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
2302
- return `${path5}.required must be an array of strings`;
1796
+ return `${path4}.required must be an array of strings`;
2303
1797
  }
2304
1798
  if (new Set(schema.required).size !== schema.required.length) {
2305
- return `${path5}.required must not contain duplicates`;
1799
+ return `${path4}.required must not contain duplicates`;
2306
1800
  }
2307
1801
  for (const name of schema.required) {
2308
- if (!Object.hasOwn(properties, name)) return `${path5}.required names unknown property '${name}'`;
1802
+ if (!Object.hasOwn(properties, name)) return `${path4}.required names unknown property '${name}'`;
2309
1803
  }
2310
1804
  }
2311
1805
  if (schema.additionalProperties !== void 0 && typeof schema.additionalProperties !== "boolean") {
2312
- return `${path5}.additionalProperties must be a boolean`;
1806
+ return `${path4}.additionalProperties must be a boolean`;
2313
1807
  }
2314
1808
  continue;
2315
1809
  }
2316
1810
  if (schema.type === "array") {
2317
- if (!isPlainObject(schema.items)) return `${path5}.items must be a schema object`;
1811
+ if (!isPlainObject(schema.items)) return `${path4}.items must be a schema object`;
2318
1812
  if (schema.properties !== void 0 || schema.required !== void 0 || schema.additionalProperties !== void 0) {
2319
- return `${path5} contains object-only keywords on an array schema`;
1813
+ return `${path4} contains object-only keywords on an array schema`;
2320
1814
  }
2321
- stack.push({ schema: schema.items, path: `${path5}.items` });
1815
+ stack.push({ schema: schema.items, path: `${path4}.items` });
2322
1816
  continue;
2323
1817
  }
2324
1818
  if (schema.properties !== void 0 || schema.required !== void 0 || schema.items !== void 0 || schema.additionalProperties !== void 0) {
2325
- return `${path5} contains container keywords on a ${schema.type} schema`;
1819
+ return `${path4} contains container keywords on a ${schema.type} schema`;
2326
1820
  }
2327
1821
  }
2328
1822
  return null;
@@ -2551,7 +2045,7 @@ function validateJobSpec(spec) {
2551
2045
  }
2552
2046
  }
2553
2047
  if ("protectedArtifactRemap" in spec && spec.protectedArtifactRemap !== void 0) {
2554
- if (!isPlainObject2(spec.protectedArtifactRemap) || Object.keys(spec.protectedArtifactRemap).some((key) => key !== "sourceRoot" && key !== "workerRoot") || typeof spec.protectedArtifactRemap.sourceRoot !== "string" || !path3.isAbsolute(spec.protectedArtifactRemap.sourceRoot) || typeof spec.protectedArtifactRemap.workerRoot !== "string" || !path3.isAbsolute(spec.protectedArtifactRemap.workerRoot)) {
2048
+ if (!isPlainObject2(spec.protectedArtifactRemap) || Object.keys(spec.protectedArtifactRemap).some((key) => key !== "sourceRoot" && key !== "workerRoot") || typeof spec.protectedArtifactRemap.sourceRoot !== "string" || !path2.isAbsolute(spec.protectedArtifactRemap.sourceRoot) || typeof spec.protectedArtifactRemap.workerRoot !== "string" || !path2.isAbsolute(spec.protectedArtifactRemap.workerRoot)) {
2555
2049
  errors.push("protectedArtifactRemap must carry absolute sourceRoot and workerRoot paths");
2556
2050
  }
2557
2051
  }
@@ -2736,7 +2230,7 @@ function validateJobSpec(spec) {
2736
2230
  const effectiveWriteRoots = Array.isArray(spec.writeRoots) && spec.writeRoots.length > 0 && spec.writeRoots.every((root) => typeof root === "string" && root.length > 0) ? spec.writeRoots : isDispatchIntent(spec.intent) && spec.intent.writeRoots.length > 0 ? spec.intent.writeRoots : void 0;
2737
2231
  if (effectiveWriteRoots !== void 0) {
2738
2232
  const jobCwd = typeof spec.cwd === "string" && spec.cwd.length > 0 ? spec.cwd : process.cwd();
2739
- out.writeRoots = isDispatchIntent(spec.intent) ? effectiveWriteRoots.map((root) => resolvePathBoundary(jobCwd, String(root))) : effectiveWriteRoots.map((root) => asDirectoryPathBoundary(path3.resolve(jobCwd, String(root))));
2233
+ out.writeRoots = isDispatchIntent(spec.intent) ? effectiveWriteRoots.map((root) => resolvePathBoundary(jobCwd, String(root))) : effectiveWriteRoots.map((root) => asDirectoryPathBoundary(path2.resolve(jobCwd, String(root))));
2740
2234
  }
2741
2235
  if (typeof spec.requestOrigin === "string" && VALID_REQUEST_ORIGINS.has(spec.requestOrigin)) {
2742
2236
  out.requestOrigin = spec.requestOrigin;
@@ -2801,7 +2295,7 @@ function isValidPlannedNode(value) {
2801
2295
  return value.kind === "ssh" && typeof value.host === "string" && value.host.trim().length > 0;
2802
2296
  }
2803
2297
  function isValidProtectedArtifactRemap(value) {
2804
- return isPlainObject2(value) && typeof value.sourceRoot === "string" && path3.isAbsolute(value.sourceRoot) && typeof value.workerRoot === "string" && path3.isAbsolute(value.workerRoot);
2298
+ return isPlainObject2(value) && typeof value.sourceRoot === "string" && path2.isAbsolute(value.sourceRoot) && typeof value.workerRoot === "string" && path2.isAbsolute(value.workerRoot);
2805
2299
  }
2806
2300
  var VALID_GATE_ROLES = /* @__PURE__ */ new Set(["builder", "reviewer", "candidate", "judge", "member", "synthesis"]);
2807
2301
  var VALID_GATE_VERDICTS = /* @__PURE__ */ new Set(["pass", "fail", "revise"]);
@@ -2837,7 +2331,7 @@ function isValidGate(value) {
2837
2331
  if (value.worktree !== void 0) {
2838
2332
  if (!isPlainObject2(value.worktree)) return false;
2839
2333
  if (typeof value.worktree.backend !== "string" || !VALID_WORKTREE_BACKENDS.has(value.worktree.backend)) return false;
2840
- if (typeof value.worktree.path !== "string" || !path3.isAbsolute(value.worktree.path)) return false;
2334
+ if (typeof value.worktree.path !== "string" || !path2.isAbsolute(value.worktree.path)) return false;
2841
2335
  if (typeof value.worktree.branch !== "string" || value.worktree.branch.length === 0) return false;
2842
2336
  if (value.worktree.workspaceId !== void 0 && typeof value.worktree.workspaceId !== "string") return false;
2843
2337
  if (value.worktree.fallback !== void 0 && (typeof value.worktree.fallback !== "string" || !VALID_WORKTREE_FALLBACKS.has(value.worktree.fallback))) {
@@ -2920,7 +2414,7 @@ var DEFAULT_MAX_OUTPUT_BYTES = 2e4;
2920
2414
  var PERSONA_MAX_CHARS = 8e3;
2921
2415
  var THINKING_LEVELS2 = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
2922
2416
  var VALID_THINKING2 = new Set(THINKING_LEVELS2);
2923
- function isRecord5(value) {
2417
+ function isRecord4(value) {
2924
2418
  return typeof value === "object" && value !== null && !Array.isArray(value);
2925
2419
  }
2926
2420
  function stringArg(args, ...names) {
@@ -3000,7 +2494,7 @@ function dispatchRequestFromArgs(args, options) {
3000
2494
  if (request.worktree !== true) return { ok: false, message: "apply requires worktree: true" };
3001
2495
  request.apply = args.apply;
3002
2496
  }
3003
- if (Object.hasOwn(args, "gate") && isRecord5(args.intent) && Object.hasOwn(args.intent, "verification")) {
2497
+ if (Object.hasOwn(args, "gate") && isRecord4(args.intent) && Object.hasOwn(args.intent, "verification")) {
3004
2498
  return { ok: false, message: "gate_and_intent_verification_conflict: gate cannot combine with intent.verification" };
3005
2499
  }
3006
2500
  let rawIntent = args.intent;
@@ -3011,7 +2505,7 @@ function dispatchRequestFromArgs(args, options) {
3011
2505
  message: "gate must be a non-empty declared check id: a check verify() lists, never a shell command; omit gate and run the check yourself after the receipt"
3012
2506
  };
3013
2507
  }
3014
- rawIntent = { ...isRecord5(rawIntent) ? rawIntent : {}, verification: [{ check: args.gate.trim() }] };
2508
+ rawIntent = { ...isRecord4(rawIntent) ? rawIntent : {}, verification: [{ check: args.gate.trim() }] };
3015
2509
  }
3016
2510
  if (rawIntent !== void 0) {
3017
2511
  if (options.resolveIntent === void 0) return { ok: false, message: "intent resolver is unavailable" };
@@ -3083,9 +2577,9 @@ function dispatchRequestsFromArgs(args, options) {
3083
2577
  const requests = [];
3084
2578
  for (let index = 0; index < tasks.length; index += 1) {
3085
2579
  const item = tasks[index];
3086
- const itemArgs = isRecord5(item) ? { ...shared, ...item } : { ...shared, task: item };
3087
- const sharedIntent = isRecord5(shared.intent) ? shared.intent : null;
3088
- const itemIntent = isRecord5(item) && Object.hasOwn(item, "intent") && isRecord5(item.intent) ? item.intent : null;
2580
+ const itemArgs = isRecord4(item) ? { ...shared, ...item } : { ...shared, task: item };
2581
+ const sharedIntent = isRecord4(shared.intent) ? shared.intent : null;
2582
+ const itemIntent = isRecord4(item) && Object.hasOwn(item, "intent") && isRecord4(item.intent) ? item.intent : null;
3089
2583
  if (sharedIntent !== null && itemIntent !== null) itemArgs.intent = { ...sharedIntent, ...itemIntent };
3090
2584
  const parsed = dispatchRequestFromArgs(itemArgs, options);
3091
2585
  if (!parsed.ok) return { ok: false, message: `dispatch: task ${index + 1}: ${parsed.message}` };
@@ -3116,7 +2610,7 @@ function prepareDispatchArguments(args) {
3116
2610
  }
3117
2611
  }
3118
2612
  }
3119
- if (isRecord5(next.tasks)) next.tasks = [next.tasks];
2613
+ if (isRecord4(next.tasks)) next.tasks = [next.tasks];
3120
2614
  if (typeof next.tasks === "string") next.tasks = [next.tasks];
3121
2615
  if (next.tasks === void 0 && typeof next.task === "string") {
3122
2616
  const { task: _task, ...rest } = next;
@@ -3174,7 +2668,7 @@ function withResolvedPlanTaskPin(request, task, options = {}) {
3174
2668
  }
3175
2669
  };
3176
2670
  }
3177
- function isRecord6(value) {
2671
+ function isRecord5(value) {
3178
2672
  return typeof value === "object" && value !== null && !Array.isArray(value);
3179
2673
  }
3180
2674
  function str(value) {
@@ -3232,7 +2726,7 @@ function taskViews(args) {
3232
2726
  const sharedNode = str(args.node);
3233
2727
  const sharedTarget = str(args.target);
3234
2728
  return tasks.map((item) => {
3235
- const record3 = isRecord6(item) ? item : {};
2729
+ const record3 = isRecord5(item) ? item : {};
3236
2730
  const view = {
3237
2731
  agent: str(record3.agent) ?? sharedAgent,
3238
2732
  task: str(item) ?? str(record3.task) ?? "(invalid task)",
@@ -3275,7 +2769,7 @@ function canonicalCandidates(value) {
3275
2769
  if (!Array.isArray(value)) return null;
3276
2770
  const out = [];
3277
2771
  for (const item of value) {
3278
- if (!isRecord6(item)) return null;
2772
+ if (!isRecord5(item)) return null;
3279
2773
  const agentId = str(item.agentId);
3280
2774
  const target = str(item.target);
3281
2775
  const model = str(item.model);
@@ -3286,10 +2780,10 @@ function canonicalCandidates(value) {
3286
2780
  return out.length > 0 ? out : null;
3287
2781
  }
3288
2782
  function topologyOf(args) {
3289
- if (isRecord6(args.apply_winner)) return "compete";
2783
+ if (isRecord5(args.apply_winner)) return "compete";
3290
2784
  if (args.mode === "compete") return "compete";
3291
2785
  if (args.mode === "council") return "council";
3292
- if (args.review === true || isRecord6(args.review)) return "review";
2786
+ if (args.review === true || isRecord5(args.review)) return "review";
3293
2787
  if (args.detach === true) return "detached";
3294
2788
  if (args.mode === "sequential") return "sequential";
3295
2789
  if (args.mode === "pipeline") return "pipeline";
@@ -3372,14 +2866,14 @@ function renderPlanText(topology, tasks, costCeilingUsd, deadlineMs, source, max
3372
2866
  lines.push(...renderLegacyPathScope(task, cwd));
3373
2867
  for (const check of task.resolvedVerification ?? []) {
3374
2868
  lines.push(
3375
- ` verification check=${safeField(check.check)} argv=${JSON.stringify(check.argv)} cwd=${JSON.stringify(check.cwd)} timeout_ms=${check.timeoutMs}`
2869
+ ` verification check=${safeField(check.check)}${check.kind !== void 0 ? ` kind=${check.kind}` : ""} argv=${JSON.stringify(check.argv)} cwd=${JSON.stringify(check.cwd)} timeout_ms=${check.timeoutMs}`
3376
2870
  );
3377
2871
  }
3378
2872
  }
3379
2873
  return lines.join("\n");
3380
2874
  }
3381
2875
  function isResolvedTask(value) {
3382
- if (!isRecord6(value)) return false;
2876
+ if (!isRecord5(value)) return false;
3383
2877
  const allowedKeys = /* @__PURE__ */ new Set([
3384
2878
  "agent",
3385
2879
  "task",
@@ -3436,7 +2930,7 @@ function isResolvedTask(value) {
3436
2930
  }
3437
2931
  if (value.position !== void 0 && (!Number.isInteger(value.position) || Number(value.position) < 1)) return false;
3438
2932
  if (value.council !== void 0) {
3439
- if (!isRecord6(value.council) || typeof value.council.label !== "string" || value.council.label.length === 0 || value.council.color !== void 0 && typeof value.council.color !== "string" || !Number.isInteger(value.council.round) || Number(value.council.round) < 1 || !Number.isInteger(value.council.rounds) || Number(value.council.rounds) < 1 || value.council.synthesis !== "none" && value.council.synthesis !== "judge" && value.council.synthesis !== "vote")
2933
+ if (!isRecord5(value.council) || typeof value.council.label !== "string" || value.council.label.length === 0 || value.council.color !== void 0 && typeof value.council.color !== "string" || !Number.isInteger(value.council.round) || Number(value.council.round) < 1 || !Number.isInteger(value.council.rounds) || Number(value.council.rounds) < 1 || value.council.synthesis !== "none" && value.council.synthesis !== "judge" && value.council.synthesis !== "vote")
3440
2934
  return false;
3441
2935
  }
3442
2936
  if (value.nodeKind !== "local" && value.nodeKind !== "ssh") return false;
@@ -3464,7 +2958,7 @@ function isResolvedTask(value) {
3464
2958
  if (value.agentDecision !== null && !isAgentDecision(value.agentDecision)) return false;
3465
2959
  if (value.intent !== void 0 && !isDispatchIntent(value.intent)) return false;
3466
2960
  if (value.resolvedVerification !== void 0 && (!Array.isArray(value.resolvedVerification) || !value.resolvedVerification.every(
3467
- (check) => isRecord6(check) && typeof check.check === "string" && Array.isArray(check.argv) && check.argv.every((arg) => typeof arg === "string") && typeof check.cwd === "string" && typeof check.timeoutMs === "number"
2961
+ (check) => isRecord5(check) && typeof check.check === "string" && Array.isArray(check.argv) && check.argv.every((arg) => typeof arg === "string") && typeof check.cwd === "string" && typeof check.timeoutMs === "number" && (check.kind === void 0 || check.kind === "numeric-compare" || check.kind === "perf-budget") && (check.numeric === void 0 || isRecord5(check.numeric) && typeof check.numeric.reference === "string") && (check.perf === void 0 || isRecord5(check.perf))
3468
2962
  )))
3469
2963
  return false;
3470
2964
  if (value.failover === "approved") {
@@ -3493,13 +2987,13 @@ var RESULT_CONTRACT_KINDS = /* @__PURE__ */ new Set([
3493
2987
  "delegation-plan"
3494
2988
  ]);
3495
2989
  function isAuthorityGrant(value) {
3496
- return isRecord6(value) && Object.keys(value).sort().join("\0") === "basis\0requested" && AGENT_AUTOMATION_AUTHORITIES.includes(value.requested) && (value.basis === "operator-plan-approval" || value.basis === "full-auto-policy");
2990
+ return isRecord5(value) && Object.keys(value).sort().join("\0") === "basis\0requested" && AGENT_AUTOMATION_AUTHORITIES.includes(value.requested) && (value.basis === "operator-plan-approval" || value.basis === "full-auto-policy");
3497
2991
  }
3498
2992
  function isAgentDecision(value) {
3499
- return isRecord6(value) && value.policyVersion === ROUTE_POLICY_VERSION && (value.mode === "shadow" || value.mode === "active" || value.mode === "fixed") && isRecord6(value.selected) && isRecord6(value.executedRoute) && Array.isArray(value.approvedFallbacks) && Array.isArray(value.candidateEvaluations) && Array.isArray(value.hardConstraints) && Array.isArray(value.reasonCodes) && typeof value.decisionHash === "string" && /^[0-9a-f]{64}$/u.test(value.decisionHash) && isRouteDecisionAgentSelection(value.agentSelection);
2993
+ return isRecord5(value) && value.policyVersion === ROUTE_POLICY_VERSION && (value.mode === "shadow" || value.mode === "active" || value.mode === "fixed") && isRecord5(value.selected) && isRecord5(value.executedRoute) && Array.isArray(value.approvedFallbacks) && Array.isArray(value.candidateEvaluations) && Array.isArray(value.hardConstraints) && Array.isArray(value.reasonCodes) && typeof value.decisionHash === "string" && /^[0-9a-f]{64}$/u.test(value.decisionHash) && isRouteDecisionAgentSelection(value.agentSelection);
3500
2994
  }
3501
2995
  function isResolvedAgentSelection(value) {
3502
- if (!isRecord6(value)) return false;
2996
+ if (!isRecord5(value)) return false;
3503
2997
  if (Object.keys(value).sort().join("\0") !== ["approvedAuthorities", "authorityBasis", "baselineAgentId", "mode", "version"].sort().join("\0"))
3504
2998
  return false;
3505
2999
  if (value.version !== 1 || value.mode !== "auto") return false;
@@ -3513,7 +3007,7 @@ function isResolvedAgentSelection(value) {
3513
3007
  }
3514
3008
  function resolvedDispatchPlanFromArgs(args) {
3515
3009
  const value = args[RESOLVED_DISPATCH_PLAN_ARGUMENT];
3516
- if (!isRecord6(value) || value.version !== 3) return null;
3010
+ if (!isRecord5(value) || value.version !== 3) return null;
3517
3011
  const artifactKeys = /* @__PURE__ */ new Set([
3518
3012
  "version",
3519
3013
  "topology",
@@ -3541,7 +3035,7 @@ function resolvedDispatchPlanFromArgs(args) {
3541
3035
  if (!Array.isArray(value.tasks) || !value.tasks.every(isResolvedTask)) return null;
3542
3036
  let confirmation;
3543
3037
  if (value.confirmation !== void 0) {
3544
- if (!isRecord6(value.confirmation) || !["branch\0group\0index", "branch\0cwd\0group\0index"].includes(
3038
+ if (!isRecord5(value.confirmation) || !["branch\0group\0index", "branch\0cwd\0group\0index"].includes(
3545
3039
  Object.keys(value.confirmation).sort().join("\0")
3546
3040
  ) || typeof value.confirmation.branch !== "string" || value.confirmation.branch.trim().length === 0 || typeof value.confirmation.group !== "string" || value.confirmation.group.trim().length === 0 || value.confirmation.cwd !== void 0 && (typeof value.confirmation.cwd !== "string" || value.confirmation.cwd.trim().length === 0) || !Number.isInteger(value.confirmation.index) || Number(value.confirmation.index) < 1) {
3547
3041
  return null;
@@ -3620,7 +3114,7 @@ function resolvedDispatchPlanFromArgs(args) {
3620
3114
  }
3621
3115
  function parsePlanSource(value) {
3622
3116
  if (value === null) return null;
3623
- if (!isRecord6(value) || Object.keys(value).sort().join("\0") !== "executionPlanHash\0kind\0receiptDigest\0runId")
3117
+ if (!isRecord5(value) || Object.keys(value).sort().join("\0") !== "executionPlanHash\0kind\0receiptDigest\0runId")
3624
3118
  return void 0;
3625
3119
  if (value.kind !== "scout-transition" || typeof value.runId !== "string" || value.runId.length === 0 || typeof value.receiptDigest !== "string" || !/^[0-9a-f]{64}$/u.test(value.receiptDigest) || typeof value.executionPlanHash !== "string" || !/^[0-9a-f]{64}$/u.test(value.executionPlanHash))
3626
3120
  return void 0;
@@ -3647,7 +3141,7 @@ function describeDispatchPlan(rawArgs) {
3647
3141
  const maxWorkers = resolved?.maxWorkers ?? null;
3648
3142
  const onFailure = resolved?.onFailure ?? null;
3649
3143
  const remote = tasks.some((task) => task.node !== void 0 && task.node !== "local");
3650
- const planScale = !preparationFailed && args.list !== true && (tasks.length > 1 || source !== null || topology === "compete" || topology === "council" || remote || tasks.some((task) => task.failover === "approved") || confirmation !== void 0 || isRecord6(args.apply_winner));
3144
+ const planScale = !preparationFailed && args.list !== true && (tasks.length > 1 || source !== null || topology === "compete" || topology === "council" || remote || tasks.some((task) => task.failover === "approved") || confirmation !== void 0 || isRecord5(args.apply_winner));
3651
3145
  const text = renderPlanText(
3652
3146
  topology,
3653
3147
  tasks,
@@ -4144,7 +3638,7 @@ ${guidance}`,
4144
3638
  }
4145
3639
  function skillSurfaceBlockedVerdict(decision, tool, violation) {
4146
3640
  const lifetime = violation.carriedSurface ? "The narrowing stays active for the rest of the session, across the operator's later turns, until a different skill replaces it or the operator clears it with /skill off." : "The narrowing ends when the skill policy's turn or worker run ends.";
4147
- const reason = violation.disallowedBy.length > 0 ? `${tool} is disallowed by the active skill(s) ${violation.disallowedBy.join(", ")} (disallowed-tools). ${lifetime} Work within the skill workflow; if it genuinely needs this step, use ask_user when available or state the blocker in your reply.` : `${tool} is outside the tool surface declared by the active skill(s) ${violation.skills.join(", ")}. Tools are narrowed to: ${(violation.mergedAllowedTools ?? []).join(", ")} (plus context and ask_user). ${lifetime} Work within the skill workflow; if it genuinely needs this step, use ask_user when available or state the blocker in your reply.`;
3641
+ const reason = violation.disallowedBy.length > 0 ? `${tool} is disallowed by the active skill(s) ${violation.disallowedBy.join(", ")} (disallowed-tools). ${lifetime} Work within the skill workflow; if it genuinely needs this step, use ask_user when available or state the blocker in your reply.` : `${tool} is outside the tool surface declared by the active skill(s) ${violation.skills.join(", ")}. Tools are narrowed to: ${(violation.mergedAllowedTools ?? []).join(", ")} (plus context and ask_user). The limitation receipt is also available unless explicitly disallowed. ${lifetime} Work within the skill workflow; if it genuinely needs this step, use ask_user when available or state the blocker in your reply.`;
4148
3642
  const blocked = {
4149
3643
  kind: "block",
4150
3644
  classification: decision.classification,
@@ -4835,7 +4329,6 @@ function createProcessTreeTerminator(child, graceMs = 1500) {
4835
4329
  let sent = false;
4836
4330
  let timer = null;
4837
4331
  const signal = (name) => {
4838
- if (child.exitCode !== null) return;
4839
4332
  if (child.pid && process.platform !== "win32") {
4840
4333
  try {
4841
4334
  process.kill(-child.pid, name);
@@ -4843,6 +4336,7 @@ function createProcessTreeTerminator(child, graceMs = 1500) {
4843
4336
  } catch {
4844
4337
  }
4845
4338
  }
4339
+ if (child.exitCode !== null) return;
4846
4340
  child.kill(name);
4847
4341
  };
4848
4342
  return {
@@ -4850,11 +4344,17 @@ function createProcessTreeTerminator(child, graceMs = 1500) {
4850
4344
  if (sent) return;
4851
4345
  sent = true;
4852
4346
  signal("SIGTERM");
4853
- timer = setTimeout(() => signal("SIGKILL"), graceMs);
4347
+ timer = setTimeout(() => {
4348
+ timer = null;
4349
+ signal("SIGKILL");
4350
+ }, graceMs);
4854
4351
  },
4855
4352
  cleanup() {
4856
- if (timer) clearTimeout(timer);
4857
- timer = null;
4353
+ if (timer) {
4354
+ clearTimeout(timer);
4355
+ timer = null;
4356
+ signal("SIGKILL");
4357
+ }
4858
4358
  }
4859
4359
  };
4860
4360
  }
@@ -5221,7 +4721,6 @@ function startAntigravityWorkerRun(input, emit, dependencies = {}) {
5221
4721
  // src/engine/claude/subprocess-runtime.ts
5222
4722
  init_esm_shims();
5223
4723
  import { spawn as spawn2 } from "node:child_process";
5224
- import { createInterface } from "node:readline";
5225
4724
 
5226
4725
  // src/engine/claude/session-id.ts
5227
4726
  init_esm_shims();
@@ -5232,6 +4731,9 @@ function isClaudeCodeSessionId(value) {
5232
4731
 
5233
4732
  // src/engine/claude/subprocess-runtime.ts
5234
4733
  var READ_ONLY_CLAUDE_TOOLS = ["Read", "Grep", "Glob", "LS", "WebFetch", "WebSearch"];
4734
+ var CLAUDE_BINARY = "claude";
4735
+ var CLAUDE_MAX_STREAM_LINE_BYTES = 1024 * 1024;
4736
+ var CLAUDE_MAX_STREAM_BYTES = 8 * 1024 * 1024;
5235
4737
  function claudeSubprocessPermissionConfigForAutonomy(level, env = process.env) {
5236
4738
  if (level === "full-auto" && env.CLIO_CODER_ALLOW_EXTERNAL_FULL_ACCESS === "1") {
5237
4739
  return {
@@ -5262,9 +4764,9 @@ function buildClaudeCodePrompt(input) {
5262
4764
  parts.push(input.task);
5263
4765
  return parts.join("\n\n");
5264
4766
  }
5265
- function buildClaudeCodeArgs(input) {
4767
+ function buildClaudeCodeArgs(input, gateEnv = process.env) {
5266
4768
  assertToolProfileEnforceable(input.toolProfile, "claude-code");
5267
- const permission = claudeSubprocessPermissionConfigForAutonomy(input.autonomy);
4769
+ const permission = claudeSubprocessPermissionConfigForAutonomy(input.autonomy, gateEnv);
5268
4770
  const args = [
5269
4771
  "-p",
5270
4772
  "--output-format",
@@ -5279,7 +4781,6 @@ function buildClaudeCodeArgs(input) {
5279
4781
  const systemPrompt = input.systemPrompt.trim();
5280
4782
  if (systemPrompt.length > 0) args.push("--append-system-prompt", systemPrompt);
5281
4783
  if (isClaudeCodeSessionId(input.sessionId)) args.push("--session-id", input.sessionId.trim());
5282
- args.push(buildClaudeCodePrompt(input));
5283
4784
  return args;
5284
4785
  }
5285
4786
  function finite2(value) {
@@ -5343,7 +4844,9 @@ function resultError(record3, stderr) {
5343
4844
  return stderr.trim();
5344
4845
  }
5345
4846
  function buildAssistantMessage2(input) {
5346
- const errorMessage = input.exitCode === 0 ? "" : resultError(input.result, input.stderr);
4847
+ const transportError = input.transportError ?? "";
4848
+ const failed = input.exitCode !== 0 || transportError.length > 0;
4849
+ const errorMessage = !failed ? "" : transportError || resultError(input.result, input.stderr);
5347
4850
  const message = {
5348
4851
  role: "assistant",
5349
4852
  content: [{ type: "text", text: input.text }],
@@ -5351,12 +4854,12 @@ function buildAssistantMessage2(input) {
5351
4854
  provider: "anthropic",
5352
4855
  model: input.model,
5353
4856
  usage: normalizeUsage2(input.result?.usage, finite2(input.result?.total_cost_usd)),
5354
- stopReason: input.aborted ? "aborted" : input.exitCode === 0 ? "stop" : "error",
4857
+ stopReason: input.aborted ? "aborted" : failed ? "error" : "stop",
5355
4858
  timestamp: Date.now()
5356
4859
  };
5357
4860
  if (typeof input.result?.request_id === "string") message.responseId = input.result.request_id;
5358
4861
  if (typeof input.result?.model === "string") message.responseModel = input.result.model;
5359
- if (errorMessage.length > 0) message.errorMessage = errorMessage;
4862
+ if (errorMessage.length > 0) message.errorMessage = boundedExternalDiagnostic(errorMessage);
5360
4863
  return message;
5361
4864
  }
5362
4865
  function emitTextDelta2(emit, state, delta) {
@@ -5386,9 +4889,14 @@ function emitTextDelta2(emit, state, delta) {
5386
4889
  });
5387
4890
  }
5388
4891
  async function readJsonLines(child, emit, state) {
5389
- const rl = createInterface({ input: child.stdout });
5390
- for await (const line of rl) {
5391
- const trimmed = line.trim();
4892
+ for await (const bounded of readBoundedLines(child.stdout, {
4893
+ maxLineBytes: CLAUDE_MAX_STREAM_LINE_BYTES,
4894
+ maxTotalBytes: CLAUDE_MAX_STREAM_BYTES
4895
+ })) {
4896
+ if (bounded.kind === "oversized") {
4897
+ throw new Error(`claude stream-json line exceeded ${CLAUDE_MAX_STREAM_LINE_BYTES} bytes`);
4898
+ }
4899
+ const trimmed = bounded.line.trim();
5392
4900
  if (trimmed.length === 0) continue;
5393
4901
  let parsed;
5394
4902
  try {
@@ -5411,12 +4919,17 @@ async function readJsonLines(child, emit, state) {
5411
4919
  emitTextDelta2(emit, state, extractDelta(record3));
5412
4920
  }
5413
4921
  }
5414
- function startClaudeCodeWorkerRun(input, emit) {
5415
- const args = buildClaudeCodeArgs(input);
5416
- const child = spawn2("claude", args, {
5417
- cwd: process.cwd(),
5418
- env: process.env,
5419
- stdio: ["ignore", "pipe", "pipe"]
4922
+ function startClaudeCodeWorkerRun(input, emit, dependencies = {}) {
4923
+ const sourceEnv = dependencies.environment ?? process.env;
4924
+ const args = buildClaudeCodeArgs(input, sourceEnv);
4925
+ const prompt = buildClaudeCodePrompt(input);
4926
+ const workspaceRoot = dependencies.workspaceRoot ?? process.cwd();
4927
+ const cwd = resolveSafeCwd(input.cwd, workspaceRoot);
4928
+ const child = spawn2(dependencies.binary ?? CLAUDE_BINARY, args, {
4929
+ cwd,
4930
+ env: buildSafeToolEnv({}, sourceEnv),
4931
+ detached: process.platform !== "win32",
4932
+ stdio: ["pipe", "pipe", "pipe"]
5420
4933
  });
5421
4934
  const streamState = {
5422
4935
  started: false,
@@ -5425,51 +4938,61 @@ function startClaudeCodeWorkerRun(input, emit) {
5425
4938
  result: null
5426
4939
  };
5427
4940
  let aborted = false;
5428
- let killTimer = null;
4941
+ let settled = false;
4942
+ let transportError = "";
4943
+ const terminator = createProcessTreeTerminator(child, dependencies.killGraceMs ?? 1500);
5429
4944
  const abort = () => {
4945
+ if (settled) return;
5430
4946
  aborted = true;
5431
- if (child.killed) return;
5432
- child.kill("SIGTERM");
5433
- killTimer = setTimeout(() => {
5434
- if (!child.killed) child.kill("SIGKILL");
5435
- }, 1500);
4947
+ terminator.terminate();
5436
4948
  };
5437
- if (input.signal) {
5438
- if (input.signal.aborted) abort();
5439
- else input.signal.addEventListener("abort", abort, { once: true });
5440
- }
4949
+ const onAbort = () => abort();
4950
+ if (input.signal?.aborted) abort();
4951
+ else input.signal?.addEventListener("abort", onAbort, { once: true });
4952
+ child.once("error", (cause) => {
4953
+ transportError ||= cause.code === "ENOENT" ? "Claude Code CLI (`claude`) is not installed or not on PATH." : cause.message;
4954
+ });
4955
+ child.stdin.on("error", (cause) => {
4956
+ if (!aborted) transportError ||= `could not send prompt to Claude Code CLI: ${cause.message}`;
4957
+ });
4958
+ child.stdin.end(prompt);
5441
4959
  const promise = (async () => {
5442
4960
  emit({ type: "agent_start" });
5443
- const stderrPromise = readStderr(child);
5444
- const stdoutPromise = readJsonLines(child, emit, streamState);
5445
- const exitCode = await waitForClose(child);
5446
- await stdoutPromise.catch(() => {
5447
- });
5448
- const stderr = await stderrPromise.catch(() => "");
5449
- if (killTimer) clearTimeout(killTimer);
5450
- const finalText = streamState.text || resultText(streamState.result) || (exitCode === 0 ? "" : resultError(streamState.result, stderr));
5451
- const finalMessage = buildAssistantMessage2({
5452
- model: streamState.model,
5453
- text: finalText,
5454
- result: streamState.result,
5455
- exitCode,
5456
- aborted,
5457
- stderr
5458
- });
5459
- if (!streamState.started) emit({ type: "message_start", message: finalMessage });
5460
- emit({ type: "message_end", message: finalMessage });
5461
- const messages = [finalMessage];
5462
- emit({ type: "agent_end", messages });
5463
- if (exitCode !== 0 && stderr.trim().length > 0 && !aborted) {
5464
- process.stderr.write(`[worker:claude-code] ${stderr.trim()}
4961
+ try {
4962
+ const stderrPromise = readStderr(child);
4963
+ const stdoutPromise = readJsonLines(child, emit, streamState).catch((cause) => {
4964
+ transportError ||= cause instanceof Error ? cause.message : String(cause);
4965
+ terminator.terminate();
4966
+ });
4967
+ const exitCode = await waitForClose(child);
4968
+ await stdoutPromise;
4969
+ const stderr = await stderrPromise.catch(() => "");
4970
+ const finalText = streamState.text || resultText(streamState.result) || (exitCode === 0 ? "" : resultError(streamState.result, stderr));
4971
+ const finalMessage = buildAssistantMessage2({
4972
+ model: streamState.model,
4973
+ text: finalText,
4974
+ result: streamState.result,
4975
+ exitCode,
4976
+ aborted,
4977
+ stderr,
4978
+ transportError
4979
+ });
4980
+ if (!streamState.started) emit({ type: "message_start", message: finalMessage });
4981
+ emit({ type: "message_end", message: finalMessage });
4982
+ const messages = [finalMessage];
4983
+ emit({ type: "agent_end", messages });
4984
+ if (finalMessage.stopReason === "error" && finalMessage.errorMessage && !aborted) {
4985
+ process.stderr.write(`[worker:claude-code] ${finalMessage.errorMessage}
5465
4986
  `);
4987
+ }
4988
+ return { messages, exitCode: finalMessage.stopReason === "stop" ? 0 : 1 };
4989
+ } finally {
4990
+ settled = true;
4991
+ terminator.cleanup();
4992
+ input.signal?.removeEventListener("abort", onAbort);
5466
4993
  }
5467
- return { messages, exitCode: exitCode === 0 ? 0 : 1 };
5468
4994
  })();
5469
- return {
5470
- promise,
5471
- abort
5472
- };
4995
+ return { promise, abort };
5473
4996
  }
5474
4997
 
5475
4998
  // src/engine/worker-runtime-capabilities.ts
@@ -5491,6 +5014,7 @@ var FOLDED_WITH_DIFF = {
5491
5014
  failureExcerpt: true
5492
5015
  };
5493
5016
  var TOOL_PRESENTATION = {
5017
+ [ToolNames.Evidence]: FOLDED,
5494
5018
  [ToolNames.Read]: FOLDED,
5495
5019
  [ToolNames.Grep]: FOLDED,
5496
5020
  [ToolNames.Find]: FOLDED,
@@ -5509,6 +5033,8 @@ var TOOL_PRESENTATION = {
5509
5033
  [ToolNames.Tasks]: FOLDED,
5510
5034
  [ToolNames.Ledger]: FOLDED,
5511
5035
  [ToolNames.Panes]: FOLDED,
5036
+ [ToolNames.Limitation]: FOLDED,
5037
+ [ToolNames.Decide]: FOLDED,
5512
5038
  [ToolNames.WebFetch]: FOLDED,
5513
5039
  [ToolNames.AskUser]: FOLDED,
5514
5040
  [ToolNames.Artifact]: FOLDED
@@ -5520,9 +5046,9 @@ function readStringField(args, key) {
5520
5046
  }
5521
5047
  function classifyResourceRead(toolName, args) {
5522
5048
  if (toolName !== ToolNames.Read) return null;
5523
- const path5 = readStringField(args, "path");
5524
- if (path5 === null) return null;
5525
- const normalized = path5.replace(/\\/g, "/");
5049
+ const path4 = readStringField(args, "path");
5050
+ if (path4 === null) return null;
5051
+ const normalized = path4.replace(/\\/g, "/");
5526
5052
  const base = normalized.split("/").pop() ?? "";
5527
5053
  if (base === "SKILL.md") return "skill";
5528
5054
  if (base === "CLIO-CODER.md") return "handbook";
@@ -5891,6 +5417,13 @@ var exactMutationPolicy = {
5891
5417
  };
5892
5418
  var TOOL_METADATA = {
5893
5419
  // OBSERVE: read-class, parallel, envelope + shared turn budget.
5420
+ [ToolNames.Evidence]: {
5421
+ objective: "Inspect canonical evidence, trust status, gate decisions, and findings.",
5422
+ uiLabel: "Evidence",
5423
+ retrySafety: "idempotent",
5424
+ resultSizePolicy: summaryPolicy("Inspect one run with evidence(mode=run, runId=<id>) to narrow the output."),
5425
+ costLatency: "local_medium"
5426
+ },
5894
5427
  [ToolNames.Read]: {
5895
5428
  objective: "Read exact UTF-8 file content with line and byte bounds.",
5896
5429
  uiLabel: "Read",
@@ -6078,6 +5611,30 @@ var TOOL_METADATA = {
6078
5611
  costLatency: "local_fast",
6079
5612
  promptHint: 'When the operator asks to see a dispatched agent ("show me the tester"), call panes(action="show", target=<agent id>).'
6080
5613
  },
5614
+ [ToolNames.Limitation]: {
5615
+ objective: "Record what the turn could not verify and why as a ledger receipt.",
5616
+ uiLabel: "Limitation",
5617
+ retrySafety: "idempotent",
5618
+ resultSizePolicy: {
5619
+ kind: "exact",
5620
+ maxBytes: 4096,
5621
+ followUpHint: "Call limitation again with a narrower scope if the first call was rejected."
5622
+ },
5623
+ costLatency: "local_fast"
5624
+ },
5625
+ [ToolNames.Decide]: {
5626
+ objective: "Record a design decision with its rejected alternatives and rationale on the session decision board.",
5627
+ uiLabel: "Decide",
5628
+ // A repeated call with the same key supersedes the earlier record, so
5629
+ // the surface as a whole is not retry safe.
5630
+ retrySafety: "not_retry_safe",
5631
+ resultSizePolicy: {
5632
+ kind: "exact",
5633
+ maxBytes: 4096,
5634
+ followUpHint: "The decision ref in the result is what receipts and commits cite."
5635
+ },
5636
+ costLatency: "local_fast"
5637
+ },
6081
5638
  // RETRIEVE: network-class.
6082
5639
  [ToolNames.WebFetch]: {
6083
5640
  objective: "Fetch HTTP(S) text for explicit external research.",
@@ -6142,7 +5699,7 @@ function builtin(spec, sourceInfo) {
6142
5699
 
6143
5700
  // src/domains/agents/result-contract-filesystem.ts
6144
5701
  init_esm_shims();
6145
- import { existsSync as existsSync2, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
5702
+ import { existsSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
6146
5703
  function nodeResultContractFilesystem() {
6147
5704
  return {
6148
5705
  readFile(filePath) {
@@ -6153,7 +5710,7 @@ function nodeResultContractFilesystem() {
6153
5710
  }
6154
5711
  },
6155
5712
  pathExists(filePath) {
6156
- return existsSync2(filePath);
5713
+ return existsSync(filePath);
6157
5714
  },
6158
5715
  isDirectory(filePath) {
6159
5716
  return statSync2(filePath, { throwIfNoEntry: false })?.isDirectory() === true;
@@ -6163,7 +5720,7 @@ function nodeResultContractFilesystem() {
6163
5720
 
6164
5721
  // src/domains/safety/run-effects.ts
6165
5722
  init_esm_shims();
6166
- import path4 from "node:path";
5723
+ import path3 from "node:path";
6167
5724
  var ENUMERABLE_ACTION_CLASSES = /* @__PURE__ */ new Set(["read", "write"]);
6168
5725
  function toolWritesOpaquely(toolName) {
6169
5726
  return !ENUMERABLE_ACTION_CLASSES.has(classify({ tool: toolName }).actionClass);
@@ -6215,11 +5772,11 @@ function createRunEffectsRecorder(cwd, options = {}) {
6215
5772
  const verificationCommand = validationCommandOf(toolName, args, "grounding");
6216
5773
  const opaque = toolWritesOpaquely(toolName);
6217
5774
  if (!opaque && paths.length === 0 && validationCommand === null && verificationCommand === null) return;
6218
- const base = typeof args?.cwd === "string" && args.cwd.length > 0 ? path4.resolve(cwd, args.cwd) : cwd;
5775
+ const base = typeof args?.cwd === "string" && args.cwd.length > 0 ? path3.resolve(cwd, args.cwd) : cwd;
6219
5776
  pending.set(toolCallId, {
6220
5777
  tool: toolName,
6221
5778
  toolCallId,
6222
- paths: paths.map((target) => path4.resolve(base, target)),
5779
+ paths: paths.map((target) => path3.resolve(base, target)),
6223
5780
  validationCommand,
6224
5781
  verificationCommand,
6225
5782
  opaque
@@ -6287,8 +5844,8 @@ function claimConflicts(body, live, runId) {
6287
5844
  }
6288
5845
  return conflicts;
6289
5846
  }
6290
- function citedPathKey(path5) {
6291
- const trimmed = path5.trim();
5847
+ function citedPathKey(path4) {
5848
+ const trimmed = path4.trim();
6292
5849
  if (trimmed.length === 0) return trimmed;
6293
5850
  const absolute = isAbsolute(trimmed);
6294
5851
  const candidate = absolute ? relative(process.cwd(), trimmed) : trimmed;
@@ -6300,21 +5857,21 @@ function corroboration(entries) {
6300
5857
  const runsByPath = /* @__PURE__ */ new Map();
6301
5858
  for (const entry of entries) {
6302
5859
  if (entry.body.kind !== "finding") continue;
6303
- const path5 = entry.body.path === void 0 ? void 0 : citedPathKey(entry.body.path);
6304
- if (path5 === void 0) continue;
6305
- const runs = runsByPath.get(path5) ?? [];
5860
+ const path4 = entry.body.path === void 0 ? void 0 : citedPathKey(entry.body.path);
5861
+ if (path4 === void 0) continue;
5862
+ const runs = runsByPath.get(path4) ?? [];
6306
5863
  if (!runs.includes(entry.runId)) runs.push(entry.runId);
6307
- runsByPath.set(path5, runs);
5864
+ runsByPath.set(path4, runs);
6308
5865
  }
6309
5866
  const byEntryId = /* @__PURE__ */ new Map();
6310
5867
  for (const entry of entries) {
6311
5868
  if (entry.body.kind !== "finding") continue;
6312
- const path5 = entry.body.path;
6313
- if (path5 === void 0) {
5869
+ const path4 = entry.body.path;
5870
+ if (path4 === void 0) {
6314
5871
  byEntryId.set(entry.id, "ungrounded lead");
6315
5872
  continue;
6316
5873
  }
6317
- const runs = runsByPath.get(citedPathKey(path5)) ?? [];
5874
+ const runs = runsByPath.get(citedPathKey(path4)) ?? [];
6318
5875
  byEntryId.set(entry.id, runs.length >= 2 ? "corroborated" : "uncorroborated");
6319
5876
  }
6320
5877
  return { byEntryId, byPath: runsByPath };
@@ -6381,7 +5938,7 @@ function renderAll(entries) {
6381
5938
  // src/engine/claude/tool-safety.ts
6382
5939
  init_esm_shims();
6383
5940
  import { performance as performance2 } from "node:perf_hooks";
6384
- function isRecord7(value) {
5941
+ function isRecord6(value) {
6385
5942
  return typeof value === "object" && value !== null && !Array.isArray(value);
6386
5943
  }
6387
5944
  function stringField(record3, ...keys) {
@@ -6392,8 +5949,8 @@ function stringField(record3, ...keys) {
6392
5949
  return void 0;
6393
5950
  }
6394
5951
  function pathArgs(input) {
6395
- const path5 = stringField(input, "file_path", "filePath", "path", "notebook_path", "source", "target");
6396
- return path5 ? { ...input, path: path5 } : { ...input };
5952
+ const path4 = stringField(input, "file_path", "filePath", "path", "notebook_path", "source", "target");
5953
+ return path4 ? { ...input, path: path4 } : { ...input };
6397
5954
  }
6398
5955
  function commandArgs(input, cwd) {
6399
5956
  const command = stringField(input, "command", "cmd", "shell", "input", "description") ?? JSON.stringify(input);
@@ -6654,7 +6211,7 @@ function emitClaudeToolPermissionDecision(input) {
6654
6211
  return decision;
6655
6212
  }
6656
6213
  function coerceToolInput(value) {
6657
- return isRecord7(value) ? value : {};
6214
+ return isRecord6(value) ? value : {};
6658
6215
  }
6659
6216
 
6660
6217
  export {
@@ -6692,14 +6249,6 @@ export {
6692
6249
  cancelledAskUserResult,
6693
6250
  finalizeAskUserInterviewForHost,
6694
6251
  createAskUserTool,
6695
- resolveDispatchPathScope,
6696
- declaredScopeReplacementDiagnostic,
6697
- declaredScopeReplacementNotice,
6698
- inferredScopeParentTokenDiagnostic,
6699
- inferredScopeParentTokenNotice,
6700
- declaredScopeIntent,
6701
- narrowDispatchIntentToReadOnly,
6702
- normalizeDispatchIntent,
6703
6252
  assertApprovedAssignmentRoute,
6704
6253
  approvedRouteCandidates,
6705
6254
  assertApprovedRecoveryCapability,
@@ -6759,4 +6308,4 @@ export {
6759
6308
  isTerminalRunEnvelope,
6760
6309
  runKindSupportsLiveSteering
6761
6310
  };
6762
- //# sourceMappingURL=chunk-PAJQJ7BS.js.map
6311
+ //# sourceMappingURL=chunk-75W7L2E2.js.map