fix(compression): only an error-bearing result counts as a refused call

Gate finding BN03.r1.2c (Medium): status == "blocked" alone was treated
as a refusal, but successful kanban results use it as a task state --
kanban_block (and kanban_create with initial_status="blocked") return
{"ok": true, "status": "blocked", ...}. Those summarized as
"[kanban_block] BLOCKED, not run", so after pruning or fallback
compaction the model would read its own successful block/create as
refused and might repeat it (e.g. a duplicate card).

Every real refusal envelope carries a non-empty error string
(terminal _error_json / _blocked_json, tool_error); the kanban success
payloads have none. Require it. Adds the kanban_block success payload
as a negative row in the existing parametrize.
This commit is contained in:
kshitijk4poor
2026-10-03 15:13:12 +05:30
committed by kshitij
parent a287a7ea52
commit 2cad7ef208
2 changed files with 9 additions and 3 deletions

View File

@@ -2023,7 +2023,7 @@ def _summarize_refused_tool_result(tool_name: str, args: dict, content: str) ->
error = content.strip()
if status == "pending_approval":
outcome = "awaiting the user's approval, not run"
elif status == "blocked" or error.lstrip().startswith("BLOCKED"):
elif error and (status == "blocked" or error.lstrip().startswith("BLOCKED")):
outcome = "BLOCKED, not run"
if "NOT consented" in error:
outcome += "; the user did NOT consent, do not retry or reach the same outcome another way"

View File

@@ -438,9 +438,11 @@ class TestSummarizeToolResultClarify:
def _refusals():
"""Refused-call results from the real producers: the approval gate messages in their terminal /
tool_error envelopes, and a pending gateway approval. ``expected`` lists substrings the summary
must contain."""
tool_error envelopes, a pending gateway approval, and a successful kanban_block (``status``
"blocked" with no error, which is not a refusal). ``expected`` lists substrings the summary must
contain; empty means it must not read as refused."""
from tools import approval
from tools.kanban_tools import _ok
from tools.registry import tool_error
from tools.terminal_tool import _error_json
@@ -465,6 +467,9 @@ def _refusals():
pytest.param("terminal", {"command": "rm -rf build"},
_error_json("", status="pending_approval"),
["awaiting the user's approval, not run"], id="pending_approval"),
pytest.param("kanban_block", {"reason": "need creds"},
_ok(task_id="t_1", run_id=None, status="blocked", block_kind="needs_input"),
[], id="kanban_block_ok"),
]
@@ -477,6 +482,7 @@ class TestSummarizeToolResultRefusals:
summary = _summarize_tool_result(tool_name, json.dumps(args), content)
assert all(part in summary for part in expected), summary
assert ("not run" in summary) == bool(expected), summary
assert "ran `" not in summary and "wrote to" not in summary
assert len(summary) <= _PRUNE_MIN_CHARS - 1