-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest_tool_dispatch_adversarial.py
More file actions
147 lines (116 loc) · 5.44 KB
/
Copy pathtest_tool_dispatch_adversarial.py
File metadata and controls
147 lines (116 loc) · 5.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""Behavioral adversarial fixtures for ``_TOOL_RESULT_DISPATCH`` predicate overlap.
Structural tuple-position guards live in ``test_tool_dispatch_ordering.py``.
These tests construct ``toolUseResult`` JSON that satisfies multiple predicates
and assert the classified winner via ``_parse_tool_result`` (first match wins).
"""
from __future__ import annotations
from collections.abc import Callable
import pytest
from tests.test_tool_dispatch_ordering import ORDERING_INVARIANT_IDS, ORDERING_INVARIANTS
from utils import tool_dispatch
from utils.tool_dispatch import _TOOL_RESULT_DISPATCH, _parse_tool_result
# Overlap blobs: keys chosen so both predicates in each ORDERING_INVARIANTS pair match.
PLAN_FILE_WRITE_OVERLAP: dict[str, object] = {
"plan": {"name": "sprint-plan", "steps": ["index", "search", "render"]},
"filePath": ".cursor/plans/week28.md",
"content": "Plan body that would also satisfy file_write.",
}
TASK_MESSAGE_RETRIEVAL_OVERLAP: dict[str, object] = {
"task_id": "task-overlap-retrieval",
"message": "polling retrieval",
"retrieval_status": "found",
"task": {"task_id": "task-overlap-retrieval", "description": "subagent scan"},
}
TASK_MESSAGE_COMPLETED_OVERLAP: dict[str, object] = {
"agentId": "agent-overlap-completed",
"totalDurationMs": 3200,
"totalTokens": 900,
"status": "completed",
"message": "task finished",
}
TASK_MESSAGE_ASYNC_OVERLAP: dict[str, object] = {
"agentId": "agent-overlap-async",
"isAsync": True,
"description": "explore auth handlers",
"message": "task launched",
}
# Narrow retrieval shape: only the downstream predicate matches (no task_id/message).
TASK_RETRIEVAL_NARROW: dict[str, object] = {
"retrieval_status": "pending",
"task": {"task_id": "task-narrow", "description": "wait for result"},
}
AssertWinner = Callable[[dict[str, object]], None]
def _assert_plan_beats_file_write(result: dict[str, object]) -> None:
assert result["result_type"] == "plan"
assert result.get("file_path") == ".cursor/plans/week28.md"
def _assert_task_message_beats_retrieval(result: dict[str, object]) -> None:
assert result["result_type"] == "task"
assert result.get("task_id") == "task-overlap-retrieval"
assert "retrieval_status" not in result
def _assert_task_message_beats_completed(result: dict[str, object]) -> None:
assert result["result_type"] == "task"
assert result.get("agent_id") is None
assert result.get("total_duration_ms") is None
def _assert_task_message_beats_async(result: dict[str, object]) -> None:
assert result["result_type"] == "task"
assert result.get("agent_id") is None
assert result.get("description") is None
_INVARIANT_BEHAVIOR: dict[str, tuple[dict[str, object], AssertWinner]] = {
"plan_before_file_write": (PLAN_FILE_WRITE_OVERLAP, _assert_plan_beats_file_write),
"task_message_before_task_retrieval": (
TASK_MESSAGE_RETRIEVAL_OVERLAP,
_assert_task_message_beats_retrieval,
),
"task_message_before_task_completed": (
TASK_MESSAGE_COMPLETED_OVERLAP,
_assert_task_message_beats_completed,
),
"task_message_before_task_async": (
TASK_MESSAGE_ASYNC_OVERLAP,
_assert_task_message_beats_async,
),
}
_INVARIANT_PREDICATES = dict(zip(ORDERING_INVARIANT_IDS, ORDERING_INVARIANTS, strict=True))
@pytest.mark.parametrize(
"fixture_id",
ORDERING_INVARIANT_IDS,
)
def test_adversarial_overlap_classifies_documented_winner(fixture_id: str) -> None:
blob, assert_winner = _INVARIANT_BEHAVIOR[fixture_id]
before, after, _ = _INVARIANT_PREDICATES[fixture_id]
assert before(blob), f"{fixture_id}: fixture no longer matches {before.__name__}"
assert after(blob), f"{fixture_id}: fixture no longer matches {after.__name__}"
result = _parse_tool_result(blob)
assert result is not None
assert_winner(result)
def test_task_retrieval_narrow_shape_without_task_message_keys() -> None:
"""Boundary: narrow retrieval wins when broad task_message keys are absent."""
result = _parse_tool_result(TASK_RETRIEVAL_NARROW)
assert result is not None
assert result["result_type"] == "task"
assert result.get("retrieval_status") == "pending"
assert result.get("task_id") == "task-narrow"
def test_inverted_plan_file_write_dispatch_misclassifies_overlap(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Regression: swapping plan below file_write flips the overlap winner."""
table = list(_TOOL_RESULT_DISPATCH)
plan_idx = next(
i for i, (pred, _) in enumerate(table) if pred.__name__ == "is_plan_tool_result"
)
write_idx = next(
i for i, (pred, _) in enumerate(table) if pred.__name__ == "is_file_write_tool_result"
)
table[plan_idx], table[write_idx] = table[write_idx], table[plan_idx]
monkeypatch.setattr(tool_dispatch, "_TOOL_RESULT_DISPATCH", tuple(table))
result = _parse_tool_result(PLAN_FILE_WRITE_OVERLAP)
assert result is not None
assert result["result_type"] == "file_write"
assert result.get("file_path") == ".cursor/plans/week28.md"
with pytest.raises(AssertionError):
_assert_plan_beats_file_write(result)
def test_ordering_invariants_have_adversarial_coverage() -> None:
"""Every ORDERING_INVARIANTS row has a behavioral fixture (keeps tables in sync)."""
assert len(ORDERING_INVARIANTS) == len(ORDERING_INVARIANT_IDS)
assert len(ORDERING_INVARIANT_IDS) == len(_INVARIANT_BEHAVIOR)
assert set(_INVARIANT_BEHAVIOR.keys()) == set(ORDERING_INVARIANT_IDS)