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