构建记录
把手工验证变成一条命令
M6 把前面所有「跑过一次」的验证固化成可复现的门禁,并补上欠着的 Lighthouse 分数
为什么做这一步
前几步的验证有一个共同问题:它们都是「我跑过一次,当时是绿的」。
E4 三条硬校验、Slow 4G 下的 LCP、Pagefind 能不能搜到、拔掉动态层后 5 个页面可读、
表单字段有没有带来源——这些散落在十几个脚本里,靠人记得按顺序跑。
一旦换了机器、或者有人改了 src/pages/search.astro 里那段内联脚本,
之前的「绿」就悄悄失效了,而没人会知道。
M6 要解决的不是「再测一遍」,而是让「测过」这件事本身可复现、且断了会报警。
落地了什么
- 两条链:
pnpm run quality(构建 + CSP 生成 + check + E4 三条 + 24 个单测 + 链自检),pnpm run quality:browser(性能/搜索/线索/不变量 + Playwright + Lighthouse + axe)。 本地和.github/workflows/ci.yml跑的是同一组脚本,CI 不另搞一套只在 CI 里绿的断言。 - 补上 M4 欠的账:之前只有 CDP 自测 LCP,不是 Lighthouse 分数。这一步用本机真实 Chrome 跑 Lighthouse 13,四类分数都是 100(门槛 95),G2 才算真的闭环。
- 严格 CSP 从产物反推:审计 18 个 HTML 后确认只有
/search一个内联脚本, 于是script-src只放行'self'+ 一个 sha256 +'wasm-unsafe-eval',不放unsafe-inline。 本地服务器和 Playwright 把 CSP 作为真实 HTTP 响应头发出,测的是与托管平台一致的行为。
又一次「假测试」的教训
这一步修掉的 bug 里,绝大多数不在站点代码,而在测试自己:
verify-ci.mjs初版用字符串包含判断「回归脚本有没有进链」,把经test间接进入的test:rules/test:unit误报成孤立 → 改成 BFS 可达性。- Playwright 首跑 4 条红:主 CTA 在首屏和次级区各出现一次(设计如此)、
CSP 断言误伤了
style-src里明确放开的unsafe-inline、中文 slug 被浏览器百分号编码。 - axe 首跑倒是真的抓到 2 处站点缺陷:作品/日志列表页 h1 下面直接是 h3,
跳过了 h2。这是 M6 唯一改到生产代码的修复(卡片标题支持
headingLevel)。
还有一个不大但会咬人的发现:pnpm ci 是 pnpm 内建的 clean-install 命令,
会静默遮蔽 package.json 里的同名脚本。所以门禁改叫 quality,不叫 ci。
故意写坏一次
CI 的 DoD 要求「故意破坏一条 schema 时 CI 必须红」。我没有只写一个断言,
而是真的往 src/content/capabilities/ 塞了一条 evidence_ids: [] 的内容:
pnpm build 退出码 1、错误可读;删掉后退出码 0。
因为 quality 链里包含真实 build,把违规内容提交进仓库时 CI 也必然红。
「测试通过了」和「测试真的测了」之间,差的往往是一次故意写坏的探针。 这句话 M3 写过一次,M5 又写过一次,M6 再写一次——它值得重复。
相关记录
- 把动态层拔掉,站还站得住吗 · 2026/11/12