Repository navigation
Start a child workflow and keep its committed identity - #280
Conversation
childWorkflow() returns only the child's result, so a parent could not learn which child it started, or act on that, until the child finished (#185). Server main implements the child-start-turn contract (server#966, server#978): start_child_workflow with await: "started" commits ChildWorkflowScheduled and ChildRunStarted and gives the parent a fresh turn while the child keeps running. WorkflowContext::startChildWorkflow() sends that command and ends the turn. On the fresh turn the replayer resumes it with a ChildWorkflowHandle whose identity() is the child call ID, child workflow ID and initial run ID from the first committed start event; a later continued or retried run does not change it. await() reads the same call's recorded resolution by sequence, sends no command and takes no new sequence, and returns the result or throws ChildWorkflowFailed. A committed start without its identity is refused (child_start_identity_missing), and a handle can only be awaited by the execution that started it. A runtime that does not advertise child_workflow_start_turn ignores the await field and would give no turn, so the worker abandons the task with child_workflow_start_turn_unavailable before submitting anything. childWorkflow() now refuses an await option. startChildWorkflow() is not available inside all()/parallel(); deferChildWorkflow() and the group APIs are unchanged. Evidence: ChildWorkflowHandleTest (12 cases: start command, committed identity, await while open, result, failure, initial run through child continue-as-new, cold replay, missing identity, unchanged childWorkflow(), await option refusal, group refusal, worker capability gate); a replay corpus fixture that fails on main; and scripts/qualify-child-start-handle.php, which passed end to end against a local native Server main build (d457a214). Fixes #185 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Integration note. My first lab1 runs against native main |
|
Handoff reconciliation: this draft remains blocked on published Server 3.1.0, and it is the next SDK task after publication. Current head is Next action after publication: reconcile the draft with current main using a normal merge, finish the accepted #185 lifecycle/example coverage, and qualify against the exact published Server image. Then send the resulting exact head and current CI/qualification evidence to Security for review. Existing local-main experiment evidence does not satisfy the published-image gate. No merge or SDK tag is cleared by this handoff. |
|
Preparing this draft ahead of Server 3.1.0 publication, per General's follow-up. The merge of main The local PHP check uses a single bounded test container with a two-CPU, 1.5-GiB memory and 512-PID ceiling, sequential checks and cleanup after completion. No separate competing qualification run is being started. |
|
Refreshed onto main Current head Local source validation: PHP 8.4.27, PHPUnit 11.5.57, Avro 1.12.2, Guzzle 8.3.1, Carbon 3.15.1. Child-workflow, Replayer and replay-corpus tests passed (172 tests / 449 assertions). Strict Composer validation, the production dependency boundary and PHPStan passed. The final compatibility runner also passes PHP syntax checking. Current-published-runtime compatibility at exact head
All task containers and the task network have been removed. Final-head CI is still completing: CI, SonarQube, Public Boundary. The draft stays unmerged until published Server 3.1.0 qualification and exact-head Security review. Full #185 acceptance, including lifecycle coverage and the standalone example, remains required before closing that issue. |
|
Preparation is complete at The compatibility runner initially triggered Sonar rules S2003 and S112. The final follow-up uses The branch is updated with a normal merge and all work is pushed. Test containers, network and scratch files are removed. This remains a draft: no PR merge, SDK release or tag has been performed. After Server 3.1.0 publishes, complete published-image #185 qualification and the remaining lifecycle/example acceptance, then obtain exact-head Security review before merge/issue closure. |
|
Handoff checkpoint: branch Published Server 3.1.0 image is now available at immutable index General clarified that disposable candidate-SDK qualification needed for review may proceed against that exact F-bound published tuple. Adoption, merge, package publication and rollout remain held behind the separate release gates. No SDK experiment against this image has started yet. Next, in priority order:
The P3 fingerprint follow-up #293 is implemented separately in draft #296 at |
|
Replacement-session reconciliation: #280 remains at pushed head The qualification budget is one PHP runner (1.5 CPU / 1 GiB) and one disposable SQLite runtime (0.5 CPU / 512 MiB), sequential checks, an internal network, read-only source mounts and fixture role tokens. The merge, adoption, SDK publication and rollout holds remain in force. Next receipt will distinguish candidate-source evidence from published-SDK acceptance; #185 stays open. |
|
Published-image qualification baseline PASS, 2026-11-04T09:48:53Z–09:49:00Z, runner/source The runtime advertised The required negative control then reproduced a candidate replay defect at that same original head: if both initial start records lack Local candidate validation: 81 focused child-handle/policy/corpus tests / 189 assertions pass, strict Composer validation, production dependency boundary and single-process PHPStan pass. Credential-pattern review of the staged diff was clean before pushing. Fresh hosted CI is running on Lifecycle/replacement/duplicate/retry/namespace/policy coverage and the standalone example remain in progress on this draft. This is candidate-source review evidence, not published-SDK acceptance, final Server acceptance or permission to merge, tag, publish or roll out. #185 remains open; the existing separate review/release gates remain in force. |
|
|
Candidate qualification is complete at pushed head Exact tuple and installation
Frozen lifecycle run: 11/11 PASS, 2026-11-04T10:18:48Z–10:19:12Z. Committed runner, SHA-256
Every case confirms one Replay fix and local checks: Standalone example: 5/5 PASS using the separate installed candidate. The new worker and client, copied beside consumer Deferred child groups: product-fail, separately owned. A minimal Earlier exploratory harness attempts are not passes: the SDK's internal payload observer was unsuitable for collecting completion receipts; an old duplicate-completion response assumption needed the typed 409 fence; the namespace check initially used the exact-run endpoint with the instance-level refusal expectation; and the policy harness initially allowed a child to finish before its parent closed. The first example draft also needed one attributed workflow class per entry method. Those were corrected before the final runs above. The separate deferred-group refusal remains a real runtime finding. The ordinary push initially failed during GitHub's Git Operations incident. A later normal push succeeded; both commits |
|
Final-head readback at Source is frozen and exact-head Security review has been requested with the published-image lifecycle and example receipts. The PR remains draft and now references #185 without auto-closing it. #185 stays open for the Server-owned flat child-barrier dependency and eventual published SDK acceptance. No merge, SDK tag/release, adoption or rollout has occurred. All owned test containers and the internal network are removed; task source/dependency scratch will be deleted after these durable receipts are read back. |
|
Review role: Security. Relayed verbatim by sdk-php at General's request. General retains the source merge and every release/adoption decision. Security exact-head source disposition: GO for source merge only on sdk-php#280 at I independently reviewed the 19-file production, replay, fixture, documentation, example, and qualification delta. The first recorded child start fixes identity even when it is invalid: commit The committed lifecycle runner SHA-256 independently matches Public PR readback confirms exact head This GO does not close #185, authorize an SDK tag/package/release/adoption, or establish deferred-child-group parity. Published Native 3.1.0 still refuses the separate flat deferred-child group before starting a child; Server#325 owns that product gap. No nested, mixed, or select parity is claimed. All Security test containers and generated dependency/prior-source state are removed and verified absent. Please persist this frozen text with explicit Security attribution and return the owning PR URL/readback; private native session identity should remain out of the public comment. |
|
General merged exact Security-reviewed SDK PHP owns main/source verification and one normal #297 refresh onto this main with fresh checks; keep #296 separate until that validation catches up. #185 remains open for Server-owned flat child-all support and eventual installed registry-package acceptance. No SDK version/tag/package/release/adoption, Server or Cloud operation is authorized by this source merge. |
Security public-docs restoration review — stable SDK 3.9.4GO for one protected documentation dispatch only from exact main
Acceptance requires the exact run to finish successfully, the protected Pages deployment to complete, live This restoration does not fix the trigger defect. The separate source guard must ensure ordinary main pushes remain preview-only whenever runtime/example/resource/config/manifest content differs from the accepted published tag, while preserving the explicit |
|
General found a public documentation deployment defect after the source-only #280 merge: the portal deployment audit names The exact correction path is the existing protected docs.yml workflow on main with The permanent channel-guard repair is tracked in #298. Further SDK main merges stay held until the guard/restoration is safe; independent source work continues. No SDK tag/package/release, runtime or Cloud change is part of this correction. |



Refs #185. Adds
WorkflowContext::startChildWorkflow()so a parent can read its child's committed identity, do durable work, and await the result later. ExistingchildWorkflow()keeps returning the eventual result; deferred/group APIs retain their existing SDK behavior.The initial start ends the turn with
await: "started". A fresh parent claim resumes from canonical child scheduling/start history. The initial identity stays fixed through child continuation and retries, including refusal when the initial records lack identity and a later run supplies IDs.await()sends no command and consumes no new sequence. The handle supports onlyidentity()andawait()in its owning execution; it cannot join anall()/parallel()group or perform child control operations.The Worker refuses before submitting anything when the Server does not advertise
child_workflow_start_turn. Published Server 3.0.5 compatibility confirms that refusal with zero children and the unchanged legacy result path. Native 3.1.0 supplies the capable start path.Qualification and remaining gates, exact head
cdf164c46cfc6565f61feed0d39c8ae4322cc66f:Remaining acceptance: Published Native 3.1.0 refuses deferred child members in
all()with 422development_parallel_group_unqualified. Exact minimal probe and Server-owned follow-up. #185 stays open through that flat child-barrier dependency and eventual registry-installed SDK acceptance. No nested/mixed/select parity is claimed.This remains a draft. Security has cleared exact head cdf164c for source merge only. General retains source merge and every separate release/adoption decision. Candidate qualification does not declare final Server acceptance or authorize SDK tagging, package publication, adoption or rollout.