接续 88dd570,保存 W20–W24 已实现的共享接口、业务入口、迁移、工作台、测试与文档。 W20/W22/W23 保持 in_progress,W21/W24 保持 verified;此提交不宣称方法或规则正式启用、多轮返修、真实角色评测完成。 W25 新增实验、标定、逐调用交付与角色执行及其迁移/测试/索引留在实施工作树,原有私人和旧实现保留项不纳入。 验证:离线 571、前端 33 通过;PG 469 项通过、2 项浏览器未启用,2 项误带入的 W25 用例已移出本提交;最终任务与交付边界 37 项通过。make 检查、最终类型、84 项资源及 diff 检查通过。未重跑浏览器或 Pi 宿主,不以合成调用认证外部模型效果。 独立整体审查四维通过;证据保存在 R2-20260909/提交W20-W24。
97 lines
4.3 KiB
Python
97 lines
4.3 KiB
Python
"""真实PG规则版本与诊断报告;当前正文、候选预览和不可变历史分别验证。"""
|
||
|
||
from copy import deepcopy
|
||
from dataclasses import replace
|
||
|
||
import pytest
|
||
from psycopg import OperationalError
|
||
|
||
from muse.作品规划.接口 import 档案保存
|
||
from muse.审校修订.接口 import 审校错误, 读取内置规则
|
||
from muse.正文写作.接口 import 文本节点, 正文草稿, 段落
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
|
||
|
||
@pytest.fixture
|
||
def 诊断环境(章后环境):
|
||
app, 身份 = 章后环境["装配"], 章后环境["作者"]
|
||
svc = app.要求作品()
|
||
结构 = svc.新档案结构(身份, "diagnosis-work", "work_core", 1)
|
||
svc.保存档案(
|
||
身份, "diagnosis-work", 档案保存("diagnosis-work", 0, {"名称": "合成诊断作品"}, 结构)
|
||
)
|
||
svc.添加章节(身份, "diagnosis-ch", "diagnosis-work", "diagnosis-ch", "诊断章", 预期目录版本=0)
|
||
app.要求正文().保存人工(
|
||
身份,
|
||
"diag-text",
|
||
"diagnosis-ch",
|
||
0,
|
||
正文草稿((段落("p1", (文本节点("值得注意的是,窗外正在下雨。"),)),)),
|
||
)
|
||
doc = app.要求正文().读取正文(身份, "diagnosis-ch")
|
||
target = {
|
||
"work_id": "diagnosis-work",
|
||
"chapter_id": "diagnosis-ch",
|
||
"revision": doc["revision"],
|
||
"document_hash": doc["document_hash"],
|
||
"branch_id": "main",
|
||
}
|
||
return app, 身份, target
|
||
|
||
|
||
def test_规则候选幂等新版追加与旧版拒绝覆盖__229001(诊断环境):
|
||
app, 身份, _ = 诊断环境
|
||
svc = app.要求审校()
|
||
预览 = svc.导入规则候选(身份, 预览=True)
|
||
assert not 预览["persisted"] and svc.读取规则库(身份, 预览候选=True)["rules"] == {}
|
||
一 = svc.导入规则候选(身份)
|
||
二 = svc.导入规则候选(身份)
|
||
assert len(一["results"]) == 26 and all(r["duplicate"] for r in 二["results"])
|
||
assert svc.读取规则库(身份)["rules"] == {}
|
||
assert svc.读取规则库(身份, 预览候选=True)["fingerprint"] == 读取内置规则()["fingerprint"]
|
||
库 = deepcopy(读取内置规则())
|
||
库["rules"]["l002"]["fix_hint"] = "保持并询问功能"
|
||
with pytest.raises(审校错误, match="递增版本"):
|
||
svc.导入规则候选(身份, 规则库=库)
|
||
库["rules"]["l002"]["version"] += 1
|
||
svc.导入规则候选(身份, 规则库=库)
|
||
assert svc.读取规则库(身份, 预览候选=True)["rules"]["l002"]["version"] == 2
|
||
with app.要求数据库().连接(只读=True) as conn:
|
||
assert conn.execute("SELECT count(*) FROM muse_rule_version").fetchone()[0] == 27
|
||
|
||
|
||
def test_正式零命中与候选预览真实报告及过期__229002(诊断环境):
|
||
app, 身份, target = 诊断环境
|
||
svc = app.要求审校()
|
||
svc.导入规则候选(身份)
|
||
报告 = svc.生成诊断(身份, target)
|
||
assert 报告["report"]["findings"] == [] and 报告["report"]["mode"] == "active"
|
||
assert 报告 == svc.生成诊断(身份, target)
|
||
预览 = svc.生成诊断(身份, target, 预览候选=True)
|
||
assert 预览["report"]["findings"] and 预览["report"]["mode"] == "candidate_preview"
|
||
assert not svc.读取诊断(身份, 预览["diagnosis_id"])["stale"]
|
||
app.要求正文().保存人工(
|
||
身份, "diag-text-new", "diagnosis-ch", 1, 正文草稿((段落("p1", (文本节点("雨停了。"),)),))
|
||
)
|
||
历史 = svc.读取诊断(身份, 预览["diagnosis_id"])
|
||
assert 历史["stale"] and 历史["report"] == 预览["report"]
|
||
with pytest.raises(审校错误):
|
||
svc.生成诊断(身份, target, 预览候选=True)
|
||
with pytest.raises(审校错误):
|
||
svc.读取诊断(replace(身份, 作者="另一作者"), 预览["diagnosis_id"])
|
||
assert app.要求正文().读取正文(身份, "diagnosis-ch")["visible_text"] == "雨停了。"
|
||
|
||
|
||
def test_数据库缺规则或篡改不退回种子__229003(诊断环境, monkeypatch):
|
||
app, 身份, target = 诊断环境
|
||
svc = app.要求审校()
|
||
assert svc.生成诊断(身份, target, 预览候选=True)["report"]["executed_rules"] == []
|
||
|
||
def 断库(*args, **kwargs):
|
||
raise OperationalError("合成数据库不可用")
|
||
|
||
monkeypatch.setattr(type(svc.数据库), "连接", 断库)
|
||
with pytest.raises(OperationalError):
|
||
svc.读取规则库(身份, 预览候选=True)
|