* Fix stable CI test harness failures
* Fix dev e2e cleanup races
* Restore non-Next dev cleanup
* Keep Next dev temp workflow files intact
* Keep dev test placeholders on disk
* Speed up workflow port detection
* Probe workflow health with POST
* Support HEAD workflow health checks
* Stabilize local CI health checks
* Retry flaky Vercel agent e2e
* Wrap generated framework route exports
* Relax remote addTen e2e timeout
* Materialize manual webhook responses
* Give remote CLI inspect more time
* Stabilize remote sleep and hook e2e checks
* Wait for step return streams before completion
* Stabilize hook and stream e2e waits
* Bound queue health check timeouts
* Address stable CI review feedback
* Fix route export replacement with embedded source maps
* feat: export semantic error types and add API reference documentation
Add missing error exports (HookNotFoundError, EntityConflictError,
RunExpiredError, TooEarlyError, ThrottleError, RunNotSupportedError,
WorkflowWorldError) to workflow/internal/errors. Create new error
classes for world-level semantics. Tighten TSDoc comments on all
error classes. Add API reference docs for all error types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use @setup declarations, workflow/errors import, and errors/ doc section
- Replace @skip-typecheck with proper `declare` + `// @setup` lines
so code samples are typechecked but setup lines hidden from readers
- Add `workflow/errors` export to package.json (public API, replaces
`workflow/internal/errors` in docs)
- Add `workflow/errors` path mapping in docs-typecheck type-checker
- Add HookConflictError to re-export list
- Move all error docs under api-reference/workflow/errors/ subdirectory
- Update all internal cross-references and links
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: move error docs to top-level workflow-errors section
- Move semantic error docs to api-reference/workflow-errors/ (matching
the workflow/errors import path, like workflow-api for workflow/api)
- Keep FatalError and RetryableError in api-reference/workflow/ since
they're imported from workflow, not workflow/errors
- Fix all cross-reference links
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update HTTP debug logger JSDoc to clarify scope
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: make TooEarlyError.retryAfter a number (seconds) matching WorkflowWorldError
TooEarlyError.retryAfter is now seconds (number) instead of a Date,
consistent with ThrottleError and WorkflowWorldError. The conversion
from seconds to Date is done at the consumer site (step-handler) rather
than at construction time.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback on docs accuracy
- WorkflowWorldError docs: add status, code, url, retryAfter properties
to TSDoc; clarify that .is() only matches direct instances (not
subclasses); use instanceof in catch-all example
- TooEarlyError/ThrottleError docs: mark retryAfter as optional (?)
to match actual type definitions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
This PR changes how the SWC compiler generates IDs for workflows, steps, and classes. Instead of using raw file paths, IDs are now based on **Node.js module specifiers** when the file belongs to a package (either in `node_modules` or a workspace package).
## Motivation
Previously, IDs were generated using file paths like `step//src/jobs/order.ts//fetchData`. This caused several issues:
1. **Package exports conditions**: When a package uses conditional exports (e.g., `"workflow"` vs `"default"` conditions in `package.json`), the same import specifier can resolve to different files. Using file paths meant IDs could differ based on which export condition was used.
2. **Cross-bundle consistency**: Classes serialized in one bundle couldn't be deserialized in another if the file paths differed.
3. **Version tracking**: No way to include package versions in IDs for cache invalidation.
## Changes
### New ID Format
IDs now use the format `{type}//{modulePath}//{identifier}` where `modulePath` is either:
- A **module specifier** like `point@0.0.1` or `@myorg/shared@1.2.3` for package files
- A **relative path** prefixed with `./` like `./src/jobs/order` for local app files
Examples:
- `step//workflow@4.0.1-beta.50//fetch` (SDK step)
- `step//./workflows/order//processOrder` (local step)
- `class//point@0.0.1//Point` (package class)
- `class//./src/models/User//User` (local class)
### New Module Specifier Resolution
Added `packages/builders/src/module-specifier.ts` which:
- Detects if a file is in `node_modules` or a workspace package
- Finds the nearest `package.json` and extracts name/version
- Returns the module specifier for the SWC plugin to use
### SWC Plugin Changes
- Added `moduleSpecifier` option to plugin config
- Updated `naming.rs` to support both module specifiers and relative paths
- Added `get_module_path()` helper that uses specifier when available, falls back to `./filename` format
### Special Cases
- **Builtin functions** (`__builtin_*`): Continue to use just the function name as the ID for stable, version-independent lookup from the workflow VM runtime.
## Testing
- Updated all 125+ SWC plugin test fixtures to use new ID format
- Added tests for module specifier resolution
- Added tests for Windows path normalization in naming
## Breaking Changes
This is technically a breaking change for any persisted workflow runs that reference the old ID format. However, since IDs are internal implementation details and not user-facing, this should not affect end users.
## Files Changed
- `packages/builders/src/module-specifier.ts` - **NEW**: Module specifier resolution logic
- `packages/builders/src/apply-swc-transform.ts` - Pass module specifier to SWC plugin
- `packages/builders/src/base-builder.ts` - Use `getImportPath` for virtual entry imports
- `packages/swc-plugin-workflow/transform/src/lib.rs` - Accept and use module specifier
- `packages/swc-plugin-workflow/transform/src/naming.rs` - New ID formatting with module paths
- `packages/swc-plugin-workflow/spec.md` - Updated documentation
- `packages/core/e2e/e2e.test.ts` - Updated test assertions for new ID format
* chore: use workflow health endpoint to check for port
* chore: update comment
* changeset
* Fix: The JSDoc comment for the `probePort` function is outdated and doesn't match the implementation. It claims the function returns true for "non-404 response" but the code now checks for exactly 200 status.
This commit fixes the issue reported at packages/utils/src/get-port.ts:251
## Outdated JSDoc comment in probePort() function doesn't match implementation
**What fails:** The JSDoc comment at line 251 of `packages/utils/src/get-port.ts` claims the `probePort()` function `@returns true if the port responds as a workflow server (non-404 response)`, but the actual implementation at line 269 explicitly checks `return response.status === 200;`
**How to reproduce:**
1. Read the JSDoc comment for `probePort()` function in `packages/utils/src/get-port.ts` (line 251)
2. Read the implementation at lines 268-269
3. Observe the mismatch: the comment says "non-404 response" but code checks for exactly status 200
**What happened vs expected behavior:**
- The code behavior was changed in commit `34cb235` (Dec 15, 2025) from checking `response.status !== 404` to checking `response.status === 200`
- The internal code comments were updated in commit `5840ab2`, but the JSDoc was left outdated
- Developers reading the JSDoc would incorrectly believe the function accepts any non-404 response (400, 405, etc.) when it actually requires exactly 200
**Fix:** Updated the JSDoc `@returns` line to accurately reflect the implementation: `@returns true if the port responds with a 200 status from the health check endpoint`
**Verification:** All 19 tests in `packages/utils/src/get-port.test.ts` pass with the updated documentation.
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
---------
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
* feat: add getPort method for detecting pid port
* lockfile
* update tests and fix getPort usage
* changeset
* docs: update sveltekit getting started
* fix: use pid-port
* fix: not using config port env
* fix: remove unused getPort from world core
* remove unused stuff
* fix: world local config returning port 3000 as fallback
* changeset
* fix: rebase conflicts
* fix: util test missing http import
* changeset
* fix: wrong import for getPort in core runtime
* fix: getPort in @workflow/utils being imported into workflow runtime
* test: simplify sveltekit test
* fix missing import in test
* fix: async await stuff with getPort
* refactor: move getPort to @workflow/utils/get-port
* test: simplfiy getPort tests
* test: fix sveltekit ports
Add a new `@workflow/utils` package to extract common utility functions.
- Created a new `@workflow/utils` package with common utility functions:
- `parseDurationToDate()` - Parses duration strings, numbers, or Date objects
- `withResolvers()` - Polyfill for `Promise.withResolvers()`
- `once()` - Creates a lazily-evaluated, memoized function
- `PromiseWithResolvers` - Type interface for promise resolvers
- Moved these utility functions from the core package to the new utils package
- Updated imports in the core package to use the new utils package
- Added tests for the utility functions in the new package
Signed-off-by: Nathan Rajlich <n@n8.io>