@iowarp/clio-coder 0.4.2 → 0.4.4

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 (523) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/CONTRIBUTING.md +86 -19
  3. package/README.md +35 -6
  4. package/dist/{acp-TMDQZDIG.js → acp-WNAYYF4F.js} +12 -13
  5. package/dist/{agents-5N5NG3XG.js → agents-3OKXHLOI.js} +60 -57
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-Z5CCBXKQ.js → auth-VKNNMGPU.js} +21 -19
  8. package/dist/{builtins-K6TNDT24.js → builtins-WGALA46I.js} +9 -4
  9. package/dist/{chunk-XE3PCIXH.js → chunk-23L32XTI.js} +12 -9
  10. package/dist/{chunk-I64IFBLB.js → chunk-25QBEXRS.js} +18 -11
  11. package/dist/{chunk-CDNVLKUX.js → chunk-26QSH3EJ.js} +13 -7
  12. package/dist/{chunk-QQLGQY2A.js → chunk-2ASED4PZ.js} +22 -22
  13. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  14. package/dist/chunk-2DSOYNFC.js +108 -0
  15. package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
  16. package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
  17. package/dist/{chunk-O3YUNJZ2.js → chunk-2ZSONWVL.js} +82 -25
  18. package/dist/{chunk-2NHR3NAY.js → chunk-36CT5VVL.js} +331 -42
  19. package/dist/{chunk-2X4RYJTJ.js → chunk-3GY4F45V.js} +3 -3
  20. package/dist/{chunk-ZW55JB7N.js → chunk-3ODX73FK.js} +4 -6
  21. package/dist/{chunk-PBP4B7XR.js → chunk-3UNOLWNZ.js} +3 -3
  22. package/dist/{chunk-4JDLP6ZS.js → chunk-3UUXNFEX.js} +14 -10
  23. package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
  24. package/dist/{chunk-ZW4HH5JJ.js → chunk-4M6Z5QVF.js} +6 -6
  25. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  26. package/dist/{chunk-M2DAX4F6.js → chunk-4WR7VSYB.js} +2 -2
  27. package/dist/{chunk-FSP7CMNU.js → chunk-54X7T7DK.js} +61 -6
  28. package/dist/{chunk-54ODD65L.js → chunk-5636DCO5.js} +4 -4
  29. package/dist/chunk-57XXR6DR.js +3763 -0
  30. package/dist/{chunk-3KIPBMUA.js → chunk-5ICU3EUH.js} +2 -2
  31. package/dist/{chunk-77QIVUZB.js → chunk-5MEZN6CB.js} +4 -4
  32. package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
  33. package/dist/{chunk-YJISEZKC.js → chunk-5TUB6SLS.js} +6 -6
  34. package/dist/{chunk-IMXMHHMQ.js → chunk-6OSVSQL5.js} +341 -57
  35. package/dist/{chunk-Q4XWMHX6.js → chunk-6PAZTBPA.js} +14 -2
  36. package/dist/{chunk-FVDGR2ZL.js → chunk-6Q3CYFD3.js} +112 -39
  37. package/dist/{chunk-IDNA72AH.js → chunk-6QOTUPRG.js} +155 -36
  38. package/dist/{chunk-X7IARSHT.js → chunk-6UINWWS6.js} +16 -10
  39. package/dist/{chunk-CYZW7JHJ.js → chunk-72YIHOZQ.js} +9 -9
  40. package/dist/{chunk-IKSLQ4XV.js → chunk-75W7L2E2.js} +752 -861
  41. package/dist/{chunk-CRFOIAX3.js → chunk-7UGL4MB5.js} +6 -6
  42. package/dist/{chunk-HIICAHCJ.js → chunk-AUPNRN7C.js} +2 -2
  43. package/dist/{chunk-7BHIY2MW.js → chunk-BJVFZO5U.js} +8 -50
  44. package/dist/{chunk-B74PXLU7.js → chunk-CUSRQKPU.js} +65 -3
  45. package/dist/chunk-DQOVN6KV.js +386 -0
  46. package/dist/{chunk-E7GT7O5N.js → chunk-DT3LWJOB.js} +7 -4
  47. package/dist/chunk-DXKJURES.js +671 -0
  48. package/dist/{chunk-JBCS7CRR.js → chunk-EL24TAU4.js} +10 -10
  49. package/dist/{chunk-TPEQIQIE.js → chunk-ELWDPP3Y.js} +8 -8
  50. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  51. package/dist/chunk-EXLD33WO.js +381 -0
  52. package/dist/chunk-FEAXX7B6.js +101 -0
  53. package/dist/{chunk-RLYRBIYQ.js → chunk-FFUPXJC4.js} +90 -331
  54. package/dist/{chunk-5PFYMY2V.js → chunk-FTMGRKEF.js} +2 -2
  55. package/dist/{chunk-34BHNEE3.js → chunk-GHS5EBTQ.js} +58 -7
  56. package/dist/{chunk-DYHAXKHD.js → chunk-GWZNEVM2.js} +12 -8
  57. package/dist/chunk-GX5WYQO4.js +59 -0
  58. package/dist/chunk-GYV6VZOC.js +26 -0
  59. package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
  60. package/dist/chunk-I2DWJ4GM.js +390 -0
  61. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  62. package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
  63. package/dist/{chunk-XQRY4DTA.js → chunk-IGLP3ODT.js} +10 -10
  64. package/dist/chunk-IRXAATOX.js +539 -0
  65. package/dist/chunk-IXIY2H4R.js +44 -0
  66. package/dist/{chunk-SSEYRH53.js → chunk-IZXGRF7P.js} +92 -147
  67. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  68. package/dist/{chunk-JWJGP5DQ.js → chunk-JEIYHLOR.js} +7 -7
  69. package/dist/{chunk-F2I26BDK.js → chunk-JQLNNIKT.js} +4 -4
  70. package/dist/{chunk-BYMNWQ7O.js → chunk-JSD46VO2.js} +315 -63
  71. package/dist/{chunk-AK5XEFVZ.js → chunk-JT2RFCC5.js} +64 -14
  72. package/dist/{chunk-MCMZMDAC.js → chunk-K6T2ZAMZ.js} +168 -6
  73. package/dist/{chunk-PGF63K6I.js → chunk-KFV5L5SK.js} +73 -4
  74. package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
  75. package/dist/{chunk-PJX3WQUQ.js → chunk-LLXSDWXS.js} +3 -3
  76. package/dist/{chunk-DZAW46HP.js → chunk-LTIKRKFL.js} +3 -3
  77. package/dist/{chunk-DZEK6CJN.js → chunk-N56KALIC.js} +21 -21
  78. package/dist/{chunk-B7HM5Z7T.js → chunk-NAI6ZFCY.js} +9 -5
  79. package/dist/{chunk-I66ZTYNP.js → chunk-NRO2BJRH.js} +2656 -2213
  80. package/dist/{chunk-ZGNYYXQ6.js → chunk-NXIMQY5W.js} +3 -3
  81. package/dist/{chunk-IKOZFYBN.js → chunk-NXYCB2VD.js} +149 -106
  82. package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
  83. package/dist/{chunk-462T4EGZ.js → chunk-O5CVSAG5.js} +2 -2
  84. package/dist/chunk-ODGTEFFI.js +50 -0
  85. package/dist/{chunk-3F7VUY77.js → chunk-OEJSLEPW.js} +2 -2
  86. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  87. package/dist/{chunk-5KW52TEP.js → chunk-Q4WO54TA.js} +132 -77
  88. package/dist/{chunk-W6NIE6OW.js → chunk-QUFRYSWI.js} +13 -7
  89. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  90. package/dist/chunk-R6Q67RJH.js +134 -0
  91. package/dist/{chunk-W4YEMFBX.js → chunk-RAY4OVGZ.js} +3 -3
  92. package/dist/{chunk-ZNT2M6TG.js → chunk-RQCKCSRL.js} +17 -17
  93. package/dist/{chunk-LJID3DYZ.js → chunk-RXTN6AKH.js} +3 -3
  94. package/dist/{chunk-P75RZCJW.js → chunk-RZDWV63N.js} +3 -3
  95. package/dist/{chunk-UH632ZYL.js → chunk-S6PYF2XF.js} +2 -2
  96. package/dist/{chunk-HJWWJ6IL.js → chunk-TOIVGRUX.js} +17 -5
  97. package/dist/{chunk-HLAFFSEK.js → chunk-TQAHXW6Y.js} +2 -2
  98. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  99. package/dist/{chunk-2HFQNRV3.js → chunk-UEPWCCTY.js} +12 -12
  100. package/dist/chunk-UOIZ7DA4.js +41 -0
  101. package/dist/{chunk-UH347SHR.js → chunk-USR47QNF.js} +11 -11
  102. package/dist/{chunk-AZ4WMN4W.js → chunk-V6HJFQZE.js} +2 -2
  103. package/dist/chunk-V76WTFTW.js +318 -0
  104. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  105. package/dist/{chunk-KPXDY6QF.js → chunk-XRZT5WY5.js} +2 -2
  106. package/dist/{chunk-UBRFI4HS.js → chunk-XULDXHTN.js} +142 -50
  107. package/dist/chunk-XXYSBZIQ.js +283 -0
  108. package/dist/{chunk-HKMD33FO.js → chunk-Y55JBDO5.js} +405 -122
  109. package/dist/{chunk-XOXV5GKE.js → chunk-YD5GIKET.js} +17 -8
  110. package/dist/{chunk-XGDPUNND.js → chunk-YECAMM3D.js} +2 -2
  111. package/dist/{chunk-BO7Y52RY.js → chunk-YNFKXPEC.js} +7 -7
  112. package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
  113. package/dist/{chunk-M2WXEHER.js → chunk-ZA4VCIGV.js} +2 -2
  114. package/dist/cli/index.js +42 -40
  115. package/dist/{clio-7VB377CC.js → clio-QLICPCF5.js} +7 -7
  116. package/dist/{code-nav-YVLCYA7V.js → code-nav-IJR2DBPR.js} +9 -9
  117. package/dist/{components-UBWCQSRW.js → components-2TGAI2RC.js} +5 -6
  118. package/dist/{config-4HVOS65E.js → config-IUA6OYNS.js} +88 -81
  119. package/dist/{configure-PIWO7B24.js → configure-VEPX4NMX.js} +26 -25
  120. package/dist/{context-KQYIWPWT.js → context-2DKHWH2T.js} +60 -45
  121. package/dist/{context-IYEHL3WQ.js → context-4MPR7WKB.js} +78 -69
  122. package/dist/{context-N6ZE3LGJ.js → context-BOYF5EJM.js} +15 -11
  123. package/dist/{context-clear-G4OGZJDS.js → context-clear-S4ZJCQUX.js} +73 -65
  124. package/dist/context-map-COB37XXN.js +505 -0
  125. package/dist/{context-working-set-BWLF6LJP.js → context-working-set-3I3FYX6Y.js} +18 -17
  126. package/dist/detail-A7JAVSIG.js +98 -0
  127. package/dist/{dispatch-runner-2QQAITS3.js → dispatch-runner-RJ5I2F2O.js} +99 -75
  128. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  129. package/dist/{doctor-LHBD36VU.js → doctor-DKICC2SN.js} +71 -48
  130. package/dist/{eval-C45FYRJ6.js → eval-OQOQUDHK.js} +308 -146
  131. package/dist/{eval-inventory-6DEJPLBF.js → eval-inventory-Y6QRFOH5.js} +4 -4
  132. package/dist/{evidence-6SHONYAF.js → evidence-4DQ25GUQ.js} +79 -175
  133. package/dist/evidence-4F5USFKH.js +208 -0
  134. package/dist/{evolve-KRKMV72X.js → evolve-GSS52E5J.js} +71 -67
  135. package/dist/{extensions-KPZ2UHBB.js → extensions-G7MFLYHT.js} +8 -9
  136. package/dist/{fleet-IVTCKDHT.js → fleet-Q37YHHAQ.js} +126 -118
  137. package/dist/{fleet-commands-EDWL3IT7.js → fleet-commands-G7E4N7SM.js} +16 -13
  138. package/dist/{fleet-decisions-YP3YEFGK.js → fleet-decisions-O7M6QBA2.js} +9 -8
  139. package/dist/{fleet-graph-ZFWKHY2M.js → fleet-graph-TOUBW6OW.js} +21 -20
  140. package/dist/{fleet-inspect-FVUNCBML.js → fleet-inspect-SW33JJNI.js} +65 -60
  141. package/dist/{fleet-preflight-UN5XED4R.js → fleet-preflight-CV2655TW.js} +4 -5
  142. package/dist/{fleet-validate-XOWC4HSX.js → fleet-validate-KESZX2YH.js} +25 -24
  143. package/dist/{fleet-verify-UN3SODEL.js → fleet-verify-UQPMTVE3.js} +66 -61
  144. package/dist/{fleet-view-TWHJKCN6.js → fleet-view-MN2VG4MR.js} +65 -60
  145. package/dist/{init-T2QORQ3Y.js → init-PXEXQSBF.js} +90 -82
  146. package/dist/{interop-IN5I2A66.js → interop-ZG5T62U3.js} +12 -13
  147. package/dist/inventory-C26CFDRR.js +101 -0
  148. package/dist/{library-LSCATDLZ.js → library-B2W4N74O.js} +29 -29
  149. package/dist/{memory-HYOKAGGJ.js → memory-YCANYS5A.js} +73 -69
  150. package/dist/{models-2GPMFYCM.js → models-GERTU3YI.js} +51 -47
  151. package/dist/{monitor-E4ASVUJH.js → monitor-CPNIUULB.js} +74 -67
  152. package/dist/{orchestrator-DDMPR3PY.js → orchestrator-J4BSH4WQ.js} +1288 -1606
  153. package/dist/{panes-E3RUXOW5.js → panes-BOHAEGYC.js} +4 -4
  154. package/dist/{panes-IXKLOKA2.js → panes-NXSLDQZ2.js} +10 -11
  155. package/dist/{paths-L7LGY6RN.js → paths-VSUWNC22.js} +6 -7
  156. package/dist/reset-TNWTB5LU.js +343 -0
  157. package/dist/{resources-OTRSN34L.js → resources-4PXNMD5G.js} +29 -22
  158. package/dist/{run-5DEYH5QK.js → run-D6XJ34CN.js} +132 -132
  159. package/dist/{share-IHWTLO3M.js → share-2NWMJJEE.js} +27 -27
  160. package/dist/{skills-IYMXMKW4.js → skills-KR7WON5G.js} +40 -33
  161. package/dist/{skills-eval-DROHSJAR.js → skills-eval-O2ZNOLDS.js} +81 -77
  162. package/dist/{skills-inventory-D7X4L4ZX.js → skills-inventory-ZZOUBK7O.js} +23 -22
  163. package/dist/{slash-commands-QBM7UZ3B.js → slash-commands-ZXPJD64J.js} +47 -37
  164. package/dist/{steer-Z5DO23FJ.js → steer-XA25PSCS.js} +4 -4
  165. package/dist/{support-U7QOWY26.js → support-7EMVWYG2.js} +6 -6
  166. package/dist/{targets-P2FUC4IL.js → targets-OMH2XCSN.js} +50 -49
  167. package/dist/tasks-IPAGMEIX.js +36 -0
  168. package/dist/{terminal-lease-YREJ3JX2.js → terminal-lease-C2J3JYRE.js} +4 -4
  169. package/dist/{tools-5B7RO6MV.js → tools-EFFEAIDP.js} +8 -9
  170. package/dist/{trace-YMGMUM6A.js → trace-FXMXUZUF.js} +7 -7
  171. package/dist/uninstall-HALS6BLF.js +407 -0
  172. package/dist/upgrade-MS72RJEP.js +306 -0
  173. package/dist/{usage-ME5MPXGX.js → usage-NHG6MCJM.js} +162 -108
  174. package/dist/{verifiers-BVZ7IWOO.js → verifiers-7AUNVXDY.js} +155 -22
  175. package/dist/{verify-5K7ZKQFC.js → verify-FWYGPKMR.js} +14 -12
  176. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  177. package/dist/{wiki-generate-F5W5QTYY.js → wiki-generate-743CIGJW.js} +99 -90
  178. package/dist/{with-panes-BYOJCLAM.js → with-panes-BDQEWBRT.js} +10 -10
  179. package/dist/worker/entry.js +72 -68
  180. package/docs/README.md +3 -2
  181. package/docs/architecture/acp.md +17 -0
  182. package/docs/architecture/artifact-placement.md +1 -0
  183. package/docs/architecture/artifact-versions.md +2 -2
  184. package/docs/architecture/context-engine.md +4 -0
  185. package/docs/architecture/dispatch-typed-intent.md +1 -1
  186. package/docs/architecture/evidence-and-memory.md +1 -1
  187. package/docs/architecture/middleware-and-components.md +1 -1
  188. package/docs/architecture/model-catalog.md +21 -10
  189. package/docs/architecture/observability.md +19 -2
  190. package/docs/architecture/prompt-envelope-and-tools.md +17 -5
  191. package/docs/architecture/provider-adapter-cookbook.md +63 -0
  192. package/docs/architecture/safety-model.md +25 -22
  193. package/docs/architecture/tui-design.md +1 -1
  194. package/docs/guide/built-in-agents.md +25 -11
  195. package/docs/guide/commands-and-modes.md +18 -3
  196. package/docs/guide/configuration-and-targets.md +100 -10
  197. package/docs/guide/configuration-reference.md +17 -7
  198. package/docs/guide/environment-variables.md +4 -2
  199. package/docs/guide/installation-and-lifecycle.md +37 -4
  200. package/docs/guide/proactive-memory.md +66 -55
  201. package/docs/guide/skills-marketplace.md +18 -0
  202. package/docs/guide/tool-usage.md +78 -3
  203. package/docs/history/config-knobs-audit.md +2 -2
  204. package/docs/process/development-pipeline.md +40 -2
  205. package/docs/process/eval-runner.md +67 -3
  206. package/docs/process/git-commit-provenance.md +15 -0
  207. package/docs/process/release-cut-checklist.md +207 -0
  208. package/docs/process/scientific-validation.md +18 -17
  209. package/evals/behavioral-machinery-support.ts +1 -0
  210. package/evals/behavioral-machinery.yaml +1 -1
  211. package/evals/behavioral-model.yaml +3 -2
  212. package/package.json +2 -2
  213. package/skills/README.md +7 -5
  214. package/skills/coding/ast-grep/SKILL.md +101 -30
  215. package/skills/coding/ast-grep/evals.md +26 -0
  216. package/skills/coding/coding-standards/SKILL.md +47 -2
  217. package/skills/coding/coding-standards/evals.md +23 -0
  218. package/skills/coding/prototype/SKILL.md +87 -28
  219. package/skills/coding/prototype/evals.md +19 -0
  220. package/skills/coding/tdd/SKILL.md +80 -53
  221. package/skills/coding/tdd/evals.md +20 -0
  222. package/skills/context/context-handoff/SKILL.md +43 -2
  223. package/skills/context/context-handoff/evals.md +44 -0
  224. package/skills/context/context-prime/SKILL.md +45 -15
  225. package/skills/context/context-prime/evals.md +45 -0
  226. package/skills/git/branch-closeout/SKILL.md +132 -0
  227. package/skills/git/branch-closeout/evals.md +133 -0
  228. package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
  229. package/skills/git/file-ticket/SKILL.md +77 -63
  230. package/skills/git/file-ticket/assets/issue-template.md +22 -0
  231. package/skills/git/file-ticket/evals.md +31 -26
  232. package/skills/git/file-ticket/references/issue-discovery.md +49 -0
  233. package/skills/git/fix-issue/SKILL.md +87 -64
  234. package/skills/git/fix-issue/evals.md +35 -31
  235. package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
  236. package/skills/git/resolve-merge-conflicts/SKILL.md +100 -51
  237. package/skills/git/resolve-merge-conflicts/evals.md +52 -25
  238. package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
  239. package/skills/git/ship/SKILL.md +103 -67
  240. package/skills/git/ship/assets/pr-template.md +21 -0
  241. package/skills/git/ship/evals.md +44 -28
  242. package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
  243. package/skills/git/worktree-create/SKILL.md +80 -50
  244. package/skills/git/worktree-create/evals.md +40 -33
  245. package/skills/git/worktree-create/references/worktree-setup.md +62 -66
  246. package/skills/git/worktree-merge/SKILL.md +112 -65
  247. package/skills/git/worktree-merge/evals.md +42 -34
  248. package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
  249. package/skills/planning/archify/SKILL.md +196 -0
  250. package/skills/planning/archify/evals.md +65 -0
  251. package/skills/planning/architecture/SKILL.md +61 -12
  252. package/skills/planning/architecture/evals.md +65 -0
  253. package/skills/planning/backlog/SKILL.md +130 -14
  254. package/skills/planning/backlog/evals.md +142 -0
  255. package/skills/planning/prd/SKILL.md +47 -6
  256. package/skills/planning/prd/evals.md +54 -0
  257. package/skills/planning/product-intent/SKILL.md +57 -2
  258. package/skills/planning/product-intent/evals.md +70 -0
  259. package/skills/planning/tech-spec/SKILL.md +53 -2
  260. package/skills/planning/tech-spec/evals.md +73 -0
  261. package/skills/registry.yaml +58 -50
  262. package/skills/remote.yaml +13 -0
  263. package/skills/research/arxiv-literature/SKILL.md +76 -18
  264. package/skills/research/arxiv-literature/evals.md +50 -0
  265. package/skills/research/experiment-protocol/SKILL.md +20 -1
  266. package/skills/research/experiment-protocol/evals.md +23 -0
  267. package/skills/research/scientific-debugging/SKILL.md +24 -1
  268. package/skills/research/scientific-debugging/evals.md +18 -0
  269. package/skills/research/scientific-modernization/SKILL.md +26 -1
  270. package/skills/research/scientific-modernization/evals.md +27 -0
  271. package/skills/skill-marketplace.json +63 -28
  272. package/skills/workflow/cut-it/SKILL.md +64 -5
  273. package/skills/workflow/cut-it/evals.md +101 -0
  274. package/skills/workflow/design-council/SKILL.md +112 -27
  275. package/skills/workflow/design-council/evals.md +161 -0
  276. package/skills/workflow/grill-me/SKILL.md +85 -10
  277. package/skills/workflow/grill-me/evals.md +153 -0
  278. package/skills/workflow/workflow-distiller/SKILL.md +76 -17
  279. package/skills/workflow/workflow-distiller/evals.md +118 -0
  280. package/src/cli/args.ts +0 -8
  281. package/src/cli/configure-interop.ts +105 -13
  282. package/src/cli/configure-oauth.ts +57 -0
  283. package/src/cli/configure-onboarding.ts +980 -0
  284. package/src/cli/configure-target.ts +594 -0
  285. package/src/cli/configure.ts +1084 -529
  286. package/src/cli/context-map.ts +114 -0
  287. package/src/cli/context.ts +4 -0
  288. package/src/cli/doctor-state-size.ts +1 -12
  289. package/src/cli/doctor-validation-contract.ts +28 -0
  290. package/src/cli/doctor.ts +5 -0
  291. package/src/cli/evidence-detail.ts +1 -75
  292. package/src/cli/evidence-inventory.ts +1 -167
  293. package/src/cli/index.ts +3 -0
  294. package/src/cli/lifecycle-presenter.ts +436 -0
  295. package/src/cli/models.ts +10 -2
  296. package/src/cli/modes/print.ts +5 -1
  297. package/src/cli/reset.ts +228 -106
  298. package/src/cli/run.ts +7 -4
  299. package/src/cli/select.ts +664 -0
  300. package/src/cli/skills.ts +9 -2
  301. package/src/cli/targets.ts +3 -0
  302. package/src/cli/tasks.ts +84 -0
  303. package/src/cli/uninstall.ts +233 -165
  304. package/src/cli/upgrade.ts +210 -150
  305. package/src/cli/usage.ts +92 -27
  306. package/src/cli/validate-model.ts +3 -3
  307. package/src/cli/verifiers.ts +147 -1
  308. package/src/cli/wiki-generate.ts +1 -0
  309. package/src/core/commit-attribution.ts +41 -1
  310. package/src/core/config.ts +56 -0
  311. package/src/core/external-diagnostic.ts +44 -0
  312. package/src/core/gateway-routing.ts +157 -0
  313. package/src/core/git-commit-attribution.ts +46 -3
  314. package/src/core/run-overrides.ts +0 -5
  315. package/src/core/safe-exec.ts +17 -2
  316. package/src/core/skill-activation.ts +92 -2
  317. package/src/core/tool-names.ts +5 -2
  318. package/src/domains/agents/builtins/architect.md +1 -1
  319. package/src/domains/agents/builtins/coder.md +1 -1
  320. package/src/domains/agents/builtins/documenter.md +1 -1
  321. package/src/domains/agents/builtins/git-master.md +1 -1
  322. package/src/domains/agents/builtins/provenance.md +7 -7
  323. package/src/domains/agents/builtins/tester.md +1 -1
  324. package/src/domains/agents/builtins/verifier.md +2 -2
  325. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  326. package/src/domains/agents/builtins/world-knowledge.md +31 -0
  327. package/src/domains/agents/catalog.ts +1 -1
  328. package/src/domains/agents/result-contract.ts +70 -0
  329. package/src/domains/context/extension.ts +31 -7
  330. package/src/domains/context/refresh.ts +3 -0
  331. package/src/domains/context/wiki/frontmatter.ts +5 -2
  332. package/src/domains/context/wiki/generate.ts +6 -0
  333. package/src/domains/context/wiki/map-seed.ts +589 -0
  334. package/src/domains/context/wiki/plan.ts +2 -2
  335. package/src/domains/context/wiki/prompts.ts +43 -0
  336. package/src/domains/dispatch/active-route-planner.ts +4 -0
  337. package/src/domains/dispatch/admission.ts +29 -0
  338. package/src/domains/dispatch/agent-candidates.ts +10 -0
  339. package/src/domains/dispatch/budget-envelope.ts +86 -1
  340. package/src/domains/dispatch/capability-match.ts +1 -0
  341. package/src/domains/dispatch/capacity-lease.ts +17 -0
  342. package/src/domains/dispatch/code-step.ts +11 -4
  343. package/src/domains/dispatch/contract.ts +42 -8
  344. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  345. package/src/domains/dispatch/extension.ts +184 -56
  346. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  347. package/src/domains/dispatch/fleet-run.ts +1 -0
  348. package/src/domains/dispatch/host-verification.ts +114 -13
  349. package/src/domains/dispatch/intent.ts +28 -18
  350. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  351. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  352. package/src/domains/dispatch/reservation-store.ts +5 -3
  353. package/src/domains/dispatch/state.ts +15 -2
  354. package/src/domains/dispatch/types.ts +20 -2
  355. package/src/domains/dispatch/worker-model-metadata.ts +38 -0
  356. package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
  357. package/src/domains/eval/metrics/token-stream.ts +201 -31
  358. package/src/domains/eval/metrics/tracked.ts +40 -4
  359. package/src/domains/eval/runners/clio-run.ts +17 -11
  360. package/src/domains/eval/runners/context-index.ts +2 -7
  361. package/src/domains/eval/runners/context-init.ts +3 -6
  362. package/src/domains/eval/runners/external-command.ts +29 -11
  363. package/src/domains/eval/schema/suite.ts +28 -0
  364. package/src/domains/eval/schema/verdict.ts +2 -2
  365. package/src/domains/eval/suites/resolve.ts +13 -1
  366. package/src/domains/eval/suites/run.ts +24 -3
  367. package/src/domains/evidence/build.ts +102 -15
  368. package/src/domains/evidence/detail.ts +69 -0
  369. package/src/domains/evidence/eval.ts +13 -1
  370. package/src/domains/evidence/finish-contract-map.ts +5 -1
  371. package/src/domains/evidence/inventory.ts +167 -0
  372. package/src/domains/evidence/store.ts +16 -0
  373. package/src/domains/evidence/types.ts +12 -0
  374. package/src/domains/extensions/resources.ts +7 -0
  375. package/src/domains/interop/registry.ts +6 -2
  376. package/src/domains/interop/types.ts +4 -0
  377. package/src/domains/lifecycle/migrations/index.ts +4 -0
  378. package/src/domains/memory/task-memory-policy.ts +70 -26
  379. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  380. package/src/domains/middleware/index.ts +0 -1
  381. package/src/domains/middleware/marketplace-offer.ts +22 -35
  382. package/src/domains/middleware/memory-intervention.ts +127 -32
  383. package/src/domains/middleware/memory-step-endpoint.ts +3 -2
  384. package/src/domains/middleware/runtime.ts +7 -3
  385. package/src/domains/middleware/skills-reminder.ts +31 -2
  386. package/src/domains/mux/detect.ts +3 -6
  387. package/src/domains/observability/accountability.ts +15 -1
  388. package/src/domains/observability/compaction-usage.ts +118 -0
  389. package/src/domains/observability/contract.ts +52 -7
  390. package/src/domains/observability/cost.ts +1 -1
  391. package/src/domains/observability/evidence-index.ts +10 -0
  392. package/src/domains/observability/extension.ts +15 -6
  393. package/src/domains/observability/out-of-turn-usage.ts +52 -21
  394. package/src/domains/observability/projection.ts +394 -45
  395. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  396. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  397. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  398. package/src/domains/providers/contract.ts +4 -1
  399. package/src/domains/providers/extension.ts +40 -9
  400. package/src/domains/providers/model-capabilities.ts +9 -0
  401. package/src/domains/providers/model-discovery.ts +3 -4
  402. package/src/domains/providers/model-runtime-capabilities.ts +15 -5
  403. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +48 -26
  404. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
  405. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  406. package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
  407. package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
  408. package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
  409. package/src/domains/providers/support.ts +11 -5
  410. package/src/domains/providers/target-model-cache.ts +25 -2
  411. package/src/domains/providers/types/capability-flags.ts +2 -0
  412. package/src/domains/providers/types/runtime-descriptor.ts +20 -1
  413. package/src/domains/providers/types/target-descriptor.ts +19 -0
  414. package/src/domains/resources/index.ts +3 -0
  415. package/src/domains/resources/skills/install.ts +72 -7
  416. package/src/domains/resources/skills/loader.ts +7 -0
  417. package/src/domains/resources/skills/marketplace.ts +63 -11
  418. package/src/domains/safety/action-classifier.ts +7 -0
  419. package/src/domains/safety/autonomy.ts +15 -0
  420. package/src/domains/safety/default-path-policy.ts +2 -0
  421. package/src/domains/safety/finish-contract-registration.ts +29 -14
  422. package/src/domains/safety/finish-contract.ts +252 -40
  423. package/src/domains/safety/index.ts +21 -1
  424. package/src/domains/safety/path-policy.ts +1 -1
  425. package/src/domains/safety/policy-engine.ts +60 -17
  426. package/src/domains/safety/protected-artifacts.ts +191 -88
  427. package/src/domains/safety/rigor.ts +53 -39
  428. package/src/domains/safety/run-effects.ts +2 -22
  429. package/src/domains/safety/skill-authority.ts +55 -0
  430. package/src/domains/safety/validation-contract.ts +388 -0
  431. package/src/domains/session/archive-readers.ts +10 -1
  432. package/src/domains/session/compaction/compact.ts +72 -22
  433. package/src/domains/session/decision-board.ts +101 -2
  434. package/src/domains/session/entries.ts +50 -7
  435. package/src/domains/session/extension.ts +4 -4
  436. package/src/domains/session/handoff.ts +2 -1
  437. package/src/domains/session/manager.ts +2 -3
  438. package/src/domains/session/task-board.ts +14 -1
  439. package/src/domains/session/tree/fork.ts +1 -2
  440. package/src/domains/session/tree/navigator.ts +1 -1
  441. package/src/domains/session/usage.ts +3 -3
  442. package/src/domains/user-tasks/acceptance.ts +56 -0
  443. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  444. package/src/domains/user-tasks/store.ts +34 -3
  445. package/src/engine/acp/adapter.ts +24 -6
  446. package/src/engine/acp/server.ts +21 -4
  447. package/src/engine/acp/transport.ts +53 -8
  448. package/src/engine/acp/types.ts +4 -0
  449. package/src/engine/agent.ts +13 -3
  450. package/src/engine/ai.ts +26 -8
  451. package/src/engine/antigravity/subprocess-runtime.ts +386 -120
  452. package/src/engine/api-registry.ts +3 -0
  453. package/src/engine/apis/ollama-native.ts +15 -0
  454. package/src/engine/apis/openai-completions.ts +117 -14
  455. package/src/engine/claude/subprocess-runtime.ts +107 -60
  456. package/src/engine/external-subprocess.ts +122 -6
  457. package/src/entry/background-model-metadata.ts +18 -0
  458. package/src/entry/compaction-prompt.ts +57 -0
  459. package/src/entry/orchestrator.ts +416 -218
  460. package/src/entry/task-memory-lifecycle.ts +35 -0
  461. package/src/interactive/chat-loop-messages.ts +13 -4
  462. package/src/interactive/chat-loop.ts +65 -2
  463. package/src/interactive/chat-renderer.ts +1 -0
  464. package/src/interactive/cost-overlay.ts +26 -2
  465. package/src/interactive/dispatch-board.ts +46 -717
  466. package/src/interactive/fleet-run-preview.ts +2 -1
  467. package/src/interactive/interactive-application.ts +3 -2
  468. package/src/interactive/interactive-presentation.ts +55 -12
  469. package/src/interactive/interactive-slash-runtime.ts +4 -2
  470. package/src/interactive/oracle.ts +5 -2
  471. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  472. package/src/interactive/overlays/message-picker.ts +2 -2
  473. package/src/interactive/overlays/settings.ts +2 -2
  474. package/src/interactive/overlays/tree-selector.ts +2 -2
  475. package/src/interactive/renderers/branch-summary.ts +1 -1
  476. package/src/interactive/renderers/worker-entry.ts +32 -0
  477. package/src/interactive/slash-autocomplete.ts +4 -6
  478. package/src/interactive/slash-commands.ts +49 -45
  479. package/src/interactive/slash-spec.ts +28 -0
  480. package/src/interactive/theme/labels.ts +19 -13
  481. package/src/interactive/turn-context.ts +9 -5
  482. package/src/interactive/turn-recovery.ts +8 -0
  483. package/src/interactive/turn-runtime.ts +27 -11
  484. package/src/interactive/turn-state.ts +7 -0
  485. package/src/interactive/view/artifacts.ts +2 -0
  486. package/src/interactive/worker-receipts.ts +1 -0
  487. package/src/interactive/worker-stream.ts +13 -4
  488. package/src/tools/bootstrap.ts +4 -0
  489. package/src/tools/builtin-tool-catalog.ts +31 -0
  490. package/src/tools/compete-worktrees.ts +7 -1
  491. package/src/tools/context/index.ts +30 -9
  492. package/src/tools/core-bootstrap.ts +16 -0
  493. package/src/tools/decide.ts +136 -0
  494. package/src/tools/dispatch-admission.ts +21 -0
  495. package/src/tools/dispatch-arguments.ts +1 -0
  496. package/src/tools/dispatch-event-text.ts +10 -0
  497. package/src/tools/dispatch-plan.ts +6 -2
  498. package/src/tools/dispatch-runner.ts +27 -1
  499. package/src/tools/dispatch-types.ts +6 -0
  500. package/src/tools/evidence.ts +96 -0
  501. package/src/tools/limitation.ts +76 -0
  502. package/src/tools/policy.ts +9 -0
  503. package/src/tools/presentation.ts +3 -0
  504. package/src/tools/registry.ts +11 -5
  505. package/src/tools/result-shaping.ts +17 -5
  506. package/src/tools/task-worktree.ts +13 -3
  507. package/src/tools/tasks.ts +10 -1
  508. package/src/tools/verify/authoring.ts +170 -83
  509. package/src/tools/verify/catalog.ts +122 -5
  510. package/src/tools/verify/index.ts +2 -1
  511. package/src/tools/verify/numeric.ts +298 -0
  512. package/src/tools/verify/perf.ts +143 -0
  513. package/src/tools/verify/scripts.ts +229 -2
  514. package/src/tools/worker-evidence.ts +3 -1
  515. package/src/worker/spec-contract.ts +4 -0
  516. package/dist/chunk-2Z2IKEXI.js +0 -1554
  517. package/dist/chunk-RVG5JXAL.js +0 -41
  518. package/dist/chunk-T56WDKA5.js +0 -183
  519. package/dist/chunk-VN3SHNBN.js +0 -313
  520. package/dist/chunk-VPKWYKEY.js +0 -169
  521. package/dist/reset-OAQP3W4O.js +0 -230
  522. package/dist/uninstall-N34PCTGJ.js +0 -331
  523. package/dist/upgrade-PXK3S2YM.js +0 -325
@@ -2,32 +2,32 @@ import { spawn } from "node:child_process";
2
2
  import { initializeClioHome } from "../core/init.js";
3
3
  import { clioStateDir } from "../core/xdg.js";
4
4
  import { detectInstallMethod } from "../domains/lifecycle/install-method.js";
5
- import { listMigrations, runPending } from "../domains/lifecycle/migrations/index.js";
5
+ import { listMigrations, readMigrationManifest, runPending } from "../domains/lifecycle/migrations/index.js";
6
6
  import { readStateInfo } from "../domains/lifecycle/state.js";
7
7
  import { getVersionInfo } from "../domains/lifecycle/version.js";
8
- import { printError, printHeader, printOk } from "./shared.js";
8
+ import { createLifecyclePresenter, shortenPath } from "./lifecycle-presenter.js";
9
+ import { printError } from "./shared.js";
9
10
 
10
11
  const CHANNELS = ["latest", "beta", "dev"] as const;
11
12
  type Channel = (typeof CHANNELS)[number];
12
13
 
13
- const HELP = `clio-coder upgrade [--dry-run] [--channel=<latest|beta|dev>] [--skip-migrations]
14
+ const HELP = `clio-coder upgrade [--dry-run] [--channel=<latest|beta|dev>] [--skip-migrations] [--json]
14
15
 
15
- Refresh state metadata and apply pending data-dir migrations. An npm-installed
16
- binary is also reinstalled via npm; a source-checkout install instead prints
16
+ Upgrade Clio Coder and apply pending state migrations. An npm-installed
17
+ binary is reinstalled via npm; a source-checkout install instead prints
17
18
  the git-based update steps and never touches the global npm prefix.
18
19
 
19
20
  Flags:
20
21
  --dry-run print planned actions without changing anything
21
22
  --channel=<chan> npm dist-tag to install (latest|beta|dev). npm installs only.
22
23
  --skip-migrations skip migrations after the install step
24
+ --json emit machine-readable JSON output
25
+ --help, -h show this message
23
26
  `;
24
27
 
25
28
  const SOURCE_UPGRADE_STEPS = ["git pull", "npm run install:local", "hash -r"] as const;
26
-
27
- function printSourceUpgradeSteps(): void {
28
- process.stdout.write("[upgrade] source checkout install: update the code with:\n");
29
- for (const step of SOURCE_UPGRADE_STEPS) process.stdout.write(` ${step}\n`);
30
- }
29
+ /** One wording for the source-update advice. Three paths print it; they used to disagree. */
30
+ const SOURCE_UPGRADE_LEAD = "To update the checkout itself, run:";
31
31
 
32
32
  interface UpgradeOptions {
33
33
  dryRun: boolean;
@@ -35,108 +35,136 @@ interface UpgradeOptions {
35
35
  skipMigrations: boolean;
36
36
  help: boolean;
37
37
  postInstall: boolean;
38
+ json: boolean;
38
39
  }
39
40
 
41
+ /**
42
+ * Positional scan, not `argv.indexOf`. The previous parser looked each token up
43
+ * by value to find its neighbour, so the second `--channel` in a repeated pair
44
+ * read the first one's value, and a value that happened to equal an earlier
45
+ * token was consumed at the wrong index.
46
+ */
40
47
  function parseUpgradeArgs(argv: ReadonlyArray<string>): UpgradeOptions {
41
48
  let dryRun = false;
42
49
  let channel: Channel = "latest";
43
50
  let skipMigrations = false;
44
51
  let help = false;
45
52
  let postInstall = false;
46
- for (const arg of argv) {
47
- if (arg === "upgrade") continue;
48
- if (arg === "--help" || arg === "-h") {
49
- help = true;
50
- continue;
51
- }
52
- if (arg === "--dry-run") {
53
- dryRun = true;
54
- continue;
55
- }
56
- if (arg === "--skip-migrations") {
57
- skipMigrations = true;
58
- continue;
59
- }
60
- if (arg === "--post-install") {
61
- postInstall = true;
62
- continue;
63
- }
64
- if (arg.startsWith("--channel=")) {
65
- const value = arg.slice("--channel=".length);
66
- if (!(CHANNELS as ReadonlyArray<string>).includes(value)) {
67
- throw new Error(`--channel must be one of ${CHANNELS.join("|")}, got '${value}'`);
68
- }
69
- channel = value as Channel;
70
- continue;
53
+ let json = false;
54
+
55
+ const toChannel = (value: string | undefined): Channel => {
56
+ if (value === undefined || !(CHANNELS as ReadonlyArray<string>).includes(value)) {
57
+ throw new Error(`--channel must be one of ${CHANNELS.join("|")}, got '${value ?? ""}'`);
71
58
  }
72
- throw new Error(`unknown upgrade argument: ${arg}`);
59
+ return value as Channel;
60
+ };
61
+
62
+ for (let i = 0; i < argv.length; i += 1) {
63
+ const arg = argv[i];
64
+ if (arg === undefined || arg === "upgrade") continue;
65
+ if (arg === "--help" || arg === "-h") help = true;
66
+ else if (arg === "--dry-run") dryRun = true;
67
+ else if (arg === "--skip-migrations") skipMigrations = true;
68
+ else if (arg === "--post-install") postInstall = true;
69
+ else if (arg === "--json") json = true;
70
+ else if (arg.startsWith("--channel=")) channel = toChannel(arg.slice("--channel=".length));
71
+ else if (arg === "--channel") {
72
+ channel = toChannel(argv[i + 1]);
73
+ i += 1;
74
+ } else throw new Error(`unknown upgrade argument: ${arg}`);
73
75
  }
74
- return { dryRun, channel, skipMigrations, help, postInstall };
76
+ return { dryRun, channel, skipMigrations, help, postInstall, json };
75
77
  }
76
78
 
77
- function streamPrefixed(source: NodeJS.ReadableStream, sink: NodeJS.WritableStream): void {
78
- let buffered = "";
79
- source.on("data", (chunk: Buffer | string) => {
80
- buffered += typeof chunk === "string" ? chunk : chunk.toString("utf8");
81
- let idx = buffered.indexOf("\n");
82
- while (idx !== -1) {
83
- const line = buffered.slice(0, idx);
84
- buffered = buffered.slice(idx + 1);
85
- // A spawned `clio-coder upgrade --post-install` prefixes its own lines;
86
- // wrapping those again printed `[upgrade] [upgrade] ...` for every row.
87
- sink.write(line.startsWith("[upgrade] ") ? `${line}\n` : `[upgrade] ${line}\n`);
88
- idx = buffered.indexOf("\n");
89
- }
90
- });
91
- source.on("end", () => {
92
- if (buffered.length > 0) sink.write(`[upgrade] ${buffered}\n`);
93
- });
79
+ /**
80
+ * What the registry said, and whether it was asked at all.
81
+ *
82
+ * "Not asked" and "asked and could not answer" are different facts, and
83
+ * collapsing both into `null` is what let an offline npm install report itself
84
+ * already current: an unanswered lookup compared nothing, so it cannot conclude
85
+ * the installed version is the newest one.
86
+ */
87
+ type RegistryLookup =
88
+ | { asked: false; reason: "source checkout" | "network checks are disabled" }
89
+ | { asked: true; version: string | null };
90
+
91
+ function testSeam(name: string): string | undefined {
92
+ if (process.env.NODE_ENV !== "test") return undefined;
93
+ return process.env[name];
94
94
  }
95
95
 
96
- async function runNpmInstall(channel: Channel): Promise<void> {
97
- const args = ["install", "-g", `@iowarp/clio-coder@${channel}`];
98
- process.stdout.write(`[upgrade] npm ${args.join(" ")}\n`);
99
- await new Promise<void>((resolve, reject) => {
100
- const child = spawn("npm", args, { stdio: ["ignore", "pipe", "pipe"] });
101
- streamPrefixed(child.stdout, process.stdout);
102
- streamPrefixed(child.stderr, process.stderr);
103
- child.on("error", reject);
104
- child.on("exit", (code) => {
105
- if (code === 0) resolve();
106
- else reject(new Error(`npm exited with code ${code ?? -1}`));
96
+ async function lookUpAvailableVersion(
97
+ channel: Channel,
98
+ method: "source" | "npm",
99
+ noNetwork: boolean,
100
+ ): Promise<RegistryLookup> {
101
+ const seam = testSeam("CLIO_CODER_TEST_UPGRADE_AVAILABLE");
102
+ // `unreachable` stands in for a registry that answered nothing, which is the
103
+ // only way to reach that branch without a network in the test.
104
+ if (seam) return { asked: true, version: seam === "unreachable" ? null : seam };
105
+ if (noNetwork) return { asked: false, reason: "network checks are disabled" };
106
+ if (method === "source") return { asked: false, reason: "source checkout" };
107
+ try {
108
+ const res = await fetch(`https://registry.npmjs.org/@iowarp/clio-coder/${channel}`, {
109
+ headers: { Accept: "application/json" },
110
+ signal: AbortSignal.timeout(2500),
107
111
  });
108
- });
112
+ if (!res.ok) return { asked: true, version: null };
113
+ const data = (await res.json()) as { version?: unknown };
114
+ return { asked: true, version: typeof data.version === "string" ? data.version : null };
115
+ } catch {
116
+ return { asked: true, version: null };
117
+ }
109
118
  }
110
119
 
111
- async function runDoctorFixAfterInstall(): Promise<void> {
112
- const args = ["doctor", "--fix"];
113
- process.stdout.write(`[upgrade] clio-coder ${args.join(" ")}\n`);
120
+ /**
121
+ * Run one child to completion, keeping its last output for the failure message.
122
+ *
123
+ * The pipes have to be drained. `npm install -g` writes well past a 64 KB pipe
124
+ * buffer, and a child whose stdout nobody reads blocks on the write and never
125
+ * exits, so the upgrade hung with no output and no way to tell it apart from a
126
+ * slow registry. Draining also gives the failure something to say beyond an
127
+ * exit code.
128
+ */
129
+ async function runChild(command: string, args: ReadonlyArray<string>, label: string): Promise<void> {
114
130
  await new Promise<void>((resolve, reject) => {
115
- const child = spawn("clio-coder", args, { stdio: ["ignore", "pipe", "pipe"] });
116
- streamPrefixed(child.stdout, process.stdout);
117
- streamPrefixed(child.stderr, process.stderr);
131
+ const child = spawn(command, [...args], { stdio: ["ignore", "pipe", "pipe"] });
132
+ let tail = "";
133
+ const keepTail = (chunk: Buffer): void => {
134
+ tail = `${tail}${chunk.toString("utf8")}`.slice(-2000);
135
+ };
136
+ child.stdout?.on("data", keepTail);
137
+ child.stderr?.on("data", keepTail);
118
138
  child.on("error", reject);
119
- child.on("exit", (code) => {
120
- if (code === 0) resolve();
121
- else reject(new Error(`clio-coder doctor --fix exited with code ${code ?? -1}`));
139
+ child.on("close", (code) => {
140
+ if (code === 0) {
141
+ resolve();
142
+ return;
143
+ }
144
+ const lastLine = tail.trimEnd().split("\n").at(-1) ?? "";
145
+ reject(new Error(`${label} exited with code ${code ?? -1}${lastLine ? `: ${lastLine}` : ""}`));
122
146
  });
123
147
  });
124
148
  }
125
149
 
150
+ async function runNpmInstall(channel: Channel): Promise<void> {
151
+ if (testSeam("CLIO_CODER_TEST_UPGRADE_FAIL") === "npm") {
152
+ throw new Error("npm ERR! 404 Not Found (mock failure)");
153
+ }
154
+ await runChild("npm", ["install", "-g", `@iowarp/clio-coder@${channel}`], "npm install");
155
+ }
156
+
157
+ async function runDoctorFixAfterInstall(): Promise<void> {
158
+ if (testSeam("CLIO_CODER_TEST_UPGRADE_FAIL") === "doctor") {
159
+ throw new Error("mock doctor fix failure");
160
+ }
161
+ await runChild("clio-coder", ["doctor", "--fix"], "clio-coder doctor --fix");
162
+ }
163
+
126
164
  async function runPostInstallUpgrade(opts: UpgradeOptions): Promise<void> {
127
165
  const args = ["upgrade", "--post-install", `--channel=${opts.channel}`];
128
166
  if (opts.skipMigrations) args.push("--skip-migrations");
129
- process.stdout.write(`[upgrade] clio-coder ${args.join(" ")}\n`);
130
- await new Promise<void>((resolve, reject) => {
131
- const child = spawn("clio-coder", args, { stdio: ["ignore", "pipe", "pipe"] });
132
- streamPrefixed(child.stdout, process.stdout);
133
- streamPrefixed(child.stderr, process.stderr);
134
- child.on("error", reject);
135
- child.on("exit", (code) => {
136
- if (code === 0) resolve();
137
- else reject(new Error(`clio-coder upgrade --post-install exited with code ${code ?? -1}`));
138
- });
139
- });
167
+ await runChild("clio-coder", args, "clio-coder upgrade --post-install");
140
168
  }
141
169
 
142
170
  export async function runUpgradeCommand(argv: ReadonlyArray<string>): Promise<number> {
@@ -152,25 +180,36 @@ export async function runUpgradeCommand(argv: ReadonlyArray<string>): Promise<nu
152
180
  return 0;
153
181
  }
154
182
 
183
+ const presenter = createLifecyclePresenter({ json: opts.json });
184
+ presenter.header("Upgrade", "upgrade");
185
+
155
186
  const before = getVersionInfo().clio;
156
187
  const stateDir = clioStateDir();
157
188
  const method = detectInstallMethod();
158
- printHeader("Clio Coder upgrade");
159
- process.stdout.write(`install ${method === "source" ? "source checkout" : "npm"}\n`);
160
- if (method === "npm") process.stdout.write(`channel ${opts.channel}\n`);
161
- process.stdout.write(`current ${before}\n`);
162
- process.stdout.write(`state dir ${stateDir}\n`);
189
+ const methodLabel = method === "source" ? "source checkout" : "npm global";
190
+ presenter.setMethod(methodLabel);
191
+
192
+ const noNetwork = Boolean(testSeam("CLIO_CODER_TEST_UPGRADE_NO_NETWORK"));
193
+ const lookup = await lookUpAvailableVersion(opts.channel, method, noNetwork);
194
+ const availableVersion = lookup.asked ? lookup.version : null;
195
+
196
+ presenter.step(`Installation method: ${methodLabel}`);
197
+ presenter.step(`Current version: ${before}`);
198
+ // A source checkout is not upgraded from the registry, so the registry is
199
+ // never asked. Reporting that as "registry check failed" told the operator a
200
+ // lookup had gone wrong when none was owed.
201
+ if (availableVersion !== null) presenter.step(`Available version: ${availableVersion}`);
202
+ else if (!lookup.asked) presenter.step(`Available version: not checked (${lookup.reason})`);
203
+ else presenter.step("Available version: unknown (the registry could not be reached)");
204
+ if (method === "npm") presenter.step(`Channel: ${opts.channel}`);
205
+ presenter.step(`State dir: ${shortenPath(stateDir)}`);
163
206
 
164
- const noNetwork = Boolean(process.env.CLIO_CODER_TEST_UPGRADE_NO_NETWORK);
165
207
  const migrations = listMigrations();
166
208
  const migrationIds = migrations.map((m) => m.id);
167
- // What the state root says it is on, as distinct from the binary answering.
168
- // After `npm install -g` the two differ until the refresh below, and that
169
- // difference is the upgrade this command reports.
209
+ const appliedIds = new Set(readMigrationManifest(stateDir).applied);
210
+ const pendingMigrationIds = opts.skipMigrations ? [] : migrationIds.filter((id) => !appliedIds.has(id));
211
+
170
212
  const recorded = readStateInfo()?.version ?? null;
171
- // Both the dry run and the real run print this, so it stays in the mood the
172
- // call site sets with "would refresh" or "refreshed". The null branch used to
173
- // bake in "would write it", which a real upgrade printed after writing it.
174
213
  const describeRefresh = (): string =>
175
214
  recorded === null
176
215
  ? "state metadata (none recorded)"
@@ -178,104 +217,125 @@ export async function runUpgradeCommand(argv: ReadonlyArray<string>): Promise<nu
178
217
  ? `state metadata (already ${before})`
179
218
  : `state metadata ${recorded} -> ${before}`;
180
219
 
220
+ // "Already current" is a claim about a version that was compared. A lookup
221
+ // that was made and came back empty has compared nothing, so it does not get
222
+ // to make it: the run falls through and attempts the install, which is what
223
+ // the operator asked for. A lookup that was never owed (a checkout, or the
224
+ // network seam) leaves the recorded state version to decide.
225
+ const versionIsCurrent =
226
+ (lookup.asked ? lookup.version === before : true) && (recorded === null || recorded === before);
227
+ const hasPendingMigrations = pendingMigrationIds.length > 0;
228
+
229
+ if (versionIsCurrent && !hasPendingMigrations) {
230
+ presenter.warn(`Already on ${before}, with no pending migrations. Nothing to do.`);
231
+ if (method === "source") presenter.commandAdvice(SOURCE_UPGRADE_LEAD, SOURCE_UPGRADE_STEPS.join("\n"));
232
+ if (opts.dryRun) presenter.warn("Dry run: no changes made");
233
+ presenter.done("Done");
234
+ return 0;
235
+ }
236
+
181
237
  if (opts.dryRun) {
182
- if (method === "source") {
183
- printSourceUpgradeSteps();
184
- } else {
185
- process.stdout.write(`[upgrade] would run: npm install -g @iowarp/clio-coder@${opts.channel}\n`);
186
- }
187
- if (opts.skipMigrations) {
188
- process.stdout.write("[upgrade] would skip migrations (--skip-migrations)\n");
189
- } else if (migrationIds.length === 0) {
190
- process.stdout.write("[upgrade] no migrations registered; the manifest would be written as is\n");
191
- } else {
192
- process.stdout.write(`[upgrade] would consider ${migrationIds.length} migration(s):\n`);
193
- for (const id of migrationIds) process.stdout.write(` - ${id}\n`);
238
+ if (method === "source") presenter.commandAdvice(SOURCE_UPGRADE_LEAD, SOURCE_UPGRADE_STEPS.join("\n"));
239
+ else presenter.note(`Would run: npm install -g @iowarp/clio-coder@${opts.channel}`);
240
+ if (opts.skipMigrations) presenter.note("Would skip migrations (--skip-migrations).");
241
+ else if (pendingMigrationIds.length === 0) presenter.note("No pending migrations.");
242
+ else {
243
+ presenter.note(
244
+ `Would apply ${pendingMigrationIds.length} pending migration${pendingMigrationIds.length === 1 ? "" : "s"}:`,
245
+ );
246
+ // As substeps, so a --json consumer sees the plan instead of only the
247
+ // three detected facts the old dry run recorded.
248
+ for (const id of pendingMigrationIds) presenter.substep(id, "–");
194
249
  }
195
- process.stdout.write(`[upgrade] would refresh ${describeRefresh()}\n`);
196
- printOk("dry run complete, no changes made");
250
+ presenter.note(`Would refresh ${describeRefresh()}.`);
251
+ presenter.warn("Dry run: no changes made");
252
+ presenter.done("Done");
197
253
  return 0;
198
254
  }
199
255
 
200
256
  if (opts.postInstall) {
201
- process.stdout.write("[upgrade] running post-install checks with the active clio binary\n");
257
+ presenter.note("Running post-install checks with the active clio-coder binary.");
202
258
  } else if (method === "source") {
203
- process.stdout.write("[upgrade] source checkout install detected; skipping npm install\n");
259
+ presenter.note("Source checkout: no npm install to run.");
204
260
  } else if (noNetwork) {
205
- process.stdout.write("[upgrade] CLIO_CODER_TEST_UPGRADE_NO_NETWORK set, skipping npm install\n");
261
+ presenter.note("CLIO_CODER_TEST_UPGRADE_NO_NETWORK is set; skipping npm install.");
206
262
  } else {
207
263
  try {
208
264
  await runNpmInstall(opts.channel);
265
+ presenter.completedStep(`Installed @iowarp/clio-coder@${opts.channel}`);
209
266
  } catch (err) {
210
- printError(err instanceof Error ? err.message : String(err));
267
+ presenter.fail("npm install failed", err instanceof Error ? err.message : String(err));
268
+ presenter.commandAdvice(
269
+ "To upgrade by hand, run:",
270
+ `npm install -g @iowarp/clio-coder@${opts.channel}\nclio-coder doctor --fix`,
271
+ );
272
+ presenter.finish();
211
273
  return 1;
212
274
  }
213
275
  try {
214
276
  await runPostInstallUpgrade(opts);
215
- printOk(`${before} -> post-install checks complete`);
277
+ presenter.done("Done");
216
278
  return 0;
217
279
  } catch (err) {
218
- printError(err instanceof Error ? err.message : String(err));
280
+ presenter.fail("post-install checks failed", err instanceof Error ? err.message : String(err));
281
+ presenter.commandAdvice("To finish the upgrade by hand, run:", "clio-coder doctor --fix");
282
+ presenter.finish();
219
283
  return 1;
220
284
  }
221
285
  }
222
286
 
223
287
  let appliedCount = 0;
224
- let appliedIds: string[] = [];
225
288
  if (opts.skipMigrations) {
226
- process.stdout.write("[upgrade] skipping migrations (--skip-migrations)\n");
289
+ presenter.note("Skipping migrations (--skip-migrations).");
227
290
  } else {
228
- // Migrations run on the state tree directly rather than through the
229
- // lifecycle domain. Loading that domain pulls in `config`, whose start
230
- // runs the strict settings reader, and a settings-repairing migration is
231
- // precisely the one that cannot get past it: `clio-coder upgrade` on a
232
- // home whose settings.yaml names a retired key failed the domain load and
233
- // never reached the migration that removes the key. A runner that needs
234
- // valid config in order to repair invalid config can never run. The
235
- // domain's `runMigrations` is a passthrough to this same function, so
236
- // nothing is lost by calling it where the circularity does not exist.
237
291
  let result: Awaited<ReturnType<typeof runPending>>;
238
292
  try {
293
+ if (testSeam("CLIO_CODER_TEST_UPGRADE_FAIL") === "migration") {
294
+ throw new Error("mock migration failure in 2026-09-01-settings-v2");
295
+ }
239
296
  result = await runPending(stateDir);
240
297
  } catch (err) {
241
- // A migration reports why it could not run, but on its own that reads
242
- // as the whole upgrade being impossible. It is not: the rest of the
243
- // upgrade is independent of it, and naming the flag that runs the rest
244
- // is the difference between a stuck operator and a moved one.
245
- printError(
246
- `migration failed: ${err instanceof Error ? err.message : String(err)}`,
247
- "the rest of the upgrade does not depend on it; run `clio-coder upgrade --skip-migrations` to continue, then fix the cause and re-run `clio-coder upgrade`.",
298
+ presenter.fail("migration failed", err instanceof Error ? err.message : String(err));
299
+ presenter.commandAdvice(
300
+ "The rest of the upgrade does not depend on it. To continue, run:",
301
+ "clio-coder upgrade --skip-migrations",
248
302
  );
303
+ presenter.finish();
249
304
  return 1;
250
305
  }
251
- appliedIds = [...result.applied];
252
- appliedCount = appliedIds.length;
253
- if (appliedCount === 0) {
254
- process.stdout.write("[upgrade] no pending migrations\n");
255
- } else {
256
- for (const id of appliedIds) process.stdout.write(`[upgrade] applied migration ${id}\n`);
257
- }
306
+ const applied = [...result.applied];
307
+ appliedCount = applied.length;
308
+ if (appliedCount === 0) presenter.note("No pending migrations.");
309
+ else for (const id of applied) presenter.completedStep(`Applied migration ${id}`);
258
310
  }
259
311
 
260
312
  if (method === "source" || noNetwork) {
261
313
  const refresh = describeRefresh();
262
314
  initializeClioHome();
263
- process.stdout.write(`[upgrade] refreshed ${refresh}\n`);
315
+ presenter.completedStep(`Refreshed ${refresh}`);
264
316
  } else {
265
317
  try {
266
318
  await runDoctorFixAfterInstall();
319
+ presenter.completedStep("Checked the install with clio-coder doctor --fix");
267
320
  } catch (err) {
268
- printError(err instanceof Error ? err.message : String(err));
321
+ presenter.fail("doctor fix failed", err instanceof Error ? err.message : String(err));
322
+ presenter.commandAdvice("To resolve the findings by hand, run:", "clio-coder doctor --fix");
323
+ presenter.finish();
269
324
  return 1;
270
325
  }
271
326
  }
272
327
 
273
- if (method === "source") printSourceUpgradeSteps();
328
+ if (method === "source") presenter.commandAdvice(SOURCE_UPGRADE_LEAD, SOURCE_UPGRADE_STEPS.join("\n"));
274
329
 
275
- // `before` is the binary that ran; on the post-install and local paths that
276
- // is already the new version, and `0.3.1 -> 0.3.1` was a claim about a
277
- // transition that never happened. The version that moved is the recorded one.
278
330
  const after = getVersionInfo().clio;
279
- printOk(`${recorded ?? before} -> ${after} (migrations: ${appliedCount})`);
331
+ // One closing word on every path, with the outcome above it as steps. The
332
+ // summary used to carry the version arrow, so three exits printed three
333
+ // different shapes of last line.
334
+ if (appliedCount > 0 || (recorded ?? before) !== after) {
335
+ presenter.note(
336
+ `Now on ${after}${appliedCount > 0 ? `, ${appliedCount} migration${appliedCount === 1 ? "" : "s"} applied` : ""}.`,
337
+ );
338
+ }
339
+ presenter.done("Done");
280
340
  return 0;
281
341
  }