Repository navigation
Description
Service-mode workflow authors cannot choose a stable application ID for a child workflow. The current PHP worker API accepts an options array, but putting an ID in that array does not assign the child's workflow instance ID.
Validated public main source:
- PHP SDK
cad2b8cc53cdac36e19e563fc37565438e386f1b: WorkflowCommand::childWorkflow carries the workflow type and options into a child command. - Workflow
67833a7938b65e8ec663b4a63b25b4ac1b0beeef: WorkflowCommandNormalizer has no child instance-ID field in its normalized command. DefaultWorkflowTaskBridge::applyStartChildWorkflow creates the child instance with an engine-generated ID.
An isolated PHP 8.3 control loaded these exact source files. Normalizing a minimal child command with workflow_id, child_workflow_id, or instance_id produced the same result as omitting them, without an error. The SDK construction control retained workflow_id and correctly normalized a typed ParentClosePolicy::Abandon. This checks option handling, not a full worker/server execution.
Priority P3, additive feature. A custom child ID is not an existing documented guarantee, so this is not a regression claim.
Acceptance:
- Define one optional portable child instance-ID field and expose it through supported child-authoring options. Distinguish the stable instance ID, concrete run ID and parent-issued child-call identity.
- Keep generated IDs as the default. Specify namespace validation, collision/duplicate behavior and how an explicit ID behaves across parent task retries, replay, child retries and continue-as-new.
- Retain the ID in normalized commands and durable child scheduling history. Replay must neither create a second child nor silently change the requested identity.
- Qualify the PHP SDK/server path and coordinate the portable command with other SDKs. State the supported artifact baseline; source support alone does not certify published/native runtime parity.
- Until support exists, document the limitation and avoid suggesting that arbitrary ID keys in an options array are effective.
Searched existing child-workflow issue metadata; the closed queue, resolution and parallel replay defects do not cover explicit child instance IDs.
Activity
rmcdaniel commentedon Nov 4, 2026
Owner: Workflow for the portable embedded child-command contract; Server and all SDK owners for consumer parity; General for duplicate/reuse policy. Next is one explicit optional child instance-ID field and capability/version boundary, preserving generated IDs as default and distinguishing instance/run/parent-issued call identities.
I asked Server to return its existing native explicit-ID command shape or a concrete missing contract, including namespace collision, task retries, cold replay, child retries and continue-as-new. Arbitrary ignored options must not be documented as effective, and a duplicate receipt must not create a second child. This is separate from #989's await-started turn and #868's parent handoff. No guessed SDK field or new child writer is enabled by this inventory.
rmcdaniel commentedon Nov 13, 2026
Queue position (2026-11-13, workflow agent): after the #863 embedded implementation (contract merged in #1122) and the #996 implementation on #1126. Owner: Workflow. This P3 is next in line after those. Next action: the Core command contract for an explicit child
workflow_idon service-modestart_child_workflow, with duplicate-instance behavior matching embeddedchild(), then a Server parity issue.rmcdaniel commentedon Nov 13, 2026
Workflow owns this actionable embedded protocol change after #863/#996. The reviewed normalizer still does not make arbitrary child ID options effective.
Next action: add the single explicit optional child workflow_id contract and capability boundary, preserving generated IDs by default. Cover namespace collision, duplicate task receipt, retries, cold replay and continue-as-new against embedded child() semantics before enabling the field. Server/SDK follow-through must consume that same contract; #989's await-started turn stays independent.
rmcdaniel commentedon Nov 13, 2026
Current-source audit confirms this remains unimplemented. On merged Workflow
86b3de68, the normalizer'sstart_child_workflowoutput has no requested instance-ID field, and the bridge creates the child instance without an explicit id. Embedded v2ChildWorkflowOptionsalso has no instance-id option; its executor creates generated child ids. Published native3.9.1 source7d7ad9d6likewise assignschild_instance = id()inrust/src/runtime/children.rs. These are source observations, not a new installed qualification.One clarification to the earlier queue notes: there is no existing explicit-id collision/reuse policy in embedded v2
child()to copy. Top-level start validation and receipts are relevant primitives, but child identity behavior still needs an explicit product decision.Proposed bounded contract for General/Server review: one optional portable
workflow_ididentifies the stable child instance; omit it to keep generated ids. A distinct existing instance is rejected without attachment, replacement, cancellation or partial child writes. A repeated completion for the same canonical parent task/call uses its retained receipt and original child identity; replay never re-resolves a different requested id. Child run ids and parent-issued call ids remain engine identities. Child retry/continue-as-new retain the admitted instance identity and existing original clocks. Validate scope/length with the canonical start rules, preserve cross-namespace non-disclosure, and require actual producer/worker admission before an SDK emits the field to a runtime that would otherwise ignore it.Workflow still owns implementation after #996 as already queued. General owns collision/reuse disposition; Server has been asked to countercheck against the current native writer before a parity implementation is opened. No field/capability or claimed support is enabled by this audit.
rmcdaniel commentedon Nov 13, 2026
Native source countercheck at accepted main d66e33bf and published 3.9.1 source7d7ad9d6 agrees:
children.rsassigns freshchild_instance = id(),child_run = id()and call id; thestart_child_workflowcommand field set has no caller instance-ID field. The child inherits the parent's namespace and build pin. Existing child-call/link/attempt identities do not establish an explicit application-ID collision/reuse contract.The proposed optional portable workflow_id boundary therefore needs General's product disposition rather than copying an existing native promise. Generated IDs should remain the default; any explicit-ID support must bind the original parent call/attempt/receipt, validate scope before writes, refuse a distinct instance without attachment or replacement, preserve original clocks through retry/continue and avoid cross-namespace disclosure. It must be capability-gated so a producer that lacks the field cannot silently ignore an author's chosen identity. No current native custom-ID or installed parity support is claimed. Server retains native follow-through after current correctness work, coordinated with Workflow's owned authoring/normalizer contract and #989's separate await-started boundary.