muse-agent-example/tests/迁移/test_质量资产迁移.py
zizi d909d1bd1b 后端实现与用例身份:19 包集成落地并修复收尾缺陷
实现侧:
- 上下文:任务范围拆分为 范围校验/范围授权;索引按可发现口径重建、索引新鲜度改对称差;依赖校验统一快照漂移说明。
- 知识方法:方法与材料读取口径统一;超限方法材料按可选省略,核对路径不再二次计费;删除无合同的读时重算。
- 任务运行:新增 context.usage/tool.denied 事件类型;连接池常驻并在装配生命周期内开关;调用结算与核对分列。
- 效果评测/审校修订/交付连载/作者经验/作品规划:凭据冻结、标定消费、导出补证、事实引文核对等收尾修复。
- 资源加载:能力正文不再夹带索引用的导航注记(该注记此前进入角色与技能的模型提示)。
- 元数据:受保护骨架与代码保护属性对齐;字段校验与内置结构口径同步。
- 基础设施:环境预检进入装配生命周期;数据库连接运行期字段不参与相等比较;索引指纹归一化 jsonb 浮点。
- 删除被替代实现:7 份旧提示词模板与空壳 资料来源 读取器。

用例侧:
- 用例身份与导航元信息迁移;夹具补生命周期、同库暴露与模板封存;
- 本轮定向修复:方法材料省略、事实引文、迁移回执、额度与暂停用例、慢用例超时预算等。
2026-09-18 01:15:00 +08:00

821 lines
35 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.

"""旧规则/质量案例只经B06公开用例迁移,原状态不升格。"""
from __future__ import annotations
import base64
import hashlib
import json
from copy import deepcopy
from types import SimpleNamespace
import psycopg
import pytest
import yaml
from psycopg import sql
from muse.作品规划.接口 import 档案保存
from muse.元数据.接口 import 元数据服务, 导入内置结构
from muse.共享.调用身份 import 内容用途, 用途, 调用身份
from muse.启动 import 构建
from muse.基础设施.数据库.连接 import 数据库工厂
from muse.正文写作.接口 import 文本节点, 正文结构哈希, 正文草稿, 段落
from muse.配置 import 应用配置, 数据库引用
from 导入新库 import 初始化目标, 导入快照
from 建立映射 import 稳定JSON, 旧快照, 映射配置, 迁移错误
from 映射台账 import 迁移台账
from 核对结果 import 核对迁移结果
from 知识记录分流 import 分流批次
from 读取旧文件 import 读取文件集
from 转换业务对象 import 准备目标请求, 提交目标请求
from 转换质量资产 import 准备质量请求, 转换规则库
def _文件快照(路径: str, 值: dict) -> 旧快照:
字节 = yaml.safe_dump(值, allow_unicode=True, sort_keys=False).encode()
哈希 = hashlib.sha256(字节).hexdigest()
return 旧快照.从载荷(
{
"source": {
"system": "file",
"database": '{"dataset":"synthetic-quality-files","scope":"files"}',
"table": "legacy_file",
"id": 路径,
"revision": "snapshot-v1",
},
"record": {
"id": 路径,
"revision": "snapshot-v1",
"relpath": 路径,
"size": len(字节),
"sha256": 哈希,
"content_base64": base64.b64encode(字节).decode(),
},
}
)
def _例证(kind: str) -> dict:
前缀 = {"sf": "sf", "snf": "snf", "boundary": "b", "regression": "reg"}[kind]
return {
"id": f"{前缀}-l002-01",
"type": kind,
"rules": ["l002"],
"carrier": "narration",
"source": "synthetic",
"text": f"{kind}的合成句子。",
"note": f"{kind}的合成说明。",
}
def _规则文件批次():
规则 = {
"id": "l002",
"name": "空洞元话语",
"layer": "lexical",
"carrier_scope": "narration",
"trigger": {"type": "regex", "pattern": "值得注意的是"},
"carve_out": ["评书腔"],
"default_disposition": "candidate",
"function_check": ["是否承担声线功能"],
"fix_hint": "无功能时删除",
"samples": {kind: [_例证(kind)["id"]] for kind in ("sf", "snf", "boundary", "regression")},
"version": 1,
"status": "active",
"evidence": "旧库人工已激活历史",
"case_card_ids": [],
}
主 = _文件快照("rules/l002.yaml", 规则)
例证 = [
_文件快照(f"samples/{kind}.yaml", {"samples": [_例证(kind)]})
for kind in ("sf", "snf", "boundary", "regression")
]
绑定 = [
{
"source_key": 主.source.记录键,
"source_hash": 主.源哈希,
"route": "rule_version",
"author_id": "migration-author",
"sources": [
{
"source_key": s.source.记录键,
"source_hash": s.源哈希,
"sample_ids": [
next(
iter(
yaml.safe_load(base64.b64decode(s.原行["content_base64"]))[
"samples"
]
)
)["id"]
],
"license": "synthetic",
"source_ref": "legacy-file:" + s.source.id,
}
for s in 例证
],
"parameters": {"rule_id": "l002", "version": 1},
},
*[
{
"source_key": s.source.记录键,
"source_hash": s.源哈希,
"route": "rule_example",
"author_id": "migration-author",
"sources": [],
"parameters": {"sample_ids": [例["id"]]},
}
for s, 例 in zip(
例证, [_例证(k) for k in ("sf", "snf", "boundary", "regression")], strict=True
)
],
]
return [主, *例证], 映射配置({"works": [], "quality_bindings": 绑定})
def _PG规则批次():
快照, 映射 = _规则文件批次()
规则 = yaml.safe_load(base64.b64decode(快照[0].原行["content_base64"]))
行 = deepcopy(规则)
行["id"], 行["rule_id"] = 1, 行.pop("id")
行["trigger_json"] = 行.pop("trigger")
行["sample_refs"] = 行.pop("samples")
del 规则["case_card_ids"]
行["payload"] = 规则
行["content_sha256"] = hashlib.sha256(稳定JSON(规则).encode()).hexdigest()
主 = 旧快照.从载荷(
{
"source": {
"system": "pg",
"database": "synthetic-quality-pg",
"table": "example_ai_flavor_rule",
"id": "1",
"revision": "export-v1",
},
"record": 行,
}
)
绑定 = {**映射.质量绑定(快照[0]), "source_key": 主.source.记录键, "source_hash": 主.源哈希}
可用源 = {}
for i, 源绑定 in enumerate(绑定["sources"], start=1):
样例 = yaml.safe_load(base64.b64decode(快照[i].原行["content_base64"]))["samples"][0]
行 = {
**样例,
"id": i,
"sample_id": 样例["id"],
"sample_type": 样例["type"],
"source_license": "synthetic",
"source_ref": "",
"payload": 样例,
"content_sha256": hashlib.sha256(稳定JSON(样例).encode()).hexdigest(),
}
del 行["type"]
源 = 旧快照.从载荷(
{
"source": {
"system": "pg",
"database": "synthetic-quality-pg",
"table": "example_ai_flavor_sample",
"id": str(i),
"revision": "export-v1",
},
"record": 行,
}
)
源绑定.update(
source_key=源.source.记录键,
source_hash=源.源哈希,
source_ref="migration-source:" + 源.源哈希,
)
可用源[源.source.记录键] = 源
return 主, 绑定, 可用源
@pytest.mark.case_id(
"NC-mig-80a0a8",
environment="离线迁移测试;协议替身与临时目录,不连真实数据库",
given="payload键完全缺失且投影等于注册DDL默认的规则/样例",
when="补缺省投影",
then=["仅补DDL默认投影,源哈希不变;非默认值不补"],
contract="docs/系统架构/新版设计/迁移与验收.md",
)
def test_PG规则及样例缺省字段仅兼容DDL默认且保留原哈希__2b8da9():
主, 绑定, 可用源 = _PG规则批次()
原始 = deepcopy(主.导出())
原例证 = {键: deepcopy(源.导出()) for 键, 源 in 可用源.items()}
库, 旧源 = 转换规则库(主, 绑定, 可用源)
assert 库["rules"]["l002"]["case_card_ids"] == []
assert 库["rules"]["l002"]["status"] == "candidate"
assert set(库["rules"]["l002"]["samples"]) == {"sf", "snf", "boundary", "regression"}
assert 旧源 == {
"status": "active",
"source_key": 主.source.记录键,
"source_hash": 原始["source_hash"],
}
assert 主.导出() == 原始
assert "case_card_ids" not in 主.原行["payload"]
assert 主.原行["content_sha256"] == 原始["record"]["content_sha256"]
assert {键: 源.导出() for 键, 源 in 可用源.items()} == 原例证
assert {样例["source_license"] for 样例 in 库["samples"].values()} == {"synthetic"}
for 源绑定 in 绑定["sources"]:
源 = 可用源[源绑定["source_key"]]
assert "source_license" not in 源.原行["payload"]
assert "source_ref" not in 源.原行["payload"]
样例 = 库["samples"][源绑定["sample_ids"][0]]
assert 样例["source_ref"] == "migration-source:" + 源.源哈希
@pytest.mark.case_id(
"NC-mig-d850b1",
environment="离线迁移测试;协议替身与临时目录,不连真实数据库",
given="异常投影形态(部分缺失、类型错、多余键)",
when="执行缺省投影",
then=["一律精确失败,不做兼容放行"],
contract="docs/系统架构/新版设计/迁移与验收.md",
)
@pytest.mark.parametrize(
"字段",
["case_card_ids", "source_license", "source_ref"],
ids=["case_card_ids", "source_license", "source_ref"],
)
@pytest.mark.parametrize(
"反例",
["显式null", "非默认投影", "投影错型", "载荷错型", "投影缺失", "其他字段缺省", "内容哈希不符"],
ids=[
"显式null",
"非默认投影",
"投影错型",
"载荷错型",
"投影缺失",
"其他字段缺省",
"内容哈希不符",
],
)
def test_PG质量默认投影兼容不放过异常__f2e3f7(字段, 反例):
主, 绑定, 可用源 = _PG规则批次()
源 = 主 if 字段 == "case_card_ids" else next(iter(可用源.values()))
导出 = 源.导出()
del 导出["source_hash"]
行 = 导出["record"]
错误码 = "quality_projection_mismatch"
不符字段 = 字段
if 反例 == "显式null":
行["payload"][字段] = None
elif 反例 == "非默认投影":
行[字段] = ["case-other"] if 字段 == "case_card_ids" else "other"
elif 反例 == "投影错型":
行[字段] = {}
if 字段 == "case_card_ids":
错误码 = "quality_source_invalid"
elif 反例 == "载荷错型":
行["payload"][字段] = {}
elif 反例 == "投影缺失":
del 行[字段]
if 字段 == "case_card_ids":
错误码 = "quality_source_invalid"
elif 反例 == "其他字段缺省":
不符字段 = "carve_out" if 字段 == "case_card_ids" else "note"
del 行["payload"][不符字段]
行[不符字段] = [] if 字段 == "case_card_ids" else ""
行["content_sha256"] = hashlib.sha256(稳定JSON(行["payload"]).encode()).hexdigest()
if 反例 == "内容哈希不符":
行["content_sha256"] = "0" * 64
错误码 = "quality_content_hash_mismatch"
异常源 = 旧快照.从载荷(导出)
if 字段 == "case_card_ids":
主 = 异常源
绑定["source_hash"] = 主.源哈希
else:
可用源[源.source.记录键] = 异常源
绑定["sources"][0]["source_hash"] = 异常源.源哈希
原始 = 异常源.导出()
匹配 = 错误码
if 错误码 == "quality_projection_mismatch":
匹配 += ".*:" + 不符字段
with pytest.raises(迁移错误, match=匹配):
转换规则库(主, 绑定, 可用源)
assert 异常源.导出() == 原始
@pytest.mark.case_id(
"NC-mig-718cf7",
environment="离线迁移测试;协议替身与临时目录,不连真实数据库",
given="缺省投影与冻结来源绑定并存",
when="导入样例",
then=["投影只补形状,不替代冻结来源绑定"],
contract="docs/系统架构/新版设计/迁移与验收.md",
)
@pytest.mark.parametrize(
("字段", "值", "错误码"),
[
("source_ref", "", "quality_binding_invalid"),
("source_ref", None, "quality_binding_invalid"),
("source_hash", "0" * 64, "quality_source_drift"),
("license", "unknown", "quality_binding_invalid"),
],
ids=["出处为空", "出处null", "源哈希漂移", "许可未知"],
)
def test_PG样例默认投影不替代冻结来源绑定__ba3dc2(字段, 值, 错误码):
主, 绑定, 可用源 = _PG规则批次()
绑定["sources"][0][字段] = 值
with pytest.raises(迁移错误, match=错误码):
转换规则库(主, 绑定, 可用源)
def _保全规则文件(snapshots, tmp_path):
source = tmp_path / "source-quality"
source.mkdir()
files = []
for snapshot in snapshots:
path = source / snapshot.source.id
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(base64.b64decode(snapshot.原行["content_base64"]))
files.append(
{
"relpath": snapshot.source.id,
"revision": snapshot.source.revision,
"sha256": snapshot.原行["sha256"],
}
)
output = tmp_path / "preserved-quality"
actual = 读取文件集(source, files, 数据集="synthetic-quality-files", 输出目录=output)
assert [s.导出() for s in actual] == [s.导出() for s in snapshots]
return output / "文件回执.json"
@pytest.mark.case_id(
"NC-w29-29e201",
environment="离线合成转换",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["文件规则及四类例证冻结且旧active只留历史"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
def test_文件规则及四类例证冻结且旧active只留历史__29e201():
快照, 映射 = _规则文件批次()
分流 = 分流批次(快照, 映射)
assert 分流[0].reason_code == "quality_rule_version"
assert all(r.reason_code == "rule_example_dependency" for r in 分流[1:])
绑定 = 映射.质量绑定(快照[0])
库, 旧源 = 转换规则库(快照[0], 绑定, {s.source.记录键: s for s in 快照})
assert 旧源["status"] == "active"
assert 库["rules"]["l002"]["status"] == "candidate"
assert set(库["rules"]["l002"]["samples"]) == {"sf", "snf", "boundary", "regression"}
assert {s["source_license"] for s in 库["samples"].values()} == {"synthetic"}
@pytest.mark.case_id(
"NC-w29-29e202",
environment="离线合成转换",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["缺例证和经验表不会被猜成质量案例"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
def test_缺例证和经验表不会被猜成质量案例__29e202():
快照, 映射 = _规则文件批次()
with pytest.raises(迁移错误, match="quality_dependency_missing"):
转换规则库(快照[0], 映射.质量绑定(快照[0]), {s.source.记录键: s for s in 快照[:-1]})
经验 = 旧快照.从载荷(
{
"source": {
"system": "sqlite",
"database": "synthetic-lessons",
"table": "lessons",
"id": "lesson-1",
"revision": "v1",
},
"record": {
"id": "lesson-1",
"status": "promoted",
"kind": "lesson",
"title": "不是案例",
},
}
)
判定 = 分流批次([经验], 映射配置({"works": []}))[0]
assert (判定.disposition, 判定.reason_code) == ("隔离", "deferred_W26_27")
@pytest.mark.case_id(
"NC-w29-29e207",
environment="离线合成转换",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["旧案例准备固定为未决backfill并核真实片段"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
def test_旧案例准备固定为未决backfill并核真实片段__29e207():
文本 = "她把伞递过去。值得注意的是,门外下雨了。"
片段 = "值得注意的是,门外下雨了。"
开始, 结束 = 文本.index(片段), len(文本)
草稿 = 正文草稿((段落("p1", (文本节点(文本),)),))
文档哈希 = 正文结构哈希(草稿)
片段哈希 = hashlib.sha256(片段.encode()).hexdigest()
行 = {
"id": 9,
"card_id": "case-legacy-9",
"state": "canonical",
"label": "snf",
"capture_mode": "live_feedback",
"source_license": "owned",
"source_sha256": "9" * 64,
"excerpt_sha256": 片段哈希,
"source_ref": "legacy:chapter:9",
"work_ref": "legacy-work-9",
"source_location": {"chapter": 9, "start": 开始, "end": 结束},
"excerpt": 片段,
"context": 文本,
"deleted": False,
}
快照 = 旧快照.从载荷(
{
"source": {
"system": "pg",
"database": "synthetic-case",
"table": "example_ai_flavor_case",
"id": "9",
"revision": "export-v1",
},
"record": 行,
}
)
绑定 = {
"source_key": 快照.source.记录键,
"source_hash": 快照.源哈希,
"route": "quality_case",
"author_id": "migration-author",
"sources": [
{
"role": "before",
"license": "owned",
"license_ref": "legacy-decision:9",
"legacy": {
"source_ref": 行["source_ref"],
"work_ref": 行["work_ref"],
"source_sha256": 行["source_sha256"],
"excerpt_sha256": 片段哈希,
"location": 行["source_location"],
},
"target": {
"kind": "document",
"ref_id": "chapter-9",
"revision": 3,
"source_hash": 文档哈希,
"start": 开始,
"end": 结束,
"excerpt_hash": 片段哈希,
"branch_id": "main",
"work_ref": "work:new-work-9",
},
}
],
"parameters": {"card_id": 行["card_id"], "preserve_text": True},
}
class 正文替身:
def 读取正文(self, 身份, chapter_id, *, 分支, 版本):
assert (chapter_id, 分支, 版本) == ("chapter-9", "main", 3)
return {"work_id": "new-work-9", "document": 草稿}
class 装配替身:
def 要求正文(self):
return 正文替身()
身份 = SimpleNamespace(作者="migration-author")
冻结 = 准备质量请求(
装配替身(),
身份,
快照,
映射配置({"works": [], "quality_bindings": [绑定]}),
{快照.source.记录键: 快照},
)
assert 冻结["payload"]["mode"] == "backfill"
assert 冻结["payload"]["feedback_command_id"] is None
assert 冻结["payload"]["label"] == "snf"
assert 冻结["payload"]["disposition"] == "ask"
assert 冻结["legacy_source"]["state"] == "canonical"
@pytest.fixture
def 质量迁移目标(测试数据库端点, 隔离数据库URL, tmp_path):
管理文件 = tmp_path / "管理连接.txt"
管理文件.write_text(隔离数据库URL, encoding="utf-8")
管理文件.chmod(0o600)
with psycopg.connect(隔离数据库URL) as 连:
允许 = {
"endpoint_type": "unix" if 连.info.host.startswith("/") else "tcp",
"host": 连.info.host,
"port": 连.info.port,
"system_identifier": str(
连.execute(
"SELECT system_identifier FROM pg_catalog.pg_control_system()"
).fetchone()[0]
),
"data_directory": 连.execute("SHOW data_directory").fetchone()[0],
}
允许文件 = tmp_path / "允许实例.json"
允许文件.write_text(json.dumps(允许), encoding="utf-8")
输出 = tmp_path / "目标"
管理引用 = 数据库引用("受控存储", str(管理文件))
回执 = 初始化目标(
允许实例=允许文件,
管理引用=管理引用,
维护模板=测试数据库端点[用途.维护].引用,
应用模板=测试数据库端点[用途.生产].引用,
输出目录=输出,
)
try:
库 = 数据库工厂(数据库引用("受控存储", str(输出 / "应用连接.txt")), 用途.生产)
维护 = 数据库工厂(数据库引用("受控存储", str(输出 / "维护连接.txt")), 用途.维护)
with 维护.连接() as 连, 连.transaction():
导入内置结构(元数据服务(连))
装配 = 构建(应用配置(库.引用, "synthetic"))
with 装配.生命周期():
身份 = 调用身份("migration-author", None, 用途.生产, 内容用途.规划)
作品 = 装配.要求作品()
结构 = 作品.新档案结构(身份, "quality-work", "work_core", 1)
作品.保存档案(
身份,
"quality-work",
档案保存("quality-work", 0, {"名称": "质量迁移合成作品"}, 结构),
)
作品.添加章节(
身份, "quality-ch", "quality-work", "quality-ch", "合成章", 预期目录版本=0
)
文本 = "她把伞递过去。值得注意的是,门外已经下起了雨。两人谁也没说话。"
装配.要求正文().保存人工(
身份, "quality-body", "quality-ch", 0, 正文草稿((段落("p1", (文本节点(文本),)),))
)
参数 = {"允许实例": 允许文件, "管理引用": 管理引用, "目标回执": 输出 / "目标回执.json"}
yield 装配, 身份, 库, 参数, 文本
finally:
with psycopg.connect(隔离数据库URL, autocommit=True) as 连:
连.execute(
sql.SQL("DROP DATABASE {} WITH (FORCE)").format(sql.Identifier(回执["database"]))
)
def _案例快照与映射(装配, 身份, 文本, *, 错作品=False):
正文 = 装配.要求正文().读取正文(身份, "quality-ch")
片段 = "值得注意的是,门外已经下起了雨。"
开始, 结束 = 文本.index(片段), 文本.index(片段) + len(片段)
片段哈希 = hashlib.sha256(片段.encode()).hexdigest()
行 = {
"id": 1,
"card_id": "case-legacy-quality-001",
"schema_version": "ai-flavor-case-v1",
"card_type": "ai_flavor_case",
"state": "canonical",
"label": "sf",
"layer": "lexical",
"carrier": "narration",
"capture_mode": "live_feedback",
"source_kind": "existing_work",
"source_license": "owned",
"source_sha256": "1" * 64,
"excerpt_sha256": 片段哈希,
"source_ref": "legacy:quality-ch:1",
"work_ref": "legacy-work-7",
"source_location": {"chapter": 1, "start": 开始, "end": 结束},
"excerpt": 片段,
"context": 文本,
"deleted": False,
}
快照 = 旧快照.从载荷(
{
"source": {
"system": "pg",
"database": "synthetic-quality-pg",
"table": "example_ai_flavor_case",
"id": "1",
"revision": "export-v1",
},
"record": 行,
}
)
绑定 = {
"source_key": 快照.source.记录键,
"source_hash": 快照.源哈希,
"route": "quality_case",
"author_id": 身份.作者,
"sources": [
{
"role": "before",
"license": "owned",
"license_ref": "legacy-decision:owned-1",
"legacy": {
"source_ref": 行["source_ref"],
"work_ref": 行["work_ref"],
"source_sha256": 行["source_sha256"],
"excerpt_sha256": 行["excerpt_sha256"],
"location": 行["source_location"],
},
"target": {
"kind": "document",
"ref_id": "quality-ch",
"revision": 正文["revision"],
"source_hash": 正文["document_hash"],
"start": 开始,
"end": 结束,
"excerpt_hash": 片段哈希,
"branch_id": "main",
"work_ref": "work:wrong" if 错作品 else "work:quality-work",
},
}
],
"parameters": {"card_id": 行["card_id"], "preserve_text": True},
}
return 快照, 映射配置({"works": [], "quality_bindings": [绑定]})
@pytest.mark.case_id(
"NC-w29-29e203",
environment="隔离PG与真实owner",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["案例经B06回填为未决且重放不重复创建"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
@pytest.mark.数据库
def test_案例经B06回填为未决且重放不重复创建__29e203(质量迁移目标):
装配, 身份, 库, 参数, 文本 = 质量迁移目标
快照, 映射 = _案例快照与映射(装配, 身份, 文本)
首次 = 导入快照(装配, 身份, [快照], 映射, **参数)
重放 = 导入快照(装配, 身份, [快照], 映射, **参数)
assert 首次["states"] == 重放["states"] == {"mapped": 1}
记录 = 迁移台账(库, 身份, 装配.要求知识方法().正式, 装配.要求故事世界(), 装配.要求审校()).读取(
快照.source.记录键
)
案例 = 装配.要求审校().读取案例(身份, 记录["targets"][0]["id"], revision=1)
assert 案例["state"] == "shadow" and not 案例["sampleable"]
assert 案例["payload"]["request"]["mode"] == "backfill"
assert 案例["payload"]["request"]["label"] == "sf"
assert 记录["frozen_request"]["legacy_source"]["state"] == "canonical"
with 库.连接(只读=True) as 连:
assert 连.execute("SELECT count(*) FROM muse_quality_case").fetchone()[0] == 1
assert 核对迁移结果(装配, 身份, [快照], 映射, **参数)["data_checks_passed"]
@pytest.mark.case_id(
"NC-w29-29e204",
environment="隔离PG与真实owner",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["S01已写案例但台账中断时只补原回执"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
@pytest.mark.数据库
def test_S01已写案例但台账中断时只补原回执__29e204(质量迁移目标):
装配, 身份, 库, 参数, 文本 = 质量迁移目标
快照, 映射 = _案例快照与映射(装配, 身份, 文本)
判定 = 分流批次([快照], 映射)[0]
台账 = 迁移台账(库, 身份, 装配.要求知识方法().正式, 装配.要求故事世界(), 装配.要求审校())
映射哈希 = hashlib.sha256(稳定JSON(映射.值).encode()).hexdigest()
行 = 台账.占用(快照, 映射哈希, 判定)
冻结 = 准备目标请求(装配, 身份, 快照, 判定, 映射, 可用源={快照.source.记录键: 快照})
台账.冻结请求(快照.source.记录键, 冻结)
原回执 = 提交目标请求(装配, 身份, 行["command_id"], 冻结)
assert 台账.读取(快照.source.记录键)["state"] == "reserved"
导入快照(装配, 身份, [快照], 映射, **参数)
恢复 = 台账.读取(快照.source.记录键)
assert 恢复["state"] == "mapped" and 恢复["receipt"] == 原回执
with 库.连接(只读=True) as 连:
assert 连.execute("SELECT count(*) FROM muse_quality_case").fetchone()[0] == 1
@pytest.mark.case_id(
"NC-w29-29e205",
environment="隔离PG与真实owner",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["错作品绑定在B06业务前隔离且零案例写入"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
@pytest.mark.数据库
def test_错作品绑定在B06业务前隔离且零案例写入__29e205(质量迁移目标):
装配, 身份, 库, 参数, 文本 = 质量迁移目标
with 库.连接(只读=True) as 连:
原命令数 = 连.execute("SELECT count(*) FROM muse_change_command").fetchone()[0]
快照, 映射 = _案例快照与映射(装配, 身份, 文本, 错作品=True)
结果 = 导入快照(装配, 身份, [快照], 映射, **参数)
assert 结果["states"] == {"quarantined": 1}
assert 结果["errors"][0]["reason_code"] == "quality_source_mismatch"
with 库.连接(只读=True) as 连:
assert 连.execute("SELECT count(*) FROM muse_quality_case").fetchone()[0] == 0
assert 连.execute("SELECT count(*) FROM muse_change_command").fetchone()[0] == 原命令数
@pytest.mark.case_id(
"NC-w29-29e206",
environment="隔离PG与真实owner",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["规则缺精确单版读回时保留reserved且不调B06导入"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
@pytest.mark.数据库
def test_规则缺精确单版读回时保留reserved且不调B06导入__29e206(质量迁移目标, monkeypatch):
装配, 身份, 库, _, _ = 质量迁移目标
monkeypatch.setattr(装配.要求审校(), "读取规则版本", None)
快照, 映射 = _规则文件批次()
判定 = 分流批次(快照, 映射)[0]
台账 = 迁移台账(库, 身份, 装配.要求知识方法().正式, 装配.要求故事世界(), 装配.要求审校())
台账.占用(快照[0], hashlib.sha256(稳定JSON(映射.值).encode()).hexdigest(), 判定)
with pytest.raises(迁移错误, match="target_owner_read_unavailable"):
准备目标请求(
装配,
身份,
快照[0],
判定,
映射,
可用源={s.source.记录键: s for s in 快照},
)
with 库.连接(只读=True) as 连:
assert 连.execute("SELECT count(*) FROM muse_rule_version").fetchone()[0] == 0
assert (
连.execute(
"SELECT count(*) FROM muse_legacy_import_record WHERE state='reserved'"
).fetchone()[0]
== 1
)
@pytest.mark.case_id(
"NC-w29-29e208",
environment="隔离PG与真实owner",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["真实规则导入未启用且新版本存在时仍核对原版本"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
@pytest.mark.数据库
def test_真实规则导入未启用且新版本存在时仍核对原版本__29e208(质量迁移目标, tmp_path):
app, author, db, options, _ = 质量迁移目标
snapshots, mapping = _规则文件批次()
options = {**options, "文件回执": _保全规则文件(snapshots, tmp_path)}
imported = 导入快照(app, author, snapshots, mapping, **options)
assert imported["states"].get("mapped") == 1, imported
assert imported["states"].get("quarantined", 0) == 0, imported
assert sum(imported["states"].values()) == 5
ledger = 迁移台账(db, author, app.要求知识方法().正式, app.要求故事世界(), app.要求审校())
entry = ledger.读取(snapshots[0].source.记录键)
original = app.要求审校().读取规则版本(author, "l002", 1)
assert original["status"] == "candidate" and not original["activation_recorded"]
assert original["version_id"] == entry["targets"][0]["id"]
assert entry["frozen_request"]["legacy_source"]["status"] == "active"
later = deepcopy(entry["frozen_request"]["payload"])
later["rules"]["l002"]["version"] = 2
later["rules"]["l002"]["name"] = "后续候选版本"
app.要求审校().导入规则候选(author, 规则库=later)
assert app.要求审校().读取规则版本(author, "l002", 2)["version_id"] != original["version_id"]
assert app.要求审校().读取规则版本(author, "l002", 1) == original
assert 导入快照(app, author, snapshots, mapping, **options)["states"].get("mapped") == 1
assert 核对迁移结果(app, author, snapshots, mapping, **options)["data_checks_passed"]
with db.连接(只读=True) as conn:
assert conn.execute("SELECT count(*) FROM muse_rule_activation").fetchone()[0] == 0
@pytest.mark.case_id(
"NC-w29-29e209",
environment="隔离PG与真实owner",
given="具名作者、固定来源、隔离测试配置与真实模块存储",
when="通过实际公开入口执行并核对拒绝、状态及持久结果",
then=["规则已保存但台账中断时补同一版本且不伪造S01回执"],
contract="docs/系统架构/新版设计/数据模型/旧知识记录分流.md#旧规则版本与质量案例",
)
@pytest.mark.数据库
def test_规则已保存但台账中断时补同一版本且不伪造S01回执__29e209(质量迁移目标, tmp_path):
app, author, db, options, _ = 质量迁移目标
snapshots, mapping = _规则文件批次()
options = {**options, "文件回执": _保全规则文件(snapshots, tmp_path)}
route = 分流批次(snapshots, mapping)[0]
ledger = 迁移台账(db, author, app.要求知识方法().正式, app.要求故事世界(), app.要求审校())
row = ledger.占用(
snapshots[0],
hashlib.sha256(稳定JSON(mapping.值).encode()).hexdigest(),
route,
)
frozen = 准备目标请求(
app,
author,
snapshots[0],
route,
mapping,
可用源={s.source.记录键: s for s in snapshots},
)
ledger.冻结请求(snapshots[0].source.记录键, frozen)
receipt = 提交目标请求(app, author, row["command_id"], frozen)
assert ledger.读取(snapshots[0].source.记录键)["state"] == "reserved"
result = 导入快照(app, author, snapshots, mapping, **options)
assert result["states"].get("mapped") == 1, result
current = ledger.读取(snapshots[0].source.记录键)
assert current["targets"][0]["id"] == receipt["results"][0]["version_id"]
with db.连接(只读=True) as conn:
assert conn.execute("SELECT count(*) FROM muse_rule_version").fetchone()[0] == 1
assert (
conn.execute(
"SELECT count(*) FROM muse_change_command WHERE command_id=%s", (row["command_id"],)
).fetchone()[0]
== 0
)