UAT: SubplanService.validate_spawn() incorrectly rejects parallel spawn when entry count exceeds max_parallel — spec defines max_parallel as a concurrency cap, not a total count limit #4566

Open
opened 2026-04-08 15:23:59 +00:00 by HAL9000 · 0 comments
Owner

Bug Report

Feature Area: Multi-project and hierarchical plans — subplan spawning validation

What Was Tested

Code analysis of SubplanService.validate_spawn() in src/cleveragents/application/services/subplan_service.py (lines 362–369) against the spec definition of SubplanConfig.max_parallel.

Expected Behavior (from spec)

From docs/specification.md (line 18417):

Parallel execution is bounded by SubplanConfig.max_parallel (default: 5, range: 1–50). This cap prevents runaway resource consumption when a large number of child plans are spawned simultaneously. The runtime uses a ThreadPoolExecutor with min(max_parallel, len(subplans)) workers.

The spec explicitly states min(max_parallel, len(subplans)) workers — meaning you can have more subplans than max_parallel. The executor simply limits concurrency to max_parallel workers at a time. This is the standard thread pool pattern: queue more work than workers, process in batches.

Actual Behavior (bug)

SubplanService.validate_spawn() rejects spawn requests where the number of spawn entries exceeds max_parallel:

# src/cleveragents/application/services/subplan_service.py, lines 362-369
# 3. max_parallel bounds validation
if config.execution_mode == ExecutionMode.PARALLEL:
    entry_count: int = len(spawn_entries)
    if entry_count > config.max_parallel:
        errors.append(
            f"Number of spawn entries ({entry_count}) exceeds "
            f"max_parallel bound ({config.max_parallel})"
        )

This means that with the default max_parallel=5, you cannot spawn more than 5 child plans in PARALLEL mode — even though the spec explicitly supports this via min(max_parallel, len(subplans)) workers.

Concrete Impact

Consider Example 4 (Multi-Project Dependency Update) from the spec: a parent plan spawning 4 child plans (one per microservice) in parallel. If max_parallel=3, the validation would reject the spawn entirely, even though the correct behavior is to run 3 at a time and queue the 4th.

For any real-world use case with more subplans than max_parallel, the system will fail with a validation error instead of batching execution.

Steps to Reproduce

from cleveragents.application.services.subplan_service import SubplanService, SpawnEntry
from cleveragents.domain.models.core.plan import SubplanConfig, ExecutionMode, SubplanMergeStrategy
from cleveragents.domain.models.core.decision import Decision, DecisionType

# Create config with max_parallel=2
config = SubplanConfig(
    execution_mode=ExecutionMode.PARALLEL,
    max_parallel=2,
    merge_strategy=SubplanMergeStrategy.GIT_THREE_WAY,
)

# Create 3 spawn entries (more than max_parallel)
entries = [
    SpawnEntry(
        decision=Decision(plan_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", sequence_number=i,
                          decision_type=DecisionType.SUBPLAN_SPAWN,
                          question="spawn", chosen_option="local/action"),
        action_name="local/action",
    )
    for i in range(3)
]

# This should succeed (run 2 at a time, queue 3rd)
# But it raises SpawnValidationError: "Number of spawn entries (3) exceeds max_parallel bound (2)"
result = SubplanService(mock_decision_service).validate_spawn(config, entries)

Code Location

  • File: src/cleveragents/application/services/subplan_service.py
  • Lines: 362–369 (the max_parallel bounds validation block)

Fix

Remove the validation check that rejects spawn requests where entry_count > max_parallel. The SubplanExecutionService._execute_parallel() already correctly uses min(self._config.max_parallel, len(statuses)) workers, so the concurrency cap is properly enforced at execution time without needing to reject spawns at validation time.


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area:** Multi-project and hierarchical plans — subplan spawning validation ### What Was Tested Code analysis of `SubplanService.validate_spawn()` in `src/cleveragents/application/services/subplan_service.py` (lines 362–369) against the spec definition of `SubplanConfig.max_parallel`. ### Expected Behavior (from spec) From `docs/specification.md` (line 18417): > Parallel execution is bounded by `SubplanConfig.max_parallel` (default: `5`, range: 1–50). This cap prevents runaway resource consumption when a large number of child plans are spawned simultaneously. **The runtime uses a `ThreadPoolExecutor` with `min(max_parallel, len(subplans))` workers.** The spec explicitly states `min(max_parallel, len(subplans))` workers — meaning you **can** have more subplans than `max_parallel`. The executor simply limits concurrency to `max_parallel` workers at a time. This is the standard thread pool pattern: queue more work than workers, process in batches. ### Actual Behavior (bug) `SubplanService.validate_spawn()` **rejects** spawn requests where the number of spawn entries exceeds `max_parallel`: ```python # src/cleveragents/application/services/subplan_service.py, lines 362-369 # 3. max_parallel bounds validation if config.execution_mode == ExecutionMode.PARALLEL: entry_count: int = len(spawn_entries) if entry_count > config.max_parallel: errors.append( f"Number of spawn entries ({entry_count}) exceeds " f"max_parallel bound ({config.max_parallel})" ) ``` This means that with the default `max_parallel=5`, you cannot spawn more than 5 child plans in PARALLEL mode — even though the spec explicitly supports this via `min(max_parallel, len(subplans))` workers. ### Concrete Impact Consider Example 4 (Multi-Project Dependency Update) from the spec: a parent plan spawning 4 child plans (one per microservice) in parallel. If `max_parallel=3`, the validation would **reject** the spawn entirely, even though the correct behavior is to run 3 at a time and queue the 4th. For any real-world use case with more subplans than `max_parallel`, the system will fail with a validation error instead of batching execution. ### Steps to Reproduce ```python from cleveragents.application.services.subplan_service import SubplanService, SpawnEntry from cleveragents.domain.models.core.plan import SubplanConfig, ExecutionMode, SubplanMergeStrategy from cleveragents.domain.models.core.decision import Decision, DecisionType # Create config with max_parallel=2 config = SubplanConfig( execution_mode=ExecutionMode.PARALLEL, max_parallel=2, merge_strategy=SubplanMergeStrategy.GIT_THREE_WAY, ) # Create 3 spawn entries (more than max_parallel) entries = [ SpawnEntry( decision=Decision(plan_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", sequence_number=i, decision_type=DecisionType.SUBPLAN_SPAWN, question="spawn", chosen_option="local/action"), action_name="local/action", ) for i in range(3) ] # This should succeed (run 2 at a time, queue 3rd) # But it raises SpawnValidationError: "Number of spawn entries (3) exceeds max_parallel bound (2)" result = SubplanService(mock_decision_service).validate_spawn(config, entries) ``` ### Code Location - **File**: `src/cleveragents/application/services/subplan_service.py` - **Lines**: 362–369 (the `max_parallel bounds validation` block) ### Fix Remove the validation check that rejects spawn requests where `entry_count > max_parallel`. The `SubplanExecutionService._execute_parallel()` already correctly uses `min(self._config.max_parallel, len(statuses))` workers, so the concurrency cap is properly enforced at execution time without needing to reject spawns at validation time. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.5.0 milestone 2026-04-08 17:41:40 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#4566
No description provided.