8.0 KiB
Agent Challenge Report Projections Design
Status
Approved for implementation planning on 2026-06-23.
Purpose
Agent challenge trials currently preserve raw result JSON, prompt text, and normalized metrics, but the central V2 runner does not automatically create a bounded report for review. Existing report helpers are also not wired into the V2 run or manual-audit paths.
This slice adds one normalized report model with two generated projections:
- human-readable Markdown in the trial workspace;
- machine-readable JSON beside the raw result.
The raw trial result remains immutable evidence. Manual audit is authoritative and regenerates both projections without rewriting raw evidence.
Goals
- Make every completed, failed, timed-out, or partially parsed trial produce a bounded report automatically.
- Let a reviewer understand a trial without opening a large raw result file.
- Preserve a machine-readable report suitable for later aggregation.
- Show ordered commands and tool calls without copying full tool outputs.
- Keep automatic outcome, policy validity, agent self-report, and manual grade distinct.
- Regenerate both projections after manual audit.
Non-Goals
- Aggregate model scoring or statistical claims.
- Replacing the immutable raw result JSON.
- Automatically deciding whether reading an example constituted copying a ready-made solution when the tool trace is ambiguous.
- Adding the future branching/
foreachchallenge. - Writing the broader operator/evaluation runbook; that follows this slice.
Artifact Layout
For a trial slug such as opencode_deepseek-v4-flash-free-trial-001:
results/
opencode_deepseek-v4-flash-free-trial-001.json
opencode_deepseek-v4-flash-free-trial-001.report.json
workspaces/opencode_deepseek-v4-flash-free-trial-001/
rendered-prompt.md
metrics.json
final-report.md
manual-audit.yaml # created after human review
The existing result JSON is raw evidence and is never modified by report or
audit commands. The .report.json and final-report.md files are disposable
projections that can be regenerated.
Normalized Report Model
Add a versioned Pydantic TrialReport DTO. Both output formats must be derived
from the same instance so their meaning cannot drift.
The model contains these sections:
- Identity and provenance
- report schema version;
- challenge id;
- model, variant, profile, and trial index;
- repository commit and dirty flag;
- prompt hashes;
- raw result path and workspace path.
- Outcome
- automatic task outcome;
- automatic evaluation validity;
- duration and return code;
- assertion or parser failures.
- Agent self-report
- extracted
challenge_report, when present; - final agent answer, bounded for human rendering.
- extracted
- Command and tool brief
- ordinal, tool, status, title;
- shell command or read/search path when available;
- failure marker, output character count, and output hash;
- no full output payload;
- bounded preview only when useful.
- Automatic evidence
- token, cost, step, tool-call, and failure counts;
- observed read categories;
- product-code escalation;
- disallowed reads and opaque commands.
- Discrepancies
- machine-observable conflicts between self-report and policy evidence;
- for example,
read.product_code=falsewhile observed reads include source, tests, docs, or implementation examples; - ambiguous cases remain manual-review pointers rather than automatic facts.
- Manual audit
- pending when no audit exists;
- official outcome, auditor, timestamp, corrections, evidence overrides, and notes after audit.
- Follow-up pointers
- concise warnings such as missing report fields, parse failures, opaque commands, or required manual checks.
Markdown Projection
final-report.md uses this stable order:
# Trial Report
## Outcome
## Agent Self-Report
## Commands And Tool Calls
## Automatic Evidence
## Policy Findings
## Self-Report Discrepancies
## Manual Audit
## Follow-Up Notes
The Markdown must remain bounded. It may include complete commands because commands are audit evidence, but it must not include full tool outputs or raw JSONL. Long commands and previews receive explicit length limits and retain a hash/character count in the machine report.
Machine Projection
<trial>.report.json is TrialReport.model_dump(mode="json") written with
stable indentation and key ordering. It contains the normalized command/tool
brief and audit information, not full stdout/stderr.
This report is the future aggregation input. Aggregators must not need to parse Markdown or the agent-authored YAML block.
Runner Flow
The V2 runner must:
- execute the trial and retain available stdout/stderr;
- normalize metrics, policy, parsed text, and challenge report;
- write the raw result JSON first;
- build a
TrialReportfrom the raw result with audit statuspending; - write
<trial>.report.jsonbeside the raw result; - write
final-report.mdin the workspace; - print or return both generated paths.
Report-generation failure must not destroy raw evidence. The runner should retain the raw result and surface a concise report-generation error to the caller.
The raw result gains explicit challenge_id, workspace_path, and
result_path fields. Report code must not infer the workspace from an
agent-authored workflow_file path.
Manual Audit Flow
The existing save_manual_audit.py remains the review entrypoint.
It must:
- load the immutable raw result;
- resolve the workspace from the explicit raw-result field;
- write
manual-audit.yamlin the workspace; - rebuild
TrialReportfrom raw evidence plus the audit; - overwrite both generated projections;
- print the audit, Markdown, and machine-report paths.
The command keeps current correction flags such as --set-read,
--set-evidence, --correction, and --notes. A reviewer should be able to
correct a trial in one command without opening the raw result.
Prompt Clarification
Put the following shared rule in the base challenge prompt so every challenge uses the same definition:
Files under
tests/andexamples/may contain complete or partial solutions. If you inspect them, reportread.product_code: true; also reportread.existing_solution: truewhen they provide a ready-made solution, orread.adjacent_attempts: truewhen they contain prior trial outputs.
Challenge-specific prompts may explain additional evidence fields but must not weaken this rule.
Error Handling
- Missing or malformed challenge reports remain visible as automatic failures or follow-up pointers.
- Missing manual audit means
pending, not failure. - Unknown tool event types remain counted in automatic evidence.
- Report generation accepts timeout and parse-error results with partial data.
- Invalid manual audit input fails without mutating either generated report.
- Projection writes use temporary files followed by replacement so reviewers do not observe half-written reports.
Testing
Add focused tests proving:
- one
TrialReportgenerates equivalent Markdown and JSON meaning; - commands are ordered and full tool output is absent;
- the V2 runner writes raw result, machine report, and Markdown report;
- timeout and parse-error trials still generate reports;
- explicit workspace/result paths are used instead of self-report inference;
- automatic discrepancies catch observable self-report conflicts;
- ambiguous existing-solution reads remain manual pointers;
- manual audit writes YAML and regenerates both projections;
- failed audit validation leaves prior projections unchanged;
- shared prompt text includes the
tests/andexamples/disclosure rule.
Follow-Up
After this slice:
- write the generic challenge operator/evaluation runbook;
- run repeated browser-click and report-workflow trials;
- design a third challenge using branching and
foreachto test graph reasoning, routing, iteration isolation, reducers, and recovery from validation failures.