主题
AI 编程工作流
AI 编程最容易陷入两个极端:只用补全写几行代码,或者把整个仓库交给 Agent 后等待“完成”。真正稳定的做法是围绕开发者每天要交付的对象组织协作:代码库地图、可失败的测试、迁移清单、可审查差异、验证记录和回滚方案。
本页不从“怎么写提示词”开始,而是给出四条能直接用于真实仓库的工作流。
1. 先建立交付协议
把仓库规则写进 AGENTS.md 或同类项目说明,至少包含:
markdown
# Repository rules
## Architecture
- 业务逻辑位于 src/domain,HTTP 层不得直接写数据库。
- 跨租户查询必须显式携带 tenant_id。
## Commands
- Unit: npm test
- Typecheck: npm run typecheck
- Build: npm run build
## Change boundaries
- 不修改生成目录、锁文件和迁移历史。
- 行为变更必须补测试;接口变更必须更新契约与示例。
- 没有复现证据时,不以“可能”为由重构无关代码。
## Delivery
- 汇总改动文件、验证命令、未验证项、风险与回滚方式。规则必须是仓库真实约束。不要把通用“最佳实践”堆成几百行,真正关键的架构边界反而被淹没。
每个任务再单独写交付卡:
text
用户行为:谁在什么情况下遇到什么问题。
当前证据:日志、错误、复现步骤、相关文件或工单。
期望结果:对外行为和可以观察到的变化。
范围内:允许修改的模块。
范围外:这次明确不解决什么。
验收:自动检查 + 人工体验。
风险:数据、权限、兼容性、性能、回滚。2. 工作流一:接手陌生代码库
目标不是让 AI “解释整个项目”,而是在 30–60 分钟内产出一张可验证的任务地图。
2.1 第一轮只收集事实
让 Agent 读取目录、清单文件、入口、配置和测试命令,不修改文件:
text
任务:为“新增退款原因字段”建立代码库任务地图,不修改文件。
请用仓库搜索和文件阅读回答:
1. 请求从哪个入口进入,经过哪些模块,最终写到哪里;
2. 相关数据结构、数据库字段、API 契约和事件在哪里定义;
3. 现有测试覆盖哪条路径,哪些命令可验证;
4. 哪些结论有文件与行号证据,哪些仍是未知项;
5. 最小改动集合与可能的兼容性边界。
不要泛读整个仓库。每个结论附 path:line;未找到就写“未找到”。期望产物不是长篇架构介绍,而是:
text
入口:src/http/refunds.ts:42
领域服务:src/domain/refund-service.ts:18
持久化:src/db/refund-repository.ts:71
契约:contracts/refund-created.schema.json:1
消费者:workers/refund-sync.ts:33
测试:tests/refund-service.spec.ts:54
未知:旧消费者是否允许新增字段2.2 用命令验证地图
人工抽查三类关系:入口能否追到领域层、写入能否追到 Schema、事件能否找到消费者。再运行 Agent 找到的测试命令,确认它们真实存在。错误地图必须先修正,不能在错误理解上继续写代码。
2.3 把高价值事实留在仓库
只沉淀稳定内容:模块职责、入口、关键命令、危险边界。临时任务猜测留在工单,不要把 AI 生成的整篇说明直接当架构文档。
3. 工作流二:先把线上故障变成可失败测试
没有复现就开始改代码,是 AI 编程最常见的高成本错误。正确顺序是:证据包 → 最小复现 → 失败测试 → 最小修复 → 回归验证。
3.1 建立脱敏故障包
text
incident/
├── request.json # 脱敏后的最小输入
├── observed.json # 实际输出
├── expected.json # 期望输出
├── logs.txt # 只保留相关 trace
├── environment.md # 版本、配置差异、发生时间
└── README.md # 复现步骤与影响范围不要把整份生产日志或客户数据交给模型。保留 Trace ID、时间顺序和必要字段,用占位符替换身份信息。
3.2 先要求定位,不允许修复
text
读取 incident/ 和相关代码。先不要修改。
请输出:
1. 最小复现链路;
2. 三个以内、按证据强弱排序的原因假设;
3. 每个假设需要观察什么才能证伪;
4. 最适合加入失败测试的层级;
5. 你实际读取过的文件和命令结果。
禁止把日志中没有出现的现象写成事实。3.3 写一个只证明当前故障的测试
让 AI 先提交测试,运行并保存失败输出。测试应断言外部行为,不要复制当前错误实现。示例:
ts
it("uses the policy version captured when the order was paid", async () => {
const order = await givenPaidOrder({
paidAt: "2026-09-01T00:00:00Z",
refundPolicyVersion: "v3"
});
await setCurrentRefundPolicy({ version: "v4", windowDays: 7 });
const decision = await refundEligibility(order.id, "2026-09-11T00:00:00Z");
expect(decision).toMatchObject({ eligible: true, policyVersion: "v3" });
});看到测试因目标问题失败后,才允许做最小修复。修复完成运行:新测试、同模块测试、类型检查;跨模块影响再扩大验证范围。
3.4 必须记录的结果
text
复现命令:……
修复前失败:……
根因:……(带 path:line)
修复差异:……
修复后验证:命令 + 退出码
没有验证:……
回滚:……4. 工作流三:做跨文件批量迁移
框架升级、API 改名、配置迁移和弃用清理适合 AI,但不能用一次全仓替换完成。安全流程是:盘点 → 分类 → 试点 → 分批 → 对账。
4.1 先生成迁移台账
要求 Agent 搜索所有调用点,并写成机器可读清单:
json
[
{
"path": "src/orders/client.ts",
"symbol": "legacyRequest",
"category": "direct-call",
"migration": "replace-with-httpClient.request",
"verification": "tests/orders/client.spec.ts",
"status": "pending"
},
{
"path": "src/testing/mock-client.ts",
"symbol": "legacyRequest",
"category": "test-double",
"migration": "update-mock-contract",
"verification": "npm test -- mock-client",
"status": "pending"
}
]调用点至少区分:直接调用、包装器、测试替身、类型定义、配置、文档示例、生成文件和第三方代码。分类不同,迁移策略也不同。
4.2 只试点一个代表性切片
挑一个同时包含正常调用、错误处理和测试的模块。让 AI 修改后运行最小验证,再由人审查 API 语义是否等价。试点暴露出来的新规则写回迁移台账,不要马上全仓铺开。
4.3 分批迁移并做集合对账
每批只处理一种类别或一个模块,完成后重新运行原搜索:
text
初始调用点集合 - 已迁移集合 - 明确豁免集合 = 0仅仅“测试通过”不能证明没有遗漏未覆盖的调用点。搜索结果、迁移台账和测试结果要同时对账。
4.4 最后一批才删除兼容层
先证明所有消费者迁移完,再删除旧 API、兼容适配器和弃用配置。删除前保留一个可回滚提交点;数据库迁移遵守“扩展 → 双写/兼容 → 回填 → 切换 → 收缩”,不要在一次发布中同时破坏新旧版本兼容。
5. 工作流四:审查变更半径,而不只审查代码风格
代码审查最有价值的问题是“这个变化还影响了什么”,不是让 AI 重复 linter。
5.1 输入要包含仓库事实
- 暂存区或 Pull Request 差异;
- 相关模块所有者和关键不变量;
- 可用测试命令;
- 公开 API、事件和数据库契约;
- 与该模块相关的历史故障。
5.2 输出使用结构协议
json
{
"summary": "退款资格从读取当前配置改为读取订单政策版本",
"risk_level": "medium",
"findings": [
{
"severity": "high",
"path": "src/refund-policy.ts",
"evidence": "eligibleUntil now uses order.policyVersion",
"impact": "历史订单路径依赖 policyVersion 完整性",
"verification": ["构造缺失 policyVersion 的旧订单", "验证降级与告警"]
}
],
"missing_context": ["生产旧订单中 policyVersion 的空值比例是多少?"]
}程序应验证引用路径确实在差异中;模型不得声称测试已经运行;建议命令只能从仓库允许列表选择。可跟着《代码变更风险扫描器》做一个本地工具。
6. 让 AI 执行命令时守住边界
6.1 读操作和写操作分层
第一阶段允许目录浏览、代码搜索、读取和测试;修改文件前先确认计划。数据库写入、云资源变更、发布、删除和凭证操作保持独立审批。
6.2 不把非零退出码都当失败
grep 未匹配、测试发现失败用例、格式检查输出差异,都可能是有效结果。要求 Agent 报告命令、退出码和关键输出,不要只说“命令失败”。
6.3 长命令设置超时与范围
先跑受影响模块,再扩到全量;为测试和构建设置合理超时;禁止无边界递归读取大型目录。依赖安装、锁文件更新和网络下载都要显式说明。
7. 代码差异的人工审查清单
不要逐行和 AI 比语法,重点检查:
7.1 行为与边界
- 是否满足用户行为,而不是只满足内部实现;
- 空值、重试、并发、时区、编码和大输入是否处理;
- 旧客户端、旧数据和滚动发布期间是否兼容。
7.2 数据与安全
- 租户、身份和权限是否在服务端验证;
- 日志、提示和 Trace 是否可能包含秘密或个人数据;
- 写操作是否幂等,失败是否会留下半完成状态;
- 模型或外部内容是否有机会构造任意命令、路径或查询。
7.3 测试质量
- 测试是在验证可观察行为,还是复制实现;
- 新测试是否在修复前真的失败;
- Mock 是否让关键集成路径永远不会出错;
- 验证命令是否真实运行并保留退出结果。
7.4 运维与回滚
- 指标和日志能否区分新旧路径;
- 灰度、停止阈值和回滚步骤是否明确;
- 数据迁移回滚是逻辑回滚还是数据恢复,是否实际演练。
8. 一次交付的标准报告
让 Agent 最后按固定格式汇总,不接受“已完成所有需求”:
markdown
## 改动
- path:line — 改了什么,以及对应哪条验收标准
## 验证
- `command` — 退出码、通过/失败数量、关键输出
## 未验证
- 没有运行什么,为什么,对上线有何影响
## 风险
- 兼容性、数据、权限、性能、外部依赖
## 发布与回滚
- 灰度范围、观测指标、停止阈值、回滚动作这份报告既是代码审查入口,也是后续故障排查的上下文。
9. 用四个指标判断是否真的提效
持续记录同类任务:
- 从接手到第一个可信计划的时间;
- 从故障报告到可失败测试的时间;
- 首轮代码审查发现的有效问题数与误报数;
- 合并后 7 天内的返工、回滚和遗漏文档数量。
代码生成速度上升但返工和事故也上升,不是效率提升。AI 编程的目标是缩短从问题到可信交付的时间,而不是增加每天生成的代码行数。
10. 用 WorkBuddy 搭建一次代码交付
10.1 建立隔离工作区
复制或克隆仓库到独立分支,确认没有 .env、生产密钥、客户数据和可写的生产连接。把需求、复现步骤和验收命令写入仓库内的 task-brief.md;WorkBuddy 只选择该仓库为工作空间,不授权上级目录。
10.2 按闸门执行
- 要求 WorkBuddy 先读取
AGENTS.md、README、包管理文件和测试配置,只输出代码库地图; - 运行现有测试、类型检查和构建,记录修改前基线;
- 输出变更计划:文件、原因、风险、测试和回滚,不改代码;
- 人工确认后先写一个会失败的测试,保存失败输出;
- 只做让测试通过的最小修改,再运行相关测试和全量检查;
- 生成差异摘要,人工阅读
git diff后才提交; - 发布继续使用仓库现有 CI/CD 和审批,不让 WorkBuddy直接操作生产。
text
读取仓库规则和 task-brief.md。第一轮只输出:架构入口、相关文件、现有测试、验证命令、未知项。
运行只读检查并记录修改前基线,然后给出最小变更计划,等待我确认。
计划确认后先新增失败测试;证明测试因目标问题失败后,再修改实现。
完成后运行相关测试、全量测试、类型检查和构建,并输出 git diff 摘要与回滚方式。
不要读取仓库外目录,不要提交、推送或部署。10.3 交付验收
验收报告必须列出改动、验证、未验证、风险和发布 / 回滚。人工检查需求边界、异常分支、数据迁移、日志和权限;所有命令及退出码保存到任务记录。失败测试没有在修复前复现,或构建未通过时,不进入提交与发布。