范围漂移
Agent 顺手加相邻重构、新字段或产品行为,评审时才发现没人授权。
对应## Out of scope
spec.mdSpec Coding 把模糊的 AI 编码请求变成一份短的、可评审的规格包,先写清楚,再让 agent 动手。优惠码案例展示了半小时写作能提前拦住什么:没有边界的范围、无法测试的“体验友好一点”、没有回滚路径。
大多数返工不是代码质量问题,而是假设没有对齐。如果十分钟能写清 spec,通常就能省掉 agent 三轮错误实现;如果写不清,说明这个功能可能还没准备好进入编码。
Agent 顺手加相邻重构、新字段或产品行为,评审时才发现没人授权。
对应## Out of scope
PR 看起来合理,但评审者无法把 diff 对应到明确的用户可见行为。
对应## Acceptance
测试、截图、日志、发布信号和回滚路径都在代码之后才临时补。
对应## Evidence
小任务用一份 spec.md 就够。风险更高的变更,用一个小文件夹把行为、任务和证据分开,让评审者能挑战正确的层级。下面是同一个优惠码变更,逐个文件展开。
这次改动在哪里,哪些文件已经相关,应该复用什么现有模式。
上线后用户或系统行为具体发生什么变化。
可评审的实现步骤、命名文件、依赖关系和测试命令。
那些诱人的重构、顺手优化和相邻需求,明确不做。
可观察的通过标准,以及合并前需要提供的测试、日志、截图或发布信号。
## Context 现有 checkout 总价在 billing/totals.ts 中计算。 ## Goal 付款创建前应用一个有效优惠码。 ## Plan 1. 通过小 API endpoint 校验优惠码。 2. 校验后更新 checkout summary。 3. 保持 draft order 状态幂等。 ## Out of scope - 优惠码后台 UI - 多个优惠码叠加 - 无关的 totals 重构 ## Acceptance - 过期优惠码显示内联错误 - 付款金额使用折扣后总价 - 刷新后保留已选择优惠码
## T1 校验接口 文件:apps/api/routes/coupons.ts, apps/api/routes/coupons.test.ts 完成标准:过期、已使用、不存在的码返回类型化错误 运行:pnpm test coupons ## T2 结账摘要输入框 文件:apps/web/routes/checkout/CouponInput.tsx, CheckoutSummary.tsx 完成标准:显示内联错误,失败时总价不变 ## T3 总价与 draft order 文件:packages/billing/totals.ts, packages/orders/draft.ts 完成标准:payment intent 金额等于折扣后总价 ## 不允许 - 除折扣入参外改动 computeTotals 内部 - 新增优惠码后台路由
## 合并前 - [ ] 单元:validateCoupon 拒绝过期码和已使用码 - [ ] 集成:带优惠码的 checkout 总价 == payment intent 金额 - [ ] 截图:摘要卡片上的内联错误状态 - [ ] 刷新后 draft order 仍保留已应用的优惠码 ## 上线 - 开关:checkout_coupon_input(默认关闭) - 观察:payment_intent_amount_mismatch 24 小时内为 0 - 回滚:关闭开关即可,无数据迁移需要回退
Spec Coding 不是完整产品流程,也不是沉重的形式化规格系统。它是模糊聊天提示和生产 diff 之间那份小的工作文件。
| 方法 | 主要产物 | 适合场景 |
|---|---|---|
| Vibe coding | 只有聊天 | 探索、一次性脚本、原型,以及错误成本很低的尝试。 |
| spec-coding | feature.spec.md | 日常功能开发:需要对齐,但不值得写 30 页 PRD。 |
| SDD / formal spec | spec.md + design.md + tasks.md | 监管系统、多团队交付,以及写错成本很高的改动。 |
| Working Backwards | PR / FAQ | 实现前的产品框架。Spec Coding 处理它下面的一次具体功能实现。 |
| Shape Up | pitch + appetite | 周期规划和 shaping。spec 是 shaped work 内部的实现协议。 |
术语说明。很多人会用 spec-first、spec as code、code spec 或 coding spec 搜索这类方法。中文里也可以把它理解为规范编码:先把行为、边界和证据写清,再进入实现。在本站,它们都指向同一个实用产物:一份靠近代码、实现前可评审的短 spec.md。
第一次来可以按顺序读;已经有具体任务时,也可以直接跳到对应步骤。每一步都指向真实页面、模板或工具。
模板用 repo 文件列表的方式展示,因为团队实际就是这样使用它们。点“复制”会把 Markdown 放进剪贴板,并在下方预览。
| 文件 | 什么时候用 | 行数 | 更新 | 操作 |
|---|---|---|---|---|
feature.spec.md |
标准功能开发:新 endpoint、新页面或新流程。 | 42 | 2026-05-15 | 打开 |
api.spec.md |
API 契约、请求响应示例、错误码和兼容规则。 | 48 | 2026-05-15 | 打开 |
database.spec.md |
Schema 变更、索引、约束、回填和回滚计划。 | 39 | 2026-05-15 | 打开 |
spec.md |
目标、非目标、验收标准、开放问题和证据要求。 | 36 | 2026-05-11 | 打开 |
design.md |
架构选择、接口、被拒绝方案、上线顺序和回滚。 | 52 | 2026-05-11 | 打开 |
tasks.md |
可评审实现切片,包含允许文件和测试命令。 | 44 | 2026-05-11 | 打开 |
evidence.md |
测试、截图、日志、指标、手工检查和发布停止信号。 | 31 | 2026-05-11 | 打开 |
最贵的 spec 是你跳过的那份。一份短 spec 只要在代码评审前抓住一个范围歧义,就能省掉一周返工。从历史上给你造成最多生产问题的决策点开始写:验收标准、边界条件和回滚方案。
越是用 AI,越需要 Spec。没有规格,AI 会发散:多写、多改、多加功能,最后更难收敛。Spec 是 AI 的"护栏"。
反而更适合。小团队最怕"上下文丢失"和"口头约定",Spec 让你过一周再回来也能秒捡起来。
更新 Spec 就好。Spec 本来就是活文档,不是刻在石头上的契约。用 git 管理版本,Spec 永远反映当前的真实需求。
PRD 从业务视角描述产品该做什么;Spec 从工程视角描述代码必须做什么——包含验收标准、边界情况和可测试的契约。两者互补,不是替代关系。
它们有重叠。中文里可以把 Spec Coding 理解为规范编码:先把行为、边界和证据写清,再进入实现。spec-first 强调先写行为再写代码;spec as code 强调把规格放进代码仓库;code spec 和 coding spec 常被用来搜索同一类小产物:可评审、可实现的 spec.md。