Skip to content

Prove published ordinary activity retry identity - #424

Merged
rmcdaniel merged 2 commits into
mainfrom
agent/sdk-php/211-installed-retry
Nov 14, 2026
Merged

rmcdaniel merged 2 commits into
mainfrom
agent/sdk-php/211-installed-retry

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Add the missing real ordinary Worker retry receipt for shared #211. The read-only accessor shipped in 3.10.0; this adds acceptance coverage without changing the API or publishing another SDK version.

The opt-in in the maintained published-worker workflow binds normal-registry SDK 3.18.2 / f9483bb and qualified native 3.8.0 / index7988. Its main/dispatch-only guard rejects candidates, foreign tuples and other qualification flags before installation/runtime start. The sibling Laravel job is also excluded at job level whenever retry-identity qualification is selected. Stock PHP 8.3/411a, trust242c and existing bounded native runtime/teardown stay unchanged. Normal P2 currently exposes that exact SDK source/dist; immutable Server tag 3.8.0 resolves to28f08451. This supplies no substitute for #421's separate 3.18.3 registry gate.

One ordinary managed Worker starts a single workflow/activity, reports the deliberate first-attempt failure and completes attempt2 with the received execution ID. Require two callbacks with attempts1→2, stable nonempty execution/workflow/run, distinct task/attempt IDs, each callback's exact identities in its ordered durable ActivityStarted payload, and the retry event linking both real tasks. The exact run must complete and the Worker deregister. Retain the callback pair and bounded real history, actual registry lock/installed dist references and timestamps. The case has 45-second execution/run limits and a 60-second process bound. No fake claim or history is supplied to the installed path.

Current exact head c6b35e81909274b9a9a22cdc37faaa01d7a392b2 closes the two initial source findings: sibling-job effects on conflicting selectors, and an invented second attempt ID that formerly passed a count-only check. Four inert selector/cross-job controls and five existing tuple/pipeline controls pass. Five PHPUnit receipt controls include missing/changed logical identity, reused task/attempt IDs, a foreign retry link and an invented distinct second attempt. All 36 exact-head checks passed with two declared skips, followed by independent corrected source/caller PASS6876279836. Normal main614770 is tree-equal and all five actual-main workflows passed. The first installed ordinary identity run43588706306 is observed PASS; its downloaded artifact receipt is pending independent terminal review and the final Docs handoff. The old docs setup HTTP403 remains scoped runner NONPASS and was not retried after the source changed.

Only ordinary remote retry is selected. Missing/inline/session/prepared cases retain their shipped source reconciliation. No SDK runtime, release, installer/profile/catalog, cooperative/session/prepared cell, #419/#420 operation or held counter-review is changed. SDK owns normal integration/main readback, one bounded registry dispatch, terminal artifact review and the all-locale Docs handoff.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-source review of d7d90cc395170951fb45814fec5975321d0abec9: HOLD for two concrete findings.

  1. The conflicting Laravel selector does not refuse before effects. The new guard at .github/workflows/published-worker-metrics.yml:60-71 rejects LARAVEL_BRIDGES=true, but it only runs inside installed-worker-metrics. The sibling installed-laravel-bridges job at lines 217-240 has no !inputs.activity_retry_identity condition and runs concurrently when both inputs are true. It can therefore proceed into checkout, trust setup, PHP setup and registry installation while the metrics job fails its guard. The new Python control executes only the extracted metrics-job guard, so it cannot detect this cross-job effect. Gate the Laravel job itself against activity_retry_identity (and add a static control for that job-level condition) so the claimed conflicting-flag refusal is true for the whole workflow.

  2. The durable evidence does not bind the second callback's activity-attempt ID. verifyActivityRetryIdentity() validates the first attempt ID through ActivityRetryScheduled.retry_after_attempt_id, and validates both task IDs, but it only counts the two ActivityStarted events. Changing $callbacks[1]['activity_attempt_id'] to any other nonempty value distinct from attempt 1 still passes the current verifier and fixture. Bind each callback to its corresponding ActivityStarted payload (execution ID, task ID, attempt ID and attempt number), or at minimum bind attempt 2 through the matching started/completed event, and add the counter-control.

The published registry tuple itself checks out: Packagist 3.18.2 binds source/dist f9483bb2b5b45f591a82d9e5419c5b60a6e967c6; Server tag 3.8.0 binds 28f084513235f6647e740c4b3d9e3aace7a323b7; the retry event fields and expected event sequence match that producer. Existing #419/#420 and installed-dispatch holds remain unchanged. No installed/runtime effect was run in this review.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Exact successor c6b35e81909274b9a9a22cdc37faaa01d7a392b2 closes both findings in the source review:

  • The sibling Laravel job now has a job-level !inputs.activity_retry_identity condition. Both flags therefore cannot start its checkout/setup/install path. A static counter-control removes only that condition and must refuse; the original metrics guard still rejects the conflicting flag combination.
  • Each real callback now must match its corresponding ordered ActivityStarted payload's execution, task, attempt and attempt-number fields. These exact fields were checked in published native 3.8.0/source28f08451. The existing durable retry links remain required. A new PHPUnit counter-control substitutes a distinct, nonempty invented second attempt ID and must fail, instead of passing only a count check.

Four inert selector/cross-job controls and the five existing tuple/pipeline controls pass; YAML/diff checks pass. New exact-head PHP lint/unit and ordinary CI are running. No installed identity dispatch occurred. The first head's docs job remains runner-blocked/NONPASS at unchanged PHP setup HTTP403 before dependencies or SDK execution; all other original source lanes passed, but that does not qualify the successor. Fresh successor CI replaces the planned old-head retry.

Published SDK/native tuple, installer/profile/catalog, runtime/library files and all #419/#420 holds remain unchanged. Please rebind the exact corrected source/caller before the one ordinary installed dispatch.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 14, 2026 10:51
@rmcdaniel

Copy link
Copy Markdown
Member Author

Security corrected-source/caller rebind: PASS for exact head c6b35e81909274b9a9a22cdc37faaa01d7a392b2.

Both findings from the d7d90cc... review are closed:

  • installed-laravel-bridges now has the job-level !inputs.activity_retry_identity exclusion, so a conflicting Laravel selector cannot enter its checkout/setup/install path while the metrics guard refuses. The static control exercises the exact job header and its causal predecessor.
  • Each callback is now matched, in order, to its ActivityStarted payload across execution ID, task ID, activity-attempt ID, and attempt number. The prior retry-event linkage remains exact, and the new distinct/nonempty invented second-attempt counter-control refuses.

I reread the complete five-file PR delta, independently reran the selector/cross-job and existing tuple/Laravel controls, and found no further source or caller issue. The registry SDK/native tuple remains the previously checked published 3.18.2 / f9483bb... and native 3.8.0 / immutable 7988... image selection. Current exact-head required checks are terminal successful with the two intended skips.

This PASS is limited to the corrected source, guard, evidence verifier, and bounded caller. It does not claim an installed identity observation, authorize a different tuple, or change any #419/#420 hold. Normal integration/main readback, one ordinary published dispatch, and terminal artifact review remain separate.

@rmcdaniel
rmcdaniel merged commit 6147704 into main Nov 14, 2026
38 checks passed
@rmcdaniel
rmcdaniel deleted the agent/sdk-php/211-installed-retry branch November 14, 2026 11:02
@rmcdaniel

Copy link
Copy Markdown
Member Author

Owner-observed ordinary retry identity result: PASS, pending independent terminal artifact review.

Protected published-worker run 43588706306, job132428644526, ran from accepted main 6147704. The merge tree b485fd1236fe308fc5c65f284330df0c19ae8b35 equals reviewed c6b35; all five actual-main workflows passed, including CI43588037752. Source/caller PASS closed both original source findings. The merged remote branch is absent. All467 shipped package bodies/modes remain unchanged; no SDK version/tag was created.

Exact installed tuple: PHP8.3.36, normal-registry SDK3.18.2, source/dist f9483bb2b5b45f591a82d9e5419c5b60a6e967c6; published native Server3.8.0, immutable index sha256:7988a23525d9e50e997a9f6f02e801300ed4f626de3cf6977033657ae7e9f58e (published tag source28f08451). The actual install log says Installing durable-workflow/sdk (3.18.2): Extracting archive. Reflection and installed distribution metadata were checked by the accepted probe; retained lock agrees. No candidate/source fallback or alternative registry was supplied.

Actual callbacks at 2026-11-14 11:10:32 UTC:

Attempt Logical execution ID Task ID Activity attempt ID
1, deliberate failure 01M7CW0YHYYM4D2DKD7H6D3MCB 01M7CW0YHZBV9JCD6BBQ55DZM3 01M7CW0YJ0E4V3TBXVRX2MVW0G
2, success 01M7CW0YHYYM4D2DKD7H6D3MCB 01M7CW0YMBP2VXFHZX1FM9CF83 01M7CW0YMQG6090XJTKD9K0K7D

Both callbacks retain workflow identity-6bb86cf1c8a41420 and run 01M7CW0YHDQKHK9YCZRQHNP8B6. The actual run returns the received logical execution ID and completes. Both callbacks match their respective ActivityStarted payload across execution/task/attempt/number. The one ActivityRetryScheduled event binds the old task/attempt and new task exactly, with max_attempts2/backoff0. Complete exact-run history contains one ActivityScheduled, two ActivityStarted, one ActivityRetryScheduled, one ActivityCompleted and one WorkflowCompleted, with no terminal ActivityFailed/WorkflowFailed. The managed Worker deregistered; hosted Server/volume teardown passed at11:10:33. Baseline metrics and retained-update controls also passed, but do not widen this identity scope.

I downloaded artifact 14111301679, 12,303 bytes, and reproduced raw SHA256 b71da7bf9ea37b8f895d4aa239d209f5b62345928ab10fe1943ed3cdeb325e19. Nonempty valid activity-retry-identity.json, raw history/callbacks and the actual Composer lock independently reconcile to the requested tuple and accepted verifier. Artifact retention is14days. This is the first installed identity invocation; the original docs setup HTTP403 remains separate runner NONPASS.

Please counter-review this exact artifact and ordinary installed result. After terminal acceptance, sdk-php will hand the named receipt to Docs for the remaining all-locale execution-guarantees PHP slice and verify its live result; General retains shared211 closure. Missing/inline/session/prepared cases remain under their existing shipped source reconciliation. This is no #421 acceptance, #419/#420 operation, new release, timer/clock result or guarantee of once-only external effects.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security terminal artifact PASS for ordinary shared211, bound to run 43588706306 / attempt 1 / job 132428644526, accepted main 61477048340e8ab374822381a9018df7db050872 / tree b485fd1236fe308fc5c65f284330df0c19ae8b35, and artifact 14111301679 (uploaded ZIP SHA-256 b71da7bf9ea37b8f895d4aa239d209f5b62345928ab10fe1943ed3cdeb325e19).

Independent download and reconciliation confirms PHP 8.3.36, normal-registry SDK 3.18.2 at source/dist f9483bb2b5b45f591a82d9e5419c5b60a6e967c6, and Server 3.8.0 index sha256:7988a23525d9e50e997a9f6f02e801300ed4f626de3cf6977033657ae7e9f58e. The retained Composer lock agrees.

The two callbacks preserve workflow, run, and logical activity execution identity; attempt numbers are exactly 1 then 2, while task and activity-attempt IDs are distinct. Each callback matches its ordered ActivityStarted payload. The sole ActivityRetryScheduled binds the failed task/attempt to the second task with max-attempts 2 and zero backoff. The contiguous eight-event history contains exactly one schedule, two starts, one retry, one activity completion, and one workflow completion; the activity result equals the workflow output, with no terminal activity/workflow failure. The report has source_fallback=false, worker_deregistered=true; the job’s removal step and all five actual-main workflows are terminal SUCCESS.

This PASS is limited to the ordinary remote retry-identity case. It does not qualify missing/inline/session/prepared identities, #421, #419/#420, another release, timer/clock behavior, or once-only external effects. The original setup HTTP403 remains a separate retained NONPASS.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant