Skip to content

[docs] Make v5 the default documentation version - #3714

Open
VaguelySerious wants to merge 2 commits into
mainfrom
peter/docs-v5-default
Open

[docs] Make v5 the default documentation version#3714
VaguelySerious wants to merge 2 commits into
mainfrom
peter/docs-v5-default

Conversation

@VaguelySerious

@VaguelySerious VaguelySerious commented Aug 21, 2026

Copy link
Copy Markdown
Member

Makes v5 the default documentation version for the 5.0.0 GA, and catches the v5 content up with everything that landed on main since the v5 docs were last refreshed. Companion to #3090 (exit changeset pre mode) and #3091 (pin 4.x publishes to previous).

Version flip and routing

content/docs/v5 and content/worlds/v5 now serve unprefixed — /docs, /worlds, /cookbook — and v4 moves under a /v4 prefix. The versioned source config drives both route trees (the root tree always renders versionedSources.current), so this is a routePrefix move plus source re-binding, not a restructure. The only file moves are app/[lang]/v5/**app/[lang]/v4/**.

  • Version switcher: labels are v5 (Latest) / v4 (Maintenance); current: 'v5'.
  • Banner: pre-release-banner.tsxmaintenance-banner.tsx. v4 pages carry an amber notice (with dark-mode styling) whose "Go to Workflow 5 (Latest)" link deep-links to the same page on the current version; v4-only pages land on the nearest section index via the fallback redirects. v4 pages keep robots: noindex, follow.
  • Redirects (docs/next.config.ts): /v5/* → unprefixed equivalent (permanent; bare /v5 gets its own rule because :path* expands to an empty Location otherwise). The world-docs and api-reference restructure rules are mirrored onto /v4/docs/*, and every page that exists in only one tree has a version-switcher fallback (verified by diffing the two content trees).
  • Worlds routes: both the unprefixed and /v4 worlds routes pass an explicit version into the shared page components, whose semantics flipped with the switch — smoke checks (assertWorldVersionMarkers, assertServesDirectly('/worlds/turso')) now guard the pairing so the canonical /worlds/* pages can't silently serve the maintenance version or self-redirect-loop again.
  • Link lint (docs/scripts/lint.ts): the two-space model swaps with the URL space; redirect destinations resolve against the real HTTP space since redirects are matched before render-time href rewriting.
  • Intentional oddity: rewriteHrefForVersion pulls unprefixed hrefs on v4 pages into the /v4 view, so a /v5/... href is the only way for v4 content to point at a current page. Three such links are kept deliberately; the lint models this.

What moves with the flip

  • whats-new enters the v5 sidebar, first in the tree. [docs] v5 GA content: What's new, World upgrade guide, migration skills #3100 adds the page but leaves it out of content/docs/v5/meta.json, so until this lands it is reachable only by URL.
  • upgrading-to-v5 moves from app/[lang]/v5/worlds/ to app/[lang]/worlds/, following the rest of the v5 worlds routes.
  • Two cross-version links become expressible and are restored. While v4 is the unprefixed version, a v5 page cannot link to a v4 page at all: an unprefixed href on a v5 page is rewritten into the /v5 view. [docs] v5 GA content: What's new, World upgrade guide, migration skills #3100 therefore phrases both as pointers to the version picker. Here they go back to being links — the v4 docs entry point in the What's new callout, and the v4 version of the code-transform page.
  • editPath on the unprefixed docs route points at docs/content/docs/v5/{path}.

Catch-up with main

Swept the 53 commits that landed since the last content refresh, and added what the docs were missing. Most changesets in that window are fixes, internal, or already documented by their own PR; three things were not.

Spec 7, the sealed log (#3634, not merged, default for v5). Positions are handed out ahead of the commit instead of being claimed by the write that fills them, so concurrent writers never contend and a wide fan-out stops serializing. The cost is a position whose writer dies, which the backend closes with a noop event that replay steps over without delivering it and without advancing the deterministic clock.

  • upgrading-to-v5 › Spec versions is rewritten around mintedSpecVersion(). The accepted range widens back to two versions, because a deployment with WORKFLOW_SEALED_LOG=0 stamps the one below, and that makes both SPEC_VERSION_CURRENT and SPEC_VERSION_SUPPORTS_SLOT_IDENTITY literals by another name for declaring it — neither follows the setting. This replaces what [docs] v5 GA content: What's new, World upgrade guide, migration skills #3100 said for spec 6, which was that exactly one version is accepted.
  • A new "Sealed logs and noop events" subsection says what this costs an implementer, which for most is nothing: a World allocating each position at the commit cannot leave a hole, so it never seals and never emits a noop. The obligation belongs to a World that pre-assigns positions; the half that binds everyone is the reader's.
  • WORKFLOW_SEALED_LOG is documented in runtime-tuning, taken verbatim from Add support for 'noop' event type - spec version 7 #3634 so whichever lands second is a no-op merge. The deep reference sections that PR writes — in event-sourcing and the World allocation contract — are left to it, so this does not duplicate them.
  • The migration skill (v0.2.0) gets the same treatment, phrased as findings to report rather than edits to make.

events.createBatch (#3025). An optional World method appending an ordered list of events in one durable write with per-event outcomes. It was documented only as a changelog page and an env var, so the World reference had no mention of a method a World author has to decide about. Added to the interface snippet, to the Key Implementation Details as a contract note (atomicity per attempt, what a World must reject, the one legal same-entity pair), to the upgrade guide's optional surface, and to the skill.

runs.waitForTerminalStatus (#3570). Also missing from the upgrade guide and the skill. It is what makes await run.returnValue a long poll rather than an interval, which is user-facing, so What's new gets that as an entry.

What's new also gains the batched suspension write and the positions change under faster-and-cheaper runs, where they belong: neither has any API surface.

Not addressed. workflow.step.execute.duration, the OpenTelemetry histogram from #3526, has nowhere to go — the docs carry no metrics reference at all, and inventing one for a single metric is a bigger call than this sweep. Flagging rather than guessing.

Verification

Link lint passes with 0 errors. pnpm build compiles, with /en/docs/whats-new prerendered under the unprefixed route, /[lang]/v4/docs/[[...slug]] serving the maintenance tree, and ƒ /[lang]/worlds/upgrading-to-v5.

Docs Preview

Links will be added from the workflow-docs preview once it deploys.

🤖 Generated with Claude Code

@VaguelySerious
VaguelySerious requested review from a team, fantix and msullivan as code owners August 21, 2026 18:58
@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, v0 Aug 21, 2026 8:06pm
example-nextjs-workflow-webpack Ready Ready Preview, v0 Aug 21, 2026 8:06pm
example-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-astro-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-express-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-fastify-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-hono-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-nestjs-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-nitro-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-nuxt-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-python-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-sveltekit-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-tanstack-start-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workbench-vite-workflow Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workflow-docs Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workflow-swc-playground Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workflow-tarballs Ready Ready Preview, v0 Aug 21, 2026 8:06pm
workflow-web Ready Ready Preview, v0 Aug 21, 2026 8:06pm

@changeset-bot

changeset-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a08bced

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Sim World

Simulated world deterministic testing for races. Traces

🟠 world-sim scenario book — 1 fail of 41 total

fence=per-spec

scenario outcome events virt replay violations
smoke-no-steps completed 3 0ms ok 0
smoke-one-step completed 6 0ms ok 0
hook-at-step-started completed 12 0ms ok 0
hook-at-step-completed completed 12 0ms ok 0
hook-at-hook-created completed 12 0ms ok 0
deadline-hook-wins completed 7 1.0h ok 0
deadline-expires completed 7 1.0h ok 0
long-sleep completed 11 30.0d ok 0
hook-never-arrives stalled 3 0ms skipped 0
step-retries-twice completed 10 2.0s ok 0
parallel-steps completed 9 0ms ok 0
hook-on-execution-state completed 12 0ms ok 0
peek-hook-before-branch completed 12 0ms ok 0
peek-hook-after-branch completed 12 0ms ok 0
peek-hook-at-registration completed 12 0ms ok 0
race-hook-before-probe completed 12 0ms ok 0
race-hook-after-probe completed 12 0ms ok 0
race-duplicate-delivery completed 13 0ms ok 0
attr-hook-before-step completed 11 0ms ok 0
attr-hook-after-step completed 11 0ms ok 0
attr-from-step-body completed 13 0ms ok 0
fork-hook-after-timeout completed 14 1.0m ok 0
fork-hook-before-timeout completed 14 1.0m ok 0
count-hook-after-timeout completed 17 1.0m ok 0
count-hook-before-timeout completed 20 1.0m ok 0
stale-read-step-count-fork completed 20 1.0m ok 0
stale-read-equal-step-counts completed 14 1.0m ok 0
step-vs-step-fork completed 12 0ms ok 0
step-vs-step-fork-fenced completed 12 0ms ok 0
fence-catches-benign-direction completed 12 5ms ok 0
in-flight-before-decision completed 17 1.0m ok 0
in-flight-before-decision-counted completed 17 1.0m ok 0
in-flight-after-decision completed 19 2.0m ok 0
stale-read-step-count-fork-fenced completed 20 1.0m ok 0
fork-hook-wins completed 13 1.0m ok 0
fork-timeout-wins completed 13 1.0m ok 0
unclaimed-payload-under-fork completed 17 1.0m ok 0
claimed-payload-under-fork completed 17 1.0m ok 0
writers-independent-step-bodies completed 12 0ms ok 0
writers-scripted-tempo completed 12 0ms ok 0
cancel-mid-step cancelled 7 0ms skipped 0

Full trace: world-sim.txt

VaguelySerious and others added 2 commits August 21, 2026 12:50
Serves `content/docs/v5` and `content/worlds/v5` unprefixed at /docs,
/worlds and /cookbook, moves v4 under /v4, and puts What's new first in
the v5 sidebar.

The versioned source config drives both route trees (the root tree always
renders `versionedSources.current`), so this is a `routePrefix` move plus
source re-binding rather than a restructure. The only file moves are
`app/[lang]/v5/**` → `app/[lang]/v4/**`.

- Version switcher: `v5 (Latest)` / `v4 (Maintenance)`, `current: 'v5'`.
- `pre-release-banner.tsx` becomes `maintenance-banner.tsx`. v4 pages
  carry an amber notice whose "Go to Workflow 5 (Latest)" link deep-links
  to the same page on the current version, falling back to the nearest
  section index for v4-only pages, and keep `robots: noindex, follow`.
- Redirects: `/v5/*` to the unprefixed equivalent (bare `/v5` needs its
  own rule, since `:path*` expands to an empty Location). The world-docs
  and api-reference restructure rules are mirrored onto `/v4/docs/*`, and
  every page existing in only one tree gets a version-switcher fallback.
- Both worlds route trees pass an explicit version into the shared page
  components, whose semantics flipped with the switch, so the smoke checks
  now assert the pairing: a " · v4" title marker and noindex on the
  maintenance routes, neither on the canonical ones, and a community world
  serving directly rather than self-redirecting.
- The link lint's two URL spaces swap with the prefixes. Redirect
  destinations resolve against the real HTTP space, since redirects are
  matched before render-time href rewriting.
- The two `/v4/...` links this makes expressible are restored: a v5 page
  cannot link to a v4 page while v4 is the unprefixed version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sweep of everything that landed on main since the last content refresh,
plus the spec-7 sealed log from #3634, which is not merged but is the
default for v5.

Spec 7 changes what a World declares, so the upgrade guide's Spec
versions section is rewritten around `mintedSpecVersion()`. The accepted
range widens back to two versions, because a deployment with
`WORKFLOW_SEALED_LOG=0` stamps the one below, and both `SPEC_VERSION_CURRENT`
and `SPEC_VERSION_SUPPORTS_SLOT_IDENTITY` become literals by another name
for the purpose of declaring it: neither follows the setting. The new
section says what a sealed log costs an implementer, which for most is
nothing — a World allocating each position at the commit cannot leave a
hole, so it never seals and never writes a `noop`. The obligation belongs
to a World that pre-assigns positions, and the half that binds everyone
is the reader's.

`WORKFLOW_SEALED_LOG` is documented in runtime-tuning, taken verbatim
from #3634 so whichever lands second is a no-op merge. The deep
reference sections that PR writes, in event-sourcing and the World
allocation contract, are left to it.

Two optional World members shipped after the guide was written and were
missing everywhere:

- `events.createBatch` — in the World reference (interface and contract
  note), the upgrade guide's optional surface, and the skill. Implementing
  it is the declaration, so the note leads with atomicity per attempt and
  what a World must reject.
- `runs.waitForTerminalStatus` — same three places. It is also what makes
  `await run.returnValue` a long poll rather than an interval, which is
  user-facing, so What's new gets it too.

What's new also gains the batched suspension write and the pre-assigned
positions behind it, both under faster-and-cheaper runs where they belong:
neither has any API surface.

Not addressed: `workflow.step.execute.duration`, the OpenTelemetry
histogram added in #3526, has nowhere to go. The docs have no metrics
reference at all, and inventing one for a single metric is a bigger call
than this sweep.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

❌ Failed E2E Tests

▲ Vercel Production (239 failed)

astro-node (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

astro-quickjs (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

example-node (10 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

example-quickjs (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run

express-node (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

express-quickjs (11 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

fastify-node (8 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

fastify-quickjs (11 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run

hono-node (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

hono-quickjs (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

nest-node (11 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

nest-quickjs (11 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

nextjs-turbopack-node (5 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

nextjs-turbopack-quickjs (11 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

nextjs-webpack-node (8 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

nextjs-webpack-quickjs (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

nitro-node (10 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

nitro-quickjs (7 failed):

  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run

nuxt-node (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting

nuxt-quickjs (8 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands

sveltekit-node (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting

sveltekit-quickjs (12 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

tanstack-start-node (7 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes fire-and-forget: void setAttributes lands without awaiting

tanstack-start-quickjs (10 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run

vite-node (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting

vite-quickjs (9 failed):

  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41M0JZ1DFJ0GZ2EMP194NYDXPA | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41M0JZ0FGY0GV851EDJTRMY0PZ | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41M0JZ1QYD0GMNZ5PJVXHP917Q | 🔍 observability
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable | wrun_41M0JZ2P690GZCSMTG0A7CJCQS | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
💻 Local Development (26 failed)

nextjs-webpack-canary-node (26 failed):

  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41M0JZ46KA0GQK0Y127FV0ZQYP
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41M0JZ55E00GNT7575JCJR8X1V
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41M0JZ5WX10GWF5D3VT7H67GE5
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41M0JZ6BZN0GSWVQR2BQ5BE7MB
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
  • AbortController abortReasonTypesWorkflow: various abort reason types propagate correctly
  • AbortController abortFetchUncaughtWorkflow: uncaught fetch AbortError is FatalError, no retries
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • getterStepWorkflow - getter functions with "use step" directive | wrun_41M0JZ8NXZ0GREBSDCW6ERB6MW
  • distributedAbortController - manual abort triggers signal | wrun_41M0JZ93NN0GS319GV8H7YVSVR
  • distributedAbortController - TTL expiration triggers signal | wrun_41M0JZ9VNR0GHMXTSW00SC835M
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes validation DX: invalid writes throw catchable FatalErrors naming rule and limit

🪟 Windows (1 failed)

nextjs-turbopack-node (1 failed):

  • cancelRun via CLI - cancelling a running workflow | wrun_41M0JZ6ADY0GKZ8WCYHQ4V18QX

⚠️ Flaky E2E Tests (passed on retry)

These tests failed at least once and passed on a retry. A recurring entry here is a real race worth investigating.

18 flaky tests
  • addTenWorkflow (hono)
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously (fastify)
  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data (nextjs-webpack)
  • hookCleanupTestWorkflow - hook token reuse after workflow completion (nitro)
  • hookGetConflictThenStepParallelWorkflow - hook.getConflict() continuation step runs alongside other steps (nextjs-webpack)
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable (express)
  • hookMinRetentionWorkflow - terminal Hook cannot resume and its token stays unavailable (hono)
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token (nextjs-webpack)
  • Promise.all of disjoint-key writes: every key lands (sveltekit)
  • sleepWinsRaceWorkflow (vite)
  • start: reserved-prefix initial attributes are seeded with allowReservedAttributes (nextjs-turbopack)
  • start: reserved-prefix initial attributes are seeded with allowReservedAttributes (nitro)
  • validation DX: invalid writes throw catchable FatalErrors naming rule and limit (hono)
  • validation DX: invalid writes throw catchable FatalErrors naming rule and limit (sveltekit)
  • workflow throws after awaited setAttributes: attribute still persists on the failed run (example)
  • workflow throws after awaited setAttributes: attribute still persists on the failed run (hono)
  • workflow throws after awaited setAttributes: attribute still persists on the failed run (nest)
  • workflow throws after awaited setAttributes: attribute still persists on the failed run (nuxt)

🛠 Infra Events (absorbed by the harness)

Platform anomalies the e2e harness detected and worked around (e.g. a run the queue never picked up, replaced by a fresh run). Clustered timestamps indicate a backend blip; a steady drip indicates a platform issue worth escalating.

42 infra events
  • cold-start-warmup · suite warmup (tanstack-start) · at 20:06:30Z · abandoned wrun_01M0JYWCRVDS6Y1WH3BV8FZG85
  • run-pickup-stall · plainModuleDoneHook resumed via plain API route (o2flow shape) (nextjs-webpack) · at 20:15:39Z · abandoned wrun_01M0JZDGZ6Y8BD6JYNK4QBA1NC
  • run-pickup-stall · hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep (nextjs-webpack) · at 20:15:39Z · abandoned wrun_01M0JZDGZXW3RMPC2EGD9WEQT6
  • run-pickup-stall · sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) (nextjs-webpack) · at 20:16:06Z · abandoned wrun_01M0JZEC3ZFC2G0EAJCS7MSZ4N
  • run-pickup-stall · abortTimeoutWorkflow: timeout cancels long-running step (nextjs-webpack) · at 20:16:44Z · abandoned wrun_01M0JZFGATJXJAHBT40V413H90
  • run-pickup-stall · abortParallelWorkflow: abort cancels all parallel steps (nextjs-webpack) · at 20:16:51Z · abandoned wrun_01M0JZFQCYE1Q7JPXG44XEAMF6
  • run-pickup-stall · abortFromStepWorkflow: step abort cancels an in-flight sibling step (nextjs-webpack) · at 20:16:55Z · abandoned wrun_01M0JZFV2KN6DP016D7HFK0X7R
  • run-pickup-stall · abortAlreadyAbortedWorkflow: pre-aborted signal seen by step (nextjs-webpack) · at 20:16:59Z · abandoned wrun_01M0JZFZRBBJ0HS16RRR7RT2Z1
  • run-pickup-stall · getterStepWorkflow - getter functions with "use step" directive (nextjs-webpack) · at 20:18:46Z · abandoned wrun_01M0JZK7YEP35GM6ZG49TH1CTN
  • run-pickup-stall · abortFromStepWorkflow: step abort cancels an in-flight sibling step (nextjs-webpack) · at 20:19:08Z · abandoned wrun_01M0JZKXTFYBY6VYHXRJRDT0M0
  • run-pickup-stall · abortViaHookWorkflow: external hook triggers abort on in-flight step (nextjs-webpack) · at 20:19:15Z · abandoned wrun_01M0JZM3R6V2Q9KHJ8DSHB4CXJ
  • run-pickup-stall · distributedAbortController - TTL expiration triggers signal (nextjs-webpack) · at 20:19:25Z · abandoned wrun_01M0JZME69EJTQ15D1JT5TJQT2
  • run-pickup-stall · abortExternalSignalWorkflow: signal passed as workflow input (nextjs-webpack) · at 20:19:46Z · abandoned wrun_01M0JZN2HE7SP2J9TX5AKW510C
  • run-pickup-stall · abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps (nextjs-webpack) · at 20:19:56Z · abandoned wrun_01M0JZNBW10SR7P557Z11VYEH4
  • run-pickup-stall · distributedAbortController - reconnect to existing controller (nextjs-webpack) · at 20:20:00Z · abandoned wrun_01M0JZNFVYA4ANGET0DZ6WF2HG
  • run-pickup-stall · abortAnyInWorkflowWorkflow: AbortSignal.any composes signals inside the workflow VM (nextjs-webpack) · at 20:20:08Z · abandoned wrun_01M0JZNRDFV0GJNVQVW4WE9YAS
  • run-pickup-stall · getterStepWorkflow - getter functions with "use step" directive (nextjs-webpack) · at 20:20:25Z · abandoned wrun_01M0JZP8S9M42M9EQH4W1AD9GJ
  • run-pickup-stall · distributedAbortController - manual abort triggers signal (nextjs-webpack) · at 20:20:45Z · abandoned wrun_01M0JZPVX9F9P7PD3HZZAFME38
  • run-pickup-stall · abortViaHookWorkflow: external hook triggers abort on in-flight step (nextjs-webpack) · at 20:20:46Z · abandoned wrun_01M0JZPXBSMFWET5HP2DN9ZVHV
  • run-pickup-stall · abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals (nextjs-webpack) · at 20:20:56Z · abandoned wrun_01M0JZQ6EYA8KED3PZN8EV9D0F
  • run-pickup-stall · distributedAbortController - TTL expiration triggers signal (nextjs-webpack) · at 20:21:08Z · abandoned wrun_01M0JZQK0G9QMJM2AVHZF0NPPG
  • run-pickup-stall · distributedAbortController - reconnect to existing controller (nextjs-webpack) · at 20:21:25Z · abandoned wrun_01M0JZR3CAQ8JGM8G64N3081E2
  • run-pickup-stall · abortExternalSignalWorkflow: signal passed as workflow input (nextjs-webpack) · at 20:21:30Z · abandoned wrun_01M0JZR81BGHS6QA24MB1BZ5WT
  • run-pickup-stall · abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps (nextjs-webpack) · at 20:21:32Z · abandoned wrun_01M0JZR9NAG0TNMW2BW4962NDA
  • run-pickup-stall · abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals (nextjs-webpack) · at 20:23:22Z · abandoned wrun_01M0JZVNN2N13VVFC4823N0PAY
  • run-pickup-stall · validation DX: invalid writes throw catchable FatalErrors naming rule and limit (nextjs-webpack) · at 20:23:24Z · abandoned wrun_01M0JZVQJGC31038WVJDCS02WB
  • run-pickup-stall · fire-and-forget: void setAttributes lands without awaiting (nextjs-webpack) · at 20:23:27Z · abandoned wrun_01M0JZVT8RDGGRM3ZX8GCMW5F0
  • run-pickup-stall · Promise.all of disjoint-key writes: every key lands (nextjs-webpack) · at 20:23:41Z · abandoned wrun_01M0JZW855PKB7N2PGXXNH5MDS
  • run-pickup-stall · abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries (nextjs-webpack) · at 20:23:54Z · abandoned wrun_01M0JZWMW1DBX9GYXD2KWKHVR3
  • run-pickup-stall · abortReasonTypesWorkflow: various abort reason types propagate correctly (nextjs-webpack) · at 20:23:57Z · abandoned wrun_01M0JZWQJ8GCME9SCM5TZW6AV1
  • run-pickup-stall · abortFetchUncaughtWorkflow: uncaught fetch AbortError is FatalError, no retries (nextjs-webpack) · at 20:24:11Z · abandoned wrun_01M0JZX5NT84QKRGD4923W8AG9
  • run-pickup-stall · validation DX: invalid writes throw catchable FatalErrors naming rule and limit (nextjs-webpack) · at 20:24:22Z · abandoned wrun_01M0JZXG82ECP1Q76SQYZERMB8
  • run-pickup-stall · abortFetchInFlightWorkflow: aborting cancels an in-flight fetch (nextjs-webpack) · at 20:24:41Z · abandoned wrun_01M0JZY2DHTS1728KFADPMASS7
  • run-pickup-stall · abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works (nextjs-webpack) · at 20:24:52Z · abandoned wrun_01M0JZYDHKRHPNYX6TJ82NBT6Q
  • run-pickup-stall · abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay (nextjs-webpack) · at 20:24:54Z · abandoned wrun_01M0JZYFJQNBPT35BBSE63CWRC
  • run-pickup-stall · abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal (nextjs-webpack) · at 20:24:57Z · abandoned wrun_01M0JZYJ6WGCSYERJ1ME2YYZZ0
  • run-pickup-stall · abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires (nextjs-webpack) · at 20:25:11Z · abandoned wrun_01M0JZZ0B1BGPMW1V0X5X072X1
  • run-pickup-stall · abortFetchInFlightWorkflow: aborting cancels an in-flight fetch (nextjs-webpack) · at 20:25:41Z · abandoned wrun_01M0JZZX2NRNHF775EAA6HGSBE
  • run-pickup-stall · abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works (nextjs-webpack) · at 20:25:52Z · abandoned wrun_01M0K00867K5TJDBSK9RGMM5EJ
  • run-pickup-stall · abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay (nextjs-webpack) · at 20:25:54Z · abandoned wrun_01M0K00A7RT48NB45FMY04RKVH
  • run-pickup-stall · abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal (nextjs-webpack) · at 20:25:57Z · abandoned wrun_01M0K00CVS16DC83RRC6NMGX1Q
  • run-pickup-stall · abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires (nextjs-webpack) · at 20:26:12Z · abandoned wrun_01M0K00V07S7JYFS8TESVCKJPP

E2E Test Summary

Summary
Passed Failed Skipped Total
❌ ▲ Vercel Production 3339 239 742 4320
❌ 💻 Local Development 3896 26 558 4480
✅ 📦 Local Production 3922 0 558 4480
✅ 🐘 Local Postgres 3922 0 558 4480
❌ 🪟 Windows 319 1 0 320
✅ 🌐 Cross-language Conformance 9 0 132 141
✅ vercel-multi-region 27 0 0 27
Total 15434 266 2548 18248
Details by Category

❌ ▲ Vercel Production

App Passed Failed Skipped
❌ astro-node 123 9 28
❌ astro-quickjs 123 9 28
❌ example-node 122 10 28
❌ example-quickjs 123 9 28
❌ express-node 123 9 28
❌ express-quickjs 121 11 28
❌ fastify-node 124 8 28
❌ fastify-quickjs 121 11 28
❌ hono-node 123 9 28
❌ hono-quickjs 123 9 28
❌ nest-node 121 11 28
❌ nest-quickjs 121 11 28
❌ nextjs-turbopack-node 152 5 3
❌ nextjs-turbopack-quickjs 146 11 3
❌ nextjs-webpack-node 149 8 3
❌ nextjs-webpack-quickjs 148 9 3
❌ nitro-node 122 10 28
❌ nitro-quickjs 125 7 28
❌ nuxt-node 123 9 28
❌ nuxt-quickjs 124 8 28
✅ python-node 8 0 152
❌ sveltekit-node 142 9 9
❌ sveltekit-quickjs 139 12 9
❌ tanstack-start-node 125 7 28
❌ tanstack-start-quickjs 122 10 28
❌ vite-node 123 9 28
❌ vite-quickjs 123 9 28

❌ 💻 Local Development

App Passed Failed Skipped
✅ astro-stable-node 134 0 26
✅ astro-stable-quickjs 134 0 26
✅ express-stable-node 134 0 26
✅ express-stable-quickjs 134 0 26
✅ fastify-stable-node 134 0 26
✅ fastify-stable-quickjs 134 0 26
✅ hono-stable-node 134 0 26
✅ hono-stable-quickjs 134 0 26
✅ nest-stable-node 134 0 26
✅ nest-stable-quickjs 134 0 26
✅ nextjs-turbopack-canary-node 141 0 19
✅ nextjs-turbopack-canary-quickjs 141 0 19
✅ nextjs-turbopack-stable-node 160 0 0
✅ nextjs-turbopack-stable-quickjs 160 0 0
❌ nextjs-webpack-canary-node 115 26 19
✅ nextjs-webpack-canary-quickjs 141 0 19
✅ nextjs-webpack-stable-node 160 0 0
✅ nextjs-webpack-stable-quickjs 160 0 0
✅ nitro-stable-node 134 0 26
✅ nitro-stable-quickjs 134 0 26
✅ nuxt-stable-node 134 0 26
✅ nuxt-stable-quickjs 134 0 26
✅ sveltekit-stable-node 153 0 7
✅ sveltekit-stable-quickjs 153 0 7
✅ tanstack-start-node 134 0 26
✅ tanstack-start-quickjs 134 0 26
✅ vite-stable-node 134 0 26
✅ vite-stable-quickjs 134 0 26

✅ 📦 Local Production

App Passed Failed Skipped
✅ astro-stable-node 134 0 26
✅ astro-stable-quickjs 134 0 26
✅ express-stable-node 134 0 26
✅ express-stable-quickjs 134 0 26
✅ fastify-stable-node 134 0 26
✅ fastify-stable-quickjs 134 0 26
✅ hono-stable-node 134 0 26
✅ hono-stable-quickjs 134 0 26
✅ nest-stable-node 134 0 26
✅ nest-stable-quickjs 134 0 26
✅ nextjs-turbopack-canary-node 141 0 19
✅ nextjs-turbopack-canary-quickjs 141 0 19
✅ nextjs-turbopack-stable-node 160 0 0
✅ nextjs-turbopack-stable-quickjs 160 0 0
✅ nextjs-webpack-canary-node 141 0 19
✅ nextjs-webpack-canary-quickjs 141 0 19
✅ nextjs-webpack-stable-node 160 0 0
✅ nextjs-webpack-stable-quickjs 160 0 0
✅ nitro-stable-node 134 0 26
✅ nitro-stable-quickjs 134 0 26
✅ nuxt-stable-node 134 0 26
✅ nuxt-stable-quickjs 134 0 26
✅ sveltekit-stable-node 153 0 7
✅ sveltekit-stable-quickjs 153 0 7
✅ tanstack-start-node 134 0 26
✅ tanstack-start-quickjs 134 0 26
✅ vite-stable-node 134 0 26
✅ vite-stable-quickjs 134 0 26

✅ 🐘 Local Postgres

App Passed Failed Skipped
✅ astro-stable-node 134 0 26
✅ astro-stable-quickjs 134 0 26
✅ express-stable-node 134 0 26
✅ express-stable-quickjs 134 0 26
✅ fastify-stable-node 134 0 26
✅ fastify-stable-quickjs 134 0 26
✅ hono-stable-node 134 0 26
✅ hono-stable-quickjs 134 0 26
✅ nest-stable-node 134 0 26
✅ nest-stable-quickjs 134 0 26
✅ nextjs-turbopack-canary-node 141 0 19
✅ nextjs-turbopack-canary-quickjs 141 0 19
✅ nextjs-turbopack-stable-node 160 0 0
✅ nextjs-turbopack-stable-quickjs 160 0 0
✅ nextjs-webpack-canary-node 141 0 19
✅ nextjs-webpack-canary-quickjs 141 0 19
✅ nextjs-webpack-stable-node 160 0 0
✅ nextjs-webpack-stable-quickjs 160 0 0
✅ nitro-stable-node 134 0 26
✅ nitro-stable-quickjs 134 0 26
✅ nuxt-stable-node 134 0 26
✅ nuxt-stable-quickjs 134 0 26
✅ sveltekit-stable-node 153 0 7
✅ sveltekit-stable-quickjs 153 0 7
✅ tanstack-start-node 134 0 26
✅ tanstack-start-quickjs 134 0 26
✅ vite-stable-node 134 0 26
✅ vite-stable-quickjs 134 0 26

❌ 🪟 Windows

App Passed Failed Skipped
❌ nextjs-turbopack-node 159 1 0
✅ nextjs-turbopack-quickjs 160 0 0

✅ 🌐 Cross-language Conformance

App Passed Failed Skipped
✅ python 9 0 132

✅ vercel-multi-region

App Passed Failed Skipped
✅ nextjs-turbopack 27 0 0

📋 View full workflow run

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

📊 Workflow Benchmarks

The benchmark run for a08bced failed. See the run logs for details.

No benchmark results were produced.

ℹ️ Metric definitions & methodology

Metrics —

All timestamps are deployment-side; runs are triggered in-deployment, so the CI runner and api.vercel.com sit outside every measured window. TTFS = start() → first step body (includes dispatch + any cold start); Fan-out TTFS/TTLS = first/last step completion of one Promise.all from the same anchor (the gap is the runtime’s fan-out spread); STSO/WO between step bodies; CRTT inside the workflow (excludes the api.vercel.com read path).

Cold starts stay in the numbers (real bursty-workload latency, inflates P75+); Best is the warm floor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant