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

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 (717) 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 +3 -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/helpers.d.ts +2 -7
  25. package/lib/assertions/core/helpers.d.ts.map +1 -1
  26. package/lib/assertions/core/helpers.js +2 -6
  27. package/lib/assertions/core/helpers.js.map +1 -1
  28. package/lib/assertions/core/index.d.ts.map +1 -1
  29. package/lib/assertions/core/index.js +2 -1
  30. package/lib/assertions/core/index.js.map +1 -1
  31. package/lib/assertions/core/resource-checks.d.ts +19 -0
  32. package/lib/assertions/core/resource-checks.d.ts.map +1 -1
  33. package/lib/assertions/core/resource-checks.js +35 -5
  34. package/lib/assertions/core/resource-checks.js.map +1 -1
  35. package/lib/assertions/rubric/index.d.ts +26 -3
  36. package/lib/assertions/rubric/index.d.ts.map +1 -1
  37. package/lib/assertions/rubric/index.js +59 -13
  38. package/lib/assertions/rubric/index.js.map +1 -1
  39. package/lib/assertions/rubric/internal.d.ts +30 -5
  40. package/lib/assertions/rubric/internal.d.ts.map +1 -1
  41. package/lib/assertions/rubric/internal.js +181 -28
  42. package/lib/assertions/rubric/internal.js.map +1 -1
  43. package/lib/authoring.d.ts +36 -2
  44. package/lib/authoring.d.ts.map +1 -1
  45. package/lib/authoring.js +36 -1
  46. package/lib/authoring.js.map +1 -1
  47. package/lib/cli/bin.js +2 -13
  48. package/lib/cli/bin.js.map +1 -1
  49. package/lib/cli/command-runtime.d.ts +3 -3
  50. package/lib/cli/command-runtime.d.ts.map +1 -1
  51. package/lib/cli/command-runtime.js +17 -6
  52. package/lib/cli/command-runtime.js.map +1 -1
  53. package/lib/cli/doctor.d.ts +55 -0
  54. package/lib/cli/doctor.d.ts.map +1 -0
  55. package/lib/cli/doctor.js +14 -0
  56. package/lib/cli/doctor.js.map +1 -0
  57. package/lib/cli/harness-plan.d.ts +26 -0
  58. package/lib/cli/harness-plan.d.ts.map +1 -0
  59. package/lib/cli/harness-plan.js +75 -0
  60. package/lib/cli/harness-plan.js.map +1 -0
  61. package/lib/cli/init-templates.d.ts +11 -0
  62. package/lib/cli/init-templates.d.ts.map +1 -0
  63. package/lib/cli/init-templates.js +215 -0
  64. package/lib/cli/init-templates.js.map +1 -0
  65. package/lib/cli/init.d.ts +10 -0
  66. package/lib/cli/init.d.ts.map +1 -1
  67. package/lib/cli/init.js +34 -173
  68. package/lib/cli/init.js.map +1 -1
  69. package/lib/cli/output-schemas.d.ts +1406 -0
  70. package/lib/cli/output-schemas.d.ts.map +1 -0
  71. package/lib/cli/output-schemas.js +91 -0
  72. package/lib/cli/output-schemas.js.map +1 -0
  73. package/lib/cli/program.d.ts +140 -12
  74. package/lib/cli/program.d.ts.map +1 -1
  75. package/lib/cli/program.js +778 -646
  76. package/lib/cli/program.js.map +1 -1
  77. package/lib/cli/render/reporter.d.ts.map +1 -1
  78. package/lib/cli/render/reporter.js +40 -7
  79. package/lib/cli/render/reporter.js.map +1 -1
  80. package/lib/cli/run-options.d.ts +20 -4
  81. package/lib/cli/run-options.d.ts.map +1 -1
  82. package/lib/cli/run-options.js +100 -19
  83. package/lib/cli/run-options.js.map +1 -1
  84. package/lib/cli/view.d.ts +15 -0
  85. package/lib/cli/view.d.ts.map +1 -0
  86. package/lib/cli/view.js +168 -0
  87. package/lib/cli/view.js.map +1 -0
  88. package/lib/container/driver.d.ts +27 -0
  89. package/lib/container/driver.d.ts.map +1 -0
  90. package/lib/container/driver.js +197 -0
  91. package/lib/container/driver.js.map +1 -0
  92. package/lib/container/protocol.d.ts +12 -0
  93. package/lib/container/protocol.d.ts.map +1 -0
  94. package/lib/container/protocol.js +38 -0
  95. package/lib/container/protocol.js.map +1 -0
  96. package/lib/container/resources.d.ts +12 -0
  97. package/lib/container/resources.d.ts.map +1 -0
  98. package/lib/container/resources.js +133 -0
  99. package/lib/container/resources.js.map +1 -0
  100. package/lib/container/worker.d.ts +2 -0
  101. package/lib/container/worker.d.ts.map +1 -0
  102. package/lib/container/worker.js +85 -0
  103. package/lib/container/worker.js.map +1 -0
  104. package/lib/core/action-events.d.ts +29 -0
  105. package/lib/core/action-events.d.ts.map +1 -0
  106. package/lib/core/action-events.js +51 -0
  107. package/lib/core/action-events.js.map +1 -0
  108. package/lib/core/agent-activity.d.ts +49 -0
  109. package/lib/core/agent-activity.d.ts.map +1 -0
  110. package/lib/core/agent-activity.js +206 -0
  111. package/lib/core/agent-activity.js.map +1 -0
  112. package/lib/core/agent-environment.d.ts +5 -0
  113. package/lib/core/agent-environment.d.ts.map +1 -0
  114. package/lib/core/agent-environment.js +47 -0
  115. package/lib/core/agent-environment.js.map +1 -0
  116. package/lib/core/agent-events.d.ts +26 -0
  117. package/lib/core/agent-events.d.ts.map +1 -0
  118. package/lib/core/agent-events.js +13 -0
  119. package/lib/core/agent-events.js.map +1 -0
  120. package/lib/core/annotation.d.ts +6 -2
  121. package/lib/core/annotation.d.ts.map +1 -1
  122. package/lib/core/annotation.js +2 -1
  123. package/lib/core/annotation.js.map +1 -1
  124. package/lib/core/answerer.d.ts +12 -0
  125. package/lib/core/answerer.d.ts.map +1 -1
  126. package/lib/core/answerer.js +2 -0
  127. package/lib/core/answerer.js.map +1 -1
  128. package/lib/core/artifact-evidence.d.ts +8 -0
  129. package/lib/core/artifact-evidence.d.ts.map +1 -1
  130. package/lib/core/artifact-evidence.js +36 -4
  131. package/lib/core/artifact-evidence.js.map +1 -1
  132. package/lib/core/assertion.d.ts +15 -0
  133. package/lib/core/assertion.d.ts.map +1 -1
  134. package/lib/core/assertion.js +16 -0
  135. package/lib/core/assertion.js.map +1 -1
  136. package/lib/core/case.d.ts +106 -2
  137. package/lib/core/case.d.ts.map +1 -1
  138. package/lib/core/case.js +16 -2
  139. package/lib/core/case.js.map +1 -1
  140. package/lib/core/command-verification.d.ts +10 -0
  141. package/lib/core/command-verification.d.ts.map +1 -0
  142. package/lib/core/command-verification.js +66 -0
  143. package/lib/core/command-verification.js.map +1 -0
  144. package/lib/core/driver-execution.d.ts +83 -0
  145. package/lib/core/driver-execution.d.ts.map +1 -0
  146. package/lib/core/driver-execution.js +72 -0
  147. package/lib/core/driver-execution.js.map +1 -0
  148. package/lib/core/driver-metrics.d.ts +98 -0
  149. package/lib/core/driver-metrics.d.ts.map +1 -0
  150. package/lib/core/driver-metrics.js +36 -0
  151. package/lib/core/driver-metrics.js.map +1 -0
  152. package/lib/core/driver.d.ts +64 -0
  153. package/lib/core/driver.d.ts.map +1 -1
  154. package/lib/core/driver.js +28 -0
  155. package/lib/core/driver.js.map +1 -1
  156. package/lib/core/duration.d.ts +5 -0
  157. package/lib/core/duration.d.ts.map +1 -0
  158. package/lib/core/duration.js +49 -0
  159. package/lib/core/duration.js.map +1 -0
  160. package/lib/core/environment.d.ts +18 -0
  161. package/lib/core/environment.d.ts.map +1 -0
  162. package/lib/core/environment.js +21 -0
  163. package/lib/core/environment.js.map +1 -0
  164. package/lib/core/evaluation-clusters.d.ts +17 -0
  165. package/lib/core/evaluation-clusters.d.ts.map +1 -0
  166. package/lib/core/evaluation-clusters.js +23 -0
  167. package/lib/core/evaluation-clusters.js.map +1 -0
  168. package/lib/core/events.d.ts +36 -0
  169. package/lib/core/events.d.ts.map +1 -1
  170. package/lib/core/events.js +12 -2
  171. package/lib/core/events.js.map +1 -1
  172. package/lib/core/experiment.d.ts +32 -2
  173. package/lib/core/experiment.d.ts.map +1 -1
  174. package/lib/core/experiment.js +35 -18
  175. package/lib/core/experiment.js.map +1 -1
  176. package/lib/core/file-tree.d.ts +7 -0
  177. package/lib/core/file-tree.d.ts.map +1 -0
  178. package/lib/core/file-tree.js +35 -0
  179. package/lib/core/file-tree.js.map +1 -0
  180. package/lib/core/global-id.d.ts +6 -0
  181. package/lib/core/global-id.d.ts.map +1 -0
  182. package/lib/core/global-id.js +17 -0
  183. package/lib/core/global-id.js.map +1 -0
  184. package/lib/core/harness-catalog.d.ts +35 -0
  185. package/lib/core/harness-catalog.d.ts.map +1 -0
  186. package/lib/core/harness-catalog.js +45 -0
  187. package/lib/core/harness-catalog.js.map +1 -0
  188. package/lib/core/harness-catalogs/antigravity.d.ts +11 -0
  189. package/lib/core/harness-catalogs/antigravity.d.ts.map +1 -0
  190. package/lib/core/harness-catalogs/antigravity.js +23 -0
  191. package/lib/core/harness-catalogs/antigravity.js.map +1 -0
  192. package/lib/core/harness-catalogs/claude-code.d.ts +12 -0
  193. package/lib/core/harness-catalogs/claude-code.d.ts.map +1 -0
  194. package/lib/core/harness-catalogs/claude-code.js +24 -0
  195. package/lib/core/harness-catalogs/claude-code.js.map +1 -0
  196. package/lib/core/harness-catalogs/codex.d.ts +11 -0
  197. package/lib/core/harness-catalogs/codex.d.ts.map +1 -0
  198. package/lib/core/harness-catalogs/codex.js +26 -0
  199. package/lib/core/harness-catalogs/codex.js.map +1 -0
  200. package/lib/core/harness-catalogs/copilot.d.ts +29 -0
  201. package/lib/core/harness-catalogs/copilot.d.ts.map +1 -0
  202. package/lib/core/harness-catalogs/copilot.js +45 -0
  203. package/lib/core/harness-catalogs/copilot.js.map +1 -0
  204. package/lib/core/harness-catalogs/cursor.d.ts +2 -0
  205. package/lib/core/harness-catalogs/cursor.d.ts.map +1 -0
  206. package/lib/core/harness-catalogs/cursor.js +13 -0
  207. package/lib/core/harness-catalogs/cursor.js.map +1 -0
  208. package/lib/core/harness-catalogs/grok-build.d.ts +7 -0
  209. package/lib/core/harness-catalogs/grok-build.d.ts.map +1 -0
  210. package/lib/core/harness-catalogs/grok-build.js +18 -0
  211. package/lib/core/harness-catalogs/grok-build.js.map +1 -0
  212. package/lib/core/harness-catalogs/index.d.ts +73 -0
  213. package/lib/core/harness-catalogs/index.d.ts.map +1 -0
  214. package/lib/core/harness-catalogs/index.js +17 -0
  215. package/lib/core/harness-catalogs/index.js.map +1 -0
  216. package/lib/core/harness-matrix.d.ts +154 -0
  217. package/lib/core/harness-matrix.d.ts.map +1 -0
  218. package/lib/core/harness-matrix.js +204 -0
  219. package/lib/core/harness-matrix.js.map +1 -0
  220. package/lib/core/index.d.ts +12 -0
  221. package/lib/core/index.d.ts.map +1 -1
  222. package/lib/core/index.js +12 -0
  223. package/lib/core/index.js.map +1 -1
  224. package/lib/core/lifecycle-fixtures.d.ts.map +1 -1
  225. package/lib/core/lifecycle-fixtures.js +4 -2
  226. package/lib/core/lifecycle-fixtures.js.map +1 -1
  227. package/lib/core/model-cli.d.ts +9 -11
  228. package/lib/core/model-cli.d.ts.map +1 -1
  229. package/lib/core/model-cli.js +31 -19
  230. package/lib/core/model-cli.js.map +1 -1
  231. package/lib/core/platform-process.d.ts +6 -1
  232. package/lib/core/platform-process.d.ts.map +1 -1
  233. package/lib/core/platform-process.js +49 -11
  234. package/lib/core/platform-process.js.map +1 -1
  235. package/lib/core/run.d.ts +292 -1
  236. package/lib/core/run.d.ts.map +1 -1
  237. package/lib/core/run.js +27 -0
  238. package/lib/core/run.js.map +1 -1
  239. package/lib/core/secure-copy.d.ts.map +1 -0
  240. package/lib/core/secure-copy.js.map +1 -0
  241. package/lib/core/usage.d.ts +5 -0
  242. package/lib/core/usage.d.ts.map +1 -1
  243. package/lib/core/usage.js +3 -0
  244. package/lib/core/usage.js.map +1 -1
  245. package/lib/core/wire.d.ts +12 -0
  246. package/lib/core/wire.d.ts.map +1 -1
  247. package/lib/core/wire.js +5 -1
  248. package/lib/core/wire.js.map +1 -1
  249. package/lib/drivers/antigravity/artifacts.d.ts +2 -0
  250. package/lib/drivers/antigravity/artifacts.d.ts.map +1 -0
  251. package/lib/drivers/antigravity/artifacts.js +33 -0
  252. package/lib/drivers/antigravity/artifacts.js.map +1 -0
  253. package/lib/drivers/antigravity/config.d.ts +88 -0
  254. package/lib/drivers/antigravity/config.d.ts.map +1 -0
  255. package/lib/drivers/antigravity/config.js +87 -0
  256. package/lib/drivers/antigravity/config.js.map +1 -0
  257. package/lib/drivers/antigravity/events.d.ts +4 -0
  258. package/lib/drivers/antigravity/events.d.ts.map +1 -0
  259. package/lib/drivers/antigravity/events.js +241 -0
  260. package/lib/drivers/antigravity/events.js.map +1 -0
  261. package/lib/drivers/antigravity/index.d.ts +114 -0
  262. package/lib/drivers/antigravity/index.d.ts.map +1 -0
  263. package/lib/drivers/antigravity/index.js +113 -0
  264. package/lib/drivers/antigravity/index.js.map +1 -0
  265. package/lib/drivers/antigravity/runtime.d.ts +7 -0
  266. package/lib/drivers/antigravity/runtime.d.ts.map +1 -0
  267. package/lib/drivers/antigravity/runtime.js +83 -0
  268. package/lib/drivers/antigravity/runtime.js.map +1 -0
  269. package/lib/drivers/claude-code/deferred-process.d.ts +17 -0
  270. package/lib/drivers/claude-code/deferred-process.d.ts.map +1 -0
  271. package/lib/drivers/claude-code/deferred-process.js +108 -0
  272. package/lib/drivers/claude-code/deferred-process.js.map +1 -0
  273. package/lib/drivers/claude-code/index.d.ts +180 -10
  274. package/lib/drivers/claude-code/index.d.ts.map +1 -1
  275. package/lib/drivers/claude-code/index.js +186 -252
  276. package/lib/drivers/claude-code/index.js.map +1 -1
  277. package/lib/drivers/claude-code/isolation.d.ts +8 -0
  278. package/lib/drivers/claude-code/isolation.d.ts.map +1 -0
  279. package/lib/drivers/claude-code/isolation.js +199 -0
  280. package/lib/drivers/claude-code/isolation.js.map +1 -0
  281. package/lib/drivers/claude-code/parse-events.d.ts.map +1 -1
  282. package/lib/drivers/claude-code/parse-events.js +73 -8
  283. package/lib/drivers/claude-code/parse-events.js.map +1 -1
  284. package/lib/drivers/codex/app-events.d.ts +9 -2
  285. package/lib/drivers/codex/app-events.d.ts.map +1 -1
  286. package/lib/drivers/codex/app-events.js +104 -12
  287. package/lib/drivers/codex/app-events.js.map +1 -1
  288. package/lib/drivers/codex/config.d.ts +66 -5
  289. package/lib/drivers/codex/config.d.ts.map +1 -1
  290. package/lib/drivers/codex/config.js +39 -8
  291. package/lib/drivers/codex/config.js.map +1 -1
  292. package/lib/drivers/codex/exec-events.d.ts +4 -0
  293. package/lib/drivers/codex/exec-events.d.ts.map +1 -0
  294. package/lib/drivers/codex/exec-events.js +230 -0
  295. package/lib/drivers/codex/exec-events.js.map +1 -0
  296. package/lib/drivers/codex/index.d.ts +138 -4
  297. package/lib/drivers/codex/index.d.ts.map +1 -1
  298. package/lib/drivers/codex/index.js +112 -276
  299. package/lib/drivers/codex/index.js.map +1 -1
  300. package/lib/drivers/copilot/config.d.ts +84 -0
  301. package/lib/drivers/copilot/config.d.ts.map +1 -0
  302. package/lib/drivers/copilot/config.js +57 -0
  303. package/lib/drivers/copilot/config.js.map +1 -0
  304. package/lib/drivers/copilot/index.d.ts +107 -0
  305. package/lib/drivers/copilot/index.d.ts.map +1 -0
  306. package/lib/drivers/copilot/index.js +268 -0
  307. package/lib/drivers/copilot/index.js.map +1 -0
  308. package/lib/drivers/cursor/config.d.ts +28 -0
  309. package/lib/drivers/cursor/config.d.ts.map +1 -0
  310. package/lib/drivers/cursor/config.js +28 -0
  311. package/lib/drivers/cursor/config.js.map +1 -0
  312. package/lib/drivers/cursor/index.d.ts +44 -0
  313. package/lib/drivers/cursor/index.d.ts.map +1 -0
  314. package/lib/drivers/cursor/index.js +286 -0
  315. package/lib/drivers/cursor/index.js.map +1 -0
  316. package/lib/drivers/cursor/interaction.d.ts +6 -0
  317. package/lib/drivers/cursor/interaction.d.ts.map +1 -0
  318. package/lib/drivers/cursor/interaction.js +55 -0
  319. package/lib/drivers/cursor/interaction.js.map +1 -0
  320. package/lib/drivers/grok-build/config.d.ts +68 -0
  321. package/lib/drivers/grok-build/config.d.ts.map +1 -0
  322. package/lib/drivers/grok-build/config.js +40 -0
  323. package/lib/drivers/grok-build/config.js.map +1 -0
  324. package/lib/drivers/grok-build/index.d.ts +87 -0
  325. package/lib/drivers/grok-build/index.d.ts.map +1 -0
  326. package/lib/drivers/grok-build/index.js +293 -0
  327. package/lib/drivers/grok-build/index.js.map +1 -0
  328. package/lib/drivers/mcp/index.d.ts +37 -4
  329. package/lib/drivers/mcp/index.d.ts.map +1 -1
  330. package/lib/drivers/mcp/index.js +25 -11
  331. package/lib/drivers/mcp/index.js.map +1 -1
  332. package/lib/drivers/shared/acp-events.d.ts +15 -0
  333. package/lib/drivers/shared/acp-events.d.ts.map +1 -0
  334. package/lib/drivers/shared/acp-events.js +83 -0
  335. package/lib/drivers/shared/acp-events.js.map +1 -0
  336. package/lib/drivers/shared/acp-interaction.d.ts +7 -0
  337. package/lib/drivers/shared/acp-interaction.d.ts.map +1 -0
  338. package/lib/drivers/shared/acp-interaction.js +20 -0
  339. package/lib/drivers/shared/acp-interaction.js.map +1 -0
  340. package/lib/drivers/shared/acp-session.d.ts +4 -0
  341. package/lib/drivers/shared/acp-session.d.ts.map +1 -0
  342. package/lib/drivers/shared/acp-session.js +23 -0
  343. package/lib/drivers/shared/acp-session.js.map +1 -0
  344. package/lib/drivers/shared/acp-transport.d.ts +40 -0
  345. package/lib/drivers/shared/acp-transport.d.ts.map +1 -0
  346. package/lib/drivers/shared/acp-transport.js +152 -0
  347. package/lib/drivers/shared/acp-transport.js.map +1 -0
  348. package/lib/drivers/shared/artifacts.d.ts.map +1 -1
  349. package/lib/drivers/shared/artifacts.js +3 -2
  350. package/lib/drivers/shared/artifacts.js.map +1 -1
  351. package/lib/drivers/shared/experiment-behavior.d.ts +13 -0
  352. package/lib/drivers/shared/experiment-behavior.d.ts.map +1 -0
  353. package/lib/drivers/shared/experiment-behavior.js +197 -0
  354. package/lib/drivers/shared/experiment-behavior.js.map +1 -0
  355. package/lib/drivers/shared/experiment-policy.d.ts +4 -0
  356. package/lib/drivers/shared/experiment-policy.d.ts.map +1 -0
  357. package/lib/drivers/shared/experiment-policy.js +143 -0
  358. package/lib/drivers/shared/experiment-policy.js.map +1 -0
  359. package/lib/drivers/subprocess/index.d.ts +39 -4
  360. package/lib/drivers/subprocess/index.d.ts.map +1 -1
  361. package/lib/drivers/subprocess/index.js +56 -12
  362. package/lib/drivers/subprocess/index.js.map +1 -1
  363. package/lib/index.d.ts +22 -8
  364. package/lib/index.d.ts.map +1 -1
  365. package/lib/index.js +20 -6
  366. package/lib/index.js.map +1 -1
  367. package/lib/optimization/reflective.d.ts +3 -1
  368. package/lib/optimization/reflective.d.ts.map +1 -1
  369. package/lib/optimization/reflective.js +3 -2
  370. package/lib/optimization/reflective.js.map +1 -1
  371. package/lib/orchestrator/annotation-loader.d.ts +6 -2
  372. package/lib/orchestrator/annotation-loader.d.ts.map +1 -1
  373. package/lib/orchestrator/annotation-loader.js +8 -0
  374. package/lib/orchestrator/annotation-loader.js.map +1 -1
  375. package/lib/orchestrator/annotation-store.d.ts.map +1 -1
  376. package/lib/orchestrator/annotation-store.js +16 -2
  377. package/lib/orchestrator/annotation-store.js.map +1 -1
  378. package/lib/orchestrator/artifact-origin.d.ts +3 -0
  379. package/lib/orchestrator/artifact-origin.d.ts.map +1 -0
  380. package/lib/orchestrator/artifact-origin.js +40 -0
  381. package/lib/orchestrator/artifact-origin.js.map +1 -0
  382. package/lib/orchestrator/campaign-lifecycle.d.ts +1 -0
  383. package/lib/orchestrator/campaign-lifecycle.d.ts.map +1 -1
  384. package/lib/orchestrator/campaign-lifecycle.js +4 -1
  385. package/lib/orchestrator/campaign-lifecycle.js.map +1 -1
  386. package/lib/orchestrator/candidates.d.ts.map +1 -1
  387. package/lib/orchestrator/candidates.js +3 -2
  388. package/lib/orchestrator/candidates.js.map +1 -1
  389. package/lib/orchestrator/compare.d.ts +17 -1
  390. package/lib/orchestrator/compare.d.ts.map +1 -1
  391. package/lib/orchestrator/compare.js +25 -1
  392. package/lib/orchestrator/compare.js.map +1 -1
  393. package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
  394. package/lib/orchestrator/comparison-identity.js +2 -0
  395. package/lib/orchestrator/comparison-identity.js.map +1 -1
  396. package/lib/orchestrator/config.d.ts +177 -1
  397. package/lib/orchestrator/config.d.ts.map +1 -1
  398. package/lib/orchestrator/config.js +18 -4
  399. package/lib/orchestrator/config.js.map +1 -1
  400. package/lib/orchestrator/discover.d.ts +1 -0
  401. package/lib/orchestrator/discover.d.ts.map +1 -1
  402. package/lib/orchestrator/discover.js +7 -1
  403. package/lib/orchestrator/discover.js.map +1 -1
  404. package/lib/orchestrator/doctor.d.ts +1 -0
  405. package/lib/orchestrator/doctor.d.ts.map +1 -1
  406. package/lib/orchestrator/doctor.js +121 -33
  407. package/lib/orchestrator/doctor.js.map +1 -1
  408. package/lib/orchestrator/driver-capabilities.d.ts +4 -0
  409. package/lib/orchestrator/driver-capabilities.d.ts.map +1 -0
  410. package/lib/orchestrator/driver-capabilities.js +13 -0
  411. package/lib/orchestrator/driver-capabilities.js.map +1 -0
  412. package/lib/orchestrator/driver-identity.d.ts +5 -0
  413. package/lib/orchestrator/driver-identity.d.ts.map +1 -0
  414. package/lib/orchestrator/driver-identity.js +51 -0
  415. package/lib/orchestrator/driver-identity.js.map +1 -0
  416. package/lib/orchestrator/experiment-context.d.ts +51 -3
  417. package/lib/orchestrator/experiment-context.d.ts.map +1 -1
  418. package/lib/orchestrator/experiment-context.js.map +1 -1
  419. package/lib/orchestrator/experiment-contracts.d.ts +30 -1
  420. package/lib/orchestrator/experiment-contracts.d.ts.map +1 -1
  421. package/lib/orchestrator/experiment-corpus.d.ts +2 -1
  422. package/lib/orchestrator/experiment-corpus.d.ts.map +1 -1
  423. package/lib/orchestrator/experiment-corpus.js +28 -22
  424. package/lib/orchestrator/experiment-corpus.js.map +1 -1
  425. package/lib/orchestrator/experiment-effects.d.ts +33 -0
  426. package/lib/orchestrator/experiment-effects.d.ts.map +1 -0
  427. package/lib/orchestrator/experiment-effects.js +44 -0
  428. package/lib/orchestrator/experiment-effects.js.map +1 -0
  429. package/lib/orchestrator/experiment-evaluation.d.ts.map +1 -1
  430. package/lib/orchestrator/experiment-evaluation.js +56 -5
  431. package/lib/orchestrator/experiment-evaluation.js.map +1 -1
  432. package/lib/orchestrator/experiment-identity.d.ts +3 -0
  433. package/lib/orchestrator/experiment-identity.d.ts.map +1 -1
  434. package/lib/orchestrator/experiment-identity.js +22 -33
  435. package/lib/orchestrator/experiment-identity.js.map +1 -1
  436. package/lib/orchestrator/experiment-loader.d.ts +8 -3
  437. package/lib/orchestrator/experiment-loader.d.ts.map +1 -1
  438. package/lib/orchestrator/experiment-preflight.d.ts +3 -0
  439. package/lib/orchestrator/experiment-preflight.d.ts.map +1 -0
  440. package/lib/orchestrator/experiment-preflight.js +21 -0
  441. package/lib/orchestrator/experiment-preflight.js.map +1 -0
  442. package/lib/orchestrator/experiment-report.d.ts +90 -1
  443. package/lib/orchestrator/experiment-report.d.ts.map +1 -1
  444. package/lib/orchestrator/experiment-report.js +9 -1
  445. package/lib/orchestrator/experiment-report.js.map +1 -1
  446. package/lib/orchestrator/experiment-runs.d.ts +61 -2
  447. package/lib/orchestrator/experiment-runs.d.ts.map +1 -1
  448. package/lib/orchestrator/experiment-runs.js +13 -5
  449. package/lib/orchestrator/experiment-runs.js.map +1 -1
  450. package/lib/orchestrator/experiment-runtime-identity.d.ts +0 -16
  451. package/lib/orchestrator/experiment-runtime-identity.d.ts.map +1 -1
  452. package/lib/orchestrator/experiment-runtime-identity.js +5 -220
  453. package/lib/orchestrator/experiment-runtime-identity.js.map +1 -1
  454. package/lib/orchestrator/experiment-selection.d.ts.map +1 -1
  455. package/lib/orchestrator/experiment-selection.js +52 -0
  456. package/lib/orchestrator/experiment-selection.js.map +1 -1
  457. package/lib/orchestrator/experiment.d.ts +3 -3
  458. package/lib/orchestrator/experiment.d.ts.map +1 -1
  459. package/lib/orchestrator/experiment.js +26 -21
  460. package/lib/orchestrator/experiment.js.map +1 -1
  461. package/lib/orchestrator/fixture-identity.d.ts +1 -0
  462. package/lib/orchestrator/fixture-identity.d.ts.map +1 -1
  463. package/lib/orchestrator/fixture-identity.js +6 -1
  464. package/lib/orchestrator/fixture-identity.js.map +1 -1
  465. package/lib/orchestrator/fs-read.d.ts +1 -6
  466. package/lib/orchestrator/fs-read.d.ts.map +1 -1
  467. package/lib/orchestrator/fs-read.js +2 -32
  468. package/lib/orchestrator/fs-read.js.map +1 -1
  469. package/lib/orchestrator/grader-experiment.d.ts +29 -1
  470. package/lib/orchestrator/grader-experiment.d.ts.map +1 -1
  471. package/lib/orchestrator/grader-experiment.js +54 -9
  472. package/lib/orchestrator/grader-experiment.js.map +1 -1
  473. package/lib/orchestrator/grading.d.ts +2 -1
  474. package/lib/orchestrator/grading.d.ts.map +1 -1
  475. package/lib/orchestrator/grading.js +27 -8
  476. package/lib/orchestrator/grading.js.map +1 -1
  477. package/lib/orchestrator/harness-catalog-drift.d.ts +22 -0
  478. package/lib/orchestrator/harness-catalog-drift.d.ts.map +1 -0
  479. package/lib/orchestrator/harness-catalog-drift.js +90 -0
  480. package/lib/orchestrator/harness-catalog-drift.js.map +1 -0
  481. package/lib/orchestrator/harness-registry.d.ts +4 -0
  482. package/lib/orchestrator/harness-registry.d.ts.map +1 -0
  483. package/lib/orchestrator/harness-registry.js +5 -0
  484. package/lib/orchestrator/harness-registry.js.map +1 -0
  485. package/lib/orchestrator/index.d.ts +1 -1
  486. package/lib/orchestrator/index.d.ts.map +1 -1
  487. package/lib/orchestrator/index.js +1 -1
  488. package/lib/orchestrator/index.js.map +1 -1
  489. package/lib/orchestrator/list-runs.d.ts +8 -1
  490. package/lib/orchestrator/list-runs.d.ts.map +1 -1
  491. package/lib/orchestrator/list-runs.js +77 -12
  492. package/lib/orchestrator/list-runs.js.map +1 -1
  493. package/lib/orchestrator/optimization-lifecycle.d.ts.map +1 -1
  494. package/lib/orchestrator/optimization-lifecycle.js +3 -1
  495. package/lib/orchestrator/optimization-lifecycle.js.map +1 -1
  496. package/lib/orchestrator/orchestrator.d.ts +18 -2
  497. package/lib/orchestrator/orchestrator.d.ts.map +1 -1
  498. package/lib/orchestrator/orchestrator.js +50 -168
  499. package/lib/orchestrator/orchestrator.js.map +1 -1
  500. package/lib/orchestrator/paired-effects.d.ts +34 -0
  501. package/lib/orchestrator/paired-effects.d.ts.map +1 -0
  502. package/lib/orchestrator/paired-effects.js +158 -0
  503. package/lib/orchestrator/paired-effects.js.map +1 -0
  504. package/lib/orchestrator/provenance.d.ts +5 -1
  505. package/lib/orchestrator/provenance.d.ts.map +1 -1
  506. package/lib/orchestrator/provenance.js +16 -3
  507. package/lib/orchestrator/provenance.js.map +1 -1
  508. package/lib/orchestrator/regrade.d.ts +7 -0
  509. package/lib/orchestrator/regrade.d.ts.map +1 -1
  510. package/lib/orchestrator/rubric-loader.js +1 -1
  511. package/lib/orchestrator/rubric-loader.js.map +1 -1
  512. package/lib/orchestrator/run-dir.d.ts +2 -0
  513. package/lib/orchestrator/run-dir.d.ts.map +1 -1
  514. package/lib/orchestrator/run-dir.js +1 -1
  515. package/lib/orchestrator/run-dir.js.map +1 -1
  516. package/lib/orchestrator/run-execution.d.ts +3 -0
  517. package/lib/orchestrator/run-execution.d.ts.map +1 -1
  518. package/lib/orchestrator/run-execution.js +66 -12
  519. package/lib/orchestrator/run-execution.js.map +1 -1
  520. package/lib/orchestrator/run-lifecycle.d.ts +1 -0
  521. package/lib/orchestrator/run-lifecycle.d.ts.map +1 -1
  522. package/lib/orchestrator/run-lifecycle.js +3 -2
  523. package/lib/orchestrator/run-lifecycle.js.map +1 -1
  524. package/lib/orchestrator/run-workspace.d.ts +10 -0
  525. package/lib/orchestrator/run-workspace.d.ts.map +1 -0
  526. package/lib/orchestrator/run-workspace.js +58 -0
  527. package/lib/orchestrator/run-workspace.js.map +1 -0
  528. package/lib/orchestrator/suite-compare.d.ts +37 -0
  529. package/lib/orchestrator/suite-compare.d.ts.map +1 -1
  530. package/lib/orchestrator/suite-compare.js +27 -17
  531. package/lib/orchestrator/suite-compare.js.map +1 -1
  532. package/lib/orchestrator/suite-runs.d.ts +6 -1
  533. package/lib/orchestrator/suite-runs.d.ts.map +1 -1
  534. package/lib/orchestrator/suite-runs.js +14 -2
  535. package/lib/orchestrator/suite-runs.js.map +1 -1
  536. package/lib/orchestrator/suite-summary.d.ts +77 -0
  537. package/lib/orchestrator/suite-summary.d.ts.map +1 -1
  538. package/lib/orchestrator/suite-summary.js +61 -12
  539. package/lib/orchestrator/suite-summary.js.map +1 -1
  540. package/lib/previewer/artifacts.d.ts +25 -0
  541. package/lib/previewer/artifacts.d.ts.map +1 -0
  542. package/lib/previewer/artifacts.js +180 -0
  543. package/lib/previewer/artifacts.js.map +1 -0
  544. package/lib/previewer/server.d.ts +111 -0
  545. package/lib/previewer/server.d.ts.map +1 -0
  546. package/lib/previewer/server.js +558 -0
  547. package/lib/previewer/server.js.map +1 -0
  548. package/package.json +3 -3
  549. package/skills/lux-answerer/SKILL.md +2 -2
  550. package/src/answerers/claude-code/index.ts +6 -5
  551. package/src/answerers/persona/index.ts +75 -34
  552. package/src/answerers/terminal/index.ts +8 -12
  553. package/src/assertions/authoring.ts +2 -0
  554. package/src/assertions/core/command-exits-zero.ts +61 -7
  555. package/src/assertions/core/event-checks.ts +64 -3
  556. package/src/assertions/core/helpers.ts +3 -6
  557. package/src/assertions/core/index.ts +2 -0
  558. package/src/assertions/core/resource-checks.ts +38 -5
  559. package/src/assertions/rubric/index.ts +68 -13
  560. package/src/assertions/rubric/internal.ts +227 -27
  561. package/src/authoring.ts +345 -2
  562. package/src/cli/bin.ts +2 -12
  563. package/src/cli/command-runtime.ts +20 -9
  564. package/src/cli/doctor.ts +17 -0
  565. package/src/cli/harness-plan.ts +117 -0
  566. package/src/cli/init-templates.ts +238 -0
  567. package/src/cli/init.ts +53 -184
  568. package/src/cli/output-schemas.ts +106 -0
  569. package/src/cli/program.ts +689 -721
  570. package/src/cli/render/reporter.ts +43 -7
  571. package/src/cli/run-options.ts +132 -25
  572. package/src/cli/view.ts +129 -0
  573. package/src/container/driver.ts +211 -0
  574. package/src/container/protocol.ts +48 -0
  575. package/src/container/resources.ts +153 -0
  576. package/src/container/worker.ts +107 -0
  577. package/src/core/action-events.ts +59 -0
  578. package/src/core/agent-activity.ts +236 -0
  579. package/src/core/agent-environment.ts +64 -0
  580. package/src/core/agent-events.ts +17 -0
  581. package/src/core/annotation.ts +2 -1
  582. package/src/core/answerer.ts +9 -0
  583. package/src/core/artifact-evidence.ts +47 -4
  584. package/src/core/assertion.ts +18 -0
  585. package/src/core/case.ts +16 -2
  586. package/src/core/command-verification.ts +74 -0
  587. package/src/core/driver-execution.ts +84 -0
  588. package/src/core/driver-metrics.ts +51 -0
  589. package/src/core/driver.ts +76 -0
  590. package/src/core/duration.ts +52 -0
  591. package/src/core/environment.ts +22 -0
  592. package/src/core/evaluation-clusters.ts +35 -0
  593. package/src/core/events.ts +14 -2
  594. package/src/core/experiment.ts +64 -24
  595. package/src/core/file-tree.ts +35 -0
  596. package/src/core/global-id.ts +26 -0
  597. package/src/core/harness-catalog.ts +100 -0
  598. package/src/core/harness-catalogs/antigravity.ts +24 -0
  599. package/src/core/harness-catalogs/claude-code.ts +25 -0
  600. package/src/core/harness-catalogs/codex.ts +27 -0
  601. package/src/core/harness-catalogs/copilot.ts +46 -0
  602. package/src/core/harness-catalogs/cursor.ts +13 -0
  603. package/src/core/harness-catalogs/grok-build.ts +19 -0
  604. package/src/core/harness-catalogs/index.ts +31 -0
  605. package/src/core/harness-matrix.ts +316 -0
  606. package/src/core/index.ts +12 -0
  607. package/src/core/lifecycle-fixtures.ts +4 -2
  608. package/src/core/model-cli.ts +52 -23
  609. package/src/core/platform-process.ts +58 -10
  610. package/src/core/run.ts +31 -0
  611. package/src/core/usage.ts +8 -0
  612. package/src/core/wire.ts +5 -1
  613. package/src/drivers/antigravity/README.md +171 -0
  614. package/src/drivers/antigravity/artifacts.ts +37 -0
  615. package/src/drivers/antigravity/config.ts +92 -0
  616. package/src/drivers/antigravity/events.ts +290 -0
  617. package/src/drivers/antigravity/index.ts +132 -0
  618. package/src/drivers/antigravity/runtime.ts +94 -0
  619. package/src/drivers/claude-code/deferred-process.ts +118 -0
  620. package/src/drivers/claude-code/index.ts +216 -281
  621. package/src/drivers/claude-code/isolation.ts +228 -0
  622. package/src/drivers/claude-code/parse-events.ts +98 -12
  623. package/src/drivers/codex/app-events.ts +126 -16
  624. package/src/drivers/codex/config.ts +50 -8
  625. package/src/drivers/codex/exec-events.ts +258 -0
  626. package/src/drivers/codex/index.ts +144 -312
  627. package/src/drivers/copilot/README.md +60 -0
  628. package/src/drivers/copilot/config.ts +61 -0
  629. package/src/drivers/copilot/index.ts +310 -0
  630. package/src/drivers/cursor/README.md +66 -0
  631. package/src/drivers/cursor/config.ts +31 -0
  632. package/src/drivers/cursor/index.ts +326 -0
  633. package/src/drivers/cursor/interaction.ts +74 -0
  634. package/src/drivers/grok-build/README.md +112 -0
  635. package/src/drivers/grok-build/config.ts +43 -0
  636. package/src/drivers/grok-build/index.ts +331 -0
  637. package/src/drivers/mcp/index.ts +25 -11
  638. package/src/drivers/shared/acp-events.ts +94 -0
  639. package/src/drivers/shared/acp-interaction.ts +27 -0
  640. package/src/drivers/shared/acp-session.ts +40 -0
  641. package/src/drivers/shared/acp-transport.ts +187 -0
  642. package/src/drivers/shared/artifacts.ts +6 -2
  643. package/src/drivers/shared/experiment-behavior.ts +214 -0
  644. package/src/drivers/shared/experiment-policy.ts +195 -0
  645. package/src/drivers/subprocess/index.ts +55 -12
  646. package/src/index.ts +115 -10
  647. package/src/optimization/reflective.ts +3 -2
  648. package/src/orchestrator/annotation-loader.ts +10 -0
  649. package/src/orchestrator/annotation-store.ts +24 -3
  650. package/src/orchestrator/artifact-origin.ts +50 -0
  651. package/src/orchestrator/campaign-lifecycle.ts +5 -1
  652. package/src/orchestrator/candidates.ts +3 -2
  653. package/src/orchestrator/compare.ts +34 -1
  654. package/src/orchestrator/comparison-identity.ts +2 -0
  655. package/src/orchestrator/config.ts +20 -3
  656. package/src/orchestrator/discover.ts +8 -1
  657. package/src/orchestrator/doctor.ts +189 -28
  658. package/src/orchestrator/driver-capabilities.ts +21 -0
  659. package/src/orchestrator/driver-identity.ts +69 -0
  660. package/src/orchestrator/experiment-context.ts +3 -2
  661. package/src/orchestrator/experiment-corpus.ts +53 -37
  662. package/src/orchestrator/experiment-effects.ts +61 -0
  663. package/src/orchestrator/experiment-evaluation.ts +71 -10
  664. package/src/orchestrator/experiment-identity.ts +42 -48
  665. package/src/orchestrator/experiment-preflight.ts +27 -0
  666. package/src/orchestrator/experiment-report.ts +21 -1
  667. package/src/orchestrator/experiment-runs.ts +11 -4
  668. package/src/orchestrator/experiment-runtime-identity.ts +5 -243
  669. package/src/orchestrator/experiment-selection.ts +77 -0
  670. package/src/orchestrator/experiment.ts +29 -29
  671. package/src/orchestrator/fixture-identity.ts +9 -1
  672. package/src/orchestrator/fs-read.ts +2 -32
  673. package/src/orchestrator/grader-experiment.ts +74 -13
  674. package/src/orchestrator/grading.ts +35 -7
  675. package/src/orchestrator/harness-catalog-drift.ts +132 -0
  676. package/src/orchestrator/harness-registry.ts +12 -0
  677. package/src/orchestrator/index.ts +1 -0
  678. package/src/orchestrator/list-runs.ts +95 -11
  679. package/src/orchestrator/optimization-lifecycle.ts +4 -1
  680. package/src/orchestrator/orchestrator.ts +92 -216
  681. package/src/orchestrator/paired-effects.ts +209 -0
  682. package/src/orchestrator/provenance.ts +23 -3
  683. package/src/orchestrator/rubric-loader.ts +1 -1
  684. package/src/orchestrator/run-dir.ts +8 -1
  685. package/src/orchestrator/run-execution.ts +77 -11
  686. package/src/orchestrator/run-lifecycle.ts +4 -2
  687. package/src/orchestrator/run-workspace.ts +62 -0
  688. package/src/orchestrator/suite-compare.ts +29 -19
  689. package/src/orchestrator/suite-runs.ts +13 -2
  690. package/src/orchestrator/suite-summary.ts +122 -13
  691. package/src/previewer/artifacts.ts +221 -0
  692. package/src/previewer/server.ts +787 -0
  693. package/viewer/app.css +2075 -0
  694. package/viewer/app.js +627 -0
  695. package/viewer/artifact-view.js +48 -0
  696. package/viewer/charts.js +86 -0
  697. package/viewer/detail.js +1231 -0
  698. package/viewer/format.js +129 -0
  699. package/viewer/index.html +151 -0
  700. package/lib/answerers/scripted/index.d.ts +0 -8
  701. package/lib/answerers/scripted/index.d.ts.map +0 -1
  702. package/lib/answerers/scripted/index.js +0 -163
  703. package/lib/answerers/scripted/index.js.map +0 -1
  704. package/lib/cli/skills.d.ts +0 -38
  705. package/lib/cli/skills.d.ts.map +0 -1
  706. package/lib/cli/skills.js +0 -84
  707. package/lib/cli/skills.js.map +0 -1
  708. package/lib/drivers/shared/secure-copy.d.ts.map +0 -1
  709. package/lib/drivers/shared/secure-copy.js.map +0 -1
  710. package/skills/lux/SKILL.md +0 -85
  711. package/skills/lux/references/cli.md +0 -102
  712. package/skills/lux/references/eval-authoring.md +0 -105
  713. package/src/answerers/scripted/index.ts +0 -186
  714. package/src/cli/skills.ts +0 -129
  715. /package/lib/{drivers/shared → core}/secure-copy.d.ts +0 -0
  716. /package/lib/{drivers/shared → core}/secure-copy.js +0 -0
  717. /package/src/{drivers/shared → core}/secure-copy.ts +0 -0
@@ -4,6 +4,7 @@ import {
4
4
  createToolOutcomeAccumulator,
5
5
  emptyRunUsage,
6
6
  type GradingAssertionEntry,
7
+ type GradingReport,
7
8
  harnessUsage,
8
9
  isUsageEmpty,
9
10
  type LifecycleStage,
@@ -18,6 +19,7 @@ import {
18
19
  TurnUsageSchema,
19
20
  totalTokens,
20
21
  } from "../../core/index.js";
22
+ import { hasAgentUsage } from "../../core/usage.js";
21
23
  import type { CaseObserver, SuiteCaseResult, SuiteObserver } from "../../orchestrator/index.js";
22
24
  import {
23
25
  formatAlignedUsage,
@@ -77,7 +79,9 @@ type CaseView = {
77
79
  assertionTotal: number;
78
80
  currentAssertion: string | null;
79
81
  assertions: GradingAssertionEntry[];
82
+ skippedAssertions: NonNullable<GradingReport["skippedAssertions"]>;
80
83
  usage: RunUsage;
84
+ agentUsageReported: boolean;
81
85
  /** Per-API-call agent usage, in order — the split behind `usage.agent`. */
82
86
  agentTurns: TurnUsage[];
83
87
  phaseDurationMs: PhaseDurations | null;
@@ -117,7 +121,10 @@ const statusMark = (status: CaseStatus, theme: Theme): string => {
117
121
 
118
122
  const assertionTally = (view: CaseView): string => {
119
123
  const passed = view.assertions.filter((a) => a.passed).length;
120
- return view.assertions.length === 0 ? "—" : `${passed}/${view.assertions.length}`;
124
+ const evaluated = view.assertions.length === 0 ? "—" : `${passed}/${view.assertions.length}`;
125
+ return view.skippedAssertions.length > 0
126
+ ? `${evaluated} · ${view.skippedAssertions.length} skipped`
127
+ : evaluated;
121
128
  };
122
129
 
123
130
  /**
@@ -154,6 +161,7 @@ const cell = (text: string, width: number): string => {
154
161
  */
155
162
  const scoreNote = (entry: GradingAssertionEntry): string => {
156
163
  if (entry.errorMessage) return entry.errorMessage;
164
+ if (entry.abstention) return "insufficient evidence";
157
165
  if (entry.passed) return "";
158
166
  const score = formatScore(entry.score);
159
167
  if (entry.threshold > 0) return `score ${score} < ${formatScore(entry.threshold)}`;
@@ -233,7 +241,9 @@ export class ConsoleReporter implements SuiteObserver {
233
241
  assertionTotal: 0,
234
242
  currentAssertion: null,
235
243
  assertions: [],
244
+ skippedAssertions: [],
236
245
  usage: emptyRunUsage(),
246
+ agentUsageReported: false,
237
247
  agentTurns: [],
238
248
  phaseDurationMs: null,
239
249
  runDir: null,
@@ -267,6 +277,13 @@ export class ConsoleReporter implements SuiteObserver {
267
277
  view.toolUnresolved = tools.unresolved;
268
278
  view.toolUnmatchedResults = tools.unmatchedResults;
269
279
  view.toolMalformed = tools.malformedEvents;
280
+ } else if (event.type === "progress" && event.kind === "driver-stderr" && this.verbose) {
281
+ const payload = event.payload as { text?: unknown; truncated?: unknown } | null;
282
+ if (payload && typeof payload.text === "string") {
283
+ this.region.staticLine(this.theme.dim(` [${view.caseId}] ${payload.text}`));
284
+ if (payload.truncated === true)
285
+ this.region.staticLine(this.theme.dim(" [driver stderr truncated]"));
286
+ }
270
287
  } else if (event.type === "progress" && event.kind === "usage") {
271
288
  const turn = TurnUsageSchema.safeParse(event.payload).data;
272
289
  if (turn) view.agentTurns.push(turn);
@@ -299,7 +316,9 @@ export class ConsoleReporter implements SuiteObserver {
299
316
  if (result.errorMessage) view.errorMessage = result.errorMessage;
300
317
  if (result.result) {
301
318
  view.assertions = result.result.grading.assertions;
319
+ view.skippedAssertions = result.result.grading.skippedAssertions ?? [];
302
320
  view.usage = result.result.metadata.usage;
321
+ view.agentUsageReported = hasAgentUsage(result.result.metadata);
303
322
  view.phaseDurationMs = result.result.metadata.phaseDurationMs ?? null;
304
323
  const tools = result.result.metadata.toolOutcomes;
305
324
  if (tools) {
@@ -315,6 +334,7 @@ export class ConsoleReporter implements SuiteObserver {
315
334
  // Assertions reported before the run failed to persist are not results
316
335
  // and must not inflate the closing tally of a case that errored.
317
336
  view.assertions = [];
337
+ view.skippedAssertions = [];
318
338
  }
319
339
 
320
340
  this.region.staticLine(this.finishedLine(view));
@@ -443,15 +463,23 @@ export class ConsoleReporter implements SuiteObserver {
443
463
  Math.max(NAME_MIN, ...view.assertions.map((a) => a.name.length)),
444
464
  );
445
465
  for (const entry of view.assertions) {
446
- const mark = entry.passed ? this.theme.green("✓") : this.theme.red("✗");
466
+ let mark = entry.passed ? this.theme.green("✓") : this.theme.red("✗");
467
+ if (entry.abstention) mark = this.theme.dim("?");
447
468
  const duration = formatDuration(entry.durationMs).padStart(DURATION_COL);
448
469
  const note = scoreNote(entry);
449
- const suffix = note ? ` ${this.theme.red(note)}` : "";
470
+ const suffix = note
471
+ ? ` ${entry.abstention ? this.theme.dim(note) : this.theme.red(note)}`
472
+ : "";
450
473
  nodes.push({
451
474
  head: `${mark} ${cell(entry.name, width)} ${this.theme.dim(duration)}${suffix}`,
452
475
  body: !entry.passed && entry.comment ? [this.theme.dim(entry.comment)] : [],
453
476
  });
454
477
  }
478
+ for (const skipped of view.skippedAssertions) {
479
+ nodes.push({
480
+ head: `${this.theme.dim("⊘")} ${skipped.name} ${this.theme.dim("skipped: judge disabled")}`,
481
+ });
482
+ }
455
483
 
456
484
  if (view.toolCalls > 0 || view.toolUnmatchedResults > 0 || view.toolMalformed > 0) {
457
485
  const parts = [
@@ -550,15 +578,17 @@ export class ConsoleReporter implements SuiteObserver {
550
578
  }
551
579
 
552
580
  const assertions = this.cases.flatMap((c) => c.assertions);
553
- if (assertions.length > 0) {
581
+ const skippedAssertions = this.cases.flatMap((c) => c.skippedAssertions);
582
+ if (assertions.length > 0 || skippedAssertions.length > 0) {
554
583
  const ok = assertions.filter((a) => a.passed).length;
555
584
  const bad = assertions.length - ok;
556
585
  const tally = formatTally(
557
586
  [
558
587
  [ok, this.theme.green("passed")],
559
588
  [bad, this.theme.red("failed")],
589
+ [skippedAssertions.length, this.theme.dim("skipped")],
560
590
  ],
561
- assertions.length,
591
+ assertions.length + skippedAssertions.length,
562
592
  );
563
593
  lines.push(` ${label("Assertions")}${tally}`);
564
594
  }
@@ -615,11 +645,17 @@ export class ConsoleReporter implements SuiteObserver {
615
645
  emptyRunUsage(),
616
646
  );
617
647
  const harness = harnessUsage(total);
618
- if (isUsageEmpty(total.agent) && isUsageEmpty(harness)) {
648
+ const reported = this.cases.filter(
649
+ (view) => view.agentUsageReported || !isUsageEmpty(this.agentUsageOf(view)),
650
+ ).length;
651
+ if (reported === 0 && isUsageEmpty(total.agent) && isUsageEmpty(harness)) {
619
652
  return live ? [] : [` ${label("Tokens")}${this.theme.dim("none reported")}`];
620
653
  }
621
654
 
622
- const agentText = isUsageEmpty(total.agent) ? this.theme.dim("none") : formatUsage(total.agent);
655
+ const missing = this.cases.length - reported;
656
+ const partial = missing > 0 ? ` (${missing} run${missing === 1 ? "" : "s"} unavailable)` : "";
657
+ const agentText =
658
+ reported === 0 ? this.theme.dim("unavailable") : `${formatUsage(total.agent)}${partial}`;
623
659
  if (live) {
624
660
  const harnessText = isUsageEmpty(harness)
625
661
  ? ""
@@ -1,4 +1,9 @@
1
- import { InvalidArgumentError } from "commander";
1
+ import { existsSync } from "node:fs";
2
+ import { basename, extname, resolve } from "node:path";
3
+ import { Errors } from "incur";
4
+ import type { HarnessFocus, ReasoningEffort } from "../core/index.js";
5
+ import { type DiscoveredCase, type SuiteItem, selectCases } from "../orchestrator/index.js";
6
+ import { planHarnessItems } from "./harness-plan.js";
2
7
 
3
8
  export type RunOptions = {
4
9
  tag?: string[];
@@ -8,28 +13,24 @@ export type RunOptions = {
8
13
  listTags?: boolean;
9
14
  interactive?: boolean;
10
15
  claudeAnswerer?: boolean;
16
+ skipJudge?: boolean;
11
17
  runsRoot?: string;
12
18
  profile?: string;
19
+ driver?: string;
20
+ model?: string;
21
+ effort?: ReasoningEffort;
13
22
  subjectRoot?: string;
14
23
  verbose?: boolean;
15
24
  };
16
25
 
17
- export const collectTags = (value: string, previous: string[]): string[] =>
18
- previous.concat(
19
- value
20
- .split(",")
21
- .map((tag) => tag.trim())
22
- .filter(Boolean),
23
- );
24
-
25
- export const collectValues = (value: string, previous: string[]): string[] => [...previous, value];
26
-
27
26
  export const parseAnnotationAssertion = (
28
27
  value: string,
29
28
  ): [string, { passed: boolean; score?: number }] => {
30
29
  const match = /^(.+)=(pass|fail)(?::(.+))?$/.exec(value);
31
- if (!match?.[1] || !match[2]) {
32
- throw new InvalidArgumentError("--assertion must use id=pass, id=fail, or id=pass:0.8 syntax");
30
+ if (!match?.[1]?.trim() || !match[2]) {
31
+ throw new Errors.ParseError({
32
+ message: "--assertion must use id=pass, id=fail, or id=pass:0.8 syntax",
33
+ });
33
34
  }
34
35
  const score = match[3] === undefined ? undefined : parseUnitInterval(match[3]);
35
36
  return [
@@ -41,19 +42,10 @@ export const parseAnnotationAssertion = (
41
42
  ];
42
43
  };
43
44
 
44
- export const parsePositiveInt = (value: string): number => {
45
- // Number() rejects partial numbers such as "3abc" and "2.9".
45
+ const parseUnitInterval = (value: string): number => {
46
46
  const parsed = Number(value);
47
- if (!Number.isInteger(parsed) || parsed < 1) {
48
- throw new InvalidArgumentError("must be a positive integer");
49
- }
50
- return parsed;
51
- };
52
-
53
- export const parseUnitInterval = (value: string): number => {
54
- const parsed = Number(value);
55
- if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
56
- throw new InvalidArgumentError("must be a number between 0 and 1");
47
+ if (!value.trim() || !Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
48
+ throw new Errors.ParseError({ message: "must be a number between 0 and 1" });
57
49
  }
58
50
  return parsed;
59
51
  };
@@ -80,3 +72,118 @@ export const resolveAnswererOverride = (options: RunOptions): string | undefined
80
72
  if (options.claudeAnswerer) return "claude-code";
81
73
  return undefined;
82
74
  };
75
+
76
+ const caseIdOf = (casePath: string): string => basename(casePath, extname(casePath));
77
+
78
+ export const suiteTitle = (
79
+ patterns: string[],
80
+ tags: string[],
81
+ explicit: SuiteItem[],
82
+ loop: number,
83
+ focus: HarnessFocus,
84
+ ): string => {
85
+ const parts = [...patterns, ...explicit.map((e) => e.id), ...tags.map((t) => `#${t}`)];
86
+ const filter = parts.length > 0 ? ` ${parts.join(" ")}` : "";
87
+ const focusParts = [focus.driver, focus.model, focus.effort].filter(
88
+ (part): part is string => part !== undefined,
89
+ );
90
+ const focused = focusParts.length > 0 ? ` @${focusParts.join(":")}` : "";
91
+ const repeat = loop > 1 ? ` ×${loop}` : "";
92
+ return `run${filter}${focused}${repeat}`;
93
+ };
94
+
95
+ type FilterPartition = { explicit: SuiteItem[]; patterns: string[] };
96
+
97
+ // A filter that names an existing `.ts` file runs that file directly — it may
98
+ // sit outside the discovery root. Everything else is a substring pattern — but
99
+ // a `.ts` filter that resolves to nothing is almost always a typo'd path, so
100
+ // the silent downgrade to a pattern gets called out.
101
+ export const partitionFilters = (filters: string[], cwd: string): FilterPartition => {
102
+ const explicit: SuiteItem[] = [];
103
+ const patterns: string[] = [];
104
+ for (const f of filters) {
105
+ const abs = resolve(cwd, f);
106
+ if (f.endsWith(".ts") && existsSync(abs)) {
107
+ explicit.push({ path: abs, id: caseIdOf(f) });
108
+ } else {
109
+ if (f.endsWith(".ts")) {
110
+ process.stderr.write(`lux: ${abs} does not exist; treating "${f}" as a pattern\n`);
111
+ }
112
+ patterns.push(f);
113
+ }
114
+ }
115
+ return { explicit, patterns };
116
+ };
117
+
118
+ // The selected set — substring/tag matches plus explicitly named files — is
119
+ // the same whether it is run, `--list`ed, or `--list-tags`ed. No filters at
120
+ // all means "everything discovered"; any filter narrows.
121
+ export const selectSuite = (
122
+ cases: DiscoveredCase[],
123
+ { explicit, patterns }: FilterPartition,
124
+ tags: string[],
125
+ ): DiscoveredCase[] => {
126
+ const hasFilter = explicit.length > 0 || patterns.length > 0 || tags.length > 0;
127
+ const byPath = new Map<string, DiscoveredCase>();
128
+ if (!hasFilter) {
129
+ for (const c of cases) byPath.set(c.path, c);
130
+ } else {
131
+ if (patterns.length > 0 || tags.length > 0) {
132
+ for (const c of selectCases(cases, { patterns, tags })) byPath.set(c.path, c);
133
+ }
134
+ for (const e of explicit) {
135
+ const discovered = cases.find((c) => c.path === e.path);
136
+ // Discovery knows the case's declared id; the filename-derived one is
137
+ // only a fallback for files discovery never saw.
138
+ byPath.set(e.path, {
139
+ path: e.path,
140
+ id: discovered?.id ?? e.id,
141
+ relPath: discovered?.relPath ?? e.id,
142
+ tags: discovered?.tags ?? [],
143
+ });
144
+ }
145
+ }
146
+ return [...byPath.values()].sort((a, b) => a.id.localeCompare(b.id));
147
+ };
148
+
149
+ // `--loop` repeats each eval before moving to the next; each repeat gets a
150
+ // `#n` display suffix so the reporter keeps them apart, while `caseId` keeps
151
+ // every repeat filed under one run history.
152
+ export const expandLoop = (base: SuiteItem[], loop: number): SuiteItem[] =>
153
+ loop > 1
154
+ ? base.flatMap((b) =>
155
+ Array.from({ length: loop }, (_, i) => ({
156
+ ...b,
157
+ id: `${b.id} #${i + 1}`,
158
+ caseId: b.caseId ?? b.id,
159
+ })),
160
+ )
161
+ : base;
162
+
163
+ export const planSuiteItems = async (
164
+ selected: readonly { path: string; id: string }[],
165
+ options: Parameters<typeof planHarnessItems>[1],
166
+ ): Promise<SuiteItem[]> => {
167
+ const plan = await planHarnessItems(selected, options);
168
+ for (const skipped of plan.unavailable) {
169
+ process.stderr.write(
170
+ `lux: skipping ${skipped.id}: harness command not found: ${skipped.commands.join(", ")}\n`,
171
+ );
172
+ }
173
+ if (plan.excluded.length > 0) {
174
+ process.stderr.write(
175
+ `lux: the harness focus excludes ${plan.excluded.length} pinned case${plan.excluded.length === 1 ? "" : "s"}: ${plan.excluded.join(", ")}\n`,
176
+ );
177
+ }
178
+ if (plan.items.length === 0) {
179
+ throw new Errors.IncurError({
180
+ code: plan.unavailable.length > 0 ? "NO_RUNNABLE_HARNESSES" : "NO_CASES_MATCHED",
181
+ message:
182
+ plan.unavailable.length > 0
183
+ ? "No cases remain: all selected matrix harnesses are unavailable."
184
+ : "No cases remain after applying the harness focus.",
185
+ exitCode: 1,
186
+ });
187
+ }
188
+ return plan.items;
189
+ };
@@ -0,0 +1,129 @@
1
+ import { resolve } from "node:path";
2
+ import { Errors } from "incur";
3
+ import {
4
+ isExperimentRun,
5
+ listExperimentRuns,
6
+ listRuns,
7
+ listSuiteRuns,
8
+ loadExperimentRun,
9
+ loadLuxConfig,
10
+ loadRunDetail,
11
+ loadSuiteRun,
12
+ } from "../orchestrator/index.js";
13
+ import { openPreviewUrl, startPreviewServer } from "../previewer/server.js";
14
+ import { abortOnInterrupt, ensureDirectory, failWith } from "./command-runtime.js";
15
+
16
+ const SIGINT_EXIT_CODE = 130;
17
+
18
+ export type ViewOptions = {
19
+ runsRoot?: string;
20
+ case?: string;
21
+ suites?: boolean;
22
+ experiments?: boolean;
23
+ web?: boolean;
24
+ port?: number;
25
+ open?: boolean;
26
+ };
27
+
28
+ const previewKind = async (
29
+ initialPath: string | undefined,
30
+ options: ViewOptions,
31
+ ): Promise<"run" | "suite" | "experiment" | undefined> => {
32
+ if (initialPath) {
33
+ if (isExperimentRun(initialPath)) return "experiment";
34
+ if (await loadSuiteRun(initialPath)) return "suite";
35
+ return "run";
36
+ }
37
+ if (options.experiments) return "experiment";
38
+ if (options.suites) return "suite";
39
+ return undefined;
40
+ };
41
+
42
+ export async function* webViewCommand(
43
+ runDirArg: string | undefined,
44
+ options: ViewOptions,
45
+ ): AsyncGenerator<{ url: string; runsRoot: string }, void> {
46
+ const config = await loadLuxConfig(process.cwd());
47
+ const runsRoot = options.runsRoot ? resolve(options.runsRoot) : config.runsRoot;
48
+ const initialPath = runDirArg ? resolve(runDirArg) : undefined;
49
+ if (initialPath && !(await ensureDirectory("view", initialPath))) failWith(1);
50
+ const initialKind = await previewKind(initialPath, options);
51
+ using controller = abortOnInterrupt();
52
+ const preview = await startPreviewServer({
53
+ runsRoot,
54
+ ...(options.port !== undefined ? { port: options.port } : {}),
55
+ ...(initialPath ? { initialPath } : {}),
56
+ ...(initialKind ? { initialKind } : {}),
57
+ ...(options.case ? { caseFilter: options.case } : {}),
58
+ signal: controller.signal,
59
+ });
60
+ try {
61
+ yield { url: preview.url, runsRoot };
62
+ if (options.open !== false) {
63
+ try {
64
+ await openPreviewUrl(preview.url);
65
+ } catch (error) {
66
+ const message = error instanceof Error ? error.message : String(error);
67
+ process.stderr.write(`lux view: could not open a browser (${message})\n`);
68
+ }
69
+ }
70
+ await preview.closed;
71
+ if (controller.signal.aborted) failWith(SIGINT_EXIT_CODE);
72
+ } finally {
73
+ await preview.close();
74
+ }
75
+ }
76
+
77
+ export const viewCommand = async (
78
+ runDirArg: string | undefined,
79
+ options: ViewOptions,
80
+ ): Promise<unknown> => {
81
+ if (options.port !== undefined || options.open === false) {
82
+ throw new Errors.ParseError({ message: "--port and --no-open require --web" });
83
+ }
84
+ if (runDirArg) {
85
+ const path = resolve(runDirArg);
86
+ if (!(await ensureDirectory("view", path))) return;
87
+ if (isExperimentRun(path)) {
88
+ const experiment = await loadExperimentRun(path);
89
+ if (!experiment) {
90
+ throw new Errors.IncurError({
91
+ code: "INVALID_EXPERIMENT",
92
+ message: `Invalid experiment at ${path}.`,
93
+ exitCode: 1,
94
+ });
95
+ }
96
+ return { experimentDir: path, ...experiment };
97
+ }
98
+ const suite = await loadSuiteRun(path);
99
+ if (suite) {
100
+ return { suiteDir: path, ...suite };
101
+ }
102
+ return loadRunDetail(path);
103
+ }
104
+
105
+ const config = await loadLuxConfig(process.cwd());
106
+ const runsRoot = options.runsRoot ? resolve(options.runsRoot) : config.runsRoot;
107
+ const readErrors: Array<{ path: string; message: string }> = [];
108
+ const listingOptions = {
109
+ onReadError: (path: string, error: unknown) => {
110
+ readErrors.push({ path, message: error instanceof Error ? error.message : String(error) });
111
+ },
112
+ };
113
+ if (options.experiments) {
114
+ const experiments = await listExperimentRuns(runsRoot, listingOptions);
115
+ return { runsRoot, experiments, ...(readErrors.length ? { readErrors } : {}) };
116
+ }
117
+ if (options.suites) {
118
+ const suites = await listSuiteRuns(runsRoot, listingOptions);
119
+ return { runsRoot, suites, ...(readErrors.length ? { readErrors } : {}) };
120
+ }
121
+ const all = await listRuns(runsRoot);
122
+ const runs = options.case ? all.filter((run) => run.caseSlug === options.case) : all;
123
+ return {
124
+ runsRoot,
125
+ ...(!options.case ? { suites: await listSuiteRuns(runsRoot, listingOptions) } : {}),
126
+ runs,
127
+ ...(readErrors.length ? { readErrors } : {}),
128
+ };
129
+ };
@@ -0,0 +1,211 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import { resolve, sep } from "node:path";
3
+ import type { AgentDriver, Artifact, DriverEventMap, StartContext } from "../core/driver.js";
4
+ import type { ContainerExecution } from "../core/driver-execution.js";
5
+ import { TypedEmitter } from "../core/emitter.js";
6
+ import {
7
+ type Answer,
8
+ DoneSchema,
9
+ ErrorEventSchema,
10
+ InterruptSchema,
11
+ ProgressSchema,
12
+ type ReadyState,
13
+ ReadyStateSchema,
14
+ } from "../core/events.js";
15
+ import { type ManagedProcess, spawnManagedProcess } from "../core/exec.js";
16
+ import { walkArtifacts } from "../drivers/shared/artifacts.js";
17
+ import { LUX_VERSION } from "../orchestrator/package-version.js";
18
+ import { type Message, readMessages, writeMessage } from "./protocol.js";
19
+ import { prepareContainer } from "./resources.js";
20
+
21
+ export class ContainerDriver extends TypedEmitter<DriverEventMap> implements AgentDriver {
22
+ private process: ManagedProcess | undefined;
23
+ private resources: Awaited<ReturnType<typeof prepareContainer>> | undefined;
24
+ private sequence = 0;
25
+ private pending = new Map<
26
+ number,
27
+ { resolve: (value: unknown) => void; reject: (error: Error) => void }
28
+ >();
29
+ private closing: Promise<void> | undefined;
30
+ private context: StartContext | undefined;
31
+ private terminal = false;
32
+ private readonly abort = () => {
33
+ void this.close().catch(() => {});
34
+ };
35
+
36
+ private readonly name: string;
37
+ private readonly config: unknown;
38
+ private readonly execution: ContainerExecution;
39
+ constructor(name: string, config: unknown, execution: ContainerExecution) {
40
+ super();
41
+ this.name = name;
42
+ this.config = config;
43
+ this.execution = execution;
44
+ JSON.stringify(config, (_key, value: unknown) => {
45
+ if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint")
46
+ throw new Error("container driver configuration must be JSON serializable");
47
+ return value;
48
+ });
49
+ }
50
+
51
+ private fail = (error: Error): void => {
52
+ for (const pending of this.pending.values()) pending.reject(error);
53
+ this.pending.clear();
54
+ if (!this.terminal && !this.closing) {
55
+ this.terminal = true;
56
+ void this.emit("error", { exitReason: "error", reason: error.message }).catch(() => {});
57
+ }
58
+ };
59
+
60
+ private receive = (message: Message): void => {
61
+ if (message.event) {
62
+ const dispatch = async () => {
63
+ switch (message.event) {
64
+ case "interrupt":
65
+ await this.emit("interrupt", InterruptSchema.parse(message.value));
66
+ break;
67
+ case "progress":
68
+ await this.emit("progress", ProgressSchema.parse(message.value));
69
+ break;
70
+ case "done":
71
+ this.terminal = true;
72
+ await this.emit("done", DoneSchema.parse(message.value));
73
+ break;
74
+ case "error":
75
+ this.terminal = true;
76
+ await this.emit("error", ErrorEventSchema.parse(message.value));
77
+ break;
78
+ default:
79
+ throw new Error("unknown container event");
80
+ }
81
+ if (this.process) writeMessage(this.process.child.stdin, { id: message.id, ack: true });
82
+ };
83
+ void dispatch().catch(this.fail);
84
+ return;
85
+ }
86
+ const pending = this.pending.get(message.id);
87
+ if (!pending) return;
88
+ this.pending.delete(message.id);
89
+ if (message.error !== undefined) pending.reject(new Error(message.error));
90
+ else pending.resolve(message.value);
91
+ };
92
+
93
+ private rpc = (method: string, value?: unknown, timeoutMs = 30_000): Promise<unknown> =>
94
+ new Promise((resolvePromise, reject) => {
95
+ if (!this.process) {
96
+ reject(new Error("container process is unavailable"));
97
+ return;
98
+ }
99
+ const id = ++this.sequence;
100
+ const timer = setTimeout(() => {
101
+ this.pending.delete(id);
102
+ reject(new Error(`container ${method} timed out`));
103
+ }, timeoutMs);
104
+ this.pending.set(id, {
105
+ resolve: (result) => {
106
+ clearTimeout(timer);
107
+ resolvePromise(result);
108
+ },
109
+ reject: (error) => {
110
+ clearTimeout(timer);
111
+ reject(error);
112
+ },
113
+ });
114
+ try {
115
+ writeMessage(this.process.child.stdin, { id, method, value });
116
+ } catch (error) {
117
+ this.pending.get(id)?.reject(error as Error);
118
+ this.pending.delete(id);
119
+ }
120
+ });
121
+
122
+ async start(ctx: StartContext): Promise<ReadyState> {
123
+ this.context = ctx;
124
+ if (ctx.abortSignal.aborted) throw new Error("container run aborted before startup");
125
+ const raw = this.config as { cwd?: string; cwdMode?: string };
126
+ if (raw?.cwdMode === "runDir")
127
+ throw new Error("container drivers must use the artifacts workspace, not cwdMode: runDir");
128
+ if (raw?.cwd && (await realpath(raw.cwd)) !== (await realpath(ctx.artifactsDir)))
129
+ throw new Error("container driver cwd must be the mounted artifacts workspace");
130
+ this.resources = await prepareContainer(this.execution, ctx.artifactsDir);
131
+ try {
132
+ this.process = spawnManagedProcess(this.resources.command, this.resources.args, {
133
+ env: this.resources.env,
134
+ });
135
+ readMessages(this.process.child.stdout, this.receive, this.fail);
136
+ // Harness stderr can contain secrets. The normalized driver protocol is the evidence surface.
137
+ this.process.child.stderr.resume();
138
+ void this.process.exited.then(() => this.fail(new Error("container worker exited")));
139
+ ctx.abortSignal.addEventListener("abort", this.abort, { once: true });
140
+ await this.process.spawned;
141
+ if (ctx.abortSignal.aborted) throw new Error("container run aborted during startup");
142
+ const { abortSignal: _signal, ...context } = ctx;
143
+ const ready = ReadyStateSchema.parse(
144
+ await this.rpc(
145
+ "start",
146
+ {
147
+ version: LUX_VERSION,
148
+ name: this.name,
149
+ config: this.config,
150
+ module: this.execution.driverModule,
151
+ context: {
152
+ ...context,
153
+ artifactsDir: this.resources.root,
154
+ ...(context.fixtures
155
+ ? { fixtures: { ...context.fixtures, rootDir: this.resources.root } }
156
+ : {}),
157
+ runDir: "/tmp/lux-run",
158
+ runsRoot: "/tmp/lux-runs",
159
+ },
160
+ },
161
+ this.execution.startupTimeoutMs ?? 60_000,
162
+ ),
163
+ );
164
+ return {
165
+ ...ready,
166
+ detail: { ...ready.detail, execution: "container", image: this.resources.image },
167
+ };
168
+ } catch (error) {
169
+ await this.close();
170
+ throw error;
171
+ }
172
+ }
173
+
174
+ async respond(answer: Answer): Promise<void> {
175
+ await this.rpc("respond", answer);
176
+ }
177
+ async quiesce(): Promise<void> {
178
+ await this.rpc("quiesce");
179
+ }
180
+ async collect(): Promise<Artifact[]> {
181
+ const root = this.resources?.root;
182
+ if (!root) return [];
183
+ try {
184
+ const artifacts = (await this.rpc("collect")) as Artifact[];
185
+ for (const artifact of artifacts) {
186
+ const path = resolve(artifact.root ?? root, artifact.path);
187
+ if (path !== root && !path.startsWith(`${root}${sep}`))
188
+ throw new Error("container driver returned artifacts outside its mounted workspace");
189
+ }
190
+ } finally {
191
+ await this.close();
192
+ }
193
+ return walkArtifacts(root);
194
+ }
195
+ close(): Promise<void> {
196
+ this.closing ??= (async () => {
197
+ this.context?.abortSignal.removeEventListener("abort", this.abort);
198
+ try {
199
+ if (this.process) {
200
+ await this.rpc("close", undefined, 5_000).catch(() => {});
201
+ this.process.child.stdin.end();
202
+ }
203
+ await this.resources?.cleanup();
204
+ } finally {
205
+ await this.process?.terminate();
206
+ this.fail(new Error("container driver closed"));
207
+ }
208
+ })();
209
+ return this.closing;
210
+ }
211
+ }