auto-sync: 2026-06-05 11:03:30

This commit is contained in:
cfdaily
2026-06-05 11:03:30 +08:00
parent e9c9aaddfe
commit 6a649aba07
30 changed files with 602 additions and 1276 deletions
+87
View File
@@ -0,0 +1,87 @@
"""F14 Rebuttal 单元测试
按 test-plan-v2.6.md §F14
- F14 T1: 反驳权流程(P0
- F14 T2: 最大轮次限制(P0
"""
import json
import pytest
from pathlib import Path
from unittest.mock import MagicMock
from src.blackboard.models import Task
from src.blackboard.operations import Blackboard
from src.daemon.review import RebuttalManager
pytestmark = pytest.mark.unit
@pytest.fixture
def db_path(tmp_path):
return tmp_path / "blackboard.db"
@pytest.fixture
def bb(db_path):
return Blackboard(db_path)
# ---------------------------------------------------------------------------
# F14 T1: 反驳权流程
# ---------------------------------------------------------------------------
class TestRebuttal:
def test_submit_rebuttal_accepted(self, bb):
task = Task(id="t1", title="T", status="pending", assigned_by="d")
bb.create_task(task)
rm = RebuttalManager(bb=bb)
result = rm.submit_rebuttal("t1", "agent-1", "I disagree with the review")
assert result["status"] == "accepted"
assert result["round"] == 1
assert result["escalation_target"] == "simayi-challenger"
def test_second_round_escalates_to_pangtong(self, bb):
task = Task(id="t1", title="T", status="pending", assigned_by="d")
bb.create_task(task)
rm = RebuttalManager(bb=bb)
rm.submit_rebuttal("t1", "agent-1", "Round 1")
result = rm.submit_rebuttal("t1", "agent-1", "Round 2")
assert result["status"] == "accepted"
assert result["round"] == 2
assert result["escalation_target"] == "pangtong-fujunshi"
# ---------------------------------------------------------------------------
# F14 T2: 最大轮次限制
# ---------------------------------------------------------------------------
class TestRebuttalLimits:
def test_max_rounds_rejected(self, bb):
task = Task(id="t1", title="T", status="pending", assigned_by="d")
bb.create_task(task)
rm = RebuttalManager(bb=bb)
rm.submit_rebuttal("t1", "a", "R1")
rm.submit_rebuttal("t1", "a", "R2")
result = rm.submit_rebuttal("t1", "a", "R3")
assert result["status"] == "rejected"
assert "Max" in result["reason"]
def test_rebuttal_without_bb(self):
rm = RebuttalManager(bb=None)
result = rm.submit_rebuttal("t1", "a", "reason")
assert result["status"] == "accepted"
assert result["round"] == 1
def test_rebuttal_observation_recorded(self, bb):
task = Task(id="t1", title="T", status="pending", assigned_by="d")
bb.create_task(task)
rm = RebuttalManager(bb=bb)
rm.submit_rebuttal("t1", "agent-1", "test reason", evidence="file.txt")
obs = bb.get_observations(task_id="t1")
rebuttals = [o for o in obs if "Rebuttal round" in (o.body or "")]
assert len(rebuttals) == 1