mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(mcp): C1 per-verb circuit breaker trips on incomplete_input too
Smoke run 3 showed Main PM hitting 7 incomplete_input rejections on the decision-note required-fields gate before finally succeeding. The per-verb breaker tracks repeated rejections of the same verb in a 60s window and returns circuit_open after the 3rd strike — but its classification set only included tracing_gap. incomplete_input was added in Wave 1 (pre-gateway parity for decision/reflect structured fields) and should have been added to the breaker at the same time. Spec ref: docs/superpowers/specs/2026-05-12-post-smoke-3-fixes-design.md section C1.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Wave C1: per-verb circuit breaker trips on incomplete_input too.
|
||||
|
||||
Smoke run 3 showed Main PM hitting 7 incomplete_input rejections in
|
||||
~30 seconds on the decision-note required-fields gate. The breaker
|
||||
only included tracing_gap; incomplete_input was added in Wave 1 but
|
||||
the breaker classification wasn't updated.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import json
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import types
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
_MINIMAL_MANIFEST = {
|
||||
"agent_id": "00000000-0000-0000-0000-000000000042",
|
||||
"role": "main_pm",
|
||||
"team": "management",
|
||||
"workspace_path": "/tmp/test",
|
||||
"flow_tools": ["i_will_plan", "triage_all", "unblock", "complete", "i_am_idle"],
|
||||
"do_tools": [],
|
||||
"read_tools": [],
|
||||
"write_tools": [],
|
||||
"bash_allowed": False,
|
||||
"subagent_allowed": False,
|
||||
"subagent_model": None,
|
||||
"env": {},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def flow_module(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> types.ModuleType:
|
||||
"""Import flow_server with minimal env vars needed for constant inspection."""
|
||||
manifest_path = tmp_path / "tool-manifest.json"
|
||||
manifest_path.write_text(json.dumps(_MINIMAL_MANIFEST))
|
||||
|
||||
monkeypatch.setenv("ROBOCO_AGENT_ID", "00000000-0000-0000-0000-000000000042")
|
||||
monkeypatch.setenv("ROBOCO_AGENT_ROLE", "main_pm")
|
||||
monkeypatch.setenv("ROBOCO_ORCHESTRATOR_URL", "http://test-orchestrator:8000")
|
||||
monkeypatch.setenv("ROBOCO_SDK_URL", "http://test-sdk:9000")
|
||||
monkeypatch.setenv("ROBOCO_TOOL_MANIFEST_PATH", str(manifest_path))
|
||||
|
||||
import roboco.mcp.flow_server as srv
|
||||
|
||||
importlib.reload(srv)
|
||||
return srv
|
||||
|
||||
|
||||
def test_circuit_kinds_include_incomplete_input(
|
||||
flow_module: types.ModuleType,
|
||||
) -> None:
|
||||
"""incomplete_input is in the breaker's rejection-kind set."""
|
||||
assert "incomplete_input" in flow_module._CIRCUIT_REJECTION_KINDS
|
||||
|
||||
|
||||
def test_circuit_kinds_include_tracing_gap(
|
||||
flow_module: types.ModuleType,
|
||||
) -> None:
|
||||
"""Regression: tracing_gap stays in the set (the original kind)."""
|
||||
assert "tracing_gap" in flow_module._CIRCUIT_REJECTION_KINDS
|
||||
Reference in New Issue
Block a user