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

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 (756) 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 +65 -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 +67 -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 +211 -46
  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 +153 -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 +31 -15
  250. package/lib/core/model-cli.d.ts.map +1 -1
  251. package/lib/core/model-cli.js +53 -23
  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 +198 -253
  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 +149 -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 +231 -10
  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 +163 -78
  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 +52 -4
  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 +32 -24
  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 +50 -42
  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 +59 -179
  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/regrade.js +5 -1
  546. package/lib/orchestrator/regrade.js.map +1 -1
  547. package/lib/orchestrator/rubric-loader.js +1 -1
  548. package/lib/orchestrator/rubric-loader.js.map +1 -1
  549. package/lib/orchestrator/run-dir.d.ts +2 -0
  550. package/lib/orchestrator/run-dir.d.ts.map +1 -1
  551. package/lib/orchestrator/run-dir.js +1 -1
  552. package/lib/orchestrator/run-dir.js.map +1 -1
  553. package/lib/orchestrator/run-execution.d.ts +3 -0
  554. package/lib/orchestrator/run-execution.d.ts.map +1 -1
  555. package/lib/orchestrator/run-execution.js +64 -10
  556. package/lib/orchestrator/run-execution.js.map +1 -1
  557. package/lib/orchestrator/run-lifecycle.d.ts +1 -0
  558. package/lib/orchestrator/run-lifecycle.d.ts.map +1 -1
  559. package/lib/orchestrator/run-lifecycle.js +3 -2
  560. package/lib/orchestrator/run-lifecycle.js.map +1 -1
  561. package/lib/orchestrator/run-workspace.d.ts +10 -0
  562. package/lib/orchestrator/run-workspace.d.ts.map +1 -0
  563. package/lib/orchestrator/run-workspace.js +58 -0
  564. package/lib/orchestrator/run-workspace.js.map +1 -0
  565. package/lib/orchestrator/suite-compare.d.ts +37 -0
  566. package/lib/orchestrator/suite-compare.d.ts.map +1 -1
  567. package/lib/orchestrator/suite-compare.js +44 -22
  568. package/lib/orchestrator/suite-compare.js.map +1 -1
  569. package/lib/orchestrator/suite-runs.d.ts +6 -1
  570. package/lib/orchestrator/suite-runs.d.ts.map +1 -1
  571. package/lib/orchestrator/suite-runs.js +14 -2
  572. package/lib/orchestrator/suite-runs.js.map +1 -1
  573. package/lib/orchestrator/suite-summary.d.ts +79 -0
  574. package/lib/orchestrator/suite-summary.d.ts.map +1 -1
  575. package/lib/orchestrator/suite-summary.js +67 -14
  576. package/lib/orchestrator/suite-summary.js.map +1 -1
  577. package/lib/previewer/artifacts.d.ts +25 -0
  578. package/lib/previewer/artifacts.d.ts.map +1 -0
  579. package/lib/previewer/artifacts.js +180 -0
  580. package/lib/previewer/artifacts.js.map +1 -0
  581. package/lib/previewer/server.d.ts +111 -0
  582. package/lib/previewer/server.d.ts.map +1 -0
  583. package/lib/previewer/server.js +559 -0
  584. package/lib/previewer/server.js.map +1 -0
  585. package/package.json +4 -2
  586. package/skills/lux-answerer/SKILL.md +2 -2
  587. package/src/answerers/claude-code/index.ts +6 -5
  588. package/src/answerers/persona/index.ts +80 -34
  589. package/src/answerers/terminal/index.ts +7 -11
  590. package/src/assertions/authoring.ts +2 -0
  591. package/src/assertions/core/command-exits-zero.ts +82 -17
  592. package/src/assertions/core/event-checks.ts +64 -3
  593. package/src/assertions/core/index.ts +2 -0
  594. package/src/assertions/core/resource-checks.ts +38 -5
  595. package/src/assertions/core/safe-regex.ts +16 -6
  596. package/src/assertions/rubric/evidence.ts +85 -0
  597. package/src/assertions/rubric/index.ts +76 -46
  598. package/src/assertions/rubric/internal.ts +264 -46
  599. package/src/authoring.ts +346 -2
  600. package/src/cli/bin.ts +2 -12
  601. package/src/cli/command-runtime.ts +20 -9
  602. package/src/cli/doctor.ts +17 -0
  603. package/src/cli/harness-plan.ts +123 -0
  604. package/src/cli/init-templates.ts +176 -0
  605. package/src/cli/init.ts +53 -184
  606. package/src/cli/output-schemas.ts +109 -0
  607. package/src/cli/program.ts +697 -730
  608. package/src/cli/render/format.ts +1 -1
  609. package/src/cli/render/reporter.ts +36 -8
  610. package/src/cli/run-options.ts +131 -25
  611. package/src/cli/view.ts +129 -0
  612. package/src/container/driver.ts +213 -0
  613. package/src/container/paths.ts +29 -0
  614. package/src/container/protocol.ts +48 -0
  615. package/src/container/resources.ts +165 -0
  616. package/src/container/worker.ts +107 -0
  617. package/src/core/action-events.ts +59 -0
  618. package/src/core/agent-activity.ts +236 -0
  619. package/src/core/agent-environment.ts +64 -0
  620. package/src/core/agent-events.ts +17 -0
  621. package/src/core/annotation.ts +2 -1
  622. package/src/core/answerer.ts +9 -0
  623. package/src/core/artifact-evidence.ts +40 -5
  624. package/src/core/assertion.ts +8 -2
  625. package/src/core/case-defaults.ts +65 -0
  626. package/src/core/case.ts +79 -8
  627. package/src/core/command-verification.ts +74 -0
  628. package/src/core/driver-execution.ts +84 -0
  629. package/src/core/driver-metrics.ts +51 -0
  630. package/src/core/driver.ts +76 -0
  631. package/src/core/duration.ts +52 -0
  632. package/src/core/environment.ts +22 -0
  633. package/src/core/evaluation-clusters.ts +35 -0
  634. package/src/core/events.ts +13 -2
  635. package/src/core/experiment.ts +71 -25
  636. package/src/core/file-tree.ts +35 -0
  637. package/src/core/global-id.ts +26 -0
  638. package/src/core/harness-catalog.ts +100 -0
  639. package/src/core/harness-catalogs/antigravity.ts +24 -0
  640. package/src/core/harness-catalogs/claude-code.ts +25 -0
  641. package/src/core/harness-catalogs/codex.ts +27 -0
  642. package/src/core/harness-catalogs/copilot.ts +46 -0
  643. package/src/core/harness-catalogs/cursor.ts +13 -0
  644. package/src/core/harness-catalogs/grok-build.ts +19 -0
  645. package/src/core/harness-catalogs/index.ts +31 -0
  646. package/src/core/harness-matrix.ts +316 -0
  647. package/src/core/index.ts +12 -0
  648. package/src/core/lifecycle-fixtures.ts +4 -2
  649. package/src/core/model-cli.ts +78 -28
  650. package/src/core/platform-process.ts +65 -16
  651. package/src/core/reference-defaults.ts +47 -0
  652. package/src/core/run.ts +31 -0
  653. package/src/core/usage.ts +8 -0
  654. package/src/drivers/antigravity/README.md +171 -0
  655. package/src/drivers/antigravity/artifacts.ts +37 -0
  656. package/src/drivers/antigravity/config.ts +92 -0
  657. package/src/drivers/antigravity/events.ts +290 -0
  658. package/src/drivers/antigravity/index.ts +132 -0
  659. package/src/drivers/antigravity/runtime.ts +94 -0
  660. package/src/drivers/claude-code/deferred-process.ts +118 -0
  661. package/src/drivers/claude-code/index.ts +228 -282
  662. package/src/drivers/claude-code/isolation.ts +228 -0
  663. package/src/drivers/claude-code/parse-events.ts +98 -12
  664. package/src/drivers/codex/app-events.ts +126 -16
  665. package/src/drivers/codex/config.ts +59 -8
  666. package/src/drivers/codex/exec-events.ts +258 -0
  667. package/src/drivers/codex/index.ts +146 -312
  668. package/src/drivers/copilot/README.md +60 -0
  669. package/src/drivers/copilot/config.ts +61 -0
  670. package/src/drivers/copilot/index.ts +310 -0
  671. package/src/drivers/cursor/README.md +66 -0
  672. package/src/drivers/cursor/config.ts +31 -0
  673. package/src/drivers/cursor/index.ts +326 -0
  674. package/src/drivers/cursor/interaction.ts +74 -0
  675. package/src/drivers/grok-build/README.md +112 -0
  676. package/src/drivers/grok-build/config.ts +43 -0
  677. package/src/drivers/grok-build/index.ts +331 -0
  678. package/src/drivers/mcp/index.ts +25 -11
  679. package/src/drivers/shared/acp-events.ts +94 -0
  680. package/src/drivers/shared/acp-interaction.ts +27 -0
  681. package/src/drivers/shared/acp-session.ts +40 -0
  682. package/src/drivers/shared/acp-transport.ts +187 -0
  683. package/src/drivers/shared/artifacts.ts +6 -2
  684. package/src/drivers/shared/experiment-behavior.ts +217 -0
  685. package/src/drivers/shared/experiment-policy.ts +201 -0
  686. package/src/drivers/shared/skills.ts +74 -0
  687. package/src/drivers/subprocess/index.ts +55 -12
  688. package/src/index.ts +117 -6
  689. package/src/optimization/reflective.ts +3 -2
  690. package/src/orchestrator/annotation-loader.ts +10 -0
  691. package/src/orchestrator/annotation-store.ts +24 -3
  692. package/src/orchestrator/artifact-origin.ts +50 -0
  693. package/src/orchestrator/campaign-lifecycle.ts +5 -1
  694. package/src/orchestrator/candidates.ts +3 -2
  695. package/src/orchestrator/compare.ts +62 -13
  696. package/src/orchestrator/comparison-identity.ts +2 -0
  697. package/src/orchestrator/config.ts +23 -1
  698. package/src/orchestrator/discover.ts +8 -1
  699. package/src/orchestrator/doctor.ts +281 -74
  700. package/src/orchestrator/driver-capabilities.ts +21 -0
  701. package/src/orchestrator/driver-identity.ts +69 -0
  702. package/src/orchestrator/experiment-context.ts +5 -3
  703. package/src/orchestrator/experiment-corpus.ts +68 -39
  704. package/src/orchestrator/experiment-effects.ts +63 -0
  705. package/src/orchestrator/experiment-evaluation.ts +88 -10
  706. package/src/orchestrator/experiment-identity.ts +98 -61
  707. package/src/orchestrator/experiment-preflight.ts +27 -0
  708. package/src/orchestrator/experiment-report.ts +21 -1
  709. package/src/orchestrator/experiment-runs.ts +11 -4
  710. package/src/orchestrator/experiment-runtime-identity.ts +5 -243
  711. package/src/orchestrator/experiment-selection.ts +178 -18
  712. package/src/orchestrator/experiment.ts +29 -29
  713. package/src/orchestrator/fixture-identity.ts +9 -1
  714. package/src/orchestrator/fs-read.ts +2 -32
  715. package/src/orchestrator/grader-experiment.ts +74 -13
  716. package/src/orchestrator/grading.ts +60 -31
  717. package/src/orchestrator/harness-catalog-drift.ts +132 -0
  718. package/src/orchestrator/harness-registry.ts +12 -0
  719. package/src/orchestrator/index.ts +1 -0
  720. package/src/orchestrator/list-runs.ts +102 -18
  721. package/src/orchestrator/optimization-lifecycle.ts +4 -1
  722. package/src/orchestrator/orchestrator.ts +104 -226
  723. package/src/orchestrator/paired-effects.ts +214 -0
  724. package/src/orchestrator/profile.ts +24 -0
  725. package/src/orchestrator/provenance.ts +23 -3
  726. package/src/orchestrator/regrade.ts +5 -1
  727. package/src/orchestrator/rubric-loader.ts +1 -1
  728. package/src/orchestrator/run-dir.ts +8 -1
  729. package/src/orchestrator/run-execution.ts +75 -10
  730. package/src/orchestrator/run-lifecycle.ts +4 -2
  731. package/src/orchestrator/run-workspace.ts +62 -0
  732. package/src/orchestrator/suite-compare.ts +47 -23
  733. package/src/orchestrator/suite-runs.ts +13 -2
  734. package/src/orchestrator/suite-summary.ts +129 -15
  735. package/src/previewer/artifacts.ts +221 -0
  736. package/src/previewer/server.ts +789 -0
  737. package/viewer/app.css +2111 -0
  738. package/viewer/app.js +627 -0
  739. package/viewer/artifact-view.js +48 -0
  740. package/viewer/charts.js +98 -0
  741. package/viewer/detail.js +1266 -0
  742. package/viewer/format.js +129 -0
  743. package/viewer/index.html +151 -0
  744. package/lib/cli/skills.d.ts +0 -38
  745. package/lib/cli/skills.d.ts.map +0 -1
  746. package/lib/cli/skills.js +0 -84
  747. package/lib/cli/skills.js.map +0 -1
  748. package/lib/drivers/shared/secure-copy.d.ts.map +0 -1
  749. package/lib/drivers/shared/secure-copy.js.map +0 -1
  750. package/skills/lux/SKILL.md +0 -89
  751. package/skills/lux/references/cli.md +0 -125
  752. package/skills/lux/references/eval-authoring.md +0 -257
  753. package/src/cli/skills.ts +0 -129
  754. /package/lib/{drivers/shared → core}/secure-copy.d.ts +0 -0
  755. /package/lib/{drivers/shared → core}/secure-copy.js +0 -0
  756. /package/src/{drivers/shared → core}/secure-copy.ts +0 -0
@@ -59,7 +59,7 @@ export const formatAlignedUsage = (usage: TokenUsage): string =>
59
59
  ].join(" "),
60
60
  ].join(" ");
61
61
 
62
- export const formatScore = (score: number): string => `${Math.round(score * 100)}%`;
62
+ export const formatScore = (score: number): string => `${Number((score * 100).toPrecision(15))}%`;
63
63
 
64
64
  /** A one-line count summary: "2 passed · 1 failed · 1 running (4)". */
65
65
  export const formatTally = (parts: [count: number, label: string][], total: number): string => {
@@ -19,6 +19,7 @@ import {
19
19
  TurnUsageSchema,
20
20
  totalTokens,
21
21
  } from "../../core/index.js";
22
+ import { hasAgentUsage } from "../../core/usage.js";
22
23
  import type { CaseObserver, SuiteCaseResult, SuiteObserver } from "../../orchestrator/index.js";
23
24
  import {
24
25
  formatAlignedUsage,
@@ -80,6 +81,7 @@ type CaseView = {
80
81
  assertions: GradingAssertionEntry[];
81
82
  skippedAssertions: NonNullable<GradingReport["skippedAssertions"]>;
82
83
  usage: RunUsage;
84
+ agentUsageReported: boolean;
83
85
  /** Per-API-call agent usage, in order — the split behind `usage.agent`. */
84
86
  agentTurns: TurnUsage[];
85
87
  phaseDurationMs: PhaseDurations | null;
@@ -119,7 +121,10 @@ const statusMark = (status: CaseStatus, theme: Theme): string => {
119
121
 
120
122
  const assertionTally = (view: CaseView): string => {
121
123
  const passed = view.assertions.filter((a) => a.passed).length;
122
- const evaluated = view.assertions.length === 0 ? "—" : `${passed}/${view.assertions.length}`;
124
+ const evaluated =
125
+ view.assertions.length === 0
126
+ ? "—"
127
+ : `${passed}/${view.assertions.filter((a) => a.passed !== null).length}`;
123
128
  return view.skippedAssertions.length > 0
124
129
  ? `${evaluated} · ${view.skippedAssertions.length} skipped`
125
130
  : evaluated;
@@ -159,9 +164,12 @@ const cell = (text: string, width: number): string => {
159
164
  */
160
165
  const scoreNote = (entry: GradingAssertionEntry): string => {
161
166
  if (entry.errorMessage) return entry.errorMessage;
162
- if (entry.passed) return "";
167
+ if (entry.abstention) return "insufficient evidence";
168
+ if (entry.passed === null) return `informational; score ${formatScore(entry.score)}`;
169
+ if (entry.passed) return entry.score < 1 ? `score ${formatScore(entry.score)}` : "";
163
170
  const score = formatScore(entry.score);
164
- if (entry.threshold > 0) return `score ${score} < ${formatScore(entry.threshold)}`;
171
+ if (entry.threshold !== undefined && entry.threshold > 0)
172
+ return `score ${score} < ${formatScore(entry.threshold)}`;
165
173
  return entry.score > 0 ? `score ${score}` : "";
166
174
  };
167
175
 
@@ -240,6 +248,7 @@ export class ConsoleReporter implements SuiteObserver {
240
248
  assertions: [],
241
249
  skippedAssertions: [],
242
250
  usage: emptyRunUsage(),
251
+ agentUsageReported: false,
243
252
  agentTurns: [],
244
253
  phaseDurationMs: null,
245
254
  runDir: null,
@@ -273,6 +282,13 @@ export class ConsoleReporter implements SuiteObserver {
273
282
  view.toolUnresolved = tools.unresolved;
274
283
  view.toolUnmatchedResults = tools.unmatchedResults;
275
284
  view.toolMalformed = tools.malformedEvents;
285
+ } else if (event.type === "progress" && event.kind === "driver-stderr" && this.verbose) {
286
+ const payload = event.payload as { text?: unknown; truncated?: unknown } | null;
287
+ if (payload && typeof payload.text === "string") {
288
+ this.region.staticLine(this.theme.dim(` [${view.caseId}] ${payload.text}`));
289
+ if (payload.truncated === true)
290
+ this.region.staticLine(this.theme.dim(" [driver stderr truncated]"));
291
+ }
276
292
  } else if (event.type === "progress" && event.kind === "usage") {
277
293
  const turn = TurnUsageSchema.safeParse(event.payload).data;
278
294
  if (turn) view.agentTurns.push(turn);
@@ -307,6 +323,7 @@ export class ConsoleReporter implements SuiteObserver {
307
323
  view.assertions = result.result.grading.assertions;
308
324
  view.skippedAssertions = result.result.grading.skippedAssertions ?? [];
309
325
  view.usage = result.result.metadata.usage;
326
+ view.agentUsageReported = hasAgentUsage(result.result.metadata);
310
327
  view.phaseDurationMs = result.result.metadata.phaseDurationMs ?? null;
311
328
  const tools = result.result.metadata.toolOutcomes;
312
329
  if (tools) {
@@ -451,10 +468,14 @@ export class ConsoleReporter implements SuiteObserver {
451
468
  Math.max(NAME_MIN, ...view.assertions.map((a) => a.name.length)),
452
469
  );
453
470
  for (const entry of view.assertions) {
454
- const mark = entry.passed ? this.theme.green("✓") : this.theme.red("✗");
471
+ let mark = entry.passed ? this.theme.green("✓") : this.theme.red("✗");
472
+ if (entry.passed === null) mark = this.theme.dim("ℹ");
473
+ if (entry.abstention) mark = this.theme.dim("?");
455
474
  const duration = formatDuration(entry.durationMs).padStart(DURATION_COL);
456
475
  const note = scoreNote(entry);
457
- const suffix = note ? ` ${this.theme.red(note)}` : "";
476
+ const suffix = note
477
+ ? ` ${entry.abstention || entry.passed !== false ? this.theme.dim(note) : this.theme.red(note)}`
478
+ : "";
458
479
  nodes.push({
459
480
  head: `${mark} ${cell(entry.name, width)} ${this.theme.dim(duration)}${suffix}`,
460
481
  body: !entry.passed && entry.comment ? [this.theme.dim(entry.comment)] : [],
@@ -566,11 +587,12 @@ export class ConsoleReporter implements SuiteObserver {
566
587
  const skippedAssertions = this.cases.flatMap((c) => c.skippedAssertions);
567
588
  if (assertions.length > 0 || skippedAssertions.length > 0) {
568
589
  const ok = assertions.filter((a) => a.passed).length;
569
- const bad = assertions.length - ok;
590
+ const bad = assertions.filter((a) => a.passed === false).length;
570
591
  const tally = formatTally(
571
592
  [
572
593
  [ok, this.theme.green("passed")],
573
594
  [bad, this.theme.red("failed")],
595
+ [assertions.filter((a) => a.passed === null).length, this.theme.dim("informational")],
574
596
  [skippedAssertions.length, this.theme.dim("skipped")],
575
597
  ],
576
598
  assertions.length + skippedAssertions.length,
@@ -630,11 +652,17 @@ export class ConsoleReporter implements SuiteObserver {
630
652
  emptyRunUsage(),
631
653
  );
632
654
  const harness = harnessUsage(total);
633
- if (isUsageEmpty(total.agent) && isUsageEmpty(harness)) {
655
+ const reported = this.cases.filter(
656
+ (view) => view.agentUsageReported || !isUsageEmpty(this.agentUsageOf(view)),
657
+ ).length;
658
+ if (reported === 0 && isUsageEmpty(total.agent) && isUsageEmpty(harness)) {
634
659
  return live ? [] : [` ${label("Tokens")}${this.theme.dim("none reported")}`];
635
660
  }
636
661
 
637
- const agentText = isUsageEmpty(total.agent) ? this.theme.dim("none") : formatUsage(total.agent);
662
+ const missing = this.cases.length - reported;
663
+ const partial = missing > 0 ? ` (${missing} run${missing === 1 ? "" : "s"} unavailable)` : "";
664
+ const agentText =
665
+ reported === 0 ? this.theme.dim("unavailable") : `${formatUsage(total.agent)}${partial}`;
638
666
  if (live) {
639
667
  const harnessText = isUsageEmpty(harness)
640
668
  ? ""
@@ -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[];
@@ -11,26 +16,21 @@ export type RunOptions = {
11
16
  skipJudge?: boolean;
12
17
  runsRoot?: string;
13
18
  profile?: string;
19
+ driver?: string;
20
+ model?: string;
21
+ effort?: ReasoningEffort;
14
22
  subjectRoot?: string;
15
23
  verbose?: boolean;
16
24
  };
17
25
 
18
- export const collectTags = (value: string, previous: string[]): string[] =>
19
- previous.concat(
20
- value
21
- .split(",")
22
- .map((tag) => tag.trim())
23
- .filter(Boolean),
24
- );
25
-
26
- export const collectValues = (value: string, previous: string[]): string[] => [...previous, value];
27
-
28
26
  export const parseAnnotationAssertion = (
29
27
  value: string,
30
28
  ): [string, { passed: boolean; score?: number }] => {
31
29
  const match = /^(.+)=(pass|fail)(?::(.+))?$/.exec(value);
32
- if (!match?.[1] || !match[2]) {
33
- 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
+ });
34
34
  }
35
35
  const score = match[3] === undefined ? undefined : parseUnitInterval(match[3]);
36
36
  return [
@@ -42,19 +42,10 @@ export const parseAnnotationAssertion = (
42
42
  ];
43
43
  };
44
44
 
45
- export const parsePositiveInt = (value: string): number => {
46
- // Number() rejects partial numbers such as "3abc" and "2.9".
45
+ const parseUnitInterval = (value: string): number => {
47
46
  const parsed = Number(value);
48
- if (!Number.isInteger(parsed) || parsed < 1) {
49
- throw new InvalidArgumentError("must be a positive integer");
50
- }
51
- return parsed;
52
- };
53
-
54
- export const parseUnitInterval = (value: string): number => {
55
- const parsed = Number(value);
56
- if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
57
- 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" });
58
49
  }
59
50
  return parsed;
60
51
  };
@@ -81,3 +72,118 @@ export const resolveAnswererOverride = (options: RunOptions): string | undefined
81
72
  if (options.claudeAnswerer) return "claude-code";
82
73
  return undefined;
83
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,213 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import { posix } 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 { containerPaths } from "./paths.js";
19
+ import { type Message, readMessages, writeMessage } from "./protocol.js";
20
+ import { prepareContainer } from "./resources.js";
21
+
22
+ export class ContainerDriver extends TypedEmitter<DriverEventMap> implements AgentDriver {
23
+ private process: ManagedProcess | undefined;
24
+ private resources: Awaited<ReturnType<typeof prepareContainer>> | undefined;
25
+ private sequence = 0;
26
+ private pending = new Map<
27
+ number,
28
+ { resolve: (value: unknown) => void; reject: (error: Error) => void }
29
+ >();
30
+ private closing: Promise<void> | undefined;
31
+ private context: StartContext | undefined;
32
+ private terminal = false;
33
+ private readonly abort = () => {
34
+ void this.close().catch(() => {});
35
+ };
36
+
37
+ private readonly name: string;
38
+ private readonly config: unknown;
39
+ private readonly execution: ContainerExecution;
40
+ constructor(name: string, config: unknown, execution: ContainerExecution) {
41
+ super();
42
+ this.name = name;
43
+ this.config = config;
44
+ this.execution = execution;
45
+ JSON.stringify(config, (_key, value: unknown) => {
46
+ if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint")
47
+ throw new Error("container driver configuration must be JSON serializable");
48
+ return value;
49
+ });
50
+ }
51
+
52
+ private fail = (error: Error): void => {
53
+ for (const pending of this.pending.values()) pending.reject(error);
54
+ this.pending.clear();
55
+ if (!this.terminal && !this.closing) {
56
+ this.terminal = true;
57
+ void this.emit("error", { exitReason: "error", reason: error.message }).catch(() => {});
58
+ }
59
+ };
60
+
61
+ private receive = (message: Message): void => {
62
+ if (message.event) {
63
+ const dispatch = async () => {
64
+ switch (message.event) {
65
+ case "interrupt":
66
+ await this.emit("interrupt", InterruptSchema.parse(message.value));
67
+ break;
68
+ case "progress":
69
+ await this.emit("progress", ProgressSchema.parse(message.value));
70
+ break;
71
+ case "done":
72
+ this.terminal = true;
73
+ await this.emit("done", DoneSchema.parse(message.value));
74
+ break;
75
+ case "error":
76
+ this.terminal = true;
77
+ await this.emit("error", ErrorEventSchema.parse(message.value));
78
+ break;
79
+ default:
80
+ throw new Error("unknown container event");
81
+ }
82
+ if (this.process) writeMessage(this.process.child.stdin, { id: message.id, ack: true });
83
+ };
84
+ void dispatch().catch(this.fail);
85
+ return;
86
+ }
87
+ const pending = this.pending.get(message.id);
88
+ if (!pending) return;
89
+ this.pending.delete(message.id);
90
+ if (message.error !== undefined) pending.reject(new Error(message.error));
91
+ else pending.resolve(message.value);
92
+ };
93
+
94
+ private rpc = (method: string, value?: unknown, timeoutMs = 30_000): Promise<unknown> =>
95
+ new Promise((resolvePromise, reject) => {
96
+ if (!this.process) {
97
+ reject(new Error("container process is unavailable"));
98
+ return;
99
+ }
100
+ const id = ++this.sequence;
101
+ const timer = setTimeout(() => {
102
+ this.pending.delete(id);
103
+ reject(new Error(`container ${method} timed out`));
104
+ }, timeoutMs);
105
+ this.pending.set(id, {
106
+ resolve: (result) => {
107
+ clearTimeout(timer);
108
+ resolvePromise(result);
109
+ },
110
+ reject: (error) => {
111
+ clearTimeout(timer);
112
+ reject(error);
113
+ },
114
+ });
115
+ try {
116
+ writeMessage(this.process.child.stdin, { id, method, value });
117
+ } catch (error) {
118
+ this.pending.get(id)?.reject(error as Error);
119
+ this.pending.delete(id);
120
+ }
121
+ });
122
+
123
+ async start(ctx: StartContext): Promise<ReadyState> {
124
+ this.context = ctx;
125
+ if (ctx.abortSignal.aborted) throw new Error("container run aborted before startup");
126
+ const raw = this.config as { cwd?: string; cwdMode?: string };
127
+ if (raw?.cwdMode === "runDir")
128
+ throw new Error("container drivers must use the artifacts workspace, not cwdMode: runDir");
129
+ if (raw?.cwd && (await realpath(raw.cwd)) !== (await realpath(ctx.artifactsDir)))
130
+ throw new Error("container driver cwd must be the mounted artifacts workspace");
131
+ this.resources = await prepareContainer(this.execution, ctx.artifactsDir);
132
+ try {
133
+ this.process = spawnManagedProcess(this.resources.command, this.resources.args, {
134
+ env: this.resources.env,
135
+ });
136
+ readMessages(this.process.child.stdout, this.receive, this.fail);
137
+ // Harness stderr can contain secrets. The normalized driver protocol is the evidence surface.
138
+ this.process.child.stderr.resume();
139
+ void this.process.exited.then(() => this.fail(new Error("container worker exited")));
140
+ ctx.abortSignal.addEventListener("abort", this.abort, { once: true });
141
+ await this.process.spawned;
142
+ if (ctx.abortSignal.aborted) throw new Error("container run aborted during startup");
143
+ const { abortSignal: _signal, ...context } = ctx;
144
+ const ready = ReadyStateSchema.parse(
145
+ await this.rpc(
146
+ "start",
147
+ {
148
+ version: LUX_VERSION,
149
+ name: this.name,
150
+ config: containerPaths(this.config, this.resources.pathMappings),
151
+ module: this.execution.driverModule,
152
+ context: {
153
+ ...containerPaths(context, this.resources.pathMappings),
154
+ artifactsDir: this.resources.containerRoot,
155
+ ...(context.fixtures
156
+ ? { fixtures: { ...context.fixtures, rootDir: this.resources.containerRoot } }
157
+ : {}),
158
+ runDir: "/tmp/lux-run",
159
+ runsRoot: "/tmp/lux-runs",
160
+ },
161
+ },
162
+ this.execution.startupTimeoutMs ?? 60_000,
163
+ ),
164
+ );
165
+ return {
166
+ ...ready,
167
+ detail: { ...ready.detail, execution: "container", image: this.resources.image },
168
+ };
169
+ } catch (error) {
170
+ await this.close();
171
+ throw error;
172
+ }
173
+ }
174
+
175
+ async respond(answer: Answer): Promise<void> {
176
+ await this.rpc("respond", answer);
177
+ }
178
+ async quiesce(): Promise<void> {
179
+ await this.rpc("quiesce");
180
+ }
181
+ async collect(): Promise<Artifact[]> {
182
+ const root = this.resources?.root;
183
+ const containerRoot = this.resources?.containerRoot;
184
+ if (!root || !containerRoot) return [];
185
+ try {
186
+ const artifacts = (await this.rpc("collect")) as Artifact[];
187
+ for (const artifact of artifacts) {
188
+ const path = posix.resolve(artifact.root ?? containerRoot, artifact.path);
189
+ if (path !== containerRoot && !path.startsWith(`${containerRoot}/`))
190
+ throw new Error("container driver returned artifacts outside its mounted workspace");
191
+ }
192
+ } finally {
193
+ await this.close();
194
+ }
195
+ return walkArtifacts(root);
196
+ }
197
+ close(): Promise<void> {
198
+ this.closing ??= (async () => {
199
+ this.context?.abortSignal.removeEventListener("abort", this.abort);
200
+ try {
201
+ if (this.process) {
202
+ await this.rpc("close", undefined, 5_000).catch(() => {});
203
+ this.process.child.stdin.end();
204
+ }
205
+ await this.resources?.cleanup();
206
+ } finally {
207
+ await this.process?.terminate();
208
+ this.fail(new Error("container driver closed"));
209
+ }
210
+ })();
211
+ return this.closing;
212
+ }
213
+ }
@@ -0,0 +1,29 @@
1
+ /** Translate only mounted host paths; unrelated configuration remains untouched. */
2
+ export const containerPaths = <T>(
3
+ value: T,
4
+ mappings: readonly (readonly [string, string])[],
5
+ ): T => {
6
+ const ordered = [...mappings].sort(([a], [b]) => b.length - a.length);
7
+ const visit = (entry: unknown): unknown => {
8
+ if (typeof entry === "string") {
9
+ let text = entry;
10
+ for (const [source, target] of ordered) {
11
+ if (source === target) continue;
12
+ if (text === source) return target;
13
+ if (text.startsWith(`${source}\\`) || text.startsWith(`${source}/`))
14
+ return target + text.slice(source.length).replaceAll("\\", "/");
15
+ const escaped = source.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
16
+ text = text.replace(
17
+ new RegExp(`${escaped}([\\\\/][^\\s"']*)?(?=$|[\\s"'])`, "g"),
18
+ (_match, suffix: string | undefined) => target + (suffix ?? "").replaceAll("\\", "/"),
19
+ );
20
+ }
21
+ return text;
22
+ }
23
+ if (Array.isArray(entry)) return entry.map(visit);
24
+ if (entry && typeof entry === "object")
25
+ return Object.fromEntries(Object.entries(entry).map(([key, item]) => [key, visit(item)]));
26
+ return entry;
27
+ };
28
+ return visit(value) as T;
29
+ };