From bfd7d5b992653364d709a22f775b30f3793eb496 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 13 Feb 2026 15:18:56 +0530 Subject: [PATCH] feat: add status_requested field to task updates and implement related logic in task approval process --- backend/app/api/tasks.py | 9 +++- .../tests/test_tasks_done_approval_gate.py | 47 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/backend/app/api/tasks.py b/backend/app/api/tasks.py index bcb0aada..83f68d18 100644 --- a/backend/app/api/tasks.py +++ b/backend/app/api/tasks.py @@ -1054,12 +1054,16 @@ async def update_task( updates.pop("comment", None) updates.pop("depends_on_task_ids", None) updates.pop("tag_ids", None) + requested_status = payload.status if "status" in payload.model_fields_set else None update = _TaskUpdateInput( task=task, actor=actor, board_id=board_id, previous_status=previous_status, previous_assigned=previous_assigned, + status_requested=( + requested_status is not None and requested_status != previous_status + ), updates=updates, comment=comment, depends_on_task_ids=depends_on_task_ids, @@ -1299,6 +1303,7 @@ class _TaskUpdateInput: board_id: UUID previous_status: str previous_assigned: UUID | None + status_requested: bool updates: dict[str, object] comment: str | None depends_on_task_ids: list[UUID] | None @@ -1597,7 +1602,7 @@ async def _apply_lead_task_update( task_id=update.task.id, previous_status=update.previous_status, target_status=update.task.status, - status_requested="status" in update.updates, + status_requested=update.status_requested, ) await _require_review_before_done_when_enabled( session, @@ -1878,7 +1883,7 @@ async def _finalize_updated_task( task_id=update.task.id, previous_status=update.previous_status, target_status=update.task.status, - status_requested="status" in update.updates, + status_requested=update.status_requested, ) await _require_review_before_done_when_enabled( session, diff --git a/backend/tests/test_tasks_done_approval_gate.py b/backend/tests/test_tasks_done_approval_gate.py index a3d6deea..308ac97e 100644 --- a/backend/tests/test_tasks_done_approval_gate.py +++ b/backend/tests/test_tasks_done_approval_gate.py @@ -356,6 +356,53 @@ async def test_update_task_allows_status_change_with_pending_approval_when_toggl await engine.dispose() +@pytest.mark.asyncio +async def test_update_task_allows_dependency_change_with_pending_approval() -> None: + engine = await _make_engine() + try: + async with await _make_session(engine) as session: + board, task, _agent = await _seed_board_task_and_agent( + session, + task_status="review", + require_approval_for_done=False, + block_status_changes_with_pending_approval=True, + ) + dependency = Task( + id=uuid4(), + board_id=board.id, + title="Dependency", + status="inbox", + ) + session.add(dependency) + session.add( + Approval( + id=uuid4(), + board_id=board.id, + task_id=task.id, + action_type="task.execute", + confidence=70, + status="pending", + ), + ) + await session.commit() + + updated = await tasks_api.update_task( + payload=TaskUpdate( + status="review", + depends_on_task_ids=[dependency.id], + ), + task=task, + session=session, + actor=ActorContext(actor_type="user"), + ) + + assert updated.depends_on_task_ids == [dependency.id] + assert updated.status == "inbox" + assert updated.blocked_by_task_ids == [dependency.id] + finally: + await engine.dispose() + + @pytest.mark.asyncio async def test_update_task_rejects_status_change_for_pending_multi_task_link_when_toggle_enabled() -> ( None