aps-agent/tests/golden/test_plan_transition.py

74 lines
3.3 KiB
Python
Raw Normal View History

# ============================================================
# Plan 批准/驳回审计黄金测试(plan.md §3.1 / 矩阵 110 行剩余项)
# 覆盖:DRAFT->APPROVED 批准(追加版本、regenCount 不变、证据引用)、
# DRAFT->FAILED 驳回、非法流转拒绝、历史不可变。
# ============================================================
from __future__ import annotations
from pathlib import Path
import pytest
from server.agent_core.plan_runtime import (
PlanStore,
PlanTransitionError,
)
def _store(tmp_path: Path) -> PlanStore:
return PlanStore(str(tmp_path / "plans.json"))
def test_approve_appends_status_version(tmp_path: Path):
"""批准:DRAFT->APPROVED 追加新版本,regenCount 不变,证据引用记录 status。"""
store = _store(tmp_path)
plan = store.create(plan_id="p-approve", layer="L0", parent_id=None,
inputs={"prompt": "x"}, payload={"goal": "g"})
assert plan.status == "DRAFT" and plan.version == 1 and plan.regenCount == 0
approved = store.transition_status("p-approve", new_status="APPROVED",
created_by="USER", note="计划员批准")
assert approved.status == "APPROVED"
assert approved.version == 2
assert approved.regenCount == 0 # 状态流转不消耗重生额度
assert approved.evidenceRefs[-1] == "status:APPROVED"
# 历史不可变:v1 仍为 DRAFT
assert store.node_at("p-approve", 1).status == "DRAFT"
def test_reject_appends_failed_version(tmp_path: Path):
"""驳回:DRAFT->FAILED 追加新版本,携带 note 入 payload。"""
store = _store(tmp_path)
store.create(plan_id="p-reject", layer="L0", parent_id=None,
inputs={"prompt": "x"}, payload={"goal": "g"})
rejected = store.transition_status("p-reject", new_status="FAILED",
created_by="USER", note="驳回:数据不足")
assert rejected.status == "FAILED"
assert rejected.version == 2
assert rejected.payload["_note"][-1]["status"] == "FAILED"
assert rejected.payload["_note"][-1]["note"] == "驳回:数据不足"
def test_illegal_transition_rejected(tmp_path: Path):
"""非法流转:APPROVED->DRAFT 必须拒绝(PlanTransitionError)。"""
store = _store(tmp_path)
store.create(plan_id="p-illegal", layer="L0", parent_id=None,
inputs={"prompt": "x"}, payload={"goal": "g"})
store.transition_status("p-illegal", new_status="APPROVED")
with pytest.raises(PlanTransitionError):
store.transition_status("p-illegal", new_status="DRAFT")
def test_transition_chain_approve_then_done(tmp_path: Path):
"""连续流转:DRAFT->APPROVED->DONE 合法,每步追加版本且历史不变量保持。"""
store = _store(tmp_path)
store.create(plan_id="p-chain", layer="L0", parent_id=None,
inputs={"prompt": "x"}, payload={"goal": "g"})
store.transition_status("p-chain", new_status="APPROVED")
done = store.transition_status("p-chain", new_status="DONE")
assert done.status == "DONE"
assert done.version == 3
versions = store.versions("p-chain")
assert [v.status for v in versions] == ["DRAFT", "APPROVED", "DONE"]
assert [v.regenCount for v in versions] == [0, 0, 0]