@prismatic-io/lux 0.0.1

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 (636) hide show
  1. package/LICENSE +21 -0
  2. package/lib/answerers/claude-code/index.d.ts +17 -0
  3. package/lib/answerers/claude-code/index.d.ts.map +1 -0
  4. package/lib/answerers/claude-code/index.js +280 -0
  5. package/lib/answerers/claude-code/index.js.map +1 -0
  6. package/lib/answerers/persona/index.d.ts +40 -0
  7. package/lib/answerers/persona/index.d.ts.map +1 -0
  8. package/lib/answerers/persona/index.js +265 -0
  9. package/lib/answerers/persona/index.js.map +1 -0
  10. package/lib/answerers/scripted/index.d.ts +8 -0
  11. package/lib/answerers/scripted/index.d.ts.map +1 -0
  12. package/lib/answerers/scripted/index.js +163 -0
  13. package/lib/answerers/scripted/index.js.map +1 -0
  14. package/lib/answerers/shared.d.ts +13 -0
  15. package/lib/answerers/shared.d.ts.map +1 -0
  16. package/lib/answerers/shared.js +17 -0
  17. package/lib/answerers/shared.js.map +1 -0
  18. package/lib/answerers/terminal/index.d.ts +9 -0
  19. package/lib/answerers/terminal/index.d.ts.map +1 -0
  20. package/lib/answerers/terminal/index.js +97 -0
  21. package/lib/answerers/terminal/index.js.map +1 -0
  22. package/lib/assertions/core/command-exits-zero.d.ts +21 -0
  23. package/lib/assertions/core/command-exits-zero.d.ts.map +1 -0
  24. package/lib/assertions/core/command-exits-zero.js +87 -0
  25. package/lib/assertions/core/command-exits-zero.js.map +1 -0
  26. package/lib/assertions/core/event-checks.d.ts +57 -0
  27. package/lib/assertions/core/event-checks.d.ts.map +1 -0
  28. package/lib/assertions/core/event-checks.js +123 -0
  29. package/lib/assertions/core/event-checks.js.map +1 -0
  30. package/lib/assertions/core/file-checks.d.ts +103 -0
  31. package/lib/assertions/core/file-checks.d.ts.map +1 -0
  32. package/lib/assertions/core/file-checks.js +288 -0
  33. package/lib/assertions/core/file-checks.js.map +1 -0
  34. package/lib/assertions/core/helpers.d.ts +66 -0
  35. package/lib/assertions/core/helpers.d.ts.map +1 -0
  36. package/lib/assertions/core/helpers.js +170 -0
  37. package/lib/assertions/core/helpers.js.map +1 -0
  38. package/lib/assertions/core/index.d.ts +15 -0
  39. package/lib/assertions/core/index.d.ts.map +1 -0
  40. package/lib/assertions/core/index.js +56 -0
  41. package/lib/assertions/core/index.js.map +1 -0
  42. package/lib/assertions/core/json-pointer-equals.d.ts +19 -0
  43. package/lib/assertions/core/json-pointer-equals.d.ts.map +1 -0
  44. package/lib/assertions/core/json-pointer-equals.js +71 -0
  45. package/lib/assertions/core/json-pointer-equals.js.map +1 -0
  46. package/lib/assertions/core/output-checks.d.ts +46 -0
  47. package/lib/assertions/core/output-checks.d.ts.map +1 -0
  48. package/lib/assertions/core/output-checks.js +121 -0
  49. package/lib/assertions/core/output-checks.js.map +1 -0
  50. package/lib/assertions/core/predicate.d.ts +14 -0
  51. package/lib/assertions/core/predicate.d.ts.map +1 -0
  52. package/lib/assertions/core/predicate.js +55 -0
  53. package/lib/assertions/core/predicate.js.map +1 -0
  54. package/lib/assertions/core/resource-checks.d.ts +71 -0
  55. package/lib/assertions/core/resource-checks.d.ts.map +1 -0
  56. package/lib/assertions/core/resource-checks.js +159 -0
  57. package/lib/assertions/core/resource-checks.js.map +1 -0
  58. package/lib/assertions/core/safe-regex.d.ts +23 -0
  59. package/lib/assertions/core/safe-regex.d.ts.map +1 -0
  60. package/lib/assertions/core/safe-regex.js +102 -0
  61. package/lib/assertions/core/safe-regex.js.map +1 -0
  62. package/lib/assertions/core/tool-called-with.d.ts +21 -0
  63. package/lib/assertions/core/tool-called-with.d.ts.map +1 -0
  64. package/lib/assertions/core/tool-called-with.js +69 -0
  65. package/lib/assertions/core/tool-called-with.js.map +1 -0
  66. package/lib/assertions/core/tool-calls.d.ts +22 -0
  67. package/lib/assertions/core/tool-calls.d.ts.map +1 -0
  68. package/lib/assertions/core/tool-calls.js +17 -0
  69. package/lib/assertions/core/tool-calls.js.map +1 -0
  70. package/lib/assertions/core/tool-invocation.d.ts +36 -0
  71. package/lib/assertions/core/tool-invocation.d.ts.map +1 -0
  72. package/lib/assertions/core/tool-invocation.js +170 -0
  73. package/lib/assertions/core/tool-invocation.js.map +1 -0
  74. package/lib/assertions/core/tool-result-checks.d.ts +59 -0
  75. package/lib/assertions/core/tool-result-checks.d.ts.map +1 -0
  76. package/lib/assertions/core/tool-result-checks.js +193 -0
  77. package/lib/assertions/core/tool-result-checks.js.map +1 -0
  78. package/lib/assertions/mcp/discovery-checks.d.ts +36 -0
  79. package/lib/assertions/mcp/discovery-checks.d.ts.map +1 -0
  80. package/lib/assertions/mcp/discovery-checks.js +122 -0
  81. package/lib/assertions/mcp/discovery-checks.js.map +1 -0
  82. package/lib/assertions/mcp/index.d.ts +10 -0
  83. package/lib/assertions/mcp/index.d.ts.map +1 -0
  84. package/lib/assertions/mcp/index.js +25 -0
  85. package/lib/assertions/mcp/index.js.map +1 -0
  86. package/lib/assertions/rubric/index.d.ts +104 -0
  87. package/lib/assertions/rubric/index.d.ts.map +1 -0
  88. package/lib/assertions/rubric/index.js +191 -0
  89. package/lib/assertions/rubric/index.js.map +1 -0
  90. package/lib/assertions/rubric/internal.d.ts +14 -0
  91. package/lib/assertions/rubric/internal.d.ts.map +1 -0
  92. package/lib/assertions/rubric/internal.js +335 -0
  93. package/lib/assertions/rubric/internal.js.map +1 -0
  94. package/lib/authoring.d.ts +3 -0
  95. package/lib/authoring.d.ts.map +1 -0
  96. package/lib/authoring.js +3 -0
  97. package/lib/authoring.js.map +1 -0
  98. package/lib/cli/bin.d.ts +3 -0
  99. package/lib/cli/bin.d.ts.map +1 -0
  100. package/lib/cli/bin.js +15 -0
  101. package/lib/cli/bin.js.map +1 -0
  102. package/lib/cli/command-runtime.d.ts +5 -0
  103. package/lib/cli/command-runtime.d.ts.map +1 -0
  104. package/lib/cli/command-runtime.js +30 -0
  105. package/lib/cli/command-runtime.js.map +1 -0
  106. package/lib/cli/init.d.ts +21 -0
  107. package/lib/cli/init.d.ts.map +1 -0
  108. package/lib/cli/init.js +340 -0
  109. package/lib/cli/init.js.map +1 -0
  110. package/lib/cli/program.d.ts +22 -0
  111. package/lib/cli/program.d.ts.map +1 -0
  112. package/lib/cli/program.js +757 -0
  113. package/lib/cli/program.js.map +1 -0
  114. package/lib/cli/render/format.d.ts +14 -0
  115. package/lib/cli/render/format.d.ts.map +1 -0
  116. package/lib/cli/render/format.js +71 -0
  117. package/lib/cli/render/format.js.map +1 -0
  118. package/lib/cli/render/reporter.d.ts +73 -0
  119. package/lib/cli/render/reporter.d.ts.map +1 -0
  120. package/lib/cli/render/reporter.js +519 -0
  121. package/lib/cli/render/reporter.js.map +1 -0
  122. package/lib/cli/render/tty.d.ts +77 -0
  123. package/lib/cli/render/tty.d.ts.map +1 -0
  124. package/lib/cli/render/tty.js +283 -0
  125. package/lib/cli/render/tty.js.map +1 -0
  126. package/lib/cli/run-options.d.ts +27 -0
  127. package/lib/cli/run-options.d.ts.map +1 -0
  128. package/lib/cli/run-options.js +58 -0
  129. package/lib/cli/run-options.js.map +1 -0
  130. package/lib/cli/skills.d.ts +38 -0
  131. package/lib/cli/skills.d.ts.map +1 -0
  132. package/lib/cli/skills.js +84 -0
  133. package/lib/cli/skills.js.map +1 -0
  134. package/lib/core/annotation.d.ts +56 -0
  135. package/lib/core/annotation.d.ts.map +1 -0
  136. package/lib/core/annotation.js +92 -0
  137. package/lib/core/annotation.js.map +1 -0
  138. package/lib/core/answerer.d.ts +68 -0
  139. package/lib/core/answerer.d.ts.map +1 -0
  140. package/lib/core/answerer.js +17 -0
  141. package/lib/core/answerer.js.map +1 -0
  142. package/lib/core/artifact-evidence.d.ts +50 -0
  143. package/lib/core/artifact-evidence.d.ts.map +1 -0
  144. package/lib/core/artifact-evidence.js +185 -0
  145. package/lib/core/artifact-evidence.js.map +1 -0
  146. package/lib/core/artifact-snapshot.d.ts +37 -0
  147. package/lib/core/artifact-snapshot.d.ts.map +1 -0
  148. package/lib/core/artifact-snapshot.js +339 -0
  149. package/lib/core/artifact-snapshot.js.map +1 -0
  150. package/lib/core/assertion.d.ts +129 -0
  151. package/lib/core/assertion.d.ts.map +1 -0
  152. package/lib/core/assertion.js +75 -0
  153. package/lib/core/assertion.js.map +1 -0
  154. package/lib/core/case.d.ts +79 -0
  155. package/lib/core/case.d.ts.map +1 -0
  156. package/lib/core/case.js +90 -0
  157. package/lib/core/case.js.map +1 -0
  158. package/lib/core/conversation-turn.d.ts +23 -0
  159. package/lib/core/conversation-turn.d.ts.map +1 -0
  160. package/lib/core/conversation-turn.js +31 -0
  161. package/lib/core/conversation-turn.js.map +1 -0
  162. package/lib/core/driver.d.ts +64 -0
  163. package/lib/core/driver.d.ts.map +1 -0
  164. package/lib/core/driver.js +18 -0
  165. package/lib/core/driver.js.map +1 -0
  166. package/lib/core/emitter.d.ts +20 -0
  167. package/lib/core/emitter.d.ts.map +1 -0
  168. package/lib/core/emitter.js +34 -0
  169. package/lib/core/emitter.js.map +1 -0
  170. package/lib/core/events.d.ts +202 -0
  171. package/lib/core/events.d.ts.map +1 -0
  172. package/lib/core/events.js +107 -0
  173. package/lib/core/events.js.map +1 -0
  174. package/lib/core/exec.d.ts +82 -0
  175. package/lib/core/exec.d.ts.map +1 -0
  176. package/lib/core/exec.js +168 -0
  177. package/lib/core/exec.js.map +1 -0
  178. package/lib/core/experiment.d.ts +285 -0
  179. package/lib/core/experiment.d.ts.map +1 -0
  180. package/lib/core/experiment.js +389 -0
  181. package/lib/core/experiment.js.map +1 -0
  182. package/lib/core/glob.d.ts +3 -0
  183. package/lib/core/glob.d.ts.map +1 -0
  184. package/lib/core/glob.js +32 -0
  185. package/lib/core/glob.js.map +1 -0
  186. package/lib/core/hash.d.ts +8 -0
  187. package/lib/core/hash.d.ts.map +1 -0
  188. package/lib/core/hash.js +214 -0
  189. package/lib/core/hash.js.map +1 -0
  190. package/lib/core/index.d.ts +29 -0
  191. package/lib/core/index.d.ts.map +1 -0
  192. package/lib/core/index.js +29 -0
  193. package/lib/core/index.js.map +1 -0
  194. package/lib/core/lifecycle-fixtures.d.ts +20 -0
  195. package/lib/core/lifecycle-fixtures.d.ts.map +1 -0
  196. package/lib/core/lifecycle-fixtures.js +109 -0
  197. package/lib/core/lifecycle-fixtures.js.map +1 -0
  198. package/lib/core/lifecycle-hooks.d.ts +52 -0
  199. package/lib/core/lifecycle-hooks.d.ts.map +1 -0
  200. package/lib/core/lifecycle-hooks.js +42 -0
  201. package/lib/core/lifecycle-hooks.js.map +1 -0
  202. package/lib/core/mcp-events.d.ts +44 -0
  203. package/lib/core/mcp-events.d.ts.map +1 -0
  204. package/lib/core/mcp-events.js +23 -0
  205. package/lib/core/mcp-events.js.map +1 -0
  206. package/lib/core/model-cli.d.ts +57 -0
  207. package/lib/core/model-cli.d.ts.map +1 -0
  208. package/lib/core/model-cli.js +237 -0
  209. package/lib/core/model-cli.js.map +1 -0
  210. package/lib/core/observer.d.ts +31 -0
  211. package/lib/core/observer.d.ts.map +1 -0
  212. package/lib/core/observer.js +25 -0
  213. package/lib/core/observer.js.map +1 -0
  214. package/lib/core/platform-process.d.ts +33 -0
  215. package/lib/core/platform-process.d.ts.map +1 -0
  216. package/lib/core/platform-process.js +214 -0
  217. package/lib/core/platform-process.js.map +1 -0
  218. package/lib/core/registry.d.ts +22 -0
  219. package/lib/core/registry.d.ts.map +1 -0
  220. package/lib/core/registry.js +45 -0
  221. package/lib/core/registry.js.map +1 -0
  222. package/lib/core/rubric.d.ts +18 -0
  223. package/lib/core/rubric.d.ts.map +1 -0
  224. package/lib/core/rubric.js +49 -0
  225. package/lib/core/rubric.js.map +1 -0
  226. package/lib/core/run.d.ts +419 -0
  227. package/lib/core/run.d.ts.map +1 -0
  228. package/lib/core/run.js +126 -0
  229. package/lib/core/run.js.map +1 -0
  230. package/lib/core/statistics.d.ts +39 -0
  231. package/lib/core/statistics.d.ts.map +1 -0
  232. package/lib/core/statistics.js +163 -0
  233. package/lib/core/statistics.js.map +1 -0
  234. package/lib/core/subject.d.ts +4 -0
  235. package/lib/core/subject.d.ts.map +1 -0
  236. package/lib/core/subject.js +46 -0
  237. package/lib/core/subject.js.map +1 -0
  238. package/lib/core/tool-events.d.ts +69 -0
  239. package/lib/core/tool-events.d.ts.map +1 -0
  240. package/lib/core/tool-events.js +242 -0
  241. package/lib/core/tool-events.js.map +1 -0
  242. package/lib/core/usage.d.ts +78 -0
  243. package/lib/core/usage.d.ts.map +1 -0
  244. package/lib/core/usage.js +104 -0
  245. package/lib/core/usage.js.map +1 -0
  246. package/lib/core/wire.d.ts +83 -0
  247. package/lib/core/wire.d.ts.map +1 -0
  248. package/lib/core/wire.js +101 -0
  249. package/lib/core/wire.js.map +1 -0
  250. package/lib/core/zod.d.ts +10 -0
  251. package/lib/core/zod.d.ts.map +1 -0
  252. package/lib/core/zod.js +18 -0
  253. package/lib/core/zod.js.map +1 -0
  254. package/lib/drivers/claude-code/index.d.ts +55 -0
  255. package/lib/drivers/claude-code/index.d.ts.map +1 -0
  256. package/lib/drivers/claude-code/index.js +779 -0
  257. package/lib/drivers/claude-code/index.js.map +1 -0
  258. package/lib/drivers/claude-code/parse-events.d.ts +46 -0
  259. package/lib/drivers/claude-code/parse-events.d.ts.map +1 -0
  260. package/lib/drivers/claude-code/parse-events.js +387 -0
  261. package/lib/drivers/claude-code/parse-events.js.map +1 -0
  262. package/lib/drivers/codex/app-events.d.ts +16 -0
  263. package/lib/drivers/codex/app-events.d.ts.map +1 -0
  264. package/lib/drivers/codex/app-events.js +184 -0
  265. package/lib/drivers/codex/app-events.js.map +1 -0
  266. package/lib/drivers/codex/config.d.ts +55 -0
  267. package/lib/drivers/codex/config.d.ts.map +1 -0
  268. package/lib/drivers/codex/config.js +125 -0
  269. package/lib/drivers/codex/config.js.map +1 -0
  270. package/lib/drivers/codex/index.d.ts +8 -0
  271. package/lib/drivers/codex/index.d.ts.map +1 -0
  272. package/lib/drivers/codex/index.js +904 -0
  273. package/lib/drivers/codex/index.js.map +1 -0
  274. package/lib/drivers/mcp/index.d.ts +52 -0
  275. package/lib/drivers/mcp/index.d.ts.map +1 -0
  276. package/lib/drivers/mcp/index.js +282 -0
  277. package/lib/drivers/mcp/index.js.map +1 -0
  278. package/lib/drivers/mcp/transport.d.ts +50 -0
  279. package/lib/drivers/mcp/transport.d.ts.map +1 -0
  280. package/lib/drivers/mcp/transport.js +190 -0
  281. package/lib/drivers/mcp/transport.js.map +1 -0
  282. package/lib/drivers/shared/artifacts.d.ts +4 -0
  283. package/lib/drivers/shared/artifacts.d.ts.map +1 -0
  284. package/lib/drivers/shared/artifacts.js +81 -0
  285. package/lib/drivers/shared/artifacts.js.map +1 -0
  286. package/lib/drivers/shared/secure-copy.d.ts +2 -0
  287. package/lib/drivers/shared/secure-copy.d.ts.map +1 -0
  288. package/lib/drivers/shared/secure-copy.js +35 -0
  289. package/lib/drivers/shared/secure-copy.js.map +1 -0
  290. package/lib/drivers/subprocess/index.d.ts +24 -0
  291. package/lib/drivers/subprocess/index.d.ts.map +1 -0
  292. package/lib/drivers/subprocess/index.js +451 -0
  293. package/lib/drivers/subprocess/index.js.map +1 -0
  294. package/lib/index.d.ts +40 -0
  295. package/lib/index.d.ts.map +1 -0
  296. package/lib/index.js +48 -0
  297. package/lib/index.js.map +1 -0
  298. package/lib/optimization/reflective.d.ts +27 -0
  299. package/lib/optimization/reflective.d.ts.map +1 -0
  300. package/lib/optimization/reflective.js +257 -0
  301. package/lib/optimization/reflective.js.map +1 -0
  302. package/lib/orchestrator/annotation-loader.d.ts +65 -0
  303. package/lib/orchestrator/annotation-loader.d.ts.map +1 -0
  304. package/lib/orchestrator/annotation-loader.js +73 -0
  305. package/lib/orchestrator/annotation-loader.js.map +1 -0
  306. package/lib/orchestrator/annotation-store.d.ts +3 -0
  307. package/lib/orchestrator/annotation-store.d.ts.map +1 -0
  308. package/lib/orchestrator/annotation-store.js +100 -0
  309. package/lib/orchestrator/annotation-store.js.map +1 -0
  310. package/lib/orchestrator/authored-dependencies.d.ts +3 -0
  311. package/lib/orchestrator/authored-dependencies.d.ts.map +1 -0
  312. package/lib/orchestrator/authored-dependencies.js +146 -0
  313. package/lib/orchestrator/authored-dependencies.js.map +1 -0
  314. package/lib/orchestrator/campaign-lifecycle.d.ts +105 -0
  315. package/lib/orchestrator/campaign-lifecycle.d.ts.map +1 -0
  316. package/lib/orchestrator/campaign-lifecycle.js +141 -0
  317. package/lib/orchestrator/campaign-lifecycle.js.map +1 -0
  318. package/lib/orchestrator/candidate-integrity.d.ts +4 -0
  319. package/lib/orchestrator/candidate-integrity.d.ts.map +1 -0
  320. package/lib/orchestrator/candidate-integrity.js +14 -0
  321. package/lib/orchestrator/candidate-integrity.js.map +1 -0
  322. package/lib/orchestrator/candidates.d.ts +13 -0
  323. package/lib/orchestrator/candidates.d.ts.map +1 -0
  324. package/lib/orchestrator/candidates.js +577 -0
  325. package/lib/orchestrator/candidates.js.map +1 -0
  326. package/lib/orchestrator/compare.d.ts +80 -0
  327. package/lib/orchestrator/compare.d.ts.map +1 -0
  328. package/lib/orchestrator/compare.js +270 -0
  329. package/lib/orchestrator/compare.js.map +1 -0
  330. package/lib/orchestrator/comparison-identity.d.ts +10 -0
  331. package/lib/orchestrator/comparison-identity.d.ts.map +1 -0
  332. package/lib/orchestrator/comparison-identity.js +39 -0
  333. package/lib/orchestrator/comparison-identity.js.map +1 -0
  334. package/lib/orchestrator/config.d.ts +121 -0
  335. package/lib/orchestrator/config.d.ts.map +1 -0
  336. package/lib/orchestrator/config.js +176 -0
  337. package/lib/orchestrator/config.js.map +1 -0
  338. package/lib/orchestrator/content-bound-json.d.ts +5 -0
  339. package/lib/orchestrator/content-bound-json.d.ts.map +1 -0
  340. package/lib/orchestrator/content-bound-json.js +59 -0
  341. package/lib/orchestrator/content-bound-json.js.map +1 -0
  342. package/lib/orchestrator/discover.d.ts +45 -0
  343. package/lib/orchestrator/discover.d.ts.map +1 -0
  344. package/lib/orchestrator/discover.js +98 -0
  345. package/lib/orchestrator/discover.js.map +1 -0
  346. package/lib/orchestrator/doctor.d.ts +141 -0
  347. package/lib/orchestrator/doctor.d.ts.map +1 -0
  348. package/lib/orchestrator/doctor.js +525 -0
  349. package/lib/orchestrator/doctor.js.map +1 -0
  350. package/lib/orchestrator/driver-session.d.ts +177 -0
  351. package/lib/orchestrator/driver-session.d.ts.map +1 -0
  352. package/lib/orchestrator/driver-session.js +396 -0
  353. package/lib/orchestrator/driver-session.js.map +1 -0
  354. package/lib/orchestrator/evaluator-identity.d.ts +7 -0
  355. package/lib/orchestrator/evaluator-identity.d.ts.map +1 -0
  356. package/lib/orchestrator/evaluator-identity.js +42 -0
  357. package/lib/orchestrator/evaluator-identity.js.map +1 -0
  358. package/lib/orchestrator/experiment-budget.d.ts +11 -0
  359. package/lib/orchestrator/experiment-budget.d.ts.map +1 -0
  360. package/lib/orchestrator/experiment-budget.js +51 -0
  361. package/lib/orchestrator/experiment-budget.js.map +1 -0
  362. package/lib/orchestrator/experiment-context.d.ts +43 -0
  363. package/lib/orchestrator/experiment-context.d.ts.map +1 -0
  364. package/lib/orchestrator/experiment-context.js +9 -0
  365. package/lib/orchestrator/experiment-context.js.map +1 -0
  366. package/lib/orchestrator/experiment-contracts.d.ts +290 -0
  367. package/lib/orchestrator/experiment-contracts.d.ts.map +1 -0
  368. package/lib/orchestrator/experiment-contracts.js +38 -0
  369. package/lib/orchestrator/experiment-contracts.js.map +1 -0
  370. package/lib/orchestrator/experiment-corpus.d.ts +21 -0
  371. package/lib/orchestrator/experiment-corpus.d.ts.map +1 -0
  372. package/lib/orchestrator/experiment-corpus.js +276 -0
  373. package/lib/orchestrator/experiment-corpus.js.map +1 -0
  374. package/lib/orchestrator/experiment-evaluation.d.ts +44 -0
  375. package/lib/orchestrator/experiment-evaluation.d.ts.map +1 -0
  376. package/lib/orchestrator/experiment-evaluation.js +542 -0
  377. package/lib/orchestrator/experiment-evaluation.js.map +1 -0
  378. package/lib/orchestrator/experiment-finish.d.ts +6 -0
  379. package/lib/orchestrator/experiment-finish.d.ts.map +1 -0
  380. package/lib/orchestrator/experiment-finish.js +19 -0
  381. package/lib/orchestrator/experiment-finish.js.map +1 -0
  382. package/lib/orchestrator/experiment-identity.d.ts +6 -0
  383. package/lib/orchestrator/experiment-identity.d.ts.map +1 -0
  384. package/lib/orchestrator/experiment-identity.js +257 -0
  385. package/lib/orchestrator/experiment-identity.js.map +1 -0
  386. package/lib/orchestrator/experiment-loader.d.ts +175 -0
  387. package/lib/orchestrator/experiment-loader.d.ts.map +1 -0
  388. package/lib/orchestrator/experiment-loader.js +77 -0
  389. package/lib/orchestrator/experiment-loader.js.map +1 -0
  390. package/lib/orchestrator/experiment-report.d.ts +450 -0
  391. package/lib/orchestrator/experiment-report.d.ts.map +1 -0
  392. package/lib/orchestrator/experiment-report.js +570 -0
  393. package/lib/orchestrator/experiment-report.js.map +1 -0
  394. package/lib/orchestrator/experiment-runs.d.ts +379 -0
  395. package/lib/orchestrator/experiment-runs.d.ts.map +1 -0
  396. package/lib/orchestrator/experiment-runs.js +796 -0
  397. package/lib/orchestrator/experiment-runs.js.map +1 -0
  398. package/lib/orchestrator/experiment-runtime-identity.d.ts +41 -0
  399. package/lib/orchestrator/experiment-runtime-identity.d.ts.map +1 -0
  400. package/lib/orchestrator/experiment-runtime-identity.js +411 -0
  401. package/lib/orchestrator/experiment-runtime-identity.js.map +1 -0
  402. package/lib/orchestrator/experiment-selection.d.ts +25 -0
  403. package/lib/orchestrator/experiment-selection.d.ts.map +1 -0
  404. package/lib/orchestrator/experiment-selection.js +286 -0
  405. package/lib/orchestrator/experiment-selection.js.map +1 -0
  406. package/lib/orchestrator/experiment.d.ts +11 -0
  407. package/lib/orchestrator/experiment.d.ts.map +1 -0
  408. package/lib/orchestrator/experiment.js +639 -0
  409. package/lib/orchestrator/experiment.js.map +1 -0
  410. package/lib/orchestrator/fixture-identity.d.ts +7 -0
  411. package/lib/orchestrator/fixture-identity.d.ts.map +1 -0
  412. package/lib/orchestrator/fixture-identity.js +55 -0
  413. package/lib/orchestrator/fixture-identity.js.map +1 -0
  414. package/lib/orchestrator/fs-read.d.ts +19 -0
  415. package/lib/orchestrator/fs-read.d.ts.map +1 -0
  416. package/lib/orchestrator/fs-read.js +113 -0
  417. package/lib/orchestrator/fs-read.js.map +1 -0
  418. package/lib/orchestrator/grader-experiment.d.ts +190 -0
  419. package/lib/orchestrator/grader-experiment.d.ts.map +1 -0
  420. package/lib/orchestrator/grader-experiment.js +579 -0
  421. package/lib/orchestrator/grader-experiment.js.map +1 -0
  422. package/lib/orchestrator/grading.d.ts +31 -0
  423. package/lib/orchestrator/grading.d.ts.map +1 -0
  424. package/lib/orchestrator/grading.js +186 -0
  425. package/lib/orchestrator/grading.js.map +1 -0
  426. package/lib/orchestrator/index.d.ts +22 -0
  427. package/lib/orchestrator/index.d.ts.map +1 -0
  428. package/lib/orchestrator/index.js +30 -0
  429. package/lib/orchestrator/index.js.map +1 -0
  430. package/lib/orchestrator/lifecycle-hook-execution.d.ts +4 -0
  431. package/lib/orchestrator/lifecycle-hook-execution.d.ts.map +1 -0
  432. package/lib/orchestrator/lifecycle-hook-execution.js +67 -0
  433. package/lib/orchestrator/lifecycle-hook-execution.js.map +1 -0
  434. package/lib/orchestrator/list-runs.d.ts +33 -0
  435. package/lib/orchestrator/list-runs.d.ts.map +1 -0
  436. package/lib/orchestrator/list-runs.js +308 -0
  437. package/lib/orchestrator/list-runs.js.map +1 -0
  438. package/lib/orchestrator/loader.d.ts +3 -0
  439. package/lib/orchestrator/loader.d.ts.map +1 -0
  440. package/lib/orchestrator/loader.js +17 -0
  441. package/lib/orchestrator/loader.js.map +1 -0
  442. package/lib/orchestrator/optimization-lifecycle.d.ts +12 -0
  443. package/lib/orchestrator/optimization-lifecycle.d.ts.map +1 -0
  444. package/lib/orchestrator/optimization-lifecycle.js +92 -0
  445. package/lib/orchestrator/optimization-lifecycle.js.map +1 -0
  446. package/lib/orchestrator/orchestrator.d.ts +144 -0
  447. package/lib/orchestrator/orchestrator.d.ts.map +1 -0
  448. package/lib/orchestrator/orchestrator.js +632 -0
  449. package/lib/orchestrator/orchestrator.js.map +1 -0
  450. package/lib/orchestrator/owned-lock.d.ts +17 -0
  451. package/lib/orchestrator/owned-lock.d.ts.map +1 -0
  452. package/lib/orchestrator/owned-lock.js +149 -0
  453. package/lib/orchestrator/owned-lock.js.map +1 -0
  454. package/lib/orchestrator/package-version.d.ts +2 -0
  455. package/lib/orchestrator/package-version.d.ts.map +1 -0
  456. package/lib/orchestrator/package-version.js +4 -0
  457. package/lib/orchestrator/package-version.js.map +1 -0
  458. package/lib/orchestrator/provenance.d.ts +5 -0
  459. package/lib/orchestrator/provenance.d.ts.map +1 -0
  460. package/lib/orchestrator/provenance.js +137 -0
  461. package/lib/orchestrator/provenance.js.map +1 -0
  462. package/lib/orchestrator/regrade.d.ts +80 -0
  463. package/lib/orchestrator/regrade.d.ts.map +1 -0
  464. package/lib/orchestrator/regrade.js +433 -0
  465. package/lib/orchestrator/regrade.js.map +1 -0
  466. package/lib/orchestrator/rubric-loader.d.ts +7 -0
  467. package/lib/orchestrator/rubric-loader.d.ts.map +1 -0
  468. package/lib/orchestrator/rubric-loader.js +65 -0
  469. package/lib/orchestrator/rubric-loader.js.map +1 -0
  470. package/lib/orchestrator/run-dir.d.ts +40 -0
  471. package/lib/orchestrator/run-dir.d.ts.map +1 -0
  472. package/lib/orchestrator/run-dir.js +161 -0
  473. package/lib/orchestrator/run-dir.js.map +1 -0
  474. package/lib/orchestrator/run-execution.d.ts +30 -0
  475. package/lib/orchestrator/run-execution.d.ts.map +1 -0
  476. package/lib/orchestrator/run-execution.js +531 -0
  477. package/lib/orchestrator/run-execution.js.map +1 -0
  478. package/lib/orchestrator/run-lifecycle.d.ts +115 -0
  479. package/lib/orchestrator/run-lifecycle.d.ts.map +1 -0
  480. package/lib/orchestrator/run-lifecycle.js +136 -0
  481. package/lib/orchestrator/run-lifecycle.js.map +1 -0
  482. package/lib/orchestrator/suite-compare.d.ts +76 -0
  483. package/lib/orchestrator/suite-compare.d.ts.map +1 -0
  484. package/lib/orchestrator/suite-compare.js +159 -0
  485. package/lib/orchestrator/suite-compare.js.map +1 -0
  486. package/lib/orchestrator/suite-lifecycle.d.ts +157 -0
  487. package/lib/orchestrator/suite-lifecycle.d.ts.map +1 -0
  488. package/lib/orchestrator/suite-lifecycle.js +253 -0
  489. package/lib/orchestrator/suite-lifecycle.js.map +1 -0
  490. package/lib/orchestrator/suite-runs.d.ts +91 -0
  491. package/lib/orchestrator/suite-runs.d.ts.map +1 -0
  492. package/lib/orchestrator/suite-runs.js +157 -0
  493. package/lib/orchestrator/suite-runs.js.map +1 -0
  494. package/lib/orchestrator/suite-summary.d.ts +109 -0
  495. package/lib/orchestrator/suite-summary.d.ts.map +1 -0
  496. package/lib/orchestrator/suite-summary.js +213 -0
  497. package/lib/orchestrator/suite-summary.js.map +1 -0
  498. package/lib/orchestrator/trace-limits.d.ts +20 -0
  499. package/lib/orchestrator/trace-limits.d.ts.map +1 -0
  500. package/lib/orchestrator/trace-limits.js +28 -0
  501. package/lib/orchestrator/trace-limits.js.map +1 -0
  502. package/lib/orchestrator/validate-plugin-config.d.ts +10 -0
  503. package/lib/orchestrator/validate-plugin-config.d.ts.map +1 -0
  504. package/lib/orchestrator/validate-plugin-config.js +26 -0
  505. package/lib/orchestrator/validate-plugin-config.js.map +1 -0
  506. package/package.json +84 -0
  507. package/skills/lux/SKILL.md +85 -0
  508. package/skills/lux/references/cli.md +102 -0
  509. package/skills/lux/references/eval-authoring.md +105 -0
  510. package/skills/lux-answerer/SKILL.md +169 -0
  511. package/src/answerers/claude-code/index.ts +342 -0
  512. package/src/answerers/persona/index.ts +327 -0
  513. package/src/answerers/scripted/index.ts +186 -0
  514. package/src/answerers/shared.ts +23 -0
  515. package/src/answerers/terminal/index.ts +117 -0
  516. package/src/assertions/core/command-exits-zero.ts +94 -0
  517. package/src/assertions/core/event-checks.ts +138 -0
  518. package/src/assertions/core/file-checks.ts +336 -0
  519. package/src/assertions/core/helpers.ts +203 -0
  520. package/src/assertions/core/index.ts +80 -0
  521. package/src/assertions/core/json-pointer-equals.ts +84 -0
  522. package/src/assertions/core/output-checks.ts +134 -0
  523. package/src/assertions/core/predicate.ts +67 -0
  524. package/src/assertions/core/resource-checks.ts +180 -0
  525. package/src/assertions/core/safe-regex.ts +196 -0
  526. package/src/assertions/core/tool-called-with.ts +68 -0
  527. package/src/assertions/core/tool-calls.ts +28 -0
  528. package/src/assertions/core/tool-invocation.ts +198 -0
  529. package/src/assertions/core/tool-result-checks.ts +211 -0
  530. package/src/assertions/mcp/discovery-checks.ts +139 -0
  531. package/src/assertions/mcp/index.ts +37 -0
  532. package/src/assertions/rubric/index.ts +258 -0
  533. package/src/assertions/rubric/internal.ts +367 -0
  534. package/src/authoring.ts +2 -0
  535. package/src/cli/bin.ts +14 -0
  536. package/src/cli/command-runtime.ts +34 -0
  537. package/src/cli/init.ts +410 -0
  538. package/src/cli/program.ts +992 -0
  539. package/src/cli/render/format.ts +69 -0
  540. package/src/cli/render/reporter.ts +643 -0
  541. package/src/cli/render/tty.ts +314 -0
  542. package/src/cli/run-options.ts +82 -0
  543. package/src/cli/skills.ts +129 -0
  544. package/src/core/annotation.ts +104 -0
  545. package/src/core/answerer.ts +75 -0
  546. package/src/core/artifact-evidence.ts +249 -0
  547. package/src/core/artifact-snapshot.ts +429 -0
  548. package/src/core/assertion.ts +156 -0
  549. package/src/core/case.ts +103 -0
  550. package/src/core/conversation-turn.ts +47 -0
  551. package/src/core/driver.ts +75 -0
  552. package/src/core/emitter.ts +38 -0
  553. package/src/core/events.ts +135 -0
  554. package/src/core/exec.ts +263 -0
  555. package/src/core/experiment.ts +467 -0
  556. package/src/core/glob.ts +31 -0
  557. package/src/core/hash.ts +237 -0
  558. package/src/core/index.ts +28 -0
  559. package/src/core/lifecycle-fixtures.ts +145 -0
  560. package/src/core/lifecycle-hooks.ts +101 -0
  561. package/src/core/mcp-events.ts +57 -0
  562. package/src/core/model-cli.ts +271 -0
  563. package/src/core/observer.ts +50 -0
  564. package/src/core/platform-process.ts +284 -0
  565. package/src/core/registry.ts +57 -0
  566. package/src/core/rubric.ts +52 -0
  567. package/src/core/run.ts +144 -0
  568. package/src/core/statistics.ts +194 -0
  569. package/src/core/subject.ts +50 -0
  570. package/src/core/tool-events.ts +292 -0
  571. package/src/core/usage.ts +123 -0
  572. package/src/core/wire.ts +135 -0
  573. package/src/core/zod.ts +20 -0
  574. package/src/drivers/claude-code/index.ts +866 -0
  575. package/src/drivers/claude-code/parse-events.ts +464 -0
  576. package/src/drivers/codex/app-events.ts +218 -0
  577. package/src/drivers/codex/config.ts +128 -0
  578. package/src/drivers/codex/index.ts +995 -0
  579. package/src/drivers/mcp/index.ts +351 -0
  580. package/src/drivers/mcp/transport.ts +222 -0
  581. package/src/drivers/shared/artifacts.ts +86 -0
  582. package/src/drivers/shared/secure-copy.ts +40 -0
  583. package/src/drivers/subprocess/index.ts +490 -0
  584. package/src/index.ts +594 -0
  585. package/src/optimization/reflective.ts +319 -0
  586. package/src/orchestrator/annotation-loader.ts +97 -0
  587. package/src/orchestrator/annotation-store.ts +112 -0
  588. package/src/orchestrator/authored-dependencies.ts +193 -0
  589. package/src/orchestrator/campaign-lifecycle.ts +181 -0
  590. package/src/orchestrator/candidate-integrity.ts +18 -0
  591. package/src/orchestrator/candidates.ts +683 -0
  592. package/src/orchestrator/compare.ts +358 -0
  593. package/src/orchestrator/comparison-identity.ts +45 -0
  594. package/src/orchestrator/config.ts +205 -0
  595. package/src/orchestrator/content-bound-json.ts +71 -0
  596. package/src/orchestrator/discover.ts +132 -0
  597. package/src/orchestrator/doctor.ts +781 -0
  598. package/src/orchestrator/driver-session.ts +507 -0
  599. package/src/orchestrator/evaluator-identity.ts +45 -0
  600. package/src/orchestrator/experiment-budget.ts +61 -0
  601. package/src/orchestrator/experiment-context.ts +41 -0
  602. package/src/orchestrator/experiment-contracts.ts +43 -0
  603. package/src/orchestrator/experiment-corpus.ts +416 -0
  604. package/src/orchestrator/experiment-evaluation.ts +749 -0
  605. package/src/orchestrator/experiment-finish.ts +33 -0
  606. package/src/orchestrator/experiment-identity.ts +356 -0
  607. package/src/orchestrator/experiment-loader.ts +105 -0
  608. package/src/orchestrator/experiment-report.ts +788 -0
  609. package/src/orchestrator/experiment-runs.ts +960 -0
  610. package/src/orchestrator/experiment-runtime-identity.ts +465 -0
  611. package/src/orchestrator/experiment-selection.ts +467 -0
  612. package/src/orchestrator/experiment.ts +991 -0
  613. package/src/orchestrator/fixture-identity.ts +67 -0
  614. package/src/orchestrator/fs-read.ts +126 -0
  615. package/src/orchestrator/grader-experiment.ts +856 -0
  616. package/src/orchestrator/grading.ts +260 -0
  617. package/src/orchestrator/index.ts +186 -0
  618. package/src/orchestrator/lifecycle-hook-execution.ts +90 -0
  619. package/src/orchestrator/list-runs.ts +384 -0
  620. package/src/orchestrator/loader.ts +19 -0
  621. package/src/orchestrator/optimization-lifecycle.ts +126 -0
  622. package/src/orchestrator/orchestrator.ts +919 -0
  623. package/src/orchestrator/owned-lock.ts +147 -0
  624. package/src/orchestrator/package-version.ts +5 -0
  625. package/src/orchestrator/provenance.ts +140 -0
  626. package/src/orchestrator/regrade.ts +580 -0
  627. package/src/orchestrator/rubric-loader.ts +74 -0
  628. package/src/orchestrator/run-dir.ts +209 -0
  629. package/src/orchestrator/run-execution.ts +694 -0
  630. package/src/orchestrator/run-lifecycle.ts +174 -0
  631. package/src/orchestrator/suite-compare.ts +195 -0
  632. package/src/orchestrator/suite-lifecycle.ts +335 -0
  633. package/src/orchestrator/suite-runs.ts +202 -0
  634. package/src/orchestrator/suite-summary.ts +276 -0
  635. package/src/orchestrator/trace-limits.ts +65 -0
  636. package/src/orchestrator/validate-plugin-config.ts +34 -0
@@ -0,0 +1,134 @@
1
+ import { z } from "zod";
2
+ import type { AssertionImpl, Run, RunEvent } from "../../core/index.js";
3
+ import { baseAssertionFields as baseFields } from "./helpers.js";
4
+ import { inspectSafeRegexes, testSafeRegex } from "./safe-regex.js";
5
+
6
+ const MAX_REGEX_PATTERN_CHARS = 2_000;
7
+ const MAX_REGEX_TEXT_CHARS = 1024 * 1024;
8
+
9
+ // Skip `responded` events: they carry the answerer's reply, not agent output,
10
+ // so sampling them would grade the persona's words instead of the agent's.
11
+ const agentMessageText = (e: RunEvent | undefined): string | undefined => {
12
+ if (e?.type === "progress" && e.kind === "agent-message") {
13
+ const payload = e.payload as { text?: unknown };
14
+ if (typeof payload?.text === "string") return payload.text;
15
+ }
16
+ return undefined;
17
+ };
18
+
19
+ const finalAssistantText = (events: RunEvent[]): string => {
20
+ for (let i = events.length - 1; i >= 0; i--) {
21
+ const text = agentMessageText(events[i]);
22
+ if (text !== undefined) return text;
23
+ }
24
+ return "";
25
+ };
26
+
27
+ const allAssistantText = (events: RunEvent[]): string => {
28
+ const parts: string[] = [];
29
+ for (const e of events) {
30
+ const text = agentMessageText(e);
31
+ if (text !== undefined) parts.push(text);
32
+ }
33
+ return parts.join("\n");
34
+ };
35
+
36
+ const TARGETS = ["transcript-final", "transcript-all"] as const;
37
+ const targetSchema = z.enum(TARGETS).default("transcript-final");
38
+
39
+ const sample = (run: Run, against: (typeof TARGETS)[number]): string =>
40
+ against === "transcript-all" ? allAssistantText(run.events) : finalAssistantText(run.events);
41
+
42
+ // Empty text vacuously passes contains (and vacuously fails not-contains);
43
+ // reject it at authoring time like the other no-op configs.
44
+ export const ContainsConfigSchema = z
45
+ .object({
46
+ type: z.literal("contains"),
47
+ text: z.string().min(1),
48
+ against: targetSchema,
49
+ ...baseFields,
50
+ })
51
+ .strict();
52
+ export type ContainsConfig = z.infer<typeof ContainsConfigSchema>;
53
+
54
+ export const containsAssertion: AssertionImpl<ContainsConfig> = {
55
+ type: "contains",
56
+ configSchema: ContainsConfigSchema,
57
+ evaluate: async (config, run) => {
58
+ const actual = sample(run, config.against);
59
+ const passed = actual.includes(config.text);
60
+ return {
61
+ passed,
62
+ score: passed ? 1 : 0,
63
+ comment: passed ? `contains '${config.text}'` : `does not contain '${config.text}'`,
64
+ };
65
+ },
66
+ };
67
+
68
+ export const NotContainsConfigSchema = z
69
+ .object({
70
+ type: z.literal("not-contains"),
71
+ text: z.string().min(1),
72
+ against: targetSchema,
73
+ ...baseFields,
74
+ })
75
+ .strict();
76
+ export type NotContainsConfig = z.infer<typeof NotContainsConfigSchema>;
77
+
78
+ export const notContainsAssertion: AssertionImpl<NotContainsConfig> = {
79
+ type: "not-contains",
80
+ configSchema: NotContainsConfigSchema,
81
+ evaluate: async (config, run) => {
82
+ const actual = sample(run, config.against);
83
+ const passed = !actual.includes(config.text);
84
+ return {
85
+ passed,
86
+ score: passed ? 1 : 0,
87
+ comment: passed
88
+ ? `does not contain '${config.text}'`
89
+ : `unexpectedly contains '${config.text}'`,
90
+ };
91
+ },
92
+ };
93
+
94
+ export const RegexConfigSchema = z
95
+ .object({
96
+ type: z.literal("regex"),
97
+ pattern: z.string().max(MAX_REGEX_PATTERN_CHARS),
98
+ flags: z.string().max(16).optional(),
99
+ against: targetSchema,
100
+ ...baseFields,
101
+ })
102
+ .strict()
103
+ .superRefine(async (config, ctx) => {
104
+ const [inspection] = await inspectSafeRegexes([config.pattern], config.flags ?? "");
105
+ if (inspection && "error" in inspection) {
106
+ ctx.addIssue({ code: "custom", path: ["pattern"], message: inspection.error });
107
+ }
108
+ });
109
+ export type RegexConfig = z.infer<typeof RegexConfigSchema>;
110
+
111
+ export const regexAssertion: AssertionImpl<RegexConfig> = {
112
+ type: "regex",
113
+ configSchema: RegexConfigSchema,
114
+ evaluate: async (config, run, ctx) => {
115
+ const actual = sample(run, config.against);
116
+ if (actual.length > MAX_REGEX_TEXT_CHARS) {
117
+ return {
118
+ passed: false,
119
+ score: 0,
120
+ comment: `transcript exceeds the ${MAX_REGEX_TEXT_CHARS}-character regex assertion limit`,
121
+ };
122
+ }
123
+ const passed = await testSafeRegex(config.pattern, config.flags ?? "", actual, {
124
+ abortSignal: ctx?.abortSignal,
125
+ });
126
+ return {
127
+ passed,
128
+ score: passed ? 1 : 0,
129
+ comment: passed
130
+ ? `matches /${config.pattern}/${config.flags ?? ""}`
131
+ : `does not match /${config.pattern}/${config.flags ?? ""}`,
132
+ };
133
+ },
134
+ };
@@ -0,0 +1,67 @@
1
+ import { z } from "zod";
2
+ import {
3
+ type AssertionImpl,
4
+ type AssertionResult,
5
+ AssertionResultSchema,
6
+ type Run,
7
+ } from "../../core/index.js";
8
+ import { baseAssertionFields } from "./helpers.js";
9
+
10
+ export type PredicateFn = (
11
+ run: Run,
12
+ ) => boolean | AssertionResult | Promise<boolean | AssertionResult>;
13
+
14
+ export const PredicateConfigSchema = z
15
+ .object({
16
+ type: z.literal("predicate"),
17
+ fn: z.custom<PredicateFn>((v) => typeof v === "function"),
18
+ ...baseAssertionFields,
19
+ })
20
+ .strict();
21
+ export type PredicateConfig = z.infer<typeof PredicateConfigSchema>;
22
+
23
+ const isAssertionResult = (v: unknown): v is AssertionResult =>
24
+ AssertionResultSchema.safeParse(v).success;
25
+
26
+ export const predicateAssertion: AssertionImpl<PredicateConfig> = {
27
+ type: "predicate",
28
+ configSchema: PredicateConfigSchema,
29
+ evaluate: async (config, run) => {
30
+ if (typeof config.fn !== "function") {
31
+ const errorMessage = "predicate.fn is not a function";
32
+ return {
33
+ passed: false,
34
+ score: 0,
35
+ comment: errorMessage,
36
+ errorMessage,
37
+ };
38
+ }
39
+ try {
40
+ const result = await config.fn(run);
41
+ if (isAssertionResult(result)) return result;
42
+ if (typeof result !== "boolean") {
43
+ const errorMessage =
44
+ "predicate returned an invalid result; expected boolean or AssertionResult";
45
+ return {
46
+ passed: false,
47
+ score: 0,
48
+ comment: errorMessage,
49
+ errorMessage,
50
+ };
51
+ }
52
+ return {
53
+ passed: result,
54
+ score: result ? 1 : 0,
55
+ comment: result ? "predicate returned true" : "predicate returned false",
56
+ };
57
+ } catch (err) {
58
+ const errorMessage = `predicate threw: ${err instanceof Error ? err.message : String(err)}`;
59
+ return {
60
+ passed: false,
61
+ score: 0,
62
+ comment: errorMessage,
63
+ errorMessage,
64
+ };
65
+ }
66
+ },
67
+ };
@@ -0,0 +1,180 @@
1
+ import { z } from "zod";
2
+ import { type AssertionImpl, inspectRunArtifact, isUsageEmpty } from "../../core/index.js";
3
+ import { baseAssertionFields as baseFields } from "./helpers.js";
4
+
5
+ const UnavailablePolicySchema = z.enum(["pass", "fail"]);
6
+
7
+ const unavailable = (resource: string, policy: z.infer<typeof UnavailablePolicySchema>) => ({
8
+ passed: policy === "pass",
9
+ score: policy === "pass" ? 1 : 0,
10
+ comment: `${resource} unavailable`,
11
+ detail: { unavailable: true },
12
+ });
13
+
14
+ export const LatencyUnderConfigSchema = z
15
+ .object({
16
+ type: z.literal("latency-under"),
17
+ maxMs: z.number().positive(),
18
+ ...baseFields,
19
+ })
20
+ .strict();
21
+ export type LatencyUnderConfig = z.infer<typeof LatencyUnderConfigSchema>;
22
+
23
+ export const latencyUnderAssertion: AssertionImpl<LatencyUnderConfig> = {
24
+ type: "latency-under",
25
+ configSchema: LatencyUnderConfigSchema,
26
+ evaluate: async (config, run) => {
27
+ const start = Date.parse(run.metadata.startedAt);
28
+ const end = Date.parse(run.metadata.endedAt);
29
+ if (Number.isNaN(start) || Number.isNaN(end)) {
30
+ return {
31
+ passed: false,
32
+ score: 0,
33
+ comment: "duration unavailable (missing timestamps)",
34
+ };
35
+ }
36
+ const ms = end - start;
37
+ const passed = ms <= config.maxMs;
38
+ return {
39
+ passed,
40
+ score: passed ? 1 : 0,
41
+ comment: `${ms}ms ${passed ? "<=" : ">"} ${config.maxMs}ms`,
42
+ detail: { durationMs: ms },
43
+ };
44
+ },
45
+ };
46
+
47
+ export const TokensUnderConfigSchema = z
48
+ .object({
49
+ type: z.literal("tokens-under"),
50
+ max: z.number().positive(),
51
+ /**
52
+ * `total` is uncached input + output, the historical meaning. Cache traffic
53
+ * is counted separately because it is billed differently and, on a warm
54
+ * session, dwarfs `input` by two orders of magnitude.
55
+ */
56
+ component: z.enum(["input", "output", "total", "cacheRead", "cacheCreation"]).default("total"),
57
+ /** Compatibility defaults to pass; optimization campaigns should require fail. */
58
+ onUnavailable: UnavailablePolicySchema.optional(),
59
+ ...baseFields,
60
+ })
61
+ .strict();
62
+ export type TokensUnderConfig = z.infer<typeof TokensUnderConfigSchema>;
63
+
64
+ // Grades the agent under test, never the harness: an eval must not fail
65
+ // because the persona answerer or the LLM judge got chatty.
66
+ export const tokensUnderAssertion: AssertionImpl<TokensUnderConfig> = {
67
+ type: "tokens-under",
68
+ configSchema: TokensUnderConfigSchema,
69
+ evaluate: async (config, run) => {
70
+ const agent = run.metadata.usage.agent;
71
+ // A driver that reports nothing arrives here as all-zeros. Treat that as
72
+ // "unknown", not as "the agent spent zero tokens" — no real agent spends
73
+ // zero.
74
+ if (isUsageEmpty(agent)) {
75
+ return unavailable("tokens (driver did not report)", config.onUnavailable ?? "pass");
76
+ }
77
+ const value =
78
+ config.component === "total" ? agent.input + agent.output : agent[config.component];
79
+ const passed = value <= config.max;
80
+ return {
81
+ passed,
82
+ score: passed ? 1 : 0,
83
+ comment: `${config.component} tokens=${value} ${passed ? "<=" : ">"} ${config.max}`,
84
+ detail: { tokens: value },
85
+ };
86
+ },
87
+ };
88
+
89
+ export const CostUnderConfigSchema = z
90
+ .object({
91
+ type: z.literal("cost-under"),
92
+ maxUsd: z.number().positive(),
93
+ onUnavailable: UnavailablePolicySchema.optional(),
94
+ ...baseFields,
95
+ })
96
+ .strict();
97
+ export type CostUnderConfig = z.infer<typeof CostUnderConfigSchema>;
98
+
99
+ export const costUnderAssertion: AssertionImpl<CostUnderConfig> = {
100
+ type: "cost-under",
101
+ configSchema: CostUnderConfigSchema,
102
+ evaluate: async (config, run) => {
103
+ const usd = run.metadata.cost?.usd;
104
+ if (usd === undefined) {
105
+ return unavailable("cost (driver did not report)", config.onUnavailable ?? "pass");
106
+ }
107
+ const passed = usd <= config.maxUsd;
108
+ return {
109
+ passed,
110
+ score: passed ? 1 : 0,
111
+ comment: `$${usd.toFixed(4)} ${passed ? "<=" : ">"} $${config.maxUsd.toFixed(4)}`,
112
+ detail: { usd },
113
+ };
114
+ },
115
+ };
116
+
117
+ export const ArtifactBytesUnderConfigSchema = z
118
+ .object({
119
+ type: z.literal("artifact-bytes-under"),
120
+ max: z.number().int().nonnegative(),
121
+ onUnavailable: UnavailablePolicySchema.optional(),
122
+ ...baseFields,
123
+ })
124
+ .strict();
125
+ export type ArtifactBytesUnderConfig = z.infer<typeof ArtifactBytesUnderConfigSchema>;
126
+
127
+ export const artifactBytesUnderAssertion: AssertionImpl<ArtifactBytesUnderConfig> = {
128
+ type: "artifact-bytes-under",
129
+ configSchema: ArtifactBytesUnderConfigSchema,
130
+ evaluate: async (config, run) => {
131
+ const sizes = await Promise.all(
132
+ run.artifacts.map(async (artifact) => {
133
+ if (artifact.size !== undefined) return artifact.size;
134
+ const inspected = await inspectRunArtifact(run, artifact.path);
135
+ return inspected.stats?.isFile() ? inspected.stats.size : null;
136
+ }),
137
+ );
138
+ if (sizes.some((size) => size === null)) {
139
+ return unavailable(
140
+ "artifact bytes (one or more files could not be measured)",
141
+ config.onUnavailable ?? "pass",
142
+ );
143
+ }
144
+ const bytes = sizes.reduce<number>((sum, size) => sum + (size ?? 0), 0);
145
+ const passed = bytes <= config.max;
146
+ return {
147
+ passed,
148
+ score: passed ? 1 : 0,
149
+ comment: `artifact bytes=${bytes} ${passed ? "<=" : ">"} ${config.max}`,
150
+ detail: { bytes, files: sizes.length },
151
+ };
152
+ },
153
+ };
154
+
155
+ // A crashed or truncated run can still satisfy structural checks (a
156
+ // `file-exists` staged by a fixture, say). This lets a case require the
157
+ // agent to have finished cleanly as a first-class, graded expectation —
158
+ // complementing the automatic `casePassed` downgrade the orchestrator does.
159
+ export const RunSucceededConfigSchema = z
160
+ .object({
161
+ type: z.literal("run-succeeded"),
162
+ ...baseFields,
163
+ })
164
+ .strict();
165
+ export type RunSucceededConfig = z.infer<typeof RunSucceededConfigSchema>;
166
+
167
+ export const runSucceededAssertion: AssertionImpl<RunSucceededConfig> = {
168
+ type: "run-succeeded",
169
+ configSchema: RunSucceededConfigSchema,
170
+ evaluate: async (_config, run) => {
171
+ const { exitReason } = run.metadata;
172
+ const passed = exitReason === "done";
173
+ return {
174
+ passed,
175
+ score: passed ? 1 : 0,
176
+ comment: passed ? "run completed cleanly" : `run ended with '${exitReason}'`,
177
+ detail: { exitReason },
178
+ };
179
+ },
180
+ };
@@ -0,0 +1,196 @@
1
+ import { Worker } from "node:worker_threads";
2
+
3
+ const REGEX_TIMEOUT_MS = 2_000;
4
+
5
+ // An eval worker keeps source tests and the compiled package on the same
6
+ // loader-independent path while still making pathological V8 regexes killable.
7
+ const REGEX_WORKER_SOURCE = `
8
+ const { parentPort, workerData } = require("node:worker_threads");
9
+
10
+ const evaluate = () => {
11
+ if (workerData.operation === "test") {
12
+ return new RegExp(workerData.pattern, workerData.flags).test(workerData.text);
13
+ }
14
+ if (workerData.operation === "set") {
15
+ return workerData.patterns.map(
16
+ (pattern) => new RegExp(pattern, workerData.flags).test(workerData.text),
17
+ );
18
+ }
19
+ if (workerData.operation === "inspect") {
20
+ return workerData.patterns.map((pattern) => {
21
+ try {
22
+ return { matchesEmpty: new RegExp(pattern, workerData.flags).test("") };
23
+ } catch (error) {
24
+ return {
25
+ error: error instanceof Error ? error.message : String(error),
26
+ };
27
+ }
28
+ });
29
+ }
30
+ if (workerData.operation === "groups") {
31
+ return workerData.groups.map(({ pattern, flags, texts }) => {
32
+ const expression = new RegExp(pattern, flags);
33
+ return texts.map((text) => {
34
+ expression.lastIndex = 0;
35
+ return expression.test(text);
36
+ });
37
+ });
38
+ }
39
+ const flags = workerData.flags.includes("g")
40
+ ? workerData.flags
41
+ : workerData.flags + "g";
42
+ const expression = new RegExp(workerData.pattern, flags);
43
+ let count = 0;
44
+ for (const _match of workerData.text.matchAll(expression)) {
45
+ count += 1;
46
+ if (count >= workerData.stopAfter) return { count, exact: false };
47
+ }
48
+ return { count, exact: true };
49
+ };
50
+
51
+ try {
52
+ parentPort.postMessage({ ok: true, value: evaluate() });
53
+ } catch (error) {
54
+ parentPort.postMessage({
55
+ ok: false,
56
+ errorName: error instanceof Error ? error.name : "Error",
57
+ error: error instanceof Error ? error.message : String(error),
58
+ });
59
+ }
60
+ `;
61
+
62
+ type RegexTask =
63
+ | {
64
+ operation: "test";
65
+ pattern: string;
66
+ flags: string;
67
+ text: string;
68
+ }
69
+ | {
70
+ operation: "set";
71
+ patterns: string[];
72
+ flags: string;
73
+ text: string;
74
+ }
75
+ | {
76
+ operation: "count";
77
+ pattern: string;
78
+ flags: string;
79
+ text: string;
80
+ stopAfter: number;
81
+ }
82
+ | {
83
+ operation: "inspect";
84
+ patterns: string[];
85
+ flags: string;
86
+ }
87
+ | {
88
+ operation: "groups";
89
+ groups: Array<{
90
+ pattern: string;
91
+ flags: string;
92
+ texts: string[];
93
+ }>;
94
+ };
95
+
96
+ type WorkerResponse<T> = { ok: true; value: T } | { ok: false; errorName: string; error: string };
97
+
98
+ export type RegexEvaluationOptions = {
99
+ abortSignal?: AbortSignal | undefined;
100
+ timeoutMs?: number;
101
+ };
102
+
103
+ export type SafeRegexInspection = { matchesEmpty: boolean } | { error: string };
104
+
105
+ export type SafeRegexGroup = {
106
+ pattern: string;
107
+ flags: string;
108
+ texts: string[];
109
+ };
110
+
111
+ const evaluateRegex = async <T>(
112
+ task: RegexTask,
113
+ options: RegexEvaluationOptions = {},
114
+ ): Promise<T> =>
115
+ await new Promise<T>((resolve, reject) => {
116
+ const worker = new Worker(REGEX_WORKER_SOURCE, {
117
+ eval: true,
118
+ workerData: task,
119
+ });
120
+ let settled = false;
121
+ const finish = (settle: () => void) => {
122
+ if (settled) return;
123
+ settled = true;
124
+ clearTimeout(timeout);
125
+ options.abortSignal?.removeEventListener("abort", abort);
126
+ settle();
127
+ void worker.terminate();
128
+ };
129
+ const abort = () =>
130
+ finish(() => reject(options.abortSignal?.reason ?? new Error("regex evaluation aborted")));
131
+ const timeout = setTimeout(
132
+ () =>
133
+ finish(() =>
134
+ reject(new Error(`regex evaluation exceeded ${options.timeoutMs ?? REGEX_TIMEOUT_MS}ms`)),
135
+ ),
136
+ options.timeoutMs ?? REGEX_TIMEOUT_MS,
137
+ );
138
+ worker.once("message", (response: WorkerResponse<T>) => {
139
+ finish(() => {
140
+ if (response.ok) resolve(response.value);
141
+ else {
142
+ const ErrorConstructor = response.errorName === "SyntaxError" ? SyntaxError : Error;
143
+ reject(new ErrorConstructor(`regex evaluation failed: ${response.error}`));
144
+ }
145
+ });
146
+ });
147
+ worker.once("error", (error) => finish(() => reject(error)));
148
+ worker.once("exit", (code) => {
149
+ if (code !== 0 && !settled) {
150
+ finish(() => reject(new Error(`regex worker exited with code ${code}`)));
151
+ }
152
+ });
153
+ if (options.abortSignal?.aborted) abort();
154
+ else options.abortSignal?.addEventListener("abort", abort, { once: true });
155
+ });
156
+
157
+ export const testSafeRegex = async (
158
+ pattern: string,
159
+ flags: string,
160
+ text: string,
161
+ options?: RegexEvaluationOptions,
162
+ ): Promise<boolean> =>
163
+ await evaluateRegex<boolean>({ operation: "test", pattern, flags, text }, options);
164
+
165
+ export const testSafeRegexSet = async (
166
+ patterns: string[],
167
+ flags: string,
168
+ text: string,
169
+ options?: RegexEvaluationOptions,
170
+ ): Promise<boolean[]> =>
171
+ await evaluateRegex<boolean[]>({ operation: "set", patterns, flags, text }, options);
172
+
173
+ export const inspectSafeRegexes = async (
174
+ patterns: string[],
175
+ flags: string,
176
+ options?: RegexEvaluationOptions,
177
+ ): Promise<SafeRegexInspection[]> =>
178
+ await evaluateRegex<SafeRegexInspection[]>({ operation: "inspect", patterns, flags }, options);
179
+
180
+ export const testSafeRegexGroups = async (
181
+ groups: SafeRegexGroup[],
182
+ options?: RegexEvaluationOptions,
183
+ ): Promise<boolean[][]> =>
184
+ await evaluateRegex<boolean[][]>({ operation: "groups", groups }, options);
185
+
186
+ export const countSafeRegex = async (
187
+ pattern: string,
188
+ flags: string,
189
+ text: string,
190
+ stopAfter: number,
191
+ options?: RegexEvaluationOptions,
192
+ ): Promise<{ count: number; exact: boolean }> =>
193
+ await evaluateRegex<{ count: number; exact: boolean }>(
194
+ { operation: "count", pattern, flags, text, stopAfter },
195
+ options,
196
+ );
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+ import type { AssertionImpl } from "../../core/index.js";
3
+ import { matchesAgentScope } from "./event-checks.js";
4
+ import { deepEquals, isToolCallEvent, resolvePointer, weightThresholdFields } from "./helpers.js";
5
+
6
+ export const ToolCalledWithConfigSchema = z
7
+ .object({
8
+ type: z.literal("tool-called-with"),
9
+ name: z.string(),
10
+ /** RFC 6901 JSON pointer into the tool's input. Defaults to "" (whole input). */
11
+ argsJsonPointer: z.string().default(""),
12
+ /** Structural (key-order-insensitive) equality against the value at the JSON pointer. */
13
+ argsValue: z.unknown().optional(),
14
+ /** Substring containment check (stringifies the value at the pointer). */
15
+ argsContains: z.string().optional(),
16
+ /** How many matching calls are required. Default 1. `minTimes: 0` would pass vacuously. */
17
+ minTimes: z.number().int().positive().optional(),
18
+ /** Whose calls count: "main" agent, "subagent", or "any". */
19
+ by: z.enum(["any", "main", "subagent"]).default("any"),
20
+ ...weightThresholdFields,
21
+ })
22
+ .strict()
23
+ .refine((c) => c.argsValue === undefined || c.argsContains === undefined, {
24
+ message: "set only one of argsValue or argsContains",
25
+ });
26
+ export type ToolCalledWithConfig = z.infer<typeof ToolCalledWithConfigSchema>;
27
+
28
+ const matches = (value: unknown, config: ToolCalledWithConfig): boolean => {
29
+ if (config.argsValue !== undefined) {
30
+ return deepEquals(value, config.argsValue);
31
+ }
32
+ if (config.argsContains !== undefined) {
33
+ // An unresolved pointer is a non-match, not an error — a later event may
34
+ // still genuinely match.
35
+ if (value === undefined) return false;
36
+ const stringified = typeof value === "string" ? value : JSON.stringify(value);
37
+ return stringified.includes(config.argsContains);
38
+ }
39
+ // Both unset — match any tool call with that name.
40
+ return true;
41
+ };
42
+
43
+ export const toolCalledWithAssertion: AssertionImpl<ToolCalledWithConfig> = {
44
+ type: "tool-called-with",
45
+ configSchema: ToolCalledWithConfigSchema,
46
+ evaluate: async (config, run) => {
47
+ const min = config.minTimes ?? 1;
48
+ let hits = 0;
49
+ for (const e of run.events) {
50
+ if (!isToolCallEvent(e)) continue;
51
+ if (!matchesAgentScope(e, config.by)) continue;
52
+ const payload = e.payload as { name?: unknown; input?: unknown };
53
+ if (payload?.name !== config.name) continue;
54
+ const argsRoot = payload.input ?? null;
55
+ const value = resolvePointer(argsRoot, config.argsJsonPointer);
56
+ if (matches(value, config)) hits++;
57
+ }
58
+ const passed = hits >= min;
59
+ const bound = passed ? `>= ${min}` : `need ${min}`;
60
+ const scope = (config.by ?? "any") === "any" ? "" : ` by ${config.by}`;
61
+ return {
62
+ passed,
63
+ score: passed ? 1 : 0,
64
+ comment: `tool '${config.name}' called ${hits}×${scope} with matching args (${bound})`,
65
+ detail: { hits },
66
+ };
67
+ },
68
+ };
@@ -0,0 +1,28 @@
1
+ import type { Run } from "../../core/index.js";
2
+ import { type AgentScope, matchesAgentScope } from "./event-checks.js";
3
+ import { isToolCallEvent } from "./helpers.js";
4
+
5
+ /**
6
+ * A tool call projected from a `tool-call` progress event's payload.
7
+ * `parentToolUseId` is set only when a spawned subagent made the call.
8
+ */
9
+ export type ToolCall = { name: string; input: unknown; parentToolUseId?: string };
10
+
11
+ /**
12
+ * Every tool call the run made, in order. Reach for it inside a `predicate`
13
+ * assertion to grade what the agent *did*, not what it said. Pass `by` to scope
14
+ * to the "main" agent or a "subagent" (default "any").
15
+ */
16
+ export const toolCalls = (run: Run, by: AgentScope = "any"): ToolCall[] =>
17
+ run.events
18
+ .filter(isToolCallEvent)
19
+ .filter((e) => matchesAgentScope(e, by))
20
+ .map((e) => e.payload as ToolCall)
21
+ .filter((p): p is ToolCall => typeof p?.name === "string");
22
+
23
+ /** Stringified inputs of every tool call, for substring checks in a predicate. */
24
+ export const toolCallInputs = (run: Run, by: AgentScope = "any"): string[] =>
25
+ toolCalls(run, by).map((c) => JSON.stringify(c.input ?? {}));
26
+
27
+ /** Tool calls made by a spawned subagent (the driver tags these with `parentToolUseId`). */
28
+ export const subagentToolCalls = (run: Run): ToolCall[] => toolCalls(run, "subagent");