@iowarp/clio-coder 0.3.7 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +13 -4
  3. package/dist/{acp-SK4MD6MM.js → acp-7LOELQFP.js} +13 -13
  4. package/dist/{agents-2FN2K6ME.js → agents-FIBG2SHA.js} +41 -37
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-QIYZWM5I.js → auth-OI4LIH2I.js} +31 -24
  7. package/dist/builtins-AD25UL3C.js +17 -0
  8. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  9. package/dist/chunk-3DPEIQKN.js +113 -0
  10. package/dist/{chunk-EOOQZZDE.js → chunk-3DUR4WUA.js} +19 -19
  11. package/dist/{chunk-WHJYKASB.js → chunk-3MRC2YSQ.js} +2 -2
  12. package/dist/{chunk-EBEFWSGL.js → chunk-3UUY7R3Z.js} +14 -10
  13. package/dist/{chunk-LADCF22A.js → chunk-3V5AYSEQ.js} +113 -54
  14. package/dist/{chunk-BMWK7ZIZ.js → chunk-465CC7FK.js} +16 -13
  15. package/dist/{chunk-5WIGXA4T.js → chunk-47CMYGET.js} +111 -4
  16. package/dist/{chunk-CEYBNUGC.js → chunk-4H6ULJ3H.js} +378 -36
  17. package/dist/{chunk-YTYFXUI3.js → chunk-4LJX2PUC.js} +9 -9
  18. package/dist/{chunk-DOOEX22V.js → chunk-56KB5IJP.js} +5 -5
  19. package/dist/{chunk-SPULKLCF.js → chunk-5DQRIYDZ.js} +2 -2
  20. package/dist/{chunk-TSHXZTOQ.js → chunk-5HFBWUMU.js} +23 -11
  21. package/dist/{chunk-5UJ6ECTS.js → chunk-5PVQ4SRS.js} +80 -8
  22. package/dist/{chunk-ZWLZP4ZT.js → chunk-5QKCQQ3E.js} +359 -17
  23. package/dist/{chunk-6M7VS3J3.js → chunk-5T7RBWN2.js} +111 -5
  24. package/dist/chunk-774ILSRL.js +172 -0
  25. package/dist/chunk-7C6RYZGQ.js +391 -0
  26. package/dist/{chunk-GH5622CP.js → chunk-A2NJGIB3.js} +2 -2
  27. package/dist/{chunk-C4JBQ5SR.js → chunk-AD7Y7STJ.js} +6 -6
  28. package/dist/{chunk-GEYXPTRF.js → chunk-AEYBF3TB.js} +33 -12
  29. package/dist/{chunk-2SFS6XQE.js → chunk-AMKHQW3C.js} +3 -2
  30. package/dist/{chunk-D4MDIG46.js → chunk-B5CSFE7B.js} +7 -7
  31. package/dist/{chunk-MXI6J5JF.js → chunk-B5XRQOLB.js} +10 -10
  32. package/dist/{chunk-X2KV5FXT.js → chunk-BVDVID7E.js} +2 -2
  33. package/dist/{chunk-JNXPYBB4.js → chunk-CA42X6KT.js} +3 -3
  34. package/dist/{chunk-VREKEFLL.js → chunk-D73KXYPF.js} +3 -3
  35. package/dist/{chunk-JTSEDYVQ.js → chunk-DG4M6ZUE.js} +7 -7
  36. package/dist/{chunk-DQA7QLMD.js → chunk-EBOC7MT3.js} +10 -25
  37. package/dist/{chunk-KZ2H5X4G.js → chunk-ECUO3KDP.js} +129 -14
  38. package/dist/{chunk-JRIO5UD2.js → chunk-EQ63NRB7.js} +5 -5
  39. package/dist/{chunk-YD734TPH.js → chunk-FALJGAWU.js} +2 -2
  40. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  41. package/dist/{chunk-XEGB6BCN.js → chunk-GAYUJ7LE.js} +68 -14
  42. package/dist/{chunk-UND3GU2L.js → chunk-H7IXIC72.js} +2 -2
  43. package/dist/{chunk-IR4CFBFN.js → chunk-HAY4ZE2P.js} +12 -12
  44. package/dist/{chunk-UVDSQ6LW.js → chunk-HCBCAYZU.js} +74 -147
  45. package/dist/{chunk-4DWFMQDR.js → chunk-HJB5IUKP.js} +89 -145
  46. package/dist/{chunk-M4AKACEO.js → chunk-HKO36JWF.js} +33 -5
  47. package/dist/{chunk-KCMKRQX4.js → chunk-HPCTNZM2.js} +45 -82
  48. package/dist/{chunk-465YSENW.js → chunk-IFBNV6H6.js} +3 -3
  49. package/dist/{chunk-FJ3H4MN5.js → chunk-IHKBWSXF.js} +2 -2
  50. package/dist/chunk-JEQQR47K.js +3025 -0
  51. package/dist/{chunk-FO5ZOVUY.js → chunk-KV2AOLDF.js} +27 -7
  52. package/dist/chunk-LU7P4LHA.js +33 -0
  53. package/dist/{chunk-6TUKSZVF.js → chunk-LXPJXFM5.js} +11 -11
  54. package/dist/{chunk-VQNODYQ4.js → chunk-MIX5N5AC.js} +488 -3668
  55. package/dist/chunk-MLOK6ZOS.js +2888 -0
  56. package/dist/{chunk-ZZMN5OM4.js → chunk-MV2VUEJC.js} +2 -2
  57. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  58. package/dist/{chunk-OBMAI2DP.js → chunk-N3PBVRTZ.js} +12 -388
  59. package/dist/{chunk-WJHBC77E.js → chunk-N5XKWMDW.js} +17 -7
  60. package/dist/{chunk-5C3AQNDW.js → chunk-NNNWO6F2.js} +124 -36
  61. package/dist/{chunk-UFQ3F4FW.js → chunk-NQ6UCCOD.js} +4 -4
  62. package/dist/chunk-NUGM5KR6.js +165 -0
  63. package/dist/{chunk-DMD2AGVS.js → chunk-NZU6YDNV.js} +20 -18
  64. package/dist/{chunk-WHGPSPT5.js → chunk-O6I4CIEU.js} +151 -13
  65. package/dist/{chunk-XN3L4EYL.js → chunk-OEDBCISO.js} +2 -2
  66. package/dist/{chunk-PD3MESLB.js → chunk-P3JGPQFL.js} +4 -4
  67. package/dist/{chunk-UHXRNZ2J.js → chunk-PNY46YEY.js} +23 -6
  68. package/dist/{chunk-THKY7CD7.js → chunk-PZ4I4JE2.js} +134 -29
  69. package/dist/{chunk-SROCI7ZU.js → chunk-QQ7EKM72.js} +5 -5
  70. package/dist/{chunk-QCTRSGHQ.js → chunk-R7LNVMCS.js} +91 -53
  71. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  72. package/dist/chunk-RKKLTLYB.js +45 -0
  73. package/dist/{chunk-OB5HIGJY.js → chunk-RKRLDWD3.js} +4 -1
  74. package/dist/{chunk-DJNLUABN.js → chunk-S4COXYBG.js} +588 -32
  75. package/dist/{chunk-3HAPLH5M.js → chunk-T3Z6VAAF.js} +172 -11
  76. package/dist/{chunk-FOT2FX5J.js → chunk-TD7UE2L5.js} +12 -10
  77. package/dist/{chunk-UUANF5CR.js → chunk-TEO2TLVN.js} +856 -967
  78. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  79. package/dist/{chunk-EELBMBT6.js → chunk-VKBMFOYV.js} +74 -15
  80. package/dist/chunk-VO2LKSTM.js +165 -0
  81. package/dist/{chunk-5C77SEEY.js → chunk-VPTUJU4P.js} +3 -3
  82. package/dist/{chunk-WEH5XRJQ.js → chunk-WIE7ZOSW.js} +2 -2
  83. package/dist/{chunk-J7PIKKWC.js → chunk-WXCJ7VME.js} +8 -8
  84. package/dist/{chunk-4DGYLA73.js → chunk-XDOQXGFO.js} +22 -7
  85. package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
  86. package/dist/{chunk-AB4XIIVB.js → chunk-YKOFT37S.js} +6 -6
  87. package/dist/chunk-YSEHGPCT.js +127 -0
  88. package/dist/{chunk-HFSBBKSQ.js → chunk-YW7UVM5V.js} +138 -3
  89. package/dist/cli/index.js +32 -32
  90. package/dist/{clio-WBVQEBKO.js → clio-LT5V7SSZ.js} +9 -9
  91. package/dist/{code-nav-FGGFIE7L.js → code-nav-LMW275PA.js} +5 -5
  92. package/dist/codewiki/build-worker.js +4 -4
  93. package/dist/{components-F7OEATSO.js → components-ZFA3SAER.js} +8 -8
  94. package/dist/{config-TRBL3RCF.js → config-RXS5T3JT.js} +98 -65
  95. package/dist/{configure-OLCVPHNM.js → configure-2WYWSCSD.js} +26 -22
  96. package/dist/{context-MJIJ6GOX.js → context-I3BTOTCS.js} +12 -12
  97. package/dist/{context-XEWE3MOJ.js → context-MVOORGMF.js} +54 -47
  98. package/dist/{context-WFPKQSM6.js → context-PALKKQYL.js} +28 -28
  99. package/dist/{context-clear-KNOS2JPB.js → context-clear-N2WOYZ2K.js} +53 -46
  100. package/dist/{context-index-SSR5ECNE.js → context-index-HNG3MOME.js} +6 -6
  101. package/dist/{context-working-set-EUXAZI6N.js → context-working-set-MIEVECVZ.js} +17 -18
  102. package/dist/{dispatch-runner-B7MTOVKL.js → dispatch-runner-VVA4SRRH.js} +90 -61
  103. package/dist/{docs-FLJTIDSE.js → docs-7LQ23DLM.js} +8 -8
  104. package/dist/doctor-TWBWFK5V.js +165 -0
  105. package/dist/eval-IJ5VEZDJ.js +4483 -0
  106. package/dist/{evidence-JZNBUOQZ.js → evidence-L5APPXNV.js} +68 -61
  107. package/dist/{evolve-FJVC4KKI.js → evolve-RGNKFJ52.js} +47 -40
  108. package/dist/{extensions-IQL36S7K.js → extensions-7WYWUX5A.js} +13 -7
  109. package/dist/{fleet-BDKYJFCP.js → fleet-6CNVBZZP.js} +113 -76
  110. package/dist/{fleet-commands-ZFIWZSB3.js → fleet-commands-L2SXSYEI.js} +10 -10
  111. package/dist/{fleet-graph-Y6HPXIVF.js → fleet-graph-2J3OOIPO.js} +17 -15
  112. package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-CZRJ4JP5.js} +5 -6
  113. package/dist/{fleet-validate-BIYREGIK.js → fleet-validate-C5RI6DP7.js} +20 -19
  114. package/dist/{init-LQUB5COQ.js → init-VBN2ACVA.js} +70 -63
  115. package/dist/{library-NJAHIGG4.js → library-JHGUMLY2.js} +22 -20
  116. package/dist/{memory-OG6HOYKM.js → memory-K4OQIYWG.js} +49 -42
  117. package/dist/{models-5ZG5XY7J.js → models-2NCZUWDD.js} +35 -29
  118. package/dist/{monitor-TJ7AMTGB.js → monitor-MMVTJABD.js} +64 -45
  119. package/dist/{orchestrator-WZYB54DM.js → orchestrator-ZKBPCHW6.js} +1971 -520
  120. package/dist/{paths-XUC7GS6E.js → paths-DBXMZMDU.js} +5 -5
  121. package/dist/registry-LG64LTF4.js +11 -0
  122. package/dist/{reset-PXQT45IY.js → reset-DD5JGOY3.js} +11 -11
  123. package/dist/{run-FQ74YF62.js → run-QEGNX7FL.js} +89 -83
  124. package/dist/{share-FW7SVCL3.js → share-JKD3BQMW.js} +20 -18
  125. package/dist/{skills-7E7IRB3R.js → skills-LMQIKDOZ.js} +23 -21
  126. package/dist/{skills-eval-LI75W6OK.js → skills-eval-I7X2774U.js} +59 -52
  127. package/dist/{steer-GGWFUJUD.js → steer-CF5TDANS.js} +3 -3
  128. package/dist/support-I7LOJLIF.js +38 -0
  129. package/dist/{targets-4CIFKCTW.js → targets-RUSR6B5Z.js} +77 -42
  130. package/dist/{terminal-lease-WUZY7ZV5.js → terminal-lease-QYVORFR4.js} +6 -4
  131. package/dist/{trace-PNCASAXC.js → trace-ODOQIVIW.js} +61 -6
  132. package/dist/{uninstall-7FV7IP4E.js → uninstall-ZJF5H5ZN.js} +8 -8
  133. package/dist/{upgrade-K2HVIVMQ.js → upgrade-XANW3FXB.js} +29 -26
  134. package/dist/{usage-GTZELZQX.js → usage-4H7ZRXQT.js} +110 -61
  135. package/dist/{verifiers-RLAHT27O.js → verifiers-UZXNBZEB.js} +13 -13
  136. package/dist/{verify-BX3BRKH5.js → verify-BVKWTNDL.js} +9 -9
  137. package/dist/{wiki-generate-ASIFASCN.js → wiki-generate-MY7WV2QI.js} +76 -69
  138. package/dist/worker/entry.js +69 -66
  139. package/docs/alcf-provider.md +1 -1
  140. package/docs/architecture.md +1 -1
  141. package/docs/artifact-versions.md +11 -5
  142. package/docs/built-in-agents.md +1 -1
  143. package/docs/capacity-and-scheduling.md +23 -2
  144. package/docs/commands-and-modes.md +2 -2
  145. package/docs/configuration-and-targets.md +37 -5
  146. package/docs/context-engine.md +63 -4
  147. package/docs/documentation-coverage.md +3 -3
  148. package/docs/documentation-guide.md +1 -1
  149. package/docs/environment-variables.md +2 -0
  150. package/docs/eval-runner.md +262 -11
  151. package/docs/evals-internal.md +72 -2
  152. package/docs/evidence-and-memory.md +77 -12
  153. package/docs/evolution.md +1 -1
  154. package/docs/extensions-and-sharing.md +3 -1
  155. package/docs/fleet-dispatch.md +34 -9
  156. package/docs/glossary.md +21 -1
  157. package/docs/installation-and-lifecycle.md +1 -1
  158. package/docs/middleware-and-components.md +1 -1
  159. package/docs/model-catalog.md +1 -1
  160. package/docs/observability.md +54 -3
  161. package/docs/proactive-memory.md +127 -14
  162. package/docs/prompt-envelope-and-tools.md +22 -2
  163. package/docs/provider-adapter-cookbook.md +1 -1
  164. package/docs/release-cut-checklist.md +60 -41
  165. package/docs/safety-model.md +1 -1
  166. package/docs/scientific-validation.md +1 -1
  167. package/docs/skills-marketplace.md +1 -1
  168. package/docs/tool-usage.md +1 -1
  169. package/docs/trace-store.md +1 -1
  170. package/docs/troubleshooting.md +87 -0
  171. package/docs/tui-design.md +1 -1
  172. package/docs/worker-dispatch-mechanics.md +1 -1
  173. package/package.json +2 -2
  174. package/src/cli/agents.ts +1 -1
  175. package/src/cli/argv.ts +5 -0
  176. package/src/cli/config-inspect.ts +33 -6
  177. package/src/cli/config.ts +1 -1
  178. package/src/cli/configure.ts +107 -23
  179. package/src/cli/doctor-state-size.ts +82 -0
  180. package/src/cli/doctor.ts +7 -1
  181. package/src/cli/eval.ts +80 -16
  182. package/src/cli/evidence.ts +30 -25
  183. package/src/cli/extensions.ts +5 -1
  184. package/src/cli/fleet-preflight.ts +2 -12
  185. package/src/cli/fleet.ts +32 -3
  186. package/src/cli/shared.ts +1 -0
  187. package/src/cli/targets.ts +45 -11
  188. package/src/cli/trace.ts +63 -4
  189. package/src/cli/usage.ts +63 -14
  190. package/src/cli/validate-model.ts +60 -5
  191. package/src/core/bus-events.ts +54 -1
  192. package/src/core/cache-telemetry.ts +42 -0
  193. package/src/core/commit-attribution.ts +4 -4
  194. package/src/core/config.ts +18 -0
  195. package/src/core/defaults.ts +36 -6
  196. package/src/core/endpoint-key.ts +27 -0
  197. package/src/core/path-boundary.ts +100 -0
  198. package/src/core/residency-target-key.ts +25 -0
  199. package/src/core/response-schema.ts +36 -2
  200. package/src/domains/agents/extension.ts +2 -11
  201. package/src/domains/agents/fleet-contract.ts +30 -12
  202. package/src/domains/agents/recipe.ts +7 -1
  203. package/src/domains/agents/registry.ts +73 -5
  204. package/src/domains/agents/result-contract.ts +128 -17
  205. package/src/domains/agents/write-boundary.ts +15 -50
  206. package/src/domains/config/classify.ts +3 -0
  207. package/src/domains/context/codewiki/coordinator.ts +12 -4
  208. package/src/domains/context/project-rules.ts +51 -1
  209. package/src/domains/dispatch/admission.ts +40 -3
  210. package/src/domains/dispatch/assignment-reconcile.ts +22 -5
  211. package/src/domains/dispatch/assignment-store.ts +151 -14
  212. package/src/domains/dispatch/capacity-lease.ts +98 -9
  213. package/src/domains/dispatch/contract.ts +26 -1
  214. package/src/domains/dispatch/delegation-plan.ts +2 -5
  215. package/src/domains/dispatch/execution-plan.ts +44 -4
  216. package/src/domains/dispatch/execution-role.ts +9 -1
  217. package/src/domains/dispatch/extension.ts +309 -96
  218. package/src/domains/dispatch/fleet-run.ts +78 -4
  219. package/src/domains/dispatch/gate-role-prompts.ts +38 -0
  220. package/src/domains/dispatch/heartbeat.ts +32 -8
  221. package/src/domains/dispatch/index.ts +6 -1
  222. package/src/domains/dispatch/intent-requirements.ts +40 -0
  223. package/src/domains/dispatch/intent.ts +84 -8
  224. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  225. package/src/domains/dispatch/path-scope.ts +370 -0
  226. package/src/domains/dispatch/receipt-integrity.ts +2 -1
  227. package/src/domains/dispatch/reservation-store.ts +116 -8
  228. package/src/domains/dispatch/state.ts +4 -0
  229. package/src/domains/dispatch/types.ts +14 -7
  230. package/src/domains/dispatch/validation.ts +6 -3
  231. package/src/domains/dispatch/worker-spawn.ts +25 -11
  232. package/src/domains/dispatch/write-boundary-enforcer.ts +62 -0
  233. package/src/domains/dispatch/write-boundary.ts +262 -22
  234. package/src/domains/eval/artifacts/store.ts +62 -0
  235. package/src/domains/eval/compare/behavioral.ts +224 -0
  236. package/src/domains/eval/compare/compare.ts +355 -2
  237. package/src/domains/eval/compare/envelope.ts +128 -0
  238. package/src/domains/eval/compare/gates.ts +24 -6
  239. package/src/domains/eval/compare/thresholds.ts +30 -3
  240. package/src/domains/eval/execution-provenance.ts +240 -0
  241. package/src/domains/eval/metrics/aggregate.ts +136 -0
  242. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  243. package/src/domains/eval/metrics/evidence.ts +79 -2
  244. package/src/domains/eval/metrics/tracked.ts +413 -0
  245. package/src/domains/eval/provenance.ts +117 -0
  246. package/src/domains/eval/reports/comparison.ts +128 -0
  247. package/src/domains/eval/reports/junit.ts +17 -3
  248. package/src/domains/eval/reports/markdown.ts +3 -3
  249. package/src/domains/eval/reports/text.ts +14 -0
  250. package/src/domains/eval/run-compare.ts +20 -0
  251. package/src/domains/eval/runners/clio-run.ts +139 -2
  252. package/src/domains/eval/runners/external-command.ts +28 -3
  253. package/src/domains/eval/schema/adapter.ts +111 -0
  254. package/src/domains/eval/schema/artifact.ts +20 -0
  255. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  256. package/src/domains/eval/schema/behavioral.ts +520 -0
  257. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  258. package/src/domains/eval/schema/serving.ts +74 -0
  259. package/src/domains/eval/schema/suite.ts +38 -8
  260. package/src/domains/eval/schema/validate.ts +58 -3
  261. package/src/domains/eval/schema/verdict.ts +237 -0
  262. package/src/domains/eval/suites/resolve.ts +2 -0
  263. package/src/domains/eval/suites/run.ts +264 -33
  264. package/src/domains/eval/verifiers/command.ts +2 -1
  265. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  266. package/src/domains/evidence/build.ts +68 -21
  267. package/src/domains/evidence/eval.ts +2 -12
  268. package/src/domains/evidence/findings-markdown.ts +33 -0
  269. package/src/domains/evidence/index.ts +21 -0
  270. package/src/domains/evidence/provenance.ts +46 -11
  271. package/src/domains/evidence/run-trust.ts +7 -113
  272. package/src/domains/evidence/trust-projection.ts +274 -0
  273. package/src/domains/evidence/trust-status.ts +145 -17
  274. package/src/domains/evidence/types.ts +4 -0
  275. package/src/domains/extensions/compatibility.ts +285 -0
  276. package/src/domains/extensions/discovery.ts +126 -4
  277. package/src/domains/extensions/resources.ts +21 -9
  278. package/src/domains/extensions/state.ts +18 -5
  279. package/src/domains/extensions/types.ts +6 -1
  280. package/src/domains/lifecycle/doctor.ts +209 -2
  281. package/src/domains/memory/index.ts +14 -0
  282. package/src/domains/memory/task-bank-promotion.ts +64 -0
  283. package/src/domains/memory/task-memory-policy.ts +77 -8
  284. package/src/domains/memory/task-memory-spend.ts +131 -0
  285. package/src/domains/memory/task-memory-status.ts +7 -0
  286. package/src/domains/memory/task-memory-telemetry.ts +2 -0
  287. package/src/domains/middleware/index.ts +1 -0
  288. package/src/domains/middleware/memory-intervention.ts +69 -5
  289. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  290. package/src/domains/observability/background-memory-usage.ts +140 -0
  291. package/src/domains/observability/cost.ts +1 -1
  292. package/src/domains/observability/index.ts +7 -0
  293. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  294. package/src/domains/observability/trace-store.ts +192 -2
  295. package/src/domains/prompts/compiler.ts +100 -13
  296. package/src/domains/prompts/contract.ts +3 -5
  297. package/src/domains/providers/endpoint-capacity.ts +96 -0
  298. package/src/domains/providers/extension.ts +30 -2
  299. package/src/domains/providers/index.ts +10 -0
  300. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  301. package/src/domains/providers/runtime-resolution.ts +8 -1
  302. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  303. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  304. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  305. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  306. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  307. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  308. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  309. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  310. package/src/domains/providers/types/capability-flags.ts +2 -0
  311. package/src/domains/providers/types/target-descriptor.ts +2 -0
  312. package/src/domains/resources/common-loader.ts +3 -0
  313. package/src/domains/resources/prompts/loader.ts +184 -17
  314. package/src/domains/safety/call-target.ts +52 -0
  315. package/src/domains/safety/policy-engine.ts +5 -5
  316. package/src/domains/safety/run-effects.ts +96 -2
  317. package/src/domains/safety/scope.ts +7 -12
  318. package/src/domains/session/context-accounting.ts +52 -1
  319. package/src/domains/session/context-ledger.ts +37 -13
  320. package/src/domains/session/index.ts +6 -0
  321. package/src/domains/session/prompt-cache.ts +140 -0
  322. package/src/domains/session/prompt-manifest.ts +42 -0
  323. package/src/engine/acp/adapter.ts +18 -3
  324. package/src/engine/acp/server.ts +4 -1
  325. package/src/engine/ai.ts +35 -0
  326. package/src/engine/apis/llamacpp-residency.ts +55 -3
  327. package/src/engine/apis/lmstudio.ts +25 -5
  328. package/src/engine/apis/ollama-native.ts +2 -1
  329. package/src/engine/apis/openai-completions.ts +80 -17
  330. package/src/engine/apis/residency-lock.ts +3 -1
  331. package/src/engine/apis/residency.ts +34 -1
  332. package/src/engine/prompt-templates.ts +18 -1
  333. package/src/engine/provider-payload.ts +29 -1
  334. package/src/engine/worker-runtime.ts +6 -3
  335. package/src/entry/orchestrator.ts +176 -30
  336. package/src/interactive/chat-loop-messages.ts +26 -7
  337. package/src/interactive/chat-loop.ts +318 -41
  338. package/src/interactive/chat-panel.ts +62 -8
  339. package/src/interactive/clio-editor.ts +45 -8
  340. package/src/interactive/context-activity.ts +5 -1
  341. package/src/interactive/context-meter.ts +1 -1
  342. package/src/interactive/context-overlay.ts +40 -10
  343. package/src/interactive/cost-overlay.ts +64 -6
  344. package/src/interactive/dispatch-board.ts +127 -5
  345. package/src/interactive/fleet-run-preview.ts +41 -15
  346. package/src/interactive/handoff-round.ts +41 -2
  347. package/src/interactive/interactive-application.ts +24 -1
  348. package/src/interactive/interactive-event-projection.ts +14 -0
  349. package/src/interactive/interactive-input-runtime.ts +8 -0
  350. package/src/interactive/interactive-presentation.ts +4 -0
  351. package/src/interactive/interactive-shell.ts +20 -17
  352. package/src/interactive/interactive-slash-runtime.ts +27 -4
  353. package/src/interactive/memory-overlay.ts +8 -0
  354. package/src/interactive/mutation-preview.ts +295 -0
  355. package/src/interactive/overlay-general-openers.ts +16 -0
  356. package/src/interactive/overlay-key-routing.ts +38 -0
  357. package/src/interactive/overlay-lifecycle.ts +38 -5
  358. package/src/interactive/overlay-permission-lifecycle.ts +22 -2
  359. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  360. package/src/interactive/overlays/ask-user.ts +91 -19
  361. package/src/interactive/overlays/help-reference.ts +4 -0
  362. package/src/interactive/overlays/prompts.ts +11 -1
  363. package/src/interactive/overlays/settings.ts +176 -48
  364. package/src/interactive/permission-hint.ts +34 -2
  365. package/src/interactive/permission-overlay.ts +159 -9
  366. package/src/interactive/prewarm.ts +197 -0
  367. package/src/interactive/render-trace.ts +162 -15
  368. package/src/interactive/renderers/tool-execution.ts +4 -0
  369. package/src/interactive/side-question.ts +58 -1
  370. package/src/interactive/slash-commands.ts +7 -2
  371. package/src/interactive/status/controller.ts +11 -0
  372. package/src/interactive/status/state-machine.ts +54 -2
  373. package/src/interactive/status/types.ts +7 -0
  374. package/src/interactive/terminal-lease.ts +2 -0
  375. package/src/interactive/turn-context.ts +299 -31
  376. package/src/interactive/turn-persistence.ts +14 -4
  377. package/src/interactive/turn-prewarm.ts +364 -0
  378. package/src/interactive/turn-queues.ts +7 -4
  379. package/src/interactive/turn-runtime.ts +8 -1
  380. package/src/interactive/turn-state.ts +23 -0
  381. package/src/interactive/view/artifacts.ts +42 -9
  382. package/src/interactive/view/view-overlay.ts +43 -6
  383. package/src/interactive/worker-receipts.ts +14 -2
  384. package/src/interactive/worker-stream.ts +8 -0
  385. package/src/tools/ask-user.ts +43 -2
  386. package/src/tools/dispatch-admission.ts +12 -13
  387. package/src/tools/dispatch-arguments.ts +27 -0
  388. package/src/tools/dispatch-plan.ts +46 -9
  389. package/src/tools/dispatch-runner.ts +48 -13
  390. package/src/tools/dispatch-scout.ts +1 -1
  391. package/src/tools/monitor.ts +13 -0
  392. package/src/tools/registry.ts +16 -0
  393. package/src/tools/worker-evidence.ts +19 -13
  394. package/src/worker/spec-contract.ts +2 -1
  395. package/dist/chunk-AOCYTWAV.js +0 -449
  396. package/dist/chunk-HWUFFB6L.js +0 -83
  397. package/dist/chunk-R346GLFC.js +0 -31
  398. package/dist/chunk-ZGH7FGS5.js +0 -1079
  399. package/dist/doctor-RN4YKO2X.js +0 -87
  400. package/dist/eval-RUBJVSNQ.js +0 -2557
@@ -1,16 +1,18 @@
1
1
  import { InvalidIdError } from "../core/safe-id.js";
2
2
  import { clioDataDir, clioStateDir } from "../core/xdg.js";
3
- import type { CanonicalTrustStatus, EvidenceOverview, EvidenceRunProvenance } from "../domains/evidence/index.js";
3
+ import type { EvidenceOverview, EvidenceRunProvenance } from "../domains/evidence/index.js";
4
4
  import {
5
5
  buildEvalEvidence,
6
6
  buildEvidence,
7
7
  EvidenceNotFoundError,
8
+ formatTrustAxes,
9
+ formatTrustSummary,
8
10
  inspectEvidence,
9
11
  listEvidenceOverviews,
10
12
  loadEvidenceRunProvenance,
11
13
  provenanceTranscriptLines,
12
14
  } from "../domains/evidence/index.js";
13
- import { printError, printOk } from "./shared.js";
15
+ import { printError, printNote, printOk } from "./shared.js";
14
16
 
15
17
  const HELP = `clio-coder evidence build --run <runId>
16
18
  clio-coder evidence build --session <sessionId>
@@ -137,15 +139,19 @@ export async function runEvidenceCommand(args: ReadonlyArray<string>): Promise<n
137
139
  // but the verdict line and exit code must not say ok over a receipt
138
140
  // that failed integrity verification.
139
141
  const integrityFailures = result.findings.filter((entry) => entry.tag === "receipt-integrity");
140
- if (integrityFailures.length > 0) {
141
- process.stdout.write(`wrote ${result.evidenceId} ${result.directory}\n`);
142
- for (const failure of integrityFailures) {
143
- printError(`${failure.runId !== null ? `run ${failure.runId}: ` : ""}${failure.message}`);
144
- }
145
- return 1;
142
+ // A retired seal is the expected state of every run that predates an
143
+ // integrity bump: the receipt is set aside unread, as a missing one
144
+ // is, so it is a note beside the verdict and leaves the exit code alone.
145
+ const retiredSeals = result.findings.filter((entry) => entry.tag === "receipt-retired");
146
+ if (integrityFailures.length > 0) process.stdout.write(`wrote ${result.evidenceId} ${result.directory}\n`);
147
+ else printOk(`wrote ${result.evidenceId} ${result.directory}`);
148
+ for (const entry of retiredSeals) {
149
+ printNote(`${entry.runId !== null ? `run ${entry.runId}: ` : ""}${entry.message}`);
146
150
  }
147
- printOk(`wrote ${result.evidenceId} ${result.directory}`);
148
- return 0;
151
+ for (const failure of integrityFailures) {
152
+ printError(`${failure.runId !== null ? `run ${failure.runId}: ` : ""}${failure.message}`);
153
+ }
154
+ return integrityFailures.length > 0 ? 1 : 0;
149
155
  }
150
156
  if (parsed.command === "inspect") {
151
157
  const evidenceId = parsed.evidenceId;
@@ -191,30 +197,29 @@ function renderEvidence(
191
197
  if (trustStatus.projection === "historical_format") {
192
198
  process.stdout.write("trust status: unavailable (historical bundle without canonical projection)\n");
193
199
  } else {
200
+ // The compact projection answers the trust questions; the canonical axis
201
+ // line beneath it is the drill-down, in the same form the dispatch tool
202
+ // and monitor print.
194
203
  for (const run of trustStatus.runs) {
195
- process.stdout.write(`trust ${run.runId}: ${formatTrustStatus(run.status)}\n`);
204
+ process.stdout.write(`trust ${run.runId}: ${formatTrustSummary(run.status)}\n`);
205
+ process.stdout.write(` ${formatTrustAxes(run.status)}\n`);
196
206
  }
197
207
  }
198
- // Provenance is printed only for runs whose receipts carry it, so a legacy
199
- // bundle prints nothing new here.
208
+ // Provenance is the detail behind the projection, never a second reading
209
+ // of it: each run's block is gated on that run's canonical status, so a
210
+ // receipt the projection withheld (a broken or retired seal) prints no
211
+ // autonomy value here, and a run whose block would be empty prints no
212
+ // header. A historical bundle has no projection and admits no axis detail.
213
+ const statusByRun = new Map(trustStatus.runs.map((entry) => [entry.runId, entry.status]));
200
214
  for (const { runId, view } of provenance) {
215
+ const lines = provenanceTranscriptLines(view, statusByRun.get(runId));
216
+ if (lines.length === 0) continue;
201
217
  process.stdout.write(`provenance ${runId}:\n`);
202
- for (const line of provenanceTranscriptLines(view)) process.stdout.write(` ${line}\n`);
218
+ for (const line of lines) process.stdout.write(` ${line}\n`);
203
219
  }
204
220
  process.stdout.write(`files: ${formatList(overview.files)}\n`);
205
221
  }
206
222
 
207
- function formatTrustStatus(status: CanonicalTrustStatus): string {
208
- return [
209
- `artifactIntegrity=${status.artifactIntegrity.state}`,
210
- `validationGrounding=${status.validationGrounding.state}`,
211
- `independentReview=${status.independentReview.state}`,
212
- `contextProvenance=${status.contextProvenance.state}`,
213
- `autonomyEnforcement=${status.autonomyEnforcement.state}`,
214
- `completionEvidence=${status.completionEvidence.state}`,
215
- ].join(" ");
216
- }
217
-
218
223
  function renderEvidenceList(overviews: ReadonlyArray<EvidenceOverview>): void {
219
224
  process.stdout.write(`${overviews.length} evidence artifacts\n`);
220
225
  if (overviews.length === 0) return;
@@ -91,6 +91,7 @@ function resourceSummary(extension: InstalledExtension): string {
91
91
  }
92
92
 
93
93
  function stateLabel(extension: InstalledExtension): string {
94
+ if (!extension.compatible) return "incompatible";
94
95
  if (!extension.enabled) return "disabled";
95
96
  if (!extension.effective) return `shadowed:${extension.overriddenBy ?? "higher"}`;
96
97
  return "active";
@@ -143,7 +144,10 @@ export function runExtensionsCommand(argv: ReadonlyArray<string>): number {
143
144
  case "list": {
144
145
  const items = listInstalledExtensions(process.cwd(), { ...scopeOptions, all: parsed.all });
145
146
  if (parsed.json) process.stdout.write(`${JSON.stringify({ extensions: items }, null, 2)}\n`);
146
- else printList(items);
147
+ else {
148
+ printList(items);
149
+ for (const item of items) printDiagnostics(item.diagnostics);
150
+ }
147
151
  return 0;
148
152
  }
149
153
  case "discover": {
@@ -1,7 +1,4 @@
1
- import { join } from "node:path";
2
1
  import { readSettings } from "../core/config.js";
3
- import { resolvePackageRoot } from "../core/package-root.js";
4
- import { clioConfigDir } from "../core/xdg.js";
5
2
  import {
6
3
  type FleetCommandRegistry,
7
4
  type FleetContract,
@@ -9,7 +6,7 @@ import {
9
6
  loadFleetContract,
10
7
  renderFleetPrompt,
11
8
  } from "../domains/agents/index.js";
12
- import { type AgentRecipeDiagnostic, loadRecipesFromDir, mergeRecipes } from "../domains/agents/registry.js";
9
+ import { discoverAgentRecipes } from "../domains/agents/registry.js";
13
10
  import { type AgentSpec, normalizeAgentSpec } from "../domains/agents/spec.js";
14
11
  import type { ExecutionPlan } from "../domains/dispatch/execution-plan.js";
15
12
  import { requestExecutionRole, withAttemptRole } from "../domains/dispatch/execution-role.js";
@@ -23,14 +20,7 @@ export interface FleetPreflightResult {
23
20
  }
24
21
 
25
22
  function discoverSpecs(cwd: string): AgentSpec[] {
26
- const diagnostics: AgentRecipeDiagnostic[] = [];
27
- const builtin = loadRecipesFromDir(
28
- { dir: join(resolvePackageRoot(), "src", "domains", "agents", "builtins"), source: "builtin" },
29
- diagnostics,
30
- );
31
- const user = loadRecipesFromDir({ dir: join(clioConfigDir(), "agents"), source: "user" }, diagnostics);
32
- const project = loadRecipesFromDir({ dir: join(cwd, ".clio-coder", "agents"), source: "project" }, diagnostics);
33
- return mergeRecipes(builtin, user, project).map(normalizeAgentSpec);
23
+ return discoverAgentRecipes(cwd).map(normalizeAgentSpec);
34
24
  }
35
25
 
36
26
  export function inspectFleet(name: string, vars?: Readonly<Record<string, string>>): FleetPreflightResult {
package/src/cli/fleet.ts CHANGED
@@ -47,8 +47,8 @@ import {
47
47
  type RunToolBudgetEnvelope,
48
48
  } from "../domains/dispatch/budget-envelope.js";
49
49
  import { type CapacityDrain, capacityDrain, setCapacityDraining } from "../domains/dispatch/capacity-lease.js";
50
- import type { DispatchContract } from "../domains/dispatch/contract.js";
51
- import type { ExecutionPlan } from "../domains/dispatch/execution-plan.js";
50
+ import type { DispatchContract, DispatchRequest } from "../domains/dispatch/contract.js";
51
+ import { bindExecutionPlanEndpoints, type ExecutionPlan } from "../domains/dispatch/execution-plan.js";
52
52
  import { agentRoleFactsResolver, requestExecutionRole, withAttemptRole } from "../domains/dispatch/execution-role.js";
53
53
  import { compileFleetExecutionPlan } from "../domains/dispatch/fleet-plan.js";
54
54
  import {
@@ -67,7 +67,7 @@ import { ensureClioState, LifecycleDomainModule } from "../domains/lifecycle/ind
67
67
  import { MiddlewareDomainModule } from "../domains/middleware/index.js";
68
68
  import { ObservabilityDomainModule } from "../domains/observability/index.js";
69
69
  import { createPromptsDomainModule } from "../domains/prompts/index.js";
70
- import { ProvidersDomainModule } from "../domains/providers/index.js";
70
+ import { foregroundStreamUsage, ProvidersDomainModule } from "../domains/providers/index.js";
71
71
  import { ResourcesDomainModule } from "../domains/resources/index.js";
72
72
  import type { SafetyContract } from "../domains/safety/contract.js";
73
73
  import { SafetyDomainModule } from "../domains/safety/index.js";
@@ -372,6 +372,35 @@ async function runFleet(args: ReadonlyArray<string>): Promise<number> {
372
372
  await loaded.stop();
373
373
  return fail(err instanceof Error ? err.message : String(err));
374
374
  }
375
+ if (dispatch.preview !== undefined) {
376
+ try {
377
+ const foreground = foregroundStreamUsage();
378
+ const bindings: Record<string, { key: string; limit: number; foregroundHeld?: number } | undefined> = {};
379
+ for (const step of plan.steps) {
380
+ if (step.kind === "code") continue;
381
+ const request: DispatchRequest = {
382
+ agentId: step.agentId,
383
+ executionRole: step.executionRole,
384
+ task: step.task,
385
+ ...(step.scope === "readonly" ? { autonomy: "read-only" as const } : {}),
386
+ ...(step.target !== undefined ? { target: step.target } : {}),
387
+ ...(step.profile !== undefined ? { workerProfile: step.profile } : {}),
388
+ };
389
+ const endpoint = dispatch.preview(request).endpoint;
390
+ if (endpoint === undefined) continue;
391
+ const foregroundHeld = foreground[endpoint.key] ?? 0;
392
+ bindings[step.id] = {
393
+ key: endpoint.key,
394
+ limit: endpoint.limit,
395
+ ...(foregroundHeld > 0 ? { foregroundHeld } : {}),
396
+ };
397
+ }
398
+ plan = bindExecutionPlanEndpoints(plan, bindings);
399
+ } catch (err) {
400
+ await loaded.stop();
401
+ return fail(`route preflight failed: ${err instanceof Error ? err.message : String(err)}`);
402
+ }
403
+ }
375
404
  try {
376
405
  preflightWriteBoundaries(plan, process.cwd());
377
406
  } catch (err) {
package/src/cli/shared.ts CHANGED
@@ -15,6 +15,7 @@ export {
15
15
  parseFlags,
16
16
  printError,
17
17
  printHeader,
18
+ printNote,
18
19
  printOk,
19
20
  } from "./argv.js";
20
21
 
@@ -14,6 +14,7 @@ import { ConfigDomainModule } from "../domains/config/index.js";
14
14
  import { ensureClioState } from "../domains/lifecycle/index.js";
15
15
  import type { ProvidersContract, TargetStatus } from "../domains/providers/contract.js";
16
16
  import {
17
+ endpointCapacityForStatus,
17
18
  isDispatchEligibleRuntime,
18
19
  isOrchestratorEligibleRuntime,
19
20
  ProvidersDomainModule,
@@ -24,7 +25,7 @@ import type { CapabilityFlags } from "../domains/providers/types/capability-flag
24
25
  import type { RuntimeTier } from "../domains/providers/types/runtime-descriptor.js";
25
26
  import { runConfigureCommand, runTargetRemove, runTargetRename } from "./configure.js";
26
27
  import { printError, printOk } from "./shared.js";
27
- import { column, terminalColumns, truncate } from "./text-layout.js";
28
+ import { column, terminalColumns, truncate, wrapPlain } from "./text-layout.js";
28
29
 
29
30
  const HEADER: ReadonlyArray<string> = ["id", "tier", "runtime", "auth", "url", "model", "health", "caps", "notes"];
30
31
  type ProviderOutputTier = RuntimeTier | "unknown";
@@ -805,9 +806,11 @@ export interface TargetTableRow {
805
806
  health: string;
806
807
  caps: string;
807
808
  notes: string;
809
+ /** Full degraded-health reason, kept separately so a narrow table can repeat it below the row. */
810
+ diagnostic?: string;
808
811
  }
809
812
 
810
- type TargetTableColumn = keyof TargetTableRow;
813
+ type TargetTableColumn = Exclude<keyof TargetTableRow, "diagnostic">;
811
814
  type TargetTableWidths = Record<TargetTableColumn, number>;
812
815
 
813
816
  const TABLE_COLUMNS: ReadonlyArray<TargetTableColumn> = [
@@ -918,20 +921,35 @@ export function formatTargetTable(
918
921
  rows: ReadonlyArray<TargetTableRow>,
919
922
  width: number,
920
923
  paintHealth: (cell: string, row: TargetTableRow) => string = (cell) => cell,
921
- ): { header: string; rows: ReadonlyArray<string> } {
924
+ ): { header: string; rows: ReadonlyArray<string>; details: ReadonlyArray<ReadonlyArray<string>> } {
922
925
  const widths = tableWidths(rows, width);
923
926
  const line = (cells: ReadonlyArray<string>): string => cells.join(" ".repeat(TABLE_GAP)).trimEnd();
927
+ const formatted = rows.map((row) => {
928
+ const cells = TABLE_COLUMNS.map((key) => column(row[key], widths[key]));
929
+ const plain = line(cells);
930
+ const rendered =
931
+ plain.length > width
932
+ ? truncate(plain, width)
933
+ : line(cells.map((cell, index) => (TABLE_COLUMNS[index] === "health" ? paintHealth(cell, row) : cell)));
934
+ const diagnosticFits = !row.diagnostic || (plain.length <= width && widths.notes >= row.diagnostic.length);
935
+ const details = diagnosticFits ? [] : targetDiagnosticDetails(row.diagnostic ?? "", width);
936
+ return { rendered, details };
937
+ });
924
938
  return {
925
939
  header: truncate(line(TABLE_COLUMNS.map((key, index) => column(HEADER[index] ?? key, widths[key]))), width),
926
- rows: rows.map((row) => {
927
- const cells = TABLE_COLUMNS.map((key) => column(row[key], widths[key]));
928
- const plain = line(cells);
929
- if (plain.length > width) return truncate(plain, width);
930
- return line(cells.map((cell, index) => (TABLE_COLUMNS[index] === "health" ? paintHealth(cell, row) : cell)));
931
- }),
940
+ rows: formatted.map(({ rendered }) => rendered),
941
+ details: formatted.map(({ details }) => details),
932
942
  };
933
943
  }
934
944
 
945
+ /** Indented diagnostic text that retains every word when the table row cannot. */
946
+ function targetDiagnosticDetails(diagnostic: string, width: number): string[] {
947
+ const indent = 2;
948
+ return wrapPlain(`reason: ${diagnostic}`, Math.max(8, width - indent), indent).map((line, index) =>
949
+ index === 0 ? `${" ".repeat(indent)}${line}` : line,
950
+ );
951
+ }
952
+
935
953
  function renderTable(providers: ProvidersContract, entries: ReadonlyArray<TargetStatus>): void {
936
954
  const sorted = [...entries].sort(compareStatusByTier);
937
955
  const table = formatTargetTable(
@@ -950,10 +968,12 @@ function renderTable(providers: ProvidersContract, entries: ReadonlyArray<Target
950
968
  process.stdout.write(`${chalk.bold(table.header)}\n`);
951
969
  }
952
970
  process.stdout.write(`${table.rows[index] ?? ""}\n`);
971
+ for (const detail of table.details[index] ?? []) process.stdout.write(`${detail}\n`);
953
972
  }
954
973
  }
955
974
 
956
- function targetTableRow(providers: ProvidersContract, status: TargetStatus): TargetTableRow {
975
+ export function targetTableRow(providers: ProvidersContract, status: TargetStatus): TargetTableRow {
976
+ const diagnostic = degradedHealthDiagnostic(status);
957
977
  return {
958
978
  id: status.target.id,
959
979
  tier: statusTier(status),
@@ -964,6 +984,7 @@ function targetTableRow(providers: ProvidersContract, status: TargetStatus): Tar
964
984
  health: status.health.status,
965
985
  caps: capabilityBadges(status.capabilities),
966
986
  notes: formatNotes(status),
987
+ ...(diagnostic ? { diagnostic } : {}),
967
988
  };
968
989
  }
969
990
 
@@ -1044,8 +1065,14 @@ export function formatContextWindow(
1044
1065
  : `ctx ${window}`;
1045
1066
  }
1046
1067
 
1047
- function formatNotes(status: TargetStatus): string {
1068
+ export function formatNotes(status: TargetStatus): string {
1048
1069
  const parts: string[] = [];
1070
+ const diagnostic = degradedHealthDiagnostic(status);
1071
+ // The health diagnosis leads because gateway, context, and residency facts
1072
+ // are supplementary once the target says it cannot serve its default model.
1073
+ if (diagnostic) parts.push(diagnostic);
1074
+ const endpoint = endpointCapacityForStatus(status);
1075
+ if (endpoint) parts.push(`slots ${endpoint.limit}`);
1049
1076
  if (status.target.gateway) parts.push("gateway");
1050
1077
  if (status.runtime?.auth === "oauth") parts.push("oauth");
1051
1078
  if (status.runtime?.auth === "claude-cli") parts.push("claude-cli");
@@ -1057,6 +1084,10 @@ function formatNotes(status: TargetStatus): string {
1057
1084
  return parts.join(" ");
1058
1085
  }
1059
1086
 
1087
+ function degradedHealthDiagnostic(status: TargetStatus): string | null {
1088
+ return status.health.status === "degraded" && status.health.lastError ? status.health.lastError : null;
1089
+ }
1090
+
1060
1091
  function statusTier(status: TargetStatus): ProviderOutputTier {
1061
1092
  return status.runtime?.tier ?? "unknown";
1062
1093
  }
@@ -1117,6 +1148,7 @@ interface SerializedStatus {
1117
1148
  tier: ProviderOutputTier;
1118
1149
  detectedReasoning: boolean | null;
1119
1150
  reasoningCandidateModelId: string | null;
1151
+ endpointCapacity?: ReturnType<typeof endpointCapacityForStatus>;
1120
1152
  }
1121
1153
 
1122
1154
  function serializeStatus(
@@ -1138,6 +1170,8 @@ function serializeStatus(
1138
1170
  detectedReasoning: extras.detectedReasoning,
1139
1171
  reasoningCandidateModelId: extras.candidateModelId,
1140
1172
  };
1173
+ const endpointCapacity = endpointCapacityForStatus(status);
1174
+ if (endpointCapacity !== null) out.endpointCapacity = endpointCapacity;
1141
1175
  if (status.contextWindowProvenance !== undefined) {
1142
1176
  out.contextWindowProvenance = status.contextWindowProvenance;
1143
1177
  }
package/src/cli/trace.ts CHANGED
@@ -4,12 +4,15 @@ import { resolve } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { clioStatePath } from "../core/xdg.js";
6
6
  import {
7
+ DEFAULT_TRACE_RETENTION_POLICY,
8
+ resolveTraceRetentionPolicy,
7
9
  TRACE_EVENT_POLL_LIMIT,
8
10
  type TraceEventRow,
9
11
  type TracePhaseRow,
10
12
  type TraceProcessRow,
11
13
  TraceReader,
12
14
  type TraceRunRow,
15
+ TraceStore,
13
16
  traceDatabasePath,
14
17
  } from "../domains/observability/trace-store.js";
15
18
 
@@ -18,11 +21,15 @@ const HELP = `Usage:
18
21
  clio-coder trace phases <runId> [--db PATH]
19
22
  clio-coder trace tail <runId> [--follow] [--db PATH]
20
23
  clio-coder trace procs <runId> [--db PATH]
24
+ clio-coder trace prune [--max-age-days N] [--max-bytes N] [--db PATH] [--json]
21
25
  clio-coder trace sql <SELECT query> [--db PATH]
22
26
  clio-coder trace ui [--db PATH] [--port N] source checkout only
23
27
 
24
28
  The viewer ships with the repository, not the npm package, so from an installed
25
29
  Clio the subcommands above are the way in. They read the same database.
30
+ Pruning keeps ${DEFAULT_TRACE_RETENTION_POLICY.maxAgeDays} days and at most ${DEFAULT_TRACE_RETENTION_POLICY.maxBytes} bytes by default. Set
31
+ CLIO_CODER_TRACE_RETENTION_DAYS or CLIO_CODER_TRACE_MAX_BYTES to change the automatic
32
+ policy; prune flags override those values for one command.
26
33
  `;
27
34
 
28
35
  interface ParsedTraceArgs {
@@ -34,6 +41,8 @@ interface ParsedTraceArgs {
34
41
  limit: number;
35
42
  port: number;
36
43
  json: boolean;
44
+ maxAgeDays: number | undefined;
45
+ maxBytes: number | undefined;
37
46
  }
38
47
 
39
48
  function parseTraceArgs(args: string[]): ParsedTraceArgs {
@@ -44,11 +53,19 @@ function parseTraceArgs(args: string[]): ParsedTraceArgs {
44
53
  let limit = 50;
45
54
  let port = 0;
46
55
  let json = false;
56
+ let maxAgeDays: number | undefined;
57
+ let maxBytes: number | undefined;
47
58
  for (let index = 0; index < args.length; index += 1) {
48
59
  const arg = args[index];
49
60
  if (arg === "--follow") follow = true;
50
61
  else if (arg === "--json") json = true;
51
- else if (arg === "--db" || arg === "--limit" || arg === "--port") {
62
+ else if (
63
+ arg === "--db" ||
64
+ arg === "--limit" ||
65
+ arg === "--port" ||
66
+ arg === "--max-age-days" ||
67
+ arg === "--max-bytes"
68
+ ) {
52
69
  const value = args[index + 1];
53
70
  if (value === undefined) throw new Error(`${arg} requires a value`);
54
71
  index += 1;
@@ -56,20 +73,25 @@ function parseTraceArgs(args: string[]): ParsedTraceArgs {
56
73
  db = resolve(value);
57
74
  dbExplicit = true;
58
75
  } else if (arg === "--limit") limit = parseInteger(value, "--limit", 1, 500);
59
- else port = parseInteger(value, "--port", 0, 65_535);
76
+ else if (arg === "--port") port = parseInteger(value, "--port", 0, 65_535);
77
+ else if (arg === "--max-age-days") maxAgeDays = parseInteger(value, arg, 1, 36_500);
78
+ else maxBytes = parseInteger(value, arg, 1024 * 1024, Number.MAX_SAFE_INTEGER);
60
79
  } else if (arg?.startsWith("--db=")) {
61
80
  db = resolve(arg.slice(5));
62
81
  dbExplicit = true;
63
82
  } else if (arg?.startsWith("--limit=")) limit = parseInteger(arg.slice(8), "--limit", 1, 500);
64
83
  else if (arg?.startsWith("--port=")) port = parseInteger(arg.slice(7), "--port", 0, 65_535);
84
+ else if (arg?.startsWith("--max-age-days=")) maxAgeDays = parseInteger(arg.slice(15), "--max-age-days", 1, 36_500);
85
+ else if (arg?.startsWith("--max-bytes="))
86
+ maxBytes = parseInteger(arg.slice(12), "--max-bytes", 1024 * 1024, Number.MAX_SAFE_INTEGER);
65
87
  else if (arg?.startsWith("-")) throw new Error(`unknown trace flag: ${arg}`);
66
88
  else if (arg !== undefined) positional.push(arg);
67
89
  }
68
- return { positional, db, dbExplicit, follow, limit, port, json };
90
+ return { positional, db, dbExplicit, follow, limit, port, json, maxAgeDays, maxBytes };
69
91
  }
70
92
 
71
93
  /** Every subcommand `trace` answers to. Anything else is a usage error. */
72
- const TRACE_COMMANDS = new Set(["runs", "phases", "tail", "procs", "sql", "ui"]);
94
+ const TRACE_COMMANDS = new Set(["runs", "phases", "tail", "procs", "prune", "sql", "ui"]);
73
95
 
74
96
  /** The subcommands whose first positional is a run id. */
75
97
  const TRACE_COMMANDS_NEEDING_RUN_ID = new Set(["phases", "tail", "procs"]);
@@ -132,6 +154,7 @@ export async function runTraceCommand(args: string[]): Promise<number> {
132
154
  // the operator typed is a different claim, so a --db that is not there stays
133
155
  // an error and says which path it means.
134
156
  if (!existsSync(parsed.db)) return missingDatabase(parsed);
157
+ if (command === "prune") return runTracePrune(parsed);
135
158
 
136
159
  let reader: TraceReader;
137
160
  try {
@@ -189,6 +212,42 @@ export async function runTraceCommand(args: string[]): Promise<number> {
189
212
  }
190
213
  }
191
214
 
215
+ function runTracePrune(parsed: ParsedTraceArgs): number {
216
+ let policy: ReturnType<typeof resolveTraceRetentionPolicy>;
217
+ try {
218
+ policy = resolveTraceRetentionPolicy({
219
+ ...(parsed.maxAgeDays === undefined ? {} : { maxAgeDays: parsed.maxAgeDays }),
220
+ ...(parsed.maxBytes === undefined ? {} : { maxBytes: parsed.maxBytes }),
221
+ });
222
+ } catch (error) {
223
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
224
+ return 1;
225
+ }
226
+ let store: TraceStore;
227
+ try {
228
+ store = new TraceStore(parsed.db, { retention: policy });
229
+ } catch (error) {
230
+ process.stderr.write(`trace database: ${error instanceof Error ? error.message : String(error)}\n`);
231
+ return 1;
232
+ }
233
+ try {
234
+ const result = store.prune(policy);
235
+ if (parsed.json) {
236
+ process.stdout.write(`${JSON.stringify({ policy, ...result }, null, 2)}\n`);
237
+ } else {
238
+ process.stdout.write(
239
+ `trace prune: removed ${result.runsRemoved.toLocaleString("en-US")} runs and ${result.rowsRemoved.toLocaleString("en-US")} rows; reclaimed ${result.bytesRemoved.toLocaleString("en-US")} bytes; VACUUM ${result.vacuumed ? "ran" : "not needed"}; protected ${result.protectedRuns.toLocaleString("en-US")} live runs\n`,
240
+ );
241
+ }
242
+ return 0;
243
+ } catch (error) {
244
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
245
+ return 1;
246
+ } finally {
247
+ store.close();
248
+ }
249
+ }
250
+
192
251
  async function tail(reader: TraceReader, runId: string, follow: boolean): Promise<void> {
193
252
  let cursor = 0;
194
253
  let idleTerminalPolls = 0;
package/src/cli/usage.ts CHANGED
@@ -12,9 +12,12 @@ import { readEvidenceIndex } from "../domains/observability/evidence-index.js";
12
12
  import { type OutOfTurnUsageRow, readOutOfTurnUsageRows } from "../domains/observability/out-of-turn-usage.js";
13
13
  import { loadSkills } from "../domains/resources/index.js";
14
14
  import {
15
+ foldPromptCacheTelemetry,
16
+ hasPromptCacheTelemetry,
15
17
  type LedgerUsageCall,
16
18
  ledgerUsageCalls,
17
19
  listSessionLedgerRefs,
20
+ type PromptCacheTelemetry,
18
21
  parseSessionEntries,
19
22
  readAuditRows,
20
23
  } from "../domains/session/index.js";
@@ -69,6 +72,8 @@ interface SessionUsage {
69
72
  entriesInWindow: number;
70
73
  /** Completed API calls this session recorded in the window, one per call. */
71
74
  usageCalls: LedgerUsageCall[];
75
+ /** Backend prompt-cache facts persisted on assistant calls in the window. */
76
+ promptCache: PromptCacheTelemetry;
72
77
  }
73
78
 
74
79
  /** Per-call usage folded over one grouping (a model, or the whole window). */
@@ -102,32 +107,37 @@ function addResponseModelIdObservation(counts: ResponseModelIdObservationCounts,
102
107
 
103
108
  /**
104
109
  * How the folded calls split between the session's own turns and the rounds
105
- * that were billed beside it. A `/btw` side question and a `/handoff` round are
106
- * real spend and belong in the token and cost totals, but neither is a turn:
107
- * they never entered the session. `turns` therefore subtracts them from the
108
- * folded row count, which is exactly what the `/cost` overlay does.
110
+ * that were billed beside it. A `/btw` side question, a `/handoff` round, a
111
+ * session pre-warm, and a proactive-memory step are real spend and belong in
112
+ * the token and cost totals, but none of them is a turn: they never entered
113
+ * the session. `turns` therefore subtracts them from the folded row count,
114
+ * which is exactly what the `/cost` overlay does.
109
115
  */
110
116
  interface CallOrigins {
111
117
  rows: number;
112
118
  sideQuestions: number;
113
119
  handoffs: number;
120
+ prewarms: number;
121
+ backgroundMemory: number;
114
122
  }
115
123
 
116
124
  function emptyCallOrigins(): CallOrigins {
117
- return { rows: 0, sideQuestions: 0, handoffs: 0 };
125
+ return { rows: 0, sideQuestions: 0, handoffs: 0, prewarms: 0, backgroundMemory: 0 };
118
126
  }
119
127
 
120
128
  function turnsOf(origins: CallOrigins): number {
121
- return origins.rows - origins.sideQuestions - origins.handoffs;
129
+ return origins.rows - origins.sideQuestions - origins.handoffs - origins.prewarms - origins.backgroundMemory;
122
130
  }
123
131
 
124
132
  function hasLabelledCall(origins: CallOrigins): boolean {
125
- return origins.sideQuestions > 0 || origins.handoffs > 0;
133
+ return origins.sideQuestions > 0 || origins.handoffs > 0 || origins.prewarms > 0 || origins.backgroundMemory > 0;
126
134
  }
127
135
 
128
136
  function addOutOfTurnRow(origins: CallOrigins, row: OutOfTurnUsageRow): void {
129
137
  origins.rows += 1;
130
138
  if (row.label === "side-question") origins.sideQuestions += 1;
139
+ else if (row.label === "prewarm") origins.prewarms += 1;
140
+ else if (row.label === "background-memory") origins.backgroundMemory += 1;
131
141
  else origins.handoffs += 1;
132
142
  }
133
143
 
@@ -435,6 +445,9 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
435
445
  const usageRows = [...usageByModel.values()].sort(
436
446
  (a, b) => b.totals.totalTokens - a.totals.totalTokens || a.providerId.localeCompare(b.providerId),
437
447
  );
448
+ const cacheSessions = sessions
449
+ .filter((session) => hasPromptCacheTelemetry(session.promptCache))
450
+ .sort((a, b) => a.sessionId.localeCompare(b.sessionId));
438
451
 
439
452
  const approvedMemory = memoryRecords.filter((record) => record.approved && record.rejectedAt === undefined);
440
453
  const pendingMemory = memoryRecords.filter((record) => !record.approved && record.rejectedAt === undefined);
@@ -515,8 +528,8 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
515
528
  emit({ kind: "fact", fact: "audit-tool-calls", value: auditToolCalls.length, blocked: auditBlocked.length });
516
529
  if (usageMeasurable) {
517
530
  // The origin split is emitted only when something out of turn was
518
- // recorded, so a report over an archive with no `/btw` or `/handoff`
519
- // round in it stays byte-identical to what it printed before.
531
+ // recorded, so a report over an archive with no `/btw`, `/handoff`, or
532
+ // pre-warm round in it stays byte-identical to what it printed before.
520
533
  emit({
521
534
  kind: "fact",
522
535
  fact: "tokens",
@@ -526,6 +539,8 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
526
539
  turns: turnsOf(callOrigins),
527
540
  sideQuestions: callOrigins.sideQuestions,
528
541
  handoffs: callOrigins.handoffs,
542
+ prewarms: callOrigins.prewarms,
543
+ backgroundMemorySteps: callOrigins.backgroundMemory,
529
544
  }
530
545
  : {}),
531
546
  });
@@ -540,6 +555,15 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
540
555
  ...row.totals,
541
556
  });
542
557
  }
558
+ for (const session of cacheSessions) {
559
+ emit({
560
+ kind: "fact",
561
+ fact: "session-cache",
562
+ sessionId: session.sessionId,
563
+ uncachedPrefillTokens: session.promptCache.uncachedPrefillTokens,
564
+ verdictCounts: session.promptCache.verdictCounts,
565
+ });
566
+ }
543
567
  }
544
568
  for (const [tool, totals] of topTools) emit({ kind: "fact", fact: "top-tool", tool, ...totals });
545
569
  for (const [shape, count] of topShapes) {
@@ -600,6 +624,10 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
600
624
  out(` turns in window: ${turnsOf(callOrigins)}`);
601
625
  if (callOrigins.sideQuestions > 0) out(` side questions in window: ${callOrigins.sideQuestions}`);
602
626
  if (callOrigins.handoffs > 0) out(` handoffs in window: ${callOrigins.handoffs}`);
627
+ if (callOrigins.prewarms > 0) out(` pre-warms in window: ${callOrigins.prewarms}`);
628
+ if (callOrigins.backgroundMemory > 0) {
629
+ out(` background memory steps in window: ${callOrigins.backgroundMemory}`);
630
+ }
603
631
  }
604
632
  out(` provider-reported cost in window: $${usageTotals.costUsd.toFixed(4)}`);
605
633
  }
@@ -639,6 +667,27 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
639
667
  ),
640
668
  );
641
669
  }
670
+ if (cacheSessions.length > 0) {
671
+ out("");
672
+ out(" prompt cache by session (from backend timings and persisted verdicts)");
673
+ process.stdout.write(
674
+ indent(
675
+ formatColumns([
676
+ ["session", "uncached prefill", "hot/partial/cold/small"],
677
+ ...cacheSessions.map((session) => [
678
+ session.sessionId,
679
+ session.promptCache.uncachedPrefillTokens === null ? "n/a" : String(session.promptCache.uncachedPrefillTokens),
680
+ [
681
+ session.promptCache.verdictCounts.hot,
682
+ session.promptCache.verdictCounts.partial,
683
+ session.promptCache.verdictCounts.cold,
684
+ session.promptCache.verdictCounts.small,
685
+ ].join("/"),
686
+ ]),
687
+ ]),
688
+ ),
689
+ );
690
+ }
642
691
  if (topTools.length > 0) {
643
692
  out("");
644
693
  out(" top tools (from receipt toolStats)");
@@ -865,6 +914,9 @@ async function readSessions(
865
914
  }
866
915
  const parsedEntries = parseSessionEntries(raw, ref.path);
867
916
  diagnostics.malformedSessionLines += parsedEntries.errors.length;
917
+ const accountingEntries = parsedEntries.entries.filter(
918
+ (entry) => entry.kind === "modelChange" || inWindow(entry.timestamp, windowStart, windowEnd),
919
+ );
868
920
  const usage: SessionUsage = {
869
921
  sessionId: ref.sessionId,
870
922
  cwdHash: ref.cwdHash,
@@ -874,11 +926,8 @@ async function readSessions(
874
926
  // modelChange rows are kept regardless of the window: they carry no
875
927
  // usage of their own, and dropping the ones that predate the window
876
928
  // would attribute in-window calls to the wrong target.
877
- usageCalls: ledgerUsageCalls(
878
- parsedEntries.entries.filter(
879
- (entry) => entry.kind === "modelChange" || inWindow(entry.timestamp, windowStart, windowEnd),
880
- ),
881
- ),
929
+ usageCalls: ledgerUsageCalls(accountingEntries),
930
+ promptCache: foldPromptCacheTelemetry(accountingEntries),
882
931
  };
883
932
  for (const entry of parsedEntries.entries) {
884
933
  if (!inWindow(entry.timestamp, windowStart, windowEnd)) continue;