@iowarp/clio-coder 0.4.7 → 0.4.9

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 (675) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +111 -0
  3. package/CONTRIBUTING.md +83 -74
  4. package/README.md +69 -47
  5. package/dist/{acp-W3Y3TRHD.js → acp-ZWZCPS2A.js} +15 -15
  6. package/dist/{agents-J4ICNLQ3.js → agents-LYSOWZUE.js} +61 -59
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/assets/web-notices/@hono__node-server-LICENSE +21 -0
  9. package/dist/assets/web-notices/hono-LICENSE +21 -0
  10. package/dist/{auth-X2UJUMOC.js → auth-WBQGKWQ5.js} +27 -27
  11. package/dist/background-BUMOBAQN.js +37 -0
  12. package/dist/{builtins-XLXWWSRF.js → builtins-ODRJOEDI.js} +7 -7
  13. package/dist/{chunk-C3G5PNUO.js → chunk-2DRRZ57Q.js} +36 -27
  14. package/dist/chunk-2JBZYUPY.js +105 -0
  15. package/dist/chunk-2KUBKL63.js +336 -0
  16. package/dist/chunk-2VBWFXYE.js +198 -0
  17. package/dist/{chunk-XZ6UFQ52.js → chunk-2X2R3UTH.js} +25 -15
  18. package/dist/{chunk-M6Z2V6YU.js → chunk-37LW32LZ.js} +5 -5
  19. package/dist/{chunk-6LRLOJHQ.js → chunk-3AND2EFU.js} +11 -62
  20. package/dist/{chunk-FQOOGXBH.js → chunk-3RDHGNU7.js} +101 -33
  21. package/dist/{chunk-D2T66PDV.js → chunk-3SUDBGEI.js} +41 -208
  22. package/dist/{chunk-5AJPUR72.js → chunk-3TQN67I2.js} +9 -9
  23. package/dist/{chunk-LBFQMYS3.js → chunk-3U4BL2EV.js} +5 -3
  24. package/dist/{chunk-UFYNOQK4.js → chunk-3UQADNG2.js} +7 -7
  25. package/dist/{chunk-V4ZKOKRB.js → chunk-434LRQ6Z.js} +61 -53
  26. package/dist/{chunk-NO7J45X6.js → chunk-4ATBOFRP.js} +713 -218
  27. package/dist/{chunk-ECOMVOHP.js → chunk-4DNL43EZ.js} +3 -3
  28. package/dist/{chunk-WT5TRMO4.js → chunk-4HFJKRGZ.js} +255 -82
  29. package/dist/{chunk-5A6XR3RJ.js → chunk-555E2WVV.js} +16 -2
  30. package/dist/{chunk-WURGVOZJ.js → chunk-5RTEFNBP.js} +18 -14
  31. package/dist/{config-YXARKGTX.js → chunk-64XJW7NT.js} +24 -268
  32. package/dist/{chunk-24S3DN22.js → chunk-6TKOFFGE.js} +4 -4
  33. package/dist/{chunk-YKRJTYNP.js → chunk-6UJ7RDI7.js} +4 -4
  34. package/dist/{chunk-MZNWZUJM.js → chunk-7FBCRWVT.js} +288 -288
  35. package/dist/{chunk-UA6W4XFJ.js → chunk-7JSOSVLP.js} +2 -2
  36. package/dist/chunk-7N3OLLSL.js +637 -0
  37. package/dist/{chunk-KKEYGFX4.js → chunk-7QQRPB2E.js} +11 -11
  38. package/dist/{chunk-N37QC5FV.js → chunk-A6DULIMH.js} +21 -9
  39. package/dist/{fleet-decisions-S3PTZV2D.js → chunk-AB3QXXBC.js} +5 -41
  40. package/dist/chunk-ACCECAH4.js +49 -0
  41. package/dist/{chunk-CP3HIR5H.js → chunk-AM6CEP2K.js} +20 -19
  42. package/dist/chunk-AUHVBIDW.js +19 -0
  43. package/dist/{chunk-BQQ5MXUC.js → chunk-AY4XE6GN.js} +19 -13
  44. package/dist/{chunk-ISNCCX42.js → chunk-BBA2TAWV.js} +10 -9
  45. package/dist/chunk-BFPHMSK7.js +169 -0
  46. package/dist/{chunk-LVFANMOH.js → chunk-BHJMMCXS.js} +4 -4
  47. package/dist/{chunk-DO7M3LSX.js → chunk-BMNVVKEW.js} +40 -93
  48. package/dist/{chunk-VTYHHQ57.js → chunk-CTGZCEI6.js} +2 -2
  49. package/dist/{chunk-RTLNFZMD.js → chunk-DIAJYJYG.js} +3 -3
  50. package/dist/chunk-EHZRAB4U.js +63 -0
  51. package/dist/{chunk-KS7ETA3P.js → chunk-EM2DIQAJ.js} +3 -3
  52. package/dist/{chunk-MNQN3X6Y.js → chunk-ETF4ROKH.js} +5 -5
  53. package/dist/{chunk-WN552PKN.js → chunk-F2YM3JY4.js} +744 -1134
  54. package/dist/{chunk-7EEGBKV4.js → chunk-FEBQWHJT.js} +24 -19
  55. package/dist/{chunk-4QKAITQT.js → chunk-FPS4R2RN.js} +74 -10
  56. package/dist/chunk-G5R53COU.js +68 -0
  57. package/dist/chunk-GHXGMFQ5.js +40 -0
  58. package/dist/{chunk-GFQ7P2UF.js → chunk-GJDRMBDI.js} +10 -10
  59. package/dist/{chunk-LZBMXNLP.js → chunk-GM4TY6VN.js} +43 -6
  60. package/dist/{chunk-NCCQ6DVS.js → chunk-GREYLTZ5.js} +8 -8
  61. package/dist/{chunk-HOX4YZ2K.js → chunk-H2WSCZZT.js} +19 -3
  62. package/dist/{chunk-3LXJOICS.js → chunk-H6IUCY6Q.js} +2 -2
  63. package/dist/{chunk-BO4XV5VX.js → chunk-H72DCH3E.js} +95 -206
  64. package/dist/{chunk-SEDI5K5B.js → chunk-H7TXJR23.js} +20 -20
  65. package/dist/chunk-HBJQQTKM.js +40 -0
  66. package/dist/chunk-HCVKSGNZ.js +990 -0
  67. package/dist/chunk-HVCAY2FH.js +67 -0
  68. package/dist/{chunk-34XHRVKG.js → chunk-I47EJPYL.js} +3 -3
  69. package/dist/{chunk-4N2RZ4TO.js → chunk-IALGWTLO.js} +3 -3
  70. package/dist/{chunk-IQCNVLO6.js → chunk-IALZJE37.js} +10 -7
  71. package/dist/{chunk-DLIYANB7.js → chunk-IC7JXLOM.js} +16 -11
  72. package/dist/{chunk-G4LGUTOE.js → chunk-IOSVTTCD.js} +5 -5
  73. package/dist/{chunk-DBREN25X.js → chunk-IPTPMLA6.js} +8 -3
  74. package/dist/{chunk-V552WL53.js → chunk-IZZI3SKQ.js} +3 -67
  75. package/dist/{chunk-TN5FW4XY.js → chunk-JIYWMQZ5.js} +12 -9
  76. package/dist/{chunk-T7QQBNLH.js → chunk-JKU34ACI.js} +10 -8
  77. package/dist/chunk-JOBN2YQQ.js +176 -0
  78. package/dist/chunk-JOL2QRLE.js +152 -0
  79. package/dist/{chunk-GXIWHXDB.js → chunk-JTR3VSV3.js} +3 -3
  80. package/dist/{chunk-T334FW2H.js → chunk-JU6MAMRJ.js} +7 -7
  81. package/dist/chunk-JURMQWVJ.js +15 -0
  82. package/dist/{chunk-CULVKYTK.js → chunk-K3XN4LZ4.js} +5 -5
  83. package/dist/{chunk-3T4DXWP6.js → chunk-KIVFXGBM.js} +27 -7
  84. package/dist/chunk-KKRXONXG.js +43 -0
  85. package/dist/{chunk-YPRSNUTC.js → chunk-KOAHT3N2.js} +2 -2
  86. package/dist/chunk-KP5BPXR3.js +73 -0
  87. package/dist/{chunk-UA3W4FGC.js → chunk-KRJQG47M.js} +6 -6
  88. package/dist/{chunk-GI5RRMAH.js → chunk-KW6OJ7IY.js} +19 -21
  89. package/dist/{chunk-A46ILRS2.js → chunk-L3NBWLSN.js} +4 -4
  90. package/dist/{chunk-MZHXENL7.js → chunk-L4RUTLRL.js} +8 -8
  91. package/dist/{chunk-P5SC4DLJ.js → chunk-LGTVWPRN.js} +2 -2
  92. package/dist/{chunk-65BGHOUR.js → chunk-LSQW6KZO.js} +5 -5
  93. package/dist/{chunk-TZHN5ITX.js → chunk-LWJYOHT3.js} +8 -8
  94. package/dist/{chunk-U3TPUXOQ.js → chunk-M6YLF66Z.js} +74 -40
  95. package/dist/chunk-MJ4QEJVT.js +185 -0
  96. package/dist/{chunk-T4TY5GG3.js → chunk-MO65K5CH.js} +5 -5
  97. package/dist/{chunk-TZ6UVP2H.js → chunk-MTOZEQHL.js} +8 -8
  98. package/dist/chunk-MZDPF35R.js +45 -0
  99. package/dist/{chunk-P4DL2LM5.js → chunk-MZKYVIWW.js} +8 -119
  100. package/dist/{chunk-KAFMW7WM.js → chunk-NBPA5QM6.js} +2 -2
  101. package/dist/{chunk-EUEXGXXR.js → chunk-NMBEW4PP.js} +5 -5
  102. package/dist/{chunk-SELG4SUR.js → chunk-NPLLK3HO.js} +72 -89
  103. package/dist/{chunk-VCRVEDUC.js → chunk-NSYGPIVW.js} +5 -5
  104. package/dist/{context-7HJEWTTP.js → chunk-NXTV5OI5.js} +36 -90
  105. package/dist/{chunk-IMOD2YPV.js → chunk-NYDG4QP4.js} +9 -19
  106. package/dist/{chunk-6CA2BHOR.js → chunk-OA2GDACN.js} +5 -5
  107. package/dist/{chunk-A67NR5AT.js → chunk-PJI57EC6.js} +14 -11
  108. package/dist/{chunk-IJMW64DX.js → chunk-PJJBUGMR.js} +50 -50
  109. package/dist/{chunk-CPXGJI2A.js → chunk-PNJE7JPS.js} +20 -5
  110. package/dist/chunk-PP23PZEV.js +1347 -0
  111. package/dist/chunk-PPIFDSBK.js +409 -0
  112. package/dist/{chunk-T52TPHYC.js → chunk-PTFISXQO.js} +8 -7
  113. package/dist/{chunk-C6GEXX4L.js → chunk-QB33Z5S7.js} +5 -5
  114. package/dist/{chunk-VMATUZB6.js → chunk-QGNII5VC.js} +10 -10
  115. package/dist/{chunk-TLTGZTXI.js → chunk-QI72X67S.js} +104 -27
  116. package/dist/chunk-QKHZZFKH.js +98 -0
  117. package/dist/{chunk-PFLOULP3.js → chunk-RDKX2PME.js} +4 -4
  118. package/dist/{chunk-B5ZTR6KZ.js → chunk-RL7LJYN4.js} +1 -1
  119. package/dist/chunk-RPMNIFRY.js +65 -0
  120. package/dist/{chunk-L3Z5ANCV.js → chunk-RQROVOV3.js} +13 -11
  121. package/dist/{chunk-6YHPAAZR.js → chunk-S34A7BSP.js} +3 -3
  122. package/dist/{chunk-5ZSZEYJK.js → chunk-SJETVJHX.js} +2 -2
  123. package/dist/{chunk-77CZRFTE.js → chunk-SJMNU4ZS.js} +2 -2
  124. package/dist/chunk-SLLG2G44.js +85 -0
  125. package/dist/{chunk-GVZFCJHE.js → chunk-SQAZN2V3.js} +48 -22
  126. package/dist/{chunk-2O2LVQQK.js → chunk-SQBT46OF.js} +2 -2
  127. package/dist/{chunk-ZGIGW4ZG.js → chunk-TCUOGIL2.js} +5 -5
  128. package/dist/{chunk-DACXIVVF.js → chunk-TIWPKCVO.js} +5 -5
  129. package/dist/{chunk-5CMARGPF.js → chunk-UIU7MGZ3.js} +11 -2
  130. package/dist/chunk-USBBEKHW.js +177 -0
  131. package/dist/{chunk-WLHX3MM5.js → chunk-V4XJWDHR.js} +21 -11
  132. package/dist/{chunk-MBJO5VNZ.js → chunk-VPWGADBG.js} +33 -33
  133. package/dist/{chunk-UUQ5G6EZ.js → chunk-VWFCAK34.js} +6 -6
  134. package/dist/{chunk-6CB2IL4N.js → chunk-W5RM7YAH.js} +1 -1
  135. package/dist/{chunk-4MFBBY2Z.js → chunk-W72LLZAV.js} +3 -3
  136. package/dist/{chunk-4UHVS5T7.js → chunk-WGRDABW7.js} +8 -8
  137. package/dist/{chunk-XR3XJN2M.js → chunk-WWRV5RJI.js} +4 -4
  138. package/dist/{chunk-24TOGHPO.js → chunk-X6FLVUM5.js} +4 -4
  139. package/dist/{chunk-6YA46L5A.js → chunk-XFLSL7BT.js} +2 -2
  140. package/dist/{chunk-QKWL7SYE.js → chunk-XJZEDCNT.js} +50 -39
  141. package/dist/{chunk-UWD3JD5X.js → chunk-XLLEL3K7.js} +10 -10
  142. package/dist/{chunk-2GPGAE5W.js → chunk-XNIZBOFV.js} +15 -1
  143. package/dist/chunk-XNZWWDC3.js +686 -0
  144. package/dist/{chunk-WBVKKTUT.js → chunk-XRECG65F.js} +2 -2
  145. package/dist/chunk-XTQ7MEJG.js +457 -0
  146. package/dist/{chunk-GEVQNST4.js → chunk-XZWSP67B.js} +2 -2
  147. package/dist/{chunk-WB7POC6M.js → chunk-Y3M2T5RO.js} +6 -6
  148. package/dist/{chunk-RXFPB32E.js → chunk-YJCCMYYT.js} +2 -2
  149. package/dist/{chunk-EUZRMP4Y.js → chunk-YPQOPFP7.js} +20 -20
  150. package/dist/{chunk-USZA7GWL.js → chunk-YQ3GFEUY.js} +2 -2
  151. package/dist/{chunk-BAU36233.js → chunk-YQYINEJI.js} +9 -9
  152. package/dist/{chunk-CE64C5K5.js → chunk-ZF6CV4WZ.js} +1356 -235
  153. package/dist/{chunk-3XE4NRLF.js → chunk-ZKJU55MX.js} +4 -2
  154. package/dist/{chunk-IZYTT3CD.js → chunk-ZKQ63XZ5.js} +16 -39
  155. package/dist/{chunk-6TAATXXH.js → chunk-ZKVMDNAN.js} +7 -7
  156. package/dist/chunk-ZST3FRCV.js +132 -0
  157. package/dist/cli/index.js +50 -38
  158. package/dist/{clio-L2P7S2R2.js → clio-JUDCLNHC.js} +11 -11
  159. package/dist/clio-context-tools-FT672MNZ.js +136 -0
  160. package/dist/{code-nav-B5LNX4KU.js → code-nav-7OVCTP2Z.js} +39 -37
  161. package/dist/{components-63MMQKUT.js → components-OZXZMDWU.js} +11 -11
  162. package/dist/config-P3ZQVF63.js +275 -0
  163. package/dist/config-graph-GKAOBAS5.js +160 -0
  164. package/dist/{configure-LMVQJ46J.js → configure-25LRYZJG.js} +56 -55
  165. package/dist/context-72VQV7JX.js +73 -0
  166. package/dist/{context-YG2LZDYZ.js → context-COWRWXP3.js} +89 -83
  167. package/dist/{context-XSZKKFBW.js → context-WB3D474G.js} +16 -16
  168. package/dist/{context-clear-AC5NXHM2.js → context-clear-Y4LYMWC6.js} +88 -82
  169. package/dist/{context-index-KKTPRV5G.js → context-index-W6A4V7OC.js} +4 -4
  170. package/dist/{context-map-T7ROR5D5.js → context-map-DKL3QT6D.js} +3 -3
  171. package/dist/{context-working-set-F4Q4J3NS.js → context-working-set-TMZYVC7A.js} +27 -25
  172. package/dist/data-tool-KMBWKKWR.js +2987 -0
  173. package/dist/{detail-H73BEF2N.js → detail-4GLROGY5.js} +89 -83
  174. package/dist/{dispatch-runner-3RY5FSJC.js → dispatch-runner-TR3LBP5P.js} +113 -107
  175. package/dist/docs-ZK777W2G.js +101 -0
  176. package/dist/{doctor-EQYJOGUG.js → doctor-WC4OV2OB.js} +76 -73
  177. package/dist/{eval-4P7O6CCE.js → eval-FUNWJNUJ.js} +88 -73
  178. package/dist/{eval-inventory-QOYZERXJ.js → eval-inventory-CX24K2JT.js} +5 -60
  179. package/dist/evals-L73EBHSU.js +104 -0
  180. package/dist/{evidence-O76QF7TZ.js → evidence-AVJ2RTHX.js} +99 -93
  181. package/dist/{evidence-D6GUSYJW.js → evidence-P4NZOAK7.js} +88 -82
  182. package/dist/evidence-Y55WKYHH.js +246 -0
  183. package/dist/{evolve-H47BCETS.js → evolve-MAWKRYWF.js} +93 -87
  184. package/dist/{extensions-NNL3ZOCU.js → extensions-PYQH3H47.js} +14 -13
  185. package/dist/fleet-M4H2QBWT.js +268 -0
  186. package/dist/{fleet-KMNS6NOM.js → fleet-ULBXXRDR.js} +146 -138
  187. package/dist/{fleet-commands-DOWSYCBX.js → fleet-commands-7NNC4JZU.js} +18 -17
  188. package/dist/fleet-decisions-EHEY7KPU.js +52 -0
  189. package/dist/{fleet-graph-F2DE2TME.js → fleet-graph-LQ2AHZT3.js} +24 -24
  190. package/dist/{fleet-inspect-EN2Q6IVB.js → fleet-inspect-5IGBIIYZ.js} +98 -258
  191. package/dist/{fleet-preflight-FRLETDD3.js → fleet-preflight-UTTNOKMG.js} +9 -4
  192. package/dist/{fleet-validate-B2XDLS57.js → fleet-validate-YGILJKA6.js} +29 -29
  193. package/dist/{fleet-verify-4JKUWGJ7.js → fleet-verify-AUWTCDKR.js} +88 -82
  194. package/dist/{fleet-view-BHJFW26B.js → fleet-view-TGUFCY5A.js} +90 -84
  195. package/dist/{init-XAT5N5YM.js → init-GFN2Z7NF.js} +111 -104
  196. package/dist/install-6PIF6F6W.js +19 -0
  197. package/dist/{interop-FVECHFKG.js → interop-EF5JUWWK.js} +29 -29
  198. package/dist/{inventory-7KFQGLCV.js → inventory-I6VJDDYF.js} +90 -84
  199. package/dist/library-3J5IO2OJ.js +75 -0
  200. package/dist/{library-QAPAO23R.js → library-IJTOFTDS.js} +20 -19
  201. package/dist/{library-NY2XOT75.js → library-Z3KZSHPE.js} +35 -35
  202. package/dist/{library-import-5Y6MAS3R.js → library-import-IMKFLDHX.js} +29 -29
  203. package/dist/{library-inventory-JT6HWITQ.js → library-inventory-CQP5D6GU.js} +21 -21
  204. package/dist/{library-validation-EQUH25DC.js → library-validation-33UTX7AI.js} +19 -19
  205. package/dist/mcp-5FWZKUS6.js +26 -0
  206. package/dist/{memory-DYVTTCP6.js → memory-36CWN67Y.js} +93 -87
  207. package/dist/{models-MASFJ6Y2.js → models-KQ6PQJJQ.js} +57 -56
  208. package/dist/{monitor-YMP4NXJJ.js → monitor-XX6ZD6KC.js} +98 -91
  209. package/dist/{orchestrator-AFQRRTEI.js → orchestrator-SK6HDAOP.js} +1537 -832
  210. package/dist/{panes-NICTHQCV.js → panes-L27QRXUH.js} +14 -14
  211. package/dist/{panes-D3Y2KFG5.js → panes-LXZIWNOZ.js} +4 -4
  212. package/dist/{paths-PSFAUIGO.js → paths-7DJDU4P4.js} +6 -6
  213. package/dist/{preload-5Q7VXRFJ.js → preload-K2TDYI4Y.js} +88 -82
  214. package/dist/{reset-7NKZK7JN.js → reset-73VU3XNT.js} +13 -13
  215. package/dist/{resources-NILSIZAT.js → resources-3BYJYVYL.js} +24 -24
  216. package/dist/{run-BPZGEBZV.js → run-AR7PY6GW.js} +144 -136
  217. package/dist/run-script-H2KUDIII.js +41 -0
  218. package/dist/settings-3VMBMWID.js +72 -0
  219. package/dist/{share-EZ6ERBMH.js → share-HVWH4FPF.js} +30 -30
  220. package/dist/{skills-BTVVNYVM.js → skills-5TYEY75Q.js} +30 -30
  221. package/dist/{skills-eval-UY34MNK7.js → skills-eval-CK3MD63Z.js} +114 -103
  222. package/dist/{skills-inventory-JDHSIA7I.js → skills-inventory-KSFYG3I6.js} +24 -24
  223. package/dist/{slash-commands-K4FNQ2AT.js → slash-commands-DMVHML7P.js} +60 -57
  224. package/dist/{steer-2B3EQGFH.js → steer-XCD6V3EW.js} +4 -4
  225. package/dist/{support-L2SOL3IE.js → support-JAZL6VBR.js} +7 -7
  226. package/dist/system-3TDQRMZZ.js +116 -0
  227. package/dist/{targets-44VKGFLN.js → targets-EZKHAYRN.js} +74 -72
  228. package/dist/{tasks-3KODKFU7.js → tasks-SNEFHWYW.js} +18 -18
  229. package/dist/{terminal-lease-LXA7MMPO.js → terminal-lease-BNLFA4OF.js} +8 -7
  230. package/dist/{tools-3UB7TEVR.js → tools-7IM6BDCE.js} +12 -12
  231. package/dist/{trace-TAMIU4OJ.js → trace-C3MBGD4S.js} +16 -65
  232. package/dist/{tui-primitives-A6MUW32V.js → tui-primitives-36BY2774.js} +2 -2
  233. package/dist/{uninstall-QYVRPEM4.js → uninstall-WWLOSZ42.js} +35 -10
  234. package/dist/{upgrade-7PMKM2JH.js → upgrade-ETK2JNSJ.js} +42 -51
  235. package/dist/{usage-6EQV7EQK.js → usage-S2HOB7BZ.js} +112 -102
  236. package/dist/{verifiers-JLITWSHU.js → verifiers-QDTEVH7R.js} +26 -24
  237. package/dist/{verify-T7NAEVIG.js → verify-SUKUK6XM.js} +16 -15
  238. package/dist/web/client/THIRD_PARTY_LICENSES.md +1809 -0
  239. package/dist/web/client/assets/abnfDiagram-VCTEODGH-BznNOe_I.js +1 -0
  240. package/dist/web/client/assets/arc-Pry-7G1_.js +1 -0
  241. package/dist/web/client/assets/architecture-7GRP2DOG-BQO9DL_y.js +1 -0
  242. package/dist/web/client/assets/architectureDiagram-5GKGNRK7-CKPbdvyx.js +36 -0
  243. package/dist/web/client/assets/array-BifhSqXX.js +1 -0
  244. package/dist/web/client/assets/atkinson-hyperlegible-next-latin-ext-wght-normal-C6vrW8VD.woff2 +0 -0
  245. package/dist/web/client/assets/atkinson-hyperlegible-next-latin-wght-normal-BcXVPD7q.woff2 +0 -0
  246. package/dist/web/client/assets/blockDiagram-I7D4REHJ-prINbpbM.js +129 -0
  247. package/dist/web/client/assets/c4Diagram-7LVT6UL2-DkVRKtyU.js +38 -0
  248. package/dist/web/client/assets/channel-c4EeUUqA.js +1 -0
  249. package/dist/web/client/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  250. package/dist/web/client/assets/chunk-4HAMMTFA-CV0Z1ApC.js +62 -0
  251. package/dist/web/client/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  252. package/dist/web/client/assets/chunk-75Z2AOVW-D34Nohxq.js +2 -0
  253. package/dist/web/client/assets/chunk-DU6HZSFF-Das_cS-O.js +125 -0
  254. package/dist/web/client/assets/chunk-F27PBJKO-CmRojxkG.js +1 -0
  255. package/dist/web/client/assets/chunk-FOHPRMQF-CoA4358r.js +161 -0
  256. package/dist/web/client/assets/chunk-GMAD6QVW-ClYZmc73.js +72 -0
  257. package/dist/web/client/assets/chunk-GVQU2GXP-B2BiHFt-.js +1 -0
  258. package/dist/web/client/assets/chunk-IMKFNOWR-BGApZ8nP.js +231 -0
  259. package/dist/web/client/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  260. package/dist/web/client/assets/chunk-L3NEJ4N5-DIzCgpkY.js +1 -0
  261. package/dist/web/client/assets/chunk-OSK3NFVY-BPT-yePv.js +10 -0
  262. package/dist/web/client/assets/chunk-P2QGCYS3-BC1WTc2t.js +1 -0
  263. package/dist/web/client/assets/chunk-POPQ4Y6H-BSjzBmZU.js +1 -0
  264. package/dist/web/client/assets/chunk-PWAF6VOD-BIjLs86Z.js +1 -0
  265. package/dist/web/client/assets/chunk-SHT3W25Y-CduDz2cm.js +168 -0
  266. package/dist/web/client/assets/chunk-SVP7TREG-XUn4pPAP.js +88 -0
  267. package/dist/web/client/assets/chunk-TICWLB2K-DcBy2DKy.js +206 -0
  268. package/dist/web/client/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  269. package/dist/web/client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  270. package/dist/web/client/assets/classDiagram-ZZMXUADV-C0HR7YKN.js +1 -0
  271. package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-C0HR7YKN.js +1 -0
  272. package/dist/web/client/assets/commit-mono-latin-400-normal-s0S3qwFW.woff +0 -0
  273. package/dist/web/client/assets/commit-mono-latin-400-normal-wzhe4RuD.woff2 +0 -0
  274. package/dist/web/client/assets/cose-bilkent-JH36ORCC-CVh1icwb.js +1 -0
  275. package/dist/web/client/assets/cynefin-OW5HDTMX-BecPbyM6.js +1 -0
  276. package/dist/web/client/assets/cynefinDiagram-5FMLGOSQ-BzMzFwyT.js +62 -0
  277. package/dist/web/client/assets/cytoscape.esm-c2aL46s-.js +321 -0
  278. package/dist/web/client/assets/dagre-C-rnJpZF.js +1 -0
  279. package/dist/web/client/assets/dagre-GXQ25YYZ-CAWJmRMG.js +4 -0
  280. package/dist/web/client/assets/defaultLocale-BFoDCU3G.js +1 -0
  281. package/dist/web/client/assets/diagram-S7CK7UJ4--lp0ALmn.js +30 -0
  282. package/dist/web/client/assets/diagram-UQ7AKVKN-gKUnsjcj.js +41 -0
  283. package/dist/web/client/assets/diagram-VSXAHHWV-BoN5D1Gh.js +3 -0
  284. package/dist/web/client/assets/diagram-VX7I27RA-BMtuswQ6.js +24 -0
  285. package/dist/web/client/assets/diagram-Z3DM3KII-DtU8LXrA.js +24 -0
  286. package/dist/web/client/assets/dist-v5Q1xZ2K.js +1 -0
  287. package/dist/web/client/assets/ebnfDiagram-PWID7BFC-DDcnv9BH.js +1 -0
  288. package/dist/web/client/assets/erDiagram-RLTQ6QDP-DvRb4iDL.js +99 -0
  289. package/dist/web/client/assets/eventmodeling-NTZA5JFV-01h4SbTc.js +1 -0
  290. package/dist/web/client/assets/flowDiagram-HODETNUW-Bll_YZ6T.js +1 -0
  291. package/dist/web/client/assets/framework-YGoR34M4.js +9 -0
  292. package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-DdFZ9hvH.js +292 -0
  293. package/dist/web/client/assets/gitGraph-4MIJSDKK-DjD_AAMj.js +1 -0
  294. package/dist/web/client/assets/gitGraphDiagram-WWUBYQGX-CDyN9n2u.js +106 -0
  295. package/dist/web/client/assets/graphlib-DS17s2tU.js +1 -0
  296. package/dist/web/client/assets/index-CVcy0FAn.js +75 -0
  297. package/dist/web/client/assets/index-Dsi52apB.css +1 -0
  298. package/dist/web/client/assets/info-A6RAGUB7-C_XK8Hq0.js +1 -0
  299. package/dist/web/client/assets/infoDiagram-27XIBGKW-DIe4tJ1i.js +2 -0
  300. package/dist/web/client/assets/init-C-OQMol4.js +1 -0
  301. package/dist/web/client/assets/ishikawaDiagram-5VMMS53U-CVl5unKI.js +70 -0
  302. package/dist/web/client/assets/journeyDiagram-3NMN7TZE-CPEB1Vt8.js +139 -0
  303. package/dist/web/client/assets/kanban-definition-UXKFOSKX-j-9WXjYQ.js +89 -0
  304. package/dist/web/client/assets/katex-ZlcWpGUi.js +257 -0
  305. package/dist/web/client/assets/line-BIDAcEtX.js +1 -0
  306. package/dist/web/client/assets/linear-SzVmGSw4.js +1 -0
  307. package/dist/web/client/assets/mermaid-parser.core-Ux4vssh0.js +7 -0
  308. package/dist/web/client/assets/mermaid.core-CDuwVKeh.js +44 -0
  309. package/dist/web/client/assets/mindmap-definition-YA3MSWOX-5MlQEeQ6.js +96 -0
  310. package/dist/web/client/assets/newsreader-latin-ext-wght-normal-C-3rgBeH.woff2 +0 -0
  311. package/dist/web/client/assets/newsreader-latin-wght-normal-CCVVNp6i.woff2 +0 -0
  312. package/dist/web/client/assets/newsreader-vietnamese-wght-normal-Czsa-EzN.woff2 +0 -0
  313. package/dist/web/client/assets/ordinal-BDEzSJ7C.js +1 -0
  314. package/dist/web/client/assets/packet-AYTQ26CC-DRO66c9Q.js +1 -0
  315. package/dist/web/client/assets/path-fybaL0A-.js +1 -0
  316. package/dist/web/client/assets/pegDiagram-XKGWAZYB-BakZnSjM.js +1 -0
  317. package/dist/web/client/assets/pie-WAS4IAKB-BEzcmhz8.js +1 -0
  318. package/dist/web/client/assets/pieDiagram-E7YTZNPT-DpmqgoPt.js +39 -0
  319. package/dist/web/client/assets/prism-bash-D6zCJ74D.js +1 -0
  320. package/dist/web/client/assets/prism-c-04YixN25.js +1 -0
  321. package/dist/web/client/assets/prism-clike-DapgWyxx.js +1 -0
  322. package/dist/web/client/assets/prism-core-BtsZdCS6.js +1 -0
  323. package/dist/web/client/assets/prism-cpp-C-lJbC-6.js +1 -0
  324. package/dist/web/client/assets/prism-css-CPgOzxXp.js +1 -0
  325. package/dist/web/client/assets/prism-diff-BF8m0_mq.js +3 -0
  326. package/dist/web/client/assets/prism-docker-DkT6yOFj.js +1 -0
  327. package/dist/web/client/assets/prism-fortran-Be5x3y1V.js +1 -0
  328. package/dist/web/client/assets/prism-go-C_8qAH5n.js +1 -0
  329. package/dist/web/client/assets/prism-ini-BESK3y0r.js +1 -0
  330. package/dist/web/client/assets/prism-javascript-BnO-swvr.js +1 -0
  331. package/dist/web/client/assets/prism-json-Dp_-W-Hv.js +1 -0
  332. package/dist/web/client/assets/prism-jsx-D-D0NWtC.js +1 -0
  333. package/dist/web/client/assets/prism-julia-DIjOgiAV.js +1 -0
  334. package/dist/web/client/assets/prism-latex-DNMbqcH_.js +1 -0
  335. package/dist/web/client/assets/prism-makefile-CRKWLQ8l.js +1 -0
  336. package/dist/web/client/assets/prism-markdown-C0FPJ1Iz.js +1 -0
  337. package/dist/web/client/assets/prism-markup-Cp04rIa1.js +1 -0
  338. package/dist/web/client/assets/prism-matlab-D-nk08al.js +1 -0
  339. package/dist/web/client/assets/prism-python-CfiSVtM6.js +1 -0
  340. package/dist/web/client/assets/prism-r-QmNGR8LX.js +1 -0
  341. package/dist/web/client/assets/prism-rust-Bu9N8X3N.js +1 -0
  342. package/dist/web/client/assets/prism-shell-session-Be4UuYoM.js +1 -0
  343. package/dist/web/client/assets/prism-sql-CYhVDMEE.js +1 -0
  344. package/dist/web/client/assets/prism-toml-DKb54GAT.js +1 -0
  345. package/dist/web/client/assets/prism-tsx-p6J2Kc_4.js +1 -0
  346. package/dist/web/client/assets/prism-typescript-BMqONzxf.js +1 -0
  347. package/dist/web/client/assets/prism-yaml-C0JHu8gr.js +1 -0
  348. package/dist/web/client/assets/purify.es-ChwZkWde.js +3 -0
  349. package/dist/web/client/assets/quadrantDiagram-AXDQQJYC-DuMPwwV2.js +7 -0
  350. package/dist/web/client/assets/radar-RG4KPBEZ-Djm3oXl5.js +1 -0
  351. package/dist/web/client/assets/railroad-74A4TZTK-Cpvkwsao.js +1 -0
  352. package/dist/web/client/assets/railroad-abnf-HS5TGJTU-CpRQ3ruG.js +1 -0
  353. package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-1Rm5a5eJ.js +1 -0
  354. package/dist/web/client/assets/railroad-peg-WCYAUIDC-C8344cTh.js +1 -0
  355. package/dist/web/client/assets/railroadDiagram-O6MQD6OU-CgMS4B6R.js +1 -0
  356. package/dist/web/client/assets/requirementDiagram-BXWQKSXE-CX5eoNdN.js +84 -0
  357. package/dist/web/client/assets/rolldown-runtime-hePW80VL.js +1 -0
  358. package/dist/web/client/assets/rough.esm-Dy-Kn_BL.js +1 -0
  359. package/dist/web/client/assets/sankeyDiagram-P5KCCOFB-CODBX2N3.js +40 -0
  360. package/dist/web/client/assets/sequenceDiagram-WJ2MYXX4-eUhhF8OR.js +162 -0
  361. package/dist/web/client/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  362. package/dist/web/client/assets/src-B6xuSHsQ.js +1 -0
  363. package/dist/web/client/assets/stateDiagram-D77RDMKH-vR6l0NC2.js +1 -0
  364. package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-BYUm8jLY.js +1 -0
  365. package/dist/web/client/assets/swimlanes-42K2YHIH-v9Tw_zX7.js +1 -0
  366. package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-B2jdCvhD.js +8 -0
  367. package/dist/web/client/assets/timeline-definition-24CTP7MA-DxianbhU.js +120 -0
  368. package/dist/web/client/assets/treeView-Q6P3EWNA-DLxnZb9R.js +1 -0
  369. package/dist/web/client/assets/treemap-WGGIJYW6-I7UnZ6xJ.js +1 -0
  370. package/dist/web/client/assets/vennDiagram-4TSXK5OY-Ar7M8Mrj.js +34 -0
  371. package/dist/web/client/assets/wardley-WFR3VGLG-B8ZSHeDu.js +1 -0
  372. package/dist/web/client/assets/wardleyDiagram-VM6X3IG4-Qks2FmIn.js +78 -0
  373. package/dist/web/client/assets/xychartDiagram-S5SC5T6Z-BBBjRtiE.js +7 -0
  374. package/dist/web/client/clio-coder-logo.webp +0 -0
  375. package/dist/web/client/icon-192.png +0 -0
  376. package/dist/web/client/icon-512.png +0 -0
  377. package/dist/web/client/index.html +6 -0
  378. package/dist/web/client/manifest.webmanifest +15 -0
  379. package/dist/web/client/offline.css +55 -0
  380. package/dist/web/client/offline.html +5 -0
  381. package/dist/web/client/offline.js +27 -0
  382. package/dist/web/client/sw.js +34 -0
  383. package/dist/web/ops-worker.js +37 -0
  384. package/dist/web/reads-worker.js +1726 -0
  385. package/dist/web/server.js +8499 -0
  386. package/dist/web-EMGUGGEI.js +13 -0
  387. package/dist/{web-fetch-W4TNW4Q7.js → web-fetch-6BRRVQON.js} +22 -5
  388. package/dist/{wiki-generate-T2TJQJUA.js → wiki-generate-XHSJTDOP.js} +120 -113
  389. package/dist/{with-panes-CHFC7HGI.js → with-panes-Z6BTEHMZ.js} +12 -12
  390. package/dist/worker/entry.js +113 -99
  391. package/docs/README.md +28 -27
  392. package/docs/architecture/acp.md +5 -9
  393. package/docs/architecture/alcf-provider.md +0 -3
  394. package/docs/architecture/architecture.md +0 -3
  395. package/docs/architecture/artifact-placement.md +12 -4
  396. package/docs/architecture/artifact-versions.md +0 -3
  397. package/docs/architecture/capacity-and-scheduling.md +0 -3
  398. package/docs/architecture/context-engine.md +0 -3
  399. package/docs/architecture/context-working-set.md +0 -3
  400. package/docs/architecture/dispatch-architecture-rationale.md +0 -3
  401. package/docs/architecture/dispatch-typed-intent.md +0 -3
  402. package/docs/architecture/evidence-and-memory.md +0 -3
  403. package/docs/architecture/library.md +1 -3
  404. package/docs/architecture/middleware-and-components.md +0 -3
  405. package/docs/architecture/model-catalog.md +1 -4
  406. package/docs/architecture/observability.md +0 -3
  407. package/docs/architecture/pi-boundary.md +6 -9
  408. package/docs/architecture/prompt-envelope-and-tools.md +37 -30
  409. package/docs/architecture/provider-adapter-cookbook.md +1 -4
  410. package/docs/architecture/safety-model.md +19 -9
  411. package/docs/architecture/session-lifecycle.md +10 -7
  412. package/docs/architecture/time-conventions.md +0 -3
  413. package/docs/architecture/trace-store.md +28 -20
  414. package/docs/architecture/tui-design.md +38 -18
  415. package/docs/architecture/worker-context.md +1 -3
  416. package/docs/architecture/worker-dispatch-mechanics.md +1 -4
  417. package/docs/guide/authoring-plugins.md +1 -3
  418. package/docs/guide/built-in-agents.md +0 -3
  419. package/docs/guide/commands-and-modes.md +41 -25
  420. package/docs/guide/configuration-and-targets.md +204 -9
  421. package/docs/guide/configuration-reference.md +125 -17
  422. package/docs/guide/environment-variables.md +2 -8
  423. package/docs/guide/exit-codes-and-output.md +0 -3
  424. package/docs/guide/extensions-and-sharing.md +0 -3
  425. package/docs/guide/fleet-dispatch.md +3 -5
  426. package/docs/guide/glossary.md +1 -4
  427. package/docs/guide/harness-extensions.md +0 -2
  428. package/docs/guide/installation-and-lifecycle.md +3 -6
  429. package/docs/guide/interop.md +0 -2
  430. package/docs/guide/panes-and-files.md +0 -3
  431. package/docs/guide/plugins.md +0 -3
  432. package/docs/guide/proactive-memory.md +0 -3
  433. package/docs/guide/resource-library.md +1 -3
  434. package/docs/guide/skills-marketplace.md +0 -2
  435. package/docs/guide/tool-usage.md +166 -67
  436. package/docs/guide/troubleshooting.md +1 -4
  437. package/docs/history/config-knobs-audit.md +0 -3
  438. package/docs/history/release-cut-checklist.md +0 -3
  439. package/docs/process/development-pipeline.md +0 -3
  440. package/docs/process/documentation-coverage.md +3 -3
  441. package/docs/process/documentation-guide.md +16 -22
  442. package/docs/process/eval-runner.md +0 -3
  443. package/docs/process/evals-internal.md +0 -3
  444. package/docs/process/evolution.md +0 -3
  445. package/docs/process/fleet-demo-runbook.md +6 -9
  446. package/docs/process/git-commit-provenance.md +0 -3
  447. package/docs/process/performance-methodology.md +1 -4
  448. package/docs/process/release-cut-checklist.md +114 -221
  449. package/docs/process/scientific-validation.md +23 -6
  450. package/docs/process/tool-audit-v0.4.9.md +357 -0
  451. package/library/registry.yaml +2 -2
  452. package/library/skills/meta/clio-coder-test/SKILL.md +25 -15
  453. package/library/skills/meta/clio-coder-test/evals.md +16 -2
  454. package/library/skills/meta/clio-coder-test/plugin.json +1 -1
  455. package/library/skills/meta/clio-coder-test/references/test-map.md +19 -18
  456. package/library/skills/registry.yaml +2 -2
  457. package/library/skills/skill-marketplace.json +1 -1
  458. package/package.json +13 -11
  459. package/src/cli/argv.ts +31 -0
  460. package/src/cli/clio.ts +17 -13
  461. package/src/cli/config.ts +4 -0
  462. package/src/cli/docs.ts +65 -328
  463. package/src/cli/doctor-panes.ts +1 -1
  464. package/src/cli/doctor.ts +3 -1
  465. package/src/cli/index.ts +17 -2
  466. package/src/cli/mcp.ts +106 -0
  467. package/src/cli/skills-eval.ts +8 -2
  468. package/src/cli/trace.ts +4 -65
  469. package/src/cli/uninstall.ts +26 -0
  470. package/src/cli/upgrade.ts +34 -38
  471. package/src/cli/usage.ts +3 -0
  472. package/src/cli/verifiers.ts +1 -1
  473. package/src/cli/web.ts +79 -0
  474. package/src/core/bash-exec.ts +27 -4
  475. package/src/core/bus-events.ts +3 -4
  476. package/src/core/config.ts +73 -1
  477. package/src/core/defaults.ts +10 -1
  478. package/src/core/domain-loader.ts +37 -28
  479. package/src/core/event-bus.ts +1 -1
  480. package/src/core/run-records.ts +438 -0
  481. package/src/core/safe-exec.ts +506 -56
  482. package/src/core/skill-activation.ts +5 -3
  483. package/src/core/termination.ts +16 -12
  484. package/src/core/tool-names.ts +33 -12
  485. package/src/domains/agents/contract.ts +1 -1
  486. package/src/domains/agents/extension.ts +18 -10
  487. package/src/domains/config/extension.ts +5 -4
  488. package/src/domains/context/clio-md.ts +1 -1
  489. package/src/domains/context/worker/pressure.ts +6 -2
  490. package/src/domains/context/working-set/path-index.ts +7 -2
  491. package/src/domains/dispatch/code-step.ts +7 -2
  492. package/src/domains/dispatch/contract.ts +7 -0
  493. package/src/domains/dispatch/execution-role.ts +3 -3
  494. package/src/domains/dispatch/execution-scheduler.ts +204 -79
  495. package/src/domains/dispatch/extension.ts +206 -26
  496. package/src/domains/dispatch/fleet-preflight.ts +18 -3
  497. package/src/domains/dispatch/fleet-run.ts +1 -0
  498. package/src/domains/dispatch/gate-decisions.ts +3 -3
  499. package/src/domains/dispatch/heartbeat.ts +1 -1
  500. package/src/domains/dispatch/host-verification.ts +16 -14
  501. package/src/domains/dispatch/index.ts +1 -0
  502. package/src/domains/dispatch/orphan-recovery.ts +1 -0
  503. package/src/domains/dispatch/receipt-findings.ts +3 -4
  504. package/src/domains/dispatch/receipt-integrity.ts +3 -0
  505. package/src/domains/dispatch/reservation-store.ts +7 -9
  506. package/src/domains/dispatch/route-facts.ts +1 -1
  507. package/src/domains/dispatch/state.ts +4 -5
  508. package/src/domains/dispatch/types.ts +3 -1
  509. package/src/domains/eval/metrics/tracked.ts +22 -2
  510. package/src/domains/evidence/build.ts +35 -7
  511. package/src/domains/extensions/operator-runtime.ts +3 -1
  512. package/src/domains/gateway/mcp/client.ts +923 -0
  513. package/src/domains/gateway/mcp/config.ts +456 -0
  514. package/src/domains/gateway/mcp/index.ts +88 -0
  515. package/src/domains/gateway/mcp/protocol.ts +273 -0
  516. package/src/domains/gateway/mcp/trust.ts +263 -0
  517. package/src/domains/lifecycle/doctor.ts +17 -3
  518. package/src/domains/middleware/hooks.ts +2 -2
  519. package/src/domains/mux/contract.ts +5 -9
  520. package/src/domains/mux/detect.ts +1 -1
  521. package/src/domains/mux/extension.ts +1 -1
  522. package/src/domains/mux/protocol.ts +5 -7
  523. package/src/domains/mux/socket-client.ts +3 -3
  524. package/src/domains/observability/accountability.ts +2 -2
  525. package/src/domains/observability/background-memory-usage.ts +3 -0
  526. package/src/domains/observability/compaction-usage.ts +2 -0
  527. package/src/domains/observability/contract.ts +7 -3
  528. package/src/domains/observability/cost.ts +5 -0
  529. package/src/domains/observability/evidence-index.ts +2 -2
  530. package/src/domains/observability/extension.ts +1 -0
  531. package/src/domains/observability/out-of-turn-usage.ts +2 -0
  532. package/src/domains/observability/projection.ts +10 -0
  533. package/src/domains/observability/trace-store.ts +65 -5
  534. package/src/domains/prompts/compiler.ts +41 -23
  535. package/src/domains/prompts/extension.ts +4 -17
  536. package/src/domains/prompts/fragments/identity/docs-routing.md +2 -2
  537. package/src/domains/prompts/fragments/operating/skills.md +12 -10
  538. package/src/domains/providers/cache-deployment.ts +147 -0
  539. package/src/domains/providers/catalog.ts +12 -7
  540. package/src/domains/providers/extension.ts +27 -5
  541. package/src/domains/providers/index.ts +6 -1
  542. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +42 -10
  543. package/src/domains/providers/plugins.ts +3 -13
  544. package/src/domains/providers/probe/http.ts +44 -59
  545. package/src/domains/providers/probe/reasoning.ts +2 -0
  546. package/src/domains/providers/runtimes/common/local-synth.ts +4 -0
  547. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +20 -31
  548. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +9 -4
  549. package/src/domains/providers/types/target-descriptor.ts +17 -0
  550. package/src/domains/safety/action-classifier.ts +17 -1
  551. package/src/domains/safety/call-target.ts +14 -0
  552. package/src/domains/safety/contract.ts +1 -1
  553. package/src/domains/safety/finish-contract.ts +9 -3
  554. package/src/domains/safety/loop-detector.ts +1 -1
  555. package/src/domains/safety/policy-engine.ts +7 -0
  556. package/src/domains/safety/protected-artifacts.ts +3 -4
  557. package/src/domains/safety/rejection-feedback.ts +1 -1
  558. package/src/domains/safety/scope.ts +2 -3
  559. package/src/domains/safety/validation-contract.ts +3 -2
  560. package/src/domains/scheduling/budget.ts +5 -3
  561. package/src/domains/scheduling/contract.ts +2 -1
  562. package/src/domains/scheduling/extension.ts +3 -3
  563. package/src/domains/session/compaction/branch-summary.ts +1 -1
  564. package/src/domains/session/compaction/compact.ts +29 -3
  565. package/src/domains/session/compaction/cut-point.ts +1 -1
  566. package/src/domains/session/compaction/tokens.ts +5 -10
  567. package/src/domains/session/contract.ts +1 -1
  568. package/src/domains/session/cwd-fallback.ts +2 -2
  569. package/src/domains/session/entries.ts +1 -0
  570. package/src/domains/session/handoff.ts +5 -1
  571. package/src/domains/session/history.ts +6 -0
  572. package/src/domains/session/manager.ts +14 -7
  573. package/src/domains/session/retry.ts +2 -1
  574. package/src/domains/session/session-artifacts.ts +12 -7
  575. package/src/domains/session/task-board.ts +2 -3
  576. package/src/domains/session/usage.ts +6 -7
  577. package/src/engine/acp/server.ts +11 -0
  578. package/src/engine/ai.ts +2 -0
  579. package/src/engine/apis/openai-completions.ts +17 -4
  580. package/src/engine/loop-guard.ts +7 -0
  581. package/src/engine/prewarm.ts +232 -0
  582. package/src/engine/provider-diagnostics.ts +6 -1
  583. package/src/engine/provider-error-body.ts +65 -0
  584. package/src/engine/session.ts +118 -29
  585. package/src/engine/worker-runtime.ts +3 -0
  586. package/src/entry/boot-options.ts +2 -0
  587. package/src/entry/orchestrator.ts +38 -18
  588. package/src/interactive/chat-loop-messages.ts +3 -0
  589. package/src/interactive/chat-loop-policy.ts +1 -0
  590. package/src/interactive/chat-loop.ts +10 -12
  591. package/src/interactive/chat-panel.ts +23 -9
  592. package/src/interactive/chat-renderer.ts +33 -11
  593. package/src/interactive/clio-editor.ts +13 -5
  594. package/src/interactive/dispatch-board.ts +70 -30
  595. package/src/interactive/editor-submit.ts +30 -25
  596. package/src/interactive/footer/widgets.ts +12 -9
  597. package/src/interactive/interactive-presentation.ts +2 -3
  598. package/src/interactive/mux-bridge.ts +3 -7
  599. package/src/interactive/overlay-general-openers.ts +14 -7
  600. package/src/interactive/overlays/cwd-fallback.ts +1 -1
  601. package/src/interactive/overlays/library-model.ts +114 -35
  602. package/src/interactive/overlays/library.ts +52 -5
  603. package/src/interactive/overlays/list-overlay.ts +4 -1
  604. package/src/interactive/overlays/session-selector.ts +28 -23
  605. package/src/interactive/overlays/settings.ts +20 -1
  606. package/src/interactive/overlays/tree-selector.ts +47 -10
  607. package/src/interactive/panes-runtime.ts +1 -1
  608. package/src/interactive/prewarm.ts +11 -197
  609. package/src/interactive/renderers/compaction-summary.ts +1 -1
  610. package/src/interactive/renderers/provider-error.ts +118 -0
  611. package/src/interactive/renderers/retry-status.ts +59 -23
  612. package/src/interactive/renderers/tool-execution.ts +67 -7
  613. package/src/interactive/renderers/worker-answer.ts +198 -0
  614. package/src/interactive/renderers/worker-entry.ts +57 -163
  615. package/src/interactive/session-usage-reseed.ts +2 -0
  616. package/src/interactive/side-question.ts +2 -0
  617. package/src/interactive/slash-commands.ts +26 -1
  618. package/src/interactive/slash-spec.ts +2 -2
  619. package/src/interactive/theme/labels.ts +66 -30
  620. package/src/interactive/turn-context.ts +1 -0
  621. package/src/interactive/turn-persistence.ts +9 -1
  622. package/src/interactive/turn-prewarm.ts +126 -19
  623. package/src/interactive/turn-recovery.ts +2 -1
  624. package/src/interactive/turn-runtime.ts +36 -5
  625. package/src/interactive/view/artifacts.ts +3 -2
  626. package/src/interactive/view/view-overlay.ts +96 -20
  627. package/src/tools/agent-tools.ts +21 -7
  628. package/src/tools/artifact.ts +16 -8
  629. package/src/tools/bash.ts +90 -11
  630. package/src/tools/bootstrap.ts +42 -4
  631. package/src/tools/builtin-tool-catalog.ts +80 -11
  632. package/src/tools/context/index.ts +27 -31
  633. package/src/tools/context/library.ts +3 -1
  634. package/src/tools/context/surface.ts +12 -26
  635. package/src/tools/core-bootstrap.ts +72 -1
  636. package/src/tools/data/csv.ts +1189 -0
  637. package/src/tools/data/index.ts +308 -0
  638. package/src/tools/data/json.ts +1799 -0
  639. package/src/tools/data/jsonl.ts +561 -0
  640. package/src/tools/data/shared.ts +452 -0
  641. package/src/tools/edit-diff.ts +0 -7
  642. package/src/tools/edit.ts +115 -18
  643. package/src/tools/file-mutation-queue.ts +114 -4
  644. package/src/tools/find.ts +108 -29
  645. package/src/tools/gateway/caps.ts +11 -0
  646. package/src/tools/gateway/clio-context-surface.ts +41 -0
  647. package/src/tools/gateway/clio-context-tools.ts +77 -0
  648. package/src/tools/gateway/data-surface.ts +138 -0
  649. package/src/tools/gateway/data-tool.ts +201 -0
  650. package/src/tools/gateway/index.ts +342 -0
  651. package/src/tools/gateway/mcp-capabilities.ts +469 -0
  652. package/src/tools/grep.ts +88 -33
  653. package/src/tools/harness-extensions.ts +3 -0
  654. package/src/tools/ignore-policy.ts +7 -5
  655. package/src/tools/ls.ts +111 -20
  656. package/src/tools/policy.ts +35 -13
  657. package/src/tools/presentation.ts +6 -0
  658. package/src/tools/read.ts +634 -156
  659. package/src/tools/registry.ts +106 -8
  660. package/src/tools/run-script.ts +997 -0
  661. package/src/tools/spawn-hygiene.ts +157 -5
  662. package/src/tools/surface.ts +163 -0
  663. package/src/tools/verify/authoring.ts +8 -3
  664. package/src/tools/verify/catalog.ts +14 -1
  665. package/src/tools/verify/numeric.ts +367 -59
  666. package/src/tools/verify/perf.ts +171 -9
  667. package/src/tools/verify/scripts.ts +178 -26
  668. package/src/tools/web-fetch-surface.ts +22 -0
  669. package/src/tools/web-fetch.ts +26 -1
  670. package/src/tools/write.ts +45 -19
  671. package/src/worker/spec-contract.ts +27 -0
  672. package/dist/chunk-B6UM3OZC.js +0 -15
  673. package/dist/chunk-GJ24ODAX.js +0 -196
  674. package/dist/chunk-HRAKUPIH.js +0 -57
  675. package/dist/docs-BL7ROUFN.js +0 -292
@@ -0,0 +1,923 @@
1
+ /**
2
+ * One local MCP server over stdio: spawn, initialize, list and call tools,
3
+ * close. The client owns exactly one child process and never restarts it; a
4
+ * server that dies stays dead until the gateway decides to create a new
5
+ * client. Every request carries its own timeout, every failure is a typed
6
+ * McpError, and nothing the server prints reaches this process's stdout or
7
+ * stderr. Launching a server here is not sandboxing it: the child gets the
8
+ * allowlisted tool environment and a workspace-contained cwd, nothing more.
9
+ *
10
+ * Both directions are bounded. The framer caps inbound lines; an outbound
11
+ * cap bounds the bytes waiting on a server that stopped reading its stdin,
12
+ * and crossing it is a fatal `overload` that closes the client. Teardown
13
+ * covers the server's whole process group, not only the child it spawned,
14
+ * escalates to SIGKILL for any member that outlives the grace period, and
15
+ * begins the moment the leader is seen to exit, whether or not close() has
16
+ * been called.
17
+ */
18
+
19
+ import { type ChildProcess, spawn } from "node:child_process";
20
+ import { realpathSync, statSync } from "node:fs";
21
+ import path from "node:path";
22
+ import { performance } from "node:perf_hooks";
23
+ import { buildSafeToolEnv, resolveSafeCwd } from "../../../core/safe-exec.js";
24
+ import { clampTimerDelayMs, sleep } from "../../../core/timers.js";
25
+ import {
26
+ createLineFramer,
27
+ DEFAULT_MAX_LINE_BYTES,
28
+ encodeJsonRpcMessage,
29
+ JSON_RPC_METHOD_NOT_FOUND,
30
+ type JsonRpcId,
31
+ type JsonRpcMessage,
32
+ MCP_PROTOCOL_VERSION,
33
+ McpError,
34
+ structuredContentJson,
35
+ } from "./protocol.js";
36
+
37
+ export const MCP_CLIENT_NAME = "clio-coder";
38
+ export const DEFAULT_MCP_CLIENT_VERSION = "0.4.9";
39
+ export const DEFAULT_INITIALIZE_TIMEOUT_MS = 15_000;
40
+ export const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
41
+ export const DEFAULT_STDERR_TAIL_BYTES = 16 * 1024;
42
+ export const DEFAULT_RESULT_TEXT_BYTES = 1024 * 1024;
43
+ export const DEFAULT_KILL_GRACE_MS = 3_000;
44
+ /** Bytes accepted for the server's stdin but not yet flushed before the client fails with `overload`. */
45
+ export const DEFAULT_MAX_OUTBOUND_BYTES = 4 * 1024 * 1024;
46
+ /** Tools accepted from one server before pagination stops. */
47
+ export const MCP_TOOL_LIST_CAP = 500;
48
+ /** Pages followed before a cursor that never ends is abandoned. */
49
+ const MCP_TOOL_LIST_PAGE_CAP = 100;
50
+ /** Smallest outbound cap a caller may configure; initialize alone needs a few hundred bytes. */
51
+ const MIN_OUTBOUND_BYTES = 4096;
52
+ /** How long a teardown waits for a SIGKILLed group to disappear before it gives up and says so. */
53
+ export const DEFAULT_TEARDOWN_BOUND_MS = 2_000;
54
+
55
+ export interface McpServerSpec {
56
+ id: string;
57
+ command: string;
58
+ args?: ReadonlyArray<string>;
59
+ cwd?: string;
60
+ env?: Readonly<Record<string, string>>;
61
+ }
62
+
63
+ export interface McpClientOptions {
64
+ /** Containment root for the server's cwd; a cwd outside it, by path or by symlink, is refused before spawn. */
65
+ workspaceRoot: string;
66
+ clientVersion?: string;
67
+ initializeTimeoutMs?: number;
68
+ requestTimeoutMs?: number;
69
+ stderrTailBytes?: number;
70
+ maxLineBytes?: number;
71
+ /** Cap on the plain-text rendering of one tool result. */
72
+ maxResultTextBytes?: number;
73
+ /** Cap on bytes queued for a server that is not reading its stdin; crossing it fails the client. */
74
+ maxOutboundBytes?: number;
75
+ /** Delay between SIGTERM and SIGKILL on close. */
76
+ killGraceMs?: number;
77
+ /** Wait for the group to disappear after SIGKILL before the teardown is reported incomplete. */
78
+ teardownBoundMs?: number;
79
+ /** Aborting this signal closes the client. */
80
+ signal?: AbortSignal;
81
+ }
82
+
83
+ export type McpClientStatus = "idle" | "starting" | "ready" | "closed" | "failed";
84
+
85
+ /**
86
+ * How the process-group teardown ended. `complete: false` means members of
87
+ * the group were still present when the post-SIGKILL bound passed; the id was
88
+ * released all the same (see GroupPhase), so `pgid` is for the operator's
89
+ * report, never for another signal.
90
+ */
91
+ export type McpTeardownOutcome =
92
+ | { complete: true }
93
+ | { complete: false; reason: "group-survived-sigkill"; pgid: number; boundMs: number };
94
+
95
+ export type McpClientState = ({ status: Exclude<McpClientStatus, "failed"> } | { status: "failed"; reason: string }) & {
96
+ /** Group members were still present when the post-SIGKILL bound passed; the client stopped waiting for them. */
97
+ cleanupIncomplete: boolean;
98
+ /** The teardown's outcome, null until one has run. Kept alongside an earlier fatal error, never in place of it. */
99
+ teardown: McpTeardownOutcome | null;
100
+ };
101
+
102
+ export interface McpServerInfo {
103
+ protocolVersion: string;
104
+ serverInfo: { name: string; version: string } | null;
105
+ capabilities: Record<string, unknown>;
106
+ instructions: string | null;
107
+ }
108
+
109
+ export interface McpToolDescriptor {
110
+ name: string;
111
+ title: string | null;
112
+ description: string;
113
+ inputSchema: Record<string, unknown>;
114
+ /** Server-declared hints; advisory only, never a safety input. */
115
+ annotations: Record<string, unknown> | null;
116
+ }
117
+
118
+ export interface McpToolListing {
119
+ tools: McpToolDescriptor[];
120
+ /** True when the server offered more tools than the cap admits. */
121
+ truncated: boolean;
122
+ }
123
+
124
+ export type McpContentBlock =
125
+ | { type: "text"; text: string }
126
+ | { type: "image"; mimeType: string; data: string }
127
+ | { type: "audio"; mimeType: string; data: string }
128
+ | { type: "resource"; uri: string; text?: string; mimeType?: string }
129
+ | { type: "other"; raw: unknown };
130
+
131
+ export interface McpToolCallResult {
132
+ content: McpContentBlock[];
133
+ isError: boolean;
134
+ /** JSON-safe values; numeric tokens that do not round-trip use {$literal: source}. */
135
+ structuredContent?: unknown;
136
+ /** Normalized structured JSON retaining numeric source tokens, bounded by the incoming-line cap. */
137
+ structuredContentJson?: string;
138
+ /** Bounded plain rendering of the content blocks. */
139
+ text: string;
140
+ textTruncated: boolean;
141
+ }
142
+
143
+ export interface McpCallToolOptions {
144
+ signal?: AbortSignal;
145
+ timeoutMs?: number;
146
+ }
147
+
148
+ export interface McpClient {
149
+ readonly id: string;
150
+ readonly pid: number | undefined;
151
+ initialize(): Promise<McpServerInfo>;
152
+ listTools(): Promise<McpToolListing>;
153
+ callTool(name: string, args: Record<string, unknown>, options?: McpCallToolOptions): Promise<McpToolCallResult>;
154
+ /** Resolves with the teardown outcome; an incomplete teardown is flagged there and in state(), not thrown. */
155
+ close(): Promise<McpTeardownOutcome>;
156
+ /** Synchronous exit backstop. Signals only a currently owned group; use close() for awaited teardown. */
157
+ killOwnedOnExit(): void;
158
+ state(): McpClientState;
159
+ serverInfo(): McpServerInfo | null;
160
+ /** Set by `notifications/tools/list_changed`; cleared by acknowledgeToolsChanged. */
161
+ toolsChanged(): boolean;
162
+ acknowledgeToolsChanged(): void;
163
+ notificationCount(): number;
164
+ /** Bounded tail of everything the server wrote to stderr. */
165
+ stderrTail(): string;
166
+ }
167
+
168
+ interface PendingRequest {
169
+ method: string;
170
+ resolve(value: unknown): void;
171
+ reject(error: McpError): void;
172
+ }
173
+
174
+ type OutboundMessage = Parameters<typeof encodeJsonRpcMessage>[0];
175
+
176
+ interface OutboundEntry {
177
+ payload: Buffer;
178
+ /** The request this line carries, so a request that settles unsent can be withdrawn. */
179
+ requestId: number | null;
180
+ onError: ((error: Error) => void) | undefined;
181
+ }
182
+
183
+ type EnqueueOutcome = { kind: "queued" } | { kind: "oversized"; bytes: number } | { kind: "overloaded" };
184
+
185
+ /**
186
+ * Lifecycle of the server's process group as this client tracks it. The
187
+ * leader's pid doubles as the group id because the child is spawned detached.
188
+ * The kernel keeps a group id reserved only while some member of that group
189
+ * exists; once the last member is reaped, the number can be handed to an
190
+ * unrelated process, and a signal-0 probe would then report a stranger as
191
+ * alive. Two rules keep this client from ever signalling a stranger:
192
+ *
193
+ * 1. Cleanup starts the moment the leader is seen to exit, not when close()
194
+ * happens to be called. At that instant the group is still ours or is
195
+ * already empty, so an arbitrarily late close() never gets to signal a
196
+ * number that has had time to change hands.
197
+ * 2. Once the group has been observed gone (ESRCH), or cleanup has run to
198
+ * its bound, the id is `released` and is never probed or signalled
199
+ * again, whatever a later probe would say. A group that survives SIGKILL
200
+ * for the confirm window is unreaped zombies or something we cannot end
201
+ * either way; keeping the number is worth nothing and risks a stranger.
202
+ *
203
+ * The residual exposure is a reuse of the number between two 10 ms polls of
204
+ * one active cleanup, the same window every group-signalling spawner in this
205
+ * codebase accepts. Direct-child signals go through Node's own handle, which
206
+ * knows whether that pid has been reaped, so they carry no such risk.
207
+ */
208
+ type GroupPhase = "unspawned" | "live" | "cleaning" | "released";
209
+
210
+ function isRecord(value: unknown): value is Record<string, unknown> {
211
+ return value !== null && typeof value === "object" && !Array.isArray(value);
212
+ }
213
+
214
+ function errorMessage(error: unknown): string {
215
+ return error instanceof Error ? error.message : String(error);
216
+ }
217
+
218
+ /** Cut a string at a UTF-8 byte boundary at or below `maxBytes`. */
219
+ function cutUtf8(text: string, maxBytes: number): string {
220
+ if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
221
+ const bytes = Buffer.from(text, "utf8");
222
+ let cut = Math.max(0, maxBytes);
223
+ while (cut > 0) {
224
+ const byte = bytes[cut];
225
+ if (byte === undefined || (byte & 0xc0) !== 0x80) break;
226
+ cut -= 1;
227
+ }
228
+ return bytes.subarray(0, cut).toString("utf8");
229
+ }
230
+
231
+ /**
232
+ * The canonical directory the server starts in, or why there is none. The cwd
233
+ * must stay inside the workspace root lexically and after every symbolic link
234
+ * is followed, and it must exist as a directory. Checked once at creation for
235
+ * early feedback and again at spawn, which is the boundary that matters.
236
+ */
237
+ function containedCwd(spec: McpServerSpec, workspaceRoot: string): string | Error {
238
+ let lexical: string;
239
+ try {
240
+ lexical = resolveSafeCwd(spec.cwd, workspaceRoot);
241
+ } catch (error) {
242
+ return error instanceof Error ? error : new Error(String(error));
243
+ }
244
+ let realRoot: string;
245
+ let real: string;
246
+ try {
247
+ realRoot = realpathSync(path.resolve(workspaceRoot));
248
+ real = realpathSync(lexical);
249
+ if (!statSync(real).isDirectory()) return new Error(`cwd is not a directory: ${lexical}`);
250
+ } catch (error) {
251
+ return new Error(`cwd cannot be resolved: ${lexical} (${errorMessage(error)})`);
252
+ }
253
+ try {
254
+ resolveSafeCwd(real, realRoot);
255
+ } catch {
256
+ return new Error(`cwd escapes workspace root through a symbolic link: ${lexical} -> ${real}`);
257
+ }
258
+ return real;
259
+ }
260
+
261
+ function parseServerInfo(value: unknown): McpServerInfo | McpError {
262
+ if (!isRecord(value)) return new McpError("protocol", "initialize result is not an object");
263
+ if (typeof value.protocolVersion !== "string" || value.protocolVersion.length === 0) {
264
+ return new McpError("protocol", "initialize result lacks a protocolVersion string");
265
+ }
266
+ const capabilities = isRecord(value.capabilities) ? value.capabilities : {};
267
+ let serverInfo: McpServerInfo["serverInfo"] = null;
268
+ if (isRecord(value.serverInfo)) {
269
+ serverInfo = {
270
+ name: typeof value.serverInfo.name === "string" ? value.serverInfo.name : "",
271
+ version: typeof value.serverInfo.version === "string" ? value.serverInfo.version : "",
272
+ };
273
+ }
274
+ return {
275
+ protocolVersion: value.protocolVersion,
276
+ serverInfo,
277
+ capabilities,
278
+ instructions: typeof value.instructions === "string" ? value.instructions : null,
279
+ };
280
+ }
281
+
282
+ function parseToolDescriptor(value: unknown): McpToolDescriptor | McpError {
283
+ if (!isRecord(value)) return new McpError("protocol", "tools/list entry is not an object");
284
+ if (typeof value.name !== "string" || value.name.length === 0) {
285
+ return new McpError("protocol", "tools/list entry lacks a name");
286
+ }
287
+ const inputSchema = isRecord(value.inputSchema) ? value.inputSchema : { type: "object" };
288
+ return {
289
+ name: value.name,
290
+ title: typeof value.title === "string" ? value.title : null,
291
+ description: typeof value.description === "string" ? value.description : "",
292
+ inputSchema,
293
+ annotations: isRecord(value.annotations) ? value.annotations : null,
294
+ };
295
+ }
296
+
297
+ function normalizeContentBlock(value: unknown): McpContentBlock {
298
+ if (!isRecord(value) || typeof value.type !== "string") return { type: "other", raw: value };
299
+ switch (value.type) {
300
+ case "text":
301
+ return typeof value.text === "string" ? { type: "text", text: value.text } : { type: "other", raw: value };
302
+ case "image":
303
+ case "audio":
304
+ if (typeof value.data === "string" && typeof value.mimeType === "string") {
305
+ return { type: value.type, mimeType: value.mimeType, data: value.data };
306
+ }
307
+ return { type: "other", raw: value };
308
+ case "resource": {
309
+ const resource = value.resource;
310
+ if (!isRecord(resource) || typeof resource.uri !== "string") return { type: "other", raw: value };
311
+ return {
312
+ type: "resource",
313
+ uri: resource.uri,
314
+ ...(typeof resource.text === "string" ? { text: resource.text } : {}),
315
+ ...(typeof resource.mimeType === "string" ? { mimeType: resource.mimeType } : {}),
316
+ };
317
+ }
318
+ case "resource_link":
319
+ if (typeof value.uri !== "string") return { type: "other", raw: value };
320
+ return {
321
+ type: "resource",
322
+ uri: value.uri,
323
+ ...(typeof value.mimeType === "string" ? { mimeType: value.mimeType } : {}),
324
+ };
325
+ default:
326
+ return { type: "other", raw: value };
327
+ }
328
+ }
329
+
330
+ function renderContentBlock(block: McpContentBlock): string {
331
+ switch (block.type) {
332
+ case "text":
333
+ return block.text;
334
+ case "image":
335
+ case "audio":
336
+ return `[${block.type} ${block.mimeType}, ${Buffer.byteLength(block.data, "base64")} bytes]`;
337
+ case "resource":
338
+ return block.text === undefined ? `[resource ${block.uri}]` : `[resource ${block.uri}]\n${block.text}`;
339
+ case "other": {
340
+ const type = isRecord(block.raw) && typeof block.raw.type === "string" ? block.raw.type : "unknown";
341
+ return `[unsupported content type ${type}]`;
342
+ }
343
+ }
344
+ }
345
+
346
+ /** Render every block as plain text and bound the whole rendering. */
347
+ export function renderMcpContent(
348
+ blocks: ReadonlyArray<McpContentBlock>,
349
+ maxBytes: number = DEFAULT_RESULT_TEXT_BYTES,
350
+ ): { text: string; truncated: boolean } {
351
+ const joined = blocks.map(renderContentBlock).join("\n");
352
+ if (Buffer.byteLength(joined, "utf8") <= maxBytes) return { text: joined, truncated: false };
353
+ const marker = `\n[mcp result text truncated at ${maxBytes} bytes]`;
354
+ const budget = Math.max(0, maxBytes - Buffer.byteLength(marker, "utf8"));
355
+ return { text: `${cutUtf8(joined, budget)}${marker}`, truncated: true };
356
+ }
357
+
358
+ function parseToolCallResult(value: unknown, maxTextBytes: number): McpToolCallResult | McpError {
359
+ if (!isRecord(value)) return new McpError("protocol", "tools/call result is not an object");
360
+ if (!Array.isArray(value.content)) return new McpError("protocol", "tools/call result.content must be an array");
361
+ if (value.isError !== undefined && typeof value.isError !== "boolean") {
362
+ return new McpError("protocol", "tools/call result.isError must be a boolean");
363
+ }
364
+ if (value.structuredContent !== undefined && !isRecord(value.structuredContent)) {
365
+ return new McpError("protocol", "tools/call result.structuredContent must be an object");
366
+ }
367
+ const content = value.content.map(normalizeContentBlock);
368
+ const structuredText = structuredContentJson(value);
369
+ // Use transport-retained numeric tokens, not reserialized JS numbers.
370
+ // The evidence object uses explicit $literal tags for non-round-trips.
371
+ const rendered = renderMcpContent(
372
+ content.length === 0 && value.structuredContent !== undefined
373
+ ? [{ type: "text", text: structuredText ?? JSON.stringify(value.structuredContent) }]
374
+ : content,
375
+ maxTextBytes,
376
+ );
377
+ const result: McpToolCallResult = {
378
+ content,
379
+ isError: value.isError === true,
380
+ text: rendered.text,
381
+ textTruncated: rendered.truncated,
382
+ };
383
+ if (value.structuredContent !== undefined) result.structuredContent = value.structuredContent;
384
+ if (structuredText !== undefined) result.structuredContentJson = structuredText;
385
+ return result;
386
+ }
387
+
388
+ export function createMcpStdioClient(spec: McpServerSpec, options: McpClientOptions): McpClient {
389
+ const initialCwd = containedCwd(spec, options.workspaceRoot);
390
+ if (initialCwd instanceof Error) throw new McpError("spawn", `mcp server ${spec.id}: ${initialCwd.message}`);
391
+ const initializeTimeoutMs = clampTimerDelayMs(options.initializeTimeoutMs ?? DEFAULT_INITIALIZE_TIMEOUT_MS);
392
+ const requestTimeoutMs = clampTimerDelayMs(options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
393
+ const stderrTailBytes = Math.max(0, options.stderrTailBytes ?? DEFAULT_STDERR_TAIL_BYTES);
394
+ const maxResultTextBytes = Math.max(64, options.maxResultTextBytes ?? DEFAULT_RESULT_TEXT_BYTES);
395
+ const maxOutboundBytes = Math.max(MIN_OUTBOUND_BYTES, options.maxOutboundBytes ?? DEFAULT_MAX_OUTBOUND_BYTES);
396
+ const killGraceMs = clampTimerDelayMs(options.killGraceMs ?? DEFAULT_KILL_GRACE_MS);
397
+ const teardownBoundMs = clampTimerDelayMs(options.teardownBoundMs ?? DEFAULT_TEARDOWN_BOUND_MS);
398
+ const clientVersion = options.clientVersion ?? DEFAULT_MCP_CLIENT_VERSION;
399
+ const framer = createLineFramer(options.maxLineBytes ?? DEFAULT_MAX_LINE_BYTES);
400
+
401
+ let status: McpClientStatus = "idle";
402
+ let failure: McpError | null = null;
403
+ let child: ChildProcess | null = null;
404
+ let spawned: Promise<boolean> | null = null;
405
+ let exited: Promise<void> | null = null;
406
+ let leaderExited = false;
407
+ let groupPhase: GroupPhase = "unspawned";
408
+ let groupCleanup: Promise<McpTeardownOutcome> | null = null;
409
+ let teardown: McpTeardownOutcome | null = null;
410
+ let closing = false;
411
+ let initializePromise: Promise<McpServerInfo> | null = null;
412
+ let closePromise: Promise<McpTeardownOutcome> | null = null;
413
+ let info: McpServerInfo | null = null;
414
+ let nextId = 1;
415
+ const pending = new Map<number, PendingRequest>();
416
+ const outbound: OutboundEntry[] = [];
417
+ let outboundQueuedBytes = 0;
418
+ let awaitingDrain = false;
419
+ let notifications = 0;
420
+ let toolsChangedFlag = false;
421
+ let stderrTailBuffer = Buffer.alloc(0);
422
+
423
+ const isAlive = (): boolean => child !== null && child.exitCode === null && child.signalCode === null;
424
+
425
+ /** The error every later request gets once the client cannot serve it. */
426
+ const closedError = (): McpError => failure ?? new McpError("closed", `mcp server ${spec.id} is closed`);
427
+
428
+ const rejectAllPending = (error: McpError): void => {
429
+ for (const entry of [...pending.values()]) entry.reject(error);
430
+ };
431
+
432
+ /** Record the first fatal error; later ones never overwrite the cause a caller sees. */
433
+ const fail = (error: McpError): void => {
434
+ if (status === "closed" || status === "failed") return;
435
+ status = "failed";
436
+ failure = error;
437
+ rejectAllPending(error);
438
+ };
439
+
440
+ /** The group id may be signalled only while the group is known to be ours (see GroupPhase). */
441
+ const groupOwned = (): boolean => groupPhase === "live" || groupPhase === "cleaning";
442
+
443
+ const signalGroup = (signalName: NodeJS.Signals): void => {
444
+ const pid = child?.pid;
445
+ if (pid !== undefined && process.platform !== "win32" && groupOwned()) {
446
+ try {
447
+ process.kill(-pid, signalName);
448
+ return;
449
+ } catch (error) {
450
+ // ESRCH: the group is gone, and the number is no longer ours to touch.
451
+ if ((error as NodeJS.ErrnoException).code === "ESRCH") groupPhase = "released";
452
+ }
453
+ }
454
+ // Node's handle knows whether this pid was reaped, so the direct child is always safe to address.
455
+ try {
456
+ child?.kill(signalName);
457
+ } catch {
458
+ // Already exited.
459
+ }
460
+ };
461
+
462
+ /** True while any member of the server's process group exists, whether or not the leader does. */
463
+ const groupAlive = (): boolean => {
464
+ const pid = child?.pid;
465
+ if (pid === undefined || !groupOwned()) return false;
466
+ if (process.platform !== "win32") {
467
+ try {
468
+ process.kill(-pid, 0);
469
+ return true;
470
+ } catch (error) {
471
+ // ESRCH means every member is gone; the number is released for good.
472
+ // EPERM means a member exists that this process may not signal;
473
+ // anything else is treated as alive so cleanup never reports a
474
+ // teardown it did not observe.
475
+ if ((error as NodeJS.ErrnoException).code !== "ESRCH") return true;
476
+ groupPhase = "released";
477
+ return false;
478
+ }
479
+ }
480
+ return isAlive();
481
+ };
482
+
483
+ const terminationObserved = (): boolean => leaderExited && !groupAlive();
484
+
485
+ /** Poll until the leader has been reaped and its group is empty, or the bound elapses. */
486
+ const waitForTermination = async (timeoutMs: number): Promise<boolean> => {
487
+ const deadline = performance.now() + timeoutMs;
488
+ while (!terminationObserved()) {
489
+ const remaining = deadline - performance.now();
490
+ if (remaining <= 0) return terminationObserved();
491
+ const nap = sleep(Math.min(10, remaining));
492
+ await (leaderExited || exited === null ? nap : Promise.race([exited, nap]));
493
+ }
494
+ return true;
495
+ };
496
+
497
+ const destroyStdio = (): void => {
498
+ for (const stream of [child?.stdin, child?.stdout, child?.stderr]) stream?.destroy();
499
+ };
500
+
501
+ /**
502
+ * Tear the group down once: SIGTERM, the grace period, SIGKILL for whatever
503
+ * is left, a bounded wait for it to disappear, then release the id for
504
+ * good. Runs from close() and from the leader's exit, whichever comes first;
505
+ * the second caller shares the first run. When something survives even
506
+ * SIGKILL the outcome says so, with the group id, and our pipe ends are
507
+ * dropped so the survivor cannot pin this process's event loop; otherwise
508
+ * the pipes drain naturally and the stderr tail stays whole. The outcome is
509
+ * flagged rather than thrown: a caller's shutdown loop cannot do anything
510
+ * about a survivor except report it, and the flag carries what to report.
511
+ */
512
+ const cleanupGroup = (): Promise<McpTeardownOutcome> => {
513
+ if (groupCleanup !== null) return groupCleanup;
514
+ groupCleanup = (async () => {
515
+ let terminated = true;
516
+ const pgid = child?.pid;
517
+ if (groupPhase === "live" && pgid !== undefined) {
518
+ groupPhase = "cleaning";
519
+ if (groupAlive()) signalGroup("SIGTERM");
520
+ terminated = await waitForTermination(killGraceMs);
521
+ if (!terminated) {
522
+ if (groupAlive()) signalGroup("SIGKILL");
523
+ terminated = await waitForTermination(teardownBoundMs);
524
+ }
525
+ } else {
526
+ await (exited ?? Promise.resolve());
527
+ }
528
+ groupPhase = "released";
529
+ const outcome: McpTeardownOutcome =
530
+ terminated || pgid === undefined
531
+ ? { complete: true }
532
+ : { complete: false, reason: "group-survived-sigkill", pgid, boundMs: killGraceMs + teardownBoundMs };
533
+ teardown = outcome;
534
+ if (!outcome.complete) destroyStdio();
535
+ return outcome;
536
+ })();
537
+ return groupCleanup;
538
+ };
539
+
540
+ /** Bytes accepted for the server but not yet flushed: this queue plus the stream's own buffer. */
541
+ const pendingOutboundBytes = (): number => outboundQueuedBytes + (child?.stdin?.writableLength ?? 0);
542
+
543
+ const flushOutbound = (): void => {
544
+ while (!awaitingDrain) {
545
+ const entry = outbound.shift();
546
+ if (entry === undefined) return;
547
+ outboundQueuedBytes -= entry.payload.length;
548
+ const stdin = child?.stdin;
549
+ if (!stdin || stdin.destroyed || !stdin.writable) {
550
+ entry.onError?.(new Error("server stdin is not writable"));
551
+ continue;
552
+ }
553
+ const accepted = stdin.write(entry.payload, (error) => {
554
+ if (error) entry.onError?.(error);
555
+ });
556
+ if (!accepted) {
557
+ awaitingDrain = true;
558
+ stdin.once("drain", () => {
559
+ awaitingDrain = false;
560
+ flushOutbound();
561
+ });
562
+ }
563
+ }
564
+ };
565
+
566
+ /**
567
+ * Queue one line for the server. A line larger than the cap is refused on
568
+ * its own; a line that would push the unflushed total over the cap means the
569
+ * server stopped reading, which fails the client and closes it.
570
+ */
571
+ const enqueueOutbound = (
572
+ message: OutboundMessage,
573
+ requestId: number | null,
574
+ onError?: (error: Error) => void,
575
+ ): EnqueueOutcome => {
576
+ const payload = encodeJsonRpcMessage(message);
577
+ if (payload.length > maxOutboundBytes) return { kind: "oversized", bytes: payload.length };
578
+ const queued = pendingOutboundBytes();
579
+ if (queued + payload.length > maxOutboundBytes) {
580
+ fail(
581
+ new McpError(
582
+ "overload",
583
+ `mcp server ${spec.id} stopped reading its stdin: ${queued} bytes are queued for it and the outbound cap is ${maxOutboundBytes} bytes`,
584
+ ),
585
+ );
586
+ void close();
587
+ return { kind: "overloaded" };
588
+ }
589
+ outbound.push({ payload, requestId, onError });
590
+ outboundQueuedBytes += payload.length;
591
+ flushOutbound();
592
+ return { kind: "queued" };
593
+ };
594
+
595
+ /** Drop a request's line if it is still waiting in the queue. */
596
+ const withdrawOutbound = (requestId: number): void => {
597
+ const index = outbound.findIndex((entry) => entry.requestId === requestId);
598
+ if (index === -1) return;
599
+ const [entry] = outbound.splice(index, 1);
600
+ if (entry !== undefined) outboundQueuedBytes -= entry.payload.length;
601
+ };
602
+
603
+ const dispatch = (frame: JsonRpcMessage): void => {
604
+ if (frame.kind === "response") {
605
+ const id = frame.message.id;
606
+ if (typeof id !== "number") return;
607
+ const entry = pending.get(id);
608
+ if (entry === undefined) return;
609
+ if (frame.message.error !== undefined) {
610
+ const error = frame.message.error;
611
+ entry.reject(new McpError("server", `${entry.method}: ${error.message} (code ${error.code})`, error));
612
+ return;
613
+ }
614
+ entry.resolve(frame.message.result);
615
+ return;
616
+ }
617
+ if (frame.kind === "request") {
618
+ const request = frame.message;
619
+ const outcome = enqueueOutbound(
620
+ {
621
+ jsonrpc: "2.0",
622
+ id: request.id as JsonRpcId,
623
+ error: { code: JSON_RPC_METHOD_NOT_FOUND, message: `method not found: ${request.method}` },
624
+ },
625
+ null,
626
+ );
627
+ if (outcome.kind === "oversized") {
628
+ fail(
629
+ new McpError(
630
+ "overload",
631
+ `mcp server ${spec.id} sent a request whose ${outcome.bytes}-byte reply exceeds the ${maxOutboundBytes}-byte outbound cap`,
632
+ ),
633
+ );
634
+ void close();
635
+ }
636
+ return;
637
+ }
638
+ notifications += 1;
639
+ if (frame.message.method === "notifications/tools/list_changed") toolsChangedFlag = true;
640
+ };
641
+
642
+ const consumeFrames = (frames: ReturnType<typeof framer.push>): void => {
643
+ for (const frame of frames) {
644
+ if (status === "closed" || status === "failed") return;
645
+ if (frame.kind === "message") {
646
+ dispatch(frame.message);
647
+ continue;
648
+ }
649
+ fail(new McpError("protocol", `protocol error from mcp server ${spec.id}: ${frame.error.message}`));
650
+ void close();
651
+ return;
652
+ }
653
+ };
654
+
655
+ const spawnChild = (): boolean => {
656
+ const cwd = containedCwd(spec, options.workspaceRoot);
657
+ if (cwd instanceof Error) {
658
+ fail(new McpError("spawn", `mcp server ${spec.id} failed to start: ${cwd.message}`));
659
+ return false;
660
+ }
661
+ let proc: ChildProcess;
662
+ try {
663
+ proc = spawn(spec.command, [...(spec.args ?? [])], {
664
+ cwd,
665
+ env: buildSafeToolEnv({ ...(spec.env ?? {}) }),
666
+ detached: process.platform !== "win32",
667
+ stdio: ["pipe", "pipe", "pipe"],
668
+ });
669
+ } catch (error) {
670
+ fail(new McpError("spawn", `mcp server ${spec.id} failed to start: ${errorMessage(error)}`));
671
+ return false;
672
+ }
673
+ child = proc;
674
+ if (proc.pid !== undefined) groupPhase = "live";
675
+ spawned = new Promise<boolean>((resolve) => {
676
+ proc.once("spawn", () => resolve(true));
677
+ proc.once("error", (error) => {
678
+ fail(new McpError("spawn", `mcp server ${spec.id} failed to start: ${error.message}`));
679
+ resolve(false);
680
+ });
681
+ });
682
+ exited = new Promise<void>((resolve) => {
683
+ proc.once("exit", (code, signal) => {
684
+ leaderExited = true;
685
+ if (!closing && status !== "failed") {
686
+ fail(
687
+ new McpError(
688
+ "closed",
689
+ `mcp server ${spec.id} exited with ${signal !== null ? `signal ${signal}` : `code ${code ?? "?"}`} before the client closed it`,
690
+ ),
691
+ );
692
+ } else {
693
+ rejectAllPending(closedError());
694
+ }
695
+ resolve();
696
+ // Whatever the leader left in its group is torn down now, while the id is still ours.
697
+ void cleanupGroup();
698
+ });
699
+ proc.once("error", () => {
700
+ if (proc.pid === undefined) {
701
+ leaderExited = true;
702
+ resolve();
703
+ }
704
+ });
705
+ });
706
+ proc.stdin?.on("error", () => {
707
+ // Surfaced through the write callbacks; a bare listener keeps the event from throwing.
708
+ });
709
+ proc.stdout?.on("data", (chunk: Buffer) => consumeFrames(framer.push(chunk)));
710
+ proc.stdout?.on("end", () => consumeFrames(framer.flush()));
711
+ proc.stderr?.on("data", (chunk: Buffer) => {
712
+ if (stderrTailBytes === 0) return;
713
+ const joined = Buffer.concat([stderrTailBuffer, chunk]);
714
+ stderrTailBuffer =
715
+ joined.length > stderrTailBytes ? Buffer.from(joined.subarray(joined.length - stderrTailBytes)) : joined;
716
+ });
717
+ return true;
718
+ };
719
+
720
+ const request = (method: string, params: unknown, timeoutMs: number, signal?: AbortSignal): Promise<unknown> =>
721
+ new Promise<unknown>((resolve, reject) => {
722
+ if (signal?.aborted) {
723
+ reject(new McpError("aborted", `${method} aborted before it was sent`));
724
+ return;
725
+ }
726
+ if (child === null || status === "closed" || status === "failed") {
727
+ reject(closedError());
728
+ return;
729
+ }
730
+ const id = nextId++;
731
+ let timer: ReturnType<typeof setTimeout> | null = null;
732
+ const settle = (finish: () => void): void => {
733
+ if (!pending.has(id)) return;
734
+ pending.delete(id);
735
+ withdrawOutbound(id);
736
+ if (timer !== null) clearTimeout(timer);
737
+ signal?.removeEventListener("abort", onAbort);
738
+ finish();
739
+ };
740
+ const onAbort = (): void => settle(() => reject(new McpError("aborted", `${method} aborted`)));
741
+ pending.set(id, {
742
+ method,
743
+ resolve: (value) => settle(() => resolve(value)),
744
+ reject: (error) => settle(() => reject(error)),
745
+ });
746
+ if (timeoutMs > 0) {
747
+ timer = setTimeout(
748
+ () => settle(() => reject(new McpError("timeout", `${method} timed out after ${timeoutMs}ms`))),
749
+ timeoutMs,
750
+ );
751
+ }
752
+ signal?.addEventListener("abort", onAbort, { once: true });
753
+ const outcome = enqueueOutbound(
754
+ { jsonrpc: "2.0", id, method, ...(params === undefined ? {} : { params }) },
755
+ id,
756
+ (error) => {
757
+ settle(() => reject(failure ?? new McpError("closed", `write to mcp server ${spec.id} failed: ${error.message}`)));
758
+ },
759
+ );
760
+ if (outcome.kind === "oversized") {
761
+ settle(() =>
762
+ reject(
763
+ new McpError(
764
+ "overload",
765
+ `${method} request of ${outcome.bytes} bytes exceeds the ${maxOutboundBytes}-byte outbound cap`,
766
+ ),
767
+ ),
768
+ );
769
+ }
770
+ // An overloaded queue already failed the client, which rejected this request with the cause.
771
+ });
772
+
773
+ const initialize = (): Promise<McpServerInfo> => {
774
+ if (status === "closed" || status === "failed") return Promise.reject(closedError());
775
+ if (initializePromise !== null) return initializePromise;
776
+ initializePromise = (async () => {
777
+ status = "starting";
778
+ if (!spawnChild()) {
779
+ await close();
780
+ throw closedError();
781
+ }
782
+ const started = await (spawned ?? Promise.resolve(false));
783
+ if (!started) {
784
+ await close();
785
+ throw closedError();
786
+ }
787
+ let result: unknown;
788
+ try {
789
+ result = await request(
790
+ "initialize",
791
+ {
792
+ protocolVersion: MCP_PROTOCOL_VERSION,
793
+ capabilities: {},
794
+ clientInfo: { name: MCP_CLIENT_NAME, version: clientVersion },
795
+ },
796
+ initializeTimeoutMs,
797
+ );
798
+ } catch (error) {
799
+ const cause = error instanceof McpError ? error : new McpError("protocol", errorMessage(error));
800
+ fail(new McpError(cause.code, `initialize failed: ${cause.message}`, cause.data));
801
+ await close();
802
+ throw closedError();
803
+ }
804
+ const parsed = parseServerInfo(result);
805
+ if (parsed instanceof McpError) {
806
+ fail(new McpError("protocol", `initialize failed: ${parsed.message}`));
807
+ await close();
808
+ throw closedError();
809
+ }
810
+ info = parsed;
811
+ enqueueOutbound({ jsonrpc: "2.0", method: "notifications/initialized" }, null);
812
+ if (status === "starting") status = "ready";
813
+ return parsed;
814
+ })();
815
+ return initializePromise;
816
+ };
817
+
818
+ const ensureReady = async (): Promise<void> => {
819
+ if (status === "ready") return;
820
+ await initialize();
821
+ };
822
+
823
+ const listTools = async (): Promise<McpToolListing> => {
824
+ await ensureReady();
825
+ const tools: McpToolDescriptor[] = [];
826
+ let cursor: string | undefined;
827
+ let pages = 0;
828
+ for (;;) {
829
+ pages += 1;
830
+ const result = await request("tools/list", cursor === undefined ? {} : { cursor }, requestTimeoutMs);
831
+ if (!isRecord(result) || !Array.isArray(result.tools)) {
832
+ throw new McpError("protocol", "tools/list result lacks a tools array");
833
+ }
834
+ for (const entry of result.tools) {
835
+ if (tools.length >= MCP_TOOL_LIST_CAP) return { tools, truncated: true };
836
+ const descriptor = parseToolDescriptor(entry);
837
+ if (descriptor instanceof McpError) throw descriptor;
838
+ tools.push(descriptor);
839
+ }
840
+ const next = typeof result.nextCursor === "string" && result.nextCursor.length > 0 ? result.nextCursor : undefined;
841
+ if (next === undefined) return { tools, truncated: false };
842
+ if (tools.length >= MCP_TOOL_LIST_CAP || pages >= MCP_TOOL_LIST_PAGE_CAP) return { tools, truncated: true };
843
+ cursor = next;
844
+ }
845
+ };
846
+
847
+ const callTool = async (
848
+ name: string,
849
+ args: Record<string, unknown>,
850
+ callOptions: McpCallToolOptions = {},
851
+ ): Promise<McpToolCallResult> => {
852
+ await ensureReady();
853
+ const timeoutMs = clampTimerDelayMs(callOptions.timeoutMs ?? requestTimeoutMs);
854
+ const result = await request("tools/call", { name, arguments: args }, timeoutMs, callOptions.signal);
855
+ const parsed = parseToolCallResult(result, maxResultTextBytes);
856
+ if (parsed instanceof McpError) throw parsed;
857
+ return parsed;
858
+ };
859
+
860
+ /**
861
+ * End the server: close its stdin, then run (or join) the group teardown.
862
+ * The leader's exit is not the end of it; a descendant that outlives the
863
+ * leader is signalled and waited for the same way. Our ends of the pipes
864
+ * are dropped last, since nobody reads them after close.
865
+ */
866
+ const close = (): Promise<McpTeardownOutcome> => {
867
+ if (closePromise !== null) return closePromise;
868
+ closePromise = (async () => {
869
+ closing = true;
870
+ if (status !== "failed") status = "closed";
871
+ rejectAllPending(closedError());
872
+ outbound.length = 0;
873
+ outboundQueuedBytes = 0;
874
+ if (child === null) {
875
+ teardown ??= { complete: true };
876
+ return teardown;
877
+ }
878
+ try {
879
+ child.stdin?.end();
880
+ } catch {
881
+ // Nothing to flush on a dead pipe.
882
+ }
883
+ const outcome = await cleanupGroup();
884
+ destroyStdio();
885
+ return outcome;
886
+ })();
887
+ return closePromise;
888
+ };
889
+
890
+ if (options.signal !== undefined) {
891
+ if (options.signal.aborted) void close();
892
+ else options.signal.addEventListener("abort", () => void close(), { once: true });
893
+ }
894
+
895
+ return {
896
+ id: spec.id,
897
+ get pid() {
898
+ return child?.pid;
899
+ },
900
+ initialize,
901
+ listTools,
902
+ callTool,
903
+ close,
904
+ killOwnedOnExit: () => {
905
+ // ESRCH releases ownership before the asynchronous teardown record settles.
906
+ // Check the live ownership state, never the retained pid or final outcome.
907
+ if (groupOwned()) signalGroup("SIGKILL");
908
+ },
909
+ state: () => {
910
+ const cleanup = { cleanupIncomplete: teardown?.complete === false, teardown };
911
+ return status === "failed"
912
+ ? { status, reason: failure?.message ?? `mcp server ${spec.id} failed`, ...cleanup }
913
+ : { status, ...cleanup };
914
+ },
915
+ serverInfo: () => info,
916
+ toolsChanged: () => toolsChangedFlag,
917
+ acknowledgeToolsChanged: () => {
918
+ toolsChangedFlag = false;
919
+ },
920
+ notificationCount: () => notifications,
921
+ stderrTail: () => stderrTailBuffer.toString("utf8"),
922
+ };
923
+ }