Repository navigation
Replay a redriven run from the failed run's start time - #233
Conversation
A redrive successor's WorkflowStarted is recorded at redrive time. Core replays it from payload.replayed_started_at when recovery_kind is redrive; the SDK used recorded_at, so ctx.now() and ctx.uuid7() before the failed step differed from the failed run. Use the replayed start, refuse an invalid one, and let the cancellation clock prefer reused_recorded_at. Fixes #232 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Security exact-head review of
The new Please give a string |
The cancellation clock read the event's top-level timestamp before reused_recorded_at, so a step reused by redrive still advanced cleanup time to the redrive. Prefer reused_recorded_at, as Core's RedriveReplayClock::recordedAt does, and pin the remaining budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Security re-review of exact head The correction now matches Core ordering exactly: a string |



Fixes #232. Part (C) of workflow#864.
Problem
Redrive creates a new run whose
WorkflowStartedis recorded at redrive time. Core replays that run from the failed run's start, usingpayload.replayed_started_atwhenpayload.recovery_kindisredrive(RedriveReplayClock::startedAt,WorkflowFiberRunner::workflowStartedAt). The SDK usedrecorded_at. Soctx.now()andctx.uuid7()before the failed step returned redrive-time values, and arguments or branches derived from them could differ from the failed run.Change
replay(): on aWorkflowStartedwithrecovery_kind == "redrive"and areplayed_started_atkey, that value is the start clock. An invalid or naive value is refused with the existing explicit clock error, namingpayload.replayed_started_at, and never falls back. Withoutrecovery_kind: redrivethe key is ignored, as in Core.reused_recorded_atuses it, consistent withRedriveReplayClock::recordedAt.test_history_event_contract.pydocuments Core's redrive payload keys:resume_step_sequence,recovery_kindandreplayed_started_atonWorkflowStarted, andreused_*onActivityCompleted,TimerFired,SideEffectRecordedandVersionMarkerRecorded. They are excluded from the published-PHP fixture comparison, because ordinary runs never carry them.Evidence (local, Python 3.13)
ctx.now()and theuuid7timestamp, with a reused activity result;recovery_kind;workflow.pyreverted, 6 of the 7 new tests fail. The ignored-without-redrive case passes either way, as intended.Missing Authority Key Identifier) and two boundary-scanner tests tied to the host git identity. Hosted CI is the environment check.🤖 Generated with Claude Code