## 第三阶段 · 检查 + 渲染 > 前两阶段已经把内容都填进了 `workflow.json`,这里只做两件事:跑检查、渲染出网页。**产物只有网页(HTML)。** | 小步 | 做什么 | |------|------| | **3.1 检查 + 渲染** | 跑两个脚本:① `lint-case.py` 检查类型完整性、内容有没有偷懒写引用、**章节有没有整段漏抽、文本 value 是不是缩写**(后两条要带 `--source` 原文才比对),并自动登记新类型;② `render-case.py` 渲染出网页(脚本在内存里组装数据,不另存中间文件)。检查报问题就回对应阶段改(**章节漏抽 / value 缩写都要回 Phase 1 补**)。 | ```bash # lint 一定要带 --source 原文 (+ --ocr 配图文本, 有就带) 才会跑「章节覆盖」+「value 逐字」两条结构/值强制 python spec/tools/lint-case.py --workflow outputs/case-N/workflow.json --case-id N \ --source input/case-N.json --ocr outputs/case-N/_scratch/ocr.txt python spec/tools/render-case.py --workflow outputs/case-N/workflow.json \ --source-input input/case-N-raw.json --page-title "Case N · 主题" --case-id N \ --out outputs/case-N/case-N-.html ``` ### 收尾检查清单 下面每条都要过,过不去就回对应步骤改: | 检查 | 规则 | 反面例子 | |------|------|------| | **输出编号唯一** | 每个输出都有编号,且工序内不重复 | 两个输出都叫 `s2o1` | | **数据流连得上** | 每个输入的"来源"(`← 某编号`)都能找到已存在的输出编号(或 `← 工序输入`、字面量) | 引用了 `← s2o9` 但根本没有这个编号 | | **类型对得上** | 输入的类型,和它"来源"指向的那个输出的类型一致 | 输入写 `分镜图` 但来源那个输出是 `参考图` | | **循环索引合理** | `[i]`/`[-1]` 用在循环里或合理位置 | 不是循环却用了 `[i]` | | **"值"写真内容** | "值"写数据本身(文字写全文;图片视频用 `<整段描述>`);不写 `← sN` 引用、不写 `[图N显示]` 这种说明 | 值 = `← s1o1`;值 = `<描述>开头的` | | **作用/动作命中词表** | 作用是 9 个标准词之一;动作是动作词表里的路径 | 作用写成"开端"(词表里没有) | | **类型命中词表或挂靠** | 类型是词表里的词,或自造但在本工序 `type_registry` 里写了"算作"哪个标准词 | 类型写"小品"却没说挂靠 `视频成品` | | **自造类型登记齐全**(脚本自动查) | 跑 `lint-case.py`,若提示"类型完整性 N 个问题",说明有自造类型没在 `type_registry` 登记 / 缺挂靠 / 缺说明 → 回去补 | `s1 输出的 type='主角图' 是自造但没登记` | | **章节全覆盖**(脚本带 `--source` 查) | 原文每个 `0N` 章节都对应到某工序/步骤;lint 报"章节覆盖 X 个章节疑似漏抽"就是有整段没抽 → 回 Phase 1 补工序 | 原文"02 结构化框架""04 更多案例"整章没抽 | | **文本 value 逐字**(脚本带 `--source` 查) | 文本类 value 是原文一整段连续文本;lint 报"value 逐字 X 处疑似缩写"就是抄了开头后缩写 → 回 Phase 1 用 `@quote` 重填 | 350 字提示词被写成"主题:…。核心要素:人物、产品、环境" | | **"目的"列规范** | ≤25 字一句话;标记取自本行真实有的值;合法类别 5 个;别写成公式 | `{act:反推}: {in-type:视频} → {out-type:提示词}`(写成公式了) |