Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix(swc-plugin): remove __builtin special-case step ID generation by VaguelySerious · Pull Request #1607 · vercel/workflow · GitHub
Skip to content

fix(swc-plugin): remove __builtin special-case step ID generation - #1607

Merged
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration
Apr 3, 2026
Merged

fix(swc-plugin): remove __builtin special-case step ID generation#1607
VaguelySerious merged 1 commit into
pgp/revert-revert-startfrom
peter/builtin-step-id-registration

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Summary

  • Removes a hardcoded special case in the SWC Rust plugin that generated bare function names (no step// prefix, no module specifier) for any function whose name starts with __builtin
  • With this fix, __builtin_response_* functions get proper step//workflow/internal/builtins@{version}//{name} IDs, matching what builtinStepId() constructs in the workflow VM

Context

The __builtin special case (at transform/src/lib.rs:1581) was added so the workflow VM could look up response builtins by bare name. Since #1491 switches the VM to fully-qualified IDs via builtinStepId(), the special case causes a mismatch:

Registered step IDVM lookup ID
Before__builtin_response_text__builtin_response_text
After #1491__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text
After this fixstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_textstep//workflow/internal/builtins@4.2.0-beta.76//__builtin_response_text

The parent commit (Fix 1) adds a fallback alias in getStepFunction() that unblocks the tests even without this fix, but this fix makes the IDs match directly — which is the architecturally correct solution.

Test plan

  • 138 Rust tests pass (cargo test in transform crate)
  • 573 @workflow/core tests pass
  • 124 @workflow/builders tests pass
  • Verified registerStepFunction output in example workbench build — all 12 builtins now have proper step//workflow/internal/builtins@{version}//... IDs

🤖 Generated with Claude Code

The SWC plugin had a hardcoded special case that generated bare function
names (no step// prefix, no module specifier) for any function whose name
starts with "__builtin". This was originally intended to produce stable,
version-independent IDs for the workflow VM.
With the introduction of builtinStepId() in @workflow/core, the VM now
constructs fully-qualified step IDs (step//workflow/internal/builtins@{version}//name).
The bare-name special case causes a mismatch: the VM requests a qualified ID
but only a bare name is registered, causing StepNotRegisteredError.
Remove the special case so __builtin functions follow the standard step ID
generation path, receiving proper step//moduleSpecifier//name IDs like all
other step functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VaguelySerious
VaguelySerious requested a review from a team as a code ownerApril 3, 2026 21:06
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e51bd7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

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

@vercel

vercelBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production800060860
✅ 💻 Local Development7100150860
✅ 📦 Local Production7100150860
✅ 🐘 Local Postgres7100150860
✅ 🪟 Windows780886
❌ 🌍 Community Worlds1386324225
✅ 📋 Other216042258
Total3362635844009

❌ Failed Tests

🌍 Community Worlds (63 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ

turso (58 failed):

  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • addTenWorkflow | wrun_01KNAJVAY23C7ZZ4FDHYHES2Q4
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNAJX9N6M8XW52G1BKB1TJRD
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNAJVGX0NAX28RMDJB72J30P
  • promiseRaceWorkflow | wrun_01KNAJVMZ9B3FF50WKX1R6XE24
  • promiseAnyWorkflow | wrun_01KNAJVPX7HKWV58F6QPFSB8JN
  • importedStepOnlyWorkflow | wrun_01KNAJXNJFP2HTSFF1BC8982YA
  • hookWorkflow | wrun_01KNAJW30A9CA5GFMXYEDW93H8
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNAJWDD2PWGT17JAQGRJRPPZ
  • webhookWorkflow | wrun_01KNAJWNVKDGV95787T826DAST
  • sleepingWorkflow | wrun_01KNAJWVTH6WNHX27VSPP5CNXX
  • parallelSleepWorkflow | wrun_01KNAJX7MDGJD87MKYMNW37DFW
  • nullByteWorkflow | wrun_01KNAJXBPNRJTJJFKXBQXPK0KN
  • workflowAndStepMetadataWorkflow | wrun_01KNAJXFSYM1S2BEK0JTGJAQZW
  • fetchWorkflow | wrun_01KNAK03VD6RGT0V4D7593106T
  • promiseRaceStressTestWorkflow | wrun_01KNAK07ZFA1XPG1R8Z5XKTCJJ
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KNAK3FEPR1B4FF8TV80BEQG3
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNAK4481THVEEM1NTVB143RZ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNAK4SRYKR59M8TE6YJT0Z52
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNAK5D2EVXSZMJBN4KWM66JE
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNAK5PSWAH8GT34DEYSP4FR1
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNAK5WMMYERWY3W03JCWV503
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNAK5YJX8P2QQKH7AQFWB008
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KNAK69JBXHBB5Q519JY5W4BS
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KNAK6BY33267E48BH849281Z
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNAK6SS75MS5A3XZ7AJFTRPD
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNAK6YQYC173Z1N7PWXK1VAY
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNAK75S2WECEG8DFER300YKJ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNAK7CQ708EA1EF7Y17YVXV2
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNAK7JP0ZNH4H3WPD29GQQWC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNAK7TC7D3NBPVEW1EEVPC3A
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNAK83J8Z1FAKNVX5H4FTQT5
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNAK8DMZGMDNH79VK9ET4H67
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNAK8MNBW7QRFH91J14FYJPX
  • cancelRun - cancelling a running workflow | wrun_01KNAK8THW2GRZHBC5CSHRRK42
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNAK9342XH5GYKKB0Y3GW485
  • 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_01KNAK9E6WA288RED8PVR2HWEV
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNAKA0V7M1HAMW5YB75WN2G6
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNAKABP8DSFXRP17WVE1RKF9
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNAKAJ633AEGTA8WEDKD4NA5
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577)

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro7907
✅ example7907
✅ express7907
✅ fastify7907
✅ hono7907
✅ nextjs-turbopack8402
✅ nextjs-webpack8402
✅ nitro7907
✅ nuxt7907
✅ vite7907
✅ 💻 Local Development
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 📦 Local Production
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ express-stable72014
✅ fastify-stable72014
✅ hono-stable72014
✅ nextjs-turbopack-canary61025
✅ nextjs-turbopack-stable7808
✅ nextjs-webpack-canary61025
✅ nextjs-webpack-stable7808
✅ nitro-stable72014
✅ nuxt-stable72014
✅ vite-stable72014
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack7808
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev500
❌ mongodb5938
✅ redis-dev500
❌ redis6028
✅ turso-dev500
❌ turso4588
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable72014
✅ e2e-local-postgres-nest-stable72014
✅ e2e-local-prod-nest-stable72014

📋 View full workflow run

@karthikscale3karthikscale3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review:

Assessment: Low risk, architecturally correct — no blockers

What this does

Deletes 7 lines from the SWC Rust plugin's create_id function — a special case that generated bare function names (e.g. __builtin_response_text) for any function starting with __builtin, instead of the standard step//{moduleSpecifier}//{name} format.

Why it's needed

The base branch (pgp/revert-revert-start) introduces builtinStepId() in packages/core/src/workflow/builtin-step-id.ts, which changes the VM to look up builtins using fully-qualified IDs:

// VM now requests:step//workflow/internal/builtins@{version}//__builtin_response_text

Without this PR, the SWC plugin still registers the bare name __builtin_response_text, creating a mismatch.

No regressions expected

  1. Safety net exists: The base branch already adds getBuiltinStepAlias() which handles both directions — bare-name lookup of qualified registrations AND qualified lookup of bare-name registrations. Even without this PR the system works; this PR makes the direct match path work, eliminating the need for the fallback.

  2. No event replay concerns: The workflow VM uses a seeded PRNG (vmGlobalThis.Math.random()) for deterministic ULID generation, so correlationIds match during replay. The stepName is only used for step function dispatch, not event matching. And dispatch is guarded by the getBuiltinStepAlias fallback.

  3. No user-facing __builtin convention: The __builtin prefix is internal SDK convention. User code should never use it.

  4. Spec-aligned: spec.md on the base branch already documents builtins with qualified IDs (step//workflow/internal/builtins@4.0.0//start), so this PR aligns the implementation with the spec.

Minor callout

Missing changeset: The changeset-bot flagged this. Since this changes SWC plugin behavior (step ID generation for __builtin functions), it should include a patch changeset for @workflow/swc-plugin before merge.

@VaguelySerious
VaguelySerious merged commit b394412 into pgp/revert-revert-startApr 3, 2026
78 of 85 checks passed
@VaguelySerious
VaguelySerious deleted the peter/builtin-step-id-registration branch April 3, 2026 21:27
Sign up for freeto 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.

2 participants

@VaguelySerious@karthikscale3