feat!: v8 audit remediation — robustness, unthrown, DX, and family consistency - #357
Conversation
…/ErrAsync Family-consistency audit against amqp-contract/unthrown conventions: - New TypedWorker class with a static create(options) factory (the org's Typed*.create() shape, sibling of TypedClient.create) returning AsyncResult<TypedWorker, never>; infrastructure failures stay TechnicalError-caused defects. run() returns AsyncResult<void, never> (never-rejecting, mid-run crash = defect), shutdown() delegates, and the raw Temporal Worker is exposed via .raw (runUntil/getState). The free createWorker is removed (beta window). - createContractTest's worker fixture now exposes the TypedWorker and drops the unhandled-rejection guard (run()'s promise never rejects). - Pre-lifted async results are built with OkAsync(v)/ErrAsync(e) (canonical since unthrown 4.1) instead of Ok(v).toAsync()/Err(e).toAsync() across source, specs, TSDoc, docs, examples, and agent rules. - Docs/README/upgrade-guide sweep + changeset (fixed group, major).
…e contract boundary - SignalNamesOf/QueryNamesOf/UpdateNamesOf/DeclaredErrorsOf renamed to the Infer* prefix family - defineActivity defaultOptions renamed to activityOptions - typed-error wire envelope marker (details[1]); data-less rehydration now requires the marker - onRehydrationMiss diagnostic hook for degrade-to-generic rehydration - strict ms-grammar duration validation at defineContract time - Temporal-reserved name rejection (__temporal_* prefix, __stack_trace, __enhanced_stack_trace) - activity-only contracts allowed (workflows may be empty when global activities exist) - exported error tag constants (CONTRACT_ERROR_TAG, TECHNICAL_ERROR_TAG)
…close the qualify defect hole - shared activity implemented twice with different functions now throws at declaration time - context.defineSignal/defineQuery/defineUpdate renamed to handleSignal/handleQuery/handleUpdate - export WorkflowContext, DeclareWorkflowOptions, child handle types, ActivityImplementationFor - qualifyFailure requires an expected-cause discriminator; unexpected causes ride the defect channel; inner nonRetryable inherited by default; expected: "any" is the explicit escape hatch - rethrowCancellation helper; swallowed-cancellation warnings on cancellation error classes - async query/update schemas rejected at bind time with ContractMisuseError - continueAsNew can no longer override workflowType/taskQueue via options spread - ChildWorkflowError carries workflowName; validation errors carry a direction field - worker error tag constants; TypedWorker.create verifies workflow registration by default
…combinator refactor - WorkflowCancelledError/WorkflowTerminatedError/WorkflowTimeoutError classified from result paths - UpdateFailedError/UpdateRejectedError/QueryFailedError replace defect-channel leaks - error tag constants + P-composable tag bundles (tagPatterns helper) - handle.raw escape hatch; ContractClient/TypedScheduleClient constructors privatized - ContractClient exposes contract and taskQueue; DATETIME rejects invalid Date - interceptors can patch only input/signalInput, never identity fields - imperative assertNoDefect thunks replaced with AsyncResult combinator chains - schedule update() validates args against the contract when workflowType is declared
…, replay and skew coverage
- createContractTest({ contract, ... }) and runActivity(definition, options) per family convention
- runActivityHandler routes through the real declareActivitiesHandler wrapping and wire round-trip
- @unthrown/vitest wired in; raw boolean asserts migrated to matchers across worker/testing specs
- replay-history spec proves the Result machinery replays deterministically
- e2e specs: contract-skew degrade + onRehydrationMiss, marker false-positive regression,
activityOptionsByName taskQueue routing (Docker)
- testcontainers moved to an optional peer dependency with a lazy import and install-hint error
… off public subpaths - client/worker drop CJS output and legacy main/module/types fields; attw esm-only on all packages - @temporalio/* peer ranges tightened to ^1.16.0 (schedule API + search-attribute imports) - _internal_* symbols move to @temporal-contract/contract/internal; /result-async subpath removed - @standard-schema/spec regular-dep exception documented in dependencies rule
…owing, match folds
- client matchers use exported tag constants and tagPatterns bundles
- ContractError discrimination via the { errorName } object pattern
- workflow error handling via match({ ok, errCases, defect }) with rethrow-on-defect
- fix README link to the examples overview
There was a problem hiding this comment.
Pull request overview
This PR is a broad v8 “audit remediation” pass across the Temporal contract ecosystem, tightening correctness and robustness around unthrown integration, typed error wire format + rehydration, workflow/worker safety checks, and aligning naming/API shapes across the btravstack family as the 8.0 major stabilizes.
Changes:
- Strengthens typed error handling: introduces a wire marker for contract errors, adds rehydration diagnostics, and adds
_tagconstant exports/bundles for matcher ergonomics. - Improves worker/runtime robustness: adds bind-time schema synchronicity probing for query/update-input schemas, adds workflow registration branding, and hardens activity option merging / continue-as-new routing invariants.
- DX + packaging alignment: ESM-only outputs, catalog-managed doc dependencies, optional
testcontainersin testing, and widespread docs/tests updates to new APIs (TypedWorker,OkAsync/ErrAsync,handle*).
Reviewed changes
Copilot reviewed 131 out of 132 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| turbo.json | Adds lint/format tasks + dependencies. |
| pnpm-workspace.yaml | Adds mermaid/vitepress deps to catalog. |
| pnpm-lock.yaml | Lockfile updates for catalog + dev dep moves. |
| packages/worker/typedoc.json | Adds worker entrypoint to typedoc. |
| packages/worker/src/workflow-proxy.spec.ts | Renames defaultOptions→activityOptions in tests. |
| packages/worker/src/workflow-errors.spec.ts | Updates typed error wire marker expectations. |
| packages/worker/src/workflow-brand.ts | New workflow branding helper for registration checks. |
| packages/worker/src/wire-format.spec.ts | Switches to @unthrown/vitest matchers. |
| packages/worker/src/types.ts | Updates docs/comments for handle* renames. |
| packages/worker/src/internal.ts | Internal import path moves + option merge / child error shaping. |
| packages/worker/src/handlers.ts | Adds sync-schema probing for query/update binding. |
| packages/worker/src/errors.spec.ts | Adds coverage for tags, structured fields, cancellation rethrow helper. |
| packages/worker/src/error-tags.ts | New worker error-tag constants module. |
| packages/worker/src/contract-errors.ts | Adds wire marker slotting to ApplicationFailure details. |
| packages/worker/src/continue-as-new.spec.ts | Tests validated target wins over smuggled overrides. |
| packages/worker/src/child-workflow.ts | Uses InferSignalNames + carries workflowName structured field. |
| packages/worker/src/child-workflow.spec.ts | Verifies structured workflowName on ChildWorkflowError. |
| packages/worker/src/activities-proxy.ts | Moves rehydration helper import to contract/internal. |
| packages/worker/src/activities-proxy.spec.ts | Matcher updates + typed tag assertions. |
| packages/worker/src/tests/worker.spec.ts | Migrates to TypedWorker + OkAsync/ErrAsync patterns. |
| packages/worker/src/tests/time-skipping.inprocess.spec.ts | Migrates to TypedWorker + adds cancellation outcome test. |
| packages/worker/src/tests/test.workflows.ts | Updates to handleSignal/handleQuery/handleUpdate. |
| packages/worker/src/tests/routing.workflows.ts | Adds routed activityOptionsByName workflow for routing spec. |
| packages/worker/src/tests/routing.spec.ts | Adds end-to-end routing integration spec. |
| packages/worker/src/tests/routing.contract.ts | Contract for routing spec (activityOptions + routing queues). |
| packages/worker/src/tests/replay.inprocess.spec.ts | Adds replay determinism coverage for unthrown machinery. |
| packages/worker/src/tests/rehydration.workflows.ts | Adds workflows for rehydration audit gaps. |
| packages/worker/src/tests/rehydration.inprocess.spec.ts | Adds in-process rehydration audit-gap integration tests. |
| packages/worker/src/tests/rehydration.contract.ts | Defines skewed worker/client contracts for rehydration tests. |
| packages/worker/src/tests/registration.contract.ts | Contract for workflow registration check tests. |
| packages/worker/src/tests/registration-raw.workflows.ts | Adds “raw workflow function” scenario. |
| packages/worker/src/tests/registration-missing.workflows.ts | Adds “missing exported workflow” scenario. |
| packages/worker/src/tests/registration-mismatch.workflows.ts | Adds “export name mismatch” scenario. |
| packages/worker/src/tests/registration-complete.workflows.ts | Adds “registration complete” happy path scenario. |
| packages/worker/src/tests/inprocess.workflows.ts | Adds waitForever workflow for cancellation outcome coverage. |
| packages/worker/src/tests/inprocess.contract.ts | Adds waitForever workflow + activityOptions rename. |
| packages/worker/README.md | Updates docs to TypedWorker + run().get() semantics. |
| packages/worker/package.json | Drops CJS exports; tightens @temporalio peer ranges; esm-only attw. |
| packages/testing/vitest.config.ts | Adds vitest setupFiles; updates alias to contract/internal. |
| packages/testing/tsconfig.json | Updates TS path alias to contract/internal. |
| packages/testing/src/vitest.setup.ts | Registers @unthrown/vitest matchers globally. |
| packages/testing/src/time-skipping.ts | Updates examples to TypedWorker + raw.runUntil. |
| packages/testing/src/global-setup.ts | Lazily imports optional testcontainers with helpful error. |
| packages/testing/src/contract.ts | createContractTest moves to options bag + TypedWorker fixture. |
| packages/testing/src/tests/test.contract.ts | Updates activityOptions rename. |
| packages/testing/src/tests/contract-test.spec.ts | Updates OkAsync + matcher usage + options bag API. |
| packages/testing/package.json | Makes testcontainers optional peer; adds @unthrown/vitest. |
| packages/contract/typedoc.json | Adds errors.ts to typedoc entrypoints. |
| packages/contract/src/types.ts | Renames type helpers; defaultOptions→activityOptions. |
| packages/contract/src/types-inference.spec.ts | Updates to new Infer* helper names + adds activity-only contract test. |
| packages/contract/src/internal.ts | Establishes contract/internal entry + re-exports internal error helpers. |
| packages/contract/src/internal.spec.ts | Updates internal helper import path. |
| packages/contract/src/index.ts | Re-exports tag constants + renamed helper types. |
| packages/contract/src/errors.spec.ts | Adds marker + onRehydrationMiss coverage + tag constant checks. |
| packages/contract/src/error-tags.ts | New contract tag constants module. |
| packages/contract/package.json | Replaces /result-async with /internal subpath. |
| packages/client/src/types.ts | Widens query/update error unions with new first-class errors. |
| packages/client/src/types-inference.spec.ts | Pins new unions; ensures clients aren’t publicly constructible. |
| packages/client/src/schedule.spec.ts | Hardens schedule update semantics + validation coverage. |
| packages/client/src/interceptors.ts | Restricts interceptor patches to payload keys only. |
| packages/client/src/index.ts | Re-exports new errors + tag bundles + TagPatterns type. |
| packages/client/src/error-tags.ts | Adds client tag constants + grouped tag bundles. |
| packages/client/src/tests/client.spec.ts | Uses tag bundles + tagPatterns helper in matcher arms. |
| packages/client/package.json | Drops CJS output + sets attw esm-only profile + tightens peers. |
| knip.json | Updates Knip schema version + adds worker workflow entrypoints. |
| examples/order-processing-worker/src/application/worker.ts | Migrates to TypedWorker + defect handling + run().get(). |
| examples/order-processing-worker/src/application/activities.ts | Requires qualifyFailure.expected + OkAsync/ErrAsync usage. |
| examples/order-processing-worker/README.md | Updates docs links (examples overview). |
| docs/tutorial/your-first-workflow.md | Updates TypedWorker, retry cap, tag bundles, qualifyFailure.expected. |
| docs/tutorial/adding-signals-and-queries.md | Updates handle* APIs + sync-schema rules explanation. |
| docs/reference/glossary.md | Clarifies qualification as “expected-only” mapping. |
| docs/reference/errors.md | Updates TypedWorker.create naming and tables. |
| docs/reference/contract-surface.md | Updates activityOptions rename + reserved names/durations rules + marker docs. |
| docs/package.json | Moves docs deps to catalog specifiers. |
| docs/index.md | Updates qualifyFailure.expected + tag bundle matching. |
| docs/how-to/use-signals-queries-and-updates.md | Updates contract example + handle* + getOrThrow guidance. |
| docs/how-to/tune-activity-options.md | Updates defaultOptions→activityOptions + duration validation docs. |
| docs/how-to/troubleshoot.md | Updates TypedWorker naming + extractor guidance + qualifyFailure.expected docs. |
| docs/how-to/schedule-workflows.md | Documents schedule client reachability + update validation + extractor usage. |
| docs/how-to/run-child-workflows.md | Clarifies child signal arg behavior + parentClosePolicy default. |
| docs/how-to/model-domain-errors.md | Updates qualifyFailure.expected + CONTRACT_ERROR_TAG + marker explanation. |
| docs/how-to/migrate-from-neverthrow.md | Corrects historical neverthrow removal + updates unthrown idioms. |
| docs/how-to/intercept-client-calls.md | Documents patch-key restrictions + correct tap/tapFailure patterns. |
| docs/how-to/install.md | Tightens peer floors + documents optional peers. |
| docs/how-to/index-workflows-with-search-attributes.md | Fixes Result narrowing (Ok vs Err vs Defect). |
| docs/how-to/implement-activities.md | Requires qualifyFailure.expected + updates ErrAsync/OkAsync guidance. |
| docs/how-to/handle-cancellation.md | Adds rethrowCancellation guidance + corrects heartbeat behavior. |
| docs/how-to/define-a-contract.md | Updates collision semantics + activityOptions validation + activity-only contracts. |
| docs/how-to/continue-as-new.md | Fixes cursor advancement + continueAsNew option semantics. |
| docs/how-to/add-activity-middleware.md | Updates ErrAsync usage + qualifyFailure.expected examples. |
| docs/explanation/workflow-determinism.md | Updates handleSignal naming in examples. |
| docs/explanation/validation-boundaries.md | Updates contract shape rules + reserved names + activityOptions. |
| docs/explanation/the-result-model.md | Updates TypedWorker naming. |
| docs/explanation/nexus.md | Requires qualifyFailure.expected in example. |
| docs/explanation/architecture.md | Updates TypedWorker naming in examples. |
| docs/examples/index.md | Corrects integration test command. |
| docs/api/index.md | Adds testing surface ref + clarifies entrypoint-based docs. |
| docs/.vitepress/config.ts | Adds Testing surface to sidebar. |
| AGENTS.md | Updates agent rules to prefer OkAsync/ErrAsync and TypedWorker wording. |
| .changeset/v8-audit-remediation.md | Major changeset documenting full audit remediation surface. |
| .changeset/family-consistency-typed-worker.md | Major changeset documenting TypedWorker migration + idiom sweep. |
| .agents/rules/handlers.md | Updates worker/setup and qualifyFailure.expected guidance. |
| .agents/rules/dependencies.md | Tightens peer floors + documents optional peers and spec exception. |
| .agents/rules/contract-patterns.md | Adds verb-tier naming policy + options-bag signature rule. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Addresses both review comments on #357. `bindQueryHandler` / `bindUpdateHandler`'s per-call sync guards used `instanceof Promise` while the bind-time probe used `isThenable`. Standard Schema types the async branch as `Promise<Result>`, but an implementation may hand back any `PromiseLike` — that slipped past `instanceof Promise`, and the helper then read `.issues` (undefined, i.e. "valid") and `.value` (undefined) straight off the thenable, handing the handler an unvalidated `undefined` instead of tripping `ContractMisuseError`. Both call sites now share an `isAsyncValidation` helper that matches the probe's check and detaches the thenable's settlement. `_internal_declaredWorkflowName` read a symbol property off an arbitrary module export, so a `Proxy` with a throwing `get` trap (or a throwing getter) aborted the whole workflow-registration check with an unrelated exception. The read is now guarded — anything that fails to yield a string brand is simply "not a declared workflow". Also fixes the red Integration Tests job: turbo ran the four `test:integration` tasks in parallel, each spinning up its own Temporal + Postgres testcontainer pair, and the contention pushed the client suite's fixture setup past Vitest's 10s `hookTimeout` default. Serialize the task (the workaround already documented in the PR description) and give the integration projects a `hookTimeout` sized for fixture setup that opens Temporal connections and builds a workflow bundle per worker. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The reusable CI workflow already invokes the root script with `--concurrency 3`, so hard-coding `--concurrency=1` inside it produced `turbo run … --concurrency=1 --concurrency 3`, which turbo rejects with "the argument '--concurrency <CONCURRENCY>' cannot be used multiple times". The `hookTimeout` bump on the integration projects is the fix that actually addresses the original failure (a 10s hook timeout during fixture setup); serializing the task stays available as the documented local workaround. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
btravers
left a comment
There was a problem hiding this comment.
Reviewed the full diff, with focus on the worker/client runtime surface. The
architecture holds up well — the triage philosophy behind qualifyFailure's
required expected, the shared-activity clobber guard, continueAsNew's
validated-target-wins ordering, the interceptor patch-key restriction, and the
outcome-error classification all read as sound and are properly tested.
Findings below, plus notes on what I pushed for the two Copilot comments and
the red Integration job.
Pushed in this branch
Both Copilot comments are addressed (351b56b).
The instanceof Promise → isThenable one is worth calling out as a real
correctness bug, not just an inconsistency. Standard Schema types the async
branch as Promise<Result>, but an implementation may legally return any
PromiseLike. Such a value slipped past instanceof Promise, and the code
then read .issues off the thenable (undefined → "no issues, valid") and
.value (undefined) — handing the handler an unvalidated undefined
instead of tripping ContractMisuseError. All four per-call guards now share
an isAsyncValidation helper that matches the bind-time probe's check and
detaches the thenable's settlement for the same reason the probe does.
The regression test was verified to fail against the pre-fix code before being
kept. _internal_declaredWorkflowName's guarded read has its own new
workflow-brand.spec.ts covering the throwing-getter and throwing-Proxy cases.
Integration Tests was failing on Hook timed out in 10000ms in the client
suite's fixture setup, which opens three Temporal connections and
webpack-bundles the workflows per worker — Vitest's 10s hookTimeout default
was never sized for that, and CI runs three integration tasks concurrently,
each with its own Temporal + Postgres containers. Fixed with
hookTimeout: 60_000 on the integration projects; the test body is still
bounded by testTimeout.
(For the record: I first also hard-coded --concurrency=1 into the root
test:integration script, which broke CI — the reusable workflow already
passes --concurrency 3 and turbo rejects a duplicate flag. Reverted in
c970308; serializing stays available as the manual workaround this PR's
description documents.)
Worth addressing before merge
packages/client/src/schedule.ts:338 — update loses conflict safety
To get validation in before anything persists, the wrapper now calls
describe() itself and hands handle.update() a precomputed object:
handle.update(() => updated)Temporal's ConditionFailed retry loop re-invokes that callback — but it now
returns the same options, built from a description that may since have gone
stale. So a concurrent modification landing between describe and update is
silently overwritten, where the SDK's own contract (re-run updateFn against a
fresh description) is precisely what makes concurrent updates safe.
The JSDoc states the mechanism ("the same computed options are retried") but
not the consequence. Either say last-writer-wins outright so callers can plan
for it, or re-describe → re-run updateFn → re-validate on conflict.
Minor
-
packages/contract/src/builder.ts—assertDurationordering. The guard
is!MS_DURATION_PATTERN.test(value) || value.length > 100. The regex is
linear so this isn't exploitable, but the cheap length cap belongs first. -
Wire-marker rolling upgrades. A data-less contract error emitted by a
pre-8.0 worker carries no marker, so an 8.0 client won't rehydrate it and it
degrades to a generic failure. Correct behavior for a major, and
onRehydrationMissmakes the window observable — but the upgrade guide should
state the deploy ordering explicitly, since the degrade is silent to anyone
who hasn't registered the hook. -
ActivityDefinition.activityOptionsis still typedActivityDefaultOptions
(packages/contract/src/types.ts:102). The property was renamed as part of the
defaultOptions→activityOptionssweep; the type name wasn't. -
The integration fixtures are per-test. 19 tests each build two workers, so
the suite pays the bundle cost ~38 times. ThehookTimeoutbump treats the
symptom; file-scoped fixtures would cut wall clock several-fold and remove the
sensitivity to runner contention entirely. Good follow-up — too invasive to
fold into this PR.
…schedule update concurrency Review remediation on the v8 audit branch. - `ActivityDefaultOptions` -> `ContractActivityOptions`. The property was renamed to `activityOptions` in the earlier sweep but the type name was missed; the new name also keeps the contract-level, portable subset distinct from Temporal's own `ActivityOptions`, which is what the worker-side `activityOptionsByName` overrides take. - `assertDuration` checks the cheap length cap before running the regex. The pattern is linear so this was never exploitable, just the wrong order. - `TypedScheduleHandle.update`'s JSDoc claimed Temporal retries `updateFn` on a server-side conflict. It does not: in SDK 1.20.3 `ScheduleHandle.update` describes once, calls `updateFn` once, and `_updateSchedule` sends no conflict token, so `UpdateSchedule` is unconditional. Concurrent updates are last-writer-wins in the raw SDK too. Documented plainly, including the one thing the wrapper does change (an extra `describe`, slightly widening the window) and the one guarantee it keeps (validated options == persisted options).
The example used `expected: Error` at every `qualifyFailure` site, which matches essentially every throw — the pre-v8 catch-all spelled differently. It was accurate (the domain only threw plain `Error`s) but it neutralized the feature the flagship example is meant to teach, and a reader landing on one of the bare sites had nothing to go on. Adds `domain/errors.ts` with one class per port under a shared `OrderProcessingError` base, and throws those from the use cases and the payment adapter. Each activity now names the failure it actually anticipates (`expected: ShippingError`, `expected: PaymentError`, ...), so the triage is visible: a provider fault is a modeled activity failure, a `TypeError` from a bug stays a defect and re-throws at the edge with its original stack.
- The v8 upgrade guide now has a rolling-upgrade warning for the typed-error wire marker. A data-less contract error emitted by a 7.x worker carries no marker, so an 8.0 reader degrades it to a generic failure — silently, unless `onRehydrationMiss` is registered. Documents workers-before-callers ordering, the hook, and that schema-bearing errors are unaffected. Added to the checklist. - `ActivityDefaultOptions` -> `ContractActivityOptions` in the rename table, the checklist, the contract-surface reference, and the changeset.
Review-body findings — resolvedFollow-up to the four items from the self-review that weren't inline comments. Pushed in
|
Addresses both review comments on #357. `bindQueryHandler` / `bindUpdateHandler`'s per-call sync guards used `instanceof Promise` while the bind-time probe used `isThenable`. Standard Schema types the async branch as `Promise<Result>`, but an implementation may hand back any `PromiseLike` — that slipped past `instanceof Promise`, and the helper then read `.issues` (undefined, i.e. "valid") and `.value` (undefined) straight off the thenable, handing the handler an unvalidated `undefined` instead of tripping `ContractMisuseError`. Both call sites now share an `isAsyncValidation` helper that matches the probe's check and detaches the thenable's settlement. `_internal_declaredWorkflowName` read a symbol property off an arbitrary module export, so a `Proxy` with a throwing `get` trap (or a throwing getter) aborted the whole workflow-registration check with an unrelated exception. The read is now guarded — anything that fails to yield a string brand is simply "not a declared workflow". Also fixes the red Integration Tests job: turbo ran the four `test:integration` tasks in parallel, each spinning up its own Temporal + Postgres testcontainer pair, and the contention pushed the client suite's fixture setup past Vitest's 10s `hookTimeout` default. Serialize the task (the workaround already documented in the PR description) and give the integration projects a `hookTimeout` sized for fixture setup that opens Temporal connections and builds a workflow bundle per worker. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Second full-surface pass hardening robustness, the unthrown integration, developer experience, and btravstack-family consistency before the 8.0 major stabilises. Driven by a five-track audit (unthrown integration, API/DX, robustness, docs, cross-library consistency).
Verification: typecheck (12 tasks), lint, unit tests (all packages), build (10), publint + attw
esm-only(14), knip, and the VitePress docs build all pass. Integration is green serially (worker 21, client 19, testing 3, sample-worker 8); the paralleltest:integrationcan fail on Docker resource contention — runturbo run test:integration --concurrency=1.Critical fix
activitiesmap.unthrown integration
qualifyFailure(type, { expected })—expectedis now required (error class / array / predicate / literal"any"). Unexpected causes ride the defect channel instead of being mislabelled a business error; a matched innernonRetryableis inherited.WorkflowCancelledError/WorkflowTerminatedError/WorkflowTimeoutErrorandUpdateFailedError/UpdateRejectedError/QueryFailedError.assertNoDefectthunks →AsyncResultcombinator chains;OkAsync/ErrAsyncand@unthrown/vitestmatchers adopted throughout.Robustness
details[1] = { $tc: 1 }) closes a rehydration false positive for data-less errors;onRehydrationMissdiagnostic hook on degrade-to-generic.rethrowCancellationhelper + docs for the swallowed-cancellation hazard when an activity declares anerrorsmap.TypedWorker.createverifies workflow registration by default (verifyWorkflowRegistration: falseto opt out);continueAsNewcan't override its validated target; reserved-name andms-duration validation atdefineContract.runActivityHandler(boundary-faithful activity testing) + a replay-determinism test.DX & family consistency
WorkflowContext, child-handle types,ActivityImplementationFor, …).context.defineSignal/defineQuery/defineUpdate→handleSignal/handleQuery/handleUpdate.Infer*helper naming anddefineActivity({ activityOptions })align with amqp-contract; P-composable tag bundles +tagPatternscollapse repetitive match arms.@temporalio/*peers tightened to^1.16.0; internals moved to a private/internalsubpath.Docs
isErr()-then-.valuesamples across every page, plus behavioral bugs (heartbeat()never throws,parentClosePolicydefault isTERMINATE, the tutorial's unbounded-retry hang, the boguscontinueAsNewretry option).reference/testing-surface.md; typedoc entry points forworker.tsand contracterrors.ts; a complete migration section added to the v8 upgrade guide.A changeset (all four packages, major) documents the full set. All changes are breaking and intended for the 8.0 major.