Reported by the domain:services dev that delivered #15788 (lane 2 of the #14945 ruling 2′) as an out-of-scope finding, and filed here by the seat — dev agents report findings with dedupe words; they ⛔ do not file.
Mechanism
packages/services/service-automation/src/builtin/subflow-node.ts branches only on child.status === 'paused'. Every other child status falls through the same success path, so a child run recorded refused returns success: true and the parent walks straight down the subflow node's out-edges.
⇒ An author who writes a refusing end inside a subflow gets the opposite of what the refusal means at the parent level: the parent continues as though the child said yes.
Why it is filed now, and why it is ⛔ NOT a regression of #15788
Before #15788's delivery nothing could write refused at all, so the parent's behaviour was identical (a refusing child merely completed, and the parent continued). ⛔ PR #18109 does not change subflow-node.ts and does not make any existing flow behave differently.
What changed is reachability: the end executor now produces refused, so this path becomes live the moment authors start writing refusals — which is exactly what lane 2 was ruled in to enable. ⚠️ The #14945 ruling says nothing about subflow rollup, so this is ⛔ not a shortfall in that ruling and ⛔ not something #18109 should have ridden in.
Relationship to the sibling card
⚠️ #16314 is the INVERSE direction and is a different card: it is about subflow and map rolling a child's contained failures into the parent's failed through the ExecutionStepMetrics failure slot. This card is about a refused child rolling up as success — the refusal reaching nobody. Same file, opposite failure mode. ⛔ Do not close either as a duplicate of the other.
Not prescribed here
The fix direction is a real fork and belongs to whoever takes this, not to the filer: does a refusing child terminate the parent run as refused, surface as a distinguishable branch the author can route on, or stay a success with the refusal recorded? A refusal is a successful evaluation that says no, ⛔ not a failure, so folding it into the failed rollup #16314 describes would be the wrong answer in a way that is easy to reach for.
Dedupe words
subflow child refused rollup · subflow-node.ts child.status paused · refused subflow parent continues · end node outcome refused subflow · #14945 lane 2 subflow
Related: #16314 · #14945 · #15788 · PR #18109
⛔ domain:*, type and priority are the triage seat's; this card is filed ungraded.
Generated by Claude Code
Reported by the
domain:servicesdev that delivered #15788 (lane 2 of the #14945 ruling 2′) as an out-of-scope finding, and filed here by the seat — dev agents report findings with dedupe words; they ⛔ do not file.Mechanism
packages/services/service-automation/src/builtin/subflow-node.tsbranches only onchild.status === 'paused'. Every other child status falls through the same success path, so a child run recordedrefusedreturnssuccess: trueand the parent walks straight down the subflow node's out-edges.⇒ An author who writes a refusing
endinside a subflow gets the opposite of what the refusal means at the parent level: the parent continues as though the child said yes.Why it is filed now, and why it is ⛔ NOT a regression of #15788
Before #15788's delivery nothing could write
refusedat all, so the parent's behaviour was identical (a refusing child merely completed, and the parent continued). ⛔ PR #18109 does not changesubflow-node.tsand does not make any existing flow behave differently.What changed is reachability: the⚠️ The #14945 ruling says nothing about subflow rollup, so this is ⛔ not a shortfall in that ruling and ⛔ not something #18109 should have ridden in.
endexecutor now producesrefused, so this path becomes live the moment authors start writing refusals — which is exactly what lane 2 was ruled in to enable.Relationship to the sibling card
subflowandmaprolling a child's contained failures into the parent'sfailedthrough theExecutionStepMetricsfailure slot. This card is about arefusedchild rolling up as success — the refusal reaching nobody. Same file, opposite failure mode. ⛔ Do not close either as a duplicate of the other.Not prescribed here
The fix direction is a real fork and belongs to whoever takes this, not to the filer: does a refusing child terminate the parent run as refused, surface as a distinguishable branch the author can route on, or stay a success with the refusal recorded? A refusal is a successful evaluation that says no, ⛔ not a failure, so folding it into the
failedrollup #16314 describes would be the wrong answer in a way that is easy to reach for.Dedupe words
subflow child refused rollup·subflow-node.ts child.status paused·refused subflow parent continues·end node outcome refused subflow·#14945 lane 2 subflowRelated: #16314 · #14945 · #15788 · PR #18109
⛔
domain:*, type and priority are the triage seat's; this card is filed ungraded.Generated by Claude Code