mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(mcp): flow_server i_will_work_on forwards steps — completes #172
#172 (4c397e1) added IWillWorkOnRequest.steps, the flow_dev route
threading, the _dev_steps_gate, and the developer prompt — but never
updated the roboco-flow MCP tool. flow_server.i_will_work_on exposed
only (task_id, plan) and posted only those, so the agent's tool could
not transmit steps. Every fresh dev claim hit the gate's
incomplete_input missing=['steps'] with no way to satisfy it →
permanent wedge for every code task (observed in smoke-16: be-dev-1
looped ~20 times, then deadlocked — could not claim, block, or idle).
Add the steps parameter and forward it, mirroring the existing
i_will_plan/sub_tasks pattern (which is why PM i_will_plan was never
affected). Update the two body-shape tests and add a steps-passthrough
regression test.
This commit is contained in:
@@ -210,9 +210,28 @@ def give_me_work() -> dict[str, Any]:
|
|||||||
return _post(_role_path("give_me_work"), {})
|
return _post(_role_path("give_me_work"), {})
|
||||||
|
|
||||||
|
|
||||||
def i_will_work_on(task_id: str, plan: str | None = None) -> dict[str, Any]:
|
def i_will_work_on(
|
||||||
"""Claim/start/recover a task. Works for pending, claimed, needs_revision."""
|
task_id: str,
|
||||||
return _post(_role_path("i_will_work_on"), {"task_id": task_id, "plan": plan})
|
plan: str | None = None,
|
||||||
|
steps: list[dict[str, str]] | None = None,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Claim/start/recover a task. Works for pending, claimed, needs_revision.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
task_id: UUID of the task you are claiming.
|
||||||
|
plan: One-paragraph narrative of how you'll execute the task.
|
||||||
|
steps: Ordered execution checklist — list of
|
||||||
|
``{"title": "...", "description": "..."}``. Required on a
|
||||||
|
FRESH claim: the gateway's ``_dev_steps_gate`` rejects an
|
||||||
|
empty or thin list, and the same list is reused as the
|
||||||
|
progress checklist (#173 — completing a step advances %).
|
||||||
|
Re-entry / recovery claims (already-claimed or
|
||||||
|
needs_revision) do not need steps re-supplied.
|
||||||
|
"""
|
||||||
|
return _post(
|
||||||
|
_role_path("i_will_work_on"),
|
||||||
|
{"task_id": task_id, "plan": plan, "steps": steps or []},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def open_pr(task_id: str) -> dict[str, Any]:
|
def open_pr(task_id: str) -> dict[str, Any]:
|
||||||
|
|||||||
@@ -140,7 +140,11 @@ def test_i_will_work_on_passes_plan(flow_module: types.ModuleType) -> None:
|
|||||||
flow_module.i_will_work_on("task-uuid", plan="my plan")
|
flow_module.i_will_work_on("task-uuid", plan="my plan")
|
||||||
|
|
||||||
args, kwargs = fake_client.post.call_args
|
args, kwargs = fake_client.post.call_args
|
||||||
assert kwargs["json"] == {"task_id": "task-uuid", "plan": "my plan"}
|
assert kwargs["json"] == {
|
||||||
|
"task_id": "task-uuid",
|
||||||
|
"plan": "my plan",
|
||||||
|
"steps": [],
|
||||||
|
}
|
||||||
assert "/api/v2/flow/developer/i_will_work_on" in args[0]
|
assert "/api/v2/flow/developer/i_will_work_on" in args[0]
|
||||||
|
|
||||||
|
|
||||||
@@ -151,7 +155,28 @@ def test_i_will_work_on_plan_defaults_to_none(flow_module: types.ModuleType) ->
|
|||||||
flow_module.i_will_work_on("task-uuid")
|
flow_module.i_will_work_on("task-uuid")
|
||||||
|
|
||||||
_, kwargs = fake_client.post.call_args
|
_, kwargs = fake_client.post.call_args
|
||||||
assert kwargs["json"] == {"task_id": "task-uuid", "plan": None}
|
assert kwargs["json"] == {"task_id": "task-uuid", "plan": None, "steps": []}
|
||||||
|
|
||||||
|
|
||||||
|
def test_i_will_work_on_passes_steps(flow_module: types.ModuleType) -> None:
|
||||||
|
"""#172: the MCP tool must forward the steps checklist; the
|
||||||
|
server-side _dev_steps_gate rejects a fresh claim without it, so a
|
||||||
|
tool that drops steps wedges every code task."""
|
||||||
|
fake_client = _make_fake_client({"status": "in_progress"})
|
||||||
|
steps = [
|
||||||
|
{"title": "Checkout", "description": "create branch and read README"},
|
||||||
|
{"title": "Edit", "description": "append the timestamp comment"},
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch("httpx.Client", return_value=fake_client):
|
||||||
|
flow_module.i_will_work_on("task-uuid", plan="p", steps=steps)
|
||||||
|
|
||||||
|
_, kwargs = fake_client.post.call_args
|
||||||
|
assert kwargs["json"] == {
|
||||||
|
"task_id": "task-uuid",
|
||||||
|
"plan": "p",
|
||||||
|
"steps": steps,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_i_am_done_sends_task_id_and_notes(flow_module: types.ModuleType) -> None:
|
def test_i_am_done_sends_task_id_and_notes(flow_module: types.ModuleType) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user