一篇正文完整的 Markdown,可能只因为头部写成下面这样,就不应该进入发布集合:
kind: note
accent: green
featured: "yes"
这三个值都能被当成普通文本读出来,却不满足当前博客的数据契约。问题如果一直拖到页面生成以后才暴露,作者看到的往往不是“第几篇文章的哪个字段错了”,而是缺少索引、错误筛选或不完整订阅。
这篇文章只区分三件事:当前已经硬失败的契约、曾经会静默退化的路径,以及仍然需要人工判断的内容质量。
内容链路有四个责任层
Markdown source
→ typed content index
→ repository / curation
→ static pages and feeds
Markdown 是作者维护的事实来源。生成脚本解析元数据和正文,产出类型化文章索引;内容仓库再组织 Start Here、系列、About 代表作、搜索和相关推荐;Next.js 最后生成文章 HTML、元数据、RSS 与 Sitemap。
四层不能维护同一份重复真相:
- 标题和摘要只写在 Markdown,不在策展配置里复制;
- 生成索引只由脚本产生,不手工修改;
- 策展只保存 slug 与顺序;
out/是构建产物,不是内容源。
这样出现漂移时,才知道应该在哪一层失败。
front matter 已经是硬契约
当前生成器会直接拒绝:
| 输入问题 | 当前行为 |
|---|---|
| 缺少必填字段 | 生成失败并指出文件与字段 |
| 未知或重复字段 | 生成失败 |
| 非法日期、kind 或 accent | 生成失败 |
非布尔 featured | 生成失败 |
| 空 tags 或非法标签值 | 生成失败 |
| 非小写 kebab-case 文件名 | 生成失败 |
| 重复 slug | 生成失败 |
这不是“建议以后严格校验”,而是当前内容生成阶段已经执行的检查。
生成器仍然故意不判断文章观点是否成立、系列是否真正推进同一个问题。这类判断没有稳定的机器 oracle,应该留给编辑审阅。严格 schema 的目标是阻止确定性错误,不是让作者为了过门禁填出形式正确的空话。
一个被 slice 掩盖的策展错误
策展引用已经有明确失败入口。Start Here、About 和系列按 slug 解析文章,目标不存在时会抛错;相关推荐也会排除当前文章本身。
但首页代表作曾经使用另一种行为:
筛选 featured=true
→ slice(0, 3)
→ 渲染首页
如果第四篇文章被标为 featured,页面仍能正常构建,只是多出的代表作被静默截断。这种“看起来没坏”的退化比明确报错更难发现,因为内容源和最终页面都各自像是合理的。
本轮把规则前移到了内容生成阶段:featured 必须恰好为三篇,否则直接失败。首页仍保留容量限制,但它不再承担发现内容错误的职责。
| 契约 | 当前失败位置 | 还需要什么 |
|---|---|---|
| front matter 合法 | 内容生成器 | 已实现 |
| 策展 slug 存在 | 仓库解析 / 构建 | 已实现 |
| featured 恰好三篇 | 内容生成器与测试 | 本轮补齐 |
| 相关推荐不包含自身 | 仓库逻辑与测试 | 已实现 |
| 系列是否推进同一问题 | 人工编辑审阅 | 不能只靠代码 |
这和《一条被 continue 绕过的 Kill 条件检查》是同一种教训:规则写下来了还不够,必须检查它真正位于哪条控制流上。
RSS、Sitemap 与隐私分别能证明什么
当前测试会确认每篇文章进入 RSS 和 Sitemap,About 也出现在 Sitemap 中;公开内容对象还会检查手机号、简历私有字段、内部仓库标识和本地来源路径。
这些测试能够证明被列出的确定性契约,没有证明所有上下文敏感信息都安全。一个看似普通的业务 ID、脱敏不完整的请求样本或能够反推出客户的信息,仍然需要人工审阅。
同样,RSS 项数一致只说明文章集合对齐,不说明摘要写得好;Sitemap 有 URL 也不证明页面中的论点可信。内容基础设施负责“正确发布了哪一批文字”,不能替文章完成事实核查。
静态导出的完成证据
当前发布链按下面的顺序收敛:
generate content
→ lint / typecheck / test
→ static build
→ upload to staging
→ verify per-file hashes
→ atomic directory switch
→ retain rollback copy
这里能够确认的是:构建产物经过文件数、文章数、RSS、Sitemap、隐私模式和 SHA-256 核对,切换前保留完整备份与快速回滚目录。
这不等于已经证明任何条件下都零停机,也不意味着正则扫描能够识别全部隐私风险。部署流程提供的是可重复检查与可回退路径,不是绝对保证。
失败报告应该指向编辑动作
一个对作者有用的内容报告,至少要按层输出:
frontmatter fields and enums valid
curation every slug resolved
featured exactly 3
routes every article exported
feeds RSS / Sitemap aligned
privacy no deterministic hit
每项失败都应指向文章、字段或引用,避免作者在长构建日志里猜原因。当前项目已经分别通过生成器、仓库测试和静态构建覆盖这些层;上下文隐私和系列质量继续由人工负责。
Markdown 写完只是源文件状态。只有它进入正确的类型索引、策展关系、静态页面和发布集合,才完成这次内容变更。