Viewing files at commit 2caecb1e6549Commit detailsView latest

scenarios/agent.yaml 693 lines · 27.8 KB · yaml
1
version: 1
2
suite: agent_workflow
3
suite_version: 2026-06-09
4
description: >-
5
  End-to-end agent workflow benchmark definitions for comparing VCS-backed
6
  coding tasks across Git and Oak without assuming a specific model provider.
7
8
runner_contract:
9
  row_schema: scripts/agent_metrics_schema.py
10
  row_granularity: one result row per scenario, agent, subject, vcs_mode, and run
11
  comparison_policy: >-
12
    Compare the same agent adapter and task prompt across VCS modes first. Cross-agent
13
    comparisons must report provider-reported tokens separately from normalized text
14
    and tool I/O metrics.
15
  setup_excluded_from_timing:
16
    - fixture_generation
17
    - subject_binary_build
18
    - dependency_cache_population
19
  timed_phases:
20
    - task_setup
21
    - prompt_delivery
22
    - agent_work
23
    - tool_wait
24
    - vcs_operations
25
    - tests
26
    - merge_or_cleanup
27
28
vcs_modes:
29
  git_single_checkout:
30
    subject_kind: git
31
    description: One mutable checkout per run. Parallel scenarios must run serially in this mode.
32
  git_worktree_per_task:
33
    subject_kind: git
34
    description: One Git worktree or clone per task branch, with merge back to the run root.
35
  oak_single_mount:
36
    subject_kind: oak
37
    description: One Oak mount for the run, with branches created inside that mount.
38
  oak_mount_per_task:
39
    subject_kind: oak
40
    description: One Oak mount per task branch, without the higher-level Oak space template flow.
41
  oak_space_per_task:
42
    subject_kind: oak
43
    description: One Oak space subdirectory per task, using the agent-oriented mount lifecycle.
44
45
mode_sets:
46
  single_task_modes: &single_task_modes
47
    - git_single_checkout
48
    - git_worktree_per_task
49
    - oak_single_mount
50
    - oak_mount_per_task
51
    - oak_space_per_task
52
  isolated_parallel_modes: &isolated_parallel_modes
53
    - git_worktree_per_task
54
    - oak_mount_per_task
55
    - oak_space_per_task
56
  cleanup_modes: &cleanup_modes
57
    - git_single_checkout
58
    - git_worktree_per_task
59
    - oak_single_mount
60
    - oak_mount_per_task
61
    - oak_space_per_task
62
63
metric_groups:
64
  token_metrics: &token_metrics
65
    - input_tokens_reported
66
    - output_tokens_reported
67
    - reasoning_tokens_reported
68
    - cache_read_tokens_reported
69
    - cache_write_tokens_reported
70
    - total_tokens_reported
71
    - normalized_input_chars
72
    - normalized_output_chars
73
    - transcript_chars
74
    - context_truncation_events
75
    - token_budget
76
    - token_source
77
  tool_call_metrics: &tool_call_metrics
78
    - tool_calls_total
79
    - tool_calls_by_kind
80
    - terminal_commands_total
81
    - file_read_calls
82
    - file_write_calls
83
    - search_calls
84
    - edit_calls
85
    - vcs_commands_total
86
    - test_commands_total
87
    - network_calls_total
88
    - privileged_calls_total
89
    - parallel_batches_total
90
    - max_concurrency
91
  failed_command_retry_metrics: &failed_command_retry_metrics
92
    - failed_tool_calls_total
93
    - failed_commands_total
94
    - failed_vcs_commands_total
95
    - failed_test_commands_total
96
    - retry_attempts_total
97
    - retry_chains_total
98
    - same_command_retries_total
99
    - retry_after_failure_ms
100
    - recoverable_failures_total
101
    - unrecoverable_failures_total
102
  wall_clock_metrics: &wall_clock_metrics
103
    - total_ms
104
    - setup_ms
105
    - agent_active_ms
106
    - tool_wait_ms
107
    - vcs_ms
108
    - test_ms
109
    - merge_ms
110
    - cleanup_ms
111
    - idle_ms
112
    - timeout_ms
113
  bytes_read_hydrated_metrics: &bytes_read_hydrated_metrics
114
    - workspace_logical_bytes
115
    - workspace_materialized_bytes
116
    - bytes_read_by_agent
117
    - bytes_written_by_agent
118
    - bytes_hydrated
119
    - files_hydrated
120
    - hydration_events
121
    - large_file_bytes_scanned
122
    - binary_bytes_touched
123
    - command_output_bytes
124
125
scenarios:
126
  - id: one_line_bug_fix
127
    title: One-line bug fix
128
    category: small_edit
129
    prompt_shape: >-
130
      Fix the failing unit test by making the smallest reasonable code change.
131
    expected_fixtures:
132
      fixture_id: agent_one_line_bug_fix
133
      repo_shape: Small text application with one intentionally wrong conditional or operator.
134
      required_files:
135
        - src/calculator.py
136
        - tests/test_calculator.py
137
        - README.md
138
      seeded_state:
139
        - Exactly one deterministic failing test identifies the behavior.
140
        - Neighboring files contain plausible but irrelevant code.
141
      expected_change_shape:
142
        files_changed_min: 1
143
        files_changed_max: 2
144
        binary_assets: false
145
    allowed_vcs_modes: *single_task_modes
146
    task_success_criteria:
147
      - The targeted test suite passes.
148
      - The broken behavior is fixed for the asserted edge case.
149
      - No unrelated source, docs, lockfile, generated, or asset files change.
150
      - The final VCS state is clean and snapshotable.
151
    token_metrics: *token_metrics
152
    tool_call_metrics: *tool_call_metrics
153
    failed_command_retry_metrics: *failed_command_retry_metrics
154
    wall_clock_metrics: *wall_clock_metrics
155
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
156
    metric_focus:
157
      - Baseline overhead for tiny tasks where VCS setup can dominate agent work.
158
      - Ratio of useful file reads to exploratory reads.
159
160
  - id: docs_edit
161
    title: Docs edit
162
    category: documentation
163
    prompt_shape: >-
164
      Update the user-facing documentation for a changed command or option without
165
      changing executable code.
166
    expected_fixtures:
167
      fixture_id: agent_docs_edit
168
      repo_shape: Medium repo with README, docs pages, and nearby stale examples.
169
      required_files:
170
        - README.md
171
        - docs/usage.md
172
        - docs/reference.md
173
        - src/cli/options.py
174
      seeded_state:
175
        - Source code already implements the behavior.
176
        - At least two docs files contain outdated wording.
177
      expected_change_shape:
178
        files_changed_min: 1
179
        files_changed_max: 3
180
        binary_assets: false
181
    allowed_vcs_modes: *single_task_modes
182
    task_success_criteria:
183
      - Documentation reflects the fixture's current command behavior.
184
      - Code and generated files remain unchanged.
185
      - Markdown formatting checks pass when the fixture provides them.
186
      - Final status reports no dirty files after snapshot.
187
    token_metrics: *token_metrics
188
    tool_call_metrics: *tool_call_metrics
189
    failed_command_retry_metrics: *failed_command_retry_metrics
190
    wall_clock_metrics: *wall_clock_metrics
191
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
192
    metric_focus:
193
      - Cost of inspecting source only enough to verify docs facts.
194
      - Avoiding broad repo scans after the relevant docs are found.
195
196
  - id: cross_file_refactor
197
    title: Cross-file refactor
198
    category: refactor
199
    prompt_shape: >-
200
      Rename or reshape a public helper used across implementation, tests, and docs
201
      while preserving behavior.
202
    expected_fixtures:
203
      fixture_id: agent_cross_file_refactor
204
      repo_shape: Text-heavy application with shared modules, tests, examples, and docs references.
205
      required_files:
206
        - src/core/serializer.py
207
        - src/api/client.py
208
        - src/cli/main.py
209
        - tests/test_serializer.py
210
        - docs/api.md
211
      seeded_state:
212
        - The old symbol appears in code, tests, comments, and docs.
213
        - Similar symbol names exist and must not be changed.
214
      expected_change_shape:
215
        files_changed_min: 4
216
        files_changed_max: 12
217
        binary_assets: false
218
    allowed_vcs_modes: *single_task_modes
219
    task_success_criteria:
220
      - All runtime references use the new API name or shape.
221
      - Tests and type checks pass for the fixture language.
222
      - Similar but unrelated symbols are untouched.
223
      - Docs examples compile or match the new public API.
224
    token_metrics: *token_metrics
225
    tool_call_metrics: *tool_call_metrics
226
    failed_command_retry_metrics: *failed_command_retry_metrics
227
    wall_clock_metrics: *wall_clock_metrics
228
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
229
    metric_focus:
230
      - Search and edit breadth needed for a correct multi-file change.
231
      - Retry behavior after tests expose a missed reference.
232
233
  - id: dependency_upgrade
234
    title: Dependency upgrade
235
    category: dependency_management
236
    prompt_shape: >-
237
      Upgrade one pinned dependency to the requested version and fix any API or lockfile fallout.
238
    expected_fixtures:
239
      fixture_id: agent_dependency_upgrade
240
      repo_shape: Small service with a package manifest, lockfile, cached dependency artifacts, and tests.
241
      required_files:
242
        - package.json
243
        - package-lock.json
244
        - src/server.js
245
        - tests/server.test.js
246
      seeded_state:
247
        - A local fixture cache or registry provides the target dependency version.
248
        - The upgraded dependency requires a small source or test adjustment.
249
      expected_change_shape:
250
        files_changed_min: 2
251
        files_changed_max: 5
252
        binary_assets: false
253
    allowed_vcs_modes: *single_task_modes
254
    task_success_criteria:
255
      - Manifest and lockfile agree on the requested dependency version.
256
      - The package manager runs without reaching an uncontrolled network source.
257
      - Tests pass after any required API adjustment.
258
      - Unrelated dependencies are not upgraded.
259
    token_metrics: *token_metrics
260
    tool_call_metrics: *tool_call_metrics
261
    failed_command_retry_metrics: *failed_command_retry_metrics
262
    wall_clock_metrics: *wall_clock_metrics
263
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
264
    metric_focus:
265
      - Lockfile churn and command retries caused by package-manager behavior.
266
      - Fair treatment of network-disabled or cache-only runners.
267
268
  - id: generated_file_churn
269
    title: Generated-file churn
270
    category: generated_outputs
271
    prompt_shape: >-
272
      Change a schema or template, run the generator, and commit the resulting deterministic output.
273
    expected_fixtures:
274
      fixture_id: agent_generated_file_churn
275
      repo_shape: Project with source schema, generator script, and hundreds of generated text files.
276
      required_files:
277
        - schema/events.yaml
278
        - scripts/generate_events.py
279
        - src/generated/events/
280
        - tests/test_generated_events.py
281
      seeded_state:
282
        - Generated files are stale relative to the requested schema change.
283
        - A fixture test fails until generation is rerun.
284
      expected_change_shape:
285
        files_changed_min: 20
286
        files_changed_max: 400
287
        binary_assets: false
288
    allowed_vcs_modes: *single_task_modes
289
    task_success_criteria:
290
      - Source schema reflects the requested change.
291
      - Generated files match a clean generator run.
292
      - Tests pass without hand-editing generated output to hide generator drift.
293
      - VCS snapshot handles high file-count churn correctly.
294
    token_metrics: *token_metrics
295
    tool_call_metrics: *tool_call_metrics
296
    failed_command_retry_metrics: *failed_command_retry_metrics
297
    wall_clock_metrics: *wall_clock_metrics
298
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
299
    metric_focus:
300
      - File-status and snapshot cost under many changed files.
301
      - Distinguishing agent reads from generator-written bytes.
302
303
  - id: binary_asset_update
304
    title: Binary asset update
305
    category: binary_assets
306
    prompt_shape: >-
307
      Replace or update a binary asset and adjust the metadata that validates it.
308
    expected_fixtures:
309
      fixture_id: agent_binary_asset_update
310
      repo_shape: App with small source files, binary images, and checksum or dimension metadata.
311
      required_files:
312
        - assets/logo.png
313
        - assets/[email protected]
314
        - src/assets_manifest.json
315
        - tests/test_assets.py
316
      seeded_state:
317
        - Replacement binary assets are provided inside the fixture inputs directory.
318
        - Metadata is stale until the asset update is applied.
319
      expected_change_shape:
320
        files_changed_min: 2
321
        files_changed_max: 4
322
        binary_assets: true
323
    allowed_vcs_modes: *single_task_modes
324
    task_success_criteria:
325
      - The requested binary asset bytes are installed exactly.
326
      - Checksums, dimensions, or manifest entries are correct.
327
      - Binary files are not corrupted by text editing tools.
328
      - Asset validation tests pass.
329
    token_metrics: *token_metrics
330
    tool_call_metrics: *tool_call_metrics
331
    failed_command_retry_metrics: *failed_command_retry_metrics
332
    wall_clock_metrics: *wall_clock_metrics
333
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
334
    metric_focus:
335
      - Bytes hydrated and copied for binary-heavy changes.
336
      - Whether the agent avoids dumping binary content into context.
337
338
  - id: large_file_inspection
339
    title: Large-file inspection
340
    category: large_files
341
    prompt_shape: >-
342
      Inspect a large structured data file to answer a targeted question, then update
343
      a small verification file or test expectation.
344
    expected_fixtures:
345
      fixture_id: agent_large_file_inspection
346
      repo_shape: Repo containing a large NDJSON or CSV file plus small indexes and tests.
347
      required_files:
348
        - data/events.ndjson
349
        - data/events.index.json
350
        - tests/test_event_fixture.py
351
        - docs/event-fixture-notes.md
352
      seeded_state:
353
        - The target record is discoverable by a stable key.
354
        - The large file is too large to read fully into the agent transcript.
355
      expected_change_shape:
356
        files_changed_min: 1
357
        files_changed_max: 3
358
        binary_assets: false
359
    allowed_vcs_modes: *single_task_modes
360
    task_success_criteria:
361
      - The answer or expectation matches the targeted record in the large file.
362
      - The agent does not modify the large fixture unless the task explicitly requires it.
363
      - Tests or verification commands pass.
364
      - The transcript does not contain a bulk dump of the large file.
365
    token_metrics: *token_metrics
366
    tool_call_metrics: *tool_call_metrics
367
    failed_command_retry_metrics: *failed_command_retry_metrics
368
    wall_clock_metrics: *wall_clock_metrics
369
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
370
    metric_focus:
371
      - Logical bytes read versus bytes hydrated from storage.
372
      - Effectiveness of range reads, search, and indexes.
373
374
  - id: find_the_right_file_exploration
375
    title: Find-the-right-file exploration
376
    category: navigation
377
    prompt_shape: >-
378
      Resolve a vague bug report by locating the responsible file in a broad repo.
379
    expected_fixtures:
380
      fixture_id: agent_find_right_file
381
      repo_shape: Wide source tree with many plausible modules and one localized bug.
382
      required_files:
383
        - src/features/
384
        - src/shared/
385
        - tests/integration/test_user_flow.py
386
        - docs/architecture.md
387
      seeded_state:
388
        - The failing behavior is described at product level, not by filename.
389
        - Several files contain similar terms to create realistic search noise.
390
      expected_change_shape:
391
        files_changed_min: 1
392
        files_changed_max: 4
393
        binary_assets: false
394
    allowed_vcs_modes: *single_task_modes
395
    task_success_criteria:
396
      - The correct module is changed and the reported behavior is fixed.
397
      - Search noise files remain untouched.
398
      - Integration and targeted tests pass.
399
      - The agent records enough evidence in tool traces to justify the file choice.
400
    token_metrics: *token_metrics
401
    tool_call_metrics: *tool_call_metrics
402
    failed_command_retry_metrics: *failed_command_retry_metrics
403
    wall_clock_metrics: *wall_clock_metrics
404
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
405
    metric_focus:
406
      - Search calls, directory listings, and file reads before first edit.
407
      - Whether lazy hydration reduces cost for broad exploration.
408
409
  - id: parallel_independent_tasks
410
    title: Parallel independent tasks
411
    category: parallel_work
412
    prompt_shape: >-
413
      Run multiple independent agent tasks against the same starting revision and merge them.
414
    expected_fixtures:
415
      fixture_id: agent_parallel_independent
416
      repo_shape: App with three unrelated issues in separate modules and tests.
417
      required_files:
418
        - src/payments/
419
        - src/search/
420
        - docs/cli.md
421
        - tests/
422
      seeded_state:
423
        - Task A is a source bug fix.
424
        - Task B is a docs edit.
425
        - Task C is a small test expectation update.
426
      expected_change_shape:
427
        files_changed_min: 3
428
        files_changed_max: 9
429
        binary_assets: false
430
    allowed_vcs_modes: *isolated_parallel_modes
431
    task_success_criteria:
432
      - Every subtask succeeds against the shared starting revision.
433
      - All accepted changes are present after merge or squash.
434
      - No subtask observes another subtask's unmerged dirty work.
435
      - Final combined tests pass and the run root is clean.
436
    token_metrics: *token_metrics
437
    tool_call_metrics: *tool_call_metrics
438
    failed_command_retry_metrics: *failed_command_retry_metrics
439
    wall_clock_metrics: *wall_clock_metrics
440
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
441
    metric_focus:
442
      - Branch or mount creation overhead under concurrent work.
443
      - Wall-clock speedup versus serialized task duration.
444
445
  - id: parallel_overlapping_tasks
446
    title: Parallel overlapping tasks
447
    category: parallel_work
448
    prompt_shape: >-
449
      Run multiple tasks that touch nearby files or non-conflicting hunks, then merge them.
450
    expected_fixtures:
451
      fixture_id: agent_parallel_overlapping
452
      repo_shape: App with two feature requests touching the same module family.
453
      required_files:
454
        - src/config/defaults.py
455
        - src/config/validation.py
456
        - tests/test_config.py
457
        - docs/config.md
458
      seeded_state:
459
        - Subtasks overlap in file set but target different symbols or sections.
460
        - The correct combined result should merge without semantic loss.
461
      expected_change_shape:
462
        files_changed_min: 2
463
        files_changed_max: 8
464
        binary_assets: false
465
    allowed_vcs_modes: *isolated_parallel_modes
466
    task_success_criteria:
467
      - Both overlapping task intents survive the final merge.
468
      - Any auto-merge is verified by tests and direct inspection.
469
      - No last-writer-wins overwrite is accepted.
470
      - Final status is clean after snapshot or merge.
471
    token_metrics: *token_metrics
472
    tool_call_metrics: *tool_call_metrics
473
    failed_command_retry_metrics: *failed_command_retry_metrics
474
    wall_clock_metrics: *wall_clock_metrics
475
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
476
    metric_focus:
477
      - Conflict-free overlap handling and merge verification cost.
478
      - Extra reads needed to confirm both task intents remain present.
479
480
  - id: conflict_resolution
481
    title: Conflict resolution
482
    category: merge_conflicts
483
    prompt_shape: >-
484
      Merge two completed task branches that intentionally edit the same lines, resolve
485
      the conflict, and preserve both behavioral intents.
486
    expected_fixtures:
487
      fixture_id: agent_conflict_resolution
488
      repo_shape: Small service with two branches or mounts that change the same function.
489
      required_files:
490
        - src/routing/rules.py
491
        - tests/test_routing_rules.py
492
        - docs/routing.md
493
      seeded_state:
494
        - Branch A changes behavior for one route class.
495
        - Branch B changes behavior for a second route class in the same hunk.
496
        - The naive conflict choices each break one test.
497
      expected_change_shape:
498
        files_changed_min: 1
499
        files_changed_max: 5
500
        binary_assets: false
501
    allowed_vcs_modes: *isolated_parallel_modes
502
    task_success_criteria:
503
      - The conflict is detected and resolved deliberately.
504
      - Tests for both branch intents pass after resolution.
505
      - Conflict markers are absent from tracked files.
506
      - Merge metadata or snapshot state is clean and auditable.
507
    token_metrics: *token_metrics
508
    tool_call_metrics: *tool_call_metrics
509
    failed_command_retry_metrics: *failed_command_retry_metrics
510
    wall_clock_metrics: *wall_clock_metrics
511
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
512
    metric_focus:
513
      - Failed merge commands, conflict-resolution retries, and verification tests.
514
      - Whether VCS output gives agents enough context without excessive file reads.
515
516
  - id: failed_test_then_fix
517
    title: Failed-test-then-fix
518
    category: recovery
519
    prompt_shape: >-
520
      Make an apparently obvious fix, observe the failing test output, then diagnose
521
      and apply the correct fix.
522
    expected_fixtures:
523
      fixture_id: agent_failed_test_then_fix
524
      repo_shape: Small application where the first plausible edit leaves a hidden edge case broken.
525
      required_files:
526
        - src/parser.py
527
        - tests/test_parser.py
528
        - tests/fixtures/parser_cases.json
529
      seeded_state:
530
        - The direct symptom points to one line, but the correct fix requires another helper.
531
        - Test output includes enough detail for recovery.
532
      expected_change_shape:
533
        files_changed_min: 1
534
        files_changed_max: 4
535
        binary_assets: false
536
    allowed_vcs_modes: *single_task_modes
537
    task_success_criteria:
538
      - At least one failing test command is observed before the final successful run.
539
      - The final fix handles both the original symptom and the edge case.
540
      - Tests pass after the recovery edit.
541
      - Failed intermediate edits are not left as unrelated churn.
542
    token_metrics: *token_metrics
543
    tool_call_metrics: *tool_call_metrics
544
    failed_command_retry_metrics: *failed_command_retry_metrics
545
    wall_clock_metrics: *wall_clock_metrics
546
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
547
    metric_focus:
548
      - Command failure handling and useful retries after test output.
549
      - Additional context cost required for recovery.
550
551
  - id: abandon_and_cleanup
552
    title: Abandon and cleanup
553
    category: lifecycle
554
    prompt_shape: >-
555
      Start a task, discover from repository evidence that the requested change should
556
      not be made, then abandon the branch or mount cleanly.
557
    expected_fixtures:
558
      fixture_id: agent_abandon_cleanup
559
      repo_shape: Project with a misleading request contradicted by policy docs or tests.
560
      required_files:
561
        - docs/policy.md
562
        - src/feature_flags.py
563
        - tests/test_feature_flags.py
564
      seeded_state:
565
        - The requested feature is explicitly disallowed by repository policy.
566
        - A partial local edit would be easy but incorrect.
567
      expected_change_shape:
568
        files_changed_min: 0
569
        files_changed_max: 0
570
        binary_assets: false
571
    allowed_vcs_modes: *cleanup_modes
572
    task_success_criteria:
573
      - The agent identifies repository evidence for abandoning the task.
574
      - No partial edits, commits, branches, mounts, or worktrees are leaked after cleanup.
575
      - The original checkout or space is clean.
576
      - The final result records an intentional abandoned outcome rather than a task failure.
577
    token_metrics: *token_metrics
578
    tool_call_metrics: *tool_call_metrics
579
    failed_command_retry_metrics: *failed_command_retry_metrics
580
    wall_clock_metrics: *wall_clock_metrics
581
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
582
    metric_focus:
583
      - Lifecycle cleanup cost and correctness.
584
      - Distinguishing productive abandonment from timeout or crash failure.
585
586
  - id: history_archaeology
587
    title: History archaeology
588
    category: history_read
589
    prompt_shape: >-
590
      Answer "what changed recently, what did the last commit touch, when did this
591
      file last change, and which commit introduced this term" using history
592
      commands only.
593
    expected_fixtures:
594
      fixture_id: agent_history_archaeology
595
      repo_shape: Small application with several seeded commits carrying meaningful messages.
596
      required_files:
597
        - app/pricing.py
598
        - app/totals.py
599
        - README.md
600
      seeded_state:
601
        - At least three commits after the initial snapshot, each editing a known file.
602
        - Commit messages name the behavior change so log output is answerable.
603
      expected_change_shape:
604
        files_changed_min: 0
605
        files_changed_max: 0
606
        binary_assets: false
607
    allowed_vcs_modes: *single_task_modes
608
    task_success_criteria:
609
      - The history questions are answered from command output, not guesses.
610
      - No working-tree files change.
611
      - Subjects lacking a capability (file-scoped log, pickaxe, show) run the
612
        closest available command; the gap is recorded, not hidden.
613
    token_metrics: *token_metrics
614
    tool_call_metrics: *tool_call_metrics
615
    failed_command_retry_metrics: *failed_command_retry_metrics
616
    wall_clock_metrics: *wall_clock_metrics
617
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
618
    metric_focus:
619
      - Token cost per answered history question, by subject.
620
      - Capability gaps where one subject needs extra commands or full-history dumps.
621
    implemented_by: scripts/workflow_ab.py --workflows history_archaeology
622
623
  - id: vcs_error_recovery
624
    title: VCS error recovery
625
    category: failure_recovery
626
    prompt_shape: >-
627
      Recover from common VCS failures: a snapshot with nothing to record and a
628
      mistyped subcommand, then complete a real change and snapshot it.
629
    expected_fixtures:
630
      fixture_id: agent_vcs_error_recovery
631
      repo_shape: Small clean repository where the first snapshot attempt has nothing to commit.
632
      required_files:
633
        - app/pricing.py
634
        - README.md
635
      seeded_state:
636
        - The working tree is clean so the first commit attempt fails or no-ops.
637
        - The scripted lane also issues one intentionally unknown subcommand.
638
      expected_change_shape:
639
        files_changed_min: 1
640
        files_changed_max: 1
641
        binary_assets: false
642
    allowed_vcs_modes: *single_task_modes
643
    task_success_criteria:
644
      - The run ends with the real change snapshotted and a clean tree.
645
      - Error output cost (bytes, estimated tokens) is recorded per failure step.
646
      - For real-agent rows, turns_to_recovery and tokens_to_recovery are populated
647
        when the adapter exposes per-call outcomes.
648
    token_metrics: *token_metrics
649
    tool_call_metrics: *tool_call_metrics
650
    failed_command_retry_metrics: *failed_command_retry_metrics
651
    wall_clock_metrics: *wall_clock_metrics
652
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
653
    metric_focus:
654
      - Error-message ergonomics, measured as recovery turns and tokens; an error
655
        message is a prompt.
656
      - Exit-code clarity and whether a follow-up status call is needed to learn state.
657
    implemented_by: scripts/workflow_ab.py --workflows vcs_error_recovery
658
659
  - id: model_familiarity_tax
660
    title: Model familiarity tax
661
    category: zero_shot_competence
662
    prompt_shape: >-
663
      Run an identical task at three instruction levels (zero-shot, cheat-sheet,
664
      full-docs) and compare success rate, help/discovery calls, hallucinated
665
      commands, and tokens to reach parity.
666
    expected_fixtures:
667
      fixture_id: agent_one_line_bug_fix
668
      repo_shape: Reuses an existing small-task fixture; only the instructions vary.
669
      required_files:
670
        - app/pricing.py
671
        - tests/test_pricing.py
672
      seeded_state:
673
        - Git is in every model's pretraining data; a new VCS is not. The fixed
674
          per-session instruction cost and the guessing cost are the measurement.
675
      expected_change_shape:
676
        files_changed_min: 1
677
        files_changed_max: 2
678
        binary_assets: false
679
    allowed_vcs_modes: *single_task_modes
680
    task_success_criteria:
681
      - Rows record agent.instruction_level and are never aggregated across levels.
682
      - Zero-shot rows count help_calls_total and unknown_command_failures_total.
683
      - The headline metric is instruction tokens required to reach git-parity
684
        success rate, per scenario.
685
    token_metrics: *token_metrics
686
    tool_call_metrics: *tool_call_metrics
687
    failed_command_retry_metrics: *failed_command_retry_metrics
688
    wall_clock_metrics: *wall_clock_metrics
689
    bytes_read_hydrated_metrics: *bytes_read_hydrated_metrics
690
    metric_focus:
691
      - Success rate and retry chains per instruction level, per subject.
692
      - Help/discovery tool calls and hallucinated-command failures at zero-shot.
693
    implemented_by: scripts/agent_workflow.py --instruction-level {zero-shot,cheat-sheet,full-docs}