mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(gateway): hold pre-assigned dev at give_me_work's list_assigned fallback when deps are unmet
This commit is contained in:
@@ -613,6 +613,29 @@ class Choreographer:
|
||||
return f"call i_will_plan(task_id='{tid}', plan='<plan>') to start"
|
||||
return f"call i_will_work_on(task_id='{tid}', plan='<plan>') to start"
|
||||
|
||||
async def _drop_dependency_held(self, tasks: list[Any]) -> list[Any]:
|
||||
"""Drop pre-assigned PENDING tasks whose non-terminal dependencies are
|
||||
still unresolved.
|
||||
|
||||
``give_me_work``'s ``list_assigned_for_agent`` fallback includes PENDING
|
||||
rows with no dependency filter, so without this a held pre-assigned
|
||||
subtask (e.g. a frontend dev's task waiting on the UX/UI design) would
|
||||
still be offered and the agent only bounced at claim time. Mirrors the
|
||||
gate in ``TaskService.list_pending_for_agent`` and ``_run_claim_guards``.
|
||||
Only PENDING rows are gated — an already-claimed task is past the gate.
|
||||
"""
|
||||
offerable: list[Any] = []
|
||||
for task in tasks:
|
||||
dep_ids = list(getattr(task, "dependency_ids", []) or [])
|
||||
if (
|
||||
str(task.status) == "pending"
|
||||
and dep_ids
|
||||
and await self._deps.task.unmet_dependency_ids(dep_ids)
|
||||
):
|
||||
continue
|
||||
offerable.append(task)
|
||||
return offerable
|
||||
|
||||
async def give_me_work(self, agent_id: UUID) -> Envelope:
|
||||
"""Return the agent's most-actionable task or signal idle."""
|
||||
agent = await self._deps.task.agent_for(agent_id)
|
||||
@@ -632,7 +655,9 @@ class Choreographer:
|
||||
next=self._claim_verb_hint(role, t),
|
||||
context_briefing=await self._briefing_for(agent_id, t.id),
|
||||
).with_introspection(task=t, role=role)
|
||||
assigned = await self._deps.task.list_assigned_for_agent(agent_id)
|
||||
assigned = await self._drop_dependency_held(
|
||||
await self._deps.task.list_assigned_for_agent(agent_id)
|
||||
)
|
||||
if assigned:
|
||||
t = assigned[0]
|
||||
return Envelope.ok(
|
||||
|
||||
@@ -274,10 +274,20 @@ async def test_all_three_dev_paths_gate_then_release(dep_gate_setup: dict) -> No
|
||||
assert issue is not None, "spawn validation must hold the dev while UX is unmet"
|
||||
assert "dependency" in issue
|
||||
|
||||
# --- (b) give_me_work: list_pending_for_agent ---
|
||||
# --- (b) give_me_work has TWO offer paths and both must exclude the held
|
||||
# subtask: list_pending_for_agent (primary) and the
|
||||
# list_assigned_for_agent fallback (PENDING rows, no built-in dep filter).
|
||||
offered = await svc.list_pending_for_agent(fe_dev_db_id)
|
||||
assert dev_subtask.id not in {t.id for t in offered}, (
|
||||
"give_me_work must not offer the dev subtask while UX is unmet"
|
||||
"list_pending_for_agent must not offer the held dev subtask"
|
||||
)
|
||||
assigned = await svc.list_assigned_for_agent(fe_dev_db_id)
|
||||
assert dev_subtask.id in {t.id for t in assigned}, (
|
||||
"sanity: the held subtask is assigned+pending, so the fallback path is real"
|
||||
)
|
||||
offerable = await choreo._drop_dependency_held(assigned)
|
||||
assert dev_subtask.id not in {t.id for t in offerable}, (
|
||||
"give_me_work's list_assigned_for_agent fallback must not offer it"
|
||||
)
|
||||
|
||||
# --- (c) claim: _run_claim_guards (the i_will_work_on guard set) ---
|
||||
@@ -300,7 +310,13 @@ async def test_all_three_dev_paths_gate_then_release(dep_gate_setup: dict) -> No
|
||||
)
|
||||
offered_after = await svc.list_pending_for_agent(fe_dev_db_id)
|
||||
assert dev_subtask.id in {t.id for t in offered_after}, (
|
||||
"give_me_work must offer the dev subtask once UX is terminal"
|
||||
"list_pending_for_agent must offer the dev subtask once UX is terminal"
|
||||
)
|
||||
offerable_after = await choreo._drop_dependency_held(
|
||||
await svc.list_assigned_for_agent(fe_dev_db_id)
|
||||
)
|
||||
assert dev_subtask.id in {t.id for t in offerable_after}, (
|
||||
"the assigned-fallback gate must release the subtask once UX is terminal"
|
||||
)
|
||||
released = await svc.get(dev_subtask.id)
|
||||
assert (
|
||||
|
||||
Reference in New Issue
Block a user