- src/muse 新版全模块(装配/共享/上下文/任务运行/作品规划/故事世界/正文写作/审校修订/知识方法/作者经验/效果评测/交付连载/资料研究/正式变更/元数据/接入/基础设施/编排)+ 测试树(单元/契约/集成/架构/迁移/端到端/夹具) - 129 项功能全部实现与自动验证(功能覆盖.json/矩阵),含 W31 补齐的规则与代价/节奏安排/伏笔与承诺 - 旧实现按处置清单退出(702 条中 324 删,保护合同与未迁移条目留存有据);web/app.py 旧工作台退役,新工作台为唯一写入口 - 数据库/旧库迁移:真实旧库内容批次迁移链(端点守卫/PG作品正文映射/质量资产缺省投影) - 运行手册 docs/运行手册.md;W30 本机服务阶段一已运行(infra PG 为正式内容权威) - R2 执行证据与私有运行材料在 .agents.local/改造/R2-20260909/(不入库)
360 lines
13 KiB
Python
360 lines
13 KiB
Python
"""B06规则启停与实际消费;审阅决定始终由S01保存。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import asdict, dataclass
|
||
from typing import Annotated, Literal
|
||
from uuid import UUID
|
||
|
||
from pydantic import Field
|
||
|
||
from muse.审校修订.存储 import 审校存储
|
||
from muse.审校修订.机器味规则 import 核对规则
|
||
from muse.审校修订.模型 import 审校错误
|
||
from muse.正式变更.接口 import (
|
||
作者动作,
|
||
依赖引用,
|
||
修改影响,
|
||
参与操作,
|
||
固定哈希,
|
||
审阅内容,
|
||
提交计划,
|
||
读取作者决定,
|
||
)
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class 规则状态命令:
|
||
rule_id: str
|
||
version: Annotated[int, Field(strict=True, ge=1)]
|
||
action: Literal["enable", "disable"]
|
||
expected_activation_revision: Annotated[int, Field(strict=True, ge=0)] = 0
|
||
credential_id: str = ""
|
||
|
||
def __post_init__(self):
|
||
if (
|
||
not self.rule_id
|
||
or self.action not in {"enable", "disable"}
|
||
or type(self.version) is not int
|
||
or self.version < 1
|
||
or type(self.expected_activation_revision) is not int
|
||
or self.expected_activation_revision < 0
|
||
):
|
||
raise 审校错误("规则状态命令需要精确规则、版本和激活基线")
|
||
if self.action == "enable":
|
||
try:
|
||
UUID(self.credential_id)
|
||
except (ValueError, TypeError, AttributeError):
|
||
raise 审校错误("规则启用需要B10具体诊断用途凭据") from None
|
||
elif self.credential_id:
|
||
raise 审校错误("规则停用不得夹带另一份启用凭据")
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class 规则状态写入:
|
||
作者: str
|
||
命令ID: str
|
||
review_id: str
|
||
命令: 规则状态命令
|
||
version_id: str
|
||
candidate_id: str
|
||
candidate_hash: str
|
||
|
||
|
||
def _版本(store: 审校存储, author: str, command: 规则状态命令):
|
||
row = store.读取规则版本(author, command.rule_id, command.version)
|
||
if row is None or 固定哈希(row["payload"]) != row["payload_hash"]:
|
||
raise 审校错误("规则版本不存在、不属于本作者或哈希不符")
|
||
rule = row["payload"]["rule"]
|
||
核对规则(rule, row["payload"]["samples"])
|
||
if (
|
||
rule["id"] != command.rule_id
|
||
or rule["version"] != command.version
|
||
or rule["layer"] == "semantic"
|
||
or rule["trigger"]["type"] == "model_judgment"
|
||
):
|
||
raise 审校错误("启用用途只接受精确的B06非语义确定性规则")
|
||
return row
|
||
|
||
|
||
def _target(row: dict, rule_id: str, version: int) -> dict:
|
||
return {
|
||
"kind": "diagnostic_rule",
|
||
"target_ref": "B06.rule:" + rule_id,
|
||
"version": str(version),
|
||
"version_id": str(row["version_id"]),
|
||
"content_hash": row["payload_hash"],
|
||
"rule_hash": 固定哈希(row["payload"]["rule"]),
|
||
"examples_hash": 固定哈希(
|
||
{key: row["payload"]["samples"][key] for key in sorted(row["payload"]["samples"])}
|
||
),
|
||
}
|
||
|
||
|
||
def 读取规则目标(conn, author: str, rule_id: str, version: int) -> dict:
|
||
if not rule_id or type(version) is not int or version < 1:
|
||
raise 审校错误("规则目标需要明确规则身份与正数版本")
|
||
store = 审校存储(conn)
|
||
row = store.读取规则版本(author, rule_id, version)
|
||
if row is None or 固定哈希(row["payload"]) != row["payload_hash"]:
|
||
raise 审校错误("规则版本不存在、不属于本作者或哈希不符")
|
||
rule = row["payload"]["rule"]
|
||
核对规则(rule, row["payload"]["samples"])
|
||
if rule["id"] != rule_id or rule["version"] != version:
|
||
raise 审校错误("规则内容与精确版本身份不一致")
|
||
latest = store.最新规则版本(author, rule_id)
|
||
return {
|
||
"target": _target(row, rule_id, version),
|
||
"candidate_status": rule["status"],
|
||
"is_latest": bool(latest and str(latest["version_id"]) == str(row["version_id"])),
|
||
"activation_recorded": row["activation_recorded"],
|
||
}
|
||
|
||
|
||
def 列出规则诊断消费(conn, author: str, rule_id: str, version: int) -> list[dict]:
|
||
projection = 读取规则目标(conn, author, rule_id, version)
|
||
target = projection["target"]
|
||
return 审校存储(conn).列规则诊断消费(author, target["version_id"], target["content_hash"])
|
||
|
||
|
||
def _s01_target(author: str, rule_id: str) -> str:
|
||
return f"rule:{author}:{rule_id}"
|
||
|
||
|
||
def _current_basis(current: dict | None):
|
||
if current is None:
|
||
return None
|
||
return {
|
||
key: current[key]
|
||
for key in (
|
||
"rule_id",
|
||
"activation_revision",
|
||
"version_id",
|
||
"state",
|
||
"credential_id",
|
||
"latest_event_id",
|
||
"action",
|
||
"candidate_id",
|
||
"candidate_hash",
|
||
"review_id",
|
||
"command_id",
|
||
)
|
||
}
|
||
|
||
|
||
def _核对命令(conn, author: str, command: 规则状态命令, *, protect=False):
|
||
store = 审校存储(conn)
|
||
row = _版本(store, author, command)
|
||
current = store.读取规则激活(author, command.rule_id)
|
||
actual_revision = int(current["activation_revision"]) if current else 0
|
||
if actual_revision != command.expected_activation_revision:
|
||
raise 审校错误("规则激活基线已改变")
|
||
latest = store.最新规则版本(author, command.rule_id)
|
||
if latest is None:
|
||
raise 审校错误("规则当前版本不存在")
|
||
credential = None
|
||
if command.action == "enable":
|
||
if latest["revision"] != command.version or str(latest["version_id"]) != str(
|
||
row["version_id"]
|
||
):
|
||
raise 审校错误("旧规则版本不得在新版本发布后启用")
|
||
if current and current["state"] == "active":
|
||
raise 审校错误("规则已激活;替换前须先明确停用")
|
||
from muse.效果评测.接口 import 核对规则诊断凭据, 评测错误
|
||
|
||
try:
|
||
credential = 核对规则诊断凭据(
|
||
conn, author, command.credential_id, _target(row, command.rule_id, command.version)
|
||
)
|
||
except 评测错误 as exc:
|
||
raise 审校错误("规则诊断凭据不可用:" + exc.说明) from None
|
||
else:
|
||
if (
|
||
current is None
|
||
or current["state"] != "active"
|
||
or current["version_id"] != str(row["version_id"])
|
||
):
|
||
raise 审校错误("只能停用当前实际激活的精确规则版本")
|
||
if protect:
|
||
store.锁定规则版本(author, command.rule_id)
|
||
store.锁定规则激活(author, command.rule_id)
|
||
return row, current, latest, credential
|
||
|
||
|
||
class 规则状态入口:
|
||
身份 = "B06.change_rule_state"
|
||
请求类型 = 规则状态命令
|
||
|
||
def 查看(self, conn, identity, change):
|
||
command = change.业务请求
|
||
row, current, latest, credential = _核对命令(conn, identity.作者, command)
|
||
target = _s01_target(identity.作者, command.rule_id)
|
||
revision = int(current["activation_revision"]) if current else 0
|
||
next_revision = revision + 1
|
||
candidate_hash = 固定哈希(
|
||
[
|
||
asdict(command),
|
||
str(row["version_id"]),
|
||
row["payload_hash"],
|
||
credential["receipt_hash"] if credential else None,
|
||
]
|
||
)
|
||
return 审阅内容(
|
||
target,
|
||
revision,
|
||
target,
|
||
next_revision,
|
||
candidate_hash,
|
||
candidate_hash,
|
||
"",
|
||
"",
|
||
固定哈希(
|
||
[
|
||
str(latest["version_id"]),
|
||
_current_basis(current),
|
||
credential["receipt_hash"] if credential else None,
|
||
]
|
||
),
|
||
("rule_activation" if command.action == "enable" else "rule_deactivation",),
|
||
(
|
||
依赖引用("B06.rule_activation", target, str(revision)),
|
||
依赖引用("B06.rule_version", target, str(latest["revision"])),
|
||
),
|
||
)
|
||
|
||
def 准备(self, conn, identity, change, current):
|
||
if change.动作 in {作者动作.拒绝, 作者动作.暂缓}:
|
||
return 提交计划(())
|
||
if change.动作 is not 作者动作.采纳 or not change.审阅ID:
|
||
raise 审校错误("规则启停需要作者针对精确版本的审阅决定")
|
||
row, _, _, credential = _核对命令(conn, identity.作者, change.业务请求, protect=True)
|
||
return 提交计划(
|
||
(
|
||
参与操作(
|
||
"B06.apply_rule_state",
|
||
规则状态写入(
|
||
identity.作者,
|
||
change.命令ID,
|
||
change.审阅ID,
|
||
change.业务请求,
|
||
str(row["version_id"]),
|
||
current.候选ID,
|
||
current.候选哈希,
|
||
),
|
||
),
|
||
),
|
||
(
|
||
修改影响(
|
||
current.目标,
|
||
"rule_activation_changed",
|
||
str(current.数据版本),
|
||
str(current.候选版本),
|
||
),
|
||
),
|
||
)
|
||
|
||
|
||
class 规则状态参与者:
|
||
身份 = "B06.apply_rule_state"
|
||
请求类型 = 规则状态写入
|
||
|
||
def 提交(self, conn, operation):
|
||
row, _, _, _ = _核对命令(conn, operation.作者, operation.命令, protect=True)
|
||
if str(row["version_id"]) != operation.version_id:
|
||
raise 审校错误("被审规则版本已改变")
|
||
return 审校存储(conn).写规则激活事件(operation.作者, operation)
|
||
|
||
|
||
def _依赖范围(object_id: str) -> tuple[str, str]:
|
||
parts = object_id.split(":", 2)
|
||
if len(parts) != 3 or parts[0] != "rule" or not parts[1] or not parts[2]:
|
||
raise 审校错误("规则依赖身份不合法")
|
||
return parts[1], parts[2]
|
||
|
||
|
||
class _规则版本依赖:
|
||
种类 = "B06.rule_version"
|
||
|
||
def 锁定当前(self, conn, object_id: str) -> str:
|
||
author, rule_id = _依赖范围(object_id)
|
||
return str(审校存储(conn).锁定规则版本(author, rule_id))
|
||
|
||
|
||
class _规则激活依赖:
|
||
种类 = "B06.rule_activation"
|
||
|
||
def 锁定当前(self, conn, object_id: str) -> str:
|
||
author, rule_id = _依赖范围(object_id)
|
||
return str(审校存储(conn).锁定规则激活(author, rule_id))
|
||
|
||
|
||
def 登记规则参与者(directory) -> None:
|
||
"""装配签名由主代理调用;作者范围由S01目标与调用身份共同固定。"""
|
||
directory.登记入口(规则状态入口())
|
||
directory.登记参与者(规则状态参与者())
|
||
directory.登记依赖(_规则版本依赖())
|
||
directory.登记依赖(_规则激活依赖())
|
||
|
||
|
||
def 核对已激活规则(conn, author: str, current: dict, *, protect=False):
|
||
store = 审校存储(conn)
|
||
if protect:
|
||
store.锁定规则激活(author, current["rule_id"], 共享=True, 锁行=True)
|
||
row = store.读取规则版本ID(author, current["rule_id"], current["version_id"])
|
||
if (
|
||
current["state"] != "active"
|
||
or current["action"] != "enable"
|
||
or row is None
|
||
or 固定哈希(row["payload"]) != row["payload_hash"]
|
||
):
|
||
raise 审校错误("已激活规则的精确版本不可回查")
|
||
if 读取作者决定(conn, current["candidate_id"], current["activation_revision"]) != "adopt":
|
||
raise 审校错误("规则激活缺少S01实际作者采纳决定")
|
||
from muse.效果评测.接口 import 核对规则诊断凭据, 评测错误
|
||
|
||
try:
|
||
credential = 核对规则诊断凭据(
|
||
conn,
|
||
author,
|
||
current["credential_id"],
|
||
_target(row, current["rule_id"], int(row["revision"])),
|
||
)
|
||
except 评测错误 as exc:
|
||
raise 审校错误("已激活规则的凭据失效:" + exc.说明) from None
|
||
return row, credential
|
||
|
||
|
||
def 读取规则状态(conn, author: str, rule_id: str) -> dict:
|
||
store = 审校存储(conn)
|
||
current = store.读取规则激活(author, rule_id)
|
||
history = store.列规则激活历史(author, rule_id)
|
||
usable, reason = False, None
|
||
if current and current["state"] == "active":
|
||
try:
|
||
核对已激活规则(conn, author, current)
|
||
usable = True
|
||
except 审校错误 as exc:
|
||
reason = exc.说明
|
||
elif current:
|
||
reason = "rule_disabled"
|
||
if current:
|
||
version = store.读取规则版本ID(author, rule_id, current["version_id"])
|
||
current = {**current, "rule_version": int(version["revision"]) if version else None}
|
||
return {
|
||
"rule_id": rule_id,
|
||
"current": current,
|
||
"history": history,
|
||
"consumable": usable,
|
||
"reason": reason,
|
||
}
|
||
|
||
|
||
__all__ = [
|
||
"规则状态命令",
|
||
"登记规则参与者",
|
||
"核对已激活规则",
|
||
"读取规则目标",
|
||
"读取规则状态",
|
||
"列出规则诊断消费",
|
||
]
|