agentv 5.0.0-next.1 → 5.2.0-next.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 (108) hide show
  1. package/README.md +239 -53
  2. package/dist/{agentv-provider-AYXH7WLW-NJRC6UQX.js → agentv-provider-AYXH7WLW-6YZKZ7PS.js} +2 -2
  3. package/dist/{artifact-writer-QD52FC56.js → artifact-writer-SN6UNL5G.js} +15 -8
  4. package/dist/{chunk-GZJMODLW.js → chunk-3S6A2RKR.js} +45880 -30542
  5. package/dist/chunk-3S6A2RKR.js.map +1 -0
  6. package/dist/{chunk-6Q56CEXV.js → chunk-3X357HS4.js} +7900 -8985
  7. package/dist/chunk-3X357HS4.js.map +1 -0
  8. package/dist/{chunk-6JVM4GJI.js → chunk-46K2OET3.js} +187 -80
  9. package/dist/chunk-46K2OET3.js.map +1 -0
  10. package/dist/{chunk-IJEZFZJR.js → chunk-7BGERE6L.js} +2 -2
  11. package/dist/chunk-7BGERE6L.js.map +1 -0
  12. package/dist/{chunk-UG4JHZYM.js → chunk-ALVZQUZP.js} +670 -1427
  13. package/dist/chunk-ALVZQUZP.js.map +1 -0
  14. package/dist/{chunk-RCIEHFQ2.js → chunk-PEUTJS7B.js} +3 -3
  15. package/dist/{chunk-5H446C7X.js → chunk-QMRVH5ZP.js} +2 -8
  16. package/dist/{chunk-IBI7A5RP.js → chunk-T4AD3H3Y.js} +3444 -2251
  17. package/dist/chunk-T4AD3H3Y.js.map +1 -0
  18. package/dist/cli.js +8 -9
  19. package/dist/cli.js.map +1 -1
  20. package/dist/dashboard/assets/{index-D5_8DE_B.js → index-DNgf3qJ2.js} +1 -1
  21. package/dist/dashboard/assets/index-D_bokML8.css +1 -0
  22. package/dist/dashboard/assets/index-r_jSJmlw.js +121 -0
  23. package/dist/dashboard/index.html +2 -2
  24. package/dist/{dist-KJ6PELQY.js → dist-DEPJOMCA.js} +74 -60
  25. package/dist/{docker-workspace-ZJ2ESVBI-6UDETQII.js → docker-workspace-NNK4Z6FR-QRTIG6TM.js} +3 -3
  26. package/dist/{exec-MYPAJJP7-C5HD5WG5.js → exec-4HFFRQ3B-AXDMJNLJ.js} +3 -3
  27. package/dist/index.js +8 -9
  28. package/dist/{interactive-2WMVAASS.js → interactive-36ZNMQB2.js} +13 -29
  29. package/dist/interactive-36ZNMQB2.js.map +1 -0
  30. package/dist/skills/agentv-bench/SKILL.md +38 -34
  31. package/dist/skills/agentv-bench/agents/analyzer.md +6 -6
  32. package/dist/skills/agentv-bench/agents/comparator.md +4 -5
  33. package/dist/skills/agentv-bench/agents/grader.md +4 -4
  34. package/dist/skills/agentv-bench/references/autoresearch.md +3 -3
  35. package/dist/skills/agentv-bench/references/description-optimization.md +2 -2
  36. package/dist/skills/agentv-bench/references/environment-adaptation.md +10 -10
  37. package/dist/skills/agentv-bench/references/eval-yaml-spec.md +51 -30
  38. package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +4 -4
  39. package/dist/skills/agentv-bench/references/subagent-pipeline.md +13 -12
  40. package/dist/skills/agentv-eval-migrations/SKILL.md +33 -0
  41. package/dist/skills/agentv-eval-migrations/references/breaking-changes.md +1012 -0
  42. package/dist/skills/agentv-eval-review/SKILL.md +6 -3
  43. package/dist/skills/agentv-eval-review/scripts/lint_eval.py +1 -1
  44. package/dist/skills/agentv-eval-writer/SKILL.md +380 -246
  45. package/dist/skills/agentv-eval-writer/references/{config-schema.json → config.schema.json} +6 -5
  46. package/dist/skills/agentv-eval-writer/references/custom-evaluators.md +23 -18
  47. package/dist/skills/agentv-eval-writer/references/eval.schema.json +9852 -0
  48. package/dist/skills/agentv-eval-writer/references/python-helpers.md +8 -8
  49. package/dist/skills/agentv-eval-writer/references/rubric-evaluator.md +21 -22
  50. package/dist/skills/agentv-trace-analyst/SKILL.md +4 -4
  51. package/dist/templates/.agentv/targets.yaml +41 -40
  52. package/dist/{ts-eval-loader-RE43OAGX-AMRCUKBZ.js → ts-eval-loader-OMG2JBHP-OP5RR7A3.js} +5 -4
  53. package/package.json +19 -4
  54. package/dist/chunk-6JVM4GJI.js.map +0 -1
  55. package/dist/chunk-6Q56CEXV.js.map +0 -1
  56. package/dist/chunk-76FOHROU.js +0 -96
  57. package/dist/chunk-76FOHROU.js.map +0 -1
  58. package/dist/chunk-GZJMODLW.js.map +0 -1
  59. package/dist/chunk-HSHTTN6C.js +0 -565
  60. package/dist/chunk-HSHTTN6C.js.map +0 -1
  61. package/dist/chunk-IBI7A5RP.js.map +0 -1
  62. package/dist/chunk-IJEZFZJR.js.map +0 -1
  63. package/dist/chunk-LRULMAAA.js +0 -1711
  64. package/dist/chunk-LRULMAAA.js.map +0 -1
  65. package/dist/chunk-R3CXYNTN.js +0 -1238
  66. package/dist/chunk-R3CXYNTN.js.map +0 -1
  67. package/dist/chunk-UG4JHZYM.js.map +0 -1
  68. package/dist/chunk-VQ2ZO7XJ.js +0 -2098
  69. package/dist/chunk-VQ2ZO7XJ.js.map +0 -1
  70. package/dist/chunk-XALGXSKB.js +0 -21
  71. package/dist/chunk-XALGXSKB.js.map +0 -1
  72. package/dist/dashboard/assets/index-BVMrdN8a.js +0 -119
  73. package/dist/dashboard/assets/index-DZWXfWsv.css +0 -1
  74. package/dist/esm-NNMQYIKT.js +0 -32
  75. package/dist/esm-R77SNOF5.js +0 -65
  76. package/dist/esm-RVQPUGWH.js +0 -1207
  77. package/dist/esm-RVQPUGWH.js.map +0 -1
  78. package/dist/esm-TTEMJEVV.js +0 -933
  79. package/dist/esm-TTEMJEVV.js.map +0 -1
  80. package/dist/esm-ZADQ4XQH-QUFGGZL4.js +0 -924
  81. package/dist/esm-ZADQ4XQH-QUFGGZL4.js.map +0 -1
  82. package/dist/exec-MYPAJJP7-C5HD5WG5.js.map +0 -1
  83. package/dist/getMachineId-bsd-HSK5LZMG.js +0 -41
  84. package/dist/getMachineId-bsd-HSK5LZMG.js.map +0 -1
  85. package/dist/getMachineId-darwin-4DP6CCJV.js +0 -41
  86. package/dist/getMachineId-darwin-4DP6CCJV.js.map +0 -1
  87. package/dist/getMachineId-linux-44LJ5UJB.js +0 -33
  88. package/dist/getMachineId-linux-44LJ5UJB.js.map +0 -1
  89. package/dist/getMachineId-unsupported-NVK6IATM.js +0 -24
  90. package/dist/getMachineId-unsupported-NVK6IATM.js.map +0 -1
  91. package/dist/getMachineId-win-YZ36S7VA.js +0 -43
  92. package/dist/getMachineId-win-YZ36S7VA.js.map +0 -1
  93. package/dist/interactive-2WMVAASS.js.map +0 -1
  94. package/dist/otlp-json-file-exporter-RY63S3IG-PZBQPVYY.js +0 -9
  95. package/dist/otlp-json-file-exporter-RY63S3IG-PZBQPVYY.js.map +0 -1
  96. package/dist/skills/agentv-eval-writer/references/eval-schema.json +0 -17295
  97. package/dist/skills/agentv-eval-writer/references/experiment-schema.json +0 -278
  98. package/dist/src-76ISS3LH.js +0 -1733
  99. package/dist/src-76ISS3LH.js.map +0 -1
  100. package/dist/ts-eval-loader-RE43OAGX-AMRCUKBZ.js.map +0 -1
  101. /package/dist/{agentv-provider-AYXH7WLW-NJRC6UQX.js.map → agentv-provider-AYXH7WLW-6YZKZ7PS.js.map} +0 -0
  102. /package/dist/{artifact-writer-QD52FC56.js.map → artifact-writer-SN6UNL5G.js.map} +0 -0
  103. /package/dist/{chunk-RCIEHFQ2.js.map → chunk-PEUTJS7B.js.map} +0 -0
  104. /package/dist/{chunk-5H446C7X.js.map → chunk-QMRVH5ZP.js.map} +0 -0
  105. /package/dist/{dist-KJ6PELQY.js.map → dist-DEPJOMCA.js.map} +0 -0
  106. /package/dist/{docker-workspace-ZJ2ESVBI-6UDETQII.js.map → docker-workspace-NNK4Z6FR-QRTIG6TM.js.map} +0 -0
  107. /package/dist/{esm-NNMQYIKT.js.map → exec-4HFFRQ3B-AXDMJNLJ.js.map} +0 -0
  108. /package/dist/{esm-R77SNOF5.js.map → ts-eval-loader-OMG2JBHP-OP5RR7A3.js.map} +0 -0
@@ -6,20 +6,20 @@ import {
6
6
  filterByCategory,
7
7
  findRepoRoot,
8
8
  getCategories,
9
+ resolveExistingRunPrimaryPath,
9
10
  runEvalCommand
10
- } from "./chunk-IBI7A5RP.js";
11
- import "./chunk-6JVM4GJI.js";
12
- import "./chunk-UG4JHZYM.js";
13
- import "./chunk-76FOHROU.js";
14
- import "./chunk-RCIEHFQ2.js";
11
+ } from "./chunk-T4AD3H3Y.js";
12
+ import "./chunk-46K2OET3.js";
13
+ import "./chunk-ALVZQUZP.js";
15
14
  import {
16
15
  getAgentvConfigDir,
17
16
  listTargetNames,
18
17
  readTargetDefinitions
19
- } from "./chunk-GZJMODLW.js";
20
- import "./chunk-IJEZFZJR.js";
18
+ } from "./chunk-3S6A2RKR.js";
19
+ import "./chunk-7BGERE6L.js";
20
+ import "./chunk-PEUTJS7B.js";
21
21
  import "./chunk-M7BUKBAF.js";
22
- import "./chunk-5H446C7X.js";
22
+ import "./chunk-QMRVH5ZP.js";
23
23
 
24
24
  // src/commands/eval/interactive.ts
25
25
  import { existsSync } from "node:fs";
@@ -70,7 +70,6 @@ ${ANSI_DIM}Resuming run at ${relativeDir}...${ANSI_RESET}
70
70
  evalPaths: lastConfig.evalPaths,
71
71
  target: lastConfig.target,
72
72
  workers: lastConfig.workers,
73
- dryRun: lastConfig.dryRun,
74
73
  cache: lastConfig.cache
75
74
  },
76
75
  { resumeOutputDir: lastConfig.outputDir }
@@ -85,7 +84,6 @@ ${ANSI_DIM}Rerunning last configuration...${ANSI_RESET}
85
84
  evalPaths: lastConfig.evalPaths,
86
85
  target: lastConfig.target,
87
86
  workers: lastConfig.workers,
88
- dryRun: lastConfig.dryRun,
89
87
  cache: lastConfig.cache
90
88
  });
91
89
  return;
@@ -103,8 +101,8 @@ ${ANSI_DIM}Rerunning last configuration...${ANSI_RESET}
103
101
  async function promptMainMenu(lastConfig) {
104
102
  const choices = [];
105
103
  if (lastConfig?.outputDir) {
106
- const indexPath = path2.join(lastConfig.outputDir, "index.jsonl");
107
- if (existsSync(indexPath)) {
104
+ const indexPath = resolveExistingRunPrimaryPath(lastConfig.outputDir);
105
+ if (indexPath && existsSync(indexPath)) {
108
106
  const dirLabel = path2.basename(lastConfig.outputDir);
109
107
  choices.push({
110
108
  name: "\u23EF Resume last run",
@@ -245,7 +243,7 @@ async function promptAdvancedOptions() {
245
243
  default: false
246
244
  });
247
245
  if (!customize) {
248
- return { workers: 3, dryRun: false, cache: false };
246
+ return { workers: 3, cache: false };
249
247
  }
250
248
  const workers = await number({
251
249
  message: "Number of parallel workers (1-50)",
@@ -253,15 +251,11 @@ async function promptAdvancedOptions() {
253
251
  min: 1,
254
252
  max: 50
255
253
  }) ?? 3;
256
- const dryRun = await confirm({
257
- message: "Enable dry-run mode (mock responses)?",
258
- default: false
259
- });
260
254
  const cache = await confirm({
261
255
  message: "Enable response cache?",
262
256
  default: false
263
257
  });
264
- return { workers, dryRun, cache };
258
+ return { workers, cache };
265
259
  }
266
260
  async function promptReviewAndConfirm(config, cwd) {
267
261
  const evalDisplay = config.evalPaths.map((p) => {
@@ -275,7 +269,6 @@ ${ANSI_BOLD}Review Configuration${ANSI_RESET}`);
275
269
  ${evalDisplay}`);
276
270
  console.log(`${ANSI_GREEN}Target:${ANSI_RESET} ${config.target}`);
277
271
  console.log(`${ANSI_GREEN}Workers:${ANSI_RESET} ${config.workers}`);
278
- console.log(`${ANSI_GREEN}Dry run:${ANSI_RESET} ${config.dryRun ? "yes" : "no"}`);
279
272
  console.log(`${ANSI_GREEN}Cache:${ANSI_RESET} ${config.cache ? "yes" : "no"}`);
280
273
  console.log(`${ANSI_DIM}${"\u2500".repeat(40)}${ANSI_RESET}`);
281
274
  return confirm({
@@ -288,12 +281,8 @@ async function executeConfig(config, opts) {
288
281
  const rawOptions = {
289
282
  target: config.target,
290
283
  workers: config.workers,
291
- dryRun: config.dryRun,
292
284
  cache: config.cache,
293
285
  ...opts?.resumeOutputDir ? { output: opts.resumeOutputDir, resume: true } : {},
294
- dryRunDelay: 0,
295
- dryRunDelayMin: 0,
296
- dryRunDelayMax: 0,
297
286
  agentTimeout: 120,
298
287
  maxRetries: 2,
299
288
  verbose: false,
@@ -312,7 +301,6 @@ async function executeConfig(config, opts) {
312
301
  evalPaths: config.evalPaths,
313
302
  target: config.target,
314
303
  workers: config.workers,
315
- dryRun: config.dryRun,
316
304
  cache: config.cache,
317
305
  outputDir: path2.dirname(result.outputPath)
318
306
  });
@@ -335,13 +323,9 @@ ${ANSI_DIM}Retrying execution errors...${ANSI_RESET}
335
323
  const rawOptions = {
336
324
  target: config.target,
337
325
  workers: config.workers,
338
- dryRun: config.dryRun,
339
326
  cache: config.cache,
340
327
  retryErrors: outputPath,
341
328
  out: outputPath,
342
- dryRunDelay: 0,
343
- dryRunDelayMin: 0,
344
- dryRunDelayMax: 0,
345
329
  agentTimeout: 120,
346
330
  maxRetries: 2,
347
331
  verbose: false,
@@ -360,4 +344,4 @@ ${ANSI_DIM}Retrying execution errors...${ANSI_RESET}
360
344
  export {
361
345
  launchInteractiveWizard
362
346
  };
363
- //# sourceMappingURL=interactive-2WMVAASS.js.map
347
+ //# sourceMappingURL=interactive-36ZNMQB2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/eval/interactive.ts","../src/commands/eval/last-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { listTargetNames, readTargetDefinitions } from '@agentv/core';\nimport { checkbox, confirm, number, search, select } from '@inquirer/prompts';\n\nimport { TARGET_FILE_CANDIDATES, fileExists } from '../../utils/targets.js';\nimport {\n type DiscoveredEvalFile,\n discoverEvalFiles,\n filterByCategory,\n getCategories,\n} from './discover.js';\nimport { type LastConfig, loadLastConfig, saveLastConfig } from './last-config.js';\nimport { resolveExistingRunPrimaryPath } from './result-layout.js';\nimport { runEvalCommand } from './run-eval.js';\nimport { findRepoRoot } from './shared.js';\n\nconst ANSI_BOLD = '\\x1b[1m';\nconst ANSI_DIM = '\\x1b[2m';\nconst ANSI_CYAN = '\\x1b[36m';\nconst ANSI_GREEN = '\\x1b[32m';\nconst ANSI_RESET = '\\x1b[0m';\n\nexport interface InteractiveConfig {\n readonly evalPaths: readonly string[];\n readonly target: string;\n readonly workers: number;\n readonly cache: boolean;\n}\n\n/**\n * Launch the interactive wizard when `agentv eval` is called with no arguments.\n */\nexport async function launchInteractiveWizard(): Promise<void> {\n const cwd = process.cwd();\n\n console.log(`\\n${ANSI_BOLD}${ANSI_CYAN}AgentV Interactive Mode${ANSI_RESET}\\n`);\n\n const lastConfig = await loadLastConfig();\n const action = await promptMainMenu(lastConfig);\n\n if (action === 'exit') {\n return;\n }\n\n if (action === 'resume' && lastConfig?.outputDir) {\n const relativeDir = path.relative(cwd, lastConfig.outputDir) || lastConfig.outputDir;\n console.log(`\\n${ANSI_DIM}Resuming run at ${relativeDir}...${ANSI_RESET}\\n`);\n await executeConfig(\n {\n evalPaths: lastConfig.evalPaths,\n target: lastConfig.target,\n workers: lastConfig.workers,\n cache: lastConfig.cache,\n },\n { resumeOutputDir: lastConfig.outputDir },\n );\n return;\n }\n\n if (action === 'rerun' && lastConfig) {\n console.log(`\\n${ANSI_DIM}Rerunning last configuration...${ANSI_RESET}\\n`);\n await executeConfig({\n evalPaths: lastConfig.evalPaths,\n target: lastConfig.target,\n workers: lastConfig.workers,\n cache: lastConfig.cache,\n });\n return;\n }\n\n // Run new evaluation flow\n const config = await promptNewEvaluation(cwd);\n if (!config) {\n return;\n }\n\n // Review & confirm\n const confirmed = await promptReviewAndConfirm(config, cwd);\n if (!confirmed) {\n return;\n }\n\n await executeConfig(config);\n}\n\nasync function promptMainMenu(\n lastConfig: LastConfig | undefined,\n): Promise<'new' | 'rerun' | 'resume' | 'exit'> {\n type MenuChoice = 'new' | 'rerun' | 'resume' | 'exit';\n const choices: Array<{ name: string; value: MenuChoice; description?: string }> = [];\n\n // Resume entry: only when the prior run has a known artifact dir with a manifest.\n if (lastConfig?.outputDir) {\n const indexPath = resolveExistingRunPrimaryPath(lastConfig.outputDir);\n if (indexPath && existsSync(indexPath)) {\n const dirLabel = path.basename(lastConfig.outputDir);\n choices.push({\n name: '⏯ Resume last run',\n value: 'resume',\n description: `${dirLabel} (target: ${lastConfig.target})`,\n });\n }\n }\n\n if (lastConfig) {\n const evalCount = lastConfig.evalPaths.length;\n choices.push({\n name: '🔄 Rerun last config',\n value: 'rerun',\n description: `${evalCount} eval file(s), target: ${lastConfig.target}`,\n });\n }\n\n choices.push({ name: '🚀 Run new evaluation', value: 'new' }, { name: '✕ Exit', value: 'exit' });\n\n return select<MenuChoice>({\n message: 'What would you like to do?',\n choices,\n });\n}\n\nasync function promptNewEvaluation(cwd: string): Promise<InteractiveConfig | undefined> {\n // Step 1: Discover eval files\n console.log(`\\n${ANSI_DIM}Scanning for eval files...${ANSI_RESET}`);\n const allFiles = await discoverEvalFiles(cwd);\n\n if (allFiles.length === 0) {\n console.log(\n '\\n⚠ No eval files found in the current directory.\\n' +\n ' Place .yaml or .jsonl eval files in your project, or use:\\n' +\n ' agentv eval <path-to-eval.yaml>\\n',\n );\n return undefined;\n }\n\n console.log(`${ANSI_DIM}Found ${allFiles.length} eval file(s)${ANSI_RESET}\\n`);\n\n // Step 2: Select eval files (optionally filter by category first)\n const selectedFiles = await promptEvalSelection(allFiles);\n if (selectedFiles.length === 0) {\n console.log('\\nNo eval files selected.');\n return undefined;\n }\n\n // Step 3: Select target\n const target = await promptTargetSelection(cwd, selectedFiles[0].path);\n\n // Step 4: Advanced options\n const advanced = await promptAdvancedOptions();\n\n return {\n evalPaths: selectedFiles.map((f) => f.path),\n target,\n ...advanced,\n };\n}\n\nasync function promptEvalSelection(\n allFiles: readonly DiscoveredEvalFile[],\n): Promise<DiscoveredEvalFile[]> {\n const categories = getCategories(allFiles);\n\n // If only one category or few files, skip category selection\n let filesToSelect: readonly DiscoveredEvalFile[];\n\n if (categories.length > 1) {\n const selectedCategory = await search<string>({\n message: 'Select a category (type to search)',\n source: async (term) => {\n const filtered = term\n ? categories.filter((c) => c.toLowerCase().includes(term.toLowerCase()))\n : categories;\n return [\n { name: '(all categories)', value: '__all__' },\n ...filtered.map((c) => {\n const count = filterByCategory(allFiles, c).length;\n return { name: `${c} (${count} file${count > 1 ? 's' : ''})`, value: c };\n }),\n ];\n },\n });\n\n filesToSelect =\n selectedCategory === '__all__' ? allFiles : filterByCategory(allFiles, selectedCategory);\n } else {\n filesToSelect = allFiles;\n }\n\n return checkbox<DiscoveredEvalFile>({\n message: 'Select eval files to run (space to toggle, enter to confirm)',\n choices: filesToSelect.map((f) => ({\n name: f.relativePath,\n value: f,\n checked: filesToSelect.length <= 5, // auto-select if few files\n })),\n required: true,\n });\n}\n\nasync function promptTargetSelection(cwd: string, firstEvalPath: string): Promise<string> {\n const repoRoot = await findRepoRoot(cwd);\n\n // Try to find targets.yaml — search near the eval file first, then cwd/repoRoot\n const targetsPath = await findTargetsFile(cwd, repoRoot, firstEvalPath);\n\n if (!targetsPath) {\n console.log(`${ANSI_DIM}No targets.yaml found. Using default target.${ANSI_RESET}`);\n return 'default';\n }\n\n const definitions = await readTargetDefinitions(targetsPath);\n const targetNames = listTargetNames(definitions);\n\n if (targetNames.length === 0) {\n return 'default';\n }\n\n if (targetNames.length === 1) {\n console.log(`${ANSI_DIM}Using target: ${targetNames[0]}${ANSI_RESET}`);\n return targetNames[0];\n }\n\n return search<string>({\n message: 'Select a target (type to search)',\n source: async (term) => {\n const filtered = term\n ? targetNames.filter((t) => t.toLowerCase().includes(term.toLowerCase()))\n : targetNames;\n return filtered.map((t) => {\n const def = definitions.find((d) => d.name === t);\n return {\n name: t,\n value: t,\n description: def ? `provider: ${def.provider}` : undefined,\n };\n });\n },\n });\n}\n\nasync function findTargetsFile(\n cwd: string,\n repoRoot: string,\n evalFilePath?: string,\n): Promise<string | undefined> {\n // Build directory chain: eval file dir → cwd → repoRoot (mirrors discoverTargetsFile)\n const dirsToSearch: string[] = [];\n\n if (evalFilePath) {\n const evalDir = path.dirname(evalFilePath);\n if (!dirsToSearch.includes(evalDir)) {\n dirsToSearch.push(evalDir);\n }\n }\n\n if (!dirsToSearch.includes(cwd)) {\n dirsToSearch.push(cwd);\n }\n\n if (repoRoot !== cwd && !dirsToSearch.includes(repoRoot)) {\n dirsToSearch.push(repoRoot);\n }\n\n for (const dir of dirsToSearch) {\n for (const candidate of TARGET_FILE_CANDIDATES) {\n const fullPath = `${dir}/${candidate}`;\n if (await fileExists(fullPath)) {\n return fullPath;\n }\n }\n }\n\n return undefined;\n}\n\nasync function promptAdvancedOptions(): Promise<{\n workers: number;\n cache: boolean;\n}> {\n const customize = await confirm({\n message: 'Configure advanced options?',\n default: false,\n });\n\n if (!customize) {\n return { workers: 3, cache: false };\n }\n\n const workers =\n (await number({\n message: 'Number of parallel workers (1-50)',\n default: 3,\n min: 1,\n max: 50,\n })) ?? 3;\n\n const cache = await confirm({\n message: 'Enable response cache?',\n default: false,\n });\n\n return { workers, cache };\n}\n\nasync function promptReviewAndConfirm(config: InteractiveConfig, cwd: string): Promise<boolean> {\n const evalDisplay = config.evalPaths\n .map((p) => {\n const rel = p.startsWith(cwd) ? p.slice(cwd.length + 1) : p;\n return ` ${rel}`;\n })\n .join('\\n');\n\n console.log(`\\n${ANSI_BOLD}Review Configuration${ANSI_RESET}`);\n console.log(`${ANSI_DIM}${'─'.repeat(40)}${ANSI_RESET}`);\n console.log(`${ANSI_GREEN}Eval files:${ANSI_RESET}\\n${evalDisplay}`);\n console.log(`${ANSI_GREEN}Target:${ANSI_RESET} ${config.target}`);\n console.log(`${ANSI_GREEN}Workers:${ANSI_RESET} ${config.workers}`);\n console.log(`${ANSI_GREEN}Cache:${ANSI_RESET} ${config.cache ? 'yes' : 'no'}`);\n console.log(`${ANSI_DIM}${'─'.repeat(40)}${ANSI_RESET}`);\n\n return confirm({\n message: 'Run evaluation with this configuration?',\n default: true,\n });\n}\n\nasync function executeConfig(\n config: InteractiveConfig,\n opts?: { resumeOutputDir?: string },\n): Promise<void> {\n const cwd = process.cwd();\n const rawOptions: Record<string, unknown> = {\n target: config.target,\n workers: config.workers,\n cache: config.cache,\n ...(opts?.resumeOutputDir ? { output: opts.resumeOutputDir, resume: true } : {}),\n agentTimeout: 120,\n maxRetries: 2,\n verbose: false,\n keepWorkspaces: false,\n cleanupWorkspaces: false,\n trace: false,\n };\n\n const result = await runEvalCommand({\n testFiles: [...config.evalPaths],\n rawOptions,\n });\n\n // Persist config with the resolved artifact dir so the wizard can offer\n // \"Resume last run\" on the next invocation. Done after a successful run so\n // the saved outputDir always points at a real run manifest.\n if (result) {\n await saveLastConfig({\n timestamp: new Date().toISOString(),\n cwd,\n evalPaths: config.evalPaths,\n target: config.target,\n workers: config.workers,\n cache: config.cache,\n outputDir: path.dirname(result.outputPath),\n });\n }\n\n // Prompt to retry errors when execution errors were detected in a TTY\n if (result && result.executionErrorCount > 0 && process.stdin.isTTY) {\n await promptRetryErrors(config, result.outputPath);\n }\n}\n\nasync function promptRetryErrors(config: InteractiveConfig, outputPath: string): Promise<void> {\n const shouldRetry = await confirm({\n message: `Retry ${ANSI_BOLD}execution errors${ANSI_RESET} from this run?`,\n default: true,\n });\n\n if (!shouldRetry) {\n return;\n }\n\n console.log(`\\n${ANSI_DIM}Retrying execution errors...${ANSI_RESET}\\n`);\n\n const rawOptions: Record<string, unknown> = {\n target: config.target,\n workers: config.workers,\n cache: config.cache,\n retryErrors: outputPath,\n out: outputPath,\n agentTimeout: 120,\n maxRetries: 2,\n verbose: false,\n keepWorkspaces: false,\n cleanupWorkspaces: false,\n trace: false,\n };\n\n const retryResult = await runEvalCommand({\n testFiles: [...config.evalPaths],\n rawOptions,\n });\n\n // Allow chained retries if there are still errors\n if (retryResult && retryResult.executionErrorCount > 0 && process.stdin.isTTY) {\n await promptRetryErrors(config, retryResult.outputPath);\n }\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { getAgentvConfigDir } from '@agentv/core';\n\nconst CONFIG_DIR = getAgentvConfigDir();\nconst LAST_CONFIG_PATH = path.join(CONFIG_DIR, 'last-config.json');\n\nexport interface LastConfig {\n readonly timestamp: string;\n readonly cwd: string;\n readonly evalPaths: readonly string[];\n readonly target: string;\n readonly workers: number;\n readonly cache: boolean;\n /**\n * Resolved artifact directory of the last completed wizard run. Used to\n * power the wizard's \"Resume last run\" entry. Optional for backward\n * compatibility with configs saved before this field existed.\n */\n readonly outputDir?: string;\n}\n\nexport async function loadLastConfig(): Promise<LastConfig | undefined> {\n try {\n const content = await readFile(LAST_CONFIG_PATH, 'utf-8');\n return JSON.parse(content) as LastConfig;\n } catch {\n return undefined;\n }\n}\n\nexport async function saveLastConfig(config: LastConfig): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n await writeFile(LAST_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8');\n}\n"],"mappings":"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","names":["path","path"]}
@@ -65,24 +65,28 @@ Before running or optimizing, understand what you're working with.
65
65
 
66
66
  AgentV supports two evaluation formats:
67
67
 
68
- **EVAL.yaml** (native, full features) — supports workspaces, code graders, multi-turn conversations, tool trajectory scoring, workspace file tracking, multi-provider targets. Use this for agent evaluation.
68
+ **EVAL.yaml** (native, full features) — supports environment recipes, script graders, multi-turn conversations, tool trajectory scoring, workspace file tracking, and multi-provider targets. Use this for agent evaluation.
69
69
 
70
70
  ```yaml
71
71
  # example.eval.yaml
72
+ prompts:
73
+ - "{{ task }}"
74
+
75
+ environment:
76
+ type: host
77
+ workdir: ./workspace-template
78
+ setup:
79
+ command: ["bash", "-lc", "bun install && bun run build"]
80
+ cwd: "."
81
+
72
82
  tests:
73
83
  - id: basic-code-review
74
- input: "Review this TypeScript file for bugs and suggest improvements"
75
- criteria: "Identifies the null pointer bug on line 12 and suggests a fix"
76
- assertions:
84
+ vars:
85
+ task: "Review this TypeScript file for bugs and suggest improvements"
86
+ assert:
77
87
  - type: contains
78
88
  value: "null"
79
89
  - Review identifies the null pointer bug and suggests a concrete fix
80
-
81
- workspace:
82
- template: ./workspace-template
83
- hooks:
84
- before_each:
85
- reset: fast
86
90
  ```
87
91
 
88
92
  Multi-skill evaluation is handled naturally via input messages — describe the task in the test input, and the agent uses whatever skills it needs.
@@ -113,9 +117,9 @@ Start with 2-3 realistic test cases — the kind of thing a real user would actu
113
117
 
114
118
  Good assertions are objectively verifiable and have descriptive names. Subjective quality ("the output is good") is better evaluated qualitatively — don't force assertions onto things that need human judgment.
115
119
 
116
- **Grader types** (cheapest to most expensive): `exact`, `contains`, `regex`, `is-json`, `field-accuracy`, `composite`, `code-grader`, `tool-trajectory`, `llm-grader`. See `references/eval-yaml-spec.md` for full config and grading recipes for each type.
120
+ **Grader types** (cheapest to most expensive): `exact`, `contains`, `regex`, `is-json`, `field-accuracy`, `assert-set`, `script`, `tool-trajectory`, `llm-rubric`. See `references/eval-yaml-spec.md` for full config and grading recipes for each type.
117
121
 
118
- Prefer deterministic graders over LLM graders whenever possible. If an assertion can be checked with `contains` or `regex`, don't use `llm-grader`.
122
+ Prefer deterministic graders over LLM graders whenever possible. If an assertion can be checked with `contains` or `regex`, don't use `llm-rubric`.
119
123
 
120
124
  ---
121
125
 
@@ -129,24 +133,24 @@ Each run produces a new `.agentv/results/default/<timestamp>/` directory automat
129
133
 
130
134
  **User instruction takes priority.** If the user says "run in subagent mode", "use subagent mode", or "use CLI mode", use that mode directly.
131
135
 
132
- If the user has not specified a mode, default to `subagent`.
136
+ If the user has not specified a mode, default to AgentV CLI mode.
133
137
 
134
- | `AGENT_EVAL_MODE` | Mode | How |
135
- |----------------------|------|-----|
136
- | `subagent` (default) | **Subagent mode** | Subagent-driven eval parses eval.yaml, spawns executor + grader subagents. Zero CLI dependency. |
137
- | `cli` | **AgentV CLI** | `agentv eval <path>` end-to-end, multi-provider |
138
+ | Mode | When to use | How |
139
+ |------|-------------|-----|
140
+ | **AgentV CLI** (default) | Normal eval runs, multi-provider benchmarking, CI, artifact generation, and Dashboard-compatible results. | `agentv eval <path>` |
141
+ | **Subagent mode** | Explicit user request, no usable CLI/runtime, or rare provider/request-cost constraints. | Read `references/subagent-pipeline.md` first. |
138
142
 
139
- Set `AGENT_EVAL_MODE` in `.env` at the project root as the default when no mode is specified. If absent, default to `subagent`. **User instruction always overrides this.**
143
+ Do not read `AGENT_EVAL_MODE` or another environment variable to decide the default mode. **User instruction always overrides the default.**
140
144
 
141
- **`subagent`** — Parses eval.yaml directly, spawns executor subagents to run each test case in the current workspace, then spawns grader subagents to evaluate all assertion types natively. No CLI or external API calls required. Read `references/subagent-pipeline.md` for the detailed procedure.
145
+ **Subagent mode** — Parses eval.yaml directly, spawns executor subagents to run each test case in the current workspace, then spawns grader subagents to evaluate assertion types natively. This is an opt-in fallback. Read `references/subagent-pipeline.md` for the detailed procedure before using it.
142
146
 
143
- **`cli`** — AgentV CLI handles execution, grading, and artifact generation end-to-end. Works with all providers. Use when you need multi-provider benchmarking or CLI-specific features.
147
+ **AgentV CLI mode** — AgentV CLI handles execution, grading, and artifact generation end-to-end. Works with all providers. Use this unless the user explicitly asks for subagent mode or the CLI path is unavailable.
144
148
 
145
149
  ### Running evaluations
146
150
 
147
- **AgentV CLI mode** (end-to-end, EVAL.yaml):
151
+ **AgentV CLI mode** (default, end-to-end, EVAL.yaml):
148
152
  ```bash
149
- agentv eval <eval-path> --output .agentv/artifacts/
153
+ agentv eval <eval-path>
150
154
  ```
151
155
 
152
156
  **Subagent mode** — read `references/subagent-pipeline.md` for the detailed procedure. In brief: use `pipeline input` to extract inputs, dispatch one `executor` subagent per test case (all in parallel), then proceed to grading below.
@@ -196,19 +200,19 @@ grading until all responses are present.
196
200
 
197
201
  **In subagent mode**, grading has three phases. **All three are required — do not stop after phase 1.**
198
202
 
199
- **Phase 1: Code graders** (deterministic, zero-cost)
203
+ **Phase 1: script graders** (deterministic, zero-cost)
200
204
 
201
205
  ```bash
202
206
  agentv pipeline grade <run-dir>
203
207
  ```
204
208
 
205
209
  This evaluates all deterministic assertions against `response.md` files. Two types are handled:
206
- - **`code-grader` scripts** — external scripts executed against the response (arbitrary logic, any language)
210
+ - **`script-grader` scripts** — external scripts executed against the response (arbitrary logic, any language)
207
211
  - **Built-in assertion types** — evaluated in-process: `contains`, `contains-any`, `contains-all`, `icontains`, `regex`, `equals`, `starts-with`, `ends-with`, `is-json`, and variants
208
212
 
209
- Both types are configured by `pipeline input` into `code_graders/<name>.json` and graded by `pipeline grade`. Results are written to `<test-id>/code_grader_results/<name>.json`. Alternatively, pass `--grader-type code` to `pipeline run` to run these inline.
213
+ Both types are configured by `pipeline input` into `script_graders/<name>.json` and graded by `pipeline grade`. Results are written to `<test-id>/script_grader_results/<name>.json`. Alternatively, pass `--grader-type code` to `pipeline run` to run these inline.
210
214
 
211
- **Do not dispatch LLM grader subagents for tests that only have `contains`, `regex`, or other built-in assertions** — `pipeline grade` handles them entirely, at zero cost. To detect which tests need Phase 2, check whether `<test-id>/llm_graders/` contains any `.json` config files — `pipeline input` only writes there for `llm-grader` assertions. Tests with an empty (or missing) `llm_graders/` directory are done after Phase 1.
215
+ **Do not dispatch LLM grader subagents for tests that only have `contains`, `regex`, or other built-in assertions** — `pipeline grade` handles them entirely, at zero cost. To detect which tests need Phase 2, check whether `<test-id>/llm_graders/` contains any `.json` config files — `pipeline input` only writes there for `llm-rubric` assertions. Tests with an empty (or missing) `llm_graders/` directory are done after Phase 1.
212
216
 
213
217
  **Phase 2: LLM grading** (semantic — do NOT skip this phase)
214
218
 
@@ -242,7 +246,7 @@ agentv pipeline bench <run-dir>
242
246
  agentv results validate <run-dir>
243
247
  ```
244
248
 
245
- `pipeline bench` reads LLM grader results from `llm_grader_results/<name>.json` per test automatically, merges with code-grader scores, computes weighted pass_rate, and writes `grading.json` + `index.jsonl` + `summary.json`.
249
+ `pipeline bench` reads LLM grader results from `llm_grader_results/<name>.json` per test automatically, merges with script-grader scores, computes weighted pass_rate, and writes `grading.json` + `index.jsonl` + `summary.json`.
246
250
 
247
251
  > **Diagnosing `pass_rate=0`:** If `pipeline bench` reports `pass_rate=0` across the board, do **not** assume the tests genuinely failed. First verify the grading pipeline ran correctly: check that `<test-id>/llm_grader_results/<name>.json` exists and is non-empty for each test. If these files are absent or empty, the grader subagents failed to produce output (most common cause: `agents/grader.md` was not embedded in the subagent prompts — see Phase 2). Treat `pass_rate=0` as a real signal only after confirming grader results exist.
248
252
 
@@ -255,11 +259,11 @@ All artifacts use established schemas — see `references/schemas.md` for the fu
255
259
 
256
260
  Write artifacts to `.agentv/artifacts/` or the iteration directory.
257
261
 
258
- ### Workspace features (EVAL.yaml only)
262
+ ### Environment features (EVAL.yaml only)
259
263
 
260
- - **Workspace isolation** — clone repos, run setup/teardown hooks (before_all, before_each, after_each, after_all)
261
- - **Materialization modes** — `pooled` (reuse slots), `temp` (fresh per run), `static` (existing dir)
262
- - **Multi-repo** — clone multiple repos with sparse checkout and shallow clone support
264
+ - **Environment recipes** — prepare host or Docker testbeds with `type`, `workdir`, and argv-only `setup.command`
265
+ - **Static local override** — use `--workspace-path` only when an existing local directory should be reused as-is
266
+ - **Multi-repo** — materialize repos from setup scripts when a task needs several checkouts
263
267
  - **File change tracking** — grade by diffing workspace files before/after agent execution
264
268
 
265
269
  ---
@@ -276,7 +280,7 @@ Read the JSONL results and look for:
276
280
  - **Always-fail tests** — task impossible, eval broken, or assertion misconfigured. Don't optimize against broken evals.
277
281
  - **Flaky tests** — non-deterministic results across runs. Investigate before treating failures as real.
278
282
  - **Systematic failures** — same failure pattern across multiple tests. This usually points to a missing instruction or wrong approach.
279
- - **Deterministic upgrade candidates** — `llm-grader` assertions that could be replaced with `contains`, `regex`, or `is-json` (cheaper, faster, more reliable).
283
+ - **Deterministic upgrade candidates** — `llm-rubric` assertions that could be replaced with `contains`, `regex`, or `is-json` (cheaper, faster, more reliable).
280
284
 
281
285
  ### Dispatch subagents
282
286
 
@@ -289,7 +293,7 @@ Read the JSONL results and look for:
289
293
  Use CLI tools for deeper investigation:
290
294
  ```bash
291
295
  agentv inspect <results-file> # Detailed execution trace inspection
292
- agentv compare <file-a> <file-b> # Structured diff between runs
296
+ agentv results compare <file-a> <file-b> # Structured diff between runs
293
297
  ```
294
298
 
295
299
  Look for: tool call patterns, error recovery behavior, conversation flow, wasted steps.
@@ -360,7 +364,7 @@ After improving:
360
364
 
361
365
  ### Automated keep/discard
362
366
 
363
- For autonomous iteration, use `agentv compare --json` to automatically decide whether to keep or discard each change based on wins/losses/ties. Read `references/autoresearch.md` for the full decision rules, logging format, and integration with the iteration loop.
367
+ For autonomous iteration, use `agentv results compare --json` to automatically decide whether to keep or discard each change based on wins/losses/ties. Read `references/autoresearch.md` for the full decision rules, logging format, and integration with the iteration loop.
364
368
 
365
369
  ---
366
370
 
@@ -28,7 +28,7 @@ If `eval-path` is provided, also read the EVAL.yaml to understand grader configu
28
28
 
29
29
  ### Step 2: Deterministic-Upgrade Analysis
30
30
 
31
- For each grader entry in `scores` where `type` is `"llm-grader"` or `"rubrics"`, inspect the `reasoning` and `assertions` fields for patterns that indicate a deterministic assertion would suffice:
31
+ For each grader entry in `scores` where `type` is `"llm-rubric"` or `"rubrics"`, inspect the `reasoning` and `assertions` fields for patterns that indicate a deterministic assertion would suffice:
32
32
 
33
33
  | Signal | Detection | Suggested Upgrade |
34
34
  |--------|-----------|-------------------|
@@ -48,7 +48,7 @@ For each grader entry in `scores` where `type` is `"llm-grader"` or `"rubrics"`,
48
48
 
49
49
  ### Step 3: Weak Assertion Detection
50
50
 
51
- Scan the EVAL.yaml `assertions` entries (if `eval-path` provided) and the `reasoning` fields in results for weak assertions:
51
+ Scan the EVAL.yaml `assert` entries (if `eval-path` provided) and the `reasoning` fields in results for weak assertions:
52
52
 
53
53
  | Weakness | Detection | Improvement |
54
54
  |----------|-----------|-------------|
@@ -56,7 +56,7 @@ Scan the EVAL.yaml `assertions` entries (if `eval-path` provided) and the `reaso
56
56
  | Tautological | Contains "is correct", "is good", "works properly", "is valid" without specifying what correct/good means | Define explicit pass/fail conditions |
57
57
  | Compound criteria | Single assertion checks multiple independent things (uses "and", "also", "additionally" joining distinct checks) | Split into separate assertions, one per concern |
58
58
  | Missing expected value | `type: equals` or `type: contains` without a `value` field | Add the expected value |
59
- | Overly broad LLM-grader | LLM-grader with no rubric items, just a single vague `prompt` string | Convert to `type: rubrics` with enumerated criteria, or use deterministic checks |
59
+ | Overly broad LLM-grader | LLM-grader with no rubric items, just a single vague `prompt` string | Convert to `type: llm-rubric` with enumerated criteria, or use deterministic checks |
60
60
 
61
61
  ### Step 4: Cost/Quality Signals
62
62
 
@@ -94,7 +94,7 @@ Produce a structured report in this exact format:
94
94
 
95
95
  | # | Test ID | Grader | Current Type | Evidence | Suggested Type | Suggested Config |
96
96
  |---|---------|-----------|-------------|----------|----------------|-----------------|
97
- | 1 | <test_id> | <grader name> | llm-grader | <brief evidence> | contains | `value: "exact string"` |
97
+ | 1 | <test_id> | <grader name> | llm-rubric | <brief evidence> | contains | `value: "exact string"` |
98
98
 
99
99
  ### Weak Assertions
100
100
 
@@ -122,8 +122,8 @@ If a section has no findings, include the header with "None found." underneath.
122
122
 
123
123
  - **Be specific:** Every suggestion must include the test case ID, grader name, evidence from the results, and a concrete replacement config.
124
124
  - **Be conservative:** Only suggest deterministic upgrades when the pattern is clear and consistent. Partial or ambiguous evidence should be noted but not acted on.
125
- - **Prioritize by impact:** Order suggestions by estimated cost savings (`llm-grader` → deterministic saves the most).
126
- - **Handle all grader types:** Process `code-grader`, `tool-trajectory`, `llm-grader`, `rubrics`, `composite`, and all deterministic types. Only LLM-based types are candidates for deterministic upgrades.
125
+ - **Prioritize by impact:** Order suggestions by estimated cost savings (`llm-rubric` → deterministic saves the most).
126
+ - **Handle all grader types:** Process `script`, `tool-trajectory`, `llm-rubric`, `rubrics`, `assert-set`, and all deterministic types. Only LLM-based types are candidates for deterministic upgrades.
127
127
  - **Multi-provider awareness:** When results span multiple targets, note if a suggestion applies to all targets or is target-specific.
128
128
  - **No false positives:** It is better to miss a suggestion than to recommend an incorrect upgrade. If unsure, add the finding to a "Needs Review" subsection with your reasoning.
129
129
 
@@ -24,8 +24,7 @@ You are the Blind Comparator for AgentV's evaluation workflow. Your job is to co
24
24
  You will receive:
25
25
  - `outputs`: Array of evaluation outputs to compare. Each contains:
26
26
  - `target_id`: The provider/configuration identifier (DO NOT read this during scoring)
27
- - `answer`: The candidate response text
28
- - `evaluator_results`: Array of grader scores and details (code-grader, tool-trajectory, llm-grader, deterministic)
27
+ - `evaluator_results`: Array of grader scores and details (script, tool-trajectory, llm-rubric, deterministic)
29
28
  - `workspace_changes`: File changes made during workspace evaluation (if applicable)
30
29
  - `tool_calls`: Tool invocations and results from multi-turn conversations (if applicable)
31
30
  - `conversation`: Full multi-turn conversation history (if applicable)
@@ -91,9 +90,9 @@ For each content criterion, define:
91
90
 
92
91
  **Grader-Specific Scoring** — when grader results are present:
93
92
 
94
- - **code-grader**: Factor in pass/fail results, test coverage, assertion hit rates
93
+ - **script-grader**: Factor in pass/fail results, test coverage, assertion hit rates
95
94
  - **tool-trajectory**: Factor in tool call accuracy, sequence correctness, unnecessary tool calls
96
- - **llm-grader**: Factor in existing LLM grader scores as a reference signal (not as ground truth)
95
+ - **llm-rubric**: Factor in existing LLM grader scores as a reference signal (not as ground truth)
97
96
  - **deterministic**: Factor in exact match / keyword hit rates
98
97
 
99
98
  ### Phase 3: Scoring
@@ -236,7 +235,7 @@ Also produce a human-readable markdown summary:
236
235
  - **Be evidence-based**: Every score must cite specific evidence from the output.
237
236
  - **Evaluate substance over style**: Correct, complete answers with rough formatting score higher than polished but incorrect answers.
238
237
  - **Handle missing data gracefully**: If an output lacks workspace changes or tool calls but others have them, score what is present — do not penalize for data the target wasn't expected to produce.
239
- - **Respect grader signals**: When code-grader or tool-trajectory results exist, they represent objective ground truth. Weight these heavily.
238
+ - **Respect grader signals**: When script-grader or tool-trajectory results exist, they represent objective ground truth. Weight these heavily.
240
239
 
241
240
  ## Edge Cases
242
241
 
@@ -3,7 +3,7 @@ name: grader
3
3
  description: >-
4
4
  Grade a candidate response for an AgentV evaluation test case. Evaluates all
5
5
  assertion types natively — deterministic checks via string operations, LLM grading
6
- via Claude's own reasoning, code-grader via Bash script execution. Zero CLI dependency.
6
+ via Claude's own reasoning, script-grader via Bash script execution. Zero CLI dependency.
7
7
  Dispatch this agent after a candidate completes a test case.
8
8
  model: inherit
9
9
  color: yellow
@@ -12,7 +12,7 @@ tools: ["Read", "Bash", "Glob", "Grep", "Write"]
12
12
 
13
13
  You are the grader for an AgentV evaluation test case. You have two jobs: **grade the outputs** and **critique the evals themselves**. A passing grade on a weak assertion is worse than useless — it creates false confidence. When you notice an assertion that's trivially satisfied, or an important outcome that no assertion checks, say so.
14
14
 
15
- **For deterministic assertions, write and run a script rather than eyeballing it.** Scripts are faster, more reliable, and can be reused. Use LLM reasoning only for assertions that genuinely require semantic understanding (`llm-grader`, `rubric`).
15
+ **For deterministic assertions, write and run a script rather than eyeballing it.** Scripts are faster, more reliable, and can be reused. Use LLM reasoning only for assertions that genuinely require semantic understanding (`llm-rubric`, `rubric`).
16
16
 
17
17
  **You will receive these parameters:**
18
18
  - `eval-path`: Path to the eval YAML file
@@ -63,7 +63,7 @@ For each assertion in the test's `assertions[]`, evaluate it natively based on i
63
63
 
64
64
  | Type | How to evaluate |
65
65
  |------|----------------|
66
- | `llm-grader` | Read the `prompt` field. Evaluate the response against those criteria. Score 0.0-1.0 with evidence. |
66
+ | `llm-rubric` | Read `value` for free-form criteria, `rubrics` for itemized criteria, or `prompt_content`/`prompt` for a custom grading prompt. Evaluate the response against those criteria. Score 0.0-1.0 with evidence. |
67
67
  | `rubric` / `rubrics` | Read rubric items/criteria. Score each item 0.0-1.0. Aggregate as weighted average. |
68
68
 
69
69
  For LLM-graded types: be rigorous and fair. Score based on substance, not exact wording. If a `criteria` field exists on the test case, use it as additional context for your evaluation. If `expected_output` exists, use it as a reference answer (not as the only correct answer).
@@ -72,7 +72,7 @@ For LLM-graded types: be rigorous and fair. Score based on substance, not exact
72
72
 
73
73
  | Type | How to evaluate |
74
74
  |------|----------------|
75
- | `code-grader` | Run: `bun <script-path>` or `python <script-path>`. Pass response via file. Parse stdout JSON: `{"score": N, "reason": "..."}` |
75
+ | `script-grader` | Run: `bun <script-path>` or `python <script-path>`. Pass response via file. Parse stdout JSON: `{"score": N, "reason": "..."}` |
76
76
 
77
77
  **Composite assertions** — evaluate sub-assertions, then aggregate per the configured mode (weighted_average, min, max, all_pass).
78
78
 
@@ -11,7 +11,7 @@ After each iteration, you can automatically decide whether to keep or discard th
11
11
  After re-running test cases, compare the new results against the previous iteration's baseline:
12
12
 
13
13
  ```bash
14
- agentv compare <baseline>.jsonl <candidate>.jsonl --json
14
+ agentv results compare <baseline>.jsonl <candidate>.jsonl --json
15
15
  ```
16
16
 
17
17
  Where `<baseline>.jsonl` is the `index.jsonl` from the previous best iteration and `<candidate>.jsonl` is the `index.jsonl` from the run you just completed.
@@ -75,7 +75,7 @@ The automated keep/discard replaces the manual compare-and-present cycle (steps
75
75
 
76
76
  1. Apply change to prompts/skills/config
77
77
  2. Re-run all test cases
78
- 3. Run `agentv compare baseline.jsonl candidate.jsonl --json`
78
+ 3. Run `agentv results compare baseline.jsonl candidate.jsonl --json`
79
79
  4. Apply keep/discard rules → promote or revert
80
80
  5. Log the decision
81
81
  6. If this is iteration 3, 6, or 9 → present progress to the user (human checkpoint)
@@ -244,7 +244,7 @@ The trajectory chart fetches `iterations.jsonl` directly via HTTP on each auto-r
244
244
 
245
245
  Apply the automated keep/discard rules from the section above:
246
246
 
247
- 1. Run `agentv compare <baseline>.jsonl <candidate>.jsonl --json` where `<baseline>` is the best iteration's `index.jsonl` (or the first run's `index.jsonl` for cycle 1) and `<candidate>` is this cycle's `index.jsonl`.
247
+ 1. Run `agentv results compare <baseline>.jsonl <candidate>.jsonl --json` where `<baseline>` is the best iteration's `index.jsonl` (or the first run's `index.jsonl` for cycle 1) and `<candidate>` is this cycle's `index.jsonl`.
248
248
  2. If `wins > losses` → **KEEP**.
249
249
  3. If `wins <= losses` → **DISCARD**.
250
250
  4. If `mean_delta == 0` and the artifact is simpler → **KEEP** (simpler is better at equal performance). Simplicity: for files, compare line count; for directories, compare total size via `du -sb`.
@@ -35,12 +35,12 @@ it's a natural utterance):
35
35
  tests:
36
36
  - id: should-trigger-casual-optimize
37
37
  input: "ok so I have this agent that keeps failing on the code review tasks, can you help me figure out why and fix it"
38
- assertions:
38
+ assert:
39
39
  - type: skill-trigger
40
40
  skill: agentv-bench
41
41
  - id: should-not-trigger-build-error
42
42
  input: "my TypeScript build is failing with type errors in src/auth.ts"
43
- assertions:
43
+ assert:
44
44
  - type: skill-trigger
45
45
  skill: agentv-bench
46
46
  should_trigger: false
@@ -29,28 +29,28 @@ to any platform with skill-discovery mechanisms. All listed providers support sk
29
29
  ## Unsupported Providers: Use a Code-Grader
30
30
 
31
31
  The built-in `skill-trigger` grader covers Claude, Copilot, Pi, Codex and VS Code out
32
- of the box. For providers with different tool-call formats, write a code-grader that inspects
32
+ of the box. For providers with different tool-call formats, write a script-grader that inspects
33
33
  the agent's transcript messages or tool call trace.
34
34
 
35
- A code-grader receives the full evaluation context including the final `output` string,
35
+ A script-grader receives the full evaluation context including the final `output` string,
36
36
  transcript `messages`, and structured `trace`. Inspect `messages` or `trace.events` for
37
37
  tool calls; reserve `output` for final-answer text checks.
38
38
 
39
39
  ```yaml
40
- # Example: code-grader for Codex skill-trigger detection
40
+ # Example: script-grader for Codex skill-trigger detection
41
41
  tests:
42
42
  - id: should-trigger-codex
43
43
  input: "Analyze this CSV file"
44
- assertions:
45
- - type: code-grader
44
+ assert:
45
+ - type: script
46
46
  command: [bun, run, ./judges/codex-skill-trigger.ts]
47
47
  ```
48
48
 
49
49
  ```typescript
50
50
  // judges/codex-skill-trigger.ts
51
- import { defineCodeGrader } from '@agentv/sdk';
51
+ import { defineScriptGrader } from '@agentv/sdk';
52
52
 
53
- export default defineCodeGrader(({ messages }) => {
53
+ export default defineScriptGrader(({ messages }) => {
54
54
  const skillName = 'csv-analyzer';
55
55
  const toolCalls = messages.flatMap((msg) => msg.toolCalls ?? []);
56
56
  const firstTool = toolCalls[0];
@@ -65,7 +65,7 @@ export default defineCodeGrader(({ messages }) => {
65
65
  if (cmd.includes(skillName)) {
66
66
  return {
67
67
  score: 1,
68
- assertions: [
68
+ assert: [
69
69
  { text: `Skill "${skillName}" triggered via command`, passed: true, evidence: cmd },
70
70
  ],
71
71
  };
@@ -78,14 +78,14 @@ export default defineCodeGrader(({ messages }) => {
78
78
  if (path.includes(skillName)) {
79
79
  return {
80
80
  score: 1,
81
- assertions: [{ text: 'Skill file accessed', passed: true, evidence: path }],
81
+ assert: [{ text: 'Skill file accessed', passed: true, evidence: path }],
82
82
  };
83
83
  }
84
84
  }
85
85
 
86
86
  return {
87
87
  score: 0,
88
- assertions: [
88
+ assert: [
89
89
  {
90
90
  text: `First tool was not a skill invocation for "${skillName}"`,
91
91
  passed: false,