接续 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。
124 lines
5.8 KiB
Python
124 lines
5.8 KiB
Python
"""从PG留存旧记录试算来源追加;请求顺序不冒充旧历史,不产生Canonical。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import re
|
||
from copy import deepcopy
|
||
|
||
from muse.共享.错误 import Muse错误
|
||
from 关联已确认 import 冻结模式
|
||
from 建立映射 import 稳定JSON, 读取JSON, 旧快照, 迁移错误
|
||
from 转换结构 import 取一致值
|
||
|
||
|
||
def 只读回放来源(台账, 请求, 映射哈希: str) -> dict:
|
||
结果: dict = {
|
||
"requested": 请求 is not None,
|
||
"passed": True,
|
||
"initial": None,
|
||
"steps": [],
|
||
"final": None,
|
||
"checked_sources": 0,
|
||
"issues": [],
|
||
"order_basis": "caller_selected_order",
|
||
"historical_order_verified": False,
|
||
"canonical_written": False,
|
||
}
|
||
if 请求 is None:
|
||
return 结果
|
||
缓存 = {}
|
||
|
||
def 读取(指针):
|
||
if (
|
||
not isinstance(指针, dict)
|
||
or set(指针) != {"source_key", "source_hash"}
|
||
or not isinstance(指针["source_key"], str)
|
||
or not 指针["source_key"]
|
||
or not isinstance(指针["source_hash"], str)
|
||
or re.fullmatch(r"[0-9a-f]{64}", 指针["source_hash"]) is None
|
||
):
|
||
raise 迁移错误("legacy_lineage_invalid", "回放来源必须是明确key/hash")
|
||
key = 指针["source_key"]
|
||
if key not in 缓存:
|
||
行 = 台账.读取(key)
|
||
if (
|
||
行 is None
|
||
or 行["state"] != "mapped"
|
||
or 行["frozen_request"] is None
|
||
or 冻结模式(行["frozen_request"]) != "link_confirmed"
|
||
):
|
||
raise 迁移错误("legacy_lineage_invalid", "回放来源不是已核历史关联")
|
||
台账.核对关联(key)
|
||
缓存[key] = 行
|
||
行 = 缓存[key]
|
||
if 行["source_hash"] != 指针["source_hash"] or 行["mapping_hash"] != 映射哈希:
|
||
raise 迁移错误("legacy_lineage_invalid", "回放来源或映射哈希不符")
|
||
return 行, 旧快照.从载荷(行["original"])
|
||
|
||
try:
|
||
if (
|
||
not isinstance(请求, dict)
|
||
or set(请求) != {"base", "steps"}
|
||
or not isinstance(请求["steps"], list)
|
||
or not 1 <= len(请求["steps"]) <= 500
|
||
):
|
||
raise 迁移错误("legacy_lineage_invalid", "回放需要一个根和1至500个明确步骤")
|
||
根行, 根 = 读取(请求["base"])
|
||
if (
|
||
根.source.table.rsplit(".", 1)[-1] != "muse_knowledge_entity"
|
||
or 根行["frozen_request"]["payload"]["target_source"] != 请求["base"]
|
||
):
|
||
raise 迁移错误("legacy_lineage_invalid", "回放基线须为正式实体根")
|
||
原链 = 根.原行.get("lineage_payload")
|
||
链 = {} if 原链 is None else deepcopy(原链)
|
||
if not isinstance(链, dict):
|
||
raise 迁移错误("legacy_lineage_invalid", "已有来源链不是对象,不能清空")
|
||
引用 = 链.get("sourceRefs", [])
|
||
if not isinstance(引用, list) or not all(isinstance(r, dict) for r in 引用):
|
||
raise 迁移错误("legacy_lineage_invalid", "已有结构化引用不是对象数组")
|
||
结果["initial"] = deepcopy(链)
|
||
已有 = {稳定JSON(r) for r in 引用}
|
||
for 指针 in 请求["steps"]:
|
||
行, 源 = 读取(指针)
|
||
if (
|
||
源.source.table.rsplit(".", 1)[-1] != "muse_knowledge_draft"
|
||
or 源.原行.get("draft_type") != "entity"
|
||
or 源.原行.get("status") != "confirmed"
|
||
or 行["frozen_request"]["payload"]["target_source"] != 请求["base"]
|
||
or 行["frozen_request"]["subject_ref"] != 根行["frozen_request"]["subject_ref"]
|
||
):
|
||
raise 迁移错误("legacy_lineage_invalid", "步骤不是同根实体的已确认草稿")
|
||
载荷 = 取一致值(源.原行, ("draft_payload", "payload_json"), 默认={})
|
||
载荷 = 读取JSON(载荷) if isinstance(载荷, str) else 载荷
|
||
if not isinstance(载荷, dict):
|
||
raise 迁移错误("legacy_lineage_invalid", "历史草稿载荷不是对象")
|
||
当前引用 = deepcopy(取一致值(载荷, ("source", "来源", "出处"), 默认={}))
|
||
if not isinstance(当前引用, dict):
|
||
raise 迁移错误("legacy_lineage_invalid", "来源字符串提示不能当结构化引用")
|
||
证据 = 取一致值(载荷, ("evidence", "证据"))
|
||
if 证据 is not None and not isinstance(证据, str):
|
||
raise 迁移错误("legacy_lineage_invalid", "证据不是原字符串")
|
||
if 证据 not in (None, ""):
|
||
if "evidence" in 当前引用 and 当前引用["evidence"] != 证据:
|
||
raise 迁移错误("field_conflict", "原引用与独立证据冲突")
|
||
当前引用["evidence"] = 证据
|
||
类型 = 源.原行.get("source_type")
|
||
if not isinstance(类型, str) or not 类型:
|
||
raise 迁移错误("legacy_lineage_invalid", "来源类型缺失,不能补造")
|
||
序列化 = 稳定JSON(当前引用)
|
||
if 当前引用 and 序列化 not in 已有:
|
||
引用.append(当前引用)
|
||
已有.add(序列化)
|
||
链.update(
|
||
sourceRefs=引用, lastDraftId=源.原行.get("id", 源.source.id), lastSourceType=类型
|
||
)
|
||
结果["steps"].append({**指针, "lineage": deepcopy(链)})
|
||
结果["final"] = 链
|
||
except (迁移错误, Muse错误, ValueError, RecursionError) as 错:
|
||
代码 = (
|
||
错.code if isinstance(错, 迁移错误) else getattr(错, "错误码", "legacy_lineage_invalid")
|
||
)
|
||
结果.update(passed=False, final=None, issues=[{"reason_code": 代码}])
|
||
结果["checked_sources"] = len(缓存)
|
||
return 结果
|