Skip to content

Target readiness

Preview environments, sleeping stacks and local services can answer with a placeholder. A paused stack might still return HTTP 200 with a “this app is paused” page. Browser steps then fail with assertions about missing content, which look like application regressions.

Configure HTTP health probes for the selected target. Before admitting new work, Reflow sends one GET to each probe. A failure returns target_not_ready before any new run or test step starts.

Readiness is opt-in and HTTP-only. It does not load pages, run scripts, wait for a selector or check page titles.

Write a JSON file listing the probes. This generic example checks an application route, a separate API and an identity provider:

{
"timeoutMs": 10000,
"probes": [
{ "url": "/login", "status": [200], "headers": { "absent": ["x-app-paused"] } },
{ "url": "https://localhost:8080/healthz", "status": [200] },
{ "url": "http://localhost:35291/health", "status": "any" }
]
}

Select it with the same target URL and group you already use:

Terminal window
reflow target https://localhost:5173/ --group my-app --collection <collection-id> \
--allow-origin https://localhost:8080 --allow-origin http://localhost:35291 \
--readiness /absolute/path/to/readiness.json

Reflow copies the configuration when you select the target. Editing the file later has no effect until you select the target again with --readiness. The file must be a regular file, not a symbolic link.

For the same connection, checkout, collection, URL, group and scope, omitting --readiness keeps the current probes. Use --clear-readiness to remove them.

In local MCP, pass the same object inline to manage_execution with action: "target":

{
"action": "target",
"url": "https://localhost:5173/",
"group": "my-app",
"readiness": {
"timeoutMs": 10000,
"probes": [{ "url": "/healthz", "status": [200] }]
}
}

Omit readiness to keep the current probes, or pass readiness: null to clear them.

Selecting a target starts a new evidence epoch, including when only readiness changes. Earlier step results cannot be reused even if the URL and group stay the same. Configure readiness when you first select the target, then repeat plan and apply as usual.

FieldMeaning
timeoutMsTotal time for all probes together, 1 to 60000 milliseconds. Default 10000.
probes1 to 8 probes, checked concurrently. Results retain configuration order; all must pass.
probes[].urlA path relative to the target, such as /healthz, or an absolute HTTP(S) URL.
probes[].statusStatus codes that count as ready. Default [200]. Use "any" to accept any HTTP response.
probes[].headers.absentResponse header names that must not be present.
probes[].headers.presentResponse header names that must be present.
probes[].headers.equalsMap of name: value that must each appear exactly once with exactly that value.

Header names are matched case-insensitively. A header can’t be both required and forbidden.

Readiness needs a target URL. An absolute probe URL must use the target origin or an origin you have already granted with --allow-origin. Readiness never adds a grant. Credentials in URLs, wildcards and non-HTTP schemes are refused when you select the target.

A response is ready only when its status is in the list. Any HTTP response counts only when you say "status": "any"; use that for a service whose reachability is enough, such as an identity provider that answers its health route with a redirect.

Each probe is a single plain GET:

  • It does not follow redirects. A redirect is judged by its own status and headers.
  • It sends no cookies, no binding or team request headers, and no credentials.
  • It doesn’t retry or poll, and it never tries to wake a paused service.
  • It doesn’t run a browser, page scripts or DOM checks.
  • HTTPS uses normal certificate verification against the system and default CAs. There is no option to skip TLS verification.
  • Reflow keeps the origin, status, readiness and a short reason for each probe. It does not keep response bodies, paths or query strings.

These are real network requests to your services. Point probes at health endpoints that are safe to call repeatedly, such as /healthz, /health or a lightweight login page. Don’t use routes that create sessions, send email or change data.

Probes run only before Reflow admits new work:

  • reflow plan never sends readiness requests.
  • An apply where every step reuses earlier evidence sends none.
  • Reconciling an existing request ID sends none.
  • apply with steps to execute checks all probes first, then admits the work.

Readiness requests are separate from test steps. They never become step results, and test steps never run during the check.

All configured probes run concurrently under the same total deadline. One failure does not hide the other services. The CLI and MCP return target_not_ready with the origin, status (when one was received) and reason for every configured probe. A probe still waiting when the deadline expires reports timed_out; completed observations retain their outcome. Reasons include:

ReasonMeaning
status_mismatchThe status is not in the probe’s status list.
header_must_be_absent:<name>A forbidden header was present, for example a paused marker.
header_missing:<name>A required header was missing.
header_mismatch:<name>A header did not have the exact expected value.
unavailableNo usable HTTP response, for example a refused connection or TLS failure.
timed_outThe total timeoutMs ran out.
cancelledThe request was cancelled.

No work was admitted, so there is no new run or step result to taint. The CLI exits with code 75 (target_not_ready, a temporary environment refusal). Failed tests and other command errors use exit code 1. For a readiness refusal, apply --json reports admission: "none" and error.code: "target_not_ready". Earlier outcomes are unchanged, including steps whose completion is still unknown. Those still need inspection and an explicit taint before they run again.

Start or resume the paused service yourself, then repeat plan and apply.

A passing check is a point-in-time observation. It does not guarantee the target stays ready while the run continues. A service that pauses mid-run still produces ordinary step failures.

Readiness covers HTTP status and headers only. Checks for a page title, DOM selector or browser-rendered content are not implemented. For an application whose paused page looks identical over HTTP, expose a health route or a response header that tells the two states apart.

Readiness applies to local CLI and MCP plan/apply targets. It does not configure separate device jobs or the HTTP batch API. See the Browser plugin for navigation origins and the getting started guide for target selection.