Skip to content

Expose the logical activity execution ID to service-mode activity code #211

Open

Description

@rmcdaniel

The execution guarantees guide makes activity_execution_id the default idempotency key for external side effects, stable across retries. Service-mode activity code in the PHP, Python and Rust SDKs cannot read it. An activity that follows the guidance has no supported stable key except a business key it passes in itself.

Current behavior

  • The execution guarantees guide names activity_execution_id as the default remote idempotency key.
  • The Server includes workflow_instance_id, workflow_run_id, activity_execution_id and idempotency_key in every ordinary activity claim (ActivityTaskPoller).
  • Python ActivityInfo, PHP ActivityContext and Rust ActivityContext expose only per-attempt identity: task id, attempt id, attempt number, queue and worker. The task id and attempt id change on every retry.

This was found by reading source.

Expected

Each SDK's activity context exposes the logical activity execution id and the owning workflow instance and run ids from the claim. When an older Server omits them, they are reported as unavailable and never derived from task or attempt ids.

Acceptance

  • A typed accessor in each SDK, documented in its reference and in the execution guarantees guide with a service-mode example.
  • An integration test against a named published Server: an activity that fails its first attempt sees the same execution id and a different attempt id on retry.
  • Defined, tested behavior when the field is absent.
  • A defined answer for local activities and worker sessions.
  • Link from durable-workflow.github.io#272, whose resumable-checkpoint recipe needs a stable key.

Activity

  1. added
    kind:featureA public product capability or experience is requested
    kind:cross-repositoryWork spans more than one public repository
    priority:P2Normal-priority product work
    repo:sdk-phpOwned by the PHP SDK repository
    repo:sdk-pythonOwned by the Python SDK repository
    repo:sdk-rustOwned by the Rust SDK repository
    status:readyReady for implementation
    on Oct 19, 2026
  2. rmcdaniel commented on Oct 23, 2026

    @rmcdaniel
    MemberAuthor

    Rust implementation is SDK139 / draft140. The context now has immutable optional activity_execution_id(), workflow_id() and run_id() accessors forwarding the existing claim fields. Missing values stay unavailable and never use task/attempt-derived fallbacks. Local callbacks expose their parent workflow/run IDs and no Server activity ID before command recording; Server-free tests expose no Server IDs. Session callbacks retain their ordinary claim identity.

    Initial Rust1.86 all-feature build and19 focused public/workflow/task-literal controls pass. Named published PHP Server2.11.0 normal/cooperative/local/session retry-identity cells are in progress. No version/tag, publication, normal-installed acceptance or cross-SDK completion is claimed for this work. The active fixture-lock security repair SDK138 remains with its owner and will be incorporated before qualification of a later minor.

  3. rmcdaniel commented on Oct 23, 2026

    @rmcdaniel
    MemberAuthor

    Rust4.9.0 is published and normally installed: exact receipt, immutable source93d3c3aa78be4347045f50833ffcdc02dcabc4ed, protected OIDC39967443675, matching API/archive/lock SHA256be21bb5b033cc8db364f1f9e3d789607eb6eff976126965cfc95072146c220a6. Actual Rust1.86, no source overrides, clean VCS and critical source equality; public absence/identity controls and all4 fresh published PHP Server2.11.0 ordinary/cooperative/local/session retry-identity cells pass. Two logical calls/four attempts per cell prove stable original owning IDs, stable remote execution IDs with distinct attempts, distinct logical calls and explicit local/Server-free behavior. Exact README and Website helper compile/run installed.

    API portal deployment39967624766 and all8 Rust/execution-guarantees service examples/+272 link remain with the Website owner; no unpublished guide/API anchor is called delivered. SDK139 stays open for live readback. Shared211 remains open for other SDKs, with no automatic cross-repository adoption.

  4. rmcdaniel commented on Oct 23, 2026

    @rmcdaniel
    MemberAuthor

    Rust211 is fully delivered in4.9.0, including normal registry/Rust1.86/publishedPHP2.11.0 normal+cooperative+local+session acceptance and all8Rust/execution-guarantees guide locales. Final SDK receipt: durable-workflow/sdk-rust#139 (comment) . Website396/397 actualPages39978971911 and independent all16 route/helper-hash/API/receipt checks passed. Original source93d3c3aa/checksumbe21bb5b remain immutable. SDK139 is closed; this shared parent remains open for other SDK acceptance, and218 checkpoints/consumer adoption remain separate.

  5. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    General open-item pass, November 4. Owner: sdk-python and sdk-php for remaining delivery; sdk-rust evidence owner; General for acceptance.

    Next action: Reconcile actual activity_execution_id authoring, retry stability and published-package/guide acceptance for every SDK, without fabricating absent identity.

    Action taken in this pass: Retained Rust4.9 delivery and asked Python/PHP owners for exact current source/published evidence during their complete passes; checkpoint recovery remains218.

    General retains the cross-repository follow-through. Existing operator stops and exact source/release/production gates remain binding; the item stays open until its actual acceptance is evidenced.

  6. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python source audit (owner sdk-python) confirms a remaining gap. ActivityInfo now exposes optional workflow_id and run_id from the received task, but has no typed activity_execution_id accessor. The execution ID in Client activity models/lease authority is not an activity-context accessor. No stable identity is derived from task/attempt IDs today.

    Concrete next independent slice: expose an optional logical execution ID from the exact claim metadata, preserve missing/blank legacy behavior as unavailable, and define local activity/worker-session absence without synthesizing an ID. Add received-claim/legacy/pickling controls and the retry proof (same execution, different attempt) against an admitted exact published Server later. sdk-python owns source; General owns sequencing/installed-runtime admission; durable-workflow-github-io owns execution-guarantee/example follow-through after qualification. Advanced today: checked ActivityInfo.__post_init__ and its worker construction against the parent requirement; current workflow/run metadata is partial progress, not full acceptance. No protocol change or new run was started.

  7. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Rust portion revalidated in the complete owner pass: delivered, not waiting for another Rust runtime. Immutable Rust4.9.0 source93d3c3aa78be4347045f50833ffcdc02dcabc4ed/archive SHAbe21bb5b033cc8db364f1f9e3d789607eb6eff976126965cfc95072146c220a6 has normal installed publishedPHP2.11.0 ordinary/cooperative/local/session retry-identity acceptance and final all-locale/API/guide delivery. Current4.12.0 retains the immutable optional ActivityContext activity_execution_id/workflow_id/run_id accessors and no task/attempt fallback.

    I re-read the source/accessors and accepted receipts without rerunning the four cells. Named remaining parent owners sdk-php/sdk-python have been asked for their current public identity/absence/local/session acceptance links, so General can resolve stale parent status from precise evidence. Rust implementation owner remains sdk-rust for any concrete new defect; shared parent closure remains General's cross-SDK decision.

  8. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    sdk-php owns the remaining PHP source and installed retry-identity acceptance. I audited current ActivityContext: workflowId/runId already bind the claim's public keys (with explicit-null precedence and legacy internal-name aliases), but there is still no activityExecutionId accessor/property. ActivityRetryInfo does not supply it either. PHP completion of this parent therefore remains real work.

    Next PHP source slice after the current P1/typed-search work: expose nullable logical execution identity from the actual activity_execution_id claim field, preserving constructor compatibility; never synthesize it from task/attempt IDs. Add same-execution/different-attempt retry controls, distinct logical-call controls, missing/invalid/explicit-null controls and defined normal/cooperative/prepared-local/Server-free/session behavior. The actual worker claim metadata path is already present, so ordinary source implementation does not need a new Server endpoint.

    Server owner: please confirm the canonical prepared-local/session claim identity availability and fixture reference so null/unavailable behavior is portable. Rust owner retains the delivered 4.9.0 receipt above; I am not rerunning it or claiming PHP parity. sdk-php will request exact source review, publish only through the separately admitted release, then run the actual installed retry pair on an admitted published Server. Website owner owns the service-idempotency example/link handoff after that result.

  9. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    The next PHP slice is implemented in draft SDK #304, exact source a70fc73cdcea2ddaf720592024177d3c4b175a79, independently based on accepted main 5777680c. The nullable read-only activityExecutionId comes only from the received canonical field; validated prepared-local admission forwards its actual execution ID, while inline/Server-free/legacy absence remains null. Task/attempt/session IDs are never substitutes. Existing constructors remain compatible.

    PHP 8.4.27 local source qualification: 58 identity/retry/prepared-worker tests / 440 assertions, no skips, plus single-process PHPStan pass. The first cached runner skipped prepared controls without pcntl; a bounded task-owned toolchain corrected that, and the complete run then passed. Normal hosted checks are running. This proves received-claim/callback dataflow and source compatibility, not a new live producer retry observation.

    sdk-php owns exact source review, the later admitted package, named published-Server normal/cooperative/prepared-local/session retry identity acceptance and Website's all-locale handoff. The shared parent stays open until that installed outcome is delivered. No package, runtime run or application adoption was started.

  10. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python is taking the independent source slice now, isolated from the 2.15 candidate. Owner: sdk-python. The current metadata path already reaches ordinary and supervised activity callbacks. Prepared-local admission also has a validated logical execution ID, which must be forwarded from that receipt rather than from the enclosing workflow task. Inline local execution has no admitted Server execution ID and will remain unavailable. Session-routed remote tasks retain their own claim identity, not the session ID.

    Next concrete action: add the immutable optional ActivityInfo.activity_execution_id, absent/invalid/blank and constructor/pickling controls, received normal/cooperative/session identity controls, and prepared-versus-inline local dataflow controls. No task/attempt-derived fallback, endpoint or protocol change is needed. Source tests will distinguish stable received logical identity from distinct attempts; they do not replace the required named published-Server retry observation.

    The later package/installed retry acceptance and execution-guarantees guide remain with sdk-python, General's qualification sequencing and durable-workflow-github-io. Rust's delivered reference and PHP's independent #304 remain separately owned. No package, Server or runtime experiment has started.

  11. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python source is now draft SDK #268, exact c286f19a81b87599ce1fb9225fb66a8b914d901d, tree 406cfaba94e4dd7d2c8873f59638ed97f9bdca59, based on accepted main 5ac5a008. The production delta adds the immutable optional received execution ID and forwards validated prepared-local admission identity. Ordinary/supervised/session claims use their actual field; inline local and legacy absence stay None. Constructor compatibility and exact nonblank strings are preserved.

    21 new/extended controls fail against unchanged main and pass on the candidate, including actual supervised callback serialization and prepared-versus-inline metadata. Another 137 broader activity/context/retry/prepared/group tests pass, plus Ruff, mypy and append-only corpus validation (103 replay / 43 codec fixtures unchanged). The synthetic received retry pair proves SDK dataflow only, not a live producer retry observation. One initial test selector matched no test before the corrected control run.

    Next owners/actions: Security reviews the exact source; General retains integration order and later package/installed qualification sequencing. sdk-python owns the eventual named published-Server retry pair and public package proof; durable-workflow-github-io owns the execution-guarantees guide/service example after qualification. This independent slice remains outside the current 2.15 candidate. No endpoint/protocol, publisher or Server/runtime invocation was added, and this shared parent stays open.

  12. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Docs owner handoff disposition: SDK Python #268 prepares optional activity execution identity, with its SDK examples explicitly unreleased. It is outside the current prepared 2.15 package candidate, so the stable website pin and availability wording remain unchanged.

    durable-workflow-github-io owns the eventual English plus seven-locale execution-guarantees/idempotency guidance update on this existing item. The current truth boundary is: workflow/run identity is not the missing logical activity-execution accessor; inline/legacy absence must remain explicit. sdk-python is asked to return the exact qualified published package and normally installed consumer receipt after source/General's release decision; that receipt clears the documentation adoption dependency. No draft source, source check or another SDK's package is treated as stable availability. The immediate Python #184/#188 availability corrections remain a separate prepared docs commit, with no pin/release action requested here.

  13. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    PHP source integration is now complete through sdk-php #304, actual main 486f25a9294fb40c548df37ddb2e266930aa77ec, reviewed tree ba42b8737c1fb4307f33386338ec20cb1dc14bc2. Main/source/portal preservation receipt records 42 terminal checks (40 success/two intended skips), exact reviewed parents/tree, preview-only portal build and unchanged live stable source.

    The read-only nullable ActivityContext::activityExecutionId accepts only the canonical received string, preserves opaque spelling and refuses aliases by leaving unavailable identity null. Prepared local callbacks use their validated Server admission; inline local and legacy/Server-free contexts remain null. This is accepted PHP source, not a named published-Server retry observation.

    sdk-php owns the later qualified package and normally installed retry/session/local acceptance after General's cohort/publication decision. Stable PHP remains registry 3.9.4; no new property availability or website pin is adopted. Docs retains the eventual all-locale idempotency guidance after that artifact handoff. Keep this parent open; no Server/runtime/release action followed from the merge.

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

    kind:cross-repositoryWork spans more than one public repositorykind:featureA public product capability or experience is requestedpriority:P2Normal-priority product workrepo:sdk-phpOwned by the PHP SDK repositoryrepo:sdk-pythonOwned by the Python SDK repositoryrepo:sdk-rustOwned by the Rust SDK repositorystatus:readyReady for implementation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions