Skip to content

feat(automation): approval as a durable-pause flow node (ADR-0019 P1–P3) - #1407

Merged
os-zhuang merged 1 commit into
mainfrom
feat/adr-0019-approval-as-flow-node
May 31, 2026
Merged

feat(automation): approval as a durable-pause flow node (ADR-0019 P1–P3)#1407
os-zhuang merged 1 commit into
mainfrom
feat/adr-0019-approval-as-flow-node

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

Summary

Realizes the core of ADR-0019collapse approval into the one flow engine, approval as a durable-pause node. This lands the additive, non-breaking foundation (phases A1–A3): the Approval node suspends a flow run on entry and resumes it on a human decision, riding the same engine as every other node. The standalone process-driven approval engine is left fully intact for the migration window; the destructive removal (A4/A5) is a deliberate follow-up PR.

What's in this PR

P1 — engine durable suspend/resume (service-automation)

  • FlowSuspendSignal thrown from executeNode, caught in execute()/resume(), persisted to an in-memory suspendedRuns map.
  • AutomationResult gains status: 'completed' | 'paused' | 'failed' + runId; IAutomationService gains optional resume(runId, signal?) and listSuspendedRuns().
  • On resume, the engine selects the out-edge whose label matches ResumeSignal.branchLabel. $runId is injected into flow variables.
  • screen node opts into pause via config.waitForInput.

P2 — Approval node contract (spec)

  • APPROVAL_NODE_TYPE, ApprovalDecision, APPROVAL_BRANCH_LABELS, ApprovalNodeConfigSchema — lowers approvers / behavior / lockRecord / escalation / approvalStatusField into node config.
  • ApprovalProcessSchema + ApprovalActionType deprecated via JSDoc (not removed).

P3 — node provider bridge (plugin-approvals, additive)

  • Registers the approval node (supportsPause, category: 'human') via the ADR-0018 registry. On entry it opens a sys_approval_request (reusing approver resolution / audit / record lock / status mirror verbatim) and suspends; decideApprovalNode finalizes the decision and resumes the run down the matching approve / reject edge.
  • sys_approval_request gains correlation fields: flow_run_id / flow_node_id / node_config_json.

Deferred to a follow-up PR (A4/A5)

Deleting action-executor.ts, ApprovalActionType, top-level ApprovalProcessSchema + approval.form.ts, retiring process_hash pinning, and removing connector_action remnants. Held back because these are a destructive removal of a still-functioning subsystem with active consumers (metadata-form-registry.ts, stack.zod.ts, CRM examples/seeders, and the constrained metadata-type-schemas.ts). The ADR itself frames the process model as "retained for the migration window."

Test plan

  • spec6605 pass
  • service-automation79 pass (incl. 6 new durable suspend/resume tests + screen waitForInput)
  • plugin-approvals41 pass (incl. 6 new node-bridge tests: suspend-on-entry, approve/reject resume, unanimous hold-then-resume, non-approver FORBIDDEN)
  • All three packages build clean (tsup ESM/CJS/DTS).

Collapse approval onto the one flow engine: an Approval node suspends the
run on entry and resumes on a human decision, instead of a parallel
approval engine. Additive and non-breaking — the standalone process
engine is left intact for the migration window (A4/A5 deletions follow up).
P1 — engine durable suspend/resume
- FlowSuspendSignal thrown from executeNode, caught in execute()/resume(),
persisted to an in-memory suspendedRuns map.
- AutomationResult gains status ('completed'|'paused'|'failed') + runId;
IAutomationService gains optional resume(runId, signal?) and
listSuspendedRuns(). Resume selects the out-edge whose label matches
ResumeSignal.branchLabel. $runId injected into flow variables.
- screen node opts into pause via config.waitForInput.
P2 — Approval node contract (spec)
- APPROVAL_NODE_TYPE, ApprovalDecision, APPROVAL_BRANCH_LABELS,
ApprovalNodeConfigSchema (approvers / behavior / lockRecord /
escalation / approvalStatusField lowered into node config).
- Deprecate ApprovalProcessSchema + ApprovalActionType via JSDoc.
P3 — plugin-approvals node provider (additive bridge)
- Register the `approval` node (supportsPause, category:human) via the
ADR-0018 registry: on entry open a sys_approval_request (reusing
approver resolution / audit / lock / status mirror) and suspend;
decideApprovalNode finalizes and resumes down approve/reject edge.
- sys_approval_request gains flow_run_id / flow_node_id / node_config_json.
Tests: spec 6605, service-automation 79, plugin-approvals 41 — all green.
@vercel

vercelBot commented May 31, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specBuildingBuildingPreview, CommentMay 31, 2026 6:53am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests size/xl labels May 31, 2026
@os-zhuang
os-zhuang merged commit c94827d into mainMay 31, 2026
9 of 12 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/xltests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@xuyushun441-sys@os-zhuang