Help us improve
Share bugs, ideas, or general feedback.
From session-orchestrator
Executes web tests via Playwright (Microsoft). Captures AX-tree snapshots, screenshots, and console output under deterministic run directories for orchestrator parsing.
npx claudepluginhub kanevry/session-orchestrator --plugin session-orchestratorHow this skill is triggered — by the user, by Claude, or both
Slash command
/session-orchestrator:playwright-driverhaikuThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Before anything else, read and internalize `soul.md` in this skill directory. It defines WHO you are — a thin executor, not an orchestrator. Every action in this session should reflect that identity.
Automates browser tasks via Playwright CLI for AI agents: navigate pages, take snapshots/screenshots, fill forms, click elements from command line. Use with shell access.
Automates headless E2E tests with Playwright MCP, including navigation, element interaction, verification, and form handling. Use for CI/CD test automation or cross-browser testing.
Browser automation toolkit using Playwright MCP for testing web applications. Navigate pages, click elements, fill forms, take screenshots, verify UI, check console logs, debug frontend issues, and validate responsive design.
Share bugs, ideas, or general feedback.
Before anything else, read and internalize soul.md in this skill directory. It defines WHO you are — a thin executor, not an orchestrator. Every action in this session should reflect that identity.
Read skills/_shared/bootstrap-gate.md and execute the gate check. If GATE_CLOSED, invoke skills/bootstrap/SKILL.md and wait for completion. If GATE_OPEN, continue.
The PRD originally referenced @playwright/cli — that wording is WRONG. Do not use it.
| Package | Version (2026-05-14) | Status |
|---|---|---|
playwright | 1.60.0 | Canonical — use this |
@playwright/test | 1.60.0 | Test framework (same release train) |
@playwright/cli | 0.1.13 | Unrelated, unstable — DO NOT USE |
@playwright/mcp | 0.0.75 | MCP adapter — R5 hard-gate blocks this |
Verified via npm view playwright version → 1.60.0 (2026-05-14 probe). The binary the orchestrator dispatches is named playwright (not playwright-cli). Use playwright@^1.60.0 for compatible-minor updates or pin to playwright@1.60.0 for reproducibility.
npm i -g playwright@1.60.0
playwright install chromium # download browser binaries
For project-local install (preferred in CI):
npm install --save-dev playwright@1.60.0
npx playwright install chromium
The orchestrator (skills/test-runner/) dispatches this driver via Bash. Session naming follows the artifact-paths contract:
RUN_ID="${pid}-${ms_timestamp}" # from scripts/lib/test-runner/artifact-paths.mjs:makeRunId()
RUN_DIR=".orchestrator/metrics/test-runs/${RUN_ID}"
# Output paths via env vars (Playwright canonical):
# PLAYWRIGHT_HTML_OUTPUT_DIR=${RUN_DIR}/report
# PLAYWRIGHT_JSON_OUTPUT_FILE=${RUN_DIR}/results.json
# PLAYWRIGHT_HTML_OPEN=never
PLAYWRIGHT_HTML_OUTPUT_DIR="${RUN_DIR}/report" \
PLAYWRIGHT_JSON_OUTPUT_FILE="${RUN_DIR}/results.json" \
PLAYWRIGHT_HTML_OPEN=never \
playwright test \
--output "${RUN_DIR}/test-results" \
--reporter html,json \
--trace on \
--project chromium
Canonical: see https://playwright.dev/docs/test-reporters — reporter names are comma-separated; paths flow via env vars. See
scripts/lib/playwright-driver/runner.mjsfor the canonical invocation.
The orchestrator provides RUN_ID and RUN_DIR via environment variables. The driver reads these, executes Playwright, and exits. Nothing else.
All artifacts land under ${RUN_DIR}/. Structure:
.orchestrator/metrics/test-runs/<run-id>/
results.json # Playwright JSON reporter output — orchestrator parses this
report/
index.html # HTML report (served via `playwright show-report ${RUN_DIR}/report`)
test-results/
<test-name>/
trace.zip # Playwright trace bundle (open via `playwright show-trace`)
screenshots/ # pre-created by runner.mjs; content written by test fixtures
<test-name>-<step>.png # per-step screenshots (written by test fixture via page.screenshot())
ax-snapshots/ # pre-created by runner.mjs; content written by test fixtures
<test-name>.yaml # Playwright AX-tree dump via page.accessibility.snapshot() (written by test fixture, NOT by driver)
axe-<route-slug>-<timestamp>.json # axe-core JSON output (written by test fixture using @axe-core/playwright, NOT by driver)
console.log # NDJSON console output (written by test fixture via page.on('console', ...), NOT by driver)
Division of responsibility:
playwright test, sets reporter env vars (PLAYWRIGHT_HTML_OUTPUT_DIR, PLAYWRIGHT_JSON_OUTPUT_FILE, PLAYWRIGHT_HTML_OPEN), pre-creates ax-snapshots/ and screenshots/ directories before spawn so test fixtures can write into them without racing, captures the process exit code, and routes reporter output to results.json / report/.RUN_DIR env var provided by the driver.Token discipline: NEVER inline AX-tree dumps into the coordinator context — they balloon to 50–200K tokens. Always write to disk under ${RUN_DIR}/ax-snapshots/. The ux-evaluator agent reads from disk, not from prompt context.
Tests that need AX-tree data write it in the fixture, not via the driver:
// playwright.config.ts fixture pattern
test.afterEach(async ({ page }, testInfo) => {
const snapshot = await page.accessibility.snapshot();
const snapshotPath = path.join(
process.env.RUN_DIR ?? '.orchestrator/metrics/test-runs/default',
'ax-snapshots',
`${testInfo.title.replace(/\s+/g, '-')}.yaml`
);
await fs.writeFile(snapshotPath, yaml.stringify(snapshot));
});
The driver itself never reads or forwards AX snapshots. It only controls invocation.
To capture console output as NDJSON:
// in test or fixture
page.on('console', (msg) => {
const entry = JSON.stringify({
ts: Date.now(),
type: msg.type(),
text: msg.text(),
location: msg.location(),
});
fs.appendFileSync(path.join(process.env.RUN_DIR, 'console.log'), entry + '\n');
});
Default: headless (CI-friendly). Operator override via profile:
playwright test --headed # local debugging
playwright test --debug # opens Playwright Inspector
playwright show-trace "${RUN_DIR}/test-results/<test>/trace.zip"
playwright show-report "${RUN_DIR}/report"
The test-runner profile registry (.orchestrator/policy/test-profiles.json) controls headed/headless and browser selection — the driver stays simple and reads these from environment variables set by the orchestrator.
# Output paths via env vars (Playwright canonical):
# PLAYWRIGHT_HTML_OUTPUT_DIR=${RUN_DIR}/report
# PLAYWRIGHT_JSON_OUTPUT_FILE=${RUN_DIR}/results.json
# PLAYWRIGHT_HTML_OPEN=never
bash -c "PLAYWRIGHT_HTML_OUTPUT_DIR=${RUN_DIR}/report \
PLAYWRIGHT_JSON_OUTPUT_FILE=${RUN_DIR}/results.json \
PLAYWRIGHT_HTML_OPEN=never \
playwright test \
--output ${RUN_DIR}/test-results \
--reporter html,json \
--trace on \
--project ${PROFILE_PROJECT:-chromium}"
Canonical: see https://playwright.dev/docs/test-reporters — reporter names are comma-separated; paths flow via env vars. See
scripts/lib/playwright-driver/runner.mjsfor the canonical invocation.
| Code | Meaning | Orchestrator Action |
|---|---|---|
| 0 | All tests passed | Record pass, continue |
| 1 | At least one test failed | Failures become findings (non-fatal) |
| 2 | Framework error (network, browser-install) | Surface as driver error, halt run |
${RUN_DIR}/results.json — Playwright JSON reporter format (testRun.{expected,unexpected,skipped,status})${RUN_DIR}/test-results/**/trace.zip — trace bundles, one per test${RUN_DIR}/screenshots/**/*.png — per-step screenshots${RUN_DIR}/console.log — captured console as NDJSON${RUN_DIR}/ax-snapshots/*.yaml — Playwright AX-tree dumps via page.accessibility.snapshot() (written by test fixtures)${RUN_DIR}/ax-snapshots/axe-*.json — axe-core violation reports from @axe-core/playwright (written by test fixtures; consumed by ux-evaluator Check 2)Pinned: playwright@1.60.0 (verified 2026-05-14). The 1.x line is the long-term stable track — Playwright has not announced a v2. Upper-bound advisory: re-validate this skill when upstream crosses 1.65; check for behavioral shifts in JSON reporter format and trace bundle schema before re-pinning.
| Subcommand | Purpose |
|---|---|
playwright test | Run test suite |
playwright codegen <url> | Record tests interactively |
playwright install | Download browser binaries |
playwright show-report <dir> | Serve HTML report locally |
playwright show-trace <zip> | Open trace viewer |
playwright screenshot <url> | Single-shot screenshot |
playwright open <url> | Open browser with inspector |
@playwright/mcp for browser drive — 4× token cost. R5 grep-canary blocks this at validate-plugin time.${RUN_DIR}/ax-snapshots/.npx playwright per-test in a loop — install once, dispatch the local binary.RUN_ID everywhere.@playwright/cli@0.1.13 — that is an unrelated, low-version package. Use playwright@1.60.0.${RUN_DIR} — single source of truth for the orchestrator.| File | Purpose |
|---|---|
soul.md | Driver identity: thin wrapper, not orchestrator |