Skip to content

Commit d89518e

Browse files
authored
Align repeat authoring with Promptfoo numeric repeat (#1724)
* fix(eval): require numeric repeat authoring * docs(eval): document numeric repeat authoring * chore(eval): sync numeric repeat schema
1 parent 753834e commit d89518e

33 files changed

Lines changed: 258 additions & 493 deletions

.agents/verification.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ Use live dogfood before marking PRs ready when they affect eval execution, exper
153153
- Prefer the smallest realistic eval: one or two cases, bounded timeouts, and `workers: 1` for heavyweight agent providers.
154154
- For artifact/result contract changes, prefer letting AgentV choose the canonical run directory and capture the printed `Artifact workspace written to:` and `Results written to:` paths for evidence. Do not precompute `--output` unless the test specifically needs a fixed path.
155155
- For native experiment changes, run through `agentv eval run ... --experiment <experiment.yaml|ts>` so resolution, setup, scripts, provider selection, run knobs, and artifact metadata are exercised together.
156-
- For repeat-run changes, use `evaluate_options.repeat.count >= 2` when validating repeated executions. Inspect `.internal/index.jsonl`, root `summary.json`, and the repeated case folder. Use `repeat` for authored configuration and `sample_index`/`retry_index` for produced executions. The repeated case folder should carry aggregate `summary.json`; sample-specific outputs, transcripts, grading, and metrics live under `sample-N/`. Each `sample-N/` folder should contain `result.json`, `grading.json`, `metrics.json`, `transcript.json`, `transcript-raw.jsonl`, and `outputs/answer.md` when answer output is available. `result.json` should point at `./grading.json`, `./metrics.json`, `./transcript.json`, and `./transcript-raw.jsonl` through the corresponding path fields.
156+
- For repeat-run changes, use `evaluate_options.repeat: 2` or higher when validating repeated executions. Inspect `.internal/index.jsonl`, root `summary.json`, and the repeated case folder. Use numeric `repeat` for authored configuration and `sample_index`/`retry_index` for produced executions. The repeated case folder should carry aggregate `summary.json`; sample-specific outputs, transcripts, grading, and metrics live under `sample-N/`. Each `sample-N/` folder should contain `result.json`, `grading.json`, `metrics.json`, `transcript.json`, `transcript-raw.jsonl`, and `outputs/answer.md` when answer output is available. `result.json` should point at `./grading.json`, `./metrics.json`, `./transcript.json`, and `./transcript-raw.jsonl` through the corresponding path fields.
157157
- For local OpenAI-compatible grading through the OAuth proxy, use `base_url: http://127.0.0.1:10531/v1`, but still route `api_key` and `model` through environment references such as `{{ env.LOCAL_OPENAI_PROXY_API_KEY }}` and `{{ env.LOCAL_OPENAI_PROXY_MODEL }}`. Literal secrets and literal model values are intentionally rejected by provider validation unless a resolver explicitly allows them.
158158
- For `codex`/Codex SDK live dogfood through the same local proxy, configure the agent provider with `id`, `label`, `runtime`, and `config`, and put backend settings such as `base_url`, `api_key`, `model`, and `api_format` under `config`. Configure the reusable grader in the same `providers` catalog, then select it with `defaults.grader` or assertion-level `provider`; do not put a grader selector on the system-under-test provider. A minimal run should use `bun apps/cli/src/cli.ts eval run <eval.yaml> --providers <providers.yaml> --provider <codex-label> --workers 1`.
159159
- If the local proxy returns `401 token_expired`, the blocker is stale Codex OAuth, not AgentV target configuration. Refresh from a trusted local terminal with `codex logout`, `codex login --device-auth`, then restart `openai-oauth` and rerun the same eval command.

CONCEPTS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,15 @@ env:
102102

103103
**Repeat run** — A configured request to execute the same eval case and target more than once in the same run bundle. Repeat runs measure stochastic reliability, verifier stability, and drift; they are not the default CI path.
104104

105-
**Attempt** — One concrete execution inside a repeat run. Attempts keep their own score, status, metrics, trace, transcript, logs, and artifacts so aggregate results never hide individual evidence.
105+
**Repeat sample** — One concrete execution inside a repeat run. Samples keep their own score, status, metrics, trace, transcript, logs, and artifacts so aggregate results never hide individual evidence.
106106

107-
**Pass rate** — Assertion or expectation pass rate inside a grading result: passed assertions or expectations divided by total assertions or expectations. AgentV does not use `pass_rate` for repeat-attempt success frequency.
107+
**Pass rate** — Assertion or expectation pass rate inside a grading result: passed assertions or expectations divided by total assertions or expectations. AgentV does not use `pass_rate` for repeat-sample success frequency.
108108

109-
**Attempt success rate** — Repeat-run reliability metric equal to successful counted attempts divided by counted attempts. This is distinct from `pass_rate`, which is reserved for assertion or expectation pass rate within a grading result.
109+
**Sample success rate** — Repeat-run reliability metric equal to successful counted samples divided by counted samples. This is distinct from `pass_rate`, which is reserved for assertion or expectation pass rate within a grading result.
110110

111-
**Gate policy** — The explicit rule that decides whether repeated attempts pass CI, such as `all_attempts_successful`, `any_attempt_successful`, `attempt_success_rate_at_least`, or `mean_pass_rate_at_least`. Without a repeat-run gate policy, AgentV preserves the normal single-run gate behavior and treats repeat statistics as report data.
111+
**Aggregate gate policy** — Future fatal post-run policy surface for deciding whether repeated samples pass CI. Until AgentV deliberately designs that surface, repeat configuration only sets the numeric sample count and users can parse run bundles externally for aggregate gating.
112112

113-
**Flaky eval outcome** — A repeat-run aggregate whose attempts disagree, or whose failure classification points at verifier, infrastructure, or timeout instability rather than a stable model-quality failure.
113+
**Flaky eval outcome** — A repeat-run aggregate whose samples disagree, or whose failure classification points at verifier, infrastructure, or timeout instability rather than a stable model-quality failure.
114114

115115
## Release Channels
116116

README.md

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Test AI providers on real repo tasks and measure what actually works.
1919
- **Environment / fixtures / graders** are task-owned context: host or Docker setup, repos, setup scripts, files, fixtures, deterministic checks, and LLM grading prompts.
2020
- **Provider** is the configured system under test: an agent, model provider, gateway, replay provider, CLI wrapper, transcript provider, or future app/service wrapper. Each provider entry uses `id` for the backend/spec and optional `label` for the stable AgentV selection and result identity.
2121
- **Tags** are run/result grouping labels. `tags.experiment` is the default experiment namespace, such as `with-skills` or `without-skills`; keep suite/category and provider/model names out of that tag.
22-
- **Evaluate options** configure eval run behavior such as `max_concurrency`, repeat policy, and budgets.
22+
- **Evaluate options** configure eval run behavior such as `max_concurrency`, repeat sample count, and budgets.
2323
- **Default test** configures inherited per-test defaults such as score `threshold`.
2424
- **Run** is one concrete execution of a tagged eval against a resolved provider that writes portable artifacts for readers such as Dashboard, compare, and trend.
2525

@@ -133,9 +133,7 @@ providers:
133133
api_key: "{{ env.LOCAL_OPENAI_PROXY_API_KEY }}"
134134
model: gpt-5.4-mini
135135
evaluate_options:
136-
repeat:
137-
count: 2
138-
strategy: pass_any
136+
repeat: 2
139137
140138
default_test:
141139
threshold: 0.85
@@ -253,11 +251,7 @@ const config: EvalConfig = {
253251
extends: 'copilot-sdk',
254252
model: 'claude-sonnet-4.6',
255253
},
256-
repeat: {
257-
count: 3,
258-
strategy: 'pass_any',
259-
earlyExit: false,
260-
},
254+
repeat: 3,
261255
threshold: 0.8,
262256
prompts: ['{{ input }}'],
263257
environment: {

apps/cli/src/commands/eval/run-eval.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,10 +1049,6 @@ function buildExperimentTrialsConfig(experiment: ExperimentConfig): TrialsConfig
10491049
return {
10501050
count: experiment.repeat.count,
10511051
strategy: experiment.repeat.strategy,
1052-
...(experiment.repeat.costLimitUsd !== undefined && {
1053-
costLimitUsd: experiment.repeat.costLimitUsd,
1054-
}),
1055-
...(experiment.repeat.earlyExit !== undefined && { earlyExit: experiment.repeat.earlyExit }),
10561052
};
10571053
}
10581054
return undefined;
@@ -1074,8 +1070,6 @@ function buildRunOverrideTrialsConfig(run: EvalRunOverride | undefined): TrialsC
10741070
return {
10751071
count: repeat.count,
10761072
strategy: repeat.strategy,
1077-
...(repeat.costLimitUsd !== undefined && { costLimitUsd: repeat.costLimitUsd }),
1078-
...(repeat.earlyExit !== undefined && { earlyExit: repeat.earlyExit }),
10791073
};
10801074
}
10811075

apps/cli/test/eval.integration.test.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -725,10 +725,7 @@ describe('agentv eval CLI', () => {
725725
'threshold: 0.8',
726726
'evaluate_options:',
727727
' budget_usd: 3',
728-
' repeat:',
729-
' count: 2',
730-
' strategy: pass_any',
731-
' early_exit: true',
728+
' repeat: 2',
732729
'tests:',
733730
' - include: sample.test.yaml',
734731
' type: suite',
@@ -737,10 +734,7 @@ describe('agentv eval CLI', () => {
737734
' threshold: 1.0',
738735
' timeout_seconds: 5',
739736
' budget_usd: 0.75',
740-
' repeat:',
741-
' count: 3',
742-
' strategy: pass_all',
743-
' early_exit: true',
737+
' repeat: 3',
744738
'',
745739
].join('\n'),
746740
'utf8',
@@ -765,8 +759,7 @@ describe('agentv eval CLI', () => {
765759
threshold: 1,
766760
trials: {
767761
count: 3,
768-
strategy: 'pass_all',
769-
earlyExit: true,
762+
strategy: 'pass_any',
770763
},
771764
});
772765

apps/cli/test/fixtures/mock-run-evaluation.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ interface RunEvaluationOptionsLike {
2424
readonly trials?: {
2525
readonly count: number;
2626
readonly strategy: string;
27-
readonly costLimitUsd?: number;
28-
readonly earlyExit?: boolean;
2927
};
3028
readonly threshold?: number;
3129
readonly budgetUsd?: number;

apps/web/src/content/docs/docs/next/evaluation/eval-files.mdx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,7 @@ providers:
119119
- codex-gpt5
120120
evaluate_options:
121121
max_concurrency: 3
122-
repeat:
123-
count: 2
124-
strategy: pass_any
122+
repeat: 2
125123

126124
tests:
127125
- file://../evals/cases/refund-smoke.cases.yaml
@@ -179,7 +177,7 @@ tests:
179177
| `tags` | Optional metadata map. Use `tags.experiment` as the run/result grouping label. |
180178
| `prompts` | Optional top-level prompt matrix. Entries can be strings, chat message arrays, files, or generated prompt functions rendered with `tests[].vars` and `default_test.vars`. |
181179
| `providers` | System-under-test matrix. Entries can be Promptfoo-shaped provider strings, complete package provider strings such as `package:@agentv/promptfoo-providers:CodexCliProvider` or `package:@agentv/promptfoo-providers/codex-cli:Provider`, provider option objects, or provider maps; `id` names the backend/spec and `label` is the stable AgentV identity. |
182-
| `evaluate_options.repeat` | Optional repeat policy as a positive integer shorthand or object with `count`, `strategy`, `early_exit`, and `cost_limit_usd` |
180+
| `evaluate_options.repeat` | Optional positive integer sample count for repeat runs |
183181
| `evaluate_options` | Optional evaluation runtime options such as `budget_usd`, `repeat`, and `max_concurrency` |
184182
| `timeout_seconds` | Optional per-case timeout |
185183
| `threshold` | Optional suite quality threshold |

apps/web/src/content/docs/docs/next/evaluation/experiments.mdx

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ providers:
2727
reasoning_effort: high
2828
timeout_seconds: 720
2929
evaluate_options:
30-
repeat:
31-
count: 4
32-
strategy: pass_any
30+
repeat: 4
3331
budget_usd: 2.00
3432
max_concurrency: 3
3533

@@ -120,9 +118,7 @@ providers:
120118
- agent
121119
threshold: 0.8
122120
evaluate_options:
123-
repeat:
124-
count: 3
125-
strategy: pass_any
121+
repeat: 3
126122
timeout_seconds: 300
127123
tags:
128124
area: agentic
@@ -161,7 +157,7 @@ target-specific runner state.
161157
| Configure an agent runner or provider variant | `providers` entry or `providers.yaml` |
162158
| Choose the provider | top-level `providers` or CLI `--provider` |
163159
| Override the provider's default model | `providers[].config.model` |
164-
| Configure repeat policy, budget, concurrency, timeout, threshold | `evaluate_options.repeat`, `evaluate_options.budget_usd`, `evaluate_options.max_concurrency`, `timeout_seconds`, `threshold` |
160+
| Configure repeat sample count, budget, concurrency, timeout, threshold | `evaluate_options.repeat`, `evaluate_options.budget_usd`, `evaluate_options.max_concurrency`, `timeout_seconds`, `threshold` |
165161
| Bind an existing local workspace directory | `--workspace-path` or `.agentv/config.local.yaml` |
166162

167163
```yaml
@@ -176,9 +172,7 @@ providers:
176172
before_each:
177173
command: ["sh", "-c", "cp -R skills \"{{workspace_path}}/.codex/skills\""]
178174
evaluate_options:
179-
repeat:
180-
count: 3
181-
strategy: pass_any
175+
repeat: 3
182176
```
183177

184178
Existing local workspace paths are machine-local bindings: pass
@@ -197,25 +191,10 @@ evaluate_options:
197191
repeat: 3
198192
```
199193

200-
Use object form when you need richer AgentV behavior:
201-
202-
```yaml
203-
evaluate_options:
204-
repeat:
205-
count: 3
206-
strategy: pass_any
207-
early_exit: true
208-
cost_limit_usd: 1.00
209-
```
210-
211-
`evaluate_options.repeat.strategy` controls sample aggregation. `pass_any`
212-
treats the case as successful when any completed sample passes; `pass_all`
213-
requires every completed sample to pass. `mean` and `confidence_interval`
214-
aggregate scores where supported today. `evaluate_options.repeat.early_exit` is
215-
only a scheduling and cost optimization: `pass_any` may stop at the first pass,
216-
and `pass_all` may stop at the first fail. Leave it unset or `false` when you
217-
want complete variance data. Per-case `tests[].options.repeat` overrides the
218-
global repeat count or object for that case.
194+
Repeat authoring only sets the sample count. A fatal post-run aggregate policy
195+
surface is future work; until that exists, parse the run bundle externally when
196+
CI needs aggregate gating across samples. Per-case `tests[].options.repeat`
197+
overrides the global repeat count for that case.
219198

220199
## Result Layout
221200

apps/web/src/content/docs/docs/v4.42.4/evaluation/eval-files.mdx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ controls for an evaluation run. The reserved `tags.experiment` key is the
1313
run/result grouping label, top-level `target` identifies the system under test,
1414
and fields such as `evaluate_options.repeat`, `threshold`, `timeout_seconds`,
1515
`evaluate_options.budget_usd`, and `evaluate_options.max_concurrency` control repeated
16-
attempts and gates. Coding-agent testbeds, workdirs, Docker config, repository
16+
samples and gates. Coding-agent testbeds, workdirs, Docker config, repository
1717
materialization, setup, and reset policy belong in `environment`. Provider
1818
environment-variable overrides belong in top-level `env`. Lifecycle hooks belong
1919
in `extensions`; runner-specific setup belongs in the `target` object, in
@@ -85,9 +85,7 @@ name: refunds-codex
8585
target: codex-gpt5
8686
evaluate_options:
8787
max_concurrency: 3
88-
repeat:
89-
count: 2
90-
strategy: pass_any
88+
repeat: 2
9189

9290
tests:
9391
- file://../evals/cases/refund-smoke.cases.yaml
@@ -133,7 +131,7 @@ tests:
133131
| `tags` | Optional promptfoo-style metadata map. Use `tags.experiment` as the run/result grouping label. |
134132
| `prompts` | Optional top-level prompt matrix. Entries can be strings, chat message arrays, files, or generated prompt functions. |
135133
| `targets` | Optional target matrix. Entries reference target ids or inline target objects. |
136-
| `evaluate_options.repeat` | Optional repeat policy as a positive integer shorthand or object with `count`, `strategy`, `early_exit`, and `cost_limit_usd` |
134+
| `evaluate_options.repeat` | Optional positive integer sample count for repeat runs |
137135
| `timeout_seconds` | Optional per-case timeout |
138136
| `evaluate_options` | Optional evaluation runtime options such as `budget_usd`, `repeat`, and `max_concurrency` |
139137
| `threshold` | Optional suite quality threshold |

docs/adr/0006-separate-experiments-from-eval-definitions.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Superseded for the current eval authoring contract by
2121
[ADR 0016](0016-promptfoo-superset-eval-authoring-contract.md): `tests`,
2222
`prompts`/`vars`, `assert`, direct `input`, `target`/`targets`, and
2323
`evaluate_options` are the current promptfoo-aligned authoring surface.
24+
The repeat object examples in this ADR are also superseded by Bead `av-s96i`:
25+
current public authoring uses Promptfoo-style numeric `evaluate_options.repeat`
26+
only.
2427

2528
The "Suite And Test Import Surface" section below is historical. Its
2629
`imports.suites` / `imports.tests` design is superseded by av-kfik.43 and the
@@ -85,10 +88,7 @@ target:
8588
timeout_seconds: 900
8689
threshold: 0.8
8790
evaluate_options:
88-
repeat:
89-
count: 3
90-
strategy: pass_any
91-
early_exit: false
91+
repeat: 3
9292
budget_usd: 2.00
9393

9494
tests:
@@ -122,7 +122,7 @@ The old experiment runtime fields are ported into the parent eval file:
122122

123123
- target or target matrix
124124
- thresholds
125-
- repeated run count through `evaluate_options.repeat.count`
125+
- repeated sample count through numeric `evaluate_options.repeat`
126126
- timeout
127127
- budget
128128
- other run-time controls that do not define the task itself
@@ -166,8 +166,8 @@ must stay with the lifecycle surface that actually owns that work:
166166
discovery files, provider-specific config, and target-specific harness setup
167167
belong here.
168168
- Top-level `target` selects the system under test. Top-level `policy` selects
169-
runtime and gating controls: repeat strategy, threshold, timeout, budget, and
170-
early-exit behavior. Workspace lifetime stays under
169+
runtime and gating controls such as repeat count, threshold, timeout, and
170+
budget. Workspace lifetime stays under
171171
`workspace.scope`, and Docker/container binding stays under
172172
`workspace.docker`.
173173

0 commit comments

Comments
 (0)