WP Codebox recipes use the wp-codebox/workspace-recipe/v1 schema. A recipe is
a declarative sandbox setup plus ordered workflow steps. The CLI validates the
recipe before booting the selected WordPress runtime, then returns a structured
artifact bundle after execution.
Use the generated schema and command catalog as the source of truth:
npm run wp-codebox -- schema recipe --json
npm run wp-codebox -- commands --jsonValidate recipes before using them in CI or documentation examples:
npm run wp-codebox -- recipe validate --recipe ./path/to/recipe.json --json
npm run wp-codebox -- recipe-run --recipe ./path/to/recipe.json --dry-run --json{
"schema": "wp-codebox/workspace-recipe/v1",
"runtime": {
"backend": "wordpress",
"wp": "latest"
},
"inputs": {
"mounts": [
{
"source": "../my-plugin",
"target": "/wordpress/wp-content/plugins/my-plugin",
"mode": "readonly"
}
]
},
"workflow": {
"steps": [
{
"command": "wordpress.run-php",
"args": ["code=echo get_bloginfo( 'name' );"]
}
]
}
}runtime.backend may be omitted. When present, wordpress is the neutral
WordPress runtime name and currently resolves to the WordPress Playground backend.
Existing recipes that specify wordpress-playground continue to work as a
compatibility spelling.
Raw Playground-oriented fields such as runtime.blueprint, runtime.phpVersion,
runtime.wordpressInstallMode, and Playground backend packages are advanced
compatibility fields. Prefer the neutral wordpress backend and recipe inputs
for new runtime setup where possible.
Recipe field names are case-sensitive. The current recipe schema accepts these top-level fields:
schemadistributionruntimeinputsworkflowfuzzRunartifactsprobesmetadata
inputs accepts these fields:
mountsworkspacesworkspace_preloadsextra_pluginscomponent_manifestdependency_overlaysruntimeEnvsecretEnvexternalServicespluginRuntimefixtureDatabasesfixtureUsersuserSessionssiteSeedsstagedFilessourcePackagesagent_bundlesinheritinheritance
Use inputs.extra_plugins, not inputs.extraPlugins. The camelCase form is an
old docs/example drift and is not part of wp-codebox/workspace-recipe/v1.
Use inputs.agent_bundles, not inputs.agentBundles, for runtime agent bundle
imports.
Use inputs.workspace_preloads for generic agent-runtime/workspace-preload
artifact contracts. WP Codebox materializes declared repositories as sandbox
workspace mounts; callers own the policy that decides which artifacts to pass.
Use inputs.externalServices to declare reviewer-safe boundaries for services a
recipe may observe while collecting browser or runtime evidence. The primitive is
product-neutral: it names the boundary, classifies the environment, declares host
sets, records the write policy, and lists secret environment variable names
without serializing secret values.
{
"inputs": {
"externalServices": [
{
"id": "checkout-staging",
"label": "Checkout staging API",
"environment": "staging",
"allowedHosts": ["api.example.test"],
"blockedHosts": ["api.example.com"],
"writes": "record-only",
"secretEnv": ["CHECKOUT_API_TOKEN"],
"redaction": {
"policy": "redact-fields",
"fields": ["authorization", "set-cookie"]
}
}
]
}
}Supported environment values are local, fixture, staging, production,
and external. Supported writes values are forbidden, record-only, and
allowed-with-approval. Supported redaction policies are metadata-only,
redact-fields, and omit.
Dry-run plans, run attestations, failure diagnostics, and browser evidence expose
only the declared boundary metadata and secret env names. When browser evidence
contains network-policy host observations, WP Codebox adds a safe correlation
summary from observed hosts to declared boundary ids where host names match
allowedHosts or blockedHosts.
inputs.extra_plugins mounts additional WordPress plugins before workflow steps
run. Each entry requires source or sourcePath and may include sourceSubdir,
mountSlug, pluginFile, activate, loadAs, and sha256. sourcePath is
the source root, sourceSubdir is an optional plugin directory below that root,
mountSlug is the WordPress plugin directory, and pluginFile is relative to
the mounted plugin slug.
{
"inputs": {
"extra_plugins": [
{
"source": "https://downloads.wordpress.org/plugin/bbpress.latest-stable.zip",
"pluginFile": "bbpress/bbpress.php",
"activate": false
},
{
"source": "../caller-runtime-substrate",
"slug": "caller-runtime-substrate",
"pluginFile": "caller-runtime-substrate/caller-runtime-substrate.php",
"activate": false,
"loadAs": "mu-plugin"
},
{
"sourcePath": "../monorepo",
"sourceSubdir": "plugins/example-plugin",
"mountSlug": "example-plugin",
"pluginFile": "example-plugin/example-plugin.php"
}
]
}
}Supported loadAs values:
plugin: mount below/wordpress/wp-content/plugins/<slug>and activate whenactivateis notfalse.mu-plugin: mount below/wordpress/wp-content/mu-plugins/wp-codebox-runtime/<slug>and load through WP Codebox's generated MU-plugin loader. Use this for sandbox runtime substrate, not user-visible plugins.
External HTTPS zip downloads are gated by WP_CODEBOX_ALLOW_NETWORK_DOWNLOADS=1.
Local paths are resolved relative to the recipe file.
inputs.sourcePackages materializes local recipe source directories below the
sandbox workspace. It is directory-only; use inputs.stagedFiles for single-file
staging. Each package declares a stable name, local source,
workspace-relative target, optional allow/deny path filters, and optional
provenance artifact registration.
{
"inputs": {
"sourcePackages": [
{
"name": "fixture-plugin",
"source": "./fixtures/plugin",
"target": "packages/fixture-plugin",
"allow": ["src*", "composer.json"],
"deny": ["src/secrets*"],
"artifact": true
}
]
}
}Targets are normalized under /workspace when they are not already absolute
workspace paths. Materialization uses WP Codebox prepared-source exclusions,
applies deny before allow, hashes the copied package, and writes
.wp-codebox-source-package.json into the staged package root with source,
filter, target, digest, and timestamp provenance. Validation emits blockers for
unsafe names, paths, and filters before runtime setup.
recipe build template compiles declarative source package input into generated
artifact declarations while preserving inputs.sourcePackages, so callers use
the same validation and run path as hand-written recipes without duplicate
mounts.
npm run wp-codebox -- recipe build template --options ./template-options.json --output ./recipe.jsonWorkflow steps are ordered command invocations:
{
"command": "wordpress.wp-cli",
"args": ["command=option get home"]
}Each args entry is a string. Command-specific argument names and repeatability
come from the command catalog:
npm run wp-codebox -- commands --jsonUse allowFailure: true or advisory: true for evidence-only workflow steps.
Failed advisory steps are reported in advisoryFailures and do not make an
otherwise successful recipe return success: false.
Recipes may declare a bounded, deterministic fuzz case skeleton with
fuzzRun.schema: "wp-codebox/fuzz-run/v1". This primitive does not generate
inputs or implement a fuzzing strategy. It gives callers a generic way to name
cases, attach input/hash/replay metadata, and run setup/action/assert/teardown
phases through the same command machinery as normal workflow steps.
Each case requires a stable case_id and at least one action step:
{
"schema": "wp-codebox/workspace-recipe/v1",
"workflow": {
"steps": [{ "command": "inspect-mounted-inputs" }]
},
"fuzzRun": {
"schema": "wp-codebox/fuzz-run/v1",
"cases": [
{
"case_id": "case-001",
"input": { "path": "/example" },
"inputHash": { "algorithm": "sha256", "value": "abc123" },
"phases": {
"setup": [{ "command": "wordpress.run-php", "args": ["code=update_option('case','case-001');"] }],
"action": [{ "command": "wordpress.wp-cli", "args": ["command=option get case"] }],
"assert": [{ "command": "wordpress.run-php", "args": ["code=if (get_option('case') !== 'case-001') { exit(1); }"] }],
"teardown": [{ "command": "wordpress.run-php", "args": ["code=delete_option('case');"] }]
},
"artifacts": [{ "name": "case-log", "path": "/tmp/wp-codebox/fuzz/case-001.json" }],
"replay": { "seed": "seed-001", "inputRef": "fixtures/cases/case-001.json" }
}
]
}
}The runtime output includes fuzzRun.schema: "wp-codebox/fuzz-run-result/v1"
with per-case status, timing, command references/results, declared artifact
references, diagnostics, and replay metadata placeholders. Fuzz case phase steps
are ordinary recipe commands, so command permissions and validation come from the
existing command catalog.
Use wordpress.plugin-setup for bounded plugin installation and inventory in a
contained runtime. It accepts WordPress.org slugs only; paths, URLs, and package
files are rejected so callers cannot mutate or read parent-site paths.
{
"command": "wordpress.plugin-setup",
"args": ["action=install", "plugin=my-plugin", "activate=true"]
}Use wordpress.plugin-state when a recipe or runtime caller needs structured
WordPress plugin state instead of shelling out to wp plugin directly. The
command accepts a plugin slug, plugin file, or plugin path and can report,
activate, or deactivate the resolved plugin with WordPress plugin APIs.
{
"command": "wordpress.plugin-state",
"args": ["action=activate", "plugin=my-plugin"]
}The result uses the wp-codebox/wordpress-plugin-state/v1 schema and includes
the requested action, resolved target identity, before/after active plugin
lists, network-active plugin lists where multisite is available, multisite
support notes, diagnostics, errors, and artifactRefs.
Recipes and runtime-backed fuzz workloads may use wordpress.ensure-plugin-active
as the public ensure-active form. It accepts the same plugin target arguments and
executes the wordpress.plugin-state activation contract.
Use wordpress.theme-setup for bounded theme installation, switching, and
inventory in a contained runtime:
{
"command": "wordpress.theme-setup",
"args": ["action=switch", "theme=twentytwentysix"]
}The plugin/theme setup result schemas include the requested action, target slug,
current inventory, operation diagnostics, errors, and artifactRefs.
Recipes can create named checkpoints and restore them later in the same run. Checkpoints are generic runtime isolation primitives for bounded mutation loops; they are not a high-volume fuzz runner.
{
"workflow": {
"steps": [
{ "command": "wp-codebox.checkpoint-create", "args": ["name=baseline"] },
{ "command": "wordpress.run-php", "args": ["code=update_option( 'example_flag', 'mutated' );"] },
{ "command": "wp-codebox.checkpoint-restore", "args": ["name=baseline"] },
{ "command": "wp-codebox.checkpoint-list" }
]
}
}Supported commands:
wp-codebox.checkpoint-createcaptures the current runtime state undername.wp-codebox.checkpoint-restorerestores a previously createdname.wp-codebox.checkpoint-listemits metadata for checkpoints created in the run.
Checkpoint create accepts the same snapshot scoping arguments as
wordpress.capture-state-bundle, plus optional metadata-json. Unsupported
runtime backends fail closed with a structured
wp-codebox/runtime-checkpoint-failure/v1 diagnostic and exit code 1.
Recipes can pass REST profiling workloads to wordpress.bench with
workloads-json. A workload may use route_matrix to declare a bounded set of
REST requests; the runtime expands each route into the existing rest-request
step and returns normal benchmark scenarios/artifacts.
Workloads may also use a configured rest-db-query-profiler step to run one or
more rest_request_cases, bracket each REST request with $wpdb->queries, and
return bounded, redacted query-profile metrics plus the typed
rest-db-query-profile benchmark artifact.
Recipe steps may opt into bounded per-command diagnostics with a diagnostics
object. Capture is disabled by default. The first supported capture kind is
wpdb-queries on wordpress.run-php, which records redacted SQL fingerprints
from $wpdb->queries around the command and links a structured
wp-codebox/command-diagnostics/v1 artifact from the execution result.
{
"command": "wordpress.run-php",
"args": ["code=$wpdb->get_results('SELECT * FROM wp_posts WHERE ID = 123');"],
"diagnostics": {
"capture": ["wpdb-queries"],
"maxItems": 25,
"maxBytes": 32768
}
}The same command also accepts capture-diagnostics=wpdb-queries,
diagnostics-max-items=<n>, and diagnostics-max-bytes=<n> args for direct
runtime callers. Limits are capped at 500 records and 524288 serialized bytes.
{
"command": "wordpress.bench",
"args": [
"plugin-slug=woocommerce",
"iterations=3",
"warmup-iterations=1",
"workloads-json=[{\"id\":\"rest-catalog\",\"source\":\"config\",\"route_matrix\":[{\"id\":\"products-list\",\"method\":\"GET\",\"path\":\"/wc/v3/products\",\"params\":{\"per_page\":10}}],\"run\":[{\"type\":\"rest-db-query-profiler\",\"rest_request_cases\":[{\"id\":\"products-list\",\"method\":\"GET\",\"path\":\"/wc/v3/products\",\"params\":{\"per_page\":10}}]}],\"artifacts\":{\"route-summary\":{\"path\":\"bench/rest-route-summary.json\",\"kind\":\"json\",\"source\":\"scenario-artifact\"}}}]"
]
}Use site seeds, fixture databases, or staged files for product-specific data
setup. Use artifacts on the workload for declared per-scenario outputs that
downstream lab tooling should extract from benchResults or an artifact bundle.
inputs.siteSeeds is the generic fixture import primitive. JSON fixture seeds
import through WordPress APIs for posts, options, terms, users, media, active
plugins, and active theme declarations. Those APIs can make semantic identifiers
stable, such as post slugs, term slugs, option names, user logins, plugin files,
and theme stylesheets. They cannot guarantee numeric primary keys.
Use deterministicIds to make that boundary explicit:
{
"inputs": {
"siteSeeds": [
{
"type": "fixture",
"name": "demo-content",
"source": "fixtures/content.json",
"format": "json",
"deterministicIds": {
"strategy": "platform-identifiers",
"onUnsupported": "block"
},
"scopes": {
"posts": { "slugs": ["home"] },
"options": { "names": ["blogname"] }
}
}
]
}
}When onUnsupported is block, WP Codebox reports a validation/runtime blocker
if the generic importer sees numeric id/ID fixture fields or a recipe requests
the numeric strategy. Custom importers may add format-specific support later,
but the generic contract stays honest about what platform APIs can guarantee.
Recipes may also attach reusable bootstrap declarations to a site seed:
{
"bootstrap": {
"multisite": {
"enabled": true,
"install": "subdomain",
"sites": [{ "domain": "example.test", "path": "/", "title": "Example" }]
},
"domains": [{ "domain": "example.test", "path": "/", "primary": true }]
}
}These are generic declarations for orchestrators and future runtime setup support. The current built-in fixture importer treats multisite/domain bootstrap as declared metadata and blocks executable fixture imports that require runtime setup not yet provided by WP Codebox.
Recipes can declare named WordPress fixture users in inputs.fixtureUsers and
named command execution sessions in inputs.userSessions. A fixture user is a
generic WordPress user contract: name, optional userId, username, email,
role, displayName, and password. Commands that support user/session
resolution can accept user=<name> or session=<name>.
userSessions reference a fixture user by name. Session artifacts such as
browser storage state, cookie jars, or tokens are metadata only and must be
declared with redactionRequired: true; command output reports only safe
structured metadata such as schema, selected user name/role, artifact kind/path,
and the redaction flag.
{
"inputs": {
"fixtureUsers": [
{ "name": "admin", "username": "fixture-admin", "role": "administrator" }
],
"userSessions": [
{
"name": "admin-browser",
"user": "admin",
"artifacts": [
{ "kind": "browser-storage-state", "path": "files/browser-storage-state/storage-state.json", "redactionRequired": true }
]
}
]
},
"workflow": {
"steps": [
{ "command": "wordpress.rest-request", "args": ["path=/wp/v2/users/me", "session=admin-browser"] }
]
}
}{
"command": "wordpress.browser-actions",
"args": ["url=/", "steps-json=[...]"],
"advisory": true
}Browser interaction scripts support a generic callTool verifier step shape for
caller-owned external checks:
{
"kind": "callTool",
"tool": "client/check_status",
"input": { "url": "https://example.test/status", "expected": "ready" }
}tool is the exact caller-provided host tool command name and must be allowed by
runtime policy using that same command name. input must be JSON-serializable.
WP Codebox treats this as transport and evidence only; callers own the tool and
any external system behavior. The Playground browser-actions runtime validates
and policy-checks callTool; when the caller provides a matching host tool via
RuntimeCreateSpec.hostTools, Codebox executes it through the generic host-tool
transport and records the wp-codebox/host-tool-result/v1 result inside a
redaction-required wp-codebox/browser-tool-verifier-result/v1 artifact. When no
host-tool registry or matching tool is available, or runtime policy does not
allow the exact tool command, Codebox records stable unsupported verifier
evidence instead of executing the step. Raw input values and secrets are not
serialized into unsupported verifier artifacts. Polling fields are intentionally
not part of this narrow primitive yet; callers should model repeated checks
outside the browser script.
Hosts that need an authenticated browser session for a disposable WordPress
sandbox can use Codebox fixture auth storage-state helpers instead of baking
product-specific site identifiers into recipes. The helper contract is generic:
resolve or create a named WordPress fixture user inside the sandbox, mint
short-lived WordPress admin cookies for declared browser origins, and return a
Playwright-compatible storageState envelope.
The emitted PHP returns wp-codebox/browser-auth-storage-state/v1:
{
"schema": "wp-codebox/browser-auth-storage-state/v1",
"kind": "wordpress-fixture-user-admin-auth",
"user": {
"id": 1,
"username": "wp-codebox-fixture-admin",
"email": "wp-codebox-fixture-admin@example.test",
"role": "administrator",
"created": true
},
"storageState": {
"cookies": [],
"origins": []
}
}Recipes can export that state as an artifact with the generic command:
{
"command": "wordpress.export-browser-storage-state",
"args": [
"browser-urls=http://127.0.0.1:9400,https://preview.example.test",
"user-json={\"username\":\"fixture-admin\",\"role\":\"administrator\"}"
]
}The command also accepts caller-produced state with storage-state=<json> or
storage-state=@./state.json. That value may be a raw Playwright
storageState object or the wp-codebox/browser-auth-storage-state/v1 envelope
shown above, so product-specific PHP bootstrap code can stay outside WP Codebox
and hand the resulting generic browser state to the exporter.
The command returns wp-codebox/browser-storage-state-export/v1 with
artifacts.storageState and artifacts.summary. The storage-state artifact is
the token-bearing Playwright JSON and is marked redactionRequired in
artifactRefs; the summary artifact and command output contain only
reviewer-safe metadata: schema/kind, user id/name/email/role/created flag,
cookie counts by host, origin count, and diagnostics. Product policy,
production identifiers, and cross-site account mapping stay outside WP Codebox.
wordpress.browser-probe and wordpress.browser-actions can import a reusable
storage state with storage-state=<json> or storage-state=@./state.json. The
value may be a raw Playwright storageState object or the
wp-codebox/browser-auth-storage-state/v1 envelope shown above. WP Codebox passes
the state directly to a fresh Playwright context and records only redacted
provenance in browser summaries: source type, optional schema/kind, cookie count,
cookie hosts, origin count, and diagnostics. Cookie values and localStorage values
are never written to browser evidence artifacts.
Use one browser authentication source per command. auth=wordpress-admin creates
short-lived in-memory cookies from the disposable WordPress sandbox; storage-state
imports caller-provided reusable state. Supplying both is rejected with structured
storage-state diagnostics rather than silently preferring one source.
Browser commands accept capture=websocket to write a generic
browser-websocket artifact. The artifact records safe connection metadata only:
redacted websocket URLs, open/close/error timestamps, frame counts, and aggregate
sent/received byte counts. Frame payloads are not written.
recipe-run --json returns wp-codebox/recipe-run/v1. Browser command sidecars
are promoted into browserEvidence so callers can discover stable evidence
without hardcoding artifact paths or parsing command stdout.
The same output includes result, a normalized
wp-codebox/recipe-run-summary/v1 envelope for portable callers. It groups
common artifact refs, command stdout/stderr tails, run/runtime metadata, failure
phase and summary, and held-preview reviewer access. Consumers should prefer
result before scraping latest-runtime.json, commands.jsonl, command stdout,
or preview internals from the artifact bundle.
Each browserEvidence entry includes the workflow phase/index, command,
summary file, artifact file refs, summary payload, and scriptResult when the
browser command produced one. The same browser evidence is mirrored into
latest-runtime.json under the run artifact pointer.
When a browser command captures network evidence, WP Codebox writes the raw
network.jsonl stream and a derived waterfall.json artifact using the stable
wp-codebox/browser-waterfall/v1 schema. The waterfall is HAR-style JSON with
redacted URLs, request/response status, resource type, sizes, and timing fields;
both files are registered as redaction-required browser artifacts and surfaced
through browserEvidence.files.
--preview-hold-seconds <duration> records held-preview lifecycle metadata in the
artifact bundle and returns after recipe work finishes. The cap defaults to 3600
seconds and can be raised by an operator with WP_CODEBOX_PREVIEW_HOLD_MAX_SECONDS
up to the hard 24-hour ceiling. Use
--preview-hold-blocking only for operator workflows that need the CLI process
to keep a live preview server open for the hold duration.
Hosts that expose recipe/task runner commands through WP Codebox should use the
core executeHostCommand() primitive instead of hand-rolled process wrappers. It
runs one command without shell expansion, enforces allowed working-directory and
environment policy, times out long-running work, terminates the spawned process
group, samples process-tree RSS, and returns a structured result with:
failureClassification:none,timeout,non_zero_exit, orsignal.commandSummary: a compact command line for human diagnostics.- Bounded
stdoutandstderrfields plusoutputTruncated. memorySamplesandpeakRssBytesfor runner watchdog evidence.- Optional
artifacts.stdout,artifacts.stderr, andartifacts.summaryrefs whenartifactsDirectoryis provided.
The summary artifact uses wp-codebox/host-command-summary/v1. Product-specific
orchestrators can wrap this primitive, but should keep WPCOM, CI-provider, and
deployment semantics outside the generic runner layer.
wordpress.phpunit is the lightweight WP Codebox equivalent of plugin PHPUnit
commands commonly run through wp-env run ... vendor/bin/phpunit. It boots a
disposable WordPress Playground runtime, mounts the tested plugin at
/wordpress/wp-content/plugins/<plugin-slug>, prepares the WordPress PHPUnit
contract, and captures command output in the artifact bundle.
The runtime provides:
WP_TESTS_DIRpointing at the configured WordPress tests library.WP_TESTS_CONFIG_FILE_PATHandWP_PHPUNIT__TESTS_CONFIGpointing at the generatedwp-tests-config.php.- An isolated SQLite test database via
DB_NAME=':memory:'. - A plugin working directory via
cwd=<sandbox path>, matching the practical role ofwp-env run --env-cwd. - Structured diagnostics in the recipe artifact bundle, including the raw test
result log collected from
/tmp/wp-codebox-phpunit-result.txt.
Use recipe build phpunit when generating recipes for plugin CI or offloaded lab
runners:
{
"pluginSlug": "woocommerce",
"pluginSource": "../woocommerce/plugins/woocommerce",
"cwd": "/wordpress/wp-content/plugins/woocommerce",
"autoloadFile": "/wp-codebox-vendor/autoload.php",
"testsDir": "/wp-codebox-vendor/wp-phpunit/wp-phpunit",
"bootstrapMode": "project",
"projectBootstrap": "tests/legacy/bootstrap.php",
"phpunitArgs": ["--filter", "WC_Checkout_Test::test_checkout"]
}npm run wp-codebox -- recipe build phpunit --options ./phpunit-options.json --output ./phpunit.recipe.json
npm run wp-codebox -- recipe-run --recipe ./phpunit.recipe.json --artifacts ./artifacts/phpunit --jsonTools that need to generate WordPress bench or PHPUnit recipes without shelling out to the CLI may import the supported recipe-builder module:
import {
buildWordPressBenchRecipe,
buildWordPressPhpunitRecipe,
} from "@automattic/wp-codebox-core/recipe-builders"The same subpath is exported by the root release package as
wp-codebox-workspace/recipe-builders, so callers can use one documented module
name for npm package installs and release-tarball installs without probing
packages/runtime-core/dist/index.js or other internal build paths. Local
checkout consumers should run npm run build first, then import the same
workspace package subpath through normal Node package resolution.
The CLI surface remains the stable process boundary for hosts that prefer JSON over an in-process import:
wp-codebox recipe build phpunit --options ./phpunit-options.json --output ./phpunit.recipe.json
wp-codebox recipe build bench --options ./bench-options.json --output ./bench.recipe.json
wp-codebox recipe build generic-ability-runtime-run --options ./ability-runtime-options.json --output ./ability-runtime.recipe.jsonAll builders return wp-codebox/workspace-recipe/v1 recipes. The generated
recipes should still be validated with wp-codebox recipe validate or
wp-codebox recipe-run --dry-run before execution in CI.
generic-ability-runtime-run is the stable preset for callers that need to run a
WordPress Ability in a disposable runtime with generic component/provider
contracts. The options JSON maps to buildGenericAbilityRuntimeRunRecipe and
accepts abilityId, optional abilityInput, components, providerPlugins,
providerPluginPaths, runtimeOverlays, runtimeEnv, secretEnv,
toolPolicy, expectedResultSchema, mounts, runtimeStackMounts,
stagedFiles, and verifySteps. The generated workflow invokes
wordpress.ability with runtime invocation metadata and, when
expectedResultSchema is supplied, recipe-run --json records the canonical
wp-codebox/generic-ability-runtime-run-result/v1 command output with the
ability result and discovered evidenceEnvelope.
For monorepos such as WooCommerce, set pluginSource to the directory that
should appear as wp-content/plugins/<plugin-slug> and set cwd to the same
sandbox directory a wp-env --env-cwd command would use. Relative cwd values
resolve inside the mounted plugin directory.
wordpress.browser-probe accepts repeated assert=<assertion> arguments.
Supported assertion forms are the current command contract:
exists:<selector>not-exists:<selector>visible:<selector>hidden:<selector>count:<selector><op><number>text:<selector> contains <text>attr:<selector>[name][=value]no-console-errorsno-page-errorsno-errorsrequest-count-by-host:<host><op><number>request-count-by-type:<type><op><number>total-transfer-size<op><number>- metric budgets such as
lcp_ms<=2500,fcp_ms<=1800,ttfb_ms<=800, andnav_duration_ms<=5000
Prefix an assertion with advisory: to record a failing assertion without
failing the command.
wordpress.browser-actions can assert over observations captured by prior action
steps with an assertObservation step. Supported observation assertions are:
no-console-errorsno-page-errorsrequest-count-by-host:<host><op><number>request-count-by-type:<type><op><number>
Failed assertObservation steps are recorded in the action step records and
assertion summary, and they fail the browser-actions command.
{
"command": "wordpress.browser-actions",
"args": [
"url=/",
"steps-json=[{\"kind\":\"waitFor\",\"waitFor\":\"networkidle\"},{\"kind\":\"assertObservation\",\"assertion\":\"request-count-by-host:example.test<=2\"},{\"kind\":\"assertObservation\",\"assertion\":\"no-console-errors\"}]"
]
}Do not use assert=script:passed equals true. That syntax is not supported by
the current WP Codebox browser assertion contract. Use wordpress.browser-actions
with an evaluate step and assert value when a page script must prove state:
{
"command": "wordpress.browser-actions",
"args": [
"url=/wp-admin/tools.php?page=my-plugin",
"steps-json=[{\"kind\":\"evaluate\",\"expression\":\"window.myPluginReady === true\",\"assert\":true}]"
]
}Recipes that use a browser-actions evaluate step require the runtime policy to
allow wordpress.browser-actions.evaluate in addition to
wordpress.browser-actions.
When editing docs or example recipes:
- Prefer generated schema output over hand-written field lists.
- Run
recipe validateagainst every recipe changed. - Run
recipe-run --dry-run --jsonwhen changing mounts, workspaces,extra_plugins, secrets, or workflow args. - Keep product-specific orchestration, scoring, PR creation, and deployment out of recipes. Parent control planes own those behaviors.