muse-agent-example/tests/skills/prevent-ai-flavor/test_prevent_ai_flavor.py
zizi 091b66a9bb 重构: 收敛 Agent/Skill 运行时与创作质量闭环
将角色与 Skill 从 .claude 迁入 .agent,移除 Claude CLI 运行时并接入固定 Opus 角色 profile、完整 schema、预算 deadline、raw 与回执证据链。

同步拆分 Skill 职责、复利 lesson、Gate 回放、Dashboard 人审入口、数据库登记和机械门禁;候选设计正文不包含在本提交中。
2026-08-22 02:12:32 +08:00

98 lines
4.8 KiB
Python
Raw 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.

#!/usr/bin/env python3
"""技能 2 前置预防离线测试:负约束只取 active 规则、声音账投影、串作品拒绝。"""
import pathlib
import sys
import unittest
from unittest.mock import patch
PROJECT_ROOT = pathlib.Path(__file__).resolve().parents[3]
SCRIPT_DIR = PROJECT_ROOT / ".agent" / "skills" / "prevent-ai-flavor" / "scripts"
sys.path.insert(0, str(SCRIPT_DIR))
import prevent_ai_flavor as prev # noqa: E402
LEDGER = {
"schema_version": "voice-baseline-v1",
"work_ref": "synthetic:demo",
"narrator": {"sentence_habits": ["短句收束"], "punctuation_habits": ["少用感叹号"]},
"characters": {"老周": {"verbal_tics": ["我说小子"], "sample_lines": ["我说小子,茶要凉了。"]}},
"untouchable_verbal_tics": {"老周": ["我说小子"]},
"protected_spans": ["青云城的雨说来就来"],
"blacklist": ["值得注意的是"],
}
class PreventionContractTest(unittest.TestCase):
def test_contract_without_ledger_still_valid(self):
contract = prev.build_prevention_contract("synthetic:demo")
self.assertEqual(contract["schema_version"], "ai-flavor-prevention-v2")
self.assertGreaterEqual(len(contract["negative_constraints"]), 10)
self.assertEqual(contract["positive_samples"], [])
self.assertIsNone(contract["built_from"]["voice_ledger_sha256"])
for item in contract["negative_constraints"]:
self.assertTrue(item["avoid_examples"], item["rule_id"])
self.assertIn("keep_examples", item)
self.assertIn("boundary_examples", item)
self.assertIn("regression_traps", item)
def test_ledger_projects_positive_samples_and_blacklist(self):
contract = prev.build_prevention_contract("synthetic:demo", voice_ledger=LEDGER)
kinds = {(p["kind"], p["text"]) for p in contract["positive_samples"]}
self.assertIn(("verbal_tic", "我说小子"), kinds)
self.assertIn(("voice_sample", "我说小子,茶要凉了。"), kinds)
self.assertIn(("narrator_habit", "短句收束"), kinds)
self.assertEqual(contract["blacklist"], ["值得注意的是"])
self.assertEqual(contract["protected_spans"], ["青云城的雨说来就来"])
self.assertTrue(any("黑名单表达式" in item for item in prev.render_writer_constraints(contract)))
self.assertIsNotNone(contract["built_from"]["voice_ledger_sha256"])
def test_work_ref_mismatch_is_rejected(self):
with self.assertRaisesRegex(prev.PreventionContractError, "不一致"):
prev.build_prevention_contract("synthetic:other", voice_ledger=LEDGER)
def test_candidate_ledger_is_rejected_even_in_offline_projection(self):
bad = dict(LEDGER, status="candidate")
with self.assertRaisesRegex(prev.PreventionContractError, "canonical"):
prev.build_prevention_contract("synthetic:demo", voice_ledger=bad)
def test_bad_schema_version_is_rejected(self):
bad = dict(LEDGER, schema_version="nope")
with self.assertRaisesRegex(prev.PreventionContractError, "schema_version"):
prev.build_prevention_contract("synthetic:demo", voice_ledger=bad)
def test_cli_default_persists_run(self):
# 默认(非 --offline)模式生产读数据库规则库;离线测试补丁文件库接缝,不触真实连接。
import argparse # noqa: F401 (确认 CLI 依赖可导入)
import tempfile
import json
from deai import load
def _file_library(load_database):
samples = load.load_samples()
rules = load.load_rules(samples=samples)
return samples, rules, prev.rule_library_version(rules), "database"
with tempfile.TemporaryDirectory() as tmp:
output = pathlib.Path(tmp) / "contract.json"
with patch.object(prev, "persist_prevention", return_value={"run_id": "prev-x"}) as persist, \
patch.object(prev, "_load_db_ledger", return_value=None), \
patch.object(prev, "load_runtime_library", side_effect=_file_library):
code = prev.main(["--work-ref", "synthetic:demo", "--output", str(output)])
self.assertEqual(code, 0)
persist.assert_called_once()
contract = json.loads(output.read_text(encoding="utf-8"))
self.assertEqual(contract["work_ref"], "synthetic:demo")
def test_cli_offline_skips_db(self):
import tempfile
with tempfile.TemporaryDirectory() as tmp:
output = pathlib.Path(tmp) / "contract.json"
with patch.object(prev, "persist_prevention") as persist:
code = prev.main(["--work-ref", "synthetic:demo", "--output", str(output), "--offline"])
self.assertEqual(code, 0)
persist.assert_not_called()
if __name__ == "__main__":
unittest.main()