@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
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { EvaluationMetadataSchema } from "./evaluation-clusters.js";
2
3
  import { formatZodIssues } from "./zod.js";
3
4
 
4
5
  const ExpectedBooleanLabelSchema = z
@@ -35,7 +36,7 @@ export const GraderAnnotationSchema = z
35
36
  reviewer: z.string().min(1).optional(),
36
37
  /** Human rationale supplied to the rubric optimizer on mismatches. */
37
38
  feedback: z.string().optional(),
38
- meta: z.record(z.string(), z.unknown()).optional(),
39
+ meta: EvaluationMetadataSchema.optional(),
39
40
  })
40
41
  .strict()
41
42
  .superRefine((annotation, ctx) => {
@@ -73,3 +73,12 @@ export type AnswererPlugin<Cfg = unknown> = {
73
73
  configSchema?: z.ZodTypeAny;
74
74
  create: (config: Cfg) => Answerer | Promise<Answerer>;
75
75
  };
76
+
77
+ export const defineAnswerer = <S extends z.ZodType>(
78
+ definition: Omit<AnswererPlugin<z.output<S>>, "configSchema"> & { configSchema: S },
79
+ ): Omit<AnswererPlugin<z.output<S>>, "configSchema"> & { configSchema: S } => definition;
80
+
81
+ export const answererRef = <S extends z.ZodType>(
82
+ plugin: { name: string; configSchema: S },
83
+ config: z.input<S>,
84
+ ): { name: string; config: z.input<S> } => ({ name: plugin.name, config });
@@ -7,12 +7,15 @@ import type { Run } from "./run.js";
7
7
  const DEFAULT_ARTIFACT_READ_BYTES = 5 * 1024 * 1024;
8
8
  const MAX_ARTIFACT_READ_BYTES = 10 * 1024 * 1024;
9
9
 
10
+ export type RunArtifactIssueReason = "absent" | "unreadable";
11
+
10
12
  export type RunArtifactInspection = {
11
13
  target: string;
12
14
  root: string;
13
15
  artifact?: Artifact;
14
16
  stats?: Stats;
15
17
  issue?: string;
18
+ reason?: RunArtifactIssueReason;
16
19
  };
17
20
 
18
21
  type RunArtifactEvidence = {
@@ -82,6 +85,7 @@ export const inspectRunArtifact = async (
82
85
  target: authoredPath,
83
86
  root: runArtifactsRoot(run),
84
87
  issue: `${authoredPath} contains a null byte`,
88
+ reason: "unreadable",
85
89
  };
86
90
  }
87
91
  const matching = run.artifacts.filter((candidate) => candidate.path === authoredPath);
@@ -91,6 +95,7 @@ export const inspectRunArtifact = async (
91
95
  target: resolve(root, authoredPath),
92
96
  root,
93
97
  issue: `${authoredPath} was not captured in the frozen artifact index`,
98
+ reason: "absent",
94
99
  };
95
100
  }
96
101
  if (matching.some((candidate) => candidate.root !== undefined && !isAbsolute(candidate.root))) {
@@ -98,6 +103,7 @@ export const inspectRunArtifact = async (
98
103
  target: authoredPath,
99
104
  root: defaultArtifactsRoot(run),
100
105
  issue: `${authoredPath} declares a non-absolute artifact root`,
106
+ reason: "unreadable",
101
107
  };
102
108
  }
103
109
  const artifact = matching[0];
@@ -108,6 +114,7 @@ export const inspectRunArtifact = async (
108
114
  target: authoredPath,
109
115
  root: defaultArtifactsRoot(run),
110
116
  issue: `${authoredPath} is ambiguous across multiple artifact roots`,
117
+ reason: "unreadable",
111
118
  };
112
119
  }
113
120
  // A non-default root is trusted only for an exact artifact-index entry.
@@ -116,7 +123,12 @@ export const inspectRunArtifact = async (
116
123
  const root = matchingRoots[0] ?? defaultArtifactsRoot(run);
117
124
  const target = resolve(root, authoredPath);
118
125
  if (pathEscapesRoot(root, target)) {
119
- return { target, root, issue: `${authoredPath} escapes the captured artifact root` };
126
+ return {
127
+ target,
128
+ root,
129
+ issue: `${authoredPath} escapes the captured artifact root`,
130
+ reason: "unreadable",
131
+ };
120
132
  }
121
133
 
122
134
  const path = relative(root, target);
@@ -134,7 +146,13 @@ export const inspectRunArtifact = async (
134
146
  } catch (error) {
135
147
  const code = (error as NodeJS.ErrnoException).code;
136
148
  if (code === "ENOENT" || code === "ENOTDIR") {
137
- return { target, root, ...identified, issue: `${authoredPath} not found` };
149
+ return {
150
+ target,
151
+ root,
152
+ ...identified,
153
+ issue: `${authoredPath} not found`,
154
+ reason: "absent",
155
+ };
138
156
  }
139
157
  throw error;
140
158
  }
@@ -144,16 +162,17 @@ export const inspectRunArtifact = async (
144
162
  root,
145
163
  ...identified,
146
164
  issue: `${authoredPath} resolves through a symlink`,
165
+ reason: "unreadable",
147
166
  };
148
167
  }
149
168
  if (index < components.length - 1 && !stats.isDirectory()) {
150
- return { target, root, ...identified, issue: `${authoredPath} not found` };
169
+ return { target, root, ...identified, issue: `${authoredPath} not found`, reason: "absent" };
151
170
  }
152
171
  if (index === components.length - 1) {
153
172
  return { target, root, ...identified, stats };
154
173
  }
155
174
  }
156
- return { target, root, ...identified, issue: `${authoredPath} not found` };
175
+ return { target, root, ...identified, issue: `${authoredPath} not found`, reason: "absent" };
157
176
  };
158
177
 
159
178
  export type ReadRunArtifactTextOptions = {
@@ -247,3 +266,27 @@ export const readRunArtifactText = async (
247
266
  ): Promise<string> => {
248
267
  return (await readRunArtifactBytes(run, authoredPath, options)).toString("utf8");
249
268
  };
269
+
270
+ /**
271
+ * Read optional artifact evidence. Returns null when the artifact was never
272
+ * captured, and still throws when one exists but is unsafe to consume, so a
273
+ * traversal or symlink violation is never mistaken for missing evidence.
274
+ */
275
+ export const readRunArtifactTextIfPresent = async (
276
+ run: RunArtifactEvidence,
277
+ authoredPath: string,
278
+ options: ReadRunArtifactTextOptions = {},
279
+ ): Promise<string | null> => {
280
+ const inspected = await inspectRunArtifact(run, authoredPath);
281
+ if (inspected.reason === "absent") return null;
282
+ if (!inspected.stats?.isFile()) {
283
+ throw new Error(
284
+ inspected.issue ??
285
+ (inspected.stats ? `${authoredPath} is not a file` : `${authoredPath} not found`),
286
+ );
287
+ }
288
+ const maxBytes = options.maxBytes ?? DEFAULT_ARTIFACT_READ_BYTES;
289
+ return (
290
+ await readInspectedFileBytes(inspected.target, inspected.stats, maxBytes, authoredPath)
291
+ ).toString("utf8");
292
+ };
@@ -9,6 +9,8 @@ export const AssertionResultSchema = z.object({
9
9
  score: z.number().min(0).max(1),
10
10
  comment: z.exactOptional(z.string()),
11
11
  detail: z.unknown().optional(),
12
+ /** The evaluator ran successfully but lacked evidence for a verdict. */
13
+ abstention: z.exactOptional(z.literal("insufficient-evidence")),
12
14
  /** Present when the assertion could not produce a judgment. */
13
15
  errorMessage: z.exactOptional(z.string()),
14
16
  /** Tokens the assertion itself spent. Only LLM-judge assertions report this. */
@@ -100,6 +102,13 @@ export const assertionPluginIssue = (definition: {
100
102
  * Define a schema-validated assertion plugin while inferring the config passed
101
103
  * to `evaluate` from the schema.
102
104
  */
105
+ export const baseAssertionFields = {
106
+ id: z.string().min(1).optional(),
107
+ weight: z.number().positive().optional(),
108
+ threshold: z.number().min(0).max(1).optional(),
109
+ name: z.string().optional(),
110
+ } as const;
111
+
103
112
  export const defineAssertion = <S extends z.ZodObject>(
104
113
  definition: AssertionPluginDefinition<S>,
105
114
  ): AssertionPlugin<SchemaAssertion<S>, SchemaAssertionInput<S>> => {
@@ -136,16 +145,25 @@ export const GradingAssertionEntrySchema = z.object({
136
145
  durationMs: z.number(),
137
146
  comment: z.exactOptional(z.string()),
138
147
  detail: z.unknown().optional(),
148
+ abstention: z.exactOptional(z.literal("insufficient-evidence")),
139
149
  errorMessage: z.exactOptional(z.string()),
140
150
  usage: z.exactOptional(TokenUsageSchema),
141
151
  });
142
152
  export type GradingAssertionEntry = z.infer<typeof GradingAssertionEntrySchema>;
143
153
 
154
+ const SkippedGradingAssertionSchema = z.object({
155
+ id: z.string(),
156
+ type: z.string(),
157
+ name: z.string(),
158
+ reason: z.literal("judge-disabled"),
159
+ });
160
+
144
161
  export const GradingReportSchema = z.object({
145
162
  schemaVersion: z.literal(1),
146
163
  casePassed: z.boolean().nullable(),
147
164
  caseScore: z.number().nullable(),
148
165
  assertions: z.array(GradingAssertionEntrySchema),
166
+ skippedAssertions: z.array(SkippedGradingAssertionSchema).optional(),
149
167
  /**
150
168
  * Present when the subject run or grading did not complete. Assertions may
151
169
  * still contain partial diagnostics, but the report is not a clean verdict.
package/src/core/case.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import type { AssertionPlugin } from "./assertion.js";
3
3
  import { collectEvalCaseExtensions, setEvalCaseExtensions } from "./case-authoring-state.js";
4
+ import { DriverCapabilitySchema } from "./driver.js";
5
+ import { DriverExecutionSchema } from "./driver-execution.js";
6
+ import { EvaluationMetadataSchema } from "./evaluation-clusters.js";
7
+ import { HarnessMatrixSchema } from "./harness-matrix.js";
4
8
  import type { LifecycleHooksPlugin } from "./lifecycle-hooks.js";
5
9
  import { formatZodIssues } from "./zod.js";
6
10
 
@@ -17,7 +21,13 @@ export type FixturesRef = z.infer<typeof FixturesRefSchema>;
17
21
  // `defineEvalCase` discriminate the config type on `name`.
18
22
  export const DriverRefSchema = z.union([
19
23
  z.string(),
20
- z.object({ name: z.string(), config: z.unknown().optional() }).strict(),
24
+ z
25
+ .object({
26
+ name: z.string(),
27
+ config: z.unknown().optional(),
28
+ execution: DriverExecutionSchema.optional(),
29
+ })
30
+ .strict(),
21
31
  ]);
22
32
  export type DriverRef = z.infer<typeof DriverRefSchema>;
23
33
 
@@ -44,10 +54,13 @@ const EvalCaseObjectSchema = z.object({
44
54
  prompt: z.string().min(1, "prompt is required"),
45
55
  persona: z.string().min(1).optional(),
46
56
  driver: DriverRefSchema.optional(),
57
+ /** Harness permutations this case runs through instead of the project matrix. */
58
+ matrix: HarnessMatrixSchema.optional(),
47
59
  answerer: AnswererRefSchema.optional(),
48
60
  fixtures: FixturesRefSchema.optional(),
61
+ requires: z.array(DriverCapabilitySchema).optional(),
49
62
  assertions: z.array(AssertionSchema).optional(),
50
- meta: z.record(z.string(), z.unknown()).optional(),
63
+ meta: EvaluationMetadataSchema.optional(),
51
64
  });
52
65
 
53
66
  export const EvalCaseSchema = EvalCaseObjectSchema
@@ -149,6 +162,7 @@ export const PersistedCaseSchema = EvalCaseObjectSchema.partial()
149
162
  driver: PersistedDriverRefSchema.optional(),
150
163
  answerer: PersistedAnswererRefSchema.optional(),
151
164
  fixtures: PersistedFixturesRefSchema.optional(),
165
+ meta: z.record(z.string(), z.unknown()).optional(),
152
166
  })
153
167
  .loose();
154
168
  export type PersistedCase = z.infer<typeof PersistedCaseSchema>;
@@ -0,0 +1,74 @@
1
+ import { chmod, lstat, mkdir, mkdtemp, readdir, realpath, rm, symlink } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
+ import type { Run } from "./run.js";
5
+ import { copyRegularFileNoFollow } from "./secure-copy.js";
6
+
7
+ const executionWorkspaces = new WeakMap<Run, string>();
8
+
9
+ /** Internal: live execution state is deliberately absent from persisted run evidence. */
10
+ export const bindRunExecutionWorkspace = (run: Run, root: string): void => {
11
+ executionWorkspaces.set(run, resolve(root));
12
+ };
13
+
14
+ export const runExecutionWorkspace = (run: Run): string | undefined => executionWorkspaces.get(run);
15
+
16
+ const within = (root: string, path: string): boolean => {
17
+ const rel = relative(root, path);
18
+ return rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
19
+ };
20
+
21
+ /** A disposable command tree preserves dependencies without exposing host symlink targets. */
22
+ export const copyCommandWorkspace = async (
23
+ source: string,
24
+ signal?: AbortSignal,
25
+ ): Promise<{
26
+ root: string;
27
+ close: () => Promise<void>;
28
+ }> => {
29
+ const sourceRoot = await realpath(source);
30
+ if (!(await lstat(source)).isDirectory() || (await lstat(source)).isSymbolicLink()) {
31
+ throw new Error(`verification workspace must be a real directory: ${source}`);
32
+ }
33
+ const root = await mkdtemp(join(tmpdir(), "lux-command-verification-"));
34
+ const close = () => rm(root, { recursive: true, force: true });
35
+ let entries = 0;
36
+ const copy = async (directory: string): Promise<void> => {
37
+ if (!within(sourceRoot, await realpath(directory))) {
38
+ throw new Error(`verification directory escapes its workspace: ${directory}`);
39
+ }
40
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
41
+ signal?.throwIfAborted();
42
+ if (++entries > 100_000) throw new Error("verification workspace exceeds 100000 entries");
43
+ if (directory === sourceRoot && entry.name === ".lux-claude") continue;
44
+ const path = join(directory, entry.name);
45
+ const target = join(root, relative(sourceRoot, path));
46
+ const metadata = await lstat(path);
47
+ if (metadata.isSymbolicLink()) {
48
+ const resolved = await realpath(path);
49
+ if (!within(sourceRoot, resolved)) {
50
+ throw new Error(`verification symlink escapes its workspace: ${path}`);
51
+ }
52
+ await symlink(
53
+ relative(dirname(target), join(root, relative(sourceRoot, resolved))),
54
+ target,
55
+ );
56
+ } else if (metadata.isDirectory()) {
57
+ await mkdir(target, { mode: (metadata.mode & 0o777) | 0o700 });
58
+ await copy(path);
59
+ await chmod(target, metadata.mode & 0o777);
60
+ } else if (metadata.isFile()) {
61
+ await copyRegularFileNoFollow(sourceRoot, path, target);
62
+ } else {
63
+ throw new Error(`verification workspace contains an unsupported entry: ${path}`);
64
+ }
65
+ }
66
+ };
67
+ try {
68
+ await copy(sourceRoot);
69
+ return { root, close };
70
+ } catch (error) {
71
+ await close();
72
+ throw error;
73
+ }
74
+ };
@@ -0,0 +1,84 @@
1
+ import { z } from "zod";
2
+
3
+ const homePath = z
4
+ .string()
5
+ .min(1)
6
+ .refine(
7
+ (value) =>
8
+ !value.startsWith("/") &&
9
+ !value.includes("\\") &&
10
+ value.split("/").every((part) => part !== ".." && part !== "." && part !== ""),
11
+ "must be a relative path within the container home",
12
+ );
13
+
14
+ export const ContainerExecutionSchema = z
15
+ .object({
16
+ kind: z.literal("container"),
17
+ /** A locally available image containing Lux and the selected Linux harness. */
18
+ image: z.string().min(1),
19
+ command: z.string().min(1).optional(),
20
+ /** The worker shipped with the same Lux build as the host. */
21
+ worker: z.string().min(1).optional(),
22
+ /** Optional module in the image exporting a custom DriverPlugin as default. */
23
+ driverModule: z.string().min(1).optional(),
24
+ mounts: z
25
+ .array(
26
+ z
27
+ .object({
28
+ source: z.string().min(1),
29
+ target: z.string().min(1).optional(),
30
+ readOnly: z.boolean().optional(),
31
+ })
32
+ .strict(),
33
+ )
34
+ .optional(),
35
+ /** Only these host environment variables enter the container. */
36
+ passEnv: z.array(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/)).optional(),
37
+ env: z.record(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/), z.string()).optional(),
38
+ /** Private copies, never host-home mounts; deleted after the run. */
39
+ homeFiles: z
40
+ .array(
41
+ z
42
+ .object({
43
+ destination: homePath,
44
+ source: z.discriminatedUnion("kind", [
45
+ z.object({ kind: z.literal("file"), path: z.string().min(1) }).strict(),
46
+ z
47
+ .object({
48
+ kind: z.literal("keychain"),
49
+ service: z.string().min(1),
50
+ account: z.string().min(1),
51
+ encoding: z.enum(["utf8", "go-keyring-base64"]).optional(),
52
+ })
53
+ .strict(),
54
+ ]),
55
+ })
56
+ .strict(),
57
+ )
58
+ .max(32)
59
+ .optional(),
60
+ network: z.enum(["bridge", "none"]).optional(),
61
+ user: z.string().min(1).optional(),
62
+ memory: z
63
+ .string()
64
+ .regex(/^[1-9][0-9]*[bkmgt]?$/i)
65
+ .optional(),
66
+ cpus: z.number().positive().optional(),
67
+ pidsLimit: z.number().int().positive().optional(),
68
+ startupTimeoutMs: z.number().int().positive().optional(),
69
+ })
70
+ .strict();
71
+
72
+ export const DriverExecutionSchema = z.discriminatedUnion("kind", [
73
+ z.object({ kind: z.literal("host") }).strict(),
74
+ ContainerExecutionSchema,
75
+ ]);
76
+ export type DriverExecution = z.infer<typeof DriverExecutionSchema>;
77
+ export type ContainerExecution = z.infer<typeof ContainerExecutionSchema>;
78
+
79
+ export const driverExecutionOf = (reference: unknown): DriverExecution | undefined => {
80
+ if (!reference || typeof reference !== "object" || !("execution" in reference)) return undefined;
81
+ return reference.execution === undefined
82
+ ? undefined
83
+ : DriverExecutionSchema.parse(reference.execution);
84
+ };
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+
3
+ export const DriverMetricUnitSchema = z.enum([
4
+ "number",
5
+ "count",
6
+ "milliseconds",
7
+ "bytes",
8
+ "tokens",
9
+ "usd",
10
+ "ratio",
11
+ "percent",
12
+ "score",
13
+ ]);
14
+ export type DriverMetricUnit = z.infer<typeof DriverMetricUnitSchema>;
15
+
16
+ export const DriverMetricDescriptorSchema = z
17
+ .object({
18
+ unit: DriverMetricUnitSchema.default("number"),
19
+ label: z.string().min(1).max(120).optional(),
20
+ better: z.enum(["lower", "higher", "neutral"]).default("neutral"),
21
+ })
22
+ .strict();
23
+ export type DriverMetricDescriptor = z.infer<typeof DriverMetricDescriptorSchema>;
24
+
25
+ export const DriverMetricSchema = DriverMetricDescriptorSchema.extend({
26
+ value: z.number().finite(),
27
+ }).strict();
28
+ export type DriverMetric = z.infer<typeof DriverMetricSchema>;
29
+
30
+ export const DriverMetricsSchema = z.record(z.string().min(1).max(120), DriverMetricSchema);
31
+ export type DriverMetrics = z.infer<typeof DriverMetricsSchema>;
32
+
33
+ const ReportedDriverMetricSchema = z.union([z.number().finite(), DriverMetricSchema]);
34
+ export const ReportedDriverMetricsSchema = z.record(
35
+ z.string().min(1).max(120),
36
+ ReportedDriverMetricSchema,
37
+ );
38
+ export type ReportedDriverMetrics = z.input<typeof ReportedDriverMetricsSchema>;
39
+
40
+ export const normalizeDriverMetrics = (value: unknown): DriverMetrics => {
41
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
42
+ return Object.fromEntries(
43
+ Object.entries(value).flatMap(([name, metric]) => {
44
+ if (name.length === 0 || name.length > 120) return [];
45
+ const parsed = DriverMetricSchema.safeParse(
46
+ typeof metric === "number" ? { value: metric } : metric,
47
+ ).data;
48
+ return parsed ? [[name, parsed]] : [];
49
+ }),
50
+ );
51
+ };
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
+ import type { DriverExecution } from "./driver-execution.js";
2
3
  import type { EventHandler } from "./emitter.js";
3
4
  import type { Answer, Done, ErrorEvent, Interrupt, Progress, ReadyState } from "./events.js";
5
+ import type { ReasoningEffort } from "./harness-catalog.js";
4
6
  import type { FixtureValueBinding } from "./lifecycle-hooks.js";
5
7
 
6
8
  export const ArtifactSchema = z.object({
@@ -11,6 +13,8 @@ export const ArtifactSchema = z.object({
11
13
  * Consumers resolve `path` against this before falling back to the default.
12
14
  */
13
15
  root: z.exactOptional(z.string()),
16
+ /** Assigned by Lux against fixture bytes frozen before the subject starts. */
17
+ origin: z.exactOptional(z.enum(["generated", "modified", "fixture"])),
14
18
  contentType: z.exactOptional(z.string()),
15
19
  size: z.exactOptional(z.number()),
16
20
  meta: z.exactOptional(z.record(z.string(), z.unknown())),
@@ -27,6 +31,8 @@ export type ResolvedFixtures = z.infer<typeof ResolvedFixturesSchema>;
27
31
  export type StartContext = {
28
32
  /** Stable selected case id, available to drivers that multiplex scenarios. */
29
33
  caseId?: string;
34
+ /** Private home owned by an outer execution boundary; never the caller’s home. */
35
+ isolatedHome?: string;
30
36
  prompt: string;
31
37
  fixtures?: ResolvedFixtures | undefined;
32
38
  /** Authored fixture values selected for this case. */
@@ -68,11 +74,81 @@ export interface AgentDriver {
68
74
  * responsible for stopping background writers before this promise resolves.
69
75
  */
70
76
  collect(): Promise<Artifact[]>;
77
+ /** Optional quiesced full execution tree for private command verification, until close. */
78
+ verificationWorkspace?(): Promise<string | undefined>;
71
79
  close(): Promise<void>;
72
80
  }
73
81
 
82
+ export const DriverCapabilitySchema = z.enum([
83
+ "interactive",
84
+ "tool-calls",
85
+ "tool-results",
86
+ "artifacts",
87
+ "subagents",
88
+ "usage",
89
+ "cost",
90
+ "isolation",
91
+ ]);
92
+ export type DriverCapability = z.infer<typeof DriverCapabilitySchema>;
93
+
94
+ export type DriverRuntime = {
95
+ commands: string[];
96
+ /** Missing keys mean unknown; false means the adapter cannot provide the capability. */
97
+ capabilities: Partial<Record<DriverCapability, boolean>>;
98
+ };
99
+
100
+ export type DriverExperiment<Cfg> = {
101
+ version: string;
102
+ /** Bind a configuration to the experiment environment; Lux validates the returned config. */
103
+ prepare(config: Cfg): unknown;
104
+ /** Fingerprint behavior outside authored cases/configuration and the reported executables. */
105
+ identity(config: Cfg, context: { rootDir: string }): unknown | Promise<unknown>;
106
+ };
107
+
108
+ /** Model and reasoning effort chosen by a harness matrix permutation. */
109
+ export type HarnessSelection = {
110
+ model?: string | undefined;
111
+ effort?: ReasoningEffort | undefined;
112
+ };
113
+
74
114
  export type DriverPlugin<Cfg = unknown> = {
75
115
  name: string;
76
116
  configSchema?: z.ZodTypeAny;
77
117
  create: (config: Cfg) => AgentDriver | Promise<AgentDriver>;
118
+ runtime?: (config: Cfg) => DriverRuntime;
119
+ /** Ordinary runs remain supported when controlled experiments are not declared. */
120
+ experiment?: DriverExperiment<Cfg>;
121
+ /**
122
+ * Apply a matrix selection to raw (unvalidated) configuration. Drivers
123
+ * without a model concept leave this undefined and reject selection.
124
+ */
125
+ selectHarness?: (config: unknown, selection: HarnessSelection) => unknown;
78
126
  };
127
+
128
+ /** Selection for drivers whose configuration uses `model` and `reasoningEffort`. */
129
+ export const selectModelAndReasoningEffort = (
130
+ config: unknown,
131
+ selection: HarnessSelection,
132
+ ): unknown => ({
133
+ ...(config && typeof config === "object" && !Array.isArray(config)
134
+ ? (config as Record<string, unknown>)
135
+ : {}),
136
+ ...(selection.model !== undefined ? { model: selection.model } : {}),
137
+ ...(selection.effort !== undefined || selection.model !== undefined
138
+ ? { reasoningEffort: selection.effort }
139
+ : {}),
140
+ });
141
+
142
+ export const defineDriver = <S extends z.ZodType>(
143
+ definition: Omit<DriverPlugin<z.output<S>>, "configSchema"> & { configSchema: S },
144
+ ): Omit<DriverPlugin<z.output<S>>, "configSchema"> & { configSchema: S } => definition;
145
+
146
+ export const driverRef = <S extends z.ZodType>(
147
+ plugin: { name: string; configSchema: S },
148
+ config: z.input<S>,
149
+ execution?: DriverExecution,
150
+ ): { name: string; config: z.input<S>; execution?: DriverExecution } => ({
151
+ name: plugin.name,
152
+ config,
153
+ ...(execution ? { execution } : {}),
154
+ });
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+
3
+ const UNITS: Record<string, number> = {
4
+ ms: 1,
5
+ millisecond: 1,
6
+ milliseconds: 1,
7
+ s: 1000,
8
+ second: 1000,
9
+ seconds: 1000,
10
+ m: 60_000,
11
+ minute: 60_000,
12
+ minutes: 60_000,
13
+ h: 3_600_000,
14
+ hour: 3_600_000,
15
+ hours: 3_600_000,
16
+ d: 86_400_000,
17
+ day: 86_400_000,
18
+ days: 86_400_000,
19
+ };
20
+ const MAX_TIMER_MS = 2_147_483_647;
21
+ const INVALID_DURATION =
22
+ 'Expected a positive duration such as "20 minutes", "1.5 hours", or "500 ms", up to 2147483647 milliseconds';
23
+
24
+ /** Explicit units prevent ambiguous numeric configuration and Node timer overflow. */
25
+ export const durationMs = (value: string): number => {
26
+ if (value.length > 80) throw new Error(INVALID_DURATION);
27
+ const match =
28
+ /^(\d+(?:\.\d+)?)\s*(ms|milliseconds?|s|seconds?|m|minutes?|h|hours?|d|days?)$/i.exec(
29
+ value.trim(),
30
+ );
31
+ const amount = match?.[1];
32
+ const multiplier = match?.[2] ? UNITS[match[2].toLowerCase()] : undefined;
33
+ if (!amount || !multiplier) throw new Error(INVALID_DURATION);
34
+ const [whole, fraction = ""] = amount.split(".");
35
+ const scale = 10n ** BigInt(fraction.length);
36
+ const numerator = BigInt(`${whole}${fraction}`) * BigInt(multiplier);
37
+ const milliseconds = numerator / scale;
38
+ if (numerator % scale !== 0n || milliseconds <= 0n || milliseconds > BigInt(MAX_TIMER_MS)) {
39
+ throw new Error(INVALID_DURATION);
40
+ }
41
+ return Number(milliseconds);
42
+ };
43
+
44
+ // Keep strings in validated configs: schema validation may run again during
45
+ // experiment preparation or replay. Conversion belongs at the timer boundary.
46
+ export const DurationSchema = z.string().superRefine((value, ctx) => {
47
+ try {
48
+ durationMs(value);
49
+ } catch {
50
+ ctx.addIssue({ code: "custom", message: INVALID_DURATION });
51
+ }
52
+ });
@@ -0,0 +1,22 @@
1
+ import { z } from "zod";
2
+
3
+ /** Author-declared execution conditions. Lux records these without enforcing or verifying them. */
4
+ export const EnvironmentDeclarationSchema = z
5
+ .object({
6
+ imageDigest: z
7
+ .string()
8
+ .regex(/^(?:[^@\s]+@)?sha256:[a-f0-9]{64}$/)
9
+ .optional(),
10
+ toolchains: z.record(z.string().min(1), z.string().min(1)).optional(),
11
+ network: z.enum(["disabled", "restricted", "unrestricted"]).optional(),
12
+ resources: z
13
+ .object({
14
+ cpuCount: z.number().positive().optional(),
15
+ memoryBytes: z.number().int().positive().optional(),
16
+ diskBytes: z.number().int().positive().optional(),
17
+ })
18
+ .strict()
19
+ .optional(),
20
+ })
21
+ .strict();
22
+ export type EnvironmentDeclaration = z.infer<typeof EnvironmentDeclarationSchema>;
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+
3
+ export const EvaluationMetadataSchema = z
4
+ .object({
5
+ /** Related perturbations share one independent statistical unit. */
6
+ cluster: z.string().trim().min(1).optional(),
7
+ })
8
+ .catchall(z.unknown());
9
+
10
+ export const clusterKey = (id: string, cluster: string | undefined): string =>
11
+ JSON.stringify(cluster === undefined ? ["case", id] : ["cluster", cluster]);
12
+
13
+ export const independentClusterCount = (
14
+ items: readonly { id: string; cluster?: string | undefined }[],
15
+ ): number => new Set(items.map((item) => clusterKey(item.id, item.cluster))).size;
16
+
17
+ export const assertDisjointClusters = (
18
+ splits: readonly {
19
+ name: string;
20
+ items: readonly { id: string; cluster?: string | undefined }[];
21
+ }[],
22
+ ): void => {
23
+ const owners = new Map<string, string>();
24
+ for (const split of splits) {
25
+ for (const item of split.items) {
26
+ if (item.cluster === undefined) continue;
27
+ const owner = owners.get(item.cluster);
28
+ if (owner !== undefined && owner !== split.name)
29
+ throw new Error(
30
+ `evaluation cluster '${item.cluster}' appears in both ${owner} and ${split.name} splits`,
31
+ );
32
+ owners.set(item.cluster, split.name);
33
+ }
34
+ }
35
+ };