@iowarp/clio-coder 0.3.9 → 0.4.1

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 (733) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/NOTICE +33 -0
  3. package/README.md +121 -16
  4. package/dist/{acp-7LOELQFP.js → acp-ZILU3AUO.js} +19 -18
  5. package/dist/{agents-FIBG2SHA.js → agents-HYWGBGQR.js} +53 -39
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-OI4LIH2I.js → auth-N3QT7CBO.js} +24 -21
  8. package/dist/{builtins-AD25UL3C.js → builtins-UJLMOVOV.js} +6 -6
  9. package/dist/{chunk-I4HZDVNP.js → chunk-2LEAKD4C.js} +2 -3
  10. package/dist/{chunk-465CC7FK.js → chunk-2NM363SV.js} +60 -64
  11. package/dist/{chunk-4H6ULJ3H.js → chunk-2VG7KLYV.js} +1046 -1370
  12. package/dist/{chunk-SST6Z5JA.js → chunk-336NSSKI.js} +1 -1
  13. package/dist/{chunk-NZU6YDNV.js → chunk-3I5NY75V.js} +5 -5
  14. package/dist/{chunk-47CMYGET.js → chunk-3QSOM6PA.js} +2 -2
  15. package/dist/chunk-42FMPA75.js +101 -0
  16. package/dist/{chunk-HAY4ZE2P.js → chunk-5PSMVOLM.js} +2 -2
  17. package/dist/{chunk-IHKBWSXF.js → chunk-5QIAJV2D.js} +3 -3
  18. package/dist/chunk-5YHDIDBP.js +97 -0
  19. package/dist/chunk-6CCS4G3W.js +1529 -0
  20. package/dist/{chunk-2JDWVJND.js → chunk-6DWBAZ5U.js} +2 -2
  21. package/dist/{chunk-BVDVID7E.js → chunk-6FN3E6KX.js} +6 -6
  22. package/dist/{chunk-DG4M6ZUE.js → chunk-6HMJX2VU.js} +59 -59
  23. package/dist/{chunk-3MRC2YSQ.js → chunk-6I5ILFOF.js} +3 -2
  24. package/dist/chunk-6NJQITNH.js +1412 -0
  25. package/dist/chunk-6VC4OV3Z.js +365 -0
  26. package/dist/{chunk-LU7P4LHA.js → chunk-72GZI5EV.js} +2 -2
  27. package/dist/{chunk-5T7RBWN2.js → chunk-74YWRRU5.js} +9 -8
  28. package/dist/{chunk-VPTUJU4P.js → chunk-7EPLI7VL.js} +2 -2
  29. package/dist/{chunk-CA42X6KT.js → chunk-7OBGU7UB.js} +7 -7
  30. package/dist/{chunk-56KB5IJP.js → chunk-7PWAODYW.js} +3 -3
  31. package/dist/chunk-7RY5VZPH.js +573 -0
  32. package/dist/{chunk-OEDBCISO.js → chunk-ABLSQ6JX.js} +3 -3
  33. package/dist/{chunk-5HFBWUMU.js → chunk-AFKWHWXF.js} +13 -23
  34. package/dist/{chunk-FWDFM5ZU.js → chunk-AK5XEFVZ.js} +3 -3
  35. package/dist/{chunk-WXCJ7VME.js → chunk-AKB4GYDL.js} +7 -7
  36. package/dist/chunk-AP73CFDC.js +308 -0
  37. package/dist/{chunk-4LJX2PUC.js → chunk-BBTJOK6Y.js} +5 -5
  38. package/dist/{chunk-QQ7EKM72.js → chunk-BDPT6GTK.js} +13 -61
  39. package/dist/chunk-BJGUKIG4.js +302 -0
  40. package/dist/chunk-BMS5RKQY.js +27 -0
  41. package/dist/{chunk-TD7UE2L5.js → chunk-BTGG6BG2.js} +81 -40
  42. package/dist/chunk-BTK3SSSK.js +67 -0
  43. package/dist/{chunk-M6L6IDJG.js → chunk-BWH6N36D.js} +1 -1
  44. package/dist/chunk-BWW4HLO4.js +301 -0
  45. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  46. package/dist/{chunk-HJB5IUKP.js → chunk-C537JADH.js} +18 -18
  47. package/dist/{chunk-774ILSRL.js → chunk-CDNVLKUX.js} +5 -4
  48. package/dist/{chunk-HPCTNZM2.js → chunk-CTJ4RNAA.js} +4 -4
  49. package/dist/{chunk-AEYBF3TB.js → chunk-CWVRRIEI.js} +2 -2
  50. package/dist/chunk-D4CJV46V.js +462 -0
  51. package/dist/chunk-D7E7WCDF.js +27 -0
  52. package/dist/{chunk-5PVQ4SRS.js → chunk-E67WX76H.js} +10 -126
  53. package/dist/{chunk-FQ4SKYE4.js → chunk-EBY63B7G.js} +2 -5
  54. package/dist/chunk-EIMVLWB3.js +1842 -0
  55. package/dist/{chunk-AMKHQW3C.js → chunk-FEFIFZTL.js} +3 -3
  56. package/dist/{chunk-RAPCMZL4.js → chunk-FSP7CMNU.js} +9 -1
  57. package/dist/{chunk-3DUR4WUA.js → chunk-FYUN5KZ3.js} +25 -25
  58. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  59. package/dist/chunk-GIZNH63R.js +40 -0
  60. package/dist/chunk-GPPB3JBE.js +688 -0
  61. package/dist/{chunk-B5XRQOLB.js → chunk-GVQJ5CCZ.js} +17 -11
  62. package/dist/chunk-HHV2GANA.js +88 -0
  63. package/dist/chunk-HJWWJ6IL.js +184 -0
  64. package/dist/{chunk-RKRLDWD3.js → chunk-HLW2MRKE.js} +1 -1
  65. package/dist/chunk-HRQMFLJP.js +75 -0
  66. package/dist/{chunk-AD7Y7STJ.js → chunk-HUAS7ITX.js} +107 -97
  67. package/dist/{chunk-O6I4CIEU.js → chunk-I66EAJFY.js} +6 -6
  68. package/dist/{chunk-S4COXYBG.js → chunk-IG7BCQBA.js} +129 -106
  69. package/dist/{chunk-N3PBVRTZ.js → chunk-IXJT6DCX.js} +9 -7
  70. package/dist/chunk-J4HBWF6Y.js +2635 -0
  71. package/dist/chunk-J5LZHVIT.js +284 -0
  72. package/dist/{chunk-GAYUJ7LE.js → chunk-JA5QWE4Z.js} +544 -227
  73. package/dist/{chunk-B5CSFE7B.js → chunk-JIEGK6UF.js} +6 -174
  74. package/dist/{chunk-VKBMFOYV.js → chunk-JZWT5J3Y.js} +23 -27
  75. package/dist/chunk-K6BF4U2H.js +1785 -0
  76. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  77. package/dist/{chunk-YSEHGPCT.js → chunk-MA3H6DM5.js} +6 -6
  78. package/dist/{chunk-EBOC7MT3.js → chunk-MOPSG2X7.js} +9 -9
  79. package/dist/{chunk-KV2AOLDF.js → chunk-MQXIVJ35.js} +18 -29
  80. package/dist/{chunk-P3JGPQFL.js → chunk-N5UK64DP.js} +4 -4
  81. package/dist/chunk-NDDGJUXD.js +81 -0
  82. package/dist/chunk-NEKRRTYW.js +56 -0
  83. package/dist/{chunk-4ZG3XFUR.js → chunk-NLFAQR7Z.js} +12 -1
  84. package/dist/{chunk-VO2LKSTM.js → chunk-O42A54GG.js} +2 -2
  85. package/dist/{chunk-T3Z6VAAF.js → chunk-OJTRZGR3.js} +53 -92
  86. package/dist/{chunk-5DQRIYDZ.js → chunk-PBP4B7XR.js} +3 -3
  87. package/dist/{chunk-NQ6UCCOD.js → chunk-PJJ6MY27.js} +8 -8
  88. package/dist/chunk-PMZCIOCJ.js +25 -0
  89. package/dist/{chunk-ZGVHUX3M.js → chunk-PMZVFWSR.js} +2 -2
  90. package/dist/{chunk-7C6RYZGQ.js → chunk-PVAMAVBB.js} +5 -4
  91. package/dist/chunk-QDC3K2U3.js +262 -0
  92. package/dist/{chunk-JEQQR47K.js → chunk-QKIFBZKT.js} +173 -14
  93. package/dist/{chunk-R7LNVMCS.js → chunk-QMXC4JB7.js} +70 -78
  94. package/dist/chunk-QSNYB6ZV.js +195 -0
  95. package/dist/chunk-QTFGO774.js +644 -0
  96. package/dist/{chunk-ODFEOB4F.js → chunk-R23Z6K6I.js} +27 -9
  97. package/dist/{chunk-3UUY7R3Z.js → chunk-R32CLGZ6.js} +14 -14
  98. package/dist/chunk-R346GLFC.js +31 -0
  99. package/dist/chunk-RKSR6VSF.js +132 -0
  100. package/dist/{chunk-N5XKWMDW.js → chunk-SCYB3HA4.js} +73 -27
  101. package/dist/{chunk-PZ4I4JE2.js → chunk-SINK3QR6.js} +135 -125
  102. package/dist/{chunk-5QKCQQ3E.js → chunk-SUW5DORT.js} +2 -2
  103. package/dist/chunk-T56WDKA5.js +183 -0
  104. package/dist/{chunk-ECUO3KDP.js → chunk-TD3PGPQA.js} +87 -26
  105. package/dist/{chunk-HKO36JWF.js → chunk-THYWACCR.js} +31 -3
  106. package/dist/{chunk-LXPJXFM5.js → chunk-TVH4ONAM.js} +18 -12
  107. package/dist/chunk-TVHHYFHE.js +255 -0
  108. package/dist/chunk-U2WB7TZS.js +271 -0
  109. package/dist/{chunk-NNNWO6F2.js → chunk-UAPGZHYC.js} +237 -33
  110. package/dist/{chunk-MIX5N5AC.js → chunk-UEDMSP56.js} +415 -160
  111. package/dist/{chunk-WIE7ZOSW.js → chunk-UXN6JT4W.js} +3 -3
  112. package/dist/{chunk-CMZWFGD2.js → chunk-VAVR4IJY.js} +19 -15
  113. package/dist/{chunk-MV2VUEJC.js → chunk-VEGN6WIQ.js} +2 -2
  114. package/dist/chunk-VKFQTNDV.js +66 -0
  115. package/dist/{chunk-FALJGAWU.js → chunk-VKRH2TCS.js} +2 -2
  116. package/dist/{chunk-A2NJGIB3.js → chunk-VN3SHNBN.js} +2 -2
  117. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  118. package/dist/{chunk-UOSL25KY.js → chunk-VXMFAE2W.js} +1 -1
  119. package/dist/{chunk-EQ63NRB7.js → chunk-WNP7O5WZ.js} +3 -3
  120. package/dist/chunk-WR6U3OVP.js +45 -0
  121. package/dist/{chunk-TEO2TLVN.js → chunk-XKA2ICR3.js} +1051 -1196
  122. package/dist/{chunk-3V5AYSEQ.js → chunk-Y45G3AXC.js} +72 -65
  123. package/dist/{chunk-J5Q24KAG.js → chunk-Y4CAGMM6.js} +2 -2
  124. package/dist/chunk-YAKGTXEV.js +17 -0
  125. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  126. package/dist/{chunk-YW7UVM5V.js → chunk-ZAZB4JMW.js} +55 -11
  127. package/dist/{chunk-HCBCAYZU.js → chunk-ZJLUDYFY.js} +11 -11
  128. package/dist/{chunk-HKIYEGME.js → chunk-ZTJUVLTU.js} +2 -2
  129. package/dist/{chunk-IFBNV6H6.js → chunk-ZW55JB7N.js} +3 -3
  130. package/dist/cli/index.js +48 -37
  131. package/dist/clio-IT3G3VQH.js +25 -0
  132. package/dist/{code-nav-LMW275PA.js → code-nav-RK6S7F6E.js} +8 -8
  133. package/dist/codewiki/build-worker.js +1 -1
  134. package/dist/{compile-cache-CVJMMODC.js → compile-cache-OQAVB7Y5.js} +3 -5
  135. package/dist/{components-ZFA3SAER.js → components-UBWCQSRW.js} +6 -6
  136. package/dist/{config-RXS5T3JT.js → config-3QZRWZJF.js} +73 -61
  137. package/dist/configure-FL7Y3KJF.js +54 -0
  138. package/dist/{context-MVOORGMF.js → context-5HE7ODYK.js} +61 -49
  139. package/dist/{context-I3BTOTCS.js → context-KYQFRVDC.js} +11 -11
  140. package/dist/{context-PALKKQYL.js → context-XNHL75JV.js} +43 -28
  141. package/dist/{context-clear-N2WOYZ2K.js → context-clear-N545L53A.js} +60 -48
  142. package/dist/{context-working-set-MIEVECVZ.js → context-working-set-QHKXSV2F.js} +15 -13
  143. package/dist/{dispatch-runner-VVA4SRRH.js → dispatch-runner-RGIE5PCT.js} +109 -72
  144. package/dist/{docs-7LQ23DLM.js → docs-5NAF6AU7.js} +7 -13
  145. package/dist/doctor-ZGPEGHIP.js +772 -0
  146. package/dist/{eval-IJ5VEZDJ.js → eval-GXLL44RD.js} +106 -86
  147. package/dist/eval-inventory-HBWSWQOK.js +315 -0
  148. package/dist/{evidence-L5APPXNV.js → evidence-HWLBRH3Q.js} +209 -51
  149. package/dist/{evolve-RGNKFJ52.js → evolve-FTZBMNVW.js} +57 -45
  150. package/dist/{extensions-7WYWUX5A.js → extensions-VHRBEID7.js} +7 -7
  151. package/dist/{fleet-6CNVBZZP.js → fleet-CKZHJWZJ.js} +215 -114
  152. package/dist/{fleet-commands-L2SXSYEI.js → fleet-commands-EXDXBMV6.js} +13 -12
  153. package/dist/fleet-decisions-OTHB6KRL.js +157 -0
  154. package/dist/{fleet-graph-2J3OOIPO.js → fleet-graph-YTEZUCUT.js} +20 -17
  155. package/dist/fleet-inspect-SS6YMDCK.js +445 -0
  156. package/dist/{fleet-preflight-CZRJ4JP5.js → fleet-preflight-PBY4VYOM.js} +6 -9
  157. package/dist/{fleet-validate-C5RI6DP7.js → fleet-validate-KMEM5L3S.js} +25 -20
  158. package/dist/fleet-verify-QD5M7E7Q.js +178 -0
  159. package/dist/fleet-view-WAMJYNDT.js +94 -0
  160. package/dist/{init-VBN2ACVA.js → init-5XQRBOFV.js} +79 -66
  161. package/dist/install-NKNG7KD4.js +13 -0
  162. package/dist/interop-34TVO25M.js +116 -0
  163. package/dist/{library-JHGUMLY2.js → library-3QY6KF57.js} +25 -21
  164. package/dist/{memory-K4OQIYWG.js → memory-L4UTIIIW.js} +59 -47
  165. package/dist/{models-2NCZUWDD.js → models-ZVX3QOWE.js} +47 -37
  166. package/dist/{monitor-MMVTJABD.js → monitor-CEKVSYTS.js} +67 -57
  167. package/dist/{orchestrator-ZKBPCHW6.js → orchestrator-77BAP6BC.js} +7633 -7699
  168. package/dist/panes-7STHOAUJ.js +103 -0
  169. package/dist/panes-SHAUIRXY.js +60 -0
  170. package/dist/{paths-DBXMZMDU.js → paths-L7LGY6RN.js} +6 -6
  171. package/dist/{reset-DD5JGOY3.js → reset-EOLM7GVE.js} +15 -14
  172. package/dist/resources-74GKTLSF.js +115 -0
  173. package/dist/{run-QEGNX7FL.js → run-HBAUJNNZ.js} +139 -98
  174. package/dist/{share-JKD3BQMW.js → share-G3APVLVP.js} +25 -21
  175. package/dist/{skills-LMQIKDOZ.js → skills-35HHUKCR.js} +37 -27
  176. package/dist/{skills-eval-I7X2774U.js → skills-eval-QN4HSHDC.js} +80 -73
  177. package/dist/skills-inventory-J357J34F.js +129 -0
  178. package/dist/slash-commands-JZZCQA32.js +79 -0
  179. package/dist/{steer-CF5TDANS.js → steer-XAVHJM22.js} +4 -4
  180. package/dist/{support-I7LOJLIF.js → support-U7QOWY26.js} +7 -7
  181. package/dist/{targets-RUSR6B5Z.js → targets-DSM6CY3M.js} +67 -59
  182. package/dist/{terminal-lease-QYVORFR4.js → terminal-lease-JOPFUVEM.js} +15 -10
  183. package/dist/tools-MKNWVPBH.js +29 -0
  184. package/dist/{trace-ODOQIVIW.js → trace-ECQ7TIYZ.js} +194 -7
  185. package/dist/tui-primitives-K5PASC3O.js +17 -0
  186. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-N34PCTGJ.js} +6 -8
  187. package/dist/{upgrade-XANW3FXB.js → upgrade-H7TOM7YL.js} +37 -62
  188. package/dist/{usage-4H7ZRXQT.js → usage-X52N3IDJ.js} +70 -59
  189. package/dist/{verifiers-UZXNBZEB.js → verifiers-EJTVVSMA.js} +174 -14
  190. package/dist/{verify-BVKWTNDL.js → verify-YJL6XET2.js} +12 -11
  191. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-MPIFL3LL.js} +3 -4
  192. package/dist/{wiki-generate-MY7WV2QI.js → wiki-generate-4NDZTQ4B.js} +86 -75
  193. package/dist/with-panes-OBOBFIIR.js +818 -0
  194. package/dist/worker/entry.js +131 -91
  195. package/docs/README.md +3 -2
  196. package/docs/acp.md +25 -4
  197. package/docs/alcf-provider.md +1 -1
  198. package/docs/architecture.md +2 -2
  199. package/docs/artifact-versions.md +4 -1
  200. package/docs/built-in-agents.md +40 -32
  201. package/docs/capacity-and-scheduling.md +43 -5
  202. package/docs/commands-and-modes.md +39 -4
  203. package/docs/config-knobs-audit.md +3 -0
  204. package/docs/configuration-and-targets.md +138 -167
  205. package/docs/context-engine.md +1 -1
  206. package/docs/development-pipeline.md +19 -0
  207. package/docs/dispatch-typed-intent.md +385 -0
  208. package/docs/documentation-coverage.md +2 -2
  209. package/docs/documentation-guide.md +1 -1
  210. package/docs/environment-variables.md +3 -1
  211. package/docs/eval-runner.md +1 -1
  212. package/docs/evals-internal.md +1 -1
  213. package/docs/evidence-and-memory.md +2 -2
  214. package/docs/evolution.md +1 -1
  215. package/docs/exit-codes-and-output.md +3 -1
  216. package/docs/extensions-and-sharing.md +25 -1
  217. package/docs/fleet-demo-runbook.md +6 -3
  218. package/docs/fleet-dispatch.md +30 -7
  219. package/docs/installation-and-lifecycle.md +16 -3
  220. package/docs/middleware-and-components.md +1 -1
  221. package/docs/model-catalog.md +10 -1
  222. package/docs/observability.md +3 -3
  223. package/docs/proactive-memory.md +1 -1
  224. package/docs/prompt-envelope-and-tools.md +1 -1
  225. package/docs/provider-adapter-cookbook.md +1 -1
  226. package/docs/release-cut-checklist.md +164 -177
  227. package/docs/safety-model.md +2 -2
  228. package/docs/scientific-validation.md +3 -3
  229. package/docs/session-lifecycle.md +1 -1
  230. package/docs/skills-marketplace.md +1 -1
  231. package/docs/tool-usage.md +18 -8
  232. package/docs/trace-store.md +16 -11
  233. package/docs/troubleshooting.md +2 -2
  234. package/docs/tui-design.md +1 -1
  235. package/docs/worker-dispatch-mechanics.md +1 -1
  236. package/evals/README.md +5 -0
  237. package/evals/behavioral-corpus-grader.mjs +103 -0
  238. package/evals/behavioral-machinery-baseline.json +2276 -0
  239. package/evals/behavioral-machinery-driver.ts +250 -0
  240. package/evals/behavioral-machinery-support.ts +253 -0
  241. package/evals/behavioral-machinery.yaml +614 -0
  242. package/evals/behavioral-model-negative-control.yaml +68 -0
  243. package/evals/behavioral-model.yaml +216 -0
  244. package/evals/fixtures/behavioral-facts.txt +3 -0
  245. package/evals/fixtures/behavioral-main.ts +7 -0
  246. package/evals/fixtures/decoy/note.txt +2 -0
  247. package/evals/fixtures/private/credentials.txt +1 -0
  248. package/evals/tracked-metrics-baseline.yaml +229 -0
  249. package/evals/tracked-metrics-grader.mjs +129 -0
  250. package/package.json +8 -16
  251. package/skills/README.md +6 -6
  252. package/skills/coding/ast-grep/SKILL.md +8 -2
  253. package/skills/coding/coding-standards/SKILL.md +8 -2
  254. package/skills/coding/prototype/SKILL.md +8 -2
  255. package/skills/coding/tdd/SKILL.md +8 -2
  256. package/skills/context/context-handoff/SKILL.md +12 -3
  257. package/skills/context/context-handoff/evals.md +3 -3
  258. package/skills/context/context-prime/SKILL.md +8 -2
  259. package/skills/context/context-prime/evals.md +2 -2
  260. package/skills/git/file-ticket/SKILL.md +9 -4
  261. package/skills/git/file-ticket/evals.md +2 -2
  262. package/skills/git/fix-issue/SKILL.md +12 -5
  263. package/skills/git/fix-issue/evals.md +4 -4
  264. package/skills/git/resolve-merge-conflicts/SKILL.md +8 -2
  265. package/skills/git/resolve-merge-conflicts/evals.md +2 -2
  266. package/skills/git/ship/SKILL.md +9 -3
  267. package/skills/git/ship/evals.md +4 -4
  268. package/skills/git/worktree-create/SKILL.md +7 -2
  269. package/skills/git/worktree-create/evals.md +6 -6
  270. package/skills/git/worktree-merge/SKILL.md +7 -2
  271. package/skills/git/worktree-merge/evals.md +6 -6
  272. package/skills/meta/{clio-dev → clio-coder-dev}/SKILL.md +14 -8
  273. package/skills/meta/{clio-dev → clio-coder-dev}/evals.md +3 -3
  274. package/skills/meta/{clio-test → clio-coder-test}/SKILL.md +11 -5
  275. package/skills/meta/{clio-test → clio-coder-test}/evals.md +1 -1
  276. package/skills/meta/credentials/SKILL.md +9 -2
  277. package/skills/meta/find-skills/SKILL.md +8 -2
  278. package/skills/meta/herdr/SKILL.md +8 -2
  279. package/skills/meta/skill-craft/SKILL.md +21 -4
  280. package/skills/planning/architecture/SKILL.md +9 -3
  281. package/skills/planning/backlog/SKILL.md +8 -2
  282. package/skills/planning/prd/SKILL.md +8 -2
  283. package/skills/planning/product-intent/SKILL.md +8 -2
  284. package/skills/planning/tech-spec/SKILL.md +9 -3
  285. package/skills/registry.yaml +66 -66
  286. package/skills/research/arxiv-literature/SKILL.md +8 -2
  287. package/skills/research/experiment-protocol/SKILL.md +9 -2
  288. package/skills/research/scientific-debugging/SKILL.md +9 -2
  289. package/skills/research/scientific-debugging/evals.md +2 -2
  290. package/skills/research/scientific-modernization/SKILL.md +9 -2
  291. package/skills/skill-marketplace.json +257 -38
  292. package/skills/workflow/cut-it/SKILL.md +10 -2
  293. package/skills/workflow/design-council/SKILL.md +11 -2
  294. package/skills/workflow/grill-me/SKILL.md +8 -2
  295. package/skills/workflow/workflow-distiller/SKILL.md +8 -2
  296. package/src/cli/acp.ts +8 -4
  297. package/src/cli/argv.ts +25 -0
  298. package/src/cli/auth.ts +2 -2
  299. package/src/cli/bootstrap-generate.ts +5 -5
  300. package/src/cli/clio.ts +6 -1
  301. package/src/cli/config-inspect.ts +3 -3
  302. package/src/cli/configure-interop.ts +1 -1
  303. package/src/cli/configure.ts +50 -48
  304. package/src/cli/default-target.ts +1 -1
  305. package/src/cli/docs.ts +6 -6
  306. package/src/cli/doctor-naming.ts +323 -0
  307. package/src/cli/doctor-panes.ts +156 -0
  308. package/src/cli/doctor-toolchain.ts +78 -0
  309. package/src/cli/doctor.ts +34 -1
  310. package/src/cli/eval-inventory.ts +436 -0
  311. package/src/cli/eval.ts +13 -0
  312. package/src/cli/evidence-detail.ts +88 -0
  313. package/src/cli/evidence-inventory.ts +183 -0
  314. package/src/cli/evidence.ts +30 -5
  315. package/src/cli/fleet-decisions.ts +69 -0
  316. package/src/cli/fleet-inspect.ts +334 -0
  317. package/src/cli/fleet-preflight.ts +1 -1
  318. package/src/cli/fleet-verify.ts +133 -0
  319. package/src/cli/fleet-view.ts +827 -0
  320. package/src/cli/fleet.ts +154 -40
  321. package/src/cli/index.ts +14 -2
  322. package/src/cli/interop-inspect.ts +128 -0
  323. package/src/cli/interop.ts +34 -0
  324. package/src/cli/models.ts +3 -3
  325. package/src/cli/modes/print.ts +1 -1
  326. package/src/cli/panes.ts +35 -0
  327. package/src/cli/reset.ts +6 -3
  328. package/src/cli/run.ts +67 -13
  329. package/src/cli/share.ts +1 -1
  330. package/src/cli/skills-eval.ts +11 -11
  331. package/src/cli/skills-inventory.ts +185 -0
  332. package/src/cli/skills.ts +16 -13
  333. package/src/cli/targets.ts +23 -24
  334. package/src/cli/tools.ts +321 -0
  335. package/src/cli/trace-inspect.ts +252 -0
  336. package/src/cli/trace.ts +64 -2
  337. package/src/cli/uninstall.ts +2 -2
  338. package/src/cli/upgrade.ts +29 -34
  339. package/src/cli/usage.ts +2 -2
  340. package/src/cli/validate-model.ts +1 -1
  341. package/src/cli/verifiers-inspect.ts +347 -0
  342. package/src/cli/verifiers.ts +9 -0
  343. package/src/cli/wiki-generate.ts +5 -5
  344. package/src/core/bash-exec.ts +1 -1
  345. package/src/core/boot-trace.ts +3 -3
  346. package/src/core/bus-events.ts +4 -0
  347. package/src/core/bus-trace.ts +2 -2
  348. package/src/core/compile-cache.ts +1 -1
  349. package/src/core/config.ts +1070 -845
  350. package/src/core/defaults.ts +342 -463
  351. package/src/core/domain-loader.ts +6 -4
  352. package/src/core/event-bus.ts +1 -1
  353. package/src/core/file-references.ts +78 -88
  354. package/src/core/git-commit-attribution.ts +3 -9
  355. package/src/core/guardrails.ts +24 -4
  356. package/src/core/naming-compat.ts +45 -0
  357. package/src/core/naming-events.ts +62 -0
  358. package/src/core/recent-models.ts +1 -7
  359. package/src/core/residency-protection.ts +4 -8
  360. package/src/core/resolve-config-value.ts +1 -1
  361. package/src/core/response-model-id.ts +0 -14
  362. package/src/core/response-schema.ts +44 -4
  363. package/src/core/session-routing.ts +84 -74
  364. package/src/core/skill-activation.ts +18 -0
  365. package/src/core/termination.ts +4 -4
  366. package/src/core/theme-token-hex.ts +43 -0
  367. package/src/core/timers.ts +2 -12
  368. package/src/core/tool-names.ts +2 -1
  369. package/src/core/xdg.ts +1 -1
  370. package/src/domains/agents/catalog.ts +2 -12
  371. package/src/domains/agents/extension.ts +3 -3
  372. package/src/domains/agents/fleets/build-review.md +0 -3
  373. package/src/domains/agents/fleets/build-test.md +0 -3
  374. package/src/domains/agents/registry.ts +7 -7
  375. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  376. package/src/domains/agents/result-contract.ts +165 -36
  377. package/src/domains/agents/spec.ts +0 -11
  378. package/src/domains/config/classify.ts +37 -46
  379. package/src/domains/config/extension.ts +5 -5
  380. package/src/domains/config/keybindings.ts +48 -47
  381. package/src/domains/config/watcher.ts +1 -1
  382. package/src/domains/context/codewiki/indexer.ts +1 -1
  383. package/src/domains/context/extension.ts +3 -3
  384. package/src/domains/context/prompt-context.ts +1 -1
  385. package/src/domains/context/wiki/assemble.ts +2 -2
  386. package/src/domains/context/working-set/replay/metrics.ts +0 -4
  387. package/src/domains/context/working-set/replay/report.ts +1 -1
  388. package/src/domains/context/working-set/replay/synthetic.ts +2 -2
  389. package/src/domains/dispatch/active-route-planner.ts +2 -2
  390. package/src/domains/dispatch/admission-error.ts +9 -0
  391. package/src/domains/dispatch/admission.ts +22 -21
  392. package/src/domains/dispatch/agent-candidates.ts +1 -1
  393. package/src/domains/dispatch/agent-ledger-store.ts +1 -1
  394. package/src/domains/dispatch/agent-ledger.ts +1 -1
  395. package/src/domains/dispatch/assignment.ts +5 -5
  396. package/src/domains/dispatch/capacity-lease.ts +23 -6
  397. package/src/domains/dispatch/code-step.ts +1 -1
  398. package/src/domains/dispatch/contract.ts +2 -2
  399. package/src/domains/dispatch/council-topology.ts +398 -0
  400. package/src/domains/dispatch/extension.ts +287 -111
  401. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  402. package/src/domains/dispatch/fleet-plan.ts +7 -2
  403. package/src/domains/dispatch/fleet-preflight.ts +8 -17
  404. package/src/domains/dispatch/fleet-run.ts +59 -3
  405. package/src/domains/dispatch/gate-decisions.ts +36 -15
  406. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  407. package/src/domains/dispatch/gate-topology.ts +289 -0
  408. package/src/domains/dispatch/index.ts +19 -0
  409. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  410. package/src/domains/dispatch/intent.ts +85 -1
  411. package/src/domains/dispatch/joint-route-resolver.ts +1 -1
  412. package/src/domains/dispatch/path-scope.ts +0 -61
  413. package/src/domains/dispatch/placement.ts +2 -2
  414. package/src/domains/dispatch/receipt-findings.ts +1 -1
  415. package/src/domains/dispatch/receipt-integrity.ts +20 -8
  416. package/src/domains/dispatch/reservation-store.ts +24 -27
  417. package/src/domains/dispatch/route-decision.ts +1 -1
  418. package/src/domains/dispatch/route-history.ts +1 -1
  419. package/src/domains/dispatch/route-policy.ts +1 -1
  420. package/src/domains/dispatch/route-readiness.ts +0 -28
  421. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  422. package/src/domains/dispatch/run-event-journal.ts +599 -0
  423. package/src/domains/dispatch/state.ts +45 -1
  424. package/src/domains/dispatch/tool-stats.ts +1 -1
  425. package/src/domains/dispatch/transport.ts +2 -19
  426. package/src/domains/dispatch/types.ts +16 -3
  427. package/src/domains/dispatch/validation.ts +33 -8
  428. package/src/domains/dispatch/worker-protocol.ts +2 -2
  429. package/src/domains/eval/artifacts/store.ts +5 -4
  430. package/src/domains/eval/compare/compare.ts +3 -16
  431. package/src/domains/eval/compare/thresholds.ts +0 -8
  432. package/src/domains/eval/execution-provenance.ts +1 -1
  433. package/src/domains/eval/inventory.ts +113 -0
  434. package/src/domains/eval/metrics/token-stream.ts +0 -7
  435. package/src/domains/eval/report.ts +1 -1
  436. package/src/domains/eval/runner.ts +1 -1
  437. package/src/domains/eval/runners/clio-run.ts +7 -6
  438. package/src/domains/eval/runners/external-command.ts +4 -3
  439. package/src/domains/eval/schema/artifact.ts +1 -1
  440. package/src/domains/eval/schema/behavioral-metrics.ts +3 -2
  441. package/src/domains/eval/schema/behavioral.ts +7 -6
  442. package/src/domains/eval/schema/execution-envelope.ts +4 -2
  443. package/src/domains/eval/schema/naming.ts +10 -0
  444. package/src/domains/eval/schema/serving.ts +31 -0
  445. package/src/domains/eval/schema/suite.ts +2 -2
  446. package/src/domains/eval/schema/validate.ts +9 -5
  447. package/src/domains/eval/schema/verdict.ts +4 -2
  448. package/src/domains/eval/store.ts +12 -2
  449. package/src/domains/eval/suites/run.ts +12 -6
  450. package/src/domains/eval/types.ts +1 -1
  451. package/src/domains/eval/workspaces/git.ts +1 -1
  452. package/src/domains/eval/workspaces/temp-copy.ts +1 -1
  453. package/src/domains/evidence/build.ts +13 -5
  454. package/src/domains/evidence/store.ts +6 -0
  455. package/src/domains/interop/consent.ts +7 -7
  456. package/src/domains/interop/extension.ts +1 -1
  457. package/src/domains/lifecycle/doctor.ts +27 -21
  458. package/src/domains/lifecycle/migrations/2026-09-01-clio-coder-naming.ts +155 -0
  459. package/src/domains/lifecycle/migrations/2026-09-01-retire-panes-knobs.ts +59 -0
  460. package/src/domains/lifecycle/migrations/2026-09-01-settings-v2.ts +338 -0
  461. package/src/domains/lifecycle/migrations/index.ts +20 -1
  462. package/src/domains/lifecycle/naming-history.ts +153 -0
  463. package/src/domains/lifecycle/naming-mutable-state.ts +104 -0
  464. package/src/domains/lifecycle/naming-resources.ts +261 -0
  465. package/src/domains/lifecycle/naming-tool-markers.ts +139 -0
  466. package/src/domains/lifecycle/naming-yazi.ts +81 -0
  467. package/src/domains/lifecycle/upgrade-notice.ts +1 -1
  468. package/src/domains/memory/index.ts +0 -1
  469. package/src/domains/memory/task-memory-handoff.ts +6 -3
  470. package/src/domains/memory/task-memory-policy.ts +6 -10
  471. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  472. package/src/domains/middleware/index.ts +7 -0
  473. package/src/domains/middleware/marketplace-offer.ts +339 -0
  474. package/src/domains/middleware/memory-intervention.ts +33 -21
  475. package/src/domains/middleware/runtime.ts +2 -2
  476. package/src/domains/mux/contract.ts +566 -0
  477. package/src/domains/mux/detect.ts +182 -0
  478. package/src/domains/mux/dock-controller.ts +365 -0
  479. package/src/domains/mux/extension.ts +53 -0
  480. package/src/domains/mux/index.ts +116 -0
  481. package/src/domains/mux/manifest.ts +6 -0
  482. package/src/domains/mux/operations.ts +192 -0
  483. package/src/domains/mux/pane-registry.ts +90 -0
  484. package/src/domains/mux/protocol.ts +62 -0
  485. package/src/domains/mux/socket-client.ts +964 -0
  486. package/src/domains/mux/types.ts +265 -0
  487. package/src/domains/mux/viewer-command.ts +59 -0
  488. package/src/domains/mux/yazi/assets/init.lua +2 -0
  489. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  490. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  491. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  492. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  493. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  494. package/src/domains/mux/yazi/event-stream.ts +182 -0
  495. package/src/domains/mux/yazi/profile.ts +299 -0
  496. package/src/domains/mux/yazi/session.ts +251 -0
  497. package/src/domains/mux/yazi/theme.ts +30 -0
  498. package/src/domains/observability/cost.ts +21 -0
  499. package/src/domains/observability/extension.ts +1 -1
  500. package/src/domains/observability/index.ts +2 -0
  501. package/src/domains/observability/out-of-turn-usage.ts +2 -2
  502. package/src/domains/observability/projection.ts +1 -1
  503. package/src/domains/observability/trace-store.ts +63 -11
  504. package/src/domains/prompts/compiler.ts +2 -2
  505. package/src/domains/prompts/extension.ts +3 -3
  506. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -1
  507. package/src/domains/prompts/fragments/operating/skills.md +25 -18
  508. package/src/domains/providers/endpoint-capacity.ts +154 -22
  509. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  510. package/src/domains/providers/extension.ts +25 -8
  511. package/src/domains/providers/index.ts +22 -0
  512. package/src/domains/providers/knowledge-base-path.ts +1 -1
  513. package/src/domains/providers/model-runtime-capabilities.ts +46 -2
  514. package/src/domains/providers/models/cloud-models/alcf.yaml +1 -1
  515. package/src/domains/providers/models/local-models/{clio-local-coding-targets.yaml → clio-coder-local-coding-targets.yaml} +4 -4
  516. package/src/domains/providers/plugins.ts +1 -1
  517. package/src/domains/providers/resolver.ts +1 -1
  518. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  519. package/src/domains/providers/runtimes/builtins.ts +2 -0
  520. package/src/domains/providers/runtimes/cloud/alcf.ts +4 -4
  521. package/src/domains/providers/runtimes/common/lmstudio-http.ts +1 -5
  522. package/src/domains/providers/runtimes/common/local-synth.ts +3 -3
  523. package/src/domains/providers/runtimes/common/probe-helpers.ts +2 -2
  524. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  525. package/src/domains/providers/runtimes/local-native/lmstudio.ts +2 -9
  526. package/src/domains/providers/runtimes/protocol/litellm.ts +285 -0
  527. package/src/domains/providers/support.ts +1 -0
  528. package/src/domains/providers/target-model-cache.ts +124 -0
  529. package/src/domains/providers/types/knowledge-base.ts +13 -0
  530. package/src/domains/providers/types/local-model-quirks.ts +2 -2
  531. package/src/domains/providers/types/target-descriptor.ts +3 -3
  532. package/src/domains/resources/extension.ts +1 -1
  533. package/src/domains/resources/index.ts +3 -0
  534. package/src/domains/resources/library.ts +6 -6
  535. package/src/domains/resources/prompts/loader.ts +1 -1
  536. package/src/domains/resources/skills/content-hash.ts +7 -6
  537. package/src/domains/resources/skills/evals.ts +1 -1
  538. package/src/domains/resources/skills/install.ts +36 -12
  539. package/src/domains/resources/skills/loader.ts +72 -13
  540. package/src/domains/resources/skills/marketplace.ts +21 -2
  541. package/src/domains/resources/skills/promotion.ts +214 -0
  542. package/src/domains/safety/action-classifier.ts +6 -0
  543. package/src/domains/safety/audit.ts +2 -2
  544. package/src/domains/safety/finish-contract.ts +2 -1
  545. package/src/domains/safety/run-effects.ts +1 -1
  546. package/src/domains/scheduling/extension.ts +4 -4
  547. package/src/domains/session/archive-readers.ts +9 -1
  548. package/src/domains/session/compaction/branch-summary.ts +4 -0
  549. package/src/domains/session/compaction/compact.ts +1 -1
  550. package/src/domains/session/compaction/tokens.ts +4 -0
  551. package/src/domains/session/context-accounting.ts +1 -1
  552. package/src/domains/session/decision-board.ts +1 -1
  553. package/src/domains/session/extension.ts +1 -1
  554. package/src/domains/session/handoff.ts +2 -2
  555. package/src/domains/session/prompt-manifest.ts +0 -5
  556. package/src/domains/session/protected-artifact-journal.ts +12 -6
  557. package/src/domains/session/retry.ts +1 -1
  558. package/src/domains/share/archive.ts +85 -36
  559. package/src/domains/toolchain/archive.ts +175 -0
  560. package/src/domains/toolchain/contract.ts +28 -0
  561. package/src/domains/toolchain/extension.ts +47 -0
  562. package/src/domains/toolchain/index.ts +39 -0
  563. package/src/domains/toolchain/install.ts +327 -0
  564. package/src/domains/toolchain/manifest.ts +8 -0
  565. package/src/domains/toolchain/paths.ts +34 -0
  566. package/src/domains/toolchain/registry.ts +265 -0
  567. package/src/domains/toolchain/remove.ts +218 -0
  568. package/src/domains/toolchain/resolve.ts +182 -0
  569. package/src/domains/toolchain/types.ts +113 -0
  570. package/src/domains/toolchain/version.ts +88 -0
  571. package/src/engine/acp/adapter.ts +3 -3
  572. package/src/engine/acp/event-mapper.ts +3 -3
  573. package/src/engine/acp/server.ts +440 -96
  574. package/src/engine/acp/tool-mediator.ts +2 -2
  575. package/src/engine/acp/types.ts +20 -2
  576. package/src/engine/alcf-oauth.ts +5 -5
  577. package/src/engine/antigravity/subprocess-runtime.ts +2 -2
  578. package/src/engine/api-registry.ts +1 -1
  579. package/src/engine/apis/llamacpp-residency.ts +1 -19
  580. package/src/engine/apis/lmstudio.ts +1 -6
  581. package/src/engine/apis/ollama-native.ts +3 -3
  582. package/src/engine/apis/openai-completions.ts +2 -2
  583. package/src/engine/apis/residency.ts +3 -9
  584. package/src/engine/claude/sdk-module.ts +87 -0
  585. package/src/engine/claude/sdk-runtime.ts +25 -17
  586. package/src/engine/claude/subprocess-runtime.ts +1 -1
  587. package/src/engine/claude/tool-safety.ts +4 -4
  588. package/src/engine/loop-guard.ts +0 -5
  589. package/src/engine/session.ts +14 -7
  590. package/src/engine/tui-primitives.ts +21 -0
  591. package/src/engine/tui.ts +1 -0
  592. package/src/engine/worker-events.ts +6 -6
  593. package/src/engine/worker-runtime.ts +16 -26
  594. package/src/entry/boot-options.ts +2 -0
  595. package/src/entry/orchestrator.ts +207 -90
  596. package/src/entry/panes-activation.ts +31 -0
  597. package/src/entry/with-panes.ts +20 -0
  598. package/src/interactive/application-controller.ts +21 -21
  599. package/src/interactive/bus-notices.ts +2 -2
  600. package/src/interactive/chat-loop.ts +8 -8
  601. package/src/interactive/chat-panel.ts +1 -1
  602. package/src/interactive/clio-editor.ts +105 -1
  603. package/src/interactive/context-activity.ts +8 -6
  604. package/src/interactive/context-meter.ts +3 -6
  605. package/src/interactive/context-overlay.ts +2 -1
  606. package/src/interactive/cost-overlay.ts +3 -1
  607. package/src/interactive/council-grid.ts +3 -5
  608. package/src/interactive/council.ts +11 -0
  609. package/src/interactive/dispatch-board.ts +56 -49
  610. package/src/interactive/editor-bash.ts +21 -0
  611. package/src/interactive/editor-steer.ts +9 -4
  612. package/src/interactive/editor-submit.ts +24 -18
  613. package/src/interactive/external-editor.ts +1 -1
  614. package/src/interactive/file-reference-completion.ts +360 -0
  615. package/src/interactive/footer/dashboard.ts +15 -17
  616. package/src/interactive/footer/notifications.ts +14 -8
  617. package/src/interactive/footer/widgets.ts +2 -44
  618. package/src/interactive/interactive-application.ts +229 -62
  619. package/src/interactive/interactive-event-projection.ts +1 -1
  620. package/src/interactive/interactive-input-runtime.ts +9 -2
  621. package/src/interactive/interactive-presentation.ts +21 -16
  622. package/src/interactive/interactive-shell.ts +2 -2
  623. package/src/interactive/interactive-slash-runtime.ts +99 -23
  624. package/src/interactive/interactive-subscriptions.ts +1 -1
  625. package/src/interactive/interactive-tickers.ts +1 -1
  626. package/src/interactive/keybinding-manager.ts +4 -4
  627. package/src/interactive/layout.ts +1 -1
  628. package/src/interactive/memory-overlay.ts +3 -2
  629. package/src/interactive/modal-marker.ts +151 -0
  630. package/src/interactive/mutation-preview.ts +1 -1
  631. package/src/interactive/mux-bridge.ts +214 -0
  632. package/src/interactive/overlay-frame.ts +62 -14
  633. package/src/interactive/overlay-general-openers.ts +7 -2
  634. package/src/interactive/overlay-key-routing.ts +21 -10
  635. package/src/interactive/overlay-lifecycle.ts +20 -4
  636. package/src/interactive/overlay-model-selectors.ts +43 -6
  637. package/src/interactive/overlay-permission-lifecycle.ts +90 -22
  638. package/src/interactive/overlay-transitions.ts +18 -4
  639. package/src/interactive/overlays/agents.ts +3 -2
  640. package/src/interactive/overlays/ask-user.ts +161 -41
  641. package/src/interactive/overlays/auth-dialog.ts +1 -0
  642. package/src/interactive/overlays/context-reset.ts +29 -4
  643. package/src/interactive/overlays/cwd-fallback.ts +29 -4
  644. package/src/interactive/overlays/decisions.ts +15 -13
  645. package/src/interactive/overlays/extensions.ts +1 -0
  646. package/src/interactive/overlays/fleet-run-approval.ts +4 -3
  647. package/src/interactive/overlays/handoff-review.ts +3 -2
  648. package/src/interactive/overlays/help-reference.ts +2 -0
  649. package/src/interactive/overlays/interop.ts +2 -1
  650. package/src/interactive/overlays/library-install-confirm.ts +2 -1
  651. package/src/interactive/overlays/library-tabs.ts +28 -0
  652. package/src/interactive/overlays/list-overlay.ts +10 -1
  653. package/src/interactive/overlays/message-picker.ts +2 -1
  654. package/src/interactive/overlays/model-scope.ts +86 -0
  655. package/src/interactive/overlays/model-selector.ts +40 -31
  656. package/src/interactive/overlays/prompts.ts +11 -4
  657. package/src/interactive/overlays/session-selector.ts +3 -2
  658. package/src/interactive/overlays/settings-sections.ts +30 -0
  659. package/src/interactive/overlays/settings.ts +849 -268
  660. package/src/interactive/overlays/side-question.ts +3 -2
  661. package/src/interactive/overlays/skills-hub.ts +11 -19
  662. package/src/interactive/overlays/tree-selector.ts +3 -2
  663. package/src/interactive/pane-policy.ts +46 -0
  664. package/src/interactive/panes-runtime.ts +318 -0
  665. package/src/interactive/permission-overlay.ts +2 -2
  666. package/src/interactive/renderers/compaction-summary.ts +29 -0
  667. package/src/interactive/renderers/retry-status.ts +12 -4
  668. package/src/interactive/renderers/tool-execution.ts +4 -4
  669. package/src/interactive/renderers/worker-entry.ts +122 -14
  670. package/src/interactive/session-transcript.ts +3 -3
  671. package/src/interactive/slash-autocomplete.ts +454 -165
  672. package/src/interactive/slash-commands.ts +521 -189
  673. package/src/interactive/slash-spec.ts +160 -17
  674. package/src/interactive/status/controller.ts +2 -2
  675. package/src/interactive/stream-pacing-policy.ts +1 -1
  676. package/src/interactive/tasks-overlay.ts +21 -13
  677. package/src/interactive/terminal-lease.ts +6 -7
  678. package/src/interactive/theme/tokens.ts +3 -14
  679. package/src/interactive/turn-context.ts +58 -13
  680. package/src/interactive/turn-persistence.ts +2 -2
  681. package/src/interactive/turn-prewarm.ts +2 -2
  682. package/src/interactive/turn-runtime.ts +8 -8
  683. package/src/interactive/turn-state.ts +1 -1
  684. package/src/interactive/view/artifacts.ts +120 -9
  685. package/src/interactive/view/view-overlay.ts +14 -10
  686. package/src/interactive/watch-pane.ts +180 -0
  687. package/src/interactive/welcome-dashboard.ts +15 -15
  688. package/src/interactive/worker-progress.ts +11 -5
  689. package/src/interactive/worker-receipts.ts +20 -2
  690. package/src/interactive/worker-stream.ts +6 -4
  691. package/src/interactive/yazi-bridge.ts +451 -0
  692. package/src/tools/ask-user.ts +3 -3
  693. package/src/tools/bash.ts +1 -1
  694. package/src/tools/bootstrap.ts +26 -2
  695. package/src/tools/builtin-tool-catalog.ts +16 -1
  696. package/src/tools/compete-worktrees.ts +108 -17
  697. package/src/tools/context/index.ts +15 -1
  698. package/src/tools/core-bootstrap.ts +2 -1
  699. package/src/tools/dispatch-admission.ts +18 -5
  700. package/src/tools/dispatch-arguments.ts +21 -21
  701. package/src/tools/dispatch-plan.ts +0 -11
  702. package/src/tools/dispatch-run-events.ts +145 -28
  703. package/src/tools/dispatch-runner.ts +40 -13
  704. package/src/tools/dispatch-types.ts +15 -3
  705. package/src/tools/dispatch.ts +2 -2
  706. package/src/tools/executables.ts +17 -14
  707. package/src/tools/find.ts +1 -6
  708. package/src/tools/monitor.ts +4 -4
  709. package/src/tools/observation.ts +54 -4
  710. package/src/tools/observers.ts +0 -33
  711. package/src/tools/panes-surface.ts +38 -0
  712. package/src/tools/panes.ts +112 -0
  713. package/src/tools/policy.ts +10 -1
  714. package/src/tools/presentation.ts +1 -0
  715. package/src/tools/task-worktree.ts +28 -7
  716. package/src/tools/verify/authoring.ts +3 -6
  717. package/src/tools/verify/frontend.ts +1 -1
  718. package/src/tools/web-fetch.ts +1 -1
  719. package/src/worker/entry.ts +4 -3
  720. package/src/worker/protocol.ts +16 -14
  721. package/src/worker/spec-contract.ts +2 -2
  722. package/src/worker/stdin-demux.ts +2 -2
  723. package/dist/chunk-D73KXYPF.js +0 -37
  724. package/dist/chunk-MLOK6ZOS.js +0 -2888
  725. package/dist/chunk-PNY46YEY.js +0 -1581
  726. package/dist/chunk-XDOQXGFO.js +0 -515
  727. package/dist/chunk-YKOFT37S.js +0 -279
  728. package/dist/clio-LT5V7SSZ.js +0 -26
  729. package/dist/configure-2WYWSCSD.js +0 -49
  730. package/dist/doctor-TWBWFK5V.js +0 -165
  731. package/src/engine/apis/degraded-inference.ts +0 -95
  732. /package/skills/meta/{clio-test → clio-coder-test}/references/harness.md +0 -0
  733. /package/skills/meta/{clio-test → clio-coder-test}/references/test-map.md +0 -0
@@ -0,0 +1,964 @@
1
+ /**
2
+ * Newline-delimited JSON client for a herdr server's Unix domain socket.
3
+ *
4
+ * Two connection kinds, because the server treats them differently:
5
+ *
6
+ * 1. One connection per request. herdr's `handle_connection` reads exactly one
7
+ * request line, writes the response, and closes
8
+ * (`src/api/server.rs:172`, verified against herdr 0.7.5 / protocol 17), so
9
+ * a second request written to the same socket dies with EPIPE. Spec 4.3
10
+ * describes a persistent request/response connection with a pending map;
11
+ * that is not what the pinned binary does. Each call still gets a monotonic
12
+ * id and still checks the echoed id, which catches a server answering
13
+ * something other than what was asked. A call with no response inside its
14
+ * budget rejects with {@link MuxRequestTimeout}.
15
+ * 2. One dedicated connection per `events.subscribe` stream. This is one of
16
+ * the two methods that keep a connection open (the other is
17
+ * `pane.graphics.stream`): herdr acknowledges once and then pushes event
18
+ * lines forever.
19
+ *
20
+ * Connect failures back off with a capped exponential delay, so a dead socket
21
+ * is not hammered once per call. After a subscription reconnect the client
22
+ * refetches `session.snapshot` and hands it to the resync handler: herdr's
23
+ * documented pattern is snapshot once and then trust events, and events missed
24
+ * while the socket was down are simply gone.
25
+ *
26
+ * The interactive app never shells out to the `herdr` CLI. CLI wrappers exist
27
+ * for humans, doctor, and scripts.
28
+ *
29
+ * This is the only module in the tree that reads herdr wire shapes. Every
30
+ * public method returns the Clio types from `types.ts`, and unknown fields on a
31
+ * response are ignored, which is herdr's stated forward-compatibility rule.
32
+ */
33
+
34
+ import * as net from "node:net";
35
+ import {
36
+ MuxError,
37
+ type MuxEvent,
38
+ type MuxEventKind,
39
+ type MuxLayoutNode,
40
+ type MuxLayoutTree,
41
+ type MuxLog,
42
+ type MuxNotificationSound,
43
+ type MuxPane,
44
+ type MuxRect,
45
+ type MuxReportableAgentState,
46
+ MuxRequestTimeout,
47
+ type MuxServerInfo,
48
+ type MuxSnapshot,
49
+ type MuxTab,
50
+ type MuxTabGeometry,
51
+ type MuxWorktree,
52
+ type MuxWorktreeSource,
53
+ muxErrorKind,
54
+ } from "./types.js";
55
+
56
+ /** Default per-request budget from spec 4.3. */
57
+ const DEFAULT_REQUEST_TIMEOUT_MS = 5_000;
58
+ /** Connect budget. Detection uses a tighter one; see `detect.ts`. */
59
+ const DEFAULT_CONNECT_TIMEOUT_MS = 2_000;
60
+ const DEFAULT_BACKOFF = { initialDelayMs: 250, maxDelayMs: 5_000, factor: 2 } as const;
61
+ /**
62
+ * A single response line larger than this means the peer is not a herdr server
63
+ * (or is wedged), so the connection is dropped rather than buffered forever.
64
+ */
65
+ const MAX_LINE_BYTES = 8 * 1024 * 1024;
66
+
67
+ export interface MuxBackoffOptions {
68
+ initialDelayMs: number;
69
+ maxDelayMs: number;
70
+ factor: number;
71
+ }
72
+
73
+ export interface MuxClientOptions {
74
+ socketPath: string;
75
+ requestTimeoutMs?: number;
76
+ connectTimeoutMs?: number;
77
+ backoff?: MuxBackoffOptions;
78
+ log?: MuxLog;
79
+ }
80
+
81
+ export interface MuxSubscription {
82
+ close(): void;
83
+ }
84
+
85
+ export interface MuxSplitRequest {
86
+ direction: "right" | "down";
87
+ targetPaneId?: string;
88
+ workspaceId?: string;
89
+ cwd?: string;
90
+ env?: Readonly<Record<string, string>>;
91
+ focus?: boolean;
92
+ ratio?: number;
93
+ }
94
+
95
+ export interface MuxReportAgentRequest {
96
+ paneId: string;
97
+ source: string;
98
+ agent: string;
99
+ state: MuxReportableAgentState;
100
+ message?: string;
101
+ }
102
+
103
+ export interface MuxReportMetadataRequest {
104
+ paneId: string;
105
+ source: string;
106
+ agent?: string;
107
+ title?: string;
108
+ displayAgent?: string;
109
+ tokens?: Readonly<Record<string, string | null>>;
110
+ stateLabels?: Readonly<Record<string, string>>;
111
+ ttlMs?: number;
112
+ }
113
+
114
+ export interface MuxSubscribeOptions {
115
+ /** Called after a dropped stream reconnects, with a freshly taken snapshot. */
116
+ onResync?: (snapshot: MuxSnapshot) => void;
117
+ }
118
+
119
+ export interface MuxNotificationRequest {
120
+ title: string;
121
+ body?: string;
122
+ sound?: MuxNotificationSound;
123
+ }
124
+
125
+ /**
126
+ * What the server did with a toast. `shown: false` is a normal answer: the
127
+ * operator's own herdr config can disable toasts, rate-limit them, or have no
128
+ * foreground client to paint one, and none of those is a Clio failure.
129
+ */
130
+ export interface MuxNotificationResult {
131
+ shown: boolean;
132
+ reason: string;
133
+ }
134
+
135
+ export interface MuxWorktreeListRequest {
136
+ workspaceId?: string;
137
+ cwd?: string;
138
+ }
139
+
140
+ export interface MuxWorktreeCreateRequest extends MuxWorktreeListRequest {
141
+ branch?: string;
142
+ base?: string;
143
+ path?: string;
144
+ label?: string;
145
+ focus?: boolean;
146
+ }
147
+
148
+ export interface MuxWorktreeOpenRequest extends MuxWorktreeListRequest {
149
+ branch?: string;
150
+ path?: string;
151
+ label?: string;
152
+ focus?: boolean;
153
+ }
154
+
155
+ export interface MuxWorktreeListResult {
156
+ source: MuxWorktreeSource;
157
+ worktrees: ReadonlyArray<MuxWorktree>;
158
+ }
159
+
160
+ export interface MuxWorktreeCreatedResult {
161
+ workspaceId: string;
162
+ tab: MuxTab;
163
+ rootPane: MuxPane;
164
+ worktree: MuxWorktree;
165
+ }
166
+
167
+ export interface MuxWorktreeOpenedResult extends MuxWorktreeCreatedResult {
168
+ alreadyOpen: boolean;
169
+ }
170
+
171
+ export interface MuxWorktreeRemovedResult {
172
+ workspaceId: string;
173
+ path: string;
174
+ forced: boolean;
175
+ }
176
+
177
+ /**
178
+ * The domain-facing surface. Phase 1 covers exactly the wire methods spec 4.3
179
+ * lists for this phase, plus `pane.send_text`, `pane.report_agent`,
180
+ * `pane.report_metadata` (see the notes on those methods below).
181
+ */
182
+ export interface MuxClient {
183
+ readonly socketPath: string;
184
+ /** Whether the most recent request reached the server. Requests are one per connection. */
185
+ connected(): boolean;
186
+ /** Protocol/version recorded from the most recent successful ping or snapshot. */
187
+ server(): MuxServerInfo | null;
188
+ /** Most recent `session.snapshot`, including the post-reconnect refetch. */
189
+ cachedSnapshot(): MuxSnapshot | null;
190
+
191
+ ping(options?: { timeoutMs?: number }): Promise<MuxServerInfo>;
192
+ snapshot(): Promise<MuxSnapshot>;
193
+ paneCurrent(callerPaneId?: string): Promise<MuxPane>;
194
+ paneList(workspaceId?: string): Promise<ReadonlyArray<MuxPane>>;
195
+ paneSplit(request: MuxSplitRequest): Promise<MuxPane>;
196
+ /** Set the pane's operator-facing label. Available on herdr protocol 17. */
197
+ paneRename(paneId: string, label: string): Promise<void>;
198
+ paneClose(paneId: string): Promise<void>;
199
+ /**
200
+ * Cell-precise geometry of the tab holding `paneId` (the server's focused
201
+ * pane when omitted): outer area, pane rects, and live split ratios.
202
+ */
203
+ paneLayout(paneId?: string): Promise<MuxTabGeometry>;
204
+ /**
205
+ * Focus a pane. This switches the focused tab as well as the pane (verified
206
+ * on 0.8.2), so it is only ever driven by an explicit "show me" request,
207
+ * never by background bookkeeping.
208
+ */
209
+ paneFocus(paneId: string): Promise<void>;
210
+ /** Zoom a pane. Zooming an unfocused pane steals focus; same rule as paneFocus. */
211
+ paneZoom(paneId: string, mode: "on" | "off" | "toggle"): Promise<{ changed: boolean; focusChanged: boolean }>;
212
+ /** Portable layout tree for a tab, or the tab holding `paneId`. */
213
+ layoutExport(request?: { tabId?: string; paneId?: string }): Promise<MuxLayoutTree>;
214
+ /**
215
+ * Set one split's ratio, addressed by a boolean path from the root split
216
+ * (`false` descends first, `true` second; `[]` is the root). Returns the
217
+ * updated tree.
218
+ */
219
+ layoutSetSplitRatio(request: {
220
+ tabId?: string;
221
+ paneId?: string;
222
+ path: ReadonlyArray<boolean>;
223
+ ratio: number;
224
+ }): Promise<MuxLayoutTree>;
225
+ worktreeList(request?: MuxWorktreeListRequest): Promise<MuxWorktreeListResult>;
226
+ worktreeCreate(request: MuxWorktreeCreateRequest): Promise<MuxWorktreeCreatedResult>;
227
+ worktreeOpen(request: MuxWorktreeOpenRequest): Promise<MuxWorktreeOpenedResult>;
228
+ worktreeRemove(workspaceId: string, options?: { force?: boolean }): Promise<MuxWorktreeRemovedResult>;
229
+ /**
230
+ * Deliver a command line into a pane's shell. herdr has no argv parameter on
231
+ * `pane.split`, so this is the only way an argv utility pane can run what it
232
+ * was asked to run.
233
+ */
234
+ paneSendText(paneId: string, text: string): Promise<void>;
235
+ /** Takes agent authority over a pane. Only ever called on Clio-owned panes and Clio's own pane. */
236
+ paneReportAgent(request: MuxReportAgentRequest): Promise<void>;
237
+ paneReportMetadata(request: MuxReportMetadataRequest): Promise<void>;
238
+ /**
239
+ * Ask the foreground client to paint a toast. Protocol-gated; see
240
+ * `protocol.ts`. The server answers whether it painted one and why not.
241
+ */
242
+ notificationShow(request: MuxNotificationRequest): Promise<MuxNotificationResult>;
243
+ subscribe(
244
+ kinds: ReadonlyArray<MuxEventKind>,
245
+ handler: (event: MuxEvent) => void,
246
+ options?: MuxSubscribeOptions,
247
+ ): Promise<MuxSubscription>;
248
+
249
+ close(): Promise<void>;
250
+ }
251
+
252
+ /** Opens one socket, or rejects with a typed transport error. */
253
+ function connectSocket(socketPath: string, timeoutMs: number): Promise<net.Socket> {
254
+ return new Promise((resolve, reject) => {
255
+ const socket = net.connect({ path: socketPath });
256
+ socket.setNoDelay(true);
257
+ const timer = setTimeout(() => {
258
+ socket.destroy();
259
+ reject(new MuxError("transport", `mux socket connect to ${socketPath} timed out after ${timeoutMs}ms`));
260
+ }, timeoutMs);
261
+ timer.unref?.();
262
+ const settle = (error: Error | null): void => {
263
+ clearTimeout(timer);
264
+ socket.removeListener("connect", onConnect);
265
+ socket.removeListener("error", onError);
266
+ if (error) {
267
+ socket.destroy();
268
+ reject(new MuxError("transport", `mux socket connect to ${socketPath} failed: ${error.message}`));
269
+ return;
270
+ }
271
+ resolve(socket);
272
+ };
273
+ const onConnect = (): void => settle(null);
274
+ const onError = (error: Error): void => settle(error);
275
+ socket.once("connect", onConnect);
276
+ socket.once("error", onError);
277
+ });
278
+ }
279
+
280
+ /**
281
+ * Splits an incoming byte stream into JSON lines.
282
+ *
283
+ * `onOverflow` fires when one line exceeds the sanity cap, which the caller
284
+ * treats as a dead connection rather than growing the buffer without bound.
285
+ */
286
+ function readJsonLines(
287
+ socket: net.Socket,
288
+ onValue: (value: Record<string, unknown>) => void,
289
+ onOverflow: () => void,
290
+ ): void {
291
+ let buffer = "";
292
+ socket.setEncoding("utf8");
293
+ socket.on("data", (chunk: string) => {
294
+ buffer += chunk;
295
+ if (buffer.length > MAX_LINE_BYTES) {
296
+ buffer = "";
297
+ onOverflow();
298
+ return;
299
+ }
300
+ let newline = buffer.indexOf("\n");
301
+ while (newline >= 0) {
302
+ const line = buffer.slice(0, newline).trim();
303
+ buffer = buffer.slice(newline + 1);
304
+ if (line.length > 0) {
305
+ let parsed: unknown;
306
+ try {
307
+ parsed = JSON.parse(line);
308
+ } catch {
309
+ parsed = null;
310
+ }
311
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
312
+ onValue(parsed as Record<string, unknown>);
313
+ }
314
+ }
315
+ newline = buffer.indexOf("\n");
316
+ }
317
+ });
318
+ }
319
+
320
+ function asRecord(value: unknown): Record<string, unknown> | null {
321
+ return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : null;
322
+ }
323
+
324
+ function requireString(source: Record<string, unknown>, key: string, context: string): string {
325
+ const value = source[key];
326
+ if (typeof value !== "string") {
327
+ throw new MuxError("protocol", `mux ${context} response is missing string field ${key}`);
328
+ }
329
+ return value;
330
+ }
331
+
332
+ function optionalString(source: Record<string, unknown>, key: string): string | null {
333
+ const value = source[key];
334
+ return typeof value === "string" ? value : null;
335
+ }
336
+
337
+ function stringMap(value: unknown): Record<string, string> {
338
+ const source = asRecord(value);
339
+ if (!source) return {};
340
+ const out: Record<string, string> = {};
341
+ for (const [key, entry] of Object.entries(source)) {
342
+ if (typeof entry === "string") out[key] = entry;
343
+ }
344
+ return out;
345
+ }
346
+
347
+ const AGENT_STATES = new Set(["idle", "working", "blocked", "done", "unknown"]);
348
+
349
+ function readAgentState(value: unknown): MuxPane["agentState"] {
350
+ return typeof value === "string" && AGENT_STATES.has(value) ? (value as MuxPane["agentState"]) : "unknown";
351
+ }
352
+
353
+ function readPane(value: unknown): MuxPane {
354
+ const source = asRecord(value);
355
+ if (!source) throw new MuxError("protocol", "mux pane response is not an object");
356
+ const revision = source.revision;
357
+ return {
358
+ paneId: requireString(source, "pane_id", "pane"),
359
+ tabId: requireString(source, "tab_id", "pane"),
360
+ workspaceId: requireString(source, "workspace_id", "pane"),
361
+ focused: source.focused === true,
362
+ agentState: readAgentState(source.agent_status),
363
+ revision: typeof revision === "number" ? revision : 0,
364
+ label: optionalString(source, "label"),
365
+ title: optionalString(source, "title"),
366
+ cwd: optionalString(source, "cwd"),
367
+ agent: optionalString(source, "agent"),
368
+ tokens: stringMap(source.tokens),
369
+ };
370
+ }
371
+
372
+ function readTab(value: unknown): MuxTab {
373
+ const source = asRecord(value);
374
+ if (!source) throw new MuxError("protocol", "mux tab response is not an object");
375
+ const number = source.number;
376
+ const paneCount = source.pane_count;
377
+ return {
378
+ tabId: requireString(source, "tab_id", "tab"),
379
+ workspaceId: requireString(source, "workspace_id", "tab"),
380
+ number: typeof number === "number" ? number : 0,
381
+ label: optionalString(source, "label") ?? "",
382
+ focused: source.focused === true,
383
+ paneCount: typeof paneCount === "number" ? paneCount : 0,
384
+ agentState: readAgentState(source.agent_status),
385
+ };
386
+ }
387
+
388
+ function readWorktree(value: unknown): MuxWorktree {
389
+ const source = asRecord(value);
390
+ if (!source) throw new MuxError("protocol", "mux worktree response is not an object");
391
+ return {
392
+ path: requireString(source, "path", "worktree"),
393
+ branch: optionalString(source, "branch"),
394
+ isBare: source.is_bare === true,
395
+ isDetached: source.is_detached === true,
396
+ isPrunable: source.is_prunable === true,
397
+ isLinkedWorktree: source.is_linked_worktree === true,
398
+ openWorkspaceId: optionalString(source, "open_workspace_id"),
399
+ label: optionalString(source, "label") ?? "",
400
+ };
401
+ }
402
+
403
+ function readWorktreeSource(value: unknown): MuxWorktreeSource {
404
+ const source = asRecord(value);
405
+ if (!source) throw new MuxError("protocol", "mux worktree source response is not an object");
406
+ return {
407
+ repoKey: requireString(source, "repo_key", "worktree source"),
408
+ repoName: requireString(source, "repo_name", "worktree source"),
409
+ repoRoot: requireString(source, "repo_root", "worktree source"),
410
+ sourceCheckoutPath: requireString(source, "source_checkout_path", "worktree source"),
411
+ sourceWorkspaceId: optionalString(source, "source_workspace_id"),
412
+ };
413
+ }
414
+
415
+ function readArray(source: Record<string, unknown>, key: string): unknown[] {
416
+ const value = source[key];
417
+ return Array.isArray(value) ? value : [];
418
+ }
419
+
420
+ function readServerInfo(source: Record<string, unknown>): MuxServerInfo {
421
+ const protocol = source.protocol;
422
+ return {
423
+ version: optionalString(source, "version") ?? "",
424
+ protocol: typeof protocol === "number" ? protocol : 0,
425
+ };
426
+ }
427
+
428
+ function readSnapshot(value: unknown): MuxSnapshot {
429
+ const source = asRecord(value);
430
+ if (!source) throw new MuxError("protocol", "mux snapshot response is not an object");
431
+ return {
432
+ server: readServerInfo(source),
433
+ focusedPaneId: optionalString(source, "focused_pane_id"),
434
+ focusedTabId: optionalString(source, "focused_tab_id"),
435
+ focusedWorkspaceId: optionalString(source, "focused_workspace_id"),
436
+ panes: readArray(source, "panes").map(readPane),
437
+ tabs: readArray(source, "tabs").map(readTab),
438
+ };
439
+ }
440
+
441
+ function requireNumber(source: Record<string, unknown>, key: string, context: string): number {
442
+ const value = source[key];
443
+ if (typeof value !== "number") {
444
+ throw new MuxError("protocol", `mux ${context} response is missing number field ${key}`);
445
+ }
446
+ return value;
447
+ }
448
+
449
+ function readRect(value: unknown, context: string): MuxRect {
450
+ const source = asRecord(value);
451
+ if (!source) throw new MuxError("protocol", `mux ${context} rect is not an object`);
452
+ return {
453
+ x: requireNumber(source, "x", context),
454
+ y: requireNumber(source, "y", context),
455
+ width: requireNumber(source, "width", context),
456
+ height: requireNumber(source, "height", context),
457
+ };
458
+ }
459
+
460
+ function readSplitDirection(value: unknown, context: string): "right" | "down" {
461
+ if (value === "right" || value === "down") return value;
462
+ throw new MuxError("protocol", `mux ${context} split direction is not right/down`);
463
+ }
464
+
465
+ /** Parses a `PaneLayoutSnapshot`: the shape `pane.layout` and `layout_updated` both carry. */
466
+ function readTabGeometry(value: unknown): MuxTabGeometry {
467
+ const source = asRecord(value);
468
+ if (!source) throw new MuxError("protocol", "mux layout snapshot is not an object");
469
+ return {
470
+ workspaceId: requireString(source, "workspace_id", "layout"),
471
+ tabId: requireString(source, "tab_id", "layout"),
472
+ zoomed: source.zoomed === true,
473
+ area: readRect(source.area, "layout"),
474
+ focusedPaneId: optionalString(source, "focused_pane_id"),
475
+ panes: readArray(source, "panes").map((entry) => {
476
+ const pane = asRecord(entry);
477
+ if (!pane) throw new MuxError("protocol", "mux layout pane entry is not an object");
478
+ return {
479
+ paneId: requireString(pane, "pane_id", "layout pane"),
480
+ focused: pane.focused === true,
481
+ rect: readRect(pane.rect, "layout pane"),
482
+ };
483
+ }),
484
+ splits: readArray(source, "splits").map((entry) => {
485
+ const split = asRecord(entry);
486
+ if (!split) throw new MuxError("protocol", "mux layout split entry is not an object");
487
+ return {
488
+ direction: readSplitDirection(split.direction, "layout"),
489
+ ratio: requireNumber(split, "ratio", "layout split"),
490
+ rect: readRect(split.rect, "layout split"),
491
+ };
492
+ }),
493
+ };
494
+ }
495
+
496
+ function readLayoutNode(value: unknown): MuxLayoutNode {
497
+ const source = asRecord(value);
498
+ if (!source) throw new MuxError("protocol", "mux layout node is not an object");
499
+ if (source.type === "pane") {
500
+ return { type: "pane", paneId: optionalString(source, "pane_id"), label: optionalString(source, "label") };
501
+ }
502
+ if (source.type === "split") {
503
+ return {
504
+ type: "split",
505
+ direction: readSplitDirection(source.direction, "layout tree"),
506
+ ratio: requireNumber(source, "ratio", "layout tree split"),
507
+ first: readLayoutNode(source.first),
508
+ second: readLayoutNode(source.second),
509
+ };
510
+ }
511
+ throw new MuxError("protocol", "mux layout node has an unknown type");
512
+ }
513
+
514
+ function readLayoutTree(value: unknown): MuxLayoutTree {
515
+ const source = asRecord(value);
516
+ if (!source) throw new MuxError("protocol", "mux layout tree is not an object");
517
+ return {
518
+ workspaceId: requireString(source, "workspace_id", "layout tree"),
519
+ tabId: requireString(source, "tab_id", "layout tree"),
520
+ zoomed: source.zoomed === true,
521
+ focusedPaneId: optionalString(source, "focused_pane_id"),
522
+ root: readLayoutNode(source.root),
523
+ };
524
+ }
525
+
526
+ /** herdr names lifecycle event kinds with underscores on the wire and dots in subscriptions. */
527
+ const PANE_LEAVE_KIND_BY_WIRE: Readonly<Record<string, "pane.closed" | "pane.exited">> = {
528
+ pane_closed: "pane.closed",
529
+ pane_exited: "pane.exited",
530
+ };
531
+
532
+ function readEvent(line: Record<string, unknown>): MuxEvent | null {
533
+ const wireKind = line.event;
534
+ if (typeof wireKind !== "string") return null;
535
+ const data = asRecord(line.data);
536
+ if (!data) return null;
537
+ const leaveKind = PANE_LEAVE_KIND_BY_WIRE[wireKind];
538
+ if (leaveKind) {
539
+ const paneId = data.pane_id;
540
+ const workspaceId = data.workspace_id;
541
+ if (typeof paneId !== "string" || typeof workspaceId !== "string") return null;
542
+ return { kind: leaveKind, paneId, workspaceId };
543
+ }
544
+ if (wireKind === "pane_moved") {
545
+ // The move rewrites the pane id; the payload carries the new pane record
546
+ // plus the id it replaced, and consumers continue from the new one.
547
+ const pane = asRecord(data.pane);
548
+ const previousPaneId = data.previous_pane_id;
549
+ if (!pane || typeof previousPaneId !== "string") return null;
550
+ const paneId = pane.pane_id;
551
+ const tabId = pane.tab_id;
552
+ const workspaceId = pane.workspace_id;
553
+ if (typeof paneId !== "string" || typeof tabId !== "string" || typeof workspaceId !== "string") return null;
554
+ return { kind: "pane.moved", paneId, previousPaneId, tabId, workspaceId };
555
+ }
556
+ if (wireKind === "layout_updated") {
557
+ // The push already carries the full tab geometry, so a consumer never
558
+ // has to answer a layout event with a layout request.
559
+ try {
560
+ return { kind: "layout.updated", geometry: readTabGeometry(data.layout) };
561
+ } catch {
562
+ return null;
563
+ }
564
+ }
565
+ return null;
566
+ }
567
+
568
+ /** Drops undefined entries so an optional field is absent rather than `null` on the wire. */
569
+ function params(entries: Record<string, unknown>): Record<string, unknown> {
570
+ const out: Record<string, unknown> = {};
571
+ for (const [key, value] of Object.entries(entries)) {
572
+ if (value !== undefined) out[key] = value;
573
+ }
574
+ return out;
575
+ }
576
+
577
+ export function createMuxClient(options: MuxClientOptions): MuxClient {
578
+ const socketPath = options.socketPath;
579
+ const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
580
+ const connectTimeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
581
+ const backoff = options.backoff ?? DEFAULT_BACKOFF;
582
+ const log = options.log ?? ((): void => undefined);
583
+
584
+ let disposed = false;
585
+ let nextId = 0;
586
+ let reachable = false;
587
+ let serverInfo: MuxServerInfo | null = null;
588
+ let snapshotCache: MuxSnapshot | null = null;
589
+
590
+ /** Consecutive failed connect attempts. */
591
+ let connectFailures = 0;
592
+ /** Wall clock before which a new connect is refused. */
593
+ let retryAt = 0;
594
+
595
+ const delayFor = (failures: number): number =>
596
+ Math.min(backoff.maxDelayMs, backoff.initialDelayMs * backoff.factor ** Math.max(0, failures - 1));
597
+
598
+ /**
599
+ * One request, one connection.
600
+ *
601
+ * The id counter and the response-id check survive from the pending-map
602
+ * design because they still catch a server answering something other than
603
+ * what was asked, but there is no pending map: a connection carries exactly
604
+ * one outstanding call and is destroyed as soon as it settles.
605
+ */
606
+ const call = async (method: string, callParams: Record<string, unknown>, timeoutMs?: number): Promise<unknown> => {
607
+ if (disposed) throw new MuxError("transport", "mux client is closed");
608
+ const waitMs = retryAt - Date.now();
609
+ if (waitMs > 0) {
610
+ throw new MuxError("transport", `mux socket ${socketPath} is in backoff for another ${waitMs}ms`);
611
+ }
612
+ let socket: net.Socket;
613
+ try {
614
+ socket = await connectSocket(socketPath, connectTimeoutMs);
615
+ } catch (error) {
616
+ connectFailures += 1;
617
+ retryAt = Date.now() + delayFor(connectFailures);
618
+ reachable = false;
619
+ throw error;
620
+ }
621
+ connectFailures = 0;
622
+ retryAt = 0;
623
+ nextId += 1;
624
+ const id = `clio-${nextId}`;
625
+ const budget = timeoutMs ?? requestTimeoutMs;
626
+ try {
627
+ const result = await new Promise<unknown>((resolve, reject) => {
628
+ let settled = false;
629
+ const finish = (settle: () => void): void => {
630
+ if (settled) return;
631
+ settled = true;
632
+ clearTimeout(timer);
633
+ socket.destroy();
634
+ settle();
635
+ };
636
+ const timer = setTimeout(() => finish(() => reject(new MuxRequestTimeout(method, budget))), budget);
637
+ timer.unref?.();
638
+ readJsonLines(
639
+ socket,
640
+ (line) => {
641
+ const responseId = line.id;
642
+ if (typeof responseId !== "string") return;
643
+ const error = asRecord(line.error);
644
+ // herdr answers a request it could not even parse with an empty id,
645
+ // so an empty-id error line on this connection is still ours.
646
+ if (responseId !== id && !(responseId === "" && error)) return;
647
+ if (error) {
648
+ const code = typeof error.code === "string" ? error.code : "unknown";
649
+ const message = typeof error.message === "string" ? error.message : code;
650
+ finish(() => reject(new MuxError(muxErrorKind(code), message, { wireCode: code, method })));
651
+ return;
652
+ }
653
+ finish(() => resolve(line.result));
654
+ },
655
+ () => finish(() => reject(new MuxError("protocol", `mux ${method} response line was oversized`, { method }))),
656
+ );
657
+ socket.on("error", (error: Error) =>
658
+ finish(() => reject(new MuxError("transport", `mux request ${method} failed: ${error.message}`, { method }))),
659
+ );
660
+ socket.on("close", () =>
661
+ finish(() => reject(new MuxError("transport", `mux request ${method} lost its connection`, { method }))),
662
+ );
663
+ socket.write(`${JSON.stringify({ id, method, params: callParams })}\n`, (error) => {
664
+ if (!error) return;
665
+ finish(() =>
666
+ reject(new MuxError("transport", `mux request ${method} failed to write: ${error.message}`, { method })),
667
+ );
668
+ });
669
+ });
670
+ reachable = true;
671
+ return result;
672
+ } catch (error) {
673
+ if (error instanceof MuxError && error.kind === "transport") reachable = false;
674
+ throw error;
675
+ }
676
+ };
677
+
678
+ const callObject = async (
679
+ method: string,
680
+ callParams: Record<string, unknown>,
681
+ timeoutMs?: number,
682
+ ): Promise<Record<string, unknown>> => {
683
+ const result = asRecord(await call(method, callParams, timeoutMs));
684
+ if (!result) throw new MuxError("protocol", `mux ${method} returned a non-object result`, { method });
685
+ return result;
686
+ };
687
+
688
+ const snapshot = async (): Promise<MuxSnapshot> => {
689
+ const result = await callObject("session.snapshot", {});
690
+ const parsed = readSnapshot(result.snapshot);
691
+ snapshotCache = parsed;
692
+ serverInfo = parsed.server;
693
+ return parsed;
694
+ };
695
+
696
+ const subscribe = async (
697
+ kinds: ReadonlyArray<MuxEventKind>,
698
+ handler: (event: MuxEvent) => void,
699
+ subscribeOptions: MuxSubscribeOptions = {},
700
+ ): Promise<MuxSubscription> => {
701
+ let closed = false;
702
+ let socket: net.Socket | null = null;
703
+ let retryTimer: NodeJS.Timeout | null = null;
704
+ let failures = 0;
705
+
706
+ const scheduleReopen = (): void => {
707
+ if (closed || disposed) return;
708
+ failures += 1;
709
+ const delay = delayFor(failures);
710
+ retryTimer = setTimeout(() => {
711
+ retryTimer = null;
712
+ void open(true);
713
+ }, delay);
714
+ retryTimer.unref?.();
715
+ };
716
+
717
+ const open = async (isReconnect: boolean): Promise<void> => {
718
+ if (closed || disposed) return;
719
+ let stream: net.Socket;
720
+ try {
721
+ stream = await connectSocket(socketPath, connectTimeoutMs);
722
+ } catch (error) {
723
+ log("debug", `mux event stream connect failed: ${error instanceof Error ? error.message : String(error)}`);
724
+ scheduleReopen();
725
+ return;
726
+ }
727
+ if (closed || disposed) {
728
+ stream.destroy();
729
+ return;
730
+ }
731
+ socket = stream;
732
+ let acknowledged = false;
733
+ readJsonLines(
734
+ stream,
735
+ (line) => {
736
+ if (!acknowledged && typeof line.id === "string") {
737
+ acknowledged = true;
738
+ failures = 0;
739
+ if (isReconnect) {
740
+ // Events dropped while the socket was down are gone. Take a
741
+ // fresh snapshot and let the caller rebuild from it.
742
+ void snapshot().then(
743
+ (fresh) => subscribeOptions.onResync?.(fresh),
744
+ (error) =>
745
+ log("debug", `mux snapshot re-bootstrap failed: ${error instanceof Error ? error.message : String(error)}`),
746
+ );
747
+ }
748
+ return;
749
+ }
750
+ const event = readEvent(line);
751
+ if (event) handler(event);
752
+ },
753
+ () => stream.destroy(),
754
+ );
755
+ const onGone = (): void => {
756
+ if (socket !== stream) return;
757
+ socket = null;
758
+ stream.destroy();
759
+ scheduleReopen();
760
+ };
761
+ stream.on("error", onGone);
762
+ stream.on("close", onGone);
763
+ stream.write(
764
+ `${JSON.stringify({
765
+ id: `clio-sub-${kinds.join("+")}`,
766
+ method: "events.subscribe",
767
+ params: { subscriptions: kinds.map((kind) => ({ type: kind })) },
768
+ })}\n`,
769
+ );
770
+ };
771
+
772
+ await open(false);
773
+
774
+ return {
775
+ close(): void {
776
+ closed = true;
777
+ if (retryTimer) clearTimeout(retryTimer);
778
+ retryTimer = null;
779
+ socket?.destroy();
780
+ socket = null;
781
+ },
782
+ };
783
+ };
784
+
785
+ return {
786
+ socketPath,
787
+ connected(): boolean {
788
+ return reachable;
789
+ },
790
+ server(): MuxServerInfo | null {
791
+ return serverInfo;
792
+ },
793
+ cachedSnapshot(): MuxSnapshot | null {
794
+ return snapshotCache;
795
+ },
796
+ async ping(pingOptions = {}): Promise<MuxServerInfo> {
797
+ const result = await callObject("ping", {}, pingOptions.timeoutMs);
798
+ const info = readServerInfo(result);
799
+ serverInfo = info;
800
+ return info;
801
+ },
802
+ snapshot,
803
+ async paneCurrent(callerPaneId?: string): Promise<MuxPane> {
804
+ const result = await callObject("pane.current", params({ caller_pane_id: callerPaneId }));
805
+ return readPane(result.pane);
806
+ },
807
+ async paneList(workspaceId?: string): Promise<ReadonlyArray<MuxPane>> {
808
+ const result = await callObject("pane.list", params({ workspace_id: workspaceId }));
809
+ return readArray(result, "panes").map(readPane);
810
+ },
811
+ async paneSplit(request: MuxSplitRequest): Promise<MuxPane> {
812
+ const result = await callObject(
813
+ "pane.split",
814
+ params({
815
+ direction: request.direction,
816
+ target_pane_id: request.targetPaneId,
817
+ workspace_id: request.workspaceId,
818
+ cwd: request.cwd,
819
+ env: request.env,
820
+ focus: request.focus ?? false,
821
+ ratio: request.ratio,
822
+ }),
823
+ );
824
+ return readPane(result.pane);
825
+ },
826
+ async paneRename(paneId: string, label: string): Promise<void> {
827
+ await call("pane.rename", { pane_id: paneId, label });
828
+ },
829
+ async paneClose(paneId: string): Promise<void> {
830
+ await call("pane.close", { pane_id: paneId });
831
+ },
832
+ async paneLayout(paneId?: string): Promise<MuxTabGeometry> {
833
+ const result = await callObject("pane.layout", params({ pane_id: paneId }));
834
+ return readTabGeometry(result.layout);
835
+ },
836
+ async paneFocus(paneId: string): Promise<void> {
837
+ await call("pane.focus", { pane_id: paneId });
838
+ },
839
+ async paneZoom(paneId: string, mode: "on" | "off" | "toggle"): Promise<{ changed: boolean; focusChanged: boolean }> {
840
+ const result = await callObject("pane.zoom", { pane_id: paneId, mode });
841
+ const zoom = asRecord(result.zoom);
842
+ if (!zoom) throw new MuxError("protocol", "mux pane.zoom returned no zoom result");
843
+ return { changed: zoom.changed === true, focusChanged: zoom.focus_changed === true };
844
+ },
845
+ async layoutExport(request = {}): Promise<MuxLayoutTree> {
846
+ const result = await callObject("layout.export", params({ tab_id: request.tabId, pane_id: request.paneId }));
847
+ return readLayoutTree(result.layout);
848
+ },
849
+ async layoutSetSplitRatio(request): Promise<MuxLayoutTree> {
850
+ const result = await callObject(
851
+ "layout.set_split_ratio",
852
+ params({ tab_id: request.tabId, pane_id: request.paneId, path: [...request.path], ratio: request.ratio }),
853
+ );
854
+ return readLayoutTree(result.layout);
855
+ },
856
+ async worktreeList(request = {}): Promise<MuxWorktreeListResult> {
857
+ const result = await callObject("worktree.list", params({ workspace_id: request.workspaceId, cwd: request.cwd }));
858
+ return { source: readWorktreeSource(result.source), worktrees: readArray(result, "worktrees").map(readWorktree) };
859
+ },
860
+ async worktreeCreate(request: MuxWorktreeCreateRequest): Promise<MuxWorktreeCreatedResult> {
861
+ const result = await callObject(
862
+ "worktree.create",
863
+ params({
864
+ workspace_id: request.workspaceId,
865
+ cwd: request.cwd,
866
+ branch: request.branch,
867
+ base: request.base,
868
+ path: request.path,
869
+ label: request.label,
870
+ focus: request.focus ?? false,
871
+ }),
872
+ );
873
+ const workspace = asRecord(result.workspace);
874
+ if (!workspace) throw new MuxError("protocol", "mux worktree.create returned no workspace");
875
+ return {
876
+ workspaceId: requireString(workspace, "workspace_id", "workspace"),
877
+ tab: readTab(result.tab),
878
+ rootPane: readPane(result.root_pane),
879
+ worktree: readWorktree(result.worktree),
880
+ };
881
+ },
882
+ async worktreeOpen(request: MuxWorktreeOpenRequest): Promise<MuxWorktreeOpenedResult> {
883
+ const result = await callObject(
884
+ "worktree.open",
885
+ params({
886
+ workspace_id: request.workspaceId,
887
+ cwd: request.cwd,
888
+ branch: request.branch,
889
+ path: request.path,
890
+ label: request.label,
891
+ focus: request.focus ?? false,
892
+ }),
893
+ );
894
+ const workspace = asRecord(result.workspace);
895
+ if (!workspace) throw new MuxError("protocol", "mux worktree.open returned no workspace");
896
+ return {
897
+ workspaceId: requireString(workspace, "workspace_id", "workspace"),
898
+ tab: readTab(result.tab),
899
+ rootPane: readPane(result.root_pane),
900
+ worktree: readWorktree(result.worktree),
901
+ alreadyOpen: result.already_open === true,
902
+ };
903
+ },
904
+ async worktreeRemove(workspaceId: string, removeOptions = {}): Promise<MuxWorktreeRemovedResult> {
905
+ const result = await callObject("worktree.remove", {
906
+ workspace_id: workspaceId,
907
+ force: removeOptions.force ?? false,
908
+ });
909
+ return {
910
+ workspaceId: requireString(result, "workspace_id", "worktree.remove"),
911
+ path: requireString(result, "path", "worktree.remove"),
912
+ forced: result.forced === true,
913
+ };
914
+ },
915
+ async paneSendText(paneId: string, text: string): Promise<void> {
916
+ await call("pane.send_text", { pane_id: paneId, text });
917
+ },
918
+ async paneReportAgent(request: MuxReportAgentRequest): Promise<void> {
919
+ await call(
920
+ "pane.report_agent",
921
+ params({
922
+ pane_id: request.paneId,
923
+ source: request.source,
924
+ agent: request.agent,
925
+ state: request.state,
926
+ message: request.message,
927
+ }),
928
+ );
929
+ },
930
+ async paneReportMetadata(request: MuxReportMetadataRequest): Promise<void> {
931
+ await call(
932
+ "pane.report_metadata",
933
+ params({
934
+ pane_id: request.paneId,
935
+ source: request.source,
936
+ agent: request.agent,
937
+ title: request.title,
938
+ display_agent: request.displayAgent,
939
+ tokens: request.tokens,
940
+ state_labels: request.stateLabels,
941
+ ttl_ms: request.ttlMs,
942
+ }),
943
+ );
944
+ },
945
+ async notificationShow(request: MuxNotificationRequest): Promise<MuxNotificationResult> {
946
+ const result = await callObject(
947
+ "notification.show",
948
+ params({ title: request.title, body: request.body, sound: request.sound }),
949
+ );
950
+ // `reason` is required on the wire, but a server that grows a new one
951
+ // must not turn a painted toast into a protocol error, so an unreadable
952
+ // reason degrades to the shown flag alone.
953
+ return {
954
+ shown: result.shown === true,
955
+ reason: optionalString(result, "reason") ?? (result.shown === true ? "shown" : "unknown"),
956
+ };
957
+ },
958
+ subscribe,
959
+ async close(): Promise<void> {
960
+ disposed = true;
961
+ reachable = false;
962
+ },
963
+ };
964
+ }