"""同源拆书互斥:排他范围内的并发拆解被拒;任务终态释放范围后可再次发起。""" import pytest from muse.共享.错误 import Muse错误 pytestmark = pytest.mark.数据库 @pytest.mark.case_id( "NC-w18-18b01a", environment="真实隔离 PG", given="确定性输入或隔离数据库", when="同源并发拆解被作用域互斥阻塞", then=["行为可复验", "失败与歧义如实呈现"], contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md", ) def test_同源并发拆解被作用域互斥阻塞__18b01a(研究环境): 工具 = 研究环境 来源 = 工具.导入来源( "样章:风起", "第1回 风起\n内容甲。\n第2回 云涌\n内容乙。\n第3回 雨落\n内容丙。\n" ) 第一个 = 工具.发起(来源["source_id"]) 第二个 = 工具.发起(来源["source_id"]) assert 第二个["task_id"] != 第一个["task_id"] # 互斥在领取层强制:持有第一任务的首步租约时,同源第二任务无可领取步骤。 能力 = 工具.环境["处理器能力"] 运行 = 工具.装配.任务运行 首领 = 运行.领取步骤("worker", 能力) assert 首领 is not None and 首领.任务ID == 第一个["task_id"], "应先领取第一任务" assert 运行.领取步骤("worker2", 能力) is None, "同源第二任务必须被作用域互斥阻塞" 运行.执行一步(首领) # 探针领取的首步(切窗核对,不调用模型)执行放行 # 第一任务完成(合成宿主按剧本应答)后范围释放,第二任务可执行到完成。 for 实体 in ( {"name": "林深", "type": "人物", "evidence": ["风起"]}, {"name": "青云镇", "type": "地点", "evidence": ["云涌"]}, ): 工具.剧本.append(工具.分析输出([实体])) 快照 = 工具.跑任务(第一个["task_id"]) assert 快照.状态.value == "completed", f"首个拆书应完成:{快照.状态}" for 实体 in ( {"name": "林深", "type": "人物", "evidence": ["风起"]}, {"name": "青云镇", "type": "地点", "evidence": ["云涌"]}, ): 工具.剧本.append(工具.分析输出([实体])) 第二快照 = 工具.跑任务(第二个["task_id"]) assert 第二快照.状态.value == "completed", f"范围释放后第二任务应完成:{第二快照.状态}" @pytest.mark.case_id( "NC-w18-18b02b", environment="真实隔离 PG", given="确定性输入或隔离数据库", when="失败任务释放范围可重建", then=["行为可复验", "失败与歧义如实呈现"], contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md", ) def test_失败任务释放范围可重建__18b02b(研究环境): 工具 = 研究环境 来源 = 工具.导入来源( "样章:雨落", "第1回 风起\n内容甲。\n第2回 云涌\n内容乙。\n第3回 雨落\n内容丙。\n" ) # 输出合同不满足:调用已结算但终态无效 → 步骤失败、任务失败(无未知调用)。 工具.剧本.append({"类型": "文本", "文本": {"chapters": []}}) 任务 = 工具.发起(来源["source_id"]) with pytest.raises((Muse错误, RuntimeError, OSError)): 工具.跑任务(任务["task_id"]) 快照 = 工具.装配.任务运行.读取任务(任务["task_id"]) assert 快照.状态.value == "failed" 重建 = 工具.发起(来源["source_id"]) assert 重建["task_id"] != 任务["task_id"], "失败任务应已释放排他范围,允许重建"