AI原生SDLC实践笔记

AI原生SDLC实践笔记

一直在用 AI 做工程研发。前段时间读了 Anthropic 应用 AI 团队的《The AI-Native SDLC Playbook》,读完顺手拿它当尺子,量了量我过去两年几个项目的实践。这一篇记实践,差距那部分单独成篇。

一、六个阶段是一条链

Playbook 按六个阶段组织,规划、设计、构建、测试、部署、维护。这条链我画在下面,每个节点是那一阶段和它的产物,箭头表示前一个的产出喂给下一个当输入。

六个阶段连成一个环,维护阶段的产出会变成下一轮迭代的 intent。产品一直在迭代,这条链每转一圈就消耗一份新的 intent.md。

二、规划

Playbook 在这一阶段主张用 intent.md 捕获意图。一个意图配一份,写清楚想要什么、为什么、受什么约束,人在把上下文喂给 agent 之前先写完。按这个设计,下一阶段直接消费它,提交链就是审计轨迹。防漂移的锚是我给它起的读法,意思是往后写 spec、定 plan、做 diff,每一级都该拿它回来对一遍,看有没有跑偏。

Playbook 在这个阶段要的产物只有一个,就是 intent.md,一份原型规格。我的实践把它拆成两半来应对。需求怎么来是一半,需求放在哪是另一半,两半都有各自的替代,grilling 管澄清,issue 管存放。可规格本身这一份,我是缺的。

需求怎么来。澄清意图这一步,要么走 Matt Pocock 的 /grill-with-docs,要么走 openspec 的 explore 或 propose,两条路选一条,不叠着用。走 grilling 的时候,它把设计拆成一棵设计树,每个决策下面再挂子决策,然后按轮推进。每轮它把当前能问的问题一次全问完,这些前置条件已经满足、可以立刻问的问题,grilling 管它们叫 frontier。每个问题它都先给一个自己推荐的答案,我看着改,大多数时候直接采纳。答完这轮,树被重塑,定下来的决策把边界往前推,解锁原本被卡住的问题,再开下一轮,直到没有问题可问、没有任何东西被静默假定。

需求放在哪,Playbook 也给了答案,intent.md 放进一个共享的、受版本控制的目录,单产品最简单是仓库里的 intent/ 目录,还交代了这个目录怎么和已有的 Jira 或需求工具共存。我的答案是另一套,不单独开 intent/ 目录。澄清完要做什么,直接记进 GitHub Issues 或 markdown,这套 issue 标签本来就是 Matt Pocock 技能族里的东西(/setup-matt-pocock-skills 配好的),我没另起炉灶。TODO.md 只保留未完成事项的索引,不复制 issue 的详细范围、验收标准和实现讨论。issue 进来先打 triage 标签。

text 复制代码
needs-triage → ready-for-agent / ready-for-human / needs-info → wontfix

/setup-matt-pocock-skills 负责把 issue tracker 和标签词汇配好,是我很推荐的技能之一。需求一旦进入 ready-for-agent,就开一个 agent 会话去实现。

这个阶段我还试过一个有点意思的工具,Garry Tan 的 gstack 里的 office-hours(一个扮演 YC office hours 合伙人的角色,用六个 forcing questions 先逼问产品假设、确认在解决什么,再谈怎么做)。

issue 装的是要做什么,是需求的地址;intent.md 装的是这轮意图和取舍,是防漂移的锚。两者不是一回事,issue 替不了 intent.md。我实际跳过了锚,grilling 聊出来的共识大多留在会话里、没落成每轮的意图文档,需求地址直接丢给 agent 去干。代价下一篇说。

三、设计

Playbook 把规划和设计分成两个阶段,但代写的人从人换成了 agent。规划阶段,想法和 Claude 头脑风暴成 proto-spec,存为 intent.md;设计阶段,agent 据 intent.md 产出需求与设计规格 spec.md,并明确标出需要关注的区域。产品 owner 不用自己写,改成审,原文那句是 The product owner reviews that spec, but doesn't write it,传统的逐层交接,变成在 gate 上把关。

规格怎么组织,Playbook 的模型是 per-change 的,spec.md 和 intent.md 成对提交,一次变更一套,审计轨迹就是这条提交链。我在上面又叠了一层,把跨变更稳定的产品事实抽到 spec/ 目录单独维护。这不是 Playbook 的主张,是我自己的扩展,原因是这类长期演进的产品需要一份不随 change 归档而过期的权威记录。

于是分了三个层次。

per-change 层用 openspec,一个 change 一个目录,四件套。

text 复制代码
openspec/changes/<change-name>/
├── proposal.md    # Why / What Changes / Capabilities / Impact
├── design.md      # 技术方案与取舍
├── specs/         # 受影响能力的规格增量
└── tasks.md       # 实施任务清单

举个真实例子。正在做的一个变更(关于文章起草的深度与证据闭环),proposal.md 的核心是这样。

markdown 复制代码
## Why
Guide and practice articles can be too brief or omit useful operation
evidence and images even when the outline and review identify those needs.

## What Changes
- ... plan depth from each section's reader-facing promise rather than
  keyword-based article classification or character quotas.
- Route review findings to the work that can resolve them: accepted-source
  research, authorized autonomous practice, or prose revision.

稳定层是 spec/ 目录。我长期维护的那个桌面应用,现在是十份上下,产品需求和开发设计各一份打底,其余是专题,像第三方平台接口校验、打包发布、交互重构、各渠道发布实现这类。专题长哪些每个项目不一样,数目不重要,重要的是这类文档生命周期比 change 长得多,change 归档后规格增量就汇进这里。

术语层是 CONTEXT.md 加 ADR。这套结构出自 domain-modeling 技能,它假设大多数仓库是单上下文的,根目录放一份词汇表,架构决策另立目录;我这边词汇表用的是 CONTEXT.md,只记稳定的业务词汇,每个词配一条避免误用的说明,防止同名不同义。架构决策单独成文件,如 ADR 0001 记 agent 权限与派生记忆。grill-with-docs 这条链里,grilling 的逼问发生在更上游的规划阶段,逼清过程中结晶出的术语和决策落到这里,变成跨迭代复用的资产。

这一阶段的技能有三个,openspec proposal,Matt Pocock 的 /to-spec,以及 domain-modeling,CONTEXT.md 和 ADR 就出自它。/to-spec 对应 Playbook 里据已接受的 intent.md 写 spec.md 那一步。在 Matt 的工具链里,这一步的产物其实是带 ready-for-agent 标签的 issue,而不是 Playbook 里的 spec.md 文件;它不采访用户,只把已经聊透的意图综合成规格(Problem Statement / Solution / User Stories / Implementation Decisions / Testing Decisions / Out of Scope),行文用项目术语表、遵守相关 ADR。Matt 技能族和 Playbook 各阶段的完整对照放在了文末附录。

前端项目另说。涉及 UI 的项目,我用 Codex 的 Figma 插件读设计稿生成页面。Playbook 在设计阶段也有一段讲前端,那边是产品 owner 从 intent.md 出发,在 Claude Design 里 mock 出设计再导出给 Claude Code 建。我这边不一样,设计稿已经在 Figma 里了,我用插件把它读进去生成页面。

AGENTS.md 里有一张文档地图,明确写着产品规则不复制回 AGENTS.md,只放开发时必须始终遵守的少量不变量。这就是渐进式披露的纪律,文档才不会互相打架。

四、构建

从计划到实现这块,Playbook 把 plan mode 归为 Build 的开门 play。spec 获批才启动,工程师在 plan mode 里给出改哪些文件、什么顺序、用什么测试证明的实施计划,批准后提交为 plan.md 纳入审计链。之后的 PR 评审对照最终 diff,实现偏离计划时在同一 commit 里更新。plan mode 本身就是一道 gate,计划被批准之前 Claude 不能改文件。

在 Matt Pocock 的技能族里有对口工具。/to-tickets 把 spec 拆成一张张 ticket,每张是一个能端到端跑通的最小切片,英文叫 tracer-bullet,意思是先让整条链路打通,再逐步加厚。ticket 之间写明依赖,哪张挡在路上、哪张现在就能开干,一眼看清,这正是 plan.md 里 task graph 的形态。/implement-spec 负责落地,建一条 integration 分支,每张 ticket 派一个 implementer 子代理,各自在自己的 worktree 和分支上做,合回主干;能开的 ticket 变多就多派几张并发跑。如果 issue tracker 靠 PR 收口,或者用户要求,第一个 merge 之后就可以开 draft PR,全部完成后跑一轮 code-review 收尾。

我没有单独的 plan.md。openspec 四件套里的 tasks.md 承担了这个角色,实现入口还是第二节说的那句,需求进入 ready-for-agent 后开 agent 会话。

构建阶段还有一件贯穿全程的事,产物的事实来源。遗留系统(Jira、Figma、需求管理工具)和 AI 原生产物(markdown)并存的时候,Playbook 要求每件产物指定唯一权威来源,别的地方只存副本或链接。它给了三种配置。

方案 权威记录 其他系统
以仓库为事实来源 markdown 产物 遗留系统引用提交中的文件
以遗留系统为事实来源 Jira/需求工具 markdown 只是工作副本,会话中通过 MCP 写回
以关联为最低标准 双方都记记录 ID 遗留记录含 markdown 的提交 SHA

我用的是混合方案。spec/ 的 markdown 是工程事实的权威来源,需求详情在 GitHub Issues,TODO.md 只做索引。Playbook 允许按工件分别指定权威来源,所以混搭本身不算错,我缺的是第三种配置,关联,同一份需求在 spec/01 和 issue 里各存一份,中间没有能对上的记录 ID 或提交 SHA。之所以没做关联,是因为遗留协作习惯,团队在 issue 里讨论需求,markdown 承载不了讨论过程。代价当场就能看见,同一个事实得维护两份,而取舍的理由留在 issue 讨论里,agent 读 spec/ 的时候读不到那些理由。

构建阶段的治理,Playbook 有一个关键的区分。我按软硬把控制分成两类,advisory 是软的,skills、CLAUDE.md/AGENTS.md、prompt,其实只是建议 agent 怎么做,agent 可以不遵守,我的体会是上下文一长就被稀释。deterministic 是硬的,hooks、managed settings、permission deny、OS 级 sandbox,不依赖模型判断,到点就执行。

它举的例子很典型。permissions.deny 可以列出 WebFetch、Bash(curl *)、Bash(wget *)。挡得住 agent 在 shell 里跑等价命令吗?挡不住,最后还得靠 sandbox 兜底。而且 sandbox 配上 failIfUnavailable 之后,初始化失败时 agent 直接拒绝启动,兜底本身就变成了一道门禁。

AGENTS.md 是构建阶段的宪法,属于软的这一侧。我这份文件的层次是这样的。

text 复制代码
1. 用户在当前任务中的明确要求
2. AGENTS.md 及子目录更具体的 AGENTS.md
3. spec/01-product-requirements.md 已确认的需求与验收标准
4. spec/02-development-design.md 及专题设计
5. 当前代码、测试和应用内帮助体现的现状

冲突时不允许 agent 静默选择,要么按更安全的规则统一、要么向人报告。再加上三条规矩,开始修改前的检查清单、文档同步算进完成定义、以及一份禁止事项清单。软的这一侧能做的就这些,它管不住一个决心乱来的 agent,所以还需要下面这个。

hooks 就是 Playbook 说的 deterministic。我的 agent 配置在 .codex/ 下,两个 hook 脚本。

text 复制代码
.codex/hooks/
├── approval-gates.mjs                 # 人工审批门
└── verify-fix-test-immutability.mjs   # 测试不可变保护

第一个管审批门。结束测试保护、正式发布安装包、修改治理配置,必须人工在 Codex 外交互解锁,agent 自己写的变量不算授权。第二个更有意思,它保护的是缺陷修复的测试先行流程。

powershell 复制代码
npm run fix:begin -- <复现测试提交>   # 开启本地保护
npm run fix:verify                   # 修复中随时自检
npm run fix:end                      # 通过后才解除保护

保护期内,hook 检查 apply_patch、shell 命令、以及任何会写文件的 MCP/本地调用,测试文件被修改、删除或新增都会被差异审计发现,fix:end 在检查通过前不会清除保护标记。文档里写明了局限,shell 静态分析覆盖不到所有间接副作用,这道门禁是降低误改概率的加强措施,不是安全沙箱。

verifier 是独立验收子智能体。父 agent 完成实现后,委派一个独立验收员接手,只报告、不修复。它定义在 .codex/agents/verifier.toml(Codex 的项目级 agent,TOML 格式,下面有删节)。

toml 复制代码
name = "verifier"
description = "实现完成后独立验收,只报告证据与偏差"

developer_instructions = '''
你是独立验收员。父 Agent 完成实现后才接手,验证并报告,不负责修复。
1. 无法判断的一律标为未验证。
2. SKIP、未启动、仅通过类型检查,都不算已验证。
3. 只读仓库文件和运行验收命令,发现缺陷交还父 Agent。
'''

它的报告格式是固定的,结论(通过/失败/未验证)、范围、证据、偏差。未验证是一个合法结论,没有 GUI 环境就明确标未验证并给人工步骤,而不是把自动化检查通过包装成交付。

并行与会话管理这块,我偶尔用 Herdr,一个 agent 一个独立 git worktree 处理一个任务,会话之间互不可见,唯一共享的是掌舵的工程师,但没常态化,这边的任务串行依赖强。更多时候多 agent 是靠 codex 这类工具自己管起来的。

五、测试

Playbook 的主张很朴素,永远给 agent 一条验证自身工作的途径,测试、构建、截图比对都行,关键是让 agent 在工程师看到之前就自查、自行修正。

我的测试基建分三层。

第一层是 PR CI。.github/workflows/ci.yml,Windows runner。

yaml 复制代码
on:
  pull_request:
  push:
    branches: [master]

jobs:
  windows-checks:
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with: { node-version: 22, cache: npm }
      - run: npm run ci:step -- install    # 装锁定版本依赖
      - run: npm run ci:step -- tooling    # 诊断与 triage 工具自身测试
      - run: npm run ci:step -- gates      # 测试保护 hook 行为测试
      - run: npm run ci:step -- graders    # eval grader 测试
      - run: npm run ci:step -- build      # 含类型检查的生产编译
      - run: npm run ci:step -- tests      # 全量自动化测试
      - run: npm run ci:step -- rollback   # 合成夹具上的数据升级回退演练
      - run: npm run ci:diagnostics        # 无论成败,采集脱敏证据打成 bundle
        if: always()
        continue-on-error: true
      - uses: actions/upload-artifact@v6   # bundle 传成 artifact,留七天
        if: always()
        with:
          retention-days: 7

注意 gates 和 graders 两步。护栏和 eval 的 grader 自己也得有测试,否则它们什么时候坏的都没人知道。

第二层是按改动范围分级的验证矩阵。AGENTS.md 规定不同改动范围的最低验证,而不是笼统一句跑测试。

改动范围 最低验证
renderer typecheck + 人工验证受影响交互
main/shared/数据库/本地 API typecheck + npm test
preload/IPC/窗口/打包 上述 + 生产构建启动验证
依赖/构建配置 npm run build,发布改动再跑打包验证
删除/迁移/发布状态 增加针对性测试并验证失败路径

其中生产构建启动验证值得一提。npm run dev 走的是 loadURL 分支,永远不执行打包版的 loadFile 路径。dev 能启动,能说明打包版也能跑吗?不能,这是两条不同的路。这类改动的最低验证是 dist:portable 产出 + verify:installer + verify:boot(无头启动打包后的 exe,确认不白屏即退)。

第三层是 agent eval 回归,对应 Playbook 里 agent 配置也要有 CI 那句。改 AGENTS.md、改 hooks、改 eval 定义,都该跑 eval。不过真模型回归这一层还没跑起来,门禁没配齐,具体情况下一篇说。.github/workflows/agent-evals.yml 的双 job 设计是这样的。

yaml 复制代码
jobs:
  fixtures:            # 无需模型、无需 key,任何人都能跑
    steps:
      - run: node --test scripts/verify-fix-test-immutability.test.mjs
      - run: node --test scripts/approval-gates.test.mjs
      - run: node --test evals/agent/harness.test.mjs
      - run: node evals/agent/run.mjs --prepare-only --output .cache/agent-evals/prepared
  quick-evals:         # 真模型回归,三重门槛(仓库变量/key/模型 ID)
    if: >-
      vars.AGENT_EVALS_ENABLED == 'true' &&
      (github.event_name != 'pull_request' ||
        (github.event.pull_request.head.repo.full_name == github.repository &&
         contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'),
                  github.event.pull_request.author_association)))
    environment: agent-evals
    steps:
      - name: Check eval configuration    # key 和模型 ID 缺一个就报错退出
        env:
          HAS_API_KEY: ${{ secrets.OPENAI_API_KEY != '' }}
          EVAL_MODEL: ${{ vars.AGENT_EVAL_MODEL }}
        run: |
          if [ "$HAS_API_KEY" != "true" ] || [ -z "$EVAL_MODEL" ]; then
            echo "::error::Agent evals not run."
            exit 1
          fi
      - uses: openai/codex-action@1d82a3db...  # 钉死 SHA
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          codex-version: '0.156.1'
          safety-strategy: drop-sudo
      - run: node evals/agent/run.mjs          # 六个隔离 agent 任务

安全考虑藏在细节里,fork PR 不触发真模型 job(防 key 泄露),codex-action 钉 SHA 防供应链,key 走它的代理,sudo 也去掉。eval 覆盖的是 agent 行为基线(hook 行为、评审政策执行),不是产品质量,这个边界下一篇展开。

六、部署

Playbook 在这一阶段主张让 AI 进入 PR 评审回路。我的实践是 AI 出报告、人做裁决,评审回路和发布回路都按这个来。

评审政策 REVIEW.md 固定了两轴三轮。

text 复制代码
报告轴:Standards(工程规范) × Spec(需求符合性)
轮次:  Bugs × Security × Compliance
级别:  P0 灾难 → P1 严重 → P2 一般 → P3/Nit(默认省略,最多三条)

每条发现必须带 P级别轮次、文件行号、触发条件、影响、证据、规则来源。没发现问题不等于批准合并。评审前锁定 merge-base SHA,评审后确认 head 没变,防止出现评的不是现在这份代码这种事。

发布回路则是完全的人工门。release-windows.yml 在 tag 发布时跑 verify:installer 和 verify:boot 作为发布前门禁,安装包由 GitHub 的 release-production 审批后才能发布。agent 在这个回路里的角色是准备可核对的结果,不是执行者。

七、维护

我把 Playbook 的维护阶段拆成三类咬合的动作。一个确定性脚本盯着生产指标,控制带被突破时由 agent 写下一条 intent.md,检测全程不涉及模型;agent 对失败和告警做诊断;每一次生产事故都由责任团队转化为一条 eval,留在套件里当回归测试。

我的做法比它保守,可以概括成证据链三段式。

第一段是 CI 失败证据采集,不调用模型。workflow 里每一步都挂着采集器,成功失败都采,失败时包里就是失败现场,日志、manifest、summary 打成诊断包传成 artifact,留七天。逐行脱敏、限长、白名单导出,只打包固定清单里的文件,每个文件带 sha256 进 manifest。凭据按启发式规则抹掉,包里还老实写着脱敏是启发式的、分享前要人工复核。这一步没有模型参与,纯粹是把证据做硬。

第二段是本地只读分析,这一段才显式调用模型。维护者把 artifact 拉到本地,npm run ci:triage 校验清单、再次脱敏、生成 prompt,然后由人决定是否真的调用 Codex 分析。

独立入口跑在只读沙箱里,禁用 shell、插件和 web search,不接受交互审批。请求必须引用文件及原行号,输出要区分事实、最可能原因、缺口。单次失败不能认定 flaky,没有历史或复跑证据就是 unknown。日志里出现忽略之前指令这类说法,一律当不可信数据处理。

第三段是人工授权后修复。分析报告是建议,修不修、怎么修由维护者决定,修复沿用 AGENTS、review、verifier、审批门的完整链路。

配套的还有 .github/workflows/ci-health.yml,每周统计 master 最近 37 天的 CI 失败率快照。文档里特意声明这是描述性基线,不判断失败由产品、基础设施还是 flaky 引起,也不计算控制限。先观察样本量,再决定要不要上统计控制图,不用少量运行直接触发动作。这种对方法限度的自觉,比工具本身更值钱。

和 Playbook 的完整形态比,我缺的是最后一环,事故到 eval。Playbook 要求每个生产事故都写成一条 eval 留在回归套件里,作为闭环的回归测试,我的 incident 教训目前停在人的记忆和 PR 讨论里。这个缺口下一篇细说。

小结

把这六阶段摊开看,我的 AI 原生实践有两个特征。

一个是下游硬、上游软。构建、测试、评审、维护这些靠近代码和证据的阶段,我有 hooks、CI、eval、verifier、只读分析入口的沙箱这些确定性机制;规划和设计这些上游阶段,基本靠文档和人的纪律,缺一个硬锚。

另一个是 agent 的角色更像副驾驶而不是值班员。每个回路里 AI 都只做到准备可核对的结果,最终裁决权在人。换来的是可靠,代价是规模化和响应速度。

附录,Matt Pocock 技能族与 Playbook 阶段的对照

Matt 技能 Playbook 阶段 做什么
/grill-with-docs 规划 Plan grilling 逼问(设计树 + frontier),domain-modeling 产出落入设计层术语层
/to-spec 设计 Design 不采访、只综合,把聊透的意图整理成规格,发成 issue 并打 ready-for-agent
/to-tickets 衔接到 Build 把 spec 拆成带依赖关系的 ticket
/implement-spec 构建 Build 建 integration 分支逐张实现,按需提 PR
相关推荐
RockHopper20252 小时前
统一目的的分布式智能体 vs 多个独立应用智能体的集成
人工智能·系统架构·智能体·agent 工程
Json____12 小时前
用 Node.js + Vue3 打造一个家居装修 AI 智能咨询助手
node.js·agent·网站开发·智能体·wwwoop.com
神也畏惧菠萝1 天前
Coze 工作流实战 Day05:RAG 检索机制、多模态 AIGC 与智能体编排
aigc·音频处理·rag·视频生成·智能体·coze·图形处理
程序员洲洲1 天前
AI时代下,想研究一款出海商品,第一步应该怎么做?
ai·agent·智能体·ipfly
像风一样自由20201 天前
59.实战为RAG系统加入评估监控权限和审计
人工智能·智能体
AI日报派送佬2 天前
2026年10月19日AI行业日报|三星联合台积电代工英伟达HBM裸片,智谱开源法律大模型,清华发布智能体操作系统PilotDeck 2.0
人工智能·开源·英伟达·智能体·anthropic·ai日报·法律大模型
misty youth4 天前
Agent-智能体工程方法论
人工智能·ai·llm·agent·智能体
Summer-Bright4 天前
浏览器成了AI应用的新入口:智能体接管标签页之后,三本账谁买单
人工智能·chatgpt·agent·浏览器·智能体
把我格子衫拿来4 天前
VTK 与 Qt 的 CMake 工程怎么组织?模块、工具链与二进制兼容排错
c++·qt·vtk·cmake·工程实践