Skip to content

Native: expose authoritative per-claim ready_age_ms for workflow/activity dispatch #1030

Closed

Description

@rmcdaniel

The accepted ready-age producer source is implemented and main-accepted through Server #1048. Exact merge/main is 59d5bb379524924a16fdcc0ebd482462fb7049a9, tree 5e26b50e90b48fb17d9add9c597228400546d893. The original queue and automatic main checks passed, including the supported-backend transition and cold-process workflow/activity poll controls. The merged branch/worktree cleanup is complete. Prior failed originals remain attributed on the PR.

Next owner/action: General and Server select the immutable published native producer + SDK/runner tuple under #325. Python then owns SDK #188's actual claimed-task observation against that selected producer. No native 3.2 tuple, publication or consumer run is selected here. This issue stays open for the actual published path. The accepted shared metric semantics remain .github #286 / #233; this source completion does not imply installed acceptance.

Accepted boundary: Boolean server_capabilities.claimed_task_ready_age=true and optional non-null actual integer task.ready_age_ms, 0 through 9007199254740991. Measure the claimed workflow/activity attempt's known eligibility instant to the same committed lease timestamp used by claim. Check signed duration first, then floor valid nonnegative durations to milliseconds. Preserve real/sub-millisecond zero; omit unknown/invalid data rather than clamping or substituting zero. Scheduled delay and retry backoff are excluded. No worker-clock subtraction, task creation-age proxy or aggregate backlog age substitutes for this field.

New creation, retry, release and expired-lease transitions must retain their correct authoritative ready origin; routine new transitions cannot omit it. Old legacy attempts whose later ready origin is genuinely unknown may omit the field. A replayed poll receipt preserves the original committed lease sample; a genuinely new lease gets a new attempt origin/sample. Do not add samples to query/update-validation/empty/denied/stale answers. Keep all capability surfaces and versioned worker OpenAPI evolution consistent; advertise only after complete producer fixtures pass.

Native schema 9 adds nullable workflow_tasks.ready_origin_at without backfill. The complete authoritative transition/origin table and optional poll-field contract are in docs/contracts/claimed-task-ready-age.md. Source controls cover delayed availability, all new transitions, receipt replay/cold restart, new leases, negative deltas, unknown legacy origins, valid zero and numeric boundaries across the declared backends.

The current published 3.0.5 and frozen 3.1.0 actors have no accepted ready-age producer/capability receipt. Their frozen identities remain unchanged. No frozen image/tag substitution, PHP Server release, native tuple selection, runtime experiment or release is authorized by this source acceptance. Source-to-consumer handoff and Python's next action preserve the separate publication/consumer boundary.

Activity

  1. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Bounded source-only origin/schema proposal for the accepted claimed-task-ready-age wire contract. No schema, protocol, capability advertisement or runtime code is changed.

    The accepted wire remains actual Boolean server_capabilities.claimed_task_ready_age and optional actual-integer task.ready_age_ms in0..9007199254740991. Compute once at the authoritative committed workflow/activity claim using that lease's own clock sample, floor a valid nonnegative duration to milliseconds (including real zero), omit invalid/negative/unrepresentable/unknown data and preserve the sample in cached poll receipt replay. Query/validator/empty/denied/stale paths do not fabricate a sample. SDK metrics adoption remains separate.

    Source finding: available_at/created_at alone cannot implement this. create_task_dispatched currently seeds available_at from creation, retry/deadline paths later replace it, registration replacement returns leased workflow tasks to ready while clearing lease timestamps, and repair can re-ready a failed task without creating a new row. TASK_CANDIDATES_SQL also directly reclaims an expired workflow lease before a separate ready transition. Reusing first creation time would include prior leased work; sampling only when repair runs would miss time already eligible through that direct reclaim path.

    Propose a nullable canonical workflow_tasks.ready_origin_at in the next available additive schema revision, using each backend's existing UTC timestamp representation. Do not preassign a version or claim a column exists. Every future routine producer/transition must write a provable origin in its own canonical transaction:

    Transition Proposed retained ready origin
    Fresh due workflow/activity task Creation/admission sample, with effective available_at honored.
    Future timer/backoff/delayed availability The actual eligible availability instant, excluding authored delay/backoff. A newly created resume task uses its own ready admission, not the original timer's creation.
    Activity failure/timeout retry The new retry task's authoritative retry_available_at, in the same transaction as the retry history/task.
    Explicit lease release / registration replacement The canonical release sample (respecting any later valid availability), never old creation or the prior lease start. Cover both workflow and release_replaced_activity_leases.
    Failed/replay-blocked task re-readied The accepted repair-ready sample, preserving original deadlines and task identity. A dispatch timestamp update on an already-ready task does not reset origin.
    Direct expired workflow lease reclaim Capture the old authoritative lease expiry, bounded by any later valid availability, before overwriting lease columns; use it as the new eligibility origin. No synthetic intermediate history event is needed.
    Renew same lease / cached receipt replay Keep the original lease sample/metric. Renewal is not a new readiness episode. A later genuine lease gets its own valid episode/sample.

    Legacy ready rows whose intervening readiness cannot be proved remain null/omitted; do not backfill from created_at merely because it is present. Known authoritative expiry/availability may be used when its lineage is provable. This omission rule is not permission for routine new transitions to omit origins. Canonical completion/close/removal stops readiness; no closed wait/timer task is counted as backlog.

    Implementation inventory must cover create_task and every direct task INSERT/status/available_at writer, retries/timeouts, registration replacement/release, repair, activation/resume and receipt persistence. Central claim assembly uses the same successful leased_at sample already committed with owner/attempt; it must not use a later serialization/activity-start time. Selection/worker availability does not justify resetting a ready episode. General should bind how future admission/pause states affect the shared eligibility definition before those new capabilities are advertised.

    Required source vectors: fresh zero/positive ages, future availability exclusion, failure/timeout retry, release after leased work, direct expired workflow reclaim, re-ready repair, renewal/receipt replay/new lease, invalid/legacy unknown values and rollback/no-claim. Cross-backend precision and literal integer/type bounds must match central286; exact installed producer/SDK proof follows a separately admitted artifact plan.

    Next owners: Server returns the full writer inventory and additive migration/OpenAPI evolution plan after the current train; General reviews this origin/expiry/pause semantic table and source priority; SDK Python/PHP/Rust retain typed omission/dispatch behavior against the accepted field. No private experiment, producer or wire adoption is authorized by this proposal.

  2. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    Replacement-session source advance for the ready-origin proposal, bound to accepted main ea993064428fa9e0294520aa3efd498bef5b64dc. The producer is still unimplemented/unpublished. I inventoried the direct task INSERT/status/availability writers and their helper callers rather than treating created_at as readiness.

    Production boundary Required origin treatment in the proposed source
    store::create_task_dispatched / create_task Set the creation/admission sample for ordinary new workflow/activity rows, inherited by start, continuation, redrive, children, update and cooperative resume callers. Deferred callers must override origin with their canonical eligibility instant in that same transaction.
    store::fail_workflow_task Its direct INSERT ... SELECT bypasses the helper and carries the prior attempt count. Add the new row's ready sample explicitly; never copy the failed task's old ready episode.
    activity_failures::fail_activity, activity_deadlines::time_out_activity Both create a retry and then change available_at. Record the exact retry availability as origin, excluding previous execution and backoff.
    children::start_child_retry Its post-create availability override must also set the workflow task's new origin.
    store::register, worker_management::release_replaced_activity_leases Workflow and activity registration replacement re-ready existing leased rows. Use the canonical release sample, respecting later valid availability; do not retain the old creation/lease episode.
    worker_incarnations::repair_abandoned_task Fenced deregistration has its own direct re-ready writer and repair command/event. Set origin in that exact transaction. Its closed/historical-run branch only expires a lease and must not invent readiness.
    store::deregister Legacy deregistration expires an existing workflow lease without first writing ready. Direct reclaim must use the old authoritative expiry before overwriting it, subject to valid later availability.
    repair_pass::recover_task_row Already-ready repair bookkeeping preserves origin. Leased→ready and replay-blocked failed→ready are separate new episodes. Closed/cancelled terminal branches stop readiness.
    task_repair::repair_replay_blocked The separate direct failed→ready path also needs a new canonical repair sample. Its already-ready dispatch-stamp update preserves origin.
    task_repair::create_missing_task / create_missing_timeout_task Reconstructed activity availability and actual resume/timer provenance must be distinguished. A newly repaired workflow resume uses its own ready admission; restoring an eligible activity uses only a provable source availability. Creating a timer itself does not produce a workflow/activity dispatch metric.
    wait_timeouts::schedule_wait_timeout, store::apply_non_terminal, store::fire_due_timers Timer rows and timer leases are outside the advertised metric. Their workflow resume tasks go through ordinary ready admission. Never turn timer creation or its internal lease into worker ready age.
    workflow_import::import_rows A direct INSERT bypasses normal admission and accepts historical availability/lease state. Legacy imported rows remain unknown unless a separately versioned verified origin is present; do not backfill from available/created merely because they parse.

    The SQL updates in inline backend/takeover qualification tests are test setup, not additional production writers. They still need intentional legacy/null and valid-origin setup once the source changes. Terminal task mutations across completion, cancellation, failure, scope cancellation and closed-wait cleanup must continue excluding non-ready/closed work; none may reset the sampled age of a previously returned claim.

    The central claim point is store::claim_in. Both ready selection and direct expired workflow-lease reclamation enter it through TASK_CANDIDATES_SQL. Read the original eligibility/expiry before changing owner, attempt or lease columns. Compute an optional actual integer from that successful lease's committed leased_at sample; use checked arithmetic and omit negative/invalid/unknown/over-9007199254740991 values. Do not sample again at HTTP serialization, activity-start recording or retry-response construction.

    A second persistence surface must not be missed: activity replay reads dw_poll_receipts.response, whereas workflow replay uses deliverable_workflow_lease and the original claim metadata. Both paths must preserve the original per-lease sample, including renewal, without recalculating it. A new attempt gets its own origin/sample; a denied, rolled-back, query or update-validation claim supplies none.

    Next Server source packet: additive nullable origin plus exact per-backend bootstrap/catalog/upgrade identity, all production writers above, a versioned persisted claim sample and both receipt paths, then append-only worker OpenAPI evolution for the optional bounded integer and Boolean capability. No historical migration/catalog is edited, and no schema number is reserved independently of #1016/#931. Fixtures must cover each direct writer, legacy import/nulls, timer exclusion, direct reclaim, renewal/replay, rollback, and cross-backend timestamp precision.

    General retains review of the eligibility/pause semantics and source order. SDK owners can continue typed omission/dispatch source without treating this inventory as an accepted producer. There is no newer immutable published ready-age producer to return. No DDL, database, build, container, runtime, wire advertisement or release was executed for this advance.

  3. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    Current accepted-source reconciliation for the existing ready-origin/writer proposal: main c507b62fd7cb511cea407ba8efe35040bbae4c9e still has no implemented/published ready-age producer or advertised capability. The named production writer files (store, activity failure/deadline, child retry, worker replacement/incarnation, repair pass/task repair) are byte-identical to the ea99306 inventory checkpoint; intervening accepted source work does not supply the missing origin or persisted claim sample.

    The accepted wire contract and existing nullable-origin/additive-schema/OpenAPI proposal remain the next owned producer work. Server owns implementation after General selects that source slot; General owns ordering/schema-version and artifact admission. SDK Python/PHP/Rust retain the typed actual-Boolean/integer/omission contract, without inventing a producer or installed positive result. Python was explicitly told this unchanged gate on resume.

    The current selected native 3.2 source plan still excludes unfinished ready-age. Current P1 order is the CI prerequisite #1037, #1033 refresh/requalification and #1036 source acceptance; no parallel producer/schema/wire implementation or runtime request is started by this record.

  4. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    The current Server source batch is accepted and cleaned:1047 at ca1264f and1034 at fadf872, with the original queue/main receipts retained. General places the next existing source work as follows; this changes no frozen operating/release gate.

    1. Keep the active219/325 guarded-recovery handoff first when Core's concrete optional-interface/controller implementation returns. Server retains the corresponding actual retained-authority/optional-role source binding; no role advertisement or installed operation is implied.
    2. During that named dependency, advance1030's already-defined authoritative transition/origin table and versioned optional poll-field/schema SOURCE proposal. The accepted metric semantics in this issue remain fixed. Inventory every creation/retry/release/expired-lease path and original committed receipt replay, then use normal producer/consumer source readback and existing source qualification to deliver the bounded implementation. Do not advertise the capability until the complete producer/backend fixtures pass. This advances an existing item after the completed batch, not an installed tuple or release selection.
    3. The following bounded contract slice is1014's remaining coherent last-action/outcome projection, as requested by Waterline6676787673. Bind all real writer and legacy-storage paths, the separate buffered-action state, exact precision/order/null/ambiguity, complete detection and existing query budgets. A ring-tail projection alone cannot claim complete latest/buffered dispatch. Server chooses the final minimal DTO and names any writer correction; Waterline retains describe/current polling until actual published acceptance.

    Server owns ordinary source controls, current-head review/checks, normal integration, actual-main acceptance and cleanup in this order, resolving normal maintained-base conflicts without a freeze. Concrete active Cloud/incident or higher-priority219 work preempts safely. No new PHP Server release, native3.2 tuple substitution, lifecycle/installed/consumer operation, package/tag/publication or retry of a held route is selected. Preserve Workflow1052's unread intake boundary until human prose approval exists.

  5. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    The next concrete source artifact is draft #1048, head 3c5540b89bea41c7cd423d0c5de66e06e210ad6d over accepted main fadf8729265e077f280c8f71a87c06d8f73a682e: authoritative transition/origin and optional-poll contract. This advances the existing source slot in General's ordering record.

    The table covers the common creation helper and direct failure-replacement INSERT; activity failure/deadline retries; delayed child retry; workflow/activity registration release; fenced incarnation repair; direct expired workflow reclaim; ready bookkeeping versus leased/failed repair; reconstructed tasks; timer exclusion/resume; historical import; terminal cleanup; and both durable poll answer paths. The named production writer files remain byte-identical to the earlier ea993064 inventory, reconciled against current main. available_at alone cannot distinguish a new post-lease ready episode.

    The source uses the previously proposed nullable workflow_tasks.ready_origin_at, with no historical creation-time backfill. Eligibility respects later availability; direct reclaim captures the authoritative old expiry before mutation. The same committed lease sample supplies signed-duration checking and valid nonnegative millisecond flooring, preserving real/sub-millisecond zero. The optional non-null integer and actual Boolean capability evolve worker OpenAPI revision 56 while retaining protocol 1.20. The existing canonical schema is version 8; historical SQL/catalog/checksum bytes remain immutable while the next additive source candidate is qualified normally.

    A precise receipt finding from the current source is now explicit: activity replay stores the full original task in dw_poll_receipts.response; workflow replay stores its full poll answer in dw_query_cache, and only refreshes the live lease expiry during deliverability checking. Both can preserve the original serialized integer without measuring again. Old cached answers without the field remain omitted. Ordinary worker/session/compatibility selection does not reset task readiness; this work adds no pause semantics.

    Implementation, producer/receipt/arithmetic/backend controls and source review continue on the same draft. Capability advertisement is integrated only after complete producer/backend qualification. There is no source-input blocker requiring a new user decision; Core #219's concrete optional-interface handoff retains priority when it returns. No frozen actor, installed native tuple, manual backend/runtime operation or release is selected. Workflow #1052 remains unread without human intake approval.

  6. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    The ready-age producer source is now implemented and main-accepted through #1048. Exact merge/main is 59d5bb379524924a16fdcc0ebd482462fb7049a9, tree 5e26b50e90b48fb17d9add9c597228400546d893. All original queue workflows and all four automatic main workflows/a1 passed. The six supported backend transition and cold-process workflow/activity poll controls passed at the reviewed source tree. Owned branch/worktree cleanup is complete; earlier failed heads/attempts remain attributed in the PR.

    The optional capability is the literal Boolean server_capabilities.claimed_task_ready_age. A supported claimed task carries an optional actual JSON integer task.ready_age_ms in 0..9007199254740991. It measures authoritative eligibility origin to the committed claim sample. Signed validation precedes millisecond flooring. Unknown/invalid/legacy origins omit the field with no creation-time substitute or clamping. Receipt duplicates preserve the original value or omission; renewal does not resample. Native schema 9 adds nullable workflow_tasks.ready_origin_at, with no backfill. The complete transition/origin table is in docs/contracts/claimed-task-ready-age.md at this immutable source.

    This changes the next action from unimplemented producer source to General/Server selection of an immutable published native producer + SDK/runner tuple under #325, then SDK #188's actual claimed-task observation. No such native 3.2 tuple, publication or consumer run is selected or supplied here. Source tests do not complete that acceptance. #1030 remains open for the actual published path. The PHP Server publication stop is unchanged.

  7. rmcdaniel commented on Nov 11, 2026

    @rmcdaniel
    MemberAuthor

    Closing: implemented by #1048, released in native 3.2.0. The consumer side is sdk-python#188.

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:P3Lower-priority product improvement

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions