接续 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。
147 lines
7.3 KiB
Python
147 lines
7.3 KiB
Python
"""完整分析落B03;S02运行证据不被业务回查或历史承接改写。"""
|
||
|
||
from dataclasses import replace
|
||
|
||
import pytest
|
||
|
||
from muse.任务运行.接口 import 任务状态, 步骤结果
|
||
from muse.共享.错误 import Muse错误
|
||
from muse.接入.cli.研究命令 import 运行研究命令
|
||
from muse.编排.研究拆书 import 查询拆书状态
|
||
from muse.资料研究.接口 import 版本身份, 窗口, 窗计划哈希, 资料服务
|
||
from muse.配置 import 服务配置
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
|
||
|
||
def _来源(工具):
|
||
return 工具.导入来源("B03版本样例", "第1回 机舱\n林深照看机舱。\n")
|
||
|
||
|
||
def _完成(工具, 来源, 名称):
|
||
任务 = 工具.发起(来源["source_id"])
|
||
快照 = 工具.装配.任务运行.读取任务(任务["task_id"])
|
||
for _ in 快照.冻结输入["输入"]["窗计划"]:
|
||
工具.剧本.append(
|
||
工具.分析输出([{"name": 名称, "type": "人物", "evidence": ["林深照看机舱。"]}])
|
||
)
|
||
终态 = 工具.跑任务(任务["task_id"])
|
||
assert 终态.状态 == 任务状态.已完成
|
||
return 任务, 终态
|
||
|
||
|
||
def test_相同输入的不同运行分别持久化完整分析__214010(研究环境):
|
||
工具 = 研究环境
|
||
来源 = _来源(工具)
|
||
一, 原一 = _完成(工具, 来源, "第一种归纳")
|
||
二, 原二 = _完成(工具, 来源, "第二种归纳")
|
||
assert 一["版本ID"] == 二["版本ID"] and 一["task_id"] != 二["task_id"]
|
||
with 工具.库.连接(只读=True) as 连:
|
||
列表 = 工具.服务.列出分析(连, "post-author", 来源["source_id"])
|
||
assert len(列表) == 2 and {r["analysis_id"] for r in 列表} == {一["task_id"], 二["task_id"]}
|
||
assert len({r["content_hash"] for r in 列表}) == 2
|
||
assert {r["payload"]["窗口结果"]["w001"]["entities"][0]["name"] for r in 列表} == {
|
||
"第一种归纳",
|
||
"第二种归纳",
|
||
}
|
||
with pytest.raises(Muse错误):
|
||
工具.服务.读取分析(连, "foreign-author", 一["task_id"])
|
||
with 工具.库.连接() as 连, 连.transaction():
|
||
回查 = 工具.服务.承接历史分析(连, 工具.装配.任务运行, "post-author", 一["task_id"])
|
||
assert 回查["origin"] == "model"
|
||
状态 = 查询拆书状态(工具.装配, "post-author", 来源["source_id"])
|
||
assert len(状态["分析"]) == 2
|
||
assert {r["analysis_state"] for r in 状态["台账"]} == {"recorded"}
|
||
assert 工具.装配.任务运行.读取任务(一["task_id"]) == 原一
|
||
assert 工具.装配.任务运行.读取任务(二["task_id"]) == 原二
|
||
|
||
|
||
def _旧版本登记(上下文, *, 坏摘要):
|
||
# 复现升级前的最终处理器;前置窗口仍由真实S02流程和合成模型提供方执行。
|
||
任务 = 上下文.任务
|
||
输入 = 任务.冻结输入["输入"]["拆书"]
|
||
步骤 = {s["step_id"]: s for s in 任务.步骤}
|
||
结果 = 步骤["逐窗提取"]["checkpoint"]["窗口结果"]
|
||
合并 = 步骤["实体归并"]["checkpoint"]["归并"]
|
||
窗列表 = [窗口(**r) for r in 任务.冻结输入["输入"]["窗计划"]]
|
||
版本 = {
|
||
"版本ID": 版本身份(输入["source_id"], 输入["revision"], 窗列表),
|
||
"source_id": 输入["source_id"],
|
||
"revision": 输入["revision"],
|
||
"content_hash": 输入["content_hash"],
|
||
"窗计划哈希": 窗计划哈希(窗列表),
|
||
"完成窗": sorted(结果),
|
||
"实体组数": len(合并["合并组"]) + int(坏摘要),
|
||
"歧义数": len(合并["歧义"]),
|
||
"样本依据": 任务.冻结输入["输入"].get("样本依据"),
|
||
}
|
||
return 步骤结果({"版本ID": 版本["版本ID"], "歧义数": 版本["歧义数"]}, {"版本": 版本})
|
||
|
||
|
||
@pytest.mark.parametrize("坏摘要", [False, True])
|
||
def test_已完成旧检查点显式承接不造任务且坏摘要拒绝__214011(
|
||
研究环境, monkeypatch, tmp_path, 坏摘要
|
||
):
|
||
工具 = 研究环境
|
||
来源 = _来源(工具)
|
||
登记 = 工具.装配.流程登记
|
||
原获取 = 登记.获取
|
||
|
||
def 旧获取(身份, 版本):
|
||
处理器 = 原获取(身份, 版本)
|
||
if 身份 == "rs.version":
|
||
return replace(处理器, 执行=lambda ctx: _旧版本登记(ctx, 坏摘要=坏摘要))
|
||
return 处理器
|
||
|
||
with monkeypatch.context() as m:
|
||
m.setattr(登记, "获取", 旧获取)
|
||
任务, 原任务 = _完成(工具, 来源, "旧分析")
|
||
with 工具.库.连接(只读=True) as 连:
|
||
assert 工具.服务.列出分析(连, "post-author", 来源["source_id"]) == []
|
||
查询 = 查询拆书状态(工具.装配, "post-author", 来源["source_id"])
|
||
assert 查询["台账"][0]["analysis_state"] == "history_not_imported" and 查询["分析"] == []
|
||
前任务数 = len(工具.装配.任务运行.列出任务("post-author"))
|
||
工具.装配.配置 = replace(
|
||
工具.装配.配置, HTTP=服务配置(str(tmp_path / "token-reference"), "post-author")
|
||
)
|
||
if 坏摘要:
|
||
with pytest.raises(Muse错误, match="旧登记摘要与完整结果不符"):
|
||
运行研究命令(工具.装配, "承接", 任务["task_id"])
|
||
with 工具.库.连接(只读=True) as 连:
|
||
assert 工具.服务.列出分析(连, "post-author", 来源["source_id"]) == []
|
||
else:
|
||
分析 = 运行研究命令(工具.装配, "承接", 任务["task_id"])
|
||
assert 分析["origin"] == "checkpoint_history"
|
||
assert 分析["payload"]["窗口结果"]["w001"]["entities"][0]["name"] == "旧分析"
|
||
assert 运行研究命令(工具.装配, "承接", 任务["task_id"]) == 分析
|
||
assert 运行研究命令(工具.装配, "分析", 任务["task_id"]) == 分析
|
||
assert 运行研究命令(工具.装配, "检查", 任务["task_id"])["分析"] == 分析
|
||
assert 工具.装配.任务运行.读取任务(任务["task_id"]) == 原任务
|
||
assert len(工具.装配.任务运行.列出任务("post-author")) == 前任务数
|
||
assert 工具.剧本 == [], "承接不重发模型调用,也不需要额外模型剧本"
|
||
|
||
|
||
def test_历史承接拒绝未完成任务和非持有者写入__214012(研究环境):
|
||
工具 = 研究环境
|
||
来源 = _来源(工具)
|
||
任务 = 工具.发起(来源["source_id"])
|
||
with 工具.库.连接() as 连:
|
||
with pytest.raises(Muse错误, match="已完成"):
|
||
with 连.transaction():
|
||
资料服务().承接历史分析(连, 工具.装配.任务运行, "post-author", 任务["task_id"])
|
||
领取 = 工具.装配.任务运行.领取步骤("worker", 工具.环境["处理器能力"])
|
||
assert 领取 is not None
|
||
with 工具.库.连接() as 连:
|
||
with pytest.raises(Muse错误, match="只有分析登记步骤"):
|
||
with 连.transaction():
|
||
资料服务().登记模型分析(连, 工具.装配.任务运行, 领取)
|
||
工具.装配.任务运行.控制任务(
|
||
任务["task_id"], "post-author", 任务状态.运行中, "取消", 命令ID="cancel-analysis"
|
||
)
|
||
with 工具.库.连接() as 连:
|
||
with pytest.raises(Muse错误, match="任务已停止"):
|
||
with 连.transaction():
|
||
资料服务().登记模型分析(连, 工具.装配.任务运行, 领取)
|
||
with 工具.库.连接(只读=True) as 连:
|
||
assert 工具.服务.列出分析(连, "post-author", 来源["source_id"]) == []
|