muse-agent-example/tests/契约/test_诊断入口原观察.py
zizi 9e6f1c4481 R2 改造交付:新版模块化单体全量成果
- src/muse 新版全模块(装配/共享/上下文/任务运行/作品规划/故事世界/正文写作/审校修订/知识方法/作者经验/效果评测/交付连载/资料研究/正式变更/元数据/接入/基础设施/编排)+ 测试树(单元/契约/集成/架构/迁移/端到端/夹具)
- 129 项功能全部实现与自动验证(功能覆盖.json/矩阵),含 W31 补齐的规则与代价/节奏安排/伏笔与承诺
- 旧实现按处置清单退出(702 条中 324 删,保护合同与未迁移条目留存有据);web/app.py 旧工作台退役,新工作台为唯一写入口
- 数据库/旧库迁移:真实旧库内容批次迁移链(端点守卫/PG作品正文映射/质量资产缺省投影)
- 运行手册 docs/运行手册.md;W30 本机服务阶段一已运行(infra PG 为正式内容权威)
- R2 执行证据与私有运行材料在 .agents.local/改造/R2-20260909/(不入库)
2026-09-15 12:47:42 +08:00

112 lines
4.2 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.

"""原诊断样例经新版公开函数和真实离线CLI承接;预览不代表已启用。"""
import hashlib
import json
import re
import subprocess
import sys
import pytest
from muse.审校修订.接口 import 审校错误, 诊断文本, 读取内置规则
# 原测试的完整合成字面量,三个独立触发均保留。
原文 = (
"研究表明,能进这种地方的修士都不简单。"
"值得注意的是,门外已经下起了雨。"
"他嘴角微微上扬,没有说话。"
)
def test_原样例完整诊断保留三个触发与原文定位__5859aa():
report = 诊断文本(原文, work_id="synthetic:demo", 规则库=读取内置规则(), 预览候选=True)
assert {"text_hash", "rule_library_version", "mode", "findings"} <= report.keys()
assert {"l001", "l002", "l003"} <= {item["rule_id"] for item in report["findings"]}
for item in report["findings"]:
assert item["decision_proposal"] in {"repair", "ask"}
assert item["spans"][0] in 原文
assert item["quote"] == 原文[item["start"] : item["end"]]
assert report["text_hash"] == hashlib.sha256(原文.encode()).hexdigest()
assert report["coverage"]["deterministic"] == [[0, len(原文)]]
assert report["mode"] == "candidate_preview" and not report["persisted"]
def test_缺少作品身份明确拒绝诊断__4bc4c9():
with pytest.raises(审校错误, match="作品"):
诊断文本(原文, work_id="", 规则库=读取内置规则(), 预览候选=True)
def test_空正文不生成诊断产物__413b70():
with pytest.raises(审校错误, match="非空全文"):
诊断文本("", work_id="synthetic:demo", 规则库=读取内置规则(), 预览候选=True)
def test_规则库指纹稳定且随完整发布内容确定__c930db():
first, second = 读取内置规则(), 读取内置规则()
assert first["fingerprint"] == second["fingerprint"]
# 新合同使用完整SHA256,旧v-展示前缀不再作为版本身份。
assert re.fullmatch(r"[0-9a-f]{64}", first["fingerprint"])
report = 诊断文本(原文, work_id="synthetic:demo", 规则库=first, 预览候选=True)
assert report["rule_library_version"] == first["fingerprint"]
def _离线CLI(tmp_path, request):
source = tmp_path / "诊断输入.json"
source.write_text(json.dumps(request, ensure_ascii=False))
return subprocess.run(
[
sys.executable,
"-I",
"-m",
"muse",
"审校",
str(tmp_path / "不存在的数据库配置.toml"),
"诊断",
str(source),
"--离线",
],
cwd=tmp_path,
capture_output=True,
text=True,
timeout=20,
)
def test_真实离线CLI无需数据库配置输出完整产物__94b420(tmp_path):
process = _离线CLI(tmp_path, {"text": 原文, "work_id": "synthetic:demo"})
assert process.returncode == 0, process.stderr
report = json.loads(process.stdout)
assert report["findings"] and report["persisted"] is False
assert report["text_hash"] == hashlib.sha256(原文.encode()).hexdigest()
assert report["coverage"]["text_length"] == len(原文)
assert [p.name for p in tmp_path.iterdir()] == ["诊断输入.json"]
def test_外部错版发现不能从离线CLI进入诊断__a8f13e(tmp_path):
process = _离线CLI(
tmp_path,
{
"text": 原文,
"work_id": "synthetic:demo",
"external_findings": [
{
"id": "x1",
"text_hash": "sha256:deadbeef",
"rule_id": "sem001",
"rule_version": 1,
"spans": ["他"],
"context_window": "他",
"layer": "semantic",
"evidence": "外部判定证据",
"possible_function": "none",
"confidence": "medium",
"decision_proposal": "pending",
}
],
},
)
# 统一CLI中2表示参数用法错误,合法命令的内容合同拒绝使用业务失败码1。
assert process.returncode == 1
assert "不接受外部发现" in process.stderr
assert not process.stdout.strip()