Skip to content

Add Switch Case flow-control block with per-case execution branches#2452

Merged
patricknihranz merged 4 commits into
mainfrom
pn/switch-case-block
Jun 15, 2026
Merged

Add Switch Case flow-control block with per-case execution branches#2452
patricknihranz merged 4 commits into
mainfrom
pn/switch-case-block

Conversation

@patricknihranz

Copy link
Copy Markdown
Contributor

Description

Adds roboflow_core/switch_case@v1, a flow-control block that routes execution to one of several branches by matching an input value against case keys — a multi-way alternative to chaining Continue If blocks.

Block semantics

  • value (selector or literal) is string-coerced and matched against the keys of cases: Dict[str, StepSelector] (e.g. {"red": "$steps.on_red"}); optional case_insensitive toggle.
  • On match, execution continues to that case's step only; otherwise default_next_steps runs; if that is empty the branch terminates.
  • A manifest validator rejects duplicate targets across cases + default_next_steps (each target step may be referenced at most once per flow-control step — engine constraint) and case-key collisions under case-insensitive matching, with readable errors instead of the engine's compile-time one.
  • cases is a flat dict because selector discovery only finds step selectors one level deep (schema_parser.py ignores nested references).

Execution engine changes (required for per-case branching)

  1. graph_constructor.py: selectors held in dict properties now get a unique execution branch per key (Branch[$steps.switch -> cases[red]]). Previously all selectors in one property shared a single branch, so selecting one case would have activated every case target. List properties (next_steps) keep the shared-branch behavior — ContinueIf semantics are unchanged.
  2. execution_data_manager/manager.py: deduplicate branch names when registering non-SIMD flow-control masks. This fixes a pre-existing bug: any non-SIMD flow-control step with two or more next_steps crashed with "Attempted to re-register maks for execution branch" (reproducible on main with plain ContinueIf; regression test added).

UI metadata: cases is marked always_visible so the builder renders it as a primary field. Companion frontend PR in roboflow/roboflow adds per-case connection handles in the workflow builder.

Testing

  • 22 unit tests (tests/workflows/unit_tests/core_steps/control_flow/test_switch_case.py): manifest validation + run() behavior incl. coercion edge cases (True→"True", None→"None", 1.0→"1.0").
  • 5 integration tests (test_workflow_with_switch_case.py): case match / default / terminate routing through ExecutionEngine, plus compile-time duplicate-target failure.
  • 2 regression tests for the multi-next_steps ContinueIf fix (test_workflow_with_flow_control.py).
  • Full tests/workflows/unit_tests/execution_engine/ suite passes (542 total in the affected areas).
  • Manually verified end-to-end through a local HTTP server (/workflows/run) and from the workflow builder UI.

🤖 Generated with Claude Code

@patricknihranz

Copy link
Copy Markdown
Contributor Author

Companion frontend PR: roboflow/roboflow#12428

patricknihranz and others added 3 commits June 12, 2026 13:18
Adds roboflow_core/switch_case@v1: routes execution to one of several
branches by matching a string-coerced input value against case keys
(flat Dict[str, StepSelector]), with optional case-insensitive matching
and a default branch (empty default terminates).

Engine changes required for per-case branching:
- graph_constructor: selectors held in dict properties get a unique
  execution branch per key (Branch[step -> cases[red]]); list properties
  keep the shared-branch behavior, so ContinueIf semantics are unchanged.
- execution_data_manager: deduplicate branch names when registering
  non-SIMD flow-control masks. Fixes a pre-existing crash where any
  non-SIMD flow-control step with multiple next_steps raised
  'Attempted to re-register maks for execution branch' (regression
  test added).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
always_visible promotes the cases editor onto the block card itself
instead of burying it in the Additional Properties panel - the case
mapping is the primary interaction for this block.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread inference/core/workflows/core_steps/flow_control/switch_case/v1.py Outdated
Addresses review feedback on #2452:
- Bump EXECUTION_ENGINE_V1_VERSION 1.10.1 -> 1.11.0 to account for the
  per-case dict execution branches (graph_constructor) and the non-SIMD
  mask dedup fix (execution_data_manager).
- Add a changelog entry describing both changes.
- Raise SwitchCase get_execution_engine_compatibility floor to >=1.11.0
  since the block depends on the new engine behavior.
- Update the EE version assertions in workflow endpoint tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@dkosowski87 dkosowski87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥇

@patricknihranz patricknihranz merged commit cef1b80 into main Jun 15, 2026
48 checks passed
@patricknihranz patricknihranz deleted the pn/switch-case-block branch June 15, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants