backprop

backprop

热门

Bug 到 Spec 的反向回溯协议。当发现 Bug 或测试失败时,追查根因,判断新增 §V 不变量是否能防止复发,并将记录追加至 §B。这是 SDD(规范驱动开发)区别于常规“先规划后执行”模式中最精妙的一环。触发场景包括:测试失败、Bug 报告、事故复盘或用户明确要求。

1128Star
86Fork
更新于 2026/6/18
SKILL.md
只读
名称
backprop
描述

Bug 到 Spec 的反向回溯协议。当发现 Bug 或测试失败时,追查根因,判断新增 §V 不变量是否能防止复发,并将记录追加至 §B。这是 SDD(规范驱动开发)区别于常规“先规划后执行”模式中最精妙的一环。触发场景包括:测试失败、Bug 报告、事故复盘或用户明确要求。

backprop — bug → spec

常规的“先规划后执行”模式改完代码就忘。
而 SDD(规范驱动开发)在修复代码的同时还会修改 Spec(规范),从源头绝杀此类 Bug 的复发可能。
这次规范修改,就是 backprop(反向回溯)。

什么时候执行 BACKPROP

  • /build 校验阶段测试失败。
  • 用户反馈了 Bug。
  • 线上故障复盘(Post-mortem)。
  • 执行 /check 报了 VIOLATE(违反规范)且已定位到根因。

六步流程

1. 追查 (TRACE)

阅读报错输出或 Bug 报告。
定位到异常行为的具体文件与行号(file:line)。
用一句极其简短的大白话概括根因。

2. 分析 (ANALYZE)

问自己三个问题:

  • 新增一个 §V 不变量能拦住这类 Bug 吗?(绝大多数情况:能)
  • 是 §I 写错了?——即 Spec 宣称的功能,代码结构根本承载不了?(偶尔会有)
  • 是 §T 写错了?——即我们从一开始就做错方向了?(罕见但确实存在)

3. 提案 (PROPOSE)

起草 Spec 的修改内容。§B 必填;§V/§I/§T 视具体情况而定。

模板:

§B row: B<next>|<date>|<root cause>|V<N>
§V line: V<next>: <testable rule that would have caught it>

示例:

§B row: B3|2026-04-20|refund job ran twice on retry|V7
§V line: V7: ∀ refund → idempotency key check before charge reversal

4. 生成测试 (GENERATE TEST)

光有不变量没有测试就是画饼。必须先写一个会报错的测试(failing test)。
测试命名要明确引用对应的不变量,例如:TestV7_RefundIdempotent

5. 验证 (VERIFY)

修复代码。运行测试,必须通过。运行完整测试套件,绝不能出现回归问题。

6. 记录 (LOG)

将 Spec 修改 + 测试 + 代码修复打包提交。
Commit 信息:backprop §B.<n> + §V.<N>: <一句话根因>

什么是好的不变量

  • 代码可测(可 grep 检查或可用断言 assert 验证)。
  • 作用域限定在某种“行为”,而非某个具体“文件”。
  • 尽量采用正面表述(优先用 ! 维持,而非 ⊥ 禁止)。
  • 在适用处引用对应的 §I 声明层。

反面教材: V8: 代码应该是正确的。
正面示范: V8: ∀ pg_query ! params interpolated via driver, ⊥ string concat.

什么时候不需要新增 §V

  • Bug 纯粹是手抖写错的无规律打字错误(比如临时代码里的 i++ 写成了 i--)。
  • 修复属于一次性的数据迁移。
  • 根因出在外部依赖库上(这种情况应该升级依赖包,并在 §C 中做好记录)。

不过依然需要追加 §B 记录——证明你评估过这种失效模式。以后遇到同类疑难杂症,搜一下 §B 就能看到前车之鉴。

产出物形态

每次 backprop 运行会产出:

  1. §B 记录(必定产生)。
  2. §V 记录(通常产生)。
  3. 测试文件(新增 §V 时产生)。
  4. 代码修复。
  5. 一次 Commit。

不需要仪表盘,不需要乱七八糟的日志文件。SPEC.md + git 就是最完整的历史履历。