---
labels: [ready-for-agent]
status: open
title: v0.5 判定语义对齐与场景版本化
---

# v0.5 Spec：判定语义对齐与场景版本化

领域依据：`CONTEXT.md` 术语表、ADR-0001（场景版本化）、ADR-0002（通过率含执行失败）。

## Problem Statement

评测工程师在使用平台时遇到三类"结果与直觉不符"的问题：

1. 给用例同时写了期望（keywords / 时延上限）和评估规则后，期望被静默忽略——只有规则生效，用户以为两者都在把关。
2. 忘记配置判定标准的用例被计为"通过"，报告通过率虚高，且无法在报告中分辨哪些用例真正经过判定、哪些只是连通验证。
3. 编辑场景（增删用例、改模型绑定）后，新旧两次运行仍可生成对比报告——实际考纲已变，对比结论不可信，用户无从察觉。

## Solution

让判定行为与领域模型一致：

1. **期望与规则叠加生效**——期望始终转化为隐式判定并与显式规则同时执行，任一不满足即不通过。
2. **连通用例显式标注**——报告与运行详情中标出连通用例，并补充"判定型通过率"参考指标；总通过率口径不变（ADR-0002）。
3. **场景版本化**——场景携带版本号，仅考纲字段变更时递增；运行记录所用版本；对比报告要求同场景同版本，否则拒绝。

## User Stories

1. 作为评测工程师，我希望用例的期望和规则同时生效，以便我写下的每一条约束都真实参与判定。
2. 作为评测工程师，我希望期望不满足时能在结果里看到独立的判定条目（含原因），以便区分是哪条约束失败。
3. 作为评测工程师，我希望已有的"只写期望不写规则"的用例行为保持不变，以便升级后历史场景不需要改造。
4. 作为质量负责人，我希望报告里明确标出连通用例，以便判断通过率里有多少"未经判定的通过"。
5. 作为质量负责人，我希望看到"判定型通过率"参考指标，以便在连通用例较多时仍能评估真实回答质量。
6. 作为质量负责人，我希望总通过率口径保持含执行失败（ADR-0002），以便延续用户视角的质量定义。
7. 作为评测工程师，我希望场景在我修改用例集、模型绑定或 LLM 配置时自动升版，以便可比性边界由系统维护而非靠记忆。
8. 作为评测工程师，我希望仅改名称、描述、标签时版本不变，以便修文案不会断开历史可比性。
9. 作为评测工程师，我希望每次运行记录当时的场景版本，以便回看报告时知道它对应哪一版考纲。
10. 作为评测工程师，我希望对比报告只允许同场景同版本的两次运行，以便对比结论始终基于同一考纲。
11. 作为评测工程师，我希望在报告页选择对比对象时只看到可比的运行，以便不必自己排查版本是否一致。
12. 作为评测工程师，我希望跨版本对比被拒绝时得到明确提示（含双方版本号），以便理解原因并选择正确的运行。
13. 作为质量负责人，我希望运行列表和报告中展示场景版本号，以便快速识别考纲变更前后的运行分界。
14. 作为 AI 助手（OpenClaw），我希望通过标准 API 触发的评测同样记录场景版本，以便机器触发的运行与手动运行可比性规则一致。
15. 作为系统维护者，我希望存量场景和运行在迁移后获得确定的版本值，以便升级不产生"版本未知"的悬空数据。

## Implementation Decisions

- **期望叠加语义**：引擎不再"无规则才派生"，改为始终从期望派生隐式规则（keywords → keyword_match，时延 → response_time），追加到显式规则之后执行。隐式规则不参与 `rule_logic` 的 any/weighted 组合——用例通过 = 显式规则按 rule_logic 判定通过 **且** 全部隐式期望判定通过。期望是硬约束，规则组合逻辑只作用于显式规则。
- **隐式判定的可见性**：期望派生的判定结果与显式规则结果同构存储（EvalResult），reason 中标明来源为期望，前端无需特殊处理即可展示。
- **连通用例识别**：无显式规则且期望为空的用例即连通用例（与 CONTEXT.md 定义一致），判定发生在报告生成层而非存储层——不新增字段，由"该用例无任何 EvalResult 且无 turn 错误"推导。
- **报告标注**：单次与对比报告的 case 条目携带连通标记；summary 增加连通用例数与判定型通过率（判定型通过数 ÷ 判定型总数）；总通过率分母不变。
- **场景版本字段**：场景模型与表新增整型 version（默认 1）。更新场景时，仓储层比较考纲字段（cases / model_bindings / llm_config）序列化值，有差异则 version+1；元数据字段变更不升版。版本由系统维护，API 不接受外部指定。
- **运行记录版本**：运行模型与表新增 scenario_version；创建运行时从当前场景快照。迁移回填：存量场景 version=1，存量运行 scenario_version 回填为其场景当前版本（场景已删除的回填 1）。
- **对比校验升级**：对比接口在现有"同场景"校验上追加"同版本"，不满足返回 400，detail 含双方版本号。报告生成层同步收紧（ValueError）。
- **前端适配**：报告页对比候选按"同场景 + 同版本"过滤；运行列表、报告头、对比报告头展示版本号（如 `v3`）。
- **数据库迁移**：一条 Alembic 迁移（batch mode，SQLite），两表各加一列，带 server_default 回填。

## Testing Decisions

- 只测外部行为：API 响应、引擎产出的运行/结果对象、报告 JSON 结构；不断言内部函数调用。
- **引擎单元层**（MockChannel，先例 `test_engine.py`）：期望+规则叠加通过/失败矩阵、纯期望用例行为不变、rule_logic=any/weighted 时隐式规则不入组合、连通用例收到回复即通过。
- **报告单元层**（先例 `test_report.py`）：连通标记、判定型通过率计算、跨版本对比抛 ValueError。
- **API 集成层**（TestClient，先例 `test_scenarios.py` / `test_runs_api.py` / `test_reports_api.py`）：考纲变更升版 vs 元数据变更不升版、运行携带 scenario_version、跨版本对比 400 及提示内容、报告 summary 新字段。
- 迁移回填以集成测试覆盖（先例 `test_model_config_migration.py`）。

## Out of Scope

- platform"决定评测策略"的分支逻辑（意图已记录于 CONTEXT.md，行为未定义）。
- "未判定（unchecked）"结果状态——连通用例仍计通过，仅标注。
- 场景版本历史浏览、回滚、按版本查看旧考纲内容（只存当前版本号，不存版本快照）。
- 多环境 / Deployment 概念（拷问已裁定为伪需求）。
- 前端测试基线、报告趋势看板等其他 v0.5 候选项。

## Further Notes

- 通过率口径受 ADR-0002 保护：任何实现不得把执行失败或连通用例从总通过率分母中剔除。
- 场景版本语义受 ADR-0001 约束：升版判据以该 ADR 为准，如实现中发现新的考纲字段（未来扩展），需同步更新 ADR。
- 期望叠加会使部分历史场景的通过率下降（原本被忽略的期望开始生效）——这是修正而非回归，发布说明中需说明。
