
假设一个很常见的场景。
你让 Agent 改一个支付回调幂等问题,流程看起来很正规:先写计划,再派子 Agent 实现,再让 reviewer 审查。
第一轮很顺。
实现者说:
已完成支付回调幂等处理。
保留了简单实现,避免过度设计。
新增测试已通过。
然后 reviewer 也给了一个看起来还不错的结论:
Spec compliance: mostly ok.
Code quality: minor suggestions.
你放心合并。
上线后并发重复回调一打,账务事件还是发了两次。
这时候再回头看那份 review,问题其实不在“模型不够聪明”。问题在于整个 Agent 工作流的几个默认假设都很危险:
执行者的汇报是可信的。
reviewer 看不见的东西可以自己猜。
两个 reviewer 分开审会更安全。
把历史粘进 prompt 里没什么成本。
controller 记得自己已经做到第几个任务。
Superpowers 6.0.3 这次更新,真正动刀的就是这些假设。
不是换几个 prompt 文案,也不是把 changelog 翻译一遍。
这次 SDD(subagent-driven development)的重写,本质上是在给 Agent 写代码这件事补工程纪律:谁能相信,谁不能信;什么能判断,什么必须标成不可验证;状态放在哪里,不能只放在对话里。
官方 release notes 里给出的结果很直接:标准 eval 下 token 消耗大约降 50%,执行速度大约提升 2 倍。
这两个数字很诱人。
但更值得拆的是:为什么能降。
superpowers-sdd-603-01.png

我本地装的 Superpowers 旧版 SDD 里,流程是典型的两段 review:
Implementer subagent implements, tests, commits, self-reviews
-> Dispatch spec reviewer subagent
-> Spec reviewer confirms code matches spec?
-> Dispatch code quality reviewer subagent
-> Code quality reviewer approves?
对应文件也很直观:
skills/subagent-driven-development/
implementer-prompt.md
spec-reviewer-prompt.md
code-quality-reviewer-prompt.md
SKILL.md
这个设计看上去很合理。
一个 reviewer 盯规格合规,一个 reviewer 盯代码质量,分工明确。
但真实跑起来,成本和质量都会出问题。
第一层是最粗暴的成本问题。
两个 reviewer 串行跑,每个都要读一遍任务背景、实现者报告、diff、测试结果。哪怕两个 reviewer 都很短,重复读上下文的成本也已经发生了。
第二层是假独立问题。
第二个 reviewer 不是在真空里独立判断,它通常会看到前面一轮产生的上下文。前一个 reviewer 的判断,会污染后一个 reviewer 的输入。
第三层是标准不统一。
spec reviewer 眼里的 Critical,和 code quality reviewer 眼里的 Critical,不一定是同一个尺子。controller 还得把两份报告合并、解释、裁决。
说人话就是:
你为了提高质量加了一个 reviewer。
结果多花了一倍 token,还多了一层对齐成本。
6.0 的解法很克制:砍掉两个 reviewer 的分裂结构,合并成一个任务 reviewer。
但重点不是“少一个人审,所以便宜”。
重点是合并之后,它把 reviewer 的行为边界写得更硬。
6.0.3 的 task-reviewer-prompt.md 里最关键的一句话,可以翻译成:
把实现者报告当成未经验证的声明。
设计理由也是声明,不能因为实现者说了 YAGNI 或故意保持简单,
就降低问题严重性。
这条规则很狠。
因为 Agent 实现完任务后,天然会写一份“我做了什么、为什么这样做”的报告。
报告通常长这样:
Implemented:
- Added idempotency handling for duplicated payment callbacks.
- Kept the solution simple because the current system does not need a full event outbox.
- Tests pass.
Concerns:
- None.
如果 reviewer 信了这份报告,它的判断就已经歪了。
比如支付回调场景里,真实代码可能是这样:
@Transactional
public CallbackResult handle(PaymentCallback callback) {
PaymentRecord existing = paymentRecordRepository
.findByTradeNo(callback.tradeNo());
if (existing != null) {
return CallbackResult.success();
}
PaymentRecord record = PaymentRecord.paid(callback.tradeNo(), callback.amount());
paymentRecordRepository.save(record);
eventPublisher.publish(new PaymentPaidEvent(record.getOrderId()));
return CallbackResult.success();
}
这段代码在单线程测试里很容易通过。
但并发重复回调来了,两个线程都可能先查到 existing == null,然后各自插入、各自发事件。
实现者报告里那句“kept it simple deliberately”不能救它。
正确的 reviewer 应该只看代码和 diff:
问题:幂等依赖先查后写,缺少数据库唯一约束或原子插入。
影响:并发重复回调下可能重复创建支付记录,并重复发布支付成功事件。
严重性:Important,因为这是任务核心需求,不修不能信任本次实现。
改法也不是“再加一个 if”。
更稳的最小路径应该是把幂等交给数据库约束兜底:
CREATE UNIQUE INDEX uk_payment_callback_trade
ON payment_record(channel, trade_no);
然后代码承认唯一键冲突是正常业务路径:
@Transactional
public CallbackResult handle(PaymentCallback callback) {
try {
PaymentRecord record = PaymentRecord.paid(
callback.channel(),
callback.tradeNo(),
callback.amount()
);
paymentRecordRepository.save(record);
afterCommitPublisher.publish(new PaymentPaidEvent(record.getOrderId()));
} catch (DuplicateKeyException ignored) {
// Duplicate callbacks from payment channels must still be acknowledged.
}
return CallbackResult.success();
}
这里的工程含义是:reviewer 不能审“故事”,只能审“行为”。
执行者说自己有理由,不代表这个理由成立。
尤其是 Agent 写代码时,它特别擅长给自己的选择找一个听起来合理的解释。不是恶意撒谎,而是语言模型天然会把输出写得完整、乐观、能自洽。
所以 6.0.3 直接把门关上:
你的解释我会看,但我不信。
我只信 diff、测试和可验证事实。

旧版 review 还有一个很隐蔽的问题:reviewer 容易扩大搜索范围。
比如任务要求:
支付回调必须保证同一 tradeNo 只发布一次 PaymentPaidEvent。
这次 diff 只改了 service 层,没有改事件发布器,也没有改数据库 schema。
reviewer 想判断事件到底会不会重复发,就会忍不住去搜:
rg "PaymentPaidEvent"
rg "tradeNo"
rg "payment_record"
听起来很负责。
但对 SDD 来说,这种“负责”反而危险。
因为 reviewer 的输入本来是一个任务 diff。它临时去搜未改动代码,能搜到多少、漏掉多少、理解到什么程度,全是不稳定的。
有时候它搜到了关键唯一索引,说“没问题”。
有时候它漏了数据库 migration,说“有问题”。
更糟的是,它为了一次判断读了一堆无关文件,token 又开始涨。
6.0.3 的处理方式很工程化:
如果一个需求不能只从这次 diff 验证,就标成无法验证。
不要为了证明它去扩大搜索。
这条规则看起来像退缩,其实是成熟。
线上系统最怕的不是“我不知道”,而是“我不知道但我说知道”。
reviewer 输出应该像这样:
⚠️ Cannot verify from diff:
- Requirement says PaymentPaidEvent must be published once per tradeNo.
- This diff changes PaymentCallbackService but does not include database constraint or event publisher behavior.
- Need controller to verify schema/migration or run concurrency test.
这就给 controller 留出了明确动作:
安排补充审查数据库 schema。
要求实现者补并发测试。
把不可验证项升级成人类确认点。
对写 Agent 系统的人来说,这条比“加更多能力”更重要。
你要给 Agent 一个合法的“不知道”出口。
没有这个出口,它就会为了完成任务而编一个结论。
reviewer 最容易犯的另一个问题,是把所有问题都写得很严重。
比如:
Critical: test coverage could be broader.
Critical: variable name can be clearer.
Critical: consider extracting helper method.
这类 review 看起来很认真,其实没用。
因为它把“会导致任务不可信”的问题,和“代码可以更漂亮”的建议混在一起。
6.0.3 在 reviewer prompt 里明确做了校准:
不是所有问题都是 Critical。
Important 表示不修就不能信任本任务。
覆盖率可以更广、润色建议,属于 Minor。
这个规则落到工程里,大概是这样:
问题 | 合理等级 | 为什么 |
|---|---|---|
幂等依赖先查后写,缺唯一约束 | Important | 并发下核心需求会失败 |
catch 后吞掉未知异常并返回成功 | Important | 会掩盖真实支付失败 |
测试只断言方法不抛异常 | Important | 测试没有证明需求 |
覆盖了成功路径但没覆盖边界金额 | Minor | 可增强,但不一定阻断 |
变量名不够漂亮 | Minor | 除非造成误读,否则不该阻断 |
这里还有一个很微妙的设计:如果计划里明确要求了某个有缺陷的做法,reviewer 仍然要报。
但要标注为:
plan-mandated
这解决的是权力边界问题。
计划不是圣旨。
如果 plan 写了:
为避免 schema 变更,本任务只在 service 层做幂等判断。
reviewer 发现 service 层先查后写在并发下不可靠,仍然应该报告:
Important (plan-mandated):
The plan requires service-only idempotency, but the implementation cannot guarantee callback idempotency under concurrent delivery without a unique constraint or equivalent atomic guard.
Human decision needed.
这不是 reviewer 越权。
这是 reviewer 把风险交还给人。
换句话说,6.0.3 在 SDD 里做了一个小型三权分立:
implementer 负责实现
reviewer 负责审查
controller 负责调度
human 负责裁决取舍
任何一个角色想偷懒,系统质量都会掉。
这次更新里,对 token 影响最大的设计,我认为不是 reviewer 合并。
而是 File Handoffs。
SDD 的新规则非常直白:
粘进 dispatch prompt 的任何内容,和子 Agent 打印回来的任何内容,
都会留在后续会话上下文里,并被后面的 turn 反复读取。
产物应该作为文件交接。
这句话如果只读一遍,可能没感觉。
换成一个真实 SDD session 就懂了。
第 1 个任务 dispatch:
Task 1 brief: 1k chars
第 2 个任务,为了“让子 Agent 知道上下文”,controller 把第 1 个任务总结也贴进去:
Task 2 brief: 1k
Previous summary: 3k
第 5 个任务:
Task 5 brief: 1k
Previous summaries: 20k
第 8 个任务:
Task 8 brief: 1k
Previous summaries: 41k
到这里,当前任务只占 1k,历史垃圾占 41k。
更要命的是,这 42k 不是一次性成本。
它进了主会话上下文,后面每一轮都要带着它。
这就是为什么很多人感觉 Agent session 越跑越慢、越跑越贵、越跑越迷糊。
不是任务变复杂了。
是上下文被自己污染了。
6.0.3 的解法是:中间产物落文件,只传路径。
典型模式是:
scripts/task-brief docs/superpowers/plans/payment.md 3
生成类似:
.superpowers/sdd/task-brief-003.md
reviewer 也不需要把完整 diff 粘进 prompt:
scripts/review-package BASE_SHA HEAD_SHA
生成:
.superpowers/sdd/review-package-003/
diff.patch
implementer-report.md
metadata.json
dispatch prompt 只需要写:
Review task 3 using:
- Brief: .superpowers/sdd/task-brief-003.md
- Review package: .superpowers/sdd/review-package-003/
- Model: ...
这不是形式主义。
这是把“上下文窗口”从垃圾桶改回工作台。
Agent 真需要读时,再按路径读文件;不需要时,文件内容不会常驻在主对话里。
这个模式对所有 Agent 系统都适用:
长文本用文件传递。
短指令用 prompt 传递。
状态用账本保存。
把这三句做对,成本和稳定性会立刻不一样。
superpowers-sdd-603-03.png

长 session 还有一个很现实的问题:compaction。
上下文快满时,对话历史会被压缩。压缩之后,controller 可能不再清楚自己已经完成了哪些任务。
然后就会出现一种最贵的失败:
Task 1 已完成。
Task 2 已完成。
Task 3 已完成。
对话压缩。
controller 醒来后又从 Task 1 开始 dispatch。
这不是理论问题。
只要一个 SDD plan 有 8 到 10 个任务,中间又经历多轮 review,这种“我做到哪了”的状态丢失就很容易发生。
6.0.3 的解法是 Durable Progress。
它把进度写进:
.superpowers/sdd/progress.md
每完成一个任务,追加一条类似记录:
Task 3: complete (commits a1b2c3d..e4f5g6h, review clean)
controller 每次恢复 session,不是凭感觉继续,而是先读这个账本。
这套东西在后端工程里一点都不陌生。
数据库有 checkpoint。
消息队列消费者有 offset。
分布式任务有状态表。
SDD 现在只是承认了一件事:Agent controller 也是一个会宕机、会失忆、会被压缩的执行器。
既然会失忆,关键进度就不能放在易失性对话里。
它必须落盘。
v6.0.3 还把这个进度文件从 .git/ 挪到 .superpowers/sdd/。这个细节挺有意思。
.git/ 不被 Git 跟踪,拿来放临时状态很方便。
但它是 Git 的受保护目录。工具往里面写自己的运行状态,会让很多开发者不舒服,也不利于安全审计。
迁到 .superpowers/sdd/,就是从“能跑”往“工程上更正确”靠了一步。
superpowers-sdd-603-04.png

SDD 的质量不只取决于执行阶段,也取决于计划怎么写。
6.0 对 writing-plans 的结构也做了升级。
关键是两个区块。
第一个是 Global Constraints:
## Global Constraints
- Node.js >= 20.19.0
- Do not add production dependencies without approval
- All public API routes must keep the /v2 prefix
- UI copy must remain in English
它解决的是全局约束丢失问题。
以前每个子任务只看到自己的任务描述,容易漏掉项目级硬规则。
比如计划总说明里写了“不能新增生产依赖”,但 Task 4 子 Agent 只看到“实现 markdown parser”,它就可能顺手加一个包。
Global Constraints 把这类规则提到每个任务都隐式继承的位置。
第二个是 Interfaces:
**Interfaces:**
- Consumes:
- PaymentRecordRepository.findByChannelAndTradeNo(channel, tradeNo)
- PaymentCallbackParser.parse(rawBody, signature)
- Produces:
- PaymentCallbackService.handle(callback): CallbackResult
- PaymentPaidEvent(orderId, paidAt)
它解决的是任务之间的合同问题。
子 Agent 不需要知道整个系统所有细节,但必须知道自己依赖什么、产出什么。
这对 SDD 特别关键。
因为 SDD 的核心是任务隔离。
隔离不是让每个 Agent 闭眼瞎写。
隔离的前提是接口清楚。
一个计划如果写成这样:
Task 3: implement payment callback handling.
基本等于把风险全丢给实现者。
更好的写法应该是:
Task 3: Implement payment callback idempotency.
Requirements:
- Same (channel, tradeNo) must be acknowledged as success when delivered repeatedly.
- PaymentPaidEvent must be emitted at most once.
- Unknown exceptions must not be swallowed.
Interfaces:
- Consumes:
- PaymentCallbackParser.parse(rawBody, signature)
- PaymentRecordRepository.insert(record)
- Produces:
- PaymentCallbackService.handle(rawBody, signature): CallbackResult
Tests:
- concurrent duplicate callback inserts one record
- duplicate callback returns SUCCESS
- invalid signature returns FAILURE and emits no event
这个任务才适合交给子 Agent。
它有边界,有输入输出,有可验证测试。
这条规则很小,但非常关键。
6.0.3 明确要求 controller dispatch reviewer 时,不要写这种话:
Do not flag X.
Don't treat Y as a defect.
At most Minor.
The plan chose this, so ignore it.
为什么?
因为 controller 有天然动机去省 review loop。
每多一轮 review,就多一轮 token、多一段等待、多一次修复。
所以 controller 很容易在 prompt 里偷偷写:
The plan intentionally avoided database migrations, so do not flag missing unique index.
看起来是在提供背景。
其实是在预判结论。
正确做法是让 reviewer 独立报出来:
Important (plan-mandated): missing database-level idempotency guard.
然后 controller 再进入 review loop 或交给人类裁决。
这条规则和前面的几条连起来,就形成了 reviewer 独立性的三层保护:
不信执行者报告:避免 implementer 自我美化。
不能从 diff 验证就标 ⚠️:避免 reviewer 假装全知。
controller 不许预判:避免调度者提前过滤问题。
很多 Agent 系统出问题,不是因为没有 reviewer。
而是 reviewer 名义上独立,实际上被上游输入、执行者报告、controller 暗示一起驯化了。
6.0.3 这次重写,就是把这些口子一个个堵住。
很多人看到 token 成本,第一反应是把子 Agent 全换成便宜模型。
这事不一定对。
SDD 6.0 的模型选择规则里有一个很实在的判断:
Turn count beats token price.
单次 token 便宜,但如果同一个任务要多跑 2 到 3 轮,总账未必省。
尤其是多步实现、代码审查、跨文件判断这类任务,便宜模型可能:
第一轮漏需求。
第二轮修错地方。
第三轮 reviewer 仍然不通过。
第四轮 controller 只能升级模型。
这时候你省下的单价,会被更多轮次吃掉。
更坑的是,如果 dispatch prompt 里不显式指定 model,很多平台会继承当前 session 的模型。
而当前 session 往往是最贵、最强的模型。
所以 6.0.3 的建议不是“永远用便宜模型”,而是按任务分层:
任务类型 | 模型策略 | 原因 |
|---|---|---|
单文件、规格清楚、机械实现 | 快速便宜模型 | 成本低,失败面小 |
多文件集成、调试、测试修复 | 标准模型 | 需要上下文判断 |
架构、计划、review、风险裁决 | 强模型 | 错一次的代价更高 |
这也是工程里的老道理:
不要只看单价,要看完成一次正确交付的总成本。
如果你已经在用 Superpowers,这次升级我建议尽快做。
原因不是“版本新”,而是 SDD 6.0.3 改的是执行纪律。
你日常体感会主要变在几个地方:
review 轮次更少
主上下文更干净
长任务不容易压缩后重跑
reviewer 报告更像审计报告,不像礼貌建议
升级后要注意三件事。
第一,别再把大段历史粘进 dispatch。
以前你可能习惯写:
Here is what happened in tasks 1-4...
现在应该改成:
Read .superpowers/sdd/progress.md.
Use task brief file for the current task.
Use review package file for the diff.
第二,计划要写出 Global Constraints 和 Interfaces。
不然 SDD 再聪明,也只能拿到一个模糊任务。
第三,不要试图“指导 reviewer 别报某个问题”。
如果你觉得 reviewer 会误判,让它先报,再在 review loop 里裁决。
这一步看起来多花时间,实际上是在避免 controller 自己把质量闸门拆了。
我觉得不是抄 Superpowers 的目录结构。
真正值得抄的是这些工程约束。
1. 执行者不能给自己判分。
实现报告只能作为线索,不能作为证据。
reviewer 必须从 diff、测试、日志、可复现行为里判断。
2. Agent 必须能说“无法验证”。
看不到的东西不要猜。
猜对一次是运气,猜错一次就是线上事故。
3. 长内容传文件,不传 prompt。
prompt 只放当前指令和路径。
diff、计划、历史、报告、测试输出,都应该落文件。
4. 长任务必须有持久化进度。
别相信对话记忆。
compaction、重启、工具报错都会让 controller 丢状态。
5. 上游不能提前干预 reviewer。
reviewer 的价值就在于独立。
如果 controller 可以提前说“别报这个”,reviewer 就变成了橡皮图章。
如果面试官问:
Superpowers 6.0.3 的 SDD 重写,为什么能降低 token?
不要只答“优化了 prompt”。
可以这样说:
它主要不是靠压缩文字,而是改了工作流。
第一,把旧版 spec reviewer 和 code quality reviewer 合并成 task reviewer,减少重复审查轮次。
第二,引入 file handoffs,diff、task brief、review package 通过文件路径传递,避免大段内容常驻主上下文。
第三,用 durable progress 把完成状态写到 .superpowers/sdd/progress.md,避免 compaction 后重复 dispatch 已完成任务。
第四,对 reviewer 做校准:执行者报告不可信,不能从 diff 验证的需求标 ⚠️,controller 不能预先让 reviewer 忽略问题。
所以 token 下降不是单点优化,而是减少重复读取、重复审查、重复执行。
如果继续追问:
这个设计对你写 Agent 系统有什么启发?
可以接:
我会把 Agent 工作流当成分布式系统设计。
上下文是易失内存,不能存关键状态;
prompt 是控制面,不应该承载大文件;
reviewer 是独立审计角色,不能被执行者报告和 controller 暗示污染;
看不到的事实必须显式标不可验证。
这些约束比换模型更重要。
这段回答比“用了多个 Agent 协作”更像工程经验。
开头那个问题,真正危险的不是 Agent 写错了一段代码。
写错代码太正常了。
真正危险的是:实现者给了一个乐观报告,reviewer 信了;reviewer 看不见数据库约束,却假装能判断;controller 为了少跑一轮 review,提前告诉 reviewer “这个计划就是这么选的,不用报”。
这一串下来,系统表面上有流程,实际上没有质量闸门。
Superpowers 6.0.3 这次 SDD 重写,价值就在这里。
它不是让 Agent 变得更像一个天才程序员。
它是让 Agent 更像一个受约束的工程团队:
干活的人不能自证清白。
审查的人不能假装全知。
调度的人不能堵审查的嘴。
进度不能靠记忆。
大文件不能塞进 prompt。
少烧一半 token,只是结果。
真正的原因,是这套流程终于开始尊重工程系统里最朴素的纪律:状态要落盘,证据要可验,角色要隔离,边界要承认。
这比多背几个 Agent 概念有用得多。