Skip to content

feat(automation): nested durable pause — subflow chains (linked runs) - #1693

Merged
os-zhuang merged 1 commit into
mainfrom
feat-subflow-nested-pause
Jun 10, 2026
Merged

feat(automation): nested durable pause — subflow chains (linked runs)#1693
os-zhuang merged 1 commit into
mainfrom
feat-subflow-nested-pause

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Closes the last known engine capability gap from the flow-engine review: a pausing node (approval / screen / wait) inside a subflow previously failed the parent run and stranded the child's already-persisted continuation as an orphan.

Subflow pauses now suspend the whole chain as linked runs (the inter-flow half of the long-term execution-state architecture — cf. Step Functions nested executions / Temporal child workflows; the intra-flow token-tree is a separate future ADR):

  • subflow node: child pauses → suspend the parent at the node with correlation: 'subflow:<childRunId>', surfacing the child's screen. Linkage ($parentRunId / $parentNodeId / $parentOutputVariable) rides on the child's persisted context — no sys_automation_run schema change. Descriptor now publishes supportsPause: true.
  • resume() boundary only (no traverseNext/executeNode changes, per the ADR-0031 multi-agent discipline):
    • down-delegation — resuming a run paused at a subflow forwards the signal to the suspended child; multi-screen child wizards keep the parent run id stable for the UI and refresh its surfaced screen (getSuspendedScreen stays refresh-safe)
    • up-bubble — a completed run carrying $parentRunId auto-resumes its parent with the child output mapped exactly like the synchronous path (${nodeId}.output + bare outputVariable)
    • failure propagation — a child failing terminally after the pause fails every waiting ancestor (bounded walk) instead of stranding them as resumable-forever
  • Both directions compose recursively (multi-level nesting), survive restarts via the durable store, and reuse the existing resume-once idempotency guards.
  • ADR-0019 addendum documents the model + deliberate v1 boundaries (fault edges do not catch post-pause child failures; timeoutMs does not span suspension; crash-between-bubble compensable via manual resume).

Test plan

  • +7 tests: parent-suspend linking · direct-child bubble (approval/wait path) · parent delegation with screens (screen-flow path) · multi-screen wizard · two-level nesting · cold-boot restart (two engines, shared store) · post-pause failure propagation
  • Full service-automation suite: 172/172 green; tsup build + DTS clean (the 2 pre-existing tsc test-file errors reproduce on main untouched)

🤖 Generated with Claude Code

A pausing node (approval/screen/wait) inside a subflow previously failed the
parent run and stranded the child's already-persisted continuation as an
orphan. Subflow pauses now suspend the whole chain as linked runs:
- subflow node: child pauses → suspend the PARENT at the node with
correlation 'subflow:<childRunId>', surfacing the child's screen; parent
linkage ($parentRunId/$parentNodeId/$parentOutputVariable) rides on the
child's persisted context — no sys_automation_run schema change
- resume() boundary (no traverseNext/executeNode changes):
- down-delegation: resuming a run paused at a subflow forwards the signal
to the suspended child; multi-screen children keep the parent run id
stable and refresh its surfaced screen
- up-bubble: a completed run carrying $parentRunId auto-resumes its parent
with the child output mapped exactly like the synchronous path
- failure propagation: a child failing terminally after the pause fails
every waiting ancestor (bounded walk) instead of stranding them
- both directions compose recursively (multi-level nesting), survive process
restarts via the durable store, and reuse the existing resume idempotency
guards
Tests: +7 covering parent-suspend linking, direct-child bubble, parent
delegation with screens, multi-screen wizard, two-level nesting, cold-boot
restart, and post-pause failure propagation (172 total green). ADR-0019
addendum documents the model and v1 boundaries.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 10, 2026 3:39pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests size/m labels Jun 10, 2026
@os-zhuang
os-zhuang merged commit a64c0c9 into mainJun 10, 2026
12 of 13 checks passed
@os-zhuang
os-zhuang deleted the feat-subflow-nested-pause branch June 10, 2026 15:52
os-zhuang added a commit that referenced this pull request Jun 10, 2026
Adds the worked example for nested durable pause (linked runs, #1693):
- showcase_closure_signoff: reusable approval subflow (manager sign-off,
approve/reject branches recorded into its `decision` output)
- showcase_project_closure: on project completion, invokes the sign-off
subflow — the child suspends on its approval node, suspending the parent
at the subflow node too; the decision bubbles back up and the owner is
notified with the outcome
Also gates showcase_budget_approval on the budget actually CHANGING
(`budget != previous.budget`) — it previously fired on every update of a
large-budget project, colliding with any other approval flow on the same
record (approvals dedupe pending requests per record), which broke the new
example and was wrong on its own terms.
Verified live in the browser: complete a project → parent run paused at
`signoff` (correlation subflow:<child>) + child paused at `ask_signoff` →
approve via /api/v1/approvals → child completes down the approve edge and
bubbles: parent resumes, notify_owner runs, both runs completed; the Studio
Runs panel shows the same run transitioning paused → completed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
xuyushun441-sys pushed a commit that referenced this pull request Jun 13, 2026
feat(app-shell): ADR-0048 (A) — package-id app routing (resolution layer) (#1693)
objectui@e8ad3ba03c8d804bee32c18c4f1a1c3530ad46a3
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mtests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang