@dsh-fly/dsh-plugin-fly-smart 0.0.0-stage → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +122 -2
- package/THIRD_PARTY_NOTICES.md +73 -0
- package/assets/smart-debug/SKILL.md +319 -0
- package/assets/smart-diagnose/SKILL.md +170 -0
- package/assets/smart-parallel/SKILL.md +190 -0
- package/assets/smart-plan/SKILL.md +184 -0
- package/assets/smart-review-receive/SKILL.md +230 -0
- package/assets/smart-skills/SKILL.md +96 -0
- package/assets/smart-tdd/SKILL.md +333 -0
- package/assets/smart-verify-claim/SKILL.md +129 -0
- package/assets/smart-worktree/SKILL.md +182 -0
- package/assets/smart-write-skill/SKILL.md +277 -0
- package/cordis.patch.yml +12 -0
- package/index.js +847 -0
- package/lib/client.js +1569 -0
- package/lib/state.mjs +2389 -0
- package/package.json +68 -4
- package/panel/reader.js +481 -0
- package/panel/routes.mjs +393 -0
- package/tools/index.js +1505 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DSH Fly contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,123 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dsh-fly/dsh-plugin-fly-smart
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**带用户门禁的三模型工作流** —— DeepSeek Harness 插件。
|
|
4
|
+
|
|
5
|
+
方法论移植自 [obra/superpowers](https://github.com/obra/superpowers)(MIT):
|
|
6
|
+
脑设计、评审把关、手执行,**每一道门你来开**。外加 10 个可独立触发的技能 ——
|
|
7
|
+
多数日常事不必走工作流。
|
|
8
|
+
|
|
9
|
+
> **装了能得到什么**:说「修个 bug」就按根因排查走;说「做这个功能」就进带门禁的工作流;
|
|
10
|
+
> 每一份产物你都看得见、批得了、退得回。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 它解决什么
|
|
15
|
+
|
|
16
|
+
让模型干活时**少自作主张、多留痕迹**:
|
|
17
|
+
|
|
18
|
+
| 常见问题 | 这里怎么处理 |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| 模型「我觉得你要的是这个」 | 脑暴先摆**决策表**给你挑方案,选完才进设计 |
|
|
21
|
+
| 计划写了等于没写 | `plan.md` 有**内容契约**:每个任务声明它的接口、全局约束、风险面 |
|
|
22
|
+
| 评审形同虚设 | 评审走**独立路由**,且**不许回落**到执行者那条 —— 不能自己审自己 |
|
|
23
|
+
| 改完了不知道改了啥 | 执行者落**评审包**(commit 列表 + diff),裁决对着 diff 判 |
|
|
24
|
+
| 模型替你做了决定没人知道 | 逐条记「决定 — 为什么 — 错了代价」,收尾总结必须提 |
|
|
25
|
+
| 小事被 6 个阶段碾过去 | `shape` / `size` 决定走几步、每步花多少 |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 10 个技能:不用开任务也能用
|
|
30
|
+
|
|
31
|
+
技能按你说话的场景自动命中。**多数日常事到这里就够了。**
|
|
32
|
+
|
|
33
|
+
| 你说 | 会用 |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| 「这个测试挂了」 | `smart-debug` —— 先找根因,症状修复不算修 |
|
|
36
|
+
| 「给它加个函数」 | `smart-tdd` —— 先写失败的测试,看着它失败 |
|
|
37
|
+
| 「我改完了,能提交吗」 | `smart-verify-claim` —— 证据先于断言 |
|
|
38
|
+
| 「评审说这里要改」 | `smart-review-receive` —— 先核实再改,不许表演式同意 |
|
|
39
|
+
| 「这是 spec,写个计划」 | `smart-plan` —— 给没见过代码库的工程师写 |
|
|
40
|
+
| 「开个分支做这个」 | `smart-worktree` —— 先隔离,绝不在 main 上开工 |
|
|
41
|
+
| 「这 3 个测试都挂了」 | `smart-parallel` —— 各派一个并行查 |
|
|
42
|
+
| 「我要写个技能」 | `smart-write-skill` —— 写技能就是把 TDD 用在文档上 |
|
|
43
|
+
| 「这个任务卡住了」 | `smart-diagnose` —— 症状→假设→验证,每条结论带出处 |
|
|
44
|
+
| 「我要开始做个东西」 | `smart-skills` —— 先查再动 |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 需要把关时:开任务
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
smart_begin({ title, shape, size })
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| `shape` | 走什么 | 适合 |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `feature` | 设计 → 计划 → 执行 → 验收(G1–G5) | 完整交付一个功能 |
|
|
57
|
+
| `fix` | 脑暴 → 计划 → 执行 → 验收(G1、G3、G5) | 修一处、要留证据 |
|
|
58
|
+
| `review` | 只做验收(G5) | 看看这段 diff |
|
|
59
|
+
| `investigation` | 只做脑暴(G1) | 调查个问题、出结论 |
|
|
60
|
+
|
|
61
|
+
`size: light | standard | full` 决定每步花多少 —— `light` 不派评审子代理,适合小改动。
|
|
62
|
+
|
|
63
|
+
**门是给你点的**。每一阶段:
|
|
64
|
+
|
|
65
|
+
1. 产物落盘 → 生成一份**要点**,我们当面对一遍(你可以提修改)
|
|
66
|
+
2. 你觉得没问题 → 确认 → 打开这道门
|
|
67
|
+
3. 不满意 → 退回,旧版本进历史不删
|
|
68
|
+
|
|
69
|
+
*讨论不算批准,你说过「可以」才算。*
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 模型路由
|
|
74
|
+
|
|
75
|
+
**脑**设计 · **手**执行 · **评审**把关 —— 三条路由在插件设置里配,工作台面板也能改。
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
brain: <provider>/<strong-model>@high # 决策 / 产物
|
|
79
|
+
hand: <provider>/<fast-model>@max # 执行
|
|
80
|
+
review: <provider>/<strong-model>@high # 评审
|
|
81
|
+
lite: <provider>/<fast-model>@high # 探索 / 取证 / 并行调查
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
三条规则:
|
|
85
|
+
|
|
86
|
+
- **评审不许回落**到执行者的模型 —— 自己审自己等于没审
|
|
87
|
+
- **同一处反复返工**时,评审自动升到该模型的最高推理档(并且告诉你升了)
|
|
88
|
+
- 便宜模型在多步工作上常花 2–3 倍轮次,**总成本反而更高** —— 纯机械的活才用 `lite`
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 工作台面板
|
|
93
|
+
|
|
94
|
+
`fly.smart` 右抽屉:阶段板、产物查看器、待裁决 / 自裁决、返工额度、
|
|
95
|
+
每轮评审用的哪个模型、证据文件、花了多少次子代理调用。
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 装
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
dsh plugin add @dsh-fly/dsh-plugin-fly-smart
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
配好三条路由即可开用。没配会**大声报错并指路**,不会静默跑偏。
|
|
106
|
+
|
|
107
|
+
需要完整交付能力时,把它挂进 agent preset(见 [`docs/internals.md`](docs/internals.md))。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 更多
|
|
112
|
+
|
|
113
|
+
| 看什么 | 去哪 |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| 工作流细节、门与契约、两种裁决、工具面 | [`docs/internals.md`](docs/internals.md) |
|
|
116
|
+
| superpowers 移植清单与许可全文 | [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md) |
|
|
117
|
+
| Public 试运行手册 | [`docs/public-trial.md`](docs/public-trial.md) |
|
|
118
|
+
|
|
119
|
+
## 许可
|
|
120
|
+
|
|
121
|
+
MIT。方法论内核移植自 obra/superpowers(MIT,Copyright (c) 2025 Jesse Vincent),
|
|
122
|
+
移植清单见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。
|
|
123
|
+
**本插件不是** obra/superpowers 的官方移植,也不是它本身。
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
本仓库(`dsh-plugin-fly-smart`)是 [obra/superpowers](https://github.com/obra/superpowers)
|
|
4
|
+
的 **DSH 移植与扩展**。方法论内核移植自 superpowers,外加 DSH 平台适配层,
|
|
5
|
+
并扩展出 superpowers 没有的能力(用户门 G1–G5、`smart_decide` 待裁决、
|
|
6
|
+
briefing 对话回路、面板可视化、成对相位与 review bundle)。
|
|
7
|
+
|
|
8
|
+
以下内容依据 MIT License 分发。
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## superpowers
|
|
13
|
+
|
|
14
|
+
- **来源**: https://github.com/obra/superpowers
|
|
15
|
+
- **许可**: MIT License
|
|
16
|
+
- **版权**: Copyright (c) 2025 Jesse Vincent
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
MIT License
|
|
20
|
+
|
|
21
|
+
Copyright (c) 2025 Jesse Vincent
|
|
22
|
+
|
|
23
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
24
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
25
|
+
in the Software without restriction, including without limitation the rights
|
|
26
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
27
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
28
|
+
furnished to do so, subject to the following conditions:
|
|
29
|
+
|
|
30
|
+
The above copyright notice and this permission notice shall be included in all
|
|
31
|
+
copies or substantial portions of the Software.
|
|
32
|
+
|
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
34
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
35
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
36
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
37
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
38
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
39
|
+
SOFTWARE.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 移植清单
|
|
43
|
+
|
|
44
|
+
每个 `assets/<name>/SKILL.md` 的头部都带出处注释。对应关系:
|
|
45
|
+
|
|
46
|
+
| 本仓库技能 | 移植自 superpowers | 策略 |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| `assets/smart-skills/` | `skills/using-superpowers/` | 改写适配 |
|
|
49
|
+
| `assets/smart-debug/` | `skills/systematic-debugging/` | 移植(含 references 摘要) |
|
|
50
|
+
| `assets/smart-tdd/` | `skills/test-driven-development/` | 移植(含 `writing-good-tests.md`) |
|
|
51
|
+
| `assets/smart-verify-claim/` | `skills/verification-before-completion/` | 移植 |
|
|
52
|
+
| `assets/smart-review-receive/` | `skills/receiving-code-review/` | 移植 |
|
|
53
|
+
| `assets/smart-plan/` | `skills/writing-plans/` | 移植(文档契约) |
|
|
54
|
+
| `assets/smart-worktree/` | `skills/using-git-worktrees/` | 移植 |
|
|
55
|
+
| `assets/smart-parallel/` | `skills/dispatching-parallel-agents/` | 移植 |
|
|
56
|
+
| `assets/smart-write-skill/` | `skills/writing-skills/` | 移植(含 references 摘要) |
|
|
57
|
+
| `assets/smart-diagnose/` | `skills/diagnosing-superpowers/` | **改写适配**(诊断对象换成 smart 工作流) |
|
|
58
|
+
|
|
59
|
+
**未移植但用 smart 现有机制替代**的 superpowers 技能(无版权文本随包分发,但方法论来源相同):
|
|
60
|
+
|
|
61
|
+
| superpowers | 本仓库的等价物 |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `subagent-driven-development` | hand 派发 + review bundle(`smart_execute` / `smart_consult`) |
|
|
64
|
+
| `executing-plans` | `smart_execute` |
|
|
65
|
+
| `requesting-code-review` | `smart_consult` + `smart_verify` |
|
|
66
|
+
| `finishing-a-development-branch` | `smart_finish` |
|
|
67
|
+
| `brainstorming` | `brainstorm` 相位 + `smart_brief` 对话回路 |
|
|
68
|
+
| `diagnosing-superpowers` | `smart-diagnose`(改写适配) |
|
|
69
|
+
|
|
70
|
+
### 命名
|
|
71
|
+
|
|
72
|
+
本包**不是** obra/superpowers 的官方移植,也不是它本身。若在插件市场搜索
|
|
73
|
+
`superpowers` 找到本包,看到的是**衍生实现**:方法论继承,机制不同。
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: smart-debug
|
|
3
|
+
description: Use when 遇到任何 bug、测试失败、行为异常、性能问题、构建失败、集成问题,在提出任何修复之前加载:先做根因调查,症状修复不算修复。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- Ported from obra/superpowers skills/systematic-debugging/ — MIT License, Copyright (c) 2025 Jesse Vincent. Adapted for DSH. -->
|
|
7
|
+
|
|
8
|
+
# 系统化调试(Systematic Debugging)
|
|
9
|
+
|
|
10
|
+
## 总览
|
|
11
|
+
|
|
12
|
+
**核心原则:ALWAYS find root cause before attempting fixes. Symptom fixes are failure.**
|
|
13
|
+
(永远先找到根因再修。症状修复就是失败。)
|
|
14
|
+
|
|
15
|
+
**违反这个流程的字面,就是违反调试的精神(Violating the letter of this process is violating the spirit of debugging)。**
|
|
16
|
+
|
|
17
|
+
## 铁律(The Iron Law)
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
没有完成阶段 1,就不许提出修复。
|
|
24
|
+
|
|
25
|
+
## 何时使用
|
|
26
|
+
|
|
27
|
+
用于**任何**技术问题:
|
|
28
|
+
|
|
29
|
+
- 测试失败
|
|
30
|
+
- 生产环境 bug
|
|
31
|
+
- 行为异常
|
|
32
|
+
- 性能问题
|
|
33
|
+
- 构建失败
|
|
34
|
+
- 集成问题
|
|
35
|
+
|
|
36
|
+
**尤其要用在:**
|
|
37
|
+
|
|
38
|
+
- 时间压力下(紧急情况让瞎猜变得诱人)
|
|
39
|
+
- "先来个快速修复"看起来很明显时
|
|
40
|
+
- 你已经试过多个修复
|
|
41
|
+
- 上一个修复没有起作用
|
|
42
|
+
- 你并没有完全弄懂这个问题
|
|
43
|
+
|
|
44
|
+
**不许因为这些跳过:**
|
|
45
|
+
|
|
46
|
+
- 问题看起来很简单(简单 bug 也有根因)
|
|
47
|
+
- 你在赶时间(仓促保证返工)
|
|
48
|
+
- 上级要它"现在就修好"(系统化比瞎折腾快)
|
|
49
|
+
|
|
50
|
+
## 四个阶段(The Four Phases)
|
|
51
|
+
|
|
52
|
+
必须完成当前阶段,才能进入下一阶段。
|
|
53
|
+
|
|
54
|
+
### 阶段 1:根因调查(Root Cause Investigation)
|
|
55
|
+
|
|
56
|
+
**在动手修任何东西之前:**
|
|
57
|
+
|
|
58
|
+
1. **认真读错误信息(Read Error Messages Carefully)**
|
|
59
|
+
- 不要跳过报错与警告,它们常常含有精确的答案
|
|
60
|
+
- 完整读调用栈(用 `read` 读完整日志,别只看最后一行)
|
|
61
|
+
- 记下行号、文件路径、错误码
|
|
62
|
+
|
|
63
|
+
2. **稳定复现(Reproduce Consistently)**
|
|
64
|
+
- 能可靠触发吗?精确步骤是什么?每次都发生吗?
|
|
65
|
+
- 如果不能复现 → 继续收集数据,不要猜;复现跑在后台(`bash` 长任务)时用 `job_list` / `job_output` 把结果收回来再分析
|
|
66
|
+
|
|
67
|
+
3. **检查最近的改动(Check Recent Changes)**
|
|
68
|
+
- 什么改动可能导致这个?(`bash` 跑 `git diff` / `git log`)
|
|
69
|
+
- 新依赖、配置改动、环境差异(用 `grep` / `glob` 找到改动落点)
|
|
70
|
+
|
|
71
|
+
4. **多组件系统里收集证据(Gather Evidence in Multi-Component Systems)**
|
|
72
|
+
|
|
73
|
+
**当系统有多个组件时(CI → 构建 → 签名,API → 服务 → 数据库):**
|
|
74
|
+
|
|
75
|
+
**在提出修复之前,先加诊断埋点:**
|
|
76
|
+
```
|
|
77
|
+
对每一个组件边界:
|
|
78
|
+
- 记录进入组件的数据
|
|
79
|
+
- 记录离开组件的数据
|
|
80
|
+
- 验证环境 / 配置是否传播到位
|
|
81
|
+
- 检查每一层的状态
|
|
82
|
+
|
|
83
|
+
跑一次,收集证据,指出「在哪一层断了」
|
|
84
|
+
然后分析证据,锁定失败的组件
|
|
85
|
+
然后只调查那个组件
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**示例(多层系统):**
|
|
89
|
+
```bash
|
|
90
|
+
# 第 1 层:Workflow —— Secrets 可用吗?
|
|
91
|
+
echo "IDENTITY: $([ -n "${IDENTITY:-}" ] && echo SET || echo UNSET)"
|
|
92
|
+
# 第 2 层:构建脚本 —— 环境变量传到了吗?
|
|
93
|
+
printenv IDENTITY >/dev/null 2>&1 && echo "IDENTITY in environment" || echo "IDENTITY not in environment"
|
|
94
|
+
# 第 3 层:签名脚本 —— Keychain 状态
|
|
95
|
+
security list-keychains; security find-identity -v
|
|
96
|
+
# 第 4 层:真正签名
|
|
97
|
+
codesign --sign "$IDENTITY" --verbose=4 "$APP"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**这会揭示:**到底哪一层坏了(secrets → workflow ✓,workflow → build ✗)
|
|
101
|
+
|
|
102
|
+
5. **追溯数据流(Trace Data Flow)**
|
|
103
|
+
|
|
104
|
+
**当错误出现在调用栈深处时:**完整技术见下方「延伸 · 根因追溯」。速查版(就是连续追问 why 的 5-Why):坏值从哪里产生?谁带着坏值调用了这里?一路往上追,直到找到源头——**在源头修,不在症状处修(Fix at source, not at symptom)**。
|
|
105
|
+
|
|
106
|
+
### 阶段 2:模式分析(Pattern Analysis)
|
|
107
|
+
|
|
108
|
+
**修之前先找到模式:**
|
|
109
|
+
|
|
110
|
+
1. **找能工作的例子(Find Working Examples)**
|
|
111
|
+
- 在同一个代码库里找相似的、能工作的代码(`grep` / `glob`)
|
|
112
|
+
- 什么东西和坏掉的东西相似、却好使?
|
|
113
|
+
|
|
114
|
+
2. **对照参考实现(Compare Against References)**
|
|
115
|
+
- 如果在实现某个模式,**完整读**参考实现(用 `read` 从头读到尾)
|
|
116
|
+
- 不要一目十行——逐行读完再动手
|
|
117
|
+
|
|
118
|
+
3. **找出差异(Identify Differences)**
|
|
119
|
+
- 能工作的和坏掉的之间有什么不同?
|
|
120
|
+
- 列出**每一个**差异,无论多小
|
|
121
|
+
- 不要假设"这个不可能有影响"
|
|
122
|
+
|
|
123
|
+
4. **理解依赖(Understand Dependencies)**
|
|
124
|
+
- 它还需要哪些组件?哪些设置、配置、环境?
|
|
125
|
+
- 它做了什么假设?
|
|
126
|
+
|
|
127
|
+
### 阶段 3:假设与验证(Hypothesis and Testing)
|
|
128
|
+
|
|
129
|
+
**科学方法:**
|
|
130
|
+
|
|
131
|
+
1. **形成单一假设(Form Single Hypothesis)**
|
|
132
|
+
- 清楚地说出来:"我认为 X 是根因,因为 Y"
|
|
133
|
+
- 写下来,要具体,不要含糊
|
|
134
|
+
|
|
135
|
+
2. **最小化测试(Test Minimally)**
|
|
136
|
+
- 为验证假设做**最小**的改动
|
|
137
|
+
- 一次只动一个变量,不要同时修多个东西
|
|
138
|
+
|
|
139
|
+
3. **验证后再继续(Verify Before Continuing)**
|
|
140
|
+
- 有效?→ 阶段 4
|
|
141
|
+
- 无效?→ 形成**新的**假设
|
|
142
|
+
- **不要在上面继续叠加修复**
|
|
143
|
+
|
|
144
|
+
4. **不知道就说不知道(When You Don't Know)**
|
|
145
|
+
- 说"我没弄懂 X",不要装懂
|
|
146
|
+
- 求助、继续查资料
|
|
147
|
+
|
|
148
|
+
### 阶段 4:实施(Implementation)
|
|
149
|
+
|
|
150
|
+
**修根因,不修症状:**
|
|
151
|
+
|
|
152
|
+
1. **先造失败的测试用例(Create Failing Test Case)**
|
|
153
|
+
- 最简单的复现;能自动化就自动化(`write` 写一次性测试脚本也算);没有框架就写一次性脚本
|
|
154
|
+
- **修之前必须先有它**
|
|
155
|
+
|
|
156
|
+
2. **实施单一修复(Implement Single Fix)**
|
|
157
|
+
- 只处理已确认的根因,一次一个改动(用 `edit` 做最小修改)
|
|
158
|
+
- 不要"顺手也改改",不要夹带重构
|
|
159
|
+
|
|
160
|
+
3. **验证修复(Verify Fix)**
|
|
161
|
+
- 测试现在过了吗?别的测试没坏吗?问题真的解决了吗?
|
|
162
|
+
- 交付前先验证再宣称成功:把证据(命令 + 实际输出)摆出来
|
|
163
|
+
|
|
164
|
+
4. **修复无效时(If Fix Doesn't Work)**
|
|
165
|
+
- **停(STOP)**
|
|
166
|
+
- 数一数:你已经试了几个修复?
|
|
167
|
+
- **< 3 个**:回阶段 1,带着新信息重新分析
|
|
168
|
+
- **≥ 3 个**:**停,质疑架构**(见下面第 5 条)
|
|
169
|
+
- 不许在没有架构讨论的情况下尝试第 4 个修复
|
|
170
|
+
|
|
171
|
+
5. **3 次以上修复失败:质疑架构(Question Architecture)**
|
|
172
|
+
|
|
173
|
+
**预示架构问题的模式:**
|
|
174
|
+
- 每次修复都在不同地方暴露新的共享状态 / 耦合 / 问题
|
|
175
|
+
- 修复需要"大规模重构"才能实现
|
|
176
|
+
- 每次修复都在别处制造新症状
|
|
177
|
+
|
|
178
|
+
**停下来质疑根本:**这个模式本身站得住脚吗?我们是不是"纯靠惯性在坚持它"?该重构架构,还是继续修症状?
|
|
179
|
+
|
|
180
|
+
**动手再修之前,先和你的人类搭档讨论。** 这不是假设失败——这是**架构错了**。
|
|
181
|
+
|
|
182
|
+
## 红旗:停,回到流程(Red Flags - STOP and Follow Process)
|
|
183
|
+
|
|
184
|
+
如果你抓住自己正在想:
|
|
185
|
+
|
|
186
|
+
- "先快速修一下,以后再查"
|
|
187
|
+
- "改个 X 试试看行不行"
|
|
188
|
+
- "多改几处,跑一遍测试"
|
|
189
|
+
- "跳过测试吧,我手动验证"
|
|
190
|
+
- "多半是 X,我把它修了"
|
|
191
|
+
- "我不完全懂,但这样大概能行"
|
|
192
|
+
- "模式说的是 X,但我按自己的方式改改"
|
|
193
|
+
- "主要问题有这些:[没调查就列出一堆修复]"
|
|
194
|
+
- 还没追溯数据流就提出解决方案
|
|
195
|
+
- **"再修一次试试"(已经试了 2 次以上)**
|
|
196
|
+
- **每次修复都在不同地方暴露新问题**
|
|
197
|
+
|
|
198
|
+
**以上任何一条都意味着:停。回阶段 1。如果 3 次以上修复失败:质疑架构(见阶段 4 第 5 条)。**
|
|
199
|
+
|
|
200
|
+
## 你的人类搭档的信号:你做错了(Your Human Partner's Signals)
|
|
201
|
+
|
|
202
|
+
**注意这些纠偏话语:**
|
|
203
|
+
|
|
204
|
+
- "那不是没发生吗?"——你在没验证的情况下下了假设
|
|
205
|
+
- "它会给我们看出来……吗?"——你本该加证据收集
|
|
206
|
+
- "别猜了"——你在不懂的情况下提修复
|
|
207
|
+
- "往深里想"(Ultra-think this)——要质疑根本,不只是症状
|
|
208
|
+
- "我们卡住了?"(沮丧)——你的路子不对
|
|
209
|
+
|
|
210
|
+
**看到这些:停。回阶段 1。**
|
|
211
|
+
|
|
212
|
+
## 找借口对照表(Common Rationalizations)
|
|
213
|
+
|
|
214
|
+
| 借口 | 现实 |
|
|
215
|
+
|------|------|
|
|
216
|
+
| "问题很简单,不用走流程" | 简单问题也有根因。对简单 bug,流程反而快。 |
|
|
217
|
+
| "紧急,没时间走流程" | 系统化调试比"猜-试"式瞎折腾**更快**。 |
|
|
218
|
+
| "先试试这个,然后再调查" | 第一个修复定下基调。从一开始就做对。 |
|
|
219
|
+
| "等确认修复有效我再写测试" | 没测试的修复留不住。先写测试才能证明它。 |
|
|
220
|
+
| "一次修多处省时间" | 分不清哪个起了作用,还会制造新 bug。 |
|
|
221
|
+
| "参考太长,我照着模式改改" | 一知半解保证出 bug。完整读完。 |
|
|
222
|
+
| "我看出问题了,让我修" | 看到症状 ≠ 理解根因。 |
|
|
223
|
+
| "再修一次试试"(2 次失败之后) | 3 次以上失败 = 架构问题。质疑模式,别再修。 |
|
|
224
|
+
|
|
225
|
+
## 快速参考(Quick Reference)
|
|
226
|
+
|
|
227
|
+
| 阶段 | 关键活动 | 成功判据 |
|
|
228
|
+
|------|----------|----------|
|
|
229
|
+
| **1. 根因** | 读报错、复现、查改动、收集证据 | 弄懂 WHAT 与 WHY |
|
|
230
|
+
| **2. 模式** | 找能工作的例子、对照 | 列出差异 |
|
|
231
|
+
| **3. 假设** | 形成理论、最小化验证 | 假设被确认或换新假设 |
|
|
232
|
+
| **4. 实施** | 写测试、修复、验证 | bug 解决、测试通过 |
|
|
233
|
+
|
|
234
|
+
## 当流程揭示"没有根因"
|
|
235
|
+
|
|
236
|
+
如果系统化调查发现问题是纯环境性的、时序相关的或外部的:
|
|
237
|
+
|
|
238
|
+
1. 你已经走完了流程
|
|
239
|
+
2. 记录你调查了什么
|
|
240
|
+
3. 实现恰当的处理(重试、超时、错误提示)
|
|
241
|
+
4. 加监控 / 日志,为将来调查留证据
|
|
242
|
+
|
|
243
|
+
**但是:**95% 的"没有根因"其实是调查不完整。
|
|
244
|
+
|
|
245
|
+
## 延伸:三个配套技术(原参考资料摘要)
|
|
246
|
+
|
|
247
|
+
### 根因追溯(Root Cause Tracing)
|
|
248
|
+
|
|
249
|
+
Bug 常出现在调用栈深处(`git init` 在错误目录、文件建在错的地方、数据库开在错的路径)。**核心原则:沿调用链向后追,直到找到最初的触发点,在源头修。**
|
|
250
|
+
|
|
251
|
+
追溯五步:观察症状 → 找直接原因 → 问"谁调用了它?" → 继续往上追(坏值是什么?从哪来?)→ 找到原始触发点。
|
|
252
|
+
追不上时加埋点:在危险操作**之前**打印目录、`process.cwd()`、环境变量和 `new Error().stack`(测试里用 `console.error`,logger 可能被吞)。
|
|
253
|
+
|
|
254
|
+
真实案例:`.git` 被建到源码目录里 —— 5 层追溯发现 `context.tempDir` 在 `beforeEach` 之前被读到(初始值是空串,空串当 `cwd` 解析成 `process.cwd()`)。根因修法:把 `tempDir` 改成 getter,初始化前访问就抛错。**NEVER fix just the symptom.**
|
|
255
|
+
|
|
256
|
+
### 纵深防御(Defense-in-Depth)
|
|
257
|
+
|
|
258
|
+
在源头修完之后再做:**每一层数据经过的地方都校验,让 bug 在结构上不可能发生。** 单点校验:"我们修好了这个 bug";多层校验:"我们让这个 bug 不可能发生"。
|
|
259
|
+
|
|
260
|
+
| 层 | 作用 | 例子 |
|
|
261
|
+
|----|------|------|
|
|
262
|
+
| 1. 入口校验 | 在 API 边界拒绝明显非法的输入 | 空目录 / 不存在 / 不是目录就抛 |
|
|
263
|
+
| 2. 业务逻辑校验 | 数据对这个操作得说得通 | `projectDir` 必填 |
|
|
264
|
+
| 3. 环境守卫 | 阻止特定上下文里的危险操作 | 测试环境拒绝在 tmpdir 外 `git init` |
|
|
265
|
+
| 4. 调试埋点 | 事后取证 | 危险操作前打调用栈 |
|
|
266
|
+
|
|
267
|
+
逐层测试:试着绕过第 1 层,确认第 2 层接得住。**别停在一个校验点。**
|
|
268
|
+
|
|
269
|
+
### 条件等待(Condition-Based Waiting)
|
|
270
|
+
|
|
271
|
+
flaky 测试常靠任意延时猜时间。**核心原则:等你真正关心的条件,不要猜"大概要多久"。**
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
// ❌ 猜时间
|
|
275
|
+
await new Promise(r => setTimeout(r, 50));
|
|
276
|
+
// ✅ 等条件
|
|
277
|
+
await waitFor(() => getResult() !== undefined);
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
| 场景 | 模式 |
|
|
281
|
+
|------|------|
|
|
282
|
+
| 等事件 | `waitFor(() => events.find(e => e.type === 'DONE'))` |
|
|
283
|
+
| 等状态 | `waitFor(() => machine.state === 'ready')` |
|
|
284
|
+
| 等数量 | `waitFor(() => items.length >= 5)` |
|
|
285
|
+
| 等文件 | `waitFor(() => fs.existsSync(path))` |
|
|
286
|
+
|
|
287
|
+
通用轮询:每 10ms 查一次,必须带超时并抛出清晰错误,getter 在循环**内**取新鲜数据。使用任意超时的正当情形:先等触发条件,再基于**已知**节拍等待(并在注释里写清 WHY)。
|
|
288
|
+
|
|
289
|
+
### 找污染测试的二分脚本(find-polluter.sh)
|
|
290
|
+
|
|
291
|
+
不知道哪个测试制造了多余的文件 / 状态时,用二分脚本逐个跑测试:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
#!/usr/bin/env bash
|
|
295
|
+
# 用法: bash find-polluter.sh <要检查的文件/目录> <测试文件 glob> 例: '.git' 'src/**/*.test.ts'
|
|
296
|
+
set -e
|
|
297
|
+
[ $# -ne 2 ] && { echo "Usage: $0 <file_to_check> <test_pattern>"; exit 1; }
|
|
298
|
+
POLLUTION_CHECK="$1"; TEST_PATTERN="${2#./}"
|
|
299
|
+
TEST_FILES=$(find . \( -path "./$TEST_PATTERN" -o -path "./${TEST_PATTERN//\*\*\//}" \) | sort -u)
|
|
300
|
+
TOTAL=$(printf '%s\n' "$TEST_FILES" | grep -c . || true)
|
|
301
|
+
echo "Found $TOTAL test files"
|
|
302
|
+
COUNT=0
|
|
303
|
+
for TEST_FILE in $TEST_FILES; do
|
|
304
|
+
COUNT=$((COUNT + 1))
|
|
305
|
+
[ -e "$POLLUTION_CHECK" ] && { echo "⚠️ pollution already exists, skipping $TEST_FILE"; continue; }
|
|
306
|
+
echo "[$COUNT/$TOTAL] Testing: $TEST_FILE"
|
|
307
|
+
npm test "$TEST_FILE" > /dev/null 2>&1 || true
|
|
308
|
+
[ -e "$POLLUTION_CHECK" ] && { echo "🎯 FOUND POLLUTER: $TEST_FILE (created $POLLUTION_CHECK)"; ls -la "$POLLUTION_CHECK"; exit 1; }
|
|
309
|
+
done
|
|
310
|
+
echo "✅ No polluter found - all tests clean!"
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 压力测试:这套流程是为顶住压力设计的
|
|
314
|
+
|
|
315
|
+
原文用三个压力场景校验过这套纪律,遇到同类情形照流程走:**① 紧急生产事故**(每分钟在亏钱、有人喊"先修再说"——系统化仍比猜-试快);**② 沉没成本 + 疲惫**(同一个失败试了 6 次 `sleep` 还在加码——那是第 4 个修复,停,质疑架构/时序假设);**③ 权威与社交压力**(资深同事说"这模式我见多了,直接修"——照样先追根因,30 分钟的追溯比错误修复便宜)。
|
|
316
|
+
|
|
317
|
+
## 进阶:需要完整交付时
|
|
318
|
+
|
|
319
|
+
如果这个 bug 需要改代码并交付,用 `smart_begin({ shape: 'fix' })` 走 smart 工作流;只是排查定位则不必。
|