Skip to content

Advance the replay clock on consumed scalar child results - #321

Merged
rmcdaniel merged 5 commits into
mainfrom
feat/215-child-replay-clock
Nov 6, 2026
Merged

rmcdaniel merged 5 commits into
mainfrom
feat/215-child-replay-clock

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Business replay time advances when a scalar child result is consumed. The selected parent ChildRunCompleted/Failed/Cancelled/Terminated event supplies its recorded time. Sequential childWorkflow() and an actually consumed ChildWorkflowHandle::await() terminal use the validated boundary; startChildWorkflow() cannot borrow a future terminal's time.

The clock requires one ChildWorkflowScheduled, an optional single ChildRunStarted, and a unique terminal with matching canonical call/instance/run/type identities and the executor's validated sequence/path. Missing or conflicting identities, duplicate/conflicting/out-of-order rows and changing-run replacement chains preserve legacy outcomes and yield ReplayClockUnavailable. Child closed_at, started-handle time and reused_recorded_at are not substitute authorities. Grouped/scoped/selection clocks and child redrive reuse remain outside this slice.

ReplayClockHistory contains the shared pure field/time checks, while ChildReplayClockEvidence validates the child lifecycle. Both modules are covered by the existing corpus guards. The history index includes every numeric sequence the legacy resolver can claim, then requires strict integer identity on every proof row. This prevents a numeric-string duplicate from disappearing from the clock proof without changing legacy replay resolution.

Validation on source 35d1670:

  • Local PHP 8.4.27/PHPUnit 11.5.57: 100 tests / 155 assertions, including 27 child cases, 55 initial clock cases, existing handle tests and the official corpus. PHPStan: zero errors.
  • Three old-source failures reproduced on a21fa91 for numeric-string duplicate child/activity/timer terminals; corrected source refuses each while preserving the original outcome. The official corpus includes child duplicate/refusal followed by independent clock recovery, plus the four terminal-kind positive fixture.
  • Fresh current-head qualification is terminal: 41 successful checks and one intended connected-test skip, including Target branch qualification. PHP 8.4.27 ran 8,134 tests / 85,169 assertions / 56 optional-dependency skips. The official worker comparison against immutable ce41318 proves 67→69 fixtures, two revision checks, base fail / candidate pass. Direct unresolved PR Sonar issues: zero.
  • The first standalone ambiguity fixture was correctly refused by CI because it also passed on the no-child-clock base; the corrected fixture proves both refusal and later recovery without changing the validator. Original failed CI is retained in the PR record.

Maintained Core comparison: WorkflowExecutor 8fd6cb79 resumeChildResolution sends/throws at the parent resolution event.recorded_at; recordChildResolution and ChildRunHistory 006b2bc4 define canonical identities. Rust's accepted table is an independent source reference: durable-workflow/sdk-rust#219 (comment) . PHP uses its own callback/handle controls and actual worker corpus.

Refs durable-workflow/.github#215. No release/version, installed/native/runtime/authentication or publication is selected. Full #215, replacement chains, callback/ordinary-start authority and later signal/group coverage remain open. P0 matching setup/adoption preempts.

Current qualification: CI 42171170431, worker corpus, PHP 8.4. Main source updates build a documentation preview; the unchanged stable-channel gate skips Pages deployment for this unreleased 3.10 source. Published/connected workflows require manual selection and are not dispatched.

@rmcdaniel rmcdaniel added the agent:sdk-php Work done by the sdk-php repo agent label Nov 6, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

Current source checkpoint: 1c7f2f766c75512367234b55ce0a45a764754dc1 / tree d5efea5e06a5b60544f85f235b6ed33412f056fe.

Review reproduced three clock-proof failures on a21fa912: a duplicate child/activity/timer terminal with payload sequence "1" was invisible to the strict clock index while the unchanged legacy resolver claimed sequence 1. The successor indexes those rows for refusal and requires strict sequence identity on every lifecycle row. All three original outcomes remain unchanged; clock reads now throw ReplayClockUnavailable. The new official child duplicate fixture exercises the same path, alongside the four terminal-kind positive fixture. No replay result/schema/validator was weakened.

Source controls now pass 100 tests / 155 assertions and PHPStan reports zero errors. The earlier S1448 finding was corrected by separating pure history checks and child lifecycle evidence; both new modules are guarded. Fresh current-head CI and the immutable-base official worker comparison are still pending, owned by sdk-php. No installed/runtime/package/publication acceptance is claimed.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The 1c7f2f7 corpus job 127738704088 correctly rejected the standalone ambiguity fixture: it also passed on base ce413181, which has no child-clock support. That original failure is preserved.

Successor 35d1670 changes only the new fixture: after the ambiguous first child it consumes a second, independently valid child and requires that second terminal's exact time. This checks refusal plus recovery, fails the no-child-clock base on the second time, and fails the earlier permissive child implementation on the first time. The source/schema/validator/expected legacy outcomes are unchanged. Local official corpus controls pass 5 tests / 13 assertions; fresh normal exact-head CI is required and sdk-php owns it.

@sonarqubecloud

sonarqubecloud Bot commented Nov 6, 2026

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 6, 2026 06:00
@rmcdaniel
rmcdaniel merged commit a706473 into main Nov 6, 2026
42 checks passed
@rmcdaniel

Copy link
Copy Markdown
Member Author

Normal source integration completed at 2026-11-06T06:00:05Z as a706473da2a09e587fc21cc34122506b40382f13. GitHub's commit object and local Git independently agree on reviewed tree 47038f555ca66f2c0223d6f58593e1cc6c2ad668 and ordered parents [ce413181f57d6d58a26342b13d622ad375f3b0f0, 35d1670760f98a19ec4b4b33b09cd40128f1d8ad]. No history rewrite or branch-protection exception was used.

The exact PR had 42 terminal checks: 41 success and one intended connected-test skip. PHP 8.4.27 executed 8,134 tests / 85,169 assertions / 56 optional-dependency skips. The immutable-base official worker comparison passed 67→69 fixtures, two revision checks, base fail / candidate pass; direct unresolved PR Sonar issues were zero.

sdk-php owns resulting-main CI42171701497, portal preview42171701834, actual-main/source/live preservation and exact merged-branch cleanup. These are still pending; no terminal-main or live deployment acceptance is claimed. The unchanged portal stable-channel gate excludes this unreleased source from deployment. No release/tag, connected/installed/native/runtime/authentication or publisher dispatch follows.

@rmcdaniel
rmcdaniel deleted the feat/215-child-replay-clock branch November 6, 2026 06:02
@rmcdaniel

Copy link
Copy Markdown
Member Author

Terminal actual-main/source/preview/live-preservation acceptance is complete for normal merge a706473da2a09e587fc21cc34122506b40382f13 / reviewed tree 47038f555ca66f2c0223d6f58593e1cc6c2ad668. Ordered parents are ce413181f57d6d58a26342b13d622ad375f3b0f0 and 35d1670760f98a19ec4b4b33b09cd40128f1d8ad, independently reconciled through local Git and GitHub's commit object.

All 42 resulting-main checks are terminal: 40 success / two intended skips. Main CI42171701497, CodeQL, Public Boundary, Sonar and portal42171701834 passed. The exact PR qualification was 41 success / one intended skip; its official worker comparison proved 67→69 fixtures, two revision checks, base fail / candidate pass. PHP 8.4.27 executed 8,134 tests / 85,169 assertions / 56 optional-dependency skips. Direct unresolved PR Sonar issues were zero.

The downloaded Pages preview artifact 13482025584 is 1,062,011 bytes / SHA-256 6e589b893875e7e82ea16804b229b11da6d6f8598938486360b66f23b971ee4c. Its v2 audit binds source, SDK source, presentation source and workflow revision to actual main a706473. Deployment was skipped by the unchanged stable-channel condition. At 2026-11-06T06:04:19.224812Z, the live audit returned HTTP200 / 118 bytes / unchanged SHA-256 43c0159fc3ee9317a32e644e20d61d47d2fbf64d23194efe7b8e1f2b86514cd1, preserving published documentation source 6a821568db5c72983bd3990fe27c7990f092db12.

The clean merged branch was removed only after checking its exact 35d1670 head, merge ancestry, reviewed-tree equality and no open dependent PR. Local removal, empty Git transport readback and GitHub ref404 are verified. No owned source-tool containers remain. sdk-php continues the existing #215 consumed condition/signal-derived and corrected group source work; P0 matching setup/adoption preempts. Full #215 and all release/version/published/installed/native/runtime/authentication acceptance remain separate and open.

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

Labels

agent:sdk-php Work done by the sdk-php repo agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant