@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
@@ -0,0 +1,224 @@
1
+ import type { EvalArtifactResultV4, EvalArtifactV4 } from "../schema/artifact.js";
2
+ import {
3
+ EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1,
4
+ type EvalBehaviorMetricDefinitionV1,
5
+ type EvalBehaviorMetricFamilyV1,
6
+ type EvalBehaviorMetricNameV1,
7
+ type EvalBehaviorMetricSourceV1,
8
+ } from "../schema/behavioral-metrics.js";
9
+ import type { EvalExecutionMatrixDimensionV1 } from "../schema/execution-envelope.js";
10
+ import {
11
+ compareEvalExecutionEnvelopesV1,
12
+ type EvalEnvelopeComparabilityV1,
13
+ type EvalEnvelopeMismatchV1,
14
+ } from "./envelope.js";
15
+
16
+ export type EvalMetricChangeV1 = "improved" | "regressed" | "unchanged" | "incomparable";
17
+
18
+ export interface EvalBehaviorMetricDistributionV1 {
19
+ observations: number;
20
+ measured: number;
21
+ unmeasured: number;
22
+ mean: number | null;
23
+ min: number | null;
24
+ max: number | null;
25
+ p90: number | null;
26
+ variance: number | null;
27
+ standardDeviation: number | null;
28
+ source: EvalBehaviorMetricSourceV1;
29
+ }
30
+
31
+ export interface EvalBehaviorMetricComparisonV1 {
32
+ scenarioId: string;
33
+ role: string;
34
+ target: { id: string; model: string | null };
35
+ metric: EvalBehaviorMetricNameV1;
36
+ family: EvalBehaviorMetricFamilyV1;
37
+ direction: "higher" | "lower";
38
+ hardGate: boolean;
39
+ baseline: EvalBehaviorMetricDistributionV1;
40
+ candidate: EvalBehaviorMetricDistributionV1;
41
+ change: EvalMetricChangeV1;
42
+ meanDelta: number | null;
43
+ varianceChange: EvalMetricChangeV1;
44
+ varianceDelta: number | null;
45
+ comparability: EvalEnvelopeComparabilityV1;
46
+ }
47
+
48
+ export interface EvalBehaviorHardGateV1 {
49
+ pass: boolean;
50
+ envelopeFailures: EvalEnvelopeMismatchV1[];
51
+ failures: Array<{
52
+ scenarioId: string;
53
+ role: string;
54
+ target: { id: string; model: string | null };
55
+ metric: EvalBehaviorMetricNameV1;
56
+ change: "regressed" | "incomparable";
57
+ }>;
58
+ }
59
+
60
+ interface BehaviorGroup {
61
+ scenarioId: string;
62
+ role: string;
63
+ target: { id: string; model: string | null };
64
+ results: EvalArtifactResultV4[];
65
+ }
66
+
67
+ export function compareEvalBehaviorMetricsV1(
68
+ baseline: EvalArtifactV4,
69
+ candidate: EvalArtifactV4,
70
+ ): {
71
+ comparisons: EvalBehaviorMetricComparisonV1[];
72
+ hardGate: EvalBehaviorHardGateV1;
73
+ envelopeMismatches: EvalEnvelopeMismatchV1[];
74
+ } {
75
+ const baselineGroups = behaviorGroups(baseline);
76
+ const candidateGroups = behaviorGroups(candidate);
77
+ const keys = new Set([...baselineGroups.keys(), ...candidateGroups.keys()]);
78
+ const comparisons: EvalBehaviorMetricComparisonV1[] = [];
79
+ const envelopeMismatches: EvalEnvelopeMismatchV1[] = [];
80
+ const baselineDimensions = baseline.matrix.dimensions ?? ([] as EvalExecutionMatrixDimensionV1[]);
81
+ const candidateDimensions = candidate.matrix.dimensions ?? ([] as EvalExecutionMatrixDimensionV1[]);
82
+ for (const key of [...keys].sort((left, right) => left.localeCompare(right))) {
83
+ const baselineGroup = baselineGroups.get(key);
84
+ const candidateGroup = candidateGroups.get(key);
85
+ const identity = baselineGroup ?? candidateGroup;
86
+ if (identity === undefined) continue;
87
+ const envelopeMismatch = compareEvalExecutionEnvelopesV1(
88
+ identity,
89
+ baselineGroup?.results ?? [],
90
+ candidateGroup?.results ?? [],
91
+ baselineDimensions,
92
+ candidateDimensions,
93
+ );
94
+ if (envelopeMismatch !== null) envelopeMismatches.push(envelopeMismatch);
95
+ const comparability: EvalEnvelopeComparabilityV1 = {
96
+ comparable: envelopeMismatch === null,
97
+ mismatchedFields: envelopeMismatch?.fields ?? [],
98
+ };
99
+ for (const definition of EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1) {
100
+ const baselineDistribution = behaviorDistribution(baselineGroup?.results ?? [], definition);
101
+ const candidateDistribution = behaviorDistribution(candidateGroup?.results ?? [], definition);
102
+ comparisons.push({
103
+ scenarioId: identity.scenarioId,
104
+ role: identity.role,
105
+ target: identity.target,
106
+ metric: definition.name,
107
+ family: definition.family,
108
+ direction: definition.direction,
109
+ hardGate: definition.hardGate,
110
+ baseline: baselineDistribution,
111
+ candidate: candidateDistribution,
112
+ change:
113
+ envelopeMismatch === null
114
+ ? classifyChange(baselineDistribution.mean, candidateDistribution.mean, definition.direction)
115
+ : "incomparable",
116
+ meanDelta: subtractNullable(candidateDistribution.mean, baselineDistribution.mean),
117
+ varianceChange:
118
+ envelopeMismatch === null
119
+ ? classifyChange(baselineDistribution.variance, candidateDistribution.variance, "lower")
120
+ : "incomparable",
121
+ varianceDelta: subtractNullable(candidateDistribution.variance, baselineDistribution.variance),
122
+ comparability,
123
+ });
124
+ }
125
+ }
126
+ const failures = comparisons.flatMap((comparison) =>
127
+ comparison.hardGate &&
128
+ (comparison.change === "regressed" ||
129
+ (comparison.change === "incomparable" && comparison.baseline.mean !== null && comparison.candidate.mean === null))
130
+ ? [
131
+ {
132
+ scenarioId: comparison.scenarioId,
133
+ role: comparison.role,
134
+ target: comparison.target,
135
+ metric: comparison.metric,
136
+ change: comparison.change,
137
+ },
138
+ ]
139
+ : [],
140
+ );
141
+ return {
142
+ comparisons,
143
+ hardGate: {
144
+ pass: failures.length === 0 && envelopeMismatches.length === 0,
145
+ failures,
146
+ envelopeFailures: envelopeMismatches,
147
+ },
148
+ envelopeMismatches,
149
+ };
150
+ }
151
+
152
+ export function classifyChange(
153
+ baseline: number | null,
154
+ candidate: number | null,
155
+ direction: "higher" | "lower",
156
+ ): EvalMetricChangeV1 {
157
+ if (baseline === null || candidate === null) return "incomparable";
158
+ if (baseline === candidate) return "unchanged";
159
+ if (direction === "higher") return candidate > baseline ? "improved" : "regressed";
160
+ return candidate < baseline ? "improved" : "regressed";
161
+ }
162
+
163
+ function behaviorGroups(artifact: EvalArtifactV4): Map<string, BehaviorGroup> {
164
+ const groups = new Map<string, BehaviorGroup>();
165
+ for (const result of artifact.results) {
166
+ const behavioral = result.behavioralMetrics;
167
+ if (behavioral === undefined) continue;
168
+ const key = groupKey(behavioral.scenarioId, behavioral.role, behavioral.target);
169
+ const group = groups.get(key) ?? {
170
+ scenarioId: behavioral.scenarioId,
171
+ role: behavioral.role,
172
+ target: behavioral.target,
173
+ results: [],
174
+ };
175
+ group.results.push(result);
176
+ groups.set(key, group);
177
+ }
178
+ return groups;
179
+ }
180
+
181
+ function behaviorDistribution(
182
+ results: ReadonlyArray<EvalArtifactResultV4>,
183
+ definition: EvalBehaviorMetricDefinitionV1,
184
+ ): EvalBehaviorMetricDistributionV1 {
185
+ const observations = results.map((result) => result.behavioralMetrics?.metrics[definition.name].value ?? null);
186
+ const values = observations.flatMap((value) => (value === null ? [] : [value]));
187
+ if (values.length === 0) {
188
+ return {
189
+ observations: observations.length,
190
+ measured: 0,
191
+ unmeasured: observations.length,
192
+ mean: null,
193
+ min: null,
194
+ max: null,
195
+ p90: null,
196
+ variance: null,
197
+ standardDeviation: null,
198
+ source: definition.source,
199
+ };
200
+ }
201
+ const ordered = [...values].sort((left, right) => left - right);
202
+ const mean = ordered.reduce((sum, value) => sum + value, 0) / ordered.length;
203
+ const variance = ordered.reduce((sum, value) => sum + (value - mean) ** 2, 0) / ordered.length;
204
+ return {
205
+ observations: observations.length,
206
+ measured: values.length,
207
+ unmeasured: observations.length - values.length,
208
+ mean,
209
+ min: ordered[0] ?? null,
210
+ max: ordered.at(-1) ?? null,
211
+ p90: ordered[Math.max(0, Math.ceil(ordered.length * 0.9) - 1)] ?? null,
212
+ variance,
213
+ standardDeviation: Math.sqrt(variance),
214
+ source: definition.source,
215
+ };
216
+ }
217
+
218
+ function groupKey(scenarioId: string, role: string, target: { id: string; model: string | null }): string {
219
+ return JSON.stringify([scenarioId, role, target.id, target.model]);
220
+ }
221
+
222
+ function subtractNullable(left: number | null, right: number | null): number | null {
223
+ return left === null || right === null ? null : left - right;
224
+ }
@@ -1,33 +1,386 @@
1
+ import { aggregateEvalVerdicts, type EvalMetricDistributionV1 } from "../metrics/aggregate.js";
2
+ import { assertComparableTrackedMetricSources } from "../run-compare.js";
1
3
  import type { EvalArtifactV4 } from "../schema/artifact.js";
4
+ import {
5
+ type EvalServingConfigurationV1,
6
+ renderEvalServingConfiguration,
7
+ sameEvalServingConfiguration,
8
+ } from "../schema/serving.js";
9
+ import { EVAL_TRACKED_METRIC_NAMES } from "../schema/verdict.js";
10
+ import {
11
+ classifyChange,
12
+ compareEvalBehaviorMetricsV1,
13
+ type EvalBehaviorHardGateV1,
14
+ type EvalBehaviorMetricComparisonV1,
15
+ type EvalMetricChangeV1,
16
+ } from "./behavioral.js";
17
+ import type { EvalEnvelopeMismatchV1 } from "./envelope.js";
18
+
19
+ export interface EvalCompareV4Options {
20
+ metric?: string;
21
+ allowConfigDrift?: boolean;
22
+ }
23
+
24
+ export interface EvalTrackedMetricComparisonV1 {
25
+ scenarioId: string;
26
+ metric: string;
27
+ baseline: EvalMetricDistributionV1;
28
+ candidate: EvalMetricDistributionV1;
29
+ meanDelta: number | null;
30
+ p90Delta: number | null;
31
+ varianceDelta: number | null;
32
+ change: EvalMetricChangeV1;
33
+ varianceChange: EvalMetricChangeV1;
34
+ }
2
35
 
3
36
  export interface EvalCompareV4Summary {
4
37
  baselineEvalId: string;
5
38
  candidateEvalId: string;
39
+ baselineServingConfiguration: EvalServingConfigurationV1;
40
+ candidateServingConfiguration: EvalServingConfigurationV1;
41
+ configDrift: boolean;
6
42
  passRateDelta: number;
7
- /** Null when either side observed no usage: a delta against an unknown is not zero. */
43
+ /** Null when either side observed no usage because a delta against an unknown is not zero. */
8
44
  tokenDelta: number | null;
9
45
  wallTimeDelta: number;
46
+ trackedMetrics: EvalTrackedMetricComparisonV1[];
47
+ behavioralMetrics: EvalBehaviorMetricComparisonV1[];
48
+ hardGate: EvalBehaviorHardGateV1;
49
+ envelopeMismatches: EvalEnvelopeMismatchV1[];
50
+ scenarioReports: EvalBehaviorComparisonRollupV1[];
51
+ roleReports: EvalBehaviorComparisonRollupV1[];
52
+ affectedCorpusResults: Array<{ scenarioId: string; role: string; changedFields: string[] }>;
53
+ }
54
+
55
+ export interface EvalBehaviorComparisonRollupV1 {
56
+ id: string;
57
+ metrics: EvalChangeCountsV1;
58
+ variance: EvalChangeCountsV1;
59
+ }
60
+
61
+ export interface EvalChangeCountsV1 {
62
+ improved: number;
63
+ regressed: number;
64
+ unchanged: number;
65
+ incomparable: number;
66
+ }
67
+
68
+ export class EvalServingConfigurationDriftError extends Error {
69
+ readonly baseline: EvalServingConfigurationV1;
70
+ readonly candidate: EvalServingConfigurationV1;
71
+
72
+ constructor(baseline: EvalServingConfigurationV1, candidate: EvalServingConfigurationV1) {
73
+ super(
74
+ [
75
+ "serving configuration drift; pass --allow-config-drift to compare these runs",
76
+ `baseline serving: ${renderEvalServingConfiguration(baseline)}`,
77
+ `candidate serving: ${renderEvalServingConfiguration(candidate)}`,
78
+ ].join("\n"),
79
+ );
80
+ this.name = "EvalServingConfigurationDriftError";
81
+ this.baseline = baseline;
82
+ this.candidate = candidate;
83
+ }
10
84
  }
11
85
 
12
- export function compareEvalArtifactsV4(baseline: EvalArtifactV4, candidate: EvalArtifactV4): EvalCompareV4Summary {
86
+ export function compareEvalArtifactsV4(
87
+ baseline: EvalArtifactV4,
88
+ candidate: EvalArtifactV4,
89
+ options: EvalCompareV4Options = {},
90
+ ): EvalCompareV4Summary {
13
91
  const baselineTokens = baseline.summary.tokens;
14
92
  const candidateTokens = candidate.summary.tokens;
93
+ const baselineServing = servingConfigurationOf(baseline);
94
+ const candidateServing = servingConfigurationOf(candidate);
95
+ const configDrift = !sameEvalServingConfiguration(baselineServing, candidateServing);
96
+ if (configDrift && options.allowConfigDrift !== true) {
97
+ throw new EvalServingConfigurationDriftError(baselineServing, candidateServing);
98
+ }
99
+ const behavioral = compareEvalBehaviorMetricsV1(baseline, candidate);
100
+ const trackedMetrics = compareTrackedMetrics(baseline, candidate, options.metric);
101
+ const normalizedFilter = normalizeMetricFilter(options.metric);
102
+ const behavioralMetrics =
103
+ normalizedFilter === undefined
104
+ ? behavioral.comparisons
105
+ : behavioral.comparisons.filter((row) => row.metric === normalizedFilter || row.family === normalizedFilter);
106
+ if (options.metric !== undefined && trackedMetrics.length === 0 && behavioralMetrics.length === 0) {
107
+ throw new Error(`eval metric not found: ${options.metric}`);
108
+ }
15
109
  return {
16
110
  baselineEvalId: baseline.evalId,
17
111
  candidateEvalId: candidate.evalId,
112
+ baselineServingConfiguration: baselineServing,
113
+ candidateServingConfiguration: candidateServing,
114
+ configDrift,
18
115
  passRateDelta: candidate.summary.passRate - baseline.summary.passRate,
19
116
  tokenDelta: baselineTokens.measured && candidateTokens.measured ? candidateTokens.total - baselineTokens.total : null,
20
117
  wallTimeDelta: candidate.summary.wallTimeMs - baseline.summary.wallTimeMs,
118
+ trackedMetrics,
119
+ behavioralMetrics,
120
+ hardGate: behavioral.hardGate,
121
+ envelopeMismatches: behavioral.envelopeMismatches,
122
+ scenarioReports: behaviorRollups(behavioralMetrics, (row) => row.scenarioId),
123
+ roleReports: behaviorRollups(behavioralMetrics, (row) => row.role),
124
+ affectedCorpusResults: behavioral.envelopeMismatches.flatMap((mismatch) => {
125
+ const changedFields = mismatch.fields.filter((field) => field === "prompt" || field === "recipe");
126
+ return changedFields.length === 0 ? [] : [{ scenarioId: mismatch.scenarioId, role: mismatch.role, changedFields }];
127
+ }),
21
128
  };
22
129
  }
23
130
 
24
131
  export function renderEvalComparisonV4(summary: EvalCompareV4Summary): string {
132
+ const envelopeFailures = summary.envelopeMismatches.map(
133
+ (mismatch) =>
134
+ ` incomparable envelope: ${mismatch.scenarioId} ${mismatch.role} ${mismatch.target.id}/${mismatch.target.model ?? "none"} fields=${mismatch.fields.join(",")}`,
135
+ );
136
+ const affected = summary.affectedCorpusResults.map(
137
+ (result) =>
138
+ ` affected corpus result: ${result.scenarioId} role=${result.role} changed=${result.changedFields.join(",")}`,
139
+ );
140
+ const scenarioReports = renderRollups("per-scenario baseline/candidate report", summary.scenarioReports);
141
+ const roleReports = renderRollups("per-role baseline/candidate report", summary.roleReports);
142
+ const hardFailures = summary.hardGate.failures.map(
143
+ (failure) =>
144
+ ` hard failure: ${failure.scenarioId} ${failure.role} ${failure.target.id}/${failure.target.model ?? "none"} ${failure.metric} ${failure.change}`,
145
+ );
146
+ const tracked = summary.trackedMetrics.flatMap((row, index) => [
147
+ ...(index === 0
148
+ ? [
149
+ "tracked metrics:",
150
+ "scenario metric baseline_mean baseline_p90 baseline_variance candidate_mean candidate_p90 candidate_variance mean_delta p90_delta variance_delta change variance_change sources",
151
+ ]
152
+ : []),
153
+ [
154
+ row.scenarioId,
155
+ row.metric,
156
+ formatMetric(row.baseline.mean),
157
+ formatMetric(row.baseline.p90),
158
+ formatMetric(row.baseline.variance ?? null),
159
+ formatMetric(row.candidate.mean),
160
+ formatMetric(row.candidate.p90),
161
+ formatMetric(row.candidate.variance ?? null),
162
+ formatSignedMetric(row.meanDelta),
163
+ formatSignedMetric(row.p90Delta),
164
+ formatSignedMetric(row.varianceDelta),
165
+ row.change,
166
+ row.varianceChange,
167
+ `${row.baseline.sources.join("+") || "none"}->${row.candidate.sources.join("+") || "none"}`,
168
+ ].join(" "),
169
+ ]);
170
+ const behavioral = summary.behavioralMetrics.flatMap((row, index) => [
171
+ ...(index === 0
172
+ ? [
173
+ "behavioral metrics:",
174
+ "scenario role target model family metric baseline_mean baseline_variance baseline_coverage candidate_mean candidate_variance candidate_coverage mean_delta variance_delta change variance_change comparability gate source",
175
+ ]
176
+ : []),
177
+ [
178
+ row.scenarioId,
179
+ row.role,
180
+ row.target.id,
181
+ row.target.model ?? "none",
182
+ row.family,
183
+ row.metric,
184
+ formatMetric(row.baseline.mean),
185
+ formatMetric(row.baseline.variance),
186
+ `${row.baseline.measured}/${row.baseline.observations}`,
187
+ formatMetric(row.candidate.mean),
188
+ formatMetric(row.candidate.variance),
189
+ `${row.candidate.measured}/${row.candidate.observations}`,
190
+ formatSignedMetric(row.meanDelta),
191
+ formatSignedMetric(row.varianceDelta),
192
+ row.change,
193
+ row.varianceChange,
194
+ row.comparability.comparable ? "comparable" : `incomparable:${row.comparability.mismatchedFields.join(",")}`,
195
+ row.hardGate ? "hard" : "informational",
196
+ row.baseline.source,
197
+ ].join(" "),
198
+ ]);
25
199
  return [
26
200
  `baseline eval: ${summary.baselineEvalId}`,
27
201
  `candidate eval: ${summary.candidateEvalId}`,
202
+ `baseline serving: ${renderEvalServingConfiguration(summary.baselineServingConfiguration)}`,
203
+ `candidate serving: ${renderEvalServingConfiguration(summary.candidateServingConfiguration)}`,
204
+ `config drift: ${summary.configDrift ? "allowed" : "none"}`,
28
205
  `pass-rate delta: ${(summary.passRateDelta * 100).toFixed(2)}%`,
29
206
  `token delta: ${summary.tokenDelta === null ? "unmeasured" : summary.tokenDelta}`,
30
207
  `wall-time delta ms: ${summary.wallTimeDelta}`,
208
+ `behavioral hard gate: ${summary.hardGate.pass ? "pass" : `fail (${summary.hardGate.failures.length + summary.hardGate.envelopeFailures.length})`}`,
209
+ ...hardFailures,
210
+ ...envelopeFailures,
211
+ ...affected,
212
+ ...scenarioReports,
213
+ ...roleReports,
214
+ ...tracked,
215
+ ...behavioral,
31
216
  "",
32
217
  ].join("\n");
33
218
  }
219
+
220
+ function behaviorRollups(
221
+ rows: ReadonlyArray<EvalBehaviorMetricComparisonV1>,
222
+ keyOf: (row: EvalBehaviorMetricComparisonV1) => string,
223
+ ): EvalBehaviorComparisonRollupV1[] {
224
+ const groups = new Map<string, EvalBehaviorMetricComparisonV1[]>();
225
+ for (const row of rows) groups.set(keyOf(row), [...(groups.get(keyOf(row)) ?? []), row]);
226
+ return [...groups.entries()]
227
+ .sort(([left], [right]) => left.localeCompare(right))
228
+ .map(([id, grouped]) => ({
229
+ id,
230
+ metrics: changeCounts(grouped.map((row) => row.change)),
231
+ variance: changeCounts(grouped.map((row) => row.varianceChange)),
232
+ }));
233
+ }
234
+
235
+ function changeCounts(changes: ReadonlyArray<EvalMetricChangeV1>): EvalChangeCountsV1 {
236
+ return {
237
+ improved: changes.filter((change) => change === "improved").length,
238
+ regressed: changes.filter((change) => change === "regressed").length,
239
+ unchanged: changes.filter((change) => change === "unchanged").length,
240
+ incomparable: changes.filter((change) => change === "incomparable").length,
241
+ };
242
+ }
243
+
244
+ function renderRollups(title: string, reports: ReadonlyArray<EvalBehaviorComparisonRollupV1>): string[] {
245
+ if (reports.length === 0) return [];
246
+ return [
247
+ `${title}:`,
248
+ ...reports.map(
249
+ (report) =>
250
+ ` ${report.id}: metrics ${renderChangeCounts(report.metrics)}; variance ${renderChangeCounts(report.variance)}`,
251
+ ),
252
+ ];
253
+ }
254
+
255
+ function renderChangeCounts(counts: EvalChangeCountsV1): string {
256
+ return `improved=${counts.improved} regressed=${counts.regressed} unchanged=${counts.unchanged} incomparable=${counts.incomparable}`;
257
+ }
258
+
259
+ function compareTrackedMetrics(
260
+ baseline: EvalArtifactV4,
261
+ candidate: EvalArtifactV4,
262
+ metricFilter?: string,
263
+ ): EvalTrackedMetricComparisonV1[] {
264
+ const baselineAggregates =
265
+ baseline.aggregates ??
266
+ aggregateEvalVerdicts(baseline.results.flatMap((result) => (result.verdict === undefined ? [] : [result.verdict])));
267
+ const candidateAggregates =
268
+ candidate.aggregates ??
269
+ aggregateEvalVerdicts(candidate.results.flatMap((result) => (result.verdict === undefined ? [] : [result.verdict])));
270
+ const baselineByScenario = new Map(baselineAggregates.map((entry) => [entry.scenarioId, entry]));
271
+ const candidateByScenario = new Map(candidateAggregates.map((entry) => [entry.scenarioId, entry]));
272
+ const scenarioIds = [...baselineByScenario.keys()]
273
+ .filter((scenarioId) => candidateByScenario.has(scenarioId))
274
+ .sort((left, right) => left.localeCompare(right));
275
+ const filter = normalizeMetricFilter(metricFilter);
276
+ const rows: EvalTrackedMetricComparisonV1[] = [];
277
+ for (const scenarioId of scenarioIds) {
278
+ const baselineAggregate = baselineByScenario.get(scenarioId);
279
+ const candidateAggregate = candidateByScenario.get(scenarioId);
280
+ if (baselineAggregate === undefined || candidateAggregate === undefined) continue;
281
+ for (const metric of EVAL_TRACKED_METRIC_NAMES) {
282
+ if (filter !== undefined && filter !== metric) continue;
283
+ rows.push(
284
+ metricComparison(
285
+ scenarioId,
286
+ metric,
287
+ baselineAggregate.trackedMetrics[metric],
288
+ candidateAggregate.trackedMetrics[metric],
289
+ ),
290
+ );
291
+ }
292
+ const reasons = new Set([
293
+ ...Object.keys(baselineAggregate.trackedMetrics.expectedColdReasons),
294
+ ...Object.keys(candidateAggregate.trackedMetrics.expectedColdReasons),
295
+ ]);
296
+ for (const reason of [...reasons].sort((left, right) => left.localeCompare(right))) {
297
+ const metric = `expectedColdReasons.${reason}`;
298
+ if (filter !== undefined && filter !== metric && filter !== "expectedColdReasons") continue;
299
+ rows.push(
300
+ metricComparison(
301
+ scenarioId,
302
+ metric,
303
+ baselineAggregate.trackedMetrics.expectedColdReasons[reason] ?? zeroDistribution(baselineAggregate.k),
304
+ candidateAggregate.trackedMetrics.expectedColdReasons[reason] ?? zeroDistribution(candidateAggregate.k),
305
+ ),
306
+ );
307
+ }
308
+ }
309
+ return rows;
310
+ }
311
+
312
+ function metricComparison(
313
+ scenarioId: string,
314
+ metric: string,
315
+ baseline: EvalMetricDistributionV1,
316
+ candidate: EvalMetricDistributionV1,
317
+ ): EvalTrackedMetricComparisonV1 {
318
+ assertComparableTrackedMetricSources(`${scenarioId}.${metric}`, baseline.sources, candidate.sources);
319
+ const direction = trackedMetricDirection(metric);
320
+ return {
321
+ scenarioId,
322
+ metric,
323
+ baseline,
324
+ candidate,
325
+ meanDelta: subtractNullable(candidate.mean, baseline.mean),
326
+ p90Delta: subtractNullable(candidate.p90, baseline.p90),
327
+ varianceDelta: subtractNullable(candidate.variance ?? null, baseline.variance ?? null),
328
+ change: classifyChange(baseline.mean, candidate.mean, direction),
329
+ varianceChange: classifyChange(baseline.variance ?? null, candidate.variance ?? null, "lower"),
330
+ };
331
+ }
332
+
333
+ function servingConfigurationOf(artifact: EvalArtifactV4): EvalServingConfigurationV1 {
334
+ return (
335
+ artifact.servingConfiguration ?? {
336
+ targetId: artifact.matrix.target,
337
+ runtimeId: null,
338
+ modelId: artifact.matrix.model,
339
+ serverBuild: null,
340
+ total_slots: null,
341
+ thinkingLevel: artifact.matrix.thinking,
342
+ compiledPromptHash: null,
343
+ }
344
+ );
345
+ }
346
+
347
+ function normalizeMetricFilter(metric: string | undefined): string | undefined {
348
+ if (metric === undefined) return undefined;
349
+ const trimmed = metric.trim();
350
+ if (trimmed.startsWith("trackedMetrics.")) return trimmed.slice("trackedMetrics.".length);
351
+ if (trimmed.startsWith("behavioralMetrics.")) return trimmed.slice("behavioralMetrics.".length);
352
+ return trimmed;
353
+ }
354
+
355
+ function trackedMetricDirection(metric: string): "higher" | "lower" {
356
+ return metric === "cacheReadTokens" ? "higher" : "lower";
357
+ }
358
+
359
+ function zeroDistribution(observations: number): EvalMetricDistributionV1 {
360
+ return {
361
+ observations,
362
+ measured: observations,
363
+ unmeasured: 0,
364
+ mean: 0,
365
+ min: 0,
366
+ max: 0,
367
+ p90: 0,
368
+ variance: 0,
369
+ standardDeviation: 0,
370
+ sources: ["ledger"],
371
+ };
372
+ }
373
+
374
+ function subtractNullable(left: number | null, right: number | null): number | null {
375
+ return left === null || right === null ? null : left - right;
376
+ }
377
+
378
+ function formatMetric(value: number | null): string {
379
+ return value === null ? "null" : Number.isInteger(value) ? String(value) : value.toFixed(2);
380
+ }
381
+
382
+ function formatSignedMetric(value: number | null): string {
383
+ if (value === null) return "null";
384
+ const formatted = formatMetric(value);
385
+ return value > 0 ? `+${formatted}` : formatted;
386
+ }