---
name: uat
description: >
  Generate a deterministic UAT test plan (`.plantest.yml`) for a generated
  SmartStack client app. Discovers the LIVE surface — nav tree + RBAC from the
  runtime SQL database, registered page views from the frontend
  componentRegistry, API endpoints from the controllers — scoped to a
  navigation path, projects it onto every role, and writes a byte-stable plan
  plus a drift-detection `.signature` sidecar. Use when the user asks to
  prepare UAT, generate a test plan, or verify what each role can reach.
argument-hint: "[Application[/Module[/Section]]] [--dry-run]"
phase: uat
cli: cli/uat-plan
allowed-tools: [Read, Glob, Grep, Bash]
---

# uat

Generates the `.plantest.yml` plan that drives user-acceptance testing of a
generated SmartStack app. Everything after discovery is pure and
deterministic: the same app state always yields a byte-identical plan
(timestamps are injectable), so plans can be diffed and committed.

## What the plan contains

- **routes[]** — one entry per (nav node × registered view × role) in scope:
  URL, expected access verdict per role (from the RBAC matrix), permission
  gate, title hint.
- **endpoints[]** (optional, `includeApi`) — one entry per controller action:
  method, route, per-role expected status (declared `[ProducesResponseType]`
  success status — resource creates declare 201 — or 403/401 when the role
  lacks the `[RequirePermission]`).
- **meta** — generation timestamp, scope, caps, and the source signature
  (`nav_sha` / `rbac_sha` / `registry_sha`) for drift detection.

## Prerequisites

- The app's database must be reachable (connection string resolved from the
  app's appsettings, or passed explicitly) — nav tree, roles and permissions
  are discovered live from `core.*` tables.
- The frontend `componentRegistry` and the API controllers are read from the
  project sources (`projectPath`).

## Invocation

```bash
npx --prefer-offline tsx skills/uat/cli/uat-plan/index.ts --spec '<JSON>' [--dry_run]
```

`--dry_run` prints the summary + file list without writing anything.

### Spec fields (`UatPlanInputSchema` — cli/uat-plan/types.ts)

| Field | Required | Default | Role |
|-------|----------|---------|------|
| `projectPath` | yes | — | Root of the generated client app under test |
| `path` | yes | — | Scope `Application[/Module[/Section[/Resource]]]` — a partial path expands the sub-tree |
| `name` | no | last path segment, or `all` | Plan artifact basename |
| `roles` | no | discovered from `core.auth_Roles` | Override the role set |
| `modes` | no | both | Execution modes written into the plan: `bfs`, `goto` |
| `includeApi` | no | `true` | Discover + emit the `endpoints[]` API axis |
| `caps` | no | schema defaults | Partial caps override: `tabs`, `buttons`, `forms`, `depth`, `actions_per_role` |
| `outDir` | no | `.application-test/uat/{application}` | Artifact directory |
| `connectionString` | no | resolved from appsettings | Explicit SQL connection |
| `generatedAt` | no | now | Injectable ISO timestamp (byte-stable plans in tests) |

### Output

JSON envelope on stdout (`lib/output.ts` contract): `success`, `data`
(application, scope, roles, route/endpoint counts, signature), `filesCreated`
/ `filesModified` (`{name}.plantest.yml` + `{name}.signature`), `warnings`
(incl. structural invariant violations — advisory, never a hard gate),
`nextSteps`.

## Pipeline status

- **Shipped (M1)** — `uat-plan` (this CLI): plan generation.
- **Planned (M2+)** — `/uat-provision` (tenant + one user per role) and
  `/uat-api` (endpoint execution against the plan) are referenced by the
  plan's nextSteps but are **not shipped yet**; until they land, the plan is
  consumed manually or by a UI agent.
