AI-native SDLC · 第 1 篇

AI 能不能像人一样把软件打磨出来?我拿一个 IAM 平台试了半年

让 AI 写代码不难,难的是知道它写对没有。我用 auth9 这个项目试了一套办法:QA 文档当规格,16 个 skill 把规划、测试、修复、部署串成一个闭环。

发布于 更新于 7 分钟 #ai-native-sdlc #auth9 #agent-skills #qa

这是《同一套方法论,我用了三次,结果各不一样》的上半篇。最早的版本是 2026 年 2 月写的,放在 auth9 仓库的 docs/blog-ai-native-sdlc.md 里,有英中日三种语言。这一版是按项目结束时(6 月 27 日,491 次提交)的状态重写的。

我想弄清楚的一件事

2026 年初,我想回答一个问题:如果几乎所有代码都让 AI 写,能不能做出一个真正能上生产的东西?

不是 demo,不是周末小项目。得是一个复杂到能把方法论逼出原形的系统,而且安全要求高到”差不多能用”根本不算数。

我选了 IAM,也就是身份和访问管理。它里面全是互相咬合的东西:多租户隔离、OIDC 和 OAuth2、Token Exchange、层级 RBAC、webhook 签名、审计日志。一个决定做错,会在十几个地方冒出隐蔽的 bug。做 TODO 应用证明不了什么,任何方法在简单问题上都好看。

结果就是 Auth9,一个自托管的 Auth0 替代品,Rust 后端、React Router 7 前端、TiDB、Keycloak,线上有个实例在 auth9.c9r.io。代码几乎全是 AI 写的,每一步几乎都由 skill 驱动。但 Auth9 本身只是副产品,我真正在试的是那条流水线。

Auth9 管理后台

瓶颈根本不在写代码

用过 Copilot、Cursor、Claude Code 的人都知道,代码确实写得快了。但写代码从来不是最难的部分。难的是知道这段代码对不对,而且要知道得够快、够自动,不然验证就成了新的瓶颈。

AI 写出来的东西经常看着很对,一跑就倒:缺依赖、lint 不过、逻辑错。每次出错都由我去提示它,效率太低。所以我定了一条原则:验证必须和写代码一样自动化。AI 写完,自己测;测不过,自己修。我不做那个每次都要盯着报错的人。

反过来说,如果代码产出快了 10 倍,验证还靠人,那你只是得到了 10 倍的 QA 积压。

测试往前挪了一格

代码级的测试还在:cargo test 一两秒跑完,不依赖任何外部服务,我明令禁止 testcontainers 和真实数据库;Playwright 跑端到端;Vitest 管前端。这些也都是 AI 生成的。

我在这之前加了一层:QA 测试文档。就是一份结构化的说明,写清楚测什么、怎么测、在数据库里怎么核对结果。AI 生成,我审,然后 AI 执行:开浏览器点、调 API、查数据库、打 gRPC。说白了它更像传统的手工测试,只是自动化了。它现在还不能完全替代手工测试,但已经能扛下绝大部分。

顺序也变了。测试计划不是功能上线后补写的,而是功能规划完之后产出的第一份东西。它决定后面写什么代码、验什么、出问题时能抓到什么。

顺便说一下我对 spec-driven development 的看法:QA 文档才是 spec。设计文档描述你想要什么,但它没法告诉你有没有得到。QA 文档两件事都做:既定义预期行为,又能在跑着的系统上自动验证。设计文档过时了没人知道,QA 文档在现实偏离规格的那一刻就会失败。不能执行的规格,只是愿望。

那条流水线

16 个 Agent Skill 串在一起,每一步的输出是下一步的输入:

人 + AI ──► 规划功能


        ┌─ 生成 QA / 安全 / UIUX 测试文档   (qa-doc-gen)

        ┌─ 自动执行测试                      (qa-testing, e2e-testing, ...)

        ┌─ 失败 → 结构化工单                 (docs/ticket/)

        ┌─ 读工单 → 复现 → 修代码 → 重置环境
        │   → 重跑测试 → 关工单             (ticket-fix)

        ┌─ 周期性审计文档质量               (qa-doc-governance)

        ┌─ 重构后对齐测试                    (align-tests, test-coverage)

        ┌─ 部署到 Kubernetes                 (deploy-gh-k8s)
        └─────────────────────────
阶段Skill
规划project-bootstrap
编码rust-conventionskeycloak-theme
测试文档qa-doc-genqa-doc-governancefeature-request-governance
执行测试qa-testinge2e-testingperformance-testingauth9-grpc-regression
修复ticket-fixalign-tests
覆盖率test-coverage(各层不低于 90%)
部署deploy-gh-k8s
运维opsreset-local-env

每个 skill 就是一个 markdown 文件加几个脚本。同一套内容通过目录镜像和符号链接给 Claude Code、Gemini 和 Cursor 共用,不用维护三份。

信息交换我选了最土的办法:文件系统。docs/qa 放规格,docs/ticket 放工单。agent 玩 bash 玩得很溜,读写文件又准又快,而且整个过程留痕,出了问题回头就能翻。

一份真实的 QA 文档长什么样

这是租户 CRUD 那套测试里的一个场景:

初始状态:用户已登录管理后台;数据库中不存在同 slug 的租户。

测试步骤:确认左侧边栏存在”租户管理”入口 → 进入列表 → 点击”创建租户” → 填写名称 Test Company、slug test-company、Logo URL → 点击”创建”。

预期结果:显示成功提示;租户出现在列表中,状态为 Active。

预期数据状态

SELECT id, name, slug, logo_url, status FROM tenants WHERE slug = 'test-company';
-- 预期:存在一条记录,status = 'active'
SELECT action, resource_type FROM audit_logs WHERE resource_type = 'tenant' ORDER BY created_at DESC LIMIT 1;
-- 预期:action = 'tenant.create'

最后那段 SQL 是关键。AI 不能只看 UI 弹了”成功”就算过,它得去数据库里确认数据真的落了。“前端说成功、后端悄悄失败”这一整类 bug 就是这么抓出来的。

docs/qa/_manifest.yaml 是这些文档的清单,scripts/qa-doc-lint.sh 管格式。

AI 是怎么”打磨”的

ticket-fix 这个 skill 是整条流水线里最有意思的部分。测试失败会生成一张结构化工单,然后它:读工单、复现、做最小修复、重置环境(每次必做,不然环境脏了什么都测不准)、按工单原步骤重跑并留证据、分析假阳性、关工单。

假阳性分析是这套东西能转起来的关键。不是每个失败都是 bug。很多时候是测试本身有问题:命令少了个认证头,前置条件写得含糊,环境假设和 Docker 默认配置对不上,测试数据引用了根本不存在的东西。确认是假阳性之后,skill 不是把工单一关了事,它会回去改 QA 文档:把隐含要求写明,让示例命令能直接复制运行,补一张排障表。

所以不管失败原因是真 bug 还是测试写坏了,测试套件都会在每次失败后变得更好一点。软件和规格一起收敛。这就是我说的”打磨”。

这些批处理的结果会直接出现在提交标题里,比如:

Resolve 27 QA tickets: fix 9 bugs, close 14 false positives, defer 4 feature gaps
Fix 44 QA tickets: 3 bugs, 41 false-positive doc updates

整个项目里这样的提交有 36 次。

文档会烂,怎么办

测试文档会过时。路由改了、API 变了、权限重组了,一半的文档就在测一个已经不存在的行为。

我的办法是让它们一直被用。所有 QA 文档都被 agent 反复执行,文档一过时就会表现为一堆假阳性工单,想装看不见都不行。

qa-doc-governance 定期审计,按 P0(流程不可用)、P1(治理漂移)、P2(风格)分级,流程是 lint、分级、修、同步索引、出报告。可以在功能或重构后跑,也有每周脚本。有一条硬规则:每份文档必须带回归检查清单,哪怕文档漂了,清单也给你一条最小的验证路径。

qa-doc-gen 还带一个强制的跨文档影响分析:路由、token 模型、权限、UI 文案一变,就扫全部文档,每份受影响的都要标”需修补”、“需加注”或者”无需变更并写明原因”。不许只写新文档、放着旧文档烂。

那我自己干什么

  • 规划:决定做什么,写验收标准,做架构取舍。
  • 审阅:审 AI 生成的测试文档,审新功能第一版代码。QA 执行和工单修复的循环完全交给 AI。
  • 纠偏:出假阳性时看根因分析;治理审计报 P0 时决定怎么修。
  • 架构:领域建模、数据流、安全边界。

投入的个人时间和我以前做项目差不多,产出按我自己的估计超过以前的 10 倍。二十多轮迭代之后,AI 跑测试还是会产生工单,只是比早期少得多,每一轮应用都更完整一点。这和人类工程师靠反复 QA 一层层消 bug 没什么两样,区别是循环更快,而且每一轮都有记录。

我觉得人最核心的价值是定义”要做什么、不做什么”,然后提供判断力。有一件事我一开始没想到:要搭一个让 agent 能自己验证的环境,你得同时懂开发、基础设施和安全。这套方法反而更需要全栈的人。

我做开发时一直偏向极限编程,当 tech lead 的时候信任团队,但会用敏捷和测试驱动那套做风险管理。对 AI 的态度也一样:软件开发里已有的风险管理手段,尤其是极限编程的那些实践,大多数可以直接拿来管 agent。

它做不到的

  • 真正新颖的架构决策还是得人来。AI 擅长实现它见过的模式。
  • 威胁模型需要人的安全专业知识。自动化测试能覆盖已知模式,发现不了新的攻击路径。
  • skill 组合和测试重点要按项目调。有的项目不需要 UI 测试,有的更看重 API 或数据层。

一些数字

项目2026 年 2 月撰稿时2026 年 6 月项目结束时
Agent Skill1616
测试文档156(96 QA + 48 安全 + 12 UI/UX)224(155 QA + 47 安全 + 22 UI/UX)
工具脚本911
skill 定义行数约 2,3002,725
Rust 测试2,710
提交491,其中 copilot-swe-agent 24 次(约 5%)
11

想自己试试

克隆仓库,读一遍 scripts/run-qa-tests.sh,然后跑它,agent 会自己起环境、开始执行整个 SDLC。或者打开 opencode 或 claude-code,直接说 execute all QA/security/UIUX tests。Gemini 也能跑这套。

Auth9 审计日志

这套办法不是只适合身份平台。它的核心就一句话:别只用 AI 把代码写快,用它把规划、测试、修复、部署之间的循环闭起来。