@iowarp/clio-coder 0.3.8 → 0.4.0

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 (552) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/NOTICE +33 -0
  3. package/README.md +12 -3
  4. package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
  5. package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
  8. package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
  9. package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
  10. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  11. package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
  12. package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
  13. package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
  14. package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
  15. package/dist/chunk-3DPEIQKN.js +113 -0
  16. package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
  17. package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
  18. package/dist/chunk-42FMPA75.js +101 -0
  19. package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
  20. package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
  21. package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
  22. package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
  23. package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
  24. package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
  25. package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
  26. package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
  27. package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
  28. package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
  29. package/dist/chunk-BKFM6EJV.js +462 -0
  30. package/dist/chunk-BMS5RKQY.js +27 -0
  31. package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
  32. package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
  33. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  34. package/dist/chunk-C2LTL2W6.js +2447 -0
  35. package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
  36. package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
  37. package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
  38. package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
  39. package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
  40. package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
  41. package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
  42. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  43. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  44. package/dist/chunk-GKF55TAZ.js +391 -0
  45. package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
  46. package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
  47. package/dist/chunk-HHV2GANA.js +88 -0
  48. package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
  49. package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
  50. package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
  51. package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
  52. package/dist/chunk-HZHHCK24.js +1631 -0
  53. package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
  54. package/dist/chunk-IBEBSCYA.js +564 -0
  55. package/dist/chunk-IQ7KR472.js +362 -0
  56. package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
  57. package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
  58. package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
  59. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  60. package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
  61. package/dist/chunk-KMVISBZR.js +132 -0
  62. package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
  63. package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
  64. package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
  65. package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
  66. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  67. package/dist/chunk-NEKRRTYW.js +56 -0
  68. package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
  69. package/dist/chunk-NHLBIGRH.js +1506 -0
  70. package/dist/chunk-NQQH3YT7.js +302 -0
  71. package/dist/chunk-NYS75XW5.js +15 -0
  72. package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
  73. package/dist/{chunk-EMYUUSFG.js → chunk-O6TL7WWY.js} +6 -6
  74. package/dist/chunk-OQBA45DZ.js +97 -0
  75. package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
  76. package/dist/chunk-PMZCIOCJ.js +25 -0
  77. package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
  78. package/dist/{chunk-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
  79. package/dist/chunk-QDC3K2U3.js +262 -0
  80. package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
  81. package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
  82. package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
  83. package/dist/chunk-QSNYB6ZV.js +195 -0
  84. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  85. package/dist/chunk-RKKLTLYB.js +45 -0
  86. package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
  87. package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
  88. package/dist/chunk-SUCTJL45.js +45 -0
  89. package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
  90. package/dist/chunk-T56WDKA5.js +183 -0
  91. package/dist/chunk-TVHHYFHE.js +255 -0
  92. package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
  93. package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
  94. package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
  95. package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
  96. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  97. package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
  98. package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
  99. package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
  100. package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
  101. package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
  102. package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
  103. package/dist/chunk-VO67MWHC.js +75 -0
  104. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  105. package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
  106. package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
  107. package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
  108. package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
  109. package/dist/chunk-X75E3D2N.js +686 -0
  110. package/dist/{chunk-VAWNZU7Z.js → chunk-YDFRH54B.js} +4 -4
  111. package/dist/chunk-YJX4SHTD.js +40 -0
  112. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  113. package/dist/chunk-Z2RR6MAK.js +127 -0
  114. package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
  115. package/dist/cli/index.js +47 -36
  116. package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
  117. package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
  118. package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
  119. package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
  120. package/dist/{config-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
  121. package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
  122. package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
  123. package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
  124. package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
  125. package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
  126. package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
  127. package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
  128. package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
  129. package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
  130. package/dist/doctor-QOA5FNY5.js +313 -0
  131. package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
  132. package/dist/eval-inventory-SXH7PDKX.js +316 -0
  133. package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
  134. package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
  135. package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
  136. package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
  137. package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
  138. package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
  139. package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
  140. package/dist/fleet-inspect-VLY4S7QM.js +442 -0
  141. package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
  142. package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
  143. package/dist/fleet-verify-JFEL2L3H.js +175 -0
  144. package/dist/fleet-view-ZCON35AG.js +102 -0
  145. package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
  146. package/dist/install-XGLBQY5E.js +13 -0
  147. package/dist/interop-OZBKXAYL.js +114 -0
  148. package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
  149. package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
  150. package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
  151. package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
  152. package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
  153. package/dist/panes-HMABYVO4.js +58 -0
  154. package/dist/panes-KY6W3V2E.js +103 -0
  155. package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
  156. package/dist/{reset-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
  157. package/dist/resources-BB3MVJMD.js +111 -0
  158. package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
  159. package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
  160. package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
  161. package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
  162. package/dist/skills-inventory-S4MXPJFV.js +126 -0
  163. package/dist/slash-commands-ZSGASKJC.js +77 -0
  164. package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
  165. package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
  166. package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
  167. package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
  168. package/dist/tools-DAF3DI3C.js +27 -0
  169. package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
  170. package/dist/tui-primitives-2AKXQNZK.js +13 -0
  171. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
  172. package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
  173. package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
  174. package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
  175. package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
  176. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
  177. package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
  178. package/dist/with-panes-MKB46MPQ.js +782 -0
  179. package/dist/worker/entry.js +106 -75
  180. package/docs/README.md +3 -2
  181. package/docs/acp.md +24 -3
  182. package/docs/alcf-provider.md +1 -1
  183. package/docs/architecture.md +2 -2
  184. package/docs/artifact-versions.md +9 -1
  185. package/docs/built-in-agents.md +1 -1
  186. package/docs/capacity-and-scheduling.md +62 -3
  187. package/docs/commands-and-modes.md +31 -2
  188. package/docs/configuration-and-targets.md +69 -12
  189. package/docs/context-engine.md +63 -4
  190. package/docs/development-pipeline.md +19 -0
  191. package/docs/dispatch-typed-intent.md +385 -0
  192. package/docs/documentation-coverage.md +5 -5
  193. package/docs/documentation-guide.md +1 -1
  194. package/docs/environment-variables.md +3 -0
  195. package/docs/eval-runner.md +262 -11
  196. package/docs/evals-internal.md +72 -2
  197. package/docs/evidence-and-memory.md +12 -11
  198. package/docs/evolution.md +1 -1
  199. package/docs/exit-codes-and-output.md +1 -1
  200. package/docs/extensions-and-sharing.md +27 -1
  201. package/docs/fleet-dispatch.md +25 -4
  202. package/docs/installation-and-lifecycle.md +15 -2
  203. package/docs/middleware-and-components.md +1 -1
  204. package/docs/model-catalog.md +10 -1
  205. package/docs/observability.md +55 -4
  206. package/docs/proactive-memory.md +127 -14
  207. package/docs/prompt-envelope-and-tools.md +19 -1
  208. package/docs/provider-adapter-cookbook.md +1 -1
  209. package/docs/release-cut-checklist.md +19 -3
  210. package/docs/safety-model.md +2 -2
  211. package/docs/scientific-validation.md +3 -3
  212. package/docs/session-lifecycle.md +1 -1
  213. package/docs/skills-marketplace.md +1 -1
  214. package/docs/tool-usage.md +18 -8
  215. package/docs/trace-store.md +1 -1
  216. package/docs/troubleshooting.md +88 -1
  217. package/docs/tui-design.md +1 -1
  218. package/docs/worker-dispatch-mechanics.md +1 -1
  219. package/package.json +5 -2
  220. package/src/cli/acp.ts +6 -2
  221. package/src/cli/agents.ts +1 -1
  222. package/src/cli/argv.ts +25 -0
  223. package/src/cli/config-inspect.ts +33 -6
  224. package/src/cli/config.ts +1 -1
  225. package/src/cli/configure.ts +23 -21
  226. package/src/cli/doctor-panes.ts +124 -0
  227. package/src/cli/doctor-state-size.ts +82 -0
  228. package/src/cli/doctor-toolchain.ts +57 -0
  229. package/src/cli/doctor.ts +22 -1
  230. package/src/cli/eval-inventory.ts +436 -0
  231. package/src/cli/eval.ts +93 -16
  232. package/src/cli/evidence-detail.ts +88 -0
  233. package/src/cli/evidence-inventory.ts +183 -0
  234. package/src/cli/evidence.ts +30 -5
  235. package/src/cli/extensions.ts +5 -1
  236. package/src/cli/fleet-decisions.ts +69 -0
  237. package/src/cli/fleet-inspect.ts +334 -0
  238. package/src/cli/fleet-verify.ts +133 -0
  239. package/src/cli/fleet-view.ts +810 -0
  240. package/src/cli/fleet.ts +179 -39
  241. package/src/cli/index.ts +14 -2
  242. package/src/cli/interop-inspect.ts +128 -0
  243. package/src/cli/interop.ts +34 -0
  244. package/src/cli/panes.ts +35 -0
  245. package/src/cli/reset.ts +5 -2
  246. package/src/cli/run.ts +58 -0
  247. package/src/cli/skills-inventory.ts +185 -0
  248. package/src/cli/skills.ts +16 -13
  249. package/src/cli/targets.ts +44 -13
  250. package/src/cli/tools.ts +321 -0
  251. package/src/cli/trace-inspect.ts +252 -0
  252. package/src/cli/trace.ts +85 -5
  253. package/src/cli/usage.ts +63 -14
  254. package/src/cli/verifiers-inspect.ts +347 -0
  255. package/src/cli/verifiers.ts +9 -0
  256. package/src/core/bus-events.ts +33 -1
  257. package/src/core/cache-telemetry.ts +42 -0
  258. package/src/core/config.ts +67 -0
  259. package/src/core/defaults.ts +124 -8
  260. package/src/core/endpoint-key.ts +27 -0
  261. package/src/core/residency-target-key.ts +25 -0
  262. package/src/core/response-schema.ts +80 -6
  263. package/src/core/theme-token-hex.ts +43 -0
  264. package/src/core/tool-names.ts +2 -1
  265. package/src/core/xdg.ts +1 -1
  266. package/src/domains/agents/fleets/build-review.md +0 -3
  267. package/src/domains/agents/fleets/build-test.md +0 -3
  268. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  269. package/src/domains/agents/result-contract.ts +164 -35
  270. package/src/domains/config/classify.ts +6 -0
  271. package/src/domains/context/codewiki/coordinator.ts +12 -4
  272. package/src/domains/dispatch/admission-error.ts +9 -0
  273. package/src/domains/dispatch/admission.ts +52 -14
  274. package/src/domains/dispatch/capacity-lease.ts +118 -9
  275. package/src/domains/dispatch/contract.ts +11 -0
  276. package/src/domains/dispatch/council-topology.ts +398 -0
  277. package/src/domains/dispatch/execution-plan.ts +44 -4
  278. package/src/domains/dispatch/extension.ts +378 -82
  279. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  280. package/src/domains/dispatch/fleet-plan.ts +7 -2
  281. package/src/domains/dispatch/fleet-run.ts +87 -4
  282. package/src/domains/dispatch/gate-decisions.ts +11 -1
  283. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  284. package/src/domains/dispatch/gate-topology.ts +289 -0
  285. package/src/domains/dispatch/heartbeat.ts +32 -8
  286. package/src/domains/dispatch/index.ts +22 -0
  287. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  288. package/src/domains/dispatch/intent.ts +85 -1
  289. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  290. package/src/domains/dispatch/reservation-store.ts +139 -11
  291. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  292. package/src/domains/dispatch/run-event-journal.ts +598 -0
  293. package/src/domains/dispatch/state.ts +49 -1
  294. package/src/domains/dispatch/types.ts +13 -0
  295. package/src/domains/dispatch/validation.ts +33 -8
  296. package/src/domains/dispatch/worker-spawn.ts +25 -11
  297. package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
  298. package/src/domains/dispatch/write-boundary.ts +62 -1
  299. package/src/domains/eval/artifacts/store.ts +62 -0
  300. package/src/domains/eval/compare/behavioral.ts +224 -0
  301. package/src/domains/eval/compare/compare.ts +342 -2
  302. package/src/domains/eval/compare/envelope.ts +128 -0
  303. package/src/domains/eval/compare/gates.ts +24 -6
  304. package/src/domains/eval/compare/thresholds.ts +30 -3
  305. package/src/domains/eval/execution-provenance.ts +240 -0
  306. package/src/domains/eval/inventory.ts +113 -0
  307. package/src/domains/eval/metrics/aggregate.ts +136 -0
  308. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  309. package/src/domains/eval/metrics/tracked.ts +413 -0
  310. package/src/domains/eval/provenance.ts +117 -0
  311. package/src/domains/eval/reports/comparison.ts +128 -0
  312. package/src/domains/eval/reports/junit.ts +17 -3
  313. package/src/domains/eval/reports/markdown.ts +3 -3
  314. package/src/domains/eval/reports/text.ts +14 -0
  315. package/src/domains/eval/run-compare.ts +20 -0
  316. package/src/domains/eval/runners/clio-run.ts +127 -0
  317. package/src/domains/eval/runners/external-command.ts +28 -3
  318. package/src/domains/eval/schema/adapter.ts +111 -0
  319. package/src/domains/eval/schema/artifact.ts +20 -0
  320. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  321. package/src/domains/eval/schema/behavioral.ts +520 -0
  322. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  323. package/src/domains/eval/schema/serving.ts +105 -0
  324. package/src/domains/eval/schema/suite.ts +38 -8
  325. package/src/domains/eval/schema/validate.ts +58 -3
  326. package/src/domains/eval/schema/verdict.ts +237 -0
  327. package/src/domains/eval/suites/resolve.ts +2 -0
  328. package/src/domains/eval/suites/run.ts +264 -33
  329. package/src/domains/eval/verifiers/command.ts +2 -1
  330. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  331. package/src/domains/evidence/build.ts +2 -13
  332. package/src/domains/evidence/eval.ts +2 -12
  333. package/src/domains/evidence/findings-markdown.ts +33 -0
  334. package/src/domains/evidence/run-trust.ts +7 -113
  335. package/src/domains/evidence/store.ts +6 -0
  336. package/src/domains/evidence/trust-projection.ts +2 -2
  337. package/src/domains/extensions/compatibility.ts +285 -0
  338. package/src/domains/extensions/discovery.ts +38 -3
  339. package/src/domains/extensions/resources.ts +1 -1
  340. package/src/domains/extensions/state.ts +12 -3
  341. package/src/domains/extensions/types.ts +2 -0
  342. package/src/domains/lifecycle/doctor.ts +69 -1
  343. package/src/domains/memory/index.ts +14 -1
  344. package/src/domains/memory/task-bank-promotion.ts +64 -0
  345. package/src/domains/memory/task-memory-policy.ts +82 -17
  346. package/src/domains/memory/task-memory-spend.ts +131 -0
  347. package/src/domains/memory/task-memory-status.ts +7 -0
  348. package/src/domains/memory/task-memory-telemetry.ts +3 -0
  349. package/src/domains/middleware/index.ts +1 -0
  350. package/src/domains/middleware/memory-intervention.ts +97 -21
  351. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  352. package/src/domains/mux/contract.ts +434 -0
  353. package/src/domains/mux/detect.ts +158 -0
  354. package/src/domains/mux/extension.ts +47 -0
  355. package/src/domains/mux/index.ts +96 -0
  356. package/src/domains/mux/manifest.ts +6 -0
  357. package/src/domains/mux/operations.ts +164 -0
  358. package/src/domains/mux/pane-registry.ts +90 -0
  359. package/src/domains/mux/protocol.ts +49 -0
  360. package/src/domains/mux/socket-client.ts +816 -0
  361. package/src/domains/mux/types.ts +222 -0
  362. package/src/domains/mux/viewer-command.ts +59 -0
  363. package/src/domains/mux/yazi/assets/init.lua +2 -0
  364. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  365. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  366. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  367. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  368. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  369. package/src/domains/mux/yazi/event-stream.ts +180 -0
  370. package/src/domains/mux/yazi/profile.ts +299 -0
  371. package/src/domains/mux/yazi/session.ts +228 -0
  372. package/src/domains/mux/yazi/theme.ts +30 -0
  373. package/src/domains/observability/background-memory-usage.ts +140 -0
  374. package/src/domains/observability/cost.ts +22 -1
  375. package/src/domains/observability/index.ts +9 -0
  376. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  377. package/src/domains/observability/trace-store.ts +234 -2
  378. package/src/domains/prompts/compiler.ts +100 -13
  379. package/src/domains/providers/endpoint-capacity.ts +228 -0
  380. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  381. package/src/domains/providers/extension.ts +20 -3
  382. package/src/domains/providers/index.ts +32 -0
  383. package/src/domains/providers/model-runtime-capabilities.ts +32 -0
  384. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  385. package/src/domains/providers/runtime-resolution.ts +8 -1
  386. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  387. package/src/domains/providers/runtimes/builtins.ts +2 -0
  388. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  389. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  390. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  391. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  392. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  393. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  394. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  395. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  396. package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
  397. package/src/domains/providers/support.ts +1 -0
  398. package/src/domains/providers/target-model-cache.ts +124 -0
  399. package/src/domains/providers/types/capability-flags.ts +2 -0
  400. package/src/domains/providers/types/target-descriptor.ts +2 -0
  401. package/src/domains/resources/index.ts +3 -0
  402. package/src/domains/resources/prompts/loader.ts +95 -33
  403. package/src/domains/resources/skills/loader.ts +33 -0
  404. package/src/domains/safety/action-classifier.ts +6 -0
  405. package/src/domains/safety/call-target.ts +52 -0
  406. package/src/domains/safety/run-effects.ts +35 -4
  407. package/src/domains/session/context-accounting.ts +52 -1
  408. package/src/domains/session/context-ledger.ts +37 -13
  409. package/src/domains/session/index.ts +6 -0
  410. package/src/domains/session/prompt-cache.ts +140 -0
  411. package/src/domains/session/prompt-manifest.ts +42 -0
  412. package/src/domains/toolchain/archive.ts +175 -0
  413. package/src/domains/toolchain/contract.ts +28 -0
  414. package/src/domains/toolchain/extension.ts +47 -0
  415. package/src/domains/toolchain/index.ts +39 -0
  416. package/src/domains/toolchain/install.ts +327 -0
  417. package/src/domains/toolchain/manifest.ts +8 -0
  418. package/src/domains/toolchain/paths.ts +34 -0
  419. package/src/domains/toolchain/registry.ts +265 -0
  420. package/src/domains/toolchain/remove.ts +218 -0
  421. package/src/domains/toolchain/resolve.ts +182 -0
  422. package/src/domains/toolchain/types.ts +113 -0
  423. package/src/domains/toolchain/version.ts +88 -0
  424. package/src/engine/acp/adapter.ts +18 -3
  425. package/src/engine/acp/server.ts +413 -70
  426. package/src/engine/acp/types.ts +19 -1
  427. package/src/engine/ai.ts +35 -0
  428. package/src/engine/apis/llamacpp-residency.ts +55 -3
  429. package/src/engine/apis/lmstudio.ts +25 -5
  430. package/src/engine/apis/ollama-native.ts +2 -1
  431. package/src/engine/apis/openai-completions.ts +80 -17
  432. package/src/engine/apis/residency-lock.ts +3 -1
  433. package/src/engine/apis/residency.ts +34 -1
  434. package/src/engine/claude/sdk-module.ts +98 -0
  435. package/src/engine/claude/sdk-runtime.ts +19 -11
  436. package/src/engine/provider-payload.ts +29 -1
  437. package/src/engine/tui-primitives.ts +21 -0
  438. package/src/engine/tui.ts +1 -0
  439. package/src/engine/worker-runtime.ts +2 -13
  440. package/src/entry/boot-options.ts +2 -0
  441. package/src/entry/orchestrator.ts +279 -35
  442. package/src/entry/panes-activation.ts +31 -0
  443. package/src/entry/with-panes.ts +20 -0
  444. package/src/interactive/chat-loop-messages.ts +26 -7
  445. package/src/interactive/chat-loop.ts +318 -41
  446. package/src/interactive/chat-panel.ts +62 -8
  447. package/src/interactive/clio-editor.ts +45 -8
  448. package/src/interactive/context-activity.ts +5 -1
  449. package/src/interactive/context-meter.ts +1 -1
  450. package/src/interactive/context-overlay.ts +41 -10
  451. package/src/interactive/cost-overlay.ts +66 -6
  452. package/src/interactive/council-grid.ts +1 -3
  453. package/src/interactive/council.ts +11 -0
  454. package/src/interactive/dispatch-board.ts +102 -20
  455. package/src/interactive/fleet-run-preview.ts +41 -15
  456. package/src/interactive/handoff-round.ts +41 -2
  457. package/src/interactive/interactive-application.ts +177 -7
  458. package/src/interactive/interactive-input-runtime.ts +15 -0
  459. package/src/interactive/interactive-presentation.ts +4 -0
  460. package/src/interactive/interactive-shell.ts +20 -17
  461. package/src/interactive/interactive-slash-runtime.ts +63 -10
  462. package/src/interactive/memory-overlay.ts +9 -0
  463. package/src/interactive/modal-marker.ts +170 -0
  464. package/src/interactive/mutation-preview.ts +295 -0
  465. package/src/interactive/mux-bridge.ts +214 -0
  466. package/src/interactive/overlay-frame.ts +58 -2
  467. package/src/interactive/overlay-general-openers.ts +17 -0
  468. package/src/interactive/overlay-key-routing.ts +52 -3
  469. package/src/interactive/overlay-lifecycle.ts +56 -7
  470. package/src/interactive/overlay-model-selectors.ts +40 -3
  471. package/src/interactive/overlay-permission-lifecycle.ts +112 -24
  472. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  473. package/src/interactive/overlay-transitions.ts +18 -4
  474. package/src/interactive/overlays/agents.ts +1 -0
  475. package/src/interactive/overlays/ask-user.ts +227 -49
  476. package/src/interactive/overlays/auth-dialog.ts +1 -0
  477. package/src/interactive/overlays/context-reset.ts +1 -0
  478. package/src/interactive/overlays/cwd-fallback.ts +1 -0
  479. package/src/interactive/overlays/decisions.ts +11 -11
  480. package/src/interactive/overlays/extensions.ts +1 -0
  481. package/src/interactive/overlays/fleet-run-approval.ts +1 -0
  482. package/src/interactive/overlays/handoff-review.ts +1 -0
  483. package/src/interactive/overlays/help-reference.ts +6 -0
  484. package/src/interactive/overlays/interop.ts +1 -0
  485. package/src/interactive/overlays/library-install-confirm.ts +1 -0
  486. package/src/interactive/overlays/library-tabs.ts +28 -0
  487. package/src/interactive/overlays/list-overlay.ts +10 -1
  488. package/src/interactive/overlays/message-picker.ts +1 -0
  489. package/src/interactive/overlays/model-scope.ts +86 -0
  490. package/src/interactive/overlays/model-selector.ts +1 -0
  491. package/src/interactive/overlays/prompts.ts +12 -1
  492. package/src/interactive/overlays/session-selector.ts +1 -0
  493. package/src/interactive/overlays/settings-sections.ts +30 -0
  494. package/src/interactive/overlays/settings.ts +614 -45
  495. package/src/interactive/overlays/side-question.ts +1 -0
  496. package/src/interactive/overlays/skills-hub.ts +3 -11
  497. package/src/interactive/overlays/tree-selector.ts +1 -0
  498. package/src/interactive/pane-policy.ts +46 -0
  499. package/src/interactive/panes-runtime.ts +292 -0
  500. package/src/interactive/permission-hint.ts +34 -2
  501. package/src/interactive/permission-overlay.ts +159 -9
  502. package/src/interactive/prewarm.ts +197 -0
  503. package/src/interactive/render-trace.ts +162 -15
  504. package/src/interactive/renderers/compaction-summary.ts +29 -0
  505. package/src/interactive/renderers/tool-execution.ts +4 -0
  506. package/src/interactive/renderers/worker-entry.ts +122 -14
  507. package/src/interactive/side-question.ts +58 -1
  508. package/src/interactive/slash-commands.ts +251 -15
  509. package/src/interactive/status/controller.ts +11 -0
  510. package/src/interactive/status/state-machine.ts +54 -2
  511. package/src/interactive/status/types.ts +7 -0
  512. package/src/interactive/tasks-overlay.ts +1 -0
  513. package/src/interactive/terminal-lease.ts +2 -0
  514. package/src/interactive/theme/tokens.ts +3 -14
  515. package/src/interactive/turn-context.ts +346 -33
  516. package/src/interactive/turn-persistence.ts +14 -4
  517. package/src/interactive/turn-prewarm.ts +364 -0
  518. package/src/interactive/turn-queues.ts +7 -4
  519. package/src/interactive/turn-runtime.ts +8 -1
  520. package/src/interactive/turn-state.ts +23 -0
  521. package/src/interactive/view/artifacts.ts +109 -1
  522. package/src/interactive/view/view-overlay.ts +29 -3
  523. package/src/interactive/watch-pane.ts +152 -0
  524. package/src/interactive/worker-progress.ts +7 -1
  525. package/src/interactive/worker-receipts.ts +19 -1
  526. package/src/interactive/worker-stream.ts +5 -0
  527. package/src/interactive/yazi-bridge.ts +444 -0
  528. package/src/tools/ask-user.ts +43 -2
  529. package/src/tools/bootstrap.ts +26 -2
  530. package/src/tools/builtin-tool-catalog.ts +15 -0
  531. package/src/tools/compete-worktrees.ts +83 -2
  532. package/src/tools/core-bootstrap.ts +2 -1
  533. package/src/tools/dispatch-admission.ts +14 -3
  534. package/src/tools/dispatch-arguments.ts +20 -20
  535. package/src/tools/dispatch-plan.ts +17 -9
  536. package/src/tools/dispatch-run-events.ts +134 -19
  537. package/src/tools/dispatch-runner.ts +29 -7
  538. package/src/tools/dispatch-scout.ts +1 -1
  539. package/src/tools/dispatch-types.ts +15 -3
  540. package/src/tools/dispatch.ts +1 -1
  541. package/src/tools/executables.ts +17 -14
  542. package/src/tools/observation.ts +54 -4
  543. package/src/tools/panes-surface.ts +38 -0
  544. package/src/tools/panes.ts +112 -0
  545. package/src/tools/policy.ts +10 -1
  546. package/src/tools/presentation.ts +1 -0
  547. package/src/tools/registry.ts +16 -0
  548. package/dist/chunk-AOCYTWAV.js +0 -449
  549. package/dist/chunk-HLE42MG7.js +0 -37
  550. package/dist/chunk-HWUFFB6L.js +0 -83
  551. package/dist/chunk-JOZYP4GM.js +0 -279
  552. package/dist/doctor-M7YEDGAE.js +0 -91
package/src/cli/eval.ts CHANGED
@@ -2,10 +2,10 @@ import { resolve } from "node:path";
2
2
  import { InvalidIdError } from "../core/safe-id.js";
3
3
  import { clioDataDir } from "../core/xdg.js";
4
4
  import { loadEvalArtifactV4, writeEvalArtifactV4 } from "../domains/eval/artifacts/store.js";
5
- import { compareEvalArtifactsV4, renderEvalComparisonV4 } from "../domains/eval/compare/compare.js";
6
- import { evaluateGate, renderGateFailure } from "../domains/eval/compare/gates.js";
5
+ import { compareEvalArtifactsV4 } from "../domains/eval/compare/compare.js";
6
+ import { evaluateGate, renderGateFailure, renderInformationalBudget } from "../domains/eval/compare/gates.js";
7
7
  import { loadThresholds } from "../domains/eval/compare/thresholds.js";
8
-
8
+ import { type EvalComparisonReportFormat, renderEvalComparisonReportV1 } from "../domains/eval/reports/comparison.js";
9
9
  import { renderEvalJsonReportV4 } from "../domains/eval/reports/json.js";
10
10
  import { renderEvalJunitReportV4 } from "../domains/eval/reports/junit.js";
11
11
  import { renderEvalMarkdownReportV4 } from "../domains/eval/reports/markdown.js";
@@ -22,11 +22,18 @@ const HELP = `clio-coder eval <command>
22
22
 
23
23
  Commands:
24
24
  clio-coder eval validate --suite <suite.yaml>
25
- clio-coder eval run --suite <suite.yaml> [--target <id>] [--model <id>] [--out <path>] [--clio-coder-entry <path>]
26
- clio-coder eval run --task-file <tasks.yaml> [--repeat <n>] [--out <path>] [--clio-coder-entry <path>]
25
+ clio-coder eval run --suite <suite.yaml> [--trials <n>] [--target <id>] [--model <id>] [--out <path>] [--clio-coder-entry <path>]
26
+ clio-coder eval run --task-file <tasks.yaml> [--repeat <n>] [--out <path>] [--clio-coder-entry <path>]
27
27
  clio-coder eval report <evalId> --format text|json|md|swe-jsonl|junit
28
- clio-coder eval compare <baselineEvalId> <candidateEvalId>
28
+ clio-coder eval compare <baselineEvalId> <candidateEvalId> [--metric <name>] [--format text|json|md|junit] [--allow-config-drift]
29
29
  clio-coder eval gate <candidateEvalId> --baseline <baselineEvalId> [--thresholds <file>]
30
+ clio-coder eval inventory --json
31
+
32
+ inventory is the fixed machine-readable read a GUI host may run. Unlike report
33
+ and compare it names no eval id, so the process it starts cannot be steered to a
34
+ different report or a wider window. It carries each stored report's identity,
35
+ provenance, serving facts, accounting, and per-scenario outcomes, and none of
36
+ the runner attachments a report holds.
30
37
  `;
31
38
 
32
39
  type EvalCommand = "validate" | "run" | "report" | "compare" | "gate";
@@ -37,6 +44,7 @@ interface ParsedEvalArgs {
37
44
  suite?: string;
38
45
  taskFile?: string;
39
46
  repeat: number;
47
+ trials?: number;
40
48
  target?: string;
41
49
  model?: string;
42
50
  out?: string;
@@ -44,13 +52,21 @@ interface ParsedEvalArgs {
44
52
  evalId?: string;
45
53
  format: EvalReportFormat;
46
54
  compareIds: string[];
55
+ metric?: string;
56
+ allowConfigDrift: boolean;
47
57
  baseline?: string;
48
58
  thresholds?: string;
49
59
  help: boolean;
50
60
  }
51
61
 
52
62
  function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
53
- const parsed: ParsedEvalArgs = { repeat: 1, compareIds: [], format: "text", help: false };
63
+ const parsed: ParsedEvalArgs = {
64
+ repeat: 1,
65
+ compareIds: [],
66
+ format: "text",
67
+ allowConfigDrift: false,
68
+ help: false,
69
+ };
54
70
  for (let index = 0; index < args.length; index += 1) {
55
71
  const arg = args[index];
56
72
  if (arg === undefined) continue;
@@ -110,6 +126,11 @@ function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
110
126
  index += 1;
111
127
  continue;
112
128
  }
129
+ if (arg === "--trials") {
130
+ parsed.trials = positiveInteger(requiredValue(args, index, "--trials"), "--trials");
131
+ index += 1;
132
+ continue;
133
+ }
113
134
  throw new Error(`unknown eval run argument: ${arg}`);
114
135
  }
115
136
  if (parsed.command === "report") {
@@ -125,6 +146,20 @@ function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
125
146
  throw new Error(`unexpected eval report argument: ${arg}`);
126
147
  }
127
148
  if (parsed.command === "compare") {
149
+ if (arg === "--format") {
150
+ parsed.format = comparisonFormat(requiredValue(args, index, "--format"));
151
+ index += 1;
152
+ continue;
153
+ }
154
+ if (arg === "--metric") {
155
+ parsed.metric = requiredValue(args, index, "--metric");
156
+ index += 1;
157
+ continue;
158
+ }
159
+ if (arg === "--allow-config-drift") {
160
+ parsed.allowConfigDrift = true;
161
+ continue;
162
+ }
128
163
  if (!arg.startsWith("-")) {
129
164
  parsed.compareIds.push(arg);
130
165
  continue;
@@ -166,6 +201,12 @@ function parseEvalArgs(args: ReadonlyArray<string>): ParsedEvalArgs {
166
201
  }
167
202
 
168
203
  export async function runEvalCommand(args: ReadonlyArray<string>): Promise<number> {
204
+ // Routed before the shared parser so the fixed read stays exactly fixed: no
205
+ // eval flag can reach it, and no flag it does not name can be spent on it.
206
+ if (args[0] === "inventory") {
207
+ const { runEvalInventory } = await import("./eval-inventory.js");
208
+ return runEvalInventory(args.slice(1));
209
+ }
169
210
  let parsed: ParsedEvalArgs;
170
211
  try {
171
212
  parsed = parseEvalArgs(args);
@@ -202,15 +243,21 @@ async function runEvalRun(parsed: ParsedEvalArgs): Promise<number> {
202
243
  const loaded =
203
244
  parsed.suite !== undefined
204
245
  ? await loadEvalSuiteFile(parsed.suite)
205
- : await loadV1TaskFileAsSuite(parsed.taskFile ?? "", parsed.repeat);
246
+ : await loadV1TaskFileAsSuite(parsed.taskFile ?? "", parsed.trials ?? parsed.repeat);
206
247
  const resolveOptions: { target?: string; model?: string } = {};
207
248
  if (parsed.target !== undefined) resolveOptions.target = parsed.target;
208
249
  if (parsed.model !== undefined) resolveOptions.model = parsed.model;
209
- const suite = resolveSuiteForRun(loaded.suite, resolveOptions);
250
+ const suite = resolveSuiteForRun(loaded.suite, {
251
+ ...resolveOptions,
252
+ ...(parsed.trials ? { trials: parsed.trials } : {}),
253
+ });
210
254
  // Runner commands execute with cwd inside prepared eval workspaces, so a
211
255
  // relative --clio-coder-entry must be pinned to the invoking directory here.
212
256
  const clioEntry = resolve(parsed.clioEntry ?? process.argv[1] ?? "dist/cli/index.js");
213
- const artifact = await runEvalSuiteV2({ ...loaded, suite }, { clioEntry });
257
+ const artifact = await runEvalSuiteV2(
258
+ { ...loaded, suite },
259
+ { clioEntry, freshWorkspaces: parsed.trials !== undefined },
260
+ );
214
261
  const artifactPath = await writeEvalArtifactV4(clioDataDir(), artifact, parsed.out);
215
262
  process.stdout.write(`${renderEvalTextReportV4(artifact)}artifact: ${artifactPath}\n`);
216
263
  // A suite that declares thresholds is gated by them here, on the artifact
@@ -221,6 +268,10 @@ async function runEvalRun(parsed: ParsedEvalArgs): Promise<number> {
221
268
  process.stdout.write(`gate: fail (${gate.failures.length} threshold failure)\n`);
222
269
  for (const failure of gate.failures) process.stdout.write(renderGateFailure(failure));
223
270
  }
271
+ if (gate !== null && gate.informational.length > 0) {
272
+ process.stdout.write(`informational budgets: ${gate.informational.length} notice\n`);
273
+ for (const finding of gate.informational) process.stdout.write(renderInformationalBudget(finding));
274
+ }
224
275
  return artifact.summary.failed === 0 && (gate === null || gate.pass) ? 0 : 1;
225
276
  } catch (error) {
226
277
  return handleEvalLoadError(error, 1);
@@ -246,8 +297,12 @@ async function runEvalCompareCommand(parsed: ParsedEvalArgs): Promise<number> {
246
297
  const dataDir = clioDataDir();
247
298
  const baseline = await loadEvalArtifactV4(dataDir, baselineEvalId);
248
299
  const candidate = await loadEvalArtifactV4(dataDir, candidateEvalId);
249
- process.stdout.write(renderEvalComparisonV4(compareEvalArtifactsV4(baseline, candidate)));
250
- return 0;
300
+ const summary = compareEvalArtifactsV4(baseline, candidate, {
301
+ allowConfigDrift: parsed.allowConfigDrift,
302
+ ...(parsed.metric === undefined ? {} : { metric: parsed.metric }),
303
+ });
304
+ process.stdout.write(renderEvalComparisonReportV1(summary, parsed.format as EvalComparisonReportFormat));
305
+ return summary.hardGate.pass ? 0 : 1;
251
306
  } catch (error) {
252
307
  printError(error instanceof Error ? error.message : String(error));
253
308
  return error instanceof InvalidIdError ? 2 : 1;
@@ -258,18 +313,35 @@ async function runEvalGateCommand(parsed: ParsedEvalArgs): Promise<number> {
258
313
  try {
259
314
  const dataDir = clioDataDir();
260
315
  const candidate = await loadEvalArtifactV4(dataDir, parsed.evalId ?? "");
261
- await loadEvalArtifactV4(dataDir, parsed.baseline ?? "");
316
+ const baseline = await loadEvalArtifactV4(dataDir, parsed.baseline ?? "");
262
317
  const thresholds =
263
318
  parsed.thresholds === undefined
264
- ? { fail: [{ metric: "result.pass", op: "eq" as const, value: false }] }
319
+ ? { fail: [{ metric: "result.pass", op: "eq" as const, value: false }], informational: [] }
265
320
  : loadThresholds(parsed.thresholds);
266
321
  const gate = evaluateGate(candidate, thresholds);
267
- if (gate.pass) {
322
+ const comparison = compareEvalArtifactsV4(baseline, candidate);
323
+ if (gate.informational.length > 0) {
324
+ process.stdout.write(`informational budgets: ${gate.informational.length} notice\n`);
325
+ for (const finding of gate.informational) process.stdout.write(renderInformationalBudget(finding));
326
+ }
327
+ if (gate.pass && comparison.hardGate.pass) {
268
328
  process.stdout.write("gate: pass\n");
269
329
  return 0;
270
330
  }
271
- process.stdout.write(`gate: fail (${gate.failures.length} threshold failure)\n`);
331
+ const failureCount =
332
+ gate.failures.length + comparison.hardGate.failures.length + comparison.hardGate.envelopeFailures.length;
333
+ process.stdout.write(`gate: fail (${failureCount} hard failure)\n`);
272
334
  for (const failure of gate.failures) process.stdout.write(renderGateFailure(failure));
335
+ for (const failure of comparison.hardGate.failures) {
336
+ process.stdout.write(
337
+ ` ${failure.metric} [${failure.scenarioId}:${failure.role}:${failure.target.id}/${failure.target.model ?? "none"}]: ${failure.change} (hard behavioral gate)\n`,
338
+ );
339
+ }
340
+ for (const failure of comparison.hardGate.envelopeFailures) {
341
+ process.stdout.write(
342
+ ` execution envelope [${failure.scenarioId}:${failure.role}:${failure.target.id}/${failure.target.model ?? "none"}]: incomparable fields ${failure.fields.join(", ")}\n`,
343
+ );
344
+ }
273
345
  return 1;
274
346
  } catch (error) {
275
347
  printError(error instanceof Error ? error.message : String(error));
@@ -313,3 +385,8 @@ function reportFormat(value: string): EvalReportFormat {
313
385
  if (value === "text" || value === "json" || value === "md" || value === "swe-jsonl" || value === "junit") return value;
314
386
  throw new Error("--format must be text, json, md, swe-jsonl, or junit");
315
387
  }
388
+
389
+ function comparisonFormat(value: string): EvalComparisonReportFormat {
390
+ if (value === "text" || value === "json" || value === "md" || value === "junit") return value;
391
+ throw new Error("eval compare --format must be text, json, md, or junit");
392
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Fixed machine-readable projection of one evidence bundle's trust record.
3
+ *
4
+ * `evidence inspect <id>` prints an operator record that quotes the task text,
5
+ * the bundle's file list, and per-finding prose. This is the same bundle read
6
+ * down to the one thing a GUI can carry safely and usefully: which runs the
7
+ * bundle covers, what verdict each run earned, and which axis produced it.
8
+ *
9
+ * Every value here comes from a closed vocabulary. The axis names, the axis
10
+ * states, and the verdicts are all enumerations the harness owns, so there is
11
+ * no free-form text on this surface at all, which is what lets it answer the
12
+ * question the inventory raises without reopening the boundary the inventory
13
+ * closed.
14
+ *
15
+ * Unlike the other fixed reads this one takes an identifier, because an
16
+ * operator names the bundle. The GUI host may only pass back an id it served
17
+ * inside its current bounded window; see `apps/workbench/artifact-allowlist.ts`.
18
+ */
19
+
20
+ import { clioDataDir } from "../core/xdg.js";
21
+ import {
22
+ inspectEvidence,
23
+ TRUST_STATUS_AXES,
24
+ type TrustStatusAxis,
25
+ type TrustVerdict,
26
+ trustVerdict,
27
+ } from "../domains/evidence/index.js";
28
+
29
+ export const EVIDENCE_DETAIL_MAX_RUNS = 16;
30
+
31
+ export interface EvidenceDetailRun {
32
+ readonly runId: string;
33
+ readonly verdict: TrustVerdict;
34
+ /** Every axis, always all six, so an absent axis is stated rather than missing. */
35
+ readonly axes: Readonly<Record<TrustStatusAxis, string>>;
36
+ }
37
+
38
+ export interface EvidenceDetailSnapshot {
39
+ readonly version: 1;
40
+ readonly generatedAt: string;
41
+ readonly evidenceId: string;
42
+ readonly sourceKind: "run" | "session" | "eval";
43
+ /** False when the bundle predates the canonical trust projection. */
44
+ readonly canonical: boolean;
45
+ readonly runs: readonly EvidenceDetailRun[];
46
+ readonly runsTruncated: boolean;
47
+ }
48
+
49
+ export async function evidenceDetailSnapshot(
50
+ evidenceId: string,
51
+ now: () => number = Date.now,
52
+ dataDir: string = clioDataDir(),
53
+ ): Promise<EvidenceDetailSnapshot> {
54
+ const inspected = await inspectEvidence(dataDir, evidenceId);
55
+ const all = inspected.trustStatus.runs;
56
+ const window = all.slice(0, EVIDENCE_DETAIL_MAX_RUNS);
57
+ return {
58
+ version: 1,
59
+ generatedAt: new Date(now()).toISOString(),
60
+ evidenceId: inspected.overview.evidenceId,
61
+ sourceKind: inspected.overview.source.kind,
62
+ canonical: inspected.trustStatus.projection === "canonical",
63
+ runs: window.map(
64
+ (run): EvidenceDetailRun => ({
65
+ runId: run.runId,
66
+ verdict: trustVerdict(run.status),
67
+ axes: Object.fromEntries(TRUST_STATUS_AXES.map((axis) => [axis, run.status[axis].state])) as Record<
68
+ TrustStatusAxis,
69
+ string
70
+ >,
71
+ }),
72
+ ),
73
+ runsTruncated: all.length > window.length,
74
+ };
75
+ }
76
+
77
+ /**
78
+ * `clio-coder evidence inspect <id> --json`.
79
+ *
80
+ * The id is the only argument, and the caller supplies it. A GUI host is bound
81
+ * by its own allowlist rather than by this command, because an operator typing
82
+ * an id at a terminal is naming something on their own machine, which is a
83
+ * different act from a browser frame naming it.
84
+ */
85
+ export async function runEvidenceDetail(evidenceId: string): Promise<number> {
86
+ process.stdout.write(`${JSON.stringify(await evidenceDetailSnapshot(evidenceId), null, 2)}\n`);
87
+ return 0;
88
+ }
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Fixed machine-readable projection of recent evidence artifacts.
3
+ *
4
+ * `evidence list` is an operator table and `evidence inspect <id>` needs an id,
5
+ * so neither is a transport a GUI host can invoke blind. This command accepts
6
+ * no identifier, path, or limit, selects a bounded newest-first window itself,
7
+ * and emits provenance, tags, totals, and a trust verdict.
8
+ *
9
+ * An overview carries the working directories the runs executed in, the task
10
+ * text the operator typed, and the file names inside the bundle. None of that
11
+ * appears here. What does is the shape of the artifact and how far it can be
12
+ * trusted, which is what an operator picks a bundle by.
13
+ */
14
+
15
+ import { clioDataDir } from "../core/xdg.js";
16
+ import {
17
+ EVIDENCE_TAGS,
18
+ type EvidenceOverview,
19
+ type EvidenceTag,
20
+ listEvidenceOverviews,
21
+ loadEvidenceTrustStatus,
22
+ type TrustVerdict,
23
+ trustVerdict,
24
+ } from "../domains/evidence/index.js";
25
+ import { sanitizeCallTargetText } from "../domains/safety/call-target.js";
26
+ import { truncateToWidth } from "../engine/tui-primitives.js";
27
+
28
+ export const EVIDENCE_INVENTORY_MAX_ARTIFACTS = 12;
29
+ export const EVIDENCE_INVENTORY_MAX_IDS = 8;
30
+
31
+ const IDENTITY_WIDTH = 128;
32
+
33
+ /**
34
+ * Worst verdict first.
35
+ *
36
+ * An artifact covering several runs is only as trustworthy as its weakest run,
37
+ * so the fold takes the worst rather than the newest or the most common. A
38
+ * `compromised` run inside an otherwise clean bundle is the fact the operator
39
+ * needs, and averaging it away would be the one summary worth not printing.
40
+ */
41
+ const VERDICT_SEVERITY: ReadonlyArray<TrustVerdict> = ["compromised", "unverified", "unknown", "grounded", "reviewed"];
42
+
43
+ export interface EvidenceInventoryArtifact {
44
+ readonly evidenceId: string;
45
+ readonly sourceKind: "run" | "session" | "eval";
46
+ readonly generatedAt: string;
47
+ readonly startedAt: string | null;
48
+ readonly endedAt: string | null;
49
+ readonly runIds: readonly string[];
50
+ readonly runIdsTruncated: boolean;
51
+ readonly agentIds: readonly string[];
52
+ readonly statuses: readonly string[];
53
+ readonly tags: readonly EvidenceTag[];
54
+ readonly totals: Readonly<{
55
+ runs: number;
56
+ receipts: number;
57
+ toolCalls: number;
58
+ toolErrors: number;
59
+ blockedToolCalls: number;
60
+ protectedArtifacts: number;
61
+ tokens: number;
62
+ costUsd: number;
63
+ wallTimeMs: number;
64
+ }>;
65
+ /** Secret-shaped values the builder replaced across the bundle's exports. */
66
+ readonly redactionCount: number;
67
+ readonly trust: Readonly<{
68
+ verdict: TrustVerdict;
69
+ /** Runs whose canonical trust status the bundle actually recorded. */
70
+ runsCovered: number;
71
+ /** True when the bundle predates the canonical trust projection. */
72
+ historical: boolean;
73
+ }>;
74
+ }
75
+
76
+ export interface EvidenceInventorySnapshot {
77
+ readonly version: 1;
78
+ readonly generatedAt: string;
79
+ readonly artifacts: readonly EvidenceInventoryArtifact[];
80
+ readonly truncated: boolean;
81
+ }
82
+
83
+ function bounded(value: string, width: number): string {
84
+ const sanitized = sanitizeCallTargetText(value);
85
+ if (sanitized.length === 0) return "unavailable";
86
+ return sanitizeCallTargetText(truncateToWidth(sanitized, width, "…", false));
87
+ }
88
+
89
+ /** Distinct, sanitized, bounded, in first-seen order. */
90
+ function identities(values: ReadonlyArray<string>): string[] {
91
+ const seen: string[] = [];
92
+ for (const value of values) {
93
+ const text = bounded(value, IDENTITY_WIDTH);
94
+ if (!seen.includes(text)) seen.push(text);
95
+ if (seen.length >= EVIDENCE_INVENTORY_MAX_IDS) break;
96
+ }
97
+ return seen;
98
+ }
99
+
100
+ function tally(value: number | undefined): number {
101
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.trunc(value) : 0;
102
+ }
103
+
104
+ function amount(value: number | undefined): number {
105
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
106
+ }
107
+
108
+ /** Newest generation first. An unparseable stamp sorts oldest rather than throwing. */
109
+ function byNewest(a: EvidenceOverview, b: EvidenceOverview): number {
110
+ return (Date.parse(b.generatedAt) || 0) - (Date.parse(a.generatedAt) || 0);
111
+ }
112
+
113
+ export async function evidenceInventorySnapshot(
114
+ now: () => number = Date.now,
115
+ dataDir: string = clioDataDir(),
116
+ ): Promise<EvidenceInventorySnapshot> {
117
+ const all = (await listEvidenceOverviews(dataDir)).sort(byNewest);
118
+ const window = all.slice(0, EVIDENCE_INVENTORY_MAX_ARTIFACTS);
119
+ const artifacts: EvidenceInventoryArtifact[] = [];
120
+ for (const overview of window) {
121
+ // One unreadable trust file costs that artifact its verdict, never the
122
+ // whole inventory: the bundle itself is still the thing being listed.
123
+ let verdict: TrustVerdict = "unknown";
124
+ let runsCovered = 0;
125
+ let historical = true;
126
+ try {
127
+ const status = await loadEvidenceTrustStatus(dataDir, overview.evidenceId);
128
+ historical = status.projection !== "canonical";
129
+ runsCovered = status.runs.length;
130
+ const verdicts = status.runs.map((run) => trustVerdict(run.status));
131
+ verdict = VERDICT_SEVERITY.find((candidate) => verdicts.includes(candidate)) ?? "unknown";
132
+ } catch {
133
+ verdict = "unknown";
134
+ }
135
+ artifacts.push({
136
+ evidenceId: bounded(overview.evidenceId, IDENTITY_WIDTH),
137
+ sourceKind: overview.source.kind,
138
+ generatedAt: overview.generatedAt,
139
+ startedAt: overview.startedAt,
140
+ endedAt: overview.endedAt,
141
+ runIds: identities(overview.runIds),
142
+ runIdsTruncated: overview.runIds.length > EVIDENCE_INVENTORY_MAX_IDS,
143
+ agentIds: identities(overview.agentIds),
144
+ statuses: identities(overview.statuses),
145
+ tags: overview.tags.filter((tag) => EVIDENCE_TAGS.includes(tag)),
146
+ totals: {
147
+ runs: tally(overview.totals.runs),
148
+ receipts: tally(overview.totals.receipts),
149
+ toolCalls: tally(overview.totals.toolCalls),
150
+ toolErrors: tally(overview.totals.toolErrors),
151
+ blockedToolCalls: tally(overview.totals.blockedToolCalls),
152
+ protectedArtifacts: tally(overview.totals.protectedArtifacts),
153
+ tokens: tally(overview.totals.tokens),
154
+ costUsd: amount(overview.totals.costUsd),
155
+ wallTimeMs: tally(overview.totals.wallTimeMs),
156
+ },
157
+ redactionCount: tally(overview.redactionCount),
158
+ trust: { verdict, runsCovered, historical },
159
+ });
160
+ }
161
+ return {
162
+ version: 1,
163
+ generatedAt: new Date(now()).toISOString(),
164
+ artifacts,
165
+ truncated: all.length > window.length,
166
+ };
167
+ }
168
+
169
+ /**
170
+ * `clio-coder evidence inventory --json`, and nothing else.
171
+ *
172
+ * `fixed` is false as soon as the caller supplied an id or any other argument.
173
+ * A GUI host invokes this knowing the process it started cannot be steered into
174
+ * reading a different bundle or a wider window.
175
+ */
176
+ export async function runEvidenceInventory(fixed: boolean): Promise<number> {
177
+ if (!fixed) {
178
+ process.stderr.write("clio-coder evidence inventory: usage: clio-coder evidence inventory --json\n");
179
+ return 2;
180
+ }
181
+ process.stdout.write(`${JSON.stringify(await evidenceInventorySnapshot(), null, 2)}\n`);
182
+ return 0;
183
+ }
@@ -12,21 +12,25 @@ import {
12
12
  loadEvidenceRunProvenance,
13
13
  provenanceTranscriptLines,
14
14
  } from "../domains/evidence/index.js";
15
+ import { runEvidenceDetail } from "./evidence-detail.js";
16
+ import { runEvidenceInventory } from "./evidence-inventory.js";
15
17
  import { printError, printNote, printOk } from "./shared.js";
16
18
 
17
19
  const HELP = `clio-coder evidence build --run <runId>
18
20
  clio-coder evidence build --session <sessionId>
19
21
  clio-coder evidence build --eval <evalId>
20
- clio-coder evidence inspect <evidenceId>
22
+ clio-coder evidence inspect <evidenceId> [--json]
21
23
  clio-coder evidence list
24
+ clio-coder evidence inventory --json
22
25
 
23
26
  Build or inspect deterministic Clio evidence artifacts.
24
27
  `;
25
28
 
26
- type EvidenceCommand = "build" | "inspect" | "list";
29
+ type EvidenceCommand = "build" | "inspect" | "list" | "inventory";
27
30
 
28
31
  interface ParsedEvidenceArgs {
29
32
  command?: EvidenceCommand;
33
+ json: boolean;
30
34
  runId?: string;
31
35
  sessionId?: string;
32
36
  evalId?: string;
@@ -35,7 +39,7 @@ interface ParsedEvidenceArgs {
35
39
  }
36
40
 
37
41
  function parseEvidenceArgs(args: ReadonlyArray<string>): ParsedEvidenceArgs {
38
- const parsed: ParsedEvidenceArgs = { help: false };
42
+ const parsed: ParsedEvidenceArgs = { help: false, json: false };
39
43
  for (let index = 0; index < args.length; index += 1) {
40
44
  const arg = args[index];
41
45
  if (arg === undefined) continue;
@@ -44,12 +48,22 @@ function parseEvidenceArgs(args: ReadonlyArray<string>): ParsedEvidenceArgs {
44
48
  continue;
45
49
  }
46
50
  if (parsed.command === undefined) {
47
- if (arg === "build" || arg === "inspect" || arg === "list") {
51
+ if (arg === "build" || arg === "inspect" || arg === "list" || arg === "inventory") {
48
52
  parsed.command = arg;
49
53
  continue;
50
54
  }
51
55
  throw new Error(`unknown evidence command: ${arg}`);
52
56
  }
57
+ // `inventory` is the fixed read a GUI host may invoke. Its argv is not a
58
+ // surface, so anything past the one required flag is a usage error rather
59
+ // than something to ignore.
60
+ if (parsed.command === "inventory") {
61
+ if (arg === "--json" && !parsed.json) {
62
+ parsed.json = true;
63
+ continue;
64
+ }
65
+ throw new Error("inventory accepts only --json");
66
+ }
53
67
  if (parsed.command === "build") {
54
68
  if (arg === "--run") {
55
69
  const value = args[index + 1];
@@ -74,6 +88,10 @@ function parseEvidenceArgs(args: ReadonlyArray<string>): ParsedEvidenceArgs {
74
88
  }
75
89
  throw new Error(`unknown evidence build argument: ${arg}`);
76
90
  }
91
+ if (parsed.command === "inspect" && arg === "--json" && !parsed.json) {
92
+ parsed.json = true;
93
+ continue;
94
+ }
77
95
  if (parsed.command === "inspect" && parsed.evidenceId === undefined) {
78
96
  if (arg.startsWith("-")) throw new Error("inspect requires an evidence id");
79
97
  parsed.evidenceId = arg;
@@ -103,6 +121,11 @@ function parseEvidenceArgs(args: ReadonlyArray<string>): ParsedEvidenceArgs {
103
121
  ) {
104
122
  throw new Error("list does not accept extra arguments");
105
123
  }
124
+ // The GUI read is only fixed if `--json` is required rather than defaulted:
125
+ // a bare `evidence inventory` must not quietly print something else.
126
+ if (parsed.command === "inventory" && !parsed.json) {
127
+ throw new Error("inventory requires --json");
128
+ }
106
129
  return parsed;
107
130
  }
108
131
 
@@ -159,6 +182,7 @@ export async function runEvidenceCommand(args: ReadonlyArray<string>): Promise<n
159
182
  printError("inspect requires an evidence id");
160
183
  return 2;
161
184
  }
185
+ if (parsed.json) return runEvidenceDetail(evidenceId);
162
186
  const inspected = await inspectEvidence(dataDir, evidenceId);
163
187
  const provenance = await loadEvidenceRunProvenance(dataDir, evidenceId);
164
188
  renderEvidence(inspected, provenance);
@@ -168,7 +192,8 @@ export async function runEvidenceCommand(args: ReadonlyArray<string>): Promise<n
168
192
  renderEvidenceList(await listEvidenceOverviews(dataDir));
169
193
  return 0;
170
194
  }
171
- printError("evidence requires build, inspect, or list");
195
+ if (parsed.command === "inventory") return runEvidenceInventory(parsed.json);
196
+ printError("evidence requires build, inspect, list, or inventory");
172
197
  return 2;
173
198
  } catch (error) {
174
199
  printError(error instanceof Error ? error.message : String(error));
@@ -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": {
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Fixed machine-readable projection of durable coordinator gate decisions.
3
+ *
4
+ * A review or compete gate seals an integrity-covered artifact linking the
5
+ * decider receipt to every subject receipt, and nothing in the operator surface
6
+ * reads them: `fleet view` shows a run, not the verdict a gate reached about
7
+ * it. This command accepts no identifier, group, or limit, selects a bounded
8
+ * newest-first window itself, and emits the shape of each decision.
9
+ *
10
+ * It is a separate command from `fleet inspect --json` rather than another
11
+ * field on it, on the same reasoning the trace read used. The decisions live in
12
+ * their own directory with their own failure mode, and an installation that has
13
+ * never run a gate has no directory at all, so folding the read in would turn a
14
+ * missing directory into a failure of the run journal.
15
+ */
16
+
17
+ import {
18
+ GATE_TOPOLOGY_MAX_DECISIONS,
19
+ GATE_TOPOLOGY_MAX_SUBJECTS,
20
+ type GateDecisionReason,
21
+ type GateTopologyDecision,
22
+ gateTopology,
23
+ } from "../domains/dispatch/gate-topology.js";
24
+
25
+ export {
26
+ GATE_TOPOLOGY_MAX_DECISIONS as FLEET_DECISIONS_MAX,
27
+ GATE_TOPOLOGY_MAX_SUBJECTS as FLEET_DECISIONS_MAX_SUBJECTS,
28
+ };
29
+
30
+ export interface FleetDecisionsSnapshot {
31
+ readonly version: 1;
32
+ readonly generatedAt: string;
33
+ readonly available: boolean;
34
+ readonly decisions: readonly GateTopologyDecision[];
35
+ readonly truncated: boolean;
36
+ readonly unverifiable: number;
37
+ }
38
+
39
+ export type { GateDecisionReason, GateTopologyDecision };
40
+
41
+ /**
42
+ * Pure command payload builder, exported so the fixed CLI contract is testable
43
+ * without subprocess output capture.
44
+ *
45
+ * `available` separates an installation that has never run a gate from one
46
+ * whose gates all aged out of the scan. Both report no decisions and they are
47
+ * different operator states, so the flag is reported rather than inferred from
48
+ * an empty list.
49
+ */
50
+ export function fleetDecisionsSnapshot(now: () => number = Date.now): FleetDecisionsSnapshot {
51
+ const topology = gateTopology();
52
+ return {
53
+ version: 1,
54
+ generatedAt: new Date(now()).toISOString(),
55
+ available: topology.present,
56
+ decisions: topology.decisions,
57
+ truncated: topology.truncated,
58
+ unverifiable: topology.unverifiable,
59
+ };
60
+ }
61
+
62
+ export function runFleetDecisions(args: ReadonlyArray<string>): number {
63
+ if (args.length !== 1 || args[0] !== "--json") {
64
+ process.stderr.write("clio-coder fleet decisions: usage: clio-coder fleet decisions --json\n");
65
+ return 2;
66
+ }
67
+ process.stdout.write(`${JSON.stringify(fleetDecisionsSnapshot(), null, 2)}\n`);
68
+ return 0;
69
+ }