核心摘要

AI 生成的代码不会因为作者是模型就天然低质,人写的代码也不会因为作者是人就天然可靠。真正有用的问题是:这次变更是否满足版本化契约,并产生了足够的安全合并证据。

把生成视为提案,把验证视为验收。可靠工作流由明确任务边界、代码库上下文、确定性检查、结构断言、独立审查和分阶段生产证据组成。单元测试通过是一条信号,不是可维护性或安全性的证书。

把质量定义为可观察证据

“干净代码”过于主观,无法直接成为发布门禁。团队应先定义变更必须保持的属性,以及证明每项属性的证据。

质量维度 核心问题 更强证据
功能正确性 需求行为是否成立? 回归、属性、集成和负向测试
兼容性 公共契约或持久化数据是否变化? API/Schema Diff、Migration 演练、Consumer Test
可维护性 变更是否符合既有 Ownership 与抽象? 变更局部性与结构断言
安全性 不可信调用方能否跨越边界? 授权测试、SAST、依赖与 Secret 检查
可靠性 Timeout、Retry、Cancel、Restart 时怎样? 故障注入、幂等和对账测试
性能 延迟、内存或计算是否退化? 固定环境下的工作负载基准
可运营性 团队能否观测并撤销变更? Metric、Log、Alert、灰度与回滚证明

这些契约应在实现前写清楚。规范驱动开发只有在 Spec 明确行为、不变量、失败语义和验收证据时才有价值;把含糊需求改写成更长的含糊文档并没有帮助。

当前证据究竟说明了什么

现有研究不支持“AI 代码一定更差”这种普遍结论。证据说明质量会随任务、语言、工作流和测量方式变化,而且功能成功会漏掉重要失败类别。

  • Needle in the Repo(NITR) 是 2026 年预印本,用功能测试与结构 Oracle 评估 21 个经过设计的 C++ Repository Probe。在该诊断环境中,一些变更通过了行为测试,却破坏了目标可维护结构;论文数字不能外推到全部语言和生产仓库。
  • 2026 年生产 C++ 研究在一家大型企业中沿 Authoring-time Provenance 跟踪代码经过 Review、Static Finding 和运营信号的过程,报告了特定问题分布与针对性反馈效果。组织、语言、工具链和观察性研究设计限制了可迁移性。
  • NIST SSDF 给出稳定的软件开发控制:保护软件、产出更安全的 Release、响应漏洞并治理根因。它没有为 AI 代码提供例外,也没有定义单一综合分。

工程结论应更窄也更实用:所有变更承担相同发布责任,再针对 Coding Agent 带来的生成规模、不确定性、Provenance 和 Tool 权限增加控制。

从变更契约开始

Coding Agent 需要的是有边界的变更契约,而不是一个 Persona。

text
Goal:
  为 invoice retry 增加幂等能力,不改变定价行为。

Authoritative sources:
  api/invoice.yaml
  internal/billing/repository.go
  internal/billing/retry_test.go

Invariants:
  保留 Tenant 与 Principal 校验。
  相同 Operation Key 不能创建两笔扣款。
  Dispatch 后 Timeout 必须进入 outcome_unknown。

Allowed scope:
  internal/billing/**
  api/invoice.yaml

Evidence:
  相关测试、Race Test、Schema Diff、已审 Migration Plan。

Escalate:
  任何授权、数据库、依赖或外部 API 变化。

“像资深工程师一样工作”不是可验证不变量,“不得改变公共 API”才是。AI 编程助手定制进一步解释如何把可复用 Repository Rule 与任务级验收条件分开。

建立分层验证门禁

没有任何单一 Checker 能证明软件质量。按成本从低到高排列门禁,让便宜的确定性失败在进入高成本 Review 前终止变更。

flowchart LR A["变更契约"] --> B["范围与 Diff 检查"] B --> C["Build、类型、Lint"] C --> D["功能与负向测试"] D --> E["结构与安全检查"] E --> F["独立 Review"] F --> G["分阶段发布"] G --> H["生产证据"] H --> I{"接受或回滚"}
  1. 范围与来源:识别生成文件、Ownership 边界和意外文件。
  2. 构建与静态检查:Compile、Type Check、Format、Lint、Secret Scan 和 Dependency Policy。
  3. 行为测试:覆盖目标路径、非法输入、授权、并发和历史回归。
  4. 结构检查:断言 Patch 复用目标抽象、隔离副作用且没有复制 Policy。
  5. 独立审查:检查 Diff 与证据。第二个模型可以发现候选问题,但可追责的人或服务拥有决策权。
  6. 发布控制:Canary、Feature Flag、Rollback 与 Monitoring 把源码置信度连接到生产行为。

用 Go 实现可执行证据门禁

下面的标准库程序验证 Evidence Record,而不是相信模型描述。必需门禁缺失或未通过时,它会 Fail Closed。

go
package main

import (
	"errors"
	"fmt"
)

type Check struct {
	Name     string
	Required bool
	Passed   bool
	Evidence string
}

func Evaluate(checks []Check) error {
	seen := map[string]bool{}
	for _, check := range checks {
		if check.Name == "" || seen[check.Name] {
			return errors.New("invalid or duplicate check")
		}
		seen[check.Name] = true
		if check.Required && (!check.Passed || check.Evidence == "") {
			return fmt.Errorf("required check failed: %s", check.Name)
		}
	}
	for _, required := range []string{
		"scope", "build", "tests", "security", "review", "rollback",
	} {
		if !seen[required] {
			return fmt.Errorf("required check missing: %s", required)
		}
	}
	return nil
}

func main() {
	checks := []Check{
		{Name: "scope", Required: true, Passed: true, Evidence: "diff.json"},
		{Name: "build", Required: true, Passed: true, Evidence: "build.log"},
		{Name: "tests", Required: true, Passed: true, Evidence: "tests.xml"},
		{Name: "security", Required: true, Passed: true, Evidence: "sast.sarif"},
		{Name: "review", Required: true, Passed: true, Evidence: "review-42"},
		{Name: "rollback", Required: true, Passed: true, Evidence: "runbook.md"},
	}
	fmt.Println(Evaluate(checks))
	// Output: <nil>
}

生产系统应按不可变 Revision 签名或保存证据,并绑定到被 Review 的精确 Commit。“测试已通过”这行文本不等于目标 Revision 的测试输出。

增加结构 Oracle

行为测试询问当前案例是否工作,结构 Oracle 询问实现是否保留了未来变更依赖的工程属性。

实用结构断言包括:

  • 只有目标 Package 拥有某条业务规则;
  • 新类型扩展既有 Interface,而不是复制 Dispatch Logic;
  • 生产代码没有导入 Test-only 或未经批准的 Dependency;
  • Authorization 仍位于 Service Boundary;
  • Generated Client 由生成器重建,而不是手工修改;
  • 时间、随机数和网络等不确定依赖可注入测试;
  • 外部副作用统一经过一个幂等 Adapter;
  • Schema 变化包含兼容 Reader、Migration 和 Rollback。

不要把任意 Style Preference 都设成硬门禁。每条 Oracle 都应保护一个具名风险,并返回可行动诊断。Linting适合可重复的局部规则,架构与领域不变量通常需要 Repository 专用检查。

独立验证安全与供应链

Agent 可以完成 Feature,同时扩大攻击面。重点检查:

  • Caller、Tenant、Object 与 Operation Authorization;
  • Secret 访问、日志、Telemetry 与 Prompt/Tool Payload 留存;
  • 新 Package 的名称、版本、License、Registry 和 Install Script;
  • 生成期间使用的命令、文件系统、网络与 Credential Scope;
  • 不安全反序列化、Injection、Path Traversal、SSRF 与 Shell 拼接;
  • Timeout、Retry、重复请求、Cancel 与 Partial Commit 行为。

“请写安全代码”无法强制这些属性。固定依赖、使用可信 Registry、运行安全工具、隔离执行并测试应用边界。Repository 文本和 Issue 描述都应视为不可信输入,因为它们可能携带提示注入。

让人工审查围绕证据展开

Reviewer 在拿到小而连贯的 Diff 和具体证明时最有效:

  • 目标行为和 Non-goal;
  • 变化的公共契约与数据 Migration;
  • 修复前真实失败的测试;
  • 最终 Revision 上通过的测试;
  • Security 与 Dependency Finding;
  • 未解决假设和跳过检查;
  • Rollout、Monitoring 与 Rollback Plan。

不要要求 Reviewer 从数千行生成代码中猜测意图。拆分独立变更,限制无关格式 Churn,拒绝无法复现的生成产物。Reviewer 应挑战契约与证据,而不是只看语法。

衡量完整生命周期,而不是建议采纳率

Acceptance Rate 奖励“看起来合理”的输出,真正需要测量的是被接受变更能否存活。

信号 能揭示什么
按风险切片的任务成功率 工作流能否解决目标任务
Merge 前返工 隐藏的 Steering 与 Verification 成本
逃逸缺陷与回滚 哪些失败穿过了发布前门禁
变更局部性 小需求是否跨越了过多 Ownership
Dependency 与 API 增长 长期兼容性和供应链负担
Review Latency 与 Reviewer Confidence 人工瓶颈与证据质量
生产延迟、成本和事故 Merge 后的运营后果
理解与修复时间 Comprehension 与维护负担

记录 Model、Agent、Instruction、Tool、Repository 和 Evaluator Revision。没有 Provenance 的分数无法解释究竟是哪一部分系统发生了变化。

常见失败模式

  • 用“资深工程师”Persona 替代明确不变量;
  • 因为新增 Happy-path Test 通过就批准 Patch;
  • 允许模型绕过 Registry 和 License 检查添加依赖;
  • 把模型 Confidence 或 Self-review 当作校准证据;
  • 在功能变更中混入无关清理;
  • 不检查语义就接受 Snapshot Churn;
  • 因为任务看似普通就授予宽泛 Credential;
  • 没有 Idempotency 或 Reconciliation 契约就重试外部写入;
  • 只统计生成代码行,而不统计长期可维护结果;
  • 没有可追责 Reviewer 和 Rollback Path 就发布。

常见问题

为什么 AI 生成代码通过测试后仍可能质量很差?

测试只覆盖已经编码的观察,可能遗漏重复 Policy、错误 Ownership、绕开的抽象、意外公共 API 和未来扩展路径。除了当前示例,还要使用结构断言,并按 Repository Architecture 审阅变更。

更好的 Prompt 能否保证代码可维护?

不能。更好的上下文与指令可以改善提案分布,但无法强制结果。确定性工具、Repository Policy、独立 Review 和生产控制必须决定是否接受提案。

AI 生成代码的最小验证流水线是什么?

审阅 Diff,执行 Compile 或 Type Check,运行相关与负向测试,检查 Dependency 与 Security 变化,验证 Authorization 和 Side Effect,并要求可追责审批。Migration、外部写入、隐私敏感路径和大型变更需要更高门槛。

团队是否应该拒绝所有大型 AI 生成变更?

不应,但规模会提高举证责任。优先拆成独立、可审查的 Commit。无法拆分的 Migration 应提供生成与手写边界、确定性再生成、Consumer Test、灰度发布和经过演练的回滚。

团队应该如何衡量 AI 代码质量?

同时跟踪任务成功和接受后的下游成本:返工、缺陷、回滚、Dependency 增长、Review 时间、生产性能与修复时间。按任务和风险切片,避免用一个全局“AI 采纳率”掩盖关键失败。

总结

提升 AI 生成代码质量的持久方法,是让验收证据强于生成置信度。定义变更契约、约束范围、运行分层确定性与结构门禁、审阅精确 Diff,并用生产证据约束发布。模型可以写出 Patch,工程系统负责判断它是否值得长期保留。

一手来源

相关资源