@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,1169 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import type { TSchema } from "typebox";
3
+ import { isWorkerToolCallCapExceededReason } from "../core/guardrails.js";
4
+ import { HEADLESS_PERMISSION_DENIED_MARKER } from "../core/headless-permission.js";
5
+ import {
6
+ evaluateSkillToolSurface,
7
+ type PendingSkillToolPolicy,
8
+ type SkillToolSurfaceViolation,
9
+ } from "../core/skill-activation.js";
10
+ import { type ToolName, ToolNames } from "../core/tool-names.js";
11
+ import type { MiddlewareContract } from "../domains/middleware/contract.js";
12
+ import type { MiddlewareEffect, MiddlewareHookInput, MiddlewareMetadataValue } from "../domains/middleware/types.js";
13
+ import type { ActionClass, ClassifierCall } from "../domains/safety/action-classifier.js";
14
+ import { approvalAxisId } from "../domains/safety/approval-axis.js";
15
+ import {
16
+ type AutonomyExposure,
17
+ type AutonomyLevel,
18
+ autonomyAskRejection,
19
+ autonomyDenyRejection,
20
+ DEFAULT_AUTONOMY_EXPOSURE,
21
+ DEFAULT_AUTONOMY_LEVEL,
22
+ mapAutonomy,
23
+ } from "../domains/safety/autonomy.js";
24
+ import type { SafetyContract, SafetyDecision } from "../domains/safety/contract.js";
25
+ import { hashToolCall } from "../domains/safety/loop-detector.js";
26
+ import { detectValidationCommand } from "../domains/safety/protected-artifacts.js";
27
+ import { askUserExposure } from "./ask-user.js";
28
+ import { type DispatchPlanView, describeDispatchPlan } from "./dispatch-plan.js";
29
+ import { shapeToolResult } from "./result-shaping.js";
30
+
31
+ /**
32
+ * Tool registry. Admission point for every tool call. Delegates classification
33
+ * and policy decisions to the safety domain, parks one-shot confirmation asks,
34
+ * and runs admitted tool bodies. Never throws on safety rejections; the caller
35
+ * surfaces the rejection message back to the model.
36
+ */
37
+
38
+ /**
39
+ * Per-tool execution mode override forwarded to pi-agent-core's
40
+ * `AgentTool.executionMode`. Parallel tools may run concurrently with other
41
+ * parallel tool calls; sequential tools run one at a time and prevent any
42
+ * other tool in the batch from running in parallel with them. Leaving this
43
+ * undefined defers to the agent loop's global `toolExecution` setting.
44
+ */
45
+ export type ToolExecutionMode = "sequential" | "parallel";
46
+ export type ToolSourceScope = "core" | "domain";
47
+ export type ToolRetrySafety = "idempotent" | "retry_safe" | "not_retry_safe" | "unknown";
48
+ export type ToolCostLatencyClass = "local_fast" | "local_medium" | "local_slow" | "network" | "agent";
49
+
50
+ export interface ToolSourceInfo {
51
+ path: string;
52
+ scope: ToolSourceScope;
53
+ }
54
+
55
+ export interface ToolResultSizePolicy {
56
+ kind: "exact" | "bounded" | "summary" | "truncate";
57
+ maxBytes?: number;
58
+ followUpHint?: string;
59
+ }
60
+
61
+ export interface ToolMetadata {
62
+ /** Short statement of the tool's purpose for audit/UI surfaces. */
63
+ objective: string;
64
+ /** Stable UI label shown in compact renderers. */
65
+ uiLabel: string;
66
+ /** Whether automatic recovery may safely retry an unfinished call. */
67
+ retrySafety: ToolRetrySafety;
68
+ /** Expected result-size behavior at the registry boundary. */
69
+ resultSizePolicy: ToolResultSizePolicy;
70
+ /** Coarse cost/latency bucket for dashboard diagnostics. */
71
+ costLatency: ToolCostLatencyClass;
72
+ /**
73
+ * One sentence of usage guidance rendered into the session Tool Contract
74
+ * when this tool is on the frozen surface. Hints render sorted by tool
75
+ * name, so the compiled prompt stays byte-stable per surface. Most tools
76
+ * need none; the schema description covers them.
77
+ */
78
+ promptHint?: string;
79
+ }
80
+
81
+ export interface ToolSpec {
82
+ name: ToolName;
83
+ description: string;
84
+ sourceInfo?: ToolSourceInfo;
85
+ metadata?: ToolMetadata;
86
+ /**
87
+ * TypeBox schema advertised to the model so it knows which named
88
+ * parameters the tool accepts. Must be a Type.Object(...). Runtime
89
+ * validation still happens inside `run()`, so the schema is advisory
90
+ * to the model, not an enforcement boundary.
91
+ */
92
+ parameters: TSchema;
93
+ /** Base action class for this tool when arguments are trivial. */
94
+ baseActionClass: ActionClass;
95
+ /**
96
+ * Per-tool execution mode. Read-only tools set `"parallel"` so the model
97
+ * can batch scans; mutating or filesystem-racing tools set `"sequential"`
98
+ * so two `bash` or `edit` calls in the same batch never run concurrently.
99
+ */
100
+ executionMode?: ToolExecutionMode;
101
+ /**
102
+ * Optional argument normalizer applied before the tool body (and its own
103
+ * internal validation). Mirrors pi's `prepareArguments`: lets a tool accept
104
+ * the common weak-model argument shapes (legacy top-level fields, a
105
+ * JSON-string array) without hand-parsing inside every `run`. Must be pure
106
+ * and idempotent; a throwing normalizer is ignored and the raw args pass
107
+ * through. Tools that also want direct `run` calls normalized should invoke
108
+ * the same function at the top of `run`.
109
+ */
110
+ prepareArguments?(args: Record<string, unknown>): Record<string, unknown>;
111
+ /**
112
+ * Synchronous admission planner. Unlike `prepareArguments`, this runs before
113
+ * safety/autonomy mapping so approval-sensitive tools can attach the exact
114
+ * immutable artifact—and provisional resources—that admission and execution
115
+ * share. Resource owners must pair it with `disposeAdmissionArguments`.
116
+ */
117
+ prepareAdmissionArguments?(args: Record<string, unknown>): Record<string, unknown>;
118
+ /** Release provisional resources when prepared admission is denied or execution returns. */
119
+ disposeAdmissionArguments?(args: Record<string, unknown>): void;
120
+ /** Trusted admission artifact renderer used by policy after preparation. */
121
+ describeDispatchPlan?(args: Record<string, unknown>): DispatchPlanView;
122
+ /** Execute the tool. Only called after admission. */
123
+ run(args: Record<string, unknown>, options?: ToolInvokeOptions): Promise<ToolResult>;
124
+ }
125
+
126
+ export type ToolResultDetails = Record<string, unknown>;
127
+
128
+ export type ToolResult =
129
+ | {
130
+ kind: "ok";
131
+ output: string;
132
+ details?: ToolResultDetails;
133
+ /**
134
+ * Early-termination hint propagated to pi-agent-core's
135
+ * `AgentToolResult.terminate`. When every finalized tool result in
136
+ * the current batch sets this to true, the agent loop stops without
137
+ * a follow-up LLM call. Used by terminal artifact writers where
138
+ * writing the artifact is the whole turn.
139
+ */
140
+ terminate?: boolean;
141
+ }
142
+ | { kind: "error"; message: string; details?: ToolResultDetails };
143
+
144
+ export interface RegistryDeps {
145
+ safety: SafetyContract;
146
+ /**
147
+ * Hook layer. The loop guard, registered on `before_tool` by both
148
+ * composition roots (entry/orchestrator.ts and worker-runtime.ts via
149
+ * engine/loop-guard.ts), observes every call attempt through this contract;
150
+ * the registry feeds it `metadata.callFingerprint` and runs `before_tool`
151
+ * for safety-blocked attempts too, so repetition of rejected calls stays
152
+ * observable.
153
+ */
154
+ middleware?: MiddlewareContract;
155
+ /**
156
+ * Provider-routing effects emitted by tool hooks apply to the next model
157
+ * round. The registry owns those hook calls, so it forwards the complete
158
+ * effect batch to the composition root after evaluation. Consumers may only
159
+ * narrow routing (`require_tool` / `lock_tools`); admission still happens
160
+ * through this registry on the resulting call.
161
+ */
162
+ onMiddlewareEffects?: (effects: ReadonlyArray<MiddlewareEffect>, input: MiddlewareHookInput) => void;
163
+ /**
164
+ * Live autonomy level (sd-01 §2.2). Read per admission so hot-reloaded
165
+ * settings apply to the next call. The orchestrator wires this to current
166
+ * settings; workers wire it to the level carried on their WorkerSpec.
167
+ * Absent means the default level (M7: auto-edit).
168
+ */
169
+ autonomy?: () => AutonomyLevel;
170
+ }
171
+
172
+ export interface ToolInvokeOptions {
173
+ signal?: AbortSignal;
174
+ runId?: string;
175
+ sessionId?: string;
176
+ turnId?: string;
177
+ toolCallId?: string;
178
+ correlationId?: string;
179
+ pendingSkillPolicy?: PendingSkillToolPolicy;
180
+ askUserPolicy?: AskUserToolPolicy;
181
+ /** Registry-authenticated one-shot operator approval for this execution. */
182
+ approval?: { requestId: string; requestedBy: string; actionClass: ActionClass };
183
+ /**
184
+ * How long this call sat parked awaiting an operator decision, reported when
185
+ * the park resolves. A caller timing the invocation is measuring the tool,
186
+ * and the park is the operator, so the two have to be separable: without
187
+ * this a `npm test` approved after a minute of reading was recorded as a
188
+ * one-minute test run in the transcript, the receipt, and toolStats.
189
+ */
190
+ onParked?: (parkedMs: number) => void;
191
+ /**
192
+ * Display-only cumulative progress supplied by pi-agent-core's
193
+ * `AgentToolUpdateCallback`. Tool bodies may report the result snapshot the
194
+ * operator should see while the call runs. Admission, final result shaping,
195
+ * telemetry, and ledger persistence continue to consume only the terminal
196
+ * return value.
197
+ */
198
+ onUpdate?: (partialResult: ToolResult) => void;
199
+ }
200
+
201
+ export type AskUserInterviewStatus = "idle" | "active" | "complete" | "cancelled";
202
+
203
+ export interface AskUserTranscriptQuestion {
204
+ question: string;
205
+ header?: string;
206
+ options?: Array<{ label: string; description?: string }>;
207
+ multi_select?: boolean;
208
+ }
209
+
210
+ export interface AskUserTranscriptAnswer {
211
+ question: string;
212
+ answer: string;
213
+ }
214
+
215
+ export interface AskUserTranscriptDecision {
216
+ key: string;
217
+ value: string;
218
+ label?: string;
219
+ source_question?: string;
220
+ }
221
+
222
+ export interface AskUserTranscriptRound {
223
+ round: number;
224
+ requestedAt: string;
225
+ answeredAt?: string;
226
+ questions: AskUserTranscriptQuestion[];
227
+ answers: AskUserTranscriptAnswer[];
228
+ cancelled?: boolean;
229
+ }
230
+
231
+ export interface AskUserToolPolicy {
232
+ id: string;
233
+ status: AskUserInterviewStatus;
234
+ startedAt: string;
235
+ updatedAt: string;
236
+ endedAt?: string;
237
+ sessionId?: string;
238
+ turnId?: string;
239
+ transcriptPath?: string;
240
+ summary?: string;
241
+ rounds: AskUserTranscriptRound[];
242
+ decisions: AskUserTranscriptDecision[];
243
+ inFlight: boolean;
244
+ cancelled: boolean;
245
+ answerCount: number;
246
+ callCount: number;
247
+ maxCalls: number;
248
+ askedQuestionKeys: Set<string>;
249
+ }
250
+
251
+ /**
252
+ * One-shot elevation grant. The interactive layer issues this when the user
253
+ * confirms a single parked tool call without changing persistent posture.
254
+ * The registry consumes the grant on the next `resumeParkedCalls` pass so
255
+ * exactly one parked call receives elevated admission; subsequent calls go
256
+ * back through the normal safety gate.
257
+ */
258
+ export interface OneShotGrant {
259
+ /** Parked action class approved for this single admission pass. */
260
+ actionClass: ActionClass;
261
+ /** Parked approval request approved for this single admission pass. */
262
+ requestId?: string;
263
+ /** Free-form origin tag carried into audit (`tool`, `keybind:single`, ...). */
264
+ requestedBy: string;
265
+ }
266
+
267
+ export interface PermissionRequiredMeta {
268
+ requestId: string;
269
+ axis: string;
270
+ /**
271
+ * Provider tool-call id carried on the parked call's invoke options, when
272
+ * one exists. The interactive layer uses it to correlate the park to its
273
+ * transcript tool segment so a parked call renders as awaiting approval
274
+ * instead of running. Purely descriptive: park/resume semantics never
275
+ * read it.
276
+ */
277
+ toolCallId?: string;
278
+ }
279
+
280
+ export interface ToolRegistry {
281
+ register(spec: ToolSpec): void;
282
+ /** Tools visible in the single operating posture. Models only see these. */
283
+ listVisible(): ReadonlyArray<ToolSpec>;
284
+ /** Tools registered overall. For /audit, /doctor. */
285
+ listAll(): ReadonlyArray<ToolSpec>;
286
+ /** Lookup by tool id. */
287
+ get(name: ToolName): ToolSpec | undefined;
288
+ /** Tool names registered in the single operating posture. */
289
+ listRegistered(): ReadonlyArray<ToolName>;
290
+ /**
291
+ * Admission point. Classifies, evaluates safety, and either runs or
292
+ * returns a rejection. Never throws on safety rejections. When the
293
+ * a safety ask or confirmable action is encountered, the returned promise
294
+ * stays pending until a resume or cancel method resolves it.
295
+ */
296
+ invoke(call: ClassifierCall, options?: ToolInvokeOptions): Promise<RegistryVerdict>;
297
+ /**
298
+ * True while at least one call awaits operator confirmation. The interactive
299
+ * layer reads this from `closeOverlay()` to re-open the confirmation overlay
300
+ * whenever an unrelated overlay closes with a parked call still pending.
301
+ */
302
+ hasParkedCalls(): boolean;
303
+ /** Number of calls currently waiting for operator confirmation. */
304
+ parkedCount(): number;
305
+ /**
306
+ * Re-fire the permission-required signal for the oldest parked call without
307
+ * changing queue order or resolving anything.
308
+ */
309
+ renotifyHead(): void;
310
+ /**
311
+ * Re-run admission for every parked call. When `grant` is provided the
312
+ * grant covers one parked action class. Calls admitted on retry
313
+ * execute and their original promise resolves with the result. Calls still
314
+ * waiting for confirmation stay parked.
315
+ */
316
+ resumeParkedCalls(grant?: OneShotGrant): Promise<void>;
317
+ /**
318
+ * Resolve one parked call with a `blocked` verdict carrying `reason`.
319
+ * Returns true when the request was found.
320
+ */
321
+ cancelParkedCall(requestId: string, reason: string): boolean;
322
+ /**
323
+ * Resolve every parked call with a `blocked` verdict carrying `reason`.
324
+ * Used when the confirmation overlay is cancelled so the agent loop sees a
325
+ * clean rejection instead of an indefinitely pending tool call.
326
+ */
327
+ cancelParkedCalls(reason: string): void;
328
+ /**
329
+ * Subscribe to the signal fired when a call is parked awaiting permission
330
+ * confirmation. Returns an unsubscribe handle.
331
+ */
332
+ onPermissionRequired(
333
+ listener: (call: ClassifierCall, decision: SafetyDecision, meta: PermissionRequiredMeta) => void,
334
+ ): () => void;
335
+ /**
336
+ * Subscribe to the signal fired when the autonomy mapping auto-denies a
337
+ * call (deny dispositions, today only at read-only). The verdict already
338
+ * carries the rejection; this exists for operator-facing notices.
339
+ */
340
+ onAutonomyDenied(listener: (call: ClassifierCall, decision: SafetyDecision, level: AutonomyLevel) => void): () => void;
341
+ }
342
+
343
+ export type RegistryVerdict =
344
+ | { kind: "ok"; result: ToolResult; decision: SafetyDecision }
345
+ | { kind: "blocked"; reason: string; decision: SafetyDecision }
346
+ | { kind: "not_visible"; reason: string };
347
+
348
+ interface ParkedCall {
349
+ call: ClassifierCall;
350
+ decision: SafetyDecision;
351
+ meta: PermissionRequiredMeta;
352
+ resolve: (verdict: RegistryVerdict) => void;
353
+ /**
354
+ * Seals the park at the instant the operator's decision lands, before the
355
+ * admitted body runs. Idempotent, so the resolve paths that never reach a
356
+ * body still report exactly one park.
357
+ */
358
+ closePark: () => void;
359
+ options?: ToolInvokeOptions;
360
+ abortCleanup?: () => void;
361
+ }
362
+
363
+ export function createRegistry(deps: RegistryDeps): ToolRegistry {
364
+ const tools = new Map<ToolName, ToolSpec>();
365
+ const parked: ParkedCall[] = [];
366
+ const permissionListeners = new Set<
367
+ (call: ClassifierCall, decision: SafetyDecision, meta: PermissionRequiredMeta) => void
368
+ >();
369
+ const autonomyDeniedListeners = new Set<
370
+ (call: ClassifierCall, decision: SafetyDecision, level: AutonomyLevel) => void
371
+ >();
372
+ let approvalRequestCounter = 0;
373
+ const approvalRequestToken = randomBytes(4).toString("hex");
374
+
375
+ const runSpec = async (
376
+ spec: ToolSpec,
377
+ call: ClassifierCall,
378
+ decision: SafetyDecision,
379
+ options?: ToolInvokeOptions,
380
+ ): Promise<RegistryVerdict> => {
381
+ try {
382
+ // The hook layer is the only control stage past safety admission. Guards
383
+ // (loop, protected artifacts, dispatch dedup) are before_tool
384
+ // registrations; the first block_tool effect decides the verdict. Keep
385
+ // this gate inside the admission cleanup boundary: dispatch may already
386
+ // own a provisional reservation by the time a guard blocks execution.
387
+ const beforeEffects = runToolHook("before_tool", spec, call, decision, options);
388
+ const block = firstBlockToolEffect(beforeEffects);
389
+ if (block) {
390
+ const verdict = guardBlockedVerdict(decision, call.tool, block.reason);
391
+ recordRegistryDisposition(call, verdict.decision, "blocked", {
392
+ reasonCode: GUARD_BLOCK_REASON_CODE,
393
+ reasons: [block.reason],
394
+ });
395
+ return verdict;
396
+ }
397
+ try {
398
+ const preparedArgs = prepareToolArgs(spec, call.args ?? {});
399
+ const result = shapeToolResult(spec, await spec.run(preparedArgs, options), options);
400
+ const afterEffects = runToolHook("after_tool", spec, call, decision, options, result);
401
+ const finalResult = shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options);
402
+ return { kind: "ok", result: finalResult, decision };
403
+ } catch (err) {
404
+ const message = err instanceof Error ? err.message : String(err);
405
+ const result = shapeToolResult(spec, { kind: "error", message }, options);
406
+ const afterEffects = runToolHook("after_tool", spec, call, decision, options, result);
407
+ return {
408
+ kind: "ok",
409
+ result: shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options),
410
+ decision,
411
+ };
412
+ }
413
+ } finally {
414
+ disposeAdmissionArgs(spec, call.args ?? {});
415
+ }
416
+ };
417
+
418
+ const runToolHook = (
419
+ hook: "before_tool" | "after_tool",
420
+ spec: ToolSpec,
421
+ call: ClassifierCall,
422
+ decision: SafetyDecision,
423
+ options: ToolInvokeOptions | undefined,
424
+ result?: ToolResult,
425
+ ): ReadonlyArray<MiddlewareEffect> => {
426
+ if (!deps.middleware) return [];
427
+ const input = buildToolHookInput(hook, spec, call, decision, "operating", options, result);
428
+ const effects = deps.middleware.runHook(input).effects;
429
+ try {
430
+ deps.onMiddlewareEffects?.(effects, input);
431
+ } catch {
432
+ // A provider-routing sink is advisory to this call. It may narrow the
433
+ // next request, but it must never throw through tool admission.
434
+ }
435
+ return effects;
436
+ };
437
+
438
+ type AdmitOutcome =
439
+ | { kind: "terminal"; verdict: RegistryVerdict }
440
+ | { kind: "execute"; spec: ToolSpec; decision: SafetyDecision }
441
+ | { kind: "park"; decision: SafetyDecision; axis: string };
442
+
443
+ const admit = (call: ClassifierCall, grant?: OneShotGrant, options?: ToolInvokeOptions): AdmitOutcome => {
444
+ const spec = tools.get(call.tool as ToolName);
445
+ if (!spec) {
446
+ return { kind: "terminal", verdict: { kind: "not_visible", reason: `tool not registered: ${call.tool}` } };
447
+ }
448
+ const level = deps.autonomy?.() ?? DEFAULT_AUTONOMY_LEVEL;
449
+ const decision = applyRegisteredToolClassification(deps.safety.evaluate(call, grant ? "confirmed" : undefined), spec);
450
+ // Stage 1, the safety net (level-independent): engine blocks are final;
451
+ // engine asks are confirm rails that park at every level. read-only is
452
+ // the exception by definition: approvals are never invoked there, so a
453
+ // confirm rail resolves as the same auto-deny as any other mutation.
454
+ if (decision.kind === "block") {
455
+ return { kind: "terminal", verdict: { kind: "blocked", reason: decision.rejection.short, decision } };
456
+ }
457
+ // Stage 1.5, the skill tool surface: a loaded SKILL.md that declares
458
+ // allowed-tools or disallowed-tools narrows the surface until the
459
+ // policy's lifetime ends (turn end for the main agent, run end for
460
+ // workers). Narrowing only blocks; it never grants, and an out-of-
461
+ // surface call blocks terminally instead of parking for confirmation.
462
+ const surfaceViolation = evaluateSkillToolSurface(options?.pendingSkillPolicy, call.tool);
463
+ if (surfaceViolation) {
464
+ const verdict = skillSurfaceBlockedVerdict(decision, call.tool, surfaceViolation);
465
+ recordRegistryDisposition(call, verdict.decision, "blocked", {
466
+ reasonCode: "skill_surface",
467
+ reasons: [verdict.reason],
468
+ });
469
+ return { kind: "terminal", verdict };
470
+ }
471
+ const actionClass = decision.classification.actionClass;
472
+ if (decision.kind === "ask") {
473
+ if (level === "read-only") {
474
+ const verdict = autonomyDenyVerdict(decision, level, call.tool, actionClass);
475
+ recordRegistryDisposition(call, verdict.decision, "denied", { reasonCode: `autonomy:${level}` });
476
+ notifyAutonomyDenied(call, verdict.decision, level);
477
+ return { kind: "terminal", verdict };
478
+ }
479
+ if (grant?.actionClass === actionClass) return { kind: "execute", spec, decision };
480
+ return { kind: "park", decision, axis: approvalAxisId(decision, level) };
481
+ }
482
+ // One-shot grant: resumeParkedCalls re-admits exactly the parked call
483
+ // the operator approved, with a confirmed posture. The engine converts
484
+ // its confirm rail to an allow (including M3 git ask rules), so the
485
+ // grant match executes directly instead of re-entering the mapping.
486
+ if (grant?.actionClass === actionClass) {
487
+ return { kind: "execute", spec, decision };
488
+ }
489
+ if (actionClass === "git_destructive") {
490
+ recordRegistryDisposition(call, decision, "blocked", {
491
+ reasons: [`action ${actionClass} is hard-blocked`],
492
+ reasonCode: "classification:git_destructive",
493
+ });
494
+ return {
495
+ kind: "terminal",
496
+ verdict: {
497
+ kind: "blocked",
498
+ reason: `action ${actionClass} is hard-blocked`,
499
+ decision,
500
+ },
501
+ };
502
+ }
503
+ // Stage 2, the autonomy mapping (sd-01 §2.3): the net passed; the level
504
+ // decides run / ask / deny per action class. Plan-scale dispatch calls
505
+ // (multi-task, compete, remote node) carry the plan flag so supervised
506
+ // levels route them through one plan approval.
507
+ const dispatchPlan =
508
+ call.tool === ToolNames.Dispatch
509
+ ? (spec.describeDispatchPlan?.(call.args ?? {}) ?? describeDispatchPlan(call.args))
510
+ : null;
511
+ const planScale = dispatchPlan?.planScale === true;
512
+ // The exposure tier rides on the args of the gate that raised it, so the
513
+ // workflow author, not the classifier, decides what counts as outward.
514
+ // ask_user is the only tool that declares one today.
515
+ const exposure = call.tool === ToolNames.AskUser ? askUserExposure(call.args) : DEFAULT_AUTONOMY_EXPOSURE;
516
+ const disposition = mapAutonomy(level, actionClass, {
517
+ executeRecognized: decision.policy?.execRecognition !== "unrecognized",
518
+ ...(planScale ? { dispatchPlanScale: true } : {}),
519
+ ...(exposure === "outward" ? { exposure } : {}),
520
+ });
521
+ if (disposition === "deny") {
522
+ const verdict = autonomyDenyVerdict(decision, level, call.tool, actionClass);
523
+ recordRegistryDisposition(call, verdict.decision, "denied", { reasonCode: `autonomy:${level}` });
524
+ notifyAutonomyDenied(call, verdict.decision, level);
525
+ return { kind: "terminal", verdict };
526
+ }
527
+ if (disposition === "ask") {
528
+ const askDecision =
529
+ planScale && dispatchPlan !== null
530
+ ? toDispatchPlanAskDecision(decision, level, dispatchPlan)
531
+ : toAutonomyAskDecision(decision, level, call.tool, actionClass, exposure);
532
+ return { kind: "park", decision: askDecision, axis: approvalAxisId(askDecision, level) };
533
+ }
534
+ recordRegistryDisposition(call, decision, "allowed");
535
+ return { kind: "execute", spec, decision };
536
+ };
537
+
538
+ const recordRegistryDisposition = (
539
+ call: ClassifierCall,
540
+ decision: SafetyDecision,
541
+ auditDecision: "allowed" | "blocked" | "permission_requested" | "denied",
542
+ overrides?: { reasons?: ReadonlyArray<string>; reasonCode?: string; requestId?: string },
543
+ ): void => {
544
+ // Row sequence for net-pass calls: safety.evaluate writes `classified`;
545
+ // registry admission writes the final autonomy disposition. Confirmed
546
+ // re-admissions keep their existing `allowed` row from safety.evaluate.
547
+ // When the registry, not the policy engine, made the final call, the
548
+ // caller passes a reasonCode override so the row does not repeat the
549
+ // net pass's "allowed" code on a non-allowed decision.
550
+ const reasons = overrides?.reasons;
551
+ deps.safety.audit.recordToolCall?.({
552
+ tool: call.tool,
553
+ classification: decision.classification,
554
+ decision: auditDecision,
555
+ args: call.args,
556
+ ...(overrides?.requestId !== undefined ? { requestId: overrides.requestId } : {}),
557
+ ...(decision.policy !== undefined ? { policy: decision.policy } : {}),
558
+ ...(overrides?.reasonCode !== undefined ? { reasonCode: overrides.reasonCode } : {}),
559
+ ...(reasons !== undefined ? { reasons } : decision.kind === "allow" ? {} : { reasons: [decision.rejection.detail] }),
560
+ });
561
+ };
562
+
563
+ /**
564
+ * Loop-observe a safety-blocked attempt. The verdict stands and every
565
+ * effect is discarded; this exists so the before_tool loop guard sees
566
+ * rejected attempts too. Without it, a model repeating an identical
567
+ * blocked call would never trip the detector (the former worker guard sat
568
+ * in front of admission and had this coverage).
569
+ */
570
+ const observeBlockedAttempt = (
571
+ call: ClassifierCall,
572
+ verdict: RegistryVerdict,
573
+ options?: ToolInvokeOptions,
574
+ ): RegistryVerdict | null => {
575
+ if (verdict.kind !== "blocked") return null;
576
+ return guardOverrideForRejectedAttempt(
577
+ call,
578
+ verdict.decision,
579
+ observeRejectedAttempt(call, verdict.decision, options),
580
+ );
581
+ };
582
+
583
+ /**
584
+ * Run before_tool hooks for an attempt that will not execute, so repetition
585
+ * detectors see it. Most effects do not change the rejection itself; the
586
+ * worker tool-call cap is the exception, because it is the deterministic
587
+ * run bound for denied-call spirals. The returned value is the first
588
+ * block_tool reason (the loop guard's actionable feedback), which the
589
+ * park-denial path substitutes for its generic reason so a model retrying a
590
+ * denied call learns to stop instead of looping until the run times out.
591
+ */
592
+ const observeRejectedAttempt = (
593
+ call: ClassifierCall,
594
+ decision: SafetyDecision,
595
+ options?: ToolInvokeOptions,
596
+ ): string | null => {
597
+ if (!deps.middleware) return null;
598
+ const spec = tools.get(call.tool as ToolName);
599
+ if (!spec) return null;
600
+ const effects = runToolHook("before_tool", spec, call, decision, options);
601
+ return firstBlockToolEffect(effects)?.reason ?? null;
602
+ };
603
+
604
+ const guardOverrideForRejectedAttempt = (
605
+ call: ClassifierCall,
606
+ decision: SafetyDecision,
607
+ reason: string | null,
608
+ ): RegistryVerdict | null => {
609
+ if (reason === null || !isWorkerToolCallCapExceededReason(reason)) return null;
610
+ const verdict = guardBlockedVerdict(decision, call.tool, reason);
611
+ recordRegistryDisposition(call, verdict.decision, "blocked", {
612
+ reasonCode: GUARD_BLOCK_REASON_CODE,
613
+ reasons: [reason],
614
+ });
615
+ return verdict;
616
+ };
617
+
618
+ const cleanupParkedEntry = (entry: ParkedCall): void => {
619
+ entry.abortCleanup?.();
620
+ delete entry.abortCleanup;
621
+ };
622
+
623
+ const resolveParkedAsBlocked = (entry: ParkedCall, reason: string): void => {
624
+ cleanupParkedEntry(entry);
625
+ disposeAdmissionArgs(tools.get(entry.call.tool as ToolName), entry.call.args ?? {});
626
+ // A denied/cancelled park is still a model attempt: observe it so
627
+ // identical retries trip the loop detector. When the detector fires, its
628
+ // reason replaces the generic denial so the model gets recovery guidance.
629
+ const loopReason = observeRejectedAttempt(entry.call, entry.decision, entry.options);
630
+ entry.resolve(
631
+ guardOverrideForRejectedAttempt(entry.call, entry.decision, loopReason) ??
632
+ parkAnsweredBlockedVerdict(entry.decision, entry.call.tool, loopReason ?? reason),
633
+ );
634
+ };
635
+
636
+ const reparkEntry = (entry: ParkedCall, index?: number): void => {
637
+ if (index === undefined || index < 0 || index >= parked.length) {
638
+ parked.push(entry);
639
+ return;
640
+ }
641
+ parked.splice(index, 0, entry);
642
+ };
643
+
644
+ const nextApprovalRequestId = (): string => `apr-${approvalRequestToken}-${++approvalRequestCounter}`;
645
+
646
+ const notifyPermissionRequired = (
647
+ call: ClassifierCall,
648
+ decision: SafetyDecision,
649
+ meta: PermissionRequiredMeta,
650
+ ): void => {
651
+ for (const listener of permissionListeners) {
652
+ try {
653
+ listener(call, decision, meta);
654
+ } catch {
655
+ // Listener errors never abort admission; they are surfaced via
656
+ // whatever observability the caller wires up.
657
+ }
658
+ }
659
+ };
660
+
661
+ const notifyAutonomyDenied = (call: ClassifierCall, decision: SafetyDecision, level: AutonomyLevel): void => {
662
+ for (const listener of autonomyDeniedListeners) {
663
+ try {
664
+ listener(call, decision, level);
665
+ } catch {
666
+ // Same contract as permission listeners: never abort admission.
667
+ }
668
+ }
669
+ };
670
+
671
+ const cancelParkedCallById = (requestId: string, reason: string): boolean => {
672
+ const index = parked.findIndex((entry) => entry.meta.requestId === requestId);
673
+ if (index === -1) return false;
674
+ const [entry] = parked.splice(index, 1);
675
+ if (!entry) return false;
676
+ resolveParkedAsBlocked(entry, reason);
677
+ const next = parked[0];
678
+ if (next) notifyPermissionRequired(next.call, next.decision, next.meta);
679
+ return true;
680
+ };
681
+
682
+ return {
683
+ register(spec) {
684
+ tools.set(spec.name, spec);
685
+ },
686
+ listAll: () => Array.from(tools.values()),
687
+ get: (name) => tools.get(name),
688
+ listRegistered: () => Array.from(tools.keys()),
689
+ listVisible: () => Array.from(tools.values()),
690
+ async invoke(call, options) {
691
+ const admissionCall = prepareAdmissionCall(tools.get(call.tool as ToolName), call);
692
+ const outcome = admit(admissionCall, undefined, options);
693
+ if (outcome.kind === "terminal") {
694
+ disposeAdmissionArgs(tools.get(admissionCall.tool as ToolName), admissionCall.args ?? {});
695
+ return observeBlockedAttempt(admissionCall, outcome.verdict, options) ?? outcome.verdict;
696
+ }
697
+ if (outcome.kind === "execute") return runSpec(outcome.spec, admissionCall, outcome.decision, options);
698
+ const abortReason = "run aborted before the operator decided";
699
+ if (options?.signal?.aborted) {
700
+ disposeAdmissionArgs(tools.get(admissionCall.tool as ToolName), admissionCall.args ?? {});
701
+ const loopReason = observeRejectedAttempt(admissionCall, outcome.decision, options);
702
+ return { kind: "blocked", reason: loopReason ?? abortReason, decision: outcome.decision };
703
+ }
704
+ return new Promise<RegistryVerdict>((resolve) => {
705
+ const meta: PermissionRequiredMeta = {
706
+ requestId: nextApprovalRequestId(),
707
+ axis: outcome.axis,
708
+ ...(options?.toolCallId !== undefined && options.toolCallId.length > 0 ? { toolCallId: options.toolCallId } : {}),
709
+ };
710
+ recordRegistryDisposition(admissionCall, outcome.decision, "permission_requested", { requestId: meta.requestId });
711
+ // The park ends when the operator decides, not when the verdict
712
+ // resolves: an approved call runs its body inside the resume pass,
713
+ // so measuring to the resolve would fold the tool's own execution
714
+ // into the park and the caller would subtract it. A dispatch that
715
+ // fanned out for 224.8s settled as a 15ms line that way (issue #82).
716
+ // closePark seals it at the decision; settle covers every path that
717
+ // ends a park without reaching a body, including one added later,
718
+ // because they all resolve the entry through this function.
719
+ const parkedAtClock = performance.now();
720
+ let parkReported = false;
721
+ const closePark = (): void => {
722
+ if (parkReported) return;
723
+ parkReported = true;
724
+ options?.onParked?.(Math.round(performance.now() - parkedAtClock));
725
+ };
726
+ const settle = (verdict: RegistryVerdict): void => {
727
+ closePark();
728
+ resolve(verdict);
729
+ };
730
+ const parkedCall: ParkedCall = {
731
+ call: admissionCall,
732
+ decision: outcome.decision,
733
+ meta,
734
+ resolve: settle,
735
+ closePark,
736
+ };
737
+ if (options !== undefined) parkedCall.options = options;
738
+ if (options?.signal) {
739
+ const onAbort = (): void => {
740
+ cancelParkedCallById(meta.requestId, abortReason);
741
+ };
742
+ options.signal.addEventListener("abort", onAbort, { once: true });
743
+ parkedCall.abortCleanup = () => {
744
+ options.signal?.removeEventListener("abort", onAbort);
745
+ };
746
+ }
747
+ parked.push(parkedCall);
748
+ notifyPermissionRequired(admissionCall, outcome.decision, meta);
749
+ });
750
+ },
751
+ hasParkedCalls: () => parked.length > 0,
752
+ parkedCount: () => parked.length,
753
+ renotifyHead() {
754
+ const next = parked[0];
755
+ if (next) notifyPermissionRequired(next.call, next.decision, next.meta);
756
+ },
757
+ async resumeParkedCalls(grant?: OneShotGrant) {
758
+ if (parked.length === 0) return;
759
+ const pending: Array<{ entry: ParkedCall; reparkIndex?: number }> = [];
760
+ if (grant === undefined) {
761
+ pending.push(...parked.splice(0, parked.length).map((entry) => ({ entry })));
762
+ } else if (grant.requestId !== undefined) {
763
+ const index = parked.findIndex((entry) => entry.meta.requestId === grant.requestId);
764
+ if (index === -1) {
765
+ const next = parked[0];
766
+ if (next) notifyPermissionRequired(next.call, next.decision, next.meta);
767
+ return;
768
+ }
769
+ const [entry] = parked.splice(index, 1);
770
+ if (entry) pending.push({ entry, reparkIndex: index });
771
+ } else {
772
+ const [entry] = parked.splice(0, 1);
773
+ if (entry) pending.push({ entry });
774
+ }
775
+ for (const { entry, reparkIndex } of pending) {
776
+ // A one-shot grant covers only the parked call it selected. Calls
777
+ // that parked while the overlay was already open remain queued and
778
+ // need their own confirmation, so a concurrent privileged call
779
+ // cannot ride along on a grant approved for another call.
780
+ if (grant !== undefined && entry.decision.classification.actionClass !== grant.actionClass) {
781
+ reparkEntry(entry, reparkIndex);
782
+ continue;
783
+ }
784
+ const outcome = admit(entry.call, grant, entry.options);
785
+ if (outcome.kind === "park") {
786
+ reparkEntry(entry, reparkIndex);
787
+ continue;
788
+ }
789
+ cleanupParkedEntry(entry);
790
+ if (outcome.kind === "terminal") {
791
+ disposeAdmissionArgs(tools.get(entry.call.tool as ToolName), entry.call.args ?? {});
792
+ entry.resolve(observeBlockedAttempt(entry.call, outcome.verdict, entry.options) ?? outcome.verdict);
793
+ continue;
794
+ }
795
+ const approvedOptions: ToolInvokeOptions | undefined =
796
+ grant === undefined
797
+ ? entry.options
798
+ : {
799
+ ...(entry.options ?? {}),
800
+ approval: {
801
+ requestId: entry.meta.requestId,
802
+ requestedBy: grant.requestedBy,
803
+ actionClass: grant.actionClass,
804
+ },
805
+ };
806
+ // Seal the park before the body runs. Everything after this line is
807
+ // the tool working, and the caller charges that to the tool.
808
+ entry.closePark();
809
+ entry.resolve(await runSpec(outcome.spec, entry.call, outcome.decision, approvedOptions));
810
+ }
811
+ const next = parked[0];
812
+ if (next) notifyPermissionRequired(next.call, next.decision, next.meta);
813
+ },
814
+ cancelParkedCall(requestId, reason) {
815
+ return cancelParkedCallById(requestId, reason);
816
+ },
817
+ cancelParkedCalls(reason) {
818
+ if (parked.length === 0) return;
819
+ const pending = parked.splice(0, parked.length);
820
+ for (const entry of pending) {
821
+ resolveParkedAsBlocked(entry, reason);
822
+ }
823
+ },
824
+ onPermissionRequired(listener) {
825
+ permissionListeners.add(listener);
826
+ return () => {
827
+ permissionListeners.delete(listener);
828
+ };
829
+ },
830
+ onAutonomyDenied(listener) {
831
+ autonomyDeniedListeners.add(listener);
832
+ return () => {
833
+ autonomyDeniedListeners.delete(listener);
834
+ };
835
+ },
836
+ };
837
+ }
838
+
839
+ /**
840
+ * Run a tool's optional `prepareArguments` normalizer before its body. A
841
+ * throwing or non-object result is discarded so a buggy normalizer can never
842
+ * abort admission; the raw args pass through unchanged.
843
+ */
844
+ function prepareToolArgs(spec: ToolSpec, args: Record<string, unknown>): Record<string, unknown> {
845
+ if (!spec.prepareArguments) return args;
846
+ try {
847
+ const prepared = spec.prepareArguments(args);
848
+ return prepared !== null && typeof prepared === "object" && !Array.isArray(prepared) ? prepared : args;
849
+ } catch {
850
+ return args;
851
+ }
852
+ }
853
+
854
+ function disposeAdmissionArgs(spec: ToolSpec | undefined, args: Record<string, unknown>): void {
855
+ try {
856
+ spec?.disposeAdmissionArguments?.(args);
857
+ } catch {
858
+ // Cleanup is best-effort here; durable reservation expiry is the backstop.
859
+ }
860
+ }
861
+
862
+ function prepareAdmissionCall(spec: ToolSpec | undefined, call: ClassifierCall): ClassifierCall {
863
+ if (!spec?.prepareAdmissionArguments) return call;
864
+ try {
865
+ const prepared = spec.prepareAdmissionArguments(call.args ?? {});
866
+ if (prepared === null || typeof prepared !== "object" || Array.isArray(prepared)) return call;
867
+ return { ...call, args: prepared };
868
+ } catch {
869
+ return call;
870
+ }
871
+ }
872
+
873
+ function applyRegisteredToolClassification(decision: SafetyDecision, spec: ToolSpec): SafetyDecision {
874
+ if (decision.classification.actionClass !== "unknown") return decision;
875
+ const classification = {
876
+ actionClass: spec.baseActionClass,
877
+ reasons: [`registered tool: ${spec.name}`],
878
+ };
879
+ return decision.kind === "allow" ? { kind: "allow", classification } : { ...decision, classification };
880
+ }
881
+
882
+ /** Final reason code for a before_tool guard block, matching the audit convention (sd-01 §2.5). */
883
+ const GUARD_BLOCK_REASON_CODE = "guard_block";
884
+
885
+ /**
886
+ * Terminal blocked verdict for a before_tool guard block (loop guard,
887
+ * protected artifacts, dispatch dedup, declarative block rules) on a call
888
+ * whose admission already passed. The decision is re-shaped as a block, and
889
+ * the carried policy's net-pass reasonCode is replaced with the guard axis,
890
+ * so downstream consumers (worker finish events, dispatch receipts, audit)
891
+ * count a blocked safety decision instead of repeating the admission's allow.
892
+ */
893
+ function guardBlockedVerdict(
894
+ decision: SafetyDecision,
895
+ tool: string,
896
+ reason: string,
897
+ ): Extract<RegistryVerdict, { kind: "blocked" }> {
898
+ const blocked: SafetyDecision = {
899
+ kind: "block",
900
+ classification: decision.classification,
901
+ rejection: {
902
+ short: `${tool} blocked: tool guard`,
903
+ detail: reason,
904
+ hints: [],
905
+ },
906
+ ...(decision.policy !== undefined ? { policy: { ...decision.policy, reasonCode: GUARD_BLOCK_REASON_CODE } } : {}),
907
+ };
908
+ return { kind: "blocked", reason, decision: blocked };
909
+ }
910
+
911
+ /**
912
+ * Longest guidance sentence carried into a headless denial. The model-facing
913
+ * composer caps a line at 300 characters and interpolates policy text verbatim,
914
+ * so bound it here too and leave room for the elision marker.
915
+ */
916
+ const HEADLESS_GUIDANCE_MAX_CHARS = 240;
917
+
918
+ /**
919
+ * The recovery guidance a headless denial should repeat, or null when the
920
+ * parked decision has none.
921
+ *
922
+ * A headless run answers every ask with one sentence: nobody can confirm, rerun
923
+ * interactively. That says nothing about what would have run, so a headless
924
+ * model that hits an unrecognized-bash rail retries the same shape until the run
925
+ * ends. An unrecognized execution decision carries the working form in its
926
+ * reasons, and those reasons reach the audit record and the interactive approval
927
+ * overlay but not the model. The first reason states the axis the denial already
928
+ * implies, so only the reasons after it are candidates, and only the first of
929
+ * those, bounded: this is a nudge toward the recognized spelling, not a dump of
930
+ * the policy's reason list.
931
+ */
932
+ function headlessDenialGuidance(decision: SafetyDecision, reason: string): string | null {
933
+ // Interactive denials are left exactly as they were: the operator saw the
934
+ // reasons in the approval overlay before answering.
935
+ if (!reason.startsWith(HEADLESS_PERMISSION_DENIED_MARKER)) return null;
936
+ const policy = decision.policy;
937
+ if (policy?.execRecognition !== "unrecognized") return null;
938
+ const guidance = policy.reasons.slice(1).find((entry) => entry.trim().length > 0);
939
+ if (guidance === undefined) return null;
940
+ const trimmed = guidance.trim();
941
+ return trimmed.length > HEADLESS_GUIDANCE_MAX_CHARS ? `${trimmed.slice(0, HEADLESS_GUIDANCE_MAX_CHARS)}…` : trimmed;
942
+ }
943
+
944
+ /**
945
+ * Terminal blocked verdict for a parked call that has been answered: denied at
946
+ * the confirmation prompt, cancelled with the turn, or settled by an abort.
947
+ *
948
+ * The ask decision's rejection explains that the call *is* parked and what
949
+ * approving it would do. Once the answer is in, that text is stale, and
950
+ * `formatModelRejection` printed it as a second paragraph restating a denial the
951
+ * reason had already stated, followed by four approval hints for an approval
952
+ * that is not coming. The answer is the whole message; the composer still closes
953
+ * it with the standing pivot instruction.
954
+ *
955
+ * A headless answer is the exception: nobody will ever approve it, so the detail
956
+ * carries one line of recovery guidance after the denial sentence. The sentence
957
+ * stays the detail's prefix, which the skill-eval permission-wall recognizer
958
+ * depends on.
959
+ */
960
+ function parkAnsweredBlockedVerdict(
961
+ decision: SafetyDecision,
962
+ tool: string,
963
+ reason: string,
964
+ ): Extract<RegistryVerdict, { kind: "blocked" }> {
965
+ const guidance = headlessDenialGuidance(decision, reason);
966
+ const blocked: SafetyDecision = {
967
+ kind: "block",
968
+ classification: decision.classification,
969
+ rejection: {
970
+ short: `${tool} blocked: ${decision.classification.actionClass} was not approved`,
971
+ detail: guidance === null ? reason : `${reason}\n${guidance}`,
972
+ hints: [],
973
+ },
974
+ ...(decision.policy !== undefined ? { policy: decision.policy } : {}),
975
+ };
976
+ return { kind: "blocked", reason, decision: blocked };
977
+ }
978
+
979
+ /**
980
+ * Terminal blocked verdict for a call outside the merged tool surface the
981
+ * loaded skills declared. The reason carries the remediation, since blocked
982
+ * reasons are what the model reads; context and ask_user stay exempt at
983
+ * the evaluator so the message can honestly point at ask_user.
984
+ */
985
+ function skillSurfaceBlockedVerdict(
986
+ decision: SafetyDecision,
987
+ tool: string,
988
+ violation: SkillToolSurfaceViolation,
989
+ ): Extract<RegistryVerdict, { kind: "blocked" }> {
990
+ const reason =
991
+ violation.disallowedBy.length > 0
992
+ ? `${tool} is disallowed by the active skill(s) ${violation.disallowedBy.join(", ")} (disallowed-tools). The narrowing ends when the skill policy's turn or worker run ends. Work within the skill workflow; if it genuinely needs this step, use ask_user when available or state the blocker in your reply.`
993
+ : `${tool} is outside the tool surface declared by the active skill(s) ${violation.skills.join(", ")}. Tools are narrowed to: ${(violation.mergedAllowedTools ?? []).join(", ")} (plus context and ask_user). The narrowing ends when the skill policy's turn or worker run ends. Work within the skill workflow; if it genuinely needs this step, use ask_user when available or state the blocker in your reply.`;
994
+ const blocked: SafetyDecision = {
995
+ kind: "block",
996
+ classification: decision.classification,
997
+ rejection: {
998
+ short: `${tool} blocked: outside active skill tool surface`,
999
+ detail: reason,
1000
+ hints: ["Skill narrowing never grants tools; it only blocks calls outside the declared workflow surface."],
1001
+ },
1002
+ ...(decision.policy !== undefined ? { policy: decision.policy } : {}),
1003
+ };
1004
+ return { kind: "blocked", reason, decision: blocked };
1005
+ }
1006
+
1007
+ /**
1008
+ * Terminal blocked verdict for an autonomy `deny` disposition (read-only).
1009
+ * The decision is re-shaped as a block so downstream consumers (worker
1010
+ * events, dispatch receipts) report it as a denial, not a pending ask.
1011
+ */
1012
+ function autonomyDenyVerdict(
1013
+ decision: SafetyDecision,
1014
+ level: AutonomyLevel,
1015
+ tool: string,
1016
+ actionClass: ActionClass,
1017
+ ): Extract<RegistryVerdict, { kind: "blocked" }> {
1018
+ const rejection = autonomyDenyRejection(level, tool, actionClass);
1019
+ const blocked: SafetyDecision = {
1020
+ kind: "block",
1021
+ classification: decision.classification,
1022
+ rejection,
1023
+ ...(decision.policy !== undefined ? { policy: decision.policy } : {}),
1024
+ };
1025
+ return { kind: "blocked", reason: rejection.short, decision: blocked };
1026
+ }
1027
+
1028
+ /**
1029
+ * Park-shaped decision for an autonomy `ask` disposition. The engine passed
1030
+ * the call, so the rejection names the level as the asking axis; overlays and
1031
+ * non-interactive deniers read it from here. An outward-exposure park names
1032
+ * the tier instead of the action class, because the class is not why it asked.
1033
+ */
1034
+ function toAutonomyAskDecision(
1035
+ decision: SafetyDecision,
1036
+ level: AutonomyLevel,
1037
+ tool: string,
1038
+ actionClass: ActionClass,
1039
+ exposure: AutonomyExposure = DEFAULT_AUTONOMY_EXPOSURE,
1040
+ ): SafetyDecision {
1041
+ return {
1042
+ kind: "ask",
1043
+ classification: decision.classification,
1044
+ rejection: autonomyAskRejection(level, tool, actionClass, exposure),
1045
+ ...(decision.policy !== undefined ? { policy: decision.policy } : {}),
1046
+ };
1047
+ }
1048
+
1049
+ /**
1050
+ * Plan-approval ask for a plan-scale dispatch call. The rejection detail IS
1051
+ * the plan artifact (topology, per-task agent/model/node), so the approval
1052
+ * overlay shows the operator exactly what one approval will launch.
1053
+ */
1054
+ function toDispatchPlanAskDecision(
1055
+ decision: SafetyDecision,
1056
+ level: AutonomyLevel,
1057
+ plan: DispatchPlanView,
1058
+ ): SafetyDecision {
1059
+ return {
1060
+ kind: "ask",
1061
+ classification: decision.classification,
1062
+ rejection: {
1063
+ short: `dispatch plan needs approval (${plan.topology}, ${plan.taskCount} task(s)) at autonomy ${level}`,
1064
+ detail: `Approving this call approves the whole plan:\n${plan.text}`,
1065
+ hints: [
1066
+ "One approval covers every run in the plan, including remote placements.",
1067
+ "Deny to keep the fleet idle and revise the plan first.",
1068
+ ],
1069
+ },
1070
+ ...(decision.policy !== undefined ? { policy: decision.policy } : {}),
1071
+ };
1072
+ }
1073
+
1074
+ function buildToolHookInput(
1075
+ hook: "before_tool" | "after_tool",
1076
+ spec: ToolSpec,
1077
+ call: ClassifierCall,
1078
+ decision: SafetyDecision,
1079
+ posture: string,
1080
+ options: ToolInvokeOptions | undefined,
1081
+ result: ToolResult | undefined,
1082
+ ): MiddlewareHookInput {
1083
+ const metadata: Record<string, MiddlewareMetadataValue> = {
1084
+ posture,
1085
+ actionClass: decision.classification.actionClass,
1086
+ decisionKind: decision.kind,
1087
+ };
1088
+ // Stable call identity for repetition detectors (engine/loop-guard.ts).
1089
+ // Computed for before_tool only; after_tool consumers identify the call
1090
+ // via toolCallId.
1091
+ if (hook === "before_tool") metadata.callFingerprint = hashToolCall(spec.name, call.args ?? {});
1092
+ const validationCommand = detectedValidationCommand(call);
1093
+ if (validationCommand !== null) {
1094
+ metadata.validationCommand = validationCommand;
1095
+ if (result?.kind === "ok") metadata.validationExitCode = 0;
1096
+ }
1097
+ if (call.tool !== spec.name) metadata.requestedToolName = call.tool;
1098
+ if (result !== undefined) {
1099
+ metadata.resultKind = result.kind;
1100
+ if (result.kind === "error") metadata.errorMessage = result.message;
1101
+ if (result.kind === "ok" && result.terminate === true) metadata.terminate = true;
1102
+ // Result identity for the stagnation detector (engine/loop-guard.ts):
1103
+ // consecutive same-shape calls whose outputs hash identically are not
1104
+ // producing new information, whatever their size arguments say.
1105
+ if (result.kind === "ok" && typeof result.output === "string") {
1106
+ metadata.resultFingerprint = createHash("sha256").update(result.output).digest("hex");
1107
+ metadata.resultBytes = Buffer.byteLength(result.output, "utf8");
1108
+ }
1109
+ }
1110
+
1111
+ const input: MiddlewareHookInput = {
1112
+ hook,
1113
+ toolName: spec.name,
1114
+ metadata,
1115
+ };
1116
+ if (call.args !== undefined) input.toolArgs = call.args;
1117
+ if (result?.details !== undefined) input.toolResultDetails = result.details;
1118
+ if (options?.runId !== undefined) input.runId = options.runId;
1119
+ if (options?.sessionId !== undefined) input.sessionId = options.sessionId;
1120
+ if (options?.turnId !== undefined) input.turnId = options.turnId;
1121
+ if (options?.toolCallId !== undefined) input.toolCallId = options.toolCallId;
1122
+ if (options?.correlationId !== undefined) input.correlationId = options.correlationId;
1123
+ return input;
1124
+ }
1125
+
1126
+ function commandArg(args: Record<string, unknown> | undefined): string | null {
1127
+ if (!args) return null;
1128
+ return typeof args.command === "string" && args.command.length > 0 ? args.command : null;
1129
+ }
1130
+
1131
+ function detectedValidationCommand(call: ClassifierCall): string | null {
1132
+ if (call.tool !== ToolNames.Bash) return null;
1133
+ const command = commandArg(call.args);
1134
+ if (command === null) return null;
1135
+ const detected = detectValidationCommand(command);
1136
+ return detected.kind === "validation" ? detected.matched : null;
1137
+ }
1138
+
1139
+ function firstBlockToolEffect(
1140
+ effects: ReadonlyArray<MiddlewareEffect>,
1141
+ ): Extract<MiddlewareEffect, { kind: "block_tool" }> | null {
1142
+ for (const effect of effects) {
1143
+ if (effect.kind === "block_tool") return effect;
1144
+ }
1145
+ return null;
1146
+ }
1147
+
1148
+ function applyToolResultEffects(result: ToolResult, effects: ReadonlyArray<MiddlewareEffect>): ToolResult {
1149
+ const annotations = annotationMessages(effects);
1150
+ if (annotations.length === 0) return result;
1151
+ const suffix = `\n\n${annotations.join("\n")}`;
1152
+ if (result.kind === "ok") {
1153
+ const annotated: ToolResult = { kind: "ok", output: `${result.output}${suffix}` };
1154
+ if (result.details !== undefined) annotated.details = result.details;
1155
+ if (result.terminate === true) annotated.terminate = true;
1156
+ return annotated;
1157
+ }
1158
+ return { kind: "error", message: `${result.message}${suffix}` };
1159
+ }
1160
+
1161
+ function annotationMessages(effects: ReadonlyArray<MiddlewareEffect>): string[] {
1162
+ const messages: string[] = [];
1163
+ for (const effect of effects) {
1164
+ if (effect.kind !== "annotate_tool_result") continue;
1165
+ const severity = effect.severity ?? "info";
1166
+ messages.push(`[middleware:${severity}] ${effect.message}`);
1167
+ }
1168
+ return messages;
1169
+ }