@iowarp/clio-coder 0.3.0 → 0.3.2

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 (1187) hide show
  1. package/CHANGELOG.md +123 -2
  2. package/CONTRIBUTING.md +23 -23
  3. package/README.md +295 -627
  4. package/dist/acp-BIYHVZIM.js +128 -0
  5. package/dist/{agents-Q4MYPMUW.js → agents-YT6SSRIT.js} +52 -27
  6. package/dist/assets/codewiki.json +1 -0
  7. package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
  8. package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
  9. package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
  10. package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
  11. package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
  12. package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
  13. package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
  14. package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
  15. package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
  16. package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
  17. package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
  18. package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
  19. package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
  20. package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
  21. package/dist/assets/grammars/tree-sitter.wasm +0 -0
  22. package/dist/{auth-O6HYIJ6J.js → auth-5TWEIYDN.js} +30 -15
  23. package/dist/chunk-2EHAIA3X.js +481 -0
  24. package/dist/{chunk-ME6DNWIU.js → chunk-2IR2NMPA.js} +12 -4
  25. package/dist/chunk-2SFS6XQE.js +122 -0
  26. package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
  27. package/dist/chunk-2VTFPG5O.js +48 -0
  28. package/dist/chunk-3I7MS7N2.js +40 -0
  29. package/dist/chunk-3R73A4XB.js +69 -0
  30. package/dist/{chunk-JPOWPFCU.js → chunk-3ZXDFGR5.js} +52 -23
  31. package/dist/chunk-4BJ5BYCE.js +61 -0
  32. package/dist/{chunk-26BZQOAD.js → chunk-4BPJXDWC.js} +161 -260
  33. package/dist/chunk-4KLWL3UC.js +18 -0
  34. package/dist/{chunk-5LDRNKX2.js → chunk-4VP4KH3K.js} +161 -262
  35. package/dist/chunk-4ZG3XFUR.js +77 -0
  36. package/dist/chunk-5B2AEOW5.js +5407 -0
  37. package/dist/chunk-5TSRNF4G.js +510 -0
  38. package/dist/{chunk-WD6AJM35.js → chunk-5UUP6MWO.js} +48 -69
  39. package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
  40. package/dist/chunk-65DEGPJ6.js +52 -0
  41. package/dist/chunk-6EJMN2Y3.js +17 -0
  42. package/dist/chunk-6EJV5X2W.js +16405 -0
  43. package/dist/chunk-6N5PTWMY.js +136 -0
  44. package/dist/chunk-6XLNIQDB.js +27 -0
  45. package/dist/{chunk-XNISANGE.js → chunk-77VKQEHF.js} +171 -74
  46. package/dist/chunk-7CR24IG7.js +242 -0
  47. package/dist/{chunk-UWIJNAOB.js → chunk-7EYHLWU7.js} +907 -638
  48. package/dist/chunk-7MNJORFF.js +22 -0
  49. package/dist/{chunk-JWHCJDCI.js → chunk-A3CYT5EX.js} +257 -79
  50. package/dist/chunk-AGYYIBLL.js +1069 -0
  51. package/dist/chunk-AO4RKG4M.js +277 -0
  52. package/dist/chunk-APJ265NV.js +7410 -0
  53. package/dist/chunk-ARBGF5F7.js +174 -0
  54. package/dist/{chunk-TFSSEXL6.js → chunk-BMEMKKIT.js} +14 -4
  55. package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
  56. package/dist/chunk-CBCAPZAA.js +229 -0
  57. package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
  58. package/dist/chunk-CMZWFGD2.js +352 -0
  59. package/dist/chunk-ECH6PKUQ.js +39 -0
  60. package/dist/{chunk-67MTHP2E.js → chunk-ED4KHGC3.js} +13 -5
  61. package/dist/chunk-EKMEHE4H.js +340 -0
  62. package/dist/{chunk-O4EJEDHO.js → chunk-EPVUXGXG.js} +50 -35
  63. package/dist/chunk-FCSXB6T2.js +338 -0
  64. package/dist/chunk-FJ3H4MN5.js +48 -0
  65. package/dist/chunk-FQ4SKYE4.js +29 -0
  66. package/dist/chunk-G2DE3C7R.js +644 -0
  67. package/dist/chunk-G4BMMOKF.js +182 -0
  68. package/dist/{chunk-7BHLZB3A.js → chunk-GGXXDWE4.js} +190 -1218
  69. package/dist/chunk-HC4CLZ2Y.js +68 -0
  70. package/dist/{chunk-E3NYWENM.js → chunk-HFSBBKSQ.js} +55 -61
  71. package/dist/chunk-HKIYEGME.js +30 -0
  72. package/dist/chunk-I4HZDVNP.js +73 -0
  73. package/dist/chunk-IGLFWIYI.js +161 -0
  74. package/dist/chunk-IHXBNWMM.js +137 -0
  75. package/dist/chunk-IKCO5N3L.js +162 -0
  76. package/dist/chunk-IR4CFBFN.js +56 -0
  77. package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
  78. package/dist/{chunk-VOO7NYPP.js → chunk-J5HN4RYU.js} +27 -9
  79. package/dist/{chunk-4UQA7NCT.js → chunk-J5Q24KAG.js} +7 -2
  80. package/dist/{chunk-KBR4MZZR.js → chunk-JVCV3ICN.js} +7 -1
  81. package/dist/chunk-KJ5LWLOE.js +1077 -0
  82. package/dist/chunk-LBMZMYH2.js +285 -0
  83. package/dist/{chunk-3DANZDGR.js → chunk-LBNRH5WM.js} +100 -161
  84. package/dist/{chunk-TKHQ4DGZ.js → chunk-LZSJBIVT.js} +7358 -7414
  85. package/dist/{chunk-UGYAX5YI.js → chunk-M6SHUN7Q.js} +13 -8
  86. package/dist/chunk-MAW544W2.js +1882 -0
  87. package/dist/chunk-MBS4V7ZP.js +217 -0
  88. package/dist/{chunk-2J63S4SF.js → chunk-MFFY33HR.js} +167 -140
  89. package/dist/chunk-MNA4JGU4.js +255 -0
  90. package/dist/chunk-MQSRRFWA.js +3428 -0
  91. package/dist/{chunk-RQDWMVRB.js → chunk-MVVUPGPW.js} +138 -137
  92. package/dist/chunk-OAO4GE4M.js +619 -0
  93. package/dist/chunk-OHHN2SO4.js +5135 -0
  94. package/dist/chunk-OKGUZO2U.js +34 -0
  95. package/dist/{chunk-BBUH4VAA.js → chunk-OOJYHWRB.js} +60 -361
  96. package/dist/{chunk-D5YD55AR.js → chunk-OQ33BKR3.js} +12 -1
  97. package/dist/chunk-OQE5J4C6.js +73 -0
  98. package/dist/{chunk-AMFR5YA3.js → chunk-ORBHGJC5.js} +26 -12
  99. package/dist/chunk-POHLU5DW.js +1186 -0
  100. package/dist/chunk-QKMUKYO7.js +4961 -0
  101. package/dist/{chunk-7RBKDI66.js → chunk-QTYWRVRA.js} +104 -12
  102. package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
  103. package/dist/chunk-SRF2PJNW.js +184 -0
  104. package/dist/chunk-SST6Z5JA.js +80 -0
  105. package/dist/{chunk-XV4ZJ6ZM.js → chunk-STBPMHSX.js} +473 -1194
  106. package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
  107. package/dist/chunk-T6YILFSB.js +80 -0
  108. package/dist/chunk-TXOTCRLG.js +15 -0
  109. package/dist/chunk-TZTZS7QK.js +227 -0
  110. package/dist/chunk-UOV2BYIW.js +107 -0
  111. package/dist/{chunk-527KG6XR.js → chunk-V4RXGQ5Q.js} +72 -185
  112. package/dist/chunk-VAKQQHWR.js +434 -0
  113. package/dist/chunk-VG7TBQIY.js +128 -0
  114. package/dist/chunk-VJWL6YS5.js +244 -0
  115. package/dist/chunk-WEH5XRJQ.js +32 -0
  116. package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
  117. package/dist/chunk-WMSVI4G2.js +2095 -0
  118. package/dist/chunk-WVO7V2QY.js +797 -0
  119. package/dist/chunk-X4RCMKVQ.js +641 -0
  120. package/dist/chunk-X75S7HFS.js +374 -0
  121. package/dist/chunk-XN3L4EYL.js +46 -0
  122. package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
  123. package/dist/{chunk-PIDUD6M2.js → chunk-YCWGATWI.js} +12 -5
  124. package/dist/chunk-YHZX5GEU.js +193 -0
  125. package/dist/chunk-YXLYO42X.js +91 -0
  126. package/dist/{chunk-UHTSULZS.js → chunk-ZDOOVTXZ.js} +38 -73
  127. package/dist/chunk-ZI647VB5.js +37 -0
  128. package/dist/{chunk-CLJ5HLUD.js → chunk-ZWLZP4ZT.js} +25 -6
  129. package/dist/cli/index.js +70 -56
  130. package/dist/clio-4LY5K2AC.js +25 -0
  131. package/dist/code-nav-7AX6FYE6.js +600 -0
  132. package/dist/codewiki/build-worker.js +66 -0
  133. package/dist/compile-cache-CVJMMODC.js +18 -0
  134. package/dist/{components-JVHMUBEB.js → components-KELWS457.js} +31 -9
  135. package/dist/{config-ZFCDBMDC.js → config-GTLUW2PR.js} +104 -56
  136. package/dist/configure-R6A64DHX.js +42 -0
  137. package/dist/context-5VKGUVJJ.js +866 -0
  138. package/dist/{context-CDXTP2MP.js → context-JFZEJ7W5.js} +21 -13
  139. package/dist/{context-E3KIFVXI.js → context-RW5HC47S.js} +77 -36
  140. package/dist/{context-clear-3F4PLXOS.js → context-clear-6ZHBAZZT.js} +64 -30
  141. package/dist/{context-index-Q7YSYTR3.js → context-index-BZ4UYMTC.js} +36 -24
  142. package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
  143. package/dist/{docs-YIETIWZI.js → docs-2C2LTVT2.js} +32 -13
  144. package/dist/doctor-KI767GSN.js +87 -0
  145. package/dist/{eval-B3KZZESM.js → eval-XSSNATB4.js} +93 -27
  146. package/dist/{evidence-V67CHM35.js → evidence-UA6AWDQQ.js} +55 -27
  147. package/dist/{evolve-YDZSUQYA.js → evolve-QNTFGV6Z.js} +59 -26
  148. package/dist/{extensions-SRG7XCAH.js → extensions-QVDOHDGJ.js} +23 -8
  149. package/dist/{fleet-CA2CRTVG.js → fleet-Q7UOMUSG.js} +173 -56
  150. package/dist/fleet-preflight-DDN536IT.js +26 -0
  151. package/dist/{init-2OZDJE2D.js → init-WBB65ZHQ.js} +79 -34
  152. package/dist/{memory-3PIQQAKX.js → memory-MD3O64RI.js} +57 -28
  153. package/dist/{models-DY35XI7Y.js → models-BZU34YWD.js} +49 -24
  154. package/dist/monitor-MEQA5C3I.js +661 -0
  155. package/dist/{chunk-PS4PFJQP.js → orchestrator-CGFKEP27.js} +22837 -18564
  156. package/dist/{paths-5OMXW7Z4.js → paths-UXLN5YYZ.js} +17 -6
  157. package/dist/preload-P6DGH2PZ.js +13 -0
  158. package/dist/{reset-PIFYNOS3.js → reset-L2FQEE3E.js} +25 -13
  159. package/dist/{run-3VSPP24F.js → run-IV4Q6RLN.js} +115 -63
  160. package/dist/{share-D36RQCXM.js → share-S5BZQC5I.js} +23 -10
  161. package/dist/{skills-F2MRLELY.js → skills-LQEKRDTN.js} +42 -15
  162. package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-3DC4HEWS.js} +90 -45
  163. package/dist/steer-GGWFUJUD.js +77 -0
  164. package/dist/{targets-DZMEZAH4.js → targets-C4SSGQOB.js} +78 -60
  165. package/dist/terminal-lease-IT5JW2NR.js +395 -0
  166. package/dist/{trace-7NYCUI2J.js → trace-PNCASAXC.js} +48 -17
  167. package/dist/tree-sitter-HGKH6LG4.js +4673 -0
  168. package/dist/{uninstall-AD3JWHBB.js → uninstall-FZCQCDKC.js} +19 -8
  169. package/dist/{upgrade-WYYBKGDY.js → upgrade-7TT7SQ3G.js} +66 -24
  170. package/dist/{usage-ULIDAGFF.js → usage-GV4PKT3M.js} +71 -32
  171. package/dist/verify-G6V4D2G7.js +716 -0
  172. package/dist/version-KGEG7EPO.js +21 -0
  173. package/dist/web-fetch-2YHJ3KTG.js +638 -0
  174. package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-DQF6Z66B.js} +98 -48
  175. package/dist/worker/entry.js +297 -54
  176. package/dist/workspace-G4ZWUIPR.js +22 -0
  177. package/docs/README.md +29 -21
  178. package/docs/acp.md +191 -16
  179. package/docs/alcf-provider.md +1 -1
  180. package/docs/architecture.md +157 -7
  181. package/docs/artifact-placement.md +101 -0
  182. package/docs/artifact-versions.md +1 -1
  183. package/docs/built-in-agents.md +4 -2
  184. package/docs/capacity-and-scheduling.md +1 -1
  185. package/docs/commands-and-modes.md +224 -97
  186. package/docs/config-knobs-audit.md +1 -3
  187. package/docs/configuration-and-targets.md +236 -38
  188. package/docs/context-engine.md +34 -7
  189. package/docs/development-pipeline.md +102 -0
  190. package/docs/dispatch-architecture-rationale.md +1 -1
  191. package/docs/documentation-coverage.md +4 -4
  192. package/docs/documentation-guide.md +3 -3
  193. package/docs/environment-variables.md +15 -6
  194. package/docs/eval-runner.md +3 -3
  195. package/docs/evals-internal.md +2 -2
  196. package/docs/evidence-and-memory.md +10 -2
  197. package/docs/evolution.md +2 -2
  198. package/docs/exit-codes-and-output.md +15 -9
  199. package/docs/extensions-and-sharing.md +25 -18
  200. package/docs/fleet-demo-runbook.md +22 -23
  201. package/docs/fleet-dispatch.md +117 -16
  202. package/docs/git-commit-provenance.md +120 -0
  203. package/docs/glossary.md +107 -15
  204. package/docs/installation-and-lifecycle.md +75 -17
  205. package/docs/middleware-and-components.md +1 -1
  206. package/docs/model-catalog.md +46 -15
  207. package/docs/observability.md +8 -5
  208. package/docs/performance-methodology.md +491 -0
  209. package/docs/pi-boundary.md +72 -0
  210. package/docs/proactive-memory.md +14 -14
  211. package/docs/prompt-envelope-and-tools.md +25 -4
  212. package/docs/provider-adapter-cookbook.md +57 -4
  213. package/docs/release-cut-checklist.md +129 -111
  214. package/docs/safety-model.md +28 -8
  215. package/docs/scientific-validation.md +3 -3
  216. package/docs/session-lifecycle.md +55 -12
  217. package/docs/skills-marketplace.md +12 -8
  218. package/docs/time-conventions.md +101 -0
  219. package/docs/tool-usage.md +6 -5
  220. package/docs/trace-store.md +1 -1
  221. package/docs/troubleshooting.md +10 -7
  222. package/docs/tui-design.md +121 -28
  223. package/docs/worker-dispatch-mechanics.md +3 -3
  224. package/package.json +33 -36
  225. package/skills/README.md +5 -6
  226. package/skills/coding/ast-grep/SKILL.md +136 -0
  227. package/skills/coding/ast-grep/evals.md +56 -0
  228. package/skills/coding/ast-grep/references/rule_reference.md +297 -0
  229. package/skills/coding/coding-standards/SKILL.md +113 -0
  230. package/skills/coding/coding-standards/evals.md +34 -0
  231. package/skills/coding/prototype/SKILL.md +86 -0
  232. package/skills/coding/prototype/evals.md +42 -0
  233. package/skills/coding/prototype/references/LOGIC.md +67 -0
  234. package/skills/coding/prototype/references/UI.md +112 -0
  235. package/skills/coding/tdd/SKILL.md +101 -0
  236. package/skills/coding/tdd/evals.md +41 -0
  237. package/skills/coding/tdd/references/mocking.md +59 -0
  238. package/skills/coding/tdd/references/tests.md +77 -0
  239. package/skills/context/context-handoff/SKILL.md +126 -0
  240. package/skills/context/context-handoff/evals.md +57 -0
  241. package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
  242. package/skills/context/context-prime/SKILL.md +95 -0
  243. package/skills/context/context-prime/evals.md +54 -0
  244. package/skills/git/file-ticket/SKILL.md +107 -0
  245. package/skills/git/file-ticket/evals.md +54 -0
  246. package/skills/git/fix-issue/SKILL.md +106 -0
  247. package/skills/git/fix-issue/evals.md +71 -0
  248. package/skills/git/ship/SKILL.md +92 -0
  249. package/skills/git/ship/evals.md +72 -0
  250. package/skills/meta/clio-dev/SKILL.md +91 -0
  251. package/skills/meta/clio-dev/evals.md +45 -0
  252. package/skills/meta/clio-test/SKILL.md +130 -0
  253. package/skills/meta/clio-test/evals.md +43 -0
  254. package/skills/meta/clio-test/references/harness.md +97 -0
  255. package/skills/meta/clio-test/references/test-map.md +59 -0
  256. package/skills/meta/credentials/SKILL.md +125 -0
  257. package/skills/meta/credentials/evals.md +104 -0
  258. package/skills/meta/find-skills/SKILL.md +72 -0
  259. package/skills/meta/find-skills/evals.md +47 -0
  260. package/skills/meta/herdr/SKILL.md +127 -0
  261. package/skills/meta/herdr/evals.md +38 -0
  262. package/skills/meta/skill-craft/SKILL.md +102 -0
  263. package/skills/meta/skill-craft/evals.md +41 -0
  264. package/skills/planning/architecture/SKILL.md +129 -0
  265. package/skills/planning/architecture/evals.md +36 -0
  266. package/skills/planning/backlog/SKILL.md +90 -0
  267. package/skills/planning/backlog/evals.md +43 -0
  268. package/skills/planning/prd/SKILL.md +82 -0
  269. package/skills/planning/prd/evals.md +49 -0
  270. package/skills/planning/product-intent/SKILL.md +112 -0
  271. package/skills/planning/product-intent/evals.md +36 -0
  272. package/skills/planning/tech-spec/SKILL.md +115 -0
  273. package/skills/planning/tech-spec/evals.md +47 -0
  274. package/skills/registry.yaml +136 -0
  275. package/skills/research/arxiv-literature/SKILL.md +104 -0
  276. package/skills/research/arxiv-literature/evals.md +58 -0
  277. package/skills/research/experiment-protocol/SKILL.md +122 -0
  278. package/skills/research/experiment-protocol/evals.md +91 -0
  279. package/skills/research/scientific-debugging/SKILL.md +119 -0
  280. package/skills/research/scientific-debugging/evals.md +138 -0
  281. package/skills/research/scientific-modernization/SKILL.md +138 -0
  282. package/skills/research/scientific-modernization/evals.md +84 -0
  283. package/skills/skill-marketplace.json +12 -20
  284. package/skills/workflow/design-council/SKILL.md +139 -0
  285. package/skills/workflow/design-council/evals.md +97 -0
  286. package/skills/workflow/grill-me/SKILL.md +186 -0
  287. package/skills/workflow/grill-me/evals.md +78 -0
  288. package/skills/workflow/workflow-distiller/SKILL.md +136 -0
  289. package/skills/workflow/workflow-distiller/evals.md +107 -0
  290. package/src/cli/acp.ts +115 -0
  291. package/src/cli/agents.ts +60 -0
  292. package/src/cli/args.ts +280 -0
  293. package/src/cli/argv.ts +170 -0
  294. package/src/cli/ask.ts +34 -0
  295. package/src/cli/auth.ts +468 -0
  296. package/src/cli/bootstrap-generate.ts +498 -0
  297. package/src/cli/clio.ts +96 -0
  298. package/src/cli/components.ts +195 -0
  299. package/src/cli/config-inspect.ts +336 -0
  300. package/src/cli/config.ts +72 -0
  301. package/src/cli/configure-interop.ts +67 -0
  302. package/src/cli/configure-layout.ts +172 -0
  303. package/src/cli/configure.ts +1525 -0
  304. package/src/cli/context-clear.ts +76 -0
  305. package/src/cli/context-index.ts +100 -0
  306. package/src/cli/context.ts +321 -0
  307. package/src/cli/default-target.ts +55 -0
  308. package/src/cli/docs.ts +346 -0
  309. package/src/cli/doctor.ts +54 -0
  310. package/src/cli/eval.ts +315 -0
  311. package/src/cli/evidence.ts +225 -0
  312. package/src/cli/evolve.ts +219 -0
  313. package/src/cli/extensions.ts +214 -0
  314. package/src/cli/fleet.ts +868 -0
  315. package/src/cli/index.ts +338 -0
  316. package/src/cli/init.ts +219 -0
  317. package/src/cli/initial-message.ts +47 -0
  318. package/src/cli/internal-dispatch.ts +55 -0
  319. package/src/cli/memory.ts +182 -0
  320. package/src/cli/models.ts +257 -0
  321. package/src/cli/modes/json-stream.ts +121 -0
  322. package/src/cli/modes/jsonl.ts +9 -0
  323. package/src/cli/modes/print.ts +604 -0
  324. package/src/cli/oauth-manual-input.ts +72 -0
  325. package/src/cli/oauth-select.ts +36 -0
  326. package/src/cli/output-guard.ts +48 -0
  327. package/src/cli/paths.ts +44 -0
  328. package/src/cli/provider-target.ts +113 -0
  329. package/src/cli/removal.ts +72 -0
  330. package/src/cli/reset.ts +253 -0
  331. package/src/cli/run.ts +497 -0
  332. package/src/cli/share.ts +243 -0
  333. package/src/cli/shared.ts +60 -0
  334. package/src/cli/skills-eval.ts +1240 -0
  335. package/src/cli/skills.ts +485 -0
  336. package/src/cli/steer-channel.ts +86 -0
  337. package/src/cli/targets.ts +1154 -0
  338. package/src/cli/text-layout.ts +112 -0
  339. package/src/cli/trace.ts +322 -0
  340. package/src/cli/uninstall.ts +405 -0
  341. package/src/cli/upgrade.ts +286 -0
  342. package/src/cli/usage.ts +876 -0
  343. package/src/cli/validate-model.ts +28 -0
  344. package/src/cli/version.ts +7 -0
  345. package/src/cli/wiki-generate.ts +510 -0
  346. package/src/core/agent-environment.ts +7 -0
  347. package/src/core/artifact-paths.ts +43 -0
  348. package/src/core/bash-exec.ts +313 -0
  349. package/src/core/boot-trace.ts +42 -0
  350. package/src/core/bus-events.ts +744 -0
  351. package/src/core/bus-trace.ts +53 -0
  352. package/src/core/c-header-language.ts +265 -0
  353. package/src/core/clio-repo.ts +78 -0
  354. package/src/core/commit-attribution.ts +157 -0
  355. package/src/core/compile-cache.ts +159 -0
  356. package/src/core/config.ts +1722 -0
  357. package/src/core/context-floor.ts +33 -0
  358. package/src/core/defaults.ts +659 -0
  359. package/src/core/domain-loader.ts +177 -0
  360. package/src/core/event-bus.ts +94 -0
  361. package/src/core/file-references.ts +282 -0
  362. package/src/core/git-commit-attribution.ts +362 -0
  363. package/src/core/guardrails.ts +185 -0
  364. package/src/core/headless-permission.ts +21 -0
  365. package/src/core/incomplete-installation.ts +45 -0
  366. package/src/core/init.ts +223 -0
  367. package/src/core/json-payload.ts +58 -0
  368. package/src/core/package-root.ts +54 -0
  369. package/src/core/path-canonical.ts +37 -0
  370. package/src/core/process-identity.ts +41 -0
  371. package/src/core/recent-models.ts +91 -0
  372. package/src/core/residency-protection.ts +56 -0
  373. package/src/core/resolve-config-value.ts +88 -0
  374. package/src/core/response-schema.ts +279 -0
  375. package/src/core/run-overrides.ts +77 -0
  376. package/src/core/safe-exec.ts +205 -0
  377. package/src/core/safe-id.ts +37 -0
  378. package/src/core/safe-resource-write.ts +162 -0
  379. package/src/core/session-routing.ts +339 -0
  380. package/src/core/settings-layers.ts +354 -0
  381. package/src/core/shared-bus.ts +8 -0
  382. package/src/core/shell-quote.ts +26 -0
  383. package/src/core/skill-activation.ts +190 -0
  384. package/src/core/startup-timer.ts +37 -0
  385. package/src/core/state-file-lock.ts +219 -0
  386. package/src/core/termination.ts +275 -0
  387. package/src/core/timers.ts +38 -0
  388. package/src/core/tool-names.ts +65 -0
  389. package/src/core/verification-scripts.ts +13 -0
  390. package/src/core/workspace-files.ts +492 -0
  391. package/src/core/xdg.ts +177 -0
  392. package/src/domains/agents/builtins/architect.md +4 -4
  393. package/src/domains/agents/builtins/coder.md +3 -2
  394. package/src/domains/agents/builtins/debugger.md +1 -1
  395. package/src/domains/agents/builtins/documenter.md +1 -1
  396. package/src/domains/agents/builtins/git-master.md +3 -3
  397. package/src/domains/agents/builtins/provenance.md +1 -1
  398. package/src/domains/agents/builtins/researcher.md +1 -1
  399. package/src/domains/agents/builtins/scout.md +1 -1
  400. package/src/domains/agents/builtins/tester.md +1 -1
  401. package/src/domains/agents/builtins/verifier.md +1 -1
  402. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  403. package/src/domains/agents/catalog.ts +172 -0
  404. package/src/domains/agents/contract.ts +16 -0
  405. package/src/domains/agents/extension.ts +110 -0
  406. package/src/domains/agents/fleet-commands.ts +154 -0
  407. package/src/domains/agents/fleet-contract.ts +797 -0
  408. package/src/domains/agents/frontmatter.ts +40 -0
  409. package/src/domains/agents/index.ts +102 -0
  410. package/src/domains/agents/manifest.ts +6 -0
  411. package/src/domains/agents/recipe-schema.ts +202 -0
  412. package/src/domains/agents/recipe.ts +125 -0
  413. package/src/domains/agents/registry.ts +111 -0
  414. package/src/domains/agents/result-contract.ts +1265 -0
  415. package/src/domains/agents/spec.ts +371 -0
  416. package/src/domains/agents/write-boundary.ts +109 -0
  417. package/src/domains/components/diff.ts +99 -0
  418. package/src/domains/components/hash.ts +21 -0
  419. package/src/domains/components/index.ts +3 -0
  420. package/src/domains/components/scan.ts +304 -0
  421. package/src/domains/components/snapshot.ts +108 -0
  422. package/src/domains/components/types.ts +82 -0
  423. package/src/domains/config/agent-namespace.ts +13 -0
  424. package/src/domains/config/classify.ts +106 -0
  425. package/src/domains/config/contract.ts +22 -0
  426. package/src/domains/config/extension.ts +142 -0
  427. package/src/domains/config/index.ts +23 -0
  428. package/src/domains/config/keybindings.ts +200 -0
  429. package/src/domains/config/manifest.ts +6 -0
  430. package/src/domains/config/watcher.ts +41 -0
  431. package/src/domains/context/adoption.ts +880 -0
  432. package/src/domains/context/bootstrap-prompt.ts +273 -0
  433. package/src/domains/context/bootstrap.ts +1502 -0
  434. package/src/domains/context/clear.ts +91 -0
  435. package/src/domains/context/clio-md.ts +429 -0
  436. package/src/domains/context/codewiki/artifact.ts +400 -0
  437. package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
  438. package/src/domains/context/codewiki/build-worker.ts +54 -0
  439. package/src/domains/context/codewiki/cmake.ts +356 -0
  440. package/src/domains/context/codewiki/cooperative.ts +46 -0
  441. package/src/domains/context/codewiki/coordinator.ts +182 -0
  442. package/src/domains/context/codewiki/digest.ts +135 -0
  443. package/src/domains/context/codewiki/grammar-assets.ts +33 -0
  444. package/src/domains/context/codewiki/indexer.ts +1529 -0
  445. package/src/domains/context/codewiki/paths.ts +67 -0
  446. package/src/domains/context/codewiki/schema.ts +80 -0
  447. package/src/domains/context/codewiki/tree-sitter.ts +771 -0
  448. package/src/domains/context/contract.ts +68 -0
  449. package/src/domains/context/excluded-dirs.ts +1 -0
  450. package/src/domains/context/extension.ts +358 -0
  451. package/src/domains/context/fingerprint.ts +198 -0
  452. package/src/domains/context/index.ts +154 -0
  453. package/src/domains/context/init-options.ts +69 -0
  454. package/src/domains/context/manifest.ts +6 -0
  455. package/src/domains/context/operator-profile.ts +157 -0
  456. package/src/domains/context/project-metadata.ts +529 -0
  457. package/src/domains/context/project-rules.ts +227 -0
  458. package/src/domains/context/prompt-context.ts +61 -0
  459. package/src/domains/context/refresh.ts +178 -0
  460. package/src/domains/context/runtime.ts +17 -0
  461. package/src/domains/context/sibling-files.ts +10 -0
  462. package/src/domains/context/state.ts +237 -0
  463. package/src/domains/context/wiki/assemble.ts +303 -0
  464. package/src/domains/context/wiki/frontmatter.ts +210 -0
  465. package/src/domains/context/wiki/generate.ts +595 -0
  466. package/src/domains/context/wiki/layout.ts +111 -0
  467. package/src/domains/context/wiki/meta.ts +221 -0
  468. package/src/domains/context/wiki/plan-store.ts +217 -0
  469. package/src/domains/context/wiki/plan.ts +250 -0
  470. package/src/domains/context/wiki/prompts.ts +283 -0
  471. package/src/domains/context/wiki/staleness.ts +198 -0
  472. package/src/domains/dispatch/active-route-planner.ts +168 -0
  473. package/src/domains/dispatch/admission-queue.ts +150 -0
  474. package/src/domains/dispatch/admission.ts +334 -0
  475. package/src/domains/dispatch/agent-candidates.ts +307 -0
  476. package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
  477. package/src/domains/dispatch/agent-ledger-store.ts +257 -0
  478. package/src/domains/dispatch/agent-ledger.ts +212 -0
  479. package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
  480. package/src/domains/dispatch/assignment-events.ts +132 -0
  481. package/src/domains/dispatch/assignment-reconcile.ts +76 -0
  482. package/src/domains/dispatch/assignment-store.ts +162 -0
  483. package/src/domains/dispatch/assignment.ts +278 -0
  484. package/src/domains/dispatch/backoff.ts +59 -0
  485. package/src/domains/dispatch/batch-store.ts +134 -0
  486. package/src/domains/dispatch/batch-tracker.ts +66 -0
  487. package/src/domains/dispatch/capability-match.ts +155 -0
  488. package/src/domains/dispatch/capacity-lease.ts +413 -0
  489. package/src/domains/dispatch/code-step-store.ts +52 -0
  490. package/src/domains/dispatch/code-step.ts +387 -0
  491. package/src/domains/dispatch/contract.ts +278 -0
  492. package/src/domains/dispatch/dedup.ts +133 -0
  493. package/src/domains/dispatch/event-pump.ts +251 -0
  494. package/src/domains/dispatch/execution-handoff.ts +29 -0
  495. package/src/domains/dispatch/execution-plan.ts +328 -0
  496. package/src/domains/dispatch/execution-role.ts +277 -0
  497. package/src/domains/dispatch/execution-scheduler.ts +583 -0
  498. package/src/domains/dispatch/extension.ts +6006 -0
  499. package/src/domains/dispatch/failure-classification.ts +147 -0
  500. package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
  501. package/src/domains/dispatch/fleet-plan.ts +225 -0
  502. package/src/domains/dispatch/fleet-preflight.ts +394 -0
  503. package/src/domains/dispatch/gate-decisions.ts +1040 -0
  504. package/src/domains/dispatch/gate-role-prompts.ts +58 -0
  505. package/src/domains/dispatch/heartbeat.ts +27 -0
  506. package/src/domains/dispatch/index.ts +137 -0
  507. package/src/domains/dispatch/joint-route-adapter.ts +114 -0
  508. package/src/domains/dispatch/joint-route-resolver.ts +283 -0
  509. package/src/domains/dispatch/manifest.ts +6 -0
  510. package/src/domains/dispatch/orphan-recovery.ts +266 -0
  511. package/src/domains/dispatch/outcome.ts +109 -0
  512. package/src/domains/dispatch/phase-timing.ts +47 -0
  513. package/src/domains/dispatch/placement.ts +202 -0
  514. package/src/domains/dispatch/receipt-findings.ts +255 -0
  515. package/src/domains/dispatch/receipt-integrity.ts +383 -0
  516. package/src/domains/dispatch/recovery-candidates.ts +74 -0
  517. package/src/domains/dispatch/reproducibility.ts +48 -0
  518. package/src/domains/dispatch/reservation-store.ts +501 -0
  519. package/src/domains/dispatch/route-approval.ts +177 -0
  520. package/src/domains/dispatch/route-candidates.ts +57 -0
  521. package/src/domains/dispatch/route-decision.ts +1079 -0
  522. package/src/domains/dispatch/route-facts.ts +187 -0
  523. package/src/domains/dispatch/route-history.ts +238 -0
  524. package/src/domains/dispatch/route-observer.ts +488 -0
  525. package/src/domains/dispatch/route-policy.ts +327 -0
  526. package/src/domains/dispatch/route-quality.ts +256 -0
  527. package/src/domains/dispatch/route-readiness.ts +120 -0
  528. package/src/domains/dispatch/routing-intent.ts +287 -0
  529. package/src/domains/dispatch/run-identity.ts +56 -0
  530. package/src/domains/dispatch/scout-transition.ts +130 -0
  531. package/src/domains/dispatch/state.ts +302 -0
  532. package/src/domains/dispatch/tool-stats.ts +132 -0
  533. package/src/domains/dispatch/transport.ts +210 -0
  534. package/src/domains/dispatch/types.ts +799 -0
  535. package/src/domains/dispatch/validation-grounding.ts +154 -0
  536. package/src/domains/dispatch/validation.ts +721 -0
  537. package/src/domains/dispatch/worker-protocol.ts +275 -0
  538. package/src/domains/dispatch/worker-spawn.ts +585 -0
  539. package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
  540. package/src/domains/dispatch/write-boundary.ts +426 -0
  541. package/src/domains/eval/artifacts/redact.ts +42 -0
  542. package/src/domains/eval/artifacts/store.ts +173 -0
  543. package/src/domains/eval/compare/compare.ts +33 -0
  544. package/src/domains/eval/compare/gates.ts +66 -0
  545. package/src/domains/eval/compare/thresholds.ts +92 -0
  546. package/src/domains/eval/harness-metrics.ts +62 -0
  547. package/src/domains/eval/index.ts +66 -0
  548. package/src/domains/eval/metrics/chaos-stream.ts +93 -0
  549. package/src/domains/eval/metrics/context.ts +34 -0
  550. package/src/domains/eval/metrics/coverage.ts +21 -0
  551. package/src/domains/eval/metrics/evidence.ts +182 -0
  552. package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
  553. package/src/domains/eval/metrics/invariants.ts +736 -0
  554. package/src/domains/eval/metrics/latency.ts +4 -0
  555. package/src/domains/eval/metrics/token-stream.ts +139 -0
  556. package/src/domains/eval/metrics/tokens.ts +51 -0
  557. package/src/domains/eval/metrics/tool-calls.ts +7 -0
  558. package/src/domains/eval/proactive-memory.ts +279 -0
  559. package/src/domains/eval/provenance.ts +35 -0
  560. package/src/domains/eval/report.ts +234 -0
  561. package/src/domains/eval/reports/json.ts +5 -0
  562. package/src/domains/eval/reports/junit.ts +23 -0
  563. package/src/domains/eval/reports/markdown.ts +20 -0
  564. package/src/domains/eval/reports/swe-jsonl.ts +16 -0
  565. package/src/domains/eval/reports/text.ts +25 -0
  566. package/src/domains/eval/run-compare.ts +274 -0
  567. package/src/domains/eval/runner.ts +244 -0
  568. package/src/domains/eval/runners/clio-run.ts +148 -0
  569. package/src/domains/eval/runners/context-index.ts +56 -0
  570. package/src/domains/eval/runners/context-init.ts +203 -0
  571. package/src/domains/eval/runners/external-command.ts +350 -0
  572. package/src/domains/eval/runtime-paths.ts +171 -0
  573. package/src/domains/eval/schema/artifact.ts +75 -0
  574. package/src/domains/eval/schema/suite.ts +235 -0
  575. package/src/domains/eval/schema/validate.ts +339 -0
  576. package/src/domains/eval/store.ts +392 -0
  577. package/src/domains/eval/suites/load.ts +74 -0
  578. package/src/domains/eval/suites/matrix.ts +19 -0
  579. package/src/domains/eval/suites/resolve.ts +44 -0
  580. package/src/domains/eval/suites/run.ts +325 -0
  581. package/src/domains/eval/task-file.ts +186 -0
  582. package/src/domains/eval/types.ts +140 -0
  583. package/src/domains/eval/verifiers/command.ts +27 -0
  584. package/src/domains/eval/verifiers/file-exists.ts +6 -0
  585. package/src/domains/eval/verifiers/patch.ts +22 -0
  586. package/src/domains/eval/workspaces/git.ts +41 -0
  587. package/src/domains/eval/workspaces/local.ts +17 -0
  588. package/src/domains/eval/workspaces/temp-copy.ts +29 -0
  589. package/src/domains/evidence/build.ts +1754 -0
  590. package/src/domains/evidence/eval.ts +605 -0
  591. package/src/domains/evidence/failure-attribution.ts +54 -0
  592. package/src/domains/evidence/finish-contract-map.ts +42 -0
  593. package/src/domains/evidence/index.ts +55 -0
  594. package/src/domains/evidence/provenance.ts +200 -0
  595. package/src/domains/evidence/redact.ts +81 -0
  596. package/src/domains/evidence/store.ts +291 -0
  597. package/src/domains/evidence/types.ts +325 -0
  598. package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
  599. package/src/domains/evolution/index.ts +26 -0
  600. package/src/domains/evolution/manifest.ts +154 -0
  601. package/src/domains/evolution/validate.ts +304 -0
  602. package/src/domains/extensions/contract.ts +22 -0
  603. package/src/domains/extensions/discovery.ts +193 -0
  604. package/src/domains/extensions/extension.ts +46 -0
  605. package/src/domains/extensions/index.ts +34 -0
  606. package/src/domains/extensions/manager.ts +30 -0
  607. package/src/domains/extensions/manifest.ts +6 -0
  608. package/src/domains/extensions/resources.ts +38 -0
  609. package/src/domains/extensions/state.ts +224 -0
  610. package/src/domains/extensions/types.ts +83 -0
  611. package/src/domains/interop/consent.ts +185 -0
  612. package/src/domains/interop/contract.ts +29 -0
  613. package/src/domains/interop/detect.ts +173 -0
  614. package/src/domains/interop/extension.ts +59 -0
  615. package/src/domains/interop/index.ts +34 -0
  616. package/src/domains/interop/manifest.ts +6 -0
  617. package/src/domains/interop/registry.ts +139 -0
  618. package/src/domains/interop/state.ts +92 -0
  619. package/src/domains/interop/types.ts +109 -0
  620. package/src/domains/lifecycle/contract.ts +11 -0
  621. package/src/domains/lifecycle/doctor.ts +536 -0
  622. package/src/domains/lifecycle/extension.ts +23 -0
  623. package/src/domains/lifecycle/index.ts +21 -0
  624. package/src/domains/lifecycle/install-method.ts +51 -0
  625. package/src/domains/lifecycle/manifest.ts +6 -0
  626. package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
  627. package/src/domains/lifecycle/migrations/index.ts +114 -0
  628. package/src/domains/lifecycle/state.ts +93 -0
  629. package/src/domains/lifecycle/upgrade-notice.ts +35 -0
  630. package/src/domains/lifecycle/version.ts +35 -0
  631. package/src/domains/memory/index.ts +128 -0
  632. package/src/domains/memory/operations.ts +143 -0
  633. package/src/domains/memory/prompt-section.ts +86 -0
  634. package/src/domains/memory/proposal.ts +180 -0
  635. package/src/domains/memory/store.ts +163 -0
  636. package/src/domains/memory/task-bank.ts +229 -0
  637. package/src/domains/memory/task-memory-handoff.ts +222 -0
  638. package/src/domains/memory/task-memory-policy.ts +602 -0
  639. package/src/domains/memory/task-memory-status.ts +58 -0
  640. package/src/domains/memory/task-memory-telemetry.ts +346 -0
  641. package/src/domains/memory/task-memory-trace.ts +89 -0
  642. package/src/domains/memory/types.ts +74 -0
  643. package/src/domains/memory/validate.ts +297 -0
  644. package/src/domains/middleware/budget.ts +216 -0
  645. package/src/domains/middleware/contract.ts +35 -0
  646. package/src/domains/middleware/dispatch-nudge.ts +469 -0
  647. package/src/domains/middleware/extension.ts +129 -0
  648. package/src/domains/middleware/hook-receipts.ts +70 -0
  649. package/src/domains/middleware/hooks-io.ts +186 -0
  650. package/src/domains/middleware/hooks.ts +432 -0
  651. package/src/domains/middleware/index.ts +154 -0
  652. package/src/domains/middleware/manifest.ts +6 -0
  653. package/src/domains/middleware/memory-intervention.ts +701 -0
  654. package/src/domains/middleware/rules.ts +42 -0
  655. package/src/domains/middleware/runtime.ts +333 -0
  656. package/src/domains/middleware/skills-reminder.ts +202 -0
  657. package/src/domains/middleware/snapshot.ts +71 -0
  658. package/src/domains/middleware/stalled-turn.ts +71 -0
  659. package/src/domains/middleware/task-board-reminder.ts +87 -0
  660. package/src/domains/middleware/task-nudge.ts +77 -0
  661. package/src/domains/middleware/tool-choice-control.ts +42 -0
  662. package/src/domains/middleware/types.ts +131 -0
  663. package/src/domains/middleware/validate.ts +329 -0
  664. package/src/domains/observability/accountability.ts +67 -0
  665. package/src/domains/observability/contract.ts +168 -0
  666. package/src/domains/observability/cost.ts +206 -0
  667. package/src/domains/observability/evidence-index.ts +123 -0
  668. package/src/domains/observability/extension.ts +281 -0
  669. package/src/domains/observability/index.ts +78 -0
  670. package/src/domains/observability/manifest.ts +10 -0
  671. package/src/domains/observability/metrics.ts +37 -0
  672. package/src/domains/observability/projection.ts +477 -0
  673. package/src/domains/observability/telemetry.ts +89 -0
  674. package/src/domains/observability/trace-store.ts +1454 -0
  675. package/src/domains/prompts/compiler.ts +614 -0
  676. package/src/domains/prompts/contract.ts +46 -0
  677. package/src/domains/prompts/extension.ts +336 -0
  678. package/src/domains/prompts/fragment-loader.ts +138 -0
  679. package/src/domains/prompts/fragments/identity/clio.md +5 -6
  680. package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
  681. package/src/domains/prompts/fragments/identity/self-awareness.md +19 -0
  682. package/src/domains/prompts/fragments/operating/contract.md +4 -41
  683. package/src/domains/prompts/fragments/operating/delegation.md +42 -0
  684. package/src/domains/prompts/fragments/operating/skills.md +26 -0
  685. package/src/domains/prompts/fragments/operating/worker.md +16 -0
  686. package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
  687. package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
  688. package/src/domains/prompts/fragments/safety/read-only.md +4 -4
  689. package/src/domains/prompts/fragments/safety/suggest.md +2 -2
  690. package/src/domains/prompts/fragments/wiki/page.md +10 -0
  691. package/src/domains/prompts/fragments/wiki/plan.md +10 -0
  692. package/src/domains/prompts/hash.ts +73 -0
  693. package/src/domains/prompts/index.ts +32 -0
  694. package/src/domains/prompts/manifest.ts +8 -0
  695. package/src/domains/prompts/memory-intervention.ts +57 -0
  696. package/src/domains/prompts/preload.ts +82 -0
  697. package/src/domains/providers/auth/api-key.ts +47 -0
  698. package/src/domains/providers/auth/backend-file.ts +79 -0
  699. package/src/domains/providers/auth/backend-memory.ts +72 -0
  700. package/src/domains/providers/auth/boot-status.ts +65 -0
  701. package/src/domains/providers/auth/index.ts +37 -0
  702. package/src/domains/providers/auth/oauth.ts +37 -0
  703. package/src/domains/providers/auth/storage.ts +726 -0
  704. package/src/domains/providers/capabilities.ts +58 -0
  705. package/src/domains/providers/catalog.ts +162 -0
  706. package/src/domains/providers/contract.ts +162 -0
  707. package/src/domains/providers/credentials.ts +20 -0
  708. package/src/domains/providers/eligibility.ts +24 -0
  709. package/src/domains/providers/errors.ts +64 -0
  710. package/src/domains/providers/extension.ts +548 -0
  711. package/src/domains/providers/index.ts +142 -0
  712. package/src/domains/providers/knowledge-base-path.ts +102 -0
  713. package/src/domains/providers/manifest.ts +6 -0
  714. package/src/domains/providers/model-capabilities.ts +136 -0
  715. package/src/domains/providers/model-discovery.ts +144 -0
  716. package/src/domains/providers/model-family.ts +32 -0
  717. package/src/domains/providers/model-runtime-capabilities.ts +723 -0
  718. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +120 -37
  719. package/src/domains/providers/plugins.ts +61 -0
  720. package/src/domains/providers/probe/fingerprint.ts +64 -0
  721. package/src/domains/providers/probe/http.ts +114 -0
  722. package/src/domains/providers/probe/reasoning.ts +111 -0
  723. package/src/domains/providers/registry.ts +187 -0
  724. package/src/domains/providers/resolver.ts +156 -0
  725. package/src/domains/providers/runtime-resolution.ts +720 -0
  726. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
  727. package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
  728. package/src/domains/providers/runtimes/builtins.ts +78 -0
  729. package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
  730. package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
  731. package/src/domains/providers/runtimes/claude/common.ts +55 -0
  732. package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
  733. package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
  734. package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
  735. package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
  736. package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
  737. package/src/domains/providers/runtimes/cloud/google.ts +41 -0
  738. package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
  739. package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
  740. package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
  741. package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
  742. package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
  743. package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
  744. package/src/domains/providers/runtimes/common/local-synth.ts +164 -0
  745. package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
  746. package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
  747. package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
  748. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
  749. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
  750. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
  751. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
  752. package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
  753. package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
  754. package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
  755. package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
  756. package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
  757. package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
  758. package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
  759. package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
  760. package/src/domains/providers/runtimes/protocol/google.ts +27 -0
  761. package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
  762. package/src/domains/providers/support.ts +241 -0
  763. package/src/domains/providers/thinking-control-policy.ts +85 -0
  764. package/src/domains/providers/types/capability-flags.ts +114 -0
  765. package/src/domains/providers/types/cost-provenance.ts +7 -0
  766. package/src/domains/providers/types/inference.ts +41 -0
  767. package/src/domains/providers/types/knowledge-base.ts +156 -0
  768. package/src/domains/providers/types/local-model-quirks.ts +216 -0
  769. package/src/domains/providers/types/runtime-descriptor.ts +181 -0
  770. package/src/domains/providers/types/target-descriptor.ts +60 -0
  771. package/src/domains/resources/collision.ts +92 -0
  772. package/src/domains/resources/common-loader.ts +140 -0
  773. package/src/domains/resources/contract.ts +24 -0
  774. package/src/domains/resources/extension.ts +59 -0
  775. package/src/domains/resources/index.ts +74 -0
  776. package/src/domains/resources/loader.ts +85 -0
  777. package/src/domains/resources/manifest.ts +6 -0
  778. package/src/domains/resources/prompts/loader.ts +246 -0
  779. package/src/domains/resources/prompts/substitute.ts +1 -0
  780. package/src/domains/resources/skills/content-hash.ts +107 -0
  781. package/src/domains/resources/skills/evals.ts +175 -0
  782. package/src/domains/resources/skills/install.ts +427 -0
  783. package/src/domains/resources/skills/loader.ts +985 -0
  784. package/src/domains/resources/skills/marketplace.ts +301 -0
  785. package/src/domains/resources/skills/provenance-pin.ts +115 -0
  786. package/src/domains/safety/action-classifier.ts +270 -0
  787. package/src/domains/safety/approval-axis.ts +23 -0
  788. package/src/domains/safety/audit.ts +493 -0
  789. package/src/domains/safety/autonomy.ts +174 -0
  790. package/src/domains/safety/call-target.ts +59 -0
  791. package/src/domains/safety/contract.ts +65 -0
  792. package/src/domains/safety/damage-control.ts +44 -0
  793. package/src/domains/safety/default-path-policy.ts +117 -0
  794. package/src/domains/safety/extension.ts +383 -0
  795. package/src/domains/safety/finish-contract-registration.ts +128 -0
  796. package/src/domains/safety/finish-contract.ts +554 -0
  797. package/src/domains/safety/index.ts +44 -0
  798. package/src/domains/safety/loop-detector.ts +143 -0
  799. package/src/domains/safety/manifest.ts +6 -0
  800. package/src/domains/safety/path-policy.ts +164 -0
  801. package/src/domains/safety/policy-engine.ts +994 -0
  802. package/src/domains/safety/project-policy.ts +391 -0
  803. package/src/domains/safety/protected-artifacts-registration.ts +189 -0
  804. package/src/domains/safety/protected-artifacts.ts +993 -0
  805. package/src/domains/safety/rejection-feedback.ts +102 -0
  806. package/src/domains/safety/rigor.ts +72 -0
  807. package/src/domains/safety/rule-compiler.ts +48 -0
  808. package/src/domains/safety/rule-pack-loader.ts +92 -0
  809. package/src/domains/safety/run-effects.ts +197 -0
  810. package/src/domains/safety/scope.ts +61 -0
  811. package/src/domains/scheduling/budget.ts +35 -0
  812. package/src/domains/scheduling/cluster.ts +175 -0
  813. package/src/domains/scheduling/contract.ts +30 -0
  814. package/src/domains/scheduling/extension.ts +91 -0
  815. package/src/domains/scheduling/index.ts +12 -0
  816. package/src/domains/scheduling/manifest.ts +6 -0
  817. package/src/domains/session/archive-readers.ts +208 -0
  818. package/src/domains/session/checkpoint.ts +38 -0
  819. package/src/domains/session/compaction/auto.ts +89 -0
  820. package/src/domains/session/compaction/branch-summary.ts +187 -0
  821. package/src/domains/session/compaction/compact.ts +493 -0
  822. package/src/domains/session/compaction/cut-point.ts +172 -0
  823. package/src/domains/session/compaction/defaults.ts +34 -0
  824. package/src/domains/session/compaction/mask-observations.ts +265 -0
  825. package/src/domains/session/compaction/session-entries.ts +18 -0
  826. package/src/domains/session/compaction/tokens.ts +148 -0
  827. package/src/domains/session/context-accounting.ts +583 -0
  828. package/src/domains/session/context-ledger.ts +362 -0
  829. package/src/domains/session/contract.ts +159 -0
  830. package/src/domains/session/cwd-fallback.ts +65 -0
  831. package/src/domains/session/decision-board.ts +190 -0
  832. package/src/domains/session/entries.ts +572 -0
  833. package/src/domains/session/extension.ts +403 -0
  834. package/src/domains/session/history.ts +172 -0
  835. package/src/domains/session/index.ts +84 -0
  836. package/src/domains/session/manager.ts +128 -0
  837. package/src/domains/session/manifest.ts +6 -0
  838. package/src/domains/session/migrations/index.ts +27 -0
  839. package/src/domains/session/prompt-manifest.ts +173 -0
  840. package/src/domains/session/protected-artifact-journal.ts +241 -0
  841. package/src/domains/session/protected-artifacts.ts +90 -0
  842. package/src/domains/session/retry.ts +230 -0
  843. package/src/domains/session/session-artifacts.ts +107 -0
  844. package/src/domains/session/task-board.ts +569 -0
  845. package/src/domains/session/tree/active-path.ts +137 -0
  846. package/src/domains/session/tree/fork.ts +159 -0
  847. package/src/domains/session/tree/manager.ts +128 -0
  848. package/src/domains/session/tree/navigator.ts +177 -0
  849. package/src/domains/session/tree/preview.ts +259 -0
  850. package/src/domains/session/usage.ts +148 -0
  851. package/src/domains/session/workspace/git-probe.ts +167 -0
  852. package/src/domains/session/workspace/index.ts +4 -0
  853. package/src/domains/session/workspace/project-type.ts +217 -0
  854. package/src/domains/session/workspace/snapshot.ts +74 -0
  855. package/src/domains/share/archive.ts +684 -0
  856. package/src/domains/share/contract.ts +9 -0
  857. package/src/domains/share/extension.ts +26 -0
  858. package/src/domains/share/index.ts +28 -0
  859. package/src/domains/share/manifest.ts +6 -0
  860. package/src/domains/user-tasks/store.ts +297 -0
  861. package/src/engine/acp/adapter.ts +397 -0
  862. package/src/engine/acp/errors.ts +128 -0
  863. package/src/engine/acp/event-mapper.ts +154 -0
  864. package/src/engine/acp/server.ts +2238 -0
  865. package/src/engine/acp/tool-mediator.ts +686 -0
  866. package/src/engine/acp/transport.ts +775 -0
  867. package/src/engine/acp/types.ts +196 -0
  868. package/src/engine/agent.ts +29 -0
  869. package/src/engine/ai.ts +207 -0
  870. package/src/engine/alcf-oauth.ts +205 -0
  871. package/src/engine/antigravity/subprocess-runtime.ts +205 -0
  872. package/src/engine/api-registry.ts +223 -0
  873. package/src/engine/apis/degraded-inference.ts +95 -0
  874. package/src/engine/apis/index.ts +16 -0
  875. package/src/engine/apis/llamacpp-residency.ts +292 -0
  876. package/src/engine/apis/lmstudio-residency.ts +76 -0
  877. package/src/engine/apis/lmstudio.ts +243 -0
  878. package/src/engine/apis/ollama-native.ts +528 -0
  879. package/src/engine/apis/openai-completions.ts +795 -0
  880. package/src/engine/apis/output-budget.ts +99 -0
  881. package/src/engine/apis/residency-lock.ts +29 -0
  882. package/src/engine/apis/residency.ts +776 -0
  883. package/src/engine/apis/resident-models.ts +42 -0
  884. package/src/engine/apis/sampling-overrides.ts +38 -0
  885. package/src/engine/apis/types.ts +16 -0
  886. package/src/engine/claude/sdk-runtime.ts +685 -0
  887. package/src/engine/claude/session-id.ts +5 -0
  888. package/src/engine/claude/subprocess-runtime.ts +316 -0
  889. package/src/engine/claude/tool-safety.ts +400 -0
  890. package/src/engine/env-api-keys.ts +98 -0
  891. package/src/engine/external-subprocess.ts +23 -0
  892. package/src/engine/gemma-channel-filter.ts +223 -0
  893. package/src/engine/harmony-response.ts +165 -0
  894. package/src/engine/instrumented-tui.ts +192 -0
  895. package/src/engine/loop-guard.ts +1127 -0
  896. package/src/engine/messages.ts +14 -0
  897. package/src/engine/models.ts +42 -0
  898. package/src/engine/oauth.ts +196 -0
  899. package/src/engine/pi-mono-names.ts +13 -0
  900. package/src/engine/prompt-templates.ts +1 -0
  901. package/src/engine/provider-payload.ts +272 -0
  902. package/src/engine/select-list.ts +53 -0
  903. package/src/engine/session.ts +834 -0
  904. package/src/engine/strip-tokenizer-sentinels.ts +125 -0
  905. package/src/engine/truncate.ts +9 -0
  906. package/src/engine/tui.ts +111 -0
  907. package/src/engine/types.ts +63 -0
  908. package/src/engine/worker-events.ts +100 -0
  909. package/src/engine/worker-runtime-capabilities.ts +5 -0
  910. package/src/engine/worker-runtime.ts +1022 -0
  911. package/src/engine/worker-tools.ts +208 -0
  912. package/src/entry/boot-options.ts +50 -0
  913. package/src/entry/orchestrator.ts +2011 -0
  914. package/src/interactive/application-controller.ts +433 -0
  915. package/src/interactive/bus-notices.ts +265 -0
  916. package/src/interactive/chat-loop-messages.ts +626 -0
  917. package/src/interactive/chat-loop-policy.ts +18 -0
  918. package/src/interactive/chat-loop.ts +1090 -0
  919. package/src/interactive/chat-panel.ts +1820 -0
  920. package/src/interactive/chat-renderer.ts +1228 -0
  921. package/src/interactive/clio-editor.ts +161 -0
  922. package/src/interactive/command-fallbacks.ts +23 -0
  923. package/src/interactive/command-output.ts +85 -0
  924. package/src/interactive/context-activity.ts +203 -0
  925. package/src/interactive/context-meter.ts +223 -0
  926. package/src/interactive/context-overlay.ts +246 -0
  927. package/src/interactive/cost-overlay.ts +279 -0
  928. package/src/interactive/dispatch-board.ts +1319 -0
  929. package/src/interactive/dispatch-steering.ts +86 -0
  930. package/src/interactive/editor-bash.ts +46 -0
  931. package/src/interactive/editor-steer.ts +51 -0
  932. package/src/interactive/editor-submit.ts +507 -0
  933. package/src/interactive/export-html/ansi-to-html.ts +161 -0
  934. package/src/interactive/export-html/index.ts +51 -0
  935. package/src/interactive/export-html/template.ts +45 -0
  936. package/src/interactive/export-html/tool-renderer.ts +54 -0
  937. package/src/interactive/external-editor.ts +67 -0
  938. package/src/interactive/follow-up-queue-panel.ts +75 -0
  939. package/src/interactive/footer/dashboard.ts +538 -0
  940. package/src/interactive/footer/notifications.ts +275 -0
  941. package/src/interactive/footer/widgets.ts +1264 -0
  942. package/src/interactive/footer-panel.ts +187 -0
  943. package/src/interactive/format-time.ts +97 -0
  944. package/src/interactive/index.ts +11 -0
  945. package/src/interactive/interactive-application.ts +939 -0
  946. package/src/interactive/interactive-event-projection.ts +385 -0
  947. package/src/interactive/interactive-input-runtime.ts +307 -0
  948. package/src/interactive/interactive-presentation.ts +584 -0
  949. package/src/interactive/interactive-shell.ts +388 -0
  950. package/src/interactive/interactive-slash-runtime.ts +554 -0
  951. package/src/interactive/interactive-subscriptions.ts +111 -0
  952. package/src/interactive/interactive-tickers.ts +183 -0
  953. package/src/interactive/keybinding-manager.ts +496 -0
  954. package/src/interactive/layout.ts +57 -0
  955. package/src/interactive/leader-key.ts +143 -0
  956. package/src/interactive/loop-guard-interrupt.ts +101 -0
  957. package/src/interactive/memory-overlay.ts +280 -0
  958. package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
  959. package/src/interactive/overlay-auth-lifecycle.ts +308 -0
  960. package/src/interactive/overlay-frame.ts +502 -0
  961. package/src/interactive/overlay-general-openers.ts +274 -0
  962. package/src/interactive/overlay-key-routing.ts +216 -0
  963. package/src/interactive/overlay-lifecycle.ts +426 -0
  964. package/src/interactive/overlay-model-selectors.ts +127 -0
  965. package/src/interactive/overlay-permission-lifecycle.ts +345 -0
  966. package/src/interactive/overlay-resource-openers.ts +112 -0
  967. package/src/interactive/overlay-session-lifecycle.ts +327 -0
  968. package/src/interactive/overlay-transitions.ts +57 -0
  969. package/src/interactive/overlays/agents.ts +69 -0
  970. package/src/interactive/overlays/ask-user.ts +921 -0
  971. package/src/interactive/overlays/auth-dialog.ts +221 -0
  972. package/src/interactive/overlays/context-reset.ts +108 -0
  973. package/src/interactive/overlays/cwd-fallback.ts +141 -0
  974. package/src/interactive/overlays/decisions.ts +300 -0
  975. package/src/interactive/overlays/extensions.ts +54 -0
  976. package/src/interactive/overlays/help-reference.ts +145 -0
  977. package/src/interactive/overlays/interop.ts +139 -0
  978. package/src/interactive/overlays/keybinding-detail.ts +90 -0
  979. package/src/interactive/overlays/list-overlay.ts +606 -0
  980. package/src/interactive/overlays/message-picker.ts +155 -0
  981. package/src/interactive/overlays/model-selector.ts +1109 -0
  982. package/src/interactive/overlays/prompts.ts +72 -0
  983. package/src/interactive/overlays/session-selector-search.ts +31 -0
  984. package/src/interactive/overlays/session-selector.ts +284 -0
  985. package/src/interactive/overlays/settings.ts +3451 -0
  986. package/src/interactive/overlays/skills-hub.ts +237 -0
  987. package/src/interactive/overlays/tree-selector.ts +422 -0
  988. package/src/interactive/permission-overlay.ts +170 -0
  989. package/src/interactive/render-trace.ts +534 -0
  990. package/src/interactive/renderers/branch-summary.ts +86 -0
  991. package/src/interactive/renderers/code-ink.ts +420 -0
  992. package/src/interactive/renderers/compaction-summary.ts +112 -0
  993. package/src/interactive/renderers/diff.ts +137 -0
  994. package/src/interactive/renderers/mermaid.ts +53 -0
  995. package/src/interactive/renderers/notice.ts +28 -0
  996. package/src/interactive/renderers/retry-status.ts +31 -0
  997. package/src/interactive/renderers/structured.ts +89 -0
  998. package/src/interactive/renderers/tool-execution.ts +1357 -0
  999. package/src/interactive/renderers/worker-entry.ts +280 -0
  1000. package/src/interactive/session-last-turn.ts +186 -0
  1001. package/src/interactive/session-switch-settlement.ts +10 -0
  1002. package/src/interactive/session-transcript.ts +105 -0
  1003. package/src/interactive/session-usage-reseed.ts +74 -0
  1004. package/src/interactive/slash-autocomplete.ts +256 -0
  1005. package/src/interactive/slash-commands.ts +1407 -0
  1006. package/src/interactive/slash-spec.ts +424 -0
  1007. package/src/interactive/status/controller.ts +260 -0
  1008. package/src/interactive/status/index.ts +23 -0
  1009. package/src/interactive/status/state-machine.ts +530 -0
  1010. package/src/interactive/status/summary.ts +170 -0
  1011. package/src/interactive/status/types.ts +121 -0
  1012. package/src/interactive/status/verbs.ts +163 -0
  1013. package/src/interactive/status/watchdog.ts +24 -0
  1014. package/src/interactive/stdout-backpressure.ts +99 -0
  1015. package/src/interactive/stream-pacer.ts +530 -0
  1016. package/src/interactive/stream-pacing-policy.ts +66 -0
  1017. package/src/interactive/tasks-overlay.ts +540 -0
  1018. package/src/interactive/terminal-lease.ts +485 -0
  1019. package/src/interactive/theme/components.ts +55 -0
  1020. package/src/interactive/theme/glyphs.ts +70 -0
  1021. package/src/interactive/theme/index.ts +15 -0
  1022. package/src/interactive/theme/labels.ts +88 -0
  1023. package/src/interactive/theme/rules.ts +138 -0
  1024. package/src/interactive/theme/segments.ts +88 -0
  1025. package/src/interactive/theme/tokens.ts +121 -0
  1026. package/src/interactive/thinking-level-policy.ts +6 -0
  1027. package/src/interactive/tool-prose-loop.ts +122 -0
  1028. package/src/interactive/tool-prose-registration.ts +48 -0
  1029. package/src/interactive/turn-context.ts +855 -0
  1030. package/src/interactive/turn-middleware.ts +283 -0
  1031. package/src/interactive/turn-persistence.ts +458 -0
  1032. package/src/interactive/turn-queues.ts +181 -0
  1033. package/src/interactive/turn-recovery.ts +323 -0
  1034. package/src/interactive/turn-runtime.ts +869 -0
  1035. package/src/interactive/turn-state.ts +133 -0
  1036. package/src/interactive/view/artifacts.ts +1452 -0
  1037. package/src/interactive/view/view-overlay.ts +735 -0
  1038. package/src/interactive/welcome-dashboard.ts +537 -0
  1039. package/src/interactive/worker-receipts.ts +143 -0
  1040. package/src/interactive/worker-replay.ts +111 -0
  1041. package/src/interactive/worker-share.ts +100 -0
  1042. package/src/interactive/worker-stream.ts +446 -0
  1043. package/src/interactive/workspace-facts.ts +141 -0
  1044. package/src/tools/agent-tools.ts +402 -0
  1045. package/src/tools/artifact.ts +103 -0
  1046. package/src/tools/ask-user.ts +666 -0
  1047. package/src/tools/bash.ts +204 -0
  1048. package/src/tools/bootstrap.ts +77 -0
  1049. package/src/tools/builtin-tool-catalog.ts +265 -0
  1050. package/src/tools/codewiki/code-nav-surface.ts +29 -0
  1051. package/src/tools/codewiki/code-nav.ts +549 -0
  1052. package/src/tools/codewiki/shared.ts +118 -0
  1053. package/src/tools/compete-worktrees.ts +898 -0
  1054. package/src/tools/context/docs-engine.ts +630 -0
  1055. package/src/tools/context/index.ts +514 -0
  1056. package/src/tools/context/surface.ts +19 -0
  1057. package/src/tools/core-bootstrap.ts +168 -0
  1058. package/src/tools/credential-present.ts +151 -0
  1059. package/src/tools/dispatch-admission.ts +533 -0
  1060. package/src/tools/dispatch-arguments.ts +228 -0
  1061. package/src/tools/dispatch-background.ts +54 -0
  1062. package/src/tools/dispatch-event-text.ts +6 -0
  1063. package/src/tools/dispatch-plan.ts +746 -0
  1064. package/src/tools/dispatch-run-events.ts +238 -0
  1065. package/src/tools/dispatch-runner.ts +2370 -0
  1066. package/src/tools/dispatch-scout-admission.ts +295 -0
  1067. package/src/tools/dispatch-scout.ts +461 -0
  1068. package/src/tools/dispatch-types.ts +77 -0
  1069. package/src/tools/dispatch.ts +244 -0
  1070. package/src/tools/edit-diff.ts +534 -0
  1071. package/src/tools/edit.ts +128 -0
  1072. package/src/tools/executables.ts +22 -0
  1073. package/src/tools/file-mutation-queue.ts +35 -0
  1074. package/src/tools/find.ts +294 -0
  1075. package/src/tools/grep.ts +495 -0
  1076. package/src/tools/ignore-policy.ts +169 -0
  1077. package/src/tools/lazy-tool.ts +60 -0
  1078. package/src/tools/ledger.ts +206 -0
  1079. package/src/tools/ls.ts +110 -0
  1080. package/src/tools/monitor-surface.ts +36 -0
  1081. package/src/tools/monitor.ts +767 -0
  1082. package/src/tools/network-policy.ts +29 -0
  1083. package/src/tools/observation.ts +421 -0
  1084. package/src/tools/observers.ts +99 -0
  1085. package/src/tools/path-utils.ts +79 -0
  1086. package/src/tools/policy.ts +154 -0
  1087. package/src/tools/profiles.ts +108 -0
  1088. package/src/tools/read.ts +173 -0
  1089. package/src/tools/registry.ts +1169 -0
  1090. package/src/tools/result-shaping.ts +204 -0
  1091. package/src/tools/safe-exec.ts +128 -0
  1092. package/src/tools/spawn-hygiene.ts +182 -0
  1093. package/src/tools/steer-surface.ts +17 -0
  1094. package/src/tools/steer.ts +77 -0
  1095. package/src/tools/tasks.ts +265 -0
  1096. package/src/tools/truncate-utf8.ts +17 -0
  1097. package/src/tools/truncate.ts +43 -0
  1098. package/src/tools/verify/frontend.ts +687 -0
  1099. package/src/tools/verify/index.ts +31 -0
  1100. package/src/tools/verify/scripts.ts +108 -0
  1101. package/src/tools/verify/surface.ts +46 -0
  1102. package/src/tools/web-fetch-surface.ts +23 -0
  1103. package/src/tools/web-fetch.ts +759 -0
  1104. package/src/tools/worker-evidence.ts +215 -0
  1105. package/src/tools/write.ts +57 -0
  1106. package/src/utils/exif-orientation.ts +192 -0
  1107. package/src/utils/git.ts +24 -0
  1108. package/src/utils/image-resize.ts +148 -0
  1109. package/src/utils/photon.ts +103 -0
  1110. package/src/worker/control-lane.ts +22 -0
  1111. package/src/worker/entry.ts +294 -0
  1112. package/src/worker/event-projection.ts +56 -0
  1113. package/src/worker/heartbeat.ts +24 -0
  1114. package/src/worker/ledger-mirror.ts +95 -0
  1115. package/src/worker/ndjson.ts +40 -0
  1116. package/src/worker/protocol.ts +529 -0
  1117. package/src/worker/resource-facts.ts +79 -0
  1118. package/src/worker/runtime-registry.ts +12 -0
  1119. package/src/worker/spec-contract.ts +675 -0
  1120. package/src/worker/stdin-demux.ts +316 -0
  1121. package/dist/acp-UMLFVA3F.js +0 -92
  1122. package/dist/chunk-262G75JS.js +0 -35
  1123. package/dist/chunk-6CWDTGUC.js +0 -20
  1124. package/dist/chunk-BYEU76JP.js +0 -899
  1125. package/dist/chunk-GNGDQYDU.js +0 -34688
  1126. package/dist/chunk-GOTUR54M.js +0 -9
  1127. package/dist/chunk-NI4DEJMC.js +0 -88
  1128. package/dist/chunk-TPOCL34A.js +0 -2876
  1129. package/dist/chunk-UU3R62TT.js +0 -128
  1130. package/dist/clio-KIQ5SNDS.js +0 -53
  1131. package/dist/configure-G4E3A2PG.js +0 -27
  1132. package/dist/doctor-M5HJJZOL.js +0 -61
  1133. package/dist/domains/agents/builtins/architect.md +0 -33
  1134. package/dist/domains/agents/builtins/coder.md +0 -31
  1135. package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
  1136. package/dist/domains/agents/builtins/debugger.md +0 -30
  1137. package/dist/domains/agents/builtins/documenter.md +0 -31
  1138. package/dist/domains/agents/builtins/git-master.md +0 -30
  1139. package/dist/domains/agents/builtins/provenance.md +0 -30
  1140. package/dist/domains/agents/builtins/researcher.md +0 -71
  1141. package/dist/domains/agents/builtins/scout.md +0 -42
  1142. package/dist/domains/agents/builtins/tester.md +0 -31
  1143. package/dist/domains/agents/builtins/verifier.md +0 -30
  1144. package/dist/domains/agents/builtins/wiki-writer.md +0 -41
  1145. package/dist/fleet-preflight-CLIAX7YR.js +0 -21
  1146. package/dist/preload-KZVHET2B.js +0 -11
  1147. package/dist/version-ROZ6CZKH.js +0 -16
  1148. package/docs/html/agents_blueprint.html +0 -936
  1149. package/docs/html/alcf_blueprint.html +0 -324
  1150. package/docs/html/architecture_blueprint.html +0 -850
  1151. package/docs/html/commands_blueprint.html +0 -794
  1152. package/docs/html/config_knobs_audit_blueprint.html +0 -178
  1153. package/docs/html/configuration_blueprint.html +0 -1080
  1154. package/docs/html/context_blueprint.html +0 -603
  1155. package/docs/html/documentation_blueprint.html +0 -832
  1156. package/docs/html/environment_blueprint.html +0 -404
  1157. package/docs/html/eval_blueprint.html +0 -743
  1158. package/docs/html/evals_internal_blueprint.html +0 -190
  1159. package/docs/html/evolution_blueprint.html +0 -674
  1160. package/docs/html/extensions_blueprint.html +0 -2065
  1161. package/docs/html/fleet_dispatch_blueprint.html +0 -286
  1162. package/docs/html/index.html +0 -919
  1163. package/docs/html/lifecycle_blueprint.html +0 -723
  1164. package/docs/html/memory_blueprint.html +0 -699
  1165. package/docs/html/middleware_blueprint.html +0 -664
  1166. package/docs/html/models_blueprint.html +0 -2366
  1167. package/docs/html/observability_blueprint.html +0 -683
  1168. package/docs/html/provider_adapter_blueprint.html +0 -245
  1169. package/docs/html/safety_blueprint.html +0 -1386
  1170. package/docs/html/shared.css +0 -571
  1171. package/docs/html/shared.js +0 -143
  1172. package/docs/html/skills_blueprint.html +0 -671
  1173. package/docs/html/soak_blueprint.html +0 -182
  1174. package/docs/html/tool_usage_blueprint.html +0 -350
  1175. package/docs/html/tools_blueprint.html +0 -2249
  1176. package/docs/html/trace_blueprint.html +0 -235
  1177. package/docs/html/tui_design_blueprint.html +0 -314
  1178. package/docs/html/validation_blueprint.html +0 -961
  1179. package/docs/html/worker_dispatch_blueprint.html +0 -231
  1180. package/skills/git/commit-crafting/SKILL.md +0 -79
  1181. package/skills/git/commit-crafting/evals.md +0 -92
  1182. package/skills/git/create-pr/SKILL.md +0 -116
  1183. package/skills/git/create-pr/evals.md +0 -114
  1184. package/skills/git/investigate-issue/SKILL.md +0 -139
  1185. package/skills/git/investigate-issue/evals.md +0 -94
  1186. package/skills/git/review-changes/SKILL.md +0 -103
  1187. package/skills/git/review-changes/evals.md +0 -85
@@ -0,0 +1,3428 @@
1
+ import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
+ import {
3
+ DEFAULT_AUTONOMY_LEVEL,
4
+ autonomyAskRejection,
5
+ autonomyDenyRejection,
6
+ isAutonomyLevel,
7
+ mapAutonomy,
8
+ typedValidationSummary
9
+ } from "./chunk-STBPMHSX.js";
10
+ import {
11
+ ROUTE_POLICY_VERSION,
12
+ deriveExecutionRole,
13
+ isExecutionRole,
14
+ isRouteDecisionAgentSelection,
15
+ isRoutingIntent,
16
+ routePriorForLatencyClass,
17
+ sameRouteIdentity
18
+ } from "./chunk-GGXXDWE4.js";
19
+ import {
20
+ AGENT_AUTOMATION_AUTHORITIES,
21
+ agentSpecFingerprint,
22
+ detectValidationCommand,
23
+ extractCommandDeleteTargets,
24
+ extractCommandWriteTargets,
25
+ tokenizeShellLike,
26
+ toolMutationPaths
27
+ } from "./chunk-5UUP6MWO.js";
28
+ import {
29
+ resolveReadPath
30
+ } from "./chunk-OQE5J4C6.js";
31
+ import {
32
+ isSkillActivation
33
+ } from "./chunk-T6YILFSB.js";
34
+ import {
35
+ DEFAULT_MAX_LINES,
36
+ OBSERVATION_POLICY_SLACK_BYTES,
37
+ OBSERVE_SELF_CAPS,
38
+ finalizeObservation,
39
+ formatSize,
40
+ isSessionOffloadPath,
41
+ observationBudgetExhausted,
42
+ reserveObservation,
43
+ splitLinesForCounting,
44
+ truncateHead,
45
+ truncateTail
46
+ } from "./chunk-VAKQQHWR.js";
47
+ import {
48
+ truncateUtf8
49
+ } from "./chunk-6XLNIQDB.js";
50
+ import {
51
+ typebox_exports
52
+ } from "./chunk-5B2AEOW5.js";
53
+ import {
54
+ ToolNames,
55
+ isBuiltinToolName
56
+ } from "./chunk-CGKSTWHD.js";
57
+ import {
58
+ THINKING_LEVELS
59
+ } from "./chunk-ZDOOVTXZ.js";
60
+ import {
61
+ GUARDRAIL_DEFAULTS,
62
+ GUARDRAIL_ENV_VARS,
63
+ resolveGuardrail
64
+ } from "./chunk-4ZG3XFUR.js";
65
+ import {
66
+ init_esm_shims
67
+ } from "./chunk-3R73A4XB.js";
68
+
69
+ // src/tools/profiles.ts
70
+ init_esm_shims();
71
+ var TOOL_PROFILE_NAMES = ["minimal-local", "science-local", "full-agent"];
72
+ var CODEWIKI_TOOL_NAMES = [ToolNames.CodeNav];
73
+ var MINIMAL_LOCAL_TOOLS = [
74
+ ToolNames.Read,
75
+ ToolNames.Grep,
76
+ ToolNames.Find,
77
+ ToolNames.Ls,
78
+ ToolNames.Git,
79
+ ToolNames.Context,
80
+ ToolNames.CodeNav,
81
+ // A narrowed read-only scout swarm is the surface that most needs to see
82
+ // what its peers already staked.
83
+ ToolNames.Ledger
84
+ ];
85
+ var SCIENCE_LOCAL_TOOLS = [...MINIMAL_LOCAL_TOOLS, ToolNames.Verify];
86
+ var NARROW_TOOL_PROFILES = {
87
+ "minimal-local": new Set(MINIMAL_LOCAL_TOOLS),
88
+ "science-local": new Set(SCIENCE_LOCAL_TOOLS)
89
+ };
90
+ function isToolProfileName(value) {
91
+ return TOOL_PROFILE_NAMES.includes(value);
92
+ }
93
+ function narrowsToolSurface(profile) {
94
+ return profile !== void 0 && profile in NARROW_TOOL_PROFILES;
95
+ }
96
+ function assertToolProfileEnforceable(profile, runtimeLabel) {
97
+ if (narrowsToolSurface(profile)) {
98
+ throw new Error(
99
+ `${runtimeLabel} runtime cannot enforce tool_profile '${profile}': it runs its own tool surface without Clio per-tool mediation. Dispatch to a native or claude-sdk worker, or use tool_profile full-agent.`
100
+ );
101
+ }
102
+ }
103
+ function applyToolProfile(tools, profile, context) {
104
+ const unique = uniquePreservingOrder(tools);
105
+ let profiled;
106
+ if (profile === void 0 || profile === "full-agent") {
107
+ profiled = unique;
108
+ } else {
109
+ const allowed = NARROW_TOOL_PROFILES[profile];
110
+ profiled = unique.filter((tool) => isBuiltinToolName(tool) && allowed.has(tool));
111
+ }
112
+ return applyCodewikiWorkerPolicy(profiled, context);
113
+ }
114
+ function uniquePreservingOrder(tools) {
115
+ const seen = /* @__PURE__ */ new Set();
116
+ const unique = [];
117
+ for (const tool of tools) {
118
+ if (seen.has(tool)) continue;
119
+ seen.add(tool);
120
+ unique.push(tool);
121
+ }
122
+ return unique;
123
+ }
124
+ function isCodewikiTool(tool) {
125
+ return CODEWIKI_TOOL_NAMES.includes(tool);
126
+ }
127
+ function isNavigationHeavyTask(task) {
128
+ if (!task) return false;
129
+ return /\b(?:codewiki|symbol|symbols|entry\s*points?|where\s+is|code_nav|call\s*sites?|references?|imports?|exports?|map|mapping|navigate|navigation|topology|architecture|boundar(?:y|ies)|ownership|trace|locate|find\s+(?:the\s+)?(?:implementation|definition|module|file|path))\b|(?:^|\s)(?:src|tests?|cmd|pkg|lib)\/|\.(?:[cm]?[tj]sx?|py|pyw|go|rs|c|h|cc|cpp|cxx|hpp|hh|hxx|java|rb)\b/i.test(
130
+ task
131
+ );
132
+ }
133
+ function applyCodewikiWorkerPolicy(tools, context) {
134
+ if (!context?.agentId) return tools;
135
+ if (context.agentId === "scout") return tools;
136
+ if (isNavigationHeavyTask(context.task)) return tools;
137
+ return tools.filter((tool) => !isCodewikiTool(tool));
138
+ }
139
+
140
+ // src/tools/network-policy.ts
141
+ init_esm_shims();
142
+ var NO_NETWORK_TOOLS_ENV = "CLIO_CODER_NO_NETWORK_TOOLS";
143
+ function networkToolsDisabled(env = process.env) {
144
+ return env[NO_NETWORK_TOOLS_ENV] === "1";
145
+ }
146
+
147
+ // src/worker/spec-contract.ts
148
+ init_esm_shims();
149
+
150
+ // src/core/response-schema.ts
151
+ init_esm_shims();
152
+ var RESPONSE_SCHEMA_MAX_SERIALIZED_BYTES = 64 * 1024;
153
+ var RESPONSE_SCHEMA_RUNTIME_ID = "llamacpp";
154
+ function runtimeSpeaksResponseSchemaDialect(runtime) {
155
+ return runtime.id === RESPONSE_SCHEMA_RUNTIME_ID && runtime.kind === "http" && runtime.apiFamily === "openai-completions";
156
+ }
157
+ function responseSchemaConflictsWithTools(runtime, toolCount) {
158
+ return toolCount > 0 && runtimeSpeaksResponseSchemaDialect(runtime);
159
+ }
160
+ var UnsupportedResponseSchemaError = class extends Error {
161
+ code = "UNSUPPORTED_RESPONSE_SCHEMA";
162
+ constructor(message) {
163
+ super(message);
164
+ this.name = "UnsupportedResponseSchemaError";
165
+ }
166
+ };
167
+ function isResponseSchemaRejection(diagnostic) {
168
+ if (!diagnostic) return false;
169
+ const text = diagnostic.toLowerCase();
170
+ if (!/\b(?:400|422)\b|invalid_request_error|bad request/.test(text)) return false;
171
+ return /grammar|json[ _-]?schema|response[ _-]?format/.test(text);
172
+ }
173
+ function isPlainObject(value) {
174
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
175
+ const prototype = Object.getPrototypeOf(value);
176
+ return prototype === Object.prototype || prototype === null;
177
+ }
178
+ var SUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set(["type", "properties", "required", "items", "additionalProperties"]);
179
+ var SUPPORTED_SCHEMA_TYPES = /* @__PURE__ */ new Set(["object", "array", "string", "number", "integer", "boolean", "null"]);
180
+ function definesToJson(value) {
181
+ let current = value;
182
+ while (current) {
183
+ if (Object.getOwnPropertyDescriptor(current, "toJSON")) return true;
184
+ current = Object.getPrototypeOf(current);
185
+ }
186
+ return false;
187
+ }
188
+ function jsonDataError(value) {
189
+ const stack = [{ value, path: "$" }];
190
+ const active = /* @__PURE__ */ new Set();
191
+ while (stack.length > 0) {
192
+ const frame = stack.pop();
193
+ if (!frame) break;
194
+ if (frame.exit) {
195
+ active.delete(frame.exit);
196
+ continue;
197
+ }
198
+ const current = frame.value;
199
+ if (current === null || typeof current === "string" || typeof current === "boolean") continue;
200
+ if (typeof current === "number") {
201
+ if (!Number.isFinite(current)) return `${frame.path} must be a finite number`;
202
+ continue;
203
+ }
204
+ if (typeof current !== "object") return `${frame.path} contains a non-JSON value`;
205
+ if (active.has(current)) return `${frame.path} contains a circular reference`;
206
+ if (!Array.isArray(current) && !isPlainObject(current)) {
207
+ return `${frame.path} must contain only plain objects and arrays`;
208
+ }
209
+ if (definesToJson(current)) {
210
+ return `${frame.path} must not define toJSON`;
211
+ }
212
+ active.add(current);
213
+ stack.push({ value: null, path: frame.path, exit: current });
214
+ if (Array.isArray(current)) {
215
+ const descriptors2 = Object.getOwnPropertyDescriptors(current);
216
+ for (const [key, descriptor] of Object.entries(descriptors2)) {
217
+ if (key === "length" || /^(?:0|[1-9]\d*)$/.test(key)) continue;
218
+ if (descriptor.enumerable) return `${frame.path}.${key} is not a JSON array index`;
219
+ }
220
+ for (let index = current.length - 1; index >= 0; index -= 1) {
221
+ if (!Object.hasOwn(current, index)) return `${frame.path}[${index}] must not be an array hole`;
222
+ const descriptor = Object.getOwnPropertyDescriptor(current, String(index));
223
+ if (!descriptor || !("value" in descriptor)) return `${frame.path}[${index}] must be a data property`;
224
+ stack.push({ value: descriptor.value, path: `${frame.path}[${index}]` });
225
+ }
226
+ continue;
227
+ }
228
+ for (const symbol of Object.getOwnPropertySymbols(current)) {
229
+ if (Object.getOwnPropertyDescriptor(current, symbol)?.enumerable) {
230
+ return `${frame.path} must not contain symbol keys`;
231
+ }
232
+ }
233
+ const descriptors = Object.getOwnPropertyDescriptors(current);
234
+ const keys = Object.keys(descriptors);
235
+ for (let index = keys.length - 1; index >= 0; index -= 1) {
236
+ const key = keys[index];
237
+ if (key === void 0) continue;
238
+ const descriptor = descriptors[key];
239
+ if (!descriptor?.enumerable) continue;
240
+ if (!("value" in descriptor)) return `${frame.path}.${key} must be a data property`;
241
+ stack.push({ value: descriptor.value, path: `${frame.path}.${key}` });
242
+ }
243
+ }
244
+ return null;
245
+ }
246
+ function schemaSyntaxError(value) {
247
+ const stack = [{ schema: value, path: "$" }];
248
+ while (stack.length > 0) {
249
+ const frame = stack.pop();
250
+ if (!frame) break;
251
+ const { schema, path: path3 } = frame;
252
+ for (const key of Object.keys(schema)) {
253
+ if (!SUPPORTED_SCHEMA_KEYS.has(key)) return `${path3}.${key} is not supported by the llama.cpp schema subset`;
254
+ }
255
+ if (typeof schema.type !== "string" || !SUPPORTED_SCHEMA_TYPES.has(schema.type)) {
256
+ return `${path3}.type must be one of ${[...SUPPORTED_SCHEMA_TYPES].join(", ")}`;
257
+ }
258
+ if (schema.type === "object") {
259
+ if (schema.items !== void 0) return `${path3}.items is only valid for array schemas`;
260
+ if (schema.properties !== void 0 && !isPlainObject(schema.properties)) {
261
+ return `${path3}.properties must be a plain object`;
262
+ }
263
+ const properties = schema.properties ?? {};
264
+ for (const [name, child] of Object.entries(properties)) {
265
+ if (!isPlainObject(child)) return `${path3}.properties.${name} must be a schema object`;
266
+ stack.push({ schema: child, path: `${path3}.properties.${name}` });
267
+ }
268
+ if (schema.required !== void 0) {
269
+ if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
270
+ return `${path3}.required must be an array of strings`;
271
+ }
272
+ if (new Set(schema.required).size !== schema.required.length) {
273
+ return `${path3}.required must not contain duplicates`;
274
+ }
275
+ for (const name of schema.required) {
276
+ if (!Object.hasOwn(properties, name)) return `${path3}.required names unknown property '${name}'`;
277
+ }
278
+ }
279
+ if (schema.additionalProperties !== void 0 && typeof schema.additionalProperties !== "boolean") {
280
+ return `${path3}.additionalProperties must be a boolean`;
281
+ }
282
+ continue;
283
+ }
284
+ if (schema.type === "array") {
285
+ if (!isPlainObject(schema.items)) return `${path3}.items must be a schema object`;
286
+ if (schema.properties !== void 0 || schema.required !== void 0 || schema.additionalProperties !== void 0) {
287
+ return `${path3} contains object-only keywords on an array schema`;
288
+ }
289
+ stack.push({ schema: schema.items, path: `${path3}.items` });
290
+ continue;
291
+ }
292
+ if (schema.properties !== void 0 || schema.required !== void 0 || schema.items !== void 0 || schema.additionalProperties !== void 0) {
293
+ return `${path3} contains container keywords on a ${schema.type} schema`;
294
+ }
295
+ }
296
+ return null;
297
+ }
298
+ function responseSchemaValidationError(value, source = "responseSchema") {
299
+ try {
300
+ if (!isPlainObject(value)) return `${source} must be a plain object`;
301
+ const valueError = jsonDataError(value);
302
+ if (valueError) return `${source} must be JSON-serializable: ${valueError}`;
303
+ const syntaxError = schemaSyntaxError(value);
304
+ if (syntaxError) return `${source} is not an enforceable JSON schema: ${syntaxError}`;
305
+ const serialized = JSON.stringify(value);
306
+ const bytes = Buffer.byteLength(serialized, "utf8");
307
+ if (bytes > RESPONSE_SCHEMA_MAX_SERIALIZED_BYTES) {
308
+ return `${source} must be at most ${RESPONSE_SCHEMA_MAX_SERIALIZED_BYTES} serialized bytes`;
309
+ }
310
+ return null;
311
+ } catch (error) {
312
+ const detail = error instanceof Error ? error.message : String(error);
313
+ return `${source} could not be safely inspected: ${detail}`;
314
+ }
315
+ }
316
+ function assertValidResponseSchema(value, source = "responseSchema") {
317
+ const error = responseSchemaValidationError(value, source);
318
+ if (error) throw new Error(error);
319
+ }
320
+ function cloneValidatedResponseSchema(value, source = "responseSchema") {
321
+ assertValidResponseSchema(value, source);
322
+ try {
323
+ const serialized = JSON.stringify(value);
324
+ if (Buffer.byteLength(serialized, "utf8") > RESPONSE_SCHEMA_MAX_SERIALIZED_BYTES) {
325
+ throw new Error(`${source} changed while being validated`);
326
+ }
327
+ const cloned = JSON.parse(serialized);
328
+ const cloneError = responseSchemaValidationError(cloned, source);
329
+ if (cloneError) throw new Error(cloneError);
330
+ return cloned;
331
+ } catch (error) {
332
+ if (error instanceof Error && error.message.startsWith(source)) throw error;
333
+ const detail = error instanceof Error ? error.message : String(error);
334
+ throw new Error(`${source} could not be canonically cloned: ${detail}`);
335
+ }
336
+ }
337
+
338
+ // src/worker/spec-contract.ts
339
+ var WORKER_SPEC_VERSION = 3;
340
+ var WORKER_RUNTIME_DESCRIPTOR_VERSION = 2;
341
+ var WORKER_PROTECTED_ARTIFACT_STATE_VERSION = 1;
342
+ var WORKER_EXIT_PERMISSION_REQUIRED = 3;
343
+ var DEFAULT_ESCALATION_TIMEOUT_MS = 12e4;
344
+ var DEFAULT_ESCALATION_FALLBACK = "deny";
345
+ var RUNTIME_KINDS = ["http", "sdk", "subprocess"];
346
+ var RUNTIME_API_FAMILIES = [
347
+ "openai-completions",
348
+ "openai-responses",
349
+ "openai-codex-responses",
350
+ "azure-openai-responses",
351
+ "anthropic-messages",
352
+ "bedrock-converse-stream",
353
+ "google-generative-ai",
354
+ "google-vertex",
355
+ "mistral-conversations",
356
+ "ollama-native",
357
+ "rerank-http",
358
+ "embeddings-http",
359
+ "claude-agent-sdk",
360
+ "claude-code-subprocess"
361
+ ];
362
+ var RUNTIME_AUTHS = [
363
+ "api-key",
364
+ "oauth",
365
+ "aws-sdk",
366
+ "vertex-adc",
367
+ "claude-cli",
368
+ "none"
369
+ ];
370
+ var TOOL_PROFILE_NAMES2 = [
371
+ "minimal-local",
372
+ "science-local",
373
+ "full-agent"
374
+ ];
375
+ var WORKER_PRODUCTS = ["orientation"];
376
+ var TARGET_LIFECYCLES = ["user-managed", "clio-managed"];
377
+ var RESIDENCY_ROLES = ["chat", "memory", "worker", "target-default"];
378
+ var MIDDLEWARE_HOOKS = ["before_tool", "after_tool", "turn_start", "turn_end", "on_compaction"];
379
+ var MIDDLEWARE_EFFECT_KINDS = [
380
+ "inject_reminder",
381
+ "annotate_tool_result",
382
+ "block_tool",
383
+ "protect_path",
384
+ "request_continuation",
385
+ "require_tool",
386
+ "lock_tools"
387
+ ];
388
+ var RUNTIME_RESOLUTION_SEVERITIES = ["info", "warning", "error"];
389
+ var SPEC_AUTONOMY_LEVELS = [
390
+ "read-only",
391
+ "suggest",
392
+ "auto-edit",
393
+ "full-auto"
394
+ ];
395
+ var THINKING_MECHANISMS = ["effort-levels", "budget-tokens", "on-off", "always-on", "none"];
396
+ var THINKING_BUDGET_ENFORCEMENTS = ["enforced", "informational", "none"];
397
+ var THINKING_NOTICE_KINDS = ["applied", "ignored-on-off", "always-on", "unsupported"];
398
+ function serializeWorkerRuntimeDescriptor(runtime) {
399
+ return {
400
+ version: WORKER_RUNTIME_DESCRIPTOR_VERSION,
401
+ id: runtime.id,
402
+ kind: runtime.kind,
403
+ apiFamily: runtime.apiFamily,
404
+ auth: runtime.auth,
405
+ // Carried so the target check can recognize a configured runtime id that
406
+ // resolves to this runtime through an alias. Without them the contract has
407
+ // no way to tell a legacy spelling from a genuinely wrong runtime.
408
+ ...runtime.aliases !== void 0 && runtime.aliases.length > 0 ? { aliases: [...runtime.aliases] } : {}
409
+ };
410
+ }
411
+ function readRecord(value, source) {
412
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
413
+ throw new Error(`${source} must be an object`);
414
+ }
415
+ return value;
416
+ }
417
+ function readWorkerPromptMessages(value, source) {
418
+ if (value === void 0) return;
419
+ if (!Array.isArray(value)) throw new Error(`${source} must be an array`);
420
+ for (let index = 0; index < value.length; index++) {
421
+ const entry = readRecord(value[index], `${source}[${index}]`);
422
+ readString(entry.id, `${source}[${index}].id`);
423
+ readString(entry.body, `${source}[${index}].body`);
424
+ readString(entry.contentHash, `${source}[${index}].contentHash`);
425
+ }
426
+ }
427
+ function readString(value, source, options) {
428
+ if (typeof value !== "string") throw new Error(`${source} must be a string`);
429
+ if (!options?.allowEmpty && value.length === 0) throw new Error(`${source} must be a non-empty string`);
430
+ return value;
431
+ }
432
+ function readOptionalString(record2, key, source) {
433
+ if (record2[key] !== void 0) readString(record2[key], `${source}.${key}`);
434
+ }
435
+ function readOptionalBoolean(record2, key, source) {
436
+ const value = record2[key];
437
+ if (value !== void 0 && typeof value !== "boolean") throw new Error(`${source}.${key} must be a boolean`);
438
+ }
439
+ function readOptionalNumber(record2, key, source) {
440
+ const value = record2[key];
441
+ if (value !== void 0 && (typeof value !== "number" || !Number.isFinite(value))) {
442
+ throw new Error(`${source}.${key} must be a finite number`);
443
+ }
444
+ }
445
+ function readEnum(value, source, allowed) {
446
+ if (typeof value !== "string" || !allowed.includes(value)) {
447
+ throw new Error(`${source} must be one of: ${allowed.join(", ")}`);
448
+ }
449
+ return value;
450
+ }
451
+ function readOptionalEnum(record2, key, source, allowed) {
452
+ if (record2[key] !== void 0) readEnum(record2[key], `${source}.${key}`, allowed);
453
+ }
454
+ function readStringArray(value, source) {
455
+ if (!Array.isArray(value)) throw new Error(`${source} must be an array`);
456
+ return value.map((item, index) => readString(item, `${source}[${index}]`));
457
+ }
458
+ function readOptionalStringArray(record2, key, source) {
459
+ if (record2[key] !== void 0) readStringArray(record2[key], `${source}.${key}`);
460
+ }
461
+ function validateProtectedModels(value) {
462
+ if (value === void 0) return;
463
+ if (!Array.isArray(value)) throw new Error("WorkerSpec.protectedModels must be an array");
464
+ value.forEach((item, index) => {
465
+ const source = `WorkerSpec.protectedModels[${index}]`;
466
+ if (typeof item === "string") {
467
+ readString(item, source);
468
+ return;
469
+ }
470
+ const ref = readRecord(item, source);
471
+ readString(ref.modelId, `${source}.modelId`);
472
+ readEnum(ref.role, `${source}.role`, RESIDENCY_ROLES);
473
+ });
474
+ }
475
+ function validateTarget(value, runtimeId, runtimeAliases) {
476
+ const target = readRecord(value, "WorkerSpec.target");
477
+ const targetId = readString(target.id, "WorkerSpec.target.id");
478
+ const targetRuntime = readString(target.runtime, "WorkerSpec.target.runtime");
479
+ if (targetRuntime !== runtimeId && !runtimeAliases.includes(targetRuntime)) {
480
+ throw new Error(
481
+ `WorkerSpec target runtime mismatch: target.runtime=${targetRuntime} runtimeId=${runtimeId}. Set the target's runtime to '${runtimeId}' in settings.yaml, or run 'clio-coder upgrade' to migrate a legacy runtime id.`
482
+ );
483
+ }
484
+ if (targetId.length === 0) throw new Error("WorkerSpec.target.id must be a non-empty string");
485
+ readOptionalString(target, "url", "WorkerSpec.target");
486
+ readOptionalString(target, "defaultModel", "WorkerSpec.target");
487
+ readOptionalStringArray(target, "wireModels", "WorkerSpec.target");
488
+ readOptionalBoolean(target, "gateway", "WorkerSpec.target");
489
+ readOptionalEnum(target, "lifecycle", "WorkerSpec.target", TARGET_LIFECYCLES);
490
+ if (target.auth !== void 0) validateTargetAuth(target.auth);
491
+ if (target.pricing !== void 0) validateTargetPricing(target.pricing);
492
+ if (target.capabilities !== void 0) validateCapabilityPatch(target.capabilities, "WorkerSpec.target.capabilities");
493
+ }
494
+ function validateTargetAuth(value) {
495
+ const auth = readRecord(value, "WorkerSpec.target.auth");
496
+ readOptionalString(auth, "apiKeyEnvVar", "WorkerSpec.target.auth");
497
+ readOptionalString(auth, "apiKeyRef", "WorkerSpec.target.auth");
498
+ readOptionalString(auth, "oauthProfile", "WorkerSpec.target.auth");
499
+ if (auth.headers === void 0) return;
500
+ const headers = readRecord(auth.headers, "WorkerSpec.target.auth.headers");
501
+ for (const [key, value2] of Object.entries(headers)) {
502
+ readString(value2, `WorkerSpec.target.auth.headers.${key}`);
503
+ }
504
+ }
505
+ function validateTargetPricing(value) {
506
+ const pricing = readRecord(value, "WorkerSpec.target.pricing");
507
+ const input = pricing.input;
508
+ const output = pricing.output;
509
+ if (typeof input !== "number" || !Number.isFinite(input) || input < 0) {
510
+ throw new Error("WorkerSpec.target.pricing.input must be a non-negative finite number");
511
+ }
512
+ if (typeof output !== "number" || !Number.isFinite(output) || output < 0) {
513
+ throw new Error("WorkerSpec.target.pricing.output must be a non-negative finite number");
514
+ }
515
+ readOptionalNumber(pricing, "cacheRead", "WorkerSpec.target.pricing");
516
+ readOptionalNumber(pricing, "cacheWrite", "WorkerSpec.target.pricing");
517
+ }
518
+ function validateCapabilityPatch(value, source) {
519
+ const caps = readRecord(value, source);
520
+ for (const key of ["chat", "tools", "reasoning", "vision", "audio", "embeddings", "rerank", "fim"]) {
521
+ readOptionalBoolean(caps, key, source);
522
+ }
523
+ for (const key of ["contextWindow", "maxTokens"]) {
524
+ readOptionalNumber(caps, key, source);
525
+ }
526
+ for (const key of ["toolCallFormat", "thinkingFormat", "structuredOutputs"]) {
527
+ readOptionalString(caps, key, source);
528
+ }
529
+ }
530
+ function validateAllowedTools(value) {
531
+ for (const name of readStringArray(value, "WorkerSpec.allowedTools")) {
532
+ if (name.trim().length === 0) throw new Error("WorkerSpec.allowedTools entries must be non-empty strings");
533
+ }
534
+ }
535
+ function validateWorkerBudget(value) {
536
+ const budget = readRecord(value, "WorkerSpec.budget");
537
+ const expected = ["hardCap", "readReserve", "synthesis", "toolCalls"];
538
+ const actual = Object.keys(budget).sort();
539
+ if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
540
+ throw new Error(`WorkerSpec.budget must contain exactly: ${expected.join(", ")}`);
541
+ }
542
+ for (const key of ["toolCalls", "readReserve", "hardCap"]) {
543
+ const value2 = budget[key];
544
+ if (typeof value2 !== "number" || !Number.isSafeInteger(value2)) {
545
+ throw new Error(`WorkerSpec.budget.${key} must be a safe integer`);
546
+ }
547
+ }
548
+ if (budget.toolCalls <= 0) throw new Error("WorkerSpec.budget.toolCalls must be greater than zero");
549
+ if (budget.hardCap <= 0) throw new Error("WorkerSpec.budget.hardCap must be greater than zero");
550
+ if (budget.toolCalls > budget.hardCap) {
551
+ throw new Error("WorkerSpec.budget.toolCalls must not exceed WorkerSpec.budget.hardCap");
552
+ }
553
+ if (budget.readReserve < 0 || budget.readReserve >= budget.toolCalls) {
554
+ throw new Error("WorkerSpec.budget.readReserve must be an integer in [0, toolCalls)");
555
+ }
556
+ if (typeof budget.synthesis !== "boolean") throw new Error("WorkerSpec.budget.synthesis must be a boolean");
557
+ }
558
+ function validateRuntimeCapabilityDecision(value, source) {
559
+ const caps = readRecord(value, source);
560
+ for (const key of ["chat", "tools", "reasoning", "vision", "streaming"]) {
561
+ if (typeof caps[key] !== "boolean") throw new Error(`${source}.${key} must be a boolean`);
562
+ }
563
+ for (const key of ["contextWindow", "maxTokens"]) {
564
+ const n = caps[key];
565
+ if (typeof n !== "number" || !Number.isFinite(n) || n < 0)
566
+ throw new Error(`${source}.${key} must be a non-negative finite number`);
567
+ }
568
+ }
569
+ function validateRuntimeResolution(value) {
570
+ if (value === void 0) return;
571
+ const resolution = readRecord(value, "WorkerSpec.runtimeResolution");
572
+ readString(resolution.targetId, "WorkerSpec.runtimeResolution.targetId");
573
+ readString(resolution.runtimeId, "WorkerSpec.runtimeResolution.runtimeId");
574
+ readEnum(resolution.runtimeKind, "WorkerSpec.runtimeResolution.runtimeKind", RUNTIME_KINDS);
575
+ readEnum(resolution.apiFamily, "WorkerSpec.runtimeResolution.apiFamily", RUNTIME_API_FAMILIES);
576
+ readEnum(resolution.auth, "WorkerSpec.runtimeResolution.auth", RUNTIME_AUTHS);
577
+ if (typeof resolution.authRequired !== "boolean") {
578
+ throw new Error("WorkerSpec.runtimeResolution.authRequired must be a boolean");
579
+ }
580
+ readString(resolution.wireModelId, "WorkerSpec.runtimeResolution.wireModelId");
581
+ readEnum(resolution.requestedThinkingLevel, "WorkerSpec.runtimeResolution.requestedThinkingLevel", THINKING_LEVELS);
582
+ readEnum(resolution.effectiveThinkingLevel, "WorkerSpec.runtimeResolution.effectiveThinkingLevel", THINKING_LEVELS);
583
+ validateRuntimeCapabilityDecision(resolution.capabilities, "WorkerSpec.runtimeResolution.capabilities");
584
+ const thinking = readRecord(resolution.thinking, "WorkerSpec.runtimeResolution.thinking");
585
+ readEnum(thinking.mechanism, "WorkerSpec.runtimeResolution.thinking.mechanism", THINKING_MECHANISMS);
586
+ readString(thinking.display, "WorkerSpec.runtimeResolution.thinking.display", { allowEmpty: true });
587
+ for (const level of readStringArray(
588
+ thinking.supportedLevels,
589
+ "WorkerSpec.runtimeResolution.thinking.supportedLevels"
590
+ )) {
591
+ readEnum(level, "WorkerSpec.runtimeResolution.thinking.supportedLevels[]", THINKING_LEVELS);
592
+ }
593
+ readEnum(
594
+ thinking.budgetEnforcement,
595
+ "WorkerSpec.runtimeResolution.thinking.budgetEnforcement",
596
+ THINKING_BUDGET_ENFORCEMENTS
597
+ );
598
+ readEnum(thinking.noticeKind, "WorkerSpec.runtimeResolution.thinking.noticeKind", THINKING_NOTICE_KINDS);
599
+ readString(thinking.notice, "WorkerSpec.runtimeResolution.thinking.notice", { allowEmpty: true });
600
+ readRecord(resolution.request, "WorkerSpec.runtimeResolution.request");
601
+ readRecord(resolution.response, "WorkerSpec.runtimeResolution.response");
602
+ if (!Array.isArray(resolution.diagnostics)) {
603
+ throw new Error("WorkerSpec.runtimeResolution.diagnostics must be an array");
604
+ }
605
+ for (let index = 0; index < resolution.diagnostics.length; index += 1) {
606
+ const diag = readRecord(resolution.diagnostics[index], `WorkerSpec.runtimeResolution.diagnostics[${index}]`);
607
+ readEnum(diag.severity, `WorkerSpec.runtimeResolution.diagnostics[${index}].severity`, RUNTIME_RESOLUTION_SEVERITIES);
608
+ readString(diag.code, `WorkerSpec.runtimeResolution.diagnostics[${index}].code`);
609
+ readString(diag.message, `WorkerSpec.runtimeResolution.diagnostics[${index}].message`);
610
+ }
611
+ }
612
+ function validateMiddlewareSnapshot(value) {
613
+ const snapshot = readRecord(value, "WorkerSpec.middlewareSnapshot");
614
+ if (snapshot.version !== 1) throw new Error("WorkerSpec.middlewareSnapshot version must be 1");
615
+ if (!Array.isArray(snapshot.rules)) throw new Error("WorkerSpec.middlewareSnapshot.rules must be an array");
616
+ for (let index = 0; index < snapshot.rules.length; index += 1) {
617
+ const source = `WorkerSpec.middlewareSnapshot.rules[${index}]`;
618
+ const rule = readRecord(snapshot.rules[index], source);
619
+ readString(rule.id, `${source}.id`);
620
+ if (rule.source !== "builtin") throw new Error(`${source}.source must be builtin`);
621
+ readString(rule.description, `${source}.description`);
622
+ if (typeof rule.enabled !== "boolean") throw new Error(`${source}.enabled must be a boolean`);
623
+ for (const hook of readStringArray(rule.hooks, `${source}.hooks`)) {
624
+ readEnum(hook, `${source}.hooks[]`, MIDDLEWARE_HOOKS);
625
+ }
626
+ for (const kind of readStringArray(rule.effectKinds, `${source}.effectKinds`)) {
627
+ readEnum(kind, `${source}.effectKinds[]`, MIDDLEWARE_EFFECT_KINDS);
628
+ }
629
+ }
630
+ }
631
+ function validateProtectedArtifactState(value) {
632
+ const state = readRecord(value, "WorkerSpec.protectedArtifactState");
633
+ if (state.version !== WORKER_PROTECTED_ARTIFACT_STATE_VERSION) {
634
+ throw new Error(
635
+ `WorkerSpec.protectedArtifactState version ${String(state.version)} is unsupported; expected ${WORKER_PROTECTED_ARTIFACT_STATE_VERSION}`
636
+ );
637
+ }
638
+ if (!Array.isArray(state.artifacts)) {
639
+ throw new Error("WorkerSpec.protectedArtifactState.artifacts must be an array");
640
+ }
641
+ const sources = ["validation", "middleware", "user", "session"];
642
+ for (let index = 0; index < state.artifacts.length; index += 1) {
643
+ const source = `WorkerSpec.protectedArtifactState.artifacts[${index}]`;
644
+ const artifact = readRecord(state.artifacts[index], source);
645
+ readString(artifact.path, `${source}.path`);
646
+ readString(artifact.protectedAt, `${source}.protectedAt`);
647
+ readString(artifact.reason, `${source}.reason`);
648
+ readEnum(artifact.source, `${source}.source`, sources);
649
+ readOptionalString(artifact, "validationCommand", source);
650
+ readOptionalNumber(artifact, "validationExitCode", source);
651
+ }
652
+ }
653
+ function parseWorkerSpec(value) {
654
+ const spec = readRecord(value, "WorkerSpec");
655
+ if (spec.specVersion !== WORKER_SPEC_VERSION) {
656
+ throw new Error(
657
+ `WorkerSpec version ${String(spec.specVersion)} is unsupported (expected version ${WORKER_SPEC_VERSION}). Re-dispatch the request to generate a valid attested, budget-bearing worker specification.`
658
+ );
659
+ }
660
+ if (spec.budget === void 0) {
661
+ throw new Error(`WorkerSpec version ${WORKER_SPEC_VERSION} requires budget`);
662
+ }
663
+ if (typeof spec.settingsFingerprint !== "string" || !/^[0-9a-f]{64}$/.test(spec.settingsFingerprint)) {
664
+ throw new Error(`WorkerSpec version ${WORKER_SPEC_VERSION} requires settingsFingerprint as a sha256 hex digest`);
665
+ }
666
+ const runtime = readRecord(spec.runtime, "WorkerSpec.runtime");
667
+ if (runtime.version !== WORKER_RUNTIME_DESCRIPTOR_VERSION) {
668
+ throw new Error(
669
+ `WorkerSpec.runtime version ${String(runtime.version)} is unsupported; expected ${WORKER_RUNTIME_DESCRIPTOR_VERSION}`
670
+ );
671
+ }
672
+ const runtimeId = readString(spec.runtimeId, "WorkerSpec.runtimeId");
673
+ const runtimeRefId = readString(runtime.id, "WorkerSpec.runtime.id");
674
+ if (runtimeId !== runtimeRefId) {
675
+ throw new Error(`WorkerSpec runtime id mismatch: runtimeId=${runtimeId} runtime.id=${runtimeRefId}`);
676
+ }
677
+ const runtimeAliases = runtime.aliases === void 0 ? [] : readStringArray(runtime.aliases, "WorkerSpec.runtime.aliases");
678
+ const runtimeKind = readEnum(runtime.kind, "WorkerSpec.runtime.kind", RUNTIME_KINDS);
679
+ const runtimeApiFamily = readEnum(runtime.apiFamily, "WorkerSpec.runtime.apiFamily", RUNTIME_API_FAMILIES);
680
+ readEnum(runtime.auth, "WorkerSpec.runtime.auth", RUNTIME_AUTHS);
681
+ readString(spec.systemPrompt, "WorkerSpec.systemPrompt", { allowEmpty: true });
682
+ readWorkerPromptMessages(spec.dynamicPromptMessages, "WorkerSpec.dynamicPromptMessages");
683
+ readOptionalString(spec, "promptSignature", "WorkerSpec");
684
+ readOptionalString(spec, "toolSignature", "WorkerSpec");
685
+ readOptionalString(spec, "dynamicHash", "WorkerSpec");
686
+ readString(spec.agentId, "WorkerSpec.agentId");
687
+ readString(spec.task, "WorkerSpec.task");
688
+ validateTarget(spec.target, runtimeId, runtimeAliases);
689
+ readString(spec.wireModelId, "WorkerSpec.wireModelId");
690
+ readOptionalString(spec, "sessionId", "WorkerSpec");
691
+ readOptionalString(spec, "apiKey", "WorkerSpec");
692
+ readOptionalEnum(spec, "thinkingLevel", "WorkerSpec", THINKING_LEVELS);
693
+ if (spec.modelCapabilities !== void 0)
694
+ validateCapabilityPatch(spec.modelCapabilities, "WorkerSpec.modelCapabilities");
695
+ if (spec.responseSchema !== void 0) {
696
+ assertValidResponseSchema(spec.responseSchema, "WorkerSpec.responseSchema");
697
+ if (!runtimeSpeaksResponseSchemaDialect({ id: runtimeId, kind: runtimeKind, apiFamily: runtimeApiFamily })) {
698
+ throw new Error("WorkerSpec.responseSchema is supported only by the native llamacpp runtime");
699
+ }
700
+ const structuredOutputs = spec.modelCapabilities === void 0 ? void 0 : readRecord(spec.modelCapabilities, "WorkerSpec.modelCapabilities").structuredOutputs;
701
+ if (structuredOutputs !== "json-schema") {
702
+ throw new Error("WorkerSpec.responseSchema requires resolved JSON-schema model capability");
703
+ }
704
+ }
705
+ validateAllowedTools(spec.allowedTools);
706
+ validateWorkerBudget(spec.budget);
707
+ validateProtectedModels(spec.protectedModels);
708
+ validateRuntimeResolution(spec.runtimeResolution);
709
+ if (spec.middlewareSnapshot !== void 0) validateMiddlewareSnapshot(spec.middlewareSnapshot);
710
+ if (spec.protectedArtifactState !== void 0) validateProtectedArtifactState(spec.protectedArtifactState);
711
+ if (spec.noSkills !== void 0 && typeof spec.noSkills !== "boolean") {
712
+ throw new Error("WorkerSpec.noSkills must be a boolean");
713
+ }
714
+ if (spec.skillPaths !== void 0) {
715
+ readStringArray(spec.skillPaths, "WorkerSpec.skillPaths");
716
+ }
717
+ if (spec.agentSkills !== void 0) {
718
+ for (const name of readStringArray(spec.agentSkills, "WorkerSpec.agentSkills")) {
719
+ if (name.trim().length === 0) throw new Error("WorkerSpec.agentSkills entries must be non-empty strings");
720
+ }
721
+ }
722
+ if (spec.trustProjectCompatRoots !== void 0 && typeof spec.trustProjectCompatRoots !== "boolean") {
723
+ throw new Error("WorkerSpec.trustProjectCompatRoots must be a boolean");
724
+ }
725
+ if (spec.gitCommitAttribution !== void 0 && typeof spec.gitCommitAttribution !== "boolean") {
726
+ throw new Error("WorkerSpec.gitCommitAttribution must be a boolean");
727
+ }
728
+ readOptionalEnum(spec, "toolProfile", "WorkerSpec", TOOL_PROFILE_NAMES2);
729
+ readOptionalEnum(spec, "product", "WorkerSpec", WORKER_PRODUCTS);
730
+ if (spec.onPermission !== void 0 && spec.onPermission !== "deny" && spec.onPermission !== "fail" && spec.onPermission !== "escalate") {
731
+ throw new Error('WorkerSpec.onPermission must be "deny", "fail", or "escalate"');
732
+ }
733
+ if (spec.escalation !== void 0) {
734
+ const escalation = readRecord(spec.escalation, "WorkerSpec.escalation");
735
+ const timeoutMs = escalation.timeoutMs;
736
+ if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
737
+ throw new Error("WorkerSpec.escalation.timeoutMs must be a positive finite number");
738
+ }
739
+ if (escalation.fallback !== "deny" && escalation.fallback !== "fail") {
740
+ throw new Error('WorkerSpec.escalation.fallback must be "deny" or "fail"');
741
+ }
742
+ }
743
+ if (spec.autonomy !== void 0) {
744
+ readEnum(spec.autonomy, "WorkerSpec.autonomy", SPEC_AUTONOMY_LEVELS);
745
+ }
746
+ if (spec.ledger !== void 0) {
747
+ const ledger = readRecord(spec.ledger, "WorkerSpec.ledger");
748
+ readString(ledger.id, "WorkerSpec.ledger.id");
749
+ if (typeof ledger.sequence !== "number" || !Number.isSafeInteger(ledger.sequence) || ledger.sequence < 0) {
750
+ throw new Error("WorkerSpec.ledger.sequence must be a non-negative safe integer");
751
+ }
752
+ }
753
+ if (spec.writeRoots !== void 0) {
754
+ const roots = readStringArray(spec.writeRoots, "WorkerSpec.writeRoots");
755
+ if (roots.length === 0) throw new Error("WorkerSpec.writeRoots must be a non-empty array when present");
756
+ for (const root of roots) {
757
+ if (root.trim().length === 0) throw new Error("WorkerSpec.writeRoots entries must be non-empty strings");
758
+ }
759
+ }
760
+ return spec;
761
+ }
762
+ function validateRehydratedWorkerRuntime(spec, runtime) {
763
+ const expected = spec.runtime;
764
+ if (runtime.id !== expected.id) {
765
+ throw new Error(`WorkerSpec runtime rehydration mismatch for id: expected ${expected.id}, got ${runtime.id}`);
766
+ }
767
+ if (runtime.kind !== expected.kind) {
768
+ throw new Error(`WorkerSpec runtime rehydration mismatch for kind: expected ${expected.kind}, got ${runtime.kind}`);
769
+ }
770
+ if (runtime.apiFamily !== expected.apiFamily) {
771
+ throw new Error(
772
+ `WorkerSpec runtime rehydration mismatch for apiFamily: expected ${expected.apiFamily}, got ${runtime.apiFamily}`
773
+ );
774
+ }
775
+ if (runtime.auth !== expected.auth) {
776
+ throw new Error(`WorkerSpec runtime rehydration mismatch for auth: expected ${expected.auth}, got ${runtime.auth}`);
777
+ }
778
+ }
779
+
780
+ // src/domains/dispatch/gate-role-prompts.ts
781
+ init_esm_shims();
782
+ var REVIEWER_GATE_PROMPT = [
783
+ "You are a strict, read-only reviewer of one implementation run.",
784
+ "Inspect the supplied result and repository state with read-only tools.",
785
+ "You cannot modify anything.",
786
+ "Judge only whether the work passes. Whether a failure earns another attempt is not your decision.",
787
+ 'End with a JSON object only: {"verdict":"pass|fail","checks":[{"name":"...","passed":true,"evidence":"what you inspected and observed"}]}.',
788
+ "The verdict must agree with every check. Report at least one check."
789
+ ].join("\n");
790
+ var JUDGE_GATE_PROMPT = [
791
+ "You are a strict, read-only judge ranking candidate implementations of the same task.",
792
+ "Each candidate is a git branch with its work committed; inspect the branches and worktree paths you are given with read tools.",
793
+ "You cannot modify anything.",
794
+ 'End with a JSON object only: {"winner":<candidate number>,"checks":[{"name":"...","passed":true,"evidence":"what you compared and observed"}]}.',
795
+ "The winner must be one of the candidate numbers you were given. Report at least one check.",
796
+ "Report in your checks where the candidates disagreed, covering approach, files touched, and tests, not only which one won."
797
+ ].join("\n");
798
+ var COMPETE_STANCES = [
799
+ "minimal-diff",
800
+ "test-first",
801
+ "refactor-tolerant",
802
+ "spec-literal"
803
+ ];
804
+ var COMPETE_STANCE_LINERS = {
805
+ "minimal-diff": "Prefer the smallest change that satisfies the task; do not restructure surrounding code.",
806
+ "test-first": "Write or extend a test that fails for the stated reason first, then make it pass.",
807
+ "refactor-tolerant": "Reshape the surrounding code when the task exposes a bad shape, as long as existing behavior stays covered.",
808
+ "spec-literal": "Implement exactly what the task text states and nothing it leaves unasked."
809
+ };
810
+ function competeStanceLiner(stance) {
811
+ return `Compete stance: ${stance}. ${COMPETE_STANCE_LINERS[stance]}`;
812
+ }
813
+ function isBoundedGateRolePrompt(input) {
814
+ if (input.autonomy !== "read-only") return false;
815
+ if (input.role === "reviewer") return input.systemPrompt === REVIEWER_GATE_PROMPT;
816
+ if (input.role === "judge") return input.systemPrompt === JUDGE_GATE_PROMPT;
817
+ return false;
818
+ }
819
+
820
+ // src/domains/dispatch/types.ts
821
+ init_esm_shims();
822
+ function isRunOutcomeCode(value) {
823
+ return value === "vram_capacity_fit_failure" || value === "worker_tool_call_cap_exhausted" || value === "loop_guard_tools_disabled_exhausted" || value === "result_contract_exhausted" || value === "worker_final_output_missing";
824
+ }
825
+ var RETRYABLE_OUTCOMES = /* @__PURE__ */ new Set(["failed", "timed_out", "stalled", "spawn_failed"]);
826
+ function isTerminalRunEnvelope(run) {
827
+ if (run.endedAt !== null) return true;
828
+ return run.status !== "queued" && run.status !== "running";
829
+ }
830
+ function runKindSupportsLiveSteering(kind) {
831
+ return kind === "http" || kind === "sdk";
832
+ }
833
+
834
+ // src/domains/session/task-board.ts
835
+ init_esm_shims();
836
+ import { randomUUID } from "node:crypto";
837
+
838
+ // src/domains/session/entries.ts
839
+ init_esm_shims();
840
+ var SESSION_ENTRY_KINDS = [
841
+ "message",
842
+ "bashExecution",
843
+ "custom",
844
+ "modelChange",
845
+ "thinkingLevelChange",
846
+ "fileEntry",
847
+ "branchSummary",
848
+ "compactionSummary",
849
+ "sessionInfo",
850
+ "label",
851
+ "protectedArtifact",
852
+ "skillActivation",
853
+ "taskLedger",
854
+ "decisionLedger",
855
+ "workerRun"
856
+ ];
857
+ function isRecord(value) {
858
+ return !!value && typeof value === "object";
859
+ }
860
+ function isString(value) {
861
+ return typeof value === "string";
862
+ }
863
+ function isOptionalString(value) {
864
+ return value === void 0 || typeof value === "string";
865
+ }
866
+ function isOptionalBoolean(value) {
867
+ return value === void 0 || typeof value === "boolean";
868
+ }
869
+ function isNumber(value) {
870
+ return typeof value === "number" && Number.isFinite(value);
871
+ }
872
+ function isPositiveInteger(value) {
873
+ return isNumber(value) && Number.isInteger(value) && value > 0;
874
+ }
875
+ function isOptionalNumber(value) {
876
+ return value === void 0 || isNumber(value);
877
+ }
878
+ function isNullableString(value) {
879
+ return value === null || typeof value === "string";
880
+ }
881
+ function isOneOf(value, allowed) {
882
+ return typeof value === "string" && allowed.includes(value);
883
+ }
884
+ function isStringArray(value) {
885
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
886
+ }
887
+ function hasBaseSessionEntryFields(v) {
888
+ return isString(v.turnId) && isNullableString(v.parentTurnId) && isString(v.timestamp);
889
+ }
890
+ var MESSAGE_ROLES = ["user", "assistant", "tool_call", "tool_result", "system", "checkpoint"];
891
+ var FILE_OPERATIONS = ["read", "write", "edit", "create", "delete"];
892
+ var COMPACTION_TRIGGERS = ["auto", "force", "overflow"];
893
+ var PROTECTED_ARTIFACT_SOURCES = [
894
+ "validation",
895
+ "middleware",
896
+ "user",
897
+ "session"
898
+ ];
899
+ var TASK_LEDGER_STATUSES = ["pending", "active", "completed", "blocked", "cancelled"];
900
+ var TASK_LEDGER_EVIDENCE_STATUSES = [
901
+ "required",
902
+ "pending",
903
+ "passed",
904
+ "failed",
905
+ "missing"
906
+ ];
907
+ var DECISION_STATUSES = ["active", "superseded"];
908
+ var DECISION_INTERVIEW_STATUSES = ["complete", "cancelled"];
909
+ var WORKER_RUN_ORIGINS = ["user", "agent"];
910
+ var WORKER_RUN_RUNTIME_KINDS = ["clio", "acp", "claude-sdk", "claude-code"];
911
+ function isWorkerRunRuntime(value) {
912
+ if (!isRecord(value)) return false;
913
+ return isOneOf(value.kind, WORKER_RUN_RUNTIME_KINDS) && isOptionalString(value.targetId) && isOptionalString(value.wireModelId) && isOptionalString(value.peerId);
914
+ }
915
+ function isTaskLedgerGoal(value) {
916
+ if (!isRecord(value)) return false;
917
+ if (!isString(value.id) || !isString(value.title)) return false;
918
+ if (!isOneOf(value.status, TASK_LEDGER_STATUSES)) return false;
919
+ if (value.parentGoalId !== void 0 && !isNullableString(value.parentGoalId)) return false;
920
+ const hasPairedProvenance = value.origin === "user" ? isString(value.userTaskId) && /^u[1-9]\d*$/.test(value.userTaskId) : (value.origin === void 0 || value.origin === "agent") && value.userTaskId === void 0;
921
+ return isOptionalString(value.description) && hasPairedProvenance;
922
+ }
923
+ function isTaskLedgerEvidence(value) {
924
+ if (!isRecord(value)) return false;
925
+ if (!isString(value.id) || !isString(value.description)) return false;
926
+ if (!isOneOf(value.status, TASK_LEDGER_EVIDENCE_STATUSES)) return false;
927
+ return isOptionalString(value.command) && isOptionalString(value.artifactPath) && isOptionalString(value.observedAt) && isOptionalString(value.notes);
928
+ }
929
+ function isDecisionRecord(value) {
930
+ if (!isRecord(value)) return false;
931
+ if (!isString(value.key) || !/^[a-z0-9]+(?:_[a-z0-9]+)*$/.test(value.key)) return false;
932
+ if (!isString(value.value) || !isOneOf(value.status, DECISION_STATUSES) || !isString(value.decidedAt)) return false;
933
+ if (!isOptionalString(value.label) || !isOptionalString(value.source_question)) return false;
934
+ if (!isOptionalString(value.revisedAt) || !isOptionalString(value.correction)) return false;
935
+ return value.status === "superseded" ? isString(value.revisedAt) : value.revisedAt === void 0 && value.correction === void 0;
936
+ }
937
+ function isOptionalCompactionUsage(value) {
938
+ if (value === void 0) return true;
939
+ if (!isRecord(value)) return false;
940
+ const cost = value.cost;
941
+ return isNumber(value.input) && isNumber(value.output) && isNumber(value.cacheRead) && isNumber(value.cacheWrite) && isNumber(value.reasoning) && isNumber(value.totalTokens) && isNumber(value.apiCalls) && isRecord(cost) && isNumber(cost.total);
942
+ }
943
+ function isProtectedArtifact(value) {
944
+ if (!isRecord(value)) return false;
945
+ return isString(value.path) && isString(value.protectedAt) && isString(value.reason) && isOneOf(value.source, PROTECTED_ARTIFACT_SOURCES) && isOptionalString(value.validationCommand) && isOptionalNumber(value.validationExitCode);
946
+ }
947
+ function isSessionHeader(value) {
948
+ if (!isRecord(value)) return false;
949
+ return value.type === "session" && isPositiveInteger(value.version) && isString(value.id) && isString(value.timestamp) && isString(value.cwd) && isOptionalString(value.parentSession) && isOptionalString(value.parentTurnId);
950
+ }
951
+ function isSessionEntry(value) {
952
+ if (!value || typeof value !== "object") return false;
953
+ const v = value;
954
+ if (!hasBaseSessionEntryFields(v)) return false;
955
+ if (!isOneOf(v.kind, SESSION_ENTRY_KINDS)) return false;
956
+ switch (v.kind) {
957
+ case "message":
958
+ return Object.hasOwn(v, "payload") && isOneOf(v.role, MESSAGE_ROLES);
959
+ case "bashExecution":
960
+ return isString(v.command) && isString(v.output) && (v.exitCode === null || isNumber(v.exitCode)) && typeof v.cancelled === "boolean" && typeof v.truncated === "boolean" && isOptionalString(v.fullOutputPath) && isOptionalBoolean(v.excludeFromContext);
961
+ case "custom":
962
+ return isString(v.customType) && isOptionalBoolean(v.display);
963
+ case "modelChange":
964
+ return isString(v.provider) && isString(v.modelId) && isOptionalString(v.target);
965
+ case "thinkingLevelChange":
966
+ return isString(v.thinkingLevel);
967
+ case "fileEntry":
968
+ return isString(v.path) && isOneOf(v.operation, FILE_OPERATIONS) && isOptionalNumber(v.bytes) && isOptionalString(v.hash);
969
+ case "branchSummary":
970
+ return isString(v.fromTurnId) && isString(v.summary);
971
+ case "compactionSummary":
972
+ return isString(v.summary) && isNumber(v.tokensBefore) && isString(v.firstKeptTurnId) && isOptionalCompactionUsage(v.usage) && (v.trigger === void 0 || isOneOf(v.trigger, COMPACTION_TRIGGERS)) && isOptionalNumber(v.tokensAfter) && isOptionalNumber(v.messagesSummarized) && isOptionalBoolean(v.isSplitTurn);
973
+ case "sessionInfo":
974
+ return isOptionalString(v.name) && isOptionalString(v.targetTurnId) && isOptionalString(v.label);
975
+ case "label":
976
+ return isString(v.targetTurnId) && isOptionalString(v.label);
977
+ case "protectedArtifact":
978
+ return v.action === "protect" && isProtectedArtifact(v.artifact) && isOptionalString(v.toolName) && isOptionalString(v.toolCallId) && isOptionalString(v.runId) && isOptionalString(v.correlationId);
979
+ case "skillActivation":
980
+ return isSkillActivation(v.activation);
981
+ case "taskLedger":
982
+ return isOptionalString(v.boardId) && Array.isArray(v.goals) && v.goals.every(isTaskLedgerGoal) && Array.isArray(v.subgoals) && v.subgoals.every(isTaskLedgerGoal) && isStringArray(v.activeRunIds) && Array.isArray(v.requiredValidationEvidence) && v.requiredValidationEvidence.every(isTaskLedgerEvidence);
983
+ case "decisionLedger":
984
+ return isString(v.interviewId) && isOneOf(v.interviewStatus, DECISION_INTERVIEW_STATUSES) && isString(v.startedAt) && isString(v.endedAt) && isNumber(v.roundCount) && Number.isInteger(v.roundCount) && v.roundCount >= 0 && isOptionalString(v.summary) && isOptionalString(v.transcriptPath) && Array.isArray(v.decisions) && v.decisions.every(isDecisionRecord);
985
+ case "workerRun":
986
+ return isString(v.assignmentId) && isString(v.runId) && isOneOf(v.origin, WORKER_RUN_ORIGINS) && isString(v.agentId) && isWorkerRunRuntime(v.runtime) && isOptionalString(v.parentToolCallId);
987
+ }
988
+ return false;
989
+ }
990
+
991
+ // src/domains/session/task-board.ts
992
+ var TASK_BOARD_GOAL_ID = "board";
993
+ var LEGACY_TASK_BOARD_ID = "legacy";
994
+ function isOpenUserTask(task) {
995
+ return task.origin === "user" && (task.status === "pending" || task.status === "active");
996
+ }
997
+ function taskBoardCounts(board) {
998
+ const counts = {
999
+ total: board.tasks.length,
1000
+ completed: 0,
1001
+ active: 0,
1002
+ pending: 0,
1003
+ blocked: 0,
1004
+ cancelled: 0,
1005
+ open: 0
1006
+ };
1007
+ for (const task of board.tasks) {
1008
+ if (task.status === "completed") counts.completed += 1;
1009
+ else if (task.status === "active") counts.active += 1;
1010
+ else if (task.status === "pending") counts.pending += 1;
1011
+ else if (task.status === "blocked") counts.blocked += 1;
1012
+ else counts.cancelled += 1;
1013
+ }
1014
+ counts.open = counts.pending + counts.active;
1015
+ return counts;
1016
+ }
1017
+ function boardStatus(tasks) {
1018
+ const counts = taskBoardCounts({ tasks });
1019
+ if (counts.total === 0) return "pending";
1020
+ if (counts.active > 0) return "active";
1021
+ if (counts.open === 0 && counts.blocked === 0) return "completed";
1022
+ if (counts.blocked > 0 && counts.open === 0) return "blocked";
1023
+ return "pending";
1024
+ }
1025
+ function toTaskLedgerEntryFields(board, now) {
1026
+ const evidence = [];
1027
+ const subgoals = board.tasks.map((task) => {
1028
+ if (task.status === "completed" && task.evidence) {
1029
+ evidence.push({
1030
+ id: `${task.id}.evidence`,
1031
+ description: task.evidence,
1032
+ status: "passed",
1033
+ observedAt: now.toISOString()
1034
+ });
1035
+ }
1036
+ const goal = {
1037
+ id: task.id,
1038
+ title: task.title,
1039
+ status: task.status,
1040
+ parentGoalId: TASK_BOARD_GOAL_ID
1041
+ };
1042
+ if (task.origin) goal.origin = task.origin;
1043
+ if (task.userTaskId) goal.userTaskId = task.userTaskId;
1044
+ if (task.reason) goal.description = task.reason;
1045
+ return goal;
1046
+ });
1047
+ return {
1048
+ kind: "taskLedger",
1049
+ parentTurnId: null,
1050
+ boardId: board.boardId,
1051
+ goals: [{ id: TASK_BOARD_GOAL_ID, title: board.title, status: boardStatus(board.tasks) }],
1052
+ subgoals,
1053
+ activeRunIds: [...board.activeRunIds],
1054
+ requiredValidationEvidence: evidence
1055
+ };
1056
+ }
1057
+ function isTaskLedgerShaped(value) {
1058
+ return isSessionEntry(value) && value.kind === "taskLedger";
1059
+ }
1060
+ function foldTaskBoard(entries) {
1061
+ let last = null;
1062
+ for (const raw of entries) {
1063
+ if (isTaskLedgerShaped(raw)) last = toEntryView(raw);
1064
+ }
1065
+ return last;
1066
+ }
1067
+ function foldSessionTaskHistory(entries) {
1068
+ const boards = /* @__PURE__ */ new Map();
1069
+ for (const [index, raw] of entries.entries()) {
1070
+ if (!isTaskLedgerShaped(raw)) continue;
1071
+ const view = toEntryView(raw);
1072
+ if (!view) continue;
1073
+ const boardId = typeof raw.boardId === "string" && raw.boardId.length > 0 ? raw.boardId : LEGACY_TASK_BOARD_ID;
1074
+ const timestamp = typeof raw.timestamp === "string" ? raw.timestamp : "";
1075
+ if (boardId === LEGACY_TASK_BOARD_ID) {
1076
+ boards.set(boardId, {
1077
+ boardId,
1078
+ title: view.title,
1079
+ tasks: new Map(view.tasks.map((task) => [task.id, task])),
1080
+ lastSnapshotAt: timestamp,
1081
+ lastIndex: index
1082
+ });
1083
+ continue;
1084
+ }
1085
+ const existing = boards.get(boardId);
1086
+ if (!existing) {
1087
+ boards.set(boardId, {
1088
+ boardId,
1089
+ title: view.title,
1090
+ tasks: new Map(view.tasks.map((task) => [task.id, task])),
1091
+ lastSnapshotAt: timestamp,
1092
+ lastIndex: index
1093
+ });
1094
+ continue;
1095
+ }
1096
+ existing.title = view.title;
1097
+ for (const task of view.tasks) existing.tasks.set(task.id, task);
1098
+ existing.lastSnapshotAt = timestamp;
1099
+ existing.lastIndex = index;
1100
+ }
1101
+ return [...boards.values()].sort((left, right) => right.lastIndex - left.lastIndex).map(({ lastIndex: _lastIndex, tasks, ...board }) => ({ ...board, tasks: [...tasks.values()] }));
1102
+ }
1103
+ function toEntryView(entry) {
1104
+ const boardGoal = entry.goals[0];
1105
+ if (!boardGoal) return null;
1106
+ const evidenceByTask = /* @__PURE__ */ new Map();
1107
+ for (const item of entry.requiredValidationEvidence) {
1108
+ const taskId = item.id.endsWith(".evidence") ? item.id.slice(0, -".evidence".length) : item.id;
1109
+ evidenceByTask.set(taskId, item.description);
1110
+ }
1111
+ return {
1112
+ boardId: entry.boardId ?? LEGACY_TASK_BOARD_ID,
1113
+ title: boardGoal.title,
1114
+ tasks: entry.subgoals.map((goal) => {
1115
+ const task = {
1116
+ id: goal.id,
1117
+ title: goal.title,
1118
+ status: goal.status,
1119
+ origin: goal.origin ?? "agent"
1120
+ };
1121
+ if (goal.userTaskId) task.userTaskId = goal.userTaskId;
1122
+ if (goal.description) task.reason = goal.description;
1123
+ const evidence = evidenceByTask.get(goal.id);
1124
+ if (evidence) task.evidence = evidence;
1125
+ return task;
1126
+ }),
1127
+ // Run linkage is process-live: the runs recorded in old entries ended
1128
+ // with the process that dispatched them, so a refold starts empty and
1129
+ // the historical linkage stays readable in the earlier entries.
1130
+ activeRunIds: []
1131
+ };
1132
+ }
1133
+ function nextTaskId(tasks) {
1134
+ let max = 0;
1135
+ for (const task of tasks) {
1136
+ const match = /^t(\d+)$/.exec(task.id);
1137
+ if (match) max = Math.max(max, Number(match[1]));
1138
+ }
1139
+ return max + 1;
1140
+ }
1141
+ function normalizeTitles(titles) {
1142
+ return titles.map((title) => title.trim()).filter((title) => title.length > 0);
1143
+ }
1144
+ function applyMutation(board, mutation) {
1145
+ if (mutation.op === "plan") {
1146
+ const titles = normalizeTitles(mutation.tasks);
1147
+ if (mutation.title.trim().length === 0) return { error: "plan requires a non-empty title" };
1148
+ if (titles.length === 0) return { error: "plan requires at least one task" };
1149
+ const retained = board?.tasks.filter(isOpenUserTask) ?? [];
1150
+ const notes2 = [];
1151
+ const replacedOpen = board ? taskBoardCounts(board).open - retained.length : 0;
1152
+ if (board && replacedOpen > 0) {
1153
+ notes2.push(`replaced board "${board.title}" with ${replacedOpen} agent task(s) still open`);
1154
+ }
1155
+ if (retained.length > 0) notes2.push(`preserved ${retained.length} open operator task(s)`);
1156
+ const start = nextTaskId(retained);
1157
+ return {
1158
+ board: {
1159
+ boardId: "",
1160
+ title: mutation.title.trim(),
1161
+ tasks: [
1162
+ ...retained,
1163
+ ...titles.map((title, index) => ({
1164
+ id: `t${start + index}`,
1165
+ title,
1166
+ status: "pending",
1167
+ origin: "agent"
1168
+ }))
1169
+ ],
1170
+ // Runs in flight outlive a board swap: they belong to the session,
1171
+ // so the fresh board inherits the linkage until the runs finish.
1172
+ activeRunIds: board?.activeRunIds ?? []
1173
+ },
1174
+ notes: notes2
1175
+ };
1176
+ }
1177
+ if (mutation.op === "pick") {
1178
+ const title = mutation.title.trim();
1179
+ if (title.length === 0) return { error: "pick requires a non-empty operator task title" };
1180
+ if (!/^u[1-9]\d*$/.test(mutation.userTaskId)) return { error: "pick requires an operator task id like u3" };
1181
+ if (board?.tasks.some(
1182
+ (task) => task.userTaskId === mutation.userTaskId && (task.status === "pending" || task.status === "active" || task.status === "completed")
1183
+ )) {
1184
+ return { error: `operator task ${mutation.userTaskId} is already linked to durable board work` };
1185
+ }
1186
+ const tasks2 = board?.tasks ?? [];
1187
+ const picked = {
1188
+ id: `t${nextTaskId(tasks2)}`,
1189
+ title,
1190
+ status: "pending",
1191
+ origin: "user",
1192
+ userTaskId: mutation.userTaskId
1193
+ };
1194
+ return {
1195
+ board: {
1196
+ boardId: board?.boardId ?? "",
1197
+ title: board?.title ?? "Operator tasks",
1198
+ tasks: [...tasks2, picked],
1199
+ activeRunIds: board?.activeRunIds ?? []
1200
+ },
1201
+ notes: []
1202
+ };
1203
+ }
1204
+ if (board === null) return { error: 'no task board yet; declare one with action="plan" first' };
1205
+ if (mutation.op === "add") {
1206
+ const titles = normalizeTitles(mutation.tasks);
1207
+ if (titles.length === 0) return { error: "add requires at least one task" };
1208
+ const start = nextTaskId(board.tasks);
1209
+ const added = titles.map((title, index) => ({
1210
+ id: `t${start + index}`,
1211
+ title,
1212
+ status: "pending",
1213
+ origin: "agent"
1214
+ }));
1215
+ return { board: { ...board, tasks: [...board.tasks, ...added] }, notes: [] };
1216
+ }
1217
+ const target = board.tasks.find((task) => task.id === mutation.id);
1218
+ if (!target) return { error: `task ${mutation.id} not found on the board` };
1219
+ if (mutation.op === "block" && mutation.reason.trim().length === 0) {
1220
+ return { error: "block requires a reason so the ledger records why work stopped" };
1221
+ }
1222
+ if (mutation.op === "done") {
1223
+ if (mutation.evidence.trim().length === 0) {
1224
+ return {
1225
+ error: "done requires note as the evidence that the task actually finished (the command you ran, the file:line you verified). If the work did not happen, use block with a reason or drop it."
1226
+ };
1227
+ }
1228
+ if (target.status === "pending") {
1229
+ return {
1230
+ error: `task ${target.id} was never started, so it cannot be completed. Start it and do the work, or record the truth with block (reason) or drop.`
1231
+ };
1232
+ }
1233
+ }
1234
+ const notes = [];
1235
+ const tasks = board.tasks.map((task) => {
1236
+ if (task.id !== target.id) {
1237
+ if (mutation.op === "start" && task.status === "active") {
1238
+ notes.push(`parked ${task.id} back to pending (one task active at a time)`);
1239
+ return { ...task, status: "pending" };
1240
+ }
1241
+ return task;
1242
+ }
1243
+ return applyStatusMutation(task, mutation);
1244
+ });
1245
+ return { board: { ...board, tasks }, notes };
1246
+ }
1247
+ function applyStatusMutation(task, mutation) {
1248
+ switch (mutation.op) {
1249
+ case "start":
1250
+ return { ...task, status: "active" };
1251
+ case "done": {
1252
+ const done = { ...task, status: "completed", evidence: mutation.evidence.trim() };
1253
+ delete done.reason;
1254
+ return done;
1255
+ }
1256
+ case "block":
1257
+ return { ...task, status: "blocked", reason: mutation.reason.trim() };
1258
+ case "drop": {
1259
+ const dropped = { ...task, status: "cancelled" };
1260
+ if (mutation.reason?.trim()) dropped.reason = mutation.reason.trim();
1261
+ return dropped;
1262
+ }
1263
+ }
1264
+ }
1265
+ function createTaskBoardStore(deps = {}) {
1266
+ let cachedSessionId;
1267
+ let dirty = true;
1268
+ let board = null;
1269
+ const syncToSession = () => {
1270
+ const sessionId = deps.getSessionId?.() ?? null;
1271
+ if (!dirty && cachedSessionId === sessionId) return;
1272
+ dirty = false;
1273
+ cachedSessionId = sessionId;
1274
+ try {
1275
+ board = deps.readEntries ? foldTaskBoard(deps.readEntries()) : null;
1276
+ } catch {
1277
+ board = null;
1278
+ }
1279
+ };
1280
+ const persist = (next) => {
1281
+ try {
1282
+ deps.appendEntry?.(toTaskLedgerEntryFields(next, deps.now?.() ?? /* @__PURE__ */ new Date()));
1283
+ } catch {
1284
+ }
1285
+ };
1286
+ const mutationRequiresAcknowledgement = (current, mutation) => {
1287
+ if (mutation.op === "pick") return true;
1288
+ if (mutation.op === "plan") return current?.tasks.some(isOpenUserTask) ?? false;
1289
+ if (mutation.op !== "done") return false;
1290
+ return current?.tasks.some((task) => task.id === mutation.id && task.origin === "user") ?? false;
1291
+ };
1292
+ return {
1293
+ snapshot() {
1294
+ syncToSession();
1295
+ return board;
1296
+ },
1297
+ cachedSnapshot() {
1298
+ const sessionId = deps.getSessionId?.() ?? null;
1299
+ return !dirty && cachedSessionId === sessionId ? board : null;
1300
+ },
1301
+ historySnapshot() {
1302
+ syncToSession();
1303
+ try {
1304
+ return deps.readEntries ? foldSessionTaskHistory(deps.readEntries()) : [];
1305
+ } catch {
1306
+ return [];
1307
+ }
1308
+ },
1309
+ apply(mutation) {
1310
+ syncToSession();
1311
+ const result = applyMutation(board, mutation);
1312
+ if ("error" in result) return { ok: false, message: result.error };
1313
+ const needsBoardId = mutation.op === "plan" || result.board.boardId.length === 0;
1314
+ const nextBoard = needsBoardId ? { ...result.board, boardId: deps.createBoardId?.() ?? randomUUID() } : result.board;
1315
+ if (mutationRequiresAcknowledgement(board, mutation)) {
1316
+ if (!deps.appendEntry) {
1317
+ return { ok: false, message: "durable task-ledger persistence is unavailable for operator-linked work" };
1318
+ }
1319
+ try {
1320
+ deps.appendEntry(toTaskLedgerEntryFields(nextBoard, deps.now?.() ?? /* @__PURE__ */ new Date()));
1321
+ } catch (error) {
1322
+ const message = error instanceof Error ? error.message : String(error);
1323
+ return { ok: false, message: `could not persist operator-linked task board: ${message}` };
1324
+ }
1325
+ board = nextBoard;
1326
+ return { ok: true, board: nextBoard, notes: result.notes };
1327
+ }
1328
+ board = nextBoard;
1329
+ persist(nextBoard);
1330
+ return { ok: true, board: nextBoard, notes: result.notes };
1331
+ },
1332
+ attachRun(runId) {
1333
+ syncToSession();
1334
+ if (board === null || runId.length === 0 || board.activeRunIds.includes(runId)) return;
1335
+ board = { ...board, activeRunIds: [...board.activeRunIds, runId] };
1336
+ persist(board);
1337
+ },
1338
+ detachRun(runId) {
1339
+ syncToSession();
1340
+ if (board === null || !board.activeRunIds.includes(runId)) return;
1341
+ board = { ...board, activeRunIds: board.activeRunIds.filter((id) => id !== runId) };
1342
+ persist(board);
1343
+ },
1344
+ invalidate() {
1345
+ dirty = true;
1346
+ }
1347
+ };
1348
+ }
1349
+
1350
+ // src/engine/antigravity/subprocess-runtime.ts
1351
+ init_esm_shims();
1352
+ import { spawn } from "node:child_process";
1353
+
1354
+ // src/engine/external-subprocess.ts
1355
+ init_esm_shims();
1356
+ async function readStderr(child) {
1357
+ let stderr = "";
1358
+ for await (const chunk of child.stderr) {
1359
+ stderr += String(chunk);
1360
+ if (stderr.length > 8192) stderr = stderr.slice(-8192);
1361
+ }
1362
+ return stderr;
1363
+ }
1364
+ function waitForClose(child) {
1365
+ return new Promise((resolve) => {
1366
+ child.once("error", () => resolve(1));
1367
+ child.once("close", (code) => resolve(code ?? 1));
1368
+ });
1369
+ }
1370
+
1371
+ // src/engine/antigravity/subprocess-runtime.ts
1372
+ var ANTIGRAVITY_BINARY = "agy";
1373
+ var ZERO_USAGE = {
1374
+ input: 0,
1375
+ output: 0,
1376
+ cacheRead: 0,
1377
+ cacheWrite: 0,
1378
+ totalTokens: 0,
1379
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
1380
+ };
1381
+ function antigravitySubprocessConfigForAutonomy(level, env = process.env) {
1382
+ if (level === "full-auto" && env.CLIO_CODER_ALLOW_EXTERNAL_FULL_ACCESS === "1") {
1383
+ return {
1384
+ extraArgs: ["--dangerously-skip-permissions"],
1385
+ dangerousBypass: true,
1386
+ externalMode: "bypassPermissions"
1387
+ };
1388
+ }
1389
+ if (level === "suggest") {
1390
+ throw new Error(
1391
+ "antigravity-code runtime cannot enforce autonomy 'suggest': it cannot park tool calls for approval. Dispatch to a native or claude-sdk worker, or use read-only or auto-edit."
1392
+ );
1393
+ }
1394
+ if (level === "read-only") {
1395
+ return { extraArgs: ["--mode", "plan", "--sandbox"], dangerousBypass: false, externalMode: "plan+sandbox" };
1396
+ }
1397
+ return { extraArgs: [], dangerousBypass: false, externalMode: "agy-settings-default" };
1398
+ }
1399
+ function buildAntigravityPrompt(input) {
1400
+ const parts = [];
1401
+ const systemPrompt = input.systemPrompt.trim();
1402
+ if (systemPrompt.length > 0) parts.push(systemPrompt);
1403
+ for (const message of input.dynamicPromptMessages ?? []) {
1404
+ const body = message.body.trim();
1405
+ if (body.length > 0) parts.push(body);
1406
+ }
1407
+ parts.push(input.task);
1408
+ return parts.join("\n\n");
1409
+ }
1410
+ function buildAgyArgs(input) {
1411
+ assertToolProfileEnforceable(input.toolProfile, "antigravity-code");
1412
+ const permission = antigravitySubprocessConfigForAutonomy(input.autonomy);
1413
+ const args = ["--print", ...permission.extraArgs];
1414
+ if (input.wireModelId.trim().length > 0) args.push("--model", input.wireModelId.trim());
1415
+ args.push(buildAntigravityPrompt(input));
1416
+ return args;
1417
+ }
1418
+ function buildAssistantMessage(input) {
1419
+ const message = {
1420
+ role: "assistant",
1421
+ content: [{ type: "text", text: input.text }],
1422
+ api: "google-generative-ai",
1423
+ provider: "google",
1424
+ model: input.model,
1425
+ usage: ZERO_USAGE,
1426
+ stopReason: input.aborted ? "aborted" : input.exitCode === 0 ? "stop" : "error",
1427
+ timestamp: Date.now()
1428
+ };
1429
+ if (input.exitCode !== 0 && !input.aborted) {
1430
+ const detail = input.stderr.trim();
1431
+ if (detail.length > 0) message.errorMessage = detail;
1432
+ }
1433
+ return message;
1434
+ }
1435
+ function emitTextDelta(emit, state, delta) {
1436
+ if (delta.length === 0) return;
1437
+ state.text += delta;
1438
+ const message = buildAssistantMessage({
1439
+ model: state.model,
1440
+ text: state.text,
1441
+ exitCode: 0,
1442
+ aborted: false,
1443
+ stderr: ""
1444
+ });
1445
+ if (!state.started) {
1446
+ state.started = true;
1447
+ emit({ type: "message_start", message });
1448
+ }
1449
+ emit({
1450
+ type: "message_update",
1451
+ message,
1452
+ assistantMessageEvent: {
1453
+ type: "text_delta",
1454
+ contentIndex: 0,
1455
+ delta,
1456
+ partial: message
1457
+ }
1458
+ });
1459
+ }
1460
+ async function readStdout(child, emit, state) {
1461
+ for await (const chunk of child.stdout) {
1462
+ emitTextDelta(emit, state, String(chunk));
1463
+ }
1464
+ }
1465
+ function startAntigravityWorkerRun(input, emit) {
1466
+ const args = buildAgyArgs(input);
1467
+ const child = spawn(ANTIGRAVITY_BINARY, args, {
1468
+ cwd: process.cwd(),
1469
+ env: process.env,
1470
+ stdio: ["ignore", "pipe", "pipe"]
1471
+ });
1472
+ const streamState = { started: false, text: "", model: input.wireModelId };
1473
+ let aborted = false;
1474
+ let killTimer = null;
1475
+ const abort = () => {
1476
+ aborted = true;
1477
+ if (child.killed) return;
1478
+ child.kill("SIGTERM");
1479
+ killTimer = setTimeout(() => {
1480
+ if (!child.killed) child.kill("SIGKILL");
1481
+ }, 1500);
1482
+ };
1483
+ if (input.signal) {
1484
+ if (input.signal.aborted) abort();
1485
+ else input.signal.addEventListener("abort", abort, { once: true });
1486
+ }
1487
+ const promise = (async () => {
1488
+ emit({ type: "agent_start" });
1489
+ const stderrPromise = readStderr(child);
1490
+ const stdoutPromise = readStdout(child, emit, streamState);
1491
+ const exitCode = await waitForClose(child);
1492
+ await stdoutPromise.catch(() => {
1493
+ });
1494
+ const stderr = await stderrPromise.catch(() => "");
1495
+ if (killTimer) clearTimeout(killTimer);
1496
+ const finalText = streamState.text || (exitCode === 0 ? "" : stderr.trim());
1497
+ const finalMessage = buildAssistantMessage({
1498
+ model: streamState.model,
1499
+ text: finalText,
1500
+ exitCode,
1501
+ aborted,
1502
+ stderr
1503
+ });
1504
+ if (!streamState.started) emit({ type: "message_start", message: finalMessage });
1505
+ emit({ type: "message_end", message: finalMessage });
1506
+ const messages = [finalMessage];
1507
+ emit({ type: "agent_end", messages });
1508
+ if (exitCode !== 0 && stderr.trim().length > 0 && !aborted) {
1509
+ process.stderr.write(`[worker:antigravity-code] ${stderr.trim()}
1510
+ `);
1511
+ }
1512
+ return { messages, exitCode: exitCode === 0 ? 0 : 1 };
1513
+ })();
1514
+ return {
1515
+ promise,
1516
+ abort
1517
+ };
1518
+ }
1519
+
1520
+ // src/engine/claude/subprocess-runtime.ts
1521
+ init_esm_shims();
1522
+ import { spawn as spawn2 } from "node:child_process";
1523
+ import { createInterface } from "node:readline";
1524
+
1525
+ // src/engine/claude/session-id.ts
1526
+ init_esm_shims();
1527
+ var CLAUDE_CODE_SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1528
+ function isClaudeCodeSessionId(value) {
1529
+ return typeof value === "string" && CLAUDE_CODE_SESSION_ID_PATTERN.test(value.trim());
1530
+ }
1531
+
1532
+ // src/engine/claude/subprocess-runtime.ts
1533
+ var READ_ONLY_CLAUDE_TOOLS = ["Read", "Grep", "Glob", "LS", "WebFetch", "WebSearch"];
1534
+ function claudeSubprocessPermissionConfigForAutonomy(level, env = process.env) {
1535
+ if (level === "full-auto" && env.CLIO_CODER_ALLOW_EXTERNAL_FULL_ACCESS === "1") {
1536
+ return {
1537
+ permissionMode: "bypassPermissions",
1538
+ extraArgs: ["--allow-dangerously-skip-permissions"],
1539
+ dangerousBypass: true
1540
+ };
1541
+ }
1542
+ if (level === "read-only") {
1543
+ return {
1544
+ permissionMode: "plan",
1545
+ extraArgs: ["--tools", READ_ONLY_CLAUDE_TOOLS.join(",")],
1546
+ dangerousBypass: false
1547
+ };
1548
+ }
1549
+ if (level === "suggest") {
1550
+ throw new Error(
1551
+ "claude-code runtime cannot enforce autonomy 'suggest': it cannot park tool calls for approval. Dispatch to a native or claude-sdk worker, or use read-only or auto-edit."
1552
+ );
1553
+ }
1554
+ if (level === "auto-edit") {
1555
+ return { permissionMode: "acceptEdits", extraArgs: [], dangerousBypass: false };
1556
+ }
1557
+ return { permissionMode: "default", extraArgs: [], dangerousBypass: false };
1558
+ }
1559
+ function buildClaudeCodePrompt(input) {
1560
+ const parts = (input.dynamicPromptMessages ?? []).map((message) => message.body.trim()).filter(Boolean);
1561
+ parts.push(input.task);
1562
+ return parts.join("\n\n");
1563
+ }
1564
+ function buildClaudeCodeArgs(input) {
1565
+ assertToolProfileEnforceable(input.toolProfile, "claude-code");
1566
+ const permission = claudeSubprocessPermissionConfigForAutonomy(input.autonomy);
1567
+ const args = [
1568
+ "-p",
1569
+ "--output-format",
1570
+ "stream-json",
1571
+ "--include-partial-messages",
1572
+ "--no-session-persistence",
1573
+ "--permission-mode",
1574
+ permission.permissionMode,
1575
+ ...permission.extraArgs
1576
+ ];
1577
+ if (input.wireModelId.trim().length > 0) args.push("--model", input.wireModelId);
1578
+ const systemPrompt = input.systemPrompt.trim();
1579
+ if (systemPrompt.length > 0) args.push("--append-system-prompt", systemPrompt);
1580
+ if (isClaudeCodeSessionId(input.sessionId)) args.push("--session-id", input.sessionId.trim());
1581
+ args.push(buildClaudeCodePrompt(input));
1582
+ return args;
1583
+ }
1584
+ function finite(value) {
1585
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
1586
+ }
1587
+ function normalizeUsage(raw, totalCostUsd = 0) {
1588
+ const record2 = typeof raw === "object" && raw !== null ? raw : {};
1589
+ const input = finite(record2.input_tokens) + finite(record2.inputTokens) + finite(record2.input) + finite(record2.prompt_tokens) + finite(record2.promptTokens);
1590
+ const output = finite(record2.output_tokens) + finite(record2.outputTokens) + finite(record2.output) + finite(record2.completion_tokens) + finite(record2.completionTokens);
1591
+ const cacheRead = finite(record2.cache_read_input_tokens) + finite(record2.cacheReadInputTokens) + finite(record2.cacheRead) + finite(record2.cacheReadTokens);
1592
+ const cacheWrite = finite(record2.cache_creation_input_tokens) + finite(record2.cacheCreationInputTokens) + finite(record2.cacheWrite) + finite(record2.cacheWriteTokens);
1593
+ const totalTokens = input + output + cacheRead + cacheWrite;
1594
+ const total = finite(totalCostUsd) + finite(record2.costUSD) + finite(record2.cost_usd);
1595
+ return {
1596
+ input,
1597
+ output,
1598
+ cacheRead,
1599
+ cacheWrite,
1600
+ totalTokens,
1601
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total }
1602
+ };
1603
+ }
1604
+ function nestedRecord(record2, key) {
1605
+ const value = record2[key];
1606
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
1607
+ }
1608
+ function extractContentText(content) {
1609
+ if (!Array.isArray(content)) return "";
1610
+ let out = "";
1611
+ for (const block of content) {
1612
+ if (typeof block !== "object" || block === null) continue;
1613
+ const record2 = block;
1614
+ if (record2.type === "text" && typeof record2.text === "string") out += record2.text;
1615
+ }
1616
+ return out;
1617
+ }
1618
+ function extractDelta(record2) {
1619
+ const delta = nestedRecord(record2, "delta");
1620
+ if (delta && typeof delta.text === "string") return delta.text;
1621
+ if (delta && typeof delta.thinking === "string") return "";
1622
+ const contentBlock = nestedRecord(record2, "content_block");
1623
+ if (contentBlock && contentBlock.type === "text" && typeof contentBlock.text === "string") return contentBlock.text;
1624
+ if (typeof record2.delta === "string") return record2.delta;
1625
+ return "";
1626
+ }
1627
+ function assistantTextFromEvent(record2) {
1628
+ const message = nestedRecord(record2, "message");
1629
+ if (message) return extractContentText(message.content);
1630
+ return extractContentText(record2.content);
1631
+ }
1632
+ function resultText(record2) {
1633
+ if (!record2) return "";
1634
+ return typeof record2.result === "string" ? record2.result : "";
1635
+ }
1636
+ function resultError(record2, stderr) {
1637
+ if (record2) {
1638
+ if (typeof record2.error === "string") return record2.error;
1639
+ if (Array.isArray(record2.errors)) return record2.errors.map(String).join("; ");
1640
+ if (record2.subtype !== void 0 && record2.subtype !== "success") return String(record2.subtype);
1641
+ }
1642
+ return stderr.trim();
1643
+ }
1644
+ function buildAssistantMessage2(input) {
1645
+ const errorMessage = input.exitCode === 0 ? "" : resultError(input.result, input.stderr);
1646
+ const message = {
1647
+ role: "assistant",
1648
+ content: [{ type: "text", text: input.text }],
1649
+ api: "claude-code-subprocess",
1650
+ provider: "anthropic",
1651
+ model: input.model,
1652
+ usage: normalizeUsage(input.result?.usage, finite(input.result?.total_cost_usd)),
1653
+ stopReason: input.aborted ? "aborted" : input.exitCode === 0 ? "stop" : "error",
1654
+ timestamp: Date.now()
1655
+ };
1656
+ if (typeof input.result?.request_id === "string") message.responseId = input.result.request_id;
1657
+ if (typeof input.result?.model === "string") message.responseModel = input.result.model;
1658
+ if (errorMessage.length > 0) message.errorMessage = errorMessage;
1659
+ return message;
1660
+ }
1661
+ function emitTextDelta2(emit, state, delta) {
1662
+ if (delta.length === 0) return;
1663
+ state.text += delta;
1664
+ const message = buildAssistantMessage2({
1665
+ model: state.model,
1666
+ text: state.text,
1667
+ result: null,
1668
+ exitCode: 0,
1669
+ aborted: false,
1670
+ stderr: ""
1671
+ });
1672
+ if (!state.started) {
1673
+ state.started = true;
1674
+ emit({ type: "message_start", message });
1675
+ }
1676
+ emit({
1677
+ type: "message_update",
1678
+ message,
1679
+ assistantMessageEvent: {
1680
+ type: "text_delta",
1681
+ contentIndex: 0,
1682
+ delta,
1683
+ partial: message
1684
+ }
1685
+ });
1686
+ }
1687
+ async function readJsonLines(child, emit, state) {
1688
+ const rl = createInterface({ input: child.stdout });
1689
+ for await (const line of rl) {
1690
+ const trimmed = line.trim();
1691
+ if (trimmed.length === 0) continue;
1692
+ let parsed;
1693
+ try {
1694
+ parsed = JSON.parse(trimmed);
1695
+ } catch {
1696
+ continue;
1697
+ }
1698
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) continue;
1699
+ const record2 = parsed;
1700
+ if (record2.type === "system" && typeof record2.model === "string") state.model = record2.model;
1701
+ if (record2.type === "result") {
1702
+ state.result = record2;
1703
+ continue;
1704
+ }
1705
+ if (record2.type === "assistant") {
1706
+ const text = assistantTextFromEvent(record2);
1707
+ if (text.length > 0 && text.length >= state.text.length) state.text = text;
1708
+ continue;
1709
+ }
1710
+ emitTextDelta2(emit, state, extractDelta(record2));
1711
+ }
1712
+ }
1713
+ function startClaudeCodeWorkerRun(input, emit) {
1714
+ const args = buildClaudeCodeArgs(input);
1715
+ const child = spawn2("claude", args, {
1716
+ cwd: process.cwd(),
1717
+ env: process.env,
1718
+ stdio: ["ignore", "pipe", "pipe"]
1719
+ });
1720
+ const streamState = {
1721
+ started: false,
1722
+ text: "",
1723
+ model: input.wireModelId,
1724
+ result: null
1725
+ };
1726
+ let aborted = false;
1727
+ let killTimer = null;
1728
+ const abort = () => {
1729
+ aborted = true;
1730
+ if (child.killed) return;
1731
+ child.kill("SIGTERM");
1732
+ killTimer = setTimeout(() => {
1733
+ if (!child.killed) child.kill("SIGKILL");
1734
+ }, 1500);
1735
+ };
1736
+ if (input.signal) {
1737
+ if (input.signal.aborted) abort();
1738
+ else input.signal.addEventListener("abort", abort, { once: true });
1739
+ }
1740
+ const promise = (async () => {
1741
+ emit({ type: "agent_start" });
1742
+ const stderrPromise = readStderr(child);
1743
+ const stdoutPromise = readJsonLines(child, emit, streamState);
1744
+ const exitCode = await waitForClose(child);
1745
+ await stdoutPromise.catch(() => {
1746
+ });
1747
+ const stderr = await stderrPromise.catch(() => "");
1748
+ if (killTimer) clearTimeout(killTimer);
1749
+ const finalText = streamState.text || resultText(streamState.result) || (exitCode === 0 ? "" : resultError(streamState.result, stderr));
1750
+ const finalMessage = buildAssistantMessage2({
1751
+ model: streamState.model,
1752
+ text: finalText,
1753
+ result: streamState.result,
1754
+ exitCode,
1755
+ aborted,
1756
+ stderr
1757
+ });
1758
+ if (!streamState.started) emit({ type: "message_start", message: finalMessage });
1759
+ emit({ type: "message_end", message: finalMessage });
1760
+ const messages = [finalMessage];
1761
+ emit({ type: "agent_end", messages });
1762
+ if (exitCode !== 0 && stderr.trim().length > 0 && !aborted) {
1763
+ process.stderr.write(`[worker:claude-code] ${stderr.trim()}
1764
+ `);
1765
+ }
1766
+ return { messages, exitCode: exitCode === 0 ? 0 : 1 };
1767
+ })();
1768
+ return {
1769
+ promise,
1770
+ abort
1771
+ };
1772
+ }
1773
+
1774
+ // src/engine/worker-runtime-capabilities.ts
1775
+ init_esm_shims();
1776
+ var WORKER_RUNTIME_MEDIATES_CLIO_DISPATCH = false;
1777
+
1778
+ // src/tools/builtin-tool-catalog.ts
1779
+ init_esm_shims();
1780
+
1781
+ // src/tools/read.ts
1782
+ init_esm_shims();
1783
+ import { readFileSync, statSync } from "node:fs";
1784
+ var DEFAULT_READ_MAX_BYTES = GUARDRAIL_DEFAULTS.readMaxBytes;
1785
+ var READ_MAX_BYTES_ENV = GUARDRAIL_ENV_VARS.readMaxBytes;
1786
+ var MIN_READ_CAP_BYTES = 1024;
1787
+ function readMaxBytes(env = process.env) {
1788
+ return Math.max(MIN_READ_CAP_BYTES, resolveGuardrail("readMaxBytes", env));
1789
+ }
1790
+ var readTool = {
1791
+ name: ToolNames.Read,
1792
+ description: `Read a UTF-8 text file. Output is capped at ${DEFAULT_MAX_LINES} lines or ${DEFAULT_READ_MAX_BYTES / 1024}KB per call; truncated results say how to continue with offset/limit. Pass tail=N to read the last N lines (jump to EOF) instead of paging from the top.`,
1793
+ parameters: typebox_exports.Object({
1794
+ path: typebox_exports.String({ description: "File path (relative or absolute)." }),
1795
+ offset: typebox_exports.Optional(typebox_exports.Number({ description: "1-indexed start line." })),
1796
+ limit: typebox_exports.Optional(typebox_exports.Number({ description: "Max lines to read." })),
1797
+ tail: typebox_exports.Optional(
1798
+ typebox_exports.Number({ description: "Read the last N lines of the file (jump to EOF). Overrides offset/limit." })
1799
+ )
1800
+ }),
1801
+ baseActionClass: "read",
1802
+ executionMode: "parallel",
1803
+ async run(args, options) {
1804
+ const pathArg = typeof args.path === "string" ? args.path : null;
1805
+ if (!pathArg) return { kind: "error", message: "read: missing path argument" };
1806
+ const filePath = resolveReadPath(pathArg);
1807
+ const offset = typeof args.offset === "number" && args.offset > 0 ? Math.floor(args.offset) : 1;
1808
+ const limit = typeof args.limit === "number" && args.limit > 0 ? Math.floor(args.limit) : null;
1809
+ const tail = typeof args.tail === "number" && args.tail > 0 ? Math.floor(args.tail) : null;
1810
+ const reservation = isSessionOffloadPath(filePath, options?.sessionId) ? reserveObservation(readMaxBytes()) : reserveObservation(readMaxBytes(), options);
1811
+ try {
1812
+ const stat = statSync(filePath);
1813
+ if (!stat.isFile()) return { kind: "error", message: `read: not a file: ${filePath}` };
1814
+ if (stat.size > 2e7) {
1815
+ return {
1816
+ kind: "error",
1817
+ message: `read: file too large (${stat.size}B > 20MB). Use grep/find to locate the relevant section or read a smaller generated/source file; use shell access only when byte-level inspection is explicitly needed.`
1818
+ };
1819
+ }
1820
+ if (reservation.exhausted) {
1821
+ return observationBudgetExhausted({
1822
+ tool: ToolNames.Read,
1823
+ unit: "lines",
1824
+ reservation,
1825
+ subject: `reading ${pathArg}`,
1826
+ hint: "Use offset/limit in a follow-up turn or grep/find for a narrower section."
1827
+ });
1828
+ }
1829
+ const content = readFileSync(filePath, "utf8");
1830
+ const allLines = content.split("\n");
1831
+ const totalLines = splitLinesForCounting(content).length;
1832
+ const totalBytes = Buffer.byteLength(content, "utf8");
1833
+ const startIndex = Math.min(offset - 1, totalLines);
1834
+ if (tail === null && offset > 1 && startIndex >= totalLines) {
1835
+ return {
1836
+ kind: "error",
1837
+ message: `read: offset ${offset} is beyond end of file (${totalLines} lines total). The file ends at line ${totalLines} and has no further content; do not page past it or re-read the tail \u2014 a read covering line ${totalLines} has already returned everything.`
1838
+ };
1839
+ }
1840
+ const cap = reservation.callCapBytes;
1841
+ if (tail !== null) {
1842
+ const startLine = Math.max(0, totalLines - tail);
1843
+ const tailContent = allLines.slice(startLine).join("\n");
1844
+ const truncation2 = truncateTail(tailContent, { maxBytes: cap, maxLines: tail });
1845
+ const shownLines = truncation2.outputLines;
1846
+ const firstShown = Math.max(1, totalLines - shownLines + 1);
1847
+ const truncated2 = startLine > 0 || truncation2.truncated;
1848
+ return finalizeObservation({
1849
+ tool: ToolNames.Read,
1850
+ unit: "lines",
1851
+ output: truncation2.content,
1852
+ shownCount: shownLines,
1853
+ totalCount: totalLines,
1854
+ totalBytes,
1855
+ truncated: truncated2,
1856
+ ...truncated2 ? { next: `offset=${Math.max(1, firstShown - shownLines)} limit=${shownLines}` } : {},
1857
+ reservation,
1858
+ ...options ? { options } : {}
1859
+ });
1860
+ }
1861
+ const selected = limit !== null ? allLines.slice(startIndex, startIndex + limit).join("\n") : allLines.slice(startIndex).join("\n");
1862
+ const truncation = truncateHead(selected, { maxBytes: cap });
1863
+ if (truncation.firstLineExceedsLimit) {
1864
+ const firstLineSize = formatSize(Buffer.byteLength(allLines[startIndex] ?? "", "utf8"));
1865
+ const linePrefix = truncateUtf8(allLines[startIndex] ?? "", cap, "\n[line truncated]");
1866
+ const output = `${linePrefix}
1867
+
1868
+ [Line ${startIndex + 1} is ${firstLineSize}, exceeding the ${formatSize(cap)} read limit. Showing the UTF-8 prefix only. Use grep with a narrower literal/regex or edit with exact surrounding text; use shell access only when byte-level inspection is required.]`;
1869
+ return finalizeObservation({
1870
+ tool: ToolNames.Read,
1871
+ unit: "lines",
1872
+ output,
1873
+ shownCount: 0,
1874
+ totalCount: totalLines,
1875
+ totalBytes,
1876
+ truncated: true,
1877
+ omitNotice: true,
1878
+ reservation,
1879
+ ...options ? { options } : {}
1880
+ });
1881
+ }
1882
+ const endDisplay = startIndex + truncation.outputLines;
1883
+ const moreAfter = endDisplay < totalLines;
1884
+ const truncated = truncation.truncated || limit !== null && moreAfter;
1885
+ return finalizeObservation({
1886
+ tool: ToolNames.Read,
1887
+ unit: "lines",
1888
+ output: truncation.content,
1889
+ shownCount: truncation.outputLines,
1890
+ totalCount: totalLines,
1891
+ totalBytes,
1892
+ truncated,
1893
+ ...truncated && moreAfter ? { next: `offset=${endDisplay + 1}` } : {},
1894
+ reservation,
1895
+ ...options ? { options } : {}
1896
+ });
1897
+ } catch (err) {
1898
+ const msg = err instanceof Error ? err.message : String(err);
1899
+ const code = err?.code;
1900
+ if (code === "ENOENT") {
1901
+ return {
1902
+ kind: "error",
1903
+ message: `read: ${msg}. File not found at ${pathArg}. The path may be wrong. Try: code_nav, find, or ls to locate it.`
1904
+ };
1905
+ }
1906
+ return { kind: "error", message: `read: ${msg}` };
1907
+ }
1908
+ }
1909
+ };
1910
+
1911
+ // src/tools/builtin-tool-catalog.ts
1912
+ function withSourceInfo(spec, sourceInfo) {
1913
+ return { ...spec, sourceInfo };
1914
+ }
1915
+ function withMetadata(spec, metadata) {
1916
+ return { ...spec, metadata };
1917
+ }
1918
+ var policyCap = (selfCapBytes) => selfCapBytes + OBSERVATION_POLICY_SLACK_BYTES;
1919
+ var observePolicy = (selfCapBytes, followUpHint) => ({ kind: "bounded", maxBytes: policyCap(selfCapBytes), followUpHint });
1920
+ var summaryPolicy = (followUpHint) => ({ kind: "summary", maxBytes: 16384, followUpHint });
1921
+ var exactMutationPolicy = {
1922
+ kind: "exact",
1923
+ maxBytes: 8192,
1924
+ followUpHint: "Inspect the changed file or git diff for exact follow-up context."
1925
+ };
1926
+ var TOOL_METADATA = {
1927
+ // OBSERVE: read-class, parallel, envelope + shared turn budget.
1928
+ [ToolNames.Read]: {
1929
+ objective: "Read exact UTF-8 file content with line and byte bounds.",
1930
+ uiLabel: "Read",
1931
+ retrySafety: "idempotent",
1932
+ resultSizePolicy: observePolicy(
1933
+ readMaxBytes(),
1934
+ "Use offset/limit or a narrower locate/search tool call to inspect omitted content."
1935
+ ),
1936
+ costLatency: "local_fast"
1937
+ },
1938
+ [ToolNames.Grep]: {
1939
+ objective: "Search file contents and return line-referenced matches.",
1940
+ uiLabel: "Grep",
1941
+ retrySafety: "idempotent",
1942
+ resultSizePolicy: observePolicy(
1943
+ OBSERVE_SELF_CAPS.grepContent,
1944
+ "Refine the pattern, path, glob, context, or limit, or use mode=files, to inspect omitted matches."
1945
+ ),
1946
+ costLatency: "local_medium"
1947
+ },
1948
+ [ToolNames.Find]: {
1949
+ objective: "Find paths by glob pattern with optional mtime ordering.",
1950
+ uiLabel: "Find",
1951
+ retrySafety: "idempotent",
1952
+ resultSizePolicy: observePolicy(
1953
+ OBSERVE_SELF_CAPS.find,
1954
+ "Refine the pattern, path, or limit to inspect omitted paths."
1955
+ ),
1956
+ costLatency: "local_medium"
1957
+ },
1958
+ [ToolNames.Ls]: {
1959
+ objective: "List directory entries.",
1960
+ uiLabel: "List",
1961
+ retrySafety: "idempotent",
1962
+ resultSizePolicy: observePolicy(OBSERVE_SELF_CAPS.ls, "Raise limit or list a narrower directory."),
1963
+ costLatency: "local_fast"
1964
+ },
1965
+ [ToolNames.CodeNav]: {
1966
+ objective: "Navigate the codewiki index by symbol, path, entry points, outline, imports, or importers.",
1967
+ uiLabel: "Nav",
1968
+ retrySafety: "idempotent",
1969
+ resultSizePolicy: observePolicy(OBSERVE_SELF_CAPS.codeNav, "Raise limit or use a narrower mode/query."),
1970
+ costLatency: "local_fast",
1971
+ promptHint: "Use code_nav for indexed code navigation (modes: symbol, path, entries, outline, deps, dependents, wiki)."
1972
+ },
1973
+ [ToolNames.Context]: {
1974
+ objective: "Return workspace, bundled-docs, or skill context.",
1975
+ uiLabel: "Context",
1976
+ retrySafety: "idempotent",
1977
+ resultSizePolicy: observePolicy(
1978
+ Math.max(OBSERVE_SELF_CAPS.contextDocs, OBSERVE_SELF_CAPS.contextSkills, OBSERVE_SELF_CAPS.contextWorkspace),
1979
+ "Use a narrower query or scope to inspect omitted content."
1980
+ ),
1981
+ costLatency: "local_fast",
1982
+ promptHint: 'Call context with scope="skills" to list installed and marketplace skills; when one matches the task, or the operator names a skill or asks how one works, suggest the operator run /skill <name> (a marketplace skill is offered for install) and never load it uninvited. When the user message carries a skill request, first load that skill via context (scope="skills", name=<skill>) before doing anything else.'
1983
+ },
1984
+ [ToolNames.CredentialPresent]: {
1985
+ objective: "Check whether a credential key is present without returning its value.",
1986
+ uiLabel: "Credential",
1987
+ retrySafety: "idempotent",
1988
+ resultSizePolicy: {
1989
+ kind: "exact",
1990
+ maxBytes: 4096,
1991
+ followUpHint: "Use the boolean result only; never ask to print the credential value."
1992
+ },
1993
+ costLatency: "local_fast"
1994
+ },
1995
+ // MUTATE: write-class, sequential, file-mutation queue.
1996
+ [ToolNames.Write]: {
1997
+ objective: "Write a complete UTF-8 file.",
1998
+ uiLabel: "Write",
1999
+ retrySafety: "not_retry_safe",
2000
+ resultSizePolicy: exactMutationPolicy,
2001
+ costLatency: "local_fast"
2002
+ },
2003
+ [ToolNames.Edit]: {
2004
+ objective: "Apply exact text replacements to one file.",
2005
+ uiLabel: "Edit",
2006
+ retrySafety: "not_retry_safe",
2007
+ resultSizePolicy: exactMutationPolicy,
2008
+ costLatency: "local_fast"
2009
+ },
2010
+ // EXECUTE: the safe-exec spine (bash offloads its own overflow).
2011
+ [ToolNames.Bash]: {
2012
+ objective: "Execute an explicit shell command when narrower tools are insufficient.",
2013
+ uiLabel: "Shell",
2014
+ retrySafety: "unknown",
2015
+ resultSizePolicy: summaryPolicy(
2016
+ "Use a narrower command or a dedicated verification/read/search tool to inspect omitted output."
2017
+ ),
2018
+ costLatency: "local_slow"
2019
+ },
2020
+ [ToolNames.Git]: {
2021
+ objective: "Read-only git inspection: status, diff, or log.",
2022
+ uiLabel: "Git",
2023
+ retrySafety: "idempotent",
2024
+ resultSizePolicy: summaryPolicy("Limit the diff/log to one path or fewer commits."),
2025
+ costLatency: "local_fast"
2026
+ },
2027
+ [ToolNames.Verify]: {
2028
+ objective: "Run declared verification checks (scripts or frontend artifacts).",
2029
+ uiLabel: "Verify",
2030
+ retrySafety: "retry_safe",
2031
+ resultSizePolicy: summaryPolicy(
2032
+ "Rerun the check with narrower args or inspect the named failing file/test directly."
2033
+ ),
2034
+ costLatency: "local_slow"
2035
+ },
2036
+ // ORCHESTRATE: agent-class, receipts as evidence.
2037
+ [ToolNames.Tasks]: {
2038
+ objective: "Declare and track the session task board with evidence-carrying completions.",
2039
+ uiLabel: "Tasks",
2040
+ // A repeated plan/start/done lands on the same board state; a repeated
2041
+ // add duplicates a task, so the surface as a whole is not retry safe.
2042
+ retrySafety: "not_retry_safe",
2043
+ resultSizePolicy: {
2044
+ kind: "exact",
2045
+ maxBytes: 8192,
2046
+ followUpHint: 'Call tasks with action="list" to re-read the board.'
2047
+ },
2048
+ costLatency: "local_fast",
2049
+ promptHint: 'When a request contains three or more distinct steps, declare the board before your first edit: tasks action="plan" with a title and the task list. Mark one task active with "start" before working it, close it with "done" plus an evidence note (what proves it works), and use "block" with a reason instead of silently stalling.'
2050
+ },
2051
+ [ToolNames.Ledger]: {
2052
+ objective: "Coordinate with the peer workers of this dispatch through typed claims, findings, and reviews.",
2053
+ uiLabel: "Ledger",
2054
+ // A repeated post lands a second entry and spends another of the run's
2055
+ // twenty posts, so the surface as a whole is not retry safe.
2056
+ retrySafety: "not_retry_safe",
2057
+ resultSizePolicy: {
2058
+ kind: "exact",
2059
+ maxBytes: 16384,
2060
+ followUpHint: 'Call ledger with action="read" and a since sequence to re-read only what is new.'
2061
+ },
2062
+ costLatency: "local_fast"
2063
+ },
2064
+ [ToolNames.Dispatch]: {
2065
+ objective: "Dispatch bounded tasks to configured Clio workers.",
2066
+ uiLabel: "Dispatch",
2067
+ retrySafety: "not_retry_safe",
2068
+ resultSizePolicy: summaryPolicy(
2069
+ "Use the dispatch receipt paths or ask a narrower worker follow-up for omitted output."
2070
+ ),
2071
+ costLatency: "agent",
2072
+ promptHint: "Call dispatch with list:true only when the operator asks about agents, workers, or the fleet; never use it to inventory direct tools."
2073
+ },
2074
+ [ToolNames.Monitor]: {
2075
+ objective: "Inspect dispatched runs: state, recent events, receipts.",
2076
+ uiLabel: "Monitor",
2077
+ retrySafety: "idempotent",
2078
+ resultSizePolicy: summaryPolicy("Use monitor(mode=receipt) or read the receipt path for full details."),
2079
+ costLatency: "local_fast"
2080
+ },
2081
+ [ToolNames.Steer]: {
2082
+ objective: "Guide or cancel a running dispatched worker.",
2083
+ uiLabel: "Steer",
2084
+ retrySafety: "not_retry_safe",
2085
+ resultSizePolicy: {
2086
+ kind: "exact",
2087
+ maxBytes: 4096,
2088
+ followUpHint: "Use monitor(mode=status) to confirm the run state after steering."
2089
+ },
2090
+ costLatency: "local_fast"
2091
+ },
2092
+ // RETRIEVE: network-class.
2093
+ [ToolNames.WebFetch]: {
2094
+ objective: "Fetch HTTP(S) text for explicit external research.",
2095
+ uiLabel: "Fetch",
2096
+ retrySafety: "retry_safe",
2097
+ resultSizePolicy: {
2098
+ kind: "bounded",
2099
+ maxBytes: 16384,
2100
+ followUpHint: "Fetch a narrower URL or lower max_bytes to inspect a specific section."
2101
+ },
2102
+ costLatency: "network"
2103
+ },
2104
+ // INTERACT: operator dialogue.
2105
+ [ToolNames.AskUser]: {
2106
+ objective: "Ask the operator structured questions.",
2107
+ uiLabel: "Ask",
2108
+ retrySafety: "not_retry_safe",
2109
+ resultSizePolicy: {
2110
+ kind: "exact",
2111
+ maxBytes: 2e4,
2112
+ followUpHint: "Proceed with stated assumptions if the operator cancels or no UI is available."
2113
+ },
2114
+ costLatency: "local_slow",
2115
+ promptHint: 'Use ask_user only when blocked on a decision the request does not answer; never ask about anything the operator already stated. One question per round in interview workflows, up to four tightly related questions otherwise, recommended option first. Finish with action="complete" and a compact decisions array before final prose. If cancelled, continue with defaults and do not ask again.'
2116
+ },
2117
+ // ARTIFACT: terminal writers.
2118
+ [ToolNames.Artifact]: {
2119
+ objective: "Write terminal plan/review/report documents that complete the turn.",
2120
+ uiLabel: "Artifact",
2121
+ retrySafety: "not_retry_safe",
2122
+ resultSizePolicy: exactMutationPolicy,
2123
+ costLatency: "local_fast"
2124
+ }
2125
+ };
2126
+ function toolPromptHintsForNames(names) {
2127
+ const seen = /* @__PURE__ */ new Set();
2128
+ const hints = [];
2129
+ for (const name of [...names].sort()) {
2130
+ if (seen.has(name)) continue;
2131
+ seen.add(name);
2132
+ const hint = TOOL_METADATA[name]?.promptHint?.trim();
2133
+ if (hint) hints.push({ tool: name, hint });
2134
+ }
2135
+ return hints;
2136
+ }
2137
+ function withBuiltinMetadata(spec) {
2138
+ const metadata = TOOL_METADATA[spec.name];
2139
+ return metadata ? withMetadata(spec, metadata) : spec;
2140
+ }
2141
+ function builtin(spec, sourceInfo) {
2142
+ return withBuiltinMetadata(withSourceInfo(spec, sourceInfo));
2143
+ }
2144
+
2145
+ // src/domains/safety/run-effects.ts
2146
+ init_esm_shims();
2147
+ import path from "node:path";
2148
+ var GIT_PATH_MUTATIONS = /* @__PURE__ */ new Set(["mv", "rm"]);
2149
+ function gitPathOperands(command) {
2150
+ const targets = [];
2151
+ for (const segment of splitCommandSegments(command)) {
2152
+ if (segment[0] !== "git") continue;
2153
+ const subcommand = segment[1];
2154
+ if (subcommand === void 0 || !GIT_PATH_MUTATIONS.has(subcommand)) continue;
2155
+ for (const token of segment.slice(2)) {
2156
+ if (token.startsWith("-")) continue;
2157
+ targets.push(token);
2158
+ }
2159
+ }
2160
+ return targets;
2161
+ }
2162
+ function splitCommandSegments(command) {
2163
+ const segments = [];
2164
+ let current = [];
2165
+ for (const token of tokenizeShellLike(command)) {
2166
+ if (token === ";" || token === "&&" || token === "||" || token === "|") {
2167
+ if (current.length > 0) segments.push(current);
2168
+ current = [];
2169
+ continue;
2170
+ }
2171
+ current.push(token);
2172
+ }
2173
+ if (current.length > 0) segments.push(current);
2174
+ return segments;
2175
+ }
2176
+ function commandOf(args) {
2177
+ const command = args?.command;
2178
+ return typeof command === "string" && command.length > 0 ? command : null;
2179
+ }
2180
+ function mutationTargets(toolName, args) {
2181
+ if (toolName !== ToolNames.Bash) return toolMutationPaths(toolName, args);
2182
+ const command = commandOf(args);
2183
+ if (command === null) return [];
2184
+ return [...extractCommandWriteTargets(command), ...extractCommandDeleteTargets(command), ...gitPathOperands(command)];
2185
+ }
2186
+ function validationCommandOf(toolName, args, scope) {
2187
+ if (toolName === ToolNames.Bash) {
2188
+ const command = commandOf(args);
2189
+ if (command === null) return null;
2190
+ const detected = detectValidationCommand(command, scope);
2191
+ return detected.kind === "validation" ? detected.matched : null;
2192
+ }
2193
+ return typedValidationSummary(toolName, { args: args ?? {} });
2194
+ }
2195
+ function createRunEffectsRecorder(cwd) {
2196
+ const pending = /* @__PURE__ */ new Map();
2197
+ const mutatedPaths = /* @__PURE__ */ new Set();
2198
+ const failedMutationPaths = /* @__PURE__ */ new Set();
2199
+ const validationCommands = /* @__PURE__ */ new Set();
2200
+ const verificationCommands = /* @__PURE__ */ new Set();
2201
+ return {
2202
+ start(toolCallId, toolName, args) {
2203
+ const paths = mutationTargets(toolName, args);
2204
+ const validationCommand = validationCommandOf(toolName, args, "finish-contract");
2205
+ const verificationCommand = validationCommandOf(toolName, args, "grounding");
2206
+ if (paths.length === 0 && validationCommand === null && verificationCommand === null) return;
2207
+ const base = typeof args?.cwd === "string" && args.cwd.length > 0 ? path.resolve(cwd, args.cwd) : cwd;
2208
+ pending.set(toolCallId, {
2209
+ paths: paths.map((target) => path.resolve(base, target)),
2210
+ validationCommand,
2211
+ verificationCommand
2212
+ });
2213
+ },
2214
+ finish(toolCallId, failed) {
2215
+ const effects = pending.get(toolCallId);
2216
+ pending.delete(toolCallId);
2217
+ if (effects === void 0) return;
2218
+ if (failed) {
2219
+ for (const target of effects.paths) failedMutationPaths.add(target);
2220
+ return;
2221
+ }
2222
+ for (const target of effects.paths) mutatedPaths.add(target);
2223
+ if (effects.validationCommand !== null) validationCommands.add(effects.validationCommand);
2224
+ if (effects.verificationCommand !== null) verificationCommands.add(effects.verificationCommand);
2225
+ },
2226
+ snapshot() {
2227
+ return {
2228
+ mutatedPaths: new Set(mutatedPaths),
2229
+ failedMutationPaths: new Set([...failedMutationPaths].filter((target) => !mutatedPaths.has(target))),
2230
+ validationCommands: new Set(validationCommands),
2231
+ verificationCommands: new Set(verificationCommands)
2232
+ };
2233
+ }
2234
+ };
2235
+ }
2236
+
2237
+ // src/domains/dispatch/route-approval.ts
2238
+ init_esm_shims();
2239
+ var APPROVED_ASSIGNMENT_ROUTE_VERSION = 1;
2240
+ function record(value) {
2241
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2242
+ }
2243
+ function routeCandidate(value) {
2244
+ if (!record(value) || !isExecutionRole(value.executionRole)) return false;
2245
+ return [
2246
+ "agentId",
2247
+ "specFingerprint",
2248
+ "targetId",
2249
+ "modelId",
2250
+ "runtimeId",
2251
+ "nodeId",
2252
+ "toolSignature",
2253
+ "promptCompositionHash",
2254
+ "endpointIdentityHash",
2255
+ "settingsFingerprint"
2256
+ ].every((field) => typeof value[field] === "string" && value[field].length > 0);
2257
+ }
2258
+ function isApprovedAssignmentRoute(value) {
2259
+ if (!record(value) || value.version !== APPROVED_ASSIGNMENT_ROUTE_VERSION || !record(value.decision)) return false;
2260
+ const decision = value.decision;
2261
+ if (decision.mode !== "active" || !routeCandidate(decision.selected) || !routeCandidate(decision.executedRoute) || !Array.isArray(decision.approvedFallbacks) || !decision.approvedFallbacks.every(routeCandidate) || !isRouteDecisionAgentSelection(decision.agentSelection) || !Array.isArray(decision.candidateEvaluations) || !decision.candidateEvaluations.every(
2262
+ (evaluation) => record(evaluation) && routeCandidate(evaluation.candidate) && record(evaluation.activeReadiness) && typeof evaluation.activeReadiness.ready === "boolean" && Array.isArray(evaluation.activeReadiness.gaps) && evaluation.activeReadiness.gaps.every((gap) => typeof gap === "string") && Number.isInteger(evaluation.activeReadiness.labelsNeeded)
2263
+ ) || decision.policyVersion !== ROUTE_POLICY_VERSION || typeof decision.decisionHash !== "string" || !/^[0-9a-f]{64}$/u.test(decision.decisionHash)) {
2264
+ return false;
2265
+ }
2266
+ try {
2267
+ assertApprovedAssignmentRoute(value);
2268
+ return true;
2269
+ } catch {
2270
+ return false;
2271
+ }
2272
+ }
2273
+ function assertApprovedAssignmentRoute(value) {
2274
+ if (value.version !== APPROVED_ASSIGNMENT_ROUTE_VERSION) {
2275
+ throw new Error("dispatch: unsupported active route approval version");
2276
+ }
2277
+ if (value.decision.policyVersion !== ROUTE_POLICY_VERSION) {
2278
+ throw new Error("dispatch: active route approval uses an unsupported route policy");
2279
+ }
2280
+ if (!isRouteDecisionAgentSelection(value.decision.agentSelection)) {
2281
+ throw new Error("dispatch: active route approval has invalid agent-selection evidence");
2282
+ }
2283
+ if (value.decision.mode !== "active" || !sameRouteIdentity(value.decision.selected, value.decision.executedRoute)) {
2284
+ throw new Error("dispatch: active route approval must seal one selected and executed identity");
2285
+ }
2286
+ const agentSelection = value.decision.agentSelection;
2287
+ if (agentSelection.activation !== "active") {
2288
+ throw new Error("dispatch: active route approval has non-active agent selection evidence");
2289
+ }
2290
+ if (agentSelection.request === "explicit" && [value.decision.selected, ...value.decision.approvedFallbacks].some(
2291
+ (candidate) => candidate.agentId !== agentSelection.baselineAgentId
2292
+ )) {
2293
+ throw new Error("dispatch: explicit route approval cannot authorize another agent");
2294
+ }
2295
+ if (value.decision.selected.agentId !== agentSelection.baselineAgentId) {
2296
+ const transition = agentSelection.authorityTransition;
2297
+ if (agentSelection.request !== "auto" || transition === null || transition.from !== agentSelection.baselineAgentId || transition.to !== value.decision.selected.agentId)
2298
+ throw new Error("dispatch: active agent transition is not explained by the approved decision");
2299
+ }
2300
+ for (const candidate of [value.decision.selected, ...value.decision.approvedFallbacks]) {
2301
+ const evaluation = value.decision.candidateEvaluations.find((entry) => sameRouteIdentity(entry.candidate, candidate));
2302
+ if (evaluation === void 0 || evaluation.rejection !== null || !evaluation.activeReadiness.ready) {
2303
+ throw new Error("dispatch: active route approval contains a rejected or readiness-ineligible route");
2304
+ }
2305
+ const agentEvaluation = agentSelection.evaluations.find(
2306
+ (entry) => entry.agentId === candidate.agentId && entry.specFingerprint === candidate.specFingerprint && entry.executionRole === candidate.executionRole
2307
+ );
2308
+ if (agentEvaluation === void 0 || agentEvaluation.rejections.length > 0) {
2309
+ throw new Error("dispatch: active route approval contains an agent rejected by hard filters");
2310
+ }
2311
+ }
2312
+ if (!Number.isFinite(value.totalCostUpperBoundUsd) || value.totalCostUpperBoundUsd < 0) {
2313
+ throw new Error("dispatch: active route approval total cost bound is invalid");
2314
+ }
2315
+ if (!Number.isInteger(value.deadlineMs) || value.deadlineMs <= 0) {
2316
+ throw new Error("dispatch: active route approval deadline is invalid");
2317
+ }
2318
+ if (!Number.isInteger(value.maxAttempts) || value.maxAttempts < 1) {
2319
+ throw new Error("dispatch: active route approval attempt bound is invalid");
2320
+ }
2321
+ }
2322
+ function cloneApprovedAssignmentRoute(value) {
2323
+ assertApprovedAssignmentRoute(value);
2324
+ return structuredClone(value);
2325
+ }
2326
+ function approvedRouteCandidates(value) {
2327
+ assertApprovedAssignmentRoute(value);
2328
+ return [value.decision.selected, ...value.decision.approvedFallbacks].map((candidate) => ({
2329
+ agentId: candidate.agentId,
2330
+ target: candidate.targetId,
2331
+ model: candidate.modelId,
2332
+ node: candidate.nodeId
2333
+ }));
2334
+ }
2335
+ function assertApprovedRecoveryCapability(approval, actual) {
2336
+ assertApprovedAssignmentRoute(approval);
2337
+ const approved = [approval.decision.selected, ...approval.decision.approvedFallbacks].find(
2338
+ (candidate) => candidate.agentId === actual.agentId && candidate.targetId === actual.targetId && candidate.modelId === actual.modelId && candidate.runtimeId === actual.runtimeId && candidate.nodeId === actual.nodeId
2339
+ );
2340
+ if (approved === void 0 || approved.specFingerprint !== actual.specFingerprint || approved.thinkingLevel !== actual.thinkingLevel || approved.toolSignature !== actual.toolSignature || approved.endpointIdentityHash !== actual.endpointIdentityHash || approved.settingsFingerprint !== actual.settingsFingerprint) {
2341
+ throw new Error("dispatch: recovery route capability drifted outside the active approval");
2342
+ }
2343
+ }
2344
+
2345
+ // src/domains/dispatch/agent-ledger.ts
2346
+ init_esm_shims();
2347
+ import { isAbsolute, relative } from "node:path";
2348
+ var AGENT_LEDGER_PROMPT_MAX_CHARS = 4e3;
2349
+ function normalizeScopePrefix(value) {
2350
+ return value.trim().replace(/\/+$/u, "");
2351
+ }
2352
+ function prefixesOverlap(left, right) {
2353
+ const a = normalizeScopePrefix(left);
2354
+ const b = normalizeScopePrefix(right);
2355
+ if (a.length === 0 || b.length === 0) return false;
2356
+ if (a === b) return true;
2357
+ return a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
2358
+ }
2359
+ function claimConflicts(body, live, runId) {
2360
+ if (body.kind !== "claim") return [];
2361
+ const conflicts = [];
2362
+ for (const entry of live) {
2363
+ if (entry.body.kind !== "claim") continue;
2364
+ if (runId !== void 0 && entry.runId === runId) continue;
2365
+ const overlaps = entry.body.scope.some(
2366
+ (peerScope) => body.scope.some((newScope) => prefixesOverlap(newScope, peerScope))
2367
+ );
2368
+ if (overlaps) conflicts.push(entry.id);
2369
+ }
2370
+ return conflicts;
2371
+ }
2372
+ function citedPathKey(path3) {
2373
+ const trimmed = path3.trim();
2374
+ if (trimmed.length === 0) return trimmed;
2375
+ const absolute = isAbsolute(trimmed);
2376
+ const candidate = absolute ? relative(process.cwd(), trimmed) : trimmed;
2377
+ if (absolute && (candidate.length === 0 || candidate.startsWith(".."))) return trimmed;
2378
+ const normalized = candidate.split("/").filter((segment) => segment.length > 0 && segment !== ".").join("/");
2379
+ return normalized.length === 0 ? trimmed : normalized;
2380
+ }
2381
+ function corroboration(entries) {
2382
+ const runsByPath = /* @__PURE__ */ new Map();
2383
+ for (const entry of entries) {
2384
+ if (entry.body.kind !== "finding") continue;
2385
+ const path3 = entry.body.path === void 0 ? void 0 : citedPathKey(entry.body.path);
2386
+ if (path3 === void 0) continue;
2387
+ const runs = runsByPath.get(path3) ?? [];
2388
+ if (!runs.includes(entry.runId)) runs.push(entry.runId);
2389
+ runsByPath.set(path3, runs);
2390
+ }
2391
+ const byEntryId = /* @__PURE__ */ new Map();
2392
+ for (const entry of entries) {
2393
+ if (entry.body.kind !== "finding") continue;
2394
+ const path3 = entry.body.path;
2395
+ if (path3 === void 0) {
2396
+ byEntryId.set(entry.id, "ungrounded lead");
2397
+ continue;
2398
+ }
2399
+ const runs = runsByPath.get(citedPathKey(path3)) ?? [];
2400
+ byEntryId.set(entry.id, runs.length >= 2 ? "corroborated" : "uncorroborated");
2401
+ }
2402
+ return { byEntryId, byPath: runsByPath };
2403
+ }
2404
+ function disputes(entries) {
2405
+ const disputed = /* @__PURE__ */ new Set();
2406
+ for (const entry of entries) {
2407
+ if (entry.body.kind === "review" && !entry.body.passed) disputed.add(entry.body.target);
2408
+ }
2409
+ return disputed;
2410
+ }
2411
+ function authorKey(entry) {
2412
+ return `${entry.agentId}\0${entry.runId}`;
2413
+ }
2414
+ function renderBody(entry, state, disputed) {
2415
+ const marks = [];
2416
+ if (state !== void 0) marks.push(state);
2417
+ if (disputed) marks.push("disputed");
2418
+ const suffix = marks.length > 0 ? ` [${marks.join(", ")}]` : "";
2419
+ const body = entry.body;
2420
+ if (body.kind === "claim") {
2421
+ const conflicts = entry.conflictsWith !== void 0 && entry.conflictsWith.length > 0 ? ` (overlaps ${entry.conflictsWith.join(", ")})` : "";
2422
+ return `${entry.id} claim ${body.scope.join(" ")}${conflicts}: ${body.intent}${suffix}`;
2423
+ }
2424
+ if (body.kind === "finding") {
2425
+ const citation = body.path === void 0 ? "" : ` ${body.path}${body.line === void 0 ? "" : `:${body.line}`}`;
2426
+ return `${entry.id} finding${citation}: ${body.claim}${suffix}`;
2427
+ }
2428
+ return `${entry.id} review ${body.target} ${body.passed ? "passed" : "failed"}: ${body.evidence}${suffix}`;
2429
+ }
2430
+ function renderAgentLedger(entries, opts = {}) {
2431
+ const maxChars = opts.maxChars;
2432
+ let visible = [...entries].sort((left, right) => left.sequence - right.sequence);
2433
+ if (visible.length === 0) return "No peer contributions yet.";
2434
+ for (; ; ) {
2435
+ const text = renderAll(visible);
2436
+ if (maxChars === void 0 || text.length <= maxChars) return text;
2437
+ visible = visible.slice(1);
2438
+ if (visible.length === 0) return "No peer contributions yet.";
2439
+ }
2440
+ }
2441
+ function renderAll(entries) {
2442
+ const states = corroboration(entries).byEntryId;
2443
+ const disputed = disputes(entries);
2444
+ const groups = /* @__PURE__ */ new Map();
2445
+ for (const entry of entries) {
2446
+ const key = authorKey(entry);
2447
+ const group = groups.get(key) ?? [];
2448
+ group.push(entry);
2449
+ groups.set(key, group);
2450
+ }
2451
+ const lines = [];
2452
+ for (const group of groups.values()) {
2453
+ const head = group[0];
2454
+ if (head === void 0) continue;
2455
+ lines.push(`${head.agentId} (run ${head.runId}, node ${head.nodeId}):`);
2456
+ for (const entry of group) {
2457
+ lines.push(` ${renderBody(entry, states.get(entry.id), disputed.has(entry.id))}`);
2458
+ }
2459
+ }
2460
+ return lines.join("\n");
2461
+ }
2462
+
2463
+ // src/domains/dispatch/execution-handoff.ts
2464
+ init_esm_shims();
2465
+ var EXECUTION_HANDOFF_MAX_ITEMS = 16;
2466
+ var EXECUTION_HANDOFF_MAX_TEXT_BYTES = 12e3;
2467
+ function truncateUtf82(value, limit) {
2468
+ const bytes = Buffer.from(value, "utf8");
2469
+ return bytes.length <= limit ? value : bytes.subarray(0, limit).toString("utf8");
2470
+ }
2471
+ function projectExecutionHandoffs(dependencyIds, outputs) {
2472
+ if (dependencyIds.length > EXECUTION_HANDOFF_MAX_ITEMS)
2473
+ throw new Error(`execution handoff: at most ${EXECUTION_HANDOFF_MAX_ITEMS} predecessors are allowed`);
2474
+ const perItem = Math.floor(EXECUTION_HANDOFF_MAX_TEXT_BYTES / Math.max(1, dependencyIds.length));
2475
+ return dependencyIds.map((id) => {
2476
+ const source = outputs.get(id);
2477
+ if (!source) throw new Error(`execution handoff: missing successful predecessor '${id}'`);
2478
+ return { ...source, output: truncateUtf82(source.output, perItem) };
2479
+ });
2480
+ }
2481
+
2482
+ // src/domains/dispatch/validation.ts
2483
+ init_esm_shims();
2484
+ import path2 from "node:path";
2485
+ var DISPATCH_BRIEFING_MAX_BYTES = 12e3;
2486
+ var INTERNAL_DISPATCH_BRIEFING_MAX_BYTES = 64 * 1024;
2487
+ var KNOWN_KEYS = /* @__PURE__ */ new Set([
2488
+ "agentId",
2489
+ // Derived by execution-role.ts at request construction, never model-authored.
2490
+ "executionRole",
2491
+ "task",
2492
+ "briefing",
2493
+ "workerProfile",
2494
+ "workerRuntime",
2495
+ "delegationAgentId",
2496
+ "target",
2497
+ "model",
2498
+ "thinkingLevel",
2499
+ "node",
2500
+ "routingIntent",
2501
+ "failover",
2502
+ "allowedCandidates",
2503
+ "plannedNode",
2504
+ "protectedArtifactRemap",
2505
+ "reroutes",
2506
+ "requiredCapabilities",
2507
+ "toolProfile",
2508
+ "denyTools",
2509
+ "cwd",
2510
+ "memorySection",
2511
+ "noSkills",
2512
+ "skillPaths",
2513
+ "trustProjectCompatRoots",
2514
+ "responseSchema",
2515
+ "writeRoots",
2516
+ "requestOrigin",
2517
+ "pipelineInput",
2518
+ "predecessorHandoffs",
2519
+ "lineage",
2520
+ "autonomy",
2521
+ "gate",
2522
+ "plan",
2523
+ "competeStance"
2524
+ ]);
2525
+ var VALID_COMPETE_STANCES = new Set(COMPETE_STANCES);
2526
+ var VALID_THINKING = new Set(THINKING_LEVELS);
2527
+ var VALID_REQUEST_ORIGINS = /* @__PURE__ */ new Set(["user", "agent", "internal"]);
2528
+ var VALID_FAILOVER_MODES = /* @__PURE__ */ new Set(["none", "approved", "automatic"]);
2529
+ function isPlainObject2(value) {
2530
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2531
+ }
2532
+ function validateJobSpec(spec) {
2533
+ const errors = [];
2534
+ if (!isPlainObject2(spec)) {
2535
+ return { ok: false, errors: ["spec must be an object"] };
2536
+ }
2537
+ for (const key of Object.keys(spec)) {
2538
+ if (!KNOWN_KEYS.has(key)) {
2539
+ errors.push(`unknown key: ${key}`);
2540
+ }
2541
+ }
2542
+ const agentId = spec.agentId;
2543
+ if (typeof agentId !== "string" || agentId.length === 0) {
2544
+ errors.push("agentId must be a non-empty string");
2545
+ }
2546
+ const task = spec.task;
2547
+ if (typeof task !== "string" || task.length === 0) {
2548
+ errors.push("task must be a non-empty string");
2549
+ }
2550
+ if ("executionRole" in spec && !isExecutionRole(spec.executionRole)) {
2551
+ errors.push("executionRole must be a known execution role");
2552
+ }
2553
+ let briefing;
2554
+ if ("briefing" in spec && spec.briefing !== void 0) {
2555
+ if (typeof spec.briefing !== "string") {
2556
+ errors.push("briefing must be a string");
2557
+ } else {
2558
+ const normalized = spec.briefing.trim();
2559
+ if (normalized.length > 0) {
2560
+ const bytes = Buffer.byteLength(normalized, "utf8");
2561
+ const maxBytes = spec.requestOrigin === "internal" ? INTERNAL_DISPATCH_BRIEFING_MAX_BYTES : DISPATCH_BRIEFING_MAX_BYTES;
2562
+ if (bytes > maxBytes) {
2563
+ errors.push(`briefing must be ${maxBytes} UTF-8 bytes or fewer`);
2564
+ } else {
2565
+ briefing = normalized;
2566
+ }
2567
+ }
2568
+ }
2569
+ }
2570
+ if ("target" in spec && spec.target !== void 0) {
2571
+ if (typeof spec.target !== "string" || spec.target.length === 0) {
2572
+ errors.push("target must be a non-empty string");
2573
+ }
2574
+ }
2575
+ if ("workerProfile" in spec && spec.workerProfile !== void 0) {
2576
+ if (typeof spec.workerProfile !== "string" || spec.workerProfile.length === 0) {
2577
+ errors.push("workerProfile must be a non-empty string");
2578
+ }
2579
+ }
2580
+ if ("workerRuntime" in spec && spec.workerRuntime !== void 0) {
2581
+ if (typeof spec.workerRuntime !== "string" || spec.workerRuntime.length === 0) {
2582
+ errors.push("workerRuntime must be a non-empty string");
2583
+ }
2584
+ }
2585
+ if ("delegationAgentId" in spec && spec.delegationAgentId !== void 0) {
2586
+ if (typeof spec.delegationAgentId !== "string" || spec.delegationAgentId.length === 0) {
2587
+ errors.push("delegationAgentId must be a non-empty string");
2588
+ }
2589
+ }
2590
+ if ("model" in spec && spec.model !== void 0) {
2591
+ if (typeof spec.model !== "string" || spec.model.length === 0) {
2592
+ errors.push("model must be a non-empty string");
2593
+ }
2594
+ }
2595
+ if ("node" in spec && spec.node !== void 0) {
2596
+ if (typeof spec.node !== "string" || spec.node.trim().length === 0) {
2597
+ errors.push("node must be a non-empty string");
2598
+ }
2599
+ }
2600
+ if ("routingIntent" in spec && spec.routingIntent !== void 0 && !isRoutingIntent(spec.routingIntent)) {
2601
+ errors.push("routingIntent must be a normalized routing intent");
2602
+ }
2603
+ if ("failover" in spec && spec.failover !== void 0) {
2604
+ if (typeof spec.failover !== "string" || !VALID_FAILOVER_MODES.has(spec.failover)) {
2605
+ errors.push("failover must be one of: none|approved|automatic");
2606
+ }
2607
+ }
2608
+ if ("allowedCandidates" in spec && spec.allowedCandidates !== void 0) {
2609
+ if (!Array.isArray(spec.allowedCandidates) || spec.allowedCandidates.length === 0 || spec.allowedCandidates.some((candidate) => !isValidFailoverCandidate(candidate))) {
2610
+ errors.push("allowedCandidates must be a non-empty array of exact {agentId, target, model, node} tuples");
2611
+ }
2612
+ }
2613
+ if (spec.failover === "approved" && (!Array.isArray(spec.allowedCandidates) || spec.allowedCandidates.length === 0)) {
2614
+ errors.push("failover approved requires allowedCandidates");
2615
+ }
2616
+ if (spec.failover !== "approved" && spec.allowedCandidates !== void 0) {
2617
+ errors.push("allowedCandidates requires failover approved");
2618
+ }
2619
+ if (spec.failover === "automatic" && spec.plan !== void 0) {
2620
+ errors.push("failover automatic is not allowed on a plan-approved dispatch");
2621
+ }
2622
+ if ("plannedNode" in spec && spec.plannedNode !== void 0) {
2623
+ if (!isPlainObject2(spec.plannedNode)) {
2624
+ errors.push("plannedNode must be an object");
2625
+ } else {
2626
+ for (const key of Object.keys(spec.plannedNode)) {
2627
+ if (key !== "id" && key !== "kind" && key !== "host") errors.push(`plannedNode unknown key: ${key}`);
2628
+ }
2629
+ if (typeof spec.plannedNode.id !== "string" || spec.plannedNode.id.trim().length === 0) {
2630
+ errors.push("plannedNode.id must be a non-empty string");
2631
+ }
2632
+ if (spec.plannedNode.kind !== "local" && spec.plannedNode.kind !== "ssh") {
2633
+ errors.push("plannedNode.kind must be local or ssh");
2634
+ }
2635
+ if (spec.plannedNode.kind === "ssh" && (typeof spec.plannedNode.host !== "string" || spec.plannedNode.host.trim().length === 0)) {
2636
+ errors.push("plannedNode.host must be a non-empty string for ssh nodes");
2637
+ }
2638
+ if (spec.plannedNode.kind === "local" && spec.plannedNode.host !== void 0) {
2639
+ errors.push("plannedNode.host must be absent for local nodes");
2640
+ }
2641
+ }
2642
+ }
2643
+ if ("protectedArtifactRemap" in spec && spec.protectedArtifactRemap !== void 0) {
2644
+ 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)) {
2645
+ errors.push("protectedArtifactRemap must carry absolute sourceRoot and workerRoot paths");
2646
+ }
2647
+ }
2648
+ if ("reroutes" in spec && spec.reroutes !== void 0) {
2649
+ if (!Array.isArray(spec.reroutes) || spec.reroutes.some((hop) => !isValidReroute(hop))) {
2650
+ errors.push("reroutes must be an array of {attempt >= 1, fromNode (non-empty), toNode (string), reason (string)}");
2651
+ }
2652
+ }
2653
+ if ("thinkingLevel" in spec && spec.thinkingLevel !== void 0) {
2654
+ if (typeof spec.thinkingLevel !== "string" || !VALID_THINKING.has(spec.thinkingLevel)) {
2655
+ errors.push("thinkingLevel must be one of: off|minimal|low|medium|high|xhigh");
2656
+ }
2657
+ }
2658
+ if ("requiredCapabilities" in spec && spec.requiredCapabilities !== void 0) {
2659
+ if (!Array.isArray(spec.requiredCapabilities) || spec.requiredCapabilities.some((c) => typeof c !== "string")) {
2660
+ errors.push("requiredCapabilities must be a string[]");
2661
+ }
2662
+ }
2663
+ if ("toolProfile" in spec && spec.toolProfile !== void 0) {
2664
+ if (typeof spec.toolProfile !== "string" || !isToolProfileName(spec.toolProfile)) {
2665
+ errors.push("toolProfile must be one of: minimal-local|science-local|full-agent");
2666
+ }
2667
+ }
2668
+ if ("denyTools" in spec && spec.denyTools !== void 0) {
2669
+ if (!Array.isArray(spec.denyTools) || spec.denyTools.some((tool) => typeof tool !== "string" || tool.length === 0)) {
2670
+ errors.push("denyTools must be an array of non-empty strings");
2671
+ }
2672
+ }
2673
+ if ("cwd" in spec && spec.cwd !== void 0) {
2674
+ if (typeof spec.cwd !== "string" || spec.cwd.length === 0) {
2675
+ errors.push("cwd must be a non-empty string");
2676
+ }
2677
+ }
2678
+ if ("memorySection" in spec && spec.memorySection !== void 0) {
2679
+ if (typeof spec.memorySection !== "string") {
2680
+ errors.push("memorySection must be a string");
2681
+ }
2682
+ }
2683
+ if ("noSkills" in spec && spec.noSkills !== void 0) {
2684
+ if (typeof spec.noSkills !== "boolean") {
2685
+ errors.push("noSkills must be a boolean");
2686
+ }
2687
+ }
2688
+ if ("skillPaths" in spec && spec.skillPaths !== void 0) {
2689
+ if (!Array.isArray(spec.skillPaths) || spec.skillPaths.some((p) => typeof p !== "string")) {
2690
+ errors.push("skillPaths must be a string[]");
2691
+ }
2692
+ }
2693
+ if ("trustProjectCompatRoots" in spec && spec.trustProjectCompatRoots !== void 0) {
2694
+ if (typeof spec.trustProjectCompatRoots !== "boolean") {
2695
+ errors.push("trustProjectCompatRoots must be a boolean");
2696
+ }
2697
+ }
2698
+ let responseSchema;
2699
+ if ("responseSchema" in spec && spec.responseSchema !== void 0) {
2700
+ try {
2701
+ responseSchema = cloneValidatedResponseSchema(spec.responseSchema);
2702
+ } catch (error) {
2703
+ errors.push(error instanceof Error ? error.message : String(error));
2704
+ }
2705
+ }
2706
+ if ("writeRoots" in spec && spec.writeRoots !== void 0) {
2707
+ if (!Array.isArray(spec.writeRoots) || spec.writeRoots.length === 0 || spec.writeRoots.some((root) => typeof root !== "string" || root.length === 0)) {
2708
+ errors.push("writeRoots must be a non-empty array of non-empty strings");
2709
+ }
2710
+ }
2711
+ if ("requestOrigin" in spec && spec.requestOrigin !== void 0) {
2712
+ if (typeof spec.requestOrigin !== "string" || !VALID_REQUEST_ORIGINS.has(spec.requestOrigin)) {
2713
+ errors.push("requestOrigin must be one of: user|agent|internal");
2714
+ }
2715
+ }
2716
+ if ("pipelineInput" in spec && spec.pipelineInput !== void 0) {
2717
+ if (!isValidPipelineInput(spec.pipelineInput)) {
2718
+ errors.push("pipelineInput must carry fromRunId (string|null), position (integer >= 1), text (string)");
2719
+ }
2720
+ }
2721
+ if ("predecessorHandoffs" in spec && spec.predecessorHandoffs !== void 0 && !isValidPredecessorHandoffs(spec.predecessorHandoffs)) {
2722
+ errors.push(
2723
+ `predecessorHandoffs must contain at most ${EXECUTION_HANDOFF_MAX_ITEMS} authenticated bounded terminal outputs`
2724
+ );
2725
+ }
2726
+ if ("lineage" in spec && spec.lineage !== void 0) {
2727
+ if (!isValidLineage(spec.lineage)) {
2728
+ errors.push("lineage must carry parentRunId (string|null), rootRunId (string), attempt >= 0, depth >= 0");
2729
+ }
2730
+ }
2731
+ if ("autonomy" in spec && spec.autonomy !== void 0) {
2732
+ if (!isAutonomyLevel(spec.autonomy)) {
2733
+ errors.push("autonomy must be one of: read-only|suggest|auto-edit|full-auto");
2734
+ }
2735
+ }
2736
+ if ("gate" in spec && spec.gate !== void 0) {
2737
+ if (!isValidGate(spec.gate)) {
2738
+ errors.push(
2739
+ "gate must carry role (builder|reviewer|candidate|judge), group (non-empty), cycle >= 1, optional subjects [{runId, digest|null}], optional verdict (pass|fail|revise)"
2740
+ );
2741
+ }
2742
+ }
2743
+ if ("plan" in spec && spec.plan !== void 0) {
2744
+ if (!isValidPlan(spec.plan)) {
2745
+ errors.push(
2746
+ "plan must carry hash (non-empty), topology (parallel|sequential|pipeline|review|compete|detached), taskCount >= 1, approval (operator|full-auto), optional costCeilingUsd > 0"
2747
+ );
2748
+ }
2749
+ }
2750
+ if ("competeStance" in spec && spec.competeStance !== void 0) {
2751
+ if (typeof spec.competeStance !== "string" || !VALID_COMPETE_STANCES.has(spec.competeStance)) {
2752
+ errors.push(`competeStance must be one of ${[...VALID_COMPETE_STANCES].join("|")}`);
2753
+ }
2754
+ }
2755
+ if (errors.length > 0) {
2756
+ return { ok: false, errors };
2757
+ }
2758
+ const out = {
2759
+ agentId,
2760
+ task
2761
+ };
2762
+ if (briefing !== void 0) out.briefing = briefing;
2763
+ if (typeof spec.workerProfile === "string") out.workerProfile = spec.workerProfile;
2764
+ if (typeof spec.workerRuntime === "string") out.workerRuntime = spec.workerRuntime;
2765
+ if (typeof spec.delegationAgentId === "string") out.delegationAgentId = spec.delegationAgentId;
2766
+ if (typeof spec.target === "string") out.target = spec.target;
2767
+ if (typeof spec.model === "string") out.model = spec.model;
2768
+ if (typeof spec.node === "string") out.node = spec.node.trim();
2769
+ if (isRoutingIntent(spec.routingIntent)) out.routingIntent = structuredClone(spec.routingIntent);
2770
+ if (typeof spec.failover === "string" && VALID_FAILOVER_MODES.has(spec.failover)) {
2771
+ out.failover = spec.failover;
2772
+ }
2773
+ if (Array.isArray(spec.allowedCandidates) && spec.allowedCandidates.every(isValidFailoverCandidate)) {
2774
+ out.allowedCandidates = spec.allowedCandidates.map((candidate) => ({ ...candidate }));
2775
+ }
2776
+ if (isValidPlannedNode(spec.plannedNode)) out.plannedNode = { ...spec.plannedNode };
2777
+ if (isValidProtectedArtifactRemap(spec.protectedArtifactRemap)) {
2778
+ out.protectedArtifactRemap = { ...spec.protectedArtifactRemap };
2779
+ }
2780
+ if (Array.isArray(spec.reroutes) && spec.reroutes.every((hop) => isValidReroute(hop))) {
2781
+ out.reroutes = spec.reroutes.map((hop) => ({ ...hop }));
2782
+ }
2783
+ if (typeof spec.thinkingLevel === "string") out.thinkingLevel = spec.thinkingLevel;
2784
+ if (Array.isArray(spec.requiredCapabilities)) {
2785
+ out.requiredCapabilities = spec.requiredCapabilities.map((c) => String(c));
2786
+ }
2787
+ if (typeof spec.toolProfile === "string" && isToolProfileName(spec.toolProfile)) out.toolProfile = spec.toolProfile;
2788
+ if (Array.isArray(spec.denyTools)) out.denyTools = spec.denyTools.map((tool) => String(tool));
2789
+ if (typeof spec.cwd === "string") out.cwd = spec.cwd;
2790
+ if (typeof spec.memorySection === "string") out.memorySection = spec.memorySection;
2791
+ if (typeof spec.noSkills === "boolean") out.noSkills = spec.noSkills;
2792
+ if (Array.isArray(spec.skillPaths)) out.skillPaths = spec.skillPaths.map((p) => String(p));
2793
+ if (typeof spec.trustProjectCompatRoots === "boolean") out.trustProjectCompatRoots = spec.trustProjectCompatRoots;
2794
+ if (responseSchema) out.responseSchema = responseSchema;
2795
+ if (Array.isArray(spec.writeRoots) && spec.writeRoots.length > 0 && spec.writeRoots.every((root) => typeof root === "string" && root.length > 0)) {
2796
+ const jobCwd = typeof spec.cwd === "string" && spec.cwd.length > 0 ? spec.cwd : process.cwd();
2797
+ out.writeRoots = spec.writeRoots.map((root) => path2.resolve(jobCwd, String(root)));
2798
+ }
2799
+ if (typeof spec.requestOrigin === "string" && VALID_REQUEST_ORIGINS.has(spec.requestOrigin)) {
2800
+ out.requestOrigin = spec.requestOrigin;
2801
+ }
2802
+ if (isValidPipelineInput(spec.pipelineInput)) out.pipelineInput = spec.pipelineInput;
2803
+ if (isValidPredecessorHandoffs(spec.predecessorHandoffs))
2804
+ out.predecessorHandoffs = spec.predecessorHandoffs.map((handoff) => ({ ...handoff }));
2805
+ if (isValidLineage(spec.lineage)) out.lineage = spec.lineage;
2806
+ if (isAutonomyLevel(spec.autonomy)) out.autonomy = spec.autonomy;
2807
+ if (isValidGate(spec.gate)) out.gate = cloneGate(spec.gate);
2808
+ if (typeof spec.competeStance === "string" && VALID_COMPETE_STANCES.has(spec.competeStance)) {
2809
+ out.competeStance = spec.competeStance;
2810
+ }
2811
+ if (isValidPlan(spec.plan)) {
2812
+ out.plan = { ...spec.plan, source: spec.plan.source === null ? null : { ...spec.plan.source } };
2813
+ }
2814
+ return { ok: true, spec: out };
2815
+ }
2816
+ function isValidPredecessorHandoffs(value) {
2817
+ if (!Array.isArray(value) || value.length > EXECUTION_HANDOFF_MAX_ITEMS || Buffer.byteLength(JSON.stringify(value), "utf8") > EXECUTION_HANDOFF_MAX_TEXT_BYTES * 2)
2818
+ return false;
2819
+ return value.every((candidate) => {
2820
+ if (!isPlainObject2(candidate)) return false;
2821
+ const fields = [
2822
+ candidate.stepId,
2823
+ candidate.assignmentId,
2824
+ candidate.terminalRunId,
2825
+ candidate.receiptDigest,
2826
+ candidate.output
2827
+ ];
2828
+ return fields.every((field) => typeof field === "string") && typeof candidate.stepId === "string" && candidate.stepId.length > 0 && typeof candidate.assignmentId === "string" && candidate.assignmentId.length > 0 && typeof candidate.terminalRunId === "string" && candidate.terminalRunId.length > 0 && typeof candidate.receiptDigest === "string" && /^[a-f0-9]{64}$/.test(candidate.receiptDigest);
2829
+ });
2830
+ }
2831
+ function isValidPipelineInput(value) {
2832
+ if (!isPlainObject2(value)) return false;
2833
+ const fromRunOk = value.fromRunId === null || typeof value.fromRunId === "string" && value.fromRunId.length > 0;
2834
+ const positionOk = typeof value.position === "number" && Number.isInteger(value.position) && value.position >= 1;
2835
+ const textOk = typeof value.text === "string";
2836
+ return fromRunOk && positionOk && textOk;
2837
+ }
2838
+ function isValidReroute(value) {
2839
+ if (!isPlainObject2(value)) return false;
2840
+ const attemptOk = typeof value.attempt === "number" && Number.isInteger(value.attempt) && value.attempt >= 1;
2841
+ const fromOk = typeof value.fromNode === "string" && value.fromNode.length > 0;
2842
+ const toOk = typeof value.toNode === "string";
2843
+ const reasonOk = typeof value.reason === "string";
2844
+ return attemptOk && fromOk && toOk && reasonOk;
2845
+ }
2846
+ function isValidFailoverCandidate(value) {
2847
+ if (!isPlainObject2(value)) return false;
2848
+ if (Object.keys(value).some((key) => key !== "agentId" && key !== "target" && key !== "model" && key !== "node")) {
2849
+ return false;
2850
+ }
2851
+ return [value.agentId, value.target, value.model, value.node].every(
2852
+ (part) => typeof part === "string" && part.trim().length > 0
2853
+ );
2854
+ }
2855
+ function isValidPlannedNode(value) {
2856
+ if (!isPlainObject2(value) || typeof value.id !== "string" || value.id.trim().length === 0) return false;
2857
+ if (value.kind === "local") return value.host === void 0;
2858
+ return value.kind === "ssh" && typeof value.host === "string" && value.host.trim().length > 0;
2859
+ }
2860
+ function isValidProtectedArtifactRemap(value) {
2861
+ return isPlainObject2(value) && typeof value.sourceRoot === "string" && path2.isAbsolute(value.sourceRoot) && typeof value.workerRoot === "string" && path2.isAbsolute(value.workerRoot);
2862
+ }
2863
+ var VALID_GATE_ROLES = /* @__PURE__ */ new Set(["builder", "reviewer", "candidate", "judge"]);
2864
+ var VALID_GATE_VERDICTS = /* @__PURE__ */ new Set(["pass", "fail", "revise"]);
2865
+ var VALID_PLAN_TOPOLOGIES = /* @__PURE__ */ new Set(["parallel", "sequential", "pipeline", "review", "compete", "detached", "fleet"]);
2866
+ var VALID_PLAN_APPROVALS = /* @__PURE__ */ new Set(["operator", "full-auto"]);
2867
+ function isValidGate(value) {
2868
+ if (!isPlainObject2(value)) return false;
2869
+ if (typeof value.role !== "string" || !VALID_GATE_ROLES.has(value.role)) return false;
2870
+ if (typeof value.group !== "string" || value.group.length === 0) return false;
2871
+ if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) return false;
2872
+ if (value.subjects !== void 0) {
2873
+ if (!Array.isArray(value.subjects)) return false;
2874
+ for (const subject of value.subjects) {
2875
+ if (!isPlainObject2(subject)) return false;
2876
+ if (typeof subject.runId !== "string" || subject.runId.length === 0) return false;
2877
+ if (subject.digest !== null && typeof subject.digest !== "string") return false;
2878
+ }
2879
+ }
2880
+ if (value.verdict !== void 0 && (typeof value.verdict !== "string" || !VALID_GATE_VERDICTS.has(value.verdict))) {
2881
+ return false;
2882
+ }
2883
+ return true;
2884
+ }
2885
+ function cloneGate(gate) {
2886
+ return {
2887
+ role: gate.role,
2888
+ group: gate.group,
2889
+ cycle: gate.cycle,
2890
+ ...gate.subjects !== void 0 ? { subjects: gate.subjects.map((subject) => ({ ...subject })) } : {},
2891
+ ...gate.verdict !== void 0 ? { verdict: gate.verdict } : {}
2892
+ };
2893
+ }
2894
+ function isValidPlan(value) {
2895
+ if (!isPlainObject2(value)) return false;
2896
+ if (typeof value.hash !== "string" || value.hash.length === 0) return false;
2897
+ if (typeof value.topology !== "string" || !VALID_PLAN_TOPOLOGIES.has(value.topology)) return false;
2898
+ if (typeof value.taskCount !== "number" || !Number.isInteger(value.taskCount) || value.taskCount < 1) return false;
2899
+ if (typeof value.approval !== "string" || !VALID_PLAN_APPROVALS.has(value.approval)) return false;
2900
+ if (value.source !== null) {
2901
+ if (!isPlainObject2(value.source) || value.source.kind !== "scout-transition" || typeof value.source.runId !== "string" || value.source.runId.length === 0 || typeof value.source.receiptDigest !== "string" || !/^[0-9a-f]{64}$/u.test(value.source.receiptDigest) || typeof value.source.executionPlanHash !== "string" || !/^[0-9a-f]{64}$/u.test(value.source.executionPlanHash))
2902
+ return false;
2903
+ }
2904
+ if (value.approvalRequestId !== void 0 && (typeof value.approvalRequestId !== "string" || value.approvalRequestId.length === 0)) {
2905
+ return false;
2906
+ }
2907
+ if (value.approvalRequestedBy !== void 0 && (typeof value.approvalRequestedBy !== "string" || value.approvalRequestedBy.length === 0)) {
2908
+ return false;
2909
+ }
2910
+ if (value.costCeilingUsd !== void 0 && (typeof value.costCeilingUsd !== "number" || value.costCeilingUsd <= 0)) {
2911
+ return false;
2912
+ }
2913
+ return true;
2914
+ }
2915
+ function isValidLineage(value) {
2916
+ if (!isPlainObject2(value)) return false;
2917
+ const parentOk = value.parentRunId === null || typeof value.parentRunId === "string" && value.parentRunId.length > 0;
2918
+ const rootOk = typeof value.rootRunId === "string" && value.rootRunId.length > 0;
2919
+ const attemptOk = typeof value.attempt === "number" && Number.isInteger(value.attempt) && value.attempt >= 0;
2920
+ const depthOk = typeof value.depth === "number" && Number.isInteger(value.depth) && value.depth >= 0;
2921
+ return parentOk && rootOk && attemptOk && depthOk;
2922
+ }
2923
+
2924
+ // src/engine/claude/tool-safety.ts
2925
+ init_esm_shims();
2926
+ import { performance } from "node:perf_hooks";
2927
+ function isRecord2(value) {
2928
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2929
+ }
2930
+ function stringField(record2, ...keys) {
2931
+ for (const key of keys) {
2932
+ const value = record2[key];
2933
+ if (typeof value === "string" && value.trim().length > 0) return value.trim();
2934
+ }
2935
+ return void 0;
2936
+ }
2937
+ function pathArgs(input) {
2938
+ const path3 = stringField(input, "file_path", "filePath", "path", "notebook_path", "source", "target");
2939
+ return path3 ? { ...input, path: path3 } : { ...input };
2940
+ }
2941
+ function commandArgs(input, cwd) {
2942
+ const command = stringField(input, "command", "cmd", "shell", "input", "description") ?? JSON.stringify(input);
2943
+ return { ...input, command, cwd: stringField(input, "cwd") ?? cwd };
2944
+ }
2945
+ function dynamicToolName(name) {
2946
+ return name.trim().length > 0 ? `claude:${name}` : "claude:unknown";
2947
+ }
2948
+ var CLAUDE_TOOL_TO_CLIO = {
2949
+ Bash: ToolNames.Bash,
2950
+ Read: ToolNames.Read,
2951
+ NotebookRead: ToolNames.Read,
2952
+ Edit: ToolNames.Edit,
2953
+ MultiEdit: ToolNames.Edit,
2954
+ Write: ToolNames.Write,
2955
+ Grep: ToolNames.Grep,
2956
+ Glob: ToolNames.Find,
2957
+ LS: ToolNames.Ls,
2958
+ Ls: ToolNames.Ls,
2959
+ WebFetch: ToolNames.WebFetch,
2960
+ WebSearch: ToolNames.WebFetch,
2961
+ Task: ToolNames.Dispatch,
2962
+ // TodoWrite mediates as the tasks tool: both are session-scoped plan
2963
+ // bookkeeping that never mutates the workspace, so it classifies read and
2964
+ // is narrowed away exactly when the profile lacks tasks.
2965
+ TodoWrite: ToolNames.Tasks
2966
+ };
2967
+ var CLAUDE_CANONICAL_TOOLS = new Set(Object.values(CLAUDE_TOOL_TO_CLIO));
2968
+ function isClaudeCanonicalTool(name) {
2969
+ return CLAUDE_CANONICAL_TOOLS.has(name);
2970
+ }
2971
+ function claudeToolsOutsideProfile(allowedTools) {
2972
+ return Object.entries(CLAUDE_TOOL_TO_CLIO).filter(([, clioName]) => !allowedTools.has(clioName)).map(([claudeName]) => claudeName);
2973
+ }
2974
+ function mapClaudeToolCall(toolName, input, cwd) {
2975
+ switch (toolName) {
2976
+ case "Bash":
2977
+ return { claudeToolName: toolName, clioToolName: ToolNames.Bash, args: commandArgs(input, cwd), known: true };
2978
+ case "Read":
2979
+ case "NotebookRead":
2980
+ return { claudeToolName: toolName, clioToolName: ToolNames.Read, args: pathArgs(input), known: true };
2981
+ case "Edit":
2982
+ case "MultiEdit":
2983
+ return { claudeToolName: toolName, clioToolName: ToolNames.Edit, args: pathArgs(input), known: true };
2984
+ case "Write":
2985
+ return { claudeToolName: toolName, clioToolName: ToolNames.Write, args: pathArgs(input), known: true };
2986
+ case "Grep":
2987
+ return { claudeToolName: toolName, clioToolName: ToolNames.Grep, args: pathArgs(input), known: true };
2988
+ case "Glob":
2989
+ return { claudeToolName: toolName, clioToolName: ToolNames.Find, args: pathArgs(input), known: true };
2990
+ case "LS":
2991
+ case "Ls":
2992
+ return { claudeToolName: toolName, clioToolName: ToolNames.Ls, args: pathArgs(input), known: true };
2993
+ case "WebFetch":
2994
+ case "WebSearch":
2995
+ return { claudeToolName: toolName, clioToolName: ToolNames.WebFetch, args: { ...input }, known: true };
2996
+ case "Task":
2997
+ return { claudeToolName: toolName, clioToolName: ToolNames.Dispatch, args: { ...input }, known: true };
2998
+ case "TodoWrite":
2999
+ return { claudeToolName: toolName, clioToolName: ToolNames.Tasks, args: { ...input }, known: true };
3000
+ default:
3001
+ return { claudeToolName: toolName, clioToolName: dynamicToolName(toolName), args: { ...input }, known: false };
3002
+ }
3003
+ }
3004
+ function toAutonomyBlock(decision, level, call) {
3005
+ const actionClass = decision.classification.actionClass;
3006
+ return {
3007
+ kind: "block",
3008
+ classification: decision.classification,
3009
+ rejection: autonomyDenyRejection(level, call.tool, actionClass),
3010
+ ...decision.policy !== void 0 ? { policy: decision.policy } : {}
3011
+ };
3012
+ }
3013
+ function toAutonomyAsk(decision, level, call) {
3014
+ const actionClass = decision.classification.actionClass;
3015
+ return {
3016
+ kind: "ask",
3017
+ classification: decision.classification,
3018
+ rejection: autonomyAskRejection(level, call.tool, actionClass),
3019
+ ...decision.policy !== void 0 ? { policy: decision.policy } : {}
3020
+ };
3021
+ }
3022
+ function rejectionText(decision) {
3023
+ if (decision.kind === "allow") return decision.policy?.reasonCode ?? "allowed";
3024
+ return decision.rejection.short;
3025
+ }
3026
+ function budgetDenial(input, mapped, call, reason) {
3027
+ const classification = input.safety.classify(call);
3028
+ const rejection = { short: reason, detail: reason, hints: [] };
3029
+ const blocked = { kind: "block", classification, rejection };
3030
+ input.safety.audit.recordToolCall?.({
3031
+ tool: mapped.clioToolName,
3032
+ classification,
3033
+ decision: "denied",
3034
+ args: mapped.args,
3035
+ reasons: [reason],
3036
+ reasonCode: "worker-budget"
3037
+ });
3038
+ return {
3039
+ kind: "deny",
3040
+ mapped,
3041
+ decision: blocked,
3042
+ reason,
3043
+ reasonCode: "worker-budget",
3044
+ permissionRequired: false
3045
+ };
3046
+ }
3047
+ function evaluateClaudeToolPermission(input) {
3048
+ const mapped = mapClaudeToolCall(input.toolName, input.input, input.cwd);
3049
+ const call = { tool: mapped.clioToolName, args: mapped.args };
3050
+ const attempt = input.budgetGate?.attempt(mapped.clioToolName);
3051
+ if (attempt?.kind === "deny") return budgetDenial(input, mapped, call, attempt.reason);
3052
+ if (input.allowedTools !== void 0 && mapped.known && !input.allowedTools.has(mapped.clioToolName)) {
3053
+ const classification = input.safety.classify(call);
3054
+ const rejection = {
3055
+ short: `${mapped.clioToolName} is not in this worker's tool profile`,
3056
+ detail: `Tool '${mapped.clioToolName}' is outside the dispatched worker's admitted tool surface, so the request is denied. Use only the tools granted to this run.`,
3057
+ hints: []
3058
+ };
3059
+ const blocked = { kind: "block", classification, rejection };
3060
+ input.safety.audit.recordToolCall?.({
3061
+ tool: mapped.clioToolName,
3062
+ classification,
3063
+ decision: "denied",
3064
+ args: mapped.args,
3065
+ reasons: [rejection.detail],
3066
+ reasonCode: "tool-profile"
3067
+ });
3068
+ return {
3069
+ kind: "deny",
3070
+ mapped,
3071
+ decision: blocked,
3072
+ reason: rejection.short,
3073
+ reasonCode: "tool-profile",
3074
+ permissionRequired: false
3075
+ };
3076
+ }
3077
+ const decision = input.safety.evaluate(call);
3078
+ const level = input.autonomy ?? DEFAULT_AUTONOMY_LEVEL;
3079
+ if (decision.kind === "block") {
3080
+ return { kind: "deny", mapped, decision, reason: rejectionText(decision), permissionRequired: false };
3081
+ }
3082
+ if (decision.kind === "ask") {
3083
+ if (level === "read-only") {
3084
+ const blocked = toAutonomyBlock(decision, level, call);
3085
+ return {
3086
+ kind: "deny",
3087
+ mapped,
3088
+ decision: blocked,
3089
+ reason: rejectionText(blocked),
3090
+ reasonCode: `autonomy:${level}`,
3091
+ permissionRequired: false
3092
+ };
3093
+ }
3094
+ return { kind: "deny", mapped, decision, reason: rejectionText(decision), permissionRequired: true };
3095
+ }
3096
+ const actionClass = decision.classification.actionClass;
3097
+ const disposition = mapAutonomy(level, actionClass, {
3098
+ executeRecognized: decision.policy?.execRecognition !== "unrecognized"
3099
+ });
3100
+ if (disposition === "allow") {
3101
+ const admission = input.budgetGate?.admit(mapped.clioToolName);
3102
+ if (admission?.kind === "deny") return budgetDenial(input, mapped, call, admission.reason);
3103
+ return { kind: "allow", mapped, decision, reason: decision.policy?.reasonCode ?? "allowed" };
3104
+ }
3105
+ if (disposition === "deny") {
3106
+ const blocked = toAutonomyBlock(decision, level, call);
3107
+ return {
3108
+ kind: "deny",
3109
+ mapped,
3110
+ decision: blocked,
3111
+ reason: rejectionText(blocked),
3112
+ reasonCode: `autonomy:${level}`,
3113
+ permissionRequired: false
3114
+ };
3115
+ }
3116
+ const ask = toAutonomyAsk(decision, level, call);
3117
+ return {
3118
+ kind: "deny",
3119
+ mapped,
3120
+ decision: ask,
3121
+ reason: rejectionText(ask),
3122
+ reasonCode: `autonomy:${level}`,
3123
+ permissionRequired: true
3124
+ };
3125
+ }
3126
+ function finishDecision(decision) {
3127
+ if (decision.kind === "allow") return "allowed";
3128
+ if (decision.kind === "ask") return "permission_requested";
3129
+ return "blocked";
3130
+ }
3131
+ function emitToolFinish(emit, mapped, startedAtClock, decision, outcome, reason, reasonCode) {
3132
+ const event = {
3133
+ tool: mapped.clioToolName,
3134
+ posture: "operating",
3135
+ durationMs: Math.round(performance.now() - startedAtClock),
3136
+ outcome,
3137
+ actionClass: decision.classification.actionClass,
3138
+ decision: finishDecision(decision)
3139
+ };
3140
+ if (reason.length > 0 && outcome !== "ok") event.reason = reason;
3141
+ if (decision.policy?.ruleId !== void 0) event.ruleId = decision.policy.ruleId;
3142
+ const finalReasonCode = reasonCode ?? decision.policy?.reasonCode;
3143
+ if (finalReasonCode !== void 0) event.reasonCode = finalReasonCode;
3144
+ if (decision.policy?.policySource !== void 0) event.policySource = decision.policy.policySource;
3145
+ emit({ type: "clio_tool_finish", payload: event });
3146
+ }
3147
+ function emitClaudeToolPermissionDecision(input) {
3148
+ const startedAt = Date.now();
3149
+ const startedAtClock = performance.now();
3150
+ const decision = evaluateClaudeToolPermission(input);
3151
+ const start = {
3152
+ tool: decision.mapped.clioToolName,
3153
+ posture: "operating",
3154
+ startedAt
3155
+ };
3156
+ input.emit({ type: "clio_tool_start", payload: start });
3157
+ if (decision.kind === "allow") {
3158
+ emitToolFinish(
3159
+ input.emit,
3160
+ decision.mapped,
3161
+ startedAtClock,
3162
+ decision.decision,
3163
+ "ok",
3164
+ decision.reason,
3165
+ decision.reasonCode
3166
+ );
3167
+ return decision;
3168
+ }
3169
+ if (decision.permissionRequired) {
3170
+ const mode = input.onPermission ?? "deny";
3171
+ input.emit({
3172
+ type: "clio_permission_resolved",
3173
+ payload: {
3174
+ tool: decision.mapped.clioToolName,
3175
+ actionClass: decision.decision.classification.actionClass,
3176
+ mode,
3177
+ reason: mode === "fail" ? `permission required for ${decision.mapped.clioToolName}; workers.onPermission=fail ends this run` : `permission denied by policy: Claude SDK workers run non-interactively; ${decision.reason}`
3178
+ }
3179
+ });
3180
+ }
3181
+ emitToolFinish(
3182
+ input.emit,
3183
+ decision.mapped,
3184
+ startedAtClock,
3185
+ decision.decision,
3186
+ "blocked",
3187
+ decision.reason,
3188
+ decision.reasonCode
3189
+ );
3190
+ return decision;
3191
+ }
3192
+ function coerceToolInput(value) {
3193
+ return isRecord2(value) ? value : {};
3194
+ }
3195
+
3196
+ // src/domains/dispatch/agent-candidates.ts
3197
+ init_esm_shims();
3198
+ var AGENT_CANDIDATE_LIMIT = 64;
3199
+ var TASK_TYPE_RULES = [
3200
+ ["test", /\b(tests?|unit tests?|coverage|spec file)\b/i],
3201
+ ["docs", /\b(documentation|docs|readme|changelog|comment|docstring)\b/i],
3202
+ ["code_review", /\b(review|audit|critique|inspect for)\b/i],
3203
+ ["debug", /\b(debug|fix|bug|crash|failure|broken|regression)\b/i],
3204
+ ["refactor", /\b(refactor|clean ?up|restructure|rename|extract|simplify)\b/i],
3205
+ ["config", /\b(config|configuration|settings|setup|install|ci pipeline|workflow file)\b/i],
3206
+ ["research", /\b(research|investigate|explore|survey|compare|find out)\b/i],
3207
+ ["code_read", /\b(read|explain|understand|summarize|describe|walk through|map|locate|trace)\b/i],
3208
+ ["code_write", /\b(write|implement|add|create|build|develop|introduce)\b/i]
3209
+ ];
3210
+ var DOMAIN_RULES = [
3211
+ ["security", /\b(security|vulnerabilit|auth|credential|secret|cve)\b/i],
3212
+ ["frontend", /\b(ui|css|react|component|frontend|tui|overlay)\b/i],
3213
+ ["infra", /\b(docker|kubernetes|k8s|deploy|terraform|infra|slurm|cluster)\b/i],
3214
+ ["data", /\b(dataset|etl|pipeline data|schema migration|parquet|hdf5)\b/i],
3215
+ ["backend", /\b(api|server|endpoint|database|backend|service)\b/i]
3216
+ ];
3217
+ function classifyAgentTask(task) {
3218
+ const text = task.trim();
3219
+ const taskType = TASK_TYPE_RULES.find(([, pattern]) => pattern.test(text))?.[0] ?? "unknown";
3220
+ const domain = DOMAIN_RULES.find(([, pattern]) => pattern.test(text))?.[0] ?? "general";
3221
+ const words = text.split(/\s+/u).filter(Boolean).length;
3222
+ const complexity = words <= 6 ? "trivial" : words <= 25 ? "simple" : words <= 80 ? "moderate" : "complex";
3223
+ const enumerated = (text.match(/(^|\n)\s*(\d+[.)]|[-*])\s+/gu) ?? []).length;
3224
+ const conjunctions = (text.match(/\b(and then|and also|; )\b/giu) ?? []).length;
3225
+ const estimatedSubtasks = Math.max(1, Math.min(4, enumerated > 1 ? enumerated : conjunctions > 0 ? 2 : 1));
3226
+ return {
3227
+ taskType,
3228
+ complexity,
3229
+ domain,
3230
+ decomposable: estimatedSubtasks > 1,
3231
+ estimatedSubtasks,
3232
+ confidence: taskType === "unknown" ? 0.3 : 0.7
3233
+ };
3234
+ }
3235
+ function agentRouteCandidates(input) {
3236
+ const { request, specs } = input;
3237
+ const byId = new Map(specs.map((spec) => [spec.id, spec]));
3238
+ const baselineSpec = byId.get(request.agentId);
3239
+ const auto = request.agentSelection?.mode === "auto";
3240
+ const recovery = (request.lineage?.attempt ?? 0) > 0;
3241
+ const allowedAgentIds = recovery ? [...new Set((request.allowedCandidates ?? []).map((candidate) => candidate.agentId))] : input.mode === "active" ? auto ? specs.filter((spec) => {
3242
+ const role = deriveExecutionRole({
3243
+ attempt: 0,
3244
+ capabilityClass: spec.capabilityClass,
3245
+ resultContractKind: spec.resultContract.kind
3246
+ });
3247
+ return input.activeAgentRoles.some((pair) => pair.agentId === spec.id && pair.executionRole === role);
3248
+ }).map((spec) => spec.id) : [request.agentId] : null;
3249
+ const baselineAuthority = baselineSpec?.capabilityClass;
3250
+ const candidates = evaluateAgentCandidates(specs, {
3251
+ selectionMode: auto ? "auto" : "explicit",
3252
+ baselineAgentId: request.agentSelection?.baselineAgentId ?? request.agentId,
3253
+ approvedAudiences: ["base", "shadow", "custom"],
3254
+ approvedAuthorities: input.intentOverride !== void 0 ? [input.intentOverride.requestedAuthority] : auto ? request.agentSelection?.approvedAuthorities ?? [] : baselineAuthority !== void 0 && AGENT_AUTOMATION_AUTHORITIES.includes(baselineAuthority) ? [baselineAuthority] : [],
3255
+ requiredTools: [],
3256
+ requiredSkills: [],
3257
+ expectedResultContractKind: input.intentOverride?.expectedResultContractKind ?? (auto ? null : baselineSpec?.resultContract.kind ?? null),
3258
+ locality: request.routingIntent?.locality ?? "any",
3259
+ localAgentIds: specs.map((spec) => spec.id),
3260
+ allowedAgentIds,
3261
+ features: classifyAgentTask(request.task)
3262
+ });
3263
+ const evaluations = candidates.evaluations.map((evaluation) => ({
3264
+ ...evaluation,
3265
+ executionRole: recovery ? "recovery" : evaluation.executionRole
3266
+ }));
3267
+ return {
3268
+ evaluations,
3269
+ dimensions: evaluations.filter((evaluation) => evaluation.rejections.length === 0).map((evaluation) => ({
3270
+ agentId: evaluation.agentId,
3271
+ specFingerprint: evaluation.specFingerprint,
3272
+ executionRole: evaluation.executionRole,
3273
+ latencyClass: byId.get(evaluation.agentId)?.latencyClass ?? "balanced",
3274
+ coldPrior: evaluation.coldPrior
3275
+ }))
3276
+ };
3277
+ }
3278
+ var TASK_SIGNALS = {
3279
+ code_read: { ids: ["scout"], tags: ["reconnaissance", "symbols", "codewiki"], contracts: ["scout-report"] },
3280
+ research: { ids: ["researcher"], tags: ["sources", "external-context", "papers"], contracts: ["research-report"] },
3281
+ code_review: { ids: ["verifier"], tags: ["review", "verification"], contracts: ["verifier-report"] },
3282
+ debug: { ids: ["debugger"], tags: ["debugging", "root-cause"], contracts: ["debugger-report"] },
3283
+ test: { ids: ["verifier", "tester"], tags: ["tests", "validation", "regression"], contracts: ["verifier-report"] },
3284
+ docs: { ids: ["documenter"], tags: ["docs", "runbooks", "examples"], contracts: ["mutation-report"] },
3285
+ code_write: { ids: ["coder"], tags: ["implementation", "repair"], contracts: ["mutation-report"] },
3286
+ refactor: { ids: ["coder"], tags: ["refactor", "implementation"], contracts: ["mutation-report"] },
3287
+ config: { ids: ["coder"], tags: ["implementation", "operations"], contracts: ["mutation-report"] }
3288
+ };
3289
+ function coldPrior(features, spec) {
3290
+ const prior = routePriorForLatencyClass(spec.latencyClass);
3291
+ const reasons = [`latency-class:${spec.latencyClass}`];
3292
+ const signal = TASK_SIGNALS[features.taskType];
3293
+ if (signal === void 0) return { prior, reasons };
3294
+ const matches = signal.ids.includes(spec.id) || spec.tags.some((tag) => signal.tags.includes(tag)) || signal.contracts.includes(spec.resultContract.kind);
3295
+ if (!matches) return { prior, reasons };
3296
+ const confidence = Math.max(0, Math.min(1, features.confidence));
3297
+ prior.qualityMean = Math.min(1, prior.qualityMean + 0.15 * confidence);
3298
+ prior.firstPassSuccessProbability = Math.min(1, prior.firstPassSuccessProbability + 0.1 * confidence);
3299
+ prior.reliability = Math.min(1, prior.reliability + 0.05 * confidence);
3300
+ prior.expectedEndToEndMs *= 1 - 0.15 * confidence;
3301
+ reasons.push(`bounded-task-feature:${features.taskType}`);
3302
+ return { prior, reasons };
3303
+ }
3304
+ function candidateRejections(spec, intent) {
3305
+ const rejections = [];
3306
+ if (!intent.approvedAudiences.includes(spec.audience)) rejections.push(`audience:${spec.audience}`);
3307
+ if (!intent.approvedAuthorities.includes(spec.capabilityClass)) {
3308
+ rejections.push(`authority:${spec.capabilityClass}`);
3309
+ }
3310
+ for (const tool of intent.requiredTools) if (!spec.tools.includes(tool)) rejections.push(`required-tool:${tool}`);
3311
+ for (const skill of intent.requiredSkills)
3312
+ if (!spec.skills.includes(skill)) rejections.push(`required-skill:${skill}`);
3313
+ if (intent.expectedResultContractKind !== null && spec.resultContract.kind !== intent.expectedResultContractKind) {
3314
+ rejections.push(`result-contract:${spec.resultContract.kind}`);
3315
+ }
3316
+ if (intent.locality === "local-only" && !intent.localAgentIds.includes(spec.id)) rejections.push("locality:not-local");
3317
+ if (intent.allowedAgentIds !== null && !intent.allowedAgentIds.includes(spec.id))
3318
+ rejections.push("governance:not-approved");
3319
+ return rejections;
3320
+ }
3321
+ function evaluateAgentCandidates(specs, intent) {
3322
+ if (specs.length > AGENT_CANDIDATE_LIMIT) {
3323
+ throw new Error(
3324
+ `dispatch routing configuration error: agent candidate overflow (${specs.length}/${AGENT_CANDIDATE_LIMIT})`
3325
+ );
3326
+ }
3327
+ const evaluations = specs.map((spec) => {
3328
+ const { prior, reasons } = coldPrior(intent.features, spec);
3329
+ return {
3330
+ agentId: spec.id,
3331
+ specFingerprint: agentSpecFingerprint(spec),
3332
+ executionRole: deriveExecutionRole({
3333
+ attempt: 0,
3334
+ capabilityClass: spec.capabilityClass,
3335
+ resultContractKind: spec.resultContract.kind
3336
+ }),
3337
+ authority: spec.capabilityClass,
3338
+ rejections: candidateRejections(spec, intent),
3339
+ coldPrior: prior,
3340
+ priorReasons: reasons
3341
+ };
3342
+ });
3343
+ return { evaluations, eligible: evaluations.filter((evaluation) => evaluation.rejections.length === 0) };
3344
+ }
3345
+ function agentRoleReadinessReport(entries) {
3346
+ const groups = /* @__PURE__ */ new Map();
3347
+ for (const entry of entries) {
3348
+ const key = `${entry.candidate.agentId}\0${entry.candidate.specFingerprint}\0${entry.candidate.executionRole}`;
3349
+ const group = groups.get(key) ?? [];
3350
+ group.push(entry);
3351
+ groups.set(key, group);
3352
+ }
3353
+ return [...groups.values()].map((routes) => ({
3354
+ agentId: routes[0]?.candidate.agentId ?? "",
3355
+ specFingerprint: routes[0]?.candidate.specFingerprint ?? "",
3356
+ executionRole: routes[0]?.candidate.executionRole ?? "builder",
3357
+ ready: routes.some((route) => route.report.ready),
3358
+ candidateCount: routes.length,
3359
+ readyCandidateCount: routes.filter((route) => route.report.ready).length,
3360
+ routes
3361
+ }));
3362
+ }
3363
+
3364
+ export {
3365
+ RESPONSE_SCHEMA_RUNTIME_ID,
3366
+ runtimeSpeaksResponseSchemaDialect,
3367
+ responseSchemaConflictsWithTools,
3368
+ UnsupportedResponseSchemaError,
3369
+ isResponseSchemaRejection,
3370
+ TOOL_PROFILE_NAMES,
3371
+ isToolProfileName,
3372
+ assertToolProfileEnforceable,
3373
+ applyToolProfile,
3374
+ antigravitySubprocessConfigForAutonomy,
3375
+ startAntigravityWorkerRun,
3376
+ isClaudeCodeSessionId,
3377
+ claudeSubprocessPermissionConfigForAutonomy,
3378
+ startClaudeCodeWorkerRun,
3379
+ isClaudeCanonicalTool,
3380
+ claudeToolsOutsideProfile,
3381
+ emitClaudeToolPermissionDecision,
3382
+ coerceToolInput,
3383
+ WORKER_RUNTIME_MEDIATES_CLIO_DISPATCH,
3384
+ readMaxBytes,
3385
+ readTool,
3386
+ toolPromptHintsForNames,
3387
+ builtin,
3388
+ NO_NETWORK_TOOLS_ENV,
3389
+ networkToolsDisabled,
3390
+ WORKER_SPEC_VERSION,
3391
+ WORKER_PROTECTED_ARTIFACT_STATE_VERSION,
3392
+ WORKER_EXIT_PERMISSION_REQUIRED,
3393
+ DEFAULT_ESCALATION_TIMEOUT_MS,
3394
+ DEFAULT_ESCALATION_FALLBACK,
3395
+ serializeWorkerRuntimeDescriptor,
3396
+ parseWorkerSpec,
3397
+ validateRehydratedWorkerRuntime,
3398
+ createRunEffectsRecorder,
3399
+ isApprovedAssignmentRoute,
3400
+ assertApprovedAssignmentRoute,
3401
+ cloneApprovedAssignmentRoute,
3402
+ approvedRouteCandidates,
3403
+ assertApprovedRecoveryCapability,
3404
+ classifyAgentTask,
3405
+ agentRouteCandidates,
3406
+ agentRoleReadinessReport,
3407
+ AGENT_LEDGER_PROMPT_MAX_CHARS,
3408
+ claimConflicts,
3409
+ renderAgentLedger,
3410
+ REVIEWER_GATE_PROMPT,
3411
+ JUDGE_GATE_PROMPT,
3412
+ COMPETE_STANCES,
3413
+ competeStanceLiner,
3414
+ isBoundedGateRolePrompt,
3415
+ isRunOutcomeCode,
3416
+ RETRYABLE_OUTCOMES,
3417
+ isTerminalRunEnvelope,
3418
+ runKindSupportsLiveSteering,
3419
+ projectExecutionHandoffs,
3420
+ DISPATCH_BRIEFING_MAX_BYTES,
3421
+ validateJobSpec,
3422
+ isSessionHeader,
3423
+ isSessionEntry,
3424
+ taskBoardCounts,
3425
+ foldSessionTaskHistory,
3426
+ createTaskBoardStore
3427
+ };
3428
+ //# sourceMappingURL=chunk-MQSRRFWA.js.map