Claude
Skills
Sign in
Back

smoke

Included with Lifetime
$97 forever

Run an autonomous local smoke walk over a Jira ticket or adhoc investigation. Starts the local app(s), composes a walk plan from the acceptance criteria, dispatches the playwright-driver subagent to drive the browser while tailing app logs for exceptions. Local environment only — for deployed-env QA use /qa instead.

Code Review

What this skill does


In this skill, `<workspace>` refers to the Workspace path defined in the workspace `CLAUDE.md` `## Configuration` block. `<CloudId>` refers to the Jira CloudId from the same Configuration block.

# Smoke

Run an autonomous local smoke walk: start the app(s), walk the acceptance criteria via Playwright, watch the app log for exceptions, write a verdict. Local environment only.

The orchestrator (this skill) runs in the main conversation. The walk itself is dispatched to the `playwright-driver` subagent which owns the entire Playwright run end-to-end.

For deployed-env QA verification use `/qa <key> <env>` (env = `dev` | `qa` | `staging`). For pre-PR review use `engineer-toolkit:author-review`.

## Configuration

Read from the workspace `CLAUDE.md` `## Configuration` table:
- `Jira CloudId` (referred to as `<CloudId>` below)

Hardcoded in this skill:
- Active issues folder: `<workspace>\Active\`
- PlanningWorkspace fallback: `<workspace>\PlanningWorkspace\`
- Smoke profile cache: `<workspace>\.smoke\profile\<host>\`
- Jira key pattern (regex): `^[A-Z]+-\d+$`
- Playwright auth flags (Windows Integrated Authentication):
  - `--auth-server-allowlist=localhost,*.preferredcredit.net`
  - `--auth-negotiate-delegate-allowlist=localhost,*.preferredcredit.net`
- App startup timeout: 60 seconds (per app)

## Invocation

`/smoke <key-or-hint> [--vs] [--no-cross-write]`

- `<key-or-hint>` (required): Jira key (e.g. `CO-166`), adhoc slug, or substring hint.
- `--vs` (optional): the user starts the app(s) in Visual Studio and supplies log paths. Default = Claude starts via `dotnet run`.
- `--no-cross-write` (optional): suppress the `[smoke]` line written to the issue file's Discussion at end-of-run.

If `<key-or-hint>` is missing, print exactly:

```
Usage: /smoke <key-or-hint> [--vs] [--no-cross-write]
```

and stop.

## Argument Resolution

See [references/argument-resolution.md](../../references/argument-resolution.md). Apply the standard algorithm against `<workspace>\Active\` and store the resolved name as `<TARGET>`. No variant applies. Resolution runs BEFORE Phase 0.

## Phases

Run in order. Do NOT skip ahead.

### Phase 0: Setup

1. Ensure run folder exists:
   ```powershell
   New-Item -ItemType Directory -Path "<workspace>\Active\<TARGET>\Screenshots" -Force | Out-Null
   ```
2. Check for an existing `Active\<TARGET>\smoke.md`:
   - **`status: in-progress`** → print `Resuming /smoke for <TARGET>.` Skip Phase 3 (plan exists). Resume Phase 4 (driver re-dispatch).
   - **`status: passed | failed | aborted`** → prompt `R | F | C` (re-run / fork / close):
     - R → rename existing `smoke.md` to `smoke-<YYYYMMDDHHMMSS>.md`, continue as fresh.
     - F → same as R, but Phase 3 prompts the user for a new scope description before composing plan.
     - C → print `Closed.` and stop.
   - **Absent** → continue to Phase 1.

### Phase 1: Read per-repo `## Environments`

For each subdirectory `<repo>` in `Active\<TARGET>\AgentWorkspace\`:

1. Try in order:
   1. `Active\<TARGET>\AgentWorkspace\<repo>\CLAUDE.md` — the working clone on the feature branch.
   2. `PlanningWorkspace\<repo>\CLAUDE.md` — fallback for newer main not yet in feature branch.
2. Locate the `## Environments` section. Parse the fenced ```yaml``` block.
3. Required keys: `solution`, `startup_project`, `launch_profile`, `ready_signal`, `urls.local`.
4. If absent or incomplete, derive a candidate from `launchSettings.json`:
   - Find `<repo>\<startup_csproj>\Properties\launchSettings.json` (scan repo for a `Properties\launchSettings.json` whose parent project name matches the repo name pattern).
   - Pick the `https` profile if present, else the first profile.
   - `urls.local` = the `applicationUrl` value (take the first https:// entry if multiple semicolon-separated).
   - `ready_signal` = `"Now listening on: <url>"`.
   - `solution` = scan repo root for `*.sln` or `*.slnx`.
   - `startup_project` = relative path to the chosen `.csproj`.
   - `depends_on` = `[]`.
   - `urls.dev | qa | staging` = leave unset for now (only `urls.local` is required for /smoke).
5. Print the derived YAML block, ask `Save this to <repo>/CLAUDE.md (commit on current branch)? (Y / edit / N)`:
   - **Y** → write the file with a `# <repo>` heading and the `## Environments` section. Stage and commit:
     ```bash
     cd "<repo path>"
     git add CLAUDE.md
     git commit -m "[Claude] Add CLAUDE.md with ## Environments section"
     ```
   - **edit** → prompt for inline corrections, apply, re-confirm.
   - **N** → keep values in memory for this run only; do not write or commit.

Store the parsed values in memory keyed by repo name for use in subsequent phases.

### Phase 2: Start app(s)

The literal start commands (PowerShell port probe, bash build + spawn, PowerShell ready-signal poll, log-path freshness check) live in [references/start-apps.md](../../references/start-apps.md). The flow:

**`--vs` mode:** for each app, print `Start <repo> in Visual Studio (launch profile: <profile>, expected URL: <url>). Redirect stdout/stderr to a log file I can read. Reply with the absolute log path.` Wait for the user's response, validate the path (exists + modified within 5 min), re-prompt on failure. Set `apps_started_by: vs` in smoke.md.

**Default mode (Claude starts):** for each app, port-probe to detect already-running instances (prompt `R | K | A` if listening). Build each repo once (abort on non-zero exit). Determine start order via `depends_on` topo sort. Spawn each app in background via `dotnet run`. Poll each log for the `ready_signal` with a 60s timeout. Set `apps_started_by: claude` and record PID + shell ID per app for cleanup.

### Phase 3: Compose walk plan

1. Read `Active\<TARGET>\<TARGET>.md` for the Jira description (or adhoc Scope).
2. If `<TARGET>` matches a Jira key and the description looks truncated, fetch fresh via `getJiraIssue` for the `description` field.
3. Parse AC bullets and validation rules.
4. Compose a numbered plan:
   ```
   1. action: navigate to <primary_url>
      expect: page header reads "<title>", core elements render
   2. action: <playwright-executable instruction>
      expect: <observable from AC>
   ...
   N. action: free-roam — click 3-5 visible interactive elements, scroll, screenshot before/after
      expect: no new exceptions in app log(s); no obvious render failures
   ```
   - Skip the free-roam step for adhoc runs with no AC.
   - Validation rules become individual steps (one per case — "type 5, tab out, expect range error" is its own step).
5. Write `Active\<TARGET>\smoke.md` using this template:

```markdown
---
target: <TARGET>
started: <ISO 8601 timestamp>
status: in-progress
driver: playwright
apps_started_by: claude | vs
apps:
  - name: <repo>
    url: <url>
    log: <relative path>
    pid: <pid or null>
---

# Smoke Walk: <TARGET>

## Scope
<Jira summary>

<Jira description, verbatim>

## Plan
1. action: ...
   expect: ...
...

## Execution Log
_(Newest entries appended below.)_

## Verdict
_(Pending.)_
```

6. Print the plan to chat. Ask `R | E | A`:
   - R → continue to Phase 4.
   - E → ask `What would you like to change?`, apply edits to the file's `## Plan`, re-print, re-ask.
   - A → set `status: aborted` in frontmatter, write `## Verdict` noting `**ABORTED before execution.** User declined plan.`, skip to Phase 5.

### Phase 4: Dispatch driver subagent

The agent is a pure function: dispatch prompt in, return message out. It does not read or write smoke.md. /smoke owns the file format end-to-end — this phase composes the dispatch prompt from the plan, invokes the agent, then splices the agent's return back into smoke.md.

#### Step 1: Compose the dispatch prompt

Read the `## Plan` section of `Active\<TARGET>\smoke.md` and substitute it into the dispatch prompt template at [references/playwright-dispatch-prompt.md](../../references/playwright-dispatch-prompt.md). Also substitute the Apps tuples, the primary URL, the Screenshots dir, and the per-host profile dir fr

Related in Code Review