"""空规则覆盖、触发依据和同事务读取的独立边界;只用合成输入。""" from copy import deepcopy from types import SimpleNamespace from uuid import UUID import pytest from pydantic import ValidationError from muse.审校修订 import 持久返修 from muse.审校修订.持久返修 import 返修比较定位 from muse.审校修订.接口 import 读取必需检查结论于 from muse.审校修订.机器味规则 import 核对规则, 核对规则库, 读取内置规则 from muse.审校修订.机器味诊断 import 诊断文本 from muse.审校修订.模型 import 审校错误 from muse.审校修订.返修策略 import 选择返修 from muse.正式变更.接口 import 固定哈希 def _规则库(触发: dict, *, active=True): 库 = 读取内置规则() 规则 = deepcopy(库["rules"]["l002"]) 规则["trigger"] = 触发 规则["status"] = "active" if active else "candidate" return 核对规则库([规则], list(库["samples"].values())) @pytest.mark.case_id("NC-o03-b06-0001") def test_空库不得声称已执行全文规则覆盖__b06001(): 文本 = "这是合成诊断输入。" 报告 = 诊断文本(文本, work_id="synthetic", 规则库=核对规则库([], [])) assert 报告["mode"] == "active" assert 报告["rule_count"] == 0 and 报告["empty_library"] is True assert 报告["findings"] == 报告["executed_rules"] == 报告["unreviewed_rules"] == [] assert 报告["coverage"] == { "deterministic": [], "text_length": len(文本), "rules_executed": 0, } @pytest.mark.case_id("NC-o03-b06-0002") def test_有效规则零命中仍区别于空库__b06002(): 文本 = "这是合成诊断输入。" 报告 = 诊断文本( 文本, work_id="synthetic", 规则库=_规则库({"type": "regex", "pattern": "不可能命中"}) ) assert 报告["findings"] == [] assert 报告["rule_count"] == 1 and 报告["empty_library"] is False assert 报告["executed_rules"] == ["l002"] assert 报告["coverage"]["deterministic"] == [[0, len(文本)]] assert 报告["coverage"]["rules_executed"] == 1 @pytest.mark.case_id("NC-o03-b06-0003") def test_只有语义规则未审不计确定性覆盖__b06003(): 报告 = 诊断文本( "这是合成诊断输入。", work_id="synthetic", 规则库=_规则库({"type": "model_judgment", "criteria": "需要受控语义证据"}), ) assert 报告["rule_count"] == 1 and 报告["empty_library"] is False assert 报告["coverage"]["deterministic"] == [] assert 报告["coverage"]["rules_executed"] == 0 assert 报告["unreviewed_rules"] == [{"rule_id": "l002", "reason": "缺少受控语义交付"}] @pytest.mark.case_id("NC-o03-b06-0004") def test_候选规则不充当已激活覆盖__b06004(): 库 = _规则库({"type": "regex", "pattern": "合成"}, active=False) 正式 = 诊断文本("这是合成诊断输入。", work_id="synthetic", 规则库=库) 预览 = 诊断文本("这是合成诊断输入。", work_id="synthetic", 规则库=库, 预览候选=True) assert 正式["empty_library"] is True and 正式["coverage"]["deterministic"] == [] assert 预览["rule_count"] == 1 and 预览["empty_library"] is False assert 预览["mode"] == "candidate_preview" and 预览["findings"] assert 库["rules"]["l002"]["status"] == "candidate" @pytest.mark.case_id("NC-o03-b06-0005") @pytest.mark.parametrize( "触发", [ {"type": "regex", "pattern": "合成"}, {"type": "density", "pattern": "合成", "window_chars": 50, "min_hits": 2}, {"type": "handler", "handler": "short_sentence_run"}, {"type": "handler", "handler": "repeated_sentence_start"}, {"type": "handler", "handler": "camera_action_list", "pattern": "走|停"}, {"type": "handler", "handler": "uniform_paragraph_length"}, {"type": "model_judgment", "criteria": "需要受控语义证据"}, ], ids=["regex", "density", "short", "repeat", "camera", "uniform", "semantic"], ) def test_四类有效触发依据保留规范载荷__b06005(触发): 库 = _规则库(触发) 规范 = 库["rules"]["l002"]["trigger"] 期望 = { "type": 触发["type"], "pattern": None, "criteria": None, "handler": None, "max_chars": 8, "min_run": 4, "window_chars": 500, "min_hits": 3, "tolerance": 15, **触发, } assert 规范 == 期望 assert 核对规则(库["rules"]["l002"], 库["samples"]) == 库["rules"]["l002"] @pytest.mark.case_id("NC-o03-b06-0006") @pytest.mark.parametrize( "触发", [ {"type": "regex"}, {"type": "regex", "pattern": "["}, {"type": "regex", "pattern": "合成", "criteria": "不应混用"}, {"type": "density", "pattern": "合成", "handler": "short_sentence_run"}, {"type": "handler"}, {"type": "handler", "handler": "camera_action_list"}, {"type": "handler", "handler": "short_sentence_run", "pattern": "不被消费"}, {"type": "handler", "handler": "uniform_paragraph_length", "criteria": "不应混用"}, {"type": "model_judgment", "criteria": " "}, {"type": "model_judgment", "criteria": "语义判据", "pattern": "不应混用"}, ], ids=[ "missing-pattern", "bad-regex", "regex-criteria", "density-handler", "missing-handler", "camera-pattern", "unused-pattern", "handler-criteria", "blank-criteria", "semantic-pattern", ], ) def test_非法或互斥触发依据由owner拒绝__b06006(触发): with pytest.raises(审校错误, match="规则或四类例证不完整"): _规则库(触发) @pytest.mark.case_id("NC-o03-b06-0007") @pytest.mark.parametrize("判定", [None, "passed", "failed"], ids=["missing", "passed", "failed"]) def test_必需检查按确切候选版本沿用调用连接__b06007(判定): class 连接: def __init__(self): self.调用 = [] def execute(self, sql, params): self.调用.append((sql, params)) return SimpleNamespace(fetchone=lambda: None if 判定 is None else (判定,)) 连 = 连接() assert 读取必需检查结论于(连, "synthetic-candidate", 7) == 判定 assert 连.调用 == [ ( "SELECT verdict FROM muse_review_report " "WHERE candidate_id=%s AND candidate_revision=%s", ("synthetic-candidate", 7), ) ] def _返修轮次(): 候选ID = "00000000-0000-4000-8000-000000000002" 定位 = 返修比较定位( session_id=UUID("00000000-0000-4000-8000-000000000001"), round=1, candidate_id=UUID(候选ID), ) 结果 = { "candidate_id": 候选ID, "outcome": "candidate", "source_kind": "selection", "diagnosis_id": None, } 轮 = { "round_number": 1, "task_id": "synthetic-task", "outcome": "candidate", "candidate_id": 候选ID, "result": 结果, "result_hash": 固定哈希(结果), } return {"source_kind": "selection", "rounds": [轮]}, 定位 @pytest.mark.case_id("NC-o03-b06-0008") @pytest.mark.parametrize( "坏处,说明", [ ("none", None), ("wrong-candidate", "同一模型候选"), ("missing-task", "同一模型候选"), ("stale-hash", "结果哈希"), ("wrong-source", "来源类型"), ], ) def test_比较轮次独立校验保留拒绝原因__b06008(坏处, 说明): 会话, 定位 = _返修轮次() 轮 = 会话["rounds"][0] if 坏处 == "wrong-candidate": 轮["candidate_id"] = "other" elif 坏处 == "missing-task": 轮["task_id"] = None elif 坏处 == "stale-hash": 轮["result_hash"] = "0" * 64 elif 坏处 == "wrong-source": 轮["result"]["source_kind"] = "diagnosis" 轮["result_hash"] = 固定哈希(轮["result"]) if 说明 is None: assert 持久返修._核对比较轮次(会话, 定位) is 轮 else: with pytest.raises(审校错误, match=说明): 持久返修._核对比较轮次(会话, 定位) @pytest.mark.case_id("NC-o03-b06-0009") @pytest.mark.parametrize("坏处", ["none", "missing", "wrong-candidate", "failed", "false-gate"]) def test_比较报告不以引用代替保真证据__b06009(坏处): 报告 = {"candidate_id": "candidate", "verdict": "passed", "snapshot_id": "snapshot"} 结果 = {"snapshot_id": "snapshot", "checks": {"mechanical_pass": True}} if 坏处 == "missing": 报告 = None elif 坏处 == "wrong-candidate": 报告["candidate_id"] = "other" elif 坏处 == "failed": 报告["verdict"] = "failed" elif 坏处 == "false-gate": 结果["checks"]["mechanical_pass"] = False if 坏处 == "none": assert 持久返修._核对比较报告(报告, {"verdict": "passed"}, "candidate", 结果) is 报告 else: with pytest.raises(审校错误, match="保真结果"): 持久返修._核对比较报告(报告, {"verdict": "passed"}, "candidate", 结果) @pytest.mark.case_id("NC-o03-b06-0010") def test_同事务比较读取不另建连接__b0600a(monkeypatch): 连, 运行, 结果 = object(), object(), object() _, 定位 = _返修轮次() 调用 = [] def 核验(连接, 服务, 作者, 位置): 调用.append((连接, 服务, 作者, 位置)) return 结果 monkeypatch.setattr(持久返修, "_读取返修比较来源于", 核验) assert 持久返修.读取返修比较来源于(连, 运行, "author", 定位) is 结果 assert 调用 == [(连, 运行, "author", 定位)] @pytest.mark.case_id("NC-o03-b06-0011") def test_有限返修公开合同仍以五轮为界__b0600b(): assert 选择返修(已用轮数=5, 最大轮数=5, 硬门通过=True, 有修改=True)["code"] == "round_limit" with pytest.raises(审校错误, match="最多5轮"): 选择返修(已用轮数=5, 最大轮数=6, 硬门通过=True, 有修改=True) _, 定位 = _返修轮次() with pytest.raises(ValidationError): 返修比较定位(**{**定位.model_dump(), "round": 6})