# Run folder and events

> Find saved run files and read their event types, identities and schemas.

Source: https://rehearsal.dev/retest/docs/reference/run-folder

A run folder holds the result, events, logs and evidence from one run. Use it to investigate later or feed results into your own tools without opening a browser again.

```sh
npx retest inspect .retest/runs/<time>
npx retest report .retest/runs/<time>
```

The first command prints the saved result; the second writes `report.html`. Both also work with incomplete runs when enough events remain to reconstruct a result. [Debugging a failure](https://rehearsal.dev/retest/docs/essentials/debugging.md) walks through a test's timeline.

## Files and folders

The default folder is `.retest/runs/<time>`. Pass `--output <dir>` to choose another new or empty folder. Retest refuses to overwrite a folder that already holds files.

| Path inside the run | Contents |
| --- | --- |
| `events.jsonl` | One version 1 event per line, written as the run proceeds. |
| `result.json` | RunResult written at the end through an atomic rename. |
| `logs/*.log` | Test-file stdout and stderr, browser output and output of servers Retest started. |
| `artifacts/*-failure.png` | Failure screenshots, named with a test slug, attempt id and app when applicable. |
| `diagnostics/*.jsonl` | One session's console, runtime-error and network records. |
| `artifacts/<attempt>/<app>/` | Recordings, frames, AI evidence, screenshot comparison images and downloads. |
| `electron/<app-and-target>/<launch>/windows.json` | Window inventory for each Electron launch. The app and target form a slug. |
| `report.html` | Portable report, when requested with report or --reporter html. |
| `states/` | Saved sign-in states while the run is active; removed during cleanup. |
| `uploads/<attempt>/` | Temporary files created for content-based uploads while the test runs. |

Log names include a slug and hash. A browser-only run uses `logs/browser.log`; configured targets use `logs/browser-*.log`, with extra instance suffixes for browser pools. App-server logs use `logs/app-*.log`. Read paths from records instead of reconstructing filenames.

The last-run selection record is outside this folder, at `.retest/last-run.json`. It feeds `--last-failed`. A programmatic host can change its path or disable it with `lastRunFile: false`.

## Artefact paths and retention

Session artefact folders use an attempt id and a shortened app name with a hash. The following patterns describe files in those folders. Formats depend on what captured or encoded the media.

| Pattern | Contents |
| --- | --- |
| `screenshot-evaluation-<n>.png` | Screenshot captured for an AI check; the extension may also be jpg. |
| `thumbnail-*.png` | Thumbnail of a screenshot or recording; the extension may also be jpg. |
| `recording-<n>.mp4` | Playable video, or webm when that container was selected. |
| `recording-<n>.mp4.partial` | Video still being written, or an unfinished output. |
| `frames-<n>/<index>.jpg` | Numbered frames retained for an AI check; frames may also be png. |
| `<name>-<observation>-expected.png` | Readable baseline image kept after a failed screenshot comparison. |
| `<name>-<observation>-actual.png` | Actual screenshot kept after a failed comparison, including when no baseline exists. |
| `<name>-<observation>-diff.png` | Difference image kept when the failed comparison had a readable baseline. |
| `downloads/<filename>` | Saved download, using a safe form of the browser's suggested name. |

Failure screenshots and diagnostics use slug-based paths, while other media uses the session folders above. Follow each path stored in an event or result instead of assuming a single layout.

Artefact references are relative to the run folder and use forward slashes, so you can move the folder. Retest's artefact reader refuses invalid references, symbolic links, hard links, special files and files beyond its size limit. Screenshots are pixels and are not text-redacted.

Logs, screenshots, frames, downloads, diagnostics and reports remain. With `recording.keep: 'failures'`, recordings of passed attempts and their recording thumbnails are removed, except recordings used by AI checks. Unreferenced partial recording files may be removed after the media process closes. Removal events record each request and its result.

Saved states contain session cookies and are deleted at cleanup. SIGKILL can leave them behind because cleanup cannot run. [Recordings and evidence](https://rehearsal.dev/retest/docs/guides/recordings-and-evidence.md) describes capture policy and retention in more detail.

## Event envelope and identity

Every event has the following envelope. Event-specific fields then describe what happened. Sequences increase within one run; `elapsedMs` uses the run's monotonic clock rather than wall-clock differences.

| Field | Meaning |
| --- | --- |
| `schemaVersion` | 1. |
| `runId` | Run identity. |
| `sequence` | Event order within the run. |
| `time` | Wall-clock timestamp. |
| `elapsedMs` | Milliseconds since the run began, on its monotonic clock. |
| `origin` | parent for Retest's own records, child for a test-process report. |
| `type` | One of the event types below. |

| Scope field | Meaning when present |
| --- | --- |
| `testId` | Relative file path, group names and test title joined with >. |
| `attemptId` | Identity of this execution attempt. |
| `variant`, `variantKey` | App-to-target map and its printable key. |
| `session` | App name on events, or page for a browser-only run. |
| `sessionId` | One app page in one attempt, such as k3v9q0x2mb:web. |
| `stepId` | Named step or hook containing the operation. |
| `observationId` | Look that supplied the evidence, when the event rests on a look. |

Auxiliary records use `app` where events use `session`. Observation ids start again within each attempt, so join records with the attempt and session identities too. Page and layout looks can have ids without their own `observation` event, so missing numbers do not imply missing records.

## Run and collection events

| Type | Record |
| --- | --- |
| `run.started` | Retest and Node versions, platform, root, files and effective run options. |
| `collection.completed` | One file's collected tests, locations, options and variants. |
| `collection.failed` | A file that could not be collected, with its failure. |
| `file.failed` | A collected file whose process failed outside a test. |
| `run.narrowed` | Focused declarations and how many tests they kept. |
| `app.started` | App server started, including readiness address, pid and startup duration. |
| `app.reused` | An already-running app server was reused. |
| `app.failed` | App-server startup failed. |
| `browser.started` | Browser product, version, available build, engine, target and process identity. Further pool or Electron launches may add instances. |
| `native.started` | Native session identity, app, target and execution facts. |
| `native.ended` | Native session ended, with any unresolved lifecycle or input outcomes. |
| `run.finished` | Run status, exit code, completeness, counts, duration and optional failure or evidence state. |
| `run.outcome` | Corrected final outcome after reporter shutdown, when that changes the result. |

## Attempt and resource events

| Type | Record |
| --- | --- |
| `lock.acquired` | Named locks held by the attempt, wait duration and blockers. |
| `resource.acquired` | Desktop, devices or data folders held by the attempt. |
| `session.reserved` | Host-managed browser session capacity acquired for the owner. |
| `lease.taken` | Complete resource lease and release budget. |
| `lease.expired` | Resources not released within the cleanup budget. |
| `session.released` | Reserved sessions returned, with the release reason. |
| `test.started` | Test source, name and execution identity, including bundle, configuration and starting state. |
| `preparation.finished` | A host preparation's outcome and reported facts. |
| `cleanup.finished` | A host cleanup's outcome. |
| `state.saved` | Saved state name, app, target and session, without its contents. |
| `state.restored` | Restored state name, app, target and session. |
| `test.finished` | Status, assertion count, duration, failure, cleanup failures and ending; may include the final bundle and checks not run. |

A skipped test has `test.finished` without `test.started`. Waiting for locks and resources happens before the test starts and does not consume its test budget. For programmatic runs, see [Use Retest from code](https://rehearsal.dev/retest/docs/scaling-up/from-code.md).

## Steps, actions and checks

| Type | Record |
| --- | --- |
| `step.started` | Named step, parent step, source location and optional hook kind. |
| `step.finished` | Step status, duration and optional failure. |
| `action.completed` | Command, locator, page and duration, plus relevant input metadata. |
| `action.failed` | The same action facts with its failure. |
| `navigation` | Address, title, cause and document change. |
| `observation` | Redacted locator look served to the test process before it received the answer. |
| `assertion.passed` | Matcher, comparison and available observation identity, with judgedBy. |
| `assertion.failed` | Assertion facts and failure. Soft failures carry soft: true. |
| `host_check.passed` | Parent-run page check and the actual page it read. |
| `host_check.failed` | Host check facts and failure. |
| `evaluation.finished` | AI check verdict, criteria, evidence references, judge identity and available usage. |
| `baseline.written` | Screenshot baseline path, dimensions and observation, including whether it replaced a file. |
| `inbox.read` | Inbox name, read counts, wait and redacted message metadata. |
| `dialog` | Dialog type, redacted text, answer and who answered it. |
| `popup.opened` | Opener and popup identities, address and available title. |
| `popup.closed` | Popup session closed. |
| `download` | Suggested filename, redacted address, completion state and available saved path. |
| `route` | Route addition, removal or answer, including a safe response summary. |

`navigation.cause` is `goto` for explicit navigation methods, `action` for navigation attributed to dispatched input, or `page` otherwise. `document` is `new` or `same`. Navigation and action addresses omit queries and fragments; page assertions can retain the whole redacted address they compared.

Only step and assertion events originate in the test process. The parent rejudges passed locator and page assertions on its recorded look and marks them `judgedBy: 'parent'`. Value checks are `judgedBy: 'child'` because those values exist in the test process.

## Evidence and media events

| Type | Record |
| --- | --- |
| `evidence.captured` | Failure screenshot path, session, source and capture time. |
| `evidence.failed` | Why a failure screenshot was unavailable or withheld. |
| `diagnostics.started` | Capture scope, limits and any strict or required policy. |
| `diagnostics.finished` | Session capture summaries and artefact reference. |
| `recording.started` | Recording identity, source, capture mode, output, dimensions, rate and clock start. |
| `recording.finished` | Recording state, video facts, frame counts, gaps and clock mapping. |
| `media.started` | Media process identity and encoder readiness. |
| `media.failed` | Media or encoder startup failure. |
| `media.lost` | Media process exit, affected recordings and whether it will restart. |
| `media.closed` | Confirmed media-process shutdown and cleanup problems. |
| `media.leftovers` | Inspection and cleanup of a previous killed run's recorded outputs. |
| `capture.withheld` | Pixel withholding began around secret entry. |
| `capture.resumed` | Pixel withholding ended, with its reason and time span. |
| `capture.native_entry` | Native field classification and pixel-policy decision, without the secret value. |
| `capture.masked_entry` | Capture continued because secret entry was verified as masked. |
| `artifact.removal_requested` | Persisted request to remove a retained artefact. |
| `artifact.removed` | Requested file removal succeeded. |
| `artifact.removal_failed` | Requested file removal failed or was refused; the file remains. |

## Diagnostics artefact lines

Diagnostics artefacts are separate JSON lines files. Their line types are not `RetestEvent` types. They begin with `capture.started`, end with `capture.finished` and contain the record types below. Their identities name the test, attempt, app and session.

| Type | Contents |
| --- | --- |
| `console` | Level, source, cleaned message and available source location. |
| `runtime_error` | Uncaught error or unhandled rejection and bounded stack. |
| `network.request` | Request id, method, cleaned address and redirect relationship. |
| `network.response` | Status, content type and available cache or mocked-response facts. |
| `network.finished` | Request completion and available transfer size. |
| `network.failed` | Transport failure or cancellation. |
| `network.pending` | Request still pending when capture ended, with its reason. |

Capture records include their scope and completeness. Retest records no network headers or bodies. See [Console and network](https://rehearsal.dev/retest/docs/guides/console-and-network.md) for engine coverage and [Results and exit codes](https://rehearsal.dev/retest/docs/reference/results.md) for capture states.

## Read and validate a folder

`readRunFolder` validates saved results and events and returns `{ source, result, events, warnings }`. It reconstructs a missing result from events and marks it incomplete. Invalid folders throw `RunFolderReadError`.

```ts
import { readRunFolder } from '@rehearsal-labs/retest/runner'

const folder = readRunFolder('.retest/runs/saved-run')
const failedActions = folder.events.filter(event => event.type === 'action.failed')

console.log(folder.result.exitCode, failedActions.length)
console.log(folder.warnings)
```

Replace the example path with your saved folder. If the last event line was cut off during writing, the reader leaves it out and adds a warning. Invalid earlier lines, mixed run ids or non-increasing sequences make the event log unreadable. With a valid `result.json`, a damaged event log becomes a warning and the result remains readable.

The protocol export supplies `retestEventSchema`, `runResultSchema`, `eventSchemaUrl` and `resultSchemaUrl`. Installed JSON Schemas are `dist/schemas/event-v1.schema.json` and `dist/schemas/result-v1.schema.json`. Use a reader at least as new as the Retest version that wrote the folder. Version 1 rejects unknown fields, so an older reader may refuse newer records.

A host running code it does not control should take authoritative results from `runFiles` and events from its reporter. The test process can write to the run folder, so those files are saved copies rather than a trust boundary. [Use Retest from code](https://rehearsal.dev/retest/docs/scaling-up/from-code.md) describes host isolation and required checks.

## Next steps

- [Results and exit codes](https://rehearsal.dev/retest/docs/reference/results.md): Interpret statuses, failures and completeness.
- [Recordings and evidence](https://rehearsal.dev/retest/docs/guides/recordings-and-evidence.md): Configure capture, pixel rules and retention.
- [Use Retest from code](https://rehearsal.dev/retest/docs/scaling-up/from-code.md): Consume live results and events in your own host.
