aps-agent/tests/golden/test_plan_transition.py

74 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# 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]