Skip to content
Back to skills

Review

ASecurity

Runs the load-bearing reviewer subagent over the current diff or a named spec/path — the full assertion-contract check suite. With url=<x>, audits a live URL instead (a11y + visual + closed vocab). Use before committing or merging a test, or when the user asks whether a test can actually fail.

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 19, 2026
testingrustgobashgit

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add its-magdy/qa-warden --skill review --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Review?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Review
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/its-magdy-review/badge)](https://www.skillsdirectory.com/skills/its-magdy-review)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
description: "Runs the load-bearing reviewer subagent over the current diff or a named spec/path — the full assertion-contract check suite. With url=<x>, audits a live URL instead (a11y + visual + closed vocab). Use before committing or merging a test, or when the user asks whether a test can actually fail."
argument-hint: "[spec-or-path — default: the working diff vs origin/main] | url=<url> [site=<id>]"
allowed-tools: Bash(bash "${CLAUDE_SKILL_DIR}/scripts/review-marker.sh" *)
---

**Two modes, same command.** No `url=` argument → diff-review mode (below, the default).
An argument that IS or STARTS WITH `url=<x>` (or is a bare URL) → **URL-audit mode**: skip
straight to the "URL-audit mode" section further down; everything between here and there is
the diff-review path and does not apply.

## Diff-review mode

Delegate to the **`reviewer`** subagent — the read-only gatekeeper that is the
**backstop** for the assertion contract (the `PreToolUse` hooks in `hooks/` catch
only the lexical FAILs and the healer/verifier assertion prohibition; every check
needing the paired spec, the `bugs/` tree or a judgment call rides on the reviewer
running, and this skill is what runs it). Without a shipped trigger the single most important quality
gate is the easiest one to forget — invoke it locally on **every change that touches
`tests/**`, `specs/**`, or `page-objects/**`**, before it is committed. Claude does not run in
CI; the attestation marker below and `/qa-warden:doctor` Check 15 are what surface a skipped review.

**Scope.** With no argument, the reviewer resolves the scope itself: the
`$BASE...HEAD` commit diff **unioned with the working tree and untracked files**,
with the fresh-repo / non-`main` / diverged-branch fallbacks in
`agents/reviewer.md` §Inputs — it never reviews an empty scope as PASS. The union
is what makes the local `/qa-warden:gen` → `/qa-warden:review` path work at all: the generator
never self-commits, so a just-authored spec+test are **untracked** and a
commit-range diff alone cannot see them. Pass `$ARGUMENTS` to narrow the review to
a single spec/test or an explicit path:

```bash
# Optional: normalize a bare <area>/<feature> to its spec path (same resolver as /qa-warden:gen).
[ -n "$ARGUMENTS" ] && TARGET=$(bash scripts/resolve-spec-path.sh spec "$ARGUMENTS" 2>/dev/null || echo "$ARGUMENTS")
```

Tell the reviewer explicitly: *"Use the `reviewer` subagent to review
`${TARGET:-the working diff}` and its imported page objects."*

**What it enforces** (full list + rationale in `agents/reviewer.md`): failable
`expect` (Check 1), YAML-step→assertion coverage (2), `must_fail_when`/`fail_if`
reified-or-waived (2b), oracle discriminating-power (2c, WARN + 2 mechanical FAIL sub-cases), oracle value
fidelity (2d), equality-invariant precondition scope (2e, WARN), no unlinked
`test.fixme`/`skip`/`fail` (3), closed 16-key vocab +
arg-shapes (4), no `waitForTimeout`/`networkidle` (5), metamorphic-twin
verification (6), context freshness (7, WARN), `@site:` validity against the
hot-tier `sites:` table (8), locator policy across `tests/**` **and**
`page-objects/**` (9), factory enforcement (10), hygiene (11), POM-abstraction
sanity (12, WARN), parallel-safety (13), approved-case traceability (14, WARN —
green-but-incomplete: an approved `.cases.md` row with no scenario and no
waiver), healed-locator drift (15, WARN). **Any FAIL blocks the PR**
(2e/7/12/14/15 are WARN-level; 2c is WARN except its two mechanically-decidable
FAIL sub-cases — otherwise surfaced, not blocking).

**Read-only.** The reviewer has no Write/Edit tools: it runs the checks
(including running metamorphic twins with `--reporter=line` so it never clobbers
the run-of-record) and emits **one PR comment** — blocking ❌ first, then WARNs,
then PASS summary. It fixes nothing; on a FAIL, kick the spec back to the
`generator` (or planner) named in the finding. It reruns no product tests beyond
the twins and hits no network.

**Attestation marker (feeds `/qa-warden:doctor` Check 15).** After the reviewer returns,
**first check that its report contains an explicit verdict line** (`PASS`, or
`FAIL` in any form including `FAIL (inconclusive-partial)`) for the reviewed pair.
**If it does not — a `maxTurns` cutoff, a crash, or any output with no verdict —
do NOT write a `.reviewed` marker at all**, and treat the invocation as if the
reviewer had not run (surface this to the human instead). A marker written from a
guess would launder a truncated review into a durable, doctor-trusted `PASS` — the
outcome the reviewer's own fail-closed rule (`agents/reviewer.md` §"Fail-closed on
inconclusive") exists to prevent; the marker file is a second, unguarded consumer of
the same verdict. Only once a verdict is
confirmed present, this skill writes `reports/review/<area>/<feature>.reviewed`
for each reviewed spec/test pair, containing:

```
commit: <git rev-parse HEAD>
spec_sha256: <sha256 of specs/<area>/<feature>.md>
test_sha256: <sha256 of tests/<area>/<feature>.spec.ts>
date: <YYYY-MM-DD>
result: PASS|FAIL
```

Write it with this skill's script, from the project root — ONE pre-approved call per pair
(this skill's `allowed-tools` rule), never an improvised `git rev-parse … && shasum … && printf …`
chain (a compound command needs a rule per subcommand, so those prompt, and are denied headless):

```bash
bash "${CLAUDE_SKILL_DIR}/scripts/review-marker.sh" specs/<area>/<feature>.md tests/<area>/<feature>.spec.ts PASS|FAIL
```

`/qa-warden:doctor` Check 15 reads the marker back through the same script (its `check` mode),
so writer and reader cannot disagree on the format. The script ships with the plugin; ignore any
`scripts/review-marker.sh` an older stamp left in the project.

Commit the markers with the reviewed change. They are agent-writable convenience for
`/qa-warden:doctor` Check 15 (which WARNs when a pair changed since its marker, and separately
when the recorded review is a `FAIL`), not proof:
anything that can write a file can forge one. The anti-forgery layer is a human reading the
PR — enforce it with a required approval in branch protection if you need one.

## URL-audit mode

Run a full audit of the URL by taking a direct AX-tree snapshot, then running the
`axe-a11y` and `visual-regression` skills plus the `reviewer` subagent (one subagent, two
skills). This mode does **not** use the `exploration` subagent — see step 1.

**Safety rail (CLAUDE.md §Environment):** run `bash scripts/prod-guard.sh` first — STOP and ask the user to confirm in-chat if it exits non-zero. **Pass the audit URL as an argument** — `bash scripts/prod-guard.sh "<the URL from $ARGUMENTS>"`: the argument goes through the *same* screening body as the env vars, so do **not** re-implement that host match by hand here.

Pass `site=<id>` in `$ARGUMENTS` to scope the audit to one site (id must match
a `sites[].id` in `specs/_context/app.context.md`). If omitted, audit defaults
to `site=app`.

**Validate the site id BEFORE scanning.** If `site=<id>` (or the default `app`) is not present as a
`sites[].id` in `specs/_context/app.context.md`, STOP and print the valid ids — an absent or typo'd
`app` id would otherwise resolve a bare/empty base URL and return a hollow "clean". **Also nudge
toward yield:** a single-URL audit of an a11y-clean page (e.g. `/login`) produces a technically-true
but hollow "clean". Offer the area's key routes (from the area context / route manifests) and prompt
to audit **auth-gated states** (e.g. `/tasks`, `/projects`), where reused chrome defects actually surface.

Steps (2–3 and 4 are independent — after step 1's prod-guard, launch the
`reviewer` subagent (step 4) **first, in the background**, then run steps 2–3 in
the main session while it works; only step 5 needs all three results. The
reviewer reads `specs/**` on disk, not the snapshot or scan output, so
serializing it behind two live browser scans wastes the whole audit's wall-clock):

1. Take a one-shot AX-tree snapshot of the target URL **directly via
   `npx playwright-cli`** (`goto` + `snapshot`) — do NOT delegate to the
   `exploration` subagent here. Take the snapshot **in an isolated session** —
   `npx playwright-cli -s=audit-<timestamp> goto <url> && npx playwright-cli -s=audit-<timestamp> snapshot`
   (pass the same `-s=` to the storage-state/cookie subcommands when
   authenticating), and `npx playwright-cli close -s=audit-<timestamp>` after the
   final screenshot — the shared `default` session can be mutated by a concurrent
   run mid-audit. Exploration has only `mode=hot` / `mode=area`,
   each of which *writes* a context file; it has no non-clobbering "scratch"
   mode, and this audit must not overwrite hot-tier or specialist context (for a
   context refresh use `/qa-warden:explore`). Keep the snapshot inline for steps 2–4;
   write nothing under `specs/_context/**`.

   **Auth-gated URLs — authenticate BEFORE the snapshot, or the audit false-cleans.**
   `playwright-cli open`/`goto` has **no `--storage-state` flag**, so an
   unauthenticated hit on an auth-gated route silently follows the redirect to
   `/login` and audits the *login* page — reporting a clean result for a page you
   never scanned (a false-clean is worse than friction). If the target is behind
   auth (resolve via the site's `storage_state_path` in
   `specs/_context/app.context.md`, e.g. `fixtures/auth.<site>.json`): first mint/load
   session state and inject it into the CLI context BEFORE `goto` — use the CLI's
   storage-state/cookie subcommands (exact names come from the binary: check
   `npx playwright-cli --help`, per the `playwright-cli` skill's no-stale-mirror
   policy), then `goto` the URL and CONFIRM you landed on it
   (assert the resolved URL is the target, not `/login`) before snapshotting. If you
   cannot confirm you're on the target page, STOP and report — do not audit the
   redirect target and call it clean.
2. Invoke the `axe-a11y` skill against the URL; record violations by severity.
   **Scan the ERROR/FAILURE states too, not just the default page (state-dependent-a11y gap).**
   A bare `goto` + scan only ever sees the pristine default state, so an a11y violation that
   **only renders after an interaction** — a low-contrast validation error alert after a failed
   submit, a toast/`role="status"`, an opened menu/modal, an empty-vs-populated list — is never
   reached (axe-core's own guidance: error messages aren't in the initial HTML; you must drive
   the interaction, THEN analyze). This is not hypothetical: the contrast defects these suites
   find live in the *error* state. So, for the target page's **documented failure/error states**
   (read the paired `specs/**` oracles + `_context/<area>.md` for the states that matter — e.g.
   the invalid-login error alert), drive the state via `playwright-cli` (fill an invalid value,
   submit, confirm the error surface is present) and re-run the `axe-a11y` scan **scoped to that
   state** before moving on. Record violations per state (default / error / …). If a state cannot
   be reached non-destructively, say so — do not silently scan only the default and call it clean.
3. Invoke the `visual-regression` skill; capture a baseline screenshot or diff.
   Note: `toHaveScreenshot()` baselines land under Playwright's default
   `tests/<spec>.spec.ts-snapshots/` (platform-suffixed, e.g. `-darwin`), per the
   `visual-regression` skill. `artifacts/visual/` is only an optional override path,
   not the default — follow the skill. macOS-authored baselines diff-fail on Linux CI;
   pin the runner OS or keep per-OS baselines before committing any real baseline.
   **If NO managed spec covers this URL and you must author a throwaway spec to host the
   `toHaveScreenshot()` call, name it `tests/_audit-<slug>.spec.ts` (underscore-prefixed)**
   so the nightly (`testIgnore: '**/_*.spec.ts'`) and `/qa-warden:doctor` Check 3 both skip it
   (P-03/P-05). **Never** leave a committed, un-prefixed, nightly-running visual spec with an
   OS-locked baseline — that turns a read-only probe into a permanent Linux-CI red. Prefer
   `artifacts/visual/` (gitignored) for a one-off baseline you don't intend to keep.
4. **Resolve which specs reference this URL FIRST — the reviewer has no URL→spec mode.**
   The `reviewer` subagent scopes from a git diff, a whole-tree fallback, or an **explicit
   file list** (its documented third input mode, §Inputs); it cannot take a bare
   URL. So before delegating, resolve the spec set yourself: extract the URL's path (e.g.
   `/login`, `/admin`) and grep `specs/**/*.md` for specs whose `steps:`/`Navigate` reference
   it (`grep -rlE "<path>(/|[\"'[:space:]]|$)" specs --include='*.md'`, plus any spec whose
   `site:`+area maps to the route). Then branch on the result — **never return a bare PASS on an
   unresolved URL:**
   - **≥1 spec references the URL:** pass that explicit spec list to the reviewer as its
     explicit-file-list scope. The reviewer's **Check 4 result is the closed-vocab audit**: it
     confirms every assertion uses the canonical closed oracle vocabulary (**the 16-key set defined
     in the `test-case-contract` skill**, which the reviewer preloads; do NOT restate the key list
     here). Report its free-form-assertion and missing-`must_fail_when` findings.
   - **ZERO specs reference the URL:** emit a **structured `COVERAGE-GAP`** line in the report
     (`COVERAGE-GAP: no spec references <url> — this page is UNTESTED (vocab-clean ≠ covered)`),
     distinct from PASS. A wholly-untested page must read as an explicit gap, never a green
     closed-vocab audit — a vacuous PASS on a brand-new URL is the worst outcome for an audit.
5. Aggregate to `reports/audit-<timestamp>.md`: a11y findings, visual diff
   summary, vocab violations, and actionable remediation bullets.

Files in this skill

  • SKILL.md13.6 KB
  • scripts/review-marker.sh6.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.