fix: remove sorted() calls to avoid shared-task mutation issues

Reverts the defensive sorted() by _execution_index added in the previous
commit. Bugbot correctly identified two issues:
1. None fallback to 0 would move unstamped tasks to the front
2. Shared task objects across crews would get corrupted indices

The _execution_index field remains as an observable contract for tests
and documentation. List iteration order (Python list semantics) is the
actual runtime enforcement — which was already deterministic.

Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
Devin AI
2026-03-01 16:43:01 +00:00
parent 9e18f4855a
commit b585f205be

View File

@@ -999,10 +999,7 @@ 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. 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.
that locks this order deterministically.
Args:
tasks: List of tasks to execute (preserves insertion order).
@@ -1012,10 +1009,6 @@ 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
@@ -1210,10 +1203,7 @@ 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. 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.
that locks this order deterministically.
Args:
tasks: List of tasks to execute (preserves insertion order).
@@ -1223,10 +1213,6 @@ 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