fix: Do not allow conditional execution on Subgraph Nodes + Validations - #2658
Merged
camielvs merged 1 commit intoAug 24, 2026
Merged
Conversation
🎩 PreviewA preview build has been created at: |
3 tasks
Collaborator
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
3 tasks
camielvs
force-pushed
the
08-20-fix_do_not_allow_conditional_execution_on_subgraph_nodes
branch
from
August 21, 2026 16:52
2f04588 to
8fe1221
Compare
camielvs
force-pushed
the
08-20-feat_finalize_conditional_execution
branch
from
August 21, 2026 16:52
325c67e to
2d0ce95
Compare
camielvs
force-pushed
the
08-20-fix_do_not_allow_conditional_execution_on_subgraph_nodes
branch
2 times, most recently
from
August 21, 2026 17:26
07f8fcc to
f194b0e
Compare
camielvs
marked this pull request as ready for review
August 21, 2026 17:26
Mbeaulne
reviewed
Aug 21, 2026
Mbeaulne
reviewed
Aug 21, 2026
camielvs
force-pushed
the
08-20-fix_do_not_allow_conditional_execution_on_subgraph_nodes
branch
from
August 21, 2026 22:10
f194b0e to
b4fefab
Compare
camielvs
force-pushed
the
08-20-fix_do_not_allow_conditional_execution_on_subgraph_nodes
branch
from
August 21, 2026 22:55
b4fefab to
f389987
Compare
camielvs
force-pushed
the
08-20-feat_finalize_conditional_execution
branch
from
August 21, 2026 22:55
2d0ce95 to
20b5ec3
Compare
Mbeaulne
approved these changes
Aug 24, 2026
Collaborator
Author
camielvs
changed the base branch from
08-20-feat_finalize_conditional_execution
to
graphite-base/2658
August 24, 2026 18:35
camielvs
added a commit
that referenced
this pull request
Aug 24, 2026
## Description Final pass over conditional execution. Nothing changes about what gets sent to the backend — this is UI, vocabulary and test coverage. The visual direction is borrowed from the exploration in #2649. **"Run when", not "isEnabled".** `isEnabled` is spec jargon. The UI now says **Run when**, and the two literal choices read **Always** / **Never** rather than true/false. **Conditional execution gets its own purple box in the Config tab.** A single switch turns it on for a task. When it's on, the **Run when** control appears inside the box — either the Always/Never toggle, or, if something is wired into it, the upstream source it follows (`→ Flag.flag`), formatted the same way bound inputs are formatted everywhere else in the editor. **On the node, the condition is separate from the inputs.** It used to be injected into the task's input list as a fake input, which meant the list had to know about it in every place it did anything (splitting, condensing, counting). It's now its own purple row above the inputs with its own handle, which means: - it stays visible when a node's inputs are condensed, instead of being counted into "+3 more" - the input-list code went back to exactly what it is on master — the whole special case is gone - collapsed nodes get the same treatment: a purple handle plus a branch icon **Dragging off the "Run when" handle no longer creates a graph input called** **`__is_enabled__`.** The editor names an auto-created input after the port you dragged from, and the reserved port name was leaking into the user's pipeline. It now creates an input called `run_condition`, typed `String` — that's the form the condition is actually read in, and it's what lets the input connect to the ports components declare. **Naming and comments.** Internal names now say what they are (`resetRunCondition`, `runConditionBinding`, `setRunCondition`, …). Comments that narrated the code were deleted; the ones left explain a decision the code can't. **Tests.** New coverage for the shared helpers, the enable/disable actions (including that switching conditional execution off clears both the literal and the connection while leaving other connections alone), the node rendering, the auto-created input, and each of the fixes below. ### Fixes from review - **A hand-written or SDK-generated pipeline can set the condition to an unquoted `false`.** That now reads as **Never**; before, it showed as **Always** while the backend skipped the task — the display and the behaviour disagreed. - **A condition pointing at something that no longer exists** now shows what it pointed at, instead of quietly falling back to **Always**. Loading such a pipeline also keeps the condition rather than leaving the task ungated. - **Grouping tasks into a subgraph, and ungrouping them again, no longer leaks the internal port name into the pipeline.** A promoted condition becomes a readable `run_condition` input, and a fixed condition survives the round trip. - **Dragging off the handle of a task set to Never no longer ungates it.** The auto-created input now starts out holding the task's own condition, so the task keeps running when it was set to. - **The Run when control is now properly labelled for screen readers.** - One violet palette, one icon and one stated reason for both, so the condition row can't drift apart between the full and collapsed node. ## Related Issue and Pull requests Stacked on #2651. UI direction borrowed from #2649. Followed by #2658, which stops conditional execution being set where the backend won't honour it. ## Type of Change - [x] Improvement ## Checklist - [ ] I have tested this does not break current pipelines / runs functionality - [ ] I have tested the changes on staging ## Screenshots (if applicable)     ## Test Instructions The `conditional-execution` flag is off by default — turn it on in Settings first. 1. Select a task → **Config** tab → toggle **Conditional execution**. The purple box expands to show **Run when**, and the node grows a purple row. 2. Flip **Run when** between Always and Never; the node's row should follow. 3. Condense the node's inputs — the condition row stays visible. 4. Drag from the node's purple handle onto empty canvas. You should get a `run_condition` String graph input, **not** one named `__is_enabled__`. 5. Set a task to **Never**, then drag off its handle. The new input should already hold `false`, and the task should still read as gated off — not silently switch to running. 6. Wire a task output into the handle. Both the node and the Config panel should read `→ Task.output`. 7. Delete that edge. The task stays conditional and resets to **Always** rather than silently staying Never. 8. Export the pipeline YAML and re-import it — the condition should survive the round trip. 9. Hand-edit a pipeline's YAML to set a task's condition to a bare `false` (no quotes), then open it. The task should read **Never**. 10. Select a conditional task and a neighbour, group them into a subgraph, then ungroup them. The condition should come back intact, and no input named `__is_enabled__` should appear anywhere. ## Additional Comments Turning conditional execution off deliberately clears the condition (both the literal and any connection) rather than remembering it, so re-enabling starts from Always. That's the trade discussed in #2651.
camielvs
force-pushed
the
08-20-fix_do_not_allow_conditional_execution_on_subgraph_nodes
branch
from
August 24, 2026 18:41
f389987 to
2ce5fec
Compare
camielvs
deleted the
08-20-fix_do_not_allow_conditional_execution_on_subgraph_nodes
branch
August 24, 2026 18:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Description
Conditional execution only works on tasks that run a container. The backend rejects it on subgraphs, so a pipeline that gates one fails at submission with a raw error the user can't act on.
The control is hidden for subgraphs. The Conditional execution box no longer appears when the selected node is a subgraph, so it can't be switched on by accident.
Validation covers what hiding the control can't. A pipeline can arrive with the condition already set — from the SDK, from hand-written YAML, or from an earlier version of the editor. A subgraph with a run condition is now flagged as an error that blocks submission, with a Remove Condition fix offered in the issue panel.
Three related checks, since the same panel was already open:
__is_enabled__collides with the name the editor reserves for run conditions. Connecting such an input would silently save it as the task's run condition and drop the argument. It's a warning as soon as the component is used, and an error once the input is actually connected.yes, or a value the editor can't make sense of — is an error, and the message quotes the offending value. Casing and stray whitespace are fine. A condition that's wired up rather than fixed is left alone, since its value isn't known until the run.Related Issue and Pull requests
Stacked on #2657.
Type of Change
Checklist
Screenshots (if applicable)
Test Instructions
The
conditional-executionflag is off by default — turn it on in Settings first.yes. You should get an error quoting that value. Change it toTRUEorfalseand it should be accepted.Additional Comments
The reserved-name check is a guard against a name collision rather than something a user is likely to hit — a component would have to declare an input called
__is_enabled__. It's here because the failure is silent: the argument disappears on save with nothing to indicate why.The type check accepts
str,boolandtextalongside the canonical type names. Since it blocks submission, a hand-written component using a lowercase alias shouldn't be caught by it.One thing deliberately not done: the accepted conditions aren't normalized on load. The checks read leniently but write nothing — quietly rewriting a value in someone's pipeline is worse than reporting it.