/e2e — Forensic Pre-Launch Test Pipeline
One command. Six phases. Full app validation. Re-invocable: each call relaunches the entire pipeline. State lives in
.audit/test-complet-<date>/.
When to use
Invoke at major checkpoints:
- Before a production launch
- After a milestone is marked complete (M1, M2, ...)
- After a large refactor that touched many pages
- Weekly QA cadence during pre-launch phase
- When the user says: "fais un test complet de l'application", "big test", "test toute l'app"
When NOT to use
- For a single bug fix → use
/debugauditor direct Playwright - For a single page UX review → use
/uiuxaudit --url=<page> - For a single API endpoint → use
/apiaudit --files=<path>
Dynamic Workflow orchestration
/e2e is a fan-out audit pipeline, not a linear script. The natural unit of
parallelism is the auto-detected domain (Phase 1). Orchestrate it as a
Dynamic Workflow:
- Plan — Phase 1 inventories pages and emits
domains.txt. Domain count is unknown until recon runs, so this is a loop-until-dry discovery: never hardcode a domain list, never assume project shape..expected-workers(= domain count) is the sweep marker — every detected domain MUST yield a worker beforedone_cleanis legal (the Kommu/Causio premature-done gate). - Fan out — Phase 4 dispatches ONE
/debugauditworker per domain in parallel (load-aware viaomega-dispatch-budget.sh). Workers are file-disjoint by route, so they run concurrently (R-SCOPE). - Adversarially verify — a single worker's per-page verdict is an input,
never the verdict (R-VERIFY). Before Phase 6 accepts a domain as
pass, re-grade eache2e-<domain>.jsonthrough ≥3 independent skeptic lenses and require 2-of-3 consensus:- Runtime lens — does the screenshot + console + network log actually show the workflow completing? (First Law: runtime over claim.)
- Spec lens — does the page satisfy its
docs/FEATURES/F-XXX-*.mdspec, or only render without function? - Regression lens — did any previously-passing page silently break?
A domain passes only on 2-of-3 agreement; a 1-of-3 or split → downgrade to
pendingwith the dissenting evidence cited, never averaged away.
- Synthesize yourself — Phase 6 is YOUR synthesis, not a paste of worker
summaries. Merge verdicts, compute the
/100score, rank next-steps. The report owner reconciles disagreements with cited evidence.
No-hallucination guardrail: every verdict in final-report.md carries
evidence — a screenshot path, a console/network log line, or a file:line
(R-CITE). A page with no captured artifact is untested, never pass. A 403 /
401 / auth-blocked surface is an ABORT, never a silent PASS (L5).
CLI
/e2e # full pipeline (READ-ONLY — no code changes)
/e2e --full-arsenal # all 17 Quality Arsenal audits/domain (vs /debugaudit only)
/e2e --auto-dev # also dev MVP UI for placeholders (Phase 5)
/e2e --resume # continue from last completed phase
/e2e --domain=safety # only one auto-detected domain
/e2e --page=cast-availability # single page
/e2e --project-dir=/path # override project root
Default is read-only. Phases 0-4 + 6 inventory, test, and report without
touching code. Phase 5 (dev placeholders) is opt-in via --auto-dev — it
dispatches dev workers that commit + push. This reversal (was opt-out --skip-dev
in v1.0.0) follows Karpathy "surgical changes": a test command must not silently
mutate the codebase. --skip-dev is still accepted as a deprecated no-op.
Default project dir: $PWD (the directory Claude is invoked from).
Output layout
.audit/test-complet-<YYYY-MM-DD>/
├── preflight.json # Phase 0: stack + env check
├── page-inventory.json # Phase 1: routes + states + auto-detected domain
├── page-inventory.md # Phase 1: human-readable summary
├── domains.txt # Phase 1: auto-detected domains (one per line)
├── .expected-workers # Phase 1: sweep-completeness marker (int)
├── .last-phase # --resume marker (last completed phase number)
├── e2e-<domain>.json # Phase 4: per-domain test results
├── screenshots/<page>/ # Phase 4: per-workflow PNGs
├── dev-placeholders.json # Phase 5: dispatched dev workers + commits
└── final-report.md # Phase 6: /100 score + grade + ranked next-steps
Protocol — 6 phases (0 → 6, no dead phase)
Each phase is one bash script in scripts/. Phases run sequentially.
If a phase fails, the pipeline halts and reports pending. --resume
reads .last-phase and continues from the next phase.
Phase 0 — Preflight (scripts/00-preflight.sh) — NEW in v1.1.0
Goal: Fail fast if the stack/env is wrong, before any heavy work.
Hard checks (abort on fail): package.json, next dependency, a
app/dashboard or src/app/dashboard directory.
Soft checks (warn, continue): convex/, @clerk/nextjs, components/ui,
Playwright installed, .env.local, and 5 required env vars.
Writes preflight.json with detected prod URL for downstream phases.
Phase 1 — Recon (scripts/01-recon-pages.sh)
Goal: Inventory every dashboard page, classify state, auto-detect domains.
Steps:
- Find
(src/)?app/dashboard/**/page.tsx(both layouts supported) - For each page extract: route, file, domain = first route segment
(auto-detected — no hardcoded project-specific list), state,
feature_id (matched to
docs/FEATURES/F-*-<slug>.md), spec path, slug. - State detection —
placeholderif the file matches any pattern in.audit-placeholder-pattern.txt(project-overridable; default set includesDeferredFeatureShell,en cours d'assemblage,ComingSoon,PlaceholderPage,WorkInProgress,NotImplementedYet);partial_implif no data hook (useQuery|useMutation|useAction|fetch|axios); elsefull_impl. - Write
page-inventory.json(jq-pure, no fragile string building),page-inventory.md,domains.txt, and.expected-workers(= domain count → consumed byoracle-mark-done.shsweep gate so a prematuredone_cleanis downgraded topending).
Phase 3 — Test infra (scripts/02-test-infra-setup.sh)
Goal: Install Playwright + axe-core, set up auth helper and seed data helper.
Steps:
npm install -D @playwright/test @axe-core/playwright(idempotent — skip if installed)npx playwright install chromium(idempotent)- Create
e2e/dashboard-test-suite/clerk-auth.ts— uses Clerk Backend API sign-in-token + Frontend API ticket strategy (mirrors~/.claude/lib/clerk-auth-browse.sh). Sets__session+__client_uatcookies on the Playwright context. Reads admin user ID fromE2E_CLERK_USER_IDenv var. - Create
e2e/dashboard-test-suite/seed-test-data.ts— Convex client that creates a test production + 5 scenes + 10 cast + 5 crew + 3 locations + 1 callsheet. Idempotent (usesupsertByIndex). - Create
playwright.config.tsif missing — viewports: mobileiPhone 13+ desktop1440x900. Reporter:json+html.
Phase 4 — E2E tests per domain (scripts/03-run-e2e-tests.sh)
Goal: Run real forensic audits per auto-detected domain.
Steps:
- Read
domains.txt(auto-detected in Phase 1 — NOT a hardcoded list) - For each domain, dispatch ONE worker via
~/.aisb/lib/dispatch-to-session.sh. The worker prompt's first line is/debugaudit --scope=...— it invokes the real 18-phase forensic skill, never paraphrased prose steps (per CLAUDE.md AUDIT KEYWORD DETECTION mandate). The prompt passes the exact route list, prod URL (frompreflight.json), and a strict scope boundary. The worker authenticates viaclerk-auth.ts, screenshots each workflow step, runs axe-core, captures console + network failures, and writese2e-<domain>.jsonwith per-page verdict. - Workers run in parallel (CPU Guard auto-queues if VPS saturated).
- Wait loop up to 60min for all
.done.json..last-phaseset to 4.
Phase 5 — Dev placeholders (scripts/04-dev-placeholders.sh) — OPT-IN
Goal: Ship MVP UI for every placeholder page.
Disabled by default. Runs only with --auto-dev (sets AUTO_DEV=1).
A pure test command must not silently mutate the codebase — this is the
Karpathy "surgical changes" reversal from v1.0.0's opt-out --skip-dev.
Steps (when --auto-dev):
jqfilterstate == "placeholder"from inventory (no regex fragility)- For each placeholder, dispatch ONE dev worker (parallelism 3, CPU Guard):
- Read
docs/FEATURES/F-XXX-*.md - Scaffold MVP UI: spec sections, shadcn/ui, Convex
useQuery/useMutation - Create
convex/<feature>.tsif missing;convex/schema.ts+= tables (.bakfirst) - Build via
~/.aisb/lib/safe-npm-build.sh(CPU mutex) - Commit + push (auto-deploy)
- Read
- Wait for all dev workers
.done.json..last-phaseset to 5.
Phase 6 — Aggregate report (scripts/05-aggregate-report.sh)
Goal: Merge all results, produce a normalized /100 scored report.
Steps:
- Merge all
e2e-<domain>.json(auto-detected domains fromdomains.txt) - Compute normalized /100 score (Quality Arsenal canon — weighted axes):
- Functional coverage (% pages passing E2E) — 50%
- Completeness (full_impl / total) — 25%
- Domain coverage (domains tested / detected) — 15%
- Placeholder ratio (inverted: fewer = better) — 10%
- Assign grade (F/D/C/B/A/A+) + verdict (needs work / acceptable / launch ready)
- Write
final-report.md: score breakdown table, executive summary, per-domain breakdown, ranked next-steps (failing pages → placeholders → untested domains → re-run), artifacts..last-phaseset to 6.
Failure handling
| Phase | If it fails | Action |
|---|---|---|
| 0 (preflight) | hard check fails | Abort with exit 2 + preflight.json diagnosis |
| 1 (recon) | page-inventory.json not written |
Halt — manual intervention |
| 3 (infra) | npm install fails |
Halt — check package.json permissions |
| 4 (e2e) | One worker fails | Others continue. Report flags partial coverage. |
| 5 (dev) | One dev worker fails | Others continue. Phase 6 reports unshipped. |
| 6 (report) | Aggregation fails | Halt — pending with diagnosis |
Resumable: each phase writes .last-phase. --resume skips completed
phases. Idempotent: without --resume, re-invoking re-runs all phases;
outputs are date-stamped so runs coexist.
Sweep-completeness gate: Phase 1 writes .expected-workers (= domain
count). oracle-mark-done.sh reads this; if fewer audit workers completed,
a premature done_clean is auto-downgraded to pending. This is the
direct fix for the Kommu/Causio incident (2026-05-17) where an oracle
self-declared done on an under-dimensioned plan.
Expected runtime
| Project size | P0 | P1 | P3 | P4 | P5 (--auto-dev) | P6 | Total |
|---|---|---|---|---|---|---|---|
| Small (10 pages, 2 ph) | 5s | 1m | 3m | 5m | 15m×2=30m | 1m | ~40m / ~10m read-only |
| Medium (40 pages, 10 ph) | 5s | 3m | 3m | 15m | 15m×10 (3-parallel)=50m | 2m | ~75m / ~23m read-only |
| Large (82 pages, 29 ph) | 5s | 5m | 3m | 30m | 15m×29 (3-parallel)=145m | 3m | ~3-4h / ~41m read-only |
No Time Panic: full quality on every page. Default (no --auto-dev) is
read-only and skips Phase 5 entirely — the fast, safe path.
Required environment
The project being tested must have these env vars set (locally or in CI):
E2E_CLERK_USER_ID=user_xxx # admin Clerk user for auth helper
CLERK_SECRET_KEY=sk_test_xxx # Backend API key
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
NEXT_PUBLIC_CLERK_FRONTEND_API=clerk.xxx.dev
NEXT_PUBLIC_CONVEX_URL=https://xxx.convex.cloud
NEXT_PUBLIC_APP_URL=https://app.example.com # production URL to test against
If any are missing, Phase 3 halts and writes a worker-blocked-*.json listing the gaps.
Cross-references
~/.claude/lib/clerk-auth-browse.sh— Clerk authenticated browser pattern (source ofclerk-auth.ts)~/.aisb/lib/safe-npm-build.sh— CPU mutex (mandatory for build commands)~/.aisb/lib/dispatch-to-session.sh— worker dispatch (parallel Phase 4 + 5)~/.claude/rules/46-no-time-panic.md— no streamlined variants~/.claude/commands/debugaudit.md— single-page runtime forensic~/.claude/commands/uiuxaudit.md— single-page design forensic
Orchestration (how Claude runs this)
When invoked, parse flags then run phases in order. With --resume, read
.audit/test-complet-<date>/.last-phase and skip phases ≤ that number.
SK=~/.claude/skills/e2e/scripts
PD="${PROJECT_DIR:-$PWD}"
OD="$PD/.audit/test-complet-$(date +%Y-%m-%d)"
ARGS="$*"
RESUME_FROM=-1
case "$ARGS" in *--resume*) [ -f "$OD/.last-phase" ] && RESUME_FROM=$(cat "$OD/.last-phase") ;; esac
case "$ARGS" in *--auto-dev*) export AUTO_DEV=1 ;; esac
case "$ARGS" in *--full-arsenal*) export AUTO_ARSENAL=1 ;; esac # v1.2.0 #4: all 17 audits/domain
# Phase 0 always runs (cheap, fail-fast — aborts pipeline on hard fail)
bash "$SK/00-preflight.sh" "$PD" "$OD" || exit 2
[ "$RESUME_FROM" -lt 1 ] && bash "$SK/01-recon-pages.sh" "$PD" "$OD" # Phase 1
[ "$RESUME_FROM" -lt 3 ] && bash "$SK/02-test-infra-setup.sh" "$PD" # Phase 3
[ "$RESUME_FROM" -lt 4 ] && bash "$SK/03-run-e2e-tests.sh" "$PD" "$OD" "${DOMAIN:-}" # Phase 4
[ "$RESUME_FROM" -lt 5 ] && bash "$SK/04-dev-placeholders.sh" "$PD" "$OD" # Phase 5 (opt-in)
[ "$RESUME_FROM" -lt 6 ] && bash "$SK/05-aggregate-report.sh" "$PD" "$OD" # Phase 6
Phase 2 was removed in v1.1.0 (was a no-op). --resume default -1 means a
fresh run executes every phase; with --resume it skips phases ≤ .last-phase.
TLDR
/e2e # READ-ONLY: P0→P1→P3→P4→P6
/e2e --auto-dev # also P5 (dev placeholders, commits)
/e2e --resume # continue from .last-phase
→ Phase 0: preflight (stack + env, fail-fast)
→ Phase 1: inventory + AUTO-DETECT domains + sweep marker
→ Phase 3: setup Playwright + Clerk auth + Convex seed
→ Phase 4: parallel /debugaudit per domain (real forensic skill)
→ Phase 5: [opt-in] parallel dev of placeholders (commit + push)
→ Phase 6: final-report.md — /100 score + grade + ranked next-steps
Output: .audit/test-complet-<date>/final-report.md — /100 launch readiness verdict.
Changelog
v1.2.0 (2026-05-17) — Honest-coverage release (closes 3 overstated claims):
- #1 Full-app scan: Phase 1 now inventories the ENTIRE
app//src/app/(marketing, auth, public, landing, pricing, dashboard) — not dashboard only. Each page gets anareafield; report shows per-area breakdown. "Toutes les pages" is now true, not just dashboard. - #3 Adaptive dispatch: Phase 4 uses
omega-dispatch-budget.sh(load-aware) instead of fixedMAX_PARALLEL=4. Consistent with the system-wide Defense D fix —/e2ecan no longer recreate the Kommu/Causio CPU meltdown by flooding a fixed batch into a saturated box. Hard ceilingTCA_MAX_PARALLELstill caps. - #4
--full-arsenal: optional flag runs all 17 Quality Arsenal audits per domain (/audit-orchestrator full) instead of/debugauditonly. Default stays/debugaudit(fast). Now "full test complet" is achievable, not implied.
v1.1.0 (2026-05-17) — Hardening release:
- Phase 0 preflight (fail-fast stack/env check)
- Domains auto-detected from route segments (was hardcoded 8 film-production clusters; skill is now genuinely portable as its description claims)
- Dev is opt-in
--auto-dev(was opt-out--skip-dev) — test ≠ mutate - Phase 4 workers invoke real
/debugaudit(was paraphrased prose — violated CLAUDE.md audit-keyword mandate) - Sweep-completeness marker → integrates with
oracle-mark-done.shgate (prevents the Kommu/Causio premature-done incident on long sweeps) --resumevia.last-phase; jq-pure JSON (no fragile string building)/100normalized score + grade + ranked next-steps (Quality Arsenal canon)- Removed Phase 2 no-op (dead code)