When a run fails, unotest writes a failure bundle — everything needed to understand what happened, for you or the agent.
What’s captured
| Tier | Contents | Default |
|---|---|---|
| 1 | error + stack, console log, semantic DOM snapshot, DSL trace | always on |
| 2 | screenshot (viewport + element-focused) | on |
| 3 | HAR (network) + video | off — not wired yet |
Always-on failure artifacts
Independently of the bundle tiers, any scenario failure also writes
screenshot.png + page.html to the run’s failure/ directory under
unotest/.runs/ — no debug flag needed. page.html is the runtime DOM (open shadow roots included) with
secrets redacted, so it shows what the page actually was at the moment of
failure.
Step screenshots
Set UNOTEST_STEP_SCREENSHOTS=1 to capture a PNG after every executed step
into the run’s screenshot/ directory. In the
viewer a step row with a capture shows a camera icon —
click to open it full-screen. Captures settle first (network quiet + a painted
frame, capped at 2s) so a step ending on goto() isn’t shot as a blank
pre-render frame; the failure screenshot deliberately skips the settle.
Where it lives
A bundle is the failure/ directory of the run that produced it, under the
project’s unotest/.runs/ (or unotest/.runs.<env>/ for a run started with
--env; UNOTEST_ARTIFACTS_ROOT moves the whole tree to another root). The
run’s steps.jsonl sits beside it and also carries every assertJudge
verdict as a judge:verdict event — rubric, judged text, verdict, reasoning,
model — so a red judge step is explainable without a
re-run.
Retention is one window for the whole run history, bundles included:
UNOTEST_RUNS_RETENTION_DAYS (default 180; 0 keeps everything) removes
day directories older than that and then collects the blobs no run points
at any more. It runs after a collection, never before, so housekeeping
cannot delay a run or change its exit code. The viewer
renders each artifact per run; the agent reads them through the
failure-artifact MCP tools.
How the agent uses it
On failure the agent calls agent_fix, which bundles the trace, console,
semantic snapshot and scenario source plus a classification
(rewrite-selector / add-waitfor / change-assertion). It proposes a diff —
you approve it.