diff --git a/tests/test_four_phase_unit.py b/tests/test_four_phase_unit.py index 2462071..2a85a6e 100644 --- a/tests/test_four_phase_unit.py +++ b/tests/test_four_phase_unit.py @@ -536,3 +536,95 @@ class TestU10ReviewPrompt: assert "失败处理" in prompt assert "2 个" in prompt # "有 2 个 sub task failed" assert "第 2 轮" in prompt + + +class TestU11ReviewingState: + """reviewing 中间态防重复触发""" + + def test_reviewing_skipped_in_round_check(self, project_env): + """reviewing 状态的 parent 不触发一轮结束检测""" + tmpdir, pid, bb = project_env + parent = _make_task(bb, "parent-1") + _make_task(bb, "s1", parent_task=parent) + + # sub done + bb.update_task_status("s1", "claimed", agent="test") + bb.update_task_status("s1", "working", agent="test") + bb.update_task_status("s1", "review", agent="test") + bb.update_task_status("s1", "done", agent="test") + + # parent done → reviewing + bb.update_task_status("parent-1", "claimed", agent="test") + bb.update_task_status("parent-1", "working", agent="test") + bb.update_task_status("parent-1", "review", agent="test") + bb.update_task_status("parent-1", "done", agent="test") + bb.update_task_status("parent-1", "reviewing", agent="daemon") + + # 验证 summary 返回 reviewing + summary = bb.get_subtasks_summary("parent-1") + assert summary is not None + assert summary["parent_status"] == "reviewing" + + # reviewing 不在 ("done", "failed") 中 → _check_round_complete 应跳过 + assert summary["parent_status"] not in ("done", "failed") + + def test_reviewing_not_overwritten_by_aggregation(self, project_env): + """reviewing 是 MANUAL_STATUS,不被 compute_parent_status 覆盖""" + tmpdir, pid, bb = project_env + parent = _make_task(bb, "parent-2") + _make_task(bb, "s1", parent_task=parent) + + # sub done + bb.update_task_status("s1", "claimed", agent="test") + bb.update_task_status("s1", "working", agent="test") + bb.update_task_status("s1", "review", agent="test") + bb.update_task_status("s1", "done", agent="test") + + # parent done → reviewing + bb.update_task_status("parent-2", "claimed", agent="test") + bb.update_task_status("parent-2", "working", agent="test") + bb.update_task_status("parent-2", "review", agent="test") + bb.update_task_status("parent-2", "done", agent="test") + bb.update_task_status("parent-2", "reviewing", agent="daemon") + + # compute_parent_status 应返回 reviewing(不覆盖) + from src.blackboard.queries import Queries + q = Queries(bb.db_path) + computed = q.compute_parent_status("parent-2") + assert computed == "reviewing" + + def test_reviewing_to_done_transition(self, project_env): + """reviewing → done 转换合法(GOAL_ACHIEVED 时)""" + tmpdir, pid, bb = project_env + parent = _make_task(bb, "parent-3") + + bb.update_task_status("parent-3", "claimed", agent="test") + bb.update_task_status("parent-3", "working", agent="test") + bb.update_task_status("parent-3", "review", agent="test") + bb.update_task_status("parent-3", "done", agent="test") + bb.update_task_status("parent-3", "reviewing", agent="daemon") + + # reviewing → done(GOAL_ACHIEVED 后) + result = bb.update_task_status("parent-3", "done", agent="daemon") + assert result is True + + task = bb.get_task("parent-3") + assert task.status == "done" + + def test_reviewing_to_working_transition(self, project_env): + """reviewing → working 转换合法(继续下一轮时)""" + tmpdir, pid, bb = project_env + parent = _make_task(bb, "parent-4") + + bb.update_task_status("parent-4", "claimed", agent="test") + bb.update_task_status("parent-4", "working", agent="test") + bb.update_task_status("parent-4", "review", agent="test") + bb.update_task_status("parent-4", "done", agent="test") + bb.update_task_status("parent-4", "reviewing", agent="daemon") + + # reviewing → working(继续下一轮) + result = bb.update_task_status("parent-4", "working", agent="daemon") + assert result is True + + task = bb.get_task("parent-4") + assert task.status == "working"