6.5 KiB
Migration: schema_version 1.3 → 1.4
Type: MINOR but BREAKING for blind channel integrity——state 字段不变,但
rubric_notes.md必须拆开。老用户跑 migrate 之前 blind sub-agent 仍泄漏实绩。
WHAT changed
文件层(核心)
| 之前 | 之后 |
|---|---|
rubric_notes.md 顶部累积所有 bump Memo(含视频名 + 实绩 + 派生证据) |
rubric_notes.md 只含通用语言(公式 / 维度定义 / bucket 边界 / 指针),绝不含实绩 |
| —— | rubric-memo.md(新)累积所有 bump Memo 全文(含视频名 + 实绩 + 派生证据) |
state 字段
无新增 / 删除 / 改名。仅 schema_version bump 标识本次"文件层迁移"必跑。
channel B hard refusal list
cheat-score-blind/SKILL.md 加 rubric-memo.md 路径 + refusal_code blocked_rubric_memo。
WHY
PR #11 引入 blind-scoring sub-agent(channel B)时承诺它只能读 scripts/<id>.md + rubric_notes.md。但 cheat-bump Phase 5 落地时把升级 Memo(含证据数据表 + 派生证据 + 真实视频名 + 实绩)写进 rubric_notes.md ——sub-agent 通过白名单读到了本不该看的实绩数据,盲打分变成"看过实绩的事后合理化"。
实测复现(PR #11 测试):
contamination_note: rubric_notes.md v0→v1 bump memo 含本 script 同名条目「它让我发的 38w」实绩
contamination_note: rubric_notes.md 派生证据段含本 script 名+实绩 13.7w,CC 锚点被预先校准
→ refusal: "non_blind_warning"
→ all dimensions confidence: medium
修复:拆 file。rubric_notes.md 严格只放通用规则(blind 白名单),bump 历史档案沉淀到 rubric-memo.md(blind 硬禁读)。详见 shared-references/observation-lifecycle.md "Blind channel leak guard" 段。
HOW (Claude steps for /cheat-migrate)
按顺序执行。不可幂等的步骤要先检查是否已跑过——本迁移涉及内容文件改写,重跑可能产生重复内容。
Step 1:前置检查
- 读
.cheat-state.json→ 校验schema_version == "1.3",否则报错"当前 state 不是 1.3,无需此迁移" - 检查
rubric_notes.md存在;不存在 → 报错"找不到 rubric_notes.md。是不是项目还没 init?" - 检查
rubric-memo.md是否已存在:- 已存在 → 询问用户"rubric-memo.md 已有内容,跳过 split 直接 bump schema 到 1.4?回 yes 跳过,回 no 中止迁移"
- 不存在 → 进 Step 2
Step 2:备份
cp rubric_notes.md rubric_notes.md.backup-$(date +%s)
提示用户:"已备份 rubric_notes.md —— 拆分若出错可恢复"。
Step 3:扫描 + 抽离 rubric_notes.md 的违禁段
读 rubric_notes.md 全文。识别下列 pattern:
| Pattern | 处理 |
|---|---|
整段 ## v.X → v.Y 升级 Memo 含子段(触发观察 / 证据数据 / 诊断 / 跨模型审核 / 已知局限) |
整段抽离到 rubric-memo.md,原位删除 |
| 派生证据段中带视频名 + 数字(如「停止期待」实绩 13.7w) | 整条抽离到 rubric-memo.md 的"派生证据"子段;原位用通用语言替代("高抽象密度样本 → CC=1 → 低 reach") |
| 校准池重打表 / 排序对照表 | 整表抽离到 rubric-memo.md 对应 Memo 的"证据数据"子段;原位删除(公式速查表保留——公式速查不含视频名) |
| 跨模型审核引用含具体视频名 + 实绩 | 抽离 |
散落的 \d+w / \d+万 数字(例外:bucket 边界 5-30w / 30-100w 等保留) |
用 Claude 判断:是 bucket 边界 → 保留;是实绩引用 → 抽离 |
Step 4:写 rubric-memo.md
如果文件不存在 → 从 cheat-on-content/templates/rubric-memo.template.md 复制空骨架。
然后把 Step 3 抽离出来的 Memo 段按时间顺序(旧的在上 / 新的在下)append 到文件末尾。每段 Memo 用 templates/rubric-memo.template.md 的 6 组件格式包装;缺组件的标 (unknown from legacy migration)。
Step 5:清理 rubric_notes.md
- 顶部 metadata 段加:
**Upgrade memos**: 见 [rubric-memo.md](rubric-memo.md) - Memo 段被 Step 3 抽走的部分留短指针:"v0→v1 升级 Memo 已迁移到 rubric-memo.md,跑
cat rubric-memo.md查看" - 派生证据段替换为通用语言
Step 6:自检 leak guard
对清理后的 rubric_notes.md 跑:
grep -E '\d+\s*[wWmMkK万]|播放|实绩|实际' rubric_notes.md \
| grep -v -E '^\s*\|[^|]*\|[^|]*\|.*[0-9]+\s*[wkM][^a-zA-Z]' \
| grep -v -E '5-30w|30-100w|100-150w|>150w'
(grep 排除明显的 bucket 边界数字)
- 无命中 → 通过
- 命中 → 报告剩余的"实绩引用" + 让用户手工 review / 进一步抽离 → 继续 Step 7 或中止
Step 7:bump schema + 写回 state
- 设
.cheat-state.json的schema_version = "1.4" - 原子写
- 报告:"✅ 迁移到 1.4 完成。
rubric_notes.md现仅含通用语言({N} 行),rubric-memo.md含 {M} 段历史 Memo。备份保留:rubric_notes.md.backup-{ts}。"
Manual fallback
不想跑 /cheat-migrate 的用户可以手动拆:
- 备份:
cp rubric_notes.md rubric_notes.md.backup - 把所有
## v.X → v.Y 升级 Memo段从rubric_notes.md整体剪切到新建的rubric-memo.md(按时间顺序保留) - 把派生证据段的视频名 + 实绩剪到 rubric-memo.md,原位用通用语言替代
- 在
rubric_notes.md顶部加**Upgrade memos**: 见 [rubric-memo.md](rubric-memo.md)指针 - 手改
.cheat-state.json的schema_version为"1.4"
或者最懒:删 rubric_notes.md 重 init(损失:所有历史观察 + bump memo),跑 bash install.sh 后说"初始化"——cheat-init 会重新创建两份空文件。仅适合校准池还很小(< 5 条)的早期用户。
验收
迁移完成后:
# state 升到 1.4
jq '.schema_version' .cheat-state.json
# → "1.4"
# rubric_notes.md 无实绩泄漏
grep -E '播放|实绩|实际|\d+w[^a-zA-Z0-9]' rubric_notes.md \
| grep -v -E '5-30w|30-100w|100-150w|>150w' \
| head
# → 应输出空(除 bucket 边界)
# rubric-memo.md 含历史 Memo
ls -la rubric-memo.md
wc -l rubric-memo.md
# → 行数 > 50(取决于历史 bump 次数)
# blind sub-agent 不再标 non_blind_warning
# 跑 /cheat-score scripts/<已发样本>.md
# → JSON.refusal == null, JSON.self_check.any_contamination_signal == false