接续 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。
132 lines
5.8 KiB
Python
132 lines
5.8 KiB
Python
"""分支来源、合并候选和S01复检使用真实隔离PG,支线不登记主线章后任务。"""
|
||
|
||
from dataclasses import replace
|
||
|
||
import pytest
|
||
import test_正文候选与作者决定 as 候选测试
|
||
|
||
from muse.共享.调用身份 import 用途
|
||
from muse.共享.错误 import Muse错误
|
||
from muse.正文写作.接口 import 候选定位, 分支创建, 分支合并
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
候选环境 = 候选测试.候选环境
|
||
|
||
|
||
def 开分支(env):
|
||
svc, author, _ = env
|
||
original = svc.读取正文(author, "chapter-candidate")
|
||
req = 分支创建(
|
||
"chapter-candidate", "main", original["revision"], original["document_hash"], "试写"
|
||
)
|
||
receipt = svc.创建分支(author, "fork", req)
|
||
return original, req, receipt
|
||
|
||
|
||
def 合并请求(svc, author):
|
||
compare = svc.比较分支(author, "chapter-candidate", "试写")
|
||
return 分支合并(
|
||
"chapter-candidate",
|
||
"试写",
|
||
compare["source_revision"],
|
||
compare["source_hash"],
|
||
compare["expected_revision"],
|
||
compare["target_hash"],
|
||
tuple(c["change_id"] for c in compare["changes"]),
|
||
)
|
||
|
||
|
||
def test_分支固定历史起点独立保存回退且不派章后任务__234001(候选环境):
|
||
svc, author, pools = 候选环境
|
||
with pools[用途.生产].连接(只读=True) as conn:
|
||
before = conn.execute("SELECT count(*) FROM muse_task").fetchone()[0]
|
||
original, req, receipt = 开分支(候选环境)
|
||
assert svc.创建分支(author, "fork", req) == receipt
|
||
svc.保存人工(author, "side-edit", req.chapter_id, 1, 候选测试.草稿("支线变化"), 分支="试写")
|
||
svc.回退正文(author, "side-restore", req.chapter_id, 2, 1, 分支="试写")
|
||
assert svc.读取正文(author, req.chapter_id) == original
|
||
assert svc.读取正文(author, req.chapter_id, 分支="试写")["revision"] == 3
|
||
assert svc.读取正文(author, req.chapter_id, 分支="试写", 版本=2)["visible_text"].startswith(
|
||
"支线变化"
|
||
)
|
||
assert len(svc.列出分支(author, req.chapter_id)) == 2
|
||
with pools[用途.生产].连接(只读=True) as conn:
|
||
assert conn.execute("SELECT count(*) FROM muse_task").fetchone()[0] == before
|
||
with pytest.raises(Muse错误):
|
||
svc.创建分支(author, "duplicate-name", req)
|
||
with pytest.raises(Muse错误):
|
||
svc.比较分支(replace(author, 作者="other"), req.chapter_id, "试写")
|
||
|
||
|
||
def test_三方合并生成候选且独立主线修改在采纳后保持__234002(候选环境):
|
||
svc, author, _ = 候选环境
|
||
开分支(候选环境)
|
||
svc.保存人工(author, "side", "chapter-candidate", 1, 候选测试.草稿("支线首句"), 分支="试写")
|
||
main = svc.保存人工(
|
||
author, "main-change", "chapter-candidate", 1, 候选测试.草稿(尾句="作者新末段")
|
||
)
|
||
req = 合并请求(svc, author)
|
||
receipt = svc.合并分支(author, "merge", req)
|
||
assert svc.合并分支(author, "merge", req) == receipt
|
||
candidate = svc.读取候选(author, receipt["target_ref"])
|
||
assert candidate["visible_text"] == "支线首句\n\n作者新末段"
|
||
assert candidate["decision"] == "undecided"
|
||
assert svc.读取正文(author, "chapter-candidate")["revision"] == main["results"][0]["revision"]
|
||
loc = 候选定位(
|
||
candidate["candidate_id"], 1, candidate["candidate_hash"], candidate["document_id"], 2
|
||
)
|
||
review = svc.打开候选审阅(author, loc)
|
||
候选测试.决定(svc, author, "adopt-merge", loc, review)
|
||
assert svc.读取正文(author, "chapter-candidate")["visible_text"] == candidate["visible_text"]
|
||
assert svc.读取正文(author, "chapter-candidate", 分支="试写")["revision"] == 2
|
||
|
||
|
||
@pytest.mark.parametrize("changed", ["source", "target"])
|
||
def test_合并候选再编辑仍复检两端不覆盖新稿__234003(候选环境, changed):
|
||
svc, author, _ = 候选环境
|
||
开分支(候选环境)
|
||
svc.保存人工(
|
||
author, "side", "chapter-candidate", 1, 候选测试.草稿("支线首句", "支线末句"), 分支="试写"
|
||
)
|
||
receipt = svc.合并分支(author, "merge", 合并请求(svc, author))
|
||
candidate = svc.读取候选(author, receipt["target_ref"])
|
||
svc.编辑候选(
|
||
author,
|
||
"partial",
|
||
candidate["candidate_id"],
|
||
1,
|
||
candidate["candidate_hash"],
|
||
选择变更=(candidate["changes"][0]["change_id"],),
|
||
)
|
||
latest = svc.读取候选(author, candidate["candidate_id"])
|
||
loc = 候选定位(latest["candidate_id"], 2, latest["candidate_hash"], latest["document_id"], 1)
|
||
review = svc.打开候选审阅(author, loc)
|
||
svc.保存人工(
|
||
author,
|
||
"advance",
|
||
"chapter-candidate",
|
||
2 if changed == "source" else 1,
|
||
候选测试.草稿("后来保存的版本"),
|
||
分支="试写" if changed == "source" else "main",
|
||
)
|
||
with pytest.raises(Muse错误):
|
||
候选测试.决定(svc, author, "stale-merge", loc, review)
|
||
assert svc.读取候选(author, candidate["candidate_id"])["stale"]
|
||
assert (
|
||
svc.读取候选(author, candidate["candidate_id"], 版本=1)["visible_text"]
|
||
== candidate["visible_text"]
|
||
)
|
||
|
||
|
||
def test_重叠冲突或过期合并请求不产生候选__234004(候选环境):
|
||
svc, author, _ = 候选环境
|
||
开分支(候选环境)
|
||
svc.保存人工(author, "side", "chapter-candidate", 1, 候选测试.草稿("支线首句"), 分支="试写")
|
||
old_req = 合并请求(svc, author)
|
||
svc.保存人工(author, "main", "chapter-candidate", 1, 候选测试.草稿("主线冲突首句"))
|
||
for req in (old_req, 合并请求(svc, author)):
|
||
with pytest.raises(Muse错误):
|
||
svc.合并分支(author, "conflict", req)
|
||
assert svc.列出候选(author, "chapter-candidate") == []
|
||
assert svc.读取正文(author, "chapter-candidate")["visible_text"].startswith("主线冲突首句")
|