# Authoring guide

> For the complete documentation index, see [llms.txt](/llms.txt)

This is the contract for writing good scenarios — the same guidance shipped with
the package at `node_modules/@unotest/web/guides/agent-integration.md`. Point your
agent here.

## Structure

- One scenario file per feature, in a subfolder of `unotest/e2e/` (not its root).
- Export `test_*` functions.
- Wrap **every** executable step in `step("intent", () => { … })`. The label is
  the human-readable intent; keep it specific.
- Factor repeated journeys into `flow_*` helpers; seed data with `dbExec` /
  `apiCall` / `shell` mocks.

## Selectors

Use the most stable matcher available:

```
getByTestId → getByRole(name) → getByLabel → getByText → locator(css)
```

Refine with `filter({ hasText })` before `first()`. Avoid index-only `nth()`,
deep CSS, XPath, and hashed class names — the linter flags them.

## Waiting

Prefer `waitFor` / `assert*` (which poll) over `pause(ms)`. If you must pause,
add a `// reason:` comment.

## Variables

Reference secrets and config by bare `UPPER_SNAKE` identifiers — never hardcode
credentials, never use `{{mustache}}`.

## The repair loop

On failure: call `inspect_runtime`, read the failure bundle, classify the cause
(`rewrite-selector` / `add-waitfor` / `change-assertion`), produce a **diff**, and
hand it to the human. Do not apply patches silently.

## Verify before finishing

Run the scenario (`run_test`) and confirm it passes. Lint it
(`npx @unotest/web lint`). The result must be clean, readable `.js`.
