This documentation is available as Markdown. For the complete index, see llms.txt. Skip to content

Watching a collection run

For the complete documentation index, see llms.txt

An agent that starts a collection in the background —

Terminal window
npx @unotest/web collection smoke &

— sees the CLI’s per-scenario lines only when the process ends, because a piped stdout is block-buffered. The run’s own journal is the progress source. It is written line by line as the run goes:

unotest/.runs/<yyyy>/<mm>/<dd>/col-<name>-<id>/steps.jsonl

.runs becomes .runs.<env> for a --env <name> run; the date shard is UTC. col-<name>- is the collection run’s id prefix and the <id> tail is a timestamp plus random hex, so take the newest directory with that prefix once the run has started.

The events

One JSON object per line, four kinds:

kindFieldsWhen
collection-run:startedrunId, collection, scenarios[] (in order)before the first scenario
collection-run:scenario-startedscenario, scenarioRunIdeach scenario takes a worker
collection-run:scenario-finishedscenario, scenarioRunId, outcomecompleted / failed / aborted / interrupted
collection-run:finishedoutcomethe run is over — nothing follows

Every line also carries t (epoch ms). scenarioRunId names the scenario’s own run directory under the same .runs root, where its steps.jsonl and failure bundle live. A line that does not parse is the one being written — retry on the next read, never treat it as the end.

Terminal window
tail -f unotest/.runs/2026/09/03/col-smoke-*/steps.jsonl \
| jq -c 'select(.kind | startswith("collection-run:scenario"))
| {kind, scenario, outcome}'

A contract, not an implementation detail

The event types (CollectionRunArtifact) and the file name (STEPS_FILE) are exported from @unotest/protocol under semver, and the box daemon reads the same events for its metrics. Build on them.