实现侧: - 上下文:任务范围拆分为 范围校验/范围授权;索引按可发现口径重建、索引新鲜度改对称差;依赖校验统一快照漂移说明。 - 知识方法:方法与材料读取口径统一;超限方法材料按可选省略,核对路径不再二次计费;删除无合同的读时重算。 - 任务运行:新增 context.usage/tool.denied 事件类型;连接池常驻并在装配生命周期内开关;调用结算与核对分列。 - 效果评测/审校修订/交付连载/作者经验/作品规划:凭据冻结、标定消费、导出补证、事实引文核对等收尾修复。 - 资源加载:能力正文不再夹带索引用的导航注记(该注记此前进入角色与技能的模型提示)。 - 元数据:受保护骨架与代码保护属性对齐;字段校验与内置结构口径同步。 - 基础设施:环境预检进入装配生命周期;数据库连接运行期字段不参与相等比较;索引指纹归一化 jsonb 浮点。 - 删除被替代实现:7 份旧提示词模板与空壳 资料来源 读取器。 用例侧: - 用例身份与导航元信息迁移;夹具补生命周期、同库暴露与模板封存; - 本轮定向修复:方法材料省略、事实引文、迁移回执、额度与暂停用例、慢用例超时预算等。
188 lines
7.7 KiB
Python
188 lines
7.7 KiB
Python
"""原诊断样例经新版公开函数和真实离线CLI承接;预览不代表已启用。"""
|
||
|
||
import hashlib
|
||
import json
|
||
import re
|
||
import subprocess
|
||
import sys
|
||
|
||
import pytest
|
||
|
||
from muse.审校修订.接口 import 审校错误, 诊断文本, 读取内置规则
|
||
|
||
# 原测试的完整合成字面量,三个独立触发均保留。
|
||
原文 = (
|
||
"研究表明,能进这种地方的修士都不简单。"
|
||
"值得注意的是,门外已经下起了雨。"
|
||
"他嘴角微微上扬,没有说话。"
|
||
)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-5859aab495bc",
|
||
environment="离线公开函数与真实安装模块CLI;不用数据库或外部模型",
|
||
when="校验输入并运行诊断或消费结构化发现。",
|
||
contract="docs/系统架构/新版设计/功能规格/P04-声音诊断与受控修订.md",
|
||
)
|
||
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"]
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-4bc4c9fab12b",
|
||
environment="离线公开函数与真实安装模块CLI;不用数据库或外部模型",
|
||
when="校验输入并运行诊断或消费结构化发现。",
|
||
contract="docs/系统架构/新版设计/功能规格/P04-声音诊断与受控修订.md",
|
||
)
|
||
def test_缺少作品身份明确拒绝诊断__4bc4c9():
|
||
with pytest.raises(审校错误, match="作品"):
|
||
诊断文本(原文, work_id="", 规则库=读取内置规则(), 预览候选=True)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-413b70b2a7e1",
|
||
environment="离线公开函数与真实安装模块CLI;不用数据库或外部模型",
|
||
when="校验输入并运行诊断或消费结构化发现。",
|
||
contract="docs/系统架构/新版设计/功能规格/P04-声音诊断与受控修订.md",
|
||
)
|
||
def test_空正文不生成诊断产物__413b70():
|
||
with pytest.raises(审校错误, match="非空全文"):
|
||
诊断文本("", work_id="synthetic:demo", 规则库=读取内置规则(), 预览候选=True)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-c930dbdc9939",
|
||
environment="离线公开函数与真实安装模块CLI;不用数据库或外部模型",
|
||
when="校验输入并运行诊断或消费结构化发现。",
|
||
contract="docs/系统架构/新版设计/功能规格/P04-声音诊断与受控修订.md",
|
||
)
|
||
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,
|
||
)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-94b4208516c2",
|
||
environment="离线公开函数与真实安装模块CLI;不用数据库或外部模型",
|
||
when="校验输入并运行诊断或消费结构化发现。",
|
||
contract="docs/系统架构/新版设计/功能规格/P04-声音诊断与受控修订.md",
|
||
)
|
||
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"]
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-a8f13e8120e9",
|
||
environment="离线公开函数与真实安装模块CLI;不用数据库或外部模型",
|
||
when="校验输入并运行诊断或消费结构化发现。",
|
||
contract="docs/系统架构/新版设计/功能规格/P04-声音诊断与受控修订.md",
|
||
)
|
||
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()
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-diagnose-missing-work-ref-role_agent",
|
||
environment="离线诊断前置合同;不请求数据库或模型",
|
||
given="行为场景 missing-work-ref 的固定原文,没有作品身份",
|
||
when="调用实际诊断入口,任何数据库连接或模型执行均被拒绝哨兵阻断",
|
||
then=["返回 REVIEW_INVALID 缺作品身份错误", "数据库和模型调用次数均为0"],
|
||
contract="docs/系统架构/新版设计/验证设计/诊断行为场景.md",
|
||
)
|
||
def test_缺作品场景在离线前置拒绝__c0e103(monkeypatch):
|
||
from pathlib import Path
|
||
|
||
from muse.效果评测.接口 import 载入行为场景
|
||
|
||
场景 = next(
|
||
条
|
||
for 条 in 载入行为场景(
|
||
(Path(__file__).parents[1] / "夹具/行为评测/诊断机器味场景.json").read_text()
|
||
)
|
||
if 条.scenario_id == "missing-work-ref"
|
||
)
|
||
调用 = []
|
||
|
||
def 不应连接(*args, **kwargs):
|
||
调用.append("数据库")
|
||
raise AssertionError("前置拒绝不应连接数据库")
|
||
|
||
async def 不应调用模型(*args, **kwargs):
|
||
调用.append("模型")
|
||
raise AssertionError("前置拒绝不应调用模型")
|
||
|
||
monkeypatch.setattr("psycopg.connect", 不应连接)
|
||
monkeypatch.setattr("muse.任务运行.模型调用.模型执行器.执行", 不应调用模型)
|
||
monkeypatch.setattr("muse.任务运行.模型调用.模型执行器.执行回合", 不应调用模型)
|
||
assert 场景.work_ref is None and 场景.expected == "missing_work"
|
||
with pytest.raises(审校错误, match="作品") as 错误:
|
||
诊断文本(场景.text, work_id="", 规则库={}, 预览候选=True)
|
||
assert 错误.value.呈现()["code"] == "REVIEW_INVALID"
|
||
assert 调用 == []
|