mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(gateway): unblock PM planning + drop magic delegate task_type
Two coupled fixes from the 2026-05-08 smoke-test trace: 1. pm_cannot_execute_code is now scoped to i_will_work_on (the EXECUTION verb) only. Pre-fix it also fired on i_will_plan, which deadlocked any code-typed parent: cell_pm couldn't plan, so couldn't transition parent to in_progress, so couldn't delegate. PMs PLAN code-typed parents and DELEGATE the work — that's exactly the verb we were blocking. 2. delegate.task_type is now REQUIRED at both the HTTP boundary (DelegateRequest) and the choreographer dataclass (DelegateInputs). The pre-fix default of 'code' silently changed semantics whenever a caller forgot the field — main-pm's call in the smoke trace omitted it, schema defaulted to 'code', and the cell PM downstream was wedged. Also drops the choreographer's task.task_type fallback (the DB column is NOT NULL anyway). Plus middleware coverage tests for the parallel ServiceError → 4xx handler hierarchy added in the prior session, restoring 100% coverage across the touched files. Tests: 3101 passing, 100% coverage, ruff clean.
This commit is contained in:
@@ -379,6 +379,7 @@ async def test_delegate_main_pm_to_cell_pm_creates_subtask() -> None:
|
||||
description="Plan backend work for feature X",
|
||||
assigned_to="be-pm",
|
||||
team="backend",
|
||||
task_type="planning",
|
||||
),
|
||||
)
|
||||
assert env.error is None
|
||||
@@ -417,6 +418,7 @@ async def test_delegate_cell_pm_to_team_dev_creates_subtask() -> None:
|
||||
description="Add /v1/foo endpoint with tests",
|
||||
assigned_to="be-dev-1",
|
||||
team="backend",
|
||||
task_type="code",
|
||||
),
|
||||
)
|
||||
assert env.error is None
|
||||
@@ -438,7 +440,11 @@ async def test_delegate_main_pm_to_dev_is_rejected() -> None:
|
||||
main_pm_id,
|
||||
parent_id,
|
||||
DelegateInputs(
|
||||
title="x", description="y", assigned_to="be-dev-1", team="backend"
|
||||
title="x",
|
||||
description="y",
|
||||
assigned_to="be-dev-1",
|
||||
team="backend",
|
||||
task_type="code",
|
||||
),
|
||||
)
|
||||
body = env.as_dict()
|
||||
@@ -460,7 +466,13 @@ async def test_delegate_cell_pm_to_other_pm_rejected() -> None:
|
||||
env = await c.delegate(
|
||||
cell_pm_id,
|
||||
parent_id,
|
||||
DelegateInputs(title="x", description="y", assigned_to="be-pm", team="backend"),
|
||||
DelegateInputs(
|
||||
title="x",
|
||||
description="y",
|
||||
assigned_to="be-pm",
|
||||
team="backend",
|
||||
task_type="code",
|
||||
),
|
||||
)
|
||||
body = env.as_dict()
|
||||
assert body["error"] == "not_authorized"
|
||||
@@ -481,7 +493,11 @@ async def test_delegate_unknown_assignee_returns_invalid_state() -> None:
|
||||
pm_id,
|
||||
parent_id,
|
||||
DelegateInputs(
|
||||
title="x", description="y", assigned_to="nope-pm", team="backend"
|
||||
title="x",
|
||||
description="y",
|
||||
assigned_to="nope-pm",
|
||||
team="backend",
|
||||
task_type="code",
|
||||
),
|
||||
)
|
||||
body = env.as_dict()
|
||||
@@ -503,7 +519,11 @@ async def test_delegate_invalid_team_enum_rejected() -> None:
|
||||
pm_id,
|
||||
parent_id,
|
||||
DelegateInputs(
|
||||
title="x", description="y", assigned_to="be-dev-1", team="not-a-team"
|
||||
title="x",
|
||||
description="y",
|
||||
assigned_to="be-dev-1",
|
||||
team="not-a-team",
|
||||
task_type="code",
|
||||
),
|
||||
)
|
||||
assert env.as_dict()["error"] == "invalid_state"
|
||||
|
||||
Reference in New Issue
Block a user