主题
专题验证(verification)
常驻目录。这里的文档不归档,跟着代码一起活到项目结束。 最后更新以
git log -1 -- docs/verification/README.md为准(散文里的日期同样会漂)。
这个目录是什么
按爆炸半径划分的专题验证清单,每份对应一个「出问题会静默、用户不会报障」的域。 功能迭代之后重跑对应专题,确认这一域仍然收敛。
与 docs/plans/ 的区别不是重要性,是生命周期:
docs/plans/ | 本目录 | |
|---|---|---|
| 用途 | 一次性方案,做完就归档 | 反复重跑的清单 |
| 现状 | 一次性方案,做完即归档(现数:ls docs/plans/*.md docs/plans/archive/*.md | wc -l) | 只增不 archive |
| 放错的后果 | —— | 清单被排进归档队列,下轮没人找得到 |
docs/smoke-test-runbook.md(发版前冒烟)是同一体裁的先例,暂留原处不动。
🔴 三层分工:只有中间一层是文档
这是本目录最重要的一条规矩。违反它,清单会变成第二本账。
| 层 | 放哪 | 形态 |
|---|---|---|
| 机械层 能用数字或集合表达的 | 代码:scripts/<专题>-verify.sh 或单测 | assert |
| 判断层 要看上下文才能判的 | 本目录的 <专题>.md | 问句 + 假绿风险 |
| 每轮产物 | 不留 | 拆散进 CHANGELOG / backlog / 本清单的「已知未修」 |
为什么机械项必须下沉成断言
docs/plans/archive/admin-ops-acceptance-handoff.md 把机械项写成了散文清单。 2026-08-25 那轮复验实测出它自己有 4 处数字过期:测试通过数(写 70,实际 69/1 skipped)、 凭据条数(一处写 9 一处写 11)、探测 URL(还是换域名前的)、两处互相矛盾的通过基线。
散文里的数字必然漂移,而且是静默漂移——你照着过期的清单查,还以为查过了。 断言过期时会红,散文过期时不会。
为什么每轮报告要丢掉
留 10 份历史报告 = 回到 10 本烂账。价值应当当场拆散:
- 修好的 →
CHANGELOG.md(移动端的修复记rvh/CHANGELOG.md—— as-built 每端各一份) - 待修的 →
docs/plans/backlog.md - 有意不修的 → 本清单的「已知未修」节,且必须带「什么条件下重新处理」
- 趋势 → 清单顶部的「验收台账」表,每轮一行
🚫 清单里不许出现的东西
数值快照。 「当前 DB 18.7MB / cron 5 个 / 测试 70 passed」这类。 它们看起来很有用("用于识别漂移"),实际是这份文档腐烂速度最快的部分, 而且腐烂后会主动误导:读的人会拿过期数字当期望值。
要现状就现查——scripts/<专题>-verify.sh 会打出来,且永远是新鲜的。
判据一律用**「怎么算对」的问句**表述,不用「应该等于 N」。
一份清单必须有的四节
- 判据表 —— 每行一个问句 + 一列「假绿风险」
- 反向验证配方 —— 怎么造一个失败输入,确认它真的会变红
- 已知未修 / 有意接受 —— 带重启条件(形同 ADR)
- 验收台账 —— 每轮一行:日期 / 版本 / 一句话结论 / commit
🔑 清单里最值钱的是「假绿风险」那一列
功能清单可以从代码重新生成,「这一格为什么可能骗你」不能——那是踩出来的。
所以清单的定位不是「功能覆盖表」,是失效模式的账本。 随着轮次推进,它应该在假绿列变长、在机械列变短(机械项不断下沉成断言)。
判断层反复要问的那句话:
如果它要判的那件事变了,这个数字会不会跟着变? 变不了,就是接错线——无论它当前显示什么颜色。
三种结果的语义
脚本与人工判断共用同一套,别把第三种读成第一种:
- ✅ PASS 拿到了值,且值对
- ❌ FAIL 拿到了值,值不对
- ⏭️ SKIP 没拿到值(缺凭据 / 网络不通 / 需人工介入)——这是「本次没验」
「取不到 ≠ 正常」是这套系统反复栽的跟头。任何一项 SKIP,整体就不是绿的 (ops-verify.sh 为此把退出码分成 0/1/2)。
同理:恒红的闸门与恒绿的一样坏。一道因为与所守之物无关的原因而常红的检查, 会让人学会忽略它。看到红的先问「它为什么红」—— 2026-08-25 抓到的 CI Rust 恒红 17 次(行尾问题,与它守的 schema 无关)就是这个形状。
现有专题
| 专题 | 清单 | 机械层 | 覆盖 |
|---|---|---|---|
| 运维监控 | ops-monitoring.md | scripts/ops-verify.sh(24 条) | 备份心跳 / 巡检 / 容量 / 探测 / 告警通道 / 凭据台账 / 发布链路 |
| 同步与多端一致性 | sync-consistency.md | cargo test --lib sync(源码层)+ scripts/sync-verify.sh(14 条,部署态) | 同步矩阵完备性 / 红线 #5·#5b·#5i·#6b·#6d / 远端 trigger·RLS / PGRST204 契约 |
| 隐私与鉴权 | privacy-auth.md | pnpm --dir admin test(构建态+源码层)+ scripts/privacy-verify.sh(16 条,部署态) | 门与锁 / 红线 #2 聚合 / 密钥不下发 / 全库隐私分桶 / definer 授权 / Storage 桶 / 生产站点实测 |
| 发版链路 | release-chain.md | scripts/release-verify.sh(17 条 + --deep 再 1 条) | updater 接线 / endpoint 匿名可取 / 平台键 vs 构建矩阵 / 资产可下 / 签名密钥与制品验签 / semver 可升级性 / 公开 Release 非草稿 / 下载直链 / 发版凭据 |
| 数据基线与迁移 | data-baseline.md | cargo test --lib db::migrations(18 条,源码层)+ scripts/migration-verify.sh(10 条,本机层) | 已出厂迁移的字节冻结(含 v28+ 内联 SQL)/ 冻结名单覆盖面 / 指纹清单 vs 发布 tag / 本机存量库 _sqlx_migrations 与 HEAD 逐条比 / 非空存量库升级 / 幂等加法式 / §10 登记 |
| 学习循环(查词/生词/SRS) | learning-loop.md | cargo test --lib -- srs:: vocab_scope:: lemmatizer::(43 条,源码层)+ scripts/learning-loop-verify.sh(L 段跨仓 + M 段部署态) | SM-2 三端黄金向量的锁还连着吗 / mastery 阶梯(向量管不到的第二个跨端纯函数)/ 红线 #9 结构守卫 / 专名三角色 / 共享表时间戳的 UTC 标识符与排期语义 |
| 上下文预算(恒加载区棘轮) | context-budget.md | ../../scripts/context-budget.sh —— 🔴 仪表非闸门,恒 exit 0 | 恒加载合计 / 分节 Top6 / 记忆库是否在用 / 与上轮台账对比 |
待建(按爆炸半径排,都是「静默失效」域)
| 专题 | 为什么值得单列 |
|---|---|
| 阅读内容管线 | 快照三态回落,缺一态 = 换设备后正文永久丢失 |
「学习循环」原本列在这里,理由写着 「用户会自己报障,优先级低」。 2026-08-27 建成时那句话被推翻了:用户报得出来的只有「卡片没出现」, 报不出来的是「卡片出现得不对」 —— 那一轮当场抓到一个跨端排期缺陷, 六道既有守卫在同一批数据面前全绿。「用户会报障」不是不建专题的理由, 要问的是「他报得出这一类失效吗」。
怎么跑一轮
bash
./scripts/ops-verify.sh # 运维监控
cargo test --lib sync && ./scripts/sync-verify.sh # 同步与多端一致性
pnpm --dir admin test && ./scripts/privacy-verify.sh # 隐私与鉴权
./scripts/release-verify.sh # 发版链路(--deep 则真下一个制品验签)
cargo test --lib db::migrations && ./scripts/migration-verify.sh # 数据基线与迁移
./scripts/learning-loop-verify.sh # 学习循环(源码层另跑 cargo test --lib)
bash scripts/context-budget.sh # 上下文预算(仪表,恒 exit 0;跑完记一行台账)机械层绿了之后,把对应的 <专题>.md 交给一个 Claude 会话逐条过判断层。 产出按上面「每轮产物」那行拆散,不要新建一份报告文档。