---
requiresProjectContext: true
---

# Playbook: QA Session EXECUTE

You are {{agent_name}}, the {{agent_role}} on the {{project_name}} project.
TEAM ROOT: {{team_root}}

## Your Task

QA Session **EXECUTE** phase for session **{{session_id}}** (work item {{item_id}}).

The SETUP and DRAFT phases have already finished: the engine spawned the
dev-up command as a managed-spawn, and the DRAFT agent wrote a
runner-native test file under `engine/qa-tests/{{session_id}}/`. Your
job is to **invoke that test against the live managed-spawn**, capture
the configured artifacts, and write the result sidecar the engine
ingests.

- **Session id:** `{{session_id}}`
- **Session phase:** `{{session_phase}}`
- **Managed-spawn target:** `{{managed_spawn_name}}` (live — query
  `http://localhost:7331/api/managed-processes/by-name?name={{managed_spawn_name}}`
  for the freshest port / base URL / health).
- **Test file (relative to `engine/qa-tests/{{session_id}}/`):** `{{test_file}}`
- **Flows (for context):** {{flows_raw}}
- **Runner hint (optional explicit runner):** `{{runner_hint}}`
- **Capture:** `{{capture}}`
- **Mode:** `{{session_mode}}`
- **qa-runs record id (use this in the sidecar's `runId` field):** `{{qa_run_id}}`

{{additional_context}}

## What "qa-session-execute" means

A `qa-session-execute` task is the **third** of three chained work items
the engine dispatches for each QA Session (SETUP → DRAFT → EXECUTE). The
engine resolved the same runner adapter the DRAFT phase used; its
`executeBrief()` hook produced the precise invocation command + flags
below.

### Runner execute brief

{{runner_execute_brief}}

### Result sidecar (REQUIRED)

Before exit, write the result sidecar at
`agents/{{agent_id}}/qa-run-result.json` with this exact shape:

```json
{
  "runId": "{{qa_run_id}}",
  "status": "passed",
  "summary": "1 sentence rollup the dashboard will render",
  "artifacts": [
    {
      "type": "screenshot",
      "path": "engine/qa-artifacts/{{session_id}}/01-login-form.png",
      "label": "Login form rendered",
      "capturedAt": "2026-05-20T20:42:00.000Z"
    }
  ]
}
```

Valid `status` values:

- `passed` — every step in the drafted test ran green and every required
  capture artifact was produced.
- `failed` — at least one assertion failed. Still write the sidecar with
  whatever artifacts you captured plus the failing-step summary.
- `errored` — the runner itself crashed or the managed-spawn went
  unreachable mid-run (use this sparingly — distinguishes infra failure
  from real product-level failure).

The engine consumes this sidecar in `engine/lifecycle.js` and calls
`qaRuns.completeRun({{qa_run_id}}, …)`. **If the sidecar is missing when
you exit, the engine marks the run `errored`** — always write it, even on
bail-out.

The `engine/qa-sessions.js#handleExecuteComplete` hook then reads the
qa-runs terminal status and transitions the session to `done` / `failed`
accordingly.

## No PR, no commit

`qa-session-execute` is a verification task. **Do not**:

- commit, push, or open a pull request — sessions are tracked by the
  session record + qa-runs record, not a merged PR
- modify project source — if a test step requires a code change, stop,
  leave changes uncommitted, and document the gap in the result summary
- start or restart the managed-spawn — the engine owns it
- modify the drafted test file — re-drafting belongs to the DRAFT phase
  (the human invokes it via POST `/api/qa/sessions/<id>/edit`)

## Failure path (REQUIRED)

If the managed-spawn is unhealthy, the runner CLI is missing, or you
cannot even attempt the test invocation, **do not silently exit
green**. Write:

```json
{
  "status": "failed",
  "summary": "<one-line human-readable explanation of what blocked EXECUTE>",
  "failure_class": "qa-session-execute-failed",
  "retryable": false,
  "needs_rerun": false,
  "nonce": "<value of MINIONS_COMPLETION_NONCE env var>",
  "artifacts": []
}
```

…AND write a matching `qa-run-result.json` sidecar with `status: "errored"`
so the qa-runs record terminalizes correctly. The session will transition
to `failed` with `failureClass: qa-session-execute-failed`.

## Working directory

```bash
# PowerShell
echo $env:MINIONS_AGENT_CWD
pwd

# bash/zsh
echo "$MINIONS_AGENT_CWD"
pwd
```

`MINIONS_AGENT_CWD` is the engine-resolved worktree root. Prefer it over
`pwd` for any cwd-sensitive command. The test file path is **relative to
the Minions root**: full path is
`<MINIONS_ROOT>/engine/qa-tests/{{session_id}}/{{test_file}}`. Capture
artifacts to `<MINIONS_ROOT>/engine/qa-artifacts/{{session_id}}/`.

## Long-Running Commands

Playwright runs, Maestro flows, and webdriver waits can be silent for
minutes. Run the normal CLI commands and wait for them to finish; do not
add progress pings or extra logging just to keep the engine active.

## Findings

Write findings to `{{team_root}}/notes/inbox/{{agent_id}}-{{item_id}}-{{date}}.md`
only after successful completion. Include:

- Session id + target summary
- Test file + runner adapter
- Per-step pass/fail
- Artifact paths (relative to `{{team_root}}`)
- Notes for the next EXECUTE on the same target (flaky selectors, env
  quirks, runner gotchas)

## Constraints

- Do not modify production code unless explicitly asked.
- Do not remove worktrees; the engine handles cleanup automatically.
- Do not start or restart the managed-spawn — the engine owns it.
- Always emit the `qa-run-result.json` sidecar before exit — even a
  single-field
  `{"runId": "{{qa_run_id}}", "status": "errored", "summary": "...", "artifacts": []}`
  is better than an absent file.
