深入解读 Slang 的 AST-to-IR 文档评审报告:LLM 生成设计文档的独立审查与修复闭环
【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang
Slang 仓库在docs/generated/design/下维护着一套由 LLM 从编译器源码逆向生成的设计文档,并为每篇文档配备了“独立评审 → 修复(remediation)→ 台账记录”的质量保障流水线。本文以 pipeline/04-ast-to-ir.md.review.md 这份真实评审报告为主体,逐字段拆解其结构契约、逐条解析三条发现(finding)及其源码证据,并追踪它如何驱动下游修复、写入台账,帮助读者理解这套“文档即代码”的 QA 机制如何运转、如何复现和核验。
这份报告在流水线中的位置
报告被评审的对象是 pipeline/04-ast-to-ir.md——一篇讲解 Slang 编译器“已检查 AST → Slang IR” lowering 阶段的设计文档,其核心内容包括generateIRForTranslationUnit驱动入口、IRBuilder指令创建、LoweredValInfo复合值语义等。按 regenerate.md 中定义的流程,评审阶段有两个硬性身份约束:
- 评审必须由与生成方不同模型家族的模型执行(生成方是 Claude,评审方在报告中记录为
gpt-5.6-sol); - 评审者只输出报告、绝不改写被评审文档,所有编辑留给后续同家族的修复阶段完成。
评审报告固定存放在_meta/reviews/<manifest-key>.review.md,目录层级与被评审文档的 manifest key 一一对应,同一文档在磁盘上任意时刻只保留最新一份报告——这份文件的落盘路径docs/generated/design/_meta/reviews/pipeline/04-ast-to-ir.md.review.md正是该契约的体现。
Front-matter:评审报告的机器可读契约
报告开头的 YAML front-matter 是整份报告的“骨架数据”,其形状由 review-report.schema.json 严格约束(additionalProperties: false,不允许出现 schema 之外的键)。本报告的实际取值如下:
| 字段 | 本报告取值 | 含义 |
|---|---|---|
review_report | true | 哨兵字段,标记该文件为评审报告,lint 会校验 |
reviewer_model | gpt-5.6-sol | 评审模型标识;schema 要求不得包含claude/anthropic,记账命令mark-reviewed也会据此拒收 |
reviewed_at | 2026-08-04T12:08:18+00:00 | 评审时间(ISO 8601) |
target_doc | pipeline/04-ast-to-ir.md | 被评审文档的 manifest key |
target_doc_source_commit | 53b76e6d… | 被评审文档 front-matter 中记录的源码提交 |
target_doc_watched_paths_digest | bfaba426… | 评审时文档 front-matter 中记录的 watched-paths 摘要 |
source_commit | 53b76e6d… | 执行评审时仓库 HEAD |
checklist | 六个维度,见下表 | 每个评审维度必须给出pass/partial/fail |
finding_count | 3 | Findings 表行数 |
severity_breakdown | critical: 0, major: 1, minor: 2, nit: 0 | 四项之和必须等于finding_count,lint 强制校验 |
六个 checklist 维度在本报告中的取值值得注意:cross_references(相对链接全部解析)与style_consistency为pass,而factual_accuracy、completeness、source_alignment、front_matter_validity均为partial。按评审契约,每个非pass维度至少要落一条 finding,这解释了为什么三条发现分别指向 front-matter 摘要不一致(对应front_matter_validity)和两处源码对齐问题(对应source_alignment/completeness)。
“Items checked”:评审者实际做了什么
报告的## Items checked一节用具体数字记录了核验工作量,这也是判断一份评审报告可信度的关键:
- 读取了评审提示词、
_common.md契约、逐页提示词、被评审文档及两个依赖文档,并用regenerate.py show pipeline/04-ast-to-ir.md解析出评审时的7 个watched 源文件; - 通过
git diff确认这些 watched 文件相对记录的 source commit53b76e6d…无工作树漂移; - 抽查30 余个事实性论断:驱动函数签名、lowering visitor 与缓存、
IRBuilder标志位、AST 映射、内建算子、witness lowering、泛型约束处理、诊断、布局生成、入口点装饰、调试信息行为; - 重新推导了文档中全部 42 处显式行号引用及其区间端点,确认每处都指向声称的符号或行为;
- 解析了全部 34 处相对链接,确认引用的生成文档同辈页都在 manifest 中;
regenerate.py lint无结构或链接错误; - 重算了 watched-paths 摘要,确认与 front-matter 不一致(即 F-001)。
三条发现逐条解析
F-001(major):front-matter 摘要与台账不一致
报告发现文档 front-matter 记录的watched_paths_digest是bfaba426…,但当时 manifest 解析出的 7 个 watched 文件经regenerate.py digest计算得到b5b08783…——即文档 front-matter 无法标识其真实受审的源文件集合。证据链是 freshness.json 中该文档条目记录的权威摘要,加上git diff确认 7 个 watched 文件与 source commit 一致。修复建议明确写着:应通过生成工作流刷新该文档,再让评审元数据基于新摘要重新生成,“不要只修台账”。
理解这条发现需要结合系统设计:mark-fresh只把真实摘要写进freshness.json而不改写文档本身,因此文档 front-matter 里的摘要“只和上次生成代理写下的值一样新”,陈旧性是设计内现象,新鲜度判定一律以freshness.json为准。从当前树状态看,该文档已于 2026-09-11 基于 source commit48c746dc…重新生成,front-matter 摘要758dc600…与 freshness.json 记录完全一致,F-001 所描述的不一致在当前树上已不复存在。
另外可以注意到一个细节:评审时 manifest 解析出 7 个 watched 文件,而当前 manifest.yaml 中pipeline/04-ast-to-ir.md条目已扩展为16 条watched 路径(末尾新增的source/slang/slang-compile-request.cpp还带有注释,说明该页文档涉及 ending AST lowering 的setIRModule交接)。这正是 regenerate.md 中“manifest 缺口是最常见的一类流程发现”这一经验教训的实例:修复过程暴露文档引用了原本未被监视的文件,manifest 被拓宽后 digest 变化、文档被标记 stale,再走一遍生成-标记流程。
F-002(minor):漏记的一处 AST 变异
被评审文档在## Module-level outputs(约 440-455 行)与### Entry-point-scoped decorations(约 468-476 行)断言generateIRForTranslationUnit“没有额外副作用产物”,报告指出这遗漏了一个持久的 AST 变异:当某个已注册入口点没有显式EntryPointAttribute时,lowering 会创建一个该属性、用入口点 profile 填充其能力集,并在 lowering 该函数之前把它挂到 AST 函数上,使普通函数 lowering 能识别注册入口点。报告给出的证据位置是source/slang/slang-lower-to-ir.cpp:15215-15223。
在当前 HEAD 上可以直接核验这一行为:slang-lower-to-ir.cpp 中可见findModifier<EntryPointAttribute>()判空后create<EntryPointAttribute>()并addModifier(entryPointFuncDecl, entryPointAttr)——逻辑不变,行号随源码演进从 15215 一带漂移到了 15584-15592。这也提醒读者:此类行号引用天然有时效性,正是评审流程存在的意义之一。
F-003(minor):布局模块的描述过窄
报告发现## Adjacent pipelines(约 537-544 行)把布局模块(04c-layout-ir 对应产物)描述为“只有挂在 stub 全局变量和入口点上的IRLayoutDecoration”。实际上它还:装饰模块根节点、发射这些装饰所依赖的类型/变量布局指令、并可以向入口点 stub 附加IRRequireCapabilityAtomDecoration。证据位置为source/slang/slang-lower-to-ir.cpp:16395-16450(创建导入全局 stub 加类型/变量布局,并装饰全局与模块根)与16470-16498(创建入口点 stub、加能力原子装饰与布局装饰)。修复建议要求把该模块改写为“包含导入全局/入口点 stub、模块/全局/入口点布局装饰及其支撑布局元数据、以及相应能力装饰的布局聚焦模块”,避免断言布局装饰是其唯一内容。
下游闭环:修复报告与台账记录
评审不是终点。按 regenerate.md 定义的两阶段流程,下一步是由生成同家族(Claude)的代理执行修复,产出结构化的修复报告。04-ast-to-ir.md.remediation.md 记录了对三条发现的处置:
| Finding | 动作 | 理由摘要 |
|---|---|---|
| F-001 | rejected-out-of-scope | 修复提示词约定generated_at/source_commit/watched_paths_digest三个字段由操作员的mark-fresh运行负责,代理不得自行编辑;摘要会在操作员后续标记 fresh 时刷新 |
| F-002 | fixed | 在 HEAD 上确认后,把## Module-level outputs中“no additional side artefacts”的表述改写为“返回的IRModule是唯一的独立输出对象,另有隐式入口点属性被加入已检查 AST” |
| F-003 | fixed | 确认createIRModuleForLayout会装饰模块根并向入口点 stub 添加能力原子装饰后,重写## Adjacent pipelines中 04c 条目,列出 stub、模块根与 stub 的布局装饰及其支撑指令 |
两份报告随后由regenerate.py mark-reviewed/mark-remediated写入台账 review-state.json:last_reviewed记录评审模型、时间与 severity 分布(target_doc_watched_paths_digest为b5b08783…),last_remediated记录修复模型claude-opus-5与动作计数(2 fixed + 1 rejected-out-of-scope)。台账据此推导文档状态:当freshness.json中该文档的 digest 与last_reviewed.target_doc_watched_paths_digest一致且修复指向当前评审报告时,review-status会显示remediated。若文档重新生成(mark-fresh使 digest 变化),状态立即回到review-stale,触发下一轮评审——这就是生命周期图中 reviewed → stale → reviewed 的循环。
一个容易被忽略的设计点:修复不修改front-matter 的摘要字段(如 F-001 被拒的理由),因为那会造成“修了文档但台账仍指旧摘要”的半吊子状态;正确顺序永远是 manifest 变更 →mark-fresh→mark-reviewed/mark-remediated。regenerate.md 还记录了反面教训:某次周期里因最后才拓宽 manifest,21/31 份刚记录的评审被无谓地全部翻成review-stale。
给维护者的启示:如何复现与核验这份报告
这份报告为理解整个生成文档 QA 体系提供了一个完整切片,核验路径可以完全复现:
- 结构核验:
python3 docs/generated/design/_meta/regenerate.py lint pipeline/04-ast-to-ir.md—— lint 同时校验 front-matter 键、链接可达性、报告 front-matter 对 schema 的符合性,以及 severity 计数与finding_count的一致性; - 新鲜度核验:
regenerate.py digest pipeline/04-ast-to-ir.md重算 watched 摘要,与 freshness.json 对比;regenerate.py show pipeline/04-ast-to-ir.md列出 manifest 条目与当前解析出的 watched 文件清单; - 发现核验:报告中每条 finding 的 Evidence 列都给出 workspace 相对路径加行号,可直接对照 slang-lower-to-ir.cpp 与 04-ast-to-ir.md 相应章节(注意行号随提交漂移,行为才是核验对象);
- 闭环核验:
regenerate.py review-status pipeline/04-ast-to-ir.md输出该文档在台账中的当前状态,确认 review → remediation 周期是否闭合。
这套机制的核心哲学值得借鉴:文档是由代理从源码逆向生成的,评审必须由异家族模型独立执行以避免“生成与审查共享同一幻觉”;结构违规(断链、缺字段)走硬门槛 lint,内容漂移走台账记录与操作员驱动的刷新而非自动改写;front-matter 里的摘要允许陈旧,但台账是唯一事实源。对于任何“LLM 生成 + 人工/代理审阅”的文档工程,这份 47 行的评审报告连同它的 schema、提示词契约与下游修复记录,就是一个可以直接对照实施的参考实现。
【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考