muse-agent-example/tests/集成/test_案例采集与复核.py
zizi cf0f4fb985 W20–W24:保存知识方法、迁移框架、审校修订与案例行为的集成成果
接续 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。
2026-09-13 16:24:42 +08:00

724 lines
28 KiB
Python

"""案例的真实来源、许可与确认,不把元信息声明当原文授权。"""
import hashlib
from concurrent.futures import ThreadPoolExecutor
import pytest
from muse.共享.调用身份 import 用途
from muse.资料研究.接口 import 导入请求, 资料服务, 资料错误
pytestmark = pytest.mark.数据库
def test_参考作品归属稳定且无sample许可只返回哈希__240001(应用测试库):
pool = 应用测试库[用途.生产]
svc = 资料服务()
text = "仅作案例的合成文字。"
request = 导入请求(
"reference", "合成书", "synthetic:reference-a", text, ("analysis",), "synthetic:book-a"
)
with pool.连接() as conn, conn.transaction():
source = svc.导入(conn, "case-author", request)
assert svc.导入(
conn,
"case-author",
导入请求("reference", "合成书", request.origin, text, ("analysis",)),
).重复
evidence = svc.读取案例证据(conn, "case-author", source.source_id, 1, 0, 5)
assert evidence["excerpt"] is None and not evidence["text_allowed"]
assert evidence["excerpt_hash"] == hashlib.sha256(text[:5].encode()).hexdigest()
assert evidence["work_group"] == "synthetic:book-a"
with pytest.raises(资料错误):
svc.读取案例证据(conn, "other", source.source_id, 1, 0, 5)
with pytest.raises(资料错误, match="另一参考作品"):
svc.导入(
conn,
"case-author",
导入请求(
"reference", "新标题", request.origin, text, ("sample",), "synthetic:other-book"
),
)
with pytest.raises(资料错误, match="未授权"):
svc.核对来源授权(conn, source.source_id, "sample")
with pool.连接() as conn, conn.transaction():
new = svc.导入(
conn,
"case-author",
导入请求(
"reference",
"样例书",
"synthetic:reference-sample",
text,
("sample",),
"synthetic:book-b",
),
)
evidence = svc.读取案例证据(conn, "case-author", new.source_id, 1, 0, 5)
assert evidence["excerpt"] == text[:5] and evidence["text_allowed"]
def test_导入串行保留两种授权且同内容不能静默补归属__240002(应用测试库):
pool = 应用测试库[用途.生产]
svc = 资料服务()
text = "并发导入的同一原文。"
def add(use):
with pool.连接() as conn, conn.transaction():
return svc.导入(
conn,
"case-author",
导入请求(
"reference",
"同一本书",
"synthetic:same-origin",
text,
(use,),
"synthetic:same-book",
),
)
with ThreadPoolExecutor(max_workers=2) as executor:
a, b = list(executor.map(add, ["analysis", "sample"]))
assert a.source_id == b.source_id and a.revision == b.revision == 1
with pool.连接() as conn, conn.transaction():
assert set(svc.核对来源授权(conn, a.source_id, "sample")["authorized_uses"]) == {
"sample",
"analysis",
}
old = svc.导入(
conn,
"case-author",
导入请求("reference", "旧未分类资料", "synthetic:unknown-work", text, ("analysis",)),
)
with pytest.raises(资料错误, match="不能静默"):
svc.导入(
conn,
"case-author",
导入请求(
"reference",
"旧未分类资料",
"synthetic:unknown-work",
text,
("sample",),
"synthetic:claimed-book",
),
)
with pytest.raises(资料错误, match="未授权"):
svc.核对来源授权(conn, old.source_id, "sample")
@pytest.fixture
def 案例环境(章后环境):
from muse.审校修订.接口 import 案例来源, 案例采集请求
app, author = 章后环境["装配"], 章后环境["作者"]
text = "屋里只有甲。他看着窗外。雨落在街上。"
def source(origin="synthetic:quality-case", uses=("sample",), preserve=True):
with app.要求数据库().连接() as conn, conn.transaction():
row = app.要求资料().导入(
conn,
author.作者,
导入请求("reference", "合成案例来源", origin, text, uses, "synthetic:book-a"),
)
loc = 案例来源(
"source",
row.source_id,
row.revision,
row.content_hash,
0,
6,
hashlib.sha256(text[:6].encode()).hexdigest(),
)
return 案例采集请求(loc, preserve_text=preserve)
return app, author, source, text
def _采集(app, author, command, request):
from muse.审校修订.接口 import 案例定位
result = app.要求审校().采集案例(author, command, request)["results"][0]
return 案例定位(result["case_id"], result["revision"], result["case_hash"])
def _复核请求(loc, label="sf"):
from muse.审校修订.接口 import 案例复核请求
return 案例复核请求(
loc, label, "retain" if label == "snf" else "repair", "人工阅读真实片段后的分类。"
)
def _确认(app, author, loc, command="confirm-case"):
svc = app.要求审校()
req = _复核请求(loc)
review = svc.打开案例审阅(author, req)
return svc.决定案例(
author, command, req, 审阅ID=review["review_id"], 审阅哈希=review["review_hash"]
)
@pytest.mark.parametrize("sample,preserve", [(False, True), (True, False)])
def test_未授权案例仅元信息且不能确认__240003(案例环境, sample, preserve):
import json
from muse.共享.错误 import Muse错误
app, author, source, text = 案例环境
req = source(uses=("sample",) if sample else ("analysis",), preserve=preserve)
loc = _采集(app, author, "capture-metadata", req)
svc = app.要求审校()
row = svc.读取案例(author, loc.case_id)
assert row["state"] == "shadow" and not row["sampleable"]
assert row["payload"]["evidence"]["before"]["excerpt"] is None
assert row["payload"]["evidence"]["before"]["context"] is None
with pytest.raises(Muse错误, match="哈希元信息"):
svc.打开案例审阅(author, _复核请求(loc))
with app.要求数据库().连接(只读=True) as conn:
stored = conn.execute(
"SELECT payload FROM muse_quality_case_version WHERE case_id=%s", (loc.case_id,)
).fetchone()[0]
commands = conn.execute(
"SELECT to_jsonb(c) FROM muse_change_command c WHERE command_id='capture-metadata'"
).fetchone()[0]
assert text[:6] not in json.dumps([stored, commands], ensure_ascii=False)
assert len(svc.列出案例(author)) == 1
@pytest.mark.parametrize("bad", ["quote", "source", "bounds", "extra_text"])
def test_伪引文或非法范围在采集前拒绝__240004(案例环境, bad):
from dataclasses import asdict, replace
from pydantic import TypeAdapter, ValidationError
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例采集请求
app, author, source, _ = 案例环境
req = source()
with pytest.raises((Muse错误, ValidationError)):
if bad == "extra_text":
TypeAdapter(案例采集请求).validate_python(
{**asdict(req), "before_excerpt": "不允许输入正文"}
)
else:
changes = (
{"excerpt_hash": "0" * 64}
if bad == "quote"
else {"source_hash": "0" * 64}
if bad == "source"
else {"end": 900}
)
app.要求审校().采集案例(
author, "bad-case", replace(req, before=replace(req.before, **changes))
)
assert app.要求审校().列出案例(author) == []
with app.要求数据库().连接(只读=True) as conn:
assert (
conn.execute(
"SELECT count(*) FROM muse_change_command WHERE command_id='bad-case'"
).fetchone()[0]
== 0
)
def test_确认需真实审阅且撤回不改历史__240005(案例环境):
import psycopg
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例定位
app, author, source, text = 案例环境
req = source()
svc = app.要求审校()
loc = _采集(app, author, "capture-one", req)
assert _采集(app, author, "capture-one", req) == loc
assert not svc.读取案例(author, loc.case_id)["sampleable"]
with pytest.raises(Muse错误):
svc.决定案例(
author,
"fake-review",
_复核请求(loc),
审阅ID="00000000-0000-0000-0000-000000000000",
审阅哈希="0" * 64,
)
receipt = _确认(app, author, loc)
saved = svc.读取案例(author, loc.case_id)
assert saved["state"] == "confirmed" and saved["sampleable"]
assert saved["revision"] == 2 and saved["payload"]["evidence"]["before"]["excerpt"] == text[:6]
assert receipt["action"] == "adopt"
target = 案例定位(loc.case_id, saved["revision"], saved["case_hash"])
svc.撤回案例(author, "withdraw", target)
current = svc.读取案例(author, loc.case_id)
assert current["state"] == "withdrawn" and not current["sampleable"]
old = svc.读取案例(author, loc.case_id, revision=2)
assert old["payload"] == saved["payload"] and old["case_hash"] == saved["case_hash"]
assert not old["sampleable"]
with app.要求数据库().连接() as conn:
with pytest.raises(psycopg.Error), conn.transaction():
conn.execute(
"UPDATE muse_quality_case_version SET state='shadow' WHERE case_id=%s",
(loc.case_id,),
)
def test_来源推进阻止旧审阅但可重新审历史__240006(案例环境):
from muse.共享.错误 import Muse错误
app, author, source, text = 案例环境
req = source()
svc = app.要求审校()
loc = _采集(app, author, "capture-old", req)
review = svc.打开案例审阅(author, _复核请求(loc))
with app.要求数据库().连接() as conn, conn.transaction():
app.要求资料().导入(
conn,
author.作者,
导入请求(
"reference",
"合成案例来源",
"synthetic:quality-case",
text + "门开了。",
("sample",),
),
)
with pytest.raises(Muse错误):
svc.决定案例(
author,
"stale-review",
_复核请求(loc),
审阅ID=review["review_id"],
审阅哈希=review["review_hash"],
)
assert svc.读取案例(author, loc.case_id)["state"] == "shadow"
_确认(app, author, loc)
assert svc.读取案例(author, loc.case_id)["sampleable"]
def test_许可撤回即时隐藏原文且阻止确认__240007(案例环境):
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例定位
app, author, source, _ = 案例环境
req = source()
svc = app.要求审校()
first = _采集(app, author, "confirmed-before-revoke", req)
_确认(app, author, first)
second = _采集(app, author, "pending-before-revoke", req)
review = svc.打开案例审阅(author, _复核请求(second))
with app.要求数据库().连接() as conn, conn.transaction():
conn.execute(
"UPDATE muse_source SET authorized_uses=%s::jsonb WHERE source_id=%s",
('["analysis"]', req.before.ref_id),
)
with pytest.raises(Muse错误):
svc.决定案例(
author,
"revoked-case",
_复核请求(second),
审阅ID=review["review_id"],
审阅哈希=review["review_hash"],
)
row = svc.读取案例(author, first.case_id)
assert row["state"] == "confirmed" and not row["sampleable"]
assert row["payload"]["evidence"]["before"]["excerpt"] is None
assert row["payload"]["review_note"] is None
svc.撤回案例(
author, "withdraw-unlicensed", 案例定位(first.case_id, row["revision"], row["case_hash"])
)
assert svc.读取案例(author, first.case_id)["state"] == "withdrawn"
@pytest.mark.parametrize("after_kind", ["candidate", "document"])
def test_真实反馈绑定确切正文候选与S01回执__240008(案例环境, after_kind):
from dataclasses import replace
from muse.作品规划.接口 import 档案保存
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例来源, 案例采集请求
from muse.正式变更.接口 import 作者动作
from muse.正文写作.接口 import 候选定位, 文本节点, 正文草稿, 段落
app, author, _, _ = 案例环境
works, body, cases = app.要求作品(), app.要求正文(), app.要求审校()
schema = works.新档案结构(author, "case-work", "work_core", 1)
works.保存档案(
author, "create-case-work", 档案保存("case-work", 0, {"名称": "案例作品"}, schema)
)
works.添加章节(author, "create-case-ch", "case-work", "case-ch", "第一章", 预期目录版本=0)
original, changed = "甲走进了门里。", "甲推开门走进去。"
def draft(text):
return 正文草稿((段落("p1", (文本节点(text),)),))
body.保存人工(author, "before-text", "case-ch", 0, draft(original))
before = body.读取正文(author, "case-ch")
if after_kind == "candidate":
candidate = body.创建人工候选(author, "after-candidate", "case-ch", 1, draft(changed))[
"results"
][0]
row = body.读取候选(author, candidate["candidate_id"])
loc = 候选定位(
row["candidate_id"], row["revision"], row["candidate_hash"], before["document_id"], 1
)
review = body.打开候选审阅(author, loc)
receipt = body.决定候选(
author,
"choose-original",
loc,
作者动作.拒绝,
review["review_id"],
review["review_hash"],
(),
)
from muse.正文写作.接口 import 正文结构哈希
after = 案例来源(
"candidate",
row["candidate_id"],
row["revision"],
正文结构哈希(draft(changed)),
0,
len(changed),
hashlib.sha256(changed.encode()).hexdigest(),
"main",
)
else:
receipt = body.保存人工(author, "after-text", "case-ch", 1, draft(changed))
row = body.读取正文(author, "case-ch")
after = 案例来源(
"document",
"case-ch",
2,
row["document_hash"],
0,
len(changed),
hashlib.sha256(changed.encode()).hexdigest(),
"main",
)
request = 案例采集请求(
案例来源(
"document",
"case-ch",
1,
before["document_hash"],
0,
len(original),
hashlib.sha256(original.encode()).hexdigest(),
"main",
),
after,
mode="live_feedback",
preserve_text=True,
feedback_command_id=receipt["command_id"],
)
with pytest.raises(Muse错误):
cases.采集案例(author, "wrong-receipt", replace(request, feedback_command_id="before-text"))
target = _采集(app, author, "actual-feedback", request)
saved = cases.读取案例(author, target.case_id)
assert saved["payload"]["feedback"] == {
k: receipt[k] for k in ("command_id", "receipt_id", "action")
}
assert saved["payload"]["evidence"]["before"]["excerpt"] == original
assert saved["payload"]["evidence"]["after"]["excerpt"] == changed
assert saved["payload"]["evidence"]["before"]["work_group"] == "work:case-work"
assert not saved["sampleable"]
_确认(app, author, target)
assert cases.读取案例(author, target.case_id)["sampleable"]
assert body.读取正文(author, "case-ch")["revision"] == (1 if after_kind == "candidate" else 2)
@pytest.fixture
def 四类案例(案例环境):
from muse.审校修订.接口 import 案例定位, 案例来源, 案例采集请求
app, author, _, _ = 案例环境
svc = app.要求审校()
def group(works=("book-a", "book-b"), labels=("sf", "snf", "boundary", "regression")):
refs = []
for i, label in enumerate(labels):
text = f"第{i}份例证。前半句作为证据,后半句保留语境。"
with app.要求数据库().连接() as conn, conn.transaction():
row = app.要求资料().导入(
conn,
author.作者,
导入请求(
"reference",
"已声明书目",
f"synthetic:rule-source:{i}",
text,
("sample",),
works[i % len(works)],
),
)
source = 案例来源(
"source",
row.source_id,
1,
row.content_hash,
0,
7,
hashlib.sha256(text[:7].encode()).hexdigest(),
)
c = _采集(app, author, f"sample-case-{i}", 案例采集请求(source, preserve_text=True))
r = _复核请求(c, label)
review = svc.打开案例审阅(author, r)
svc.决定案例(
author,
f"confirm-{i}",
r,
审阅ID=review["review_id"],
审阅哈希=review["review_hash"],
)
case = svc.读取案例(author, c.case_id)
refs.append(案例定位(c.case_id, case["revision"], case["case_hash"]))
return tuple(refs)
return app, author, group
def _规则草案():
return {
"id": "case-rule",
"name": "待评的案例规则",
"layer": "semantic",
"carrier_scope": "all",
"trigger": {"type": "model_judgment", "criteria": "根据片段前后语境核对功能是否重复。"},
"default_disposition": "advisory",
"fix_hint": "先判断功能,保留有叙事作用的重复。",
"version": 1,
}
def test_四类跨书确认案例才能提出可追溯候选__240009(四类案例):
from dataclasses import replace
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例规则请求
app, author, group = 四类案例
refs = group()
svc = app.要求审校()
req = 案例规则请求(_规则草案(), refs)
result = svc.提出案例规则(author, req)
assert result["status"] == "candidate" and not result["duplicate"]
assert svc.提出案例规则(author, replace(req, cases=tuple(reversed(refs))))["duplicate"]
library = svc.读取规则库(author, 预览候选=True)
rule = library["rules"]["case-rule"]
assert rule["status"] == "candidate" and set(rule["samples"]) == {
"sf",
"snf",
"boundary",
"regression",
}
assert set(rule["case_card_ids"]) == {r.case_id for r in refs}
assert svc.读取规则库(author)["rules"] == {}
for sample in library["samples"].values():
case = svc.读取案例(author, sample["case_card_id"])
assert sample["text"] == case["payload"]["evidence"]["before"]["excerpt"]
assert case["case_hash"] in sample["source_ref"]
svc.撤回案例(author, "withdraw-rule-evidence", refs[0])
with pytest.raises(Muse错误, match="当前已确认"):
svc.读取规则库(author, 预览候选=True)
with pytest.raises(Muse错误, match="当前已确认"):
svc.提出案例规则(author, replace(req, definition={**req.definition, "version": 2}))
with app.要求数据库().连接(只读=True) as conn:
assert (
conn.execute(
"SELECT count(*) FROM muse_rule_version WHERE rule_id='case-rule'"
).fetchone()[0]
== 1
)
assert conn.execute("SELECT count(*) FROM muse_rule_activation").fetchone()[0] == 0
@pytest.mark.parametrize("bad", ["one_book", "unknown_book", "only_positive"])
def test_单书未知归属或单边案例不能形成规则__24000a(四类案例, bad):
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例规则请求
app, author, group = 四类案例
refs = (
group(works=("one-book",))
if bad == "one_book"
else group(works=(None,))
if bad == "unknown_book"
else group(labels=("sf",) * 4)
)
with pytest.raises(Muse错误, match="作品|四类"):
app.要求审校().提出案例规则(author, 案例规则请求(_规则草案(), refs))
with app.要求数据库().连接(只读=True) as conn:
assert (
conn.execute(
"SELECT count(*) FROM muse_rule_version WHERE rule_id='case-rule'"
).fetchone()[0]
== 0
)
def test_HTTP与CLI采集确认重放共用真实回执__24000b(案例环境, tmp_path):
import json
from dataclasses import asdict, replace
from fastapi.testclient import TestClient
from muse.审校修订.接口 import 案例定位
from muse.接入.cli.审校命令 import 运行审校命令
from muse.接入.http.应用 import 创建应用
from muse.配置 import 服务配置
app, author, source, text = 案例环境
request = {"command_id": "http-case", "request": asdict(source())}
secret = tmp_path / "password"
secret.write_text("synthetic-case-password")
secret.chmod(0o600)
app.配置 = replace(
app.配置,
HTTP=服务配置(
str(secret),
作者ID=author.作者,
公开地址="http://testserver",
允许来源=("http://testserver",),
),
)
http = 创建应用(app.配置)
path = tmp_path / "case-request.json"
with TestClient(http, headers={"origin": "http://testserver"}) as client:
http.state.装配 = app
assert client.post("/api/v1/quality-cases", json=request).status_code == 401
assert (
client.post("/api/v1/session", json={"password": secret.read_text()}).status_code == 200
)
response = client.post("/api/v1/quality-cases", json=request)
assert response.status_code == 201, response.text
path.write_text(json.dumps(request))
assert 运行审校命令(app, "案例采集", str(path)) == response.json()
result = response.json()["results"][0]
loc = 案例定位(result["case_id"], 1, result["case_hash"])
req = asdict(_复核请求(loc))
review = client.post("/api/v1/quality-case-reviews", json=req)
assert review.status_code == 200, review.text
decision = {
"command_id": "http-case-confirm",
"request": req,
"action": "adopt",
"review_id": review.json()["review_id"],
"review_hash": review.json()["review_hash"],
}
path.write_text(json.dumps(decision))
receipt = 运行审校命令(app, "案例决定", str(path))
assert client.post("/api/v1/quality-case-decisions", json=decision).json() == receipt
current = client.get(f"/api/v1/quality-cases/{loc.case_id}").json()
assert current["state"] == "confirmed" and current["sampleable"]
assert current == 运行审校命令(app, "案例", loc.case_id)
assert len(运行审校命令(app, "案例清单", None)) == 1
source_response = client.post(
"/api/v1/sources/import?work_id=synthetic:case",
json={
"kind": "reference",
"title": "合成来源",
"origin": "synthetic:http-group",
"content": text,
"authorized_uses": ["sample"],
"reference_work_ref": "synthetic:declared-book",
},
)
assert source_response.status_code == 201, source_response.text
source_id = source_response.json()["source_id"]
source_row = client.get(f"/api/v1/sources/{source_id}/versions/1").json()
assert source_row["import_result"]["参考作品归属"] == "synthetic:declared-book"
def test_同组案例支持两条规则且整库和诊断可读__24000c(四类案例):
from muse.审校修订.接口 import 案例规则请求
from muse.正文写作.接口 import 文本节点, 正文草稿, 段落
app, author, group = 四类案例
refs = group()
svc, body = app.要求审校(), app.要求正文()
first = _规则草案()
svc.提出案例规则(author, 案例规则请求(first, refs))
before = svc.读取规则库(author, 预览候选=True)
second = {**first, "id": "case-rule-second"}
svc.提出案例规则(author, 案例规则请求(second, refs))
after = svc.读取规则库(author, 预览候选=True)
assert set(after["rules"]) == {first["id"], second["id"]}
assert len(after["samples"]) == 8
assert after["rules"][first["id"]] == before["rules"][first["id"]]
assert all(after["samples"][key] == value for key, value in before["samples"].items())
assert {s["case_card_id"] for s in after["samples"].values()} == {r.case_id for r in refs}
assert len({s["source_ref"] for s in after["samples"].values()}) == 4
body.保存人工(
author,
"diagnose-shared-cases",
"ch-1",
0,
正文草稿((段落("p1", (文本节点("诊断仍可组合多个案例规则。"),)),)),
)
doc = body.读取正文(author, "ch-1")
target = {
"work_id": "post-work",
"chapter_id": "ch-1",
"branch_id": "main",
"revision": doc["revision"],
"document_hash": doc["document_hash"],
}
result = svc.生成诊断(author, target, 预览候选=True)
assert result["report"]["rule_library_version"] == after["fingerprint"]
assert svc.读取诊断(author, result["diagnosis_id"])["report"] == result["report"]
assert body.读取正文(author, "ch-1") == doc
@pytest.mark.parametrize("change", ["withdraw", "permission"])
def test_案例依据失效后旧诊断仍可读取并标过期__24000d(四类案例, change):
import json
from muse.共享.错误 import Muse错误
from muse.审校修订.接口 import 案例规则请求
from muse.正文写作.接口 import 文本节点, 正文草稿, 段落
app, author, group = 四类案例
refs = group()
svc, body = app.要求审校(), app.要求正文()
svc.提出案例规则(author, 案例规则请求(_规则草案(), refs))
case = svc.读取案例(author, refs[0].case_id)
excerpt = case["payload"]["evidence"]["before"]["excerpt"]
body.保存人工(
author,
"diagnose-before-revocation",
"ch-1",
0,
正文草稿((段落("p1", (文本节点("我的正文只保留自己的历史报告。"),)),)),
)
doc = body.读取正文(author, "ch-1")
target = {
"work_id": "post-work",
"chapter_id": "ch-1",
"branch_id": "main",
"revision": doc["revision"],
"document_hash": doc["document_hash"],
}
result = svc.生成诊断(author, target, 预览候选=True)
assert not svc.读取诊断(author, result["diagnosis_id"])["stale"]
if change == "withdraw":
svc.撤回案例(author, "withdraw-diagnosis-case", refs[0])
else:
source_id = case["payload"]["request"]["before"]["ref_id"]
with app.要求数据库().连接() as conn, conn.transaction():
conn.execute(
"UPDATE muse_source SET authorized_uses=%s::jsonb WHERE source_id=%s",
('["analysis"]', source_id),
)
readback = svc.读取诊断(author, result["diagnosis_id"])
assert readback["stale"] and any("规则依据失效" in r for r in readback["stale_reasons"])
assert readback["report"] == result["report"]
assert excerpt not in json.dumps(readback, ensure_ascii=False)
with pytest.raises(Muse错误):
svc.生成诊断(author, target, 预览候选=True)
assert body.读取正文(author, "ch-1") == doc
with app.要求数据库().连接(只读=True) as conn:
assert conn.execute("SELECT count(*) FROM muse_diagnosis").fetchone()[0] == 1