From 9e18f4855ae505b11b3ffa46012fea25db97d21f Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 16:34:08 +0000 Subject: [PATCH] fix: address review comments - add runtime enforcement and remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unused 'import asyncio' from test file - Remove unused 'original_execute_sync' variable from test - Add defensive sorted() by _execution_index in _execute_tasks and _aexecute_tasks so the field is actively used at runtime, not just metadata Co-Authored-By: João --- lib/crewai/src/crewai/crew.py | 18 ++++++++++++++++-- .../crew/test_deterministic_task_ordering.py | 2 -- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/crewai/src/crewai/crew.py b/lib/crewai/src/crewai/crew.py index ac40fc622..2e872084b 100644 --- a/lib/crewai/src/crewai/crew.py +++ b/lib/crewai/src/crewai/crew.py @@ -999,7 +999,10 @@ class Crew(FlowTrackable, BaseModel): **Ordering contract**: tasks are dispatched in the exact order they appear in *tasks* (i.e. their insertion / list order). Each task carries an ``_execution_index`` stamped at crew-construction time - that locks this order deterministically. + that locks this order deterministically. As a defensive measure + the task list is sorted by ``_execution_index`` before iteration + so ordering is enforced even if the list is mutated after + construction. Args: tasks: List of tasks to execute (preserves insertion order). @@ -1009,6 +1012,10 @@ class Crew(FlowTrackable, BaseModel): Returns: CrewOutput: Final output of the crew. """ + tasks = sorted( + tasks, + key=lambda t: t._execution_index if t._execution_index is not None else 0, + ) task_outputs: list[TaskOutput] = [] pending_tasks: list[tuple[Task, asyncio.Task[TaskOutput], int]] = [] last_sync_output: TaskOutput | None = None @@ -1203,7 +1210,10 @@ class Crew(FlowTrackable, BaseModel): **Ordering contract**: tasks are dispatched in the exact order they appear in *tasks* (i.e. their insertion / list order). Each task carries an ``_execution_index`` stamped at crew-construction time - that locks this order deterministically. + that locks this order deterministically. As a defensive measure + the task list is sorted by ``_execution_index`` before iteration + so ordering is enforced even if the list is mutated after + construction. Args: tasks: List of tasks to execute (preserves insertion order). @@ -1213,6 +1223,10 @@ class Crew(FlowTrackable, BaseModel): Returns: CrewOutput: Final output of the crew. """ + tasks = sorted( + tasks, + key=lambda t: t._execution_index if t._execution_index is not None else 0, + ) custom_start = self._get_execution_start_index(tasks) if custom_start is not None: start_index = custom_start diff --git a/lib/crewai/tests/crew/test_deterministic_task_ordering.py b/lib/crewai/tests/crew/test_deterministic_task_ordering.py index 5183810ee..3f0389f85 100644 --- a/lib/crewai/tests/crew/test_deterministic_task_ordering.py +++ b/lib/crewai/tests/crew/test_deterministic_task_ordering.py @@ -9,7 +9,6 @@ See: https://github.com/crewAIInc/crewAI/issues/4664 from __future__ import annotations -import asyncio from unittest.mock import patch import pytest @@ -129,7 +128,6 @@ class TestDeterministicSyncOrder: for _ in range(ITERATIONS): dispatch_order: list[str] = [] - original_execute_sync = Task.execute_sync def tracking_execute_sync(self_task, *args, **kwargs): dispatch_order.append(self_task.description)