Skip to main content

Run change-aware regression tests

Give your agent a saved testing workflow, source-to-journey mappings, and the commits being compared. Playrunner calculates the changed files, follows their dependencies, and runs the mapped Playwright test files. Your agent can keep working, read progress and failures, then act on the evidence.

When impact cannot be established safely, Playrunner widens the run to the full configured suite. You can also request a full suite explicitly.

Availability and prerequisites​

This guide covers the updated upstream machine API and standalone MCP server, plus the Cloud MCP contract for hosted runs. Cloud requires the corresponding server rollout: before using it, check that the connected run_workflow schema includes regression and that get_run_feedback is available. Publishing this guide or installing a client does not upgrade an existing server.

The published playrunner@0.3.0 CLI does not include --regression or feedback. Until a release includes them, build the CLI from an upstream checkout containing this feature. From the repository root, with Node.js 20 or later:

npm ci --prefix packages/cli
npm run build --prefix packages/cli
node packages/cli/dist/cli.js --help
node packages/cli/dist/cli.js feedback --help

The CLI examples below use that source build against a local or self-hosted installation. Its help must list --regression and feedback; a version number alone does not establish feature support. Your API, orchestrator and Playwright runner must also include the change. Updating only the CLI or MCP server is insufficient.

Prepare a saved workflow with GitHub-backed TypeScript Playwright tests, a working target environment and any required Authentication Profile. Version 1 does not support inline tests, Python, sharding or AI Container steps for regression execution. The GitHub connection must allow access to every repository used for the comparison and dependency analysis.

Use PLAYRUNNER_URL for the intended installation and provide PLAYRUNNER_API_KEY through a protected environment variable. A scoped workflow:execute token can run and inspect allowed workflows; authoring requires an unrestricted workflow:write token. Browser device pairing with playrunner login does not replace the workflow API token.

1. Save the journey mappings​

Read the existing workflow before editing it. Add regression to each relevant Playwright node's saved config, preserving its repository, folder, environment, Authentication Profile and other settings. Use the workflow definition format or standalone MCP get_authoring_guide, get_workflow_editor and save_workflow tools. Preserve unrelated nodes and connections when saving the graph.

The following is the regression portion of a node's configuration, not a complete workflow. Replace the example repository names, paths and revision with your own values:

{
"regression": {
"version": 1,
"repositories": [
{
"repository": "example/shop",
"aliases": {
"@/*": "src/*"
}
},
{
"repository": "example/ui",
"revision": "3333333333333333333333333333333333333333"
}
],
"dependencies": [
{
"source": {
"repository": "example/ui",
"path": "src/Dropdown.tsx"
},
"consumer": {
"repository": "example/shop",
"path": "src/checkout.ts"
},
"specifier": "@example/ui/dropdown"
}
],
"journeys": [
{
"id": "checkout",
"title": "Complete checkout",
"sources": [
{
"repository": "example/shop",
"path": "src/checkout.ts"
}
],
"tests": [
{
"file": "tests/checkout.spec.ts",
"project": "chromium"
}
]
}
]
}
}

Each journey links application source paths to the test files that exercise that behavior. Keep the mappings reviewed alongside your tests: inferred dependencies cannot prove that an assertion covers a requirement.

FieldMeaning
repositoriesRepositories participating in impact analysis, in owner/name form. Pin an exact revision for any repository absent from the run's changed sources.
aliasesExplicit import aliases for that repository. Use a literal module name or one trailing /* on both sides, such as @/* → src/*.
dependenciesExplicit edges from a source to its consumer, including cross-repository and service relationships that static imports cannot infer. Use [] if none are needed.
specifierOptional literal import resolved by that edge, only in the named consumer. It does not resolve every import from that package.
journeys[].sourcesLiteral paths relative to the named repository root.
journeys[].testsLiteral test files relative to the Playwright test workspace. If the node selects a folder, paths are relative to that folder.

Paths must not contain globs, absolute paths or parent traversal. The optional test project verifies that discovery includes that project; it does not limit execution to that project. Selected files run across all configured browser projects. Read nodes[].discovery.files for the actual file/project pairs.

The example's dependency means a change to example/ui:src/Dropdown.tsx can affect checkout in example/shop. For a service relationship without a module import, omit specifier and keep the explicit source and consumer paths.

2. Describe the commits being compared​

Save this as regression-request.json, replacing the example hashes with real commits accessible through the GitHub connection:

{
"version": 1,
"mode": "affected",
"sources": [
{
"repository": "example/shop",
"baseSha": "1111111111111111111111111111111111111111",
"headSha": "2222222222222222222222222222222222222222"
}
]
}

Use distinct, complete 40-character hexadecimal commit SHAs. Branch names, abbreviated hashes and uncommitted working-tree changes are not accepted. Include one source entry for each changed repository, up to 16 unique repositories. In the example, example/ui is unchanged and uses the revision saved in the mapping. If it also changed, add its own base/head source entry.

Playrunner compares the immutable base and head snapshots and follows reverse dependencies through supported static JavaScript and TypeScript imports in both snapshots. It also follows the saved explicit edges. When the test repository is a changed source, execution pins it to that source's headSha; otherwise, pin its revision in the saved configuration.

Set "mode": "full" to request the full configured suite for a release that needs broader coverage. Keep the exact source comparison in the request. Full mode does not limit execution to the test files listed in the mappings.

3. Start once, then keep working​

With the server URL and API token already configured, start the saved workflow:

node packages/cli/dist/cli.js WORKFLOW_ID \
--regression regression-request.json \
--no-wait \
--json

Replace WORKFLOW_ID with the workflow's actual ID. Keep the returned execution ID and idempotency key. --no-wait returns after the server accepts the run; your agent can continue other work while Playrunner runs the tests. Stopping a client's wait does not cancel the workflow.

The CLI generates an idempotency key unless you supply --idempotency-key. If a start response is lost or ambiguous, retain the reported key and reuse it only for the same intended run. Use a fresh key for a new run, including an intentional full-suite follow-up. Once an execution ID is known, inspect that execution instead of starting it again.

The older --repository, --base-sha and related CI flags attach source-change context; they do not enable this selection contract. Do not combine them with --regression. A regression file takes precedence over ambient CI change-context variables.

4. Read incremental feedback​

Use the execution ID from the start response:

node packages/cli/dist/cli.js feedback WORKFLOW_ID EXECUTION_ID \
--after 0 \
--json

This command performs one read and never starts a workflow. Keep the returned nextCursor and use it as --after on the next read. Drain additional pages while hasMore is true, then leave a few seconds between polls while your agent continues its work. Read the final feedback when the workflow finishes.

A successful feedback request exits 0 even if tests failed. That exit code means the response was retrieved, not that the tests passed or a release is approved.

FeedbackWhat the agent should inspect
status, progressWorkflow state and test progress. Workflow completion alone is not a test verdict.
nodes[].planRequested and actual mode, selected journeys, reasons, hashes and fallback reasons.
nodes[].discoveryActual discovered test count and file/project pairs; blocked means coverage was not established.
changesCursor-based progress and terminal-attempt test outcomes, available while execution continues.
failuresCurrent unexpected failures, with test identity, mapped journey IDs and available error/artifact evidence.
expectedFailureCount, issuesFailures marked expected by test configuration, plus incomplete or blocked evidence.
artifactsAuthenticated report and plan paths. Open them using the same authorized installation/account.
truncated, evidenceIncompleteLimits or missing evidence that prevent treating the compact response as a complete passing result.

Live test outcomes are emitted after a pass or the final retry attempt. The final report is authoritative and reconciles retries; a failed attempt followed by a pass should not become a new failure alert. Failures marked expected with Playwright's test.fail() are reported separately as expectedFailureCount. That configuration does not prove a historical baseline, and it does not turn the failure into passing release evidence.

Compact feedback is bounded. Read the authenticated report and regression-plan.json artifact when details are truncated; plan omission counters identify omitted entries. A stale activity timestamp, missing final report or zero reported failures must not be interpreted as a passing suite.

Use Playrunner Cloud MCP​

Connect the Cloud MCP server, call get_account first, then read get_authoring_guide and the existing workflow before authoring. Use the Cloud tools' current schemas to save the node mappings above. If the connected server does not advertise regression and get_run_feedback, that deployment does not yet support this flow.

Cloud uses requestKey for the intended execution. Call run_workflow with these arguments, replacing the ID, commits and request key:

{
"workflowId": "YOUR_WORKFLOW_ID",
"requestKey": "630e66c6-5727-48f8-8db2-2e155def417e",
"regression": {
"version": 1,
"mode": "affected",
"sources": [
{
"repository": "example/shop",
"baseSha": "1111111111111111111111111111111111111111",
"headSha": "2222222222222222222222222222222222222222"
}
]
}
}

Regression requests currently use hosted execution on Playrunner servers. Do not combine them with executionTarget: "local", deviceId or source; the connected-machine path does not support this feature. Normal local worker runs remain a separate flow.

Keep the returned executionId and call get_run_feedback with both IDs:

{
"workflowId": "YOUR_WORKFLOW_ID",
"executionId": "RETURNED_EXECUTION_ID",
"after": "0"
}

Use nextCursor as the next after, drain hasMore pages and leave a few seconds between polls. Reuse the same requestKey only to recover an ambiguous start response for the same intended run. Starting a run does not install an automatic chat notification; the agent must poll or revisit its execution.

If the start response has status: "dispatch_unknown", the execution ID is reserved but dispatch is unconfirmed. This is not proof that tests started. Preserve both requestKey and executionId, then check feedback and recent run history for a bounded period, such as up to one minute with several seconds between reads. Feedback can return 404 while no execution record is visible for that identity; that does not prove that no work was dispatched.

If the execution appears, inspect its actual status and evidence. If it remains absent, stop polling and report that dispatch could not be confirmed, including the IDs for investigation. Retrying the same key will not dispatch another run; it does not guarantee eventual execution or completion. Do not automatically switch to a new key, start another run or report a passing result.

Use the standalone MCP server​

After connecting the standalone server, read get_authoring_guide and discover the saved workflow. Call run_workflow with the following arguments, replacing the workflow ID, hashes and idempotency key:

{
"workflowId": "YOUR_WORKFLOW_ID",
"idempotencyKey": "68f967ae-2847-44c9-bbd7-087532a06d38",
"regression": {
"version": 1,
"mode": "affected",
"sources": [
{
"repository": "example/shop",
"baseSha": "1111111111111111111111111111111111111111",
"headSha": "2222222222222222222222222222222222222222"
}
]
}
}

Then call get_run_feedback with the returned execution ID:

{
"workflowId": "YOUR_WORKFLOW_ID",
"executionId": "RETURNED_EXECUTION_ID",
"after": "0"
}

Use nextCursor as the next after and drain hasMore pages as with the CLI. The agent must poll or revisit the execution; starting a run does not install an automatic chat notification. Do not combine regression with changeContext or release in the same start request. Do not substitute Cloud's requestKey for standalone idempotencyKey.

When Playrunner widens or blocks the run​

Affected mode is conservative. Unmapped changes, unresolved imports, unsupported framework/template sources, broad configuration changes and incomplete dependency information can widen the run to the full configured suite. Import aliases and explicit edges improve coverage, but do not make unsupported framework relationships automatically understood.

Playwright discovery validates the selected test files before execution. If a mapped test or required project is missing, Playrunner widens to the full suite. If full-suite discovery fails or finds no tests, coverage is blocked. Repository access failures or unavailable commit snapshots can also prevent execution; they are not evidence that the change is safe.

Report the actual plan.mode, fallback reasons, discovered scope and any unverified remainder. A full fallback is broader testing, not proof that every user journey has an adequate test.

What the result proves​

The base commit is used for impact analysis. This workflow does not run the application at the base commit and compare a baseline test result. A failing head run is a failure or possible regression; it is not a confirmed new regression without comparable baseline evidence. Feedback therefore leaves regressionConclusion as not_evaluated.

Pinning source commits also does not prove that the application at your target URL is running that build. Release approval needs independently observed deployment identity, the agreed requirements and complete, fresh evidence for the intended candidate. Keep that release decision separate from focused test selection and workflow completion.