The correlationId was generated as hc_${generateId()}, but
generateHealthCheckRunId() already adds wrun_hc_, producing
wrun_hc_hc_... Similarly, getHealthCheckStreamName() adds
__health_check__, making the hc_ prefix in correlationId redundant.
Changesets already handles dist-tags correctly:
- On main: pre-release mode publishes with the 'beta' tag
- On stable: GA publishes default to the 'latest' tag
Use named export instead of `export =` in the CJS shim so that
Node.js cjs-module-lexer can detect withWorkflow as a named export,
enabling `import { withWorkflow } from 'workflow/next'` in ESM.
* docs: clarify Next monorepo setup
Prevent confusion when Next.js apps live below the repository root and workflow code imports sibling workspace packages.
This documents the output tracing root requirement at the point where users configure withWorkflow, so monorepo setups follow the same working patterns as the shipped Next.js integration instead of failing due to unresolved workspace imports.
Ploop-Iter: 1
* ploop: iteration 2 checkpoint
Automated checkpoint commit.
Ploop-Iter: 2
* ploop: iteration 3 checkpoint
Automated checkpoint commit.
Ploop-Iter: 3
* docs: audit recent documentation coverage
Capture recent workflow documentation updates so the public docs and package guidance stay aligned with the implementation and current docs-typecheck behavior.
Ploop-Iter: 1
* docs: align docs-typecheck docs
Document the current docs verification contract so contributors do not assume JavaScript examples are type-checked when only TypeScript snippets are enforced today.
Add regression coverage around the README language and framework integration guidance to keep those docs aligned with the implemented Next.js and docs-typecheck behavior as future changes land.
Ploop-Iter: 2
* docs: add start() troubleshooting guidance
Document the most common causes of the invalid workflow function error so users can resolve start() failures from the API docs and Next.js setup flow without having to infer build-time requirements from runtime behavior.
Keep the new troubleshooting page aligned with the shipped runtime message and add regression coverage so future wording or cross-link changes do not silently break that guidance.
Ploop-Iter: 3
* docs: align NestJS setup docs
Document both supported NestJS module formats and add a regression check so the getting-started guide stays aligned with the package README as the integration evolves.
Ploop-Iter: 1
* docs: tighten NestJS CommonJS guidance
Keep the NestJS getting-started guide consistent across the ESM and CommonJS paths so readers do not mix module settings or import styles mid-setup.
Strengthen the docs regression coverage around the later guide sections so future edits are more likely to preserve the supported CommonJS path documented in the package README.
Ploop-Iter: 2
* docs: align docs with recent workflow guidance
Document the recently added troubleshooting and observability patterns so the public docs stay aligned with the behavior users now encounter in practice.
This keeps the NestJS guide, workflow API reference, and docs regression coverage in sync with the runtime-facing guidance from recent changes.
Ploop-Iter: 3
* docs: audit docs coverage
Why: keep the docs aligned with recent API and runtime behavior changes so examples and reference pages don’t drift from the supported surface.
Ploop-Iter: 1
* test: add docs audit guards
Add regression coverage for doc surfaces that are easy to drift from implementation so docs audits catch mismatches early and keep published guidance aligned with the supported API surface.
Ploop-Iter: 2
* docs: add docs audit guards
Keep new observability and server-testing guidance anchored to machine-readable interfaces so follow-up implementation changes do not silently drift away from the documented agent and automation patterns.
Ploop-Iter: 3
* docs: align observability troubleshooting guidance
Keep the docs consistent so users get the same guidance when debugging hook token collisions and correlating workflow events with platform logs.
This prevents the event-sourcing reference from drifting away from the observability and error docs, and adds guard tests to catch regressions.
Ploop-Iter: 1
* Remove the unreferenced image file img-a-clean-minimal-technical-architecture-d-2026-02-27T14-07-52-1.png from the repo root, workbench/fastify/public/index.html (a Nitro example mistakenly placed in the fastify workbench by a ploop checkpoint), all .claude/worktrees/* submodule references, and all 15 string-presence audit guard tests in packages/docs-typecheck/src/__tests__/ (they only assert keyword presence, not semantic correctness). None of these belong in the docs audit PR.
* Address all PR #1466 review feedback from VaguelySerious, pranaygp, and ijjk:
1. Remove the "Machine-Readable Surfaces" section from docs/content/docs/observability/index.mdx (reviewers say it's unnecessary and already in world docs)
2. Remove all @skip-typecheck annotations from durable-agent.mdx (8) and server-based.mdx (1) — types exist in built packages/ai/dist after pnpm build
3. In durable-agent.mdx, change "machine-readable tool activity" to "tool call details" in the stream() return description
4. In durable-agent.mdx "Aborting Long-Running Streams" section, add a warning callout that abortSignal is not yet supported (blocked by #1301), recommend timeout instead
5. In event-sourcing.mdx, update requestId description: "On Vercel, requestId is the platform request ID when available. Other worlds are not expected to provide a requestId."
6. In get-world.mdx, change "user-friendly names from the machine-readable workflowName field" to "human-readable names from the workflowName field"
7. In start-invalid-workflow-function.mdx, add "// Does NOT work" comment above the bad example line
8. In with-workflow.mdx: reframe outputFileTracingRoot as a workaround (Next.js auto-detects by default per ijjk); change options description from "control local development behavior" to "configure the Next.js integration"; scope the callout to "workflows.local options only affect local development"
9. Drop the withWorkflow() options callout from docs/content/docs/getting-started/next.mdx
10. Remove the Next.js-specific outputFileTracingRoot callout from framework-integrations.mdx
11. Add a Troubleshooting section with the start() invalid-workflow-function error to all 9 non-Next getting-started guides (astro, express, fastify, hono, nestjs, nitro, nuxt, sveltekit, vite), each with framework-appropriate config check in point 2
* docs: absorb unique accuracy fixes from PR #1200
Cherry-picked 6 still-needed fixes from #1200 that aren't covered by
this audit PR or #1516:
- Fix npx workflow description (observability)
- Remove fetch from restricted modules list (errors)
- Fix package name @workflow-worlds/postgres → @workflow/world-postgres (deploying)
- Fix stream wording (foundations/starting-workflows)
- Fix import path simple → simple-streaming (foundations/streaming)
- Add close(), getEncryptionKeyForRun(), writeToStreamMulti() to World interface,
update create() and streamer signatures (deploying/building-a-world)
* docs: address review feedback on March docs audit
- durable-agent.mdx: "structured tool activity" → "tool call information"
per VaguelySerious's suggestion
- next.mdx: drop monorepo callout from getting-started per pranaygp
(too much context too early; info is in withWorkflow API ref)
* docs: fix 2 typecheck failures in encryption and nestjs guides
- encryption.mdx: add skip-typecheck for interface signature block
(getEncryptionKeyForRun overloads are not runnable code)
- nestjs.mdx: add skip-typecheck for WorkflowModule.forRoot config
snippet (fragment inside callout, full import shown above)
Verified: pnpm vitest run passes 300/300 in docs-typecheck.
The `dataDir` option was accepted in the type definition but never
read — `WORKFLOW_LOCAL_DATA_DIR` was unconditionally set to
`.next/workflow-data`. Remove the dead option to avoid confusion.
- Pass DOMException through to the workflow VM context alongside other
Web APIs (Headers, URL, TextEncoder, etc.)
- Add DOMException reducer/reviver to the serialization pipeline,
preserving message, name, derived code, and cause when present
- Add DOMException to the Serializable type union
- 8 new tests: round-trip for AbortError, NotFoundError, default name,
cause preservation, cause absence, serialization key, cross-VM
boundaries, and VM context availability
* fix(builders): override sideEffects:false for discovered workflow/step/serde entries
When node_modules packages include "sideEffects": false in their
package.json, esbuild drops bare imports from the virtual-entry.js
file. This is incorrect because the SWC compiler transform injects
side-effectful registration code (workflow IDs, step IDs, class
serialization) into these modules.
Fix: return the resolved path alongside sideEffects: true from the
onResolve handler so esbuild uses the plugin's resolution result
instead of re-reading the package.json.
* refactor(builders): normalize sideEffectEntries with realpaths for symlink compatibility
Extract withRealpaths() helper and use it for both normalizedEntriesToBundle
and sideEffectEntries at all three bundle sites. This ensures the
sideEffects override works correctly under pnpm/workspace symlinked
layouts where enhanced-resolve may return realpaths that differ from
the original discovered file paths.
* perf(builders): skip enhanced-resolve for transitive imports when only sideEffectEntries is set
When entriesToBundle is not set (workflow/client bundles), only top-level
import statements need the sideEffects override — transitive imports
from deep within the bundle are not bare imports and don't need resolution.
Skip enhanced-resolve for non-import-statement kinds to reduce overhead.
* fix(swc-plugin): use binding name for class expression method registrations
When a pre-bundled package (e.g. via tsup) contains class expressions
like `var Foo = class _Foo { ... }`, the internal name `_Foo` is only
scoped inside the class body. The SWC plugin was incorrectly using the
internal name for method step registrations and class serialization
registrations emitted at module scope, causing ReferenceError at runtime.
Fix: always use the binding name (registration_name) for
current_class_name in visit_mut_class_expr, consistent with the existing
handling for anonymous class expressions. This ensures:
- registerStepFunction calls reference the binding name (Foo)
- Only one class registration IIFE is emitted (not duplicates for both
Foo and _Foo)
- Step IDs use the binding name in their qualified path
* refactor(swc-plugin): rename internal_class_name to tracked_class_name for clarity
The variable no longer represents the internal class expression identifier
after being reassigned to the binding name. Rename to tracked_class_name
and eliminate the intermediate registration_name variable to make the
intent clearer and reduce confusion for future readers.
* fix(swc-plugin): rewrite anonymous export default class to const declaration
When an anonymous class with serde/step methods is exported as a default
export (`export default class { ... }`), the generated registration code
(registerStepFunction, class registry IIFE) would reference a nonexistent
variable at module scope, causing a ReferenceError at runtime.
Fix: detect anonymous default class exports in visit_mut_export_default_decl
and visit_mut_export_default_expr, generate a unique binding name
(__defaultClass), and defer a rewrite in visit_mut_module_items that
transforms the export into:
const __defaultClass = class __defaultClass { ... };
export default __defaultClass;
Named default class exports (export default class Foo { ... }) are
handled by setting current_class_binding_name so the transformer
uses the existing class name for registration code.
* refactor(swc-plugin): rename __defaultClass to __DefaultClass for class naming convention
* fix(swc-plugin): fix panic for step-only anonymous default class exports
Address review feedback:
- Remove expect() that panicked when anonymous default class had step
methods but no serde methods (ident was not re-inserted). Keep
const_name in a local variable instead of relying on class_expr.ident.
- Add debug_assert for single default class export invariant.
- Update spec.md and test fixture inputs to use new this() instead of
referencing the generated binding name.
- Add step-only anonymous default class fixture to cover the bug path.
* refactor(swc-plugin): address review feedback for export default class handling
- Remove dead Expr::Class handler in visit_mut_export_default_expr
(SWC wraps parenthesized form in Expr::Paren, so it never fires)
- Extract class_needs_binding_rewrite() helper, eliminating duplicated
detection logic and unnecessary body clones
- Add debug_assert for mutual exclusivity of default_workflow_exports
and default_class_exports
- Clarify spec.md on self-name behavior difference between serde and
step-only classes
* Fix node-module-error plugin matching identifiers in multi-line comments
The findIdentifierUsage function only stripped single-line comments and
same-line block comments, but didn't track multi-line block comment state.
Lines inside JSDoc/block comments (e.g. ` * ... Writable stream`) passed
through unstripped, causing the plugin to point at comments instead of
actual code usage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Strip string literals before scanning for comment delimiters
Move string stripping before comment detection so that comment delimiters
inside string literals (e.g. `const s = "/*"`) don't incorrectly trigger
block comment mode. Adds regression test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
* fix(builders): override sideEffects:false for discovered workflow/step/serde entries
When node_modules packages include "sideEffects": false in their
package.json, esbuild drops bare imports from the virtual-entry.js
file. This is incorrect because the SWC compiler transform injects
side-effectful registration code (workflow IDs, step IDs, class
serialization) into these modules.
Fix: return the resolved path alongside sideEffects: true from the
onResolve handler so esbuild uses the plugin's resolution result
instead of re-reading the package.json.
* refactor(builders): normalize sideEffectEntries with realpaths for symlink compatibility
Extract withRealpaths() helper and use it for both normalizedEntriesToBundle
and sideEffectEntries at all three bundle sites. This ensures the
sideEffects override works correctly under pnpm/workspace symlinked
layouts where enhanced-resolve may return realpaths that differ from
the original discovered file paths.
* perf(builders): skip enhanced-resolve for transitive imports when only sideEffectEntries is set
When entriesToBundle is not set (workflow/client bundles), only top-level
import statements need the sideEffects override — transitive imports
from deep within the bundle are not bare imports and don't need resolution.
Skip enhanced-resolve for non-import-statement kinds to reduce overhead.
* fix(swc-plugin): use binding name for class expression method registrations
When a pre-bundled package (e.g. via tsup) contains class expressions
like `var Foo = class _Foo { ... }`, the internal name `_Foo` is only
scoped inside the class body. The SWC plugin was incorrectly using the
internal name for method step registrations and class serialization
registrations emitted at module scope, causing ReferenceError at runtime.
Fix: always use the binding name (registration_name) for
current_class_name in visit_mut_class_expr, consistent with the existing
handling for anonymous class expressions. This ensures:
- registerStepFunction calls reference the binding name (Foo)
- Only one class registration IIFE is emitted (not duplicates for both
Foo and _Foo)
- Step IDs use the binding name in their qualified path
* refactor(swc-plugin): rename internal_class_name to tracked_class_name for clarity
The variable no longer represents the internal class expression identifier
after being reassigned to the binding name. Rename to tracked_class_name
and eliminate the intermediate registration_name variable to make the
intent clearer and reduce confusion for future readers.
* fix(builders): override sideEffects:false for discovered workflow/step/serde entries
When node_modules packages include "sideEffects": false in their
package.json, esbuild drops bare imports from the virtual-entry.js
file. This is incorrect because the SWC compiler transform injects
side-effectful registration code (workflow IDs, step IDs, class
serialization) into these modules.
Fix: return the resolved path alongside sideEffects: true from the
onResolve handler so esbuild uses the plugin's resolution result
instead of re-reading the package.json.
* refactor(builders): normalize sideEffectEntries with realpaths for symlink compatibility
Extract withRealpaths() helper and use it for both normalizedEntriesToBundle
and sideEffectEntries at all three bundle sites. This ensures the
sideEffects override works correctly under pnpm/workspace symlinked
layouts where enhanced-resolve may return realpaths that differ from
the original discovered file paths.
* perf(builders): skip enhanced-resolve for transitive imports when only sideEffectEntries is set
When entriesToBundle is not set (workflow/client bundles), only top-level
import statements need the sideEffects override — transitive imports
from deep within the bundle are not bare imports and don't need resolution.
Skip enhanced-resolve for non-import-statement kinds to reduce overhead.
* fix: update types and documentation for start function overloads
Ensure types are 'unknown[]' and 'unknown' for 'deploymentId' and update exports and documentation.
Slack-Thread: https://vercel.slack.com/archives/C09G3EQAL84/p1773368990070059?thread_ts=1773368990.070059&cid=C09G3EQAL84
Co-authored-by: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
* fix: use generics in deploymentId overloads to avoid contravariance issue
Addresses PR review feedback: typed workflows like
WorkflowFunction<[string], number> were not assignable to
WorkflowFunction<unknown[], unknown> under strictFunctionTypes.
Changed to generic parameters while keeping Run<unknown> return type.
Also adds type-level tests for overload resolution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add changeset for start() deploymentId type changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: v0 <v0[bot]@users.noreply.github.com>
Co-authored-by: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Rename 'Workflow Development Kit' / 'DevKit' to 'Workflow SDK' across docs, code, and config
Follow-up to cdf90d5a38 (#1541)
* Fix missing </h1> closing tag and add article 'the' before 'Workflow SDK' in docs
* docs: rename 'Complex Example' to 'Instance Methods as Steps' in serialization guide
Rework the section title and introductory copy to better reflect
the purpose: making classes with Node.js APIs / side effects
workflow-compatible by adding "use step" to instance methods.
* docs: clarify that the static requirement applies to serialization hooks
Make the callout explicitly name WORKFLOW_SERIALIZE and
WORKFLOW_DESERIALIZE so it doesn't read as a blanket restriction
on instance methods, which would contradict the 'Instance Methods
as Steps' section below.