@prismatic-io/lux 0.0.2-preview.3 → 0.0.2-preview.32

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 (727) hide show
  1. package/lib/answerers/claude-code/index.d.ts +15 -3
  2. package/lib/answerers/claude-code/index.d.ts.map +1 -1
  3. package/lib/answerers/claude-code/index.js +6 -5
  4. package/lib/answerers/claude-code/index.js.map +1 -1
  5. package/lib/answerers/persona/index.d.ts +44 -5
  6. package/lib/answerers/persona/index.d.ts.map +1 -1
  7. package/lib/answerers/persona/index.js +60 -34
  8. package/lib/answerers/persona/index.js.map +1 -1
  9. package/lib/answerers/terminal/index.d.ts +9 -3
  10. package/lib/answerers/terminal/index.d.ts.map +1 -1
  11. package/lib/answerers/terminal/index.js +7 -5
  12. package/lib/answerers/terminal/index.js.map +1 -1
  13. package/lib/assertions/authoring.d.ts +2 -2
  14. package/lib/assertions/authoring.d.ts.map +1 -1
  15. package/lib/assertions/authoring.js.map +1 -1
  16. package/lib/assertions/core/command-exits-zero.d.ts +4 -1
  17. package/lib/assertions/core/command-exits-zero.d.ts.map +1 -1
  18. package/lib/assertions/core/command-exits-zero.js +50 -7
  19. package/lib/assertions/core/command-exits-zero.js.map +1 -1
  20. package/lib/assertions/core/event-checks.d.ts +3 -0
  21. package/lib/assertions/core/event-checks.d.ts.map +1 -1
  22. package/lib/assertions/core/event-checks.js +49 -3
  23. package/lib/assertions/core/event-checks.js.map +1 -1
  24. package/lib/assertions/core/file-checks.d.ts +6 -0
  25. package/lib/assertions/core/file-checks.d.ts.map +1 -1
  26. package/lib/assertions/core/helpers.d.ts +2 -7
  27. package/lib/assertions/core/helpers.d.ts.map +1 -1
  28. package/lib/assertions/core/helpers.js +2 -6
  29. package/lib/assertions/core/helpers.js.map +1 -1
  30. package/lib/assertions/core/index.d.ts.map +1 -1
  31. package/lib/assertions/core/index.js +2 -1
  32. package/lib/assertions/core/index.js.map +1 -1
  33. package/lib/assertions/core/json-pointer-equals.d.ts +1 -0
  34. package/lib/assertions/core/json-pointer-equals.d.ts.map +1 -1
  35. package/lib/assertions/core/output-checks.d.ts +3 -0
  36. package/lib/assertions/core/output-checks.d.ts.map +1 -1
  37. package/lib/assertions/core/predicate.d.ts +1 -0
  38. package/lib/assertions/core/predicate.d.ts.map +1 -1
  39. package/lib/assertions/core/resource-checks.d.ts +25 -0
  40. package/lib/assertions/core/resource-checks.d.ts.map +1 -1
  41. package/lib/assertions/core/resource-checks.js +35 -5
  42. package/lib/assertions/core/resource-checks.js.map +1 -1
  43. package/lib/assertions/rubric/index.d.ts +28 -3
  44. package/lib/assertions/rubric/index.d.ts.map +1 -1
  45. package/lib/assertions/rubric/index.js +59 -13
  46. package/lib/assertions/rubric/index.js.map +1 -1
  47. package/lib/assertions/rubric/internal.d.ts +30 -5
  48. package/lib/assertions/rubric/internal.d.ts.map +1 -1
  49. package/lib/assertions/rubric/internal.js +181 -28
  50. package/lib/assertions/rubric/internal.js.map +1 -1
  51. package/lib/authoring.d.ts +36 -2
  52. package/lib/authoring.d.ts.map +1 -1
  53. package/lib/authoring.js +36 -1
  54. package/lib/authoring.js.map +1 -1
  55. package/lib/cli/bin.js +2 -13
  56. package/lib/cli/bin.js.map +1 -1
  57. package/lib/cli/command-runtime.d.ts +3 -3
  58. package/lib/cli/command-runtime.d.ts.map +1 -1
  59. package/lib/cli/command-runtime.js +17 -6
  60. package/lib/cli/command-runtime.js.map +1 -1
  61. package/lib/cli/doctor.d.ts +55 -0
  62. package/lib/cli/doctor.d.ts.map +1 -0
  63. package/lib/cli/doctor.js +14 -0
  64. package/lib/cli/doctor.js.map +1 -0
  65. package/lib/cli/harness-plan.d.ts +26 -0
  66. package/lib/cli/harness-plan.d.ts.map +1 -0
  67. package/lib/cli/harness-plan.js +75 -0
  68. package/lib/cli/harness-plan.js.map +1 -0
  69. package/lib/cli/init-templates.d.ts +11 -0
  70. package/lib/cli/init-templates.d.ts.map +1 -0
  71. package/lib/cli/init-templates.js +215 -0
  72. package/lib/cli/init-templates.js.map +1 -0
  73. package/lib/cli/init.d.ts +10 -0
  74. package/lib/cli/init.d.ts.map +1 -1
  75. package/lib/cli/init.js +34 -173
  76. package/lib/cli/init.js.map +1 -1
  77. package/lib/cli/output-schemas.d.ts +1408 -0
  78. package/lib/cli/output-schemas.d.ts.map +1 -0
  79. package/lib/cli/output-schemas.js +91 -0
  80. package/lib/cli/output-schemas.js.map +1 -0
  81. package/lib/cli/program.d.ts +140 -12
  82. package/lib/cli/program.d.ts.map +1 -1
  83. package/lib/cli/program.js +779 -646
  84. package/lib/cli/program.js.map +1 -1
  85. package/lib/cli/render/reporter.d.ts.map +1 -1
  86. package/lib/cli/render/reporter.js +48 -8
  87. package/lib/cli/render/reporter.js.map +1 -1
  88. package/lib/cli/run-options.d.ts +20 -4
  89. package/lib/cli/run-options.d.ts.map +1 -1
  90. package/lib/cli/run-options.js +100 -19
  91. package/lib/cli/run-options.js.map +1 -1
  92. package/lib/cli/view.d.ts +15 -0
  93. package/lib/cli/view.d.ts.map +1 -0
  94. package/lib/cli/view.js +168 -0
  95. package/lib/cli/view.js.map +1 -0
  96. package/lib/container/driver.d.ts +27 -0
  97. package/lib/container/driver.d.ts.map +1 -0
  98. package/lib/container/driver.js +197 -0
  99. package/lib/container/driver.js.map +1 -0
  100. package/lib/container/protocol.d.ts +12 -0
  101. package/lib/container/protocol.d.ts.map +1 -0
  102. package/lib/container/protocol.js +38 -0
  103. package/lib/container/protocol.js.map +1 -0
  104. package/lib/container/resources.d.ts +12 -0
  105. package/lib/container/resources.d.ts.map +1 -0
  106. package/lib/container/resources.js +133 -0
  107. package/lib/container/resources.js.map +1 -0
  108. package/lib/container/worker.d.ts +2 -0
  109. package/lib/container/worker.d.ts.map +1 -0
  110. package/lib/container/worker.js +85 -0
  111. package/lib/container/worker.js.map +1 -0
  112. package/lib/core/action-events.d.ts +29 -0
  113. package/lib/core/action-events.d.ts.map +1 -0
  114. package/lib/core/action-events.js +51 -0
  115. package/lib/core/action-events.js.map +1 -0
  116. package/lib/core/agent-activity.d.ts +49 -0
  117. package/lib/core/agent-activity.d.ts.map +1 -0
  118. package/lib/core/agent-activity.js +206 -0
  119. package/lib/core/agent-activity.js.map +1 -0
  120. package/lib/core/agent-environment.d.ts +5 -0
  121. package/lib/core/agent-environment.d.ts.map +1 -0
  122. package/lib/core/agent-environment.js +47 -0
  123. package/lib/core/agent-environment.js.map +1 -0
  124. package/lib/core/agent-events.d.ts +26 -0
  125. package/lib/core/agent-events.d.ts.map +1 -0
  126. package/lib/core/agent-events.js +13 -0
  127. package/lib/core/agent-events.js.map +1 -0
  128. package/lib/core/annotation.d.ts +6 -2
  129. package/lib/core/annotation.d.ts.map +1 -1
  130. package/lib/core/annotation.js +2 -1
  131. package/lib/core/annotation.js.map +1 -1
  132. package/lib/core/answerer.d.ts +12 -0
  133. package/lib/core/answerer.d.ts.map +1 -1
  134. package/lib/core/answerer.js +2 -0
  135. package/lib/core/answerer.js.map +1 -1
  136. package/lib/core/artifact-evidence.d.ts +8 -0
  137. package/lib/core/artifact-evidence.d.ts.map +1 -1
  138. package/lib/core/artifact-evidence.js +36 -4
  139. package/lib/core/artifact-evidence.js.map +1 -1
  140. package/lib/core/assertion.d.ts +20 -2
  141. package/lib/core/assertion.d.ts.map +1 -1
  142. package/lib/core/assertion.js +19 -1
  143. package/lib/core/assertion.js.map +1 -1
  144. package/lib/core/case.d.ts +111 -3
  145. package/lib/core/case.d.ts.map +1 -1
  146. package/lib/core/case.js +17 -2
  147. package/lib/core/case.js.map +1 -1
  148. package/lib/core/command-verification.d.ts +10 -0
  149. package/lib/core/command-verification.d.ts.map +1 -0
  150. package/lib/core/command-verification.js +66 -0
  151. package/lib/core/command-verification.js.map +1 -0
  152. package/lib/core/driver-execution.d.ts +83 -0
  153. package/lib/core/driver-execution.d.ts.map +1 -0
  154. package/lib/core/driver-execution.js +72 -0
  155. package/lib/core/driver-execution.js.map +1 -0
  156. package/lib/core/driver-metrics.d.ts +98 -0
  157. package/lib/core/driver-metrics.d.ts.map +1 -0
  158. package/lib/core/driver-metrics.js +36 -0
  159. package/lib/core/driver-metrics.js.map +1 -0
  160. package/lib/core/driver.d.ts +64 -0
  161. package/lib/core/driver.d.ts.map +1 -1
  162. package/lib/core/driver.js +28 -0
  163. package/lib/core/driver.js.map +1 -1
  164. package/lib/core/duration.d.ts +5 -0
  165. package/lib/core/duration.d.ts.map +1 -0
  166. package/lib/core/duration.js +49 -0
  167. package/lib/core/duration.js.map +1 -0
  168. package/lib/core/environment.d.ts +18 -0
  169. package/lib/core/environment.d.ts.map +1 -0
  170. package/lib/core/environment.js +21 -0
  171. package/lib/core/environment.js.map +1 -0
  172. package/lib/core/evaluation-clusters.d.ts +17 -0
  173. package/lib/core/evaluation-clusters.d.ts.map +1 -0
  174. package/lib/core/evaluation-clusters.js +23 -0
  175. package/lib/core/evaluation-clusters.js.map +1 -0
  176. package/lib/core/events.d.ts +36 -0
  177. package/lib/core/events.d.ts.map +1 -1
  178. package/lib/core/events.js +12 -2
  179. package/lib/core/events.js.map +1 -1
  180. package/lib/core/experiment.d.ts +32 -2
  181. package/lib/core/experiment.d.ts.map +1 -1
  182. package/lib/core/experiment.js +35 -18
  183. package/lib/core/experiment.js.map +1 -1
  184. package/lib/core/file-tree.d.ts +7 -0
  185. package/lib/core/file-tree.d.ts.map +1 -0
  186. package/lib/core/file-tree.js +35 -0
  187. package/lib/core/file-tree.js.map +1 -0
  188. package/lib/core/global-id.d.ts +6 -0
  189. package/lib/core/global-id.d.ts.map +1 -0
  190. package/lib/core/global-id.js +17 -0
  191. package/lib/core/global-id.js.map +1 -0
  192. package/lib/core/harness-catalog.d.ts +35 -0
  193. package/lib/core/harness-catalog.d.ts.map +1 -0
  194. package/lib/core/harness-catalog.js +45 -0
  195. package/lib/core/harness-catalog.js.map +1 -0
  196. package/lib/core/harness-catalogs/antigravity.d.ts +11 -0
  197. package/lib/core/harness-catalogs/antigravity.d.ts.map +1 -0
  198. package/lib/core/harness-catalogs/antigravity.js +23 -0
  199. package/lib/core/harness-catalogs/antigravity.js.map +1 -0
  200. package/lib/core/harness-catalogs/claude-code.d.ts +12 -0
  201. package/lib/core/harness-catalogs/claude-code.d.ts.map +1 -0
  202. package/lib/core/harness-catalogs/claude-code.js +24 -0
  203. package/lib/core/harness-catalogs/claude-code.js.map +1 -0
  204. package/lib/core/harness-catalogs/codex.d.ts +11 -0
  205. package/lib/core/harness-catalogs/codex.d.ts.map +1 -0
  206. package/lib/core/harness-catalogs/codex.js +26 -0
  207. package/lib/core/harness-catalogs/codex.js.map +1 -0
  208. package/lib/core/harness-catalogs/copilot.d.ts +29 -0
  209. package/lib/core/harness-catalogs/copilot.d.ts.map +1 -0
  210. package/lib/core/harness-catalogs/copilot.js +45 -0
  211. package/lib/core/harness-catalogs/copilot.js.map +1 -0
  212. package/lib/core/harness-catalogs/cursor.d.ts +2 -0
  213. package/lib/core/harness-catalogs/cursor.d.ts.map +1 -0
  214. package/lib/core/harness-catalogs/cursor.js +13 -0
  215. package/lib/core/harness-catalogs/cursor.js.map +1 -0
  216. package/lib/core/harness-catalogs/grok-build.d.ts +7 -0
  217. package/lib/core/harness-catalogs/grok-build.d.ts.map +1 -0
  218. package/lib/core/harness-catalogs/grok-build.js +18 -0
  219. package/lib/core/harness-catalogs/grok-build.js.map +1 -0
  220. package/lib/core/harness-catalogs/index.d.ts +73 -0
  221. package/lib/core/harness-catalogs/index.d.ts.map +1 -0
  222. package/lib/core/harness-catalogs/index.js +17 -0
  223. package/lib/core/harness-catalogs/index.js.map +1 -0
  224. package/lib/core/harness-matrix.d.ts +154 -0
  225. package/lib/core/harness-matrix.d.ts.map +1 -0
  226. package/lib/core/harness-matrix.js +204 -0
  227. package/lib/core/harness-matrix.js.map +1 -0
  228. package/lib/core/index.d.ts +12 -0
  229. package/lib/core/index.d.ts.map +1 -1
  230. package/lib/core/index.js +12 -0
  231. package/lib/core/index.js.map +1 -1
  232. package/lib/core/lifecycle-fixtures.d.ts.map +1 -1
  233. package/lib/core/lifecycle-fixtures.js +4 -2
  234. package/lib/core/lifecycle-fixtures.js.map +1 -1
  235. package/lib/core/model-cli.d.ts +9 -11
  236. package/lib/core/model-cli.d.ts.map +1 -1
  237. package/lib/core/model-cli.js +31 -19
  238. package/lib/core/model-cli.js.map +1 -1
  239. package/lib/core/platform-process.d.ts +6 -1
  240. package/lib/core/platform-process.d.ts.map +1 -1
  241. package/lib/core/platform-process.js +49 -11
  242. package/lib/core/platform-process.js.map +1 -1
  243. package/lib/core/rubric.d.ts +1 -0
  244. package/lib/core/rubric.d.ts.map +1 -1
  245. package/lib/core/run.d.ts +293 -1
  246. package/lib/core/run.d.ts.map +1 -1
  247. package/lib/core/run.js +27 -0
  248. package/lib/core/run.js.map +1 -1
  249. package/lib/core/secure-copy.d.ts.map +1 -0
  250. package/lib/core/secure-copy.js.map +1 -0
  251. package/lib/core/usage.d.ts +5 -0
  252. package/lib/core/usage.d.ts.map +1 -1
  253. package/lib/core/usage.js +3 -0
  254. package/lib/core/usage.js.map +1 -1
  255. package/lib/core/wire.d.ts +12 -0
  256. package/lib/core/wire.d.ts.map +1 -1
  257. package/lib/core/wire.js +5 -1
  258. package/lib/core/wire.js.map +1 -1
  259. package/lib/drivers/antigravity/artifacts.d.ts +2 -0
  260. package/lib/drivers/antigravity/artifacts.d.ts.map +1 -0
  261. package/lib/drivers/antigravity/artifacts.js +33 -0
  262. package/lib/drivers/antigravity/artifacts.js.map +1 -0
  263. package/lib/drivers/antigravity/config.d.ts +88 -0
  264. package/lib/drivers/antigravity/config.d.ts.map +1 -0
  265. package/lib/drivers/antigravity/config.js +87 -0
  266. package/lib/drivers/antigravity/config.js.map +1 -0
  267. package/lib/drivers/antigravity/events.d.ts +4 -0
  268. package/lib/drivers/antigravity/events.d.ts.map +1 -0
  269. package/lib/drivers/antigravity/events.js +241 -0
  270. package/lib/drivers/antigravity/events.js.map +1 -0
  271. package/lib/drivers/antigravity/index.d.ts +114 -0
  272. package/lib/drivers/antigravity/index.d.ts.map +1 -0
  273. package/lib/drivers/antigravity/index.js +113 -0
  274. package/lib/drivers/antigravity/index.js.map +1 -0
  275. package/lib/drivers/antigravity/runtime.d.ts +7 -0
  276. package/lib/drivers/antigravity/runtime.d.ts.map +1 -0
  277. package/lib/drivers/antigravity/runtime.js +83 -0
  278. package/lib/drivers/antigravity/runtime.js.map +1 -0
  279. package/lib/drivers/claude-code/deferred-process.d.ts +17 -0
  280. package/lib/drivers/claude-code/deferred-process.d.ts.map +1 -0
  281. package/lib/drivers/claude-code/deferred-process.js +108 -0
  282. package/lib/drivers/claude-code/deferred-process.js.map +1 -0
  283. package/lib/drivers/claude-code/index.d.ts +180 -10
  284. package/lib/drivers/claude-code/index.d.ts.map +1 -1
  285. package/lib/drivers/claude-code/index.js +186 -252
  286. package/lib/drivers/claude-code/index.js.map +1 -1
  287. package/lib/drivers/claude-code/isolation.d.ts +8 -0
  288. package/lib/drivers/claude-code/isolation.d.ts.map +1 -0
  289. package/lib/drivers/claude-code/isolation.js +199 -0
  290. package/lib/drivers/claude-code/isolation.js.map +1 -0
  291. package/lib/drivers/claude-code/parse-events.d.ts.map +1 -1
  292. package/lib/drivers/claude-code/parse-events.js +73 -8
  293. package/lib/drivers/claude-code/parse-events.js.map +1 -1
  294. package/lib/drivers/codex/app-events.d.ts +9 -2
  295. package/lib/drivers/codex/app-events.d.ts.map +1 -1
  296. package/lib/drivers/codex/app-events.js +104 -12
  297. package/lib/drivers/codex/app-events.js.map +1 -1
  298. package/lib/drivers/codex/config.d.ts +66 -5
  299. package/lib/drivers/codex/config.d.ts.map +1 -1
  300. package/lib/drivers/codex/config.js +39 -8
  301. package/lib/drivers/codex/config.js.map +1 -1
  302. package/lib/drivers/codex/exec-events.d.ts +4 -0
  303. package/lib/drivers/codex/exec-events.d.ts.map +1 -0
  304. package/lib/drivers/codex/exec-events.js +230 -0
  305. package/lib/drivers/codex/exec-events.js.map +1 -0
  306. package/lib/drivers/codex/index.d.ts +138 -4
  307. package/lib/drivers/codex/index.d.ts.map +1 -1
  308. package/lib/drivers/codex/index.js +112 -276
  309. package/lib/drivers/codex/index.js.map +1 -1
  310. package/lib/drivers/copilot/config.d.ts +84 -0
  311. package/lib/drivers/copilot/config.d.ts.map +1 -0
  312. package/lib/drivers/copilot/config.js +57 -0
  313. package/lib/drivers/copilot/config.js.map +1 -0
  314. package/lib/drivers/copilot/index.d.ts +107 -0
  315. package/lib/drivers/copilot/index.d.ts.map +1 -0
  316. package/lib/drivers/copilot/index.js +268 -0
  317. package/lib/drivers/copilot/index.js.map +1 -0
  318. package/lib/drivers/cursor/config.d.ts +28 -0
  319. package/lib/drivers/cursor/config.d.ts.map +1 -0
  320. package/lib/drivers/cursor/config.js +28 -0
  321. package/lib/drivers/cursor/config.js.map +1 -0
  322. package/lib/drivers/cursor/index.d.ts +44 -0
  323. package/lib/drivers/cursor/index.d.ts.map +1 -0
  324. package/lib/drivers/cursor/index.js +286 -0
  325. package/lib/drivers/cursor/index.js.map +1 -0
  326. package/lib/drivers/cursor/interaction.d.ts +6 -0
  327. package/lib/drivers/cursor/interaction.d.ts.map +1 -0
  328. package/lib/drivers/cursor/interaction.js +55 -0
  329. package/lib/drivers/cursor/interaction.js.map +1 -0
  330. package/lib/drivers/grok-build/config.d.ts +68 -0
  331. package/lib/drivers/grok-build/config.d.ts.map +1 -0
  332. package/lib/drivers/grok-build/config.js +40 -0
  333. package/lib/drivers/grok-build/config.js.map +1 -0
  334. package/lib/drivers/grok-build/index.d.ts +87 -0
  335. package/lib/drivers/grok-build/index.d.ts.map +1 -0
  336. package/lib/drivers/grok-build/index.js +293 -0
  337. package/lib/drivers/grok-build/index.js.map +1 -0
  338. package/lib/drivers/mcp/index.d.ts +37 -4
  339. package/lib/drivers/mcp/index.d.ts.map +1 -1
  340. package/lib/drivers/mcp/index.js +25 -11
  341. package/lib/drivers/mcp/index.js.map +1 -1
  342. package/lib/drivers/shared/acp-events.d.ts +15 -0
  343. package/lib/drivers/shared/acp-events.d.ts.map +1 -0
  344. package/lib/drivers/shared/acp-events.js +83 -0
  345. package/lib/drivers/shared/acp-events.js.map +1 -0
  346. package/lib/drivers/shared/acp-interaction.d.ts +7 -0
  347. package/lib/drivers/shared/acp-interaction.d.ts.map +1 -0
  348. package/lib/drivers/shared/acp-interaction.js +20 -0
  349. package/lib/drivers/shared/acp-interaction.js.map +1 -0
  350. package/lib/drivers/shared/acp-session.d.ts +4 -0
  351. package/lib/drivers/shared/acp-session.d.ts.map +1 -0
  352. package/lib/drivers/shared/acp-session.js +23 -0
  353. package/lib/drivers/shared/acp-session.js.map +1 -0
  354. package/lib/drivers/shared/acp-transport.d.ts +40 -0
  355. package/lib/drivers/shared/acp-transport.d.ts.map +1 -0
  356. package/lib/drivers/shared/acp-transport.js +152 -0
  357. package/lib/drivers/shared/acp-transport.js.map +1 -0
  358. package/lib/drivers/shared/artifacts.d.ts.map +1 -1
  359. package/lib/drivers/shared/artifacts.js +3 -2
  360. package/lib/drivers/shared/artifacts.js.map +1 -1
  361. package/lib/drivers/shared/experiment-behavior.d.ts +13 -0
  362. package/lib/drivers/shared/experiment-behavior.d.ts.map +1 -0
  363. package/lib/drivers/shared/experiment-behavior.js +197 -0
  364. package/lib/drivers/shared/experiment-behavior.js.map +1 -0
  365. package/lib/drivers/shared/experiment-policy.d.ts +4 -0
  366. package/lib/drivers/shared/experiment-policy.d.ts.map +1 -0
  367. package/lib/drivers/shared/experiment-policy.js +143 -0
  368. package/lib/drivers/shared/experiment-policy.js.map +1 -0
  369. package/lib/drivers/subprocess/index.d.ts +39 -4
  370. package/lib/drivers/subprocess/index.d.ts.map +1 -1
  371. package/lib/drivers/subprocess/index.js +56 -12
  372. package/lib/drivers/subprocess/index.js.map +1 -1
  373. package/lib/index.d.ts +22 -8
  374. package/lib/index.d.ts.map +1 -1
  375. package/lib/index.js +20 -6
  376. package/lib/index.js.map +1 -1
  377. package/lib/optimization/reflective.d.ts +3 -1
  378. package/lib/optimization/reflective.d.ts.map +1 -1
  379. package/lib/optimization/reflective.js +3 -2
  380. package/lib/optimization/reflective.js.map +1 -1
  381. package/lib/orchestrator/annotation-loader.d.ts +6 -2
  382. package/lib/orchestrator/annotation-loader.d.ts.map +1 -1
  383. package/lib/orchestrator/annotation-loader.js +8 -0
  384. package/lib/orchestrator/annotation-loader.js.map +1 -1
  385. package/lib/orchestrator/annotation-store.d.ts.map +1 -1
  386. package/lib/orchestrator/annotation-store.js +16 -2
  387. package/lib/orchestrator/annotation-store.js.map +1 -1
  388. package/lib/orchestrator/artifact-origin.d.ts +3 -0
  389. package/lib/orchestrator/artifact-origin.d.ts.map +1 -0
  390. package/lib/orchestrator/artifact-origin.js +40 -0
  391. package/lib/orchestrator/artifact-origin.js.map +1 -0
  392. package/lib/orchestrator/campaign-lifecycle.d.ts +1 -0
  393. package/lib/orchestrator/campaign-lifecycle.d.ts.map +1 -1
  394. package/lib/orchestrator/campaign-lifecycle.js +4 -1
  395. package/lib/orchestrator/campaign-lifecycle.js.map +1 -1
  396. package/lib/orchestrator/candidates.d.ts.map +1 -1
  397. package/lib/orchestrator/candidates.js +3 -2
  398. package/lib/orchestrator/candidates.js.map +1 -1
  399. package/lib/orchestrator/compare.d.ts +19 -3
  400. package/lib/orchestrator/compare.d.ts.map +1 -1
  401. package/lib/orchestrator/compare.js +32 -6
  402. package/lib/orchestrator/compare.js.map +1 -1
  403. package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
  404. package/lib/orchestrator/comparison-identity.js +2 -0
  405. package/lib/orchestrator/comparison-identity.js.map +1 -1
  406. package/lib/orchestrator/config.d.ts +179 -1
  407. package/lib/orchestrator/config.d.ts.map +1 -1
  408. package/lib/orchestrator/config.js +18 -4
  409. package/lib/orchestrator/config.js.map +1 -1
  410. package/lib/orchestrator/discover.d.ts +1 -0
  411. package/lib/orchestrator/discover.d.ts.map +1 -1
  412. package/lib/orchestrator/discover.js +7 -1
  413. package/lib/orchestrator/discover.js.map +1 -1
  414. package/lib/orchestrator/doctor.d.ts +1 -0
  415. package/lib/orchestrator/doctor.d.ts.map +1 -1
  416. package/lib/orchestrator/doctor.js +121 -33
  417. package/lib/orchestrator/doctor.js.map +1 -1
  418. package/lib/orchestrator/driver-capabilities.d.ts +4 -0
  419. package/lib/orchestrator/driver-capabilities.d.ts.map +1 -0
  420. package/lib/orchestrator/driver-capabilities.js +13 -0
  421. package/lib/orchestrator/driver-capabilities.js.map +1 -0
  422. package/lib/orchestrator/driver-identity.d.ts +5 -0
  423. package/lib/orchestrator/driver-identity.d.ts.map +1 -0
  424. package/lib/orchestrator/driver-identity.js +51 -0
  425. package/lib/orchestrator/driver-identity.js.map +1 -0
  426. package/lib/orchestrator/experiment-context.d.ts +51 -3
  427. package/lib/orchestrator/experiment-context.d.ts.map +1 -1
  428. package/lib/orchestrator/experiment-context.js.map +1 -1
  429. package/lib/orchestrator/experiment-contracts.d.ts +30 -1
  430. package/lib/orchestrator/experiment-contracts.d.ts.map +1 -1
  431. package/lib/orchestrator/experiment-corpus.d.ts +2 -1
  432. package/lib/orchestrator/experiment-corpus.d.ts.map +1 -1
  433. package/lib/orchestrator/experiment-corpus.js +28 -22
  434. package/lib/orchestrator/experiment-corpus.js.map +1 -1
  435. package/lib/orchestrator/experiment-effects.d.ts +33 -0
  436. package/lib/orchestrator/experiment-effects.d.ts.map +1 -0
  437. package/lib/orchestrator/experiment-effects.js +44 -0
  438. package/lib/orchestrator/experiment-effects.js.map +1 -0
  439. package/lib/orchestrator/experiment-evaluation.d.ts.map +1 -1
  440. package/lib/orchestrator/experiment-evaluation.js +56 -5
  441. package/lib/orchestrator/experiment-evaluation.js.map +1 -1
  442. package/lib/orchestrator/experiment-identity.d.ts +3 -0
  443. package/lib/orchestrator/experiment-identity.d.ts.map +1 -1
  444. package/lib/orchestrator/experiment-identity.js +22 -33
  445. package/lib/orchestrator/experiment-identity.js.map +1 -1
  446. package/lib/orchestrator/experiment-loader.d.ts +8 -3
  447. package/lib/orchestrator/experiment-loader.d.ts.map +1 -1
  448. package/lib/orchestrator/experiment-preflight.d.ts +3 -0
  449. package/lib/orchestrator/experiment-preflight.d.ts.map +1 -0
  450. package/lib/orchestrator/experiment-preflight.js +21 -0
  451. package/lib/orchestrator/experiment-preflight.js.map +1 -0
  452. package/lib/orchestrator/experiment-report.d.ts +90 -1
  453. package/lib/orchestrator/experiment-report.d.ts.map +1 -1
  454. package/lib/orchestrator/experiment-report.js +9 -1
  455. package/lib/orchestrator/experiment-report.js.map +1 -1
  456. package/lib/orchestrator/experiment-runs.d.ts +61 -2
  457. package/lib/orchestrator/experiment-runs.d.ts.map +1 -1
  458. package/lib/orchestrator/experiment-runs.js +13 -5
  459. package/lib/orchestrator/experiment-runs.js.map +1 -1
  460. package/lib/orchestrator/experiment-runtime-identity.d.ts +0 -16
  461. package/lib/orchestrator/experiment-runtime-identity.d.ts.map +1 -1
  462. package/lib/orchestrator/experiment-runtime-identity.js +5 -220
  463. package/lib/orchestrator/experiment-runtime-identity.js.map +1 -1
  464. package/lib/orchestrator/experiment-selection.d.ts.map +1 -1
  465. package/lib/orchestrator/experiment-selection.js +52 -0
  466. package/lib/orchestrator/experiment-selection.js.map +1 -1
  467. package/lib/orchestrator/experiment.d.ts +3 -3
  468. package/lib/orchestrator/experiment.d.ts.map +1 -1
  469. package/lib/orchestrator/experiment.js +26 -21
  470. package/lib/orchestrator/experiment.js.map +1 -1
  471. package/lib/orchestrator/fixture-identity.d.ts +1 -0
  472. package/lib/orchestrator/fixture-identity.d.ts.map +1 -1
  473. package/lib/orchestrator/fixture-identity.js +6 -1
  474. package/lib/orchestrator/fixture-identity.js.map +1 -1
  475. package/lib/orchestrator/fs-read.d.ts +1 -6
  476. package/lib/orchestrator/fs-read.d.ts.map +1 -1
  477. package/lib/orchestrator/fs-read.js +2 -32
  478. package/lib/orchestrator/fs-read.js.map +1 -1
  479. package/lib/orchestrator/grader-experiment.d.ts +33 -3
  480. package/lib/orchestrator/grader-experiment.d.ts.map +1 -1
  481. package/lib/orchestrator/grader-experiment.js +54 -9
  482. package/lib/orchestrator/grader-experiment.js.map +1 -1
  483. package/lib/orchestrator/grading.d.ts +2 -1
  484. package/lib/orchestrator/grading.d.ts.map +1 -1
  485. package/lib/orchestrator/grading.js +46 -31
  486. package/lib/orchestrator/grading.js.map +1 -1
  487. package/lib/orchestrator/harness-catalog-drift.d.ts +22 -0
  488. package/lib/orchestrator/harness-catalog-drift.d.ts.map +1 -0
  489. package/lib/orchestrator/harness-catalog-drift.js +90 -0
  490. package/lib/orchestrator/harness-catalog-drift.js.map +1 -0
  491. package/lib/orchestrator/harness-registry.d.ts +4 -0
  492. package/lib/orchestrator/harness-registry.d.ts.map +1 -0
  493. package/lib/orchestrator/harness-registry.js +5 -0
  494. package/lib/orchestrator/harness-registry.js.map +1 -0
  495. package/lib/orchestrator/index.d.ts +1 -1
  496. package/lib/orchestrator/index.d.ts.map +1 -1
  497. package/lib/orchestrator/index.js +1 -1
  498. package/lib/orchestrator/index.js.map +1 -1
  499. package/lib/orchestrator/list-runs.d.ts +8 -1
  500. package/lib/orchestrator/list-runs.d.ts.map +1 -1
  501. package/lib/orchestrator/list-runs.js +81 -14
  502. package/lib/orchestrator/list-runs.js.map +1 -1
  503. package/lib/orchestrator/optimization-lifecycle.d.ts.map +1 -1
  504. package/lib/orchestrator/optimization-lifecycle.js +3 -1
  505. package/lib/orchestrator/optimization-lifecycle.js.map +1 -1
  506. package/lib/orchestrator/orchestrator.d.ts +18 -2
  507. package/lib/orchestrator/orchestrator.d.ts.map +1 -1
  508. package/lib/orchestrator/orchestrator.js +50 -168
  509. package/lib/orchestrator/orchestrator.js.map +1 -1
  510. package/lib/orchestrator/paired-effects.d.ts +34 -0
  511. package/lib/orchestrator/paired-effects.d.ts.map +1 -0
  512. package/lib/orchestrator/paired-effects.js +158 -0
  513. package/lib/orchestrator/paired-effects.js.map +1 -0
  514. package/lib/orchestrator/provenance.d.ts +5 -1
  515. package/lib/orchestrator/provenance.d.ts.map +1 -1
  516. package/lib/orchestrator/provenance.js +16 -3
  517. package/lib/orchestrator/provenance.js.map +1 -1
  518. package/lib/orchestrator/regrade.d.ts +9 -1
  519. package/lib/orchestrator/regrade.d.ts.map +1 -1
  520. package/lib/orchestrator/rubric-loader.js +1 -1
  521. package/lib/orchestrator/rubric-loader.js.map +1 -1
  522. package/lib/orchestrator/run-dir.d.ts +2 -0
  523. package/lib/orchestrator/run-dir.d.ts.map +1 -1
  524. package/lib/orchestrator/run-dir.js +1 -1
  525. package/lib/orchestrator/run-dir.js.map +1 -1
  526. package/lib/orchestrator/run-execution.d.ts +3 -0
  527. package/lib/orchestrator/run-execution.d.ts.map +1 -1
  528. package/lib/orchestrator/run-execution.js +66 -12
  529. package/lib/orchestrator/run-execution.js.map +1 -1
  530. package/lib/orchestrator/run-lifecycle.d.ts +1 -0
  531. package/lib/orchestrator/run-lifecycle.d.ts.map +1 -1
  532. package/lib/orchestrator/run-lifecycle.js +3 -2
  533. package/lib/orchestrator/run-lifecycle.js.map +1 -1
  534. package/lib/orchestrator/run-workspace.d.ts +10 -0
  535. package/lib/orchestrator/run-workspace.d.ts.map +1 -0
  536. package/lib/orchestrator/run-workspace.js +58 -0
  537. package/lib/orchestrator/run-workspace.js.map +1 -0
  538. package/lib/orchestrator/suite-compare.d.ts +37 -0
  539. package/lib/orchestrator/suite-compare.d.ts.map +1 -1
  540. package/lib/orchestrator/suite-compare.js +27 -17
  541. package/lib/orchestrator/suite-compare.js.map +1 -1
  542. package/lib/orchestrator/suite-runs.d.ts +6 -1
  543. package/lib/orchestrator/suite-runs.d.ts.map +1 -1
  544. package/lib/orchestrator/suite-runs.js +14 -2
  545. package/lib/orchestrator/suite-runs.js.map +1 -1
  546. package/lib/orchestrator/suite-summary.d.ts +77 -0
  547. package/lib/orchestrator/suite-summary.d.ts.map +1 -1
  548. package/lib/orchestrator/suite-summary.js +61 -12
  549. package/lib/orchestrator/suite-summary.js.map +1 -1
  550. package/lib/previewer/artifacts.d.ts +25 -0
  551. package/lib/previewer/artifacts.d.ts.map +1 -0
  552. package/lib/previewer/artifacts.js +180 -0
  553. package/lib/previewer/artifacts.js.map +1 -0
  554. package/lib/previewer/server.d.ts +111 -0
  555. package/lib/previewer/server.d.ts.map +1 -0
  556. package/lib/previewer/server.js +558 -0
  557. package/lib/previewer/server.js.map +1 -0
  558. package/package.json +3 -3
  559. package/skills/lux-answerer/SKILL.md +2 -2
  560. package/src/answerers/claude-code/index.ts +6 -5
  561. package/src/answerers/persona/index.ts +75 -34
  562. package/src/answerers/terminal/index.ts +8 -12
  563. package/src/assertions/authoring.ts +2 -0
  564. package/src/assertions/core/command-exits-zero.ts +61 -7
  565. package/src/assertions/core/event-checks.ts +64 -3
  566. package/src/assertions/core/helpers.ts +3 -6
  567. package/src/assertions/core/index.ts +2 -0
  568. package/src/assertions/core/resource-checks.ts +38 -5
  569. package/src/assertions/rubric/index.ts +68 -13
  570. package/src/assertions/rubric/internal.ts +227 -27
  571. package/src/authoring.ts +345 -2
  572. package/src/cli/bin.ts +2 -12
  573. package/src/cli/command-runtime.ts +20 -9
  574. package/src/cli/doctor.ts +17 -0
  575. package/src/cli/harness-plan.ts +117 -0
  576. package/src/cli/init-templates.ts +238 -0
  577. package/src/cli/init.ts +53 -184
  578. package/src/cli/output-schemas.ts +106 -0
  579. package/src/cli/program.ts +691 -721
  580. package/src/cli/render/reporter.ts +50 -8
  581. package/src/cli/run-options.ts +132 -25
  582. package/src/cli/view.ts +129 -0
  583. package/src/container/driver.ts +211 -0
  584. package/src/container/protocol.ts +48 -0
  585. package/src/container/resources.ts +153 -0
  586. package/src/container/worker.ts +107 -0
  587. package/src/core/action-events.ts +59 -0
  588. package/src/core/agent-activity.ts +236 -0
  589. package/src/core/agent-environment.ts +64 -0
  590. package/src/core/agent-events.ts +17 -0
  591. package/src/core/annotation.ts +2 -1
  592. package/src/core/answerer.ts +9 -0
  593. package/src/core/artifact-evidence.ts +47 -4
  594. package/src/core/assertion.ts +21 -1
  595. package/src/core/case.ts +21 -3
  596. package/src/core/command-verification.ts +74 -0
  597. package/src/core/driver-execution.ts +84 -0
  598. package/src/core/driver-metrics.ts +51 -0
  599. package/src/core/driver.ts +76 -0
  600. package/src/core/duration.ts +52 -0
  601. package/src/core/environment.ts +22 -0
  602. package/src/core/evaluation-clusters.ts +35 -0
  603. package/src/core/events.ts +14 -2
  604. package/src/core/experiment.ts +64 -24
  605. package/src/core/file-tree.ts +35 -0
  606. package/src/core/global-id.ts +26 -0
  607. package/src/core/harness-catalog.ts +100 -0
  608. package/src/core/harness-catalogs/antigravity.ts +24 -0
  609. package/src/core/harness-catalogs/claude-code.ts +25 -0
  610. package/src/core/harness-catalogs/codex.ts +27 -0
  611. package/src/core/harness-catalogs/copilot.ts +46 -0
  612. package/src/core/harness-catalogs/cursor.ts +13 -0
  613. package/src/core/harness-catalogs/grok-build.ts +19 -0
  614. package/src/core/harness-catalogs/index.ts +31 -0
  615. package/src/core/harness-matrix.ts +316 -0
  616. package/src/core/index.ts +12 -0
  617. package/src/core/lifecycle-fixtures.ts +4 -2
  618. package/src/core/model-cli.ts +52 -23
  619. package/src/core/platform-process.ts +58 -10
  620. package/src/core/run.ts +31 -0
  621. package/src/core/usage.ts +8 -0
  622. package/src/core/wire.ts +5 -1
  623. package/src/drivers/antigravity/README.md +171 -0
  624. package/src/drivers/antigravity/artifacts.ts +37 -0
  625. package/src/drivers/antigravity/config.ts +92 -0
  626. package/src/drivers/antigravity/events.ts +290 -0
  627. package/src/drivers/antigravity/index.ts +132 -0
  628. package/src/drivers/antigravity/runtime.ts +94 -0
  629. package/src/drivers/claude-code/deferred-process.ts +118 -0
  630. package/src/drivers/claude-code/index.ts +216 -281
  631. package/src/drivers/claude-code/isolation.ts +228 -0
  632. package/src/drivers/claude-code/parse-events.ts +98 -12
  633. package/src/drivers/codex/app-events.ts +126 -16
  634. package/src/drivers/codex/config.ts +50 -8
  635. package/src/drivers/codex/exec-events.ts +258 -0
  636. package/src/drivers/codex/index.ts +144 -312
  637. package/src/drivers/copilot/README.md +60 -0
  638. package/src/drivers/copilot/config.ts +61 -0
  639. package/src/drivers/copilot/index.ts +310 -0
  640. package/src/drivers/cursor/README.md +66 -0
  641. package/src/drivers/cursor/config.ts +31 -0
  642. package/src/drivers/cursor/index.ts +326 -0
  643. package/src/drivers/cursor/interaction.ts +74 -0
  644. package/src/drivers/grok-build/README.md +112 -0
  645. package/src/drivers/grok-build/config.ts +43 -0
  646. package/src/drivers/grok-build/index.ts +331 -0
  647. package/src/drivers/mcp/index.ts +25 -11
  648. package/src/drivers/shared/acp-events.ts +94 -0
  649. package/src/drivers/shared/acp-interaction.ts +27 -0
  650. package/src/drivers/shared/acp-session.ts +40 -0
  651. package/src/drivers/shared/acp-transport.ts +187 -0
  652. package/src/drivers/shared/artifacts.ts +6 -2
  653. package/src/drivers/shared/experiment-behavior.ts +214 -0
  654. package/src/drivers/shared/experiment-policy.ts +195 -0
  655. package/src/drivers/subprocess/index.ts +55 -12
  656. package/src/index.ts +115 -10
  657. package/src/optimization/reflective.ts +3 -2
  658. package/src/orchestrator/annotation-loader.ts +10 -0
  659. package/src/orchestrator/annotation-store.ts +24 -3
  660. package/src/orchestrator/artifact-origin.ts +50 -0
  661. package/src/orchestrator/campaign-lifecycle.ts +5 -1
  662. package/src/orchestrator/candidates.ts +3 -2
  663. package/src/orchestrator/compare.ts +41 -6
  664. package/src/orchestrator/comparison-identity.ts +2 -0
  665. package/src/orchestrator/config.ts +20 -3
  666. package/src/orchestrator/discover.ts +8 -1
  667. package/src/orchestrator/doctor.ts +189 -28
  668. package/src/orchestrator/driver-capabilities.ts +21 -0
  669. package/src/orchestrator/driver-identity.ts +69 -0
  670. package/src/orchestrator/experiment-context.ts +3 -2
  671. package/src/orchestrator/experiment-corpus.ts +53 -37
  672. package/src/orchestrator/experiment-effects.ts +61 -0
  673. package/src/orchestrator/experiment-evaluation.ts +71 -10
  674. package/src/orchestrator/experiment-identity.ts +42 -48
  675. package/src/orchestrator/experiment-preflight.ts +27 -0
  676. package/src/orchestrator/experiment-report.ts +21 -1
  677. package/src/orchestrator/experiment-runs.ts +11 -4
  678. package/src/orchestrator/experiment-runtime-identity.ts +5 -243
  679. package/src/orchestrator/experiment-selection.ts +77 -0
  680. package/src/orchestrator/experiment.ts +29 -29
  681. package/src/orchestrator/fixture-identity.ts +9 -1
  682. package/src/orchestrator/fs-read.ts +2 -32
  683. package/src/orchestrator/grader-experiment.ts +74 -13
  684. package/src/orchestrator/grading.ts +67 -28
  685. package/src/orchestrator/harness-catalog-drift.ts +132 -0
  686. package/src/orchestrator/harness-registry.ts +12 -0
  687. package/src/orchestrator/index.ts +1 -0
  688. package/src/orchestrator/list-runs.ts +98 -13
  689. package/src/orchestrator/optimization-lifecycle.ts +4 -1
  690. package/src/orchestrator/orchestrator.ts +92 -216
  691. package/src/orchestrator/paired-effects.ts +209 -0
  692. package/src/orchestrator/provenance.ts +23 -3
  693. package/src/orchestrator/rubric-loader.ts +1 -1
  694. package/src/orchestrator/run-dir.ts +8 -1
  695. package/src/orchestrator/run-execution.ts +77 -11
  696. package/src/orchestrator/run-lifecycle.ts +4 -2
  697. package/src/orchestrator/run-workspace.ts +62 -0
  698. package/src/orchestrator/suite-compare.ts +29 -19
  699. package/src/orchestrator/suite-runs.ts +13 -2
  700. package/src/orchestrator/suite-summary.ts +122 -13
  701. package/src/previewer/artifacts.ts +221 -0
  702. package/src/previewer/server.ts +787 -0
  703. package/viewer/app.css +2079 -0
  704. package/viewer/app.js +627 -0
  705. package/viewer/artifact-view.js +48 -0
  706. package/viewer/charts.js +86 -0
  707. package/viewer/detail.js +1237 -0
  708. package/viewer/format.js +129 -0
  709. package/viewer/index.html +151 -0
  710. package/lib/answerers/scripted/index.d.ts +0 -8
  711. package/lib/answerers/scripted/index.d.ts.map +0 -1
  712. package/lib/answerers/scripted/index.js +0 -163
  713. package/lib/answerers/scripted/index.js.map +0 -1
  714. package/lib/cli/skills.d.ts +0 -38
  715. package/lib/cli/skills.d.ts.map +0 -1
  716. package/lib/cli/skills.js +0 -84
  717. package/lib/cli/skills.js.map +0 -1
  718. package/lib/drivers/shared/secure-copy.d.ts.map +0 -1
  719. package/lib/drivers/shared/secure-copy.js.map +0 -1
  720. package/skills/lux/SKILL.md +0 -85
  721. package/skills/lux/references/cli.md +0 -102
  722. package/skills/lux/references/eval-authoring.md +0 -105
  723. package/src/answerers/scripted/index.ts +0 -186
  724. package/src/cli/skills.ts +0 -129
  725. /package/lib/{drivers/shared → core}/secure-copy.d.ts +0 -0
  726. /package/lib/{drivers/shared → core}/secure-copy.js +0 -0
  727. /package/src/{drivers/shared → core}/secure-copy.ts +0 -0
@@ -1,10 +1,15 @@
1
- import { basename, extname, isAbsolute, join, resolve } from "node:path";
1
+ import { basename, extname, join, resolve } from "node:path";
2
+ import { ContainerDriver } from "../container/driver.js";
3
+ import { driverExecutionOf } from "../core/driver-execution.js";
4
+ import { type EnvironmentDeclaration, EnvironmentDeclarationSchema } from "../core/environment.js";
2
5
  import {
3
6
  type Answerer,
4
7
  type AnswererModelCallAccounting,
5
8
  type AnswererRef,
6
9
  bindSubjectRoot,
7
10
  type DriverRef,
11
+ driverConfigOf,
12
+ driverNameOf,
8
13
  type EvalCase,
9
14
  type GradingAssertionEntry,
10
15
  type GradingReport,
@@ -12,6 +17,7 @@ import {
12
17
  type HarnessModelConfig,
13
18
  type LifecycleHooksPlugin,
14
19
  mergeHarnessModelConfig,
20
+ mergePluginConfig,
15
21
  type Registry,
16
22
  type RunMetadata,
17
23
  type RunObserver,
@@ -24,6 +30,8 @@ import {
24
30
  registryForEvalCase,
25
31
  valuesForFixtures,
26
32
  } from "./case-extensions.js";
33
+ import { isBuiltinDriver } from "./config.js";
34
+ import { validateDriverCapabilities } from "./driver-capabilities.js";
27
35
  import { evaluatorImplementationHash } from "./evaluator-identity.js";
28
36
  import {
29
37
  assertionEvaluatorIdentities,
@@ -102,6 +110,7 @@ const recordLifecycleCleanupFailure = async (result: RunResult, error: unknown):
102
110
  };
103
111
 
104
112
  export type OrchestratorOptions = {
113
+ environment?: EnvironmentDeclaration | undefined;
105
114
  registry: Registry;
106
115
  /** Answerer used when a case names none. Defaults to "persona". */
107
116
  defaultAnswerer?: AnswererRef;
@@ -114,6 +123,8 @@ export type OrchestratorOptions = {
114
123
  };
115
124
 
116
125
  export type RunRequest = {
126
+ /** Effective parent suite worker limit; direct runs default to one. */
127
+ suiteConcurrency?: number | undefined;
117
128
  /** Path to a TS case file. Mutually exclusive with `case`. */
118
129
  casePath?: string;
119
130
  /** Pre-loaded EvalCase. Mutually exclusive with `casePath`. */
@@ -128,6 +139,8 @@ export type RunRequest = {
128
139
  /** Root that relative `fixtures` dir paths resolve against. */
129
140
  fixturesRoot?: string | undefined;
130
141
  answererOverride?: string | undefined;
142
+ /** Skip built-in rubric judge assertions without changing subject execution. */
143
+ skipJudge?: boolean | undefined;
131
144
  startedAt?: Date | undefined;
132
145
  /** The `runSuite` invocation this case attempt belongs to. */
133
146
  suiteId?: string | undefined;
@@ -135,6 +148,12 @@ export type RunRequest = {
135
148
  subjectRoot?: string | undefined;
136
149
  subjectHash?: string | undefined;
137
150
  profileId?: string | undefined;
151
+ /**
152
+ * Driver bound by a harness permutation. It replaces the project default;
153
+ * a case pinned to another driver is rejected rather than silently rerouted.
154
+ */
155
+ driver?: DriverRef | undefined;
156
+ permutationId?: string | undefined;
138
157
  experimentId?: string | undefined;
139
158
  variantId?: string | undefined;
140
159
  candidateId?: string | undefined;
@@ -193,7 +212,13 @@ export type SuiteObserver = RunObserver & {
193
212
  * `caseId` is the canonical id runs are filed under when the case declares
194
213
  * none — display decorations (a `--loop` suffix) must not fork run history.
195
214
  */
196
- export type SuiteItem = { path: string; id: string; caseId?: string | undefined };
215
+ export type SuiteItem = {
216
+ path: string;
217
+ id: string;
218
+ caseId?: string | undefined;
219
+ driver?: DriverRef | undefined;
220
+ permutationId?: string | undefined;
221
+ };
197
222
 
198
223
  const resolveCaseId = (casePath: string, evalCase: EvalCase, fallback?: string): string => {
199
224
  if (evalCase.id) return evalCase.id;
@@ -204,39 +229,30 @@ const resolveCaseId = (casePath: string, evalCase: EvalCase, fallback?: string):
204
229
  return ext ? base.slice(0, -ext.length) : base;
205
230
  };
206
231
 
207
- const driverNameOf = (ref: DriverRef): string => (typeof ref === "string" ? ref : ref.name);
208
-
209
- const isRecord = (value: unknown): value is Record<string, unknown> =>
210
- Boolean(value) && typeof value === "object" && !Array.isArray(value);
211
-
212
- /** Merge plugin config recursively so nested Codex `config`/`env` overrides stay additive. */
213
- const mergePluginConfig = (base: unknown, local: unknown): unknown => {
214
- if (!isRecord(base) || !isRecord(local)) return local ?? base;
215
- const merged: Record<string, unknown> = { ...base };
216
- for (const [key, value] of Object.entries(local)) {
217
- merged[key] = key in merged ? mergePluginConfig(merged[key], value) : value;
218
- }
219
- return merged;
220
- };
221
-
222
232
  export const resolveDriverReference = (
223
233
  evalCase: EvalCase,
224
234
  fallback: DriverRef | undefined,
235
+ permutation?: DriverRef | undefined,
225
236
  ): DriverRef => {
226
237
  const local = evalCase.driver;
238
+ if (permutation && local && driverNameOf(local) !== driverNameOf(permutation)) {
239
+ throw new Error(
240
+ `case is pinned to driver '${driverNameOf(local)}' but the run selected '${driverNameOf(permutation)}'`,
241
+ );
242
+ }
243
+ const base = permutation ?? fallback;
227
244
  if (!local) {
228
- if (!fallback) throw new Error("case names no driver and no defaultDriver is configured");
229
- return fallback;
245
+ if (!base) throw new Error("case names no driver and no defaultDriver is configured");
246
+ return base;
230
247
  }
231
- if (!fallback || driverNameOf(local) !== driverNameOf(fallback)) return local;
248
+ if (!base || driverNameOf(local) !== driverNameOf(base)) return local;
232
249
 
233
250
  // Naming the same driver opts into project defaults. A case object only
234
251
  // needs to carry the fields it wants to override (for example a timeout).
235
- const baseConfig = typeof fallback === "object" ? fallback.config : undefined;
236
- const localConfig = typeof local === "object" ? local.config : undefined;
237
252
  return {
238
253
  name: driverNameOf(local),
239
- config: mergePluginConfig(baseConfig, localConfig),
254
+ config: mergePluginConfig(driverConfigOf(base), driverConfigOf(local)),
255
+ execution: driverExecutionOf(local) ?? driverExecutionOf(base),
240
256
  };
241
257
  };
242
258
 
@@ -257,197 +273,25 @@ export const resolveAnswererReference = (
257
273
 
258
274
  const answererNameOf = (ref: AnswererRef): string => (typeof ref === "string" ? ref : ref.name);
259
275
 
260
- const driverConfigOf = (ref: DriverRef): unknown =>
261
- typeof ref === "object" ? ref.config : undefined;
262
-
263
276
  const answererConfigOf = (ref: AnswererRef): unknown =>
264
277
  typeof ref === "object" ? ref.config : undefined;
265
278
 
266
- const EXPERIMENT_BEHAVIOR_SOURCE_ARGS = new Set([
267
- "--continue",
268
- "-c",
269
- "--fork-session",
270
- "--resume",
271
- "-r",
272
- "--add-dir",
273
- "--append-system-prompt-file",
274
- "--mcp-config",
275
- "--plugin-dir",
276
- "--settings",
277
- "--setting-sources",
278
- "--system-prompt-file",
279
- ]);
280
-
281
- const CODEX_EXPERIMENT_SOURCE_ARGS = new Set([
282
- "--add-dir",
283
- "--cd",
284
- "-C",
285
- "--config",
286
- "-c",
287
- "--profile",
288
- "-p",
289
- ]);
290
-
291
- const bindSubprocessExperimentConfig = (config: Record<string, unknown>): unknown => {
292
- if (typeof config.command !== "string" || !isAbsolute(config.command)) {
293
- throw new Error(
294
- "experiment subprocess commands must be absolute direct wrappers so Lux can fingerprint the invoked behavior",
295
- );
296
- }
297
- if (typeof config.cwd === "string") {
298
- throw new Error(
299
- "experiment runs do not allow an explicit subprocess cwd; use the candidate subject and staged fixtures",
300
- );
301
- }
302
- if (Array.isArray(config.args) && config.args.length > 0) {
303
- throw new Error(
304
- "experiment subprocesses do not allow args; put stable behavior in the fingerprinted direct wrapper",
305
- );
306
- }
307
- if (isRecord(config.env) && Object.keys(config.env).length > 0) {
308
- throw new Error(
309
- "experiment subprocesses do not allow custom env; put stable behavior in the fingerprinted direct wrapper",
310
- );
311
- }
312
- return { ...config, inheritEnv: false };
313
- };
314
-
315
- type AgentDriverName = "claude-code" | "codex";
316
-
317
- const validateAgentExperimentConfig = (
318
- driverName: AgentDriverName,
319
- config: Record<string, unknown>,
320
- ): { driverEnv: Record<string, unknown>; extraArgs: string[] } => {
321
- const driverEnv = isRecord(config.env) ? config.env : {};
322
- const commandResolutionOverride = Object.keys(driverEnv).find((name) =>
323
- ["PATH", "PATHEXT"].includes(name.toUpperCase()),
324
- );
325
- if (commandResolutionOverride) {
326
- throw new Error(
327
- `experiment runs do not allow driver env.${commandResolutionOverride}; command resolution must match the fingerprinted host executable`,
328
- );
329
- }
330
- if (typeof config.cwd === "string") {
331
- throw new Error(
332
- `experiment runs do not allow an explicit ${driverName} cwd; use the candidate subject and staged fixtures`,
333
- );
334
- }
335
-
336
- const extraArgs = Array.isArray(config.extraArgs)
337
- ? config.extraArgs.filter((value): value is string => typeof value === "string")
338
- : [];
339
- const disallowedArgs =
340
- driverName === "claude-code" ? EXPERIMENT_BEHAVIOR_SOURCE_ARGS : CODEX_EXPERIMENT_SOURCE_ARGS;
341
- const behaviorSourceArg = extraArgs.find((arg) =>
342
- [...disallowedArgs].some((name) => arg === name || arg.startsWith(`${name}=`)),
343
- );
344
- if (behaviorSourceArg) {
345
- throw new Error(
346
- `experiment runs do not allow behavior-bearing extraArgs '${behaviorSourceArg}'; use structured driver fields so Lux can fingerprint the source`,
347
- );
348
- }
349
-
350
- const isolation = isRecord(config.isolation) ? config.isolation : {};
351
- const structuredPaths = [
352
- ...(driverName === "claude-code" && Array.isArray(config.pluginDirs) ? config.pluginDirs : []),
353
- ...(Array.isArray(config.addDirs) ? config.addDirs : []),
354
- ...(driverName === "claude-code" && Array.isArray(isolation.allowRead)
355
- ? isolation.allowRead
356
- : []),
357
- ].filter((value): value is string => typeof value === "string");
358
- const relativeSource = structuredPaths.find((path) => !isAbsolute(path));
359
- if (relativeSource) {
360
- throw new Error(
361
- `experiment driver source paths must be absolute after subjectPath binding: ${relativeSource}`,
362
- );
363
- }
364
- return { driverEnv, extraArgs };
365
- };
366
-
367
- const bindCodexExperimentConfig = (
368
- config: Record<string, unknown>,
369
- extraArgs: readonly string[],
370
- ): unknown => {
371
- if (typeof config.profile === "string") {
372
- throw new Error(
373
- "experiment runs do not allow a Codex profile; use inline driver config so Lux can fingerprint it",
374
- );
375
- }
376
- if (config.ephemeral === false) {
377
- throw new Error("experiment runs require ephemeral Codex sessions");
378
- }
379
- const inlineConfig = isRecord(config.config) ? config.config : {};
380
- const externalConfigKey = ((): string | undefined => {
381
- const visit = (value: Record<string, unknown>, parent = ""): string | undefined => {
382
- for (const [key, nested] of Object.entries(value)) {
383
- const path = parent ? `${parent}.${key}` : key;
384
- if (/(?:mcp_servers|instructions_file|notify|project_doc)/i.test(key)) return path;
385
- if (isRecord(nested)) {
386
- const found = visit(nested, path);
387
- if (found) return found;
388
- }
389
- }
390
- return undefined;
391
- };
392
- return visit(inlineConfig);
393
- })();
394
- if (externalConfigKey) {
395
- throw new Error(
396
- `experiment runs do not allow path-bearing Codex config '${externalConfigKey}'`,
397
- );
398
- }
399
- const appServer = config.interactionMode !== "exec";
400
- return {
401
- ...config,
402
- ephemeral: true,
403
- ignoreUserConfig: true,
404
- ignoreRules: true,
405
- ...(appServer && !config.isolation ? { isolation: { allowRead: [] } } : {}),
406
- extraArgs,
407
- };
408
- };
409
-
410
- const bindClaudeExperimentConfig = (
411
- config: Record<string, unknown>,
412
- extraArgs: readonly string[],
413
- driverEnv: Record<string, unknown>,
414
- ): unknown => {
415
- if (config.isolation) return config;
416
- return {
417
- ...config,
418
- extraArgs: [
419
- ...extraArgs,
420
- "--setting-sources",
421
- "user",
422
- "--strict-mcp-config",
423
- "--settings",
424
- JSON.stringify({ disableAllHooks: true }),
425
- ],
426
- env: {
427
- ...driverEnv,
428
- CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1",
429
- CLAUDE_CODE_DISABLE_CLAUDE_MDS: "1",
430
- CLAUDE_CODE_SKIP_PROMPT_HISTORY: "1",
431
- CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: "1",
432
- CLAUDE_CODE_AUTO_CONNECT_IDE: "false",
433
- CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL: "1",
434
- DISABLE_AUTOUPDATER: "1",
435
- },
436
- };
437
- };
438
-
439
279
  export const boundExperimentDriverConfig = (
440
- driverName: string,
280
+ plugin: import("../core/driver.js").DriverPlugin,
441
281
  config: unknown,
442
282
  experimentId: string | undefined,
443
283
  ): unknown => {
444
- if (!experimentId || !isRecord(config)) return config;
445
- if (driverName === "subprocess") return bindSubprocessExperimentConfig(config);
446
- if (driverName !== "claude-code" && driverName !== "codex") return config;
447
- const { driverEnv, extraArgs } = validateAgentExperimentConfig(driverName, config);
448
- return driverName === "codex"
449
- ? bindCodexExperimentConfig(config, extraArgs)
450
- : bindClaudeExperimentConfig(config, extraArgs, driverEnv);
284
+ if (!experimentId) return config;
285
+ if (!plugin.experiment) {
286
+ throw new Error(
287
+ `driver '${plugin.name}' supports ordinary eval runs but does not declare controlled experiment support`,
288
+ );
289
+ }
290
+ return validatePluginConfig(
291
+ plugin.configSchema,
292
+ plugin.experiment.prepare(config),
293
+ `driver '${plugin.name}' experiment configuration`,
294
+ );
451
295
  };
452
296
 
453
297
  const closeQuietly = async (close: () => Promise<void>, label: string): Promise<void> => {
@@ -461,6 +305,7 @@ const closeQuietly = async (close: () => Promise<void>, label: string): Promise<
461
305
  };
462
306
 
463
307
  export class Orchestrator {
308
+ private readonly environment: EnvironmentDeclaration | undefined;
464
309
  private evaluatorHash: Promise<string> | undefined;
465
310
  readonly registry: Registry;
466
311
  private readonly defaultAnswerer: AnswererRef;
@@ -469,6 +314,9 @@ export class Orchestrator {
469
314
  private readonly lifecycleFixtures: readonly LifecycleHooksPlugin[];
470
315
 
471
316
  constructor(options: OrchestratorOptions) {
317
+ this.environment = options.environment
318
+ ? EnvironmentDeclarationSchema.parse(options.environment)
319
+ : undefined;
472
320
  this.registry = options.registry;
473
321
  this.defaultAnswerer = options.defaultAnswerer ?? "persona";
474
322
  this.defaultDriver = options.defaultDriver;
@@ -510,13 +358,19 @@ export class Orchestrator {
510
358
  registry,
511
359
  );
512
360
 
513
- const driverRef = resolveDriverReference(evalCase, this.defaultDriver);
361
+ const driverRef = bindSubjectRoot(
362
+ resolveDriverReference(evalCase, this.defaultDriver, request.driver),
363
+ request.subjectRoot,
364
+ );
514
365
  const driverName = driverNameOf(driverRef);
515
- const answererRef = resolveAnswererReference(
516
- evalCase,
517
- this.defaultAnswerer,
518
- this.harness,
519
- request.answererOverride,
366
+ const answererRef = bindSubjectRoot(
367
+ resolveAnswererReference(
368
+ evalCase,
369
+ this.defaultAnswerer,
370
+ this.harness,
371
+ request.answererOverride,
372
+ ),
373
+ request.subjectRoot,
520
374
  );
521
375
  const answererName = answererNameOf(answererRef);
522
376
 
@@ -532,7 +386,7 @@ export class Orchestrator {
532
386
  // Validate both configs before instantiating either plugin so a
533
387
  // schema failure can't leak a half-initialized driver/answerer.
534
388
  const driverCfg = boundExperimentDriverConfig(
535
- driverName,
389
+ driverPlugin,
536
390
  validatePluginConfig(
537
391
  driverPlugin.configSchema,
538
392
  driverConfigOf(driverRef),
@@ -546,7 +400,20 @@ export class Orchestrator {
546
400
  `answerer '${answererName}'`,
547
401
  );
548
402
 
549
- const driver = await driverPlugin.create(driverCfg);
403
+ const execution = driverExecutionOf(driverRef);
404
+ if (execution?.kind === "container" && request.experimentId)
405
+ throw new Error("container execution does not yet support controlled experiments");
406
+ if (
407
+ execution?.kind === "container" &&
408
+ !execution.driverModule &&
409
+ !isBuiltinDriver(driverPlugin)
410
+ )
411
+ throw new Error("custom container drivers require execution.driverModule in the image");
412
+ validateDriverCapabilities(driverPlugin, driverCfg, evalCase.requires, execution);
413
+ const driver =
414
+ execution?.kind === "container"
415
+ ? new ContainerDriver(driverName, driverCfg, execution)
416
+ : await driverPlugin.create(driverCfg);
550
417
  let answerer: Answerer;
551
418
  try {
552
419
  answerer = await answererPlugin.create(answererCfg);
@@ -568,6 +435,7 @@ export class Orchestrator {
568
435
  assertions: assertionImplementations,
569
436
  validatedAssertionsHash,
570
437
  graderContext: this.harness,
438
+ skipJudge: request.skipJudge ?? false,
571
439
  });
572
440
  return await this.runWithPlugins(
573
441
  {
@@ -578,9 +446,10 @@ export class Orchestrator {
578
446
  validatedAssertionConfigs,
579
447
  caseId,
580
448
  driverName,
449
+ permutationId: request.permutationId,
581
450
  answererName,
582
451
  answererConfig: answererCfg,
583
- driverConfigHash: valueHash(driverCfg),
452
+ driverConfigHash: valueHash(execution ? { config: driverCfg, execution } : driverCfg),
584
453
  answererConfigHash: valueHash(answererCfg),
585
454
  validatedAssertionsHash,
586
455
  graderConfigHash: graderHash,
@@ -593,8 +462,10 @@ export class Orchestrator {
593
462
  assertions: assertionImplementations,
594
463
  lifecycleFixtures,
595
464
  validatedAssertionsHash,
465
+ skipJudge: request.skipJudge ?? false,
596
466
  }),
597
467
  fixtureValues: valuesForFixtures(lifecycleFixtures),
468
+ environment: this.environment,
598
469
  driver,
599
470
  answerer,
600
471
  },
@@ -617,6 +488,7 @@ export class Orchestrator {
617
488
  runsRoot: string;
618
489
  fixturesRoot?: string | undefined;
619
490
  answererOverride?: string | undefined;
491
+ skipJudge?: boolean | undefined;
620
492
  observer?: SuiteObserver | undefined;
621
493
  /** Aborts the cases in flight and stops the pool pulling new ones. */
622
494
  abortSignal?: AbortSignal | undefined;
@@ -788,12 +660,16 @@ export class Orchestrator {
788
660
  runsRoot: opts.runsRoot,
789
661
  fixturesRoot: opts.fixturesRoot,
790
662
  answererOverride: opts.answererOverride,
663
+ skipJudge: opts.skipJudge,
791
664
  observer: handle ?? observer,
792
665
  abortSignal: opts.abortSignal,
793
666
  suiteId: suite.manifest.suiteId,
667
+ suiteConcurrency: concurrency,
794
668
  subjectRoot: opts.subjectRoot,
795
669
  subjectHash: opts.subjectHash,
796
670
  profileId: opts.profileId,
671
+ driver: item.driver,
672
+ permutationId: item.permutationId,
797
673
  experimentId: opts.experimentId,
798
674
  variantId: opts.variantId,
799
675
  candidateId: opts.candidateId,
@@ -0,0 +1,209 @@
1
+ import { z } from "zod";
2
+ import { clusterKey } from "../core/evaluation-clusters.js";
3
+ import {
4
+ bootstrapMeanConfidenceInterval,
5
+ type CandidateEvaluation,
6
+ type ConfidenceConfig,
7
+ ConfidenceIntervalSchema,
8
+ } from "../core/index.js";
9
+
10
+ type CaseSamples = NonNullable<CandidateEvaluation["caseSamples"]>;
11
+ type Evaluation = CandidateEvaluation & { repetitions: number };
12
+
13
+ export const clusterCaseSamples = (
14
+ groups: readonly (CaseSamples | undefined)[],
15
+ ): CaseSamples | undefined => {
16
+ if (groups.some((group) => group === undefined)) return undefined;
17
+ const result = new Map<string, CaseSamples[string]>();
18
+ for (const group of groups) {
19
+ for (const [id, sample] of Object.entries(group ?? {})) {
20
+ const current = result.get(id);
21
+ if (!current) {
22
+ result.set(id, structuredClone(sample));
23
+ continue;
24
+ }
25
+ if (current.identityHash !== sample.identityHash) current.identityHash = null;
26
+ if (current.clusterId !== sample.clusterId) current.identityHash = null;
27
+ const metrics = new Map(Object.entries(current.metrics));
28
+ for (const [metric, value] of Object.entries(sample.metrics)) {
29
+ const before = metrics.get(metric);
30
+ metrics.set(
31
+ metric,
32
+ before
33
+ ? {
34
+ mean: (before.mean * before.n + value.mean * value.n) / (before.n + value.n),
35
+ n: before.n + value.n,
36
+ }
37
+ : { ...value },
38
+ );
39
+ }
40
+ current.metrics = Object.fromEntries(metrics);
41
+ }
42
+ }
43
+ return Object.fromEntries(result);
44
+ };
45
+
46
+ const caseGroups = (samples: CaseSamples): Map<string, string[]> => {
47
+ const groups = new Map<string, string[]>();
48
+ for (const id of Object.keys(samples).sort()) {
49
+ const key = clusterKey(id, samples[id]?.clusterId);
50
+ groups.set(key, [...(groups.get(key) ?? []), id]);
51
+ }
52
+ return groups;
53
+ };
54
+
55
+ export const groupedCaseMetricSamples = (
56
+ samples: CaseSamples | undefined,
57
+ repetitions: number,
58
+ ): Record<string, number[]> | undefined => {
59
+ if (!samples || !Object.values(samples).some((sample) => sample.clusterId !== undefined))
60
+ return undefined;
61
+ const groups = caseGroups(samples);
62
+ const metrics = new Set(Object.values(samples).flatMap((sample) => Object.keys(sample.metrics)));
63
+ return Object.fromEntries(
64
+ [...metrics].flatMap((metric) => {
65
+ if (
66
+ Object.values(samples).some(
67
+ (sample) =>
68
+ !Object.hasOwn(sample.metrics, metric) || sample.metrics[metric]?.n !== repetitions,
69
+ )
70
+ )
71
+ return [];
72
+ return [
73
+ [
74
+ metric,
75
+ [...groups.values()].map(
76
+ (ids) =>
77
+ ids.reduce((sum, id) => sum + (samples[id]?.metrics[metric]?.mean ?? 0), 0) /
78
+ ids.length,
79
+ ),
80
+ ],
81
+ ];
82
+ }),
83
+ );
84
+ };
85
+
86
+ export const PairedEffectSchema = z.object({
87
+ caseIds: z.array(z.string()),
88
+ n: z.number().int().nonnegative(),
89
+ caseCount: z.number().int().nonnegative().optional(),
90
+ clusters: z.record(z.string(), z.array(z.string())).optional(),
91
+ meanDelta: z.number().finite().nullable(),
92
+ interval: ConfidenceIntervalSchema.nullable(),
93
+ note: z.string().nullable(),
94
+ });
95
+ export type PairedEffect = z.infer<typeof PairedEffectSchema>;
96
+
97
+ export const confidenceGateIssue = (
98
+ interval: z.infer<typeof ConfidenceIntervalSchema>,
99
+ ): string | undefined =>
100
+ interval.method === "percentile-bootstrap" && interval.lower === interval.upper
101
+ ? "zero-width percentile-bootstrap interval cannot establish promotion confidence; use Hoeffding for bounded means or collect more varied independent evidence"
102
+ : undefined;
103
+
104
+ const pairedDeltas = (
105
+ before: Evaluation | undefined,
106
+ after: Evaluation | undefined,
107
+ metric: string,
108
+ ): { caseIds: string[]; values: number[]; clusters: Record<string, string[]> } => {
109
+ if (!before?.caseSamples || !after?.caseSamples)
110
+ throw new Error("keyed case evidence unavailable");
111
+ if (
112
+ before.profileId !== after.profileId ||
113
+ before.split !== after.split ||
114
+ before.repetitions !== after.repetitions
115
+ ) {
116
+ throw new Error("paired evidence requires matching profile, split, and repetitions");
117
+ }
118
+ const caseIds = Object.keys(before.caseSamples).sort();
119
+ const afterIds = Object.keys(after.caseSamples).sort();
120
+ const beforeCases = Object.keys(before.casePassRates).sort();
121
+ const afterCases = Object.keys(after.casePassRates).sort();
122
+ if (
123
+ caseIds.length === 0 ||
124
+ [afterIds, beforeCases, afterCases].some(
125
+ (ids) => JSON.stringify(ids) !== JSON.stringify(caseIds),
126
+ )
127
+ ) {
128
+ throw new Error("paired evidence requires identical canonical case sets");
129
+ }
130
+ const values = caseIds.map((id) => {
131
+ const a = before.caseSamples?.[id];
132
+ const b = after.caseSamples?.[id];
133
+ if (!a?.identityHash || a.identityHash !== b?.identityHash)
134
+ throw new Error(`paired case '${id}' has incompatible evaluation identity`);
135
+ if (a.clusterId !== b.clusterId)
136
+ throw new Error(`paired case '${id}' has incompatible cluster membership`);
137
+ const av = Object.hasOwn(a.metrics, metric) ? a.metrics[metric] : undefined;
138
+ const bv = Object.hasOwn(b.metrics, metric) ? b.metrics[metric] : undefined;
139
+ if (!av || !bv || av.n !== before.repetitions || bv.n !== after.repetitions) {
140
+ throw new Error(
141
+ `paired metric '${metric}' lacks complete repetition coverage for case '${id}'`,
142
+ );
143
+ }
144
+ return bv.mean - av.mean;
145
+ });
146
+ const byCase = new Map(caseIds.map((id, index) => [id, values[index] ?? 0]));
147
+ const groups = caseGroups(before.caseSamples);
148
+ return {
149
+ caseIds,
150
+ clusters: Object.fromEntries(groups),
151
+ values: [...groups.values()].map(
152
+ (ids) => ids.reduce((sum, id) => sum + (byCase.get(id) ?? 0), 0) / ids.length,
153
+ ),
154
+ };
155
+ };
156
+
157
+ export const pairedEffect = (
158
+ before: Evaluation | undefined,
159
+ after: Evaluation | undefined,
160
+ metric: string,
161
+ confidence?: ConfidenceConfig,
162
+ ): PairedEffect => {
163
+ let paired: ReturnType<typeof pairedDeltas>;
164
+ try {
165
+ paired = pairedDeltas(before, after, metric);
166
+ } catch (error) {
167
+ return {
168
+ caseIds: [],
169
+ n: 0,
170
+ caseCount: 0,
171
+ clusters: {},
172
+ meanDelta: null,
173
+ interval: null,
174
+ note: error instanceof Error ? error.message : String(error),
175
+ };
176
+ }
177
+ const result: PairedEffect = {
178
+ caseIds: paired.caseIds,
179
+ n: paired.values.length,
180
+ caseCount: paired.caseIds.length,
181
+ clusters: paired.clusters,
182
+ meanDelta: paired.values.reduce((sum, value) => sum + value, 0) / paired.values.length,
183
+ interval: null,
184
+ note: null,
185
+ };
186
+ if (!confidence) return result;
187
+ try {
188
+ if (confidence.method === "wilson")
189
+ throw new Error("Wilson cannot estimate paired differences");
190
+ if (confidence.method === "hoeffding") {
191
+ const interval = bootstrapMeanConfidenceInterval(
192
+ paired.values.map((value) => (value + 1) / 2),
193
+ confidence,
194
+ );
195
+ result.interval = {
196
+ ...interval,
197
+ estimate: 2 * interval.estimate - 1,
198
+ lower: 2 * interval.lower - 1,
199
+ upper: 2 * interval.upper - 1,
200
+ };
201
+ } else {
202
+ result.interval = bootstrapMeanConfidenceInterval(paired.values, confidence);
203
+ }
204
+ result.note = confidenceGateIssue(result.interval) ?? null;
205
+ } catch (error) {
206
+ result.note = error instanceof Error ? error.message : String(error);
207
+ }
208
+ return result;
209
+ };