aps-agent/tests/golden/test_sop_rules.py

80 lines
3.4 KiB
Python

# ============================================================
# IND-02 SOP→约束规则包黄金测试
# ============================================================
from __future__ import annotations
from server.aps_domain.changeover import lookup_setup_minutes
from server.aps_domain.constraints import get_constraint, is_enabled
from server.aps_domain.sop_rules import (
apply_sop_pack,
compile_sop_by_asset,
compile_sop_by_query,
compile_sop_asset,
confirmation_for_sop_apply,
sop_as_block,
)
from server.knowledge import get_knowledge
from server.state.seed import seed_world
def test_compile_changeover_sop():
kb = get_knowledge()
asset = next(a for a in kb.assets if a.get("title") == "换线标准SOP")
pack = compile_sop_asset(asset)
assert pack["effects"]
ops = {e["op"] for e in pack["effects"]}
assert "constraint.set" in ops
assert "changeover.policy" in ops
cross = next(e for e in pack["effects"] if e["op"] == "changeover.policy")
assert cross["defaultCrossFamilyMin"] == 60
assert cross.get("noChangeoverAfter") == "16:00"
assert "换型" in pack["plannerSummary"]
assert "C10_changeover" not in pack["plannerSummary"]
assert "soft" not in pack["plannerSummary"]
title, lines = confirmation_for_sop_apply(pack)
confirmation_text = "\n".join(lines)
assert "应用作业标准" in title
assert "C10_changeover" not in confirmation_text
assert "changeover.policy" not in confirmation_text
assert "P2" not in confirmation_text
markdown = sop_as_block(pack).props["markdown"]
assert "作业标准规则" in sop_as_block(pack).props["title"]
assert "changeover.policy" not in markdown
assert "C13_sop" not in markdown
def test_compile_by_asset_and_apply():
world = seed_world()
asset = next(a for a in get_knowledge().assets if a.get("title") == "换线标准SOP")
compiled = compile_sop_by_asset(get_knowledge().assets, asset["assetId"])
assert compiled["ok"]
pack = compiled["pack"]
before_cross = lookup_setup_minutes(world, "CTRL", "PDU") # 无矩阵时用默认
applied = apply_sop_pack(world, pack)
assert "constraint:C10_changeover" in applied["applied"]
assert "changeover.policy" in applied["applied"]
assert is_enabled(world, "C13_sop")
c13 = get_constraint(world, "C13_sop")
assert c13 and c13.get("params", {}).get("sourceTitle") == "换线标准SOP"
assert float((world.get("changeoverPolicy") or {})["defaultCrossFamilyMin"]) == 60
after_cross = lookup_setup_minutes(world, "CTRL", "PDU")
assert after_cross == 60
assert after_cross != before_cross or before_cross == 60
assert len(world.get("rulePacks") or []) == 1
def test_compile_kit_sop():
asset = next(a for a in get_knowledge().assets if a.get("title") == "库存与齐套口径")
compiled = compile_sop_by_asset(get_knowledge().assets, asset["assetId"])
assert compiled["ok"]
ids = [e.get("id") for e in compiled["pack"]["effects"] if e.get("op") == "constraint.set"]
assert "C6_material_kit" in ids
assert "物料不齐套" in compiled["pack"]["plannerSummary"]
assert "C6_material_kit" not in compiled["pack"]["plannerSummary"]
def test_query_shell_requires_explicit_asset_id():
compiled = compile_sop_by_query(get_knowledge().assets, "换线")
assert compiled["ok"] is False
assert "assetId" in compiled["error"]