- Sprint 执行计划 v1.1:§1.1 补第一批交付实据;T9 SPIKE 结论回写 Sprint 1 表 (T-P0-16 通过 2.8ms;T-P0-12 有条件;T-P0-10 原型 6/6 + 真实照片重验前置); Sprint 2 表标注 T-P2-01~06 交付;新增 §9 两批交付记录 - 开发任务拆解 v1.5:交付回写 + 新风险登记(RTMPose 域差异、BiRefNet 异步化) - 新增 开发任务包/:三批多 agent 并行的协作规程与 14 份任务契约 - 新增 前置开通清单-云资源与资质.md - 清理已用毕的评审报告(文档评审 2026-08-13、项目整体评审 2026-08-14), README 中相应引用改为留痕表述
5.6 KiB
5.6 KiB
T13 · 黄金集回归框架接入 CI
对应任务:
T-P2-11🔴 | 需求:FR-KB-11、NFR-MAINT-04(指标退化阻断合并)、架构 §17「黄金集是最重要的一道防线」| 分支:task/t13-golden-ci| worktree:/home/xsl/meida_backend-t13先读《README.md(协作规程)》,遵守全部纪律。
1. 目标
把黄金集从"散在单测里的固定样本"升级为数据驱动的回归框架:用例存 JSON、阈值存配置、CI 强制跑、指标退化直接 fail。V1 先落两个子集(规则黄金集、检索黄金集),Agent 问答与报告结构两个子集留占位(等 Sprint 3/4)。
2. 已就绪的契约(协调提交 9c18021 已提供)
- pytest marker
golden已注册(--strict-markers下可直接用);默认 addopts 排除golden(与 integration 同待遇),make golden/ CI 防线 5c 强制跑(envMEIDA_RUN_INTEGRATION=1)。 - 规则黄金集现有资产:
tests/unit/test_rules_golden.py有 8 条规则 + 11 组样本(硬禁忌压制、多规则叠加等)——不许改它;你的 JSON 用例集是独立交付(可参考其场景设计新写,不是搬运代码)。 - 检索侧可复用:
packages/retrieval/embedding.py的DeterministicEmbedder(同文本同向量→黄金集可断言确定性结果)+packages/rules的 DSL/引擎。
黄金集规模口径(知识库文档 §7,唯一事实源)
四子集共 330 例(检索 100 / Agent 问答 100 / 诊断 100 / 报告结构 30)。本任务只搭框架 + 规则/检索各 10~15 例种子,规模达标是内容轨 T-P2-16 的事——框架必须让"加用例=加 JSON 行"。
3. 实现要点
允许改动:tests/golden/**(新目录,归你全部)、仅此一处;不改 packages/apps/已有测试。
- 目录结构:
tests/golden/ README.md # 用例格式说明 + 如何加用例 + 阈值怎么调 thresholds.json # {"rules": {"pass_rate_min": 1.0}, "retrieval": {"pass_rate_min": 0.8, "first_hit_in_top3_min": 0.8}} cases/ rules_cases.json # 规则黄金集种子 retrieval_cases.json # 检索黄金集种子 runner.py # 用例加载 + 执行 + 指标计算 + 明细报告 test_golden.py # pytest 入口(marker=golden,skipif 无 MEIDA_RUN_INTEGRATION) - 规则用例格式(rules_cases.json):
{"name", "rules": [完整 Rule DSL 数组], "context": {...RuleContext}, "expect": {"must_recommend": [{"slot": "top", "attrs_include": {...}}], "must_avoid": [...], "hard_blocks_nonempty": bool, "forbidden_recommend": [...]}}。判定:evaluate()结果逐一核对 expect;一条不符 = 该用例 fail。 - 检索用例格式(retrieval_cases.json):
{"name", "seed_entities": [{entity_type, name, attrs, status, chunks: [text]}], "query", "user_ctx": {...}, "expect": {"must_hit_names": [...], "must_miss_names": [...], "first_hit_in": "top1|top3"}。执行:每个用例先清自己 seed 的实体(按 name 前缀golden:命名,跑前 DELETE 这些行,保证幂等重跑)→ DeterministicEmbedder 写 chunk →hybrid_search→ 判定。must_miss语义 = 硬过滤红线(禁忌/draft 实体绝不出现)。 - 指标与阻断(runner.py):
- 每子集算
pass_rate(通过用例/总数);检索加算first_hit_in_top3_rate; - 规则子集阈值 = 1.0(硬结论子集,一条不许退);检索 = 0.8 起步(阈值在 thresholds.json,顾问扩充用例后可调);
- fail 时输出逐用例明细(name + 期望 vs 实际的差异摘要)——CI 日志里要能直接看出哪条退化了;
runner.py是普通模块(不依赖 pytest),test_golden.py只是薄壳调用——将来想在本地脚本或 admin 后台跑同一套,不用改框架。
- 每子集算
- README.md:写明四子集规划(330 例口径)、当前覆盖(两子集 N 例)、加用例流程、"为什么规则阈值必须 1.0"(核心结论由规则产出,规则退化=产品根基退化)。
4. 测试要求(即框架本身)
make golden(或MEIDA_RUN_INTEGRATION=1 .venv/bin/pytest -m golden --no-cov)全绿:两个种子子集通过率 100%(种子用例是手工校准过的,必须全对,否则框架自身有 bug);- 阻断语义自证:在本地临时改坏一条用例的 expect 验证会 fail 且输出明细(验证完改回来——提交里只有正确版本;这个自证过程写进提交信息,不写代码);
- 无 PG/Redis 时
pytest -m golden全部 skip(不拖累本地make test)。
5. 禁改清单
通用禁改之外:packages/**、apps/**、tests/unit/**、tests/integration/**、pyproject.toml(golden marker 已注册)、Makefile/CI(防线 5c 已挂)。你的全部产出在 tests/golden/**。
6. 验收标准(T-P2-11)
- CI 防线 5c 能跑且通过(本地等价命令全绿);
- 指标退化即 fail:人为退化会被拦截(自证过程留提交信息);
- 加用例 = 加 JSON 行,零代码改动(README 有流程);
- 规则子集含硬禁忌场景、检索子集含 must_miss(红线)场景;
- 全部检查绿(tests 不在 mypy 范围;ruff 对 tests/golden 全绿)。
7. 提交信息
test(golden): data-driven golden set framework wired into CI
tests/golden:JSON 用例 + 阈值配置 + runner(规则 pass_rate=1.0、检索 0.8
起步)+ pytest 壳;规则/检索两子集种子,Agent/报告子集占位(T-P2-11)。
偏差说明:<如有写在这里,无则写"无">