@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
package/src/cli/usage.ts CHANGED
@@ -8,6 +8,8 @@ import {
8
8
  } from "../core/response-model-id.js";
9
9
  import { clioDataDir, clioStateDir } from "../core/xdg.js";
10
10
  import { loadMemoryRecordsSync, type MemoryRecord } from "../domains/memory/index.js";
11
+ import { summarizeEvidenceIndex } from "../domains/observability/accountability.js";
12
+ import { summarizeFailedCompactionUsage } from "../domains/observability/compaction-usage.js";
11
13
  import { readEvidenceIndex } from "../domains/observability/evidence-index.js";
12
14
  import { type OutOfTurnUsageRow, readOutOfTurnUsageRows } from "../domains/observability/out-of-turn-usage.js";
13
15
  import { loadSkills } from "../domains/resources/index.js";
@@ -119,18 +121,32 @@ interface CallOrigins {
119
121
  handoffs: number;
120
122
  prewarms: number;
121
123
  backgroundMemory: number;
124
+ failedCompaction: number;
122
125
  }
123
126
 
124
127
  function emptyCallOrigins(): CallOrigins {
125
- return { rows: 0, sideQuestions: 0, handoffs: 0, prewarms: 0, backgroundMemory: 0 };
128
+ return { rows: 0, sideQuestions: 0, handoffs: 0, prewarms: 0, backgroundMemory: 0, failedCompaction: 0 };
126
129
  }
127
130
 
128
131
  function turnsOf(origins: CallOrigins): number {
129
- return origins.rows - origins.sideQuestions - origins.handoffs - origins.prewarms - origins.backgroundMemory;
132
+ return (
133
+ origins.rows -
134
+ origins.sideQuestions -
135
+ origins.handoffs -
136
+ origins.prewarms -
137
+ origins.backgroundMemory -
138
+ origins.failedCompaction
139
+ );
130
140
  }
131
141
 
132
142
  function hasLabelledCall(origins: CallOrigins): boolean {
133
- return origins.sideQuestions > 0 || origins.handoffs > 0 || origins.prewarms > 0 || origins.backgroundMemory > 0;
143
+ return (
144
+ origins.sideQuestions > 0 ||
145
+ origins.handoffs > 0 ||
146
+ origins.prewarms > 0 ||
147
+ origins.backgroundMemory > 0 ||
148
+ origins.failedCompaction > 0
149
+ );
134
150
  }
135
151
 
136
152
  function addOutOfTurnRow(origins: CallOrigins, row: OutOfTurnUsageRow): void {
@@ -138,6 +154,7 @@ function addOutOfTurnRow(origins: CallOrigins, row: OutOfTurnUsageRow): void {
138
154
  if (row.label === "side-question") origins.sideQuestions += 1;
139
155
  else if (row.label === "prewarm") origins.prewarms += 1;
140
156
  else if (row.label === "background-memory") origins.backgroundMemory += 1;
157
+ else if (row.label === "failed-compaction") origins.failedCompaction += 1;
141
158
  else origins.handoffs += 1;
142
159
  }
143
160
 
@@ -148,16 +165,32 @@ function outOfTurnUsageCall(row: OutOfTurnUsageRow): LedgerUsageCall {
148
165
  attributedModelId: row.attributedModelId,
149
166
  requestedModelId: row.attributedModelId,
150
167
  responseModelIdObservation: { state: "not-observed" },
151
- input: row.usage.input,
152
- output: row.usage.output,
153
- cacheRead: row.usage.cacheRead,
154
- cacheWrite: row.usage.cacheWrite,
155
- reasoningTokens: row.usage.reasoning,
156
- totalTokens: row.usage.totalTokens,
157
- costUsd: row.usage.costUsd,
168
+ input: row.usage.input ?? 0,
169
+ output: row.usage.output ?? 0,
170
+ cacheRead: row.usage.cacheRead ?? 0,
171
+ cacheWrite: row.usage.cacheWrite ?? 0,
172
+ reasoningTokens: row.usage.reasoning ?? 0,
173
+ totalTokens: row.usage.totalTokens ?? 0,
174
+ costUsd: row.usage.costUsd ?? 0,
158
175
  };
159
176
  }
160
177
 
178
+ /** Existing numeric accumulators sum known contributions; the report retains missing coverage. */
179
+ function reportedUsageTotals(totals: UsageTotals, rows: ReadonlyArray<OutOfTurnUsageRow>) {
180
+ const failedCompaction = summarizeFailedCompactionUsage(rows);
181
+ if (failedCompaction.calls === 0) return totals;
182
+ const reported: Record<string, unknown> = { ...totals, knownSubtotals: true, failedCompaction };
183
+ for (const [field, missing] of Object.entries(failedCompaction.unobservedUsageCalls)) {
184
+ const key = field === "reasoning" ? "reasoningTokens" : field;
185
+ if (missing > 0 && reported[key] === 0) reported[key] = null;
186
+ }
187
+ return reported;
188
+ }
189
+
190
+ function usageAmount(value: unknown): string {
191
+ return typeof value === "number" ? String(value) : "unknown";
192
+ }
193
+
161
194
  function addUsageCall(totals: UsageTotals, call: LedgerUsageCall): void {
162
195
  totals.apiCalls += call.apiCalls ?? 1;
163
196
  totals.input += call.input;
@@ -326,6 +359,7 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
326
359
  return decision === "blocked" || decision === "denied";
327
360
  });
328
361
  const evidenceRows = readEvidenceIndex(stateDir).filter((row) => inWindow(row.generatedAt, windowStart, now));
362
+ const accountability = summarizeEvidenceIndex(evidenceRows);
329
363
  let memoryRecords: MemoryRecord[] = [];
330
364
  try {
331
365
  memoryRecords = loadMemoryRecordsSync(clioDataDir());
@@ -442,6 +476,8 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
442
476
  // session store is gone can still have recorded out-of-turn spend, and
443
477
  // dropping those rows would report money that was spent as nothing at all.
444
478
  const usageMeasurable = presence.sessionsPresent || outOfTurnRows.length > 0;
479
+ const reportedTotals = reportedUsageTotals(usageTotals, outOfTurnRows);
480
+ const failedCompaction = summarizeFailedCompactionUsage(outOfTurnRows);
445
481
  const usageRows = [...usageByModel.values()].sort(
446
482
  (a, b) => b.totals.totalTokens - a.totals.totalTokens || a.providerId.localeCompare(b.providerId),
447
483
  );
@@ -525,6 +561,8 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
525
561
  else emit({ kind: "fact", fact: "session-store-missing", path: presence.sessionsPath });
526
562
  if (presence.receiptsPresent) emit({ kind: "fact", fact: "dispatch-runs", value: receipts.length });
527
563
  else emit({ kind: "fact", fact: "receipt-store-missing", path: presence.receiptsPath });
564
+ emit({ kind: "fact", fact: "unverified-successes", value: accountability.unverifiedSuccesses });
565
+ emit({ kind: "fact", fact: "ungrounded-claims", value: accountability.ungroundedClaims });
528
566
  emit({ kind: "fact", fact: "audit-tool-calls", value: auditToolCalls.length, blocked: auditBlocked.length });
529
567
  if (usageMeasurable) {
530
568
  // The origin split is emitted only when something out of turn was
@@ -533,7 +571,7 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
533
571
  emit({
534
572
  kind: "fact",
535
573
  fact: "tokens",
536
- ...usageTotals,
574
+ ...reportedTotals,
537
575
  ...(hasLabelledCall(callOrigins)
538
576
  ? {
539
577
  turns: turnsOf(callOrigins),
@@ -541,6 +579,7 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
541
579
  handoffs: callOrigins.handoffs,
542
580
  prewarms: callOrigins.prewarms,
543
581
  backgroundMemorySteps: callOrigins.backgroundMemory,
582
+ ...(callOrigins.failedCompaction > 0 ? { failedCompactionCalls: callOrigins.failedCompaction } : {}),
544
583
  }
545
584
  : {}),
546
585
  });
@@ -552,7 +591,12 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
552
591
  attributedModelId: row.attributedModelId,
553
592
  requestedModelIds: [...row.requestedModelIds].sort(),
554
593
  responseModelIdObservationCounts: row.responseModelIdObservationCounts,
555
- ...row.totals,
594
+ ...reportedUsageTotals(
595
+ row.totals,
596
+ outOfTurnRows.filter(
597
+ (call) => call.target === row.providerId && call.attributedModelId === row.attributedModelId,
598
+ ),
599
+ ),
556
600
  });
557
601
  }
558
602
  for (const session of cacheSessions) {
@@ -615,7 +659,7 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
615
659
  out(` audited tool calls in window: ${auditToolCalls.length} (${auditBlocked.length} blocked/denied)`);
616
660
  if (usageMeasurable) {
617
661
  out(
618
- ` tokens in window: ${usageTotals.totalTokens} over ${usageTotals.apiCalls} model calls (input ${usageTotals.input}, output ${usageTotals.output}, cache read ${usageTotals.cacheRead}, cache write ${usageTotals.cacheWrite}, reasoning ${usageTotals.reasoningTokens})`,
662
+ ` tokens in window: ${usageAmount(reportedTotals.totalTokens)} over ${usageTotals.apiCalls} model calls (input ${usageAmount(reportedTotals.input)}, output ${usageAmount(reportedTotals.output)}, cache read ${usageAmount(reportedTotals.cacheRead)}, cache write ${usageAmount(reportedTotals.cacheWrite)}, reasoning ${usageAmount(reportedTotals.reasoningTokens)})`,
619
663
  );
620
664
  if (hasLabelledCall(callOrigins)) {
621
665
  // Only printed when a labelled call is in the window. Over an archive
@@ -629,7 +673,18 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
629
673
  out(` background memory steps in window: ${callOrigins.backgroundMemory}`);
630
674
  }
631
675
  }
632
- out(` provider-reported cost in window: $${usageTotals.costUsd.toFixed(4)}`);
676
+ if (failedCompaction.calls > 0) {
677
+ out(
678
+ ` failed-compaction streams: ${failedCompaction.calls} (${failedCompaction.erroredCalls} errored, ${failedCompaction.abortedCalls} aborted, ${failedCompaction.successfulCalls} completed before the attempt failed)`,
679
+ );
680
+ out(" usage figures are known subtotals; missing compaction usage is not zero or a complete spending bound");
681
+ out(
682
+ ` errored compaction known cost: ${failedCompaction.erroredKnownUsage.costUsd === null ? "unknown" : `$${failedCompaction.erroredKnownUsage.costUsd.toFixed(4)}`}`,
683
+ );
684
+ }
685
+ out(
686
+ ` ${failedCompaction.calls > 0 ? "known reported/estimated" : "provider-reported"} cost in window: ${typeof reportedTotals.costUsd === "number" ? `$${reportedTotals.costUsd.toFixed(4)}` : "unknown"}`,
687
+ );
633
688
  }
634
689
  if (usageRows.length > 0) {
635
690
  out("");
@@ -650,19 +705,27 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
650
705
  "tokens",
651
706
  "cost",
652
707
  ],
653
- ...usageRows.map((row) => [
654
- row.providerId,
655
- row.attributedModelId,
656
- [...row.requestedModelIds].sort().join(","),
657
- responseModelIdObservationCountsLabel(row.responseModelIdObservationCounts),
658
- String(row.totals.apiCalls),
659
- String(row.totals.input),
660
- String(row.totals.output),
661
- String(row.totals.cacheRead),
662
- String(row.totals.reasoningTokens),
663
- String(row.totals.totalTokens),
664
- `$${row.totals.costUsd.toFixed(4)}`,
665
- ]),
708
+ ...usageRows.map((row) => {
709
+ const reported = reportedUsageTotals(
710
+ row.totals,
711
+ outOfTurnRows.filter(
712
+ (call) => call.target === row.providerId && call.attributedModelId === row.attributedModelId,
713
+ ),
714
+ );
715
+ return [
716
+ row.providerId,
717
+ row.attributedModelId,
718
+ [...row.requestedModelIds].sort().join(","),
719
+ responseModelIdObservationCountsLabel(row.responseModelIdObservationCounts),
720
+ String(row.totals.apiCalls),
721
+ usageAmount(reported.input),
722
+ usageAmount(reported.output),
723
+ usageAmount(reported.cacheRead),
724
+ usageAmount(reported.reasoningTokens),
725
+ usageAmount(reported.totalTokens),
726
+ typeof reported.costUsd === "number" ? `$${reported.costUsd.toFixed(4)}` : "unknown",
727
+ ];
728
+ }),
666
729
  ]),
667
730
  ),
668
731
  );
@@ -747,6 +810,8 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
747
810
  ),
748
811
  );
749
812
  }
813
+ out(` unverified successes: ${accountability.unverifiedSuccesses}`);
814
+ out(` ungrounded claims: ${accountability.ungroundedClaims}`);
750
815
  if (tagCounts.size > 0) {
751
816
  out("");
752
817
  out(" failure tags (from evidence index)");
@@ -15,9 +15,8 @@ export interface ValidateModelInput {
15
15
  modelId: string;
16
16
  knownModels: ReadonlyArray<string>;
17
17
  /**
18
- * The live list, when one was fetched. It is consulted only when the static
19
- * catalog is empty, so the catalog stays the authority for cloud runtimes
20
- * and the probe becomes the authority where there is nothing else.
18
+ * The live list, when one was fetched. Callers provide it only when that
19
+ * runtime declares live discovery authoritative for the concrete target.
21
20
  */
22
21
  live?: LiveModelInventory | undefined;
23
22
  force: boolean;
@@ -50,6 +49,7 @@ function formatUnadvertisedModelReason(modelId: string, live: LiveModelInventory
50
49
 
51
50
  export function validateModelChoice(input: ValidateModelInput): ValidateModelResult {
52
51
  const { runtimeId, modelId, knownModels, live, force } = input;
52
+ if (live !== undefined) return validateAgainstLive(modelId, live, force);
53
53
  if (knownModels.length === 0) return validateAgainstLive(modelId, live, force);
54
54
  if (knownModels.includes(modelId)) return { ok: true };
55
55
  if (force) {
@@ -6,8 +6,15 @@ import {
6
6
  runVerifierAuthoringWorkflow,
7
7
  type VerifierRevision,
8
8
  } from "../tools/verify/authoring.js";
9
- import { loadProjectVerifierCatalog, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH } from "../tools/verify/catalog.js";
9
+ import {
10
+ DECLARED_CHECK_KINDS,
11
+ type DeclaredCheckKind,
12
+ loadProjectVerifierCatalog,
13
+ PROJECT_VERIFIER_CATALOG_RELATIVE_PATH,
14
+ } from "../tools/verify/catalog.js";
10
15
  import { verifyTool } from "../tools/verify/index.js";
16
+ import { normalizeNumericTolerance } from "../tools/verify/numeric.js";
17
+ import { recordPerfBaseline } from "../tools/verify/scripts.js";
11
18
  import { printError, printOk } from "./argv.js";
12
19
  import { runVerifiersInspect } from "./verifiers-inspect.js";
13
20
 
@@ -23,11 +30,22 @@ Usage:
23
30
  clio-coder verifiers edit <id> [--description <text>] [--command <json-argv>] [fields] [--yes]
24
31
  clio-coder verifiers rename <old> <new> [--yes]
25
32
  clio-coder verifiers remove <id> [--yes]
33
+ clio-coder verifiers baseline <id>
26
34
 
27
35
  Fields:
28
36
  --cwd <path> repository-relative working directory (default .)
29
37
  --timeout-ms <number> bounded timeout in milliseconds (default 120000)
30
38
  --tags <a,b> comma-separated catalog tags
39
+ --kind <kind> command (default), numeric-compare, or perf-budget
40
+ --reference <path> numeric-compare: repository-relative reference JSON of string -> number | number[]
41
+ --tolerance <json> numeric-compare: {"relative"?,"absolute"?,"ulp"?}, at least one;
42
+ perf-budget with --baseline: {"relative"} headroom over the baseline
43
+ --budget-ms <number> perf-budget: wall-time bound in milliseconds
44
+ --budget-relative <r> perf-budget with --budget-ms: fractional headroom over the bound
45
+ --baseline <path> perf-budget: repository-relative baseline JSON written by 'verifiers baseline <id>'
46
+
47
+ baseline runs a perf-budget check once and records its wall time at the check's
48
+ baseline path; a failing or timed-out command records nothing.
31
49
 
32
50
  Discovery and every preview are read-only. Mutating commands write only with
33
51
  --yes after printing the exact argv, cwd, timeout, tags, source provenance, and
@@ -48,6 +66,12 @@ const VALUE_OPTIONS = new Set([
48
66
  "--exclude",
49
67
  "--rename",
50
68
  "--dry-run",
69
+ "--kind",
70
+ "--reference",
71
+ "--tolerance",
72
+ "--budget-ms",
73
+ "--budget-relative",
74
+ "--baseline",
51
75
  ]);
52
76
 
53
77
  interface ParsedAuthoringArgs {
@@ -124,6 +148,93 @@ function tags(value: string | undefined): string[] {
124
148
  .filter((tag) => tag.length > 0);
125
149
  }
126
150
 
151
+ type KindFields = Pick<Extract<VerifierRevision, { kind: "add" }>["check"], "kind" | "numeric" | "perf">;
152
+
153
+ function parseJsonObject(value: string, option: string): Record<string, unknown> | Error {
154
+ try {
155
+ const parsed = JSON.parse(value) as unknown;
156
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
157
+ return new Error(`${option} must be a JSON object`);
158
+ }
159
+ return parsed as Record<string, unknown>;
160
+ } catch (error) {
161
+ return new Error(`${option} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * The kind and its parameters from the option set. Returns `{}` when no kind
167
+ * option was given so a plain command check keeps the version-1 shape, and an
168
+ * Error when the options disagree with the kind the way the catalog parser
169
+ * would refuse them, so the operator reads one message here instead of a
170
+ * rejected preview.
171
+ */
172
+ function kindFieldsFromArgs(parsed: ParsedAuthoringArgs): KindFields | Error {
173
+ const kindValue = oneValue(parsed, "--kind") ?? "command";
174
+ if (!(DECLARED_CHECK_KINDS as ReadonlyArray<string>).includes(kindValue)) {
175
+ return new Error(`--kind must be one of ${DECLARED_CHECK_KINDS.join(", ")}`);
176
+ }
177
+ const kind = kindValue as DeclaredCheckKind;
178
+ const reference = oneValue(parsed, "--reference");
179
+ const toleranceValue = oneValue(parsed, "--tolerance");
180
+ const budgetMs = oneValue(parsed, "--budget-ms");
181
+ const budgetRelative = oneValue(parsed, "--budget-relative");
182
+ const baseline = oneValue(parsed, "--baseline");
183
+ if (kind === "command") {
184
+ const stray = [
185
+ ["--reference", reference],
186
+ ["--tolerance", toleranceValue],
187
+ ["--budget-ms", budgetMs],
188
+ ["--budget-relative", budgetRelative],
189
+ ["--baseline", baseline],
190
+ ].filter(([, value]) => value !== undefined);
191
+ if (stray.length > 0)
192
+ return new Error(`${stray.map(([name]) => name).join(", ")} require --kind numeric-compare or perf-budget`);
193
+ return {};
194
+ }
195
+ if (kind === "numeric-compare") {
196
+ if (budgetMs !== undefined || budgetRelative !== undefined || baseline !== undefined) {
197
+ return new Error("--budget-ms, --budget-relative, and --baseline belong to --kind perf-budget");
198
+ }
199
+ if (reference === undefined) return new Error("--reference is required for --kind numeric-compare");
200
+ if (toleranceValue === undefined) return new Error("--tolerance is required for --kind numeric-compare");
201
+ const toleranceJson = parseJsonObject(toleranceValue, "--tolerance");
202
+ if (toleranceJson instanceof Error) return toleranceJson;
203
+ const tolerance = normalizeNumericTolerance(toleranceJson);
204
+ if (tolerance instanceof Error) return new Error(`--tolerance ${tolerance.message}`);
205
+ return { kind, numeric: { reference, tolerance } };
206
+ }
207
+ if (reference !== undefined) return new Error("--reference belongs to --kind numeric-compare");
208
+ if ((budgetMs === undefined) === (baseline === undefined)) {
209
+ return new Error("--kind perf-budget requires exactly one of --budget-ms or --baseline");
210
+ }
211
+ if (budgetMs !== undefined) {
212
+ if (toleranceValue !== undefined) return new Error("use --budget-relative for headroom over --budget-ms");
213
+ const wallTimeMs = Number(budgetMs);
214
+ if (!Number.isFinite(wallTimeMs) || wallTimeMs <= 0) return new Error("--budget-ms must be a positive number");
215
+ const budget: NonNullable<KindFields["perf"]>["budget"] = { wallTimeMs };
216
+ if (budgetRelative !== undefined) {
217
+ const relative = Number(budgetRelative);
218
+ if (!Number.isFinite(relative) || relative < 0) return new Error("--budget-relative must be a non-negative number");
219
+ budget.tolerance = { relative };
220
+ }
221
+ return { kind, perf: { budget } };
222
+ }
223
+ if (budgetRelative !== undefined)
224
+ return new Error("--budget-relative belongs with --budget-ms; use --tolerance with --baseline");
225
+ const perf: NonNullable<KindFields["perf"]> = { baseline: baseline as string };
226
+ if (toleranceValue !== undefined) {
227
+ const toleranceJson = parseJsonObject(toleranceValue, "--tolerance");
228
+ if (toleranceJson instanceof Error) return toleranceJson;
229
+ const relative = toleranceJson.relative;
230
+ if (typeof relative !== "number" || !Number.isFinite(relative) || relative < 0) {
231
+ return new Error('--tolerance for a baseline must be {"relative": <non-negative number>}');
232
+ }
233
+ perf.tolerance = { relative };
234
+ }
235
+ return { kind, perf };
236
+ }
237
+
127
238
  function requiredValue(parsed: ParsedAuthoringArgs, option: string): string | Error {
128
239
  const value = oneValue(parsed, option);
129
240
  return value === undefined || value.length === 0 ? new Error(`${option} is required`) : value;
@@ -151,6 +262,8 @@ function addRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
151
262
  if (command instanceof Error) return command;
152
263
  const timeoutMs = parseTimeout(oneValue(parsed, "--timeout-ms"));
153
264
  if (timeoutMs instanceof Error) return timeoutMs;
265
+ const kindFields = kindFieldsFromArgs(parsed);
266
+ if (kindFields instanceof Error) return kindFields;
154
267
  return {
155
268
  kind: "add",
156
269
  check: {
@@ -160,6 +273,7 @@ function addRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
160
273
  cwd: oneValue(parsed, "--cwd") ?? ".",
161
274
  timeoutMs,
162
275
  tags: tags(oneValue(parsed, "--tags")),
276
+ ...kindFields,
163
277
  },
164
278
  };
165
279
  }
@@ -186,6 +300,13 @@ function editRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
186
300
  }
187
301
  const tagValue = oneValue(parsed, "--tags");
188
302
  if (tagValue !== undefined) changes.tags = tags(tagValue);
303
+ if (oneValue(parsed, "--kind") !== undefined) {
304
+ const kindFields = kindFieldsFromArgs(parsed);
305
+ if (kindFields instanceof Error) return kindFields;
306
+ changes.kind = kindFields.kind ?? "command";
307
+ if (kindFields.numeric !== undefined) changes.numeric = kindFields.numeric;
308
+ if (kindFields.perf !== undefined) changes.perf = kindFields.perf;
309
+ }
189
310
  if (Object.keys(changes).length === 0) return new Error("edit requires at least one changed field");
190
311
  return { kind: "edit", id, changes };
191
312
  }
@@ -260,6 +381,30 @@ async function executeWorkflow(
260
381
  return code;
261
382
  }
262
383
 
384
+ async function baselineCommand(id: string | undefined): Promise<number> {
385
+ if (id === undefined) {
386
+ printError("baseline requires a check ID");
387
+ return 2;
388
+ }
389
+ const loaded = loadProjectVerifierCatalog(process.cwd());
390
+ if (!loaded.ok) {
391
+ printError(`production catalog parser rejected ${loaded.reason}`);
392
+ return 1;
393
+ }
394
+ const check = loaded.source?.checks.find((candidate) => candidate.id === id);
395
+ if (check === undefined) {
396
+ printError(`no catalog check '${id}' in ${PROJECT_VERIFIER_CATALOG_RELATIVE_PATH}`);
397
+ return 1;
398
+ }
399
+ const recorded = await recordPerfBaseline(check);
400
+ if (!recorded.ok) {
401
+ printError(`baseline '${id}' not recorded: ${recorded.message}`);
402
+ return 1;
403
+ }
404
+ printOk(`recorded baseline for '${id}': ${Math.round(recorded.wallTimeMs)}ms at ${recorded.path}`);
405
+ return 0;
406
+ }
407
+
263
408
  async function discoverCommand(): Promise<number> {
264
409
  const discovery = discoverVerifierAuthoring();
265
410
  if (!discovery.ok) {
@@ -304,6 +449,7 @@ export async function runVerifiersCommand(argv: string[]): Promise<number> {
304
449
  const command = parsed.positional[0];
305
450
  if (command === "discover") return discoverCommand();
306
451
  if (command === "validate") return validateCommand();
452
+ if (command === "baseline") return baselineCommand(parsed.positional[1]);
307
453
  if (command === "dry-run") {
308
454
  const id = parsed.positional[1];
309
455
  if (id === undefined) {
@@ -336,6 +336,7 @@ async function runPagePhase(
336
336
  codewiki: input.codewiki,
337
337
  page,
338
338
  siblings: plan.pages,
339
+ ...(input.decisions ? { decisions: input.decisions } : {}),
339
340
  outputDir: input.outputDir,
340
341
  seeded,
341
342
  }),
@@ -15,6 +15,21 @@ export const CLIO_COMMIT_TRAILERS = {
15
15
  coAuthored: `Co-authored-by: ${CLIO_COMMIT_IDENTITY}`,
16
16
  } as const;
17
17
 
18
+ export const CLIO_DECISION_TRAILER_KEY = "Clio-Decision";
19
+
20
+ /** Most `Clio-Decision:` trailers one commit carries; matches the receipt cap. */
21
+ export const CLIO_DECISION_TRAILER_CAP = 32;
22
+
23
+ /**
24
+ * A decision ref is `<interviewId>/<key>`: an `ask_user` interview id or an
25
+ * `agent:<uuid>` decision-set id, then the decision key. Operator keys are
26
+ * snake_case and agent keys are kebab-case, the same shape `isDecisionRecord`
27
+ * admits. Only refs of this shape become trailers, so a malformed value can
28
+ * never inject a second trailer line or a stray control character into a
29
+ * commit message.
30
+ */
31
+ export const DECISION_REF_PATTERN = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,127}\/[a-z0-9]+(?:[_-][a-z0-9]+)*$/u;
32
+
18
33
  export interface CommitReceiptEvidence {
19
34
  version: 20;
20
35
  algorithm: "sha256";
@@ -37,6 +52,12 @@ export interface CommitAttributionEvidence {
37
52
  materiallyAuthored?: boolean;
38
53
  /** Optional sealed receipt for a directly relevant fact above. */
39
54
  receipt?: CommitReceiptEvidence;
55
+ /**
56
+ * Decision refs (`<interviewId>/<key>`) the committed work was done under,
57
+ * read from the session decision board or a sealed receipt's
58
+ * `decisionRefs`. Each becomes one `Clio-Decision:` trailer.
59
+ */
60
+ decisions?: ReadonlyArray<string>;
40
61
  }
41
62
 
42
63
  const TRAILER_LINE = /^([A-Za-z0-9][A-Za-z0-9-]*):[ \t]+(.+)$/u;
@@ -58,7 +79,25 @@ const KNOWN_CLIO_TRAILERS = new Set(
58
79
  );
59
80
 
60
81
  function isClioTrailer(key: string): boolean {
61
- return KNOWN_CLIO_TRAILERS.has(key) || key.startsWith("clio-evidence:receipt-v20/sha256:");
82
+ return (
83
+ KNOWN_CLIO_TRAILERS.has(key) ||
84
+ key.startsWith("clio-evidence:receipt-v20/sha256:") ||
85
+ key.startsWith(`${CLIO_DECISION_TRAILER_KEY.toLowerCase()}:`)
86
+ );
87
+ }
88
+
89
+ /** Well-formed decision refs from the evidence, deduplicated, sorted, and capped. */
90
+ export function decisionTrailerRefs(decisions: ReadonlyArray<string> | undefined): string[] {
91
+ if (decisions === undefined) return [];
92
+ const refs = new Set<string>();
93
+ for (const ref of decisions) {
94
+ if (typeof ref === "string" && DECISION_REF_PATTERN.test(ref)) refs.add(ref);
95
+ }
96
+ return [...refs].sort().slice(0, CLIO_DECISION_TRAILER_CAP);
97
+ }
98
+
99
+ function decisionTrailer(ref: string): string {
100
+ return `${CLIO_DECISION_TRAILER_KEY}: ${ref}`;
62
101
  }
63
102
 
64
103
  /**
@@ -138,6 +177,7 @@ export function attributeCommitMessage(
138
177
  if (evidence.materiallyAuthored === true) desired.push(CLIO_COMMIT_TRAILERS.coAuthored);
139
178
  const receipt = receiptTrailer(evidence.receipt);
140
179
  if (receipt !== null) desired.push(receipt);
180
+ for (const ref of decisionTrailerRefs(evidence.decisions)) desired.push(decisionTrailer(ref));
141
181
 
142
182
  const existing = new Set(
143
183
  (blockStart === null ? [] : retained.slice(blockStart))
@@ -525,6 +525,57 @@ function validateLmStudioSettings(
525
525
  return Object.keys(out).length > 0 ? out : undefined;
526
526
  }
527
527
 
528
+ function validateLiteLLMSettings(
529
+ issues: Issues,
530
+ path: string,
531
+ value: unknown,
532
+ ): ClioSettings["targets"][number]["litellm"] | undefined {
533
+ if (!isPlainObject(value)) {
534
+ issues.add(path, `expected a map, got ${describe(value)}`);
535
+ return undefined;
536
+ }
537
+ issues.unknownKeys(path, value, ["request"]);
538
+ const out: NonNullable<ClioSettings["targets"][number]["litellm"]> = {};
539
+ if ("request" in value) {
540
+ if (!isPlainObject(value.request)) {
541
+ issues.add(`${path}.request`, `expected a map, got ${describe(value.request)}`);
542
+ } else {
543
+ issues.unknownKeys(`${path}.request`, value.request, [
544
+ "tags",
545
+ "sendSessionId",
546
+ "timeoutSeconds",
547
+ "streamTimeoutSeconds",
548
+ "numRetries",
549
+ ]);
550
+ const request: NonNullable<typeof out.request> = {};
551
+ if ("tags" in value.request) {
552
+ const parsed = expectStringArray(issues, `${path}.request.tags`, value.request.tags);
553
+ if (parsed !== undefined) {
554
+ const invalidTag = parsed.find((tag) => tag.includes(","));
555
+ if (invalidTag) issues.add(`${path}.request.tags`, "tags may not contain commas");
556
+ else if (parsed.length > 0) request.tags = [...new Set(parsed)];
557
+ }
558
+ }
559
+ if ("sendSessionId" in value.request) {
560
+ const parsed = expectBoolean(issues, `${path}.request.sendSessionId`, value.request.sendSessionId);
561
+ if (parsed !== undefined) request.sendSessionId = parsed;
562
+ }
563
+ for (const key of ["timeoutSeconds", "streamTimeoutSeconds"] as const) {
564
+ if (key in value.request) {
565
+ const parsed = expectNumber(issues, `${path}.request.${key}`, value.request[key], { min: 0.001, max: 86_400 });
566
+ if (parsed !== undefined) request[key] = parsed;
567
+ }
568
+ }
569
+ if ("numRetries" in value.request) {
570
+ const parsed = expectInteger(issues, `${path}.request.numRetries`, value.request.numRetries, { min: 0, max: 100 });
571
+ if (parsed !== undefined) request.numRetries = parsed;
572
+ }
573
+ if (Object.keys(request).length > 0) out.request = request;
574
+ }
575
+ }
576
+ return Object.keys(out).length > 0 ? out : undefined;
577
+ }
578
+
528
579
  function validateTarget(issues: Issues, path: string, value: unknown): ClioSettings["targets"][number] | null {
529
580
  if (!isPlainObject(value)) {
530
581
  issues.add(path, `expected a map, got ${describe(value)}`);
@@ -542,6 +593,7 @@ function validateTarget(issues: Issues, path: string, value: unknown): ClioSetti
542
593
  "gateway",
543
594
  "pricing",
544
595
  "lmstudio",
596
+ "litellm",
545
597
  "maxConcurrentRequests",
546
598
  ]);
547
599
  const id = "id" in value ? expectString(issues, `${path}.id`, value.id) : undefined;
@@ -593,6 +645,10 @@ function validateTarget(issues: Issues, path: string, value: unknown): ClioSetti
593
645
  const v = validateLmStudioSettings(issues, `${path}.lmstudio`, value.lmstudio);
594
646
  if (v !== undefined) target.lmstudio = v;
595
647
  }
648
+ if ("litellm" in value) {
649
+ const v = validateLiteLLMSettings(issues, `${path}.litellm`, value.litellm);
650
+ if (v !== undefined) target.litellm = v;
651
+ }
596
652
  if ("maxConcurrentRequests" in value) {
597
653
  const v = expectInteger(issues, `${path}.maxConcurrentRequests`, value.maxConcurrentRequests, { min: 1 });
598
654
  if (v !== undefined) target.maxConcurrentRequests = v;
@@ -0,0 +1,44 @@
1
+ const REDACTED = "[redacted]";
2
+
3
+ /**
4
+ * Sanitize free-form text received from an external process before it crosses
5
+ * into errors, receipts, transcripts, evidence, or model-catalog snapshots.
6
+ */
7
+ function redactExternalDiagnostic(input: string): string {
8
+ return input
9
+ .replace(/\b(?:authorization|proxy-authorization)\s*:\s*[^\r\n]+/giu, `Authorization: ${REDACTED}`)
10
+ .replace(/\b(?:set-cookie|cookie)\s*:\s*[^\r\n]+/giu, `Cookie: ${REDACTED}`)
11
+ .replace(/\bbearer\s+[A-Za-z0-9._~+/-]+=*/giu, `Bearer ${REDACTED}`)
12
+ .replace(
13
+ /\b(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|secret|password)\s*[:=]\s*[^\s,;]+/giu,
14
+ (match) => {
15
+ const separator = match.includes(":") ? ":" : "=";
16
+ return `${match.slice(0, match.indexOf(separator)).trim()}${separator}${REDACTED}`;
17
+ },
18
+ )
19
+ .replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, REDACTED)
20
+ .replace(
21
+ /(?:~|\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*)\/\.(?:gemini\/antigravity-cli|antigravitycli)(?:\/[^\s]*)?/gu,
22
+ "[redacted credential path]",
23
+ )
24
+ .replace(/https?:\/\/[^\s"'<>]+/giu, (url) => {
25
+ try {
26
+ const parsed = new URL(url);
27
+ if (/(?:auth|oauth|login|signin|callback)/iu.test(parsed.pathname)) return "[redacted authorization URL]";
28
+ parsed.username = "";
29
+ parsed.password = "";
30
+ parsed.search = "";
31
+ parsed.hash = "";
32
+ return parsed.toString();
33
+ } catch {
34
+ return REDACTED;
35
+ }
36
+ });
37
+ }
38
+
39
+ export function boundedExternalDiagnostic(input: string, maxBytes = 8192): string {
40
+ const redacted = redactExternalDiagnostic(input).trim();
41
+ const bytes = Buffer.from(redacted, "utf8");
42
+ if (bytes.byteLength <= maxBytes) return redacted;
43
+ return `${bytes.subarray(0, Math.max(0, maxBytes - 32)).toString("utf8")}\n[diagnostic truncated]`;
44
+ }