Checkout 优惠码:从松散需求到规格包

这是首页示例的完整版本:一个模糊需求被整理成范围清楚的 spec、实现切片、验收标准和可检查证据。

风险金额、总价、无效状态
边界付款前应用一个优惠码
证据校验、总价、回滚检查

写 spec 之前的需求

弱工单

给 checkout 加优惠码。
无效码不要影响付款。

Spec-First 改写

Feature: Checkout coupon code
Owner: Web Checkout
Status: Ready for review

Context:
- Checkout UI 位于 apps/web/routes/checkout。
- Totals 由 packages/billing/totals.ts 计算。
- Coupon 表已存在,但还没有接入 checkout。

Goal:
- 允许登录用户在付款前应用一个有效优惠码。
- 对无效、过期、已使用的 code 显示内联错误。

Non-goals:
- 不做优惠码后台管理。
- 不支持优惠叠加。
- 不重写 billing totals。

评审真正需要看的规格包

tasks.md

- [ ] 按 code 和用户查询 coupon。
- [ ] 校验过期、禁用和已使用状态。
- [ ] 用一个折扣重新计算 checkout total。
- [ ] 不清空付款表单地显示内联错误。
- [ ] 加 feature flag 作为回滚开关。

acceptance-criteria.md

- Given 一个有效优惠码
  When 用户在付款前应用它
  Then 页面展示折扣后总价,并用它发起付款。

- Given 一个过期码
  When 用户应用它
  Then 页面显示内联错误,原始总价保持不变。

test-evidence.md

自动化:
- 优惠码校验单元测试
- checkout total 集成测试
- 已使用优惠码回归测试

手工:
- 有效码截图
- 无效码截图
- 回滚开关说明

AI coding guardrail

只实现 checkout 优惠码应用。
不要新增后台管理、叠加规则、价格规则或 totals 重构。
每个改动文件都必须对应一个任务和一条验收标准。

为什么它能提前减少返工

保护计费边界

spec 指明 totals 模块,也明确禁止无关重构,避免 AI 编码把任务做大。

让错误可测试

过期、已使用、无效优惠码都变成具体验收路径,而不是 QA 后期才发现的问题。

给发布停止信号

回滚开关和证据清单让评审者知道指标异常时如何暂停变更。

把这个模式用于下一次 checkout 改动

先用生成器起草规格包,再把它贴进 issue 或 PR,最后再让 AI 编码助手实现。

编辑说明

这个案例故意保持小而具体:重点是展示怎样用规格边界阻止 AI 生成实现偏离需求。