mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[F067] flow_main_pm: add missing /triage route
main_pm's manifest advertises triage (lifecycle.intents_for_role(MAIN_PM) includes it via _PM_ROLES, alongside triage_all) but flow_main_pm.py had no POST /triage route, so a main_pm agent calling triage hit a raw 404 that bypassed the per-verb circuit breaker. Added the route mirroring flow_cell_pm's /triage — wires to the existing team-scoped choreographer.triage (uses pm.team, works for any PM role; Main PM gets its own team's blocked/awaiting tasks). Fix direction: add-route, NOT remove-from-manifest — the manifest is spec-correct (intents_for_role by construction); removing triage would contradict the spec and leave main_pm with only cross-team triage_all. TDD: test_triage_route_exists_and_dispatches.
This commit is contained in:
@@ -105,6 +105,26 @@ async def triage_all(
|
|||||||
return envelope_to_response(env, request)
|
return envelope_to_response(env, request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/triage")
|
||||||
|
async def triage(
|
||||||
|
request: Request,
|
||||||
|
_body: TriageRequest,
|
||||||
|
x_agent_id: _AgentIdHeader,
|
||||||
|
choreographer: _ChoreographerDep,
|
||||||
|
) -> dict:
|
||||||
|
"""Team-scoped triage for the Main PM (own-team blocked / awaiting_pm_review).
|
||||||
|
|
||||||
|
F067: the main_pm manifest advertises ``triage`` (lifecycle.intents_for_role
|
||||||
|
includes it for MAIN_PM via _PM_ROLES) alongside ``triage_all``; without a
|
||||||
|
route a main_pm agent calling `triage` hit a raw 404 that bypassed the
|
||||||
|
per-verb circuit breaker. ``choreographer.triage`` is team-scoped (uses
|
||||||
|
``pm.team``) and works for any PM role — Main PM gets its own team's
|
||||||
|
blocked/awaiting tasks; ``triage_all`` is the cross-team sweep.
|
||||||
|
"""
|
||||||
|
env = await choreographer.triage(x_agent_id)
|
||||||
|
return envelope_to_response(env, request)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/submit_root")
|
@router.post("/submit_root")
|
||||||
async def submit_root(
|
async def submit_root(
|
||||||
request: Request,
|
request: Request,
|
||||||
|
|||||||
@@ -362,3 +362,26 @@ async def test_resume_dispatches() -> None:
|
|||||||
)
|
)
|
||||||
assert resp.status_code == _HTTP_200
|
assert resp.status_code == _HTTP_200
|
||||||
mock_chore.resume.assert_awaited_once()
|
mock_chore.resume.assert_awaited_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_triage_route_exists_and_dispatches() -> None:
|
||||||
|
"""F067: POST /api/v1/flow/main_pm/triage must exist and wire to
|
||||||
|
choreographer.triage. The main_pm manifest (from lifecycle.intents_for_role)
|
||||||
|
advertises `triage` alongside `triage_all`, so a main_pm agent calling
|
||||||
|
`triage` must hit a real route — not a raw 404 that bypasses the circuit
|
||||||
|
breaker. Mirrors flow_cell_pm's /triage route (the choreographer.triage
|
||||||
|
impl is team-scoped and works for any PM role).
|
||||||
|
"""
|
||||||
|
mock_chore = MagicMock()
|
||||||
|
mock_chore.triage = AsyncMock(return_value=_make_envelope(status="idle"))
|
||||||
|
client = TestClient(_build_app(mock_chore))
|
||||||
|
resp = client.post(
|
||||||
|
"/api/v1/flow/main_pm/triage",
|
||||||
|
json={},
|
||||||
|
headers=_HEADERS,
|
||||||
|
)
|
||||||
|
assert resp.status_code == _HTTP_200, resp.text
|
||||||
|
body = resp.json()
|
||||||
|
assert body["status"] == "idle"
|
||||||
|
mock_chore.triage.assert_awaited_once()
|
||||||
|
|||||||
Reference in New Issue
Block a user