实现侧: - 上下文:任务范围拆分为 范围校验/范围授权;索引按可发现口径重建、索引新鲜度改对称差;依赖校验统一快照漂移说明。 - 知识方法:方法与材料读取口径统一;超限方法材料按可选省略,核对路径不再二次计费;删除无合同的读时重算。 - 任务运行:新增 context.usage/tool.denied 事件类型;连接池常驻并在装配生命周期内开关;调用结算与核对分列。 - 效果评测/审校修订/交付连载/作者经验/作品规划:凭据冻结、标定消费、导出补证、事实引文核对等收尾修复。 - 资源加载:能力正文不再夹带索引用的导航注记(该注记此前进入角色与技能的模型提示)。 - 元数据:受保护骨架与代码保护属性对齐;字段校验与内置结构口径同步。 - 基础设施:环境预检进入装配生命周期;数据库连接运行期字段不参与相等比较;索引指纹归一化 jsonb 浮点。 - 删除被替代实现:7 份旧提示词模板与空壳 资料来源 读取器。 用例侧: - 用例身份与导航元信息迁移;夹具补生命周期、同库暴露与模板封存; - 本轮定向修复:方法材料省略、事实引文、迁移回执、额度与暂停用例、慢用例超时预算等。
226 lines
9.8 KiB
Python
226 lines
9.8 KiB
Python
"""B07真实版本反馈、作者审阅及撤回;无模型响应或私表代写业务结果。"""
|
||
|
||
from dataclasses import replace
|
||
from uuid import uuid4
|
||
|
||
import psycopg
|
||
import pytest
|
||
import test_正文候选与作者决定 as 正文测试
|
||
|
||
from muse.作者经验.接口 import (
|
||
作者经验服务,
|
||
偏好决定,
|
||
偏好范围,
|
||
偏好请求,
|
||
反馈版本,
|
||
反馈请求,
|
||
读取偏好材料,
|
||
)
|
||
from muse.共享.调用身份 import 用途
|
||
from muse.共享.错误 import Muse错误
|
||
from muse.正文写作.接口 import 读取候选依据
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
候选环境 = 正文测试.候选环境
|
||
|
||
|
||
@pytest.fixture
|
||
def 环境(候选环境):
|
||
body, author, pools = 候选环境
|
||
service = 作者经验服务(pools[用途.生产], body.正式)
|
||
_, candidate, _ = 正文测试.新候选(body, author)
|
||
original = body.读取正文(author, "chapter-candidate")
|
||
with pools[用途.生产].连接(只读=True) as conn:
|
||
updated = 读取候选依据(conn, author.作者, candidate["candidate_id"], 1)
|
||
feedback = 反馈请求(
|
||
"work-candidate",
|
||
反馈版本("document", "chapter-candidate", 1, original["document_hash"]),
|
||
反馈版本("candidate", candidate["candidate_id"], 1, updated["document_hash"]),
|
||
"这一次末段不要解释人物感受。",
|
||
"revise",
|
||
)
|
||
return service, author, pools, feedback
|
||
|
||
|
||
def _请求(**changes):
|
||
return 偏好请求(
|
||
**{
|
||
"preference_id": str(uuid4()),
|
||
"topic": "心理描写",
|
||
"text": "不解释人物感受。",
|
||
"quote": "今后不解释人物感受。",
|
||
"scope": 偏好范围(),
|
||
**changes,
|
||
}
|
||
)
|
||
|
||
|
||
def _定位(result, replacements=()):
|
||
return 偏好决定(
|
||
result["preference_id"], result["revision"], result["content_hash"], replacements
|
||
)
|
||
|
||
|
||
def _消费(pools, author):
|
||
with pools[用途.生产].连接(只读=True) as conn:
|
||
return 读取偏好材料(conn, author.作者, "work-candidate")
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w26-26a001",
|
||
environment="隔离PG;实际S01/B05/B09/S02与合成HTTP,不证明文学效果",
|
||
given="真实作者、作品及确切正文反馈版本",
|
||
when="保存范围偏好、审阅冲突、确认、撤回及重新消费",
|
||
then=["反馈保留确切原版本且不能冒充候选采纳"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md",
|
||
)
|
||
def test_反馈保留确切原版本且不能冒充候选采纳__26a001(环境):
|
||
service, author, pools, request = 环境
|
||
saved = service.记录反馈(author, "feedback", request)
|
||
assert service.记录反馈(author, "feedback", request) == saved
|
||
read = service.读取反馈(author, str(saved["feedback_id"]))
|
||
assert "原句「保留」" in read["before_text"]
|
||
assert "改过的首句" in read["after_text"]
|
||
assert read["payload"]["quote"] == request.quote
|
||
with pytest.raises(Muse错误):
|
||
service.记录反馈(author, "feedback", replace(request, quote="改了原话"))
|
||
with pytest.raises(Muse错误):
|
||
service.记录反馈(
|
||
author,
|
||
"bad-hash",
|
||
replace(request, before=replace(request.before, content_hash="0" * 64)),
|
||
)
|
||
with pools[用途.生产].连接(只读=True) as conn:
|
||
assert conn.execute("SELECT count(*) FROM muse_candidate_decision").fetchone()[0] == 0
|
||
assert service.列出偏好(author) == []
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w26-26a002",
|
||
environment="隔离PG;实际S01/B05/B09/S02与合成HTTP,不证明文学效果",
|
||
given="真实作者、作品及确切正文反馈版本",
|
||
when="保存范围偏好、审阅冲突、确认、撤回及重新消费",
|
||
then=["推断偏好待作者审阅确认且撤回保留历史"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md",
|
||
)
|
||
def test_推断偏好待作者审阅确认且撤回保留历史__26a002(环境):
|
||
service, author, pools, feedback = 环境
|
||
fid = service.记录反馈(author, "feedback", feedback)["feedback_id"]
|
||
request = _请求(origin="inferred", feedback_id=str(fid), quote=feedback.quote)
|
||
saved = service.保存偏好(author, "infer", request)["results"][0]
|
||
assert saved["state"] == "pending" and _消费(pools, author) == []
|
||
point = _定位(saved)
|
||
review = service.打开偏好审阅(author, point)
|
||
confirmed = service.确认偏好(
|
||
author, "confirm", point, 审阅ID=review["review_id"], 审阅哈希=review["review_hash"]
|
||
)
|
||
active = confirmed["results"][0]
|
||
assert active["state"] == "active" and _消费(pools, author)[0]["text"] == request.text
|
||
service.撤回偏好(author, "revoke", _定位(active))
|
||
assert _消费(pools, author) == []
|
||
assert service.读取偏好(author, request.preference_id, 2)["state"] == "active"
|
||
assert service.读取偏好(author, request.preference_id, 1)["payload"]["quote"] == feedback.quote
|
||
assert (
|
||
service.确认偏好(
|
||
author, "confirm", point, 审阅ID=review["review_id"], 审阅哈希=review["review_hash"]
|
||
)
|
||
== confirmed
|
||
)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w26-26a003",
|
||
environment="隔离PG;实际S01/B05/B09/S02与合成HTTP,不证明文学效果",
|
||
given="真实作者、作品及确切正文反馈版本",
|
||
when="保存范围偏好、审阅冲突、确认、撤回及重新消费",
|
||
then=["显式范围冲突须点名旧版本而非自动覆盖"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md",
|
||
)
|
||
def test_显式范围冲突须点名旧版本而非自动覆盖__26a003(环境):
|
||
service, author, pools, _ = 环境
|
||
first = service.保存偏好(author, "first", _请求())["results"][0]
|
||
other = _请求(
|
||
text="允许解释人物感受。",
|
||
quote="这本书允许解释。",
|
||
scope=偏好范围("work", "work-candidate"),
|
||
)
|
||
second = service.保存偏好(author, "second", other)["results"][0]
|
||
assert first["state"] == "active" and second["state"] == "pending"
|
||
assert _消费(pools, author)[0]["preference_id"] == first["preference_id"]
|
||
point = _定位(second)
|
||
review = service.打开偏好审阅(author, point)
|
||
with pytest.raises(Muse错误, match="冲突"):
|
||
service.确认偏好(
|
||
author, "bad-confirm", point, 审阅ID=review["review_id"], 审阅哈希=review["review_hash"]
|
||
)
|
||
point = _定位(second, ((first["preference_id"], first["revision"]),))
|
||
review = service.打开偏好审阅(author, point)
|
||
service.确认偏好(
|
||
author, "confirm", point, 审阅ID=review["review_id"], 审阅哈希=review["review_hash"]
|
||
)
|
||
assert [x["text"] for x in _消费(pools, author)] == [other.text]
|
||
assert service.读取偏好(author, first["preference_id"])["state"] == "withdrawn"
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w26-26a004",
|
||
environment="隔离PG;实际S01/B05/B09/S02与合成HTTP,不证明文学效果",
|
||
given="真实作者、作品及确切正文反馈版本",
|
||
when="保存范围偏好、审阅冲突、确认、撤回及重新消费",
|
||
then=["审阅后偏好变化拒绝旧批准和旧修改"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md",
|
||
)
|
||
def test_审阅后偏好变化拒绝旧批准和旧修改__26a004(环境):
|
||
service, author, _, feedback = 环境
|
||
fid = service.记录反馈(author, "feedback", feedback)["feedback_id"]
|
||
req = _请求(origin="inferred", feedback_id=str(fid), quote=feedback.quote)
|
||
first = service.保存偏好(author, "infer", req)["results"][0]
|
||
point = _定位(first)
|
||
review = service.打开偏好审阅(author, point)
|
||
service.保存偏好(author, "edit", replace(req, text="保留必要解释。", expected_revision=1))
|
||
with pytest.raises(Muse错误):
|
||
service.确认偏好(
|
||
author, "stale", point, 审阅ID=review["review_id"], 审阅哈希=review["review_hash"]
|
||
)
|
||
with pytest.raises(Muse错误):
|
||
service.保存偏好(author, "stale-edit", replace(req, expected_revision=1))
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w26-26a005",
|
||
environment="隔离PG;实际S01/B05/B09/S02与合成HTTP,不证明文学效果",
|
||
given="真实作者、作品及确切正文反馈版本",
|
||
when="保存范围偏好、审阅冲突、确认、撤回及重新消费",
|
||
then=["偏好及反馈拒绝异作者及评测用途"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md",
|
||
)
|
||
def test_偏好及反馈拒绝异作者及评测用途__26a005(环境):
|
||
service, author, pools, request = 环境
|
||
fid = str(service.记录反馈(author, "feedback", request)["feedback_id"])
|
||
pref = service.保存偏好(author, "pref", _请求())["results"][0]
|
||
stranger = replace(author, 作者="stranger")
|
||
for action in [
|
||
lambda: service.读取反馈(stranger, fid),
|
||
lambda: service.读取偏好(stranger, pref["preference_id"]),
|
||
lambda: service.保存偏好(replace(author, 用途=用途.评测), "x", _请求()),
|
||
]:
|
||
with pytest.raises(Muse错误):
|
||
action()
|
||
with pools[用途.评测].连接() as conn, pytest.raises(psycopg.errors.InsufficientPrivilege):
|
||
conn.execute("SELECT * FROM muse_author_feedback")
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w26-26a006",
|
||
environment="隔离PG;实际S01/B05/B09/S02与合成HTTP,不证明文学效果",
|
||
given="真实作者、作品及确切正文反馈版本",
|
||
when="保存范围偏好、审阅冲突、确认、撤回及重新消费",
|
||
then=["单次要求不被登记为作者长期偏好"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md",
|
||
)
|
||
def test_单次要求不被登记为作者长期偏好__26a006(环境):
|
||
with pytest.raises(Muse错误, match="一次性"):
|
||
_请求(duration="request")
|
||
with pytest.raises(Muse错误, match="反馈"):
|
||
_请求(origin="inferred")
|