Skip to content

fix(workflows): reject bool max_iterations in engine re-eval guard#3470

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/engine-max-iterations-bool-guard
Open

fix(workflows): reject bool max_iterations in engine re-eval guard#3470
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/engine-max-iterations-bool-guard

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Summary

The while / do-while step validators already reject max_iterations: true as a type error — bool is a subclass of int, so a boolean passes a bare isinstance(..., int) check, and since True - 1 == 0 it would silently cap the loop at a single iteration (0 re-iterations).

The engine's re-evaluation guard in WorkflowEngine, however, still used the older shape:

if not isinstance(max_iters, int) or max_iters < 1:
    max_iters = 10

On an unvalidated run (executing a definition without first calling the validators), a boolean max_iterations slipped through this guard and ran the loop body just once instead of falling back to the safe default of 10.

Fix

Add the explicit isinstance(max_iters, bool) rejection so the engine guard matches WhileStep.validate() / DoWhileStep.validate(). An unvalidated run now degrades to the default of 10 rather than silently under-running the loop.

Testing

  • Added test_while_loop_bool_max_iterations_falls_back_to_default, which runs a while step with max_iterations: true through the engine and asserts the body executes 10 times (not 1).
  • Verified the test fails without the engine change and passes with it (test-the-test via git stash).
  • Full while/do-while/loop suite: 16 passed.

🤖 Generated with Claude Code

The While/DoWhile step validators already reject `max_iterations: true`
as a type error (bool is an int subclass, so it would otherwise pass the
`isinstance(..., int)` check and, since `True - 1 == 0`, silently cap the
loop at a single iteration). The engine's re-evaluation guard used the
older `not isinstance(max_iters, int) or max_iters < 1` shape, so on an
unvalidated run a boolean slipped through and ran the loop body just once
instead of falling back to the safe default of 10.

Add the explicit `isinstance(max_iters, bool)` rejection so the engine
guard matches the step validators and an unvalidated run degrades to the
default rather than silently under-running the loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Fixes an engine-level edge case where max_iterations: true (a YAML boolean) could slip through an isinstance(..., int) guard and silently cap while/do-while loops to a single iteration when running an unvalidated workflow definition.

Changes:

  • Updated the workflow engine loop re-evaluation guard to explicitly reject bool values for max_iterations, falling back to the safe default (10).
  • Added a regression test that executes a while workflow with max_iterations: true through the engine and asserts the loop runs 10 times.
Show a summary per file
File Description
tests/test_workflows.py Adds a regression test ensuring max_iterations: true falls back to the default iteration cap when executed via the engine.
src/specify_cli/workflows/engine.py Updates the engine’s loop guard to treat booleans as invalid for max_iterations and default to 10.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Low

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