You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Command-outcome telemetry — one event per invocation, opt out with one env var. The CLI now posts a single "how did that command end" event to the TestSprite backend (POST /api/cli/v1/telemetry), which forwards it server-side; the CLI ships no analytics SDK and no write key. The payload is a fixed allowlist of low-cardinality fields — the leaf command that ran, success/error, the exit code, a stable machine errorCode, and a duration. It never carries target URLs, API keys, flag values, argument values, or error messages. Opt out with TESTSPRITE_NO_TELEMETRY or the cross-tool DO_NOT_TRACK. Nothing is sent when no API key is configured, under --dry-run, when no leaf command ran (bare --help, a parse error), on Ctrl-C, or from the purely local completion / test create --plan-template paths. The post is bounded at one second and every failure is swallowed: telemetry can never change a command's output, exit code, or duration beyond that bound.
test result --history --rerun / --no-rerun — narrow run history to only reruns or only fresh runs. Applied client-side on each page's isRerun (the backend has no rerun filter), so — exactly like --source — a filtered page can come back short or empty while nextCursor is still set; paginate to continue. Absent means no filter, never a silent default.
sk-member- membership keys are accepted. Workspace membership keys are now minted with an sk-member- prefix. The CLI's fail-fast key-format check knew only sk-user- and tsp_, so it rejected every newly minted membership key locally, before the key ever reached the server. All three families are now accepted from one list that also renders the error message, so the check and the message cannot drift apart; existing tsp_ keys keep authenticating.
project get shows the project's target URL. A backend project created without --url is dead on arrival on the V3 execution path (its first run is rejected no-target-resolvable), and there was no way to see that from the CLI. project get now prints targetUrl, and (not set) plus the exact project update … --url fix-it command when there is none. Absent-safe: against a backend that does not report the field the line is omitted entirely rather than claiming every project is URL-less. project list deliberately does not show it — resolving it per row costs one extra read per project.
Fixed
--wait no longer fails a healthy V3 backend run. A V3 run reports targetUrl: null (and codeVersion: null for a plan-driven frontend case with no code row), which the response validator rejected — so test create --run --wait and test wait printed INTERNAL: Response shape mismatchafter the run had already dispatched. The wire contract always allowed null on those fields; the CLI was the side out of spec.
A rate limit no longer ends a multi-run test wait. With several run ids, one 429 from the backend's IP-keyed limiter (which a CI runner or NAT can trip through no fault of the key) recorded that member as a poll error and exited 7 — reporting a healthy run as a failure to observe it. Each member now re-polls up to 3 times honoring the server's Retry-After; every backoff is clamped to the shared --timeout deadline, stays interruptible by Ctrl-C, and reports a timeout rather than a rate limit if the deadline is reached during one. When a throttle outlasts the retry budget and nothing else went wrong, the exit code is 11 (rate limited — back off, then re-attach) instead of 7, which told an automated caller to retry immediately and walk straight back into the limiter. Any real timeout or non-passed run in the same invocation still exits 7 / 1.
usage reports the wallet that actually pays for your runs. On an organization-billed account the spend drains the workspace wallet, so the legacy per-user balance was a number that never moved. When the backend reports an active organization, usage renders the workspace block (plan, remaining, per-seat allowance, seats) and suppresses the legacy balance; auth status gains a one-line org: summary. The ~N runs estimate stays on the legacy path — workspace billing prices each action separately, so there is no single per-run rate.
--no-auto-heal was a silent no-op on rerun, and test flaky never disabled healing at all. The rerun request body omitted autoHeal entirely when you opted out, and the server treats an absent field as heal-on — so the opt-out did nothing, and test flaky's strict verbatim replays (whose whole point is that a nondeterministic pass cannot be masked by a heal) were quietly healing too. All three rerun dispatch sites now send an explicit boolean, test flaky always sends autoHeal: false, and --dry-run previews the same body the real request sends. Rerun and batch-rerun responses may also carry advisories now (e.g. an engine that does not yet honor the opt-out); each renders as one [advisory] line on stderr, deduped across batch chunks, deferred retries, and flaky probes.
One closure member's poll error no longer discards a whole backend test rerun --wait. A backend rerun expands its dependency closure server-side and polls every member. A single member's non-timeout poll error (an API error, a transient failure, a malformed response) rejected the entire fan-out, throwing away the sibling results and the named test's own verdict. Classifiable member errors now land in closureFailures[] and the named test still prints its result; its own error, if any, is re-thrown after the payload. Any unobserved member — timed out or poll-errored — still forces exit 7, so --wait never reports success with an unconfirmed dependency.
Run cards use the server's dashboard link when it offers one.GET /runs/{runId} may now carry a server-built dashboardUrl, and the run-completion paths prefer it over the link this process templates. Two things the server knows and the CLI cannot: which store answered the read (a project created through the V3-native write path has no row behind the route the CLI templates, so its link could not render at all), and the portal origin outside production (against any non-prod endpoint the CLI printed no link whatsoever). An absent field reopens the client computation, so an older backend behaves exactly as before. Separately, a dashboardUrl: null on the wire no longer fails response validation and kills test wait — the same trap that had to be un-sprung for a null targetUrl.
Changed
auth status and doctor explain a workspace you cannot reach. An API key belongs to exactly one workspace, chosen when it is minted. Someone in a team using a personal key previously just saw the team's projects missing from project list, and addressing one by id failed the same way a typo does. Both commands now name the unreachable workspaces and point at minting a key there. Silent for solo users and for keys that are already workspace-bound.
The V3 routing advisory only lists gaps that are still open. It claimed test cancel could 404 and test delete could leave a zombie run; both have shipped. It now names the two real ones: --target-url is ignored on frontend runs, and a frontend rerun replays the run it was pointed at rather than the latest saved code.