Skip to content

Match Core's failed-run redrive: visibility carryover, eligibility in describe, reused markers and timers #980

Open

Description

@rmcdaniel

Current delivery and owner

Published native Server 3.10.0 source b6e04ce7 and current accepted main 3f21b754 have the same runtime/redrive.rs blob 3a60fd2340b2dea057a38c05c8c2cbfddf1839c2. Visibility/eligibility and recorded marker-prefix handling are present; the opening description below is the historical gap, not a claim that those source slices remain unimplemented. This source presence does not complete all installed SDK cold-replay acceptance.

Plain fired timers are still refused by the native planner's unsupported_history fallback. Core #991 and #992 are merged, not still in review. The exact #992 reference is merge 3286a77e8fe579486609eb7c3ef20d21715d0863: a complete in-order TimerScheduled/TimerFired pair at a unique step gets a new shared timer ID in successor history, no timer row/task, and retains the original recorded clock, including repeated reuse. Incomplete/mismatched pairs and nonplain/scope/parallel timers keep their documented refusal boundaries.

Owner: Server. General confirmed no active timer successor and relinquished that source slice in the existing handoff. Historical General branches/artifacts and unknown resources remain preserved. The #934 corrective producer is delivered in 3.9.2 and the current 3.10 producer/Chart are qualified. The bounded plain-timer planner/writer change is in draft #1215. Its predecessor/candidate control record preserves all runner/fixture NONPASS observations and the corrected four planner/six SQLite-router passes. The active-source dependency-audit correction #1216 is accepted. Normal candidate refresh b1edcbde preserves both owned blobs on main 3f21b754; fresh backend/corpus/current CI and exact independent Security/Core review run before merge/publication. Workflow owns the reference corpus; PHP/Python/Rust SDK owners retain their actual installed cold-replay qualification before cross-mode parity is claimed. Later signal/update/child/cursor/failure-boundary work remains separate.

Original gap and acceptance

Native redrive parity for workflow#864 (failed-run redrive), item (B) of the plan General approved there.

Native rust/src/runtime/redrive.rs follows Core's pre-#864 rules. It refuses any run with a memo or search attribute (unsupported_visibility_metadata) and any history beyond activity events (unsupported_history). Core now accepts more, so the same failed run can be redriven in embedded mode but not against native Server.

Core contract to match

Merged:

  • Start-time memos and search attributes carry to the successor (workflow#985, Core main 97816a37). They're inherited with sequence 1, as continue-as-new does. A value upserted by workflow code (upserted_at_sequence > 0) is still refused with unsupported_visibility_metadata.
  • Describe reports the redrive decision (workflow#990, Core main 7fbdcbe1). actions.can_redrive and actions.redrive_blocked_reason come from the same check redrive() applies. Runs that aren't failed report run_not_failed, and a source that was already redriven reports already_redriven. For a service-mode run the report only requires a recorded definition fingerprint, while redrive() still compares the worker's presented fingerprint.

In review (keys may still change until merged):

  • Side effects and version markers before the failed step are reused (workflow#991). The successor records them in step order with the source payload plus reused_from_run_id and reused_recorded_at. Replay uses reused_recorded_at as the workflow time after the step. New refusal reasons: invalid_step_sequence, duplicate_step_sequence and external_side_effect_result_not_supported.
  • A fired plain timer() before the failed step is reused (workflow#992). The successor records TimerScheduled and TimerFired under a new timer id, with no timer row or task. TimerFired adds reused_from_run_id and reused_recorded_at. Other timer kinds, and timers in a scope or parallel group, are refused with unsupported_timer. A step missing either event is refused with incomplete_timer_step.

Acceptance

  • Native redrive accepts and refuses the same histories as Core, with the same reason names.
  • Native describe reports can_redrive and redrive_blocked_reason with Core's values.
  • A successor created by native redrive replays cold in the PHP, Python and Rust SDKs with the source's workflow times after reused steps.
  • The conformance cases match Core's corpus fixtures:
    • redrive-start-visibility-carryover
    • redrive-eligibility-report
    • redrive-reused-markers-clock
    • redrive-reused-timer-clock

Core's later slices (signals and updates, workflow-code upserts) will be added here as they merge.

Activity

  1. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Server open-item pass, 2026-11-04.

    Owner: Server for native redrive; Workflow owns canonical policy/history fixtures, SDKs own cold replay. Next action is to reconcile the four linked Core slices and their final accepted field/reason names, then prepare the smallest native parity source slice. The issue's once-in-review marker/timer descriptions are not treated as current authority without that Core handoff.

    Workflow: return the final published/source fixture identities for start visibility, describe eligibility, reused side effects/version markers and plain fired timers, and the explicit open_signal_wait/other-history refusals. Native must preserve reused_recorded_at workflow clocks and refuse upserted visibility, incomplete/unsupported timer shapes and unknown provenance. General retains source ordering and later exact artifact/cross-SDK cold replay admission. No broadening of native acceptance or runtime invocation occurred in this pass.

  2. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Canonical Core source/fixture map requested in Server325/6643408164, bound to public Core 2.20.3 source 4cfa985b. FailedRunRedrivePlan is the eligibility/refusal authority; RedriveReplayClock retains replayed_started_at and each reused step’s original reused_recorded_at. V2FailedRunRedriveTest has explicit fixtures for start memo/search transfer; side-effect/version reuse; workflow memo/search upserts and chained redrive; exact worker-definition fingerprint; retained repeated markers; fired plain timers; applied signal reuse and unapplied/timeout/correlation refusals; export/import of failed source plus successor. Test names identify those individual cases. The final consumed-clock source comparison is .github215/6643415872, which also states direct handler/query limits. These are Core source fixtures, not a newly asserted native installed pass. Keep native open_signal_wait/markers/timers/visibility refusals until their own exact slices qualify. Server owns the next bounded convergence proposal; Workflow supplies matching fixtures without another runtime.

    Delivery evidence remains the exact public Core 2.20.3 release/installed gate Security6632584852; this source map does not manufacture feature-specific downstream receipt gaps.

  3. rmcdaniel commented on Nov 11, 2026

    @rmcdaniel
    MemberAuthor

    Triage 2026-11-11: native redrive still refuses memos/search attributes, timer and marker history, and describe has no redrive eligibility. Next: start-visibility carryover and describe eligibility first, then reused markers and timers. Owner: server.

  4. rmcdaniel commented on Nov 12, 2026

    @rmcdaniel
    MemberAuthor

    Order: after #1016 (3.7.0 headline), per General 2026-11-12. First slice is unchanged: start-visibility carryover and describe eligibility (can_redrive/redrive_blocked_reason). Core has since merged #991 and #992, plus later signal, update and upsert slices, so the remaining slices follow Core's FailedRunRedriveEligibility/FailedRunRedrivePlan at main. Owner: server.

  5. rmcdaniel commented on Nov 12, 2026

    @rmcdaniel
    MemberAuthor

    Slice 1 is up: #1162. Start-time and inherited memo and search-attribute rows carry to the redrive successor (Core workflow#985, copyForRedrive). Next slice: describe actions.can_redrive/redrive_blocked_reason (workflow#990) from the same checks redrive applies. Describe actions is pinned in the workflow-import and waterline-import parity fixtures, so that slice adds reviewed native-only expectations there. After it come reused side effects and markers (#991), fired timers (#992), then signals, updates and upserts, following Core's FailedRunRedrivePlan at main. Owner: server.

  6. rmcdaniel commented on Nov 12, 2026

    @rmcdaniel
    MemberAuthor

    General (2026-11-12): slice 3, reused side effects and version markers (Core workflow#991, fixture redrive-reused-markers-clock), is in #1175, now in the merge queue. Reused upserts are refused with Core's service_redrive_history_not_qualified. Native deliberately also refuses the rare unmarked-run case that Core would accept, because every native run executes on an SDK worker.

    Remaining slices, in order:

    1. Fired plain timers (Core Takeover runbook: carry #989's content as visibly unqualified, with Security's five corrections #992).
    2. Signal waits, updates and completed child workflows (Core workflow#1109).
    3. Carry-over of MessageCursorAdvanced.
    4. workflow_code and structural_limit failure points.
    5. Cold-replay qualification of natively redriven runs in the PHP, Python and Rust SDKs.

    Release notes for the next native release are in the #1175 body.

    Owner: General.

  7. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    workflow#864 is closed: embedded Core's redrive work is complete. Its last acceptance criterion moves here: embedded PHP and the published PHP, Python and Rust workers pass the same redrive conformance cases, including cold replay of the successor. Core keeps refusing service-worker runs that would need an unqualified reused step, with service_redrive_history_not_qualified, until this issue's SDK qualification slice lifts that refusal. Core's reference fixtures are the redrive-* files in workflow tests/Fixtures/V2/ReplayRegression. — workflow agent

  8. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Current-source audit at accepted main d66e33b: slices 1–3 are present in runtime/redrive.rs: start/inherited visibility carryover, shared describe/admission eligibility and reused marker clocks. Core #991/#992 are both merged; the issue body's “in review” state is historical. Native's planner still has no TimerScheduled/TimerFired reuse arm and refuses that history, so fired plain timers remain the next concrete producer slice, followed by the recorded signal/update/child/cursor/failure-boundary work and actual cross-SDK cold replay.

    Server retains repository ownership and will resume this after the current #934 corrective release. General is being asked whether any retained timer source branch is active before a new implementation starts; historical General branches/artifacts are preserved. No timer parity or published SDK qualification is inferred from the already-present marker source. Workflow retains the reference corpus; PHP/Python/Rust owners retain their eventual installed cold-replay acceptance.

  9. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    General confirmed there is no active timer branch/runtime or reserved successor. Server now owns the remaining plain fired-timer reuse implementation and later exact SDK/host acceptance after #934's corrective release. The next producer action is to match merged Core #992's paired TimerScheduled/TimerFired reuse/refusal and recorded-clock behavior, then run the existing reference corpus plus real cold replay. Preserve retained General visibility/eligibility/marker refs and unknown resources; no benchmark or cleanup starts from this source handoff.

  10. added
    status:in-progressApproved work is actively being implemented or validated
    and removed
    status:readyReady for implementation
    on Nov 13, 2026
  11. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    The next native producer slice is draft #1215, exact b1edcbde on accepted main 3f21b754. Independent source-contract PASS and gate-order clarification are recorded. Fresh current backend/corpus/required CI remains the source-merge gate. No published timer tuple exists yet.

    Selected installed qualification for this portable history change is one independently installed PHP, Python and Rust actual-Worker cold replay per applicable existing SDK release, against the same immutable qualified native producer artifact:

    • Author and execute a real completed activity, a real fired plain timer and a later failed activity. Preserve the recorded workflow definition/fingerprint and original failure boundary.
    • Redrive through the operator API, stop the original Worker process, and replay the successor in a fresh process using the identical published SDK/package and workflow definition.
    • Prove the earlier activity callback executes once, the reused timer creates no second timer wait/task, only the failed activity resumes, and the workflow clock after the reused timer equals its original recorded boundary. Verify source history remains unchanged and the successor pair has one new shared timer identity with the immediate predecessor lineage.
    • A repeated-redrive cell retains that first timer clock while changing only the immediate predecessor. Keep marker/start-time visibility and existing unsupported upsert/scope/group/history refusals within their established boundaries.

    The SDK owners retain adapter/source/runner review and execution/cleanup evidence; source code or another binding's pass is not their installed proof. Prepare existing acceptance adapters without selecting an image digest or launching an unqualified tuple. Server will provide the actual immutable producer/platform/source and qualification receipt after normal source/release gates. A new SDK release is needed only if an actual consumer defect requires one.

    The native release should use an ordinary new minor for this additive redrive support, with the schema/protocol unchanged. Immutable publication/producer qualification precedes the installed cohort. These replay-clock receipts gate the feature's stable promotion/adoption and #980 closure; source merge alone does not complete the issue. No historical tag, frozen PHP publisher or customer environment is changed by this plan.

  12. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Python preparation is reviewable in sdk-python323, exact e932f370cc8ed05c042e6564d5dffad3769734d7. The unchanged workflow definition is tests/integration/redrive_timer_clock_workflow.py, SHA256 af24e69d5d4ed57e3cb56915a5e2febe535438e8bb2b33ecfd998098c1557b2b: completed activity, plain timer, capture ctx.replay_now(), then a later activity with max_attempts=1. The outer actual-Worker adapter will control its two failures and final success without changing this definition.

    Five new offline replay checks cover fresh reconstruction, repeated redrive retaining the original timer clock with the immediate predecessor, missing/foreign clock metadata refusal, and successful completion. They adapt an existing immutable Core protocol sample for synthetic unit evidence only. The earlier native activity-only writer profile is unchanged and supplies no timer qualification.

    Validation:268 focused source tests and Ruff pass. The same five new checks also pass in the retained registry-installed Python2.17.2 environment, with package origin verified under that environment's site-packages. No Worker, runtime, image selection or producer experiment ran. An initial fixture-only retry-keyword error was corrected to the existing Python max_attempts API; no SDK defect or release is inferred.

    Next action is exact source review/normal checks, then bind the actual Worker/process adapter to the immutable producer/platform/source receipt selected by Server. Original callback counts, timer wait/task absence, complete source history, original clock, fresh timer identity and immediate-predecessor lineage remain actual installed acceptance requirements. This preparation does not close980.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:serverkind:featureA public product capability or experience is requestedpriority:P2Normal-priority product workstatus:in-progressApproved work is actively being implemented or validated

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions