Release v0.0.90
Overview
This release reorders the transition pipeline's epilogue so timers are never armed for a state the instance is already leaving. LifecycleOrder.Auto becomes 80 and LifecycleOrder.Schedule becomes 90 — auto-transition conditions are evaluated before scheduled transitions arm their timers — and a new guard skips arming entirely when the auto step has already selected a winner, logging ScheduledTransitionsSkippedForChainedNext (EventId 10156, Debug) instead of enqueuing a Dapr job and an InstanceJob row that the next hop would immediately tear down (#943). Beyond the wasted enqueue, the armed-then-cancelled window briefly exposed scheduled entries in the state function for states the instance was already leaving — clients could see a timer that would never fire. Alongside it, activation-episode tracing ties triggers, asynchronous jobs, subflows and event delivery into a single named episode, with synthetic activation spans and end-to-end activation duration metrics (#931). This release runs on component schema 0.0.53.
Features
Auto transitions are evaluated before timers are scheduled (#943)
The pipeline epilogue is re-sequenced:
| Step | Order before | Order after |
|---|---|---|
ClearBusyOnResumeStep | 79 | 79 (redefined as Auto - 1) |
RunAutomaticTransitionsStep | 90 | 80 |
ScheduleTransitionsStep | 80 | 90 |
ClearBusyOnResumeStep is redefined as Auto - 1, which keeps its numeric value at 79, so subflow and long-poll resume points are unchanged. The swap is deploy-safe in both directions: no persisted data carries step order values, and every ResumeFrom producer reads LifecycleOrder.ClearBusyOnResumeStep at fire time rather than a stored number.
The new guard. When the auto step has already selected a winner (Directives.NextTransition is set), ScheduleTransitionsStep arms nothing — no Dapr job, no InstanceJob row — and logs ScheduledTransitionsSkippedForChainedNext (EventId 10156, Debug). The guard sits after the existing HasScheduledTransitions early-out, so the "not armed" log only fires when the state actually has scheduled transitions.
Three deliberate behavior changes follow:
- When an auto winner is selected, timers for the state being left are never armed. The old behaviour armed them and cancelled them on the next hop — and if that chained hop faulted, useless timers stayed armed on a faulted instance.
- If the auto step itself fails (for example on unhandled non-blocking task failures), timers are not armed either. The instance faults anyway.
- Timer scripts now run after auto condition scripts. Auto evaluation does not mutate instance data, so timer inputs are unchanged.
Two paths were verified not to be affected by the swap: the only two RequestNextTransition call sites are the auto step (intended) and BoundaryOutcomeHandler, which always pairs it with SkipToFinalize() — so Schedule is unreachable with the directive set from the boundary path — and updateData's +Self profile excludes Schedule by name.
The client-visible effect is that a state the instance is chaining straight through no longer briefly advertises a kind: "scheduled" entry in the state function. A genuinely parked state still arms, still exposes executeAtUtc, and its timer still fires.
Reference: PR #943 — see also Transition pipeline and Workflow component.
Activation-episode tracing (#931)
An instance is "activated" by several different things — a client trigger, an asynchronous job callback, a subflow handoff, an event delivery — and each of those previously produced its own disconnected view of what followed. Activation-episode tracing gives them a shared identity:
- A synthetic activation span anchors each episode, and the episode identity is carried on job payloads and subflow/event inputs so an episode survives every hop it takes.
- End-to-end activation duration metrics measure the whole episode rather than a single transaction.
- Trace continuity across service and sidecar hops is tightened, and richer telemetry lands on transitions, settlements, faults, timeouts, enqueueing and instance availability.
The concept also gives the sub-state relay work in later releases a rest point to publish at — an episode's end is what "the chain stopped" means.
Reference: PR #931 — see also Observability.
Behavior Changes
The pipeline reorder changes observable behavior in three ways: when an auto transition wins, the state's timers are never armed at all (previously armed and cancelled on the next hop, and left armed on a faulted instance if that hop faulted); if the auto step fails, timers are not armed either; and timer scripts now run after auto condition scripts. The client-visible consequence is that a state being chained straight through no longer briefly advertises a scheduled entry in the state function. Each item, its impact direction and the migration steps are documented in the v0.0.90 breaking changes announcement.
Fixes
- Timers were armed and immediately torn down on every auto-win hop — each one paid an enqueue, a persist and a next-hop cancel for a timer that could never fire (#943).
- A faulting chained hop left useless timers armed on the faulted instance, because arming happened before the auto winner was known (#943).
- The state function briefly exposed scheduled entries for states the instance was already leaving, inside the armed-then-cancelled window (#943).
Configuration Updates
Configuration for v0.0.90:
{
"runtimeVersion": "0.0.90",
"schemaVersion": "0.0.53"
}
Note: Schema version is unchanged at 0.0.53. No configuration keys are added or changed in this release; the pipeline reorder needs no setting and no migration, because nothing persists step order values.
Container images: published at tag 0.0.90 under ghcr.io/burgan-tech/vnext/*, Cosign-signed (keyless OIDC) with SBOM + provenance. Immutable digests are listed in the GitHub release.
Issues Referenced
- vnext #943 — Evaluate auto transitions before scheduling timers.
- vnext #931 — Activation-episode tracing across triggers, jobs, subflows and event delivery.
Summary
LifecycleOrder.Auto= 80,LifecycleOrder.Schedule= 90 — autos are evaluated before timers are armed;ClearBusyOnResumeStepstays at 79 asAuto - 1, so resume points are unchanged.- A guard skips arming entirely when an auto winner exists — no Dapr job, no
InstanceJobrow — logged asScheduledTransitionsSkippedForChainedNext(EventId 10156, Debug). - Timers are not armed when the auto step fails, and timer scripts now run after auto condition scripts.
- A chained-through state no longer briefly advertises a
kind: "scheduled"entry; a genuinely parked state arms and fires exactly as before. - Activation-episode tracing: a synthetic activation span, episode identity carried across job/subflow/event hops, and end-to-end activation duration metrics.
- Schema stays at 0.0.53; no configuration change, no migration.
vNext Runtime Platform Team Released September 3, 2026
