0
0

我给 AI 生成的前端补丁加了一道 AST 验收门

最近我在做一个小型前端 Agent 工具,目标是让它根据 issue 描述自动生成局部补丁。刚开始我只看 diff 和测试结果,连续几次试跑后发现一个问题:AI 写出来的代码经常是“表面能读”,细节却不稳定。比如 import 顺序被打乱,React hook 被移动到条件分支里,类型推断被 any 偷偷绕过,或者改了一个组件 props 后没有更新关联测试。人工 review 能抓住这些问题,但每个补丁都完整读一遍,Agent 的价值会被抵消掉。

AI 补丁从 Agent 草稿经过 diff 边界、AST、类型、Lint、格式和测试门禁后再应用的流程图

原创示意图:AI 补丁先进入临时工作区,再依次通过 AST、类型、Lint、格式和测试检查,最后才允许应用到代码库。 来源:Codex image generation

问题背景

我后来把补丁处理链路改成先验收再落库。AI 仍然负责给出建议,但建议必须先进入临时工作区。工作区只把 diff 应用到一次性目录里,再跑结构化检查。TypeScript 官方 Compiler API 文档里提到 Program 表示整个应用,SourceFile 承载源文件和 TypeScript AST;示例里也通过 createProgramgetPreEmitDiagnostics 收集诊断。这个模型适合做第一道门。

关键难点

第一个坑是不要只相信文本 diff。AI 可能把一段代码写得很像正确答案,但 AST 上已经变成另一个含义。第二个坑是检查太重会让反馈变慢。如果每次都全量跑 npm test,小补丁也会排队。第三个坑是格式化不能自动吞掉风险。Prettier 的 --check 会告诉我文件是否符合格式,并在不符合时返回失败码;我更愿意先失败并记录原因,再由下一轮 Agent 明确修改。

解决思路

我的验收门分成五步。第一步只允许补丁命中白名单路径,例如 src/componentssrc/hookstests,配置文件和构建脚本必须人工确认。第二步用 TypeScript 编译器读取受影响文件,把语法错误和类型诊断转成机器可读报告。第三步跑 ESLint,自定义规则通过 visitor 抓项目内约定,比如 hook 不能出现在条件分支,桌面端桥接 API 不能从 renderer 直接 import。第四步跑 prettier --check,只检查格式,不在自动流程里静默改写。第五步用 Vitest 单次运行模式跑相关测试,能定位到文件时优先跑指定测试文件。

const report = await acceptPatch({
  diff,
  allowedPaths: ["src/components", "src/hooks", "tests"],
  gates: ["ast", "types", "lint", "format", "test"],
});

if (!report.ok) {
  return askAgentToRepair(report.failures);
}

这里最重要的是报告格式。每个失败项都必须包含文件、行列、规则名、原始错误和建议动作。Agent 下一轮拿到的是明确约束,输出会比“测试没过,重写一下”稳定很多。

可复用经验

这套门禁的收益在于把 review 前的低级风险压下去。AST 负责识别结构,类型检查负责识别契约,Lint 负责识别团队约定,格式检查负责保持提交干净,测试负责验证行为。真正需要人判断的部分会更集中:需求是否合理,组件边界是否合适,异常路径是否完整。对前端工程、Electron 桌面端和 RAG 管理台这类多模块项目来说,这道验收门很值得作为 Agent 工作流的默认入口。

主要来源

TypeScript Wiki: Using the Compiler API

ESLint Custom Rules

Prettier CLI

Vitest Command Line Interface

评论