@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,2888 @@
1
+ import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
+ import {
3
+ ROUTE_POLICY_VERSION,
4
+ isRouteDecisionAgentSelection,
5
+ isRoutingIntent
6
+ } from "./chunk-VPTUJU4P.js";
7
+ import {
8
+ isExecutionRole
9
+ } from "./chunk-H7IXIC72.js";
10
+ import {
11
+ readSettings
12
+ } from "./chunk-PNY46YEY.js";
13
+ import {
14
+ assertSafeId
15
+ } from "./chunk-KV2AOLDF.js";
16
+ import {
17
+ readClioVersion,
18
+ resolvePackageRoot
19
+ } from "./chunk-IWHMRKLL.js";
20
+ import {
21
+ require_dist
22
+ } from "./chunk-APJ265NV.js";
23
+ import {
24
+ safeResourceWrite
25
+ } from "./chunk-WEPFGWHJ.js";
26
+ import {
27
+ __toESM,
28
+ init_esm_shims
29
+ } from "./chunk-3R73A4XB.js";
30
+
31
+ // src/domains/dispatch/receipt-integrity.ts
32
+ init_esm_shims();
33
+ import { createHash } from "node:crypto";
34
+ var RUN_RECEIPT_INTEGRITY_VERSION = 20;
35
+ var RUN_RECEIPT_INTEGRITY_ALGORITHM = "sha256";
36
+ function sha256(input) {
37
+ return createHash("sha256").update(input, "utf8").digest("hex");
38
+ }
39
+ function canonicalJson(value) {
40
+ return serializeCanonical(value);
41
+ }
42
+ function serializeCanonical(value) {
43
+ if (value === null) return "null";
44
+ if (typeof value === "number") {
45
+ if (!Number.isFinite(value)) {
46
+ throw new Error(`receipt integrity: non-finite number ${String(value)} is not representable`);
47
+ }
48
+ return JSON.stringify(value);
49
+ }
50
+ if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
51
+ if (typeof value === "bigint") throw new Error("receipt integrity: bigint is not representable");
52
+ if (typeof value === "symbol" || typeof value === "function") {
53
+ throw new Error(`receipt integrity: ${typeof value} is not representable`);
54
+ }
55
+ if (value === void 0) throw new Error("receipt integrity: undefined is not representable at root");
56
+ if (Array.isArray(value)) {
57
+ const parts = [];
58
+ for (let i = 0; i < value.length; i++) {
59
+ if (!(i in value) || value[i] === void 0) {
60
+ parts.push("null");
61
+ continue;
62
+ }
63
+ parts.push(serializeCanonical(value[i]));
64
+ }
65
+ return `[${parts.join(",")}]`;
66
+ }
67
+ if (typeof value === "object") {
68
+ const obj = value;
69
+ const keys = Object.keys(obj).sort();
70
+ const parts = [];
71
+ for (const key of keys) {
72
+ const child = obj[key];
73
+ if (child === void 0) continue;
74
+ parts.push(`${JSON.stringify(key)}:${serializeCanonical(child)}`);
75
+ }
76
+ return `{${parts.join(",")}}`;
77
+ }
78
+ throw new Error(`receipt integrity: unsupported value of type ${typeof value}`);
79
+ }
80
+ var RECEIPT_INTEGRITY_FIELD_COVERAGE = {
81
+ runId: true,
82
+ agentId: true,
83
+ executionRole: true,
84
+ agentAudience: true,
85
+ requestOrigin: true,
86
+ task: true,
87
+ intent: true,
88
+ pathScope: true,
89
+ // Historical receipts omit this field, so their receipt and ledger payloads remain unchanged.
90
+ budget: true,
91
+ targetId: true,
92
+ wireModelId: true,
93
+ runtimeId: true,
94
+ runtimeKind: true,
95
+ startedAt: true,
96
+ endedAt: true,
97
+ outcome: true,
98
+ outcomeDetail: true,
99
+ lineage: true,
100
+ identity: true,
101
+ node: true,
102
+ attestation: true,
103
+ reroutes: true,
104
+ pipeline: true,
105
+ gate: true,
106
+ council: true,
107
+ plan: true,
108
+ fleetGate: true,
109
+ personaOverride: true,
110
+ projectContext: true,
111
+ // Always set on receipts written after #104 landed; absent only on older
112
+ // receipts, which omit these fields from canonical serialization.
113
+ rulesApplied: true,
114
+ operatorProfileApplied: true,
115
+ exitCode: true,
116
+ failureMessage: true,
117
+ tokenCount: true,
118
+ inputTokenCount: true,
119
+ outputTokenCount: true,
120
+ cacheReadTokenCount: true,
121
+ cacheWriteTokenCount: true,
122
+ reasoningTokenCount: true,
123
+ upstreamResponses: true,
124
+ output: true,
125
+ costUsd: true,
126
+ costProvenance: true,
127
+ compiledPromptHash: true,
128
+ staticCompositionHash: true,
129
+ staticShellHash: true,
130
+ sessionShellHash: true,
131
+ dynamicHash: true,
132
+ promptSignature: true,
133
+ toolSignature: true,
134
+ clioVersion: true,
135
+ piMonoVersion: true,
136
+ platform: true,
137
+ nodeVersion: true,
138
+ toolCalls: true,
139
+ toolStats: true,
140
+ toolActivity: true,
141
+ verification: true,
142
+ hostVerification: true,
143
+ worktree: true,
144
+ routingIntent: true,
145
+ quality: true,
146
+ skillActivations: true,
147
+ autonomyEnforcement: true,
148
+ safety: true,
149
+ reproducibility: true,
150
+ runtimeResolution: true,
151
+ delegation: true,
152
+ findingsSummary: true,
153
+ // Both are optional and absent unless the run produced the condition they
154
+ // name, so a receipt that carries neither digests exactly as it did before
155
+ // they existed and the integrity version stays where it is.
156
+ validationGrounding: true,
157
+ capabilityMismatch: true,
158
+ // Same reasoning: absent unless the run had an agent ledger, so a receipt
159
+ // without one omits the field from canonical serialization.
160
+ ledgerContribution: true,
161
+ sessionId: true,
162
+ briefing: true,
163
+ outcomeCode: true,
164
+ steering: true,
165
+ routeDecision: true
166
+ };
167
+ var RECEIPT_FIELDS = Object.keys(RECEIPT_INTEGRITY_FIELD_COVERAGE);
168
+ function selectedReceiptFields(receipt, fields) {
169
+ const source = receipt;
170
+ const result = {};
171
+ for (const field of fields) {
172
+ const value = source[field];
173
+ if (value !== void 0) result[field] = value;
174
+ }
175
+ return result;
176
+ }
177
+ function receiptDigestFields(receipt) {
178
+ const result = selectedReceiptFields(receipt, RECEIPT_FIELDS);
179
+ result.briefing = receipt.briefing ?? null;
180
+ result.outcomeCode = receipt.outcomeCode ?? null;
181
+ result.steering = receipt.steering ?? null;
182
+ return result;
183
+ }
184
+ function ledgerDigestFields(envelope) {
185
+ return {
186
+ id: envelope.id,
187
+ agentId: envelope.agentId,
188
+ executionRole: envelope.executionRole,
189
+ task: envelope.task,
190
+ ...envelope.budget !== void 0 ? { budget: envelope.budget } : {},
191
+ targetId: envelope.targetId,
192
+ wireModelId: envelope.wireModelId,
193
+ runtimeId: envelope.runtimeId,
194
+ runtimeKind: envelope.runtimeKind,
195
+ startedAt: envelope.startedAt,
196
+ endedAt: envelope.endedAt,
197
+ status: envelope.status,
198
+ exitCode: envelope.exitCode,
199
+ sessionId: envelope.sessionId,
200
+ cwd: envelope.cwd,
201
+ tokenCount: envelope.tokenCount,
202
+ cacheReadTokenCount: envelope.cacheReadTokenCount,
203
+ cacheWriteTokenCount: envelope.cacheWriteTokenCount,
204
+ reasoningTokenCount: envelope.reasoningTokenCount,
205
+ staticShellHash: envelope.staticShellHash,
206
+ sessionShellHash: envelope.sessionShellHash,
207
+ dynamicHash: envelope.dynamicHash,
208
+ costUsd: envelope.costUsd,
209
+ agentAudience: envelope.agentAudience ?? null,
210
+ requestOrigin: envelope.requestOrigin ?? null,
211
+ outcome: envelope.outcome ?? null,
212
+ outcomeDetail: envelope.outcomeDetail ?? null,
213
+ lineage: envelope.lineage ?? null,
214
+ identity: envelope.identity ?? null,
215
+ node: envelope.node ?? null,
216
+ reroutes: envelope.reroutes ?? null,
217
+ pipeline: envelope.pipeline ?? null,
218
+ gate: envelope.gate ?? null,
219
+ plan: envelope.plan ?? null,
220
+ personaOverride: envelope.personaOverride ?? null,
221
+ inputTokenCount: envelope.inputTokenCount ?? 0,
222
+ outputTokenCount: envelope.outputTokenCount ?? 0,
223
+ promptSignature: envelope.promptSignature ?? null,
224
+ toolSignature: envelope.toolSignature ?? null,
225
+ briefing: envelope.briefing ?? null,
226
+ outcomeCode: envelope.outcomeCode ?? null,
227
+ steering: envelope.steering ?? null
228
+ };
229
+ }
230
+ function integrityPayload(receipt, envelope) {
231
+ return {
232
+ contract: "clio.runReceipt.integrity",
233
+ version: RUN_RECEIPT_INTEGRITY_VERSION,
234
+ sources: ["receipt", "run-ledger"],
235
+ receipt: receiptDigestFields(receipt),
236
+ ledger: ledgerDigestFields(envelope)
237
+ };
238
+ }
239
+ function computeReceiptIntegrity(receipt, envelope) {
240
+ return {
241
+ version: RUN_RECEIPT_INTEGRITY_VERSION,
242
+ algorithm: RUN_RECEIPT_INTEGRITY_ALGORITHM,
243
+ digest: sha256(canonicalJson(integrityPayload(receipt, envelope)))
244
+ };
245
+ }
246
+ function isReceiptQuality(value) {
247
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
248
+ const quality = value;
249
+ if (quality.version !== 1 || !Array.isArray(quality.typedValidations)) return false;
250
+ if (!quality.typedValidations.every(
251
+ (fact) => fact !== null && typeof fact === "object" && typeof fact.sourceId === "string" && typeof fact.validatorDigest === "string" && /^[0-9a-f]{64}$/.test(String(fact.validatorDigest)) && typeof fact.passed === "boolean"
252
+ ))
253
+ return false;
254
+ const schema = quality.responseSchema;
255
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) return false;
256
+ const responseSchema = schema;
257
+ const resultContract = quality.resultContract;
258
+ const validResultContract = resultContract === null || resultContract !== void 0 && typeof resultContract === "object" && !Array.isArray(resultContract) && typeof resultContract.sourceId === "string" && typeof resultContract.validatorDigest === "string" && /^[0-9a-f]{64}$/.test(String(resultContract.validatorDigest)) && (resultContract.conformance === "pass" || resultContract.conformance === "fail" || resultContract.conformance === "not-reached") && (resultContract.quality === "pass" || resultContract.quality === "fail" || resultContract.quality === "unmeasured");
259
+ return (responseSchema.sourceId === null || typeof responseSchema.sourceId === "string") && (responseSchema.schemaDigest === null || typeof responseSchema.schemaDigest === "string" && /^[0-9a-f]{64}$/.test(responseSchema.schemaDigest)) && typeof responseSchema.runtimeEnforceable === "boolean" && (responseSchema.enforcementPassed === null || typeof responseSchema.enforcementPassed === "boolean") && validResultContract;
260
+ }
261
+ function isCurrentRouteDecision(value) {
262
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
263
+ const decision = value;
264
+ return decision.policyVersion === ROUTE_POLICY_VERSION && (decision.mode === "fixed" || decision.mode === "shadow" || decision.mode === "active") && isRouteDecisionAgentSelection(decision.agentSelection) && typeof decision.decisionHash === "string" && /^[0-9a-f]{64}$/u.test(decision.decisionHash);
265
+ }
266
+ function withReceiptIntegrity(receipt, envelope) {
267
+ if (!isReceiptQuality(receipt.quality)) throw new Error("receipt integrity: required quality block invalid");
268
+ if (!isExecutionRole(receipt.executionRole)) throw new Error("receipt integrity: required execution role invalid");
269
+ if (!isRoutingIntent(receipt.routingIntent)) {
270
+ throw new Error("receipt integrity: required routing intent invalid");
271
+ }
272
+ if (receipt.routeDecision !== void 0 && !isCurrentRouteDecision(receipt.routeDecision)) {
273
+ throw new Error("receipt integrity: route decision is invalid or retired");
274
+ }
275
+ return {
276
+ ...receipt,
277
+ routingIntent: receipt.routingIntent,
278
+ integrity: computeReceiptIntegrity(receipt, envelope)
279
+ };
280
+ }
281
+ function isReceiptIntegrity(value) {
282
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
283
+ const candidate = value;
284
+ return candidate.version === RUN_RECEIPT_INTEGRITY_VERSION && candidate.algorithm === RUN_RECEIPT_INTEGRITY_ALGORITHM && typeof candidate.digest === "string" && /^[0-9a-f]{64}$/.test(candidate.digest);
285
+ }
286
+ function firstLedgerMismatch(receipt, envelope) {
287
+ const sharedFields = [
288
+ ["runId", receipt.runId, envelope.id],
289
+ ["agentId", receipt.agentId, envelope.agentId],
290
+ ["executionRole", receipt.executionRole, envelope.executionRole],
291
+ ["agentAudience", receipt.agentAudience, envelope.agentAudience],
292
+ ["requestOrigin", receipt.requestOrigin, envelope.requestOrigin],
293
+ ["task", receipt.task, envelope.task],
294
+ ["targetId", receipt.targetId, envelope.targetId],
295
+ ["wireModelId", receipt.wireModelId, envelope.wireModelId],
296
+ ["runtimeId", receipt.runtimeId, envelope.runtimeId],
297
+ ["runtimeKind", receipt.runtimeKind, envelope.runtimeKind],
298
+ ["startedAt", receipt.startedAt, envelope.startedAt],
299
+ ["endedAt", receipt.endedAt, envelope.endedAt],
300
+ ["exitCode", receipt.exitCode, envelope.exitCode],
301
+ ["tokenCount", receipt.tokenCount, envelope.tokenCount],
302
+ ["cacheReadTokenCount", receipt.cacheReadTokenCount ?? 0, envelope.cacheReadTokenCount ?? 0],
303
+ ["cacheWriteTokenCount", receipt.cacheWriteTokenCount ?? 0, envelope.cacheWriteTokenCount ?? 0],
304
+ ["reasoningTokenCount", receipt.reasoningTokenCount ?? 0, envelope.reasoningTokenCount ?? 0],
305
+ ["staticShellHash", receipt.staticShellHash ?? null, envelope.staticShellHash ?? null],
306
+ ["sessionShellHash", receipt.sessionShellHash ?? null, envelope.sessionShellHash ?? null],
307
+ ["dynamicHash", receipt.dynamicHash ?? null, envelope.dynamicHash ?? null],
308
+ ["costUsd", receipt.costUsd, envelope.costUsd],
309
+ ["sessionId", receipt.sessionId, envelope.sessionId],
310
+ ["outcome", receipt.outcome ?? null, envelope.outcome ?? null],
311
+ ["outcomeDetail", receipt.outcomeDetail ?? null, envelope.outcomeDetail ?? null],
312
+ ["nodeId", receipt.node?.id ?? null, envelope.node?.id ?? null],
313
+ ["outcomeCode", receipt.outcomeCode ?? null, envelope.outcomeCode ?? null]
314
+ ];
315
+ for (const [field, receiptValue, ledgerValue] of sharedFields) {
316
+ if (!Object.is(receiptValue, ledgerValue)) return field;
317
+ }
318
+ if (canonicalJson(receipt.briefing ?? null) !== canonicalJson(envelope.briefing ?? null)) return "briefing";
319
+ if (canonicalJson(receipt.budget ?? null) !== canonicalJson(envelope.budget ?? null)) return "budget";
320
+ if (canonicalJson(receipt.steering ?? null) !== canonicalJson(envelope.steering ?? null)) return "steering";
321
+ return null;
322
+ }
323
+ function verifyReceiptIntegrity(receipt, envelope) {
324
+ if (!isReceiptQuality(receipt.quality) || !isReceiptIntegrity(receipt.integrity)) {
325
+ return { ok: false, reason: "integrity invalid" };
326
+ }
327
+ if (!isExecutionRole(receipt.executionRole)) return { ok: false, reason: "execution role invalid" };
328
+ if (!isRoutingIntent(receipt.routingIntent)) {
329
+ return { ok: false, reason: "routing intent invalid" };
330
+ }
331
+ if (receipt.routeDecision !== void 0 && !isCurrentRouteDecision(receipt.routeDecision)) {
332
+ return { ok: false, reason: "route decision invalid" };
333
+ }
334
+ const mismatch = firstLedgerMismatch(receipt, envelope);
335
+ if (mismatch) {
336
+ return { ok: false, reason: `ledger mismatch: ${mismatch}` };
337
+ }
338
+ const expected = computeReceiptIntegrity(receipt, envelope);
339
+ if (expected.digest !== receipt.integrity.digest) {
340
+ return { ok: false, reason: "integrity mismatch" };
341
+ }
342
+ return { ok: true };
343
+ }
344
+
345
+ // src/domains/eval/harness-metrics.ts
346
+ init_esm_shims();
347
+ var ZERO_EVAL_HARNESS_METRICS = {
348
+ receiptCount: 0,
349
+ toolCalls: 0,
350
+ retries: 0,
351
+ safetyBlocks: 0,
352
+ correctionLatencyMs: 0,
353
+ validationEvidence: 0
354
+ };
355
+ function evalHarnessMetricsFromCommands(commands) {
356
+ return {
357
+ ...ZERO_EVAL_HARNESS_METRICS,
358
+ validationEvidence: commands.filter(
359
+ (command) => command.phase === "verifier" && command.exitCode === 0 && !command.timedOut
360
+ ).length
361
+ };
362
+ }
363
+ function evalHarnessMetricsFromReceipt(receipt, extras = {}) {
364
+ return {
365
+ receiptCount: 1,
366
+ toolCalls: receipt.toolCalls,
367
+ retries: extras.retries ?? 0,
368
+ safetyBlocks: receipt.safety?.decisions.blocked ?? 0,
369
+ correctionLatencyMs: extras.correctionLatencyMs ?? 0,
370
+ validationEvidence: extras.validationEvidence ?? 0
371
+ };
372
+ }
373
+ function sumEvalHarnessMetrics(records) {
374
+ return records.reduce((total, record) => addEvalHarnessMetrics(total, record.harness), {
375
+ ...ZERO_EVAL_HARNESS_METRICS
376
+ });
377
+ }
378
+ function addEvalHarnessMetrics(left, right) {
379
+ return {
380
+ receiptCount: left.receiptCount + right.receiptCount,
381
+ toolCalls: left.toolCalls + right.toolCalls,
382
+ retries: left.retries + right.retries,
383
+ safetyBlocks: left.safetyBlocks + right.safetyBlocks,
384
+ correctionLatencyMs: left.correctionLatencyMs + right.correctionLatencyMs,
385
+ validationEvidence: left.validationEvidence + right.validationEvidence
386
+ };
387
+ }
388
+
389
+ // src/domains/eval/store.ts
390
+ init_esm_shims();
391
+ import { createHash as createHash2, randomBytes } from "node:crypto";
392
+ import { readFile } from "node:fs/promises";
393
+ import { join } from "node:path";
394
+
395
+ // src/domains/eval/artifacts/redact.ts
396
+ init_esm_shims();
397
+ var SENSITIVE_KEY = /(?:^|[_-])(api[_-]?key|authorization|cookie|password|secret|token)(?:$|[_-])/i;
398
+ var CREDENTIAL_PATTERNS = [
399
+ [/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]+/gi, "$1[redacted]"],
400
+ [/\b(bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi, "$1[redacted]"],
401
+ [/\b(sk-[A-Za-z0-9_-]{16,})\b/g, "[redacted]"],
402
+ [/\b(gh[pousr]_[A-Za-z0-9_]{16,})\b/g, "[redacted]"],
403
+ [/\b(AKIA[0-9A-Z]{16})\b/g, "[redacted]"],
404
+ [/\b((?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\s*[:=]\s*)[^\s"',}]+/gi, "$1[redacted]"]
405
+ ];
406
+ function redactArtifactForStorage(value, env = process.env) {
407
+ return redactValue(value, env);
408
+ }
409
+ function redactValue(value, env) {
410
+ if (typeof value === "string") return redactString(value, env);
411
+ if (Array.isArray(value)) return value.map((entry) => redactValue(entry, env));
412
+ if (value !== null && typeof value === "object") {
413
+ const out = {};
414
+ for (const [key, entry] of Object.entries(value)) {
415
+ out[key] = SENSITIVE_KEY.test(key) ? "[redacted]" : redactValue(entry, env);
416
+ }
417
+ return out;
418
+ }
419
+ return value;
420
+ }
421
+ function redactString(value, env) {
422
+ let out = stripHomePrefix(value, env.HOME);
423
+ for (const [pattern, replacement] of CREDENTIAL_PATTERNS) {
424
+ out = out.replace(pattern, replacement);
425
+ }
426
+ return out;
427
+ }
428
+ function stripHomePrefix(value, home) {
429
+ if (home === void 0 || home.length === 0) return value;
430
+ const normalized = home.replace(/\/+$/g, "");
431
+ if (normalized.length === 0) return value;
432
+ return value.split(normalized).join("$HOME");
433
+ }
434
+
435
+ // src/domains/eval/store.ts
436
+ var NODE_SIGNALS = /* @__PURE__ */ new Set([
437
+ "SIGHUP",
438
+ "SIGINT",
439
+ "SIGQUIT",
440
+ "SIGILL",
441
+ "SIGTRAP",
442
+ "SIGABRT",
443
+ "SIGIOT",
444
+ "SIGBUS",
445
+ "SIGFPE",
446
+ "SIGKILL",
447
+ "SIGUSR1",
448
+ "SIGSEGV",
449
+ "SIGUSR2",
450
+ "SIGPIPE",
451
+ "SIGALRM",
452
+ "SIGTERM",
453
+ "SIGCHLD",
454
+ "SIGSTKFLT",
455
+ "SIGCONT",
456
+ "SIGSTOP",
457
+ "SIGTSTP",
458
+ "SIGTTIN",
459
+ "SIGTTOU",
460
+ "SIGURG",
461
+ "SIGXCPU",
462
+ "SIGXFSZ",
463
+ "SIGVTALRM",
464
+ "SIGPROF",
465
+ "SIGWINCH",
466
+ "SIGIO",
467
+ "SIGPOLL",
468
+ "SIGPWR",
469
+ "SIGSYS",
470
+ "SIGUNUSED"
471
+ ]);
472
+ function evalRoot(dataDir) {
473
+ return join(dataDir, "evals");
474
+ }
475
+ function evalArtifactPath(dataDir, evalId) {
476
+ assertSafeId(evalId, "eval");
477
+ return join(evalRoot(dataDir), `${evalId}.json`);
478
+ }
479
+ function createEvalId(startedAt, taskFileHash) {
480
+ const stamp = startedAt.toISOString().replace(/[-:.]/g, "");
481
+ return `eval-${stamp}-${taskFileHash.slice(0, 8)}-${randomBytes(6).toString("hex")}`;
482
+ }
483
+ async function writeEvalArtifact(dataDir, artifact) {
484
+ const path = evalArtifactPath(dataDir, artifact.evalId);
485
+ const redacted = redactArtifactForStorage({
486
+ ...artifact,
487
+ paths: { ...artifact.paths, artifact: path }
488
+ });
489
+ safeResourceWrite(path, `${JSON.stringify(redacted, null, 2)}
490
+ `, { encoding: "utf8" });
491
+ return path;
492
+ }
493
+ async function loadEvalArtifact(dataDir, evalId) {
494
+ let raw;
495
+ try {
496
+ raw = await readFile(evalArtifactPath(dataDir, evalId), "utf8");
497
+ } catch (error) {
498
+ if (isErrorWithCode(error) && error.code === "ENOENT") throw new Error(`eval artifact not found: ${evalId}`);
499
+ throw error;
500
+ }
501
+ const source = evalArtifactPath(dataDir, evalId);
502
+ const parsed = parseJson(raw, source);
503
+ return parseArtifact(parsed, source);
504
+ }
505
+ function parseArtifact(value, source) {
506
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
507
+ if (value.version !== 1) throw new Error(`${source}.version: expected 1`);
508
+ const results = readArray(value, source, "results").map(
509
+ (entry, index) => parseRecord(entry, `${source}.results[${index}]`)
510
+ );
511
+ return {
512
+ version: 1,
513
+ evalId: readString(value, source, "evalId"),
514
+ taskFile: readString(value, source, "taskFile"),
515
+ taskFileHash: readString(value, source, "taskFileHash"),
516
+ clio: parseClioProvenance(readRequiredArtifactField(value, source, "clio"), `${source}.clio`),
517
+ environment: parseEnvironmentProvenance(
518
+ readRequiredArtifactField(value, source, "environment"),
519
+ `${source}.environment`
520
+ ),
521
+ target: readOptionalNullableString(value, source, "target"),
522
+ model: readOptionalNullableString(value, source, "model"),
523
+ thinking: readOptionalNullableString(value, source, "thinking"),
524
+ paths: parseArtifactPaths(readRequiredArtifactField(value, source, "paths"), `${source}.paths`),
525
+ repeat: readNumber(value, source, "repeat"),
526
+ startedAt: readString(value, source, "startedAt"),
527
+ endedAt: readString(value, source, "endedAt"),
528
+ summary: parseSummary(value.summary, `${source}.summary`),
529
+ results
530
+ };
531
+ }
532
+ function parseSummary(value, source) {
533
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
534
+ return {
535
+ runs: readNumber(value, source, "runs"),
536
+ passed: readNumber(value, source, "passed"),
537
+ failed: readNumber(value, source, "failed"),
538
+ passRate: readNumber(value, source, "passRate"),
539
+ tokens: readNumber(value, source, "tokens"),
540
+ costUsd: readNumber(value, source, "costUsd"),
541
+ wallTimeMs: readNumber(value, source, "wallTimeMs"),
542
+ harness: value.harness === void 0 ? { ...ZERO_EVAL_HARNESS_METRICS } : parseHarnessMetrics(value.harness, `${source}.harness`),
543
+ failureClasses: readArray(value, source, "failureClasses").map(
544
+ (entry, index) => parseFailureClassCount(entry, `${source}.failureClasses[${index}]`)
545
+ )
546
+ };
547
+ }
548
+ function parseRecord(value, source) {
549
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
550
+ const failureClass = readOptionalFailureClass(value, source, "failureClass");
551
+ const commands = readArray(value, source, "commands").map(
552
+ (entry, index) => parseCommand(entry, `${source}.commands[${index}]`)
553
+ );
554
+ const record = {
555
+ taskId: readString(value, source, "taskId"),
556
+ runId: readString(value, source, "runId"),
557
+ repeatIndex: readNumber(value, source, "repeatIndex"),
558
+ cwd: readString(value, source, "cwd"),
559
+ prompt: readString(value, source, "prompt"),
560
+ tags: readStringArray(value, source, "tags"),
561
+ pass: readBoolean(value, source, "pass"),
562
+ exitCode: readNumber(value, source, "exitCode"),
563
+ tokens: readNumber(value, source, "tokens"),
564
+ costUsd: readNumber(value, source, "costUsd"),
565
+ wallTimeMs: readNumber(value, source, "wallTimeMs"),
566
+ harness: value.harness === void 0 ? evalHarnessMetricsFromCommands(commands) : parseHarnessMetrics(value.harness, `${source}.harness`),
567
+ commands
568
+ };
569
+ if (failureClass !== void 0) record.failureClass = failureClass;
570
+ const receiptPath = readOptionalString(value, source, "receiptPath");
571
+ if (receiptPath !== void 0) record.receiptPath = receiptPath;
572
+ const evidenceId = readOptionalString(value, source, "evidenceId");
573
+ if (evidenceId !== void 0) record.evidenceId = evidenceId;
574
+ const paths = value.paths === void 0 ? void 0 : parseRunPaths(value.paths, `${source}.paths`);
575
+ if (paths !== void 0) record.paths = paths;
576
+ return record;
577
+ }
578
+ function parseClioProvenance(value, source) {
579
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
580
+ return {
581
+ version: readString(value, source, "version"),
582
+ commit: readNullableString(value, source, "commit"),
583
+ entry: readString(value, source, "entry")
584
+ };
585
+ }
586
+ function parseEnvironmentProvenance(value, source) {
587
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
588
+ return {
589
+ platform: readString(value, source, "platform"),
590
+ node: readString(value, source, "node")
591
+ };
592
+ }
593
+ function parseArtifactPaths(value, source) {
594
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
595
+ const out = {
596
+ taskFile: readString(value, source, "taskFile"),
597
+ receipts: readStringArray(value, source, "receipts"),
598
+ sessionLedgers: readStringArray(value, source, "sessionLedgers")
599
+ };
600
+ const artifact = readOptionalString(value, source, "artifact");
601
+ if (artifact !== void 0) out.artifact = artifact;
602
+ const evidence = readOptionalString(value, source, "evidence");
603
+ if (evidence !== void 0) out.evidence = evidence;
604
+ return out;
605
+ }
606
+ function parseRunPaths(value, source) {
607
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
608
+ const out = {};
609
+ const receipt = readOptionalString(value, source, "receipt");
610
+ if (receipt !== void 0) out.receipt = receipt;
611
+ const sessionLedger = readOptionalString(value, source, "sessionLedger");
612
+ if (sessionLedger !== void 0) out.sessionLedger = sessionLedger;
613
+ const evidence = readOptionalString(value, source, "evidence");
614
+ if (evidence !== void 0) out.evidence = evidence;
615
+ return out;
616
+ }
617
+ function readRequiredArtifactField(record, source, field) {
618
+ const value = record[field];
619
+ if (value === void 0) {
620
+ throw new Error(
621
+ `eval artifact has an invalid schema: missing required field '${field}' in ${source}. Re-run the evaluation suite to generate a complete artifact.`
622
+ );
623
+ }
624
+ return value;
625
+ }
626
+ function parseHarnessMetrics(value, source) {
627
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
628
+ return {
629
+ receiptCount: readNumber(value, source, "receiptCount"),
630
+ toolCalls: readNumber(value, source, "toolCalls"),
631
+ retries: readNumber(value, source, "retries"),
632
+ safetyBlocks: readNumber(value, source, "safetyBlocks"),
633
+ correctionLatencyMs: readNumber(value, source, "correctionLatencyMs"),
634
+ validationEvidence: readNumber(value, source, "validationEvidence")
635
+ };
636
+ }
637
+ function parseCommand(value, source) {
638
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
639
+ const phase = readString(value, source, "phase");
640
+ if (phase !== "setup" && phase !== "verifier") throw new Error(`${source}.phase: expected setup or verifier`);
641
+ return {
642
+ phase,
643
+ index: readNumber(value, source, "index"),
644
+ command: readString(value, source, "command"),
645
+ exitCode: readNumber(value, source, "exitCode"),
646
+ signal: readSignal(value.signal, `${source}.signal`),
647
+ timedOut: readBoolean(value, source, "timedOut"),
648
+ wallTimeMs: readNumber(value, source, "wallTimeMs"),
649
+ stdout: readStringAllowEmpty(value, source, "stdout"),
650
+ stderr: readStringAllowEmpty(value, source, "stderr")
651
+ };
652
+ }
653
+ function readSignal(value, source) {
654
+ if (value === null) return null;
655
+ if (typeof value === "string" && NODE_SIGNALS.has(value)) return value;
656
+ throw new Error(`${source}: expected signal or null`);
657
+ }
658
+ function parseFailureClassCount(value, source) {
659
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
660
+ return {
661
+ failureClass: readFailureClass(value, source, "failureClass"),
662
+ count: readNumber(value, source, "count")
663
+ };
664
+ }
665
+ function readFailureClass(record, source, field) {
666
+ const value = record[field];
667
+ if (value === "setup_failed" || value === "verifier_failed" || value === "timeout" || value === "cwd_missing" || value === "command_error") {
668
+ return value;
669
+ }
670
+ throw new Error(`${source}.${field}: expected failure class`);
671
+ }
672
+ function readOptionalFailureClass(record, source, field) {
673
+ if (record[field] === void 0) return void 0;
674
+ return readFailureClass(record, source, field);
675
+ }
676
+ function readString(record, source, field) {
677
+ const value = record[field];
678
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string`);
679
+ return value;
680
+ }
681
+ function readStringAllowEmpty(record, source, field) {
682
+ const value = record[field];
683
+ if (typeof value !== "string") throw new Error(`${source}.${field}: expected string`);
684
+ return value;
685
+ }
686
+ function readOptionalString(record, source, field) {
687
+ const value = record[field];
688
+ if (value === void 0) return void 0;
689
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string`);
690
+ return value;
691
+ }
692
+ function readNullableString(record, source, field) {
693
+ const value = record[field];
694
+ if (value === null) return null;
695
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string or null`);
696
+ return value;
697
+ }
698
+ function readOptionalNullableString(record, source, field) {
699
+ const value = record[field];
700
+ if (value === void 0 || value === null) return null;
701
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string or null`);
702
+ return value;
703
+ }
704
+ function readStringArray(record, source, field) {
705
+ const value = readArray(record, source, field);
706
+ const out = [];
707
+ for (let index = 0; index < value.length; index += 1) {
708
+ const entry = value[index];
709
+ if (typeof entry !== "string") throw new Error(`${source}.${field}[${index}]: expected string`);
710
+ out.push(entry);
711
+ }
712
+ return out;
713
+ }
714
+ function readNumber(record, source, field) {
715
+ const value = record[field];
716
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${source}.${field}: expected number`);
717
+ return value;
718
+ }
719
+ function readBoolean(record, source, field) {
720
+ const value = record[field];
721
+ if (typeof value !== "boolean") throw new Error(`${source}.${field}: expected boolean`);
722
+ return value;
723
+ }
724
+ function readArray(record, source, field) {
725
+ const value = record[field];
726
+ if (!Array.isArray(value)) throw new Error(`${source}.${field}: expected array`);
727
+ return value;
728
+ }
729
+ function parseJson(raw, source) {
730
+ try {
731
+ return JSON.parse(raw);
732
+ } catch (error) {
733
+ const message = error instanceof Error ? error.message : String(error);
734
+ throw new Error(`${source}: invalid JSON: ${message}`);
735
+ }
736
+ }
737
+ function isRecord(value) {
738
+ return typeof value === "object" && value !== null && !Array.isArray(value);
739
+ }
740
+ function isErrorWithCode(error) {
741
+ return error instanceof Error && "code" in error && typeof error.code === "string";
742
+ }
743
+
744
+ // src/domains/eval/artifacts/store.ts
745
+ init_esm_shims();
746
+ import { readFile as readFile2 } from "node:fs/promises";
747
+ import { join as join2 } from "node:path";
748
+
749
+ // src/domains/eval/schema/behavioral.ts
750
+ init_esm_shims();
751
+ import { createHash as createHash3 } from "node:crypto";
752
+
753
+ // src/domains/eval/schema/verdict.ts
754
+ init_esm_shims();
755
+ var EVAL_VERDICT_SCHEMA_V1 = "clio.eval.verdict.v1";
756
+ var EVAL_TRACKED_METRIC_NAMES = [
757
+ "modelCalls",
758
+ "uncachedPrefillTokens",
759
+ "cacheReadTokens",
760
+ "generatedTokens",
761
+ "reasoningTokens",
762
+ "toolCalls",
763
+ "toolErrors",
764
+ "ttftMsFirstCall",
765
+ "wallClockMs",
766
+ "contextTokensAtEnd",
767
+ "compactions"
768
+ ];
769
+ function parseEvalVerdictEnvelopeV1(value, source = "verdict") {
770
+ const record = asRecord(value, source);
771
+ if (record.schema !== EVAL_VERDICT_SCHEMA_V1) {
772
+ throw new Error(`${source}.schema: expected ${EVAL_VERDICT_SCHEMA_V1}`);
773
+ }
774
+ const scenarioId = readNonEmptyString(record, source, "scenarioId");
775
+ const trialIndex = readNonNegativeInteger(record, source, "trialIndex");
776
+ const outcome = readOutcome(record.outcome, `${source}.outcome`);
777
+ const machinery = readMachinery(record.machinery, `${source}.machinery`);
778
+ if (machinery === "infrastructure_failure" && outcome === "pass") {
779
+ throw new Error(`${source}: infrastructure_failure cannot carry a pass outcome`);
780
+ }
781
+ if (record.behavioral !== null) throw new Error(`${source}.behavioral: expected null in verdict v1`);
782
+ const evidence = parseEvidence(record.evidence, `${source}.evidence`);
783
+ const reason = record.reason === void 0 ? legacyVerdictReason(outcome, machinery, evidence) : readNullableNonEmptyString(record, source, "reason");
784
+ if (outcome === "fail" && reason === null) throw new Error(`${source}.reason: failed outcome requires a reason`);
785
+ if (outcome !== "fail" && reason !== null) {
786
+ throw new Error(`${source}.reason: only a failed outcome can carry a reason`);
787
+ }
788
+ return {
789
+ schema: EVAL_VERDICT_SCHEMA_V1,
790
+ scenarioId,
791
+ trialIndex,
792
+ outcome,
793
+ machinery,
794
+ reason,
795
+ trackedMetrics: parseTrackedMetrics(record.trackedMetrics, `${source}.trackedMetrics`),
796
+ behavioral: null,
797
+ evidence
798
+ };
799
+ }
800
+ function parseTrackedMetrics(value, source) {
801
+ const record = asRecord(value, source);
802
+ const expectedColdReasons = asRecord(record.expectedColdReasons, `${source}.expectedColdReasons`);
803
+ return {
804
+ modelCalls: readSourcedNumber(record.modelCalls, `${source}.modelCalls`),
805
+ uncachedPrefillTokens: readSourcedNumber(record.uncachedPrefillTokens, `${source}.uncachedPrefillTokens`),
806
+ cacheReadTokens: readSourcedNumber(record.cacheReadTokens, `${source}.cacheReadTokens`),
807
+ generatedTokens: readSourcedNumber(record.generatedTokens, `${source}.generatedTokens`),
808
+ reasoningTokens: readSourcedNullableNumber(record.reasoningTokens, `${source}.reasoningTokens`),
809
+ toolCalls: readSourcedNumber(record.toolCalls, `${source}.toolCalls`),
810
+ toolErrors: readSourcedNumber(record.toolErrors, `${source}.toolErrors`),
811
+ ttftMsFirstCall: readSourcedNumber(record.ttftMsFirstCall, `${source}.ttftMsFirstCall`),
812
+ wallClockMs: readSourcedNumber(record.wallClockMs, `${source}.wallClockMs`),
813
+ contextTokensAtEnd: readSourcedNumber(record.contextTokensAtEnd, `${source}.contextTokensAtEnd`),
814
+ compactions: readSourcedNumber(record.compactions, `${source}.compactions`),
815
+ expectedColdReasons: Object.fromEntries(
816
+ Object.entries(expectedColdReasons).map(([reason, metric]) => {
817
+ if (reason.trim().length === 0) throw new Error(`${source}.expectedColdReasons: expected non-empty reason`);
818
+ return [reason, readSourcedNumber(metric, `${source}.expectedColdReasons.${reason}`)];
819
+ })
820
+ )
821
+ };
822
+ }
823
+ function parseEvidence(value, source) {
824
+ const record = asRecord(value, source);
825
+ const terminalReceiptDigest = readNullableString2(record, source, "terminalReceiptDigest");
826
+ if (terminalReceiptDigest !== null && !/^[a-f0-9]{64}$/u.test(terminalReceiptDigest)) {
827
+ throw new Error(`${source}.terminalReceiptDigest: expected sha256 digest or null`);
828
+ }
829
+ const graderExitCode = record.graderExitCode;
830
+ if (graderExitCode !== null && (!Number.isInteger(graderExitCode) || !Number.isFinite(graderExitCode))) {
831
+ throw new Error(`${source}.graderExitCode: expected integer or null`);
832
+ }
833
+ return {
834
+ assignmentId: readNullableString2(record, source, "assignmentId"),
835
+ terminalReceiptDigest,
836
+ graderExitCode
837
+ };
838
+ }
839
+ function legacyVerdictReason(outcome, machinery, evidence) {
840
+ if (outcome !== "fail") return null;
841
+ if (machinery === "infrastructure_failure") return "infrastructure_failure";
842
+ if (evidence.graderExitCode !== null && evidence.graderExitCode !== 0) return "grader_failed";
843
+ return "outcome_failed";
844
+ }
845
+ function readSourcedNumber(value, source) {
846
+ const record = asRecord(value, source);
847
+ return {
848
+ value: readNonNegativeNumber(record.value, `${source}.value`),
849
+ source: readMetricSource(record.source, source)
850
+ };
851
+ }
852
+ function readSourcedNullableNumber(value, source) {
853
+ const record = asRecord(value, source);
854
+ return {
855
+ value: record.value === null ? null : readNonNegativeNumber(record.value, `${source}.value`),
856
+ source: readMetricSource(record.source, source)
857
+ };
858
+ }
859
+ function readMetricSource(value, source) {
860
+ if (value === "ledger" || value === "receipt" || value === "estimated") return value;
861
+ throw new Error(`${source}.source: expected ledger, receipt, or estimated`);
862
+ }
863
+ function readOutcome(value, source) {
864
+ if (value === "pass" || value === "fail" || value === "unmeasured") return value;
865
+ throw new Error(`${source}: expected pass, fail, or unmeasured`);
866
+ }
867
+ function readMachinery(value, source) {
868
+ if (value === "ok" || value === "infrastructure_failure") return value;
869
+ throw new Error(`${source}: expected ok or infrastructure_failure`);
870
+ }
871
+ function readNonNegativeNumber(value, source) {
872
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
873
+ throw new Error(`${source}: expected non-negative number`);
874
+ }
875
+ return value;
876
+ }
877
+ function readNonNegativeInteger(record, source, field) {
878
+ const value = record[field];
879
+ if (!Number.isInteger(value) || typeof value !== "number" || value < 0) {
880
+ throw new Error(`${source}.${field}: expected non-negative integer`);
881
+ }
882
+ return value;
883
+ }
884
+ function readNonEmptyString(record, source, field) {
885
+ const value = record[field];
886
+ if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${source}.${field}: expected string`);
887
+ return value;
888
+ }
889
+ function readNullableString2(record, source, field) {
890
+ const value = record[field];
891
+ if (value === null) return null;
892
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string or null`);
893
+ return value;
894
+ }
895
+ function readNullableNonEmptyString(record, source, field) {
896
+ const value = readNullableString2(record, source, field);
897
+ if (value !== null && value.trim().length === 0) {
898
+ throw new Error(`${source}.${field}: expected non-empty string or null`);
899
+ }
900
+ return value;
901
+ }
902
+ function asRecord(value, source) {
903
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return value;
904
+ throw new Error(`${source}: expected object`);
905
+ }
906
+
907
+ // src/domains/eval/schema/behavioral.ts
908
+ var EVAL_BEHAVIOR_SCENARIO_SCHEMA_V1 = "clio.eval.scenario.v1";
909
+ var EVAL_BEHAVIOR_SCHEMA_V1 = "clio.eval.behavior.v1";
910
+ var EVAL_BEHAVIOR_CATEGORIES = [
911
+ "tool_choice",
912
+ "exploration",
913
+ "delegation",
914
+ "safety_comprehension",
915
+ "claim_grounding",
916
+ "denied_tool_recovery",
917
+ "completion_behavior",
918
+ "task_correctness"
919
+ ];
920
+ var MAX_RULES = 64;
921
+ var MAX_FACTS = 128;
922
+ var MAX_EVIDENCE_PER_LABEL = 8;
923
+ var MAX_ID_CHARS = 128;
924
+ var MAX_TEXT_CHARS = 1e3;
925
+ var MAX_EXPLANATION_CHARS = 2e3;
926
+ function parseEvalBehaviorScenarioV1(value, source = "behavioral scenario") {
927
+ const record = asRecord2(value, source);
928
+ if (record.schema !== EVAL_BEHAVIOR_SCENARIO_SCHEMA_V1) {
929
+ throw new Error(`${source}.schema: expected ${EVAL_BEHAVIOR_SCENARIO_SCHEMA_V1}`);
930
+ }
931
+ const corpus = asRecord2(record.corpus, `${source}.corpus`);
932
+ const execution = asRecord2(record.execution, `${source}.execution`);
933
+ const subject = asRecord2(execution.subject, `${source}.execution.subject`);
934
+ const mode = execution.mode;
935
+ if (mode !== "machinery-only" && mode !== "model-required") {
936
+ throw new Error(`${source}.execution.mode: expected machinery-only or model-required`);
937
+ }
938
+ const subjectKind = subject.kind;
939
+ if (subjectKind !== "main-agent" && subjectKind !== "worker") {
940
+ throw new Error(`${source}.execution.subject.kind: expected main-agent or worker`);
941
+ }
942
+ const toolTarget = execution.toolTarget;
943
+ if (toolTarget !== "available" && toolTarget !== "none") {
944
+ throw new Error(`${source}.execution.toolTarget: expected available or none`);
945
+ }
946
+ const expectedBehavior = parseRules(record.expectedBehavior, `${source}.expectedBehavior`);
947
+ const forbiddenBehavior = parseRules(record.forbiddenBehavior, `${source}.forbiddenBehavior`);
948
+ const ruleIds = /* @__PURE__ */ new Set();
949
+ for (const rule of [...expectedBehavior, ...forbiddenBehavior]) {
950
+ if (ruleIds.has(rule.id)) throw new Error(`${source}: duplicate behavioral rule id ${rule.id}`);
951
+ ruleIds.add(rule.id);
952
+ }
953
+ if (ruleIds.size === 0) throw new Error(`${source}: expected at least one behavioral rule`);
954
+ const judge = asRecord2(record.judge, `${source}.judge`);
955
+ const maxEvidenceItems = readBoundedInteger(judge.maxEvidenceItems, `${source}.judge.maxEvidenceItems`, 1, MAX_FACTS);
956
+ const maxExplanationChars = readBoundedInteger(
957
+ judge.maxExplanationChars,
958
+ `${source}.judge.maxExplanationChars`,
959
+ 1,
960
+ MAX_EXPLANATION_CHARS
961
+ );
962
+ return {
963
+ schema: EVAL_BEHAVIOR_SCENARIO_SCHEMA_V1,
964
+ corpus: {
965
+ id: readId(corpus.id, `${source}.corpus.id`),
966
+ version: readText(corpus.version, `${source}.corpus.version`, MAX_ID_CHARS)
967
+ },
968
+ execution: {
969
+ mode,
970
+ subject: { kind: subjectKind, role: readId(subject.role, `${source}.execution.subject.role`) },
971
+ toolTarget
972
+ },
973
+ expectedBehavior,
974
+ forbiddenBehavior,
975
+ judge: { maxEvidenceItems, maxExplanationChars }
976
+ };
977
+ }
978
+ function canonicalizeEvalBehaviorJudgeInputV1(value, scenario, source = "behavioral judge input") {
979
+ const record = asRecord2(value, source);
980
+ if (!Array.isArray(record.facts)) throw new Error(`${source}.facts: expected array`);
981
+ if (record.facts.length > scenario.judge.maxEvidenceItems || record.facts.length > MAX_FACTS) {
982
+ throw new Error(`${source}.facts: exceeds bounded evidence limit`);
983
+ }
984
+ const facts = record.facts.map((fact, index) => parseFact(fact, `${source}.facts[${index}]`));
985
+ const factIds = /* @__PURE__ */ new Set();
986
+ const factKeys = /* @__PURE__ */ new Set();
987
+ for (const fact of facts) {
988
+ if (factIds.has(fact.id)) throw new Error(`${source}: duplicate fact id ${fact.id}`);
989
+ const key = `${fact.source}\0${fact.key}`;
990
+ if (factKeys.has(key)) throw new Error(`${source}: conflicting fact ${fact.source}.${fact.key}`);
991
+ factIds.add(fact.id);
992
+ factKeys.add(key);
993
+ }
994
+ const unavailableSources = parseSources(record.unavailableSources, `${source}.unavailableSources`);
995
+ const infrastructureFailure = record.infrastructureFailure;
996
+ if (typeof infrastructureFailure !== "boolean") {
997
+ throw new Error(`${source}.infrastructureFailure: expected boolean`);
998
+ }
999
+ const input = {
1000
+ facts: facts.sort((left, right) => left.source.localeCompare(right.source) || left.key.localeCompare(right.key)),
1001
+ unavailableSources: [...new Set(unavailableSources)].sort(),
1002
+ infrastructureFailure
1003
+ };
1004
+ return { input, digest: sha2562(stableJson(input)) };
1005
+ }
1006
+ function judgeEvalBehaviorV1(scenarioValue, verdict, inputValue) {
1007
+ const scenario = parseEvalBehaviorScenarioV1(scenarioValue);
1008
+ const { input, digest } = canonicalizeEvalBehaviorJudgeInputV1(inputValue, scenario);
1009
+ const labels = EVAL_BEHAVIOR_CATEGORIES.map(
1010
+ (category) => judgeCategory(category, scenario, input, scenario.judge.maxExplanationChars)
1011
+ );
1012
+ const outcome = input.infrastructureFailure ? "infrastructure_failure" : labels.some((label) => label.label === "violated") ? "behavioral_failure" : labels.some((label) => label.label === "unknown") ? "unknown" : labels.every((label) => label.label === "unmeasured") ? "unmeasured" : "pass";
1013
+ return parseEvalBehaviorVerdictV1({
1014
+ schema: EVAL_BEHAVIOR_SCHEMA_V1,
1015
+ verdictRef: {
1016
+ schema: verdict.schema,
1017
+ scenarioId: verdict.scenarioId,
1018
+ trialIndex: verdict.trialIndex
1019
+ },
1020
+ corpus: scenario.corpus,
1021
+ judgeInputDigest: digest,
1022
+ outcome,
1023
+ labels
1024
+ });
1025
+ }
1026
+ function parseEvalBehaviorVerdictV1(value, source = "behavioral verdict") {
1027
+ const record = asRecord2(value, source);
1028
+ if (record.schema !== EVAL_BEHAVIOR_SCHEMA_V1)
1029
+ throw new Error(`${source}.schema: expected ${EVAL_BEHAVIOR_SCHEMA_V1}`);
1030
+ const verdictRef = asRecord2(record.verdictRef, `${source}.verdictRef`);
1031
+ if (verdictRef.schema !== EVAL_VERDICT_SCHEMA_V1) {
1032
+ throw new Error(`${source}.verdictRef.schema: expected ${EVAL_VERDICT_SCHEMA_V1}`);
1033
+ }
1034
+ const corpus = asRecord2(record.corpus, `${source}.corpus`);
1035
+ const outcome = readOutcome2(record.outcome, `${source}.outcome`);
1036
+ if (!Array.isArray(record.labels)) throw new Error(`${source}.labels: expected array`);
1037
+ const labels = record.labels.map((label, index) => parseLabel(label, `${source}.labels[${index}]`));
1038
+ const categories = labels.map((label) => label.category);
1039
+ if (labels.length !== EVAL_BEHAVIOR_CATEGORIES.length || new Set(categories).size !== EVAL_BEHAVIOR_CATEGORIES.length) {
1040
+ throw new Error(`${source}.labels: expected every behavioral category exactly once`);
1041
+ }
1042
+ for (const category of EVAL_BEHAVIOR_CATEGORIES) {
1043
+ if (!categories.includes(category)) throw new Error(`${source}.labels: missing category ${category}`);
1044
+ }
1045
+ const derived = deriveOutcome(labels, outcome === "infrastructure_failure");
1046
+ if (outcome !== derived) throw new Error(`${source}.outcome: ${outcome} conflicts with labels (expected ${derived})`);
1047
+ return {
1048
+ schema: EVAL_BEHAVIOR_SCHEMA_V1,
1049
+ verdictRef: {
1050
+ schema: EVAL_VERDICT_SCHEMA_V1,
1051
+ scenarioId: readId(verdictRef.scenarioId, `${source}.verdictRef.scenarioId`),
1052
+ trialIndex: readBoundedInteger(verdictRef.trialIndex, `${source}.verdictRef.trialIndex`, 0, Number.MAX_SAFE_INTEGER)
1053
+ },
1054
+ corpus: {
1055
+ id: readId(corpus.id, `${source}.corpus.id`),
1056
+ version: readText(corpus.version, `${source}.corpus.version`, MAX_ID_CHARS)
1057
+ },
1058
+ judgeInputDigest: readDigest(record.judgeInputDigest, `${source}.judgeInputDigest`),
1059
+ outcome,
1060
+ labels
1061
+ };
1062
+ }
1063
+ function assertEvalBehaviorReferencesVerdictV1(behavior, verdict, source = "behavioral verdict") {
1064
+ if (behavior.verdictRef.scenarioId !== verdict.scenarioId || behavior.verdictRef.trialIndex !== verdict.trialIndex) {
1065
+ throw new Error(`${source}.verdictRef: conflicts with result verdict identity`);
1066
+ }
1067
+ if (verdict.machinery === "infrastructure_failure" && behavior.outcome !== "infrastructure_failure") {
1068
+ throw new Error(`${source}.outcome: machinery failure must remain infrastructure_failure`);
1069
+ }
1070
+ if (behavior.outcome === "pass" && verdict.outcome !== "pass") {
1071
+ throw new Error(`${source}.outcome: behavioral pass cannot override a failed or unmeasured result`);
1072
+ }
1073
+ }
1074
+ function judgeCategory(category, scenario, input, maxExplanationChars) {
1075
+ const expected = scenario.expectedBehavior.filter((rule) => rule.category === category);
1076
+ const forbidden = scenario.forbiddenBehavior.filter((rule) => rule.category === category);
1077
+ const rules = [...expected, ...forbidden];
1078
+ if (input.infrastructureFailure)
1079
+ return labelResult(category, "unknown", rules, [], "infrastructure failure", maxExplanationChars);
1080
+ if (rules.length === 0) return labelResult(category, "unmeasured", [], [], null, maxExplanationChars);
1081
+ const unavailable = rules.some((rule) => input.unavailableSources.includes(rule.fact.source));
1082
+ if (unavailable)
1083
+ return labelResult(category, "unmeasured", rules, [], "required evidence source unavailable", maxExplanationChars);
1084
+ const evaluations = rules.map((rule) => {
1085
+ const fact = input.facts.find(
1086
+ (candidate) => candidate.source === rule.fact.source && candidate.key === rule.fact.key
1087
+ );
1088
+ if (fact === void 0) return { rule, fact: null, holds: null };
1089
+ const matches = compare(fact.value, rule.fact.op, rule.fact.value);
1090
+ return { rule, fact, holds: expected.includes(rule) ? matches : !matches };
1091
+ });
1092
+ const evidence = evaluations.flatMap(({ fact }) => fact === null ? [] : [toEvidence(fact)]).slice(0, MAX_EVIDENCE_PER_LABEL);
1093
+ if (evaluations.some(({ holds }) => holds === false)) {
1094
+ return labelResult(category, "violated", rules, evidence, "one or more declared rules failed", maxExplanationChars);
1095
+ }
1096
+ if (evaluations.some(({ holds }) => holds === null)) {
1097
+ return labelResult(category, "unknown", rules, evidence, "required observable fact missing", maxExplanationChars);
1098
+ }
1099
+ return labelResult(category, "satisfied", rules, evidence, null, maxExplanationChars);
1100
+ }
1101
+ function labelResult(category, label, rules, evidence, explanation, maxExplanationChars) {
1102
+ return {
1103
+ category,
1104
+ label,
1105
+ ruleIds: rules.map((rule) => rule.id).sort(),
1106
+ evidence,
1107
+ explanation: explanation === null ? null : explanation.slice(0, maxExplanationChars)
1108
+ };
1109
+ }
1110
+ function deriveOutcome(labels, infrastructure) {
1111
+ if (infrastructure) return "infrastructure_failure";
1112
+ if (labels.some((label) => label.label === "violated")) return "behavioral_failure";
1113
+ if (labels.some((label) => label.label === "unknown")) return "unknown";
1114
+ if (labels.every((label) => label.label === "unmeasured")) return "unmeasured";
1115
+ return "pass";
1116
+ }
1117
+ function parseRules(value, source) {
1118
+ if (!Array.isArray(value)) throw new Error(`${source}: expected array`);
1119
+ if (value.length > MAX_RULES) throw new Error(`${source}: exceeds ${MAX_RULES} rules`);
1120
+ return value.map((entry, index) => {
1121
+ const record = asRecord2(entry, `${source}[${index}]`);
1122
+ const fact = asRecord2(record.fact, `${source}[${index}].fact`);
1123
+ const rationale = record.rationale === void 0 ? void 0 : readText(record.rationale, `${source}[${index}].rationale`, MAX_TEXT_CHARS);
1124
+ return {
1125
+ id: readId(record.id, `${source}[${index}].id`),
1126
+ category: readCategory(record.category, `${source}[${index}].category`),
1127
+ fact: {
1128
+ source: readSource(fact.source, `${source}[${index}].fact.source`),
1129
+ key: readText(fact.key, `${source}[${index}].fact.key`, MAX_TEXT_CHARS),
1130
+ op: readOp(fact.op, `${source}[${index}].fact.op`),
1131
+ value: readScalar(fact.value, `${source}[${index}].fact.value`)
1132
+ },
1133
+ ...rationale === void 0 ? {} : { rationale }
1134
+ };
1135
+ });
1136
+ }
1137
+ function parseFact(value, source) {
1138
+ const record = asRecord2(value, source);
1139
+ const evidence = asRecord2(record.evidence, `${source}.evidence`);
1140
+ return {
1141
+ id: readId(record.id, `${source}.id`),
1142
+ source: readSource(record.source, `${source}.source`),
1143
+ key: readText(record.key, `${source}.key`, MAX_TEXT_CHARS),
1144
+ value: readScalar(record.value, `${source}.value`),
1145
+ evidence: {
1146
+ locator: readText(evidence.locator, `${source}.evidence.locator`, MAX_TEXT_CHARS),
1147
+ digest: readDigest(evidence.digest, `${source}.evidence.digest`),
1148
+ excerpt: evidence.excerpt === null ? null : readText(evidence.excerpt, `${source}.evidence.excerpt`, MAX_TEXT_CHARS)
1149
+ }
1150
+ };
1151
+ }
1152
+ function parseLabel(value, source) {
1153
+ const record = asRecord2(value, source);
1154
+ const label = record.label;
1155
+ if (label !== "satisfied" && label !== "violated" && label !== "unknown" && label !== "unmeasured") {
1156
+ throw new Error(`${source}.label: expected satisfied, violated, unknown, or unmeasured`);
1157
+ }
1158
+ if (!Array.isArray(record.ruleIds) || !Array.isArray(record.evidence)) {
1159
+ throw new Error(`${source}: expected ruleIds and evidence arrays`);
1160
+ }
1161
+ if (record.evidence.length > MAX_EVIDENCE_PER_LABEL) throw new Error(`${source}.evidence: exceeds bounded limit`);
1162
+ if ((label === "satisfied" || label === "violated") && (record.ruleIds.length === 0 || record.evidence.length === 0)) {
1163
+ throw new Error(`${source}: ${label} label requires a rule and observable evidence`);
1164
+ }
1165
+ const explanation = record.explanation;
1166
+ if (explanation !== null && (typeof explanation !== "string" || explanation.length > MAX_EXPLANATION_CHARS)) {
1167
+ throw new Error(`${source}.explanation: expected bounded string or null`);
1168
+ }
1169
+ return {
1170
+ category: readCategory(record.category, `${source}.category`),
1171
+ label,
1172
+ ruleIds: record.ruleIds.map((id, index) => readId(id, `${source}.ruleIds[${index}]`)),
1173
+ evidence: record.evidence.map((entry, index) => {
1174
+ const evidence = asRecord2(entry, `${source}.evidence[${index}]`);
1175
+ return {
1176
+ factId: readId(evidence.factId, `${source}.evidence[${index}].factId`),
1177
+ source: readSource(evidence.source, `${source}.evidence[${index}].source`),
1178
+ locator: readText(evidence.locator, `${source}.evidence[${index}].locator`, MAX_TEXT_CHARS),
1179
+ digest: readDigest(evidence.digest, `${source}.evidence[${index}].digest`),
1180
+ excerpt: evidence.excerpt === null ? null : readText(evidence.excerpt, `${source}.evidence[${index}].excerpt`, MAX_TEXT_CHARS)
1181
+ };
1182
+ }),
1183
+ explanation
1184
+ };
1185
+ }
1186
+ function toEvidence(fact) {
1187
+ return { factId: fact.id, source: fact.source, ...fact.evidence };
1188
+ }
1189
+ function compare(actual, op, expected) {
1190
+ if (op === "eq") return actual === expected;
1191
+ if (op === "neq") return actual !== expected;
1192
+ if (typeof actual !== "number" || typeof expected !== "number") return false;
1193
+ if (op === "lt") return actual < expected;
1194
+ if (op === "lte") return actual <= expected;
1195
+ if (op === "gt") return actual > expected;
1196
+ return actual >= expected;
1197
+ }
1198
+ function parseSources(value, source) {
1199
+ if (!Array.isArray(value)) throw new Error(`${source}: expected array`);
1200
+ return value.map((entry, index) => readSource(entry, `${source}[${index}]`));
1201
+ }
1202
+ function readOutcome2(value, source) {
1203
+ if (value === "pass" || value === "behavioral_failure" || value === "unknown" || value === "unmeasured" || value === "infrastructure_failure")
1204
+ return value;
1205
+ throw new Error(`${source}: expected a closed behavioral outcome`);
1206
+ }
1207
+ function readCategory(value, source) {
1208
+ if (typeof value === "string" && EVAL_BEHAVIOR_CATEGORIES.includes(value)) {
1209
+ return value;
1210
+ }
1211
+ throw new Error(`${source}: expected a closed behavioral category`);
1212
+ }
1213
+ function readSource(value, source) {
1214
+ if (value === "transcript" || value === "tool" || value === "receipt" || value === "grader") return value;
1215
+ throw new Error(`${source}: expected transcript, tool, receipt, or grader`);
1216
+ }
1217
+ function readOp(value, source) {
1218
+ if (value === "eq" || value === "neq" || value === "lt" || value === "lte" || value === "gt" || value === "gte") {
1219
+ return value;
1220
+ }
1221
+ throw new Error(`${source}: expected eq, neq, lt, lte, gt, or gte`);
1222
+ }
1223
+ function readScalar(value, source) {
1224
+ if (typeof value === "boolean") return value;
1225
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1226
+ if (typeof value === "string" && value.length <= MAX_TEXT_CHARS) return value;
1227
+ throw new Error(`${source}: expected bounded string, finite number, or boolean`);
1228
+ }
1229
+ function readId(value, source) {
1230
+ const id = readText(value, source, MAX_ID_CHARS);
1231
+ if (!/^[A-Za-z0-9._-]+$/u.test(id)) throw new Error(`${source}: expected stable id`);
1232
+ return id;
1233
+ }
1234
+ function readText(value, source, maxChars) {
1235
+ if (typeof value !== "string" || value.trim().length === 0 || value.length > maxChars) {
1236
+ throw new Error(`${source}: expected non-empty string no longer than ${maxChars} characters`);
1237
+ }
1238
+ return value;
1239
+ }
1240
+ function readDigest(value, source) {
1241
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/u.test(value)) throw new Error(`${source}: expected sha256 digest`);
1242
+ return value;
1243
+ }
1244
+ function readBoundedInteger(value, source, min, max) {
1245
+ if (typeof value !== "number" || !Number.isInteger(value) || value < min || value > max) {
1246
+ throw new Error(`${source}: expected integer from ${min} through ${max}`);
1247
+ }
1248
+ return value;
1249
+ }
1250
+ function asRecord2(value, source) {
1251
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return value;
1252
+ throw new Error(`${source}: expected object`);
1253
+ }
1254
+ function stableJson(value) {
1255
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
1256
+ if (typeof value === "object" && value !== null) {
1257
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
1258
+ }
1259
+ return JSON.stringify(value);
1260
+ }
1261
+ function sha2562(value) {
1262
+ return createHash3("sha256").update(value, "utf8").digest("hex");
1263
+ }
1264
+
1265
+ // src/domains/eval/schema/behavioral-metrics.ts
1266
+ init_esm_shims();
1267
+ var EVAL_BEHAVIOR_METRICS_SCHEMA_V1 = "clio.eval.behavior.metrics.v1";
1268
+ var EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1 = [
1269
+ {
1270
+ name: "correctness.taskSolved",
1271
+ family: "correctness",
1272
+ direction: "higher",
1273
+ hardGate: true,
1274
+ source: "grader"
1275
+ },
1276
+ {
1277
+ name: "safety.violations",
1278
+ family: "safety",
1279
+ direction: "lower",
1280
+ hardGate: true,
1281
+ source: "behavioral-label"
1282
+ },
1283
+ {
1284
+ name: "behavior.labelViolations",
1285
+ family: "behavior",
1286
+ direction: "lower",
1287
+ hardGate: false,
1288
+ source: "behavioral-label"
1289
+ },
1290
+ {
1291
+ name: "efficiency.toolCalls",
1292
+ family: "efficiency",
1293
+ direction: "lower",
1294
+ hardGate: false,
1295
+ source: "tool-event"
1296
+ },
1297
+ {
1298
+ name: "exploration.unnecessaryReads",
1299
+ family: "exploration",
1300
+ direction: "lower",
1301
+ hardGate: false,
1302
+ source: "tool-event"
1303
+ },
1304
+ {
1305
+ name: "delegation.quality",
1306
+ family: "delegation",
1307
+ direction: "higher",
1308
+ hardGate: false,
1309
+ source: "behavioral-label"
1310
+ },
1311
+ {
1312
+ name: "claims.unsupported",
1313
+ family: "claims",
1314
+ direction: "lower",
1315
+ hardGate: false,
1316
+ source: "grader"
1317
+ },
1318
+ {
1319
+ name: "tokens.total",
1320
+ family: "tokens",
1321
+ direction: "lower",
1322
+ hardGate: false,
1323
+ source: "runner"
1324
+ },
1325
+ {
1326
+ name: "latency.wallMs",
1327
+ family: "latency",
1328
+ direction: "lower",
1329
+ hardGate: false,
1330
+ source: "runner"
1331
+ },
1332
+ {
1333
+ name: "cost.usd",
1334
+ family: "cost",
1335
+ direction: "lower",
1336
+ hardGate: false,
1337
+ source: "receipt"
1338
+ }
1339
+ ];
1340
+ function buildEvalBehaviorMetricsV1(result, role) {
1341
+ const label = (category) => result.behavioral?.labels.find((entry) => entry.category === category)?.label ?? null;
1342
+ const observedLabels = result.behavioral?.labels.filter(
1343
+ (entry) => entry.label === "satisfied" || entry.label === "violated"
1344
+ );
1345
+ const values = {
1346
+ "correctness.taskSolved": booleanMetric(result.metrics["task.solved"]),
1347
+ "safety.violations": violationMetric(label("safety_comprehension")),
1348
+ "behavior.labelViolations": observedLabels === void 0 || observedLabels.length !== result.behavioral?.labels.length ? null : observedLabels.filter((entry) => entry.label === "violated").length,
1349
+ "efficiency.toolCalls": numberMetric(result.metrics["tools.totalCalls"]),
1350
+ "exploration.unnecessaryReads": numberMetric(result.metrics["tools.read.outsideAllowed"]),
1351
+ "delegation.quality": qualityMetric(label("delegation")),
1352
+ "claims.unsupported": numberMetric(result.metrics["claims.unsupported"]),
1353
+ "tokens.total": numberMetric(result.metrics["tokens.total"]),
1354
+ "latency.wallMs": numberMetric(result.metrics["latency.wallMs"]),
1355
+ "cost.usd": numberMetric(result.metrics["cost.usd"])
1356
+ };
1357
+ const metrics = Object.fromEntries(
1358
+ EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1.map((definition) => [
1359
+ definition.name,
1360
+ { value: values[definition.name], source: definition.source }
1361
+ ])
1362
+ );
1363
+ return {
1364
+ schema: EVAL_BEHAVIOR_METRICS_SCHEMA_V1,
1365
+ scenarioId: result.taskId,
1366
+ role,
1367
+ target: { id: result.target.id, model: result.target.model },
1368
+ metrics
1369
+ };
1370
+ }
1371
+ function parseEvalBehaviorMetricsV1(value, source = "behavioral metrics") {
1372
+ const record = asRecord3(value, source);
1373
+ if (record.schema !== EVAL_BEHAVIOR_METRICS_SCHEMA_V1) {
1374
+ throw new Error(`${source}.schema: expected ${EVAL_BEHAVIOR_METRICS_SCHEMA_V1}`);
1375
+ }
1376
+ const target = asRecord3(record.target, `${source}.target`);
1377
+ const rawMetrics = asRecord3(record.metrics, `${source}.metrics`);
1378
+ const expectedMetricNames = new Set(EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1.map((definition) => definition.name));
1379
+ for (const metricName of Object.keys(rawMetrics)) {
1380
+ if (!expectedMetricNames.has(metricName)) {
1381
+ throw new Error(`${source}.metrics.${metricName}: unknown behavioral metric`);
1382
+ }
1383
+ }
1384
+ const metrics = Object.fromEntries(
1385
+ EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1.map((definition) => {
1386
+ const observation = asRecord3(rawMetrics[definition.name], `${source}.metrics.${definition.name}`);
1387
+ const metricSource = observation.source;
1388
+ if (metricSource !== definition.source) {
1389
+ throw new Error(`${source}.metrics.${definition.name}.source: expected ${definition.source}`);
1390
+ }
1391
+ const metricValue = observation.value;
1392
+ if (metricValue !== null && (typeof metricValue !== "number" || !Number.isFinite(metricValue))) {
1393
+ throw new Error(`${source}.metrics.${definition.name}.value: expected finite number or null`);
1394
+ }
1395
+ return [definition.name, { value: metricValue, source: metricSource }];
1396
+ })
1397
+ );
1398
+ return {
1399
+ schema: EVAL_BEHAVIOR_METRICS_SCHEMA_V1,
1400
+ scenarioId: readString2(record.scenarioId, `${source}.scenarioId`),
1401
+ role: readString2(record.role, `${source}.role`),
1402
+ target: {
1403
+ id: readString2(target.id, `${source}.target.id`),
1404
+ model: target.model === null ? null : readString2(target.model, `${source}.target.model`)
1405
+ },
1406
+ metrics
1407
+ };
1408
+ }
1409
+ function numberMetric(value) {
1410
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1411
+ }
1412
+ function booleanMetric(value) {
1413
+ return typeof value === "boolean" ? value ? 1 : 0 : null;
1414
+ }
1415
+ function violationMetric(label) {
1416
+ if (label === "violated") return 1;
1417
+ if (label === "satisfied") return 0;
1418
+ return null;
1419
+ }
1420
+ function qualityMetric(label) {
1421
+ if (label === "satisfied") return 1;
1422
+ if (label === "violated") return 0;
1423
+ return null;
1424
+ }
1425
+ function asRecord3(value, source) {
1426
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return value;
1427
+ throw new Error(`${source}: expected object`);
1428
+ }
1429
+ function readString2(value, source) {
1430
+ if (typeof value === "string" && value.length > 0) return value;
1431
+ throw new Error(`${source}: expected non-empty string`);
1432
+ }
1433
+
1434
+ // src/domains/eval/schema/execution-envelope.ts
1435
+ init_esm_shims();
1436
+ var EVAL_EXECUTION_ENVELOPE_SCHEMA_V1 = "clio.eval.execution-envelope.v1";
1437
+ var EVAL_EXECUTION_MATRIX_DIMENSIONS_V1 = [
1438
+ "prompt",
1439
+ "recipe",
1440
+ "target",
1441
+ "wireModel",
1442
+ "runtime",
1443
+ "thinkingLevel",
1444
+ "toolSignature",
1445
+ "autonomy",
1446
+ "policy",
1447
+ "projectContext",
1448
+ "corpus"
1449
+ ];
1450
+ function parseEvalExecutionEnvelopeV1(value, source = "execution envelope") {
1451
+ const record = asRecord4(value, source);
1452
+ if (record.schema !== EVAL_EXECUTION_ENVELOPE_SCHEMA_V1) {
1453
+ throw new Error(`${source}.schema: expected ${EVAL_EXECUTION_ENVELOPE_SCHEMA_V1}`);
1454
+ }
1455
+ const prompt = asRecord4(record.prompt, `${source}.prompt`);
1456
+ if (!Array.isArray(prompt.fragments)) throw new Error(`${source}.prompt.fragments: expected array`);
1457
+ const fragments = prompt.fragments.map((entry, index) => {
1458
+ const fragment = asRecord4(entry, `${source}.prompt.fragments[${index}]`);
1459
+ const version = fragment.version;
1460
+ if (version !== "unversioned" && (!Number.isInteger(version) || typeof version !== "number" || version <= 0)) {
1461
+ throw new Error(`${source}.prompt.fragments[${index}].version: expected positive integer or unversioned`);
1462
+ }
1463
+ return {
1464
+ id: readString3(fragment.id, `${source}.prompt.fragments[${index}].id`),
1465
+ version,
1466
+ contentHash: readDigest2(fragment.contentHash, `${source}.prompt.fragments[${index}].contentHash`)
1467
+ };
1468
+ });
1469
+ const fragmentIds = fragments.map((fragment) => fragment.id);
1470
+ if (new Set(fragmentIds).size !== fragmentIds.length) {
1471
+ throw new Error(`${source}.prompt.fragments: duplicate fragment id`);
1472
+ }
1473
+ const recipe = record.recipe === null ? null : (() => {
1474
+ const value2 = asRecord4(record.recipe, `${source}.recipe`);
1475
+ const version = value2.version;
1476
+ if (!Number.isInteger(version) || typeof version !== "number" || version <= 0) {
1477
+ throw new Error(`${source}.recipe.version: expected positive integer`);
1478
+ }
1479
+ return {
1480
+ id: readString3(value2.id, `${source}.recipe.id`),
1481
+ version,
1482
+ contentHash: readDigest2(value2.contentHash, `${source}.recipe.contentHash`)
1483
+ };
1484
+ })();
1485
+ const policyHashes = asRecord4(record.policyHashes, `${source}.policyHashes`);
1486
+ const projectContext = asRecord4(record.projectContext, `${source}.projectContext`);
1487
+ const projectKind = projectContext.kind;
1488
+ if (projectKind !== "none" && projectKind !== "session" && projectKind !== "worker") {
1489
+ throw new Error(`${source}.projectContext.kind: expected none, session, or worker`);
1490
+ }
1491
+ const corpus = asRecord4(record.corpus, `${source}.corpus`);
1492
+ return {
1493
+ schema: EVAL_EXECUTION_ENVELOPE_SCHEMA_V1,
1494
+ prompt: {
1495
+ fragments,
1496
+ compositionHash: readNullableDigest(prompt.compositionHash, `${source}.prompt.compositionHash`)
1497
+ },
1498
+ recipe,
1499
+ target: readString3(record.target, `${source}.target`),
1500
+ wireModel: readNullableString3(record.wireModel, `${source}.wireModel`),
1501
+ runtime: readNullableString3(record.runtime, `${source}.runtime`),
1502
+ thinkingLevel: readNullableString3(record.thinkingLevel, `${source}.thinkingLevel`),
1503
+ toolSignature: readNullableDigest(record.toolSignature, `${source}.toolSignature`),
1504
+ autonomy: readNullableString3(record.autonomy, `${source}.autonomy`),
1505
+ policyHashes: {
1506
+ rulePack: readNullableDigest(policyHashes.rulePack, `${source}.policyHashes.rulePack`),
1507
+ project: readNullableDigest(policyHashes.project, `${source}.policyHashes.project`)
1508
+ },
1509
+ projectContext: {
1510
+ kind: projectKind,
1511
+ tier: readNullableString3(projectContext.tier, `${source}.projectContext.tier`),
1512
+ contentHash: readNullableDigest(projectContext.contentHash, `${source}.projectContext.contentHash`),
1513
+ chars: readNullableNonNegativeInteger(projectContext.chars, `${source}.projectContext.chars`),
1514
+ sections: readStringArray2(projectContext.sections, `${source}.projectContext.sections`),
1515
+ rulesApplied: readStringArray2(projectContext.rulesApplied, `${source}.projectContext.rulesApplied`),
1516
+ operatorProfileApplied: readNullableBoolean(
1517
+ projectContext.operatorProfileApplied,
1518
+ `${source}.projectContext.operatorProfileApplied`
1519
+ )
1520
+ },
1521
+ corpus: {
1522
+ id: readString3(corpus.id, `${source}.corpus.id`),
1523
+ version: readString3(corpus.version, `${source}.corpus.version`)
1524
+ }
1525
+ };
1526
+ }
1527
+ function parseEvalExecutionMatrixDimensionsV1(value, source) {
1528
+ if (!Array.isArray(value)) throw new Error(`${source}: expected array`);
1529
+ const allowed = new Set(EVAL_EXECUTION_MATRIX_DIMENSIONS_V1);
1530
+ const dimensions = value.map((entry, index) => {
1531
+ if (typeof entry !== "string" || !allowed.has(entry)) {
1532
+ throw new Error(`${source}[${index}]: expected a declared execution-envelope dimension`);
1533
+ }
1534
+ return entry;
1535
+ });
1536
+ if (new Set(dimensions).size !== dimensions.length) throw new Error(`${source}: duplicate matrix dimension`);
1537
+ return dimensions;
1538
+ }
1539
+ function readString3(value, source) {
1540
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}: expected non-empty string`);
1541
+ return value;
1542
+ }
1543
+ function readNullableString3(value, source) {
1544
+ if (value === null) return null;
1545
+ return readString3(value, source);
1546
+ }
1547
+ function readDigest2(value, source) {
1548
+ const digest = readString3(value, source);
1549
+ if (!/^[a-f0-9]{64}$/u.test(digest)) throw new Error(`${source}: expected sha256 digest`);
1550
+ return digest;
1551
+ }
1552
+ function readNullableDigest(value, source) {
1553
+ return value === null ? null : readDigest2(value, source);
1554
+ }
1555
+ function readNullableNonNegativeInteger(value, source) {
1556
+ if (value === null) return null;
1557
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
1558
+ throw new Error(`${source}: expected non-negative integer or null`);
1559
+ }
1560
+ return value;
1561
+ }
1562
+ function readNullableBoolean(value, source) {
1563
+ if (value === null || typeof value === "boolean") return value;
1564
+ throw new Error(`${source}: expected boolean or null`);
1565
+ }
1566
+ function readStringArray2(value, source) {
1567
+ if (!Array.isArray(value)) throw new Error(`${source}: expected array`);
1568
+ const entries = value.map((entry, index) => readString3(entry, `${source}[${index}]`));
1569
+ if (new Set(entries).size !== entries.length) throw new Error(`${source}: duplicate value`);
1570
+ return entries;
1571
+ }
1572
+ function asRecord4(value, source) {
1573
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return value;
1574
+ throw new Error(`${source}: expected object`);
1575
+ }
1576
+
1577
+ // src/domains/eval/schema/serving.ts
1578
+ init_esm_shims();
1579
+ function parseEvalServingConfigurationV1(value, source) {
1580
+ const record = asRecord5(value, source);
1581
+ const targetId = readString4(record.targetId, `${source}.targetId`);
1582
+ const totalSlots = record.total_slots;
1583
+ if (totalSlots !== null && (typeof totalSlots !== "number" || !Number.isInteger(totalSlots) || totalSlots <= 0)) {
1584
+ throw new Error(`${source}.total_slots: expected positive integer or null`);
1585
+ }
1586
+ const compiledPromptHash = readNullableString4(record.compiledPromptHash, `${source}.compiledPromptHash`);
1587
+ if (compiledPromptHash !== null && !/^[a-f0-9]{64}$/u.test(compiledPromptHash)) {
1588
+ throw new Error(`${source}.compiledPromptHash: expected sha256 digest or null`);
1589
+ }
1590
+ return {
1591
+ targetId,
1592
+ runtimeId: readNullableString4(record.runtimeId, `${source}.runtimeId`),
1593
+ modelId: readNullableString4(record.modelId, `${source}.modelId`),
1594
+ serverBuild: readNullableString4(record.serverBuild, `${source}.serverBuild`),
1595
+ total_slots: totalSlots,
1596
+ thinkingLevel: readNullableString4(record.thinkingLevel, `${source}.thinkingLevel`),
1597
+ compiledPromptHash
1598
+ };
1599
+ }
1600
+ function sameEvalServingConfiguration(left, right) {
1601
+ return left.targetId === right.targetId && left.runtimeId === right.runtimeId && left.modelId === right.modelId && left.serverBuild === right.serverBuild && left.total_slots === right.total_slots && left.thinkingLevel === right.thinkingLevel && left.compiledPromptHash === right.compiledPromptHash;
1602
+ }
1603
+ function renderEvalServingConfiguration(config) {
1604
+ return [
1605
+ `target=${config.targetId}`,
1606
+ `runtime=${config.runtimeId ?? "unknown"}`,
1607
+ `model=${config.modelId ?? "unknown"}`,
1608
+ `server_build=${config.serverBuild ?? "unknown"}`,
1609
+ `total_slots=${config.total_slots ?? "unknown"}`,
1610
+ `thinking=${config.thinkingLevel ?? "unknown"}`,
1611
+ `compiled_prompt_hash=${config.compiledPromptHash ?? "unknown"}`
1612
+ ].join(" ");
1613
+ }
1614
+ function readString4(value, source) {
1615
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}: expected string`);
1616
+ return value;
1617
+ }
1618
+ function readNullableString4(value, source) {
1619
+ if (value === null) return null;
1620
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}: expected string or null`);
1621
+ return value;
1622
+ }
1623
+ function asRecord5(value, source) {
1624
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return value;
1625
+ throw new Error(`${source}: expected object`);
1626
+ }
1627
+
1628
+ // src/domains/eval/artifacts/store.ts
1629
+ function evalArtifactPathV4(dataDir, evalId) {
1630
+ assertSafeId(evalId, "eval");
1631
+ return join2(evalRoot(dataDir), `${evalId}.json`);
1632
+ }
1633
+ async function writeEvalArtifactV4(dataDir, artifact, out) {
1634
+ const path = out === void 0 ? evalArtifactPathV4(dataDir, artifact.evalId) : out.endsWith(".json") ? out : join2(out, `${artifact.evalId}.json`);
1635
+ safeResourceWrite(path, `${JSON.stringify(redactArtifactForStorage(artifact), null, 2)}
1636
+ `, { encoding: "utf8" });
1637
+ return path;
1638
+ }
1639
+ async function loadEvalArtifactV4(dataDir, evalId) {
1640
+ let raw;
1641
+ try {
1642
+ raw = await readFile2(evalArtifactPathV4(dataDir, evalId), "utf8");
1643
+ } catch (error) {
1644
+ if (error.code === "ENOENT") throw new Error(`eval artifact not found: ${evalId}`);
1645
+ throw error;
1646
+ }
1647
+ return parseEvalArtifactV4(JSON.parse(raw), evalId);
1648
+ }
1649
+ function parseEvalArtifactV4(value, source) {
1650
+ if (!isRecord2(value)) throw new Error(`${source}: expected object`);
1651
+ if (value.version !== 4) throw new Error(`${source}.version: expected current version 4`);
1652
+ const summary = asRecord6(value.summary, `${source}.summary`);
1653
+ const matrix = asRecord6(value.matrix, `${source}.matrix`);
1654
+ const suite = asRecord6(value.suite, `${source}.suite`);
1655
+ const servingConfiguration = value.servingConfiguration === void 0 ? void 0 : parseEvalServingConfigurationV1(value.servingConfiguration, `${source}.servingConfiguration`);
1656
+ const aggregates = value.aggregates === void 0 ? void 0 : readArray2(value, source, "aggregates");
1657
+ return {
1658
+ version: 4,
1659
+ evalId: readString5(value, source, "evalId"),
1660
+ suite: { id: readString5(suite, `${source}.suite`, "id"), hash: readString5(suite, `${source}.suite`, "hash") },
1661
+ clio: {
1662
+ version: readString5(asRecord6(value.clio, `${source}.clio`), `${source}.clio`, "version"),
1663
+ commit: readNullableString5(asRecord6(value.clio, `${source}.clio`), `${source}.clio`, "commit"),
1664
+ entry: readString5(asRecord6(value.clio, `${source}.clio`), `${source}.clio`, "entry")
1665
+ },
1666
+ environment: {
1667
+ platform: readString5(asRecord6(value.environment, `${source}.environment`), `${source}.environment`, "platform"),
1668
+ node: readString5(asRecord6(value.environment, `${source}.environment`), `${source}.environment`, "node")
1669
+ },
1670
+ matrix: {
1671
+ target: readString5(matrix, `${source}.matrix`, "target"),
1672
+ model: readNullableString5(matrix, `${source}.matrix`, "model"),
1673
+ thinking: readNullableString5(matrix, `${source}.matrix`, "thinking"),
1674
+ ...matrix.dimensions === void 0 ? {} : { dimensions: parseEvalExecutionMatrixDimensionsV1(matrix.dimensions, `${source}.matrix.dimensions`) }
1675
+ },
1676
+ ...servingConfiguration === void 0 ? {} : { servingConfiguration },
1677
+ summary: {
1678
+ runs: readNumber2(summary, `${source}.summary`, "runs"),
1679
+ passed: readNumber2(summary, `${source}.summary`, "passed"),
1680
+ failed: readNumber2(summary, `${source}.summary`, "failed"),
1681
+ passRate: readNumber2(summary, `${source}.summary`, "passRate"),
1682
+ tokens: parseTokenAccounting(summary.tokens, `${source}.summary.tokens`),
1683
+ wallTimeMs: readNumber2(summary, `${source}.summary`, "wallTimeMs")
1684
+ },
1685
+ ...aggregates === void 0 ? {} : { aggregates },
1686
+ results: readArray2(value, source, "results").map((entry, index) => parseResult(entry, `${source}.results[${index}]`))
1687
+ };
1688
+ }
1689
+ function parseTokenAccounting(value, source) {
1690
+ const record = asRecord6(value, source);
1691
+ const measured = readBoolean2(record, source, "measured");
1692
+ const runs = readNumber2(record, source, "runs");
1693
+ const measuredRuns = readNumber2(record, source, "measuredRuns");
1694
+ const countFields = ["input", "output", "total", "cacheRead", "cacheWrite"];
1695
+ if (!measured) {
1696
+ if (measuredRuns !== 0) throw new Error(`${source}.measuredRuns: expected 0 when unmeasured`);
1697
+ const present = countFields.filter((field) => field in record);
1698
+ if (present.length > 0) throw new Error(`${source}: unmeasured accounting carries no counts (${present.join(", ")})`);
1699
+ return { measured: false, runs, measuredRuns: 0 };
1700
+ }
1701
+ if (measuredRuns <= 0) throw new Error(`${source}.measuredRuns: expected a positive count when measured`);
1702
+ return {
1703
+ measured: true,
1704
+ runs,
1705
+ measuredRuns,
1706
+ input: readNumber2(record, source, "input"),
1707
+ output: readNumber2(record, source, "output"),
1708
+ total: readNumber2(record, source, "total"),
1709
+ cacheRead: readNumber2(record, source, "cacheRead"),
1710
+ cacheWrite: readNumber2(record, source, "cacheWrite")
1711
+ };
1712
+ }
1713
+ function parseResult(value, source) {
1714
+ const record = asRecord6(value, source);
1715
+ const target = asRecord6(record.target, `${source}.target`);
1716
+ const verdict = record.verdict === void 0 ? void 0 : parseEvalVerdictEnvelopeV1(record.verdict, `${source}.verdict`);
1717
+ const behavioral = record.behavioral === void 0 ? void 0 : parseEvalBehaviorVerdictV1(record.behavioral, `${source}.behavioral`);
1718
+ const behavioralMetrics = record.behavioralMetrics === void 0 ? void 0 : parseEvalBehaviorMetricsV1(record.behavioralMetrics, `${source}.behavioralMetrics`);
1719
+ const executionEnvelope = record.executionEnvelope === void 0 ? void 0 : parseEvalExecutionEnvelopeV1(record.executionEnvelope, `${source}.executionEnvelope`);
1720
+ if (behavioral !== void 0 && verdict === void 0) {
1721
+ throw new Error(`${source}.behavioral: sibling document requires a verdict`);
1722
+ }
1723
+ if (behavioral !== void 0 && verdict !== void 0) {
1724
+ assertEvalBehaviorReferencesVerdictV1(behavioral, verdict, `${source}.behavioral`);
1725
+ }
1726
+ if (behavioralMetrics !== void 0) {
1727
+ if (behavioral === void 0) throw new Error(`${source}.behavioralMetrics: requires a behavioral verdict`);
1728
+ if (behavioralMetrics.scenarioId !== readString5(record, source, "taskId")) {
1729
+ throw new Error(`${source}.behavioralMetrics.scenarioId: conflicts with result taskId`);
1730
+ }
1731
+ if (behavioralMetrics.target.id !== readString5(target, `${source}.target`, "id") || behavioralMetrics.target.model !== readNullableString5(target, `${source}.target`, "model")) {
1732
+ throw new Error(`${source}.behavioralMetrics.target: conflicts with result target`);
1733
+ }
1734
+ }
1735
+ if (executionEnvelope !== void 0) {
1736
+ if (behavioral === void 0) throw new Error(`${source}.executionEnvelope: requires a behavioral verdict`);
1737
+ if (executionEnvelope.target !== readString5(target, `${source}.target`, "id") || executionEnvelope.corpus.id !== behavioral.corpus.id || executionEnvelope.corpus.version !== behavioral.corpus.version) {
1738
+ throw new Error(`${source}.executionEnvelope: conflicts with result target or behavioral corpus`);
1739
+ }
1740
+ }
1741
+ return {
1742
+ assignmentId: readNullableString5(record, source, "assignmentId"),
1743
+ terminalReceiptDigest: readNullableDigest2(record, source, "terminalReceiptDigest"),
1744
+ taskId: readString5(record, source, "taskId"),
1745
+ repeatIndex: readNumber2(record, source, "repeatIndex"),
1746
+ target: {
1747
+ id: readString5(target, `${source}.target`, "id"),
1748
+ model: readNullableString5(target, `${source}.target`, "model"),
1749
+ thinking: readNullableString5(target, `${source}.target`, "thinking")
1750
+ },
1751
+ pass: readBoolean2(record, source, "pass"),
1752
+ failureClass: readNullableString5(record, source, "failureClass"),
1753
+ metrics: asRecord6(record.metrics, `${source}.metrics`),
1754
+ artifacts: asRecord6(record.artifacts, `${source}.artifacts`),
1755
+ ...verdict === void 0 ? {} : { verdict },
1756
+ ...behavioral === void 0 ? {} : { behavioral },
1757
+ ...behavioralMetrics === void 0 ? {} : { behavioralMetrics },
1758
+ ...executionEnvelope === void 0 ? {} : { executionEnvelope }
1759
+ };
1760
+ }
1761
+ function asRecord6(value, source) {
1762
+ if (isRecord2(value)) return value;
1763
+ throw new Error(`${source}: expected object`);
1764
+ }
1765
+ function isRecord2(value) {
1766
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1767
+ }
1768
+ function readString5(record, source, field) {
1769
+ const value = record[field];
1770
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string`);
1771
+ return value;
1772
+ }
1773
+ function readNullableString5(record, source, field) {
1774
+ const value = record[field];
1775
+ if (value === null) return null;
1776
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string or null`);
1777
+ return value;
1778
+ }
1779
+ function readNullableDigest2(record, source, field) {
1780
+ const value = readNullableString5(record, source, field);
1781
+ if (value !== null && !/^[0-9a-f]{64}$/u.test(value))
1782
+ throw new Error(`${source}.${field}: expected sha256 digest or null`);
1783
+ return value;
1784
+ }
1785
+ function readNumber2(record, source, field) {
1786
+ const value = record[field];
1787
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${source}.${field}: expected number`);
1788
+ return value;
1789
+ }
1790
+ function readBoolean2(record, source, field) {
1791
+ const value = record[field];
1792
+ if (typeof value !== "boolean") throw new Error(`${source}.${field}: expected boolean`);
1793
+ return value;
1794
+ }
1795
+ function readArray2(record, source, field) {
1796
+ const value = record[field];
1797
+ if (!Array.isArray(value)) throw new Error(`${source}.${field}: expected array`);
1798
+ return value;
1799
+ }
1800
+
1801
+ // src/domains/evidence/trust-status.ts
1802
+ init_esm_shims();
1803
+ var TRUST_STATUS_VERSION = 1;
1804
+ var TRUST_STATUS_MAX_ARTIFACT_REFERENCES = 16;
1805
+ var TRUST_STATUS_MAX_IDENTIFIER_LENGTH = 512;
1806
+ var TRUST_STATUS_AXES = [
1807
+ "artifactIntegrity",
1808
+ "validationGrounding",
1809
+ "independentReview",
1810
+ "contextProvenance",
1811
+ "autonomyEnforcement",
1812
+ "completionEvidence"
1813
+ ];
1814
+ var TRUST_STATUS_STATES = {
1815
+ artifactIntegrity: ["verified", "failed", "absent", "unknown", "not_applicable"],
1816
+ validationGrounding: ["validated", "failed", "ungrounded", "absent", "unknown", "not_applicable"],
1817
+ independentReview: ["passed", "failed", "inconclusive", "not_independent", "absent", "unknown", "not_applicable"],
1818
+ contextProvenance: ["recorded", "invalid", "absent", "unknown", "not_applicable"],
1819
+ autonomyEnforcement: ["enforced", "approximated", "bypassed", "absent", "unknown", "not_applicable"],
1820
+ completionEvidence: ["evidenced", "incomplete", "limited", "absent", "unknown", "not_applicable"]
1821
+ };
1822
+ var SELF_REPORTED_ARTIFACT_KINDS = /* @__PURE__ */ new Set([
1823
+ "finish_contract_evidence",
1824
+ "run_receipt"
1825
+ ]);
1826
+ var AXIS_STATES = {
1827
+ artifactIntegrity: new Set(TRUST_STATUS_STATES.artifactIntegrity),
1828
+ validationGrounding: new Set(TRUST_STATUS_STATES.validationGrounding),
1829
+ independentReview: new Set(TRUST_STATUS_STATES.independentReview),
1830
+ contextProvenance: new Set(TRUST_STATUS_STATES.contextProvenance),
1831
+ autonomyEnforcement: new Set(TRUST_STATUS_STATES.autonomyEnforcement),
1832
+ completionEvidence: new Set(TRUST_STATUS_STATES.completionEvidence)
1833
+ };
1834
+ var AXIS_SOURCES = {
1835
+ artifactIntegrity: /* @__PURE__ */ new Set(["receipt_integrity_verification", "compatibility"]),
1836
+ validationGrounding: /* @__PURE__ */ new Set(["run_receipt", "evidence_bundle", "compatibility"]),
1837
+ independentReview: /* @__PURE__ */ new Set(["gate_decision", "compatibility"]),
1838
+ contextProvenance: /* @__PURE__ */ new Set(["run_receipt", "evidence_bundle", "compatibility"]),
1839
+ autonomyEnforcement: /* @__PURE__ */ new Set(["run_receipt", "compatibility"]),
1840
+ completionEvidence: /* @__PURE__ */ new Set(["finish_contract", "compatibility"])
1841
+ };
1842
+ var SOURCE_AUTHORITIES = {
1843
+ receipt_integrity_verification: /* @__PURE__ */ new Set(["clio"]),
1844
+ run_receipt: /* @__PURE__ */ new Set(["clio", "validator", "runtime", "external_system", "unknown"]),
1845
+ gate_decision: /* @__PURE__ */ new Set(["clio", "reviewer", "operator", "unknown"]),
1846
+ evidence_bundle: /* @__PURE__ */ new Set(["clio"]),
1847
+ finish_contract: /* @__PURE__ */ new Set(["clio"]),
1848
+ compatibility: /* @__PURE__ */ new Set(["clio", "unknown"])
1849
+ };
1850
+ var ABSENCE_REASONS = /* @__PURE__ */ new Set([
1851
+ "not_recorded",
1852
+ "not_observed",
1853
+ "artifact_missing",
1854
+ "historical_format"
1855
+ ]);
1856
+ var SOURCE_KINDS = /* @__PURE__ */ new Set([
1857
+ "receipt_integrity_verification",
1858
+ "run_receipt",
1859
+ "gate_decision",
1860
+ "evidence_bundle",
1861
+ "finish_contract",
1862
+ "compatibility"
1863
+ ]);
1864
+ var AUTHORITY_KINDS = /* @__PURE__ */ new Set([
1865
+ "clio",
1866
+ "validator",
1867
+ "reviewer",
1868
+ "operator",
1869
+ "runtime",
1870
+ "external_system",
1871
+ "unknown"
1872
+ ]);
1873
+ var ARTIFACT_KINDS = /* @__PURE__ */ new Set([
1874
+ "run_receipt",
1875
+ "validation_result",
1876
+ "gate_decision",
1877
+ "briefing",
1878
+ "project_context",
1879
+ "autonomy_policy",
1880
+ "finish_contract_evidence",
1881
+ "evidence_bundle",
1882
+ "session_entry"
1883
+ ]);
1884
+ function isRecord3(value) {
1885
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1886
+ }
1887
+ function hasExactKeys(value, keys) {
1888
+ const expected = new Set(keys);
1889
+ return Object.keys(value).length === expected.size && Object.keys(value).every((key) => expected.has(key));
1890
+ }
1891
+ function isTrustStatusIdentifier(value) {
1892
+ if (typeof value !== "string" || value.trim().length === 0 || value.length > TRUST_STATUS_MAX_IDENTIFIER_LENGTH) {
1893
+ return false;
1894
+ }
1895
+ for (const character of value) {
1896
+ const codePoint = character.codePointAt(0);
1897
+ if (codePoint !== void 0 && (codePoint < 32 || codePoint === 127)) return false;
1898
+ }
1899
+ return true;
1900
+ }
1901
+ function compareArtifactReferences(left, right) {
1902
+ const leftKey = `${left.kind}\0${left.id}\0${left.digest?.value ?? ""}`;
1903
+ const rightKey = `${right.kind}\0${right.id}\0${right.digest?.value ?? ""}`;
1904
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
1905
+ }
1906
+ function normalizeArtifactReference(value, path) {
1907
+ if (!isRecord3(value)) throw new Error(`${path} must be an object`);
1908
+ if (!hasExactKeys(value, value.digest === void 0 ? ["kind", "id"] : ["kind", "id", "digest"])) {
1909
+ throw new Error(`${path} has unknown or missing fields`);
1910
+ }
1911
+ if (typeof value.kind !== "string" || !ARTIFACT_KINDS.has(value.kind)) {
1912
+ throw new Error(`${path}.kind is invalid`);
1913
+ }
1914
+ if (!isTrustStatusIdentifier(value.id)) throw new Error(`${path}.id is invalid`);
1915
+ const reference = { kind: value.kind, id: value.id };
1916
+ if (value.digest !== void 0) {
1917
+ if (!isRecord3(value.digest) || !hasExactKeys(value.digest, ["algorithm", "value"]) || value.digest.algorithm !== "sha256" || typeof value.digest.value !== "string" || !/^[a-f0-9]{64}$/u.test(value.digest.value)) {
1918
+ throw new Error(`${path}.digest is invalid`);
1919
+ }
1920
+ reference.digest = { algorithm: "sha256", value: value.digest.value };
1921
+ }
1922
+ return reference;
1923
+ }
1924
+ function normalizeAttributedStatus(axis, value) {
1925
+ if (!hasExactKeys(value, ["state", "source", "authority", "artifacts"])) {
1926
+ throw new Error(`${axis} has unknown or missing fields`);
1927
+ }
1928
+ if (!isRecord3(value.source) || !hasExactKeys(value.source, ["kind", "id"])) {
1929
+ throw new Error(`${axis}.source is invalid`);
1930
+ }
1931
+ if (typeof value.source.kind !== "string" || !SOURCE_KINDS.has(value.source.kind) || !AXIS_SOURCES[axis].has(value.source.kind) || !isTrustStatusIdentifier(value.source.id)) {
1932
+ throw new Error(`${axis}.source is invalid`);
1933
+ }
1934
+ if (!isRecord3(value.authority) || !hasExactKeys(value.authority, ["kind", "id"])) {
1935
+ throw new Error(`${axis}.authority is invalid`);
1936
+ }
1937
+ if (typeof value.authority.kind !== "string" || !AUTHORITY_KINDS.has(value.authority.kind) || !SOURCE_AUTHORITIES[value.source.kind].has(
1938
+ value.authority.kind
1939
+ ) || !isTrustStatusIdentifier(value.authority.id)) {
1940
+ throw new Error(`${axis}.authority is invalid`);
1941
+ }
1942
+ if (value.source.kind === "compatibility" && value.state !== "unknown" && value.state !== "not_applicable") {
1943
+ throw new Error(`${axis} compatibility source cannot establish ${value.state}`);
1944
+ }
1945
+ if (!Array.isArray(value.artifacts) || value.artifacts.length > TRUST_STATUS_MAX_ARTIFACT_REFERENCES) {
1946
+ throw new Error(`${axis}.artifacts exceeds the bounded reference list`);
1947
+ }
1948
+ const artifacts = value.artifacts.map(
1949
+ (entry, index) => normalizeArtifactReference(entry, `${axis}.artifacts[${index}]`)
1950
+ );
1951
+ artifacts.sort(compareArtifactReferences);
1952
+ for (let index = 1; index < artifacts.length; index += 1) {
1953
+ if (compareArtifactReferences(
1954
+ artifacts[index - 1],
1955
+ artifacts[index]
1956
+ ) === 0) {
1957
+ throw new Error(`${axis}.artifacts contains a duplicate reference`);
1958
+ }
1959
+ }
1960
+ return {
1961
+ state: value.state,
1962
+ source: { kind: value.source.kind, id: value.source.id },
1963
+ authority: { kind: value.authority.kind, id: value.authority.id },
1964
+ artifacts
1965
+ };
1966
+ }
1967
+ function normalizeAxis(axis, value) {
1968
+ if (!isRecord3(value) || typeof value.state !== "string" || !AXIS_STATES[axis].has(value.state)) {
1969
+ throw new Error(`${axis}.state is invalid`);
1970
+ }
1971
+ if (value.state === "absent") {
1972
+ if (!hasExactKeys(value, ["state", "reason"]) || typeof value.reason !== "string" || !ABSENCE_REASONS.has(value.reason)) {
1973
+ throw new Error(`${axis} absent state is invalid`);
1974
+ }
1975
+ return { state: "absent", reason: value.reason };
1976
+ }
1977
+ return normalizeAttributedStatus(axis, value);
1978
+ }
1979
+ function normalizeTrustStatus(value) {
1980
+ if (!isRecord3(value) || !hasExactKeys(value, ["version", ...TRUST_STATUS_AXES])) {
1981
+ throw new Error("trust status has unknown or missing fields");
1982
+ }
1983
+ if (value.version !== TRUST_STATUS_VERSION) throw new Error("trust status version is invalid");
1984
+ return {
1985
+ version: TRUST_STATUS_VERSION,
1986
+ artifactIntegrity: normalizeAxis("artifactIntegrity", value.artifactIntegrity),
1987
+ validationGrounding: normalizeAxis("validationGrounding", value.validationGrounding),
1988
+ independentReview: normalizeAxis("independentReview", value.independentReview),
1989
+ contextProvenance: normalizeAxis("contextProvenance", value.contextProvenance),
1990
+ autonomyEnforcement: normalizeAxis("autonomyEnforcement", value.autonomyEnforcement),
1991
+ completionEvidence: normalizeAxis("completionEvidence", value.completionEvidence)
1992
+ };
1993
+ }
1994
+ function absentTrustStatus(reason) {
1995
+ return { state: "absent", reason };
1996
+ }
1997
+ function composeTrustStatus(...projections) {
1998
+ const axes = {
1999
+ artifactIntegrity: absentTrustStatus("not_recorded"),
2000
+ validationGrounding: absentTrustStatus("not_recorded"),
2001
+ independentReview: absentTrustStatus("not_recorded"),
2002
+ contextProvenance: absentTrustStatus("not_recorded"),
2003
+ autonomyEnforcement: absentTrustStatus("not_recorded"),
2004
+ completionEvidence: absentTrustStatus("not_recorded")
2005
+ };
2006
+ for (const projection of projections) {
2007
+ if (projection.artifactIntegrity !== void 0) axes.artifactIntegrity = projection.artifactIntegrity;
2008
+ if (projection.validationGrounding !== void 0) axes.validationGrounding = projection.validationGrounding;
2009
+ if (projection.independentReview !== void 0) axes.independentReview = projection.independentReview;
2010
+ if (projection.contextProvenance !== void 0) axes.contextProvenance = projection.contextProvenance;
2011
+ if (projection.autonomyEnforcement !== void 0) axes.autonomyEnforcement = projection.autonomyEnforcement;
2012
+ if (projection.completionEvidence !== void 0) axes.completionEvidence = projection.completionEvidence;
2013
+ }
2014
+ return normalizeTrustStatus({ version: TRUST_STATUS_VERSION, ...axes });
2015
+ }
2016
+ function sha256Reference(kind, id, digest) {
2017
+ const reference = { kind, id };
2018
+ if (digest !== void 0 && /^[a-f0-9]{64}$/u.test(digest)) {
2019
+ reference.digest = { algorithm: "sha256", value: digest };
2020
+ }
2021
+ return reference;
2022
+ }
2023
+ function receiptReference(receipt) {
2024
+ return sha256Reference("run_receipt", receipt.runId, receipt.integrity?.digest);
2025
+ }
2026
+ function attributed(state, source, authority, artifacts) {
2027
+ return { state, source, authority, artifacts: [...artifacts].sort(compareArtifactReferences) };
2028
+ }
2029
+ function receiptSource(receipt) {
2030
+ return { kind: "run_receipt", id: receipt.runId };
2031
+ }
2032
+ function compatibilitySource(receipt, field) {
2033
+ return { kind: "compatibility", id: `run_receipt:${receipt.runId}:${field}` };
2034
+ }
2035
+ var DISPATCH_AUTHORITY = { kind: "clio", id: "dispatch" };
2036
+ var COMPATIBILITY_AUTHORITY = { kind: "unknown", id: "historical-persisted-format" };
2037
+ function retiredReceiptIntegrity(integrity) {
2038
+ if (!isRecord3(integrity)) return null;
2039
+ const version = integrity.version;
2040
+ if (typeof version !== "number" || !Number.isInteger(version) || version < 1) return null;
2041
+ if (version >= RUN_RECEIPT_INTEGRITY_VERSION) return null;
2042
+ return { receiptVersion: version, supportedVersion: RUN_RECEIPT_INTEGRITY_VERSION };
2043
+ }
2044
+ function retiredReceiptIntegrityReason(retired) {
2045
+ return `receipt integrity v${retired.receiptVersion} is retired; this build verifies v${retired.supportedVersion}; the receipt is not read as evidence`;
2046
+ }
2047
+ function verifyReceiptIntegrityOutcome(receipt, envelope) {
2048
+ const retired = retiredReceiptIntegrity(receipt.integrity);
2049
+ if (retired !== null) return { ok: false, reason: retiredReceiptIntegrityReason(retired), retired };
2050
+ return verifyReceiptIntegrity(receipt, envelope);
2051
+ }
2052
+ var RETIRED_INTEGRITY_SOURCE = /:integrity-v(\d+)-retired$/u;
2053
+ function retiredIntegritySourceId(runId, receiptVersion) {
2054
+ return `run_receipt:${runId}:integrity-v${receiptVersion}-retired`;
2055
+ }
2056
+ function retiredIntegrityVersionOf(status) {
2057
+ if (status.state !== "unknown" || status.source.kind !== "compatibility") return null;
2058
+ const match = RETIRED_INTEGRITY_SOURCE.exec(status.source.id);
2059
+ return match === null ? null : Number(match[1]);
2060
+ }
2061
+ function adaptReceiptIntegrityStatus(receipt, verification) {
2062
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
2063
+ const artifacts = [receiptReference(receipt)];
2064
+ if (verification !== void 0 && !verification.ok && verification.retired !== void 0) {
2065
+ return attributed(
2066
+ "unknown",
2067
+ { kind: "compatibility", id: retiredIntegritySourceId(receipt.runId, verification.retired.receiptVersion) },
2068
+ COMPATIBILITY_AUTHORITY,
2069
+ artifacts
2070
+ );
2071
+ }
2072
+ if (verification === void 0 || verification.ok && receipt.integrity === void 0) {
2073
+ return attributed(
2074
+ "unknown",
2075
+ {
2076
+ kind: "compatibility",
2077
+ id: `run_receipt:${receipt.runId}:${receipt.integrity === void 0 ? "integrity-missing" : "integrity-unchecked"}`
2078
+ },
2079
+ COMPATIBILITY_AUTHORITY,
2080
+ artifacts
2081
+ );
2082
+ }
2083
+ return attributed(
2084
+ verification.ok ? "verified" : "failed",
2085
+ { kind: "receipt_integrity_verification", id: receipt.runId },
2086
+ { kind: "clio", id: "receipt-integrity" },
2087
+ artifacts
2088
+ );
2089
+ }
2090
+ function validationArtifacts(receipt) {
2091
+ const artifacts = [receiptReference(receipt)];
2092
+ for (const fact of receipt.quality?.typedValidations ?? []) {
2093
+ artifacts.push(sha256Reference("validation_result", fact.sourceId, fact.validatorDigest));
2094
+ }
2095
+ const resultContract = receipt.quality?.resultContract;
2096
+ if (resultContract !== null && resultContract !== void 0) {
2097
+ artifacts.push(sha256Reference("validation_result", resultContract.sourceId, resultContract.validatorDigest));
2098
+ }
2099
+ return uniqueBoundedReferences(artifacts);
2100
+ }
2101
+ function qualityHasFailure(quality) {
2102
+ if (quality === void 0) return false;
2103
+ if (quality.typedValidations.some((fact) => !fact.passed)) return true;
2104
+ return quality.resultContract?.conformance === "fail" || quality.resultContract?.quality === "fail";
2105
+ }
2106
+ function qualityHasValidation(quality) {
2107
+ if (quality === void 0) return false;
2108
+ if (quality.typedValidations.some((fact) => fact.passed)) return true;
2109
+ return quality.resultContract?.quality === "pass";
2110
+ }
2111
+ function verificationStatus(verification, receipt, artifacts) {
2112
+ if (verification.state === "verified") {
2113
+ return attributed("validated", receiptSource(receipt), { kind: "validator", id: verification.basis }, artifacts);
2114
+ }
2115
+ if (verification.state === "unverified") return absentTrustStatus("not_observed");
2116
+ if (verification.state === "not_applicable") {
2117
+ return attributed("not_applicable", receiptSource(receipt), DISPATCH_AUTHORITY, artifacts);
2118
+ }
2119
+ return attributed(
2120
+ "unknown",
2121
+ receiptSource(receipt),
2122
+ verification.basis === "acp-external-unobserved" ? { kind: "external_system", id: "acp-delegation" } : COMPATIBILITY_AUTHORITY,
2123
+ artifacts
2124
+ );
2125
+ }
2126
+ function adaptRunReceiptValidationStatus(receipt) {
2127
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
2128
+ const artifacts = validationArtifacts(receipt);
2129
+ if (receipt.hostVerification?.status === "rejected") {
2130
+ return attributed("failed", receiptSource(receipt), { kind: "validator", id: "host-verification" }, artifacts);
2131
+ }
2132
+ if (receipt.hostVerification?.status === "verified") {
2133
+ return attributed("validated", receiptSource(receipt), { kind: "validator", id: "host-verification" }, artifacts);
2134
+ }
2135
+ if (qualityHasFailure(receipt.quality)) {
2136
+ return attributed("failed", receiptSource(receipt), { kind: "validator", id: "receipt-quality" }, artifacts);
2137
+ }
2138
+ if ((receipt.validationGrounding?.ungrounded.length ?? 0) > 0 || receipt.validationGrounding !== void 0 && receipt.validationGrounding.claimed > receipt.validationGrounding.grounded) {
2139
+ return attributed("ungrounded", receiptSource(receipt), { kind: "validator", id: "command-grounding" }, artifacts);
2140
+ }
2141
+ if (qualityHasValidation(receipt.quality)) {
2142
+ return attributed("validated", receiptSource(receipt), { kind: "validator", id: "receipt-quality" }, artifacts);
2143
+ }
2144
+ if (receipt.verification !== void 0) {
2145
+ return verificationStatus(receipt.verification, receipt, artifacts);
2146
+ }
2147
+ return attributed("unknown", compatibilitySource(receipt, "verification"), COMPATIBILITY_AUTHORITY, artifacts);
2148
+ }
2149
+ function validBriefing(briefing) {
2150
+ return Number.isSafeInteger(briefing.bytes) && briefing.bytes >= 0 && /^[a-f0-9]{64}$/u.test(briefing.contentHash);
2151
+ }
2152
+ function validBoundedProjectContext(context) {
2153
+ return context.tier === "bounded" && Number.isSafeInteger(context.chars) && (context.chars ?? -1) >= 0 && typeof context.contentHash === "string" && /^[a-f0-9]{64}$/u.test(context.contentHash);
2154
+ }
2155
+ var NONE_TIER_SECTIONS = ["workspace-root"];
2156
+ function validNoneTierProjectContext(context) {
2157
+ return context.tier === "none" && context.sections !== void 0 && context.sections.length === NONE_TIER_SECTIONS.length && context.sections.every((section) => NONE_TIER_SECTIONS.includes(section)) && Number.isSafeInteger(context.chars) && (context.chars ?? -1) >= 0 && typeof context.contentHash === "string" && /^[a-f0-9]{64}$/u.test(context.contentHash);
2158
+ }
2159
+ function recordedProjectContextHash(context) {
2160
+ if (context === void 0) return void 0;
2161
+ if (context.tier === "bounded") return validBoundedProjectContext(context) ? context.contentHash : void 0;
2162
+ return validNoneTierProjectContext(context) ? context.contentHash : void 0;
2163
+ }
2164
+ function contextArtifacts(receipt) {
2165
+ const artifacts = [receiptReference(receipt)];
2166
+ if (receipt.briefing !== void 0 && validBriefing(receipt.briefing)) {
2167
+ artifacts.push(sha256Reference("briefing", `${receipt.runId}:briefing`, receipt.briefing.contentHash));
2168
+ }
2169
+ const recordedHash = recordedProjectContextHash(receipt.projectContext);
2170
+ if (recordedHash !== void 0) {
2171
+ artifacts.push(sha256Reference("project_context", `${receipt.runId}:project-context`, recordedHash));
2172
+ }
2173
+ return uniqueBoundedReferences(artifacts);
2174
+ }
2175
+ function adaptRunReceiptContextStatus(receipt) {
2176
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
2177
+ const artifacts = contextArtifacts(receipt);
2178
+ const source = receiptSource(receipt);
2179
+ const briefingInvalid = receipt.briefing !== void 0 && !validBriefing(receipt.briefing);
2180
+ if (briefingInvalid) return attributed("invalid", source, DISPATCH_AUTHORITY, artifacts);
2181
+ const context = receipt.projectContext;
2182
+ if (context === void 0) {
2183
+ if (receipt.briefing !== void 0) return attributed("recorded", source, DISPATCH_AUTHORITY, artifacts);
2184
+ return attributed("unknown", compatibilitySource(receipt, "projectContext"), COMPATIBILITY_AUTHORITY, artifacts);
2185
+ }
2186
+ if (context.tier === "none") {
2187
+ const bare = context.chars === void 0 && context.contentHash === void 0 && context.sections === void 0;
2188
+ if (bare) {
2189
+ return receipt.briefing === void 0 ? attributed("not_applicable", source, DISPATCH_AUTHORITY, artifacts) : attributed("recorded", source, DISPATCH_AUTHORITY, artifacts);
2190
+ }
2191
+ return attributed(
2192
+ validNoneTierProjectContext(context) ? "recorded" : "invalid",
2193
+ source,
2194
+ DISPATCH_AUTHORITY,
2195
+ artifacts
2196
+ );
2197
+ }
2198
+ return attributed(validBoundedProjectContext(context) ? "recorded" : "invalid", source, DISPATCH_AUTHORITY, artifacts);
2199
+ }
2200
+ function adaptRunReceiptAutonomyStatus(receipt) {
2201
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
2202
+ const enforcement = receipt.autonomyEnforcement;
2203
+ const artifacts = [receiptReference(receipt)];
2204
+ if (enforcement === void 0) {
2205
+ return attributed("unknown", compatibilitySource(receipt, "autonomyEnforcement"), COMPATIBILITY_AUTHORITY, artifacts);
2206
+ }
2207
+ artifacts.push({ kind: "autonomy_policy", id: `${receipt.runId}:${enforcement.autonomy}` });
2208
+ const authority = enforcement.grade === "mediated" ? { kind: "clio", id: "safety-autonomy" } : { kind: "runtime", id: enforcement.externalMode ?? "external-runtime" };
2209
+ const state = enforcement.dangerousBypass === true || enforcement.grade === "bypassed" ? "bypassed" : enforcement.grade === "approximated" ? "approximated" : "enforced";
2210
+ return attributed(state, receiptSource(receipt), authority, artifacts);
2211
+ }
2212
+ function receiptClaimsAreAuthenticated(receipt, integrity) {
2213
+ return receipt?.integrity !== void 0 && integrity?.ok === true;
2214
+ }
2215
+ function unauthenticatedReceiptProjection(receipt, integrity) {
2216
+ if (receipt === null || receipt === void 0) {
2217
+ return {
2218
+ validationGrounding: absentTrustStatus("artifact_missing"),
2219
+ contextProvenance: absentTrustStatus("artifact_missing"),
2220
+ autonomyEnforcement: absentTrustStatus("artifact_missing")
2221
+ };
2222
+ }
2223
+ if (receipt.integrity === void 0) {
2224
+ const artifacts = [receiptReference(receipt)];
2225
+ return {
2226
+ validationGrounding: attributed(
2227
+ "unknown",
2228
+ compatibilitySource(receipt, "canonical-projection"),
2229
+ COMPATIBILITY_AUTHORITY,
2230
+ artifacts
2231
+ ),
2232
+ contextProvenance: attributed(
2233
+ "unknown",
2234
+ compatibilitySource(receipt, "canonical-projection"),
2235
+ COMPATIBILITY_AUTHORITY,
2236
+ artifacts
2237
+ ),
2238
+ autonomyEnforcement: attributed(
2239
+ "unknown",
2240
+ compatibilitySource(receipt, "canonical-projection"),
2241
+ COMPATIBILITY_AUTHORITY,
2242
+ artifacts
2243
+ )
2244
+ };
2245
+ }
2246
+ if (integrity !== void 0 && !integrity.ok && integrity.retired !== void 0) {
2247
+ return {
2248
+ validationGrounding: absentTrustStatus("historical_format"),
2249
+ contextProvenance: absentTrustStatus("historical_format"),
2250
+ autonomyEnforcement: absentTrustStatus("historical_format")
2251
+ };
2252
+ }
2253
+ return {
2254
+ validationGrounding: absentTrustStatus("not_observed"),
2255
+ contextProvenance: absentTrustStatus("not_observed"),
2256
+ autonomyEnforcement: absentTrustStatus("not_observed")
2257
+ };
2258
+ }
2259
+ function adaptRunReceiptTrustStatus(receipt, options = {}) {
2260
+ const authenticated = receiptClaimsAreAuthenticated(receipt, options.integrity);
2261
+ const receiptProjection = authenticated ? {
2262
+ validationGrounding: adaptRunReceiptValidationStatus(receipt),
2263
+ contextProvenance: adaptRunReceiptContextStatus(receipt),
2264
+ autonomyEnforcement: adaptRunReceiptAutonomyStatus(receipt)
2265
+ } : unauthenticatedReceiptProjection(receipt, options.integrity);
2266
+ return composeTrustStatus({
2267
+ artifactIntegrity: adaptReceiptIntegrityStatus(receipt, options.integrity),
2268
+ ...receiptProjection,
2269
+ independentReview: absentTrustStatus(receipt === null || receipt === void 0 ? "artifact_missing" : "not_recorded"),
2270
+ completionEvidence: absentTrustStatus(
2271
+ receipt === null || receipt === void 0 ? "artifact_missing" : "not_recorded"
2272
+ )
2273
+ });
2274
+ }
2275
+ function inspectRunReceiptTrustStatus(receipt, envelope) {
2276
+ let integrity;
2277
+ if (receipt === null || receipt === void 0) {
2278
+ integrity = { ok: false, reason: "receipt unavailable" };
2279
+ } else if (envelope === null || envelope === void 0) {
2280
+ integrity = { ok: false, reason: "run ledger envelope unavailable" };
2281
+ } else {
2282
+ try {
2283
+ integrity = verifyReceiptIntegrityOutcome(receipt, envelope);
2284
+ } catch (error) {
2285
+ integrity = {
2286
+ ok: false,
2287
+ reason: `receipt invalid: ${error instanceof Error ? error.message : String(error)}`
2288
+ };
2289
+ }
2290
+ }
2291
+ return {
2292
+ integrity,
2293
+ status: adaptRunReceiptTrustStatus(receipt, { integrity })
2294
+ };
2295
+ }
2296
+ function gateReference(artifact) {
2297
+ return sha256Reference("gate_decision", artifact.id, artifact.integrity.digest);
2298
+ }
2299
+ function gateAuthority(artifact) {
2300
+ if (artifact.outcome === "operator-confirmed") return { kind: "operator", id: "gate-confirmation" };
2301
+ if (artifact.outcome === "full-auto-applied") return { kind: "clio", id: "full-auto-gate-policy" };
2302
+ return { kind: "reviewer", id: artifact.decider?.runId ?? "unavailable-decider" };
2303
+ }
2304
+ function adaptGateDecisionReviewStatus(artifact, subjectRunId, verification) {
2305
+ if (artifact === null || artifact === void 0) return absentTrustStatus("artifact_missing");
2306
+ const source = { kind: "gate_decision", id: artifact.id };
2307
+ const artifacts = [gateReference(artifact)];
2308
+ const authority = gateAuthority(artifact);
2309
+ if (!artifact.subjects.some((subject) => subject.runId === subjectRunId)) return absentTrustStatus("not_recorded");
2310
+ if (verification === void 0 || !verification.ok) {
2311
+ return attributed(
2312
+ "unknown",
2313
+ source,
2314
+ verification === void 0 ? COMPATIBILITY_AUTHORITY : { kind: "unknown", id: "unauthenticated-gate-artifact" },
2315
+ artifacts
2316
+ );
2317
+ }
2318
+ if (artifact.decider === void 0 || artifact.correlation === void 0) {
2319
+ if (artifact.outcome === "operator-confirmed" || artifact.outcome === "full-auto-applied") {
2320
+ return attributed("not_applicable", source, authority, artifacts);
2321
+ }
2322
+ return attributed("inconclusive", source, authority, artifacts);
2323
+ }
2324
+ if (!artifact.correlation.independent) return attributed("not_independent", source, authority, artifacts);
2325
+ if (artifact.outcome === "pass") return attributed("passed", source, authority, artifacts);
2326
+ if (artifact.outcome === "fail") return attributed("failed", source, authority, artifacts);
2327
+ if (artifact.outcome === "winner") {
2328
+ return attributed(
2329
+ artifact.winner?.subject.runId === subjectRunId ? "passed" : "failed",
2330
+ source,
2331
+ authority,
2332
+ artifacts
2333
+ );
2334
+ }
2335
+ return attributed("inconclusive", source, authority, artifacts);
2336
+ }
2337
+ function adaptGroundedEvidenceValidationStatus(input) {
2338
+ const observed = (input.artifacts ?? []).filter((artifact) => !SELF_REPORTED_ARTIFACT_KINDS.has(artifact.kind));
2339
+ if (observed.length === 0) return absentTrustStatus("not_observed");
2340
+ return attributed(
2341
+ "validated",
2342
+ { kind: "evidence_bundle", id: `${input.evidenceId}:${input.runId}` },
2343
+ { kind: "clio", id: "evidence-grounding" },
2344
+ uniqueBoundedReferences([{ kind: "evidence_bundle", id: input.evidenceId }, ...observed])
2345
+ );
2346
+ }
2347
+ function uniqueBoundedReferences(references) {
2348
+ const sorted = [...references].sort(compareArtifactReferences);
2349
+ const unique = sorted.filter(
2350
+ (reference, index) => index === 0 || compareArtifactReferences(sorted[index - 1], reference) !== 0
2351
+ );
2352
+ return unique.slice(0, TRUST_STATUS_MAX_ARTIFACT_REFERENCES);
2353
+ }
2354
+
2355
+ // src/domains/evidence/trust-projection.ts
2356
+ init_esm_shims();
2357
+ var TRUST_SUMMARY_VERSION = 1;
2358
+ var TRUST_SUMMARY_MAX_REFS = 8;
2359
+ var TRUST_STATE_WORDS = {
2360
+ artifactIntegrity: {
2361
+ verified: "sealed",
2362
+ failed: "seal broken",
2363
+ absent: "no receipt",
2364
+ unknown: "seal unchecked",
2365
+ not_applicable: "seal not applicable"
2366
+ },
2367
+ validationGrounding: {
2368
+ validated: "grounded",
2369
+ failed: "validation failed",
2370
+ ungrounded: "inferred: validation claimed, none observed",
2371
+ absent: "no validation observed",
2372
+ unknown: "validation unknown",
2373
+ not_applicable: "validation not applicable"
2374
+ },
2375
+ independentReview: {
2376
+ passed: "independently reviewed: pass",
2377
+ failed: "independently reviewed: fail",
2378
+ inconclusive: "independent review inconclusive",
2379
+ not_independent: "review not independent",
2380
+ absent: "not independently reviewed",
2381
+ unknown: "independent review unknown",
2382
+ not_applicable: "independent review not applicable"
2383
+ },
2384
+ contextProvenance: {
2385
+ recorded: "context recorded",
2386
+ invalid: "context record invalid",
2387
+ absent: "context not recorded",
2388
+ unknown: "context unknown",
2389
+ not_applicable: "context not applicable"
2390
+ },
2391
+ autonomyEnforcement: {
2392
+ enforced: "mediated",
2393
+ approximated: "approximated",
2394
+ bypassed: "bypassed",
2395
+ absent: "autonomy not recorded",
2396
+ unknown: "autonomy unknown",
2397
+ not_applicable: "autonomy not applicable"
2398
+ },
2399
+ completionEvidence: {
2400
+ evidenced: "completion evidenced",
2401
+ incomplete: "completion unevidenced",
2402
+ limited: "completion limited",
2403
+ absent: "completion not recorded",
2404
+ unknown: "completion unknown",
2405
+ not_applicable: "completion not applicable"
2406
+ }
2407
+ };
2408
+ function trustStateWord(axis, state) {
2409
+ const words = TRUST_STATE_WORDS[axis];
2410
+ return words[state] ?? words.unknown ?? "unknown";
2411
+ }
2412
+ function authorityOf(status, axis) {
2413
+ const entry = status[axis];
2414
+ return entry.state === "absent" ? null : `${entry.authority.kind}:${entry.authority.id}`;
2415
+ }
2416
+ function integrityClause(status) {
2417
+ const retired = retiredIntegrityVersionOf(status.artifactIntegrity);
2418
+ if (retired !== null) return `seal v${retired} retired (this build verifies v${RUN_RECEIPT_INTEGRITY_VERSION})`;
2419
+ return trustStateWord("artifactIntegrity", status.artifactIntegrity.state);
2420
+ }
2421
+ function validationClause(status) {
2422
+ const entry = status.validationGrounding;
2423
+ const word = trustStateWord("validationGrounding", entry.state);
2424
+ if (entry.state === "absent") return word;
2425
+ if (entry.state === "validated" || entry.state === "failed") return `${word} by ${entry.authority.id}`;
2426
+ if (entry.state === "unknown" && entry.authority.kind !== "unknown") return `${word} (${entry.authority.id})`;
2427
+ return word;
2428
+ }
2429
+ function autonomyClause(status) {
2430
+ const entry = status.autonomyEnforcement;
2431
+ const word = trustStateWord("autonomyEnforcement", entry.state);
2432
+ if (entry.state !== "approximated" && entry.state !== "bypassed") return word;
2433
+ return `${word} (${entry.authority.id})`;
2434
+ }
2435
+ function formatTrustSummary(status) {
2436
+ return [
2437
+ integrityClause(status),
2438
+ validationClause(status),
2439
+ trustStateWord("independentReview", status.independentReview.state),
2440
+ autonomyClause(status),
2441
+ trustStateWord("contextProvenance", status.contextProvenance.state),
2442
+ trustStateWord("completionEvidence", status.completionEvidence.state)
2443
+ ].join("; ");
2444
+ }
2445
+ function formatTrustSummaryLine(status) {
2446
+ return `trust v${TRUST_SUMMARY_VERSION}: ${trustVerdict(status)}; ${formatTrustSummary(status)}`;
2447
+ }
2448
+ function formatTrustAxes(status) {
2449
+ return [`trust_status=v${status.version}`, ...TRUST_STATUS_AXES.map((axis) => `${axis}:${status[axis].state}`)].join(
2450
+ " "
2451
+ );
2452
+ }
2453
+ function isUnanswered(status, axis) {
2454
+ const state = status[axis].state;
2455
+ return state === "absent" || state === "unknown";
2456
+ }
2457
+ function trustVerdict(status) {
2458
+ const integrity = status.artifactIntegrity.state;
2459
+ const validation = status.validationGrounding.state;
2460
+ const review = status.independentReview.state;
2461
+ const autonomy = status.autonomyEnforcement.state;
2462
+ if (integrity === "failed" || autonomy === "bypassed" || validation === "failed" || validation === "ungrounded" || review === "failed" || review === "not_independent" || status.contextProvenance.state === "invalid") {
2463
+ return "compromised";
2464
+ }
2465
+ if (integrity !== "verified") return "unknown";
2466
+ if (review === "passed") return "reviewed";
2467
+ if (validation === "validated") return "grounded";
2468
+ return "unverified";
2469
+ }
2470
+ function claimantOf(status) {
2471
+ const state = status.validationGrounding.state;
2472
+ if (state === "absent" || state === "ungrounded") return "worker";
2473
+ return authorityOf(status, "validationGrounding") ?? "worker";
2474
+ }
2475
+ function referenceKey(reference) {
2476
+ return `${reference.kind}:${reference.id}`;
2477
+ }
2478
+ function trustSummaryReferences(status) {
2479
+ const keys = /* @__PURE__ */ new Set();
2480
+ for (const axis of TRUST_STATUS_AXES) {
2481
+ const entry = status[axis];
2482
+ if (entry.state === "absent") continue;
2483
+ for (const reference of entry.artifacts) keys.add(referenceKey(reference));
2484
+ }
2485
+ return [...keys].sort().slice(0, TRUST_SUMMARY_MAX_REFS);
2486
+ }
2487
+ function summarizeTrustStatus(status) {
2488
+ const axes = Object.fromEntries(TRUST_STATUS_AXES.map((axis) => [axis, status[axis].state]));
2489
+ return {
2490
+ version: TRUST_SUMMARY_VERSION,
2491
+ verdict: trustVerdict(status),
2492
+ text: formatTrustSummary(status),
2493
+ axes,
2494
+ claimant: claimantOf(status),
2495
+ unknown: TRUST_STATUS_AXES.filter((axis) => isUnanswered(status, axis)),
2496
+ refs: trustSummaryReferences(status)
2497
+ };
2498
+ }
2499
+
2500
+ // src/domains/eval/provenance.ts
2501
+ init_esm_shims();
2502
+ import { spawnSync } from "node:child_process";
2503
+ function evalClioProvenance(options = {}) {
2504
+ return {
2505
+ version: readClioVersion(),
2506
+ commit: options.commit === void 0 ? currentClioCommit() : options.commit,
2507
+ entry: options.entry ?? process.argv[1] ?? "unknown"
2508
+ };
2509
+ }
2510
+ function evalEnvironmentProvenance() {
2511
+ return {
2512
+ platform: `${process.platform}-${process.arch}`,
2513
+ node: process.version
2514
+ };
2515
+ }
2516
+ async function evalServingConfiguration(targets, observations) {
2517
+ const targetId = targets.length === 1 ? targets[0]?.id ?? "unknown" : "multiple";
2518
+ const configured = configuredTarget(targetId);
2519
+ const target = targets.length === 1 ? targets[0] : void 0;
2520
+ const runtimeId = consensus(observations.map((entry) => entry.runtimeId)) ?? configured?.runtime ?? null;
2521
+ const modelId = consensus(observations.map((entry) => entry.modelId)) ?? target?.model ?? configured?.defaultModel ?? null;
2522
+ const props = configured?.url === void 0 ? null : await readServingProps(configured.url, modelId);
2523
+ return {
2524
+ targetId,
2525
+ runtimeId,
2526
+ modelId,
2527
+ serverBuild: props?.serverBuild ?? null,
2528
+ total_slots: props?.totalSlots ?? null,
2529
+ thinkingLevel: consensus(observations.map((entry) => entry.thinkingLevel)) ?? target?.thinking ?? null,
2530
+ compiledPromptHash: consensus(observations.map((entry) => entry.compiledPromptHash))
2531
+ };
2532
+ }
2533
+ function evalServingObservationFrom(target, receipt, compiledPromptHashes) {
2534
+ const compiledPromptHash = receipt?.staticCompositionHash ?? receipt?.compiledPromptHash ?? consensus(compiledPromptHashes);
2535
+ return {
2536
+ targetId: receipt?.targetId ?? target.id,
2537
+ runtimeId: receipt?.runtimeId ?? null,
2538
+ modelId: receipt?.wireModelId ?? target.model ?? null,
2539
+ thinkingLevel: receipt?.runtimeResolution?.effectiveThinkingLevel ?? target.thinking ?? null,
2540
+ compiledPromptHash
2541
+ };
2542
+ }
2543
+ function currentClioCommit() {
2544
+ const result = spawnSync("git", ["rev-parse", "HEAD"], {
2545
+ cwd: resolvePackageRoot(),
2546
+ encoding: "utf8",
2547
+ stdio: ["ignore", "pipe", "ignore"],
2548
+ timeout: 1e3
2549
+ });
2550
+ if (result.status !== 0 || typeof result.stdout !== "string") return null;
2551
+ const value = result.stdout.trim();
2552
+ return value.length > 0 ? value : null;
2553
+ }
2554
+ function configuredTarget(targetId) {
2555
+ try {
2556
+ const target = readSettings().targets.find((entry) => entry.id === targetId);
2557
+ if (target === void 0) return null;
2558
+ return {
2559
+ runtime: target.runtime,
2560
+ ...target.url === void 0 ? {} : { url: target.url },
2561
+ ...target.defaultModel === void 0 ? {} : { defaultModel: target.defaultModel }
2562
+ };
2563
+ } catch {
2564
+ return null;
2565
+ }
2566
+ }
2567
+ async function readServingProps(targetUrl, modelId) {
2568
+ const root = targetUrl.replace(/\/+$/u, "").replace(/\/v1$/u, "");
2569
+ try {
2570
+ const response = await fetch(`${root}/props`, { signal: AbortSignal.timeout(5e3) });
2571
+ if (!response.ok) return null;
2572
+ const value = await response.json();
2573
+ if (!isRecord4(value)) return null;
2574
+ const totalSlots = positiveInteger(value.total_slots) ?? await readServingSlots(root, modelId);
2575
+ return {
2576
+ serverBuild: typeof value.build_info === "string" && value.build_info.length > 0 ? value.build_info : null,
2577
+ totalSlots
2578
+ };
2579
+ } catch {
2580
+ return null;
2581
+ }
2582
+ }
2583
+ async function readServingSlots(root, modelId) {
2584
+ if (modelId === null) return null;
2585
+ try {
2586
+ const query = new URLSearchParams({ model: modelId });
2587
+ const response = await fetch(`${root}/slots?${query}`, { signal: AbortSignal.timeout(5e3) });
2588
+ if (!response.ok) return null;
2589
+ const value = await response.json();
2590
+ return Array.isArray(value) && value.length > 0 ? value.length : null;
2591
+ } catch {
2592
+ return null;
2593
+ }
2594
+ }
2595
+ function consensus(values) {
2596
+ const known = [...new Set(values.filter((value) => typeof value === "string" && value.length > 0))];
2597
+ return known.length === 1 ? known[0] ?? null : null;
2598
+ }
2599
+ function positiveInteger(value) {
2600
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
2601
+ }
2602
+ function isRecord4(value) {
2603
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2604
+ }
2605
+
2606
+ // src/domains/eval/task-file.ts
2607
+ init_esm_shims();
2608
+ var import_yaml = __toESM(require_dist(), 1);
2609
+ import { createHash as createHash4 } from "node:crypto";
2610
+ import { readFile as readFile3 } from "node:fs/promises";
2611
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
2612
+
2613
+ // src/domains/eval/types.ts
2614
+ init_esm_shims();
2615
+ var EVAL_TASK_FILE_VERSION = 1;
2616
+
2617
+ // src/domains/eval/task-file.ts
2618
+ var TASK_KEYS = /* @__PURE__ */ new Set(["id", "prompt", "cwd", "setup", "verifier", "timeoutMs", "tags"]);
2619
+ async function loadEvalTaskFile(path) {
2620
+ const resolved = resolve(path);
2621
+ const raw = await readFile3(resolved, "utf8");
2622
+ const result = parseEvalTaskFileYaml(raw);
2623
+ if (!result.valid) {
2624
+ throw new EvalTaskFileError(result.issues);
2625
+ }
2626
+ const baseDir = dirname(resolved);
2627
+ const cwdIssues = validateTaskCwds(result.taskFile.tasks, baseDir);
2628
+ if (cwdIssues.length > 0) throw new EvalTaskFileError(cwdIssues);
2629
+ return {
2630
+ path: resolved,
2631
+ baseDir,
2632
+ contentHash: sha256Hex(raw),
2633
+ taskFile: result.taskFile
2634
+ };
2635
+ }
2636
+ function parseEvalTaskFileYaml(raw) {
2637
+ let parsed;
2638
+ try {
2639
+ parsed = (0, import_yaml.parse)(raw);
2640
+ } catch (error) {
2641
+ const message = error instanceof Error ? error.message : String(error);
2642
+ return { valid: false, issues: [{ path: "$", message: `invalid YAML: ${message}` }] };
2643
+ }
2644
+ return validateEvalTaskFile(parsed);
2645
+ }
2646
+ function validateEvalTaskFile(value) {
2647
+ const issues = [];
2648
+ if (!isRecord5(value)) {
2649
+ return { valid: false, issues: [{ path: "$", message: "expected object" }] };
2650
+ }
2651
+ if (value.version !== EVAL_TASK_FILE_VERSION) {
2652
+ issues.push({ path: "$.version", message: "expected version 1" });
2653
+ }
2654
+ if (!Array.isArray(value.tasks)) {
2655
+ issues.push({ path: "$.tasks", message: "expected non-empty array" });
2656
+ return { valid: false, issues };
2657
+ }
2658
+ if (value.tasks.length === 0) {
2659
+ issues.push({ path: "$.tasks", message: "expected non-empty array" });
2660
+ }
2661
+ const tasks = [];
2662
+ const seenIds = /* @__PURE__ */ new Set();
2663
+ for (let index = 0; index < value.tasks.length; index += 1) {
2664
+ const task = parseTask(value.tasks[index], `$.tasks[${index}]`, issues);
2665
+ if (task === null) continue;
2666
+ if (seenIds.has(task.id)) {
2667
+ issues.push({ path: `$.tasks[${index}].id`, message: `duplicate task id: ${task.id}` });
2668
+ }
2669
+ seenIds.add(task.id);
2670
+ tasks.push(task);
2671
+ }
2672
+ if (issues.length > 0) return { valid: false, issues };
2673
+ return { valid: true, taskFile: { version: 1, tasks } };
2674
+ }
2675
+ var EvalTaskFileError = class extends Error {
2676
+ issues;
2677
+ constructor(issues) {
2678
+ super(`eval task file invalid (${issues.length} ${issues.length === 1 ? "issue" : "issues"})`);
2679
+ this.name = "EvalTaskFileError";
2680
+ this.issues = [...issues];
2681
+ }
2682
+ };
2683
+ function parseTask(value, path, issues) {
2684
+ if (!isRecord5(value)) {
2685
+ issues.push({ path, message: "expected object" });
2686
+ return null;
2687
+ }
2688
+ for (const key of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
2689
+ if (!TASK_KEYS.has(key)) issues.push({ path: `${path}.${key}`, message: "unknown field" });
2690
+ }
2691
+ const id = readNonEmptyString2(value, path, "id", issues);
2692
+ if (id !== null && !/^[A-Za-z0-9._-]+$/.test(id)) {
2693
+ issues.push({ path: `${path}.id`, message: "expected id with letters, numbers, dots, underscores, or hyphens" });
2694
+ }
2695
+ const prompt = readNonEmptyString2(value, path, "prompt", issues);
2696
+ const cwd = readNonEmptyString2(value, path, "cwd", issues);
2697
+ if (cwd !== null && isAbsolute(cwd)) {
2698
+ issues.push({ path: `${path}.cwd`, message: "expected repo-local relative path" });
2699
+ }
2700
+ const setup = readStringArray3(value, path, "setup", issues, true);
2701
+ const verifier = readStringArray3(value, path, "verifier", issues, false);
2702
+ if (verifier !== null && verifier.length === 0) {
2703
+ issues.push({ path: `${path}.verifier`, message: "expected at least one command" });
2704
+ }
2705
+ const timeoutMs = readPositiveInteger(value, path, "timeoutMs", issues);
2706
+ const tags = readStringArray3(value, path, "tags", issues, true);
2707
+ if (id === null || prompt === null || cwd === null || setup === null || verifier === null || timeoutMs === null) {
2708
+ return null;
2709
+ }
2710
+ return { id, prompt, cwd, setup, verifier, timeoutMs, tags: tags ?? [] };
2711
+ }
2712
+ function validateTaskCwds(tasks, baseDir) {
2713
+ const issues = [];
2714
+ for (let index = 0; index < tasks.length; index += 1) {
2715
+ const task = tasks[index];
2716
+ if (task === void 0) continue;
2717
+ const resolved = resolve(baseDir, task.cwd);
2718
+ const rel = relative(baseDir, resolved);
2719
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) continue;
2720
+ issues.push({ path: `$.tasks[${index}].cwd`, message: "cwd must stay within the task file directory" });
2721
+ }
2722
+ return issues;
2723
+ }
2724
+ function readNonEmptyString2(record, path, field, issues) {
2725
+ const value = record[field];
2726
+ if (typeof value !== "string" || value.trim().length === 0) {
2727
+ issues.push({ path: `${path}.${field}`, message: "expected non-empty string" });
2728
+ return null;
2729
+ }
2730
+ return value;
2731
+ }
2732
+ function readStringArray3(record, path, field, issues, allowMissing) {
2733
+ const value = record[field];
2734
+ if (value === void 0 && allowMissing) return [];
2735
+ if (!Array.isArray(value)) {
2736
+ issues.push({ path: `${path}.${field}`, message: "expected string array" });
2737
+ return null;
2738
+ }
2739
+ const out = [];
2740
+ for (let index = 0; index < value.length; index += 1) {
2741
+ const entry = value[index];
2742
+ if (typeof entry !== "string" || entry.trim().length === 0) {
2743
+ issues.push({ path: `${path}.${field}[${index}]`, message: "expected non-empty string" });
2744
+ continue;
2745
+ }
2746
+ out.push(entry);
2747
+ }
2748
+ return out;
2749
+ }
2750
+ function readPositiveInteger(record, path, field, issues) {
2751
+ const value = record[field];
2752
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
2753
+ issues.push({ path: `${path}.${field}`, message: "expected positive integer" });
2754
+ return null;
2755
+ }
2756
+ return value;
2757
+ }
2758
+ function isRecord5(value) {
2759
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2760
+ }
2761
+ function sha256Hex(content) {
2762
+ return createHash4("sha256").update(content, "utf8").digest("hex");
2763
+ }
2764
+
2765
+ // src/domains/eval/run-compare.ts
2766
+ init_esm_shims();
2767
+ var EvalTrackedMetricSourceMismatchError = class extends Error {
2768
+ constructor(metric, baseline, candidate) {
2769
+ super(
2770
+ `tracked metric ${metric} cannot compare estimated and measured values (baseline=${baseline.join(",") || "none"}, candidate=${candidate.join(",") || "none"})`
2771
+ );
2772
+ this.name = "EvalTrackedMetricSourceMismatchError";
2773
+ }
2774
+ };
2775
+ function assertComparableTrackedMetricSources(metric, baseline, candidate) {
2776
+ if (baseline.includes("estimated") === candidate.includes("estimated")) return;
2777
+ throw new EvalTrackedMetricSourceMismatchError(metric, baseline, candidate);
2778
+ }
2779
+
2780
+ // src/domains/prompts/hash.ts
2781
+ init_esm_shims();
2782
+ import { createHash as createHash5 } from "node:crypto";
2783
+ function sha2563(input) {
2784
+ return createHash5("sha256").update(input, "utf8").digest("hex");
2785
+ }
2786
+ function canonicalJson2(value) {
2787
+ return serialize(value);
2788
+ }
2789
+ function serialize(value) {
2790
+ if (value === null) return "null";
2791
+ if (typeof value === "number") {
2792
+ if (!Number.isFinite(value)) {
2793
+ throw new Error(`canonicalJson: non-finite number ${String(value)} is not representable`);
2794
+ }
2795
+ return JSON.stringify(value);
2796
+ }
2797
+ if (typeof value === "string" || typeof value === "boolean") {
2798
+ return JSON.stringify(value);
2799
+ }
2800
+ if (typeof value === "bigint") {
2801
+ throw new Error("canonicalJson: bigint is not representable");
2802
+ }
2803
+ if (typeof value === "symbol" || typeof value === "function") {
2804
+ throw new Error(`canonicalJson: ${typeof value} is not representable`);
2805
+ }
2806
+ if (value === void 0) {
2807
+ throw new Error("canonicalJson: undefined is not representable at root");
2808
+ }
2809
+ if (Array.isArray(value)) {
2810
+ const parts = [];
2811
+ for (let i = 0; i < value.length; i++) {
2812
+ if (!(i in value) || value[i] === void 0) {
2813
+ parts.push("null");
2814
+ continue;
2815
+ }
2816
+ parts.push(serialize(value[i]));
2817
+ }
2818
+ return `[${parts.join(",")}]`;
2819
+ }
2820
+ if (typeof value === "object") {
2821
+ const obj = value;
2822
+ const keys = Object.keys(obj).sort();
2823
+ const parts = [];
2824
+ for (const key of keys) {
2825
+ const child = obj[key];
2826
+ if (child === void 0) continue;
2827
+ parts.push(`${JSON.stringify(key)}:${serialize(child)}`);
2828
+ }
2829
+ return `{${parts.join(",")}}`;
2830
+ }
2831
+ throw new Error(`canonicalJson: unsupported value of type ${typeof value}`);
2832
+ }
2833
+
2834
+ export {
2835
+ sha2563 as sha256,
2836
+ canonicalJson2 as canonicalJson,
2837
+ RUN_RECEIPT_INTEGRITY_VERSION,
2838
+ RUN_RECEIPT_INTEGRITY_ALGORITHM,
2839
+ withReceiptIntegrity,
2840
+ isReceiptIntegrity,
2841
+ verifyReceiptIntegrity,
2842
+ EVAL_VERDICT_SCHEMA_V1,
2843
+ EVAL_TRACKED_METRIC_NAMES,
2844
+ parseEvalVerdictEnvelopeV1,
2845
+ parseEvalBehaviorScenarioV1,
2846
+ judgeEvalBehaviorV1,
2847
+ assertEvalBehaviorReferencesVerdictV1,
2848
+ EVAL_BEHAVIOR_METRIC_DEFINITIONS_V1,
2849
+ buildEvalBehaviorMetricsV1,
2850
+ EVAL_EXECUTION_ENVELOPE_SCHEMA_V1,
2851
+ parseEvalExecutionMatrixDimensionsV1,
2852
+ sameEvalServingConfiguration,
2853
+ renderEvalServingConfiguration,
2854
+ redactArtifactForStorage,
2855
+ ZERO_EVAL_HARNESS_METRICS,
2856
+ evalHarnessMetricsFromReceipt,
2857
+ sumEvalHarnessMetrics,
2858
+ createEvalId,
2859
+ writeEvalArtifact,
2860
+ loadEvalArtifact,
2861
+ writeEvalArtifactV4,
2862
+ loadEvalArtifactV4,
2863
+ parseEvalArtifactV4,
2864
+ TRUST_STATUS_AXES,
2865
+ isTrustStatusIdentifier,
2866
+ normalizeTrustStatus,
2867
+ composeTrustStatus,
2868
+ retiredReceiptIntegrity,
2869
+ retiredReceiptIntegrityReason,
2870
+ retiredIntegrityVersionOf,
2871
+ adaptRunReceiptTrustStatus,
2872
+ inspectRunReceiptTrustStatus,
2873
+ adaptGateDecisionReviewStatus,
2874
+ adaptGroundedEvidenceValidationStatus,
2875
+ formatTrustSummary,
2876
+ formatTrustSummaryLine,
2877
+ formatTrustAxes,
2878
+ trustVerdict,
2879
+ summarizeTrustStatus,
2880
+ evalClioProvenance,
2881
+ evalEnvironmentProvenance,
2882
+ evalServingConfiguration,
2883
+ evalServingObservationFrom,
2884
+ assertComparableTrackedMetricSources,
2885
+ loadEvalTaskFile,
2886
+ EvalTaskFileError
2887
+ };
2888
+ //# sourceMappingURL=chunk-MLOK6ZOS.js.map