实现侧: - 上下文:任务范围拆分为 范围校验/范围授权;索引按可发现口径重建、索引新鲜度改对称差;依赖校验统一快照漂移说明。 - 知识方法:方法与材料读取口径统一;超限方法材料按可选省略,核对路径不再二次计费;删除无合同的读时重算。 - 任务运行:新增 context.usage/tool.denied 事件类型;连接池常驻并在装配生命周期内开关;调用结算与核对分列。 - 效果评测/审校修订/交付连载/作者经验/作品规划:凭据冻结、标定消费、导出补证、事实引文核对等收尾修复。 - 资源加载:能力正文不再夹带索引用的导航注记(该注记此前进入角色与技能的模型提示)。 - 元数据:受保护骨架与代码保护属性对齐;字段校验与内置结构口径同步。 - 基础设施:环境预检进入装配生命周期;数据库连接运行期字段不参与相等比较;索引指纹归一化 jsonb 浮点。 - 删除被替代实现:7 份旧提示词模板与空壳 资料来源 读取器。 用例侧: - 用例身份与导航元信息迁移;夹具补生命周期、同库暴露与模板封存; - 本轮定向修复:方法材料省略、事实引文、迁移回执、额度与暂停用例、慢用例超时预算等。
167 lines
6.3 KiB
Python
167 lines
6.3 KiB
Python
"""候选状态与并发:CAS 定位、编辑后旧候选拒绝、并发采纳唯一成功。"""
|
||
|
||
import pytest
|
||
from pydantic import TypeAdapter
|
||
|
||
from muse.共享.错误 import Muse错误
|
||
from muse.正式变更.接口 import 作者动作
|
||
from muse.正文写作.接口 import 文本节点, 正文草稿, 段落
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
|
||
|
||
def _建候选(环境, 命令: str, 文本: str, 预期版本: int = 0):
|
||
作者 = 环境["作者"]
|
||
候选 = (
|
||
环境["装配"]
|
||
.要求正文()
|
||
.创建人工候选(
|
||
作者,
|
||
命令,
|
||
"ch-1",
|
||
预期版本,
|
||
正文草稿((段落("p1", (文本节点(文本),)),)),
|
||
)
|
||
)
|
||
候选ID = next(
|
||
r["candidate_id"] for r in 候选["results"] if isinstance(r, dict) and "candidate_id" in r
|
||
)
|
||
候选行 = 环境["装配"].要求正文().读取候选(作者, 候选ID)
|
||
from muse.正文写作.接口 import 候选定位
|
||
|
||
定位 = 候选定位(
|
||
候选行["candidate_id"],
|
||
候选行["revision"],
|
||
候选行["candidate_hash"],
|
||
候选行["document_id"],
|
||
候选行["current_document_revision"],
|
||
)
|
||
审阅 = 环境["装配"].要求正文().打开候选审阅(作者, 定位)
|
||
return 定位, 审阅
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w16-w16d01",
|
||
environment="真实隔离 PG",
|
||
given="隔离数据库中的作品与已采纳正文",
|
||
when="候选哈希与被审版本不一致时采纳被拒",
|
||
then=["REVISION_CONFLICT 或 SCOPE_DENIED"],
|
||
contract="docs/系统架构/新版设计/功能规格/P05-章后处理与事实复核.md",
|
||
)
|
||
def test_候选哈希不匹配采纳拒绝__16d013(章后环境, 章后工具):
|
||
环境 = 章后环境
|
||
from muse.正文写作.接口 import 候选定位
|
||
|
||
定位, 审阅 = _建候选(环境, "cas-cand-1", "林深在码头。")
|
||
坏定位 = 候选定位(
|
||
定位.candidate_id,
|
||
定位.candidate_revision,
|
||
"0" * 64,
|
||
定位.target_ref,
|
||
定位.expected_revision,
|
||
)
|
||
with pytest.raises(Muse错误) as 异常:
|
||
环境["装配"].要求正文().决定候选(
|
||
环境["作者"],
|
||
"cas-adopt-bad",
|
||
坏定位,
|
||
作者动作.采纳,
|
||
审阅["review_id"],
|
||
审阅["review_hash"],
|
||
("document",),
|
||
)
|
||
assert 异常.value.错误码 in {"REVISION_CONFLICT", "SCOPE_DENIED"}
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w16-w16d02",
|
||
environment="真实隔离 PG",
|
||
given="隔离数据库中的作品与已采纳正文",
|
||
when="正文前进后旧候选不能采纳;重开审阅后可明确拒绝",
|
||
then=["陈旧采纳被拒", "拒绝仅更新决定"],
|
||
contract="docs/系统架构/新版设计/功能规格/P05-章后处理与事实复核.md",
|
||
)
|
||
def test_正文编辑后旧候选采纳拒绝但明确弃用允许__16d024(章后环境, 章后工具):
|
||
环境 = 章后环境
|
||
定位, 审阅 = _建候选(环境, "stale-cand-1", "候选版本的正文。")
|
||
# 正文前进一格:旧候选基线陈旧。
|
||
环境["剧本"].append(章后工具.抽取输出("编辑后的摘要。", []))
|
||
章后工具.保存一章("ch-1", "作者直接改过的新正文。")
|
||
with pytest.raises(Muse错误) as 异常:
|
||
环境["装配"].要求正文().决定候选(
|
||
环境["作者"],
|
||
"stale-adopt-1",
|
||
定位,
|
||
作者动作.采纳,
|
||
审阅["review_id"],
|
||
审阅["review_hash"],
|
||
("document",),
|
||
)
|
||
assert 异常.value.错误码 in {"SOURCE_STALE", "REVISION_CONFLICT"}
|
||
# 陈旧候选仍可明确弃用:作者端对当前版本重开审阅后拒绝。
|
||
from muse.正文写作.接口 import 候选定位
|
||
|
||
当前行 = 环境["装配"].要求正文().读取候选(环境["作者"], 定位.candidate_id)
|
||
重开定位 = 候选定位(
|
||
当前行["candidate_id"],
|
||
当前行["revision"],
|
||
当前行["candidate_hash"],
|
||
当前行["document_id"],
|
||
当前行["current_document_revision"],
|
||
)
|
||
重开审阅 = 环境["装配"].要求正文().打开候选审阅(环境["作者"], 重开定位)
|
||
环境["装配"].要求正文().决定候选(
|
||
环境["作者"],
|
||
"stale-reject-1",
|
||
重开定位,
|
||
作者动作.拒绝,
|
||
重开审阅["review_id"],
|
||
重开审阅["review_hash"],
|
||
(),
|
||
)
|
||
行 = 环境["装配"].要求正文().读取候选(环境["作者"], 定位.candidate_id)
|
||
assert 行["decision"] == "reject"
|
||
# 作者正文不受影响。
|
||
正文 = 环境["装配"].要求正文().读取正文(环境["作者"], "ch-1")
|
||
assert TypeAdapter(正文草稿).validate_python(正文["document"])
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w16-w16d03",
|
||
environment="真实隔离 PG",
|
||
given="隔离数据库中的作品与已采纳正文",
|
||
when="两个候选基于同一版本时仅一个采纳成功",
|
||
then=["后者 SOURCE_STALE 或 REVISION_CONFLICT", "正文版本唯一"],
|
||
contract="docs/系统架构/新版设计/功能规格/P05-章后处理与事实复核.md",
|
||
)
|
||
def test_并发采纳唯一成功且正文版本唯一__16d035(章后环境, 章后工具):
|
||
环境 = 章后环境
|
||
正文服务 = 环境["装配"].要求正文()
|
||
定位1, 审阅1 = _建候选(环境, "conc-cand-1", "并发候选甲。")
|
||
定位2, 审阅2 = _建候选(环境, "conc-cand-2", "并发候选乙。")
|
||
环境["剧本"].append(章后工具.抽取输出("并发摘要一。", []))
|
||
回执1 = 正文服务.决定候选(
|
||
环境["作者"],
|
||
"conc-adopt-1",
|
||
定位1,
|
||
作者动作.采纳,
|
||
审阅1["review_id"],
|
||
审阅1["review_hash"],
|
||
("document",),
|
||
)
|
||
# 第二个候选基于同一旧版本:采纳时基线已前进,必须被拒绝。
|
||
with pytest.raises(Muse错误) as 异常:
|
||
正文服务.决定候选(
|
||
环境["作者"],
|
||
"conc-adopt-2",
|
||
定位2,
|
||
作者动作.采纳,
|
||
审阅2["review_id"],
|
||
审阅2["review_hash"],
|
||
("document",),
|
||
)
|
||
assert 异常.value.错误码 in {"SOURCE_STALE", "REVISION_CONFLICT"}
|
||
正文 = 正文服务.读取正文(环境["作者"], "ch-1")
|
||
assert 正文["revision"] == 1
|
||
assert 回执1["receipt_id"]
|