@iowarp/clio-coder 0.4.1 → 0.4.2

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 (437) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/CONTRIBUTING.md +59 -36
  3. package/README.md +404 -472
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-TMDQZDIG.js} +7 -7
  6. package/dist/{agents-HYWGBGQR.js → agents-5N5NG3XG.js} +28 -28
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-Z5CCBXKQ.js} +8 -9
  9. package/dist/{builtins-UJLMOVOV.js → builtins-K6TNDT24.js} +4 -4
  10. package/dist/{chunk-GVQJ5CCZ.js → chunk-2HFQNRV3.js} +7 -7
  11. package/dist/{chunk-QMXC4JB7.js → chunk-2NHR3NAY.js} +163 -1401
  12. package/dist/chunk-2X4RYJTJ.js +39 -0
  13. package/dist/{chunk-Y45G3AXC.js → chunk-2Z2IKEXI.js} +6 -10
  14. package/dist/{chunk-EIMVLWB3.js → chunk-34BHNEE3.js} +7 -3
  15. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  16. package/dist/chunk-3EBYEESD.js +314 -0
  17. package/dist/{chunk-CTJ4RNAA.js → chunk-3F7VUY77.js} +2 -2
  18. package/dist/{chunk-AP73CFDC.js → chunk-3KIPBMUA.js} +2 -2
  19. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  20. package/dist/{chunk-VEGN6WIQ.js → chunk-462T4EGZ.js} +2 -2
  21. package/dist/{chunk-AFKWHWXF.js → chunk-4JDLP6ZS.js} +33 -16
  22. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  23. package/dist/{chunk-AKB4GYDL.js → chunk-54ODD65L.js} +5 -5
  24. package/dist/{chunk-BBTJOK6Y.js → chunk-5KW52TEP.js} +3 -3
  25. package/dist/{chunk-6CCS4G3W.js → chunk-5PFYMY2V.js} +2 -2
  26. package/dist/chunk-77QIVUZB.js +1334 -0
  27. package/dist/{chunk-7OBGU7UB.js → chunk-7BHIY2MW.js} +7 -13
  28. package/dist/{chunk-3QSOM6PA.js → chunk-AZ4WMN4W.js} +2 -2
  29. package/dist/{chunk-6NJQITNH.js → chunk-B74PXLU7.js} +6 -3
  30. package/dist/{chunk-R23Z6K6I.js → chunk-B7HM5Z7T.js} +15 -15
  31. package/dist/{chunk-R32CLGZ6.js → chunk-BO7Y52RY.js} +81 -20
  32. package/dist/{chunk-UEDMSP56.js → chunk-BYMNWQ7O.js} +123 -148
  33. package/dist/{chunk-ZJLUDYFY.js → chunk-CRFOIAX3.js} +4 -4
  34. package/dist/{chunk-2NM363SV.js → chunk-CYZW7JHJ.js} +7 -7
  35. package/dist/{chunk-6HMJX2VU.js → chunk-DYHAXKHD.js} +38 -10
  36. package/dist/{chunk-THYWACCR.js → chunk-DZAW46HP.js} +3 -3
  37. package/dist/{chunk-FYUN5KZ3.js → chunk-DZEK6CJN.js} +17 -17
  38. package/dist/{chunk-3I5NY75V.js → chunk-E7GT7O5N.js} +5 -5
  39. package/dist/{chunk-VKFQTNDV.js → chunk-F2I26BDK.js} +4 -4
  40. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  41. package/dist/{chunk-IXJT6DCX.js → chunk-FVDGR2ZL.js} +3 -3
  42. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  43. package/dist/{chunk-7EPLI7VL.js → chunk-HIICAHCJ.js} +2 -2
  44. package/dist/{chunk-E67WX76H.js → chunk-HKMD33FO.js} +29 -80
  45. package/dist/chunk-HLAFFSEK.js +360 -0
  46. package/dist/{chunk-UAPGZHYC.js → chunk-I64IFBLB.js} +9 -2
  47. package/dist/{chunk-XKA2ICR3.js → chunk-I66ZTYNP.js} +440 -175
  48. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  49. package/dist/{chunk-PVAMAVBB.js → chunk-IDNA72AH.js} +102 -2
  50. package/dist/{chunk-GCSMB2KY.js → chunk-IKOZFYBN.js} +1 -1
  51. package/dist/{chunk-2VG7KLYV.js → chunk-IKSLQ4XV.js} +5460 -3241
  52. package/dist/{chunk-QKIFBZKT.js → chunk-IMXMHHMQ.js} +166 -25
  53. package/dist/{chunk-74YWRRU5.js → chunk-JBCS7CRR.js} +2 -2
  54. package/dist/{chunk-BDPT6GTK.js → chunk-JWJGP5DQ.js} +2 -2
  55. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  56. package/dist/chunk-KPXDY6QF.js +47 -0
  57. package/dist/{chunk-ABLSQ6JX.js → chunk-LJID3DYZ.js} +7 -1
  58. package/dist/{chunk-VKRH2TCS.js → chunk-M2DAX4F6.js} +2 -2
  59. package/dist/{chunk-6I5ILFOF.js → chunk-M2WXEHER.js} +2 -2
  60. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  61. package/dist/{chunk-N5UK64DP.js → chunk-MCMZMDAC.js} +2 -2
  62. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  63. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  64. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  65. package/dist/{chunk-HUAS7ITX.js → chunk-O3YUNJZ2.js} +13 -21
  66. package/dist/{chunk-MA3H6DM5.js → chunk-P75RZCJW.js} +25 -3
  67. package/dist/{chunk-IG7BCQBA.js → chunk-PGF63K6I.js} +2 -2
  68. package/dist/chunk-PJX3WQUQ.js +42 -0
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-Q4XWMHX6.js} +4 -6
  70. package/dist/{chunk-OJTRZGR3.js → chunk-QQLGQY2A.js} +8 -8
  71. package/dist/{chunk-J4HBWF6Y.js → chunk-RLYRBIYQ.js} +115 -20
  72. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  73. package/dist/{chunk-C537JADH.js → chunk-SSEYRH53.js} +6 -7
  74. package/dist/chunk-SZAA6XDG.js +30 -0
  75. package/dist/{chunk-MOPSG2X7.js → chunk-TPEQIQIE.js} +6 -6
  76. package/dist/{chunk-JA5QWE4Z.js → chunk-UBRFI4HS.js} +1879 -1650
  77. package/dist/{chunk-BTGG6BG2.js → chunk-UH347SHR.js} +154 -15
  78. package/dist/{chunk-5YHDIDBP.js → chunk-UH632ZYL.js} +2 -2
  79. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  80. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  81. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  82. package/dist/{chunk-UXN6JT4W.js → chunk-W4YEMFBX.js} +2 -2
  83. package/dist/{chunk-TD3PGPQA.js → chunk-W6NIE6OW.js} +2 -2
  84. package/dist/{chunk-TVH4ONAM.js → chunk-X7IARSHT.js} +3 -3
  85. package/dist/{chunk-PJJ6MY27.js → chunk-XE3PCIXH.js} +3 -3
  86. package/dist/{chunk-FEFIFZTL.js → chunk-XGDPUNND.js} +2 -2
  87. package/dist/{chunk-SCYB3HA4.js → chunk-XOXV5GKE.js} +51 -16
  88. package/dist/{chunk-QTFGO774.js → chunk-XQRY4DTA.js} +24 -11
  89. package/dist/{chunk-BJGUKIG4.js → chunk-YJISEZKC.js} +2 -2
  90. package/dist/{chunk-GPPB3JBE.js → chunk-ZGNYYXQ6.js} +2 -2
  91. package/dist/{chunk-SINK3QR6.js → chunk-ZNT2M6TG.js} +7 -7
  92. package/dist/{chunk-7RY5VZPH.js → chunk-ZW4HH5JJ.js} +6 -6
  93. package/dist/cli/index.js +33 -32
  94. package/dist/{clio-IT3G3VQH.js → clio-7VB377CC.js} +7 -7
  95. package/dist/{code-nav-RK6S7F6E.js → code-nav-YVLCYA7V.js} +85 -17
  96. package/dist/{config-3QZRWZJF.js → config-4HVOS65E.js} +88 -43
  97. package/dist/{configure-FL7Y3KJF.js → configure-PIWO7B24.js} +10 -10
  98. package/dist/{context-5HE7ODYK.js → context-IYEHL3WQ.js} +33 -31
  99. package/dist/{context-XNHL75JV.js → context-KQYIWPWT.js} +47 -34
  100. package/dist/{context-KYQFRVDC.js → context-N6ZE3LGJ.js} +11 -11
  101. package/dist/{context-clear-N545L53A.js → context-clear-G4OGZJDS.js} +33 -31
  102. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-BWLF6LJP.js} +7 -7
  103. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-2QQAITS3.js} +38 -38
  104. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  105. package/dist/{doctor-ZGPEGHIP.js → doctor-LHBD36VU.js} +23 -22
  106. package/dist/{eval-GXLL44RD.js → eval-C45FYRJ6.js} +21 -20
  107. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-6DEJPLBF.js} +2 -2
  108. package/dist/{evidence-HWLBRH3Q.js → evidence-6SHONYAF.js} +30 -28
  109. package/dist/{evolve-FTZBMNVW.js → evolve-KRKMV72X.js} +30 -28
  110. package/dist/{extensions-VHRBEID7.js → extensions-KPZ2UHBB.js} +5 -3
  111. package/dist/{fleet-CKZHJWZJ.js → fleet-IVTCKDHT.js} +62 -61
  112. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-EDWL3IT7.js} +5 -5
  113. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-YP3YEFGK.js} +4 -4
  114. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-ZFWKHY2M.js} +16 -14
  115. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-FVUNCBML.js} +31 -29
  116. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-UN5XED4R.js} +2 -2
  117. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-XOWC4HSX.js} +17 -15
  118. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-UN3SODEL.js} +30 -28
  119. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-TWHJKCN6.js} +31 -29
  120. package/dist/{init-5XQRBOFV.js → init-T2QORQ3Y.js} +50 -49
  121. package/dist/{interop-34TVO25M.js → interop-IN5I2A66.js} +5 -5
  122. package/dist/{library-3QY6KF57.js → library-LSCATDLZ.js} +15 -13
  123. package/dist/{memory-L4UTIIIW.js → memory-HYOKAGGJ.js} +31 -29
  124. package/dist/{models-ZVX3QOWE.js → models-2GPMFYCM.js} +22 -21
  125. package/dist/{monitor-CEKVSYTS.js → monitor-E4ASVUJH.js} +34 -32
  126. package/dist/{orchestrator-77BAP6BC.js → orchestrator-DDMPR3PY.js} +984 -583
  127. package/dist/{panes-7STHOAUJ.js → panes-E3RUXOW5.js} +4 -4
  128. package/dist/{panes-SHAUIRXY.js → panes-IXKLOKA2.js} +23 -8
  129. package/dist/{reset-EOLM7GVE.js → reset-OAQP3W4O.js} +4 -4
  130. package/dist/{resources-74GKTLSF.js → resources-OTRSN34L.js} +15 -13
  131. package/dist/{run-HBAUJNNZ.js → run-5DEYH5QK.js} +60 -59
  132. package/dist/{share-G3APVLVP.js → share-IHWTLO3M.js} +19 -15
  133. package/dist/{skills-35HHUKCR.js → skills-IYMXMKW4.js} +17 -15
  134. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-DROHSJAR.js} +36 -36
  135. package/dist/{skills-inventory-J357J34F.js → skills-inventory-D7X4L4ZX.js} +15 -13
  136. package/dist/{slash-commands-JZZCQA32.js → slash-commands-QBM7UZ3B.js} +21 -18
  137. package/dist/{steer-XAVHJM22.js → steer-Z5DO23FJ.js} +2 -2
  138. package/dist/{targets-DSM6CY3M.js → targets-P2FUC4IL.js} +25 -28
  139. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-YREJ3JX2.js} +5 -5
  140. package/dist/{tools-MKNWVPBH.js → tools-5B7RO6MV.js} +4 -4
  141. package/dist/{trace-ECQ7TIYZ.js → trace-YMGMUM6A.js} +55 -7
  142. package/dist/{upgrade-H7TOM7YL.js → upgrade-PXK3S2YM.js} +11 -9
  143. package/dist/{usage-X52N3IDJ.js → usage-ME5MPXGX.js} +36 -34
  144. package/dist/{verifiers-EJTVVSMA.js → verifiers-BVZ7IWOO.js} +5 -5
  145. package/dist/{verify-YJL6XET2.js → verify-5K7ZKQFC.js} +4 -4
  146. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  147. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-F5W5QTYY.js} +48 -47
  148. package/dist/{with-panes-OBOBFIIR.js → with-panes-BYOJCLAM.js} +51 -255
  149. package/dist/worker/entry.js +45 -30
  150. package/docs/README.md +176 -81
  151. package/docs/{acp.md → architecture/acp.md} +36 -20
  152. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  153. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  154. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +26 -23
  155. package/docs/architecture/artifact-versions.md +90 -0
  156. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  157. package/docs/{context-engine.md → architecture/context-engine.md} +25 -25
  158. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  159. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  160. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  161. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  162. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  163. package/docs/{model-catalog.md → architecture/model-catalog.md} +40 -17
  164. package/docs/{observability.md → architecture/observability.md} +26 -13
  165. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  166. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +55 -20
  167. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +35 -24
  168. package/docs/{safety-model.md → architecture/safety-model.md} +20 -15
  169. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  170. package/docs/architecture/time-conventions.md +125 -0
  171. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  172. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  173. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  174. package/docs/{built-in-agents.md → guide/built-in-agents.md} +50 -34
  175. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +65 -60
  176. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +227 -289
  177. package/docs/guide/configuration-reference.md +1158 -0
  178. package/docs/{environment-variables.md → guide/environment-variables.md} +31 -28
  179. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  180. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  181. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  182. package/docs/{glossary.md → guide/glossary.md} +14 -11
  183. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +44 -13
  184. package/docs/guide/panes-and-files.md +290 -0
  185. package/docs/{proactive-memory.md → guide/proactive-memory.md} +79 -66
  186. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  187. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +7 -3
  188. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  189. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  190. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  191. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  192. package/docs/{development-pipeline.md → process/development-pipeline.md} +24 -26
  193. package/docs/process/documentation-coverage.md +100 -0
  194. package/docs/process/documentation-guide.md +187 -0
  195. package/docs/{eval-runner.md → process/eval-runner.md} +41 -50
  196. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  197. package/docs/{evolution.md → process/evolution.md} +2 -2
  198. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  199. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  200. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  201. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  202. package/evals/README.md +2 -2
  203. package/package.json +9 -7
  204. package/skills/README.md +46 -37
  205. package/skills/coding/ast-grep/SKILL.md +2 -2
  206. package/skills/coding/coding-standards/SKILL.md +2 -2
  207. package/skills/coding/prototype/SKILL.md +2 -2
  208. package/skills/coding/tdd/SKILL.md +2 -2
  209. package/skills/context/context-handoff/SKILL.md +2 -2
  210. package/skills/context/context-prime/SKILL.md +2 -2
  211. package/skills/git/file-ticket/SKILL.md +2 -2
  212. package/skills/git/fix-issue/SKILL.md +3 -3
  213. package/skills/git/resolve-merge-conflicts/SKILL.md +2 -2
  214. package/skills/git/ship/SKILL.md +2 -2
  215. package/skills/git/worktree-create/SKILL.md +2 -2
  216. package/skills/git/worktree-merge/SKILL.md +2 -2
  217. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  218. package/skills/meta/clio-coder-dev/evals.md +3 -2
  219. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  220. package/skills/meta/clio-coder-test/evals.md +9 -4
  221. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  222. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  223. package/skills/meta/credentials/SKILL.md +2 -2
  224. package/skills/meta/find-skills/SKILL.md +2 -2
  225. package/skills/meta/herdr/SKILL.md +2 -2
  226. package/skills/meta/skill-craft/SKILL.md +22 -16
  227. package/skills/planning/architecture/SKILL.md +2 -2
  228. package/skills/planning/backlog/SKILL.md +2 -2
  229. package/skills/planning/prd/SKILL.md +2 -2
  230. package/skills/planning/product-intent/SKILL.md +2 -2
  231. package/skills/planning/tech-spec/SKILL.md +2 -2
  232. package/skills/registry.yaml +62 -62
  233. package/skills/research/arxiv-literature/SKILL.md +2 -2
  234. package/skills/research/experiment-protocol/SKILL.md +2 -2
  235. package/skills/research/scientific-debugging/SKILL.md +2 -2
  236. package/skills/research/scientific-modernization/SKILL.md +2 -2
  237. package/skills/skill-marketplace.json +62 -62
  238. package/skills/workflow/cut-it/SKILL.md +2 -2
  239. package/skills/workflow/design-council/SKILL.md +2 -2
  240. package/skills/workflow/grill-me/SKILL.md +2 -2
  241. package/skills/workflow/workflow-distiller/SKILL.md +2 -2
  242. package/src/cli/args.ts +2 -2
  243. package/src/cli/bootstrap-generate.ts +1 -1
  244. package/src/cli/config-inspect.ts +65 -12
  245. package/src/cli/configure.ts +0 -4
  246. package/src/cli/docs.ts +22 -14
  247. package/src/cli/doctor-naming.ts +5 -5
  248. package/src/cli/doctor-toolchain.ts +3 -3
  249. package/src/cli/eval.ts +1 -2
  250. package/src/cli/extensions.ts +2 -1
  251. package/src/cli/fleet.ts +1 -1
  252. package/src/cli/index.ts +2 -1
  253. package/src/cli/internal-dispatch.ts +3 -4
  254. package/src/cli/panes.ts +19 -5
  255. package/src/cli/run.ts +2 -2
  256. package/src/cli/share.ts +5 -1
  257. package/src/cli/skills-eval.ts +3 -3
  258. package/src/cli/targets.ts +2 -6
  259. package/src/cli/trace.ts +55 -4
  260. package/src/cli/wiki-generate.ts +1 -1
  261. package/src/core/artifact-paths.ts +1 -1
  262. package/src/core/bash-exec.ts +131 -86
  263. package/src/core/bus-events.ts +51 -6
  264. package/src/core/config.ts +5 -1
  265. package/src/core/defaults.ts +7 -4
  266. package/src/core/dispatch-outcome.ts +16 -0
  267. package/src/core/guardrails.ts +10 -49
  268. package/src/core/prompt-hint.ts +9 -0
  269. package/src/domains/agents/builtins/architect.md +2 -3
  270. package/src/domains/agents/builtins/coder.md +3 -2
  271. package/src/domains/agents/builtins/debugger.md +2 -2
  272. package/src/domains/agents/builtins/documenter.md +2 -2
  273. package/src/domains/agents/builtins/git-master.md +1 -1
  274. package/src/domains/agents/builtins/oracle.md +1 -1
  275. package/src/domains/agents/builtins/provenance.md +1 -1
  276. package/src/domains/agents/builtins/researcher.md +1 -1
  277. package/src/domains/agents/builtins/scout.md +1 -1
  278. package/src/domains/agents/builtins/tester.md +2 -2
  279. package/src/domains/agents/builtins/verifier.md +2 -2
  280. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  281. package/src/domains/agents/catalog.ts +12 -14
  282. package/src/domains/agents/contract.ts +2 -0
  283. package/src/domains/agents/extension.ts +23 -1
  284. package/src/domains/config/keybindings.ts +8 -0
  285. package/src/domains/context/extension.ts +0 -3
  286. package/src/domains/context/working-set/path-index.ts +1 -0
  287. package/src/domains/dispatch/capability-match.ts +10 -0
  288. package/src/domains/dispatch/extension.ts +105 -22
  289. package/src/domains/dispatch/host-verification.ts +435 -39
  290. package/src/domains/dispatch/intent-requirements.ts +10 -0
  291. package/src/domains/dispatch/intent.ts +18 -1
  292. package/src/domains/dispatch/path-scope.ts +235 -24
  293. package/src/domains/dispatch/run-event-journal.ts +4 -15
  294. package/src/domains/dispatch/state.ts +2 -3
  295. package/src/domains/dispatch/transport.ts +45 -21
  296. package/src/domains/dispatch/types.ts +55 -3
  297. package/src/domains/eval/artifacts/store.ts +5 -0
  298. package/src/domains/eval/store.ts +8 -1
  299. package/src/domains/evidence/trust-status.ts +10 -1
  300. package/src/domains/extensions/contract.ts +15 -1
  301. package/src/domains/extensions/discovery.ts +238 -41
  302. package/src/domains/extensions/extension.ts +105 -6
  303. package/src/domains/extensions/index.ts +24 -0
  304. package/src/domains/extensions/integrity.ts +189 -0
  305. package/src/domains/extensions/manager.ts +17 -1
  306. package/src/domains/extensions/resource-path.ts +27 -0
  307. package/src/domains/extensions/resources.ts +18 -38
  308. package/src/domains/extensions/snapshot-store.ts +39 -0
  309. package/src/domains/extensions/snapshot.ts +180 -0
  310. package/src/domains/extensions/state.ts +385 -57
  311. package/src/domains/extensions/types.ts +118 -1
  312. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  313. package/src/domains/lifecycle/migrations/index.ts +2 -0
  314. package/src/domains/lifecycle/naming-resources.ts +19 -4
  315. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  316. package/src/domains/middleware/contract.ts +26 -0
  317. package/src/domains/middleware/extension.ts +24 -24
  318. package/src/domains/middleware/hook-receipts.ts +27 -4
  319. package/src/domains/middleware/hooks-io.ts +65 -32
  320. package/src/domains/middleware/hooks.ts +64 -0
  321. package/src/domains/middleware/index.ts +28 -4
  322. package/src/domains/middleware/registrations.ts +326 -0
  323. package/src/domains/middleware/runtime.ts +28 -0
  324. package/src/domains/middleware/snapshot.ts +20 -7
  325. package/src/domains/mux/contract.ts +38 -0
  326. package/src/domains/mux/detect.ts +6 -13
  327. package/src/domains/mux/index.ts +1 -1
  328. package/src/domains/mux/operations.ts +44 -5
  329. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  330. package/src/domains/mux/yazi/session.ts +53 -4
  331. package/src/domains/mux/yazi/theme.ts +117 -17
  332. package/src/domains/observability/contract.ts +10 -11
  333. package/src/domains/observability/extension.ts +11 -3
  334. package/src/domains/observability/projection.ts +14 -90
  335. package/src/domains/observability/trace-store.ts +43 -7
  336. package/src/domains/prompts/compiler.ts +73 -53
  337. package/src/domains/prompts/contract.ts +15 -3
  338. package/src/domains/prompts/extension.ts +97 -9
  339. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  340. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  341. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  342. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  343. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  344. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  345. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  346. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  347. package/src/domains/providers/index.ts +1 -1
  348. package/src/domains/providers/model-runtime-capabilities.ts +85 -21
  349. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +669 -104
  350. package/src/domains/providers/runtime-resolution.ts +31 -0
  351. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  352. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  353. package/src/domains/providers/types/cost-provenance.ts +19 -0
  354. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  355. package/src/domains/resources/skills/loader.ts +16 -19
  356. package/src/domains/safety/call-target.ts +1 -1
  357. package/src/domains/safety/loop-detector.ts +7 -4
  358. package/src/domains/session/task-board.ts +10 -9
  359. package/src/domains/share/archive.ts +164 -7
  360. package/src/engine/acp/server.ts +62 -9
  361. package/src/engine/apis/llamacpp-residency.ts +3 -4
  362. package/src/engine/apis/lmstudio.ts +3 -3
  363. package/src/engine/apis/ollama-native.ts +6 -6
  364. package/src/engine/apis/openai-completions.ts +28 -25
  365. package/src/engine/apis/output-budget.ts +8 -18
  366. package/src/engine/apis/residency.ts +8 -27
  367. package/src/engine/gemma-channel-filter.ts +19 -0
  368. package/src/engine/loop-guard.ts +92 -12
  369. package/src/engine/worker-runtime.ts +40 -11
  370. package/src/engine/worker-tools.ts +3 -1
  371. package/src/entry/extension-hook-sources.ts +28 -0
  372. package/src/entry/extension-reload.ts +309 -0
  373. package/src/entry/orchestrator.ts +59 -35
  374. package/src/interactive/application-controller.ts +2 -1
  375. package/src/interactive/bus-notices.ts +8 -1
  376. package/src/interactive/chat-loop-messages.ts +3 -13
  377. package/src/interactive/chat-loop.ts +10 -1
  378. package/src/interactive/chat-panel.ts +36 -13
  379. package/src/interactive/chat-renderer.ts +71 -7
  380. package/src/interactive/dispatch-board.ts +6 -11
  381. package/src/interactive/footer/widgets.ts +13 -0
  382. package/src/interactive/interactive-application.ts +39 -4
  383. package/src/interactive/interactive-input-runtime.ts +4 -0
  384. package/src/interactive/interactive-presentation.ts +2 -2
  385. package/src/interactive/interactive-slash-runtime.ts +2 -0
  386. package/src/interactive/overlays/extensions.ts +9 -1
  387. package/src/interactive/overlays/help-reference.ts +13 -0
  388. package/src/interactive/overlays/settings.ts +27 -16
  389. package/src/interactive/panes-runtime.ts +111 -35
  390. package/src/interactive/prompt-cache-identity.ts +88 -0
  391. package/src/interactive/slash-commands.ts +129 -14
  392. package/src/interactive/stream-pacing-policy.ts +0 -23
  393. package/src/interactive/turn-context.ts +30 -15
  394. package/src/interactive/yazi-bridge.ts +60 -6
  395. package/src/tools/agent-tools.ts +30 -1
  396. package/src/tools/artifact.ts +2 -2
  397. package/src/tools/ask-user.ts +3 -3
  398. package/src/tools/bash.ts +1 -1
  399. package/src/tools/bootstrap.ts +4 -0
  400. package/src/tools/builtin-tool-catalog.ts +52 -22
  401. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  402. package/src/tools/codewiki/code-nav.ts +99 -13
  403. package/src/tools/context/docs-engine.ts +20 -7
  404. package/src/tools/context/index.ts +29 -12
  405. package/src/tools/core-bootstrap.ts +28 -6
  406. package/src/tools/credential-present.ts +1 -2
  407. package/src/tools/dispatch-arguments.ts +5 -1
  408. package/src/tools/dispatch-plan.ts +48 -4
  409. package/src/tools/dispatch-run-events.ts +1 -1
  410. package/src/tools/dispatch-schema.ts +338 -0
  411. package/src/tools/dispatch-types.ts +3 -0
  412. package/src/tools/dispatch.ts +9 -254
  413. package/src/tools/ledger.ts +3 -5
  414. package/src/tools/monitor-surface.ts +5 -13
  415. package/src/tools/observation.ts +4 -5
  416. package/src/tools/panes-surface.ts +4 -11
  417. package/src/tools/panes.ts +4 -2
  418. package/src/tools/policy.ts +15 -2
  419. package/src/tools/read.ts +5 -6
  420. package/src/tools/registry.ts +30 -7
  421. package/src/tools/result-shaping.ts +18 -14
  422. package/src/tools/steer-surface.ts +1 -1
  423. package/src/tools/tasks.ts +1 -1
  424. package/src/tools/truncate.ts +6 -5
  425. package/src/tools/verify/surface.ts +6 -12
  426. package/src/tools/web-fetch-surface.ts +1 -3
  427. package/dist/chunk-5QIAJV2D.js +0 -48
  428. package/dist/chunk-JZWT5J3Y.js +0 -814
  429. package/dist/chunk-K7VKOLQQ.js +0 -15
  430. package/dist/chunk-PMZCIOCJ.js +0 -25
  431. package/dist/chunk-SUW5DORT.js +0 -819
  432. package/dist/chunk-UOV2BYIW.js +0 -107
  433. package/dist/chunk-WR6U3OVP.js +0 -45
  434. package/docs/artifact-versions.md +0 -67
  435. package/docs/documentation-coverage.md +0 -46
  436. package/docs/documentation-guide.md +0 -167
  437. package/docs/time-conventions.md +0 -101
@@ -1,5 +1,17 @@
1
1
  import { createHash } from "node:crypto";
2
- import { existsSync, lstatSync, readdirSync, readFileSync, realpathSync, type Stats, statSync } from "node:fs";
2
+ import {
3
+ existsSync,
4
+ lstatSync,
5
+ mkdirSync,
6
+ mkdtempSync,
7
+ readdirSync,
8
+ readFileSync,
9
+ realpathSync,
10
+ rmSync,
11
+ type Stats,
12
+ statSync,
13
+ } from "node:fs";
14
+ import { tmpdir } from "node:os";
3
15
  import path from "node:path";
4
16
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
5
17
  import { type ClioSettings, readSettings, settingsPath, updateSettings, validateSettings } from "../../core/config.js";
@@ -18,6 +30,10 @@ import {
18
30
  parseAgentRecipeSchema,
19
31
  parseFleetContract,
20
32
  } from "../agents/index.js";
33
+ import { loadManifestFromRoot } from "../extensions/discovery.js";
34
+ import { extensionContentDigest } from "../extensions/integrity.js";
35
+ import { extensionBaseDir, installExtension, listInstalledExtensions } from "../extensions/state.js";
36
+ import type { ExtensionScope } from "../extensions/types.js";
21
37
  import { migrateSettingsV1Document } from "../lifecycle/migrations/2026-09-01-settings-v2.js";
22
38
 
23
39
  export type ShareScope = "project" | "user";
@@ -331,7 +347,14 @@ export function createShareArchive(options: ShareExportOptions = {}): ClioShareA
331
347
  for (const scope of scopes) {
332
348
  const root =
333
349
  scope === "user" ? path.join(clioConfigDir(), "extensions") : path.join(cwd, ".clio-coder", "extensions");
334
- addTree(files, "extension", scope, root, `${scope}/extensions`, (rel) => path.basename(rel) !== "state.json");
350
+ addTree(
351
+ files,
352
+ "extension",
353
+ scope,
354
+ root,
355
+ `${scope}/extensions`,
356
+ (relativePath) => !relativePath.split("/")[0]?.startsWith(".") && path.basename(relativePath) !== "state.json",
357
+ );
335
358
  }
336
359
  }
337
360
  if (includes.includeSettings) {
@@ -453,6 +476,15 @@ interface ShareImportPreparedPlan {
453
476
  actions: ShareImportAction[];
454
477
  diagnostics: ShareDiagnostic[];
455
478
  targets: ShareImportPreparedTarget[];
479
+ extensionPackages: ShareImportPreparedExtensionPackage[];
480
+ }
481
+
482
+ interface ShareImportPreparedExtensionPackage {
483
+ id: string;
484
+ scope: ExtensionScope;
485
+ files: Array<{ relativePath: string; buffer: Buffer }>;
486
+ contentDigest: string;
487
+ install: boolean;
456
488
  }
457
489
 
458
490
  function configDirPath(): string {
@@ -608,6 +640,91 @@ function preflightImportTargets(
608
640
  return { targets, diagnostics };
609
641
  }
610
642
 
643
+ function withStagedExtensionPackage<T>(
644
+ input: { id: string; files: ReadonlyArray<{ relativePath: string; buffer: Buffer }> },
645
+ fn: (root: string) => T,
646
+ ): T {
647
+ const stagingParent = mkdtempSync(path.join(tmpdir(), "clio-share-extension-"));
648
+ const root = path.join(stagingParent, input.id);
649
+ try {
650
+ mkdirSync(root, { recursive: true });
651
+ for (const file of input.files) safeResourceWrite(path.join(root, file.relativePath), file.buffer);
652
+ return fn(root);
653
+ } finally {
654
+ rmSync(stagingParent, { recursive: true, force: true });
655
+ }
656
+ }
657
+
658
+ function prepareExtensionPackages(
659
+ targets: ReadonlyArray<ShareImportPreparedTarget>,
660
+ options: ShareImportOptions,
661
+ ): { packages: ShareImportPreparedExtensionPackage[]; diagnostics: ShareDiagnostic[] } {
662
+ const diagnostics: ShareDiagnostic[] = [];
663
+ const grouped = new Map<string, Omit<ShareImportPreparedExtensionPackage, "contentDigest" | "install">>();
664
+ for (const target of targets) {
665
+ if (target.entry.type !== "extension") continue;
666
+ const segments = relativePathSegments(target.entry.relativePath);
667
+ const id = segments?.[0];
668
+ const packagePath = segments?.slice(1).join("/");
669
+ if (!id || !packagePath) {
670
+ diagnostics.push({
671
+ type: "error",
672
+ message: `extension archive path must be <id>/<package-path>: ${pathDiagnostic(target.entry)}`,
673
+ path: target.entry.relativePath,
674
+ });
675
+ continue;
676
+ }
677
+ const scope = target.scope as ExtensionScope;
678
+ const key = `${scope}\0${id}`;
679
+ const group = grouped.get(key) ?? { id, scope, files: [] };
680
+ if (group.files.some((file) => file.relativePath === packagePath)) {
681
+ diagnostics.push({ type: "error", message: `duplicate extension archive path ${target.entry.relativePath}` });
682
+ continue;
683
+ }
684
+ group.files.push({ relativePath: packagePath, buffer: target.buffer });
685
+ grouped.set(key, group);
686
+ }
687
+
688
+ const packages: ShareImportPreparedExtensionPackage[] = [];
689
+ for (const group of [...grouped.values()].sort((a, b) => `${a.scope}/${a.id}`.localeCompare(`${b.scope}/${b.id}`))) {
690
+ try {
691
+ const contentDigest = withStagedExtensionPackage(group, (root) => {
692
+ const candidate = loadManifestFromRoot(root);
693
+ if (!candidate.valid || !candidate.manifest) {
694
+ throw new Error(candidate.diagnostics.map((diagnostic) => diagnostic.message).join("; ") || "manifest is invalid");
695
+ }
696
+ if (candidate.manifest.id !== group.id) {
697
+ throw new Error(`manifest id ${candidate.manifest.id} does not match archive package ${group.id}`);
698
+ }
699
+ return extensionContentDigest(root);
700
+ });
701
+ const cwd = path.resolve(options.cwd ?? process.cwd());
702
+ const targetRoot = path.join(extensionBaseDir(group.scope, cwd), group.id);
703
+ const existing = listInstalledExtensions(cwd, { scope: group.scope, all: true }).find(
704
+ (extension) => extension.id === group.id && extension.rootPath === targetRoot,
705
+ );
706
+ const alreadyVerified =
707
+ existing?.valid === true &&
708
+ existing.provenance?.contentDigest === contentDigest &&
709
+ existing.observedContentDigest === contentDigest;
710
+ if (existsSync(targetRoot) && !alreadyVerified && !options.force) {
711
+ diagnostics.push({
712
+ type: "conflict",
713
+ message: `extension ${group.id} is not already installed with the archive's verified digest; re-run with --force to use the canonical installer`,
714
+ path: targetRoot,
715
+ });
716
+ }
717
+ packages.push({ ...group, contentDigest, install: !alreadyVerified });
718
+ } catch (error) {
719
+ diagnostics.push({
720
+ type: "error",
721
+ message: `extension ${group.id} in share archive is invalid: ${error instanceof Error ? error.message : String(error)}`,
722
+ });
723
+ }
724
+ }
725
+ return { packages, diagnostics };
726
+ }
727
+
611
728
  function versionDiagnostics(archive: ClioShareArchive): ShareDiagnostic[] {
612
729
  const current = readClioVersion();
613
730
  const [curMajor, curMinor] = current.split(".");
@@ -657,13 +774,20 @@ function prepareShareImport(filePath: string, options: ShareImportOptions = {}):
657
774
  actions: [],
658
775
  diagnostics: [{ type: "error", message: err instanceof Error ? err.message : String(err), path: filePath }],
659
776
  targets: [],
777
+ extensionPackages: [],
660
778
  };
661
779
  }
662
780
  const diagnostics: ShareDiagnostic[] = [...versionDiagnostics(archive)];
663
781
  const actions: ShareImportAction[] = [];
664
782
  const preflight = preflightImportTargets(archive, options);
665
783
  if (preflight.diagnostics.length > 0) {
666
- return { archive, actions: [], diagnostics: [...diagnostics, ...preflight.diagnostics], targets: [] };
784
+ return {
785
+ archive,
786
+ actions: [],
787
+ diagnostics: [...diagnostics, ...preflight.diagnostics],
788
+ targets: [],
789
+ extensionPackages: [],
790
+ };
667
791
  }
668
792
  for (const targetInfo of preflight.targets) {
669
793
  const { entry, target, scope, buffer } = targetInfo;
@@ -706,7 +830,9 @@ function prepareShareImport(filePath: string, options: ShareImportOptions = {}):
706
830
  }
707
831
  actions.push({ action: "write", type: entry.type, scope, path: target });
708
832
  }
709
- return { archive, actions, diagnostics, targets: preflight.targets };
833
+ const extensions = prepareExtensionPackages(preflight.targets, options);
834
+ diagnostics.push(...extensions.diagnostics);
835
+ return { archive, actions, diagnostics, targets: preflight.targets, extensionPackages: extensions.packages };
710
836
  }
711
837
 
712
838
  function publicImportPlan(prepared: ShareImportPreparedPlan, recovery?: ShareImportRecovery): ShareImportPlan {
@@ -750,10 +876,41 @@ export function importShareArchive(filePath: string, options: ShareImportOptions
750
876
  };
751
877
  let failed: string | undefined;
752
878
  try {
879
+ for (const extensionPackage of prepared.extensionPackages) {
880
+ if (!extensionPackage.install) continue;
881
+ const cwd = path.resolve(options.cwd ?? process.cwd());
882
+ failed = path.join(extensionBaseDir(extensionPackage.scope, cwd), extensionPackage.id);
883
+ const result = withStagedExtensionPackage(extensionPackage, (root) =>
884
+ installExtension(root, {
885
+ cwd,
886
+ scope: extensionPackage.scope,
887
+ ...(options.force !== undefined ? { force: options.force } : {}),
888
+ }),
889
+ );
890
+ for (const backup of [result.recovery?.stateBackup, result.recovery?.packageBackup]) {
891
+ if (backup && !backups.includes(backup)) backups.push(backup);
892
+ }
893
+ const errors = result.diagnostics.filter((diagnostic) => diagnostic.type === "error");
894
+ if (!result.extension || errors.length > 0) {
895
+ throw new Error(errors.map((diagnostic) => diagnostic.message).join("; ") || "canonical install failed");
896
+ }
897
+ if (result.extension.provenance?.contentDigest !== extensionPackage.contentDigest) {
898
+ throw new Error(`canonical install digest mismatch for extension ${extensionPackage.id}`);
899
+ }
900
+ for (const diagnostic of result.diagnostics) {
901
+ prepared.diagnostics.push({
902
+ type: "warning",
903
+ message: diagnostic.message,
904
+ ...(diagnostic.path ? { path: diagnostic.path } : {}),
905
+ });
906
+ }
907
+ if (!written.includes(result.extension.rootPath)) written.push(result.extension.rootPath);
908
+ failed = undefined;
909
+ }
753
910
  for (let index = 0; index < prepared.targets.length; index += 1) {
754
911
  const targetInfo = prepared.targets[index];
755
912
  const action = prepared.actions[index];
756
- if (!targetInfo || !action || action.action === "skip") continue;
913
+ if (!targetInfo || !action || action.action === "skip" || targetInfo.entry.type === "extension") continue;
757
914
  failed = targetInfo.target;
758
915
  if (targetInfo.entry.type === "settings") {
759
916
  const path = mergeSettingsFragment(targetInfo.buffer);
@@ -768,7 +925,7 @@ export function importShareArchive(filePath: string, options: ShareImportOptions
768
925
  );
769
926
  failed = undefined;
770
927
  }
771
- return plan;
928
+ return publicImportPlan(prepared, backups.length > 0 ? { written, backups } : undefined);
772
929
  } catch (err) {
773
930
  if (failed) {
774
931
  const expectedBackup = safeResourceBackupPath(failed);
@@ -787,7 +944,7 @@ export function importShareArchive(filePath: string, options: ShareImportOptions
787
944
  ...prepared.diagnostics,
788
945
  {
789
946
  type: "error",
790
- message: `share import failed while writing${failed ? ` ${failed}` : ""}: ${reason}`,
947
+ message: `share import failed${failed ? ` while importing ${failed}` : ""}: ${reason}`,
791
948
  ...(failed ? { path: failed } : {}),
792
949
  },
793
950
  ],
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { realpathSync } from "node:fs";
3
3
  import { isAbsolute, resolve as resolvePath } from "node:path";
4
4
  import {
5
+ type AccountabilityEvidenceReadyPayload,
5
6
  BusChannels,
6
7
  type DispatchCompletedPayload,
7
8
  type DispatchEnqueuedPayload,
@@ -209,6 +210,8 @@ interface AcpServerUsage {
209
210
  cacheRead: number;
210
211
  cacheWrite: number;
211
212
  reasoning: number;
213
+ totalTokens: number;
214
+ costUsd: number;
212
215
  }
213
216
 
214
217
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -333,7 +336,10 @@ const ACP_MAX_REPLAY_TOOL_CALLS = 8192;
333
336
  * the list is the allowlist, and a client's requested kinds are intersected
334
337
  * with it rather than trusted. `safety.loopBlocked` was the first member; the
335
338
  * dispatch lifecycle joined it so a client can draw a live fleet board from
336
- * reported facts instead of inferring one from tool titles or timing.
339
+ * reported facts instead of inferring one from tool titles or timing;
340
+ * `accountability.evidenceReady` follows a run's terminal event once its
341
+ * evidence bundle has landed, so the board can show first-pass success and a
342
+ * finding count without reading Clio's state tree.
337
343
  */
338
344
  const ACP_FORWARDABLE_EVENT_KINDS = [
339
345
  "safety.loopBlocked",
@@ -342,6 +348,7 @@ const ACP_FORWARDABLE_EVENT_KINDS = [
342
348
  "dispatch.progress",
343
349
  "dispatch.completed",
344
350
  "dispatch.failed",
351
+ "accountability.evidenceReady",
345
352
  ] as const;
346
353
 
347
354
  type AcpForwardableEventKind = (typeof ACP_FORWARDABLE_EVENT_KINDS)[number];
@@ -359,6 +366,9 @@ const ACP_MAX_DISPATCH_TASK_PREVIEW_BYTES = 160;
359
366
 
360
367
  /** Wire bound for the short identifiers a dispatch event carries. */
361
368
  const ACP_MAX_DISPATCH_ID_BYTES = 128;
369
+ /** Evidence tags are a closed vocabulary of short identifiers; anything wider is not a tag. */
370
+ const ACP_MAX_EVIDENCE_TAGS = 32;
371
+ const ACP_MAX_EVIDENCE_TAG_BYTES = 64;
362
372
 
363
373
  /**
364
374
  * Progress events forwarded per run before the stream is capped. One run
@@ -521,8 +531,8 @@ function utf8Bytes(value: string): number {
521
531
  return Buffer.byteLength(value, "utf8");
522
532
  }
523
533
 
524
- function emptyUsage(): AcpServerUsage {
525
- return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0 };
534
+ export function emptyUsage(): AcpServerUsage {
535
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, totalTokens: 0, costUsd: 0 };
526
536
  }
527
537
 
528
538
  function createActivePromptState(): ActivePrompt {
@@ -552,15 +562,33 @@ function finite(value: unknown): number {
552
562
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
553
563
  }
554
564
 
555
- function mergeUsage(into: AcpServerUsage, usage: unknown): void {
565
+ /** Only field `sumRunUsage` (chat-loop-messages.ts) reads for a dollar figure; matched here so ACP never re-derives cost through a separate path. */
566
+ function costTotal(usage: Record<string, unknown>): number {
567
+ const cost = usage.cost;
568
+ return isRecord(cost) ? finite(cost.total) : 0;
569
+ }
570
+
571
+ export function mergeUsage(into: AcpServerUsage, usage: unknown): void {
556
572
  if (!isRecord(usage)) return;
557
- into.input +=
573
+ const input =
558
574
  finite(usage.input) + finite(usage.inputTokens) + finite(usage.input_tokens) + finite(usage.prompt_tokens);
559
- into.output +=
575
+ const output =
560
576
  finite(usage.output) + finite(usage.outputTokens) + finite(usage.output_tokens) + finite(usage.completion_tokens);
561
- into.cacheRead += finite(usage.cacheRead) + finite(usage.cacheReadTokens) + finite(usage.cache_read_tokens);
562
- into.cacheWrite += finite(usage.cacheWrite) + finite(usage.cacheWriteTokens) + finite(usage.cache_write_tokens);
563
- into.reasoning += finite(usage.reasoning) + finite(usage.reasoningTokens) + finite(usage.reasoning_tokens);
577
+ const cacheRead = finite(usage.cacheRead) + finite(usage.cacheReadTokens) + finite(usage.cache_read_tokens);
578
+ const cacheWrite = finite(usage.cacheWrite) + finite(usage.cacheWriteTokens) + finite(usage.cache_write_tokens);
579
+ const reasoning = finite(usage.reasoning) + finite(usage.reasoningTokens) + finite(usage.reasoning_tokens);
580
+ into.input += input;
581
+ into.output += output;
582
+ into.cacheRead += cacheRead;
583
+ into.cacheWrite += cacheWrite;
584
+ into.reasoning += reasoning;
585
+ // Same fallback sumRunUsage uses: prefer the provider's own total, otherwise
586
+ // sum the four merged categories for this message (reasoning excluded,
587
+ // matching sumRunUsage, since a provider that reports reasoning separately
588
+ // still counts it inside output for billing).
589
+ const explicitTotal = finite(usage.totalTokens) + finite(usage.total_tokens);
590
+ into.totalTokens += explicitTotal > 0 ? explicitTotal : input + output + cacheRead + cacheWrite;
591
+ into.costUsd += costTotal(usage);
564
592
  }
565
593
 
566
594
  function mergeMessageUsage(into: AcpServerUsage, message: unknown, seen?: WeakSet<object>): void {
@@ -1857,6 +1885,29 @@ export async function serveClioAcpAgent(options: ClioAcpServerOptions): Promise<
1857
1885
  });
1858
1886
  }),
1859
1887
  );
1888
+ unsubscribeEvents.push(
1889
+ bus.on(BusChannels.AccountabilityEvidenceReady, (payload: AccountabilityEvidenceReadyPayload) => {
1890
+ // Arrives after dispatch.completed or dispatch.failed for the same run,
1891
+ // so it is terminal too: nothing about that run follows it. The
1892
+ // bundle's prose (findings, overview) stays behind; only the summary
1893
+ // counters the projection itself carries cross, and the tags are
1894
+ // filtered to bounded identifiers rather than truncated into new ones.
1895
+ const runId = safeStoredIdentifier(payload.runId, ACP_MAX_DISPATCH_ID_BYTES);
1896
+ const evidenceId = safeStoredIdentifier(payload.evidenceId, ACP_MAX_DISPATCH_ID_BYTES);
1897
+ if (runId === null || evidenceId === null) return;
1898
+ const tags = (Array.isArray(payload.tags) ? payload.tags : [])
1899
+ .map((tag) => safeStoredIdentifier(tag, ACP_MAX_EVIDENCE_TAG_BYTES))
1900
+ .filter((tag): tag is string => tag !== null)
1901
+ .slice(0, ACP_MAX_EVIDENCE_TAGS);
1902
+ forwardEvent("accountability.evidenceReady", null, true, {
1903
+ runId,
1904
+ evidenceId,
1905
+ firstPassSuccess: payload.firstPassSuccess === true,
1906
+ findingCount: safeCount(payload.findingCount),
1907
+ tags,
1908
+ });
1909
+ }),
1910
+ );
1860
1911
  }
1861
1912
  const unsubscribeEventStream = (): void => {
1862
1913
  for (const unsubscribe of unsubscribeEvents) unsubscribe();
@@ -2607,6 +2658,8 @@ function promptResponse(stopReason: string, active: ActivePrompt): AcpPromptResp
2607
2658
  cacheRead: active.usage.cacheRead,
2608
2659
  cacheWrite: active.usage.cacheWrite,
2609
2660
  reasoning: active.usage.reasoning,
2661
+ totalTokens: active.usage.totalTokens,
2662
+ costUsd: active.usage.costUsd,
2610
2663
  },
2611
2664
  },
2612
2665
  };
@@ -5,7 +5,6 @@ import {
5
5
  type ResidencyAdapter,
6
6
  ResidencyPreconditionError,
7
7
  reconcileResidency,
8
- residencyManaged,
9
8
  residentTagProtected,
10
9
  } from "./residency.js";
11
10
 
@@ -27,8 +26,8 @@ export interface LlamaCppResidencyInput {
27
26
  runtimeId: string;
28
27
  keepModelId: string;
29
28
  /**
30
- * Combined env + target lifecycle opt-out verdict from the caller
31
- * (residencyManagedFor). Defaults to the env-only switch.
29
+ * Target lifecycle verdict from the caller (residencyManagedFor). Defaults
30
+ * to managed for direct adapter callers.
32
31
  */
33
32
  managed?: boolean;
34
33
  fetchImpl?: typeof fetch;
@@ -284,7 +283,7 @@ export async function ensureLlamaCppResidency(input: LlamaCppResidencyInput): Pr
284
283
  targetId: input.targetId,
285
284
  runtimeId: input.runtimeId,
286
285
  keepModelId: input.keepModelId,
287
- managed: input.managed ?? residencyManaged(),
286
+ managed: input.managed ?? true,
288
287
  strategy: "router",
289
288
  listResident: async () => {
290
289
  const models = await fetchRouterModels(input, fetchImpl);
@@ -16,7 +16,7 @@ import { emitResidencyMutation, emitResidencyNotice, reconcileResidency, residen
16
16
  import { withResidencyLock } from "./residency-lock.js";
17
17
 
18
18
  interface LmStudioModelMetadata {
19
- clio?: {
19
+ clioCoder?: {
20
20
  targetId: string;
21
21
  runtimeId: string;
22
22
  lifecycle?: "user-managed" | "clio-coder-managed";
@@ -42,8 +42,8 @@ function responseInstanceId(data: unknown): string | undefined {
42
42
  return typeof id === "string" && id.trim().length > 0 ? id.trim() : undefined;
43
43
  }
44
44
 
45
- function metadata(model: Model<Api>): NonNullable<LmStudioModelMetadata["clio"]> | undefined {
46
- return (model as Model<Api> & LmStudioModelMetadata).clio;
45
+ function metadata(model: Model<Api>): NonNullable<LmStudioModelMetadata["clioCoder"]> | undefined {
46
+ return (model as Model<Api> & LmStudioModelMetadata).clioCoder;
47
47
  }
48
48
 
49
49
  function targetForModel(model: Model<"openai-completions">): TargetDescriptor | null {
@@ -32,7 +32,7 @@ import {
32
32
  } from "../../domains/providers/index.js";
33
33
  import type { LocalModelQuirks, SamplingProfile } from "../../domains/providers/types/local-model-quirks.js";
34
34
  import { calculateEngineCost } from "../ai.js";
35
- import { createGemmaChannelFilter } from "../gemma-channel-filter.js";
35
+ import { createGemmaChannelFilter, usesGemmaChannelMarkers } from "../gemma-channel-filter.js";
36
36
  import { createSentinelStripper } from "../strip-tokenizer-sentinels.js";
37
37
  import { remainingContextMaxTokens } from "./output-budget.js";
38
38
  import { type ResidencyAdapter, reconcileResidency, residencyManagedFor } from "./residency.js";
@@ -43,7 +43,7 @@ import type { EngineApiProvider } from "./types.js";
43
43
  const REASONING_CHARS_PER_TOKEN = 4;
44
44
 
45
45
  interface ClioRuntimeMetadata {
46
- clio?: {
46
+ clioCoder?: {
47
47
  targetId: string;
48
48
  runtimeId: string;
49
49
  /** Present only when settings set the target lifecycle explicitly. */
@@ -55,11 +55,11 @@ interface ClioRuntimeMetadata {
55
55
  }
56
56
 
57
57
  function clioQuirks(model: Model<"ollama-native">): LocalModelQuirks | undefined {
58
- return (model as Model<"ollama-native"> & ClioRuntimeMetadata).clio?.quirks;
58
+ return (model as Model<"ollama-native"> & ClioRuntimeMetadata).clioCoder?.quirks;
59
59
  }
60
60
 
61
61
  function ollamaTargetId(model: Model<"ollama-native">): string {
62
- return (model as Model<"ollama-native"> & ClioRuntimeMetadata).clio?.targetId ?? model.provider;
62
+ return (model as Model<"ollama-native"> & ClioRuntimeMetadata).clioCoder?.targetId ?? model.provider;
63
63
  }
64
64
 
65
65
  /**
@@ -74,7 +74,7 @@ function ollamaTargetId(model: Model<"ollama-native">): string {
74
74
  async function reconcileOllamaResidency(model: Model<"ollama-native">, headers: Record<string, string>): Promise<void> {
75
75
  const baseUrl = model.baseUrl;
76
76
  if (!baseUrl) return;
77
- const metadata = (model as Model<"ollama-native"> & ClioRuntimeMetadata).clio;
77
+ const metadata = (model as Model<"ollama-native"> & ClioRuntimeMetadata).clioCoder;
78
78
  const adapter: ResidencyAdapter = {
79
79
  targetKey: residencyTargetKey("ollama-native", baseUrl),
80
80
  targetId: ollamaTargetId(model),
@@ -384,7 +384,7 @@ function runStream(
384
384
  let doneReason: string | undefined;
385
385
  const sentinelStripper = createSentinelStripper();
386
386
  const resolved = resolveModelRuntimeCapabilitiesForModel(model, thinkingLevel);
387
- const channelFilter = resolved.family === "gemma-4" ? createGemmaChannelFilter() : null;
387
+ const channelFilter = usesGemmaChannelMarkers(resolved.modelId) ? createGemmaChannelFilter() : null;
388
388
  const closeActiveThinking = () => {
389
389
  if (!activeThinking) return;
390
390
  stream.push({
@@ -28,12 +28,12 @@ import { lmStudioReasoningEffort } from "../../domains/providers/runtimes/common
28
28
  import type { ThinkingLevel } from "../../domains/providers/types/capability-flags.js";
29
29
  import type { LocalModelQuirks, SamplingProfile } from "../../domains/providers/types/local-model-quirks.js";
30
30
  import type { LmStudioTargetSettings } from "../../domains/providers/types/target-descriptor.js";
31
- import { filterGemmaChannelStream } from "../gemma-channel-filter.js";
31
+ import { filterGemmaChannelStream, usesGemmaChannelMarkers } from "../gemma-channel-filter.js";
32
32
  import { HarmonyResponseParser } from "../harmony-response.js";
33
33
  import { createSentinelStripper, stripTokenizerSentinels } from "../strip-tokenizer-sentinels.js";
34
34
  import { ensureLlamaCppResidency } from "./llamacpp-residency.js";
35
35
  import { ensureLmStudioResidency } from "./lmstudio.js";
36
- import { LOCAL_TOOL_TURN_MAX_OUTPUT_TOKENS, remainingContextMaxTokens } from "./output-budget.js";
36
+ import { remainingContextMaxTokens } from "./output-budget.js";
37
37
  import { residencyManagedFor } from "./residency.js";
38
38
  import { mergeSamplingOverride } from "./sampling-overrides.js";
39
39
  import type { EngineApiProvider } from "./types.js";
@@ -60,7 +60,7 @@ const REASONING_CHARS_PER_TOKEN = 4;
60
60
  export { estimateInputTokensFromContext, remainingContextMaxTokens } from "./output-budget.js";
61
61
 
62
62
  interface ClioRuntimeMetadata {
63
- clio?: {
63
+ clioCoder?: {
64
64
  targetId: string;
65
65
  runtimeId: string;
66
66
  /** Present only when settings set the target lifecycle explicitly. */
@@ -75,11 +75,11 @@ interface ClioRuntimeMetadata {
75
75
  }
76
76
 
77
77
  function chatTemplateKwargsUnsupported(model: Model<Api>): boolean {
78
- return (model as Model<Api> & ClioRuntimeMetadata).clio?.chatTemplateKwargsUnsupported === true;
78
+ return (model as Model<Api> & ClioRuntimeMetadata).clioCoder?.chatTemplateKwargsUnsupported === true;
79
79
  }
80
80
 
81
81
  function clioQuirks(model: Model<"openai-completions">): LocalModelQuirks | undefined {
82
- return (model as Model<"openai-completions"> & ClioRuntimeMetadata).clio?.quirks;
82
+ return (model as Model<"openai-completions"> & ClioRuntimeMetadata).clioCoder?.quirks;
83
83
  }
84
84
 
85
85
  function pickSamplingProfile(
@@ -138,7 +138,7 @@ function backendCompletionTimings(value: unknown, source: BackendTimingsSource):
138
138
  }
139
139
 
140
140
  function backendTimingsSourceForModel(model: Model<Api>): BackendTimingsSource | null {
141
- const metadata = (model as Model<Api> & ClioRuntimeMetadata).clio;
141
+ const metadata = (model as Model<Api> & ClioRuntimeMetadata).clioCoder;
142
142
  if (model.provider === "llamacpp" && metadata?.runtimeId === "llamacpp") return "llamacpp-timings";
143
143
  if (model.provider === "lmstudio" && metadata?.runtimeId === "lmstudio") return "lmstudio-timings";
144
144
  return null;
@@ -371,8 +371,23 @@ function applyThinkingPayload(
371
371
  resolved: ResolvedModelRuntimeCapabilities,
372
372
  model: Model<Api>,
373
373
  ): Record<string, unknown> {
374
- if (applied.mechanism === "none") return stripThinkingRequestFields(payload);
375
- if (applied.mechanism === "always-on") return payload;
374
+ if (applied.mechanism === "none") {
375
+ const next = stripThinkingRequestFields(payload);
376
+ if (resolved.request.chatTemplateKwargs && !chatTemplateKwargsUnsupported(model)) {
377
+ const existing = isPlainRecord(next.chat_template_kwargs) ? next.chat_template_kwargs : {};
378
+ next.chat_template_kwargs = { ...existing, ...resolved.request.chatTemplateKwargs };
379
+ }
380
+ return next;
381
+ }
382
+ if (applied.mechanism === "always-on") {
383
+ if (resolved.request.chatTemplateKwargs && !chatTemplateKwargsUnsupported(model)) {
384
+ const next: Record<string, unknown> = { ...payload };
385
+ const existing = isPlainRecord(next.chat_template_kwargs) ? next.chat_template_kwargs : {};
386
+ next.chat_template_kwargs = { ...existing, ...resolved.request.chatTemplateKwargs };
387
+ return next;
388
+ }
389
+ return payload;
390
+ }
376
391
  const next: Record<string, unknown> = { ...payload };
377
392
  if (
378
393
  resolved.request.reasoningEffort &&
@@ -563,21 +578,9 @@ function withRemainingContextBudget<TOptions extends StreamOptions>(
563
578
  context: Context,
564
579
  options: TOptions | undefined,
565
580
  ): TOptions {
566
- const metadata = runtimeMetadata(model);
567
- const localToolOutputLimit =
568
- options?.maxTokens === undefined &&
569
- (context.tools?.length ?? 0) > 0 &&
570
- (model.provider === "llamacpp" || metadata?.runtimeId === "llamacpp")
571
- ? LOCAL_TOOL_TURN_MAX_OUTPUT_TOKENS
572
- : undefined;
573
581
  return {
574
582
  ...(options ?? {}),
575
- maxTokens: remainingContextMaxTokens(
576
- model,
577
- context,
578
- options,
579
- localToolOutputLimit === undefined ? undefined : { maxOutputTokens: localToolOutputLimit },
580
- ),
583
+ maxTokens: remainingContextMaxTokens(model, context, options),
581
584
  } as TOptions;
582
585
  }
583
586
 
@@ -593,8 +596,8 @@ function hasEmptyArguments(args: Record<string, unknown>): boolean {
593
596
  return Object.keys(args).length === 0;
594
597
  }
595
598
 
596
- function runtimeMetadata(model: Model<Api>): NonNullable<ClioRuntimeMetadata["clio"]> | undefined {
597
- return (model as Model<Api> & ClioRuntimeMetadata).clio;
599
+ function runtimeMetadata(model: Model<Api>): NonNullable<ClioRuntimeMetadata["clioCoder"]> | undefined {
600
+ return (model as Model<Api> & ClioRuntimeMetadata).clioCoder;
598
601
  }
599
602
 
600
603
  function emptyErrorMessage(model: Model<"openai-completions">, message: string): AssistantMessage {
@@ -936,7 +939,7 @@ export const openAICompletionsApiProvider: EngineApiProvider<"openai-completions
936
939
  (requestModel) => piOpenAICompletions.stream(requestModel, effectiveContext, capturedOptions),
937
940
  ),
938
941
  ),
939
- resolved.family === "gemma-4",
942
+ usesGemmaChannelMarkers(resolved.modelId),
940
943
  ),
941
944
  resolved,
942
945
  ),
@@ -969,7 +972,7 @@ export const openAICompletionsApiProvider: EngineApiProvider<"openai-completions
969
972
  (requestModel) => piOpenAICompletions.streamSimple(requestModel, effectiveContext, capturedOptions),
970
973
  ),
971
974
  ),
972
- resolved.family === "gemma-4",
975
+ usesGemmaChannelMarkers(resolved.modelId),
973
976
  ),
974
977
  resolved,
975
978
  ),
@@ -13,7 +13,7 @@ const DEFAULT_MAX_OUTPUT_TOKENS = CLIO_MIN_MAX_OUTPUT_TOKENS;
13
13
 
14
14
  /**
15
15
  * Process-wide default output budget requested per turn, sourced from
16
- * settings.defaults.maxTokens at session start (see
16
+ * chat.maxOutputTokens at session start (see
17
17
  * {@link setGlobalDefaultMaxOutputTokens}). 0 means unset: callers fall back to
18
18
  * the model's advertised cap as before.
19
19
  */
@@ -30,19 +30,6 @@ export function setGlobalDefaultMaxOutputTokens(value: number): void {
30
30
  globalDefaultMaxOutputTokens = Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
31
31
  }
32
32
 
33
- /**
34
- * Output ceiling applied to a llama.cpp tool-bearing turn when the caller did
35
- * not request an explicit limit. It bounds a genuinely runaway local
36
- * generation without muzzling real work: a single tool call that writes a
37
- * sizable file (a full HTML page, a multi-function source module) needs far
38
- * more than a few thousand tokens of argument, and the tool-call argument
39
- * counts against this same response budget. Narration loops where a local
40
- * model keeps saying it will call a tool without emitting one are caught
41
- * separately by assessToolProseLoop, so this number only has to be large
42
- * enough to let legitimate large outputs through.
43
- */
44
- export const LOCAL_TOOL_TURN_MAX_OUTPUT_TOKENS = CLIO_MIN_MAX_OUTPUT_TOKENS;
45
-
46
33
  /**
47
34
  * Tokens a preflight context check should hold back for the response: the
48
35
  * smaller of the model's advertised output limit and the default output
@@ -84,15 +71,18 @@ export function remainingContextMaxTokens(
84
71
  const modelLimit = model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY;
85
72
  // Precedence for the requested ceiling when the caller gave no explicit
86
73
  // maxTokens: a more-specific tool-turn limit, then the global default, then
87
- // the model's advertised cap. Math.min below clamps the result down to the
88
- // model cap and the remaining context budget regardless, so the global
89
- // default never lets a small model overshoot what it supports.
74
+ // the model's advertised cap. A model that advertises no cap uses the product
75
+ // floor instead of requesting its entire remaining context window. Math.min
76
+ // below clamps the result down to every known boundary, so frontier providers
77
+ // with a known cap never receive a larger max_tokens value.
90
78
  const defaultLimit =
91
79
  limits?.maxOutputTokens !== undefined && limits.maxOutputTokens > 0
92
80
  ? limits.maxOutputTokens
93
81
  : globalDefaultMaxOutputTokens > 0
94
82
  ? globalDefaultMaxOutputTokens
95
- : modelLimit;
83
+ : model.maxTokens > 0
84
+ ? modelLimit
85
+ : DEFAULT_MAX_OUTPUT_TOKENS;
96
86
  const requested = options?.maxTokens ?? defaultLimit;
97
87
  const resolved = Math.min(requested, modelLimit, budget);
98
88
  return Number.isFinite(resolved) ? resolved : DEFAULT_MAX_OUTPUT_TOKENS;