实现侧: - 上下文:任务范围拆分为 范围校验/范围授权;索引按可发现口径重建、索引新鲜度改对称差;依赖校验统一快照漂移说明。 - 知识方法:方法与材料读取口径统一;超限方法材料按可选省略,核对路径不再二次计费;删除无合同的读时重算。 - 任务运行:新增 context.usage/tool.denied 事件类型;连接池常驻并在装配生命周期内开关;调用结算与核对分列。 - 效果评测/审校修订/交付连载/作者经验/作品规划:凭据冻结、标定消费、导出补证、事实引文核对等收尾修复。 - 资源加载:能力正文不再夹带索引用的导航注记(该注记此前进入角色与技能的模型提示)。 - 元数据:受保护骨架与代码保护属性对齐;字段校验与内置结构口径同步。 - 基础设施:环境预检进入装配生命周期;数据库连接运行期字段不参与相等比较;索引指纹归一化 jsonb 浮点。 - 删除被替代实现:7 份旧提示词模板与空壳 资料来源 读取器。 用例侧: - 用例身份与导航元信息迁移;夹具补生命周期、同库暴露与模板封存; - 本轮定向修复:方法材料省略、事实引文、迁移回执、额度与暂停用例、慢用例超时预算等。
126 lines
4.8 KiB
Python
126 lines
4.8 KiB
Python
"""预算时间与金额、配置引用的确定性合同。"""
|
||
|
||
from datetime import datetime, timedelta
|
||
from decimal import Decimal
|
||
from zoneinfo import ZoneInfo
|
||
|
||
import pytest
|
||
|
||
from muse.任务运行.配置版本 import 凭据引用, 提供方配置, 运行配置内容, 配置版本错误
|
||
from muse.任务运行.预算管理 import 任务预算计划, 归属窗口, 角色预算, 预算错误, 额度策略
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-2852b5b9a8d0",
|
||
environment="离线纯规则",
|
||
given="给定十个整点所在时刻",
|
||
when="计算固定本地日窗口",
|
||
then=["起点日期和小时一致,末窗到次日00"],
|
||
contract="docs/系统架构/新版设计/模块设计/S02-任务运行.md",
|
||
)
|
||
@pytest.mark.parametrize(
|
||
"hour,expected",
|
||
[(0, 0), (4, 0), (5, 5), (9, 5), (10, 10), (14, 10), (15, 15), (19, 15), (20, 20), (23, 20)],
|
||
ids=["00", "04", "05", "09", "10", "14", "15", "19", "20", "23"],
|
||
)
|
||
def test_五小时额度窗口承接每日边界__2852b5(hour: int, expected: int) -> None:
|
||
当前 = datetime(2026, 7, 16, hour, 30, tzinfo=ZoneInfo("Asia/Shanghai"))
|
||
窗口 = 归属窗口(当前)
|
||
assert 窗口.起点.strftime("%Y-%m-%dT%H") == f"2026-07-16T{expected:02}"
|
||
assert 窗口.终点 - 窗口.起点 == timedelta(hours=4 if hour >= 20 else 5)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"TC-7790f820deda",
|
||
environment="离线纯规则",
|
||
given="给定四个旧窗口边界时刻",
|
||
when="计算下一边界等待秒数",
|
||
then=["分别为7200、1800、10800、60秒"],
|
||
contract="docs/系统架构/新版设计/模块设计/S02-任务运行.md",
|
||
)
|
||
@pytest.mark.parametrize(
|
||
"hour,minute,seconds",
|
||
[(3, 0, 7200), (19, 30, 1800), (21, 0, 10800), (23, 59, 60)],
|
||
ids=["morning", "20-boundary", "midnight", "last-minute"],
|
||
)
|
||
def test_下一窗口等待秒数按原日界线计算__7790f8(hour: int, minute: int, seconds: int) -> None:
|
||
当前 = datetime(2026, 9, 9, hour, minute, tzinfo=ZoneInfo("Asia/Shanghai"))
|
||
assert (归属窗口(当前).终点 - 当前).total_seconds() == seconds
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-budget-plan-reserve",
|
||
environment="离线纯规则",
|
||
given="各角色计划次数、容量和单次金额",
|
||
when="登记任务预算计划",
|
||
then=["保留计划与570最坏预留,金额不足拒绝"],
|
||
contract="docs/系统架构/新版设计/模块设计/S02-任务运行.md",
|
||
)
|
||
def test_预算计划保留调用计划并按单次上限预留__a60003() -> None:
|
||
角色 = (
|
||
角色预算("writer", 45, 150, Decimal("5")),
|
||
角色预算("detector", 24, 150, Decimal("5")),
|
||
角色预算("judge", 45, 150, Decimal("5")),
|
||
)
|
||
计划 = 任务预算计划(
|
||
Decimal("570"), 角色, "approval-1", datetime(2030, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||
)
|
||
assert 计划.最坏预留 == Decimal("570.000000")
|
||
assert 计划.冻结()["角色"][0]["计划次数"] == 45
|
||
with pytest.raises(预算错误):
|
||
任务预算计划(Decimal("569.99"), 角色, "approval-1", 计划.截止时间)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-budget-amount-validation",
|
||
environment="离线纯规则",
|
||
given="NaN、负数与无穷金额",
|
||
when="构造额度策略",
|
||
then=["不能作为确定可用额度"],
|
||
contract="docs/系统架构/新版设计/模块设计/S02-任务运行.md",
|
||
)
|
||
@pytest.mark.parametrize(
|
||
"amount",
|
||
[Decimal("NaN"), Decimal("-1"), Decimal("Infinity")],
|
||
ids=["nan", "negative", "infinite"],
|
||
)
|
||
def test_预算拒绝不确定或负数金额__a60001(amount: Decimal) -> None:
|
||
with pytest.raises(预算错误):
|
||
额度策略("quota", "1", amount, 6000)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-config-controlled-credentials",
|
||
environment="离线纯规则",
|
||
given="明确凭据引用或角色参数内明文凭据",
|
||
when="冻结运行配置内容",
|
||
then=["引用保留而不支持的凭据字段拒绝"],
|
||
contract="docs/系统架构/新版设计/模块设计/S02-任务运行.md",
|
||
)
|
||
def test_配置凭据只保留引用且调用参数不可藏入明文__a60002() -> None:
|
||
引用 = 凭据引用("api", "环境变量", "MUSE_PROVIDER_KEY")
|
||
内容 = 运行配置内容(
|
||
"direct",
|
||
"1",
|
||
"role-policy-1",
|
||
"release-1",
|
||
"quota-1",
|
||
{"writer": {"provider": "provider", "model": "model", "thinking": "high"}},
|
||
(引用,),
|
||
(提供方配置("provider", "responses", "https://provider.invalid/v1/responses", "api"),),
|
||
"price-1",
|
||
)
|
||
assert 内容.冻结()["凭据"][0]["位置"] == "MUSE_PROVIDER_KEY"
|
||
with pytest.raises(配置版本错误):
|
||
运行配置内容(
|
||
"direct",
|
||
"1",
|
||
"policy",
|
||
"release",
|
||
"quota",
|
||
{"writer": {"api_key": "synthetic-secret"}},
|
||
(),
|
||
(),
|
||
"price-1",
|
||
)
|