FinBayes Case 库 70/20/10 三集分集物理实施约定
§0 范围与定位
本文件定义 FinBayes case 库在工程仓的物理实施:目录布局、case_id 命名规约、三集公开范围 gate、防数据泄漏约束。事实源在 Phase 4 评测体系 + ADR-007 supplement + EvalHarness 子系统 + Phase 5 治理,本文件不重述分集语义。
§1 物理目录约定(工程仓相对路径)
工程仓 case 库根目录:fixtures/cases/。三集为顶层子目录,每集按 MCA 桶(B1 / B2 / B3 / B4 / B5a / B5b / B6 / B7)二级分子目录:
fixtures/cases/
├── dev/ # 70% · 可公开 · 进 git
│ ├── B1/ C1.json C7.json
│ ├── B2/ C2.json C3.json
│ └── B7/ L1.json L2.json L9.json
├── test/ # 20% · 仅 .fact.json 进 git
│ ├── B1/ C8.fact.json
│ └── B3/ C9.fact.json
├── holdout/ # 10% · 完全私密 · 不进 git(仅 .gitkeep)
├── _truth/ # 标答 / 期望激活 / 关键洞察 / 事后演化(全部 gitignore)
├── _schema/ # case.schema.json
└── _index.json # 全集 case_id ↔ split ↔ bucket ↔ sha256 映射
文件格式:JSON(与 M0 走通骨架 Mock Provider Fixture 规范 同体例),每文件含 schema_version: 1。
§2 case_id 命名规约
保留原命名作为业务标签(C1-C10 / A-1-A-4 / L1 / L2 / L9 / L13 已在 18 case 报告中固化,迁移成本高);在 case JSON 顶层加 split + mca_bucket + public_scope 三字段补足元信息。
case 文件顶层字段:
{
"schema_version": 1,
"case_id": "C1",
"case_label": "Fed-2022",
"split": "dev",
"mca_bucket": "B1",
"public_scope": "full",
"as_of_date": "2022-09-21",
"source_anchor": "governance/workstreams/finbayes-cognition-system-research/drafts/2026-05-28-phase2-case-01-fed-2022.md",
"facts": { },
"ground_truth_ref": "_truth/C1.truth.json"
}
字段语义:split ∈ dev / test / holdout;mca_bucket ∈ B1..B7(含 B5a/B5b);public_scope ∈ full / fact-only / private;as_of_date 为该 case 事实层「认知时点」(ISO-8601 日期,详见 §5.5),即评测时模型被允许看到的信息截止时刻——事实层任何信息的时间戳不得晚于 as_of_date。与各子系统 as_of 参数(见 MCA 分类器 / 知识图谱服务)同语义。
文件命名:<case_id>.json(如 C1.json / A-2.json),事实层导出加 .fact.json 后缀。
可选 composite 标签:<split>-<bucket>-<case_id>(如 D-B1-C1 / T-B4-A2)由 _index.json 自动生成,不写入 case 文件本身,避免 split / bucket 漂移引发的级联改动。
§3 70/20/10 分集落到 18 case
| 集 | 比例 | case 数 | 候选 case |
|---|---|---|---|
| dev | 70% | 13 | C1 / C2 / C3 / C4 / C5 / C6 / C7 / A-1 / A-2 / A-4 / L1 / L2 / L9 |
| test | 20% | 4 | C8 / C9 / C10 / L13 |
| holdout | 10% | 1-2 | A-3(首选)+ 季度补 case 中 ≥ 1 |
v1→v2 治理门槛(phase5):dev 触发 ≥ 4 case + 跨 ≥ 2 MCA 桶 + ≥ 1 pending 桶证据。holdout 桶位均匀:每季度补 15-20 case 时按桶位均匀回填,避免长期偏 B1。
§4 公开范围 gate
| 集 | public_scope | 进 git | 公开内容 | 私密内容 |
|---|---|---|---|---|
| dev | full | ✅ 进治理库 + 工程仓 | 完整 case 报告 + 标答 + 期望激活清单 + 关键洞察 + 模型输出 | — |
| test | fact-only | 仅 .fact.json 进 git | 事实层(市场快照 + 信源 + 时间戳 + 关键数字 + MCA 桶位标签) | 标答 / 期望激活 / 关键洞察 / 事后演化(落 _truth/ 目录,gitignore) |
| holdout | private | ❌ 不进 git | — | 全部内容仅在评测系统本地存储 |
实施方式(v1 起步):
.gitignore规则:fixtures/cases/holdout/**!fixtures/cases/holdout/.gitkeepfixtures/cases/_truth/**!fixtures/cases/_truth/.gitkeepfixtures/cases/test/**/*.truth.jsonfixtures/cases/test/**/*.insights.json- CI 校验:pre-commit 跑
scripts/check_case_split.py,遇public_scope != "full"字段进入 git 暂存区则阻断。 - v2 升级路径(待评估):holdout 改 git-crypt 或拆独立私有 repo。v1 阶段「不进 git + 本地单点存储 + 季度 rotate」足够。
§5 防数据泄漏约束
- 三集互斥:同一
case_id不得同时出现在任意两集(_index.json + CI 校验)。 - holdout 不进任何公开评测报告 / Agent pack 派生 / Docusaurus 站点。
- 模型训练 / 提示词调试 / fixture 录制:仅用 dev 集。
- 常规评测:dev + test。
- 季度大评估 / 防退化基线对照才动用 holdout(每 4 季度 ≥ 20% 抽检,对齐 phase5 §防退化)。
- 跨集 hash 校验:按
facts+case_id计 SHA256,test / holdout 与 dev 同 hash 即报警。 - 时间序防泄漏:除上述按 case_id 的集合互斥外,再叠加按时点(
as_of_date)的时间序约束,禁止未来信息回灌到过去样本。规则见 §5.5。
§5.5 时间序切分约束(金融防泄漏核心)
金融评测的核心泄漏风险不是「同一 case 跨集」,而是时间泄漏:用「事后才知道的信息」去评判「当时只能看到过去」的判断,会系统性高估模型能力。MCA 桶随机分集解决「桶覆盖均衡」,但不约束时间——本节在其上叠加时点切分。
§5.5.1 as-of 时点是事实层的硬边界
每个 case 顶层带 as_of_date(§2)。语义:评测该 case 时,模型被允许看到的信息截止于 as_of_date 当日(含)。
| 约束 | 内容 |
|---|---|
| 事实层不含未来信息 | facts 内任何信息的时间戳 ≤ as_of_date;事后才发生的价格 / 事件 / 财报不进 facts |
| 标答与事实物理隔离 | 「之后实际怎么演化 / 标答」只落 _truth/(gitignore),评测输入阶段绝不喂给模型;模型先在 as_of_date 视角下作答,再与 _truth/ 比对 |
| 信源时间戳校验 | 每条信源带 published_at;published_at > as_of_date 的信源视为泄漏,CI 校验报错 |
as_of 参数贯穿 | 子系统调用(MCA 分类 / 知识图谱时钟相位)以 case 的 as_of_date 作为 as_of 入参,保证时点一致,不读时点之后的图谱状态 |
§5.5.2 训练 / 校准 / 评测按时点切分
在 70/20/10 桶切分之上,叠加时间序不重叠约束。原则:训练(dev)用较早时间窗,holdout 取最近时间窗,使「在最新、模型从未在训练中见过的时段」上评测,逼近真实「上线后面对未来」的场景。
| 集 | 时间窗角色 | 时间序规则 |
|---|---|---|
| dev(70%) | 较早 + 中段时间窗 | 训练 / 提示词调试 / fixture 录制只用 dev;其 as_of_date 应 ≤ 切点 T_cal |
| test(20%) | 中段时间窗(校准期) | 常规评测 + 阈值校准;as_of_date 落 (T_cal, T_holdout] |
| holdout(10%) | 最近时间窗 | as_of_date > T_holdout(取数据集中最近的时间窗);仅季度大评估启用 |
切点 T_cal / T_holdout 由数据集时间分布拍板(v1 起步建议 T_holdout = 数据集最近 1 个季度起点),任何调整走 governance/change-protocol.md。
§5.5.3 跨集时间不重叠的硬规则
| 规则 | 内容 | 违规判定 |
|---|---|---|
| 单调时点 | max(dev.as_of_date) ≤ min(test.as_of_date) ≤ min(holdout.as_of_date)(同一事件多 case 允许等于切点) | 任意集时点跨越切点反向 → CI 报错 |
| holdout 取最近 | holdout 全部 case 的 as_of_date 不早于 test / dev 的最大时点 | holdout 出现早于 test 最大时点的 case → 报警(除非显式标 legacy 例外) |
| 禁未来回灌 dev | dev 集 fixture 录制 / 训练绝不引入 as_of_date 晚于该 case 的任何外部信息 | 录制 fixture 含晚于 case as_of_date 的响应 → 报错 |
| 时点与 hash 双校验 | §5 第 6 条 SHA256 碰撞校验 + 本节时点单调校验同时跑 | 任一失败即阻断 |
与桶切分的关系:桶(B1..B7)保证「能力维度覆盖」,时点保证「无时间泄漏」。二者正交叠加——同一桶内的 case 仍须满足跨集时点单调;若某桶 case 时间分布过窄无法满足时点切分,优先保时点约束、按 phase5 季度补 case 时回填该桶的最近时间窗样本。
§5.5.4 时间序泄漏的检测落点
scripts/check_case_split.py(§7)扩展校验项:
- 每 case:
facts内信源published_at≤as_of_date(事实层无未来信息)。 - 跨集:时点单调(dev ≤ test ≤ holdout)+ holdout 取最近窗。
_index.json增列as_of_date,供 EvalHarness 按时点过滤。- 违规默认阻断(pre-commit + CI);legacy 例外须在
_index.json显式标注time_split_exempt: true+ 理由。
§6 case_id × split × bucket 建议映射表
v1 起步建议分配,待 Phase 5 治理首季评估拍板。任何调整走 governance/change-protocol.md。
| case_id | bucket | split | scope | case_id | bucket | split | scope |
|---|---|---|---|---|---|---|---|
| C1 | B1 | dev | full | C8 | B1 | test | fact-only |
| C2 | B2 | dev | full | C9 | B3 | test | fact-only |
| C3 | B2 | dev | full | C10 | B3 | test | fact-only |
| C4 | B1 | dev | full | A-3 | B5b | holdout | private |
| C5 | B1 | dev | full | L13 | B7 | test | fact-only |
| C6 | B1 | dev | full | A-1 | B5a | dev | full |
| C7 | B1 | dev | full | A-2 | B4 | dev | full |
| A-4 | B6 | dev | full | L1 | B7 | dev | full |
| L2 | B7 | dev | full | L9 | B7 | dev | full |
桶位分布(v1 起步 18 case):B1 6 + B2 2 + B3 2 + B4 1 + B5a 1 + B5b 1 + B6 1 + B7 4 = 18。
§7 实施清单(Codex / 工程仓接手人)
- 创建目录:
mkdir -p fixtures/cases/{dev,test,holdout,_truth,_schema}/{B1,B2,B3,B4,B5a,B5b,B6,B7}+ 落.gitkeep。 - case 文件迁移:从治理库 18 case 报告抽事实层 + 标答层 → 工程仓 JSON(脚本
scripts/migrate_case_reports.py,待新建)。 .gitignore更新:按 §4 规则追加。- case 文件顶层字段:按 §2 schema 落
split/mca_bucket/public_scope/as_of_date/source_anchor五字段;为 18 case 回填as_of_date(取事件认知时点)。 - 跨集校验脚本:
scripts/check_case_split.py输出 _index.json + 报 split 互斥违规 + 报 hash 碰撞 + 报时点单调违规(§5.5.3)+ 报事实层未来信息(§5.5.4),pre-commit 接入。 - _index.json:启动期 / CI 期自动生成,含
case_id/split/mca_bucket/public_scope/as_of_date/sha256/composite_id七字段(legacy 例外另带time_split_exempt)。 - EvalHarness 接入:
evaluate_batch(split=...)读取 _index.json,按 split 加载 case,并以各 caseas_of_date作为子系统as_of入参(时点一致,不读时点之后状态);holdout 仅在「季度大评估」流程显式启用。 - 时间序切点:拍板 T_cal / T_holdout(§5.5.2),v1 起步 T_holdout = 数据集最近 1 季度起点;调整走
governance/change-protocol.md。