Skip to content

feat: add conditional execution to the pipeline editor - #2649

Closed
Mbeaulne wants to merge 1 commit into
masterfrom
conditional-execution-ui
Closed

feat: add conditional execution to the pipeline editor#2649
Mbeaulne wants to merge 1 commit into
masterfrom
conditional-execution-ui

Conversation

@Mbeaulne

@Mbeaulne Mbeaulne commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds conditional task execution to the pipeline editor using TaskSpec.isEnabled as the source of truth.

  • Adds a Conditional execution toggle to container task configuration.
  • Shows a highlighted Run when property and branch indicator directly on conditional task nodes.
  • Allows pipeline inputs and task outputs to be connected as the task's run condition.
  • Serializes the visual condition connection to TaskSpec.isEnabled instead of a component argument.
  • Loads and displays conditions created through YAML or the CLI.
  • Removes the condition connection when conditional execution is disabled.
  • Preserves conditional bindings when creating, unpacking, and round-tripping subgraphs without exposing the internal editor port in the component interface.
  • Displays the conditional state in both detailed and simplified canvas views.

Related Issue and Pull requests

Type of Change

  • Bug fix
  • New feature
  • Improvement
  • Cleanup/Refactor
  • Breaking change
  • Documentation update

Checklist

  • I have tested this does not break current pipelines / runs functionality
  • I have tested the changes on staging

Screenshots (if applicable)

image image

Test Instructions

  1. Open a pipeline in the editor and select a container task.
  2. Open Config and enable Conditional execution.
  3. Confirm the task displays the violet Run when property and conditional branch indicator.
  4. Connect a pipeline input or task output containing true or false to Run when.
  5. Save and reopen the pipeline, then confirm the condition connection is preserved.
  6. Run the pipeline and confirm the task runs for true and is skipped for false.
  7. Disable conditional execution and confirm the property and its connection are removed.
  8. Check both detailed and simplified canvas views.

Automated validation:

pnpm run validate
pnpm vitest run src/utils/conditionalExecution.test.ts src/routes/v2/pages/Editor/nodes/TaskNode/context/TaskDetails/components/taskConfig.actions.test.ts src/routes/v2/shared/nodes/TaskNode/TaskNodeCard.test.tsx src/models/componentSpec/__tests__/actions/createSubgraph.test.ts src/models/componentSpec/__tests__/actions/unpackSubgraph.test.ts src/models/componentSpec/__tests__/serialization/jsonSerializer.test.ts src/models/componentSpec/__tests__/serialization/yamlDeserializer.test.ts src/models/componentSpec/__tests__/integration/roundtrip.test.ts

Additional Comments

The editor does not use an annotation to track conditional mode. An unset isEnabled means normal execution, while a present value means the task is conditional. Enabling the setting initially writes isEnabled: "true" until a condition is connected.

@github-actions

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: conditional-execution-ui/e19ce98

@Mbeaulne Mbeaulne changed the title feat: add conditional task execution UI feat: add conditional execution to the pipeline editor Aug 20, 2026

Copy link
Copy Markdown
Collaborator Author

@Mbeaulne
Mbeaulne marked this pull request as ready for review August 20, 2026 17:08
@Mbeaulne
Mbeaulne requested a review from a team as a code owner August 20, 2026 17:08

Copy link
Copy Markdown
Collaborator

Closing this in favour of #2657

@camielvs camielvs closed this Aug 21, 2026
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)

![image.png](https://app.graphite.com/user-attachments/assets/867473a8-dde6-490d-b617-311386ab3a2f.png)

![image.png](https://app.graphite.com/user-attachments/assets/29830e75-b968-45dc-8052-8b3903daa8dc.png)

![image.png](https://app.graphite.com/user-attachments/assets/4b780085-7d4a-4f78-97da-504426663f52.png)

![image.png](https://app.graphite.com/user-attachments/assets/dbdeaf0d-4da1-45c9-b7fe-3f641e6a2cd9.png)



## 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants