---
name: xqa-spec
description: Create or edit *.test.md spec files in .xqa/specs/ through guided dialogue. Triggers on /xqa-spec or implied spec authoring intent ("I want to test X", "write a spec for Y", "update the Z spec").
license: MIT
---

# xqa-spec

## When to use

- User runs `/xqa-spec` with a flow description
- User implies spec authoring intent: "I want to test X", "write a spec for Y", "update the Z spec"

Detect implied intent and self-activate without requiring explicit slash command.

## Process

```
Explore → Detect mode → Interview (one question at a time) → Draft → Review → Write
```

IMPORTANT: Never generate a draft before the interview is complete. The user describes the spec; you transcribe it.

### 1. Explore

Time budget: complete within 10 tool calls. Do not surface findings yet.

**a. Existing specs and app context — run in parallel:**

MUST issue all of the following as a single parallel batch (one message, multiple tool calls):

- Glob `**/.xqa/specs/*.test.md` → read every result
- Read `.xqa/app.md` if it exists

Learn from specs: naming conventions, step granularity, level of detail.

**b. Codebase discovery — run in parallel:**

MUST issue all of the following as a single parallel batch:

- Glob `**/*Screen.tsx` | `**/*Screen.ts`
- Glob `**/screens/**/*.tsx` | `**/screens/**/*.ts`
- Glob `**/navigation/**` | `**/routes.ts` | `**/routes.tsx` | `**/router.ts`
- Glob `**/*Navigator.tsx` | `**/*Navigator.ts`

Read every Glob result that returns ≤ 5 files. When a Glob returns > 5 files, read only the first 3 results — prioritise files whose names match the flow the user described.

**c. Feature-specific scan (conditional):**

If the user named a specific feature or screen, run ONE additional parallel batch:

- Grep the feature name across `**/*.tsx`, `**/*.ts` (files with matches only)
- Grep for copy strings related to the feature in `**/*.ts` | `**/*.tsx` | `**/*.json`

Read up to 3 matching files. Stop.

**Capture silently:** screen names, navigation routes, copy strings, feature flag identifiers. This context is used only during step 3a reminders — never presented to the user unprompted.

### 2. Detect mode

| Condition                | Mode                                            |
| ------------------------ | ----------------------------------------------- |
| Matching spec file found | Edit — read it, ask which sections to change    |
| No match                 | Create — derive kebab-case filename from intent |

In **edit mode**: ask which sections to change before doing anything. Modify only those sections; preserve everything else verbatim.

### 3. Interview (create mode only)

Ask one question at a time. Wait for the answer before asking the next. Prefer multiple choice when options are known.

**Question sequence:**

1. **What flow?** — Confirm what's being tested if not already clear. Suggest a filename and `feature` name.
2. **Starting state** — "What's already set up? What state is the device/app in?" → becomes `## Setup`
3. **Steps** — "Walk me through the steps, one at a time. For each step, describe the intent (what the user is trying to do), and optionally the expected outcome and a hint about the current label or wording." → collect each step. Prompt for outcome only when user mentions something to verify. Prompt for hint only when current label wording is useful.
4. **Global assertions** — "Any overall things that should be true at the end of the flow?" → becomes `## Assertions` (skip if none)
5. **Timeout** — "Set a timeout in seconds? (optional, for long-running specs)" → becomes `timeout:` frontmatter (offer to skip)

IMPORTANT: Ask each question in its own message. Never batch questions.

### 3a. Code-informed reminders (during step collection)

After the user describes a step, you MAY offer AT MOST ONE code-informed follow-up reminder before moving to the next step. Phrase it as:

> "I also see <intent-first phrase> in the code — want to include it as a step? (source: `<file>`)"

Rules:

- Max one unsolicited suggestion per user-described step. No bulk proposals.
- Declined once → never re-offer that suggestion.
- Translate code findings into intent-first language BEFORE presenting. Component names, route names, and variable names must be rewritten as user goals.
- Copy strings belong in `hint:` only — never in the intent phrase.
- Always cite the source file the suggestion was derived from.
- If no code-backed reminder is worth offering, stay silent and move on.

### 4. Draft

Assemble using ONLY these frontmatter fields: `feature`, `timeout`. Do not add any other frontmatter field. `feature` MUST be present. `timeout` MUST be a positive number (seconds) if included.

Steps come from the user — never invent them. Use intent-first language: describe the user's goal, not literal widget taps. Present the full draft for review.

### 5. Review

Show the draft. Ask: "Does this look right, or anything to change?"

Iterate until approved. One round of changes per message.

### 6. Write

Before writing, verify the draft passes all checks:

- [ ] `feature` is present and non-empty
- [ ] frontmatter contains only permitted fields: `feature`, `timeout`
- [ ] `timeout` if present is a positive number in seconds (not a string, not zero)
- [ ] `## Setup` section is present
- [ ] `## Steps` section is present
- [ ] No step begins with `Tap "<literal label>"` or equivalent literal-widget references — steps use intent-first language
- [ ] No forbidden fields: `tags`, `max_steps`, `priority`, `type`, `description`, `id`, `author`, `version`, `entry`

Fix any failure before writing. Save to `.xqa/specs/<name>.test.md` only after explicit approval.

## Step Grammar

```
<intent phrase> [→ <outcome state>] [hint: <advisory text>]
```

- **Intent phrase** — imperative, action-oriented, describes the user's goal. No literal widget labels. Include a domain noun (e.g., "agreement", "asset", "settings").
- **Outcome state** — optional. Include only when the step has something to verify. Observable screen state or content predicate.
- **Hint** — optional. Free-form natural text describing expected label or qualities. Agent infers role (primary/secondary/dismissal) from context. Never use structured `role=` syntax.

### Valid examples

```md
1. Accept the terms and conditions → Portfolio screen visible [hint: "Agree and continue"]
2. Open the settings menu
3. Dismiss the backup reminder [hint: skip or maybe later button]
4. Enter the recovery phrase words in order → All 12 fields filled, Confirm becomes active
```

### Anti-patterns

```md
# Literal label as selector — breaks on rename

1. Tap the "Agree and continue" button

# Vague intent — agent has nothing to anchor on

2. Do the onboarding thing
```

## File format

FRONTMATTER SCHEMA — exact fields, exact types, no others:

```
feature    string           REQUIRED
timeout    positive number (seconds) OPTIONAL — omit if not provided
```

FORBIDDEN frontmatter fields — never generate these: `tags`, `max_steps`, `priority`, `type`, `description`, `id`, `author`, `version`, `entry`

CANONICAL OUTPUT FORMAT:

```md
---
feature: <string>
timeout: <seconds>
---

## Setup

<preconditions and starting state>

## Steps

1. <intent> → <outcome> [hint: <advisory>]
2. <intent>

## Assertions

- <global flow-level check>
```

Omit `timeout` line if not provided. Omit `## Assertions` section if none. Omit `→ <outcome>` or `[hint: ...]` per-step when not applicable.

## Rules

- Step grammar: `<intent> [→ <outcome>] [hint: <advisory>]` using the → character
- Outcome and hint are optional per step; include only when useful
- Steps come from the user — never invent them
- Intent-first language only; no literal `Tap "<label>"` references
- Write file only after explicit approval
- In edit mode, ask before touching anything

### Code exploration constraints

- Never present a pre-populated step list derived from code before the user has described the flow
- Never use component names, route names, or variable names as intent phrases — translate to user-goal language first
- Never place code-derived text in the intent phrase — copy strings belong in `hint:` only
- Never re-offer a suggested step after the user declines it once
- Never propose more than one unsolicited step per user-described step (no bulk suggestions)
- Always cite the source file when proposing a code-derived reminder
- Never infer the entire flow from navigation routes or screen stack and present it as a draft
