@prismatic-io/lux 0.0.2-preview.4 → 0.0.2-preview.40

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 (753) 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 +6 -4
  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 +5 -2
  17. package/lib/assertions/core/command-exits-zero.d.ts.map +1 -1
  18. package/lib/assertions/core/command-exits-zero.js +59 -14
  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/index.d.ts.map +1 -1
  27. package/lib/assertions/core/index.js +2 -1
  28. package/lib/assertions/core/index.js.map +1 -1
  29. package/lib/assertions/core/json-pointer-equals.d.ts +1 -0
  30. package/lib/assertions/core/json-pointer-equals.d.ts.map +1 -1
  31. package/lib/assertions/core/output-checks.d.ts +3 -0
  32. package/lib/assertions/core/output-checks.d.ts.map +1 -1
  33. package/lib/assertions/core/predicate.d.ts +1 -0
  34. package/lib/assertions/core/predicate.d.ts.map +1 -1
  35. package/lib/assertions/core/resource-checks.d.ts +25 -0
  36. package/lib/assertions/core/resource-checks.d.ts.map +1 -1
  37. package/lib/assertions/core/resource-checks.js +35 -5
  38. package/lib/assertions/core/resource-checks.js.map +1 -1
  39. package/lib/assertions/core/safe-regex.d.ts.map +1 -1
  40. package/lib/assertions/core/safe-regex.js +7 -1
  41. package/lib/assertions/core/safe-regex.js.map +1 -1
  42. package/lib/assertions/rubric/evidence.d.ts +88 -0
  43. package/lib/assertions/rubric/evidence.d.ts.map +1 -0
  44. package/lib/assertions/rubric/evidence.js +75 -0
  45. package/lib/assertions/rubric/evidence.js.map +1 -0
  46. package/lib/assertions/rubric/index.d.ts +88 -34
  47. package/lib/assertions/rubric/index.d.ts.map +1 -1
  48. package/lib/assertions/rubric/index.js +59 -43
  49. package/lib/assertions/rubric/index.js.map +1 -1
  50. package/lib/assertions/rubric/internal.d.ts +30 -5
  51. package/lib/assertions/rubric/internal.d.ts.map +1 -1
  52. package/lib/assertions/rubric/internal.js +203 -41
  53. package/lib/assertions/rubric/internal.js.map +1 -1
  54. package/lib/authoring.d.ts +37 -2
  55. package/lib/authoring.d.ts.map +1 -1
  56. package/lib/authoring.js +36 -1
  57. package/lib/authoring.js.map +1 -1
  58. package/lib/cli/bin.js +2 -13
  59. package/lib/cli/bin.js.map +1 -1
  60. package/lib/cli/command-runtime.d.ts +3 -3
  61. package/lib/cli/command-runtime.d.ts.map +1 -1
  62. package/lib/cli/command-runtime.js +17 -6
  63. package/lib/cli/command-runtime.js.map +1 -1
  64. package/lib/cli/doctor.d.ts +55 -0
  65. package/lib/cli/doctor.d.ts.map +1 -0
  66. package/lib/cli/doctor.js +14 -0
  67. package/lib/cli/doctor.js.map +1 -0
  68. package/lib/cli/harness-plan.d.ts +27 -0
  69. package/lib/cli/harness-plan.d.ts.map +1 -0
  70. package/lib/cli/harness-plan.js +75 -0
  71. package/lib/cli/harness-plan.js.map +1 -0
  72. package/lib/cli/init-templates.d.ts +11 -0
  73. package/lib/cli/init-templates.d.ts.map +1 -0
  74. package/lib/cli/init-templates.js +215 -0
  75. package/lib/cli/init-templates.js.map +1 -0
  76. package/lib/cli/init.d.ts +10 -0
  77. package/lib/cli/init.d.ts.map +1 -1
  78. package/lib/cli/init.js +34 -173
  79. package/lib/cli/init.js.map +1 -1
  80. package/lib/cli/output-schemas.d.ts +1412 -0
  81. package/lib/cli/output-schemas.d.ts.map +1 -0
  82. package/lib/cli/output-schemas.js +94 -0
  83. package/lib/cli/output-schemas.js.map +1 -0
  84. package/lib/cli/program.d.ts +140 -12
  85. package/lib/cli/program.d.ts.map +1 -1
  86. package/lib/cli/program.js +783 -650
  87. package/lib/cli/program.js.map +1 -1
  88. package/lib/cli/render/format.d.ts.map +1 -1
  89. package/lib/cli/render/format.js +1 -1
  90. package/lib/cli/render/format.js.map +1 -1
  91. package/lib/cli/render/reporter.d.ts.map +1 -1
  92. package/lib/cli/render/reporter.js +35 -8
  93. package/lib/cli/render/reporter.js.map +1 -1
  94. package/lib/cli/run-options.d.ts +19 -4
  95. package/lib/cli/run-options.d.ts.map +1 -1
  96. package/lib/cli/run-options.js +100 -19
  97. package/lib/cli/run-options.js.map +1 -1
  98. package/lib/cli/view.d.ts +15 -0
  99. package/lib/cli/view.d.ts.map +1 -0
  100. package/lib/cli/view.js +168 -0
  101. package/lib/cli/view.js.map +1 -0
  102. package/lib/container/driver.d.ts +27 -0
  103. package/lib/container/driver.d.ts.map +1 -0
  104. package/lib/container/driver.js +199 -0
  105. package/lib/container/driver.js.map +1 -0
  106. package/lib/container/paths.d.ts +3 -0
  107. package/lib/container/paths.d.ts.map +1 -0
  108. package/lib/container/paths.js +27 -0
  109. package/lib/container/paths.js.map +1 -0
  110. package/lib/container/protocol.d.ts +12 -0
  111. package/lib/container/protocol.d.ts.map +1 -0
  112. package/lib/container/protocol.js +38 -0
  113. package/lib/container/protocol.js.map +1 -0
  114. package/lib/container/resources.d.ts +14 -0
  115. package/lib/container/resources.d.ts.map +1 -0
  116. package/lib/container/resources.js +141 -0
  117. package/lib/container/resources.js.map +1 -0
  118. package/lib/container/worker.d.ts +2 -0
  119. package/lib/container/worker.d.ts.map +1 -0
  120. package/lib/container/worker.js +85 -0
  121. package/lib/container/worker.js.map +1 -0
  122. package/lib/core/action-events.d.ts +29 -0
  123. package/lib/core/action-events.d.ts.map +1 -0
  124. package/lib/core/action-events.js +51 -0
  125. package/lib/core/action-events.js.map +1 -0
  126. package/lib/core/agent-activity.d.ts +49 -0
  127. package/lib/core/agent-activity.d.ts.map +1 -0
  128. package/lib/core/agent-activity.js +206 -0
  129. package/lib/core/agent-activity.js.map +1 -0
  130. package/lib/core/agent-environment.d.ts +5 -0
  131. package/lib/core/agent-environment.d.ts.map +1 -0
  132. package/lib/core/agent-environment.js +47 -0
  133. package/lib/core/agent-environment.js.map +1 -0
  134. package/lib/core/agent-events.d.ts +26 -0
  135. package/lib/core/agent-events.d.ts.map +1 -0
  136. package/lib/core/agent-events.js +13 -0
  137. package/lib/core/agent-events.js.map +1 -0
  138. package/lib/core/annotation.d.ts +6 -2
  139. package/lib/core/annotation.d.ts.map +1 -1
  140. package/lib/core/annotation.js +2 -1
  141. package/lib/core/annotation.js.map +1 -1
  142. package/lib/core/answerer.d.ts +12 -0
  143. package/lib/core/answerer.d.ts.map +1 -1
  144. package/lib/core/answerer.js +2 -0
  145. package/lib/core/answerer.js.map +1 -1
  146. package/lib/core/artifact-evidence.d.ts +6 -1
  147. package/lib/core/artifact-evidence.d.ts.map +1 -1
  148. package/lib/core/artifact-evidence.js +27 -6
  149. package/lib/core/artifact-evidence.js.map +1 -1
  150. package/lib/core/assertion.d.ts +10 -4
  151. package/lib/core/assertion.d.ts.map +1 -1
  152. package/lib/core/assertion.js +8 -2
  153. package/lib/core/assertion.js.map +1 -1
  154. package/lib/core/case-defaults.d.ts +16 -0
  155. package/lib/core/case-defaults.d.ts.map +1 -0
  156. package/lib/core/case-defaults.js +42 -0
  157. package/lib/core/case-defaults.js.map +1 -0
  158. package/lib/core/case.d.ts +120 -6
  159. package/lib/core/case.d.ts.map +1 -1
  160. package/lib/core/case.js +51 -5
  161. package/lib/core/case.js.map +1 -1
  162. package/lib/core/command-verification.d.ts +10 -0
  163. package/lib/core/command-verification.d.ts.map +1 -0
  164. package/lib/core/command-verification.js +66 -0
  165. package/lib/core/command-verification.js.map +1 -0
  166. package/lib/core/driver-execution.d.ts +83 -0
  167. package/lib/core/driver-execution.d.ts.map +1 -0
  168. package/lib/core/driver-execution.js +72 -0
  169. package/lib/core/driver-execution.js.map +1 -0
  170. package/lib/core/driver-metrics.d.ts +98 -0
  171. package/lib/core/driver-metrics.d.ts.map +1 -0
  172. package/lib/core/driver-metrics.js +36 -0
  173. package/lib/core/driver-metrics.js.map +1 -0
  174. package/lib/core/driver.d.ts +64 -0
  175. package/lib/core/driver.d.ts.map +1 -1
  176. package/lib/core/driver.js +28 -0
  177. package/lib/core/driver.js.map +1 -1
  178. package/lib/core/duration.d.ts +5 -0
  179. package/lib/core/duration.d.ts.map +1 -0
  180. package/lib/core/duration.js +49 -0
  181. package/lib/core/duration.js.map +1 -0
  182. package/lib/core/environment.d.ts +18 -0
  183. package/lib/core/environment.d.ts.map +1 -0
  184. package/lib/core/environment.js +21 -0
  185. package/lib/core/environment.js.map +1 -0
  186. package/lib/core/evaluation-clusters.d.ts +17 -0
  187. package/lib/core/evaluation-clusters.d.ts.map +1 -0
  188. package/lib/core/evaluation-clusters.js +23 -0
  189. package/lib/core/evaluation-clusters.js.map +1 -0
  190. package/lib/core/events.d.ts +34 -0
  191. package/lib/core/events.d.ts.map +1 -1
  192. package/lib/core/events.js +11 -2
  193. package/lib/core/events.js.map +1 -1
  194. package/lib/core/experiment.d.ts +33 -2
  195. package/lib/core/experiment.d.ts.map +1 -1
  196. package/lib/core/experiment.js +40 -19
  197. package/lib/core/experiment.js.map +1 -1
  198. package/lib/core/file-tree.d.ts +7 -0
  199. package/lib/core/file-tree.d.ts.map +1 -0
  200. package/lib/core/file-tree.js +35 -0
  201. package/lib/core/file-tree.js.map +1 -0
  202. package/lib/core/global-id.d.ts +6 -0
  203. package/lib/core/global-id.d.ts.map +1 -0
  204. package/lib/core/global-id.js +17 -0
  205. package/lib/core/global-id.js.map +1 -0
  206. package/lib/core/harness-catalog.d.ts +35 -0
  207. package/lib/core/harness-catalog.d.ts.map +1 -0
  208. package/lib/core/harness-catalog.js +45 -0
  209. package/lib/core/harness-catalog.js.map +1 -0
  210. package/lib/core/harness-catalogs/antigravity.d.ts +11 -0
  211. package/lib/core/harness-catalogs/antigravity.d.ts.map +1 -0
  212. package/lib/core/harness-catalogs/antigravity.js +23 -0
  213. package/lib/core/harness-catalogs/antigravity.js.map +1 -0
  214. package/lib/core/harness-catalogs/claude-code.d.ts +12 -0
  215. package/lib/core/harness-catalogs/claude-code.d.ts.map +1 -0
  216. package/lib/core/harness-catalogs/claude-code.js +24 -0
  217. package/lib/core/harness-catalogs/claude-code.js.map +1 -0
  218. package/lib/core/harness-catalogs/codex.d.ts +11 -0
  219. package/lib/core/harness-catalogs/codex.d.ts.map +1 -0
  220. package/lib/core/harness-catalogs/codex.js +26 -0
  221. package/lib/core/harness-catalogs/codex.js.map +1 -0
  222. package/lib/core/harness-catalogs/copilot.d.ts +29 -0
  223. package/lib/core/harness-catalogs/copilot.d.ts.map +1 -0
  224. package/lib/core/harness-catalogs/copilot.js +45 -0
  225. package/lib/core/harness-catalogs/copilot.js.map +1 -0
  226. package/lib/core/harness-catalogs/cursor.d.ts +2 -0
  227. package/lib/core/harness-catalogs/cursor.d.ts.map +1 -0
  228. package/lib/core/harness-catalogs/cursor.js +13 -0
  229. package/lib/core/harness-catalogs/cursor.js.map +1 -0
  230. package/lib/core/harness-catalogs/grok-build.d.ts +7 -0
  231. package/lib/core/harness-catalogs/grok-build.d.ts.map +1 -0
  232. package/lib/core/harness-catalogs/grok-build.js +18 -0
  233. package/lib/core/harness-catalogs/grok-build.js.map +1 -0
  234. package/lib/core/harness-catalogs/index.d.ts +73 -0
  235. package/lib/core/harness-catalogs/index.d.ts.map +1 -0
  236. package/lib/core/harness-catalogs/index.js +17 -0
  237. package/lib/core/harness-catalogs/index.js.map +1 -0
  238. package/lib/core/harness-matrix.d.ts +154 -0
  239. package/lib/core/harness-matrix.d.ts.map +1 -0
  240. package/lib/core/harness-matrix.js +204 -0
  241. package/lib/core/harness-matrix.js.map +1 -0
  242. package/lib/core/index.d.ts +12 -0
  243. package/lib/core/index.d.ts.map +1 -1
  244. package/lib/core/index.js +12 -0
  245. package/lib/core/index.js.map +1 -1
  246. package/lib/core/lifecycle-fixtures.d.ts.map +1 -1
  247. package/lib/core/lifecycle-fixtures.js +4 -2
  248. package/lib/core/lifecycle-fixtures.js.map +1 -1
  249. package/lib/core/model-cli.d.ts +9 -11
  250. package/lib/core/model-cli.d.ts.map +1 -1
  251. package/lib/core/model-cli.js +39 -22
  252. package/lib/core/model-cli.js.map +1 -1
  253. package/lib/core/platform-process.d.ts +7 -2
  254. package/lib/core/platform-process.d.ts.map +1 -1
  255. package/lib/core/platform-process.js +54 -16
  256. package/lib/core/platform-process.js.map +1 -1
  257. package/lib/core/reference-defaults.d.ts +5 -0
  258. package/lib/core/reference-defaults.d.ts.map +1 -0
  259. package/lib/core/reference-defaults.js +42 -0
  260. package/lib/core/reference-defaults.js.map +1 -0
  261. package/lib/core/rubric.d.ts +1 -0
  262. package/lib/core/rubric.d.ts.map +1 -1
  263. package/lib/core/run.d.ts +292 -1
  264. package/lib/core/run.d.ts.map +1 -1
  265. package/lib/core/run.js +27 -0
  266. package/lib/core/run.js.map +1 -1
  267. package/lib/core/secure-copy.d.ts.map +1 -0
  268. package/lib/core/secure-copy.js.map +1 -0
  269. package/lib/core/usage.d.ts +5 -0
  270. package/lib/core/usage.d.ts.map +1 -1
  271. package/lib/core/usage.js +3 -0
  272. package/lib/core/usage.js.map +1 -1
  273. package/lib/core/wire.d.ts +11 -0
  274. package/lib/core/wire.d.ts.map +1 -1
  275. package/lib/drivers/antigravity/artifacts.d.ts +2 -0
  276. package/lib/drivers/antigravity/artifacts.d.ts.map +1 -0
  277. package/lib/drivers/antigravity/artifacts.js +33 -0
  278. package/lib/drivers/antigravity/artifacts.js.map +1 -0
  279. package/lib/drivers/antigravity/config.d.ts +88 -0
  280. package/lib/drivers/antigravity/config.d.ts.map +1 -0
  281. package/lib/drivers/antigravity/config.js +87 -0
  282. package/lib/drivers/antigravity/config.js.map +1 -0
  283. package/lib/drivers/antigravity/events.d.ts +4 -0
  284. package/lib/drivers/antigravity/events.d.ts.map +1 -0
  285. package/lib/drivers/antigravity/events.js +241 -0
  286. package/lib/drivers/antigravity/events.js.map +1 -0
  287. package/lib/drivers/antigravity/index.d.ts +114 -0
  288. package/lib/drivers/antigravity/index.d.ts.map +1 -0
  289. package/lib/drivers/antigravity/index.js +113 -0
  290. package/lib/drivers/antigravity/index.js.map +1 -0
  291. package/lib/drivers/antigravity/runtime.d.ts +7 -0
  292. package/lib/drivers/antigravity/runtime.d.ts.map +1 -0
  293. package/lib/drivers/antigravity/runtime.js +83 -0
  294. package/lib/drivers/antigravity/runtime.js.map +1 -0
  295. package/lib/drivers/claude-code/deferred-process.d.ts +17 -0
  296. package/lib/drivers/claude-code/deferred-process.d.ts.map +1 -0
  297. package/lib/drivers/claude-code/deferred-process.js +108 -0
  298. package/lib/drivers/claude-code/deferred-process.js.map +1 -0
  299. package/lib/drivers/claude-code/index.d.ts +187 -10
  300. package/lib/drivers/claude-code/index.d.ts.map +1 -1
  301. package/lib/drivers/claude-code/index.js +197 -252
  302. package/lib/drivers/claude-code/index.js.map +1 -1
  303. package/lib/drivers/claude-code/isolation.d.ts +8 -0
  304. package/lib/drivers/claude-code/isolation.d.ts.map +1 -0
  305. package/lib/drivers/claude-code/isolation.js +199 -0
  306. package/lib/drivers/claude-code/isolation.js.map +1 -0
  307. package/lib/drivers/claude-code/parse-events.d.ts.map +1 -1
  308. package/lib/drivers/claude-code/parse-events.js +73 -8
  309. package/lib/drivers/claude-code/parse-events.js.map +1 -1
  310. package/lib/drivers/codex/app-events.d.ts +9 -2
  311. package/lib/drivers/codex/app-events.d.ts.map +1 -1
  312. package/lib/drivers/codex/app-events.js +104 -12
  313. package/lib/drivers/codex/app-events.js.map +1 -1
  314. package/lib/drivers/codex/config.d.ts +69 -5
  315. package/lib/drivers/codex/config.d.ts.map +1 -1
  316. package/lib/drivers/codex/config.js +48 -8
  317. package/lib/drivers/codex/config.js.map +1 -1
  318. package/lib/drivers/codex/exec-events.d.ts +4 -0
  319. package/lib/drivers/codex/exec-events.d.ts.map +1 -0
  320. package/lib/drivers/codex/exec-events.js +230 -0
  321. package/lib/drivers/codex/exec-events.js.map +1 -0
  322. package/lib/drivers/codex/index.d.ts +142 -4
  323. package/lib/drivers/codex/index.d.ts.map +1 -1
  324. package/lib/drivers/codex/index.js +114 -276
  325. package/lib/drivers/codex/index.js.map +1 -1
  326. package/lib/drivers/copilot/config.d.ts +84 -0
  327. package/lib/drivers/copilot/config.d.ts.map +1 -0
  328. package/lib/drivers/copilot/config.js +57 -0
  329. package/lib/drivers/copilot/config.js.map +1 -0
  330. package/lib/drivers/copilot/index.d.ts +107 -0
  331. package/lib/drivers/copilot/index.d.ts.map +1 -0
  332. package/lib/drivers/copilot/index.js +268 -0
  333. package/lib/drivers/copilot/index.js.map +1 -0
  334. package/lib/drivers/cursor/config.d.ts +28 -0
  335. package/lib/drivers/cursor/config.d.ts.map +1 -0
  336. package/lib/drivers/cursor/config.js +28 -0
  337. package/lib/drivers/cursor/config.js.map +1 -0
  338. package/lib/drivers/cursor/index.d.ts +44 -0
  339. package/lib/drivers/cursor/index.d.ts.map +1 -0
  340. package/lib/drivers/cursor/index.js +286 -0
  341. package/lib/drivers/cursor/index.js.map +1 -0
  342. package/lib/drivers/cursor/interaction.d.ts +6 -0
  343. package/lib/drivers/cursor/interaction.d.ts.map +1 -0
  344. package/lib/drivers/cursor/interaction.js +55 -0
  345. package/lib/drivers/cursor/interaction.js.map +1 -0
  346. package/lib/drivers/grok-build/config.d.ts +68 -0
  347. package/lib/drivers/grok-build/config.d.ts.map +1 -0
  348. package/lib/drivers/grok-build/config.js +40 -0
  349. package/lib/drivers/grok-build/config.js.map +1 -0
  350. package/lib/drivers/grok-build/index.d.ts +87 -0
  351. package/lib/drivers/grok-build/index.d.ts.map +1 -0
  352. package/lib/drivers/grok-build/index.js +293 -0
  353. package/lib/drivers/grok-build/index.js.map +1 -0
  354. package/lib/drivers/mcp/index.d.ts +37 -4
  355. package/lib/drivers/mcp/index.d.ts.map +1 -1
  356. package/lib/drivers/mcp/index.js +25 -11
  357. package/lib/drivers/mcp/index.js.map +1 -1
  358. package/lib/drivers/shared/acp-events.d.ts +15 -0
  359. package/lib/drivers/shared/acp-events.d.ts.map +1 -0
  360. package/lib/drivers/shared/acp-events.js +83 -0
  361. package/lib/drivers/shared/acp-events.js.map +1 -0
  362. package/lib/drivers/shared/acp-interaction.d.ts +7 -0
  363. package/lib/drivers/shared/acp-interaction.d.ts.map +1 -0
  364. package/lib/drivers/shared/acp-interaction.js +20 -0
  365. package/lib/drivers/shared/acp-interaction.js.map +1 -0
  366. package/lib/drivers/shared/acp-session.d.ts +4 -0
  367. package/lib/drivers/shared/acp-session.d.ts.map +1 -0
  368. package/lib/drivers/shared/acp-session.js +23 -0
  369. package/lib/drivers/shared/acp-session.js.map +1 -0
  370. package/lib/drivers/shared/acp-transport.d.ts +40 -0
  371. package/lib/drivers/shared/acp-transport.d.ts.map +1 -0
  372. package/lib/drivers/shared/acp-transport.js +152 -0
  373. package/lib/drivers/shared/acp-transport.js.map +1 -0
  374. package/lib/drivers/shared/artifacts.d.ts.map +1 -1
  375. package/lib/drivers/shared/artifacts.js +3 -2
  376. package/lib/drivers/shared/artifacts.js.map +1 -1
  377. package/lib/drivers/shared/experiment-behavior.d.ts +13 -0
  378. package/lib/drivers/shared/experiment-behavior.d.ts.map +1 -0
  379. package/lib/drivers/shared/experiment-behavior.js +200 -0
  380. package/lib/drivers/shared/experiment-behavior.js.map +1 -0
  381. package/lib/drivers/shared/experiment-policy.d.ts +4 -0
  382. package/lib/drivers/shared/experiment-policy.d.ts.map +1 -0
  383. package/lib/drivers/shared/experiment-policy.js +144 -0
  384. package/lib/drivers/shared/experiment-policy.js.map +1 -0
  385. package/lib/drivers/shared/skills.d.ts +3 -0
  386. package/lib/drivers/shared/skills.d.ts.map +1 -0
  387. package/lib/drivers/shared/skills.js +73 -0
  388. package/lib/drivers/shared/skills.js.map +1 -0
  389. package/lib/drivers/subprocess/index.d.ts +39 -4
  390. package/lib/drivers/subprocess/index.d.ts.map +1 -1
  391. package/lib/drivers/subprocess/index.js +56 -12
  392. package/lib/drivers/subprocess/index.js.map +1 -1
  393. package/lib/index.d.ts +24 -8
  394. package/lib/index.d.ts.map +1 -1
  395. package/lib/index.js +20 -5
  396. package/lib/index.js.map +1 -1
  397. package/lib/optimization/reflective.d.ts +3 -1
  398. package/lib/optimization/reflective.d.ts.map +1 -1
  399. package/lib/optimization/reflective.js +3 -2
  400. package/lib/optimization/reflective.js.map +1 -1
  401. package/lib/orchestrator/annotation-loader.d.ts +6 -2
  402. package/lib/orchestrator/annotation-loader.d.ts.map +1 -1
  403. package/lib/orchestrator/annotation-loader.js +8 -0
  404. package/lib/orchestrator/annotation-loader.js.map +1 -1
  405. package/lib/orchestrator/annotation-store.d.ts.map +1 -1
  406. package/lib/orchestrator/annotation-store.js +16 -2
  407. package/lib/orchestrator/annotation-store.js.map +1 -1
  408. package/lib/orchestrator/artifact-origin.d.ts +3 -0
  409. package/lib/orchestrator/artifact-origin.d.ts.map +1 -0
  410. package/lib/orchestrator/artifact-origin.js +40 -0
  411. package/lib/orchestrator/artifact-origin.js.map +1 -0
  412. package/lib/orchestrator/campaign-lifecycle.d.ts +1 -0
  413. package/lib/orchestrator/campaign-lifecycle.d.ts.map +1 -1
  414. package/lib/orchestrator/campaign-lifecycle.js +4 -1
  415. package/lib/orchestrator/campaign-lifecycle.js.map +1 -1
  416. package/lib/orchestrator/candidates.d.ts.map +1 -1
  417. package/lib/orchestrator/candidates.js +3 -2
  418. package/lib/orchestrator/candidates.js.map +1 -1
  419. package/lib/orchestrator/compare.d.ts +23 -6
  420. package/lib/orchestrator/compare.d.ts.map +1 -1
  421. package/lib/orchestrator/compare.js +45 -12
  422. package/lib/orchestrator/compare.js.map +1 -1
  423. package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
  424. package/lib/orchestrator/comparison-identity.js +2 -0
  425. package/lib/orchestrator/comparison-identity.js.map +1 -1
  426. package/lib/orchestrator/config.d.ts +180 -1
  427. package/lib/orchestrator/config.d.ts.map +1 -1
  428. package/lib/orchestrator/config.js +21 -2
  429. package/lib/orchestrator/config.js.map +1 -1
  430. package/lib/orchestrator/discover.d.ts +1 -0
  431. package/lib/orchestrator/discover.d.ts.map +1 -1
  432. package/lib/orchestrator/discover.js +7 -1
  433. package/lib/orchestrator/discover.js.map +1 -1
  434. package/lib/orchestrator/doctor.d.ts +1 -0
  435. package/lib/orchestrator/doctor.d.ts.map +1 -1
  436. package/lib/orchestrator/doctor.js +134 -69
  437. package/lib/orchestrator/doctor.js.map +1 -1
  438. package/lib/orchestrator/driver-capabilities.d.ts +4 -0
  439. package/lib/orchestrator/driver-capabilities.d.ts.map +1 -0
  440. package/lib/orchestrator/driver-capabilities.js +13 -0
  441. package/lib/orchestrator/driver-capabilities.js.map +1 -0
  442. package/lib/orchestrator/driver-identity.d.ts +5 -0
  443. package/lib/orchestrator/driver-identity.d.ts.map +1 -0
  444. package/lib/orchestrator/driver-identity.js +51 -0
  445. package/lib/orchestrator/driver-identity.js.map +1 -0
  446. package/lib/orchestrator/experiment-context.d.ts +51 -3
  447. package/lib/orchestrator/experiment-context.d.ts.map +1 -1
  448. package/lib/orchestrator/experiment-context.js +2 -1
  449. package/lib/orchestrator/experiment-context.js.map +1 -1
  450. package/lib/orchestrator/experiment-contracts.d.ts +31 -1
  451. package/lib/orchestrator/experiment-contracts.d.ts.map +1 -1
  452. package/lib/orchestrator/experiment-corpus.d.ts +2 -1
  453. package/lib/orchestrator/experiment-corpus.d.ts.map +1 -1
  454. package/lib/orchestrator/experiment-corpus.js +28 -22
  455. package/lib/orchestrator/experiment-corpus.js.map +1 -1
  456. package/lib/orchestrator/experiment-effects.d.ts +33 -0
  457. package/lib/orchestrator/experiment-effects.d.ts.map +1 -0
  458. package/lib/orchestrator/experiment-effects.js +46 -0
  459. package/lib/orchestrator/experiment-effects.js.map +1 -0
  460. package/lib/orchestrator/experiment-evaluation.d.ts.map +1 -1
  461. package/lib/orchestrator/experiment-evaluation.js +70 -5
  462. package/lib/orchestrator/experiment-evaluation.js.map +1 -1
  463. package/lib/orchestrator/experiment-identity.d.ts +3 -0
  464. package/lib/orchestrator/experiment-identity.d.ts.map +1 -1
  465. package/lib/orchestrator/experiment-identity.js +22 -33
  466. package/lib/orchestrator/experiment-identity.js.map +1 -1
  467. package/lib/orchestrator/experiment-loader.d.ts +8 -3
  468. package/lib/orchestrator/experiment-loader.d.ts.map +1 -1
  469. package/lib/orchestrator/experiment-preflight.d.ts +3 -0
  470. package/lib/orchestrator/experiment-preflight.d.ts.map +1 -0
  471. package/lib/orchestrator/experiment-preflight.js +21 -0
  472. package/lib/orchestrator/experiment-preflight.js.map +1 -0
  473. package/lib/orchestrator/experiment-report.d.ts +91 -1
  474. package/lib/orchestrator/experiment-report.d.ts.map +1 -1
  475. package/lib/orchestrator/experiment-report.js +9 -1
  476. package/lib/orchestrator/experiment-report.js.map +1 -1
  477. package/lib/orchestrator/experiment-runs.d.ts +63 -2
  478. package/lib/orchestrator/experiment-runs.d.ts.map +1 -1
  479. package/lib/orchestrator/experiment-runs.js +13 -5
  480. package/lib/orchestrator/experiment-runs.js.map +1 -1
  481. package/lib/orchestrator/experiment-runtime-identity.d.ts +0 -16
  482. package/lib/orchestrator/experiment-runtime-identity.d.ts.map +1 -1
  483. package/lib/orchestrator/experiment-runtime-identity.js +5 -220
  484. package/lib/orchestrator/experiment-runtime-identity.js.map +1 -1
  485. package/lib/orchestrator/experiment-selection.d.ts.map +1 -1
  486. package/lib/orchestrator/experiment-selection.js +151 -43
  487. package/lib/orchestrator/experiment-selection.js.map +1 -1
  488. package/lib/orchestrator/experiment.d.ts +3 -3
  489. package/lib/orchestrator/experiment.d.ts.map +1 -1
  490. package/lib/orchestrator/experiment.js +26 -21
  491. package/lib/orchestrator/experiment.js.map +1 -1
  492. package/lib/orchestrator/fixture-identity.d.ts +1 -0
  493. package/lib/orchestrator/fixture-identity.d.ts.map +1 -1
  494. package/lib/orchestrator/fixture-identity.js +6 -1
  495. package/lib/orchestrator/fixture-identity.js.map +1 -1
  496. package/lib/orchestrator/fs-read.d.ts +1 -6
  497. package/lib/orchestrator/fs-read.d.ts.map +1 -1
  498. package/lib/orchestrator/fs-read.js +2 -32
  499. package/lib/orchestrator/fs-read.js.map +1 -1
  500. package/lib/orchestrator/grader-experiment.d.ts +23 -5
  501. package/lib/orchestrator/grader-experiment.d.ts.map +1 -1
  502. package/lib/orchestrator/grader-experiment.js +54 -9
  503. package/lib/orchestrator/grader-experiment.js.map +1 -1
  504. package/lib/orchestrator/grading.d.ts +1 -0
  505. package/lib/orchestrator/grading.d.ts.map +1 -1
  506. package/lib/orchestrator/grading.js +41 -33
  507. package/lib/orchestrator/grading.js.map +1 -1
  508. package/lib/orchestrator/harness-catalog-drift.d.ts +22 -0
  509. package/lib/orchestrator/harness-catalog-drift.d.ts.map +1 -0
  510. package/lib/orchestrator/harness-catalog-drift.js +90 -0
  511. package/lib/orchestrator/harness-catalog-drift.js.map +1 -0
  512. package/lib/orchestrator/harness-registry.d.ts +4 -0
  513. package/lib/orchestrator/harness-registry.d.ts.map +1 -0
  514. package/lib/orchestrator/harness-registry.js +5 -0
  515. package/lib/orchestrator/harness-registry.js.map +1 -0
  516. package/lib/orchestrator/index.d.ts +1 -1
  517. package/lib/orchestrator/index.d.ts.map +1 -1
  518. package/lib/orchestrator/index.js +1 -1
  519. package/lib/orchestrator/index.js.map +1 -1
  520. package/lib/orchestrator/list-runs.d.ts +8 -1
  521. package/lib/orchestrator/list-runs.d.ts.map +1 -1
  522. package/lib/orchestrator/list-runs.js +83 -18
  523. package/lib/orchestrator/list-runs.js.map +1 -1
  524. package/lib/orchestrator/optimization-lifecycle.d.ts.map +1 -1
  525. package/lib/orchestrator/optimization-lifecycle.js +3 -1
  526. package/lib/orchestrator/optimization-lifecycle.js.map +1 -1
  527. package/lib/orchestrator/orchestrator.d.ts +17 -2
  528. package/lib/orchestrator/orchestrator.d.ts.map +1 -1
  529. package/lib/orchestrator/orchestrator.js +55 -177
  530. package/lib/orchestrator/orchestrator.js.map +1 -1
  531. package/lib/orchestrator/paired-effects.d.ts +34 -0
  532. package/lib/orchestrator/paired-effects.d.ts.map +1 -0
  533. package/lib/orchestrator/paired-effects.js +164 -0
  534. package/lib/orchestrator/paired-effects.js.map +1 -0
  535. package/lib/orchestrator/profile.d.ts +4 -0
  536. package/lib/orchestrator/profile.d.ts.map +1 -0
  537. package/lib/orchestrator/profile.js +10 -0
  538. package/lib/orchestrator/profile.js.map +1 -0
  539. package/lib/orchestrator/provenance.d.ts +5 -1
  540. package/lib/orchestrator/provenance.d.ts.map +1 -1
  541. package/lib/orchestrator/provenance.js +16 -3
  542. package/lib/orchestrator/provenance.js.map +1 -1
  543. package/lib/orchestrator/regrade.d.ts +4 -2
  544. package/lib/orchestrator/regrade.d.ts.map +1 -1
  545. package/lib/orchestrator/rubric-loader.js +1 -1
  546. package/lib/orchestrator/rubric-loader.js.map +1 -1
  547. package/lib/orchestrator/run-dir.d.ts +2 -0
  548. package/lib/orchestrator/run-dir.d.ts.map +1 -1
  549. package/lib/orchestrator/run-dir.js +1 -1
  550. package/lib/orchestrator/run-dir.js.map +1 -1
  551. package/lib/orchestrator/run-execution.d.ts +3 -0
  552. package/lib/orchestrator/run-execution.d.ts.map +1 -1
  553. package/lib/orchestrator/run-execution.js +64 -10
  554. package/lib/orchestrator/run-execution.js.map +1 -1
  555. package/lib/orchestrator/run-lifecycle.d.ts +1 -0
  556. package/lib/orchestrator/run-lifecycle.d.ts.map +1 -1
  557. package/lib/orchestrator/run-lifecycle.js +3 -2
  558. package/lib/orchestrator/run-lifecycle.js.map +1 -1
  559. package/lib/orchestrator/run-workspace.d.ts +10 -0
  560. package/lib/orchestrator/run-workspace.d.ts.map +1 -0
  561. package/lib/orchestrator/run-workspace.js +58 -0
  562. package/lib/orchestrator/run-workspace.js.map +1 -0
  563. package/lib/orchestrator/suite-compare.d.ts +37 -0
  564. package/lib/orchestrator/suite-compare.d.ts.map +1 -1
  565. package/lib/orchestrator/suite-compare.js +44 -22
  566. package/lib/orchestrator/suite-compare.js.map +1 -1
  567. package/lib/orchestrator/suite-runs.d.ts +6 -1
  568. package/lib/orchestrator/suite-runs.d.ts.map +1 -1
  569. package/lib/orchestrator/suite-runs.js +14 -2
  570. package/lib/orchestrator/suite-runs.js.map +1 -1
  571. package/lib/orchestrator/suite-summary.d.ts +79 -0
  572. package/lib/orchestrator/suite-summary.d.ts.map +1 -1
  573. package/lib/orchestrator/suite-summary.js +67 -14
  574. package/lib/orchestrator/suite-summary.js.map +1 -1
  575. package/lib/previewer/artifacts.d.ts +25 -0
  576. package/lib/previewer/artifacts.d.ts.map +1 -0
  577. package/lib/previewer/artifacts.js +180 -0
  578. package/lib/previewer/artifacts.js.map +1 -0
  579. package/lib/previewer/server.d.ts +111 -0
  580. package/lib/previewer/server.d.ts.map +1 -0
  581. package/lib/previewer/server.js +559 -0
  582. package/lib/previewer/server.js.map +1 -0
  583. package/package.json +4 -2
  584. package/skills/lux-answerer/SKILL.md +2 -2
  585. package/src/answerers/claude-code/index.ts +6 -5
  586. package/src/answerers/persona/index.ts +75 -34
  587. package/src/answerers/terminal/index.ts +7 -11
  588. package/src/assertions/authoring.ts +2 -0
  589. package/src/assertions/core/command-exits-zero.ts +82 -17
  590. package/src/assertions/core/event-checks.ts +64 -3
  591. package/src/assertions/core/index.ts +2 -0
  592. package/src/assertions/core/resource-checks.ts +38 -5
  593. package/src/assertions/core/safe-regex.ts +16 -6
  594. package/src/assertions/rubric/evidence.ts +85 -0
  595. package/src/assertions/rubric/index.ts +63 -46
  596. package/src/assertions/rubric/internal.ts +256 -41
  597. package/src/authoring.ts +346 -2
  598. package/src/cli/bin.ts +2 -12
  599. package/src/cli/command-runtime.ts +20 -9
  600. package/src/cli/doctor.ts +17 -0
  601. package/src/cli/harness-plan.ts +123 -0
  602. package/src/cli/init-templates.ts +238 -0
  603. package/src/cli/init.ts +53 -184
  604. package/src/cli/output-schemas.ts +109 -0
  605. package/src/cli/program.ts +697 -730
  606. package/src/cli/render/format.ts +1 -1
  607. package/src/cli/render/reporter.ts +36 -8
  608. package/src/cli/run-options.ts +131 -25
  609. package/src/cli/view.ts +129 -0
  610. package/src/container/driver.ts +213 -0
  611. package/src/container/paths.ts +29 -0
  612. package/src/container/protocol.ts +48 -0
  613. package/src/container/resources.ts +165 -0
  614. package/src/container/worker.ts +107 -0
  615. package/src/core/action-events.ts +59 -0
  616. package/src/core/agent-activity.ts +236 -0
  617. package/src/core/agent-environment.ts +64 -0
  618. package/src/core/agent-events.ts +17 -0
  619. package/src/core/annotation.ts +2 -1
  620. package/src/core/answerer.ts +9 -0
  621. package/src/core/artifact-evidence.ts +40 -5
  622. package/src/core/assertion.ts +8 -2
  623. package/src/core/case-defaults.ts +65 -0
  624. package/src/core/case.ts +79 -8
  625. package/src/core/command-verification.ts +74 -0
  626. package/src/core/driver-execution.ts +84 -0
  627. package/src/core/driver-metrics.ts +51 -0
  628. package/src/core/driver.ts +76 -0
  629. package/src/core/duration.ts +52 -0
  630. package/src/core/environment.ts +22 -0
  631. package/src/core/evaluation-clusters.ts +35 -0
  632. package/src/core/events.ts +13 -2
  633. package/src/core/experiment.ts +71 -25
  634. package/src/core/file-tree.ts +35 -0
  635. package/src/core/global-id.ts +26 -0
  636. package/src/core/harness-catalog.ts +100 -0
  637. package/src/core/harness-catalogs/antigravity.ts +24 -0
  638. package/src/core/harness-catalogs/claude-code.ts +25 -0
  639. package/src/core/harness-catalogs/codex.ts +27 -0
  640. package/src/core/harness-catalogs/copilot.ts +46 -0
  641. package/src/core/harness-catalogs/cursor.ts +13 -0
  642. package/src/core/harness-catalogs/grok-build.ts +19 -0
  643. package/src/core/harness-catalogs/index.ts +31 -0
  644. package/src/core/harness-matrix.ts +316 -0
  645. package/src/core/index.ts +12 -0
  646. package/src/core/lifecycle-fixtures.ts +4 -2
  647. package/src/core/model-cli.ts +60 -26
  648. package/src/core/platform-process.ts +65 -16
  649. package/src/core/reference-defaults.ts +47 -0
  650. package/src/core/run.ts +31 -0
  651. package/src/core/usage.ts +8 -0
  652. package/src/drivers/antigravity/README.md +171 -0
  653. package/src/drivers/antigravity/artifacts.ts +37 -0
  654. package/src/drivers/antigravity/config.ts +92 -0
  655. package/src/drivers/antigravity/events.ts +290 -0
  656. package/src/drivers/antigravity/index.ts +132 -0
  657. package/src/drivers/antigravity/runtime.ts +94 -0
  658. package/src/drivers/claude-code/deferred-process.ts +118 -0
  659. package/src/drivers/claude-code/index.ts +227 -281
  660. package/src/drivers/claude-code/isolation.ts +228 -0
  661. package/src/drivers/claude-code/parse-events.ts +98 -12
  662. package/src/drivers/codex/app-events.ts +126 -16
  663. package/src/drivers/codex/config.ts +59 -8
  664. package/src/drivers/codex/exec-events.ts +258 -0
  665. package/src/drivers/codex/index.ts +146 -312
  666. package/src/drivers/copilot/README.md +60 -0
  667. package/src/drivers/copilot/config.ts +61 -0
  668. package/src/drivers/copilot/index.ts +310 -0
  669. package/src/drivers/cursor/README.md +66 -0
  670. package/src/drivers/cursor/config.ts +31 -0
  671. package/src/drivers/cursor/index.ts +326 -0
  672. package/src/drivers/cursor/interaction.ts +74 -0
  673. package/src/drivers/grok-build/README.md +112 -0
  674. package/src/drivers/grok-build/config.ts +43 -0
  675. package/src/drivers/grok-build/index.ts +331 -0
  676. package/src/drivers/mcp/index.ts +25 -11
  677. package/src/drivers/shared/acp-events.ts +94 -0
  678. package/src/drivers/shared/acp-interaction.ts +27 -0
  679. package/src/drivers/shared/acp-session.ts +40 -0
  680. package/src/drivers/shared/acp-transport.ts +187 -0
  681. package/src/drivers/shared/artifacts.ts +6 -2
  682. package/src/drivers/shared/experiment-behavior.ts +217 -0
  683. package/src/drivers/shared/experiment-policy.ts +196 -0
  684. package/src/drivers/shared/skills.ts +74 -0
  685. package/src/drivers/subprocess/index.ts +55 -12
  686. package/src/index.ts +117 -6
  687. package/src/optimization/reflective.ts +3 -2
  688. package/src/orchestrator/annotation-loader.ts +10 -0
  689. package/src/orchestrator/annotation-store.ts +24 -3
  690. package/src/orchestrator/artifact-origin.ts +50 -0
  691. package/src/orchestrator/campaign-lifecycle.ts +5 -1
  692. package/src/orchestrator/candidates.ts +3 -2
  693. package/src/orchestrator/compare.ts +62 -13
  694. package/src/orchestrator/comparison-identity.ts +2 -0
  695. package/src/orchestrator/config.ts +23 -1
  696. package/src/orchestrator/discover.ts +8 -1
  697. package/src/orchestrator/doctor.ts +211 -65
  698. package/src/orchestrator/driver-capabilities.ts +21 -0
  699. package/src/orchestrator/driver-identity.ts +69 -0
  700. package/src/orchestrator/experiment-context.ts +5 -3
  701. package/src/orchestrator/experiment-corpus.ts +58 -37
  702. package/src/orchestrator/experiment-effects.ts +63 -0
  703. package/src/orchestrator/experiment-evaluation.ts +88 -10
  704. package/src/orchestrator/experiment-identity.ts +57 -48
  705. package/src/orchestrator/experiment-preflight.ts +27 -0
  706. package/src/orchestrator/experiment-report.ts +21 -1
  707. package/src/orchestrator/experiment-runs.ts +11 -4
  708. package/src/orchestrator/experiment-runtime-identity.ts +5 -243
  709. package/src/orchestrator/experiment-selection.ts +178 -18
  710. package/src/orchestrator/experiment.ts +29 -29
  711. package/src/orchestrator/fixture-identity.ts +9 -1
  712. package/src/orchestrator/fs-read.ts +2 -32
  713. package/src/orchestrator/grader-experiment.ts +74 -13
  714. package/src/orchestrator/grading.ts +60 -31
  715. package/src/orchestrator/harness-catalog-drift.ts +132 -0
  716. package/src/orchestrator/harness-registry.ts +12 -0
  717. package/src/orchestrator/index.ts +1 -0
  718. package/src/orchestrator/list-runs.ts +102 -18
  719. package/src/orchestrator/optimization-lifecycle.ts +4 -1
  720. package/src/orchestrator/orchestrator.ts +105 -224
  721. package/src/orchestrator/paired-effects.ts +214 -0
  722. package/src/orchestrator/profile.ts +24 -0
  723. package/src/orchestrator/provenance.ts +23 -3
  724. package/src/orchestrator/rubric-loader.ts +1 -1
  725. package/src/orchestrator/run-dir.ts +8 -1
  726. package/src/orchestrator/run-execution.ts +75 -10
  727. package/src/orchestrator/run-lifecycle.ts +4 -2
  728. package/src/orchestrator/run-workspace.ts +62 -0
  729. package/src/orchestrator/suite-compare.ts +47 -23
  730. package/src/orchestrator/suite-runs.ts +13 -2
  731. package/src/orchestrator/suite-summary.ts +129 -15
  732. package/src/previewer/artifacts.ts +221 -0
  733. package/src/previewer/server.ts +789 -0
  734. package/viewer/app.css +2111 -0
  735. package/viewer/app.js +627 -0
  736. package/viewer/artifact-view.js +48 -0
  737. package/viewer/charts.js +98 -0
  738. package/viewer/detail.js +1266 -0
  739. package/viewer/format.js +129 -0
  740. package/viewer/index.html +151 -0
  741. package/lib/cli/skills.d.ts +0 -38
  742. package/lib/cli/skills.d.ts.map +0 -1
  743. package/lib/cli/skills.js +0 -84
  744. package/lib/cli/skills.js.map +0 -1
  745. package/lib/drivers/shared/secure-copy.d.ts.map +0 -1
  746. package/lib/drivers/shared/secure-copy.js.map +0 -1
  747. package/skills/lux/SKILL.md +0 -89
  748. package/skills/lux/references/cli.md +0 -125
  749. package/skills/lux/references/eval-authoring.md +0 -257
  750. package/src/cli/skills.ts +0 -129
  751. /package/lib/{drivers/shared → core}/secure-copy.d.ts +0 -0
  752. /package/lib/{drivers/shared → core}/secure-copy.js +0 -0
  753. /package/src/{drivers/shared → core}/secure-copy.ts +0 -0
@@ -0,0 +1,24 @@
1
+ import {
2
+ mergeAnswererReference,
3
+ mergeDriverReference,
4
+ withDriverDefaults,
5
+ } from "../core/reference-defaults.js";
6
+ import type { ExperimentProfile, ResolvedLuxConfig } from "./config.js";
7
+
8
+ /** Used by ordinary runs, doctor, and experiment execution and identity alike. */
9
+ export const resolveProfile = (
10
+ config: Pick<
11
+ ResolvedLuxConfig,
12
+ "defaultDriver" | "defaultAnswerer" | "harness" | "environment" | "driverDefaults"
13
+ >,
14
+ profile: ExperimentProfile = {},
15
+ ): ExperimentProfile => ({
16
+ ...profile,
17
+ driver: withDriverDefaults(
18
+ mergeDriverReference(config.defaultDriver, profile.driver),
19
+ config.driverDefaults,
20
+ ),
21
+ answerer: mergeAnswererReference(config.defaultAnswerer, profile.answerer),
22
+ harness: profile.harness ?? config.harness,
23
+ environment: profile.environment ?? config.environment,
24
+ });
@@ -1,6 +1,8 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { lstat, readFile, readlink } from "node:fs/promises";
3
+ import { availableParallelism, cpus, release, totalmem } from "node:os";
3
4
  import { dirname, join, parse, relative, resolve, sep } from "node:path";
5
+ import type { EnvironmentDeclaration } from "../core/environment.js";
4
6
  import type { RunProvenance } from "../core/index.js";
5
7
  import { contentHash, exec, valueHash } from "../core/index.js";
6
8
 
@@ -113,13 +115,30 @@ export const runtimeIdentity = (): RunProvenance["runtime"] => ({
113
115
  arch: process.arch,
114
116
  node: process.version,
115
117
  ...(process.versions.bun ? { bun: process.versions.bun } : {}),
118
+ host: {
119
+ osRelease: release(),
120
+ cpuModels: [...new Set(cpus().map((cpu) => cpu.model))].sort(),
121
+ logicalCpuCount: cpus().length,
122
+ availableParallelism: availableParallelism(),
123
+ totalMemoryBytes: totalmem(),
124
+ },
116
125
  });
117
126
 
118
- export const runProvenance = async (casePath: string | null): Promise<RunProvenance> => {
127
+ export const runProvenance = async (
128
+ casePath: string | null,
129
+ options: {
130
+ environment?: EnvironmentDeclaration | undefined;
131
+ concurrency?: number | undefined;
132
+ } = {},
133
+ ): Promise<RunProvenance> => {
119
134
  const runtime = runtimeIdentity();
120
- if (!casePath) return { runtime };
135
+ const environment = {
136
+ ...(options.environment ? { declared: options.environment } : {}),
137
+ concurrency: options.concurrency ?? 1,
138
+ };
139
+ if (!casePath) return { runtime, environment };
121
140
  const root = gitRootAbove(casePath);
122
- if (!root) return { runtime, source: { casePath: resolve(casePath) } };
141
+ if (!root) return { runtime, environment, source: { casePath: resolve(casePath) } };
123
142
  let git = repositories.get(root);
124
143
  if (!git) {
125
144
  git = inspectRepository(root);
@@ -128,6 +147,7 @@ export const runProvenance = async (casePath: string | null): Promise<RunProvena
128
147
  const state = await git;
129
148
  return {
130
149
  runtime,
150
+ environment,
131
151
  source: {
132
152
  casePath: portablePath(relative(root, resolve(casePath))),
133
153
  ...(state ? { git: state } : {}),
@@ -9,7 +9,7 @@ const CANDIDATE_FORBIDDEN_FIELDS = [
9
9
  "provider",
10
10
  "model",
11
11
  "reasoningEffort",
12
- "timeoutMs",
12
+ "timeout",
13
13
  "promptOverride",
14
14
  ] as const;
15
15
  const RawRubricDefinitionSchema = z.looseObject({
@@ -154,6 +154,8 @@ export type OpenRunDirOptions = {
154
154
  runsRoot: string;
155
155
  caseId: string;
156
156
  driverName: string;
157
+ /** Files the run under the permutation instead of the bare driver name. */
158
+ permutationId?: string | undefined;
157
159
  startedAt?: Date | undefined;
158
160
  /** Tap on the event stream, called for every appended event. Must not throw. */
159
161
  onEvent?: ((event: RunEvent) => void) | undefined;
@@ -164,7 +166,12 @@ export type OpenRunDirOptions = {
164
166
  export const openRunDir = async (options: OpenRunDirOptions): Promise<OpenedRunDir> => {
165
167
  const ts = isoTimestampSafe(options.startedAt ?? new Date());
166
168
  const slug = slugifyCaseId(options.caseId);
167
- const basePath = join(options.runsRoot, slug, slugifyCaseId(options.driverName), ts);
169
+ const basePath = join(
170
+ options.runsRoot,
171
+ slug,
172
+ slugifyCaseId(options.permutationId ?? options.driverName),
173
+ ts,
174
+ );
168
175
  await mkdir(dirname(basePath), { recursive: true });
169
176
  // Same case+driver+millisecond must not share a dir — their events.jsonl
170
177
  // streams (opened with flags "a") would interleave silently. A bare mkdir
@@ -1,6 +1,7 @@
1
1
  import { cp } from "node:fs/promises";
2
2
  import { dirname, isAbsolute, resolve } from "node:path";
3
3
  import { z } from "zod";
4
+ import type { EnvironmentDeclaration } from "../core/environment.js";
4
5
  import {
5
6
  type AgentDriver,
6
7
  type Answerer,
@@ -10,6 +11,8 @@ import {
10
11
  AnswererModelCallAccountingSchema,
11
12
  type AnswerHistoryEntry,
12
13
  type Artifact,
14
+ actionTiming,
15
+ bindRunExecutionWorkspace,
13
16
  type EvalCase,
14
17
  emptyUsage,
15
18
  type FixturesRef,
@@ -18,6 +21,7 @@ import {
18
21
  guardRunObserver,
19
22
  inspectRunArtifact,
20
23
  type LifecycleStage,
24
+ normalizeDriverMetrics,
21
25
  type OperationalFailure,
22
26
  type PhaseDurations,
23
27
  type ReadyState,
@@ -28,12 +32,14 @@ import {
28
32
  type RunMetadata,
29
33
  type RunProvenance,
30
34
  type RunUsage,
35
+ summarizeAgentActivity,
31
36
  summarizeToolOutcomes,
32
37
  sumUsage,
33
38
  type TokenUsage,
34
39
  TokenUsageSchema,
35
40
  valueHash,
36
41
  } from "../core/index.js";
42
+ import { identifyArtifactOrigins } from "./artifact-origin.js";
37
43
  import {
38
44
  createDriverSession,
39
45
  type DriverSession,
@@ -49,6 +55,7 @@ import {
49
55
  type RunFailurePhase,
50
56
  type RunLifecycleEffects,
51
57
  } from "./run-lifecycle.js";
58
+ import { RunWorkspace } from "./run-workspace.js";
52
59
  import { isRunTraceLimit, type RunTraceLimitFailure } from "./trace-limits.js";
53
60
 
54
61
  /** Sentinel `casePath` for a pre-loaded case that has no file behind it. */
@@ -57,6 +64,7 @@ export const INLINE_CASE_PATH = "<inline>";
57
64
  type RunDirCarrier = { luxRunDir?: string };
58
65
  type InterruptCounts = { ask: number; approve: number; custom: number };
59
66
  export type RunWithPluginsArgs = {
67
+ environment?: EnvironmentDeclaration | undefined;
60
68
  request: RunRequest;
61
69
  casePath: string;
62
70
  authoredCase: EvalCase;
@@ -64,6 +72,7 @@ export type RunWithPluginsArgs = {
64
72
  validatedAssertionConfigs: readonly unknown[];
65
73
  caseId: string;
66
74
  driverName: string;
75
+ permutationId?: string | undefined;
67
76
  answererName: string;
68
77
  answererConfig: unknown;
69
78
  driverConfigHash: string;
@@ -108,7 +117,9 @@ const readAnswererUsage = (answerer: Answerer): TokenUsage =>
108
117
  const stageFixtures = async (
109
118
  ref: FixturesRef | undefined,
110
119
  options: { fixturesRoot?: string; casePath: string; artifactsDir: string },
111
- ): Promise<{ fixtures: ResolvedFixtures; hash: string } | undefined> => {
120
+ ): Promise<
121
+ { fixtures: ResolvedFixtures; hash: string; fileHashes: ReadonlyMap<string, string> } | undefined
122
+ > => {
112
123
  if (!ref) return undefined;
113
124
  const path = typeof ref === "string" ? ref : ref.path;
114
125
  if (!isAbsolute(path) && !options.fixturesRoot && options.casePath === INLINE_CASE_PATH) {
@@ -123,7 +134,11 @@ const stageFixtures = async (
123
134
  if (staged.hash !== source.hash) {
124
135
  throw new Error(`fixtures: tree changed while staging: ${source.rootDir}`);
125
136
  }
126
- return { fixtures: { rootDir: source.rootDir }, hash: staged.hash };
137
+ return {
138
+ fixtures: { rootDir: source.rootDir },
139
+ hash: staged.hash,
140
+ fileHashes: staged.fileHashes,
141
+ };
127
142
  };
128
143
 
129
144
  export const runDirOfError = (error: unknown): string | null =>
@@ -170,8 +185,17 @@ const SummaryModelAccountingSchema = z.object({
170
185
  unpricedModelCalls: z.number().int().nonnegative().optional(),
171
186
  });
172
187
 
173
- const usageFromSummary = (summary: unknown): TokenUsage | null =>
174
- SummaryUsageSchema.safeParse(summary).data?.usage ?? null;
188
+ const usageFromSummary = (summary: unknown): TokenUsage | null => {
189
+ if (!summary || typeof summary !== "object") return null;
190
+ const raw = (summary as { usage?: unknown }).usage;
191
+ if (!raw || typeof raw !== "object") return null;
192
+ const counts = raw as Record<string, unknown>;
193
+ const hasCount = ["input", "output", "cacheRead", "cacheCreation"].some((key) => {
194
+ const value = counts[key];
195
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
196
+ });
197
+ return hasCount ? (SummaryUsageSchema.safeParse(summary).data?.usage ?? null) : null;
198
+ };
175
199
 
176
200
  const costFromSummary = (summary: unknown): number | undefined => {
177
201
  if (!summary || typeof summary !== "object") return undefined;
@@ -183,6 +207,11 @@ const modelAccountingFromSummary = (
183
207
  ): { modelCalls: number; unpricedModelCalls?: number | undefined } | null =>
184
208
  SummaryModelAccountingSchema.safeParse(summary).data ?? null;
185
209
 
210
+ const metricsFromSummary = (summary: unknown) => {
211
+ if (!summary || typeof summary !== "object") return {};
212
+ return normalizeDriverMetrics((summary as { metrics?: unknown }).metrics);
213
+ };
214
+
186
215
  const artifactMeasurements = async (
187
216
  artifacts: readonly Artifact[],
188
217
  runDir: string,
@@ -287,12 +316,14 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
287
316
  private loop: DriverSession | undefined;
288
317
  private ready: ReadyState | undefined;
289
318
  private fixturesHash: string | undefined;
319
+ private fixtureFileHashes: ReadonlyMap<string, string> = new Map();
290
320
  private startAttempted = false;
291
321
  private loopOutcome: DriverSessionOutcome | undefined;
292
322
  private collection: Collection = { artifacts: [] };
293
323
  private metadata: RunMetadata | undefined;
294
324
  private usage: RunUsage | undefined;
295
325
  private run: Run | undefined;
326
+ private workspace: RunWorkspace | undefined;
296
327
 
297
328
  private constructor(
298
329
  args: RunWithPluginsArgs,
@@ -312,12 +343,14 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
312
343
  const startedAt = args.request.startedAt ?? new Date();
313
344
  const provenance = await runProvenance(
314
345
  args.casePath === INLINE_CASE_PATH ? null : args.casePath,
346
+ { environment: args.environment, concurrency: args.request.suiteConcurrency },
315
347
  );
316
348
  const observer = guardRunObserver(args.request.observer);
317
349
  const runDir = await openRunDir({
318
350
  runsRoot: resolve(args.request.runsRoot),
319
351
  caseId: args.caseId,
320
352
  driverName: args.driverName,
353
+ permutationId: args.permutationId,
321
354
  startedAt,
322
355
  onEvent: observer?.event,
323
356
  });
@@ -347,12 +380,14 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
347
380
  const { request, evalCase, casePath, driver } = this.args;
348
381
  this.lifecycle("run-loop");
349
382
  if (request.abortSignal?.aborted) return;
383
+ this.workspace = await RunWorkspace.create();
350
384
  const staged = await stageFixtures(evalCase.fixtures, {
351
385
  ...(request.fixturesRoot ? { fixturesRoot: request.fixturesRoot } : {}),
352
386
  casePath,
353
- artifactsDir: this.runDir.artifactsDir,
387
+ artifactsDir: this.workspace.path,
354
388
  });
355
389
  this.fixturesHash = staged?.hash;
390
+ this.fixtureFileHashes = staged?.fileHashes ?? new Map();
356
391
  if (request.abortSignal?.aborted) return;
357
392
 
358
393
  this.lifecycle("start-driver");
@@ -365,7 +400,7 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
365
400
  ...(this.args.fixtureValues.length > 0 ? { fixtureValues: this.args.fixtureValues } : {}),
366
401
  runsRoot: resolve(request.runsRoot),
367
402
  runDir: this.runDir.path,
368
- artifactsDir: this.runDir.artifactsDir,
403
+ artifactsDir: this.workspace.path,
369
404
  abortSignal: request.abortSignal ?? new AbortController().signal,
370
405
  });
371
406
  this.append({ type: "ready", ...this.ready });
@@ -390,6 +425,7 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
390
425
  metadata.exitReason = "error";
391
426
  metadata.operationalFailure = { phase: operationalPhase, reason };
392
427
  metadata.phaseDurationMs = phaseDurations(this.runDir.recorded);
428
+ metadata.actionTiming = actionTiming(this.runDir.recorded);
393
429
  await this.runDir.writeJson("run.json", metadata);
394
430
  await this.args.request.recordPreGradingAccounting?.(metadata);
395
431
  await this.args.request.recordModelAttemptsComplete?.(this.subjectAttemptIds);
@@ -407,9 +443,12 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
407
443
  this.lifecycle("collect-end");
408
444
  await this.runDir.events.drain();
409
445
  const completed = await this.completedAgentRun();
446
+ completed.metadata.actionTiming = actionTiming(this.runDir.recorded);
410
447
  this.metadata = completed.metadata;
411
448
  this.usage = completed.usage;
412
449
  this.run = completed.run;
450
+ const executionWorkspace = await this.args.driver.verificationWorkspace?.();
451
+ if (executionWorkspace) bindRunExecutionWorkspace(this.run, executionWorkspace);
413
452
  await writeFrozenCase(this.runDir.path, this.args.authoredCase, this.args.casePath);
414
453
  await this.runDir.writeJson("run.json", completed.metadata);
415
454
  await this.runDir.writeJson("artifacts.json", this.collection.artifacts);
@@ -430,6 +469,7 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
430
469
  grading.assertions.flatMap((assertion) => (assertion.usage ? [assertion.usage] : [])),
431
470
  );
432
471
  metadata.phaseDurationMs = phaseDurations(this.runDir.recorded);
472
+ metadata.actionTiming = actionTiming(this.runDir.recorded);
433
473
  await this.runDir.events.drain();
434
474
  await this.runDir.writeJson("run.json", metadata);
435
475
  await this.runDir.writeJson("artifacts.json", this.collection.artifacts);
@@ -438,6 +478,12 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
438
478
  }
439
479
 
440
480
  async close(primaryError: unknown | null): Promise<void> {
481
+ if (this.workspace) {
482
+ await closeQuietly(async () => {
483
+ await this.args.driver.close();
484
+ await this.workspace?.archive(this.runDir.artifactsDir);
485
+ }, `run workspace ${this.workspace.path}`);
486
+ }
441
487
  if (primaryError instanceof Error) {
442
488
  (primaryError as Error & RunDirCarrier).luxRunDir = this.runDir.path;
443
489
  }
@@ -506,6 +552,7 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
506
552
  private fallbackFailureMetadata(): RunMetadata {
507
553
  const failedAt = new Date();
508
554
  const answererAccounting = readAnswererModelAccounting(this.args.answerer);
555
+ const ready = this.ready ?? { agentId: "start-failed" };
509
556
  return {
510
557
  schemaVersion: 1,
511
558
  luxVersion: this.args.luxVersion,
@@ -514,8 +561,9 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
514
561
  agentEndedAt: failedAt.toISOString(),
515
562
  endedAt: failedAt.toISOString(),
516
563
  exitReason: "error",
517
- driver: { name: this.args.driverName, ...(this.ready ?? { agentId: "start-failed" }) },
564
+ driver: { name: this.args.driverName, ...ready },
518
565
  answerer: answererMetadata(this.args.answererName, this.args.answererConfig),
566
+ agentUsageAvailability: "unavailable",
519
567
  usage: {
520
568
  agent: emptyUsage(),
521
569
  answerer: readAnswererUsage(this.args.answerer),
@@ -530,6 +578,7 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
530
578
  interruptCounts: this.interruptCounts,
531
579
  toolCallCount: this.toolCallCount,
532
580
  toolOutcomes: summarizeToolOutcomes(this.runDir.recorded),
581
+ agentActivity: summarizeAgentActivity(this.runDir.recorded, ready),
533
582
  artifacts: { count: this.collection.artifacts.length },
534
583
  provenance: this.runProvenance(),
535
584
  };
@@ -539,7 +588,16 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
539
588
  if (!this.ready) return { artifacts: [] };
540
589
  try {
541
590
  await this.args.driver.quiesce?.();
542
- return { artifacts: await this.args.driver.collect() };
591
+ const artifacts = await this.args.driver.collect();
592
+ const archived =
593
+ (await this.workspace?.archive(this.runDir.artifactsDir, artifacts)) ?? artifacts;
594
+ return {
595
+ artifacts: await identifyArtifactOrigins(
596
+ this.runDir.path,
597
+ archived,
598
+ this.fixtureFileHashes,
599
+ ),
600
+ };
543
601
  } catch (error) {
544
602
  const reason = errorMessage(error);
545
603
  this.runDir.events.append({
@@ -563,14 +621,17 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
563
621
  const summary = outcome.kind === "done" ? outcome.done.summary : outcome.error.summary;
564
622
  const driverCost = costFromSummary(summary);
565
623
  const reportedModelAccounting = modelAccountingFromSummary(summary);
624
+ const driverMetrics = metricsFromSummary(summary);
566
625
  const answererAccounting = readAnswererModelAccounting(this.args.answerer);
567
626
  const agentCalls = this.ready ? (reportedModelAccounting?.modelCalls ?? 1) : 0;
568
627
  const operationalFailure = loopFailure(outcome, this.collection.error);
628
+ const agentUsage = usageFromSummary(summary);
569
629
  const usage: RunUsage = {
570
- agent: usageFromSummary(summary) ?? emptyUsage(),
630
+ agent: agentUsage ?? emptyUsage(),
571
631
  answerer: readAnswererUsage(this.args.answerer),
572
632
  grading: emptyUsage(),
573
633
  };
634
+ const ready = this.ready ?? { agentId: "not-started" };
574
635
  const metadata: RunMetadata = {
575
636
  schemaVersion: 1,
576
637
  luxVersion: this.args.luxVersion,
@@ -579,9 +640,10 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
579
640
  agentEndedAt: agentEndedAt.toISOString(),
580
641
  endedAt: agentEndedAt.toISOString(),
581
642
  exitReason,
582
- driver: { name: this.args.driverName, ...(this.ready ?? { agentId: "not-started" }) },
643
+ driver: { name: this.args.driverName, ...ready },
583
644
  answerer: answererMetadata(this.args.answererName, this.args.answererConfig),
584
645
  usage,
646
+ agentUsageAvailability: agentUsage === null ? "unavailable" : "reported",
585
647
  modelAccounting: {
586
648
  agentCalls,
587
649
  answererCalls: answererAccounting.calls,
@@ -593,10 +655,12 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
593
655
  interruptCounts: this.interruptCounts,
594
656
  toolCallCount: this.toolCallCount,
595
657
  toolOutcomes: summarizeToolOutcomes(this.runDir.recorded),
658
+ agentActivity: summarizeAgentActivity(this.runDir.recorded, ready),
596
659
  artifacts: await artifactMeasurements(this.collection.artifacts, this.runDir.path),
597
660
  ...(operationalFailure ? { operationalFailure } : {}),
598
661
  provenance: this.runProvenance(),
599
662
  ...(driverCost !== undefined ? { cost: { usd: driverCost } } : {}),
663
+ ...(Object.keys(driverMetrics).length > 0 ? { driverMetrics } : {}),
600
664
  };
601
665
  return {
602
666
  metadata,
@@ -621,6 +685,7 @@ class RunExecution implements RunLifecycleEffects<RunResult> {
621
685
  ...(this.fixturesHash ? { fixturesHash: this.fixturesHash } : {}),
622
686
  ...(request.subjectHash ? { subjectHash: request.subjectHash } : {}),
623
687
  ...(request.profileId ? { profileId: request.profileId } : {}),
688
+ ...(this.args.permutationId ? { permutationId: this.args.permutationId } : {}),
624
689
  ...(request.experimentId ? { experimentId: request.experimentId } : {}),
625
690
  ...(request.variantId ? { variantId: request.variantId } : {}),
626
691
  ...(request.candidateId ? { candidateId: request.candidateId } : {}),
@@ -23,6 +23,7 @@ type RunLifecycleContext = {
23
23
  phase: RunFailurePhase;
24
24
  result: unknown;
25
25
  error: unknown;
26
+ failed: boolean;
26
27
  };
27
28
  type RunLifecycleInput = { effects: ErasedEffects };
28
29
  type RunLifecycleOutcome =
@@ -56,7 +57,7 @@ const runLifecycleMachine = setup({
56
57
  actions: {
57
58
  captureError: assign(({ context, event }) => {
58
59
  const error = "error" in event ? event.error : new Error("run lifecycle failed");
59
- return { error, phase: isRunTraceLimit(error) ? "trace" : context.phase };
60
+ return { error, failed: true, phase: isRunTraceLimit(error) ? "trace" : context.phase };
60
61
  }),
61
62
  captureResult: assign({
62
63
  result: ({ event }) => ("output" in event ? event.output : undefined),
@@ -73,6 +74,7 @@ const runLifecycleMachine = setup({
73
74
  phase: "setup",
74
75
  result: undefined,
75
76
  error: undefined,
77
+ failed: false,
76
78
  }),
77
79
  initial: "preparing",
78
80
  states: {
@@ -153,7 +155,7 @@ const runLifecycleMachine = setup({
153
155
  failed: { type: "final" },
154
156
  },
155
157
  output: ({ context }) => {
156
- if (context.error !== undefined) {
158
+ if (context.failed) {
157
159
  return { status: "failed", error: context.error };
158
160
  }
159
161
  return { status: "succeeded", result: context.result };
@@ -0,0 +1,62 @@
1
+ import { cp, lstat, mkdir, mkdtemp, realpath, rename, rm, rmdir } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
+ import type { Artifact } from "../core/index.js";
5
+
6
+ /** Keep package-manager discovery and repository ignore rules outside subject workspaces. */
7
+ export class RunWorkspace {
8
+ private archived = false;
9
+ readonly path: string;
10
+
11
+ private constructor(path: string) {
12
+ this.path = path;
13
+ }
14
+
15
+ static async create(): Promise<RunWorkspace> {
16
+ const root = join(tmpdir(), `lux-workspaces-${process.getuid?.() ?? "user"}`);
17
+ await mkdir(root, { recursive: true, mode: 0o700 });
18
+ const metadata = await lstat(root);
19
+ if (
20
+ !metadata.isDirectory() ||
21
+ metadata.isSymbolicLink() ||
22
+ (process.getuid && metadata.uid !== process.getuid())
23
+ ) {
24
+ throw new Error(
25
+ `Lux workspace root must be a real directory owned by the current user: ${root}`,
26
+ );
27
+ }
28
+ return new RunWorkspace(await realpath(await mkdtemp(join(root, "run-"))));
29
+ }
30
+
31
+ async archive(destination: string, artifacts: Artifact[] = []): Promise<Artifact[]> {
32
+ if (!this.archived) {
33
+ const metadata = await lstat(this.path);
34
+ if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
35
+ throw new Error(`run workspace must remain a real directory: ${this.path}`);
36
+ }
37
+ await rmdir(destination).catch((error: NodeJS.ErrnoException) => {
38
+ if (error.code !== "ENOENT") throw error;
39
+ });
40
+ try {
41
+ await rename(this.path, destination);
42
+ } catch (error) {
43
+ if ((error as NodeJS.ErrnoException).code !== "EXDEV") throw error;
44
+ await cp(this.path, destination, { recursive: true, verbatimSymlinks: true });
45
+ await rm(this.path, { recursive: true });
46
+ }
47
+ this.archived = true;
48
+ }
49
+ return artifacts.map((artifact) => {
50
+ if (!artifact.root) return artifact;
51
+ const path = relative(this.path, resolve(artifact.root));
52
+ if (path === "") {
53
+ const { root: _root, ...captured } = artifact;
54
+ return captured;
55
+ }
56
+ if (path === ".." || path.startsWith(`..${sep}`) || isAbsolute(path)) {
57
+ return artifact;
58
+ }
59
+ return { ...artifact, root: join(destination, path) };
60
+ });
61
+ }
62
+ }
@@ -5,6 +5,7 @@ import {
5
5
  MetricSummarySchema,
6
6
  type SuiteSample,
7
7
  type SuiteSummary,
8
+ suiteGroupKey,
8
9
  summarizeNumbers,
9
10
  } from "./suite-summary.js";
10
11
 
@@ -18,6 +19,7 @@ const ComparedOutcomeSchema = z
18
19
  export const SuiteCaseComparisonSchema = z
19
20
  .object({
20
21
  canonicalCaseId: z.string(),
22
+ permutationId: z.exactOptional(z.string()),
21
23
  before: ComparedOutcomeSchema.nullable(),
22
24
  after: ComparedOutcomeSchema.nullable(),
23
25
  passRateDelta: z.number().nullable(),
@@ -40,6 +42,7 @@ export const SuiteComparisonSchema = z
40
42
  z
41
43
  .object({
42
44
  canonicalCaseId: z.string(),
45
+ permutationId: z.exactOptional(z.string()),
43
46
  repetition: z.number().int().positive(),
44
47
  before: z.string().nullable(),
45
48
  after: z.string().nullable(),
@@ -54,9 +57,10 @@ export type SuiteComparison = z.infer<typeof SuiteComparisonSchema>;
54
57
  const samplesByCase = (summary: SuiteSummary): Map<string, SuiteSample[]> => {
55
58
  const out = new Map<string, SuiteSample[]>();
56
59
  for (const sample of summary.samples) {
57
- const entries = out.get(sample.canonicalCaseId) ?? [];
60
+ const key = suiteGroupKey(sample);
61
+ const entries = out.get(key) ?? [];
58
62
  entries.push(sample);
59
- out.set(sample.canonicalCaseId, entries);
63
+ out.set(key, entries);
60
64
  }
61
65
  return out;
62
66
  };
@@ -70,10 +74,19 @@ const pairedMetricDeltas = (
70
74
  const a = before[index];
71
75
  const b = after[index];
72
76
  if (!a || !b) continue;
73
- const names = new Set([...Object.keys(a.metrics), ...Object.keys(b.metrics)]);
77
+ const am: Record<string, number> = {
78
+ ...a.metrics,
79
+ ...(a.score !== undefined ? { score: a.score } : {}),
80
+ };
81
+ const bm: Record<string, number> = {
82
+ ...b.metrics,
83
+ ...(b.score !== undefined ? { score: b.score } : {}),
84
+ };
85
+ const names = new Set([...Object.keys(am), ...Object.keys(bm)]);
74
86
  for (const name of names) {
75
- const av = a.metrics[name];
76
- const bv = b.metrics[name];
87
+ if (name === "score" && (!a.scoreBasis || a.scoreBasis !== b.scoreBasis)) continue;
88
+ const av = am[name];
89
+ const bv = bm[name];
77
90
  if (av === undefined || bv === undefined) continue;
78
91
  const values = deltas.get(name) ?? [];
79
92
  values.push(bv - av);
@@ -95,14 +108,23 @@ export const compareSuiteSummaries = (
95
108
  options: { passRateTolerance?: number } = {},
96
109
  ): SuiteComparison => {
97
110
  const passRateTolerance = options.passRateTolerance ?? 0;
98
- const aCases = new Map(a.cases.map((entry) => [entry.canonicalCaseId, entry]));
99
- const bCases = new Map(b.cases.map((entry) => [entry.canonicalCaseId, entry]));
111
+ const aCases = new Map(a.cases.map((entry) => [suiteGroupKey(entry), entry]));
112
+ const bCases = new Map(b.cases.map((entry) => [suiteGroupKey(entry), entry]));
100
113
  const aSamples = samplesByCase(a);
101
114
  const bSamples = samplesByCase(b);
102
- const ids = new Set([...aCases.keys(), ...bCases.keys()]);
103
- const identityMismatches = [...ids].sort().flatMap((canonicalCaseId) => {
104
- const before = aSamples.get(canonicalCaseId) ?? [];
105
- const after = bSamples.get(canonicalCaseId) ?? [];
115
+ const groups = new Map(
116
+ [...a.cases, ...b.cases].map((entry) => [
117
+ suiteGroupKey(entry),
118
+ {
119
+ canonicalCaseId: entry.canonicalCaseId,
120
+ ...(entry.permutationId ? { permutationId: entry.permutationId } : {}),
121
+ },
122
+ ]),
123
+ );
124
+ const keys = [...groups.keys()].sort();
125
+ const identityMismatches = keys.flatMap((key) => {
126
+ const before = aSamples.get(key) ?? [];
127
+ const after = bSamples.get(key) ?? [];
106
128
  return Array.from({ length: Math.max(before.length, after.length) }, (_, index) => {
107
129
  const beforeHash = before[index]?.identityHash ?? null;
108
130
  const afterHash = after[index]?.identityHash ?? null;
@@ -110,7 +132,7 @@ export const compareSuiteSummaries = (
110
132
  ? []
111
133
  : [
112
134
  {
113
- canonicalCaseId,
135
+ ...groups.get(key),
114
136
  repetition: index + 1,
115
137
  before: beforeHash,
116
138
  after: afterHash,
@@ -118,9 +140,9 @@ export const compareSuiteSummaries = (
118
140
  ];
119
141
  }).flat();
120
142
  });
121
- const cases = [...ids].sort().map((canonicalCaseId) => {
122
- const before = aCases.get(canonicalCaseId);
123
- const after = bCases.get(canonicalCaseId);
143
+ const cases = keys.map((key) => {
144
+ const before = aCases.get(key);
145
+ const after = bCases.get(key);
124
146
  let passRateDelta: number | null = null;
125
147
  if (before && after) {
126
148
  passRateDelta = after.passRate - before.passRate;
@@ -128,16 +150,13 @@ export const compareSuiteSummaries = (
128
150
  passRateDelta = -before.passRate;
129
151
  }
130
152
  return {
131
- canonicalCaseId,
153
+ ...groups.get(key),
132
154
  before: before ? { attempts: before.attempts, passRate: before.passRate } : null,
133
155
  after: after ? { attempts: after.attempts, passRate: after.passRate } : null,
134
156
  passRateDelta,
135
157
  regressed:
136
158
  Boolean(before) && (!after || after.passRate + passRateTolerance < (before?.passRate ?? 0)),
137
- pairedMetricDeltas: pairedMetricDeltas(
138
- aSamples.get(canonicalCaseId) ?? [],
139
- bSamples.get(canonicalCaseId) ?? [],
140
- ),
159
+ pairedMetricDeltas: pairedMetricDeltas(aSamples.get(key) ?? [], bSamples.get(key) ?? []),
141
160
  };
142
161
  });
143
162
  return SuiteComparisonSchema.parse({
@@ -182,13 +201,18 @@ export const formatSuiteComparisonText = (comparison: SuiteComparison): string =
182
201
  if (comparison.identityMismatches.length > 0) {
183
202
  lines.push(` identity mismatches: ${comparison.identityMismatches.length}`);
184
203
  for (const mismatch of comparison.identityMismatches) {
185
- lines.push(` ! ${mismatch.canonicalCaseId} repetition ${mismatch.repetition}`);
204
+ lines.push(` ! ${suiteGroupKey(mismatch)} repetition ${mismatch.repetition}`);
186
205
  }
187
206
  }
188
207
  for (const entry of comparison.cases) {
189
- if (!entry.regressed) continue;
208
+ if (entry.regressed) {
209
+ lines.push(
210
+ ` ↓ ${suiteGroupKey(entry)}: ${entry.before ? percent(entry.before.passRate) : "—"} → ${entry.after ? percent(entry.after.passRate) : "missing"}`,
211
+ );
212
+ }
213
+ const score = entry.pairedMetricDeltas.score;
190
214
  lines.push(
191
- ` ↓ ${entry.canonicalCaseId}: ${entry.before ? percent(entry.before.passRate) : "—"} → ${entry.after ? percent(entry.after.passRate) : "missing"}`,
215
+ ` ${suiteGroupKey(entry)} score change: ${score ? `${score.mean >= 0 ? "+" : ""}${score.mean} (${score.n} paired)` : "unavailable"}`,
192
216
  );
193
217
  }
194
218
  return lines.join("\n");