@iowarp/clio-coder 0.4.9 → 0.5.0

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 (1172) hide show
  1. package/.claude-plugin/marketplace.json +11 -3
  2. package/CHANGELOG.md +153 -0
  3. package/CODE_OF_CONDUCT.md +10 -0
  4. package/CONTRIBUTING.md +208 -382
  5. package/NOTICE +8 -2
  6. package/README.md +199 -418
  7. package/ROADMAP.md +82 -0
  8. package/SECURITY.md +14 -11
  9. package/dist/acp-KS7ARGV6.js +132 -0
  10. package/dist/agents-YOGJ2YEJ.js +163 -0
  11. package/dist/assets/codewiki.json +1 -1
  12. package/dist/auth-CEDCO6O6.js +557 -0
  13. package/dist/background-YWTBPSQU.js +39 -0
  14. package/dist/builtins-GDYO4RTR.js +23 -0
  15. package/dist/chunk-27YTM2CV.js +175 -0
  16. package/dist/chunk-2AF6YC7Q.js +75 -0
  17. package/dist/chunk-2DTIWSAW.js +381 -0
  18. package/dist/chunk-2EMLKSCX.js +262 -0
  19. package/dist/chunk-2OJ3YZQP.js +665 -0
  20. package/dist/chunk-2VLYHHFT.js +35 -0
  21. package/dist/chunk-2WVPJF3Z.js +204 -0
  22. package/dist/chunk-33OASOS6.js +176 -0
  23. package/dist/chunk-3BD2LXYJ.js +19 -0
  24. package/dist/chunk-3JHUFKG7.js +30 -0
  25. package/dist/chunk-3JLTRPN7.js +711 -0
  26. package/dist/chunk-3LT34CAM.js +2796 -0
  27. package/dist/chunk-3O5JWP4L.js +1670 -0
  28. package/dist/chunk-3UW3KU4A.js +21 -0
  29. package/dist/chunk-4A6YRGV4.js +569 -0
  30. package/dist/chunk-4D2BRCZ3.js +67 -0
  31. package/dist/chunk-4SYHGVDE.js +668 -0
  32. package/dist/chunk-4VDHLCF5.js +66 -0
  33. package/dist/chunk-4WOOTKFD.js +637 -0
  34. package/dist/chunk-4WV4PI66.js +80 -0
  35. package/dist/chunk-53OXPRI6.js +195 -0
  36. package/dist/chunk-55RMDDFM.js +1347 -0
  37. package/dist/chunk-56XP4FJU.js +2025 -0
  38. package/dist/chunk-5B3RTYAK.js +123 -0
  39. package/dist/chunk-5CD243WE.js +45 -0
  40. package/dist/chunk-5JQR5B4D.js +709 -0
  41. package/dist/chunk-5KQEUIWM.js +597 -0
  42. package/dist/chunk-5LP5FNNR.js +915 -0
  43. package/dist/chunk-62UK7AGW.js +9344 -0
  44. package/dist/chunk-6CTHLZFB.js +563 -0
  45. package/dist/chunk-6EJYVCTN.js +23 -0
  46. package/dist/chunk-6OWUM2NC.js +12289 -0
  47. package/dist/chunk-6RJMYYIE.js +1023 -0
  48. package/dist/chunk-6W75D37F.js +643 -0
  49. package/dist/chunk-733ZBT5P.js +1721 -0
  50. package/dist/chunk-77DCC6JZ.js +3710 -0
  51. package/dist/chunk-7QXCO3AF.js +156 -0
  52. package/dist/chunk-7RET77VB.js +481 -0
  53. package/dist/chunk-A4MVRV4C.js +65 -0
  54. package/dist/chunk-ALJWT6O6.js +93 -0
  55. package/dist/chunk-AVSR2HKI.js +232 -0
  56. package/dist/chunk-B7GY6QER.js +42 -0
  57. package/dist/chunk-BFOSV5EZ.js +178 -0
  58. package/dist/chunk-BGOIM7NB.js +103 -0
  59. package/dist/chunk-BJH6WFIB.js +372 -0
  60. package/dist/chunk-BOBCCDJ6.js +1533 -0
  61. package/dist/chunk-BRCOSE7O.js +117 -0
  62. package/dist/chunk-BYFHHCFV.js +601 -0
  63. package/dist/chunk-C2CPOIH2.js +83 -0
  64. package/dist/chunk-C7AQTPCE.js +694 -0
  65. package/dist/chunk-CBAQPTDU.js +165 -0
  66. package/dist/chunk-CDQ2UC6W.js +125 -0
  67. package/dist/chunk-CN6SW5DC.js +177 -0
  68. package/dist/chunk-CRHPCPZP.js +132 -0
  69. package/dist/chunk-CTFPFW3H.js +44 -0
  70. package/dist/chunk-D3KWFOUT.js +103 -0
  71. package/dist/chunk-D65E25JG.js +185 -0
  72. package/dist/chunk-DCGHJQ2U.js +236 -0
  73. package/dist/chunk-DE2LU267.js +106 -0
  74. package/dist/chunk-DF6PI6GN.js +97 -0
  75. package/dist/chunk-DGC6X6XR.js +53 -0
  76. package/dist/chunk-DOUISWEE.js +526 -0
  77. package/dist/chunk-DR3TAEUA.js +188 -0
  78. package/dist/chunk-DVTBERFY.js +33 -0
  79. package/dist/chunk-DXSETN72.js +1051 -0
  80. package/dist/chunk-DZLR4UEH.js +128 -0
  81. package/dist/chunk-E6IPKW2E.js +77 -0
  82. package/dist/chunk-EG4ARXPC.js +139 -0
  83. package/dist/chunk-EKV4UBCM.js +652 -0
  84. package/dist/chunk-EOJPDNUP.js +1325 -0
  85. package/dist/chunk-EX57VVWW.js +4157 -0
  86. package/dist/chunk-EYTLV3W3.js +5937 -0
  87. package/dist/chunk-EZD2BXGP.js +475 -0
  88. package/dist/chunk-EZDCA34W.js +314 -0
  89. package/dist/chunk-FD2I4KBR.js +33 -0
  90. package/dist/chunk-FD3IAHQM.js +27 -0
  91. package/dist/chunk-FFYTC2KQ.js +416 -0
  92. package/dist/chunk-FGSQHUCK.js +110 -0
  93. package/dist/chunk-GCQFN7YI.js +32 -0
  94. package/dist/chunk-GGPF6LLE.js +38 -0
  95. package/dist/chunk-GGWI3OVM.js +215 -0
  96. package/dist/chunk-GLIQT7SU.js +172 -0
  97. package/dist/chunk-GN7QBEEI.js +95 -0
  98. package/dist/chunk-GRHOXDKB.js +1104 -0
  99. package/dist/chunk-HMN2C6YL.js +54 -0
  100. package/dist/chunk-HOEDA42N.js +310 -0
  101. package/dist/chunk-HOYZUKG7.js +192 -0
  102. package/dist/chunk-HQVN7G4F.js +1021 -0
  103. package/dist/chunk-HSQQFDB3.js +519 -0
  104. package/dist/chunk-I4ELN5BX.js +47 -0
  105. package/dist/chunk-I4Y4WKZR.js +386 -0
  106. package/dist/chunk-IFPDAD7R.js +797 -0
  107. package/dist/chunk-IN7DGBVS.js +582 -0
  108. package/dist/chunk-ISHUS7HC.js +396 -0
  109. package/dist/chunk-JPXLJSGR.js +191 -0
  110. package/dist/chunk-JQCLXSFI.js +69 -0
  111. package/dist/chunk-KBUTSJSR.js +61 -0
  112. package/dist/chunk-KW5HXKLJ.js +56 -0
  113. package/dist/chunk-L4APUGCT.js +139 -0
  114. package/dist/chunk-L7G7K4I2.js +505 -0
  115. package/dist/chunk-LAR7DX5E.js +1840 -0
  116. package/dist/chunk-LAVUQX3B.js +462 -0
  117. package/dist/chunk-LJRBX7QR.js +116 -0
  118. package/dist/chunk-LNOXCGN2.js +1864 -0
  119. package/dist/chunk-LTWH2ACR.js +23002 -0
  120. package/dist/chunk-LYJJ6546.js +661 -0
  121. package/dist/chunk-M2IPMWCN.js +457 -0
  122. package/dist/chunk-MGLRTOCK.js +101 -0
  123. package/dist/chunk-MZF5IKZT.js +160 -0
  124. package/dist/chunk-N24R6KWS.js +386 -0
  125. package/dist/chunk-NASYVWDB.js +604 -0
  126. package/dist/chunk-NBXFPI7U.js +195 -0
  127. package/dist/chunk-NDPF2N2L.js +400 -0
  128. package/dist/chunk-NFSK2VNU.js +446 -0
  129. package/dist/chunk-NG3QQSXY.js +43 -0
  130. package/dist/chunk-NOCSM22Y.js +63 -0
  131. package/dist/chunk-NVPXXW2H.js +1143 -0
  132. package/dist/chunk-O63U2I6I.js +30 -0
  133. package/dist/chunk-OJXOA6YU.js +98 -0
  134. package/dist/chunk-OPD7GL6F.js +1196 -0
  135. package/dist/chunk-OQ2EOAHA.js +14399 -0
  136. package/dist/chunk-OV62D6KO.js +688 -0
  137. package/dist/chunk-OZ76TLGU.js +740 -0
  138. package/dist/chunk-P4GNZPXO.js +1156 -0
  139. package/dist/chunk-PS6JAWJZ.js +78 -0
  140. package/dist/chunk-PXRCXGLK.js +1865 -0
  141. package/dist/chunk-QDUUOZ3S.js +108 -0
  142. package/dist/chunk-QG6I2T5E.js +1416 -0
  143. package/dist/chunk-QHSBROEW.js +308 -0
  144. package/dist/chunk-QNUQ7K7D.js +46 -0
  145. package/dist/chunk-QZTTRSJE.js +333 -0
  146. package/dist/chunk-R2UUNSNQ.js +1605 -0
  147. package/dist/chunk-R7FGRZNF.js +1794 -0
  148. package/dist/chunk-RNDCROSG.js +199 -0
  149. package/dist/chunk-S36CXHO2.js +302 -0
  150. package/dist/chunk-SJGS3GDI.js +575 -0
  151. package/dist/chunk-SQZHXUB3.js +510 -0
  152. package/dist/chunk-SUTLW6ND.js +686 -0
  153. package/dist/chunk-SYF7FVBL.js +179 -0
  154. package/dist/chunk-T2MDZES3.js +1577 -0
  155. package/dist/chunk-T33IYTZM.js +1146 -0
  156. package/dist/chunk-TDGYTWM6.js +49 -0
  157. package/dist/chunk-TGL5FZVD.js +132 -0
  158. package/dist/chunk-TGWZXJ7L.js +1205 -0
  159. package/dist/chunk-TKDRT2DF.js +114 -0
  160. package/dist/chunk-TV2EBCSQ.js +152 -0
  161. package/dist/chunk-U26XXPJS.js +367 -0
  162. package/dist/chunk-U5QU5ZOD.js +419 -0
  163. package/dist/chunk-U6YTUVOX.js +1011 -0
  164. package/dist/chunk-UCINIRHW.js +188 -0
  165. package/dist/chunk-UJD5MPP6.js +52 -0
  166. package/dist/chunk-URCXX7WJ.js +146 -0
  167. package/dist/chunk-UX2L5CUD.js +898 -0
  168. package/dist/chunk-UZVYEF57.js +114 -0
  169. package/dist/chunk-V35KZDUZ.js +218 -0
  170. package/dist/chunk-VESL6DQY.js +1058 -0
  171. package/dist/chunk-VKHLUZNO.js +986 -0
  172. package/dist/chunk-VOYUCAQF.js +584 -0
  173. package/dist/chunk-VYRQHORQ.js +414 -0
  174. package/dist/chunk-W53XSRQE.js +245 -0
  175. package/dist/chunk-X4CEFOSG.js +226 -0
  176. package/dist/chunk-XDHUDE5K.js +380 -0
  177. package/dist/chunk-XISLDHEL.js +1290 -0
  178. package/dist/chunk-XM34YQ2Y.js +169 -0
  179. package/dist/chunk-XMDBTYCH.js +661 -0
  180. package/dist/chunk-XS2QPZJE.js +449 -0
  181. package/dist/chunk-YBUECLAF.js +618 -0
  182. package/dist/chunk-YQ6XEFVK.js +332 -0
  183. package/dist/chunk-YYLCPDCC.js +990 -0
  184. package/dist/chunk-Z4GLJ6J4.js +1035 -0
  185. package/dist/chunk-ZARZ4POR.js +210 -0
  186. package/dist/chunk-ZJPORZTC.js +119 -0
  187. package/dist/chunk-ZNUZ3EXD.js +243 -0
  188. package/dist/chunk-ZPST2KQO.js +49 -0
  189. package/dist/chunk-ZR5YA6ZF.js +512 -0
  190. package/dist/chunk-ZU4JPCPR.js +319 -0
  191. package/dist/chunk-ZUKUCZYZ.js +39 -0
  192. package/dist/cli/index.js +56 -45
  193. package/dist/clio-K2PBVCEM.js +27 -0
  194. package/dist/clio-context-tools-GR4OHFSO.js +145 -0
  195. package/dist/code-nav-4X3OI6DK.js +715 -0
  196. package/dist/codewiki/build-worker.js +4 -4
  197. package/dist/compile-cache-YRB6QRO7.js +18 -0
  198. package/dist/components-RQOJ6NUR.js +675 -0
  199. package/dist/config-Q5J7UBAB.js +291 -0
  200. package/dist/config-XE7XYZLU.js +38 -0
  201. package/dist/config-graph-P3555574.js +175 -0
  202. package/dist/configure-KIJ32ZO6.js +104 -0
  203. package/dist/context-LFBQOSXT.js +344 -0
  204. package/dist/context-NNLBES2Y.js +82 -0
  205. package/dist/context-WBH3KSVR.js +302 -0
  206. package/dist/context-clear-YOHMQ6SQ.js +208 -0
  207. package/dist/context-index-X2N5UAIF.js +120 -0
  208. package/dist/context-map-HOSMGUG2.js +555 -0
  209. package/dist/context-working-set-MRAEVDNV.js +1564 -0
  210. package/dist/data-tool-JJPBGMQJ.js +2986 -0
  211. package/dist/detail-RHJOTGN4.js +139 -0
  212. package/dist/dispatch-runner-NC7PYNIO.js +2477 -0
  213. package/dist/docs-K4GBWRUX.js +342 -0
  214. package/dist/doctor-S5KZ2GTN.js +1138 -0
  215. package/dist/doctor-deep-2EJQSHIZ.js +130 -0
  216. package/dist/domain-loader-MB34FDPD.js +13 -0
  217. package/dist/eval-3D6M36N7.js +5220 -0
  218. package/dist/eval-inventory-SM3HNM47.js +260 -0
  219. package/dist/evals-FO6JEUCN.js +104 -0
  220. package/dist/evidence-6IYN52ET.js +262 -0
  221. package/dist/evidence-JVECPI3F.js +250 -0
  222. package/dist/evidence-XNVPPLVK.js +410 -0
  223. package/dist/evolve-TLPUDJDM.js +634 -0
  224. package/dist/extensions-ROZJ5X3J.js +311 -0
  225. package/dist/fleet-6RJWIOEO.js +284 -0
  226. package/dist/fleet-WKVBF5SZ.js +942 -0
  227. package/dist/fleet-commands-L6WFT7KZ.js +76 -0
  228. package/dist/fleet-decisions-BTQMWU5A.js +55 -0
  229. package/dist/fleet-graph-553DZ67Q.js +141 -0
  230. package/dist/fleet-inspect-236FZPRB.js +329 -0
  231. package/dist/fleet-new-CKUXP3CO.js +48 -0
  232. package/dist/fleet-preflight-NZQHABWO.js +95 -0
  233. package/dist/fleet-validate-7NLAE26R.js +96 -0
  234. package/dist/fleet-verify-E3RO6A5W.js +226 -0
  235. package/dist/fleet-view-KMZQY7YJ.js +144 -0
  236. package/dist/gui/client/assets/abnfDiagram-VCTEODGH-DPBWQwNn.js +1 -0
  237. package/dist/gui/client/assets/architecture-7GRP2DOG-D1w8FrFW.js +1 -0
  238. package/dist/gui/client/assets/architectureDiagram-5GKGNRK7-CVPgKd1-.js +36 -0
  239. package/dist/gui/client/assets/blockDiagram-I7D4REHJ-BLmnqkK5.js +129 -0
  240. package/dist/gui/client/assets/c4Diagram-7LVT6UL2-4AU9cfM7.js +38 -0
  241. package/dist/gui/client/assets/channel-DwFZ0m8S.js +1 -0
  242. package/dist/gui/client/assets/chunk-4HAMMTFA-EOWkKCav.js +62 -0
  243. package/dist/gui/client/assets/chunk-75Z2AOVW-CygeoIMl.js +2 -0
  244. package/dist/gui/client/assets/chunk-DU6HZSFF-s27fViLb.js +125 -0
  245. package/dist/gui/client/assets/chunk-F27PBJKO-BrHvwLsZ.js +1 -0
  246. package/dist/gui/client/assets/chunk-GMAD6QVW-DzPh-7jt.js +72 -0
  247. package/dist/gui/client/assets/chunk-GVQU2GXP-pIaQkIzm.js +1 -0
  248. package/dist/gui/client/assets/chunk-IMKFNOWR-BGJVE_Br.js +231 -0
  249. package/dist/gui/client/assets/chunk-L3NEJ4N5-B3YLuhww.js +1 -0
  250. package/dist/gui/client/assets/chunk-OSK3NFVY-BRj61HHU.js +10 -0
  251. package/dist/gui/client/assets/chunk-P2QGCYS3-Sno90KxP.js +1 -0
  252. package/dist/gui/client/assets/chunk-POPQ4Y6H-Cw8NTbxr.js +1 -0
  253. package/dist/gui/client/assets/chunk-PWAF6VOD-BIhHgz37.js +1 -0
  254. package/dist/gui/client/assets/chunk-SHT3W25Y-Cqv7npBj.js +168 -0
  255. package/dist/gui/client/assets/chunk-SVP7TREG-Hxzl6Dee.js +88 -0
  256. package/dist/gui/client/assets/chunk-TICWLB2K-CIFVyVP2.js +206 -0
  257. package/dist/gui/client/assets/classDiagram-ZZMXUADV-BJbAiI_w.js +1 -0
  258. package/dist/gui/client/assets/classDiagram-v2-VYDZK3BY-BJbAiI_w.js +1 -0
  259. package/dist/gui/client/assets/cynefin-OW5HDTMX-DecLWZ-y.js +1 -0
  260. package/dist/gui/client/assets/cynefinDiagram-5FMLGOSQ-CK-T2N-D.js +62 -0
  261. package/dist/gui/client/assets/dagre-GXQ25YYZ-C0dfg-OS.js +4 -0
  262. package/dist/gui/client/assets/diagram-S7CK7UJ4-EaJukVh-.js +30 -0
  263. package/dist/gui/client/assets/diagram-UQ7AKVKN-xcOucEtP.js +41 -0
  264. package/dist/gui/client/assets/diagram-VSXAHHWV-3AUJACMf.js +3 -0
  265. package/dist/gui/client/assets/diagram-VX7I27RA-TPknLqam.js +24 -0
  266. package/dist/gui/client/assets/diagram-Z3DM3KII-wa1q3YMF.js +24 -0
  267. package/dist/gui/client/assets/ebnfDiagram-PWID7BFC-JBCF2-s7.js +1 -0
  268. package/dist/gui/client/assets/erDiagram-RLTQ6QDP-CmXjXPc4.js +99 -0
  269. package/dist/gui/client/assets/eventmodeling-NTZA5JFV-D_1aJWYl.js +1 -0
  270. package/dist/gui/client/assets/flowDiagram-HODETNUW-BQtZlael.js +1 -0
  271. package/dist/gui/client/assets/framework-Bq-znqwW.js +9 -0
  272. package/dist/gui/client/assets/ganttDiagram-EL5Y4UJY-IPaL_kaa.js +292 -0
  273. package/dist/gui/client/assets/gitGraph-4MIJSDKK-Oy0Q3hoc.js +1 -0
  274. package/dist/gui/client/assets/gitGraphDiagram-WWUBYQGX-jtAuBmbc.js +106 -0
  275. package/dist/gui/client/assets/index-CuFuBEdL.css +1 -0
  276. package/dist/gui/client/assets/index-hMbEIsX0.js +87 -0
  277. package/dist/gui/client/assets/info-A6RAGUB7-UtEs1tv7.js +1 -0
  278. package/dist/gui/client/assets/infoDiagram-27XIBGKW-hlwR1pBW.js +2 -0
  279. package/dist/gui/client/assets/ishikawaDiagram-5VMMS53U-C6vMtfsd.js +70 -0
  280. package/dist/gui/client/assets/journeyDiagram-3NMN7TZE-EAwAl_PS.js +139 -0
  281. package/dist/gui/client/assets/kanban-definition-UXKFOSKX-CQOhRKHW.js +89 -0
  282. package/dist/gui/client/assets/line-DbcwGZTW.js +1 -0
  283. package/dist/gui/client/assets/mermaid-parser.core-C2QfVcHd.js +7 -0
  284. package/dist/gui/client/assets/mermaid.core-N9qUTre1.js +44 -0
  285. package/dist/gui/client/assets/mindmap-definition-YA3MSWOX-BR_FL9gK.js +96 -0
  286. package/dist/gui/client/assets/packet-AYTQ26CC-CbBJ2oAa.js +1 -0
  287. package/dist/gui/client/assets/pegDiagram-XKGWAZYB-BruU0IHM.js +1 -0
  288. package/dist/gui/client/assets/pie-WAS4IAKB-BWdSng4H.js +1 -0
  289. package/dist/gui/client/assets/pieDiagram-E7YTZNPT-CR3ljgdU.js +39 -0
  290. package/dist/gui/client/assets/quadrantDiagram-AXDQQJYC-C-boKslr.js +7 -0
  291. package/dist/gui/client/assets/radar-RG4KPBEZ-CGlOnAKG.js +1 -0
  292. package/dist/gui/client/assets/railroad-74A4TZTK-CDvuAlyC.js +1 -0
  293. package/dist/gui/client/assets/railroad-abnf-HS5TGJTU-CQUA9crC.js +1 -0
  294. package/dist/gui/client/assets/railroad-ebnf-LZEXJU2U-CD857gxq.js +1 -0
  295. package/dist/gui/client/assets/railroad-peg-WCYAUIDC-DUV4k35E.js +1 -0
  296. package/dist/gui/client/assets/railroadDiagram-O6MQD6OU-DMR4LXmA.js +1 -0
  297. package/dist/gui/client/assets/requirementDiagram-BXWQKSXE-DVltaF6c.js +84 -0
  298. package/dist/gui/client/assets/sankeyDiagram-P5KCCOFB-CHdNz472.js +40 -0
  299. package/dist/gui/client/assets/sequenceDiagram-WJ2MYXX4-DaMafIty.js +162 -0
  300. package/dist/gui/client/assets/stateDiagram-D77RDMKH-CEbBHqn3.js +1 -0
  301. package/dist/gui/client/assets/stateDiagram-v2-MP3YSRHH-B3JgDdFg.js +1 -0
  302. package/dist/gui/client/assets/swimlanes-42K2YHIH-BlPHndnJ.js +1 -0
  303. package/dist/gui/client/assets/swimlanesDiagram-VR7AAH4N-BPabHwsZ.js +8 -0
  304. package/dist/gui/client/assets/timeline-definition-24CTP7MA-E4Y1lPBI.js +120 -0
  305. package/dist/gui/client/assets/treeView-Q6P3EWNA-DrY0uhTN.js +1 -0
  306. package/dist/gui/client/assets/treemap-WGGIJYW6-CVotnLHf.js +1 -0
  307. package/dist/gui/client/assets/vennDiagram-4TSXK5OY-DJNrLIOF.js +34 -0
  308. package/dist/gui/client/assets/wardley-WFR3VGLG-ClOpAp5S.js +1 -0
  309. package/dist/gui/client/assets/wardleyDiagram-VM6X3IG4-qhMoKOXc.js +78 -0
  310. package/dist/gui/client/assets/xychartDiagram-S5SC5T6Z-CTuXoo9R.js +7 -0
  311. package/dist/gui/client/index.html +6 -0
  312. package/dist/gui/ops-worker.js +167 -0
  313. package/dist/gui/reads-worker.js +473 -0
  314. package/dist/gui/server.js +9780 -0
  315. package/dist/gui-QJS7XQMV.js +16 -0
  316. package/dist/init-DV5B6HQG.js +354 -0
  317. package/dist/install-6C45YXFP.js +19 -0
  318. package/dist/install-O7NSRU2W.js +13 -0
  319. package/dist/interactive-OXGYZYAS.js +22381 -0
  320. package/dist/interop-J7UOBOSF.js +254 -0
  321. package/dist/inventory-OEGIL6PY.js +144 -0
  322. package/dist/library-B3UPGY4V.js +83 -0
  323. package/dist/library-MXQA5DLT.js +309 -0
  324. package/dist/library-ROZAMUIL.js +496 -0
  325. package/dist/library-import-2LTWOVBD.js +190 -0
  326. package/dist/library-inventory-LJ3XHLWO.js +60 -0
  327. package/dist/library-validation-DARHHUNW.js +46 -0
  328. package/dist/mcp-2GSPYQ54.js +28 -0
  329. package/dist/memory-J3STUUIK.js +537 -0
  330. package/dist/models-Y3GMFJ2V.js +314 -0
  331. package/dist/monitor-LHNH577J.js +811 -0
  332. package/dist/orchestrator-DTAPXULA.js +12117 -0
  333. package/dist/panes-A743ONZ5.js +103 -0
  334. package/dist/panes-CTNO57ZY.js +76 -0
  335. package/dist/paths-3SBYJQDP.js +68 -0
  336. package/dist/preload-OJBMAIXF.js +140 -0
  337. package/dist/providers-CMETPZNS.js +232 -0
  338. package/dist/registry-37T4U6X2.js +15 -0
  339. package/dist/reset-O7EUCYWO.js +346 -0
  340. package/dist/resources-FY6XYFN2.js +189 -0
  341. package/dist/run-H64MEVTA.js +1067 -0
  342. package/dist/run-script-PQ5NRU3X.js +42 -0
  343. package/dist/settings-SNIQNXCW.js +73 -0
  344. package/dist/settings-controls-X6GMCPVG.js +202 -0
  345. package/dist/share-CAFMMQLM.js +299 -0
  346. package/dist/skills-ERKQUC7L.js +114 -0
  347. package/dist/skills-eval-CQ23MYQK.js +1099 -0
  348. package/dist/skills-inventory-TVUYJDVN.js +142 -0
  349. package/dist/slash-commands-ROG3KIFJ.js +107 -0
  350. package/dist/startup-background-KDWCQMWT.js +247 -0
  351. package/dist/steer-KKYXJSH4.js +77 -0
  352. package/dist/support-M3RCUUEL.js +40 -0
  353. package/dist/system-ZDW44ZGX.js +142 -0
  354. package/dist/target-runtimes-PWA22WVW.js +73 -0
  355. package/dist/targets-AJWA6E7Z.js +1207 -0
  356. package/dist/tasks-6L2JJRC5.js +39 -0
  357. package/dist/terminal-lease-YFUSDPAD.js +432 -0
  358. package/dist/tools-5XJUABRD.js +30 -0
  359. package/dist/trace-LA5MVR4Y.js +527 -0
  360. package/dist/tree-sitter-TQW3Y52T.js +4673 -0
  361. package/dist/tui-primitives-IUCVWLH5.js +19 -0
  362. package/dist/uninstall-SAWGGXAB.js +448 -0
  363. package/dist/upgrade-HSNSVTZG.js +300 -0
  364. package/dist/usage-XSILDHKF.js +1083 -0
  365. package/dist/verifiers-ECA5GIHL.js +633 -0
  366. package/dist/verify-R6QQCCEB.js +31 -0
  367. package/dist/version-PLZYB5KW.js +22 -0
  368. package/dist/web-fetch-PVZNMBOB.js +803 -0
  369. package/dist/wiki-generate-RP22WP5K.js +647 -0
  370. package/dist/with-panes-W3PAZPRF.js +629 -0
  371. package/dist/worker/entry.js +324 -284
  372. package/dist/workspace-check-3764ZKC2.js +83 -0
  373. package/docs/README.md +26 -10
  374. package/docs/architecture/acp.md +179 -12
  375. package/docs/architecture/artifact-placement.md +1 -1
  376. package/docs/architecture/capacity-and-scheduling.md +7 -8
  377. package/docs/architecture/context-engine.md +350 -95
  378. package/docs/architecture/model-catalog.md +18 -11
  379. package/docs/architecture/observability.md +1 -1
  380. package/docs/architecture/pi-boundary.md +59 -6
  381. package/docs/architecture/prompt-envelope-and-tools.md +147 -39
  382. package/docs/architecture/provider-adapter-cookbook.md +2 -2
  383. package/docs/architecture/safety-model.md +18 -4
  384. package/docs/architecture/trace-store.md +2 -2
  385. package/docs/architecture/tui-design.md +41 -81
  386. package/docs/architecture/worker-dispatch-mechanics.md +9 -1
  387. package/docs/gui/README.md +69 -0
  388. package/docs/gui/boundary-doctrine.md +104 -0
  389. package/docs/gui/chat-rendering-spec.md +1440 -0
  390. package/docs/gui/cli-surface-routing.md +148 -0
  391. package/docs/gui/delivery-order.md +53 -0
  392. package/docs/gui/event-bus-coverage.md +103 -0
  393. package/docs/gui/inspector-presentation.md +71 -0
  394. package/docs/gui/parity/01-cli-surface.md +74 -0
  395. package/docs/gui/parity/02-slash-and-surfaces.md +110 -0
  396. package/docs/gui/parity/03-domains-and-plan.md +69 -0
  397. package/docs/gui/performance-baseline.md +76 -0
  398. package/docs/gui/settings-write-surface.md +267 -0
  399. package/docs/gui/workflow-coverage.md +64 -0
  400. package/docs/guide/built-in-agents.md +1 -1
  401. package/docs/guide/commands-and-modes.md +256 -99
  402. package/docs/guide/configuration-and-targets.md +485 -124
  403. package/docs/guide/configuration-reference.md +165 -82
  404. package/docs/guide/doctor.md +127 -0
  405. package/docs/guide/environment-variables.md +1 -1
  406. package/docs/guide/exit-codes-and-output.md +3 -1
  407. package/docs/guide/extensions-and-sharing.md +3 -14
  408. package/docs/guide/fleet-dispatch.md +231 -45
  409. package/docs/guide/glossary.md +1 -1
  410. package/docs/guide/installation-and-lifecycle.md +27 -16
  411. package/docs/guide/interop.md +2 -2
  412. package/docs/guide/proactive-memory.md +154 -68
  413. package/docs/guide/resource-library.md +4 -0
  414. package/docs/guide/skills-marketplace.md +8 -4
  415. package/docs/guide/slurm.md +88 -0
  416. package/docs/guide/tool-usage.md +134 -11
  417. package/docs/guide/troubleshooting.md +4 -2
  418. package/docs/process/battletest-2026-09-20-fixes.md +161 -0
  419. package/docs/process/configure-tree-proposal.md +637 -0
  420. package/docs/process/documentation-coverage.md +8 -0
  421. package/docs/process/documentation-guide.md +18 -1
  422. package/docs/process/eval-runner.md +58 -14
  423. package/docs/process/performance-methodology.md +11 -3
  424. package/docs/process/release-cut-checklist.md +29 -3
  425. package/docs/process/tool-audit-v0.4.9.md +3 -0
  426. package/examples/extensions/README.md +1 -3
  427. package/examples/extensions/lab-status/clio-coder-extension.json +1 -1
  428. package/examples/extensions/measurements/clio-coder-extension.json +1 -1
  429. package/library/registry.yaml +30 -5
  430. package/library/skills/git/fix-issue/SKILL.md +2 -1
  431. package/library/skills/git/fix-issue/plugin.json +1 -1
  432. package/library/skills/git/ship/SKILL.md +2 -1
  433. package/library/skills/git/ship/plugin.json +1 -1
  434. package/library/skills/meta/clio-coder-test/SKILL.md +5 -6
  435. package/library/skills/meta/clio-coder-test/evals.md +2 -2
  436. package/library/skills/meta/clio-coder-test/references/test-map.md +2 -2
  437. package/library/skills/registry.yaml +9 -5
  438. package/library/skills/research/slurm-jobs/SKILL.md +110 -0
  439. package/library/skills/research/slurm-jobs/evals.md +39 -0
  440. package/library/skills/research/slurm-jobs/plugin.json +23 -0
  441. package/library/skills/skill-marketplace.json +18 -2
  442. package/package.json +15 -10
  443. package/src/cli/args.ts +59 -0
  444. package/src/cli/argv.ts +7 -0
  445. package/src/cli/clio.ts +9 -1
  446. package/src/cli/configure-controls.ts +136 -0
  447. package/src/cli/configure-onboarding.ts +24 -7
  448. package/src/cli/configure-quick.ts +32 -7
  449. package/src/cli/configure-target.ts +11 -1
  450. package/src/cli/configure.ts +253 -256
  451. package/src/cli/docs-server.ts +290 -0
  452. package/src/cli/docs.ts +60 -15
  453. package/src/cli/doctor-deep.ts +126 -0
  454. package/src/cli/doctor-hpc.ts +122 -0
  455. package/src/cli/doctor-slurm.ts +130 -0
  456. package/src/cli/doctor-task-worktrees.ts +88 -0
  457. package/src/cli/doctor.ts +165 -16
  458. package/src/cli/fleet-verify.ts +3 -2
  459. package/src/cli/gui.ts +111 -0
  460. package/src/cli/index.ts +14 -4
  461. package/src/cli/library.ts +2 -7
  462. package/src/cli/modes/json-stream.ts +4 -2
  463. package/src/cli/modes/print.ts +252 -25
  464. package/src/cli/run.ts +199 -71
  465. package/src/cli/skills.ts +25 -7
  466. package/src/cli/targets.ts +87 -9
  467. package/src/cli/uninstall.ts +28 -8
  468. package/src/cli/usage.ts +2 -1
  469. package/src/cli/workspace-check.ts +71 -0
  470. package/src/core/bash-exec.ts +8 -2
  471. package/src/core/bus-events.ts +32 -3
  472. package/src/core/cache-telemetry.ts +3 -2
  473. package/src/core/compile-cache.ts +11 -1
  474. package/src/core/config.ts +59 -6
  475. package/src/core/defaults.ts +27 -5
  476. package/src/core/diagnostics.ts +25 -0
  477. package/src/core/event-bus.ts +2 -1
  478. package/src/core/gateway-routing.ts +10 -3
  479. package/src/core/git-commit-attribution.ts +2 -1
  480. package/src/core/naming-compat.ts +6 -4
  481. package/src/core/package-root.ts +0 -9
  482. package/src/core/path-canonical.ts +143 -24
  483. package/src/core/residency-target-key.ts +2 -6
  484. package/src/core/run-overrides.ts +1 -1
  485. package/src/core/settings-awareness.ts +108 -0
  486. package/src/core/settings-controls.ts +673 -0
  487. package/src/core/settings-navigation.ts +116 -0
  488. package/src/core/theme-token-hex.ts +19 -9
  489. package/src/core/turn-constraints.ts +52 -0
  490. package/src/domains/agents/builtins/scout.md +7 -17
  491. package/src/domains/agents/catalog.ts +5 -1
  492. package/src/domains/agents/extension.ts +2 -1
  493. package/src/domains/agents/registry.ts +4 -3
  494. package/src/domains/agents/result-contract.ts +132 -1
  495. package/src/domains/config/classify.ts +11 -7
  496. package/src/domains/config/extension.ts +5 -1
  497. package/src/domains/config/keybindings.ts +2 -2
  498. package/src/domains/context/codewiki/coordinator.ts +10 -0
  499. package/src/domains/context/worker/snapshot.ts +6 -3
  500. package/src/domains/dispatch/active-route-planner.ts +2 -0
  501. package/src/domains/dispatch/agent-candidates.ts +5 -1
  502. package/src/domains/dispatch/capability-match.ts +1 -1
  503. package/src/domains/dispatch/contract.ts +28 -0
  504. package/src/domains/dispatch/event-pump.ts +37 -3
  505. package/src/domains/dispatch/extension.ts +391 -48
  506. package/src/domains/dispatch/failure-classification.ts +37 -2
  507. package/src/domains/dispatch/receipt-integrity.ts +3 -0
  508. package/src/domains/dispatch/run-identity.ts +10 -3
  509. package/src/domains/dispatch/target-breaker.ts +163 -0
  510. package/src/domains/dispatch/types.ts +29 -2
  511. package/src/domains/dispatch/worker-model-loads.ts +66 -0
  512. package/src/domains/dispatch/worker-protocol.ts +20 -1
  513. package/src/domains/dispatch/worker-spawn.ts +28 -2
  514. package/src/domains/eval/artifacts/redact.ts +9 -0
  515. package/src/domains/eval/metrics/noop.ts +61 -0
  516. package/src/domains/eval/reports/junit.ts +5 -1
  517. package/src/domains/eval/reports/text.ts +7 -0
  518. package/src/domains/eval/runners/clio-run.ts +19 -8
  519. package/src/domains/eval/runners/external-command.ts +29 -4
  520. package/src/domains/eval/schema/adapter.ts +6 -2
  521. package/src/domains/eval/schema/suite.ts +2 -0
  522. package/src/domains/eval/schema/validate.ts +3 -0
  523. package/src/domains/eval/suites/run.ts +167 -26
  524. package/src/domains/evidence/detail.ts +3 -2
  525. package/src/domains/extensions/operator-runtime.ts +11 -4
  526. package/src/domains/gateway/mcp/client.ts +1 -1
  527. package/src/domains/lifecycle/doctor.ts +42 -26
  528. package/src/domains/lifecycle/migrations/2026-09-18-ollama-runtime-id.ts +38 -0
  529. package/src/domains/lifecycle/migrations/index.ts +2 -0
  530. package/src/domains/middleware/demo-guidance.ts +36 -0
  531. package/src/domains/middleware/dispatch-nudge.ts +1 -1
  532. package/src/domains/middleware/memory-intervention.ts +51 -4
  533. package/src/domains/middleware/runtime.ts +5 -4
  534. package/src/domains/middleware/skills-reminder.ts +29 -52
  535. package/src/domains/middleware/task-nudge.ts +1 -0
  536. package/src/domains/middleware/watchdog.ts +4 -0
  537. package/src/domains/observability/extension.ts +2 -1
  538. package/src/domains/observability/out-of-turn-usage.ts +3 -2
  539. package/src/domains/observability/projection.ts +3 -2
  540. package/src/domains/observability/worker-progress.ts +48 -0
  541. package/src/domains/prompts/compiler.ts +148 -52
  542. package/src/domains/prompts/contract.ts +3 -3
  543. package/src/domains/prompts/demo-guidance.ts +8 -0
  544. package/src/domains/prompts/extension.ts +12 -7
  545. package/src/domains/prompts/fragments/identity/clio.md +2 -1
  546. package/src/domains/prompts/fragments/identity/docs-routing.md +2 -0
  547. package/src/domains/prompts/fragments/identity/self-awareness.md +4 -0
  548. package/src/domains/prompts/fragments/operating/contract.md +16 -7
  549. package/src/domains/prompts/fragments/operating/delegation.md +29 -13
  550. package/src/domains/prompts/fragments/operating/skills.md +18 -10
  551. package/src/domains/prompts/fragments/operating/worker.md +2 -0
  552. package/src/domains/providers/cache-deployment.ts +45 -2
  553. package/src/domains/providers/contract.ts +52 -11
  554. package/src/domains/providers/extension.ts +230 -53
  555. package/src/domains/providers/model-discovery.ts +22 -8
  556. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +5 -7
  557. package/src/domains/providers/plugins.ts +3 -4
  558. package/src/domains/providers/probe/fingerprint.ts +2 -2
  559. package/src/domains/providers/probe/reasoning.ts +9 -16
  560. package/src/domains/providers/probe/tool-call.ts +236 -0
  561. package/src/domains/providers/registry.ts +51 -8
  562. package/src/domains/providers/runtime-resolution.ts +60 -12
  563. package/src/domains/providers/runtimes/boot-manifest.ts +1 -1
  564. package/src/domains/providers/runtimes/builtins.ts +2 -2
  565. package/src/domains/providers/runtimes/common/lmstudio-http.ts +57 -41
  566. package/src/domains/providers/runtimes/common/local-synth.ts +3 -1
  567. package/src/domains/providers/runtimes/common/ollama-model-ids.ts +11 -0
  568. package/src/domains/providers/runtimes/common/probe-helpers.ts +53 -0
  569. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +3 -1
  570. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +7 -13
  571. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +7 -17
  572. package/src/domains/providers/runtimes/local-native/llamacpp.ts +1 -0
  573. package/src/domains/providers/runtimes/local-native/ollama.ts +211 -0
  574. package/src/domains/providers/runtimes/protocol/litellm.ts +77 -65
  575. package/src/domains/providers/support.ts +1 -1
  576. package/src/domains/providers/types/local-model-quirks.ts +2 -3
  577. package/src/domains/providers/types/runtime-descriptor.ts +23 -3
  578. package/src/domains/providers/types/target-descriptor.ts +15 -3
  579. package/src/domains/resources/collision.ts +7 -2
  580. package/src/domains/resources/index.ts +1 -0
  581. package/src/domains/resources/library-actions.ts +4 -2
  582. package/src/domains/resources/library-inventory.ts +6 -2
  583. package/src/domains/resources/prompts/loader.ts +20 -7
  584. package/src/domains/resources/skills/availability.ts +56 -0
  585. package/src/domains/resources/skills/loader.ts +20 -9
  586. package/src/domains/safety/action-classifier.ts +282 -31
  587. package/src/domains/safety/audit.ts +2 -1
  588. package/src/domains/safety/autonomy.ts +54 -11
  589. package/src/domains/safety/decision-presentation.ts +17 -4
  590. package/src/domains/safety/finish-contract-registration.ts +25 -1
  591. package/src/domains/safety/finish-contract.ts +20 -5
  592. package/src/domains/safety/path-policy.ts +6 -2
  593. package/src/domains/safety/policy-engine.ts +168 -48
  594. package/src/domains/safety/protected-artifacts.ts +527 -16
  595. package/src/domains/safety/read-scope.ts +120 -0
  596. package/src/domains/safety/skill-authority.ts +52 -16
  597. package/src/domains/scheduling/cluster.ts +14 -3
  598. package/src/domains/scheduling/contract.ts +7 -0
  599. package/src/domains/scheduling/extension.ts +20 -9
  600. package/src/domains/scheduling/local-capacity.ts +160 -0
  601. package/src/domains/session/context-accounting.ts +44 -31
  602. package/src/domains/session/context-ledger.ts +10 -3
  603. package/src/domains/session/entries.ts +4 -0
  604. package/src/domains/session/history.ts +1 -1
  605. package/src/domains/session/prompt-cache.ts +1 -0
  606. package/src/domains/session/prompt-manifest.ts +3 -1
  607. package/src/domains/session/retry.ts +4 -6
  608. package/src/domains/session/task-board.ts +19 -4
  609. package/src/domains/session/tree/preview.ts +3 -2
  610. package/src/engine/acp/commands.ts +653 -0
  611. package/src/engine/acp/server.ts +639 -20
  612. package/src/engine/acp/tool-mediator.ts +30 -7
  613. package/src/engine/acp/types.ts +58 -0
  614. package/src/engine/agent.ts +55 -10
  615. package/src/engine/ai.ts +11 -2
  616. package/src/engine/api-registry.ts +5 -4
  617. package/src/engine/apis/degraded-inference.ts +243 -0
  618. package/src/engine/apis/llamacpp-residency.ts +50 -6
  619. package/src/engine/apis/lmstudio-residency.ts +3 -5
  620. package/src/engine/apis/lmstudio.ts +137 -31
  621. package/src/engine/apis/ollama-http.ts +118 -0
  622. package/src/engine/apis/ollama-native.ts +216 -97
  623. package/src/engine/apis/openai-completions.ts +191 -189
  624. package/src/engine/apis/output-budget.ts +3 -1
  625. package/src/engine/apis/residency-lock.ts +2 -1
  626. package/src/engine/apis/residency.ts +339 -89
  627. package/src/engine/apis/sampling-overrides.ts +23 -2
  628. package/src/engine/apis/types.ts +1 -2
  629. package/src/engine/claude/tool-safety.ts +30 -5
  630. package/src/engine/context.ts +13 -0
  631. package/src/engine/env-api-keys.ts +2 -1
  632. package/src/engine/gemma-channel-filter.ts +3 -2
  633. package/src/engine/instrumented-tui.ts +25 -0
  634. package/src/engine/loop-guard.ts +172 -6
  635. package/src/engine/pi-mono-names.ts +16 -0
  636. package/src/engine/prewarm.ts +44 -15
  637. package/src/engine/provider-payload.ts +52 -14
  638. package/src/engine/session.ts +4 -2
  639. package/src/engine/worker-events.ts +9 -1
  640. package/src/engine/worker-runtime.ts +269 -42
  641. package/src/engine/worker-tools.ts +8 -3
  642. package/src/entry/boot-options.ts +23 -0
  643. package/src/entry/orchestrator.ts +207 -36
  644. package/src/interactive/assistant-generation-timing.ts +52 -0
  645. package/src/interactive/chat-loop-messages.ts +4 -1
  646. package/src/interactive/chat-loop.ts +59 -9
  647. package/src/interactive/chat-panel.ts +10 -1
  648. package/src/interactive/clio-editor.ts +51 -79
  649. package/src/interactive/context-meter.ts +1 -0
  650. package/src/interactive/context-overlay.ts +21 -8
  651. package/src/interactive/cost-overlay.ts +1 -1
  652. package/src/interactive/dispatch-board.ts +39 -8
  653. package/src/interactive/editor-bash.ts +0 -34
  654. package/src/interactive/editor-rails.ts +43 -0
  655. package/src/interactive/editor-submit.ts +34 -2
  656. package/src/interactive/footer/dashboard.ts +67 -38
  657. package/src/interactive/footer/demo-hints.ts +40 -0
  658. package/src/interactive/footer/key-hints.ts +21 -0
  659. package/src/interactive/footer/notifications.ts +1 -1
  660. package/src/interactive/footer/pages.ts +486 -0
  661. package/src/interactive/footer/system-metrics.ts +147 -0
  662. package/src/interactive/footer/widgets.ts +158 -63
  663. package/src/interactive/footer-panel.ts +29 -7
  664. package/src/interactive/interactive-application.ts +109 -21
  665. package/src/interactive/interactive-event-projection.ts +6 -2
  666. package/src/interactive/interactive-presentation.ts +25 -29
  667. package/src/interactive/interactive-slash-runtime.ts +32 -18
  668. package/src/interactive/interactive-subscriptions.ts +25 -5
  669. package/src/interactive/interactive-tickers.ts +21 -5
  670. package/src/interactive/keybinding-manager.ts +9 -0
  671. package/src/interactive/overlay-frame.ts +29 -7
  672. package/src/interactive/overlay-lifecycle.ts +5 -3
  673. package/src/interactive/overlay-model-selectors.ts +4 -0
  674. package/src/interactive/overlay-permission-lifecycle.ts +6 -5
  675. package/src/interactive/overlays/ask-user.ts +103 -110
  676. package/src/interactive/overlays/help-reference.ts +1 -0
  677. package/src/interactive/overlays/message-picker.ts +3 -29
  678. package/src/interactive/overlays/session-selector.ts +3 -2
  679. package/src/interactive/overlays/settings-sections.ts +2 -30
  680. package/src/interactive/overlays/settings.ts +310 -607
  681. package/src/interactive/permission-hint.ts +3 -3
  682. package/src/interactive/permission-overlay.ts +45 -27
  683. package/src/interactive/renderers/doctor-report.ts +43 -0
  684. package/src/interactive/renderers/tool-execution.ts +87 -62
  685. package/src/interactive/renderers/worker-entry.ts +76 -3
  686. package/src/interactive/side-question.ts +3 -1
  687. package/src/interactive/slash-commands.ts +78 -23
  688. package/src/interactive/startup-background.ts +131 -0
  689. package/src/interactive/startup-diagnostics.ts +16 -0
  690. package/src/interactive/status/state-machine.ts +16 -3
  691. package/src/interactive/status/types.ts +2 -0
  692. package/src/interactive/status/verbs.ts +1 -1
  693. package/src/interactive/terminal-lease.ts +26 -22
  694. package/src/interactive/theme/components.ts +1 -1
  695. package/src/interactive/theme/rules.ts +1 -1
  696. package/src/interactive/theme/tokens.ts +16 -10
  697. package/src/interactive/transcript-detail.ts +4 -0
  698. package/src/interactive/turn-context.ts +56 -20
  699. package/src/interactive/turn-middleware.ts +57 -9
  700. package/src/interactive/turn-prewarm.ts +121 -18
  701. package/src/interactive/turn-recovery.ts +10 -8
  702. package/src/interactive/turn-runtime.ts +74 -29
  703. package/src/interactive/turn-state.ts +3 -0
  704. package/src/interactive/welcome-art.ts +36 -0
  705. package/src/interactive/welcome-dashboard.ts +209 -49
  706. package/src/interactive/worker-replay.ts +4 -0
  707. package/src/interactive/worker-stream.ts +17 -2
  708. package/src/tools/agent-tools.ts +22 -1
  709. package/src/tools/builtin-tool-catalog.ts +2 -2
  710. package/src/tools/codewiki/code-nav.ts +1 -1
  711. package/src/tools/codewiki/shared.ts +39 -1
  712. package/src/tools/compete-worktrees.ts +8 -91
  713. package/src/tools/context/docs-engine.ts +44 -12
  714. package/src/tools/context/index.ts +126 -22
  715. package/src/tools/context/library.ts +1 -1
  716. package/src/tools/context/surface.ts +12 -7
  717. package/src/tools/core-bootstrap.ts +3 -0
  718. package/src/tools/dispatch-runner.ts +18 -0
  719. package/src/tools/dispatch-schema.ts +187 -206
  720. package/src/tools/edit.ts +46 -42
  721. package/src/tools/file-mutation-queue.ts +25 -26
  722. package/src/tools/gateway/clio-context-surface.ts +1 -1
  723. package/src/tools/gateway/index.ts +7 -3
  724. package/src/tools/gateway/mcp-capabilities.ts +5 -3
  725. package/src/tools/grep.ts +14 -2
  726. package/src/tools/ls.ts +1 -4
  727. package/src/tools/monitor.ts +14 -1
  728. package/src/tools/observation.ts +1 -3
  729. package/src/tools/path-utils.ts +51 -18
  730. package/src/tools/process-lease.ts +99 -0
  731. package/src/tools/read.ts +1 -1
  732. package/src/tools/registry.ts +71 -9
  733. package/src/tools/task-worktree.ts +296 -17
  734. package/src/tools/tasks.ts +29 -7
  735. package/src/tools/worker-evidence.ts +60 -1
  736. package/src/tools/worktree-root.ts +252 -0
  737. package/src/tools/write.ts +34 -30
  738. package/src/worker/entry.ts +18 -1
  739. package/src/worker/protocol.ts +54 -1
  740. package/src/worker/spec-contract.ts +22 -2
  741. package/dist/acp-ZWZCPS2A.js +0 -130
  742. package/dist/agents-LYSOWZUE.js +0 -150
  743. package/dist/auth-WBQGKWQ5.js +0 -551
  744. package/dist/background-BUMOBAQN.js +0 -37
  745. package/dist/builtins-ODRJOEDI.js +0 -22
  746. package/dist/chunk-2DRRZ57Q.js +0 -571
  747. package/dist/chunk-2JBZYUPY.js +0 -105
  748. package/dist/chunk-2VBWFXYE.js +0 -198
  749. package/dist/chunk-2X2R3UTH.js +0 -1018
  750. package/dist/chunk-32KJPXAM.js +0 -75
  751. package/dist/chunk-37LW32LZ.js +0 -32
  752. package/dist/chunk-3A3CUMKA.js +0 -54
  753. package/dist/chunk-3AND2EFU.js +0 -215
  754. package/dist/chunk-3RDHGNU7.js +0 -647
  755. package/dist/chunk-3SUDBGEI.js +0 -1323
  756. package/dist/chunk-3TQN67I2.js +0 -396
  757. package/dist/chunk-3U4BL2EV.js +0 -103
  758. package/dist/chunk-3UQADNG2.js +0 -302
  759. package/dist/chunk-434LRQ6Z.js +0 -13441
  760. package/dist/chunk-4ATBOFRP.js +0 -7802
  761. package/dist/chunk-4DNL43EZ.js +0 -139
  762. package/dist/chunk-4HFJKRGZ.js +0 -5250
  763. package/dist/chunk-555E2WVV.js +0 -322
  764. package/dist/chunk-5GZICIYO.js +0 -462
  765. package/dist/chunk-5PHVPU4G.js +0 -160
  766. package/dist/chunk-5RTEFNBP.js +0 -197
  767. package/dist/chunk-64XJW7NT.js +0 -380
  768. package/dist/chunk-6TKOFFGE.js +0 -1058
  769. package/dist/chunk-6UJ7RDI7.js +0 -1143
  770. package/dist/chunk-7FBCRWVT.js +0 -1801
  771. package/dist/chunk-7JSOSVLP.js +0 -283
  772. package/dist/chunk-7N3OLLSL.js +0 -637
  773. package/dist/chunk-7QQRPB2E.js +0 -915
  774. package/dist/chunk-A6DULIMH.js +0 -986
  775. package/dist/chunk-AB3QXXBC.js +0 -123
  776. package/dist/chunk-ACCECAH4.js +0 -49
  777. package/dist/chunk-AM6CEP2K.js +0 -2120
  778. package/dist/chunk-AUHVBIDW.js +0 -19
  779. package/dist/chunk-AY4XE6GN.js +0 -665
  780. package/dist/chunk-BBA2TAWV.js +0 -667
  781. package/dist/chunk-BFPHMSK7.js +0 -169
  782. package/dist/chunk-BMNVVKEW.js +0 -604
  783. package/dist/chunk-CKK25WN3.js +0 -72
  784. package/dist/chunk-CTGZCEI6.js +0 -33
  785. package/dist/chunk-DIAJYJYG.js +0 -446
  786. package/dist/chunk-DVNAPPXU.js +0 -27
  787. package/dist/chunk-DXVMLM3Z.js +0 -92
  788. package/dist/chunk-E3LEPLQ2.js +0 -68
  789. package/dist/chunk-EHZRAB4U.js +0 -63
  790. package/dist/chunk-EM2DIQAJ.js +0 -179
  791. package/dist/chunk-EM2WNQS2.js +0 -93
  792. package/dist/chunk-ETF4ROKH.js +0 -595
  793. package/dist/chunk-F2YM3JY4.js +0 -22513
  794. package/dist/chunk-FEBQWHJT.js +0 -1023
  795. package/dist/chunk-FPS4R2RN.js +0 -1975
  796. package/dist/chunk-GD55RTIW.js +0 -33
  797. package/dist/chunk-GJDRMBDI.js +0 -573
  798. package/dist/chunk-GREYLTZ5.js +0 -658
  799. package/dist/chunk-H2WSCZZT.js +0 -238
  800. package/dist/chunk-H6IUCY6Q.js +0 -117
  801. package/dist/chunk-H72DCH3E.js +0 -563
  802. package/dist/chunk-H7TXJR23.js +0 -705
  803. package/dist/chunk-HBJQQTKM.js +0 -40
  804. package/dist/chunk-HCVKSGNZ.js +0 -990
  805. package/dist/chunk-HVCAY2FH.js +0 -67
  806. package/dist/chunk-I47EJPYL.js +0 -1377
  807. package/dist/chunk-IALGWTLO.js +0 -36
  808. package/dist/chunk-IALZJE37.js +0 -1710
  809. package/dist/chunk-IC7JXLOM.js +0 -1577
  810. package/dist/chunk-IOSVTTCD.js +0 -108
  811. package/dist/chunk-IPTPMLA6.js +0 -475
  812. package/dist/chunk-IZZI3SKQ.js +0 -128
  813. package/dist/chunk-JABWPKFY.js +0 -27
  814. package/dist/chunk-JIYWMQZ5.js +0 -175
  815. package/dist/chunk-JKU34ACI.js +0 -693
  816. package/dist/chunk-JOBN2YQQ.js +0 -176
  817. package/dist/chunk-JOL2QRLE.js +0 -152
  818. package/dist/chunk-JTR3VSV3.js +0 -44
  819. package/dist/chunk-JU6MAMRJ.js +0 -362
  820. package/dist/chunk-JURMQWVJ.js +0 -15
  821. package/dist/chunk-K2BLQC5E.js +0 -262
  822. package/dist/chunk-K3XN4LZ4.js +0 -402
  823. package/dist/chunk-KIVFXGBM.js +0 -688
  824. package/dist/chunk-KKRXONXG.js +0 -43
  825. package/dist/chunk-KOAHT3N2.js +0 -395
  826. package/dist/chunk-KP5BPXR3.js +0 -73
  827. package/dist/chunk-KQ6IDQIB.js +0 -39
  828. package/dist/chunk-KRJQG47M.js +0 -1289
  829. package/dist/chunk-KW6OJ7IY.js +0 -221
  830. package/dist/chunk-L3NBWLSN.js +0 -314
  831. package/dist/chunk-L4RUTLRL.js +0 -59
  832. package/dist/chunk-LGTVWPRN.js +0 -47
  833. package/dist/chunk-LSQW6KZO.js +0 -200
  834. package/dist/chunk-LTR5QCLS.js +0 -446
  835. package/dist/chunk-LWJYOHT3.js +0 -165
  836. package/dist/chunk-M6YLF66Z.js +0 -2687
  837. package/dist/chunk-MJ4QEJVT.js +0 -185
  838. package/dist/chunk-MO65K5CH.js +0 -1148
  839. package/dist/chunk-MTOZEQHL.js +0 -637
  840. package/dist/chunk-MZDPF35R.js +0 -45
  841. package/dist/chunk-MZKYVIWW.js +0 -188
  842. package/dist/chunk-NBPA5QM6.js +0 -386
  843. package/dist/chunk-NMBEW4PP.js +0 -688
  844. package/dist/chunk-NPLLK3HO.js +0 -3610
  845. package/dist/chunk-NSYGPIVW.js +0 -39
  846. package/dist/chunk-NXTV5OI5.js +0 -1020
  847. package/dist/chunk-NYDG4QP4.js +0 -689
  848. package/dist/chunk-OA2GDACN.js +0 -146
  849. package/dist/chunk-PJI57EC6.js +0 -236
  850. package/dist/chunk-PJJBUGMR.js +0 -4484
  851. package/dist/chunk-PNJE7JPS.js +0 -50
  852. package/dist/chunk-PP23PZEV.js +0 -1347
  853. package/dist/chunk-PPIFDSBK.js +0 -409
  854. package/dist/chunk-PTFISXQO.js +0 -319
  855. package/dist/chunk-QB33Z5S7.js +0 -1865
  856. package/dist/chunk-QGNII5VC.js +0 -110
  857. package/dist/chunk-QH3ZTUOA.js +0 -113
  858. package/dist/chunk-QI72X67S.js +0 -481
  859. package/dist/chunk-QJMRYTCX.js +0 -56
  860. package/dist/chunk-QKHZZFKH.js +0 -98
  861. package/dist/chunk-RDKX2PME.js +0 -66
  862. package/dist/chunk-RL7LJYN4.js +0 -66
  863. package/dist/chunk-RPMNIFRY.js +0 -65
  864. package/dist/chunk-RQROVOV3.js +0 -670
  865. package/dist/chunk-S34A7BSP.js +0 -97
  866. package/dist/chunk-SJETVJHX.js +0 -119
  867. package/dist/chunk-SJMNU4ZS.js +0 -634
  868. package/dist/chunk-SL2RDHKO.js +0 -19
  869. package/dist/chunk-SLLG2G44.js +0 -85
  870. package/dist/chunk-SQAZN2V3.js +0 -2744
  871. package/dist/chunk-SQBT46OF.js +0 -814
  872. package/dist/chunk-SRCEQKQS.js +0 -165
  873. package/dist/chunk-TCUOGIL2.js +0 -52
  874. package/dist/chunk-TIWPKCVO.js +0 -42
  875. package/dist/chunk-U44YYLVV.js +0 -1529
  876. package/dist/chunk-UIU7MGZ3.js +0 -486
  877. package/dist/chunk-USBBEKHW.js +0 -177
  878. package/dist/chunk-VHKTOLEW.js +0 -1416
  879. package/dist/chunk-VPWGADBG.js +0 -3151
  880. package/dist/chunk-VQD7NH7Z.js +0 -356
  881. package/dist/chunk-VWFCAK34.js +0 -697
  882. package/dist/chunk-W5RM7YAH.js +0 -78
  883. package/dist/chunk-W72LLZAV.js +0 -243
  884. package/dist/chunk-WGRDABW7.js +0 -207
  885. package/dist/chunk-WWRV5RJI.js +0 -165
  886. package/dist/chunk-XCUDZQLX.js +0 -195
  887. package/dist/chunk-XFLSL7BT.js +0 -386
  888. package/dist/chunk-XJZEDCNT.js +0 -391
  889. package/dist/chunk-XLLEL3K7.js +0 -709
  890. package/dist/chunk-XNZWWDC3.js +0 -686
  891. package/dist/chunk-XRECG65F.js +0 -308
  892. package/dist/chunk-XTQ7MEJG.js +0 -457
  893. package/dist/chunk-XW2UZICE.js +0 -372
  894. package/dist/chunk-Y3M2T5RO.js +0 -891
  895. package/dist/chunk-YGDMBK7O.js +0 -567
  896. package/dist/chunk-YJCCMYYT.js +0 -125
  897. package/dist/chunk-YPQOPFP7.js +0 -797
  898. package/dist/chunk-YQYINEJI.js +0 -132
  899. package/dist/chunk-ZF6CV4WZ.js +0 -5614
  900. package/dist/chunk-ZKJU55MX.js +0 -326
  901. package/dist/chunk-ZKQ63XZ5.js +0 -1196
  902. package/dist/chunk-ZKVMDNAN.js +0 -962
  903. package/dist/chunk-ZST3FRCV.js +0 -132
  904. package/dist/clio-JUDCLNHC.js +0 -26
  905. package/dist/clio-context-tools-FT672MNZ.js +0 -136
  906. package/dist/code-nav-7OVCTP2Z.js +0 -688
  907. package/dist/compile-cache-WJEPUZEJ.js +0 -16
  908. package/dist/components-OZXZMDWU.js +0 -674
  909. package/dist/config-P3ZQVF63.js +0 -275
  910. package/dist/config-graph-GKAOBAS5.js +0 -160
  911. package/dist/configure-25LRYZJG.js +0 -86
  912. package/dist/context-72VQV7JX.js +0 -73
  913. package/dist/context-COWRWXP3.js +0 -286
  914. package/dist/context-WB3D474G.js +0 -344
  915. package/dist/context-clear-Y4LYMWC6.js +0 -192
  916. package/dist/context-index-W6A4V7OC.js +0 -120
  917. package/dist/context-map-DKL3QT6D.js +0 -555
  918. package/dist/context-working-set-TMZYVC7A.js +0 -1560
  919. package/dist/data-tool-KMBWKKWR.js +0 -2987
  920. package/dist/detail-4GLROGY5.js +0 -123
  921. package/dist/dispatch-runner-TR3LBP5P.js +0 -2446
  922. package/dist/docs-ZK777W2G.js +0 -101
  923. package/dist/doctor-WC4OV2OB.js +0 -814
  924. package/dist/eval-FUNWJNUJ.js +0 -5050
  925. package/dist/eval-inventory-CX24K2JT.js +0 -260
  926. package/dist/evals-L73EBHSU.js +0 -104
  927. package/dist/evidence-AVJ2RTHX.js +0 -392
  928. package/dist/evidence-P4NZOAK7.js +0 -233
  929. package/dist/evidence-Y55WKYHH.js +0 -246
  930. package/dist/evolve-MAWKRYWF.js +0 -617
  931. package/dist/extensions-PYQH3H47.js +0 -308
  932. package/dist/fleet-M4H2QBWT.js +0 -268
  933. package/dist/fleet-ULBXXRDR.js +0 -923
  934. package/dist/fleet-commands-7NNC4JZU.js +0 -76
  935. package/dist/fleet-decisions-EHEY7KPU.js +0 -52
  936. package/dist/fleet-graph-LQ2AHZT3.js +0 -136
  937. package/dist/fleet-inspect-5IGBIIYZ.js +0 -312
  938. package/dist/fleet-new-RCKGSRDV.js +0 -48
  939. package/dist/fleet-preflight-UTTNOKMG.js +0 -27
  940. package/dist/fleet-validate-YGILJKA6.js +0 -91
  941. package/dist/fleet-verify-AUWTCDKR.js +0 -210
  942. package/dist/fleet-view-TGUFCY5A.js +0 -127
  943. package/dist/init-GFN2Z7NF.js +0 -333
  944. package/dist/install-3RZDDP23.js +0 -13
  945. package/dist/install-6PIF6F6W.js +0 -19
  946. package/dist/interop-EF5JUWWK.js +0 -246
  947. package/dist/inventory-I6VJDDYF.js +0 -127
  948. package/dist/library-3J5IO2OJ.js +0 -75
  949. package/dist/library-IJTOFTDS.js +0 -307
  950. package/dist/library-Z3KZSHPE.js +0 -492
  951. package/dist/library-import-IMKFLDHX.js +0 -183
  952. package/dist/library-inventory-CQP5D6GU.js +0 -56
  953. package/dist/library-validation-33UTX7AI.js +0 -42
  954. package/dist/mcp-5FWZKUS6.js +0 -26
  955. package/dist/memory-36CWN67Y.js +0 -520
  956. package/dist/models-KQ6PQJJQ.js +0 -302
  957. package/dist/monitor-XX6ZD6KC.js +0 -785
  958. package/dist/orchestrator-SK6HDAOP.js +0 -42067
  959. package/dist/panes-L27QRXUH.js +0 -74
  960. package/dist/panes-LXZIWNOZ.js +0 -103
  961. package/dist/paths-7DJDU4P4.js +0 -67
  962. package/dist/preload-K2TDYI4Y.js +0 -124
  963. package/dist/registry-DESGAXWK.js +0 -11
  964. package/dist/reset-73VU3XNT.js +0 -345
  965. package/dist/resources-3BYJYVYL.js +0 -181
  966. package/dist/run-AR7PY6GW.js +0 -896
  967. package/dist/run-script-H2KUDIII.js +0 -41
  968. package/dist/settings-3VMBMWID.js +0 -72
  969. package/dist/share-HVWH4FPF.js +0 -293
  970. package/dist/skills-5TYEY75Q.js +0 -100
  971. package/dist/skills-eval-CK3MD63Z.js +0 -1083
  972. package/dist/skills-inventory-KSFYG3I6.js +0 -138
  973. package/dist/slash-commands-DMVHML7P.js +0 -98
  974. package/dist/steer-XCD6V3EW.js +0 -77
  975. package/dist/support-JAZL6VBR.js +0 -38
  976. package/dist/system-3TDQRMZZ.js +0 -116
  977. package/dist/targets-EZKHAYRN.js +0 -1117
  978. package/dist/tasks-SNEFHWYW.js +0 -36
  979. package/dist/terminal-lease-BNLFA4OF.js +0 -419
  980. package/dist/tools-7IM6BDCE.js +0 -28
  981. package/dist/trace-C3MBGD4S.js +0 -524
  982. package/dist/tree-sitter-AQUUOSYM.js +0 -4673
  983. package/dist/tui-primitives-36BY2774.js +0 -18
  984. package/dist/uninstall-WWLOSZ42.js +0 -432
  985. package/dist/upgrade-ETK2JNSJ.js +0 -297
  986. package/dist/usage-S2HOB7BZ.js +0 -1065
  987. package/dist/verifiers-QDTEVH7R.js +0 -632
  988. package/dist/verify-SUKUK6XM.js +0 -31
  989. package/dist/version-RFPKO6T7.js +0 -21
  990. package/dist/web/client/assets/abnfDiagram-VCTEODGH-BznNOe_I.js +0 -1
  991. package/dist/web/client/assets/architecture-7GRP2DOG-BQO9DL_y.js +0 -1
  992. package/dist/web/client/assets/architectureDiagram-5GKGNRK7-CKPbdvyx.js +0 -36
  993. package/dist/web/client/assets/blockDiagram-I7D4REHJ-prINbpbM.js +0 -129
  994. package/dist/web/client/assets/c4Diagram-7LVT6UL2-DkVRKtyU.js +0 -38
  995. package/dist/web/client/assets/channel-c4EeUUqA.js +0 -1
  996. package/dist/web/client/assets/chunk-4HAMMTFA-CV0Z1ApC.js +0 -62
  997. package/dist/web/client/assets/chunk-75Z2AOVW-D34Nohxq.js +0 -2
  998. package/dist/web/client/assets/chunk-DU6HZSFF-Das_cS-O.js +0 -125
  999. package/dist/web/client/assets/chunk-F27PBJKO-CmRojxkG.js +0 -1
  1000. package/dist/web/client/assets/chunk-GMAD6QVW-ClYZmc73.js +0 -72
  1001. package/dist/web/client/assets/chunk-GVQU2GXP-B2BiHFt-.js +0 -1
  1002. package/dist/web/client/assets/chunk-IMKFNOWR-BGApZ8nP.js +0 -231
  1003. package/dist/web/client/assets/chunk-L3NEJ4N5-DIzCgpkY.js +0 -1
  1004. package/dist/web/client/assets/chunk-OSK3NFVY-BPT-yePv.js +0 -10
  1005. package/dist/web/client/assets/chunk-P2QGCYS3-BC1WTc2t.js +0 -1
  1006. package/dist/web/client/assets/chunk-POPQ4Y6H-BSjzBmZU.js +0 -1
  1007. package/dist/web/client/assets/chunk-PWAF6VOD-BIjLs86Z.js +0 -1
  1008. package/dist/web/client/assets/chunk-SHT3W25Y-CduDz2cm.js +0 -168
  1009. package/dist/web/client/assets/chunk-SVP7TREG-XUn4pPAP.js +0 -88
  1010. package/dist/web/client/assets/chunk-TICWLB2K-DcBy2DKy.js +0 -206
  1011. package/dist/web/client/assets/classDiagram-ZZMXUADV-C0HR7YKN.js +0 -1
  1012. package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-C0HR7YKN.js +0 -1
  1013. package/dist/web/client/assets/cynefin-OW5HDTMX-BecPbyM6.js +0 -1
  1014. package/dist/web/client/assets/cynefinDiagram-5FMLGOSQ-BzMzFwyT.js +0 -62
  1015. package/dist/web/client/assets/dagre-GXQ25YYZ-CAWJmRMG.js +0 -4
  1016. package/dist/web/client/assets/diagram-S7CK7UJ4--lp0ALmn.js +0 -30
  1017. package/dist/web/client/assets/diagram-UQ7AKVKN-gKUnsjcj.js +0 -41
  1018. package/dist/web/client/assets/diagram-VSXAHHWV-BoN5D1Gh.js +0 -3
  1019. package/dist/web/client/assets/diagram-VX7I27RA-BMtuswQ6.js +0 -24
  1020. package/dist/web/client/assets/diagram-Z3DM3KII-DtU8LXrA.js +0 -24
  1021. package/dist/web/client/assets/ebnfDiagram-PWID7BFC-DDcnv9BH.js +0 -1
  1022. package/dist/web/client/assets/erDiagram-RLTQ6QDP-DvRb4iDL.js +0 -99
  1023. package/dist/web/client/assets/eventmodeling-NTZA5JFV-01h4SbTc.js +0 -1
  1024. package/dist/web/client/assets/flowDiagram-HODETNUW-Bll_YZ6T.js +0 -1
  1025. package/dist/web/client/assets/framework-YGoR34M4.js +0 -9
  1026. package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-DdFZ9hvH.js +0 -292
  1027. package/dist/web/client/assets/gitGraph-4MIJSDKK-DjD_AAMj.js +0 -1
  1028. package/dist/web/client/assets/gitGraphDiagram-WWUBYQGX-CDyN9n2u.js +0 -106
  1029. package/dist/web/client/assets/index-CVcy0FAn.js +0 -75
  1030. package/dist/web/client/assets/index-Dsi52apB.css +0 -1
  1031. package/dist/web/client/assets/info-A6RAGUB7-C_XK8Hq0.js +0 -1
  1032. package/dist/web/client/assets/infoDiagram-27XIBGKW-DIe4tJ1i.js +0 -2
  1033. package/dist/web/client/assets/ishikawaDiagram-5VMMS53U-CVl5unKI.js +0 -70
  1034. package/dist/web/client/assets/journeyDiagram-3NMN7TZE-CPEB1Vt8.js +0 -139
  1035. package/dist/web/client/assets/kanban-definition-UXKFOSKX-j-9WXjYQ.js +0 -89
  1036. package/dist/web/client/assets/line-BIDAcEtX.js +0 -1
  1037. package/dist/web/client/assets/mermaid-parser.core-Ux4vssh0.js +0 -7
  1038. package/dist/web/client/assets/mermaid.core-CDuwVKeh.js +0 -44
  1039. package/dist/web/client/assets/mindmap-definition-YA3MSWOX-5MlQEeQ6.js +0 -96
  1040. package/dist/web/client/assets/packet-AYTQ26CC-DRO66c9Q.js +0 -1
  1041. package/dist/web/client/assets/pegDiagram-XKGWAZYB-BakZnSjM.js +0 -1
  1042. package/dist/web/client/assets/pie-WAS4IAKB-BEzcmhz8.js +0 -1
  1043. package/dist/web/client/assets/pieDiagram-E7YTZNPT-DpmqgoPt.js +0 -39
  1044. package/dist/web/client/assets/quadrantDiagram-AXDQQJYC-DuMPwwV2.js +0 -7
  1045. package/dist/web/client/assets/radar-RG4KPBEZ-Djm3oXl5.js +0 -1
  1046. package/dist/web/client/assets/railroad-74A4TZTK-Cpvkwsao.js +0 -1
  1047. package/dist/web/client/assets/railroad-abnf-HS5TGJTU-CpRQ3ruG.js +0 -1
  1048. package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-1Rm5a5eJ.js +0 -1
  1049. package/dist/web/client/assets/railroad-peg-WCYAUIDC-C8344cTh.js +0 -1
  1050. package/dist/web/client/assets/railroadDiagram-O6MQD6OU-CgMS4B6R.js +0 -1
  1051. package/dist/web/client/assets/requirementDiagram-BXWQKSXE-CX5eoNdN.js +0 -84
  1052. package/dist/web/client/assets/sankeyDiagram-P5KCCOFB-CODBX2N3.js +0 -40
  1053. package/dist/web/client/assets/sequenceDiagram-WJ2MYXX4-eUhhF8OR.js +0 -162
  1054. package/dist/web/client/assets/stateDiagram-D77RDMKH-vR6l0NC2.js +0 -1
  1055. package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-BYUm8jLY.js +0 -1
  1056. package/dist/web/client/assets/swimlanes-42K2YHIH-v9Tw_zX7.js +0 -1
  1057. package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-B2jdCvhD.js +0 -8
  1058. package/dist/web/client/assets/timeline-definition-24CTP7MA-DxianbhU.js +0 -120
  1059. package/dist/web/client/assets/treeView-Q6P3EWNA-DLxnZb9R.js +0 -1
  1060. package/dist/web/client/assets/treemap-WGGIJYW6-I7UnZ6xJ.js +0 -1
  1061. package/dist/web/client/assets/vennDiagram-4TSXK5OY-Ar7M8Mrj.js +0 -34
  1062. package/dist/web/client/assets/wardley-WFR3VGLG-B8ZSHeDu.js +0 -1
  1063. package/dist/web/client/assets/wardleyDiagram-VM6X3IG4-Qks2FmIn.js +0 -78
  1064. package/dist/web/client/assets/xychartDiagram-S5SC5T6Z-BBBjRtiE.js +0 -7
  1065. package/dist/web/client/index.html +0 -6
  1066. package/dist/web/ops-worker.js +0 -37
  1067. package/dist/web/reads-worker.js +0 -1726
  1068. package/dist/web/server.js +0 -8499
  1069. package/dist/web-EMGUGGEI.js +0 -13
  1070. package/dist/web-fetch-6BRRVQON.js +0 -805
  1071. package/dist/wiki-generate-XHSJTDOP.js +0 -627
  1072. package/dist/with-panes-Z6BTEHMZ.js +0 -628
  1073. package/evals/README.md +0 -9
  1074. package/evals/behavioral-corpus-grader.mjs +0 -236
  1075. package/evals/behavioral-machinery-baseline.json +0 -2276
  1076. package/evals/behavioral-machinery-driver.ts +0 -250
  1077. package/evals/behavioral-machinery-support.ts +0 -254
  1078. package/evals/behavioral-machinery.yaml +0 -614
  1079. package/evals/behavioral-model-negative-control.yaml +0 -69
  1080. package/evals/behavioral-model.yaml +0 -482
  1081. package/evals/fixtures/behavioral-facts.txt +0 -3
  1082. package/evals/fixtures/behavioral-main.ts +0 -7
  1083. package/evals/fixtures/decoy/note.txt +0 -2
  1084. package/evals/fixtures/docs-retrieval.json +0 -102
  1085. package/evals/fixtures/private/credentials.txt +0 -1
  1086. package/evals/fixtures/scalar-decision.json +0 -17
  1087. package/evals/fixtures/scout-citation-pipeline.json +0 -55
  1088. package/evals/fixtures/source-explanation.json +0 -74
  1089. package/evals/fixtures/tool-arguments.json +0 -18
  1090. package/evals/fixtures/tool-surface/read.txt +0 -4
  1091. package/evals/fixtures/tool-surface/subdir/keep.txt +0 -1
  1092. package/evals/no-edit-memory-grader.mjs +0 -149
  1093. package/evals/scalar-decision-grader.py +0 -41
  1094. package/evals/scalar-decision-machinery.ts +0 -145
  1095. package/evals/source-explanation-grader.mjs +0 -118
  1096. package/evals/tool-surface-grader.mjs +0 -53
  1097. package/evals/tool-surface-model.yaml +0 -274
  1098. package/evals/tracked-metrics-baseline.yaml +0 -229
  1099. package/evals/tracked-metrics-grader.mjs +0 -129
  1100. package/src/cli/web.ts +0 -79
  1101. package/src/domains/providers/runtimes/local-native/ollama-native.ts +0 -122
  1102. /package/dist/assets/{web-notices → gui-notices}/@hono__node-server-LICENSE +0 -0
  1103. /package/dist/assets/{web-notices → gui-notices}/hono-LICENSE +0 -0
  1104. /package/dist/{web → gui}/client/THIRD_PARTY_LICENSES.md +0 -0
  1105. /package/dist/{web → gui}/client/assets/arc-Pry-7G1_.js +0 -0
  1106. /package/dist/{web → gui}/client/assets/array-BifhSqXX.js +0 -0
  1107. /package/dist/{web → gui}/client/assets/atkinson-hyperlegible-next-latin-ext-wght-normal-C6vrW8VD.woff2 +0 -0
  1108. /package/dist/{web → gui}/client/assets/atkinson-hyperlegible-next-latin-wght-normal-BcXVPD7q.woff2 +0 -0
  1109. /package/dist/{web → gui}/client/assets/chunk-2Q5K7J3B-C1jixKkw.js +0 -0
  1110. /package/dist/{web → gui}/client/assets/chunk-5VM5RSS4-ZNzvKenW.js +0 -0
  1111. /package/dist/{web → gui}/client/assets/chunk-FOHPRMQF-CoA4358r.js +0 -0
  1112. /package/dist/{web → gui}/client/assets/chunk-JWPE2WC7-DVXcaiue.js +0 -0
  1113. /package/dist/{web → gui}/client/assets/chunk-XXDRQBXY-DqAYeljN.js +0 -0
  1114. /package/dist/{web → gui}/client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +0 -0
  1115. /package/dist/{web → gui}/client/assets/commit-mono-latin-400-normal-s0S3qwFW.woff +0 -0
  1116. /package/dist/{web → gui}/client/assets/commit-mono-latin-400-normal-wzhe4RuD.woff2 +0 -0
  1117. /package/dist/{web → gui}/client/assets/cose-bilkent-JH36ORCC-CVh1icwb.js +0 -0
  1118. /package/dist/{web → gui}/client/assets/cytoscape.esm-c2aL46s-.js +0 -0
  1119. /package/dist/{web → gui}/client/assets/dagre-C-rnJpZF.js +0 -0
  1120. /package/dist/{web → gui}/client/assets/defaultLocale-BFoDCU3G.js +0 -0
  1121. /package/dist/{web → gui}/client/assets/dist-v5Q1xZ2K.js +0 -0
  1122. /package/dist/{web → gui}/client/assets/graphlib-DS17s2tU.js +0 -0
  1123. /package/dist/{web → gui}/client/assets/init-C-OQMol4.js +0 -0
  1124. /package/dist/{web → gui}/client/assets/katex-ZlcWpGUi.js +0 -0
  1125. /package/dist/{web → gui}/client/assets/linear-SzVmGSw4.js +0 -0
  1126. /package/dist/{web → gui}/client/assets/newsreader-latin-ext-wght-normal-C-3rgBeH.woff2 +0 -0
  1127. /package/dist/{web → gui}/client/assets/newsreader-latin-wght-normal-CCVVNp6i.woff2 +0 -0
  1128. /package/dist/{web → gui}/client/assets/newsreader-vietnamese-wght-normal-Czsa-EzN.woff2 +0 -0
  1129. /package/dist/{web → gui}/client/assets/ordinal-BDEzSJ7C.js +0 -0
  1130. /package/dist/{web → gui}/client/assets/path-fybaL0A-.js +0 -0
  1131. /package/dist/{web → gui}/client/assets/prism-bash-D6zCJ74D.js +0 -0
  1132. /package/dist/{web → gui}/client/assets/prism-c-04YixN25.js +0 -0
  1133. /package/dist/{web → gui}/client/assets/prism-clike-DapgWyxx.js +0 -0
  1134. /package/dist/{web → gui}/client/assets/prism-core-BtsZdCS6.js +0 -0
  1135. /package/dist/{web → gui}/client/assets/prism-cpp-C-lJbC-6.js +0 -0
  1136. /package/dist/{web → gui}/client/assets/prism-css-CPgOzxXp.js +0 -0
  1137. /package/dist/{web → gui}/client/assets/prism-diff-BF8m0_mq.js +0 -0
  1138. /package/dist/{web → gui}/client/assets/prism-docker-DkT6yOFj.js +0 -0
  1139. /package/dist/{web → gui}/client/assets/prism-fortran-Be5x3y1V.js +0 -0
  1140. /package/dist/{web → gui}/client/assets/prism-go-C_8qAH5n.js +0 -0
  1141. /package/dist/{web → gui}/client/assets/prism-ini-BESK3y0r.js +0 -0
  1142. /package/dist/{web → gui}/client/assets/prism-javascript-BnO-swvr.js +0 -0
  1143. /package/dist/{web → gui}/client/assets/prism-json-Dp_-W-Hv.js +0 -0
  1144. /package/dist/{web → gui}/client/assets/prism-jsx-D-D0NWtC.js +0 -0
  1145. /package/dist/{web → gui}/client/assets/prism-julia-DIjOgiAV.js +0 -0
  1146. /package/dist/{web → gui}/client/assets/prism-latex-DNMbqcH_.js +0 -0
  1147. /package/dist/{web → gui}/client/assets/prism-makefile-CRKWLQ8l.js +0 -0
  1148. /package/dist/{web → gui}/client/assets/prism-markdown-C0FPJ1Iz.js +0 -0
  1149. /package/dist/{web → gui}/client/assets/prism-markup-Cp04rIa1.js +0 -0
  1150. /package/dist/{web → gui}/client/assets/prism-matlab-D-nk08al.js +0 -0
  1151. /package/dist/{web → gui}/client/assets/prism-python-CfiSVtM6.js +0 -0
  1152. /package/dist/{web → gui}/client/assets/prism-r-QmNGR8LX.js +0 -0
  1153. /package/dist/{web → gui}/client/assets/prism-rust-Bu9N8X3N.js +0 -0
  1154. /package/dist/{web → gui}/client/assets/prism-shell-session-Be4UuYoM.js +0 -0
  1155. /package/dist/{web → gui}/client/assets/prism-sql-CYhVDMEE.js +0 -0
  1156. /package/dist/{web → gui}/client/assets/prism-toml-DKb54GAT.js +0 -0
  1157. /package/dist/{web → gui}/client/assets/prism-tsx-p6J2Kc_4.js +0 -0
  1158. /package/dist/{web → gui}/client/assets/prism-typescript-BMqONzxf.js +0 -0
  1159. /package/dist/{web → gui}/client/assets/prism-yaml-C0JHu8gr.js +0 -0
  1160. /package/dist/{web → gui}/client/assets/purify.es-ChwZkWde.js +0 -0
  1161. /package/dist/{web → gui}/client/assets/rolldown-runtime-hePW80VL.js +0 -0
  1162. /package/dist/{web → gui}/client/assets/rough.esm-Dy-Kn_BL.js +0 -0
  1163. /package/dist/{web → gui}/client/assets/sizeCapture-INFHLROL-B0uUizjq.js +0 -0
  1164. /package/dist/{web → gui}/client/assets/src-B6xuSHsQ.js +0 -0
  1165. /package/dist/{web → gui}/client/clio-coder-logo.webp +0 -0
  1166. /package/dist/{web → gui}/client/icon-192.png +0 -0
  1167. /package/dist/{web → gui}/client/icon-512.png +0 -0
  1168. /package/dist/{web → gui}/client/manifest.webmanifest +0 -0
  1169. /package/dist/{web → gui}/client/offline.css +0 -0
  1170. /package/dist/{web → gui}/client/offline.html +0 -0
  1171. /package/dist/{web → gui}/client/offline.js +0 -0
  1172. /package/dist/{web → gui}/client/sw.js +0 -0
@@ -1,3151 +0,0 @@
1
- import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
- import {
3
- TASK_MEMORY_DEFAULT_PROCEDURAL_CAP,
4
- TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS,
5
- isTerminalRunEnvelope,
6
- runTaskMemoryPolicy,
7
- taskMemoryBankDelta
8
- } from "./chunk-4ATBOFRP.js";
9
- import {
10
- taskBoardCounts
11
- } from "./chunk-KOAHT3N2.js";
12
- import {
13
- hashToolCall
14
- } from "./chunk-AY4XE6GN.js";
15
- import {
16
- registerForegroundStream
17
- } from "./chunk-4HFJKRGZ.js";
18
- import {
19
- ceilChars
20
- } from "./chunk-SJMNU4ZS.js";
21
- import {
22
- BusChannels
23
- } from "./chunk-W5RM7YAH.js";
24
- import {
25
- legacyToolResultDigest,
26
- sanitizeToolResultDigest
27
- } from "./chunk-ZKQ63XZ5.js";
28
- import {
29
- captureProjectSurface,
30
- projectSurfaceTrustNotice
31
- } from "./chunk-X6FLVUM5.js";
32
- import {
33
- INSTRUCTION_SHAPED_WARNING
34
- } from "./chunk-WXA2CFJO.js";
35
- import {
36
- ToolNames
37
- } from "./chunk-V4XJWDHR.js";
38
- import {
39
- require_dist
40
- } from "./chunk-B5GGDIHT.js";
41
- import {
42
- buildSafeToolEnv
43
- } from "./chunk-XTQ7MEJG.js";
44
- import {
45
- gitCommitAttributionEnabled,
46
- reportCommitAttributionDiagnostic,
47
- withManagedGitCommitAttributionEnvironment
48
- } from "./chunk-LTR5QCLS.js";
49
- import {
50
- SKILL_INSTALL_OFFER_OPTION_NEVER,
51
- SKILL_INSTALL_OFFER_OPTION_NOT_NOW,
52
- SKILL_INSTALL_OFFER_OPTION_PROJECT,
53
- SKILL_INSTALL_OFFER_OPTION_USER,
54
- SKILL_SUGGESTION_ANCHOR,
55
- SKILL_SUGGESTION_PREFIX
56
- } from "./chunk-NBPA5QM6.js";
57
- import {
58
- clioConfigDir
59
- } from "./chunk-CTTI7G3T.js";
60
- import {
61
- safeResourceWrite
62
- } from "./chunk-ZZFWWYLX.js";
63
- import {
64
- __toESM,
65
- init_esm_shims
66
- } from "./chunk-ECBHH7LU.js";
67
-
68
- // src/domains/middleware/runtime.ts
69
- init_esm_shims();
70
-
71
- // src/domains/middleware/budget.ts
72
- init_esm_shims();
73
-
74
- // src/domains/middleware/types.ts
75
- init_esm_shims();
76
- var MIDDLEWARE_HOOKS = ["before_tool", "after_tool", "turn_start", "turn_end", "on_compaction"];
77
- var MIDDLEWARE_EFFECT_KINDS = [
78
- "inject_reminder",
79
- "annotate_tool_result",
80
- "block_tool",
81
- "protect_path",
82
- "request_continuation",
83
- "require_tool",
84
- "lock_tools"
85
- ];
86
- var MIDDLEWARE_REMINDER_SEVERITIES = ["info", "advisory", "warn", "hard-block"];
87
- var MIDDLEWARE_ANNOTATION_SEVERITIES = ["info", "warn"];
88
- var MIDDLEWARE_HOOK_TEXT_MAX_CHARS = 16e3;
89
- function metadataNumber(input, key) {
90
- const value = input.metadata?.[key];
91
- return typeof value === "number" && Number.isFinite(value) ? value : null;
92
- }
93
- function metadataString(input, key) {
94
- const value = input.metadata?.[key];
95
- return typeof value === "string" ? value : null;
96
- }
97
- function isMiddlewareHook(value) {
98
- return MIDDLEWARE_HOOKS.includes(value);
99
- }
100
- function isMiddlewareEffectKind(value) {
101
- return MIDDLEWARE_EFFECT_KINDS.includes(value);
102
- }
103
- function isMiddlewareReminderSeverity(value) {
104
- return MIDDLEWARE_REMINDER_SEVERITIES.includes(value);
105
- }
106
- function isMiddlewareAnnotationSeverity(value) {
107
- return MIDDLEWARE_ANNOTATION_SEVERITIES.includes(value);
108
- }
109
-
110
- // src/domains/middleware/budget.ts
111
- var DEFAULT_MIDDLEWARE_HOOK_BUDGETS_MS = {
112
- before_tool: 25,
113
- after_tool: 25,
114
- turn_start: 50,
115
- turn_end: 75,
116
- on_compaction: 150
117
- };
118
- var DEFAULT_HOOK_BUDGET_WARMUP_CALLS = 1;
119
- var DEFAULT_HOOK_BUDGET_WINDOW = 5;
120
- var DEFAULT_HOOK_BUDGET_THRESHOLD = 3;
121
- function parsePositiveMs(raw) {
122
- if (raw === void 0) return null;
123
- const value = Number(raw);
124
- return Number.isFinite(value) && value > 0 ? value : null;
125
- }
126
- function parsePositiveInt(raw) {
127
- if (raw === void 0) return null;
128
- const value = Number(raw);
129
- return Number.isInteger(value) && value > 0 ? value : null;
130
- }
131
- function parseNonNegativeInt(raw) {
132
- if (raw === void 0) return null;
133
- const value = Number(raw);
134
- return Number.isInteger(value) && value >= 0 ? value : null;
135
- }
136
- function hookEnvSuffix(hook) {
137
- return hook.toUpperCase();
138
- }
139
- function resolveHookBudgetsFromEnv(env = process.env) {
140
- const global = parsePositiveMs(env.CLIO_CODER_HOOK_BUDGET_MS);
141
- const map = {};
142
- for (const hook of MIDDLEWARE_HOOKS) {
143
- const perPhase = parsePositiveMs(env[`CLIO_CODER_HOOK_BUDGET_${hookEnvSuffix(hook)}_MS`]);
144
- map[hook] = perPhase ?? global ?? DEFAULT_MIDDLEWARE_HOOK_BUDGETS_MS[hook];
145
- }
146
- return map;
147
- }
148
- function resolveHookBudgetTunablesFromEnv(env = process.env) {
149
- return {
150
- warmupCalls: parseNonNegativeInt(env.CLIO_CODER_HOOK_BUDGET_WARMUP_CALLS) ?? DEFAULT_HOOK_BUDGET_WARMUP_CALLS,
151
- windowSize: parsePositiveInt(env.CLIO_CODER_HOOK_BUDGET_WINDOW) ?? DEFAULT_HOOK_BUDGET_WINDOW,
152
- threshold: parsePositiveInt(env.CLIO_CODER_HOOK_BUDGET_THRESHOLD) ?? DEFAULT_HOOK_BUDGET_THRESHOLD
153
- };
154
- }
155
- function percentile(sortedAscending, p) {
156
- if (sortedAscending.length === 0) return 0;
157
- const rank = Math.ceil(p / 100 * sortedAscending.length);
158
- const index = Math.min(sortedAscending.length - 1, Math.max(0, rank - 1));
159
- return sortedAscending[index] ?? 0;
160
- }
161
- function createHookBudgetTracker(options = {}) {
162
- const budgets = { ...DEFAULT_MIDDLEWARE_HOOK_BUDGETS_MS, ...options.budgets ?? {} };
163
- const warmupCalls = Math.max(0, options.warmupCalls ?? DEFAULT_HOOK_BUDGET_WARMUP_CALLS);
164
- const windowSize = Math.max(1, options.windowSize ?? DEFAULT_HOOK_BUDGET_WINDOW);
165
- const threshold = Math.min(windowSize, Math.max(1, options.threshold ?? DEFAULT_HOOK_BUDGET_THRESHOLD));
166
- const states = /* @__PURE__ */ new Map();
167
- function statsFor(state, budgetMs) {
168
- const sorted = [...state.window].sort((a, b) => a - b);
169
- const overCount = state.window.reduce((count, ms) => ms > budgetMs ? count + 1 : count, 0);
170
- return {
171
- sampleCount: state.postWarmupCalls,
172
- window: state.window.length,
173
- overCount,
174
- p50Ms: percentile(sorted, 50),
175
- p95Ms: percentile(sorted, 95)
176
- };
177
- }
178
- return {
179
- budgetFor(hook) {
180
- return budgets[hook];
181
- },
182
- record(registrationId, hook, elapsedMs) {
183
- const budgetMs = budgets[hook];
184
- const exceeded = elapsedMs > budgetMs;
185
- const key = `${registrationId}\0${hook}`;
186
- let state = states.get(key);
187
- if (state === void 0) {
188
- state = { calls: 0, postWarmupCalls: 0, window: [] };
189
- states.set(key, state);
190
- }
191
- state.calls += 1;
192
- if (state.calls <= warmupCalls) {
193
- return {
194
- budgetMs,
195
- exceeded,
196
- warmup: true,
197
- warn: false,
198
- stats: { sampleCount: 0, window: 0, overCount: 0, p50Ms: 0, p95Ms: 0 }
199
- };
200
- }
201
- state.postWarmupCalls += 1;
202
- state.window.push(elapsedMs);
203
- if (state.window.length > windowSize) state.window.shift();
204
- const stats = statsFor(state, budgetMs);
205
- return {
206
- budgetMs,
207
- exceeded,
208
- warmup: false,
209
- warn: exceeded && stats.overCount >= threshold,
210
- stats
211
- };
212
- }
213
- };
214
- }
215
-
216
- // src/domains/middleware/rules.ts
217
- init_esm_shims();
218
-
219
- // src/domains/middleware/injection-screen.ts
220
- init_esm_shims();
221
- var INJECTION_SCREEN_RULE = {
222
- rule: {
223
- id: "safety.untrusted-instructions",
224
- source: "builtin",
225
- description: "Warn when external tool data contains instruction-shaped markers",
226
- enabled: true,
227
- hooks: ["after_tool"],
228
- effectKinds: ["annotate_tool_result"]
229
- },
230
- toolNames: ["web_fetch", "read", "bash", "dispatch", "monitor"],
231
- predicate: (input) => input.metadata?.untrustedInstructionMarkers === true,
232
- effects: [
233
- {
234
- kind: "annotate_tool_result",
235
- severity: "warn",
236
- message: INSTRUCTION_SHAPED_WARNING
237
- }
238
- ]
239
- };
240
-
241
- // src/domains/middleware/stalled-turn.ts
242
- init_esm_shims();
243
- var STALLED_TURN_REGISTRATION_ID = "nudge.stalled-turn";
244
- var STALLED_TURN_REQUEST_CONTINUATION_MESSAGE = "You ended your turn after announcing an action without executing it: no tools were called. Continue now and perform the announced action, or state plainly that you are finished and waiting for the user.";
245
- var SKILL_SUGGESTION_WAIT_CONTINUATION_MESSAGE = "You ended your turn on a skill suggestion without doing the task. The suggestion line has already made the offer and only the operator loads a skill, so the skill choice needs nothing from them before you proceed. Continue the already-authorized task now without the skill. This continuation is not an operator answer to any other question: if the remaining work is a proposal awaiting an explicit operator go-ahead, park it on the task board and say so instead of implementing.";
246
- var INTENT_PATTERN = /\b(let me|i['’]ll|i will|i am going to|i['’]m going to|now i|next i|let's|let us)\b/i;
247
- var CONCRETE_ACTION_STEMS = [
248
- "add",
249
- "analyse",
250
- "analyze",
251
- "apply",
252
- "audit",
253
- "build",
254
- "change",
255
- "check",
256
- "compare",
257
- "compile",
258
- "create",
259
- "debug",
260
- "delete",
261
- "edit",
262
- "execute",
263
- "explore",
264
- "find",
265
- "fix",
266
- "format",
267
- "grep",
268
- "implement",
269
- "inspect",
270
- "install",
271
- "investigate",
272
- "list",
273
- "load",
274
- "look",
275
- "modify",
276
- "open",
277
- "patch",
278
- "query",
279
- "read",
280
- "refactor",
281
- "remove",
282
- "rename",
283
- "replace",
284
- "review",
285
- "run",
286
- "scan",
287
- "search",
288
- "test",
289
- "trace",
290
- "update",
291
- "validate",
292
- "verify",
293
- "write"
294
- ];
295
- var DOUBLED_CONSONANT_STEMS = /* @__PURE__ */ new Set(["debug", "format", "run", "scan"]);
296
- function concreteActionForms(stem) {
297
- const forms = /* @__PURE__ */ new Set([stem, `${stem}s`, `${stem}ed`, `${stem}ing`]);
298
- if (/(?:ch|sh|s|x|z)$/.test(stem)) forms.add(`${stem}es`);
299
- if (stem.endsWith("e")) {
300
- forms.add(`${stem}d`);
301
- forms.add(`${stem.slice(0, -1)}ing`);
302
- }
303
- if (stem.endsWith("y")) {
304
- forms.add(`${stem.slice(0, -1)}ies`);
305
- forms.add(`${stem.slice(0, -1)}ied`);
306
- }
307
- if (DOUBLED_CONSONANT_STEMS.has(stem)) {
308
- const doubled = `${stem}${stem.slice(-1)}`;
309
- forms.add(`${doubled}ed`);
310
- forms.add(`${doubled}ing`);
311
- }
312
- return [...forms];
313
- }
314
- var CONCRETE_ACTION_PATTERN = new RegExp(
315
- `\\b(?:${CONCRETE_ACTION_STEMS.flatMap(concreteActionForms).join("|")})\\b`,
316
- "giu"
317
- );
318
- var NAMED_PATH_EXTENSIONS = "c|cc|cfg|cjs|cmake|conf|cpp|cs|css|csv|env|go|h|hpp|html|ini|java|jl|js|json|jsx|lock|log|lua|md|mjs|nc|php|py|rb|rs|rst|sh|sql|toml|ts|tsx|txt|yaml|yml";
319
- var NAMED_PATH_PATTERN = new RegExp(
320
- `(?:^|[\\s\`"'(\\[])(?:[\\w@.\\-/]*[\\w@\\-]\\.(?:${NAMED_PATH_EXTENSIONS})\\b|(?:\\.{1,2}|~)\\/[\\w@.\\-/]+)`,
321
- "iu"
322
- );
323
- var NAMED_COMMAND_PATTERN = /\b(?:npm|npx|pnpm|yarn|bun|git|cargo|rustc|cmake|ctest|ninja|meson|bazel|gradle|mvn|pytest|pip|python3?|node|deno|tsc|biome|eslint|prettier|jest|vitest|ruff|mypy|docker|kubectl|mpirun|srun|sbatch|gcc|clang)\s+[-\w./]/iu;
324
- var ACTION_OBJECT_CONNECTOR_PATTERN = /^(?:at|for|in|into|on|through|to)\s+/i;
325
- var ACTION_OBJECT_DETERMINER_PATTERN = /^(?:a|an|my|our|that|the|their|these|this|those|your)\s+/i;
326
- var ACTION_OBJECT_PATTERN = /^(?!(?:again|everyone|later|next|now|soon|then|you)\b)[`"'./~]*[\p{L}\p{N}_-]/iu;
327
- var CONDITIONAL_LEAD_IN_PATTERN = /\b(?:if|once|unless|until|when|whenever)\b/i;
328
- var CONDITIONAL_INVITATION_PATTERN = /\b(?:answer|approve|ask|confirm|give|point|reply|respond|say|send|share|tell|type)\b[\s\S]*\b(?:and|then)\s*$/i;
329
- var CONDITIONAL_OFFER_SUFFIX_PATTERN = /\b(?:if\s+(?:needed|necessary|requested|approved|confirmed)\b|(?:if|after|once|until|unless|when(?:ever)?|as\s+soon\s+as|provided|assuming)\b[^.!?]*\byou\b|(?:upon|on|after|with|pending|awaiting|following)\s+(?:your\s+|the\s+operator(?:'s)?\s+)?(?:approval|go-?ahead|confirmation|sign-?off|decision|word|green\s+light|okay|ok)\b)/i;
330
- var OPERATOR_WAIT_LEAD_PATTERN = /\b(?:await(?:ing)?|pending|waiting\s+(?:for|on))\b/i;
331
- var NEGATED_OR_HYPOTHETICAL_CLAUSE_PATTERN = /^\s*(?:not|never|would|could|might|may)\b/i;
332
- var LET_ME_KNOW_PATTERN = /\blet me know\b/i;
333
- var DEFERRAL_LEAD_PATTERN = /^\s*(?:just\s+|simply\s+|now\s+)?(?:wait|hold\s+off|hold|stand\s+by|pause|defer)\b/i;
334
- var COMPLETION_PATTERN = /^\s*(?:all\s+done|done|complete|completed|all\s+set)\b|^\s*(?:here(?:'s| is)\s+)?(?:a\s+)?summary\b|^\s*summary\s*:?$/i;
335
- var STALLED_TURN_RULE_DEFINITION = {
336
- rule: {
337
- id: STALLED_TURN_REGISTRATION_ID,
338
- source: "builtin",
339
- description: "request an automatic continuation when a turn announces work but calls no tools",
340
- enabled: true,
341
- hooks: ["turn_end"],
342
- effectKinds: ["request_continuation"]
343
- },
344
- effects: [{ kind: "request_continuation", message: STALLED_TURN_REQUEST_CONTINUATION_MESSAGE }],
345
- predicate: shouldRequestStalledTurnContinuation
346
- };
347
- var SKILL_WAIT_PATTERN = /\/skill\b|\bskills?\b|\bskip\b/i;
348
- function isSkillSuggestionWait(input) {
349
- if (input.hook !== "turn_end") return false;
350
- if (!isNormalStopReason(input.metadata?.stopReason)) return false;
351
- const text = input.text ?? "";
352
- if (!text.includes(SKILL_SUGGESTION_PREFIX)) return false;
353
- const toolNames = metadataString(input, "turnToolNames");
354
- if (toolNames === null) {
355
- if ((metadataNumber(input, "turnToolCalls") ?? 0) !== 0) return false;
356
- } else if (toolNames.split(",").filter((name) => name.length > 0).some((name) => name !== ToolNames.Context)) {
357
- return false;
358
- }
359
- const lastLine = lastNonEmptyLine(text);
360
- if (lastLine === null) return false;
361
- const finalSentence = lastSentence(lastLine);
362
- if (finalSentence.length === 0) return false;
363
- return SKILL_WAIT_PATTERN.test(finalSentence) || isQuestion(finalSentence) || LET_ME_KNOW_PATTERN.test(finalSentence);
364
- }
365
- function shouldRequestStalledTurnContinuation(input) {
366
- if (input.hook !== "turn_end") return false;
367
- if (input.metadata?.turnToolCalls !== 0) return false;
368
- if (!isNormalStopReason(input.metadata?.stopReason)) return false;
369
- const lastLine = lastNonEmptyLine(input.text ?? "");
370
- if (lastLine === null) return false;
371
- const finalSentence = lastSentence(lastLine);
372
- if (finalSentence.length === 0) return false;
373
- if (isQuestion(finalSentence)) return false;
374
- if (LET_ME_KNOW_PATTERN.test(finalSentence)) return false;
375
- if (COMPLETION_PATTERN.test(lastLine) || COMPLETION_PATTERN.test(finalSentence)) return false;
376
- return announcesConcreteAction(finalSentence);
377
- }
378
- function announcesConcreteAction(sentence) {
379
- const intent = INTENT_PATTERN.exec(sentence);
380
- if (intent) {
381
- const leadIn = sentence.slice(0, intent.index);
382
- if (CONDITIONAL_LEAD_IN_PATTERN.test(leadIn) || CONDITIONAL_INVITATION_PATTERN.test(leadIn) || OPERATOR_WAIT_LEAD_PATTERN.test(leadIn) || CONDITIONAL_OFFER_SUFFIX_PATTERN.test(sentence)) {
383
- return false;
384
- }
385
- const clause = sentence.slice(intent.index + intent[0].length);
386
- if (DEFERRAL_LEAD_PATTERN.test(clause)) return false;
387
- if (NEGATED_OR_HYPOTHETICAL_CLAUSE_PATTERN.test(clause)) return false;
388
- if (hasActionWithObject(clause)) return true;
389
- if (CONDITIONAL_LEAD_IN_PATTERN.test(clause)) return false;
390
- return namesToolTarget(clause);
391
- }
392
- return sentence.endsWith(":") && hasActionWithObject(sentence);
393
- }
394
- function namesToolTarget(clause) {
395
- return NAMED_PATH_PATTERN.test(clause) || NAMED_COMMAND_PATTERN.test(clause);
396
- }
397
- function hasActionWithObject(clause) {
398
- for (const action of clause.matchAll(CONCRETE_ACTION_PATTERN)) {
399
- const remainder = clause.slice((action.index ?? 0) + action[0].length).trimStart();
400
- const withoutConnector = remainder.replace(ACTION_OBJECT_CONNECTOR_PATTERN, "");
401
- const object = withoutConnector.replace(ACTION_OBJECT_DETERMINER_PATTERN, "");
402
- if (ACTION_OBJECT_PATTERN.test(object)) return true;
403
- }
404
- return false;
405
- }
406
- function isNormalStopReason(value) {
407
- if (value === void 0 || value === null) return true;
408
- if (typeof value !== "string") return false;
409
- const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
410
- return normalized === "stop" || normalized === "end_turn" || normalized.startsWith("stop_sequence");
411
- }
412
- function lastNonEmptyLine(text) {
413
- const lines = text.split(/\r?\n/);
414
- for (let index = lines.length - 1; index >= 0; index -= 1) {
415
- const line = lines[index]?.trim();
416
- if (line && line.length > 0) return line;
417
- }
418
- return null;
419
- }
420
- var SENTENCE_TERMINATOR_PATTERN = /[.!?]+["'’)\]]*(?=\s|$)/gu;
421
- function lastSentence(line) {
422
- const trimmed = line.trimEnd();
423
- let start = 0;
424
- for (const terminator of trimmed.matchAll(SENTENCE_TERMINATOR_PATTERN)) {
425
- const end = (terminator.index ?? 0) + terminator[0].length;
426
- if (end >= trimmed.length) break;
427
- start = end;
428
- }
429
- return trimmed.slice(start).replace(/^[\s"'([{-]+/, "").trim();
430
- }
431
- function isQuestion(sentence) {
432
- return /[?]["')\]]*$/.test(sentence.trim());
433
- }
434
-
435
- // src/domains/middleware/rules.ts
436
- var BUILTIN_MIDDLEWARE_RULE_DEFINITIONS = [
437
- STALLED_TURN_RULE_DEFINITION,
438
- INJECTION_SCREEN_RULE
439
- ];
440
- var BUILTIN_MIDDLEWARE_RULE_IDS = BUILTIN_MIDDLEWARE_RULE_DEFINITIONS.map((definition) => definition.rule.id);
441
- function listMiddlewareRuleDefinitions() {
442
- return BUILTIN_MIDDLEWARE_RULE_DEFINITIONS.map(cloneRuleDefinition);
443
- }
444
- function listMiddlewareRules() {
445
- return BUILTIN_MIDDLEWARE_RULE_DEFINITIONS.map((definition) => cloneMiddlewareRule(definition.rule));
446
- }
447
- function cloneMiddlewareRule(rule) {
448
- return {
449
- id: rule.id,
450
- source: rule.source,
451
- description: rule.description,
452
- enabled: rule.enabled,
453
- hooks: [...rule.hooks],
454
- effectKinds: [...rule.effectKinds]
455
- };
456
- }
457
- function cloneRuleDefinition(definition) {
458
- const cloned = {
459
- rule: cloneMiddlewareRule(definition.rule),
460
- effects: [...definition.effects]
461
- };
462
- if (definition.toolNames !== void 0) cloned.toolNames = [...definition.toolNames];
463
- if (definition.predicate !== void 0) cloned.predicate = definition.predicate;
464
- return cloned;
465
- }
466
-
467
- // src/domains/middleware/runtime.ts
468
- function writeMiddlewareDiagnosticToStderr(diagnostic) {
469
- if (diagnostic.kind === "hook_failed") {
470
- process.stderr.write(
471
- `[clio-coder:middleware] registration '${diagnostic.registrationId}' failed on '${diagnostic.hook}': ${diagnostic.message}
472
- `
473
- );
474
- return;
475
- }
476
- if (diagnostic.kind === "registration_conflict") {
477
- process.stderr.write(`[clio-coder:middleware] ${formatRegistrationConflict(diagnostic)}
478
- `);
479
- return;
480
- }
481
- if (!diagnostic.steadyStateWarn && process.env.CLIO_CODER_HOOK_BUDGET_DEBUG !== "1") return;
482
- const stats = diagnostic.stats;
483
- const trend = stats.window > 0 ? ` (slow on ${stats.overCount}/${stats.window} recent ${diagnostic.hook} calls, p95 ${stats.p95Ms.toFixed(1)}ms)` : "";
484
- process.stderr.write(
485
- `[clio-coder:middleware] registration '${diagnostic.registrationId}' exceeded budget on '${diagnostic.hook}': ${diagnostic.elapsedMs.toFixed(1)}ms > ${diagnostic.budgetMs}ms${trend}
486
- `
487
- );
488
- }
489
- function formatRegistrationConflict(diagnostic) {
490
- return diagnostic.action === "dropped" ? `${diagnostic.owner} registration '${diagnostic.registrationId}' (generation ${diagnostic.generation}) dropped: id is held by a ${diagnostic.conflictsWith} registration` : `${diagnostic.owner} registration '${diagnostic.registrationId}' (generation ${diagnostic.generation}) evicted by a ${diagnostic.conflictsWith} registration with the same id`;
491
- }
492
- function registrationFromRuleDefinition(definition) {
493
- const registration = {
494
- id: definition.rule.id,
495
- description: definition.rule.description,
496
- hooks: [...definition.rule.hooks],
497
- evaluate: (input) => evaluateRuleDefinition(definition, input)
498
- };
499
- if (definition.toolNames !== void 0) registration.toolNames = [...definition.toolNames];
500
- return registration;
501
- }
502
- function runMiddlewareRegistrations(input, registrations, options = {}) {
503
- const onDiagnostic = options.onDiagnostic ?? writeMiddlewareDiagnosticToStderr;
504
- const now = options.now ?? (() => performance.now());
505
- const budgetTracker = options.budgetTracker ?? createHookBudgetTracker();
506
- const effects = [];
507
- const ruleIds = [];
508
- for (const registration of registrations) {
509
- if (!registration.hooks.includes(input.hook)) continue;
510
- if (registration.toolNames !== void 0) {
511
- if (input.toolName === void 0) continue;
512
- if (!registration.toolNames.includes(input.toolName)) continue;
513
- }
514
- let emitted;
515
- const startedAt = now();
516
- try {
517
- emitted = registration.evaluate(cloneHookInput(input), { priorEffects: [...effects] });
518
- } catch (err) {
519
- emitDiagnostic(onDiagnostic, {
520
- kind: "hook_failed",
521
- registrationId: registration.id,
522
- hook: input.hook,
523
- message: err instanceof Error ? err.message : String(err)
524
- });
525
- continue;
526
- }
527
- const elapsedMs = now() - startedAt;
528
- const outcome = budgetTracker.record(registration.id, input.hook, elapsedMs);
529
- if (outcome.exceeded && !outcome.warmup) {
530
- emitDiagnostic(onDiagnostic, {
531
- kind: "budget_exceeded",
532
- registrationId: registration.id,
533
- hook: input.hook,
534
- elapsedMs,
535
- budgetMs: outcome.budgetMs,
536
- steadyStateWarn: outcome.warn,
537
- stats: outcome.stats
538
- });
539
- }
540
- if (emitted.length === 0) continue;
541
- for (const effect of emitted) {
542
- effects.push(cloneMiddlewareEffect(effect));
543
- }
544
- if (!ruleIds.includes(registration.id)) ruleIds.push(registration.id);
545
- }
546
- return {
547
- hook: input.hook,
548
- input: cloneHookInput(input),
549
- effects,
550
- ruleIds
551
- };
552
- }
553
- async function runMiddlewareAsyncRegistrations(input, registrations, priorEffects = [], options = {}) {
554
- const onDiagnostic = options.onDiagnostic ?? writeMiddlewareDiagnosticToStderr;
555
- const effects = [];
556
- const ruleIds = [];
557
- for (const registration of registrations) {
558
- if (registration.evaluateAsync === void 0 || !registration.hooks.includes(input.hook)) continue;
559
- if (registration.toolNames !== void 0) {
560
- if (input.toolName === void 0 || !registration.toolNames.includes(input.toolName)) continue;
561
- }
562
- let emitted;
563
- try {
564
- emitted = await registration.evaluateAsync(cloneHookInput(input), {
565
- priorEffects: [...priorEffects, ...effects]
566
- });
567
- } catch (err) {
568
- emitDiagnostic(onDiagnostic, {
569
- kind: "hook_failed",
570
- registrationId: registration.id,
571
- hook: input.hook,
572
- message: err instanceof Error ? err.message : String(err)
573
- });
574
- continue;
575
- }
576
- for (const effect of emitted) effects.push(cloneMiddlewareEffect(effect));
577
- if (emitted.length > 0) ruleIds.push(registration.id);
578
- }
579
- return { hook: input.hook, input: cloneHookInput(input), effects, ruleIds };
580
- }
581
- function emitDiagnostic(sink, diagnostic) {
582
- try {
583
- sink(diagnostic);
584
- } catch {
585
- }
586
- }
587
- function evaluateRuleDefinition(definition, input) {
588
- const rule = definition.rule;
589
- if (!rule.enabled) return [];
590
- if (!rule.hooks.includes(input.hook)) return [];
591
- if (definition.toolNames !== void 0) {
592
- if (input.toolName === void 0) return [];
593
- if (!definition.toolNames.includes(input.toolName)) return [];
594
- }
595
- if (definition.predicate !== void 0 && !definition.predicate(input)) return [];
596
- const declaredKinds = new Set(rule.effectKinds);
597
- const emitted = [];
598
- for (const effect of definition.effects) {
599
- if (!declaredKinds.has(effect.kind)) continue;
600
- emitted.push(cloneMiddlewareEffect(effect));
601
- }
602
- return emitted;
603
- }
604
- function cloneMiddlewareEffect(effect) {
605
- switch (effect.kind) {
606
- case "inject_reminder": {
607
- const cloned = { kind: "inject_reminder", message: effect.message };
608
- if (effect.severity !== void 0) cloned.severity = effect.severity;
609
- return cloned;
610
- }
611
- case "annotate_tool_result": {
612
- const cloned = { kind: "annotate_tool_result", message: effect.message };
613
- if (effect.severity !== void 0) cloned.severity = effect.severity;
614
- return cloned;
615
- }
616
- case "block_tool":
617
- return { kind: "block_tool", reason: effect.reason, severity: effect.severity };
618
- case "protect_path":
619
- return { kind: "protect_path", path: effect.path, reason: effect.reason };
620
- case "request_continuation":
621
- return { kind: "request_continuation", message: effect.message };
622
- case "require_tool":
623
- return { kind: "require_tool", toolName: effect.toolName };
624
- case "lock_tools":
625
- return { kind: "lock_tools" };
626
- }
627
- }
628
- function cloneHookInput(input) {
629
- const cloned = { hook: input.hook };
630
- if (input.runId !== void 0) cloned.runId = input.runId;
631
- if (input.sessionId !== void 0) cloned.sessionId = input.sessionId;
632
- if (input.turnId !== void 0) cloned.turnId = input.turnId;
633
- if (input.toolCallId !== void 0) cloned.toolCallId = input.toolCallId;
634
- if (input.correlationId !== void 0) cloned.correlationId = input.correlationId;
635
- if (input.toolName !== void 0) cloned.toolName = input.toolName;
636
- if (input.modelId !== void 0) cloned.modelId = input.modelId;
637
- if (input.metadata !== void 0) cloned.metadata = { ...input.metadata };
638
- if (input.toolArgs !== void 0) cloned.toolArgs = { ...input.toolArgs };
639
- if (input.toolResultDetails !== void 0) cloned.toolResultDetails = { ...input.toolResultDetails };
640
- if (input.toolResultDigest !== void 0) {
641
- cloned.toolResultDigest = {
642
- text: input.toolResultDigest.text,
643
- provenance: { ...input.toolResultDigest.provenance }
644
- };
645
- }
646
- if (input.text !== void 0) cloned.text = input.text.slice(0, MIDDLEWARE_HOOK_TEXT_MAX_CHARS);
647
- return cloned;
648
- }
649
-
650
- // src/domains/middleware/dispatch-nudge.ts
651
- init_esm_shims();
652
- var DETACHED_DISPATCH_NUDGE_REGISTRATION_ID = "nudge.detached-dispatch";
653
- var READ_ONLY_EXPLORATION_NUDGE_REGISTRATION_ID = "nudge.read-only-exploration";
654
- var READ_ONLY_EXPLORATION_NUDGE_CALL_THRESHOLD = 9;
655
- var UNBACKED_WORKER_CLAIM_REGISTRATION_ID = "rail.unbacked-worker-claim";
656
- var SCOUT_AGENT_ID = "scout";
657
- var EXPLORATION_TOOL_NAMES = /* @__PURE__ */ new Set([
658
- ToolNames.Read,
659
- ToolNames.Grep,
660
- ToolNames.Find,
661
- ToolNames.Ls,
662
- ToolNames.CodeNav,
663
- ToolNames.Context,
664
- ToolNames.Git
665
- ]);
666
- var EXPLORATION_NUDGE_TURN_LIMIT = 32;
667
- var NO_TURN = "no-turn";
668
- var READ_ONLY_SHELL_COMMAND_PATTERN = /^\s*(?:awk|cat|fd|find|git|grep|head|jq|ls|rg|sed|tail|tree|wc)\b/;
669
- function buildReadOnlyExplorationMessage() {
670
- return `[Clio Coder] This turn used ${READ_ONLY_EXPLORATION_NUDGE_CALL_THRESHOLD}+ read-only exploration calls without a successful Scout dispatch; delegate broad repository reconnaissance to Scout.`;
671
- }
672
- function stringValue(value) {
673
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
674
- }
675
- function recordValue(value) {
676
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
677
- }
678
- function ordinaryDispatchAgents(args) {
679
- if (!args || args.list === true || args.apply_winner !== void 0 || args.review !== void 0 && args.review !== false || args.mode === "compete") {
680
- return null;
681
- }
682
- let tasks = args.tasks;
683
- if (typeof tasks === "string") {
684
- const raw = tasks.trim();
685
- if (raw.startsWith("[") || raw.startsWith("{")) {
686
- try {
687
- tasks = JSON.parse(raw);
688
- } catch {
689
- }
690
- }
691
- }
692
- if (recordValue(tasks) !== null || typeof tasks === "string") tasks = [tasks];
693
- if (tasks === void 0 && typeof args.task === "string") tasks = [{ task: args.task }];
694
- if (!Array.isArray(tasks) || tasks.length === 0) return null;
695
- const sharedAgent = stringValue(args.agent) ?? stringValue(args.agent_id) ?? "coder";
696
- const agents = [];
697
- for (const task of tasks) {
698
- if (typeof task === "string") {
699
- if (stringValue(task) === null) return null;
700
- agents.push(sharedAgent);
701
- continue;
702
- }
703
- const record = recordValue(task);
704
- if (!record || stringValue(record.task) === null) return null;
705
- agents.push(stringValue(record.agent) ?? stringValue(record.agent_id) ?? sharedAgent);
706
- }
707
- return agents;
708
- }
709
- function dispatchTargetsScout(args) {
710
- return ordinaryDispatchAgents(args)?.some((agent) => agent.toLowerCase() === SCOUT_AGENT_ID) === true;
711
- }
712
- function isNonRepositoryContextCall(input) {
713
- if (input.toolName !== ToolNames.Context) return false;
714
- const scope = stringValue(input.toolArgs?.scope)?.toLowerCase();
715
- return scope !== null && scope !== "workspace";
716
- }
717
- function isReadOnlyExplorationCall(input) {
718
- if (isNonRepositoryContextCall(input)) return false;
719
- if (input.toolName && EXPLORATION_TOOL_NAMES.has(input.toolName)) return true;
720
- if (input.toolName !== ToolNames.Bash) return false;
721
- const command = input.toolArgs?.command;
722
- return typeof command === "string" && READ_ONLY_SHELL_COMMAND_PATTERN.test(command);
723
- }
724
- function hasActiveTool(input, toolName) {
725
- const activeToolNames = input.metadata?.activeToolNames;
726
- return typeof activeToolNames === "string" && activeToolNames.split(",").map((name) => name.trim()).includes(toolName);
727
- }
728
- function newExplorationTurnState(advised = false) {
729
- return {
730
- readOnlyCalls: 0,
731
- scoutSucceeded: false,
732
- advised
733
- };
734
- }
735
- function markScoutSuccess(state) {
736
- state.scoutSucceeded = true;
737
- }
738
- function createReadOnlyExplorationNudgeRegistration() {
739
- const byTurn = /* @__PURE__ */ new Map();
740
- const turnKey = (input) => {
741
- const userTurnId = input.hook === "turn_end" ? input.metadata?.userTurnId : void 0;
742
- return (typeof userTurnId === "string" && userTurnId.length > 0 ? userTurnId : input.turnId) ?? input.runId ?? NO_TURN;
743
- };
744
- const remember = (key, state) => {
745
- if (byTurn.size >= EXPLORATION_NUDGE_TURN_LIMIT && !byTurn.has(key)) {
746
- const oldest = byTurn.keys().next().value;
747
- if (oldest !== void 0) byTurn.delete(oldest);
748
- }
749
- byTurn.set(key, state);
750
- return state;
751
- };
752
- const stateForTool = (key) => byTurn.get(key) ?? remember(key, newExplorationTurnState());
753
- const takeTurnEndState = (key) => {
754
- const bound = byTurn.get(key);
755
- if (bound === void 0) return null;
756
- byTurn.set(key, newExplorationTurnState(bound.advised));
757
- return bound;
758
- };
759
- const markAdvised = (key) => {
760
- const carried = byTurn.get(key);
761
- if (carried) carried.advised = true;
762
- };
763
- return {
764
- id: READ_ONLY_EXPLORATION_NUDGE_REGISTRATION_ID,
765
- description: "advise Scout delegation after prolonged read-only repository exploration",
766
- hooks: ["before_tool", "after_tool", "turn_end"],
767
- evaluate(input) {
768
- const key = turnKey(input);
769
- if (input.hook === "before_tool" || input.hook === "after_tool") {
770
- const state2 = stateForTool(key);
771
- if (input.toolName === ToolNames.Dispatch) {
772
- if (input.hook === "after_tool" && dispatchTargetsScout(input.toolArgs)) {
773
- if (input.metadata?.resultKind === "ok") markScoutSuccess(state2);
774
- }
775
- return [];
776
- }
777
- if (input.hook === "after_tool" || !isReadOnlyExplorationCall(input)) return [];
778
- state2.readOnlyCalls += 1;
779
- return [];
780
- }
781
- if (input.hook !== "turn_end") return [];
782
- const state = takeTurnEndState(key);
783
- const stopReason = input.metadata?.stopReason;
784
- if (stopReason !== void 0 && stopReason !== "stop") return [];
785
- if (!hasActiveTool(input, ToolNames.Dispatch)) return [];
786
- if (!state || state.advised || state.scoutSucceeded || state.readOnlyCalls < READ_ONLY_EXPLORATION_NUDGE_CALL_THRESHOLD) {
787
- return [];
788
- }
789
- markAdvised(key);
790
- return [{ kind: "inject_reminder", message: buildReadOnlyExplorationMessage(), severity: "info" }];
791
- }
792
- };
793
- }
794
- var WORKER_NOUN = "(?:scouts?|shadow (?:agent|worker)s?|sub-?agents?|workers?)";
795
- var RESULT_VERB = "(?:found|reported|returned|investigated|explored|concluded|confirmed|discovered|surfaced|completed|is complete|came back)";
796
- var WORKER_CLAIM_PATTERNS = [
797
- // "the scout found ...", "the scout investigation is complete", "workers came back ..."
798
- new RegExp(`\\b${WORKER_NOUN}\\b[^.\\n]{0,40}?\\b${RESULT_VERB}\\b`, "i"),
799
- // "... reported by the scout"
800
- new RegExp(`\\b${RESULT_VERB}\\b[^.\\n]{0,24}\\bby\\s+(?:the\\s+|a\\s+|our\\s+)?${WORKER_NOUN}\\b`, "i"),
801
- // A titled worker deliverable: "Scout Shadow Report", "Worker findings".
802
- /\b(?:scout|shadow|worker)\b[^\n]{0,20}\b(?:report|findings|summary)\b/i
803
- ];
804
- function claimsWorkerResults(text) {
805
- if (typeof text !== "string" || text.trim().length === 0) return false;
806
- return WORKER_CLAIM_PATTERNS.some((pattern) => pattern.test(text));
807
- }
808
- function buildUnbackedWorkerClaimMessage() {
809
- return "[Clio Coder] no dispatch ran this turn; worker results named above are not backed by a receipt. Dispatch the work or state plainly that you did it inline.";
810
- }
811
- function createUnbackedWorkerClaimRegistration() {
812
- const dispatchedTurns = /* @__PURE__ */ new Set();
813
- const turnKey = (input) => {
814
- const userTurnId = input.hook === "turn_end" ? input.metadata?.userTurnId : void 0;
815
- return (typeof userTurnId === "string" && userTurnId.length > 0 ? userTurnId : input.turnId) ?? input.runId ?? NO_TURN;
816
- };
817
- const remember = (key) => {
818
- if (dispatchedTurns.size >= EXPLORATION_NUDGE_TURN_LIMIT && !dispatchedTurns.has(key)) {
819
- const oldest = dispatchedTurns.values().next().value;
820
- if (oldest !== void 0) dispatchedTurns.delete(oldest);
821
- }
822
- dispatchedTurns.add(key);
823
- };
824
- return {
825
- id: UNBACKED_WORKER_CLAIM_REGISTRATION_ID,
826
- description: "contradict a worker/scout result claim that no dispatch call in the turn backs",
827
- hooks: ["after_tool", "turn_end"],
828
- evaluate(input) {
829
- const key = turnKey(input);
830
- if (input.hook === "after_tool") {
831
- if (input.toolName === ToolNames.Dispatch) remember(key);
832
- return [];
833
- }
834
- if (input.hook !== "turn_end") return [];
835
- const dispatched = dispatchedTurns.delete(key);
836
- const stopReason = input.metadata?.stopReason;
837
- if (stopReason !== void 0 && stopReason !== "stop") return [];
838
- if (!hasActiveTool(input, ToolNames.Dispatch)) return [];
839
- if (input.metadata?.sharedWorkerNote === true) return [];
840
- if (dispatched || !claimsWorkerResults(input.text)) return [];
841
- return [{ kind: "inject_reminder", message: buildUnbackedWorkerClaimMessage(), severity: "warn" }];
842
- }
843
- };
844
- }
845
- var TERMINAL_OUTCOME_ORDER = [
846
- "succeeded",
847
- "canceled",
848
- "failed",
849
- "timed_out",
850
- "stalled",
851
- "denied_by_policy",
852
- "spawn_failed",
853
- "missing",
854
- "unknown"
855
- ];
856
- function terminalOutcomeLabel(outcome) {
857
- switch (outcome) {
858
- case "timed_out":
859
- return "timed out";
860
- case "denied_by_policy":
861
- return "denied by policy";
862
- case "spawn_failed":
863
- return "spawn failed";
864
- case "missing":
865
- return "ledger row missing";
866
- case "unknown":
867
- return "outcome unknown";
868
- default:
869
- return outcome;
870
- }
871
- }
872
- function incrementTerminalOutcome(counts, outcome) {
873
- counts[outcome] = (counts[outcome] ?? 0) + 1;
874
- }
875
- function openDetachedBatchViews(dispatch) {
876
- const detached = dispatch.detached;
877
- if (!detached) return [];
878
- let records;
879
- try {
880
- records = detached.list();
881
- } catch {
882
- return [];
883
- }
884
- return records.map((record) => {
885
- let terminal = 0;
886
- const terminalOutcomes = {};
887
- for (const run of record.runs) {
888
- const row = dispatch.getRun(run.runId);
889
- if (row === null) {
890
- terminal += 1;
891
- incrementTerminalOutcome(terminalOutcomes, "missing");
892
- } else if (isTerminalRunEnvelope(row)) {
893
- terminal += 1;
894
- incrementTerminalOutcome(terminalOutcomes, row.outcome ?? "unknown");
895
- }
896
- }
897
- return { id: record.id, total: record.runs.length, terminal, terminalOutcomes };
898
- });
899
- }
900
- function detachedBatchProgress(view) {
901
- const terminalOutcomes = view.terminalOutcomes ?? {};
902
- if (view.terminal === view.total && terminalOutcomes.succeeded === view.total) {
903
- return `${view.terminal}/${view.total} run(s) done`;
904
- }
905
- let accountedFor = 0;
906
- const breakdown = TERMINAL_OUTCOME_ORDER.flatMap((outcome) => {
907
- const count = terminalOutcomes[outcome] ?? 0;
908
- accountedFor += count;
909
- return count > 0 ? [`${count} ${terminalOutcomeLabel(outcome)}`] : [];
910
- });
911
- const unavailable = Math.max(0, view.terminal - accountedFor);
912
- if (unavailable > 0) breakdown.push(`${unavailable} outcome unknown`);
913
- return `${view.terminal}/${view.total} run(s) terminal (${breakdown.join(", ")})`;
914
- }
915
- function buildDetachedBatchesMessage(ready, running) {
916
- const rows = ready.map((view) => ` - batch ${view.id}: ${detachedBatchProgress(view)}`);
917
- const runningNote = running.length > 0 ? `
918
- ${running.length} other detached batch(es) are still running; leave those for later.` : "";
919
- return `[Clio Coder] ${ready.length} detached dispatch batch(es) finished and are uncollected:
920
- ${rows.join("\n")}
921
- Collect each with monitor mode="collect" batch_id=<id> before final synthesis and act on the results. A batch stays open (and keeps nudging) until it is collected.${runningNote}`;
922
- }
923
- function createDetachedDispatchNudgeRegistration(options) {
924
- return {
925
- id: DETACHED_DISPATCH_NUDGE_REGISTRATION_ID,
926
- description: "carry the turn onward when detached dispatch results are ready to collect",
927
- hooks: ["turn_end"],
928
- evaluate(input) {
929
- if (input.hook !== "turn_end") return [];
930
- const stopReason = input.metadata?.stopReason;
931
- if (stopReason !== void 0 && stopReason !== "stop") return [];
932
- const activeToolNames = input.metadata?.activeToolNames;
933
- if (typeof activeToolNames === "string" && !activeToolNames.split(",").includes(ToolNames.Monitor)) return [];
934
- let views;
935
- try {
936
- views = options.getOpenBatches();
937
- } catch {
938
- return [];
939
- }
940
- const ready = views.filter((view) => view.total > 0 && view.terminal >= view.total);
941
- if (ready.length === 0) return [];
942
- const running = views.filter((view) => view.total > 0 && view.terminal < view.total);
943
- const message = buildDetachedBatchesMessage(ready, running);
944
- return [
945
- { kind: "request_continuation", message },
946
- { kind: "inject_reminder", message, severity: "warn" }
947
- ];
948
- }
949
- };
950
- }
951
-
952
- // src/domains/middleware/hook-receipts.ts
953
- init_esm_shims();
954
- import { readFileSync } from "node:fs";
955
- var HOOK_RECEIPT_LOG_CAPACITY = 200;
956
- var PERSIST_THROTTLE_MS = 2e3;
957
- function createHookReceiptLog(options = {}) {
958
- const capacity = options.capacity ?? HOOK_RECEIPT_LOG_CAPACITY;
959
- const now = options.now ?? Date.now;
960
- const throttleMs = options.throttleMs ?? PERSIST_THROTTLE_MS;
961
- const ring = [];
962
- let lastPersistAt = 0;
963
- let dirty = false;
964
- const persist = () => {
965
- if (options.persistPath === void 0) return;
966
- const payload = { version: 1, receipts: ring };
967
- try {
968
- safeResourceWrite(options.persistPath, `${JSON.stringify(payload, null, 2)}
969
- `, { encoding: "utf8" });
970
- dirty = false;
971
- } catch {
972
- }
973
- };
974
- return {
975
- record(receipt) {
976
- ring.push(receipt);
977
- while (ring.length > capacity) ring.shift();
978
- dirty = true;
979
- if (now() - lastPersistAt >= throttleMs) {
980
- lastPersistAt = now();
981
- persist();
982
- }
983
- },
984
- list() {
985
- return [...ring];
986
- },
987
- flush() {
988
- if (dirty) persist();
989
- }
990
- };
991
- }
992
- function readPersistedHookReceipts(persistPath) {
993
- let raw;
994
- try {
995
- raw = readFileSync(persistPath, "utf8");
996
- } catch (error) {
997
- if (error.code === "ENOENT") return [];
998
- throw error;
999
- }
1000
- const parsed = JSON.parse(raw);
1001
- if (parsed.version !== 1 || !Array.isArray(parsed.receipts)) {
1002
- throw new Error(`${persistPath}: unrecognized hook receipt log shape`);
1003
- }
1004
- return parsed.receipts;
1005
- }
1006
-
1007
- // src/domains/middleware/skills-reminder.ts
1008
- init_esm_shims();
1009
- var SKILLS_REMINDER_REGISTRATION_ID = "observer.skills-reminder";
1010
- function skillsReminderMessage(installed, installable = 0, modelActivation = false) {
1011
- const counts = installable > 0 ? `${installed} installed, ${installable} installable from the marketplace` : `${installed} installed`;
1012
- if (modelActivation) {
1013
- return `[Skills] ${counts}. Start this task by listing them with context(scope="skills") and checking for a match; if one matches, load it with context(scope="skills", name="<name>") and continue the task in the same turn. A marketplace skill is not installed and is offered for install when the operator runs it. If none match, do not mention skills and continue with the task.`;
1014
- }
1015
- return `[Skills] ${counts}. Start this task by listing them with context(scope="skills") and checking for a match; if one matches, open your reply with the line \`${SKILL_SUGGESTION_ANCHOR}\` (a comma-separated sequence, in order, when several compose) and then continue the task in the same turn without the skill. Only the operator loads a skill, and a marketplace skill is offered for install when the operator runs it. If none match, do not mention skills and continue with the task.`;
1016
- }
1017
- var NO_EFFECTS = [];
1018
- var GREETING_WORDS = /* @__PURE__ */ new Set([
1019
- "hi",
1020
- "hello",
1021
- "hey",
1022
- "heya",
1023
- "hiya",
1024
- "howdy",
1025
- "yo",
1026
- "sup",
1027
- "hola",
1028
- "greetings",
1029
- "gm",
1030
- "gn",
1031
- "morning",
1032
- "afternoon",
1033
- "evening",
1034
- "good",
1035
- "day",
1036
- "night",
1037
- "there",
1038
- "you",
1039
- "clio",
1040
- "thanks",
1041
- "thank",
1042
- "thankyou",
1043
- "thx",
1044
- "ty",
1045
- "ok",
1046
- "okay",
1047
- "k",
1048
- "cool",
1049
- "nice",
1050
- "test",
1051
- "testing",
1052
- "ping",
1053
- "pong"
1054
- ]);
1055
- function isSubstantiveUserTurn(text) {
1056
- const normalized = (text ?? "").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").replace(/\s+/g, " ").trim();
1057
- if (normalized.length === 0) return false;
1058
- const tokens = normalized.split(" ");
1059
- if (tokens.length > 4) return true;
1060
- return tokens.some((token) => !GREETING_WORDS.has(token));
1061
- }
1062
- function createSkillsReminderRegistration(deps) {
1063
- let lastSeenSessionId;
1064
- let spentForActiveSession = false;
1065
- let observedFreshStart = false;
1066
- let observedAnyTurn = false;
1067
- return {
1068
- id: SKILLS_REMINDER_REGISTRATION_ID,
1069
- description: "once per session, on the first substantive turn, teaches the skill-suggestion reply protocol; keeps a turn going that stopped on the suggestion",
1070
- hooks: ["turn_start", "turn_end"],
1071
- evaluate(input) {
1072
- if (input.hook === "turn_end") {
1073
- return isSkillSuggestionWait(input) ? [{ kind: "request_continuation", message: SKILL_SUGGESTION_WAIT_CONTINUATION_MESSAGE }] : NO_EFFECTS;
1074
- }
1075
- const sessionId = input.sessionId ?? null;
1076
- if (lastSeenSessionId === void 0) {
1077
- lastSeenSessionId = sessionId;
1078
- } else if (lastSeenSessionId === null && sessionId !== null) {
1079
- lastSeenSessionId = sessionId;
1080
- } else if (sessionId !== lastSeenSessionId) {
1081
- lastSeenSessionId = sessionId;
1082
- spentForActiveSession = false;
1083
- observedFreshStart = false;
1084
- observedAnyTurn = false;
1085
- }
1086
- if (spentForActiveSession) return NO_EFFECTS;
1087
- const conversationMessages = metadataNumber(input, "conversationMessages");
1088
- if (!observedAnyTurn) {
1089
- observedAnyTurn = true;
1090
- if (conversationMessages === null || conversationMessages > 0) {
1091
- spentForActiveSession = true;
1092
- return NO_EFFECTS;
1093
- }
1094
- observedFreshStart = true;
1095
- }
1096
- if (!observedFreshStart) {
1097
- spentForActiveSession = true;
1098
- return NO_EFFECTS;
1099
- }
1100
- if (!isSubstantiveUserTurn(input.text)) return NO_EFFECTS;
1101
- spentForActiveSession = true;
1102
- const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
1103
- if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS;
1104
- let installed = 0;
1105
- let installable = 0;
1106
- try {
1107
- installed = deps.countModelVisibleSkills();
1108
- installable = deps.countInstallableSkills?.() ?? 0;
1109
- } catch {
1110
- return NO_EFFECTS;
1111
- }
1112
- if (installed <= 0 && installable <= 0) return NO_EFFECTS;
1113
- let modelActivation = false;
1114
- try {
1115
- modelActivation = deps.modelMayActivateSkills?.() ?? false;
1116
- } catch {
1117
- }
1118
- return [
1119
- {
1120
- kind: "inject_reminder",
1121
- severity: "info",
1122
- message: skillsReminderMessage(installed, installable, modelActivation)
1123
- }
1124
- ];
1125
- }
1126
- };
1127
- }
1128
-
1129
- // src/domains/middleware/marketplace-offer.ts
1130
- init_esm_shims();
1131
- import { randomUUID } from "node:crypto";
1132
-
1133
- // src/domains/resources/skills/promotion.ts
1134
- init_esm_shims();
1135
- import { existsSync, readFileSync as readFileSync2 } from "node:fs";
1136
- import path from "node:path";
1137
- var TOKEN_STOPWORDS = /* @__PURE__ */ new Set([
1138
- "the",
1139
- "a",
1140
- "an",
1141
- "and",
1142
- "or",
1143
- "for",
1144
- "with",
1145
- "this",
1146
- "that",
1147
- "when",
1148
- "what",
1149
- "how",
1150
- "into",
1151
- "from",
1152
- "use",
1153
- "used",
1154
- "using",
1155
- "one",
1156
- "not",
1157
- "skill",
1158
- "skills",
1159
- "clio",
1160
- "please",
1161
- "can",
1162
- "you",
1163
- "should",
1164
- "would",
1165
- "about",
1166
- "need",
1167
- "want",
1168
- "help",
1169
- "make",
1170
- "file",
1171
- "files",
1172
- "code"
1173
- ]);
1174
- function normalize(text) {
1175
- return text.toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").replace(/\s+/g, " ").trim();
1176
- }
1177
- function distinctiveTokens(text) {
1178
- return new Set(
1179
- normalize(text).split(" ").filter((token) => token.length >= 4 && !TOKEN_STOPWORDS.has(token))
1180
- );
1181
- }
1182
- var TRIGGER_SCORE = 4;
1183
- var TOKEN_FIRE_THRESHOLD = 3;
1184
- function scorePromotionEntry(userText, entry) {
1185
- const haystack = ` ${normalize(userText)} `;
1186
- if (haystack.trim().length === 0) return null;
1187
- for (const trigger of entry.triggers ?? []) {
1188
- const phrase = normalize(trigger);
1189
- if (phrase.length >= 4 && haystack.includes(` ${phrase} `)) {
1190
- return { entry, score: TRIGGER_SCORE, matchedTrigger: trigger };
1191
- }
1192
- }
1193
- const requestTokens = distinctiveTokens(userText);
1194
- if (requestTokens.size === 0) return null;
1195
- const entryTokens = distinctiveTokens(`${entry.name.replace(/-/g, " ")} ${entry.description}`);
1196
- let overlap = 0;
1197
- for (const token of requestTokens) if (entryTokens.has(token)) overlap += 1;
1198
- return overlap >= TOKEN_FIRE_THRESHOLD ? { entry, score: overlap } : null;
1199
- }
1200
- function matchMarketplaceSkills(userText, entries, excludedNames) {
1201
- const matches = [];
1202
- for (const entry of entries) {
1203
- if (entry.kind !== "skill" || excludedNames.has(entry.name)) continue;
1204
- const match = scorePromotionEntry(userText, entry);
1205
- if (match) matches.push(match);
1206
- }
1207
- return matches.sort(
1208
- (a, b) => Number(b.matchedTrigger !== void 0) - Number(a.matchedTrigger !== void 0) || b.score - a.score || a.entry.name.localeCompare(b.entry.name)
1209
- );
1210
- }
1211
- var OWN_MARKETPLACE_URL_PREFIX = "https://github.com/iowarp/clio-coder/";
1212
- function isOwnMarketplaceSource(entry) {
1213
- const source = entry.sourceUrl.trim();
1214
- if (/^(?:https?:\/\/|git@)/.test(source)) return source.startsWith(OWN_MARKETPLACE_URL_PREFIX);
1215
- return entry.origin === "catalog" && path.isAbsolute(source);
1216
- }
1217
- function assertPromotionInstallSource(entry) {
1218
- if (isOwnMarketplaceSource(entry)) return;
1219
- throw new Error(
1220
- `skill promotion: refusing to install "${entry.name}" from ${entry.sourceUrl}; promotion installs only from Clio's own marketplace (local catalog or ${OWN_MARKETPLACE_URL_PREFIX}). Install manually with clio-coder library install if intended.`
1221
- );
1222
- }
1223
- var PROMOTION_DECLINES_FILE = "skill-promotion-declines.json";
1224
- function declineKey(name, version) {
1225
- return `${name}@${version ?? ""}`;
1226
- }
1227
- function declinesPath(configDir) {
1228
- return path.join(configDir ?? clioConfigDir(), PROMOTION_DECLINES_FILE);
1229
- }
1230
- function readPromotionDeclines(configDir) {
1231
- const file = declinesPath(configDir);
1232
- if (!existsSync(file)) return { never: {} };
1233
- try {
1234
- const parsed = JSON.parse(readFileSync2(file, "utf8"));
1235
- const never = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed.never : void 0;
1236
- if (never && typeof never === "object" && !Array.isArray(never)) {
1237
- const entries = Object.entries(never).filter(
1238
- (pair) => typeof pair[1] === "string"
1239
- );
1240
- return { never: Object.fromEntries(entries) };
1241
- }
1242
- } catch {
1243
- }
1244
- return { never: {} };
1245
- }
1246
- function recordPromotionNeverDecline(name, version, configDir) {
1247
- const store = readPromotionDeclines(configDir);
1248
- store.never[declineKey(name, version)] = (/* @__PURE__ */ new Date()).toISOString();
1249
- safeResourceWrite(declinesPath(configDir), `${JSON.stringify(store, null, 2)}
1250
- `, { encoding: "utf8" });
1251
- }
1252
-
1253
- // src/domains/middleware/marketplace-offer.ts
1254
- var MARKETPLACE_OFFER_REGISTRATION_ID = "observer.marketplace-offer";
1255
- var NO_EFFECTS2 = [];
1256
- function offerBindingTag(offerTag) {
1257
- return `[clio-install:${offerTag}]`;
1258
- }
1259
- function boundedDescription(text) {
1260
- return text.replace(/\[[^[\]]*\]/gu, " ").replace(/\s+/gu, " ").trim().slice(0, 200);
1261
- }
1262
- function marketplaceOfferReminder(entry, offerTag) {
1263
- return `[Marketplace] This request may need expertise no installed skill covers. The local marketplace has "${entry.name}" (not installed): ${boundedDescription(entry.description)} First check the installed side with context(scope="skills"); if ${entry.name} is genuinely the right fit and nothing installed serves, ask the operator with ask_user (mode=single_question, header "Install skill") whether to install ${entry.name}, offering exactly these options in this order: "${SKILL_INSTALL_OFFER_OPTION_PROJECT}", "${SKILL_INSTALL_OFFER_OPTION_USER}", "${SKILL_INSTALL_OFFER_OPTION_NOT_NOW}", "${SKILL_INSTALL_OFFER_OPTION_NEVER}". Include the exact tag ${offerBindingTag(offerTag)} verbatim in that question's text so the harness can bind the answer to this offer; the harness acts only on an answer carrying this tag. Then continue the task in the same turn. The harness handles the answer; never install or load a skill yourself. If it is not actually needed, do not mention it.`;
1264
- }
1265
- function answersFromDetails(details) {
1266
- const raw = details?.answers;
1267
- if (!Array.isArray(raw)) return [];
1268
- return raw.filter(
1269
- (entry) => typeof entry === "object" && entry !== null && typeof entry.question === "string" && typeof entry.answer === "string"
1270
- );
1271
- }
1272
- function chosenOfferOption(answer) {
1273
- const labels = [
1274
- SKILL_INSTALL_OFFER_OPTION_PROJECT,
1275
- SKILL_INSTALL_OFFER_OPTION_USER,
1276
- SKILL_INSTALL_OFFER_OPTION_NOT_NOW,
1277
- SKILL_INSTALL_OFFER_OPTION_NEVER
1278
- ];
1279
- for (const label of labels) {
1280
- if (answer.options?.includes(label)) return label;
1281
- }
1282
- for (const label of labels) {
1283
- if (answer.answer.includes(label)) return label;
1284
- }
1285
- return null;
1286
- }
1287
- function createMarketplaceOfferRegistration(deps) {
1288
- const declines = deps.declines ?? {
1289
- readNever: () => readPromotionDeclines().never,
1290
- recordNever: (name, version) => recordPromotionNeverDecline(name, version)
1291
- };
1292
- const newOfferTag = deps.newOfferTag ?? (() => randomUUID());
1293
- let lastSeenSessionId;
1294
- let offeredNames = /* @__PURE__ */ new Set();
1295
- let sessionDeclines = /* @__PURE__ */ new Set();
1296
- let installedNamesCache = null;
1297
- let marketplaceEntriesCache = null;
1298
- let pendingOffer = null;
1299
- const trackSession = (input) => {
1300
- const sessionId = input.sessionId ?? null;
1301
- if (lastSeenSessionId === void 0 || lastSeenSessionId === null && sessionId !== null) {
1302
- lastSeenSessionId = sessionId;
1303
- return;
1304
- }
1305
- if (sessionId !== lastSeenSessionId) {
1306
- lastSeenSessionId = sessionId;
1307
- offeredNames = /* @__PURE__ */ new Set();
1308
- sessionDeclines = /* @__PURE__ */ new Set();
1309
- pendingOffer = null;
1310
- installedNamesCache = null;
1311
- marketplaceEntriesCache = null;
1312
- }
1313
- };
1314
- const bestMatch = (text) => {
1315
- const installedWasCached = installedNamesCache !== null;
1316
- let never;
1317
- try {
1318
- installedNamesCache ??= new Set(deps.listInstalledSkillNames());
1319
- marketplaceEntriesCache ??= deps.listMarketplaceEntries();
1320
- never = declines.readNever();
1321
- } catch {
1322
- return null;
1323
- }
1324
- const declinedKeys = /* @__PURE__ */ new Set([...Object.keys(never), ...sessionDeclines]);
1325
- const findMatch = () => matchMarketplaceSkills(
1326
- text,
1327
- marketplaceEntriesCache ?? [],
1328
- /* @__PURE__ */ new Set([...installedNamesCache ?? [], ...offeredNames])
1329
- ).find((candidate) => !declinedKeys.has(declineKey(candidate.entry.name, candidate.entry.version))) ?? null;
1330
- let match = findMatch();
1331
- if (match && installedWasCached) {
1332
- try {
1333
- installedNamesCache = new Set(deps.listInstalledSkillNames());
1334
- } catch {
1335
- return null;
1336
- }
1337
- match = findMatch();
1338
- }
1339
- return match;
1340
- };
1341
- const installGated = (entry, scope) => {
1342
- assertPromotionInstallSource(entry);
1343
- const result = deps.installEntry(entry, scope);
1344
- installedNamesCache?.add(entry.name);
1345
- return result;
1346
- };
1347
- const evaluateAskUserAnswers = (input) => {
1348
- const offer = pendingOffer;
1349
- if (!offer) return NO_EFFECTS2;
1350
- const marker = offerBindingTag(offer.tag);
1351
- if (input.toolResultDetails?.cancelled === true) {
1352
- return NO_EFFECTS2;
1353
- }
1354
- for (const answer of answersFromDetails(input.toolResultDetails)) {
1355
- if (!answer.question.includes(marker)) continue;
1356
- const option = chosenOfferOption(answer);
1357
- if (option === null) continue;
1358
- pendingOffer = null;
1359
- const offerKey = declineKey(offer.entry.name, offer.entry.version);
1360
- if (option === SKILL_INSTALL_OFFER_OPTION_NOT_NOW) {
1361
- sessionDeclines.add(offerKey);
1362
- return NO_EFFECTS2;
1363
- }
1364
- if (option === SKILL_INSTALL_OFFER_OPTION_NEVER) {
1365
- sessionDeclines.add(offerKey);
1366
- try {
1367
- declines.recordNever(offer.entry.name, offer.entry.version);
1368
- } catch {
1369
- }
1370
- return NO_EFFECTS2;
1371
- }
1372
- const scope = option === SKILL_INSTALL_OFFER_OPTION_USER ? "user" : "project";
1373
- try {
1374
- const result = installGated(offer.entry, scope);
1375
- return [
1376
- {
1377
- kind: "annotate_tool_result",
1378
- severity: "info",
1379
- message: `[Marketplace] Installed skill "${offer.entry.name}" (${scope} scope) to ${result.path}. It is installed but not active; the operator activates it with /skill ${offer.entry.name}.`
1380
- }
1381
- ];
1382
- } catch (error) {
1383
- sessionDeclines.add(offerKey);
1384
- return [
1385
- {
1386
- kind: "annotate_tool_result",
1387
- severity: "warn",
1388
- message: `[Marketplace] Install of "${offer.entry.name}" failed: ${error instanceof Error ? error.message : String(error)}. Continue the task without it.`
1389
- }
1390
- ];
1391
- }
1392
- }
1393
- return NO_EFFECTS2;
1394
- };
1395
- return {
1396
- id: MARKETPLACE_OFFER_REGISTRATION_ID,
1397
- description: "offers an uninstalled marketplace skill via ask_user when the request matches it; consented installs run gated to Clio's own marketplace, declines are remembered",
1398
- hooks: ["turn_start", "after_tool"],
1399
- evaluate(input) {
1400
- trackSession(input);
1401
- if (input.hook === "after_tool") {
1402
- return input.toolName === ToolNames.AskUser ? evaluateAskUserAnswers(input) : NO_EFFECTS2;
1403
- }
1404
- if (input.hook !== "turn_start") return NO_EFFECTS2;
1405
- if (!isSubstantiveUserTurn(input.text)) return NO_EFFECTS2;
1406
- const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
1407
- if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS2;
1408
- const match = bestMatch(input.text ?? "");
1409
- if (!match) return NO_EFFECTS2;
1410
- offeredNames.add(match.entry.name);
1411
- if (deps.interactive === false) {
1412
- return [
1413
- {
1414
- kind: "inject_reminder",
1415
- severity: "info",
1416
- message: `[Marketplace] Skill "${match.entry.name}" matches this request; install with clio-coder library install ${match.entry.name}.`
1417
- }
1418
- ];
1419
- }
1420
- const tag = newOfferTag();
1421
- pendingOffer = { entry: match.entry, tag };
1422
- return [{ kind: "inject_reminder", severity: "info", message: marketplaceOfferReminder(match.entry, tag) }];
1423
- }
1424
- };
1425
- }
1426
-
1427
- // src/domains/middleware/memory-intervention.ts
1428
- init_esm_shims();
1429
- import { createHash } from "node:crypto";
1430
- var MEMORY_INTERVENTION_REGISTRATION_ID = "observer.memory-intervention";
1431
- var MEMORY_INTERVENTION_DEFAULT_WINDOW_STEPS = 8;
1432
- var MEMORY_INTERVENTION_DEFAULT_MAX_TOKENS = 2e3;
1433
- var MEMORY_INTERVENTION_DEFAULT_EVERY_N_TOOLS = 10;
1434
- var MEMORY_INTERVENTION_TIMEOUT_BACKOFF_THRESHOLD = 2;
1435
- var MEMORY_INTERVENTION_ACTIVITY_LIMIT = 20;
1436
- var CALL_DESCRIPTION_MAX_CHARS = 180;
1437
- var NO_EFFECTS3 = [];
1438
- function createMemoryInterventionRegistration(deps) {
1439
- let generation = 0;
1440
- let generationController = new AbortController();
1441
- let observedSessionId;
1442
- let disposed = false;
1443
- const pending = /* @__PURE__ */ new Map();
1444
- const trajectory = [];
1445
- const failures = /* @__PURE__ */ new Map();
1446
- let toolStep = 0;
1447
- let lastTurnEndStep = 0;
1448
- let reactivateAfterCompaction = false;
1449
- let lastInjectedOperationFingerprint = null;
1450
- let currentTask = "(current task unavailable)";
1451
- let toolsSinceMemoryStep = 0;
1452
- let consecutiveErrors = 0;
1453
- let lastPromptedBoundary = null;
1454
- let lastInjectedMessage = null;
1455
- let lastDecision = null;
1456
- const pendingTriggers = /* @__PURE__ */ new Set();
1457
- const activity = [];
1458
- const annotatedThisTurn = /* @__PURE__ */ new Set();
1459
- let telemetryBankSnapshot = deps.bank.snapshot();
1460
- let promptedStepInFlight = false;
1461
- let promptedStepTier = "rules";
1462
- let outstandingStep = Promise.resolve();
1463
- let rulesInjectedSincePromptedStep = false;
1464
- let annotatedSinceTurnEnd = false;
1465
- let consecutiveLlmTimeouts = 0;
1466
- return {
1467
- reset,
1468
- dispose() {
1469
- disposed = true;
1470
- reset();
1471
- },
1472
- id: MEMORY_INTERVENTION_REGISTRATION_ID,
1473
- description: "maintain bounded task execution memory and selectively remind after repeated failures or compaction",
1474
- hooks: ["before_tool", "after_tool", "turn_start", "turn_end", "on_compaction"],
1475
- evaluate(input) {
1476
- observeSession(input);
1477
- if (disposed || !settings().enabled) return NO_EFFECTS3;
1478
- try {
1479
- switch (input.hook) {
1480
- case "before_tool":
1481
- observeBeforeTool(input);
1482
- return NO_EFFECTS3;
1483
- case "after_tool":
1484
- return observeAfterTool(input);
1485
- case "turn_end": {
1486
- if (toolStep <= lastTurnEndStep) return NO_EFFECTS3;
1487
- const alreadyReported = annotatedSinceTurnEnd;
1488
- annotatedSinceTurnEnd = false;
1489
- const started = process.hrtime.bigint();
1490
- const effects = decideRepeatedFailure();
1491
- if (alreadyReported && effects.length === 0) return effects;
1492
- emitTelemetry(
1493
- [effects.length > 0 ? "repeated_failure" : "turn_end"],
1494
- "rules",
1495
- effects.length > 0 ? "injected" : "silent",
1496
- effects.length > 0 ? "intervened" : "no_repeated_failure",
1497
- citedEntryCount(effects[0]?.kind === "inject_reminder" ? effects[0].message : null),
1498
- 0,
1499
- 0,
1500
- started
1501
- );
1502
- return effects;
1503
- }
1504
- case "on_compaction":
1505
- if (input.metadata?.stage === "working_set_recall") return NO_EFFECTS3;
1506
- reactivateAfterCompaction = true;
1507
- return NO_EFFECTS3;
1508
- case "turn_start": {
1509
- if (input.text?.trim()) currentTask = shortText(input.text, 2e3);
1510
- annotatedThisTurn.clear();
1511
- const shouldReactivate = reactivateAfterCompaction;
1512
- const started = process.hrtime.bigint();
1513
- const effects = reactivateKnowledge();
1514
- if (shouldReactivate) {
1515
- emitTelemetry(
1516
- ["post_compaction"],
1517
- "rules",
1518
- effects.length > 0 ? "injected" : "silent",
1519
- effects.length > 0 ? "intervened" : "bank_empty",
1520
- citedEntryCount(effects[0]?.kind === "inject_reminder" ? effects[0].message : null),
1521
- 0,
1522
- 0,
1523
- started
1524
- );
1525
- }
1526
- return effects;
1527
- }
1528
- }
1529
- } catch {
1530
- return NO_EFFECTS3;
1531
- }
1532
- },
1533
- /**
1534
- * Kicks off the background memory step and returns immediately. The pi
1535
- * agent does not go idle until every `agent_end` listener settles, so
1536
- * awaiting a local memory model here would stall the visible turn for its
1537
- * full latency. Small local models measure in tens of seconds, which is far
1538
- * past any tolerable end-of-turn pause and past the policy timeout itself.
1539
- * The reminder is delivered through `onDeferredReminder` instead, landing
1540
- * in the next submitted turn, which is where an awaited turn_end reminder
1541
- * would have been buffered anyway.
1542
- */
1543
- async evaluateAsync(input, context) {
1544
- observeSession(input);
1545
- if (disposed || !settings().enabled || input.hook !== "turn_end" || pendingTriggers.size === 0) return NO_EFFECTS3;
1546
- const boundary = input.turnId ?? input.metadata?.userTurnId?.toString() ?? `tool-step:${toolStep}`;
1547
- if (boundary === lastPromptedBoundary) return NO_EFFECTS3;
1548
- if (deps.deliversDeferredReminders === false) {
1549
- emitTelemetry([...pendingTriggers], "rules", "silent", "no_consumer", 0, 0, 0, process.hrtime.bigint());
1550
- pendingTriggers.clear();
1551
- return NO_EFFECTS3;
1552
- }
1553
- if (promptedStepInFlight) {
1554
- emitTelemetry(
1555
- [...pendingTriggers],
1556
- promptedStepTier,
1557
- "dropped",
1558
- "step_in_flight",
1559
- 0,
1560
- 0,
1561
- 0,
1562
- process.hrtime.bigint()
1563
- );
1564
- return NO_EFFECTS3;
1565
- }
1566
- lastPromptedBoundary = boundary;
1567
- const triggers = [...pendingTriggers];
1568
- pendingTriggers.clear();
1569
- toolsSinceMemoryStep = 0;
1570
- consecutiveErrors = 0;
1571
- const rulesAlreadySpoke = rulesInjectedSincePromptedStep || (context?.priorEffects.some(
1572
- (effect) => effect.kind === "inject_reminder" && effect.message.startsWith("Memory:")
1573
- ) ?? false);
1574
- rulesInjectedSincePromptedStep = false;
1575
- const stepGeneration = generation;
1576
- promptedStepInFlight = true;
1577
- outstandingStep = runPromptedStep({
1578
- deterministicTrigger: triggers.some((trigger) => trigger !== "interval"),
1579
- suppressIntervention: rulesAlreadySpoke,
1580
- triggerReasons: triggers
1581
- }).then((result) => {
1582
- if (stepGeneration !== generation || disposed) return;
1583
- if (rulesAlreadySpoke && result.decision === "silent") lastDecision = "injected";
1584
- if (result.reminder === null) return;
1585
- lastInjectedMessage = result.reminder;
1586
- deps.onDeferredReminder?.(result.reminder);
1587
- }).catch(() => {
1588
- }).finally(() => {
1589
- if (stepGeneration === generation) promptedStepInFlight = false;
1590
- });
1591
- return NO_EFFECTS3;
1592
- },
1593
- runPromptedStep,
1594
- signalLoop() {
1595
- if (!disposed && settings().enabled) pendingTriggers.add("loop_signal");
1596
- },
1597
- lastDecision: () => lastDecision,
1598
- recentActivity: () => [...activity],
1599
- stepInFlight: () => promptedStepInFlight,
1600
- whenIdle: () => outstandingStep
1601
- };
1602
- function observeSession(input) {
1603
- if (input.sessionId === void 0) return;
1604
- if (observedSessionId !== void 0 && observedSessionId !== input.sessionId) reset();
1605
- observedSessionId = input.sessionId;
1606
- }
1607
- function reset() {
1608
- generation += 1;
1609
- generationController.abort();
1610
- generationController = new AbortController();
1611
- deps.bank.clear();
1612
- pending.clear();
1613
- trajectory.length = 0;
1614
- failures.clear();
1615
- toolStep = 0;
1616
- lastTurnEndStep = 0;
1617
- reactivateAfterCompaction = false;
1618
- lastInjectedOperationFingerprint = null;
1619
- currentTask = "(current task unavailable)";
1620
- toolsSinceMemoryStep = 0;
1621
- consecutiveErrors = 0;
1622
- lastPromptedBoundary = null;
1623
- lastInjectedMessage = null;
1624
- lastDecision = null;
1625
- pendingTriggers.clear();
1626
- activity.length = 0;
1627
- annotatedThisTurn.clear();
1628
- telemetryBankSnapshot = deps.bank.snapshot();
1629
- promptedStepInFlight = false;
1630
- promptedStepTier = "rules";
1631
- outstandingStep = Promise.resolve();
1632
- rulesInjectedSincePromptedStep = false;
1633
- annotatedSinceTurnEnd = false;
1634
- consecutiveLlmTimeouts = 0;
1635
- observedSessionId = void 0;
1636
- }
1637
- function settings() {
1638
- const live = deps.getSettings?.();
1639
- return {
1640
- enabled: live?.enabled ?? deps.enabled ?? true,
1641
- everyNTools: Math.max(
1642
- 2,
1643
- positiveInteger(live?.everyNTools ?? deps.everyNTools, MEMORY_INTERVENTION_DEFAULT_EVERY_N_TOOLS)
1644
- ),
1645
- windowSteps: positiveInteger(live?.windowSteps ?? deps.windowSteps, MEMORY_INTERVENTION_DEFAULT_WINDOW_STEPS),
1646
- maxTokens: positiveInteger(live?.maxTokens ?? deps.maxTokens, MEMORY_INTERVENTION_DEFAULT_MAX_TOKENS),
1647
- timeoutMs: positiveInteger(live?.timeoutMs ?? deps.timeoutMs, TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS)
1648
- };
1649
- }
1650
- async function runPromptedStep(input) {
1651
- const silent = (reason) => ({
1652
- decision: "silent",
1653
- reason,
1654
- bankOperations: 0,
1655
- droppedOperations: 0,
1656
- reminder: null,
1657
- inputTokens: 0,
1658
- outputTokens: 0,
1659
- usage: null,
1660
- effects: NO_EFFECTS3
1661
- });
1662
- const live = settings();
1663
- const stepGeneration = generation;
1664
- const isCurrent = () => !disposed && stepGeneration === generation;
1665
- const usageSink = deps.captureStepUsage?.();
1666
- if (disposed || !live.enabled) {
1667
- const result = silent("no_client");
1668
- lastDecision = result.decision;
1669
- return result;
1670
- }
1671
- const started = process.hrtime.bigint();
1672
- let attemptStarted = started;
1673
- const triggers = input.triggerReasons?.length ? input.triggerReasons : ["manual"];
1674
- let tier = "rules";
1675
- promptedStepTier = tier;
1676
- let promptedResult;
1677
- let telemetryDecision = null;
1678
- try {
1679
- if (consecutiveLlmTimeouts >= MEMORY_INTERVENTION_TIMEOUT_BACKOFF_THRESHOLD) {
1680
- promptedResult = silent("llm_timeout_backoff");
1681
- } else {
1682
- const client = deps.getModelClient?.() ?? null;
1683
- if (client === null) {
1684
- promptedResult = silent("no_client");
1685
- } else if (deps.backgroundEndpointBusy?.() === true) {
1686
- tier = "llm";
1687
- promptedStepTier = tier;
1688
- promptedResult = silent("endpoint_busy");
1689
- telemetryDecision = "dropped";
1690
- } else {
1691
- tier = "llm";
1692
- promptedStepTier = tier;
1693
- const runClient = (selected, timeoutMs) => runTaskMemoryPolicy(deps.bank, selected, {
1694
- isCurrent,
1695
- signal: generationController.signal,
1696
- onStepUsage: (usage) => {
1697
- if (usageSink) usageSink(usage, isCurrent());
1698
- else deps.onStepUsage?.(usage);
1699
- },
1700
- task: input.task?.trim() || currentTask,
1701
- trajectory: [...trajectory],
1702
- deterministicTrigger: input.deterministicTrigger,
1703
- maxTokens: live.maxTokens,
1704
- modelMaxTokens: positiveInteger(deps.getModelMaxTokens?.(live.maxTokens), live.maxTokens),
1705
- ...input.suppressIntervention === void 0 ? {} : { suppressIntervention: input.suppressIntervention },
1706
- previousReminder: lastInjectedMessage,
1707
- timeoutMs,
1708
- ...deps.onEnvelope === void 0 ? {} : { onEnvelope: deps.onEnvelope }
1709
- });
1710
- const remainingMs = () => Math.floor(live.timeoutMs - Number(process.hrtime.bigint() - started) / 1e6);
1711
- const initialTimeoutMs = remainingMs();
1712
- promptedResult = initialTimeoutMs <= 0 ? { ...silent("deadline"), decision: "timeout" } : await runClient(client, initialTimeoutMs);
1713
- if (promptedResult.reason === "client_error" && isCurrent() && remainingMs() > 0) {
1714
- let fallback = null;
1715
- let fallbackReady = false;
1716
- try {
1717
- fallback = deps.getFallbackModelClient?.() ?? null;
1718
- fallbackReady = fallback !== null && deps.backgroundEndpointBusy?.() !== true;
1719
- } catch {
1720
- }
1721
- const fallbackTimeoutMs = remainingMs();
1722
- if (fallback !== null && fallbackReady && isCurrent() && fallbackTimeoutMs > 0) {
1723
- emitTelemetry(
1724
- triggers,
1725
- tier,
1726
- promptedResult.decision,
1727
- promptedResult.reason,
1728
- 0,
1729
- promptedResult.inputTokens,
1730
- promptedResult.outputTokens,
1731
- started,
1732
- { bankOperations: promptedResult.bankOperations, droppedOperations: promptedResult.droppedOperations }
1733
- );
1734
- attemptStarted = process.hrtime.bigint();
1735
- promptedResult = await runClient(fallback, fallbackTimeoutMs);
1736
- }
1737
- }
1738
- }
1739
- }
1740
- } catch (error) {
1741
- promptedResult = silent("client_error");
1742
- deps.onEnvelope?.({
1743
- systemPrompt: "",
1744
- userPrompt: "",
1745
- response: "",
1746
- decision: "silent",
1747
- reason: "client_error",
1748
- bankOperations: 0,
1749
- droppedOperations: 0,
1750
- reminder: null,
1751
- error: error instanceof Error ? error.message : "resolving the background model client failed"
1752
- });
1753
- }
1754
- if (!isCurrent()) return { ...promptedResult, reminder: null, effects: NO_EFFECTS3 };
1755
- if (promptedResult.reason === "endpoint_busy") telemetryDecision = "dropped";
1756
- if (tier === "llm" && promptedResult.decision === "timeout") consecutiveLlmTimeouts += 1;
1757
- else if (tier === "llm" && telemetryDecision !== "dropped") consecutiveLlmTimeouts = 0;
1758
- lastDecision = promptedResult.decision;
1759
- if (promptedResult.decision === "injected") reportInjectedEntries(promptedResult.reminder);
1760
- emitTelemetry(
1761
- triggers,
1762
- tier,
1763
- telemetryDecision ?? promptedResult.decision,
1764
- promptedResult.reason,
1765
- citedEntryCount(promptedResult.reminder),
1766
- promptedResult.inputTokens,
1767
- promptedResult.outputTokens,
1768
- attemptStarted,
1769
- { bankOperations: promptedResult.bankOperations, droppedOperations: promptedResult.droppedOperations }
1770
- );
1771
- return {
1772
- ...promptedResult,
1773
- effects: promptedResult.reminder === null ? NO_EFFECTS3 : [{ kind: "inject_reminder", message: promptedResult.reminder, severity: "advisory" }]
1774
- };
1775
- }
1776
- function emitTelemetry(triggerReasons, tier, decision, reason, citedEntries2, inputTokens, outputTokens, started, operations = { bankOperations: 0, droppedOperations: 0 }) {
1777
- const next = deps.bank.snapshot();
1778
- const bankDelta = taskMemoryBankDelta(telemetryBankSnapshot, next);
1779
- telemetryBankSnapshot = next;
1780
- const latencyMs = Number(process.hrtime.bigint() - started) / 1e6;
1781
- try {
1782
- deps.telemetry?.record({
1783
- triggerReasons,
1784
- tier,
1785
- bankDelta,
1786
- decision,
1787
- reason,
1788
- bankOperations: operations.bankOperations,
1789
- droppedOperations: operations.droppedOperations,
1790
- citedEntries: citedEntries2,
1791
- inputTokens,
1792
- outputTokens,
1793
- latencyMs
1794
- });
1795
- } catch {
1796
- }
1797
- const event = {
1798
- at: (/* @__PURE__ */ new Date()).toISOString(),
1799
- triggerReasons: [...new Set(triggerReasons)],
1800
- tier,
1801
- decision,
1802
- reason,
1803
- citedEntries: citedEntries2,
1804
- bankWrites: countBankWrites(bankDelta),
1805
- latencyMs
1806
- };
1807
- activity.unshift(event);
1808
- if (activity.length > MEMORY_INTERVENTION_ACTIVITY_LIMIT) activity.length = MEMORY_INTERVENTION_ACTIVITY_LIMIT;
1809
- }
1810
- function citedEntries(message) {
1811
- if (message === null) return [];
1812
- const snapshot = deps.bank.snapshot();
1813
- return [...snapshot.knowledge, ...snapshot.procedural].filter((entry) => message.includes(`[${entry.id}]`));
1814
- }
1815
- function citedEntryCount(message) {
1816
- return citedEntries(message).length;
1817
- }
1818
- function reportInjectedEntries(reminder) {
1819
- if (deps.onInjectedEntries === void 0) return;
1820
- const entries = citedEntries(reminder);
1821
- if (entries.length === 0) return;
1822
- try {
1823
- deps.onInjectedEntries(entries);
1824
- } catch {
1825
- }
1826
- }
1827
- function observeBeforeTool(input) {
1828
- const prepared = prepareToolStep(input);
1829
- if (prepared === null) return;
1830
- setBounded(pending, pendingKey(input, prepared.operationFingerprint), prepared, settings().windowSteps);
1831
- }
1832
- function observeAfterTool(input) {
1833
- const fallback = prepareToolStep(input);
1834
- if (fallback === null) return NO_EFFECTS3;
1835
- const key = pendingKey(input, fallback.operationFingerprint);
1836
- const prepared = pending.get(key) ?? fallback;
1837
- pending.delete(key);
1838
- const outcome = input.metadata?.resultKind === "error" ? "error" : "ok";
1839
- toolStep += 1;
1840
- toolsSinceMemoryStep += 1;
1841
- const live = settings();
1842
- if (toolsSinceMemoryStep >= live.everyNTools) pendingTriggers.add("interval");
1843
- if (outcome === "error") {
1844
- consecutiveErrors += 1;
1845
- if (consecutiveErrors >= 2) pendingTriggers.add("tool_error_streak");
1846
- } else {
1847
- consecutiveErrors = 0;
1848
- }
1849
- const digest = resultDigest(input, outcome);
1850
- const step = {
1851
- ...prepared,
1852
- step: toolStep,
1853
- outcome,
1854
- resultDigest: digest.text,
1855
- resultDigestProvenance: digest.provenance
1856
- };
1857
- trajectory.push(step);
1858
- if (trajectory.length > live.windowSteps) trajectory.splice(0, trajectory.length - live.windowSteps);
1859
- if (outcome !== "error") return NO_EFFECTS3;
1860
- rememberFailure(step);
1861
- return annotateRepeatedFailure(step);
1862
- }
1863
- function annotateRepeatedFailure(step) {
1864
- if (annotatedThisTurn.has(step.operationFingerprint)) return NO_EFFECTS3;
1865
- const occurrences = trajectory.filter(
1866
- (candidate) => candidate.outcome === "error" && candidate.operationFingerprint === step.operationFingerprint
1867
- ).length;
1868
- const failure = failures.get(step.operationFingerprint);
1869
- if (occurrences < 2 || failure === void 0) return NO_EFFECTS3;
1870
- const message = boundedReminder(
1871
- `Memory: [${failure.entryId}] you already tried ${failure.callDescription} at step ${failure.firstStep} and it failed with ${failure.errorDigest}. Change the approach rather than repeating it.`,
1872
- settings().maxTokens
1873
- );
1874
- if (message.length === 0) return NO_EFFECTS3;
1875
- annotatedThisTurn.add(step.operationFingerprint);
1876
- lastInjectedOperationFingerprint = step.operationFingerprint;
1877
- lastDecision = "injected";
1878
- rulesInjectedSincePromptedStep = true;
1879
- annotatedSinceTurnEnd = true;
1880
- deps.bank.recordInjection([failure.entryId]);
1881
- emitTelemetry(["repeated_failure"], "rules", "injected", "intervened", 1, 0, 0, process.hrtime.bigint());
1882
- return [{ kind: "annotate_tool_result", message, severity: "warn" }];
1883
- }
1884
- function rememberFailure(step) {
1885
- const previous = failures.get(step.operationFingerprint);
1886
- const attempts = (previous?.attempts ?? 0) + 1;
1887
- const firstStep = previous?.firstStep ?? step.step;
1888
- const content = proceduralContent(step.callDescription, attempts, firstStep, step.resultDigest);
1889
- let entryId;
1890
- if (previous === void 0) {
1891
- entryId = deps.bank.saveProcedural(content).id;
1892
- } else {
1893
- try {
1894
- entryId = deps.bank.saveProcedural(content, { id: previous.entryId }).id;
1895
- } catch {
1896
- entryId = deps.bank.saveProcedural(content).id;
1897
- }
1898
- }
1899
- setBounded(
1900
- failures,
1901
- step.operationFingerprint,
1902
- {
1903
- entryId,
1904
- attempts,
1905
- firstStep,
1906
- callDescription: step.callDescription,
1907
- errorDigest: step.resultDigest
1908
- },
1909
- TASK_MEMORY_DEFAULT_PROCEDURAL_CAP
1910
- );
1911
- }
1912
- function decideRepeatedFailure() {
1913
- try {
1914
- for (let index = trajectory.length - 1; index >= 0; index -= 1) {
1915
- const step = trajectory[index];
1916
- if (step === void 0 || step.outcome !== "error" || step.step <= lastTurnEndStep || step.operationFingerprint === lastInjectedOperationFingerprint) {
1917
- continue;
1918
- }
1919
- const occurrences = trajectory.filter(
1920
- (candidate) => candidate.outcome === "error" && candidate.operationFingerprint === step.operationFingerprint
1921
- ).length;
1922
- const failure = failures.get(step.operationFingerprint);
1923
- if (occurrences < 2 || failure === void 0) continue;
1924
- const message = boundedReminder(
1925
- `Memory: [${failure.entryId}] you already tried ${failure.callDescription} at step ${failure.firstStep} and it failed with ${failure.errorDigest}.`,
1926
- settings().maxTokens
1927
- );
1928
- if (message.length === 0) return NO_EFFECTS3;
1929
- lastInjectedOperationFingerprint = step.operationFingerprint;
1930
- lastInjectedMessage = message;
1931
- lastDecision = "injected";
1932
- rulesInjectedSincePromptedStep = true;
1933
- deps.bank.recordInjection([failure.entryId]);
1934
- return [{ kind: "inject_reminder", message, severity: "advisory" }];
1935
- }
1936
- lastDecision = "silent";
1937
- return NO_EFFECTS3;
1938
- } finally {
1939
- lastTurnEndStep = toolStep;
1940
- }
1941
- }
1942
- function reactivateKnowledge() {
1943
- if (!reactivateAfterCompaction) return NO_EFFECTS3;
1944
- reactivateAfterCompaction = false;
1945
- const prefix = "Memory: execution state restored after compaction:\n";
1946
- const maxTokens = settings().maxTokens;
1947
- const prefixTokens = ceilChars(prefix.length);
1948
- const rendered = deps.bank.renderRestoredState(Math.max(0, maxTokens - prefixTokens));
1949
- if (rendered.length === 0) {
1950
- lastDecision = "silent";
1951
- return NO_EFFECTS3;
1952
- }
1953
- const message = boundedReminder(`${prefix}${rendered}`, maxTokens);
1954
- if (message.length === 0) {
1955
- lastDecision = "silent";
1956
- return NO_EFFECTS3;
1957
- }
1958
- const citedIds = [...message.matchAll(/\[([^\]]+)\]/gu)].map((match) => match[1]).filter((id) => id !== void 0);
1959
- deps.bank.recordInjection(citedIds);
1960
- lastInjectedMessage = message;
1961
- lastDecision = "injected";
1962
- return [{ kind: "inject_reminder", message, severity: "advisory" }];
1963
- }
1964
- }
1965
- function prepareToolStep(input) {
1966
- const toolName = input.toolName?.trim();
1967
- if (!toolName) return null;
1968
- const canonical = hashToolCall(toolName, input.toolArgs ?? {});
1969
- return {
1970
- toolName,
1971
- operationFingerprint: createHash("sha256").update(canonical).digest("hex").slice(0, 16),
1972
- callDescription: shortText(canonical, CALL_DESCRIPTION_MAX_CHARS)
1973
- };
1974
- }
1975
- function pendingKey(input, operationFingerprint) {
1976
- return input.toolCallId ?? `anonymous:${operationFingerprint}`;
1977
- }
1978
- function resultDigest(input, outcome) {
1979
- if (input.toolResultDigest !== void 0) return sanitizeToolResultDigest(input.toolResultDigest);
1980
- if (outcome === "error") {
1981
- const metadataMessage = input.metadata?.errorMessage;
1982
- if (typeof metadataMessage === "string" && metadataMessage.trim().length > 0) {
1983
- return legacyToolResultDigest(diagnosticLine(metadataMessage), { outcome });
1984
- }
1985
- for (const key of ["error", "message"]) {
1986
- const value = input.toolResultDetails?.[key];
1987
- if (typeof value === "string" && value.trim().length > 0) {
1988
- return legacyToolResultDigest(diagnosticLine(value), { outcome });
1989
- }
1990
- }
1991
- return legacyToolResultDigest("", { outcome });
1992
- }
1993
- const resultFingerprint = input.metadata?.resultFingerprint;
1994
- return legacyToolResultDigest(
1995
- typeof resultFingerprint === "string" ? `ok result ${resultFingerprint.slice(0, 16)}` : "ok",
1996
- { outcome }
1997
- );
1998
- }
1999
- var DIAGNOSTIC_HINT = /\b(error|failed|failure|cannot|unable|expected|refused|denied|missing|not found|timed out|timeout|fatal)\b/iu;
2000
- function diagnosticLine(value) {
2001
- const lines = value.split(/\r?\n/u).map((line) => line.trim()).filter((line) => line.length > 0);
2002
- return lines.find((line) => DIAGNOSTIC_HINT.test(line)) ?? lines[0] ?? "";
2003
- }
2004
- function proceduralContent(call, attempts, firstStep, error) {
2005
- return `${call} failed ${attempts} time${attempts === 1 ? "" : "s"}; first observed at step ${firstStep}: ${error}.`;
2006
- }
2007
- function boundedReminder(message, maxTokens) {
2008
- const maxChars = maxTokens * 4;
2009
- if (maxChars <= 0) return "";
2010
- const normalized = message.replace(/[^\S\n]+/gu, " ").trim();
2011
- return normalized.length <= maxChars ? normalized : normalized.slice(0, maxChars).trimEnd();
2012
- }
2013
- function shortText(value, maxChars) {
2014
- const normalized = value.replace(/\s+/gu, " ").trim();
2015
- return normalized.length <= maxChars ? normalized : `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
2016
- }
2017
- function positiveInteger(value, fallback) {
2018
- return value !== void 0 && Number.isInteger(value) && value > 0 ? value : fallback;
2019
- }
2020
- function countBankWrites(delta) {
2021
- return [delta.status, delta.knowledge, delta.procedural].reduce(
2022
- (total, entry) => total + entry.added + entry.updated + entry.deleted,
2023
- 0
2024
- );
2025
- }
2026
- function setBounded(map, key, value, capacity) {
2027
- if (!map.has(key) && map.size >= capacity) {
2028
- const oldest = map.keys().next().value;
2029
- if (oldest !== void 0) map.delete(oldest);
2030
- }
2031
- map.set(key, value);
2032
- }
2033
-
2034
- // src/domains/middleware/memory-step-endpoint.ts
2035
- init_esm_shims();
2036
- function announceMemoryStepEndpoint(deps, complete) {
2037
- const { bus, endpointKey, targetId } = deps;
2038
- if (endpointKey === null) return complete;
2039
- return async (request) => {
2040
- const releaseEndpointSlot = registerForegroundStream(endpointKey);
2041
- try {
2042
- return await complete(request);
2043
- } finally {
2044
- releaseEndpointSlot();
2045
- if (bus !== null) {
2046
- try {
2047
- bus.emit(BusChannels.MemoryStepCompleted, { endpointKey, targetId });
2048
- } catch {
2049
- }
2050
- }
2051
- }
2052
- };
2053
- }
2054
-
2055
- // src/domains/middleware/task-board-reminder.ts
2056
- init_esm_shims();
2057
- var TASK_BOARD_REMINDER_REGISTRATION_ID = "observer.task-board-reminder";
2058
- function taskBoardReminderMessage(steps) {
2059
- return `[Tasks] This request enumerates ${steps} steps. Before the first edit, declare the task board: tasks action="plan" with a title and one task per authorized step, then work them one at a time ("start", then "done" with an evidence note). A plan does not authorize implementation: for proposed work awaiting an operator go-ahead, use action="block" with a note naming the pending operator decision, or action="drop", and wait.`;
2060
- }
2061
- function countEnumeratedSteps(text) {
2062
- const value = text ?? "";
2063
- if (value.trim().length === 0) return 0;
2064
- const markers = [];
2065
- const markerPattern = /(?:^|[\s(])(?:step\s+)?([1-9])\s*[).:]\s/gi;
2066
- let match = markerPattern.exec(value);
2067
- while (match !== null) {
2068
- const digit = Number(match[1]);
2069
- if (Number.isInteger(digit)) markers.push(digit);
2070
- match = markerPattern.exec(value);
2071
- }
2072
- let run = 0;
2073
- for (const digit of markers) {
2074
- if (digit === run + 1) run += 1;
2075
- else if (digit === 1) run = 1;
2076
- }
2077
- if (run >= 3) return run;
2078
- const bulletLines = value.split(/\r?\n/).filter((line) => /^\s*[-*]\s+\S/.test(line)).length;
2079
- return bulletLines >= 3 ? bulletLines : 0;
2080
- }
2081
- var NO_EFFECTS4 = [];
2082
- function createTaskBoardReminderRegistration() {
2083
- let lastSeenSessionId;
2084
- let spentForActiveSession = false;
2085
- return {
2086
- id: TASK_BOARD_REMINDER_REGISTRATION_ID,
2087
- description: "once per session, on the first explicitly enumerated multi-step turn, teaches the board-first protocol",
2088
- hooks: ["turn_start"],
2089
- evaluate(input) {
2090
- const sessionId = input.sessionId ?? null;
2091
- if (lastSeenSessionId === void 0 || lastSeenSessionId === null && sessionId !== null) {
2092
- lastSeenSessionId = sessionId;
2093
- } else if (sessionId !== lastSeenSessionId) {
2094
- lastSeenSessionId = sessionId;
2095
- spentForActiveSession = false;
2096
- }
2097
- if (spentForActiveSession) return NO_EFFECTS4;
2098
- const steps = countEnumeratedSteps(input.text);
2099
- if (steps < 3) return NO_EFFECTS4;
2100
- spentForActiveSession = true;
2101
- const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
2102
- if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS4;
2103
- return [{ kind: "inject_reminder", severity: "info", message: taskBoardReminderMessage(steps) }];
2104
- }
2105
- };
2106
- }
2107
-
2108
- // src/domains/middleware/task-nudge.ts
2109
- init_esm_shims();
2110
- var TASK_NUDGE_REGISTRATION_ID = "nudge.open-tasks";
2111
- function openTasks(board) {
2112
- return board.tasks.filter((task) => task.status === "pending" || task.status === "active");
2113
- }
2114
- function buildOpenTasksMessage(board) {
2115
- const open = openTasks(board);
2116
- const counts = taskBoardCounts(board);
2117
- const rows = open.map((task) => ` ${task.status === "active" ? "[>]" : "[ ]"} ${task.id} ${task.title}`);
2118
- return `[Clio Coder] task board "${board.title}" still has ${open.length} of ${counts.total} task(s) open:
2119
- ${rows.join("\n")}
2120
- Continue only work already authorized by the operator. This reminder and a self-created plan are not authorization to implement a proposal. If implementation awaits an operator decision, use tasks action="block" with a note naming that pending operator decision, or action="drop"; then wait for an explicit operator go-ahead. A skill-install choice does not authorize implementation. Otherwise record the honest state on the board: tasks action="done" with an evidence note, action="block" with a reason, or action="drop". Do not end the turn with a stale board.`;
2121
- }
2122
- function createTaskNudgeRegistration(options) {
2123
- return {
2124
- id: TASK_NUDGE_REGISTRATION_ID,
2125
- description: "carry the turn onward when a work turn ends with open task-board tasks",
2126
- hooks: ["turn_end"],
2127
- evaluate(input) {
2128
- if (input.hook !== "turn_end") return [];
2129
- const stopReason = input.metadata?.stopReason;
2130
- if (stopReason !== void 0 && stopReason !== "stop") return [];
2131
- const turnToolCalls = input.metadata?.turnToolCalls;
2132
- if (typeof turnToolCalls !== "number" || turnToolCalls <= 0) return [];
2133
- const activeToolNames = input.metadata?.activeToolNames;
2134
- if (typeof activeToolNames === "string" && !activeToolNames.split(",").includes(ToolNames.Tasks)) return [];
2135
- let board;
2136
- try {
2137
- board = options.getBoard();
2138
- } catch {
2139
- return [];
2140
- }
2141
- if (board === null || openTasks(board).length === 0) return [];
2142
- const message = buildOpenTasksMessage(board);
2143
- return [
2144
- { kind: "request_continuation", message },
2145
- { kind: "inject_reminder", message, severity: "warn" }
2146
- ];
2147
- }
2148
- };
2149
- }
2150
-
2151
- // src/domains/middleware/tool-choice-control.ts
2152
- init_esm_shims();
2153
- function createMiddlewareToolChoiceControl() {
2154
- let choice = { kind: "auto" };
2155
- return {
2156
- apply(effects) {
2157
- for (const effect of effects) {
2158
- if (effect.kind === "lock_tools") {
2159
- choice = { kind: "none" };
2160
- continue;
2161
- }
2162
- if (effect.kind === "require_tool" && choice.kind !== "none") {
2163
- choice = { kind: "required", toolName: effect.toolName };
2164
- }
2165
- }
2166
- },
2167
- current: () => choice,
2168
- toolStarted(toolName) {
2169
- if (choice.kind === "required" && choice.toolName === toolName) choice = { kind: "auto" };
2170
- },
2171
- reset() {
2172
- choice = { kind: "auto" };
2173
- }
2174
- };
2175
- }
2176
-
2177
- // src/domains/middleware/watchdog.ts
2178
- init_esm_shims();
2179
- var WATCHDOG_REGISTRATION_ID = "observer.watchdog";
2180
- var WATCHDOG_DIFF_MAX_BYTES = 12 * 1024;
2181
- var WATCHDOG_PATHS_MAX = 40;
2182
- var WATCHDOG_TRUNCATION_MARKER = "\n[diff truncated]";
2183
- var MUTATING_TOOL_NAMES = /* @__PURE__ */ new Set([ToolNames.Write, ToolNames.Edit, ToolNames.Artifact]);
2184
- var NO_EFFECTS5 = [];
2185
- function stringValue2(value) {
2186
- return typeof value === "string" && value.length > 0 ? value : null;
2187
- }
2188
- function firstPath(details) {
2189
- const paths = details?.paths;
2190
- if (!Array.isArray(paths)) return null;
2191
- for (const entry of paths) {
2192
- const path2 = stringValue2(entry);
2193
- if (path2 !== null) return path2;
2194
- }
2195
- return null;
2196
- }
2197
- function coalesceTurnDiff(byPath, maxBytes = WATCHDOG_DIFF_MAX_BYTES) {
2198
- const blocks = [];
2199
- let index = 0;
2200
- for (const [path2, diff] of byPath) {
2201
- if (index >= WATCHDOG_PATHS_MAX) {
2202
- blocks.push(`[${byPath.size - WATCHDOG_PATHS_MAX} more changed path(s) omitted]`);
2203
- break;
2204
- }
2205
- blocks.push(`--- ${path2}
2206
- ${diff}`);
2207
- index += 1;
2208
- }
2209
- const whole = blocks.join("\n\n");
2210
- if (Buffer.byteLength(whole, "utf8") <= maxBytes) return whole;
2211
- const room = Math.max(0, maxBytes - Buffer.byteLength(WATCHDOG_TRUNCATION_MARKER, "utf8"));
2212
- const buffer = Buffer.from(whole, "utf8");
2213
- let cut = Math.min(room, buffer.byteLength);
2214
- while (cut > 0) {
2215
- const next = buffer[cut];
2216
- if (next === void 0 || (next & 192) !== 128) break;
2217
- cut -= 1;
2218
- }
2219
- return `${buffer.subarray(0, cut).toString("utf8")}${WATCHDOG_TRUNCATION_MARKER}`;
2220
- }
2221
- var WATCHDOG_TASK = "Review the coalesced diff in the briefing against the scope it names. Report one check per concern: a change outside the stated scope, a change the scope required that the diff does not make, or a defect visible in the diff itself. Run no commands and change nothing.";
2222
- function watchdogBriefing(trigger) {
2223
- const scope = trigger.scope === null ? "(no task board; scope is unstated)" : trigger.scope;
2224
- const paths = trigger.paths.length === 0 ? "(none)" : trigger.paths.join("\n");
2225
- return [
2226
- "## Current scope",
2227
- scope,
2228
- "",
2229
- "## Changed paths",
2230
- paths,
2231
- "",
2232
- "## Coalesced diff for this turn",
2233
- trigger.diff
2234
- ].join("\n");
2235
- }
2236
- function createWatchdogRegistration(deps) {
2237
- const diffByPath = /* @__PURE__ */ new Map();
2238
- let toolCalls = 0;
2239
- let dropped = 0;
2240
- let inFlight = false;
2241
- let outstanding = Promise.resolve();
2242
- const active = () => {
2243
- if (deps.firesOnThisSurface === false) return null;
2244
- let settings;
2245
- try {
2246
- settings = deps.getSettings();
2247
- } catch {
2248
- return null;
2249
- }
2250
- return settings.enabled ? settings : null;
2251
- };
2252
- const resetTurn = () => {
2253
- diffByPath.clear();
2254
- toolCalls = 0;
2255
- };
2256
- const fire = (reason) => {
2257
- if (diffByPath.size === 0) return;
2258
- if (inFlight) {
2259
- dropped += 1;
2260
- return;
2261
- }
2262
- const trigger = {
2263
- reason,
2264
- diff: coalesceTurnDiff(diffByPath),
2265
- paths: [...diffByPath.keys()].slice(0, WATCHDOG_PATHS_MAX),
2266
- scope: scopeNow(),
2267
- toolCalls
2268
- };
2269
- inFlight = true;
2270
- let started;
2271
- try {
2272
- started = deps.run(trigger);
2273
- } catch {
2274
- inFlight = false;
2275
- return;
2276
- }
2277
- outstanding = started.catch(() => {
2278
- }).finally(() => {
2279
- inFlight = false;
2280
- });
2281
- };
2282
- const scopeNow = () => {
2283
- try {
2284
- return deps.getScope?.() ?? null;
2285
- } catch {
2286
- return null;
2287
- }
2288
- };
2289
- return {
2290
- id: WATCHDOG_REGISTRATION_ID,
2291
- description: "review a mutating turn's coalesced diff against the board scope with a read-only verifier run",
2292
- hooks: ["after_tool", "turn_end"],
2293
- evaluate(input) {
2294
- const settings = active();
2295
- if (settings === null) {
2296
- if (input.hook === "turn_end") resetTurn();
2297
- return NO_EFFECTS5;
2298
- }
2299
- if (input.hook === "after_tool") {
2300
- toolCalls += 1;
2301
- recordMutation(input);
2302
- const cadence = settings.cadenceToolCalls;
2303
- if (cadence !== void 0 && cadence >= 1 && toolCalls % cadence === 0) fire("cadence");
2304
- return NO_EFFECTS5;
2305
- }
2306
- if (input.hook !== "turn_end") return NO_EFFECTS5;
2307
- fire("turn_end");
2308
- resetTurn();
2309
- return NO_EFFECTS5;
2310
- },
2311
- droppedTriggers: () => dropped,
2312
- runInFlight: () => inFlight,
2313
- whenIdle: () => outstanding
2314
- };
2315
- function recordMutation(input) {
2316
- if (input.metadata?.resultKind !== "ok") return;
2317
- if (input.toolName === void 0 || !MUTATING_TOOL_NAMES.has(input.toolName)) return;
2318
- const diff = stringValue2(input.toolResultDetails?.diff);
2319
- if (diff === null) return;
2320
- diffByPath.set(firstPath(input.toolResultDetails) ?? input.toolName, diff);
2321
- }
2322
- }
2323
-
2324
- // src/domains/middleware/index.ts
2325
- init_esm_shims();
2326
-
2327
- // src/domains/middleware/extension.ts
2328
- init_esm_shims();
2329
-
2330
- // src/domains/middleware/registrations.ts
2331
- init_esm_shims();
2332
- var MIDDLEWARE_REGISTRATION_OWNERS = ["user-hooks"];
2333
- function isRegistrationOwner(value) {
2334
- return MIDDLEWARE_REGISTRATION_OWNERS.includes(value);
2335
- }
2336
- function createMiddlewareRegistrationTable(options) {
2337
- const fixed = Object.freeze([...options.fixed]);
2338
- const fixedIds = new Set(fixed.map((registration) => registration.id));
2339
- const buildList = (host, slots) => {
2340
- const list = [...fixed];
2341
- const slotAt = (index) => {
2342
- for (const owner of MIDDLEWARE_REGISTRATION_OWNERS) {
2343
- const slot = slots.get(owner);
2344
- if (slot !== void 0 && slot.anchor === index) list.push(...slot.registrations);
2345
- }
2346
- };
2347
- for (let index = 0; index < host.length; index += 1) {
2348
- slotAt(index);
2349
- list.push(host[index]);
2350
- }
2351
- slotAt(host.length);
2352
- return Object.freeze(list);
2353
- };
2354
- const makeState = (host, slots) => Object.freeze({
2355
- host: Object.freeze([...host]),
2356
- hostIds: new Set(host.map((registration) => registration.id)),
2357
- slots: new Map(slots),
2358
- list: buildList(host, slots)
2359
- });
2360
- let state = makeState([], /* @__PURE__ */ new Map());
2361
- const emit = (diagnostic) => {
2362
- try {
2363
- options.diagnosticSink()(diagnostic);
2364
- } catch {
2365
- }
2366
- };
2367
- const slotFor = (base, owner) => base.slots.get(owner) ?? { generation: 0, registrations: [], anchor: base.host.length };
2368
- const disposeGeneration = (owner, generation) => {
2369
- const base = state;
2370
- const held = base.slots.get(owner);
2371
- if (held === void 0 || held.generation !== generation || held.registrations.length === 0) return;
2372
- const slots = new Map(base.slots);
2373
- slots.set(owner, { ...held, registrations: Object.freeze([]) });
2374
- state = makeState(base.host, slots);
2375
- };
2376
- const table = {
2377
- list: () => state.list,
2378
- registerHook(registration) {
2379
- const base = state;
2380
- if (fixedIds.has(registration.id) || base.hostIds.has(registration.id)) return;
2381
- const evictions = [];
2382
- const slots = new Map(base.slots);
2383
- for (const [owner, slot] of base.slots) {
2384
- if (!slot.registrations.some((entry) => entry.id === registration.id)) continue;
2385
- slots.set(owner, {
2386
- ...slot,
2387
- registrations: Object.freeze(slot.registrations.filter((entry) => entry.id !== registration.id))
2388
- });
2389
- evictions.push({
2390
- kind: "registration_conflict",
2391
- registrationId: registration.id,
2392
- owner,
2393
- generation: slot.generation,
2394
- conflictsWith: "host",
2395
- action: "evicted"
2396
- });
2397
- }
2398
- state = makeState([...base.host, registration], slots);
2399
- for (const eviction of evictions) emit(eviction);
2400
- },
2401
- prepareReplacement(owner, generation, registrations) {
2402
- if (!isRegistrationOwner(owner)) {
2403
- return { status: "rejected", owner, reason: "unknown-owner", activeGeneration: 0 };
2404
- }
2405
- const base = state;
2406
- const slot = slotFor(base, owner);
2407
- if (!Number.isInteger(generation) || generation <= slot.generation) {
2408
- return { status: "rejected", owner, reason: "stale", activeGeneration: slot.generation };
2409
- }
2410
- const dropped = [];
2411
- const conflicts = [];
2412
- const accepted = [];
2413
- const seen = /* @__PURE__ */ new Set();
2414
- for (const registration of registrations) {
2415
- const conflictsWith = fixedIds.has(registration.id) ? "builtin" : base.hostIds.has(registration.id) ? "host" : seen.has(registration.id) ? "owned" : null;
2416
- if (conflictsWith !== null) {
2417
- dropped.push({ id: registration.id, conflictsWith });
2418
- conflicts.push({
2419
- kind: "registration_conflict",
2420
- registrationId: registration.id,
2421
- owner,
2422
- generation,
2423
- conflictsWith,
2424
- action: "dropped"
2425
- });
2426
- continue;
2427
- }
2428
- seen.add(registration.id);
2429
- accepted.push(registration);
2430
- }
2431
- const slots = new Map(base.slots);
2432
- slots.set(owner, { generation, registrations: Object.freeze(accepted), anchor: slot.anchor });
2433
- const prepared = makeState(base.host, slots);
2434
- let settled = false;
2435
- const frozenDropped = Object.freeze(dropped);
2436
- const frozenConflicts = Object.freeze(conflicts);
2437
- const replacement = {
2438
- owner,
2439
- generation,
2440
- dropped: frozenDropped,
2441
- conflicts: frozenConflicts,
2442
- size: accepted.length,
2443
- // Reference identity on the base state covers every kind of
2444
- // intervening change: host appends, other replacements, disposals.
2445
- current: () => !settled && state === base,
2446
- publish() {
2447
- settled = true;
2448
- state = prepared;
2449
- },
2450
- emitConflicts() {
2451
- for (const conflict of frozenConflicts) emit(conflict);
2452
- },
2453
- dispose() {
2454
- disposeGeneration(owner, generation);
2455
- },
2456
- discard() {
2457
- settled = true;
2458
- }
2459
- };
2460
- return { status: "prepared", replacement };
2461
- },
2462
- replaceRegistrations(owner, generation, registrations) {
2463
- const prepared = table.prepareReplacement(owner, generation, registrations);
2464
- if (prepared.status === "rejected") {
2465
- return {
2466
- applied: false,
2467
- owner: prepared.owner,
2468
- activeGeneration: prepared.activeGeneration,
2469
- reason: prepared.reason,
2470
- dropped: [],
2471
- dispose: () => void 0
2472
- };
2473
- }
2474
- const replacement = prepared.replacement;
2475
- if (!replacement.current()) {
2476
- replacement.discard();
2477
- return {
2478
- applied: false,
2479
- owner,
2480
- activeGeneration: table.ownedGeneration(owner),
2481
- reason: "stale",
2482
- dropped: replacement.dropped,
2483
- dispose: () => void 0
2484
- };
2485
- }
2486
- replacement.publish();
2487
- replacement.emitConflicts();
2488
- return {
2489
- applied: true,
2490
- owner,
2491
- activeGeneration: generation,
2492
- dropped: replacement.dropped,
2493
- dispose: () => replacement.dispose()
2494
- };
2495
- },
2496
- ownedGeneration(owner) {
2497
- return state.slots.get(owner)?.generation ?? 0;
2498
- }
2499
- };
2500
- return table;
2501
- }
2502
-
2503
- // src/domains/middleware/snapshot.ts
2504
- init_esm_shims();
2505
- function createMiddlewareSnapshot(rules = listMiddlewareRules()) {
2506
- return {
2507
- version: 1,
2508
- rules: rules.map(cloneMiddlewareRule)
2509
- };
2510
- }
2511
- function createMiddlewareContractFromSnapshot(snapshot) {
2512
- const builtinById = new Map(listMiddlewareRuleDefinitions().map((definition) => [definition.rule.id, definition]));
2513
- const definitions = snapshot.rules.map((rule) => {
2514
- const builtin = builtinById.get(rule.id);
2515
- const definition = {
2516
- rule: cloneMiddlewareRule(rule),
2517
- effects: builtin === void 0 ? [] : builtin.effects.map(cloneMiddlewareEffect)
2518
- };
2519
- if (builtin?.toolNames !== void 0) definition.toolNames = [...builtin.toolNames];
2520
- if (builtin?.predicate !== void 0) definition.predicate = builtin.predicate;
2521
- return definition;
2522
- });
2523
- let diagnosticSink;
2524
- const table = createMiddlewareRegistrationTable({
2525
- fixed: definitions.map(registrationFromRuleDefinition),
2526
- diagnosticSink: () => diagnosticSink ?? writeMiddlewareDiagnosticToStderr
2527
- });
2528
- const budgetTracker = createHookBudgetTracker({
2529
- budgets: resolveHookBudgetsFromEnv(),
2530
- ...resolveHookBudgetTunablesFromEnv()
2531
- });
2532
- return {
2533
- runHook(input) {
2534
- const registrations = table.list();
2535
- return runMiddlewareRegistrations(input, registrations, {
2536
- budgetTracker,
2537
- ...diagnosticSink !== void 0 ? { onDiagnostic: diagnosticSink } : {}
2538
- });
2539
- },
2540
- listRules() {
2541
- return definitions.map((definition) => cloneMiddlewareRule(definition.rule));
2542
- },
2543
- snapshot() {
2544
- return createMiddlewareSnapshot(definitions.map((definition) => definition.rule));
2545
- },
2546
- registerHook(registration) {
2547
- table.registerHook(registration);
2548
- },
2549
- setDiagnosticSink(sink) {
2550
- diagnosticSink = sink;
2551
- },
2552
- prepareRegistrationReplacement(owner, generation, registrations) {
2553
- return table.prepareReplacement(owner, generation, registrations);
2554
- },
2555
- replaceRegistrations(owner, generation, registrations) {
2556
- return table.replaceRegistrations(owner, generation, registrations);
2557
- },
2558
- ownedGeneration(owner) {
2559
- return table.ownedGeneration(owner);
2560
- }
2561
- };
2562
- }
2563
-
2564
- // src/domains/middleware/extension.ts
2565
- function createEnvHookBudgetTracker(env = process.env) {
2566
- return createHookBudgetTracker({ budgets: resolveHookBudgetsFromEnv(env), ...resolveHookBudgetTunablesFromEnv(env) });
2567
- }
2568
- function createMiddlewareBundle(options = {}) {
2569
- const ruleDefinitions = combineRuleDefinitions(listMiddlewareRuleDefinitions(), options.ruleDefinitions ?? []);
2570
- let diagnosticSink = options.onDiagnostic;
2571
- const table = createMiddlewareRegistrationTable({
2572
- fixed: ruleDefinitions.map(registrationFromRuleDefinition),
2573
- diagnosticSink: () => diagnosticSink ?? writeMiddlewareDiagnosticToStderr
2574
- });
2575
- for (const registration of options.registrations ?? []) table.registerHook(registration);
2576
- const budgetTracker = options.budgetTracker ?? createEnvHookBudgetTracker();
2577
- const contract = {
2578
- runHook(input) {
2579
- const registrations = table.list();
2580
- return runMiddlewareRegistrations(input, registrations, {
2581
- budgetTracker,
2582
- ...diagnosticSink !== void 0 ? { onDiagnostic: diagnosticSink } : {}
2583
- });
2584
- },
2585
- runAsyncHook(input, priorEffects = []) {
2586
- const registrations = table.list();
2587
- return runMiddlewareAsyncRegistrations(input, registrations, priorEffects, {
2588
- ...diagnosticSink !== void 0 ? { onDiagnostic: diagnosticSink } : {}
2589
- });
2590
- },
2591
- listRules() {
2592
- return ruleDefinitions.map((definition) => cloneMiddlewareRule(definition.rule));
2593
- },
2594
- snapshot() {
2595
- return createMiddlewareSnapshot(ruleDefinitions.map((definition) => definition.rule));
2596
- },
2597
- registerHook(registration) {
2598
- table.registerHook(registration);
2599
- },
2600
- setDiagnosticSink(sink) {
2601
- diagnosticSink = sink;
2602
- },
2603
- prepareRegistrationReplacement(owner, generation, registrations) {
2604
- return table.prepareReplacement(owner, generation, registrations);
2605
- },
2606
- replaceRegistrations(owner, generation, registrations) {
2607
- return table.replaceRegistrations(owner, generation, registrations);
2608
- },
2609
- ownedGeneration(owner) {
2610
- return table.ownedGeneration(owner);
2611
- }
2612
- };
2613
- return {
2614
- extension: {
2615
- start() {
2616
- return void 0;
2617
- }
2618
- },
2619
- contract
2620
- };
2621
- }
2622
- function combineRuleDefinitions(builtin, registered) {
2623
- const seen = /* @__PURE__ */ new Set();
2624
- const combined = [];
2625
- for (const definition of [...builtin, ...registered]) {
2626
- if (seen.has(definition.rule.id)) continue;
2627
- seen.add(definition.rule.id);
2628
- combined.push(definition);
2629
- }
2630
- return combined;
2631
- }
2632
-
2633
- // src/domains/middleware/manifest.ts
2634
- init_esm_shims();
2635
- var MiddlewareManifest = {
2636
- name: "middleware",
2637
- dependsOn: []
2638
- };
2639
-
2640
- // src/domains/middleware/hooks.ts
2641
- init_esm_shims();
2642
- import { createHash as createHash2 } from "node:crypto";
2643
- import { isAbsolute, resolve } from "node:path";
2644
-
2645
- // src/domains/middleware/validate.ts
2646
- init_esm_shims();
2647
- function validateMiddlewareEffect(value, source = "$") {
2648
- const issues = [];
2649
- const effect = readMiddlewareEffect(value, source, issues);
2650
- if (issues.length > 0 || effect === null) return { valid: false, issues };
2651
- return { valid: true, effect, issues: [] };
2652
- }
2653
- function readMiddlewareEffect(value, path2, issues) {
2654
- if (!isRecord(value)) {
2655
- issues.push({ path: path2, message: "expected middleware effect object" });
2656
- return null;
2657
- }
2658
- const kindValue = value.kind;
2659
- if (typeof kindValue !== "string" || !isMiddlewareEffectKind(kindValue)) {
2660
- issues.push({ path: `${path2}.kind`, message: "expected known middleware effect kind" });
2661
- return null;
2662
- }
2663
- switch (kindValue) {
2664
- case "inject_reminder":
2665
- return readInjectReminder(value, path2, issues);
2666
- case "annotate_tool_result":
2667
- return readAnnotateToolResult(value, path2, issues);
2668
- case "block_tool":
2669
- return readBlockTool(value, path2, issues);
2670
- case "protect_path":
2671
- return readProtectPath(value, path2, issues);
2672
- case "request_continuation":
2673
- return readRequestContinuation(value, path2, issues);
2674
- case "require_tool":
2675
- return readRequireTool(value, path2, issues);
2676
- case "lock_tools":
2677
- rejectUnexpectedFields(value, path2, ["kind"], issues);
2678
- return { kind: "lock_tools" };
2679
- }
2680
- }
2681
- function readRequireTool(record, path2, issues) {
2682
- rejectUnexpectedFields(record, path2, ["kind", "toolName"], issues);
2683
- const toolName = readRequiredString(record, `${path2}.toolName`, issues);
2684
- return toolName === null ? null : { kind: "require_tool", toolName };
2685
- }
2686
- function readInjectReminder(record, path2, issues) {
2687
- rejectUnexpectedFields(record, path2, ["kind", "message", "severity"], issues);
2688
- const message = readRequiredString(record, `${path2}.message`, issues);
2689
- const severity = readOptionalString(record, `${path2}.severity`, issues);
2690
- if (severity !== void 0 && !isMiddlewareReminderSeverity(severity)) {
2691
- issues.push({ path: `${path2}.severity`, message: "expected info, advisory, warn, or hard-block" });
2692
- }
2693
- if (message === null) return null;
2694
- const effect = { kind: "inject_reminder", message };
2695
- if (severity !== void 0 && isMiddlewareReminderSeverity(severity)) effect.severity = severity;
2696
- return effect;
2697
- }
2698
- function readAnnotateToolResult(record, path2, issues) {
2699
- rejectUnexpectedFields(record, path2, ["kind", "message", "severity"], issues);
2700
- const message = readRequiredString(record, `${path2}.message`, issues);
2701
- const severity = readOptionalString(record, `${path2}.severity`, issues);
2702
- if (severity !== void 0 && !isMiddlewareAnnotationSeverity(severity)) {
2703
- issues.push({ path: `${path2}.severity`, message: "expected info or warn" });
2704
- }
2705
- if (message === null) return null;
2706
- const effect = { kind: "annotate_tool_result", message };
2707
- if (severity !== void 0 && isMiddlewareAnnotationSeverity(severity)) effect.severity = severity;
2708
- return effect;
2709
- }
2710
- function readBlockTool(record, path2, issues) {
2711
- rejectUnexpectedFields(record, path2, ["kind", "reason", "severity"], issues);
2712
- const reason = readRequiredString(record, `${path2}.reason`, issues);
2713
- const severity = readRequiredString(record, `${path2}.severity`, issues);
2714
- if (severity !== null && severity !== "hard-block") {
2715
- issues.push({ path: `${path2}.severity`, message: "expected hard-block" });
2716
- }
2717
- if (reason === null || severity !== "hard-block") return null;
2718
- return { kind: "block_tool", reason, severity };
2719
- }
2720
- function readProtectPath(record, path2, issues) {
2721
- rejectUnexpectedFields(record, path2, ["kind", "path", "reason"], issues);
2722
- const protectedPath = readRequiredString(record, `${path2}.path`, issues);
2723
- const reason = readRequiredString(record, `${path2}.reason`, issues);
2724
- if (protectedPath === null || reason === null) return null;
2725
- return { kind: "protect_path", path: protectedPath, reason };
2726
- }
2727
- function readRequestContinuation(record, path2, issues) {
2728
- rejectUnexpectedFields(record, path2, ["kind", "message"], issues);
2729
- const message = readRequiredString(record, `${path2}.message`, issues);
2730
- if (message === null) return null;
2731
- return { kind: "request_continuation", message };
2732
- }
2733
- function readRequiredString(record, path2, issues) {
2734
- const value = record[pathField(path2)];
2735
- if (typeof value !== "string" || value.trim().length === 0) {
2736
- issues.push({ path: path2, message: "expected non-empty string" });
2737
- return null;
2738
- }
2739
- return value;
2740
- }
2741
- function readOptionalString(record, path2, issues) {
2742
- const field = pathField(path2);
2743
- if (!Object.hasOwn(record, field)) return void 0;
2744
- const value = record[field];
2745
- if (typeof value !== "string" || value.trim().length === 0) {
2746
- issues.push({ path: path2, message: "expected non-empty string" });
2747
- return void 0;
2748
- }
2749
- return value;
2750
- }
2751
- function rejectUnexpectedFields(record, path2, allowedFields, issues) {
2752
- const allowed = new Set(allowedFields);
2753
- for (const field of Object.keys(record).sort((a, b) => a.localeCompare(b))) {
2754
- if (!allowed.has(field)) issues.push({ path: `${path2}.${field}`, message: "unexpected field" });
2755
- }
2756
- }
2757
- function pathField(path2) {
2758
- return path2.slice(path2.lastIndexOf(".") + 1);
2759
- }
2760
- function isRecord(value) {
2761
- return typeof value === "object" && value !== null && !Array.isArray(value);
2762
- }
2763
-
2764
- // src/domains/middleware/hooks.ts
2765
- var USER_HOOK_ORIGIN_ORDER = ["extension", "user", "project", "project.local"];
2766
- var USER_HOOK_COMMAND_TIMEOUT_DEFAULT_MS = 2e3;
2767
- var USER_HOOK_COMMAND_TIMEOUT_MIN_MS = 100;
2768
- var USER_HOOK_COMMAND_TIMEOUT_MAX_MS = 5e3;
2769
- var USER_HOOK_COMMAND_OUTPUT_MAX_CHARS = 4e3;
2770
- var USER_HOOK_PROMPT_MAX_CHARS = 2e3;
2771
- function isRecord2(value) {
2772
- return value !== null && typeof value === "object" && !Array.isArray(value);
2773
- }
2774
- function stableHash(value) {
2775
- return createHash2("sha256").update(canonicalJson(value)).digest("hex").slice(0, 16);
2776
- }
2777
- function canonicalJson(value) {
2778
- if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
2779
- if (isRecord2(value)) {
2780
- const keys = Object.keys(value).sort();
2781
- return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
2782
- }
2783
- return JSON.stringify(value) ?? "null";
2784
- }
2785
- function readStringArray(value) {
2786
- if (!Array.isArray(value)) return null;
2787
- const out = [];
2788
- for (const item of value) {
2789
- if (typeof item !== "string" || item.length === 0) return null;
2790
- out.push(item);
2791
- }
2792
- return out;
2793
- }
2794
- function normalizeCommandSpec(raw, options, issues) {
2795
- const argv = readStringArray(raw.argv);
2796
- if (!argv || argv.length === 0) {
2797
- issues.push("command.argv must be a non-empty array of non-empty strings");
2798
- return null;
2799
- }
2800
- const spec = {
2801
- kind: "command",
2802
- argv,
2803
- cwd: resolve(options.workspaceRoot),
2804
- timeoutMs: USER_HOOK_COMMAND_TIMEOUT_DEFAULT_MS,
2805
- as: "annotate"
2806
- };
2807
- if (raw.cwd !== void 0) {
2808
- if (typeof raw.cwd !== "string" || raw.cwd.length === 0) {
2809
- issues.push("command.cwd must be a non-empty string");
2810
- return null;
2811
- }
2812
- const resolved = isAbsolute(raw.cwd) ? resolve(raw.cwd) : resolve(options.workspaceRoot, raw.cwd);
2813
- if (!isWithin(resolved, options.workspaceRoot)) {
2814
- issues.push("command.cwd must resolve under the workspace root");
2815
- return null;
2816
- }
2817
- spec.cwd = resolved;
2818
- }
2819
- if (raw.timeoutMs !== void 0) {
2820
- if (typeof raw.timeoutMs !== "number" || !Number.isFinite(raw.timeoutMs)) {
2821
- issues.push("command.timeoutMs must be a number");
2822
- return null;
2823
- }
2824
- spec.timeoutMs = Math.min(
2825
- USER_HOOK_COMMAND_TIMEOUT_MAX_MS,
2826
- Math.max(USER_HOOK_COMMAND_TIMEOUT_MIN_MS, Math.floor(raw.timeoutMs))
2827
- );
2828
- }
2829
- if (raw.as !== void 0) {
2830
- if (raw.as !== "annotate" && raw.as !== "reminder") {
2831
- issues.push('command.as must be "annotate" or "reminder"');
2832
- return null;
2833
- }
2834
- spec.as = raw.as;
2835
- }
2836
- return spec;
2837
- }
2838
- function normalizePromptSpec(raw, issues) {
2839
- if (typeof raw.message !== "string" || raw.message.trim().length === 0) {
2840
- issues.push("prompt.message must be a non-empty string");
2841
- return null;
2842
- }
2843
- let severity = "info";
2844
- if (raw.severity !== void 0) {
2845
- if (typeof raw.severity !== "string" || !isMiddlewareReminderSeverity(raw.severity)) {
2846
- issues.push("prompt.severity must be info, advisory, warn, or hard-block");
2847
- return null;
2848
- }
2849
- severity = raw.severity;
2850
- }
2851
- return { kind: "prompt", message: raw.message.slice(0, USER_HOOK_PROMPT_MAX_CHARS), severity };
2852
- }
2853
- function normalizeEffectSpec(raw, issues) {
2854
- const result = validateMiddlewareEffect(raw.effect ?? raw, "effect");
2855
- if (!result.valid) {
2856
- for (const issue of result.issues) issues.push(`effect: ${issue.message}`);
2857
- return null;
2858
- }
2859
- return { kind: "effect", effect: result.effect };
2860
- }
2861
- function isWithin(child, parent) {
2862
- const rel = resolve(child);
2863
- const base = resolve(parent);
2864
- return rel === base || rel.startsWith(`${base}/`);
2865
- }
2866
- function normalizeUserHook(raw, source, options) {
2867
- const issues = [];
2868
- if (!isRecord2(raw)) {
2869
- return { issues: ["hook declaration must be an object"] };
2870
- }
2871
- if (raw.on === void 0 || typeof raw.on !== "string" || !isMiddlewareHook(raw.on)) {
2872
- issues.push("on must be one of before_tool, after_tool, turn_start, turn_end, on_compaction");
2873
- }
2874
- let tools;
2875
- if (raw.tools !== void 0) {
2876
- const parsed = readStringArray(raw.tools);
2877
- if (!parsed) issues.push("tools must be an array of non-empty tool names");
2878
- else tools = parsed;
2879
- }
2880
- let enabled = true;
2881
- if (raw.enabled !== void 0) {
2882
- if (typeof raw.enabled !== "boolean") issues.push("enabled must be a boolean");
2883
- else enabled = raw.enabled;
2884
- }
2885
- let spec = null;
2886
- if (raw.kind === "command") spec = normalizeCommandSpec(raw, options, issues);
2887
- else if (raw.kind === "prompt") spec = normalizePromptSpec(raw, issues);
2888
- else if (raw.kind === "effect") spec = normalizeEffectSpec(raw, issues);
2889
- else issues.push('kind must be "command", "prompt", or "effect"');
2890
- if (issues.length > 0 || spec === null || raw.on === void 0 || typeof raw.on !== "string") {
2891
- return { issues };
2892
- }
2893
- const on = raw.on;
2894
- const hash = stableHash({ on, tools: tools ?? null, spec });
2895
- const id = typeof raw.id === "string" && raw.id.length > 0 ? raw.id : `${source.sourceId ?? source.origin}.${spec.kind}.${hash}`;
2896
- const hook = { id, source, hash, on, enabled, spec };
2897
- if (tools !== void 0) hook.tools = tools;
2898
- return { hook, issues };
2899
- }
2900
- function declarationsArray(declarations) {
2901
- if (Array.isArray(declarations)) return declarations;
2902
- if (isRecord2(declarations) && Array.isArray(declarations.hooks)) return declarations.hooks;
2903
- return [];
2904
- }
2905
- function loadUserHooks(batches, options) {
2906
- const ordered = [...batches].sort(
2907
- (a, b) => USER_HOOK_ORIGIN_ORDER.indexOf(a.source.origin) - USER_HOOK_ORIGIN_ORDER.indexOf(b.source.origin)
2908
- );
2909
- const byId = /* @__PURE__ */ new Map();
2910
- const overridden = [];
2911
- const issues = [];
2912
- for (const batch of ordered) {
2913
- const declarations = declarationsArray(batch.declarations);
2914
- declarations.forEach((raw, index) => {
2915
- const result = normalizeUserHook(raw, batch.source, options);
2916
- if (!result.hook) {
2917
- issues.push({ source: batch.source, index, issues: result.issues });
2918
- return;
2919
- }
2920
- const existing = byId.get(result.hook.id);
2921
- if (existing) overridden.push({ winner: batch.source, loser: existing });
2922
- byId.set(result.hook.id, result.hook);
2923
- });
2924
- }
2925
- return { hooks: [...byId.values()], overridden, issues };
2926
- }
2927
- function reminderEffect(message, severity) {
2928
- return severity === "info" ? { kind: "inject_reminder", message } : { kind: "inject_reminder", message, severity };
2929
- }
2930
- function commandEffect(hook, output) {
2931
- const message = output.slice(0, USER_HOOK_COMMAND_OUTPUT_MAX_CHARS);
2932
- return hook.as === "reminder" ? { kind: "inject_reminder", message } : { kind: "annotate_tool_result", message };
2933
- }
2934
- function userHookToRegistration(hook, deps) {
2935
- const now = deps.now ?? Date.now;
2936
- const extension = hook.source.extension === void 0 ? void 0 : receiptExtension(hook.source.extension);
2937
- const baseReceipt = (input) => ({
2938
- at: now(),
2939
- hookId: hook.id,
2940
- origin: hook.source.origin,
2941
- sourcePath: hook.source.sourcePath,
2942
- hash: hook.hash,
2943
- hook: hook.on,
2944
- kind: hook.spec.kind,
2945
- ...extension !== void 0 ? { extension: { ...extension } } : {},
2946
- ...input.toolName !== void 0 ? { toolName: input.toolName } : {}
2947
- });
2948
- const registration = {
2949
- id: hook.id,
2950
- description: `${hook.spec.kind} hook from ${hook.source.origin} (${hook.source.sourcePath})`,
2951
- hooks: [hook.on],
2952
- evaluate: (input) => {
2953
- if (!hook.enabled) return [];
2954
- try {
2955
- if (deps.isTrusted?.() === false) {
2956
- deps.recordReceipt({ ...baseReceipt(input), outcome: "skipped" });
2957
- return [];
2958
- }
2959
- return evaluateHook(hook, deps, baseReceipt(input));
2960
- } catch {
2961
- deps.recordReceipt({ ...baseReceipt(input), outcome: "skipped" });
2962
- return [];
2963
- }
2964
- }
2965
- };
2966
- if (hook.tools !== void 0) registration.toolNames = [...hook.tools];
2967
- return registration;
2968
- }
2969
- function receiptExtension(source) {
2970
- return {
2971
- id: source.provenance.id,
2972
- scope: source.provenance.scope,
2973
- canonicalRoot: source.provenance.canonicalRoot,
2974
- manifestDigest: source.provenance.manifestDigest,
2975
- contentDigest: source.provenance.contentDigest,
2976
- declarationsDigest: source.declarationsDigest,
2977
- generation: source.generation
2978
- };
2979
- }
2980
- function evaluateHook(hook, deps, base) {
2981
- if (hook.spec.kind === "prompt") {
2982
- const effect2 = reminderEffect(hook.spec.message, hook.spec.severity);
2983
- deps.recordReceipt({ ...base, outcome: "emitted", effectKinds: ["inject_reminder"] });
2984
- return [effect2];
2985
- }
2986
- if (hook.spec.kind === "effect") {
2987
- deps.recordReceipt({ ...base, outcome: "emitted", effectKinds: [hook.spec.effect.kind] });
2988
- return [hook.spec.effect];
2989
- }
2990
- const result = deps.runCommand(hook.spec.argv, {
2991
- timeoutMs: hook.spec.timeoutMs,
2992
- ...hook.spec.cwd !== void 0 ? { cwd: hook.spec.cwd } : {}
2993
- });
2994
- const output = (result.stdout || result.stderr || "").trim();
2995
- if (result.timedOut) {
2996
- deps.recordReceipt({ ...base, outcome: "command-timeout", exitCode: result.code ?? -1, outputChars: output.length });
2997
- return [];
2998
- }
2999
- const outcome = result.code === 0 ? "command-ok" : "command-failed";
3000
- deps.recordReceipt({ ...base, outcome, exitCode: result.code ?? -1, outputChars: output.length });
3001
- if (output.length === 0) return [];
3002
- const effect = commandEffect(hook.spec, output);
3003
- return [effect];
3004
- }
3005
-
3006
- // src/domains/middleware/hooks-io.ts
3007
- init_esm_shims();
3008
- var import_yaml = __toESM(require_dist(), 1);
3009
- import { spawnSync } from "node:child_process";
3010
- var COMMAND_OUTPUT_MAX_BYTES = 1024 * 1024;
3011
- function readBatch(source, filePath, text, fileIssues) {
3012
- try {
3013
- const parsed = (0, import_yaml.parse)(text);
3014
- return { source, declarations: parsed ?? [] };
3015
- } catch (err) {
3016
- fileIssues.push({
3017
- source,
3018
- message: `failed to parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`
3019
- });
3020
- return null;
3021
- }
3022
- }
3023
- function readHookSources(options) {
3024
- const fileIssues = [];
3025
- const batches = [];
3026
- const captured = options.capturedSources;
3027
- for (const entry of captured?.sources ?? []) {
3028
- const source = {
3029
- origin: "extension",
3030
- sourcePath: `${entry.provenance.id}:hooks.yaml`,
3031
- sourceId: entry.provenance.id,
3032
- extension: {
3033
- provenance: entry.provenance,
3034
- generation: captured?.generation ?? 0,
3035
- declarationsDigest: entry.declarationsDigest
3036
- }
3037
- };
3038
- if (entry.parseError !== void 0) {
3039
- fileIssues.push({ source, message: `failed to parse ${source.sourcePath}: ${entry.parseError}` });
3040
- continue;
3041
- }
3042
- batches.push({ source, declarations: entry.declarations });
3043
- }
3044
- const projectSurface = captureProjectSurface(options.cwd, "hooks");
3045
- for (const [index, file] of projectSurface.files.entries()) {
3046
- const source = {
3047
- origin: index === 0 ? "project" : "project.local",
3048
- sourcePath: index === 0 ? ".clio-coder/hooks.yaml" : ".clio-coder/hooks.local.yaml"
3049
- };
3050
- if (file.error !== void 0) fileIssues.push({ source, message: file.error });
3051
- if (file.text === null) continue;
3052
- if (projectSurface.verdict !== "trusted") {
3053
- fileIssues.push({ source, message: projectSurfaceTrustNotice(projectSurface, file.path) });
3054
- continue;
3055
- }
3056
- const batch = readBatch(source, file.path, file.text, fileIssues);
3057
- if (batch) batches.push(batch);
3058
- }
3059
- return { batches, fileIssues, projectSurface };
3060
- }
3061
- function buildUserHookRegistrations(options) {
3062
- const workspaceRoot = options.workspaceRoot ?? options.cwd;
3063
- const readOptions = { cwd: options.cwd };
3064
- if (options.capturedSources !== void 0) readOptions.capturedSources = options.capturedSources;
3065
- const { batches, fileIssues, projectSurface } = readHookSources(readOptions);
3066
- const loaded = loadUserHooks(batches, { workspaceRoot });
3067
- const runCommand = options.runCommand ?? spawnSyncCommandRunner();
3068
- let reportedUntrusted = false;
3069
- const projectStillTrusted = () => {
3070
- const current = captureProjectSurface(options.cwd, "hooks");
3071
- if (current.verdict === "trusted" && current.contentHash === projectSurface.contentHash) return true;
3072
- if (!reportedUntrusted) {
3073
- reportedUntrusted = true;
3074
- options.report?.(
3075
- `[clio-coder:hooks] project hooks changed or trust was revoked; hooks skipped. Review with clio-coder config trust hooks, then reload extensions.`
3076
- );
3077
- }
3078
- return false;
3079
- };
3080
- const registrations = loaded.hooks.map(
3081
- (hook) => userHookToRegistration(hook, {
3082
- recordReceipt: options.recordReceipt,
3083
- runCommand,
3084
- ...hook.source.origin === "project" || hook.source.origin === "project.local" ? { isTrusted: projectStillTrusted } : {},
3085
- ...options.now !== void 0 ? { now: options.now } : {}
3086
- })
3087
- );
3088
- return { ...loaded, fileIssues, registrations };
3089
- }
3090
- function spawnSyncCommandRunner() {
3091
- return (argv, options) => {
3092
- const [command, ...args] = argv;
3093
- const attribution = withManagedGitCommitAttributionEnvironment(buildSafeToolEnv(), {
3094
- cwd: options.cwd ?? process.cwd(),
3095
- enabled: gitCommitAttributionEnabled(process.env),
3096
- evidence: {}
3097
- });
3098
- reportCommitAttributionDiagnostic(attribution.diagnostic);
3099
- const result = spawnSync(command ?? "", args, {
3100
- ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
3101
- timeout: options.timeoutMs,
3102
- maxBuffer: COMMAND_OUTPUT_MAX_BYTES,
3103
- encoding: "utf8",
3104
- shell: false,
3105
- env: attribution.env
3106
- });
3107
- const timedOut = result.error !== void 0 && result.error.code === "ETIMEDOUT";
3108
- return {
3109
- code: result.status,
3110
- timedOut,
3111
- stdout: typeof result.stdout === "string" ? result.stdout : "",
3112
- stderr: typeof result.stderr === "string" ? result.stderr : ""
3113
- };
3114
- };
3115
- }
3116
-
3117
- // src/domains/middleware/index.ts
3118
- var MiddlewareDomainModule = {
3119
- manifest: MiddlewareManifest,
3120
- createExtension: () => createMiddlewareBundle()
3121
- };
3122
-
3123
- export {
3124
- MIDDLEWARE_HOOK_TEXT_MAX_CHARS,
3125
- shouldRequestStalledTurnContinuation,
3126
- writeMiddlewareDiagnosticToStderr,
3127
- formatRegistrationConflict,
3128
- createMiddlewareContractFromSnapshot,
3129
- createReadOnlyExplorationNudgeRegistration,
3130
- createUnbackedWorkerClaimRegistration,
3131
- openDetachedBatchViews,
3132
- createDetachedDispatchNudgeRegistration,
3133
- HOOK_RECEIPT_LOG_CAPACITY,
3134
- createHookReceiptLog,
3135
- readPersistedHookReceipts,
3136
- loadUserHooks,
3137
- readHookSources,
3138
- buildUserHookRegistrations,
3139
- createSkillsReminderRegistration,
3140
- createMarketplaceOfferRegistration,
3141
- createMemoryInterventionRegistration,
3142
- announceMemoryStepEndpoint,
3143
- createTaskBoardReminderRegistration,
3144
- createTaskNudgeRegistration,
3145
- createMiddlewareToolChoiceControl,
3146
- WATCHDOG_TASK,
3147
- watchdogBriefing,
3148
- createWatchdogRegistration,
3149
- MiddlewareDomainModule
3150
- };
3151
- //# sourceMappingURL=chunk-VPWGADBG.js.map