From 5afc96f998ecf9a1345aa6a0e0133e1720a00a6b Mon Sep 17 00:00:00 2001 From: root Date: Fri, 9 Oct 2026 10:17:08 +0800 Subject: [PATCH] fix(report): count failed and budget_paused agents as incomplete coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An agent whose status is 'failed' or 'budget_paused' never finished the surfaces it held, but _INCOMPLETE_AGENT_STATUSES only listed crashed, stopped, running, and waiting — so coverage.json could claim complete: true while an agent had died mid-scan. Add both statuses and tests covering each. --- strix/report/coverage.py | 7 ++++++- tests/test_report_coverage.py | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/strix/report/coverage.py b/strix/report/coverage.py index c519853a..da1e1f01 100644 --- a/strix/report/coverage.py +++ b/strix/report/coverage.py @@ -55,7 +55,12 @@ OUTCOME_LABELS: dict[str, str] = { } #: Statuses that mean the agent stopped early rather than finishing its task. -_INCOMPLETE_AGENT_STATUSES = frozenset({"crashed", "stopped", "running", "waiting"}) +#: ``failed`` and ``budget_paused`` are in ``core.agents.Status`` too, and an +#: agent wearing either never finished the surfaces it held, so they count as +#: incomplete here just like ``crashed`` does. +_INCOMPLETE_AGENT_STATUSES = frozenset( + {"crashed", "stopped", "running", "waiting", "failed", "budget_paused"} +) #: Run statuses that mean the scan itself did not run to completion. _INCOMPLETE_RUN_STATUSES = frozenset({"failed", "interrupted", "stopped", "running"}) diff --git a/tests/test_report_coverage.py b/tests/test_report_coverage.py index 76200edf..6219ba8d 100644 --- a/tests/test_report_coverage.py +++ b/tests/test_report_coverage.py @@ -154,6 +154,27 @@ def test_unfinished_agent_makes_the_record_partial() -> None: assert "authz-tester" in doc["completeness"]["caveats"][0] +def test_failed_agent_makes_the_record_partial() -> None: + """A failed agent must not let the record read as complete (#1458).""" + doc = _document( + agent_graph=_graph(statuses={"agent-1": "failed"}), + exit_reason="finished_by_tool", + ) + + assert doc["completeness"]["complete"] is False + assert "authz-tester" in doc["completeness"]["caveats"][0] + + +def test_budget_paused_agent_makes_the_record_partial() -> None: + doc = _document( + agent_graph=_graph(statuses={"agent-1": "budget_paused"}), + exit_reason="finished_by_tool", + ) + + assert doc["completeness"]["complete"] is False + assert "authz-tester" in doc["completeness"]["caveats"][0] + + def test_failed_run_status_makes_the_record_partial() -> None: doc = _document( run_record={"run_id": "r1", "status": "failed"},