fleet-verify · git:20261009.a664025 · 2026-10-09 · sha256 302f41baa2b5956a
fleet-verify git:20261009.a664025B
Immutable. This exact content never changes and is served at /api/v1/blob/302f41baa2b5956a.
---
name: fleet-verify
description: Use after a UI or user-visible change and before you claim it works — it spawns ONE CCC verification lane that drives a real browser (gstack browse, or CCC's puppeteer snapshot as fallback) against the running app, checks the specific thing you changed, and reports a visual/behavioral verdict with a screenshot. Independent of your context; catches what a diff read and a unit test cannot.
allowed-tools: Bash
---
`/code-review` reads the diff. `pair-verify` runs a bug at two refs. Neither
opens the app and *looks*. Fleet-verify spawns one CCC lane that drives a
headless browser against the running dashboard (or your app), verifies the exact
change you describe, captures a screenshot as evidence, and reports a verdict.
It pairs CCC's spawn/report_to mechanics (`ccc-orchestration`) with gstack
`browse` (headless Chromium QA).
## Cost
**1 spawned session.** A real billed session on the kanban — state the count
before spawning. Skip it for pure backend/logic changes with no rendered surface
(there is nothing to look at); use a test or `pair-verify` instead.
## Preconditions — gather these BEFORE spawning
The lane can only check what you can point it at. Have all three:
- **(a) A running, reachable app + URL.** For CCC itself that is
`http://127.0.0.1:8090`. For another app, its dev-server URL. If nothing is
running, start it first (or say so in the prompt so the lane starts it).
- **(b) The exact thing to verify** — "the skills chip shows a count and the
status rail lists each subagent", not "check the UI". Name the selector,
text, or state you expect.
- **(c) The repo path.**
## Setup
```bash
CCC_URL="$(cat ~/.claude/command-center/port.txt 2>/dev/null || echo "${CCC_URL:-http://127.0.0.1:8090}")"
curl -sf --max-time 2 "$CCC_URL/api/version" >/dev/null 2>&1 || CCC_URL="http://127.0.0.1:8090"
curl -sf --max-time 2 "$CCC_URL/api/version" >/dev/null 2>&1 || CCC_DOWN=1
```
- Run every CCC curl with the **network sandbox disabled** (loopback is blocked
in the Bash sandbox and fails spuriously even when CCC is up).
- **URL-encode `repo_path`** in query strings.
## Spawning the verifier
```bash
curl -s -X POST "$CCC_URL/api/sessions/spawn" -H "Content-Type: application/json" -d @- <<'JSON'
{
"prompt": "Independent visual verification. Drive a headless browser and confirm a specific change. 1) Use gstack browse (the `browse` skill): `$B goto <url>`, then `$B text`, `$B js \"<expr>\"`, `$B is visible @<ref>` to check state, and `$B screenshot /tmp/fleet-verify-<slug>.png` for evidence. If gstack browse is unavailable, run CCC's `node snapshot.js` first (it writes snapshot.png). Do not substitute chrome-devtools: only use chrome-devtools after `curl -fsS --max-time 2 http://127.0.0.1:<debug-port>/json/version` returns Chrome JSON. 2) Verify EXACTLY this: <the specific thing — selector/text/state you expect>. 3) Report VERDICT (VERIFIED / NOT-VISIBLE / WRONG-STATE / APP-DOWN), the commands you ran, and the screenshot path as evidence. Be literal: report what you actually see, not what the change intended.",
"repo_path": "/abs/path/to/repo",
"report_to": "<your-session-id>"
}
JSON
```
- Omit `"model"` and `"reasoning_effort"` to use the server spawn defaults; if
you pass either, pass `"engine"` too (both are validated per engine, and the
effort ladder differs by engine: see `ccc-orchestration` § 2).
- CCC appends the return-address footer (`report_to`), so the verdict injects
back to you when the lane finishes.
## Waiting for the report
After spawning, **end your turn.** Tell the user a lane is verifying and give its
session id. The verdict arrives by injection — do **not** poll or sleep-loop. If
it never arrives, check `GET /api/sessions/spawned` for whether the lane is alive.
## Interpreting the verdict
- **VERIFIED** — the change renders/behaves as described, with a screenshot to
prove it. Ship it.
- **NOT-VISIBLE** — the lane could not find what you described. Either the change
did not take, or you pointed it at the wrong place. Investigate before claiming.
- **WRONG-STATE** — it rendered, but not as you expected. Read the evidence.
- **APP-DOWN** — nothing was running to verify. Start the app and re-run.
## Dry run
If the arguments contain `dry-run`, print the exact payload — session count (1),
the filled-in verifier prompt with URL and the specific check, and the target
repo — and POST nothing.
## Honest fallbacks
- **CCC down (`CCC_DOWN=1`):** run gstack `browse` (or `node snapshot.js`)
yourself against the running app, and in your claim say verification was
**self-run** — you know what the change was meant to do, so you are a weaker
skeptic than a fresh lane. Never pretend the spawn ran.
- **No browser tooling at all:** say so plainly and fall back to a functional
check (curl the endpoint, assert the JSON/DOM string). A string assertion is
not the same as *seeing* it render — flag the gap.