这一篇不讲方法,只摆证据。前面 33 篇讲的是「我怎么想」,这一篇摆的是我怎么证明我没在瞎说——四套脚本全部公开可下载,全部可复现,其中两套真在生产环境里抓出过东西。
对象:memberhandbook.cn/fde/kb/ 知识库本体(39 篇正文 + 7 张模板 + 42 个 HTML)。工具 kb/check.sh、kb/tools/crosscheck.py、kb/tools/scan_pg_ready.py、kb/tools/make_charts.py——四套全部只读,都不连生产库。
方法论出处:27 · 测试从 0 到 1讲测试怎么起步,本篇讲另一件事——怎么给自己已经写完的东西上锁;32 · PG 迁移预案是 scan_pg_ready.py 的完整结论页。
39 篇正文是手工写的,4 套脚本是机器查的。这两件事的关系是:手写保证内容有判断,机器查保证判断没在几十次迭代里悄悄失效。
举个具体例子。38 篇正文里,篇数从 26 涨到 37 再涨到 39,展示页的文案要跟着改 7 次;28 篇的四张图,有 3 张的 src 漏了 .png 后缀,线上是裂图,而单页体检跑了 189 项全部通过。——因为单页体检查的是「链接指向的文件存不存在」,图片 src 缺后缀在它眼里是「链接存在,只是名字怪」。
.png 那天 check.sh 依然是 189 项全绿——它永远发现不了自己看不见的东西。四个脚本的分工,一句话各自说清:
| 脚本 | 查什么 | 不查什么(重要) | 字节 |
|---|---|---|---|
| check.sh | 单页:class="on" 唯一性、本地断链、身份禁用词、样式表路径、展示页篇数哨兵 | 不查图片 src 是否真能加载;不查跨页数字口径是否漂移 | 4,106 |
| tools/crosscheck.py | 跨页:篇数自指、数字口径漂移、断图断链、陈旧待办残留 | 不判断数字本身对不对,只判断口径有没有写清 | 7,681 |
| tools/scan_pg_ready.py | 扫另一个项目的 PG 迁移就绪度,输出带行号的待改清单 | 只读文本,不连库、不写文件;只诊断不修 | 4,219 |
| tools/make_charts.py | 用 Pillow + numpy 手绘 4 张口径图(零图表库) | 不做交互、不做动态;只画「已经算好的数」 | 15,591 |
最朴素的脚本,也是唯一从第一轮就在跑的。5 组检查,其中第 5 组是后来补的——补它的原因是被它自己抓到的。
前四组是标准动作:每个非目录页的 class="on" 必须恰好 1 个(多一个导航就错乱)、同目录 html/tpl 引用不许断、身份禁用词(禁用主理人/双品牌/直营店/自有门店,规则说明行本身不算违规)、样式表必须指向 assets/kb.css。
ls *.html 再减去 3 个入口页,跟展示页文案对。人肉同步早晚会漏,脚本不会。它同时把对外口径钉死成「N 篇正文 + 7 张模板」——不写「共 N 篇」,因为那会把 3 个入口页算进「篇」里虚标。这是字面意义上的一次虚标修正。
7 组检查,跨页视角。它的存在理由就是上一节那句话:换个角度查,才可能撞见盲区。
28 篇补了 4 张实测图。第一张 src="assets/chart-1-completeness.png" 正确,后三张漏了 .png 后缀:
| 图片 | 修复前 src | 线上状态 |
|---|---|---|
| chart-1 | assets/chart-1-completeness.png | 正常 唯一正确的一张 |
| chart-2 | assets/chart-2-model-top12 | 裂图 |
| chart-3 | assets/chart-3-dealer-readiness | 裂图 |
| chart-4 | assets/chart-4-rfm-3x3 | 裂图 |
href 指向同目录 html 文件」的引用存不存在。图片的 src 缺后缀,在它眼里是「链接存在,只是文件名怪」。这是我以前从没想过的检查维度——不是检查规则不够严,是规则只覆盖了我想得到的东西。修的时候还踩了个坑,值得单独讲:第一次想用一条正则批量补后缀,结果 [a-z0-9]+ 贪婪吃掉了尾部字母,把本来正确的那张也改错了(completeness → completenes)。最后是从备份还原、按完整文件名精确替换才对。教训:改历史文件先备份;一条正则想覆盖 N 处同类内容时,宁可逐处精确替换。
全库 16 个页面引用 33,176 这个订单数,但只有 28/32/33 三篇提到过全表是 33,178。其余页面的读者会把批次口径误读成全表数。
处理方式我选了集中说明而不是逐页加括注——在 24 篇(德莉玛那组的首页)插一个 note warn 块,把两个数的关系写清:
另一处是 72 万字:26 篇里有 8 处写「72 万」,全都没标口径。而实测书稿本体只有 26.5 万字(体系篇 102,668 + 落地篇 162,200),72 万是含站点与素材池的全口径。对外第一落点反而是最不严谨的那个——顺手把 llms.txt 里的同一处口径也补了。
首跑报了 14 条 CHECK,其中 12 条是「已知且不该改」:10 个页面沿用 33,176 批次口径(口径已在 24 篇集中说明,逐页加括注是噪音)、index 里「这 13 篇」、tech-index 里「这 12 篇」是分组子集,不是全库正文数。
这个脚本最有代表性,因为它的起点小得可笑:「迁 PostgreSQL」这件事,在那个项目里只有一行注释——db/seed.ts 第 14 行 process.exit(0); // close MySQL connection pool,而实际跑的是 better-sqlite3。
注释不是预案。所以我写了个只读扫描器,把「要改什么、改在哪一行、改成什么、什么优先级」打成清单。规则命中就报,每条都带文件名 + 行号 + 改法:
纪律上,这个脚本只读文本、不连数据库、不写任何文件——要改任何东西都得人批准。理由很实在:诊断工具一旦能写东西,它就不再是诊断工具了,用它的人会开始不敢跑。
查了一遍知识库:recharts / chart.js / echarts / d3 命中全部是 0,而机器上 Pillow 12.3.0 + numpy 2.3.5 是现成的。结论是——我的短板在表达层,不在绘制层。那就不用引库,用现成的把图画出来。
画这 4 张图时定的规矩,比技术本身重要:
| 规矩 | 为什么 |
|---|---|
| 分母写进标题,不写脚注 | 脚注没人看,标题人人都看 |
| 灰块 = 无数据,绝不留白 | 留白会被误读成「这块不重要」 |
| 「样本不足」四个字要印在图上 | 不是脚注,是图的结论本身 |
| 样本 < 30 的格子不给文案、不给动作建议 | 3 个样本也能算比例,但那个比例没法用来决策 |
| 单位 / 口径行 / 数据来源三件套齐全 | 缺一个,别人就没法复核你的数 |
最典型的一张是 RFM 3×3:九格全灰,中心一个深蓝块写着「样本不足 / 库里没有 member 表 / 0 条会员 → 不做分层」。这张图不好看,但它是正确的——0 条会员就是不该做 RFM,画成九格彩色渐变才是造假。图和结论见 28 篇第 09 节。
把四套脚本摆出来,很容易被问一句:那你是不是有强迫症?我的答案是——不是。这是我能给的最便宜的质量保证。
| 门禁能证明 | 门禁不能证明 |
|---|---|
| 39 篇的导航状态、链接、样式表、身份口径、篇数文案全部一致 | 不能证明内容是对的。33,178 这个数要靠人查库,门禁只是让我别把 33,176 写成全表 |
| PG 那边的待改点逐条带行号、可复核 | 不能证明该迁。清单的结论恰恰是「现在不迁」 |
| 4 张图分母、口径、来源齐全 | 不能保证好看。RFM 全灰那张就不好看,但它是诚实的 |
| 我有可复现的自我验证路径,不是靠「我记得我改过」 | 不能替代人看。跨页一致性那套脚本,是因为裂图事故才写出来的——没人想得起来的维度,只有出过一次事才会被补上 |
没做的(两栏分开写):
real_data() 里的数是实测后写死的,库一变就得手改——这是一个我知道但还没还的债。先给动作,不给形容词:我给知识库写了四套门禁脚本,全部公开可下载,其中两套真在生产环境里抓出过东西。
第一套是单页体检,189 项,查导航唯一性、断链、身份禁用词、篇数哨兵。它抓到过一次 7 个页面同时忘记同步篇数——从那以后篇数由脚本自己数,不再靠我记。
第二套是跨页一致性,7 组。它抓到 28 篇有 3 张图 src 漏了 .png,线上是裂图,而单页体检 189 项全绿——因为单页体检查的是「链接指向的文件存不存在」,缺后缀在它眼里只是文件名怪。这次之后我的结论是:不是检查规则不够严,是规则只覆盖了我想得到的东西。
同一套还抓到 16 个页面在用一个没说清口径的数字(33,176 是导出批次、全表 33,178),以及 8 处「72 万字」没标口径而书稿实测只有 26.5 万。
第三套是只读诊断:把「迁 PostgreSQL」从一行注释变成 18 处带行号的待改清单(P0 11 / P1 7),而它的结论是「现在不迁」——诊断工具的价值不在于输出动作,在于它让「不做什么」也有了依据。纪律上它只读文本、不连库、不写文件,因为诊断工具一旦能写东西,它就不再是诊断工具了。
第四套是出图:recharts / chart.js / echarts / d3 命中全是 0,但 Pillow + numpy 现成,所以我用 Pillow 手绘了 4 张图。4 张里最不好看的那张是 RFM 九格全灰,中心写着「样本不足、库里没有 member 表」——0 条会员就是不该做 RFM,画成彩色渐变才是造假。
最后我会说清楚门禁不能证明什么:它不能证明内容是对的,只能证明我没在几十次迭代里把口径、链接、篇数改乱。而「内容对不对」只能靠重新查库——这正好是我下一个要还的债:把出图脚本的数据源从写死改成自动读库。