dev-playbooks-cn 1.0.0
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 +466 -0
- package/bin/devbooks.js +987 -0
- package/package.json +43 -0
- package/skills/Skills/344/275/277/347/224/250/350/257/264/346/230/216.md +446 -0
- package/skills/Skill/345/274/200/345/217/221/346/214/207/345/215/227.md +248 -0
- package/skills/_shared/context-detection-template.md +315 -0
- package/skills/_shared/mcp-enhancement-template.md +144 -0
- package/skills/_shared/references//351/200/232/347/224/250/345/256/210/351/227/250/345/215/217/350/256/256.md +114 -0
- package/skills/_template/config-discovery-template.md +126 -0
- package/skills/devbooks-brownfield-bootstrap/SKILL.md +167 -0
- package/skills/devbooks-brownfield-bootstrap/references//344/273/243/347/240/201/345/257/274/350/210/252/347/255/226/347/225/245.md +203 -0
- package/skills/devbooks-brownfield-bootstrap/references//345/255/230/351/207/217/351/241/271/347/233/256/345/210/235/345/247/213/345/214/226.md +96 -0
- package/skills/devbooks-brownfield-bootstrap/references//345/255/230/351/207/217/351/241/271/347/233/256/345/210/235/345/247/213/345/214/226/346/217/220/347/244/272/350/257/215.md +115 -0
- package/skills/devbooks-brownfield-bootstrap/references//346/234/257/350/257/255/350/241/250/346/250/241/346/235/277.md +42 -0
- package/skills/devbooks-brownfield-bootstrap/scripts/cod-update.sh +357 -0
- package/skills/devbooks-brownfield-bootstrap/templates/project-profile-template.md +172 -0
- package/skills/devbooks-c4-map/SKILL.md +151 -0
- package/skills/devbooks-c4-map/references/C4/346/236/266/346/236/204/345/234/260/345/233/276/346/217/220/347/244/272/350/257/215.md +33 -0
- package/skills/devbooks-c4-map/references//345/210/206/345/261/202/347/272/246/346/235/237/346/243/200/346/237/245/346/270/205/345/215/225.md +185 -0
- package/skills/devbooks-code-review/SKILL.md +175 -0
- package/skills/devbooks-code-review/references/PR/346/250/241/346/235/277/344/270/216/346/214/207/345/215/227.md +321 -0
- package/skills/devbooks-code-review/references//344/273/243/347/240/201/350/257/204/345/256/241/346/217/220/347/244/272/350/257/215.md +100 -0
- package/skills/devbooks-code-review/references//345/235/217/345/221/263/351/201/223/351/200/237/346/237/245/350/241/250.md +495 -0
- package/skills/devbooks-code-review/references//350/265/204/346/272/220/347/256/241/347/220/206/345/256/241/346/237/245/346/270/205/345/215/225.md +311 -0
- package/skills/devbooks-coder/SKILL.md +219 -0
- package/skills/devbooks-coder/references//344/273/243/347/240/201/345/256/236/347/216/260/346/217/220/347/244/272/350/257/215.md +70 -0
- package/skills/devbooks-coder/references//344/275/216/351/243/216/351/231/251/346/224/271/345/212/250/346/212/200/346/234/257.md +275 -0
- package/skills/devbooks-coder/references//346/227/245/345/277/227/350/247/204/350/214/203.md +329 -0
- package/skills/devbooks-coder/references//347/274/226/347/240/201/351/243/216/346/240/274/347/273/206/345/210/231.md +351 -0
- package/skills/devbooks-coder/references//351/224/231/350/257/257/347/240/201/350/247/204/350/214/203.md +463 -0
- package/skills/devbooks-delivery-workflow/SKILL.md +217 -0
- package/skills/devbooks-delivery-workflow/references//344/272/244/344/273/230/351/252/214/346/224/266/345/267/245/344/275/234/346/265/201.md +256 -0
- package/skills/devbooks-delivery-workflow/references//345/216/237/345/236/213-/347/224/237/344/272/247/345/217/214/350/275/250/346/250/241/345/274/217.md +168 -0
- package/skills/devbooks-delivery-workflow/references//345/217/230/346/233/264/351/252/214/350/257/201/344/270/216/350/277/275/346/272/257/346/250/241/346/235/277.md +133 -0
- package/skills/devbooks-delivery-workflow/scripts/ac-trace-check.sh +330 -0
- package/skills/devbooks-delivery-workflow/scripts/audit-scope.sh +262 -0
- package/skills/devbooks-delivery-workflow/scripts/change-check.sh +1040 -0
- package/skills/devbooks-delivery-workflow/scripts/change-codemod-scaffold.sh +135 -0
- package/skills/devbooks-delivery-workflow/scripts/change-evidence.sh +152 -0
- package/skills/devbooks-delivery-workflow/scripts/change-scaffold.sh +442 -0
- package/skills/devbooks-delivery-workflow/scripts/change-spec-delta-scaffold.sh +136 -0
- package/skills/devbooks-delivery-workflow/scripts/constitution-check.sh +237 -0
- package/skills/devbooks-delivery-workflow/scripts/env-match-check.sh +128 -0
- package/skills/devbooks-delivery-workflow/scripts/fitness-check.sh +387 -0
- package/skills/devbooks-delivery-workflow/scripts/guardrail-check.sh +519 -0
- package/skills/devbooks-delivery-workflow/scripts/handoff-check.sh +141 -0
- package/skills/devbooks-delivery-workflow/scripts/hygiene-check.sh +340 -0
- package/skills/devbooks-delivery-workflow/scripts/migrate-from-openspec.sh +385 -0
- package/skills/devbooks-delivery-workflow/scripts/migrate-to-v2-gates.sh +202 -0
- package/skills/devbooks-delivery-workflow/scripts/progress-dashboard.sh +319 -0
- package/skills/devbooks-delivery-workflow/scripts/prototype-promote.sh +341 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-preview.sh +203 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-promote.sh +118 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-rollback.sh +124 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-stage.sh +117 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-all.sh +78 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-npm-package.sh +123 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-openspec-free.sh +81 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-slash-commands.sh +146 -0
- package/skills/devbooks-delivery-workflow/templates/handoff.md +50 -0
- package/skills/devbooks-design-backport/SKILL.md +73 -0
- package/skills/devbooks-design-backport/references//345/233/236/345/206/231/350/256/276/350/256/241/346/226/207/346/241/243/346/217/220/347/244/272/350/257/215.md +196 -0
- package/skills/devbooks-design-doc/SKILL.md +121 -0
- package/skills/devbooks-design-doc/references//345/276/256/346/234/215/345/212/241/350/256/276/350/256/241/346/270/205/345/215/225.md +149 -0
- package/skills/devbooks-design-doc/references//350/256/276/350/256/241/346/226/207/346/241/243/346/217/220/347/244/272/350/257/215.md +189 -0
- package/skills/devbooks-design-doc/references//351/232/220/347/247/201/345/220/210/350/247/204/346/243/200/346/237/245/346/270/205/345/215/225.md +240 -0
- package/skills/devbooks-entropy-monitor/SKILL.md +188 -0
- package/skills/devbooks-entropy-monitor/references//347/206/265/345/272/246/351/207/217/346/226/271/346/263/225/350/256/272.md +223 -0
- package/skills/devbooks-entropy-monitor/scripts/entropy-measure.sh +449 -0
- package/skills/devbooks-entropy-monitor/scripts/entropy-report.sh +303 -0
- package/skills/devbooks-entropy-monitor/templates/thresholds.json +99 -0
- package/skills/devbooks-federation/SKILL.md +264 -0
- package/skills/devbooks-federation/scripts/federation-check.sh +144 -0
- package/skills/devbooks-federation/templates/federation.yaml +89 -0
- package/skills/devbooks-impact-analysis/SKILL.md +135 -0
- package/skills/devbooks-impact-analysis/references//345/275/261/345/223/215/345/210/206/346/236/220/346/217/220/347/244/272/350/257/215.md +82 -0
- package/skills/devbooks-impact-analysis/scripts/graph-cache.sh +214 -0
- package/skills/devbooks-implementation-plan/SKILL.md +83 -0
- package/skills/devbooks-implementation-plan/references//347/274/226/347/240/201/350/256/241/345/210/222/346/217/220/347/244/272/350/257/215.md +99 -0
- package/skills/devbooks-index-bootstrap/SKILL.md +240 -0
- package/skills/devbooks-proposal-author/SKILL.md +83 -0
- package/skills/devbooks-proposal-author/references//346/217/220/346/241/210/346/222/260/345/206/231/346/217/220/347/244/272/350/257/215.md +66 -0
- package/skills/devbooks-proposal-challenger/SKILL.md +86 -0
- package/skills/devbooks-proposal-challenger/references//344/274/246/347/220/206/344/270/216/345/220/210/350/247/204/346/243/200/346/237/245/346/270/205/345/215/225.md +176 -0
- package/skills/devbooks-proposal-challenger/references//346/217/220/346/241/210/350/264/250/347/226/221/346/217/220/347/244/272/350/257/215.md +57 -0
- package/skills/devbooks-proposal-debate-workflow/SKILL.md +78 -0
- package/skills/devbooks-proposal-debate-workflow/references//346/217/220/346/241/210/345/257/271/350/276/251/345/267/245/344/275/234/346/265/201.md +24 -0
- package/skills/devbooks-proposal-debate-workflow/references//346/217/220/346/241/210/345/257/271/350/276/251/346/250/241/346/235/277.md +35 -0
- package/skills/devbooks-proposal-debate-workflow/scripts/proposal-debate-check.sh +102 -0
- package/skills/devbooks-proposal-judge/SKILL.md +78 -0
- package/skills/devbooks-proposal-judge/references//346/217/220/346/241/210/350/243/201/345/206/263/346/217/220/347/244/272/350/257/215.md +37 -0
- package/skills/devbooks-router/SKILL.md +346 -0
- package/skills/devbooks-spec-contract/SKILL.md +191 -0
- package/skills/devbooks-spec-contract/references/API/350/256/276/350/256/241/346/214/207/345/215/227.md +349 -0
- package/skills/devbooks-spec-contract/references//345/245/221/347/272/246/344/270/216/346/225/260/346/215/256/345/256/232/344/271/211/346/217/220/347/244/272/350/257/215.md +85 -0
- package/skills/devbooks-spec-contract/references//350/247/204/346/240/274/345/217/230/346/233/264/346/217/220/347/244/272/350/257/215.md +63 -0
- package/skills/devbooks-spec-contract/references//351/232/220/345/274/217/345/217/230/346/233/264/346/243/200/346/265/213/346/217/220/347/244/272/350/257/215.md +183 -0
- package/skills/devbooks-spec-contract/scripts/implicit-change-detect.sh +378 -0
- package/skills/devbooks-spec-gardener/SKILL.md +72 -0
- package/skills/devbooks-spec-gardener/references//350/247/204/346/240/274/345/233/255/344/270/201/346/217/220/347/244/272/350/257/215.md +41 -0
- package/skills/devbooks-test-owner/SKILL.md +172 -0
- package/skills/devbooks-test-owner/references//345/217/230/346/233/264/351/252/214/350/257/201/344/270/216/350/277/275/346/272/257/346/250/241/346/235/277.md +228 -0
- package/skills/devbooks-test-owner/references//345/274/202/346/255/245/347/263/273/347/273/237/346/265/213/350/257/225/347/255/226/347/225/245.md +316 -0
- package/skills/devbooks-test-owner/references//346/265/213/350/257/225/344/273/243/347/240/201/346/217/220/347/244/272/350/257/215.md +208 -0
- package/skills/devbooks-test-owner/references//346/265/213/350/257/225/345/210/206/345/261/202/347/255/226/347/225/245.md +281 -0
- package/skills/devbooks-test-owner/references//346/265/213/350/257/225/351/251/261/345/212/250.md +394 -0
- package/skills/devbooks-test-owner/references//350/247/243/344/276/235/350/265/226/346/212/200/346/234/257/351/200/237/346/237/245/350/241/250.md +432 -0
- package/skills/devbooks-test-reviewer/SKILL.md +189 -0
- package/templates/.devbooks/config.yaml +88 -0
- package/templates/claude-commands/devbooks/apply.md +38 -0
- package/templates/claude-commands/devbooks/archive.md +33 -0
- package/templates/claude-commands/devbooks/backport.md +19 -0
- package/templates/claude-commands/devbooks/bootstrap.md +19 -0
- package/templates/claude-commands/devbooks/c4.md +19 -0
- package/templates/claude-commands/devbooks/challenger.md +19 -0
- package/templates/claude-commands/devbooks/code.md +19 -0
- package/templates/claude-commands/devbooks/debate.md +19 -0
- package/templates/claude-commands/devbooks/delivery.md +19 -0
- package/templates/claude-commands/devbooks/design.md +19 -0
- package/templates/claude-commands/devbooks/entropy.md +19 -0
- package/templates/claude-commands/devbooks/federation.md +19 -0
- package/templates/claude-commands/devbooks/gardener.md +19 -0
- package/templates/claude-commands/devbooks/impact.md +19 -0
- package/templates/claude-commands/devbooks/index.md +19 -0
- package/templates/claude-commands/devbooks/judge.md +19 -0
- package/templates/claude-commands/devbooks/plan.md +19 -0
- package/templates/claude-commands/devbooks/proposal.md +19 -0
- package/templates/claude-commands/devbooks/quick.md +42 -0
- package/templates/claude-commands/devbooks/review.md +19 -0
- package/templates/claude-commands/devbooks/router.md +19 -0
- package/templates/claude-commands/devbooks/spec.md +19 -0
- package/templates/claude-commands/devbooks/test-review.md +19 -0
- package/templates/claude-commands/devbooks/test.md +19 -0
- package/templates/dev-playbooks/README.md +458 -0
- package/templates/dev-playbooks/changes/.gitkeep +1 -0
- package/templates/dev-playbooks/constitution.md +116 -0
- package/templates/dev-playbooks/project.md +96 -0
- package/templates/dev-playbooks/scripts/.gitkeep +1 -0
- package/templates/dev-playbooks/specs/_meta/anti-patterns/.gitkeep +2 -0
- package/templates/dev-playbooks/specs/_meta/glossary.md +47 -0
- package/templates/dev-playbooks/specs/_meta/project-profile.md +79 -0
- package/templates/dev-playbooks/specs/architecture/fitness-rules.md +95 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# 资源管理审查清单
|
|
2
|
+
|
|
3
|
+
借鉴 VS Code 的 `code-no-potentially-unsafe-disposables` 和 `code-must-use-super-dispose` 规则。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1) 资源泄漏常见模式
|
|
8
|
+
|
|
9
|
+
### 订阅/监听器泄漏
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// 违规:订阅未取消
|
|
13
|
+
class MyComponent {
|
|
14
|
+
private handler = (e: Event) => { /* ... */ };
|
|
15
|
+
|
|
16
|
+
initialize() {
|
|
17
|
+
document.addEventListener('click', this.handler);
|
|
18
|
+
// 缺少对应的 removeEventListener
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 正确:使用 AbortController
|
|
23
|
+
class MyComponent {
|
|
24
|
+
private abortController = new AbortController();
|
|
25
|
+
|
|
26
|
+
initialize() {
|
|
27
|
+
document.addEventListener('click', this.handler, {
|
|
28
|
+
signal: this.abortController.signal
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dispose() {
|
|
33
|
+
this.abortController.abort();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 定时器泄漏
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// 违规:定时器未清理
|
|
42
|
+
class Poller {
|
|
43
|
+
start() {
|
|
44
|
+
setInterval(() => this.poll(), 1000);
|
|
45
|
+
// 缺少清理逻辑
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 正确:保存引用并在 dispose 中清理
|
|
50
|
+
class Poller {
|
|
51
|
+
private intervalId?: NodeJS.Timeout;
|
|
52
|
+
|
|
53
|
+
start() {
|
|
54
|
+
this.intervalId = setInterval(() => this.poll(), 1000);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
dispose() {
|
|
58
|
+
if (this.intervalId) {
|
|
59
|
+
clearInterval(this.intervalId);
|
|
60
|
+
this.intervalId = undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 流/连接泄漏
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// 违规:流未关闭
|
|
70
|
+
async function readFile(path: string) {
|
|
71
|
+
const stream = fs.createReadStream(path);
|
|
72
|
+
const data = await streamToString(stream);
|
|
73
|
+
// 如果 streamToString 抛出异常,流不会关闭
|
|
74
|
+
return data;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 正确:使用 try-finally
|
|
78
|
+
async function readFile(path: string) {
|
|
79
|
+
const stream = fs.createReadStream(path);
|
|
80
|
+
try {
|
|
81
|
+
return await streamToString(stream);
|
|
82
|
+
} finally {
|
|
83
|
+
stream.destroy();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 更好:使用 using(TypeScript 5.2+)
|
|
88
|
+
async function readFile(path: string) {
|
|
89
|
+
using stream = fs.createReadStream(path);
|
|
90
|
+
return await streamToString(stream);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 2) DisposableStore 模式
|
|
97
|
+
|
|
98
|
+
### 基本用法
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
|
102
|
+
|
|
103
|
+
class MyService extends Disposable {
|
|
104
|
+
// 必须是 readonly
|
|
105
|
+
private readonly _disposables = new DisposableStore();
|
|
106
|
+
|
|
107
|
+
constructor() {
|
|
108
|
+
super();
|
|
109
|
+
|
|
110
|
+
// 注册订阅到 store
|
|
111
|
+
this._disposables.add(
|
|
112
|
+
eventEmitter.on('change', () => this.handleChange())
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// 注册定时器到 store
|
|
116
|
+
this._disposables.add(
|
|
117
|
+
new IntervalTimer(() => this.poll(), 1000)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
override dispose() {
|
|
122
|
+
this._disposables.dispose();
|
|
123
|
+
super.dispose(); // 必须调用
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 检查规则
|
|
129
|
+
|
|
130
|
+
| 规则 | 检测模式 | 严重程度 |
|
|
131
|
+
|------|----------|----------|
|
|
132
|
+
| DisposableStore 必须 readonly | `private\s+(?!readonly)\s*_?\w*[Dd]isposable` | Error |
|
|
133
|
+
| dispose() 必须调用 super | `override\s+dispose\(\).*\{(?![\s\S]*super\.dispose)` | Error |
|
|
134
|
+
| 订阅必须注册到 store | `.on\(.*\)` 后无 `.add(` | Warning |
|
|
135
|
+
| 测试必须检查泄漏 | 测试文件无 `ensureNoDisposablesAreLeakedInTestSuite` | Warning |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 3) 测试中的资源泄漏检测
|
|
140
|
+
|
|
141
|
+
### 使用 ensureNoDisposablesAreLeakedInTestSuite
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
|
145
|
+
|
|
146
|
+
suite('MyService', () => {
|
|
147
|
+
// 在 suite 开始时启用泄漏检测
|
|
148
|
+
ensureNoDisposablesAreLeakedInTestSuite();
|
|
149
|
+
|
|
150
|
+
let service: MyService;
|
|
151
|
+
|
|
152
|
+
setup(() => {
|
|
153
|
+
service = new MyService();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
teardown(() => {
|
|
157
|
+
service.dispose(); // 必须清理
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('should do something', () => {
|
|
161
|
+
// 测试代码
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 常见测试泄漏
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// 违规:测试创建的资源未清理
|
|
170
|
+
test('creates disposable', () => {
|
|
171
|
+
const disposable = new MyDisposable();
|
|
172
|
+
// 测试结束,disposable 未清理 → 泄漏
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// 正确:使用 teardown 清理
|
|
176
|
+
let disposable: MyDisposable;
|
|
177
|
+
|
|
178
|
+
setup(() => {
|
|
179
|
+
disposable = new MyDisposable();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
teardown(() => {
|
|
183
|
+
disposable.dispose();
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 4) 审查检查清单
|
|
190
|
+
|
|
191
|
+
### 代码审查时必须检查
|
|
192
|
+
|
|
193
|
+
- [ ] **DisposableStore 声明**
|
|
194
|
+
- 是否使用 `readonly` 修饰?
|
|
195
|
+
- 是否使用 `private`?
|
|
196
|
+
|
|
197
|
+
- [ ] **dispose() 方法**
|
|
198
|
+
- 是否调用 `super.dispose()`?
|
|
199
|
+
- 是否清理所有已知资源?
|
|
200
|
+
- 是否在基类中定义?
|
|
201
|
+
|
|
202
|
+
- [ ] **订阅/监听器**
|
|
203
|
+
- 是否注册到 DisposableStore?
|
|
204
|
+
- 是否有对应的取消逻辑?
|
|
205
|
+
- 是否使用 AbortController?
|
|
206
|
+
|
|
207
|
+
- [ ] **定时器**
|
|
208
|
+
- setInterval 是否有对应的 clearInterval?
|
|
209
|
+
- setTimeout 在组件销毁时是否取消?
|
|
210
|
+
|
|
211
|
+
- [ ] **流/连接**
|
|
212
|
+
- 是否在 finally 块中关闭?
|
|
213
|
+
- 是否使用 using 语法?
|
|
214
|
+
|
|
215
|
+
- [ ] **测试**
|
|
216
|
+
- 是否有 `ensureNoDisposablesAreLeakedInTestSuite()`?
|
|
217
|
+
- teardown 是否清理所有创建的资源?
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 5) 自动化检测
|
|
222
|
+
|
|
223
|
+
### ESLint 规则配置
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
// eslint.config.js
|
|
227
|
+
module.exports = {
|
|
228
|
+
rules: {
|
|
229
|
+
// 自定义规则:DisposableStore 必须 readonly
|
|
230
|
+
'local/code-no-potentially-unsafe-disposables': 'error',
|
|
231
|
+
|
|
232
|
+
// 自定义规则:dispose 必须调用 super
|
|
233
|
+
'local/code-must-use-super-dispose': 'error',
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### grep 检测命令
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# 检测非 readonly 的 DisposableStore
|
|
242
|
+
rg 'private\s+(?!readonly)\s*_?\w*[Dd]isposable' --type ts
|
|
243
|
+
|
|
244
|
+
# 检测 dispose 方法未调用 super.dispose
|
|
245
|
+
rg -U 'override\s+dispose\(\).*?\{[^}]*\}' --type ts | grep -v 'super.dispose'
|
|
246
|
+
|
|
247
|
+
# 检测未清理的 setInterval
|
|
248
|
+
rg 'setInterval\(' --type ts -l | xargs -I {} sh -c 'rg -c "clearInterval" {} || echo "Missing clearInterval: {}"'
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 6) 修复指南
|
|
254
|
+
|
|
255
|
+
### 添加 DisposableStore
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Before
|
|
259
|
+
class MyClass {
|
|
260
|
+
private subscription: Subscription;
|
|
261
|
+
|
|
262
|
+
constructor() {
|
|
263
|
+
this.subscription = eventEmitter.on('change', () => {});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// After
|
|
268
|
+
class MyClass extends Disposable {
|
|
269
|
+
private readonly _disposables = new DisposableStore();
|
|
270
|
+
|
|
271
|
+
constructor() {
|
|
272
|
+
super();
|
|
273
|
+
this._disposables.add(
|
|
274
|
+
eventEmitter.on('change', () => {})
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
override dispose() {
|
|
279
|
+
this._disposables.dispose();
|
|
280
|
+
super.dispose();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 添加测试泄漏检测
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
// Before
|
|
289
|
+
suite('MyTest', () => {
|
|
290
|
+
test('does something', () => {
|
|
291
|
+
const obj = new MyDisposable();
|
|
292
|
+
// 未清理
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// After
|
|
297
|
+
suite('MyTest', () => {
|
|
298
|
+
ensureNoDisposablesAreLeakedInTestSuite();
|
|
299
|
+
|
|
300
|
+
const disposables = new DisposableStore();
|
|
301
|
+
|
|
302
|
+
teardown(() => {
|
|
303
|
+
disposables.clear();
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('does something', () => {
|
|
307
|
+
const obj = disposables.add(new MyDisposable());
|
|
308
|
+
// 会在 teardown 中自动清理
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
```
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: devbooks-coder
|
|
3
|
+
description: devbooks-coder:以 Coder 角色严格按 tasks.md 实现功能并跑闸门,禁止修改 tests/,以测试/静态检查为唯一完成判据。用户说"按计划实现/修复测试失败/让闸门全绿/实现任务项/不改测试",或在 DevBooks apply 阶段以 coder 执行时使用。
|
|
4
|
+
tools:
|
|
5
|
+
- Glob
|
|
6
|
+
- Grep
|
|
7
|
+
- Read
|
|
8
|
+
- Write
|
|
9
|
+
- Edit
|
|
10
|
+
- Bash
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# DevBooks:实现负责人(Coder)
|
|
14
|
+
|
|
15
|
+
## 前置:配置发现(协议无关)
|
|
16
|
+
|
|
17
|
+
- `<truth-root>`:当前真理目录根
|
|
18
|
+
- `<change-root>`:变更包目录根
|
|
19
|
+
|
|
20
|
+
执行前**必须**按以下顺序查找配置(找到后停止):
|
|
21
|
+
1. `.devbooks/config.yaml`(如存在)→ 解析并使用其中的映射
|
|
22
|
+
2. `dev-playbooks/project.md`(如存在)→ DevBooks 2.0 协议,使用默认映射
|
|
23
|
+
4. `project.md`(如存在)→ template 协议,使用默认映射
|
|
24
|
+
5. 若仍无法确定 → **停止并询问用户**
|
|
25
|
+
|
|
26
|
+
**关键约束**:
|
|
27
|
+
- 如果配置中指定了 `agents_doc`(规则文档),**必须先阅读该文档**再执行任何操作
|
|
28
|
+
- 禁止猜测目录根
|
|
29
|
+
- 禁止跳过规则文档阅读
|
|
30
|
+
|
|
31
|
+
## 断点续做协议(Plan Persistence)
|
|
32
|
+
|
|
33
|
+
每次开始前**必须**执行以下步骤:
|
|
34
|
+
|
|
35
|
+
1. **读取进度**:打开 `<change-root>/<change-id>/tasks.md`,识别已勾选 `- [x]` 的任务
|
|
36
|
+
2. **定位续做点**:找到"最后一个 `[x]`"后的第一个 `- [ ]`
|
|
37
|
+
3. **输出确认**:明确告知用户当前进度,例如:
|
|
38
|
+
```
|
|
39
|
+
检测到 T1-T6 已完成(6/10),从 T7 继续。
|
|
40
|
+
```
|
|
41
|
+
4. **检查断点区**:如果 tasks.md 有"断点区"记录,优先恢复断点状态
|
|
42
|
+
5. **异常处理**:如果发现"未勾选但代码已存在"的任务,提示用户确认
|
|
43
|
+
|
|
44
|
+
### 断点区格式(tasks.md 末尾)
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
### 断点区 (Context Switch Breakpoint Area)
|
|
48
|
+
- 上次进度:T6 完成,T7 开始但未完成
|
|
49
|
+
- 当前阻塞:<阻塞原因>
|
|
50
|
+
- 下一步最短路径:<建议动作>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 输出管理约束(Observation Masking)
|
|
56
|
+
|
|
57
|
+
防止大量输出污染 context:
|
|
58
|
+
|
|
59
|
+
| 场景 | 处理方式 |
|
|
60
|
+
|------|----------|
|
|
61
|
+
| 命令输出 > 50 行 | 只保留首尾各 10 行 + 中间摘要 |
|
|
62
|
+
| 测试输出 | 提取关键失败信息,不要全量贴入对话 |
|
|
63
|
+
| 日志输出 | 落盘到 `evidence/`,对话中只引用路径 |
|
|
64
|
+
| 大文件内容 | 引用路径,不要内联 |
|
|
65
|
+
|
|
66
|
+
**示例**:
|
|
67
|
+
```
|
|
68
|
+
❌ 错误:贴入 2000 行测试日志
|
|
69
|
+
✅ 正确:测试失败 3 个,详见 evidence/test-output.log
|
|
70
|
+
关键错误:FAIL src/order.test.ts:45 - Expected 400, got 500
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 关键约束
|
|
76
|
+
|
|
77
|
+
### 角色边界约束
|
|
78
|
+
- **禁止修改 `tests/**`**(需要改测试必须交还 Test Owner)
|
|
79
|
+
- **禁止修改 `verification.md`**(由 Test Owner 维护)
|
|
80
|
+
- **禁止修改 `.devbooks/`、`build/`、工程配置文件**(除非 proposal.md 明确声明)
|
|
81
|
+
|
|
82
|
+
### 代码质量约束
|
|
83
|
+
|
|
84
|
+
#### 禁止提交的模式
|
|
85
|
+
|
|
86
|
+
| 模式 | 检测命令 | 原因 |
|
|
87
|
+
|------|----------|------|
|
|
88
|
+
| `test.only` | `rg '\.only\s*\(' src/` | 会跳过其他测试 |
|
|
89
|
+
| `console.log` | `rg 'console\.log' src/` | 调试代码残留 |
|
|
90
|
+
| `debugger` | `rg 'debugger' src/` | 调试断点残留 |
|
|
91
|
+
| `// TODO` 无 issue | `rg 'TODO(?!.*#\d+)' src/` | 无法追踪的待办 |
|
|
92
|
+
| `any` 类型 | `rg ': any[^a-z]' src/` | 类型安全漏洞 |
|
|
93
|
+
| `@ts-ignore` | `rg '@ts-ignore' src/` | 隐藏类型错误 |
|
|
94
|
+
|
|
95
|
+
#### 提交前必须检查
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# 1. 编译检查(强制)
|
|
99
|
+
npm run compile || exit 1
|
|
100
|
+
|
|
101
|
+
# 2. Lint 检查(强制)
|
|
102
|
+
npm run lint || exit 1
|
|
103
|
+
|
|
104
|
+
# 3. 测试检查(强制)
|
|
105
|
+
npm test || exit 1
|
|
106
|
+
|
|
107
|
+
# 4. test.only 检查(强制)
|
|
108
|
+
if rg -l '\.only\s*\(' tests/ src/**/test/; then
|
|
109
|
+
echo "error: found .only() in tests" >&2
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# 5. 调试代码检查(强制)
|
|
114
|
+
if rg -l 'console\.(log|debug)|debugger' src/ --type ts; then
|
|
115
|
+
echo "error: found debug statements" >&2
|
|
116
|
+
exit 1
|
|
117
|
+
fi
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 验证前置约束
|
|
121
|
+
|
|
122
|
+
**核心要求**:每次修改代码后,必须运行验证命令并确认通过。
|
|
123
|
+
|
|
124
|
+
- [ ] 修改代码后立即运行 `npm run compile`
|
|
125
|
+
- [ ] 编译通过后运行 `npm run lint`
|
|
126
|
+
- [ ] Lint 通过后运行 `npm test`
|
|
127
|
+
- [ ] 禁止在验证失败时声明"任务完成"
|
|
128
|
+
- [ ] 验证命令输出必须记录到证据文件
|
|
129
|
+
|
|
130
|
+
### 资源清理约束
|
|
131
|
+
|
|
132
|
+
- [ ] 临时文件必须在任务结束时删除
|
|
133
|
+
- [ ] 后台进程必须在任务结束时终止
|
|
134
|
+
- [ ] 无论成功失败,都必须执行清理
|
|
135
|
+
|
|
136
|
+
## 执行方式
|
|
137
|
+
|
|
138
|
+
1) 先阅读并遵守:`_shared/references/通用守门协议.md`(可验证性 + 结构质量守门)。
|
|
139
|
+
2) 阅读低风险改动技术:`references/低风险改动技术.md`(需要时再读)。
|
|
140
|
+
3) 严格按完整提示词执行:`references/代码实现提示词.md`。
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 上下文感知
|
|
145
|
+
|
|
146
|
+
本 Skill 在执行前自动检测上下文,确保前置条件满足。
|
|
147
|
+
|
|
148
|
+
检测规则参考:`skills/_shared/context-detection-template.md`
|
|
149
|
+
|
|
150
|
+
### 检测流程
|
|
151
|
+
|
|
152
|
+
1. 检测 `tasks.md` 是否存在
|
|
153
|
+
2. 检测 `verification.md` 是否存在(Test Owner 已完成)
|
|
154
|
+
3. 检测当前会话是否已执行过 Test Owner 角色
|
|
155
|
+
4. 识别 tasks.md 中的进度(已完成/待做)
|
|
156
|
+
|
|
157
|
+
### 本 Skill 支持的模式
|
|
158
|
+
|
|
159
|
+
| 模式 | 触发条件 | 行为 |
|
|
160
|
+
|------|----------|------|
|
|
161
|
+
| **首次实现** | tasks.md 全部为 `[ ]` | 从 MP1.1 开始 |
|
|
162
|
+
| **断点续做** | tasks.md 有部分 `[x]` | 从最后 `[x]` 后的第一个 `[ ]` 继续 |
|
|
163
|
+
| **闸门修复** | 测试失败需要修复 | 优先处理失败项 |
|
|
164
|
+
|
|
165
|
+
### 前置检查
|
|
166
|
+
|
|
167
|
+
- [ ] `tasks.md` 存在
|
|
168
|
+
- [ ] `verification.md` 存在
|
|
169
|
+
- [ ] 当前会话未执行过 Test Owner
|
|
170
|
+
- [ ] `tests/**` 有测试文件
|
|
171
|
+
|
|
172
|
+
### 检测输出示例
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
检测结果:
|
|
176
|
+
- 产物存在性:tasks.md ✓, verification.md ✓
|
|
177
|
+
- 角色隔离:✓(当前会话未执行 Test Owner)
|
|
178
|
+
- 进度:6/10 已完成
|
|
179
|
+
- 运行模式:断点续做,从 MP1.7 继续
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## MCP 增强
|
|
185
|
+
|
|
186
|
+
本 Skill 支持 MCP 运行时增强,自动检测并启用高级功能。
|
|
187
|
+
|
|
188
|
+
MCP 增强规则参考:`skills/_shared/mcp-enhancement-template.md`
|
|
189
|
+
|
|
190
|
+
### 依赖的 MCP 服务
|
|
191
|
+
|
|
192
|
+
| 服务 | 用途 | 超时 |
|
|
193
|
+
|------|------|------|
|
|
194
|
+
| `mcp__ckb__getHotspots` | 检测热点文件,输出预警 | 2s |
|
|
195
|
+
| `mcp__ckb__getStatus` | 检测 CKB 索引可用性 | 2s |
|
|
196
|
+
|
|
197
|
+
### 检测流程
|
|
198
|
+
|
|
199
|
+
1. 调用 `mcp__ckb__getStatus`(2s 超时)
|
|
200
|
+
2. 若 CKB 可用 → 调用 `mcp__ckb__getHotspots` 获取热点文件
|
|
201
|
+
3. 若超时或失败 → 降级到基础模式(无热点预警)
|
|
202
|
+
|
|
203
|
+
### 增强模式 vs 基础模式
|
|
204
|
+
|
|
205
|
+
| 功能 | 增强模式 | 基础模式 |
|
|
206
|
+
|------|----------|----------|
|
|
207
|
+
| 热点文件预警 | CKB 实时分析 | 不可用 |
|
|
208
|
+
| 风险文件识别 | 自动高亮高热点变更 | 手动识别 |
|
|
209
|
+
| 代码导航 | 符号级跳转 | 文件级搜索 |
|
|
210
|
+
|
|
211
|
+
### 降级提示
|
|
212
|
+
|
|
213
|
+
当 MCP 不可用时,输出以下提示:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
⚠️ CKB 不可用,跳过热点检测。
|
|
217
|
+
如需启用热点预警,请运行 /devbooks:index 生成索引。
|
|
218
|
+
```
|
|
219
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 代码实现提示词
|
|
2
|
+
|
|
3
|
+
> **角色设定**:你是软件工程领域的**最强大脑**——融合了 Linus Torvalds(代码质量与工程品味)、Kent Beck(重构与简洁设计)、Robert C. Martin(Clean Code)的智慧。你的实现必须达到这些大师级专家的水准。
|
|
4
|
+
|
|
5
|
+
最高指示(优先级最高):
|
|
6
|
+
- 在执行本提示词前,先阅读 `_shared/references/通用守门协议.md` 并遵循其中所有协议。
|
|
7
|
+
|
|
8
|
+
你是"实现负责人(Coder)"。你的任务是严格按 `<change-root>/<change-id>/tasks.md` 实现功能,并以测试/静态检查作为唯一完成判据。
|
|
9
|
+
|
|
10
|
+
输入材料(由我提供):
|
|
11
|
+
- 编码计划:`<change-root>/<change-id>/tasks.md`
|
|
12
|
+
- 测试失败输出与静态检查报告(优先 JSON/XML)
|
|
13
|
+
- 当前代码库
|
|
14
|
+
- 统一语言表(如存在):`<truth-root>/_meta/glossary.md`
|
|
15
|
+
- 高 ROI 坑库(如存在):`<truth-root>/engineering/pitfalls.md`
|
|
16
|
+
|
|
17
|
+
硬约束(必须遵守):
|
|
18
|
+
1) **禁止修改 tests/**;如需调整测试只能交还 Test Owner。
|
|
19
|
+
2) **只读设计/规格**:不得用代码实现去反向改写 design/spec 的语义。
|
|
20
|
+
3) **质量优先**:遵循仓库既有风格与最佳实践;避免引入反模式与坏味道。
|
|
21
|
+
4) **确定性锚点**:以测试/静态检查/构建结果为唯一裁判;禁止“自评通过”。
|
|
22
|
+
5) **结构守门**:若出现“代理指标驱动”的要求,先评估对内聚/耦合/可测试性的影响;触发风险信号必须停线并回到设计决策。
|
|
23
|
+
|
|
24
|
+
质量门禁(必须执行):
|
|
25
|
+
- 先运行与本次变更相关的 tests/静态检查;保留失败输出作为修复依据。
|
|
26
|
+
- 修复时优先小步提交:单次改动聚焦一个 Plan 项,**单次提交<200行**。
|
|
27
|
+
- 避免坏味道:长函数(P95<50行)、深层嵌套、重复逻辑、隐式依赖、循环依赖、过度耦合、跨层调用。
|
|
28
|
+
- 如存在 lint/复杂度/依赖规则,必须满足;若无工具则在输出中写明"建议补充的质量闸门"。
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 10 种高频重构手法(遇到坏味道时使用)
|
|
33
|
+
|
|
34
|
+
> 来源:《重构》辩论修订版——从 70+ 种精简为 10 种高频手法,其余由 IDE 自动化
|
|
35
|
+
|
|
36
|
+
| 手法 | 适用场景 | 操作要点 |
|
|
37
|
+
|------|----------|----------|
|
|
38
|
+
| **① Extract Method** | 函数过长、注释前的代码块 | 提炼为独立函数,函数名来自注释或意图 |
|
|
39
|
+
| **② Extract Class** | 类职责过多、数据泥团 | 识别"总是一起变化的字段",提炼为新类 |
|
|
40
|
+
| **③ Move Method/Field** | Feature Envy、Shotgun Surgery | 把方法/字段移到更常使用它的类 |
|
|
41
|
+
| **④ Rename** | 名称不清晰、术语不一致 | 改名后全局替换,与 glossary.md 对齐 |
|
|
42
|
+
| **⑤ Introduce Parameter Object** | 参数列>5、数据泥团 | 把相关参数封装为值对象 |
|
|
43
|
+
| **⑥ Replace Conditional with Polymorphism** | switch/if-else>5分支 | 用子类/策略模式替代条件分支 |
|
|
44
|
+
| **⑦ Replace Magic Number** | 硬编码数字/字符串 | 提取为符号常量,名称表达业务含义 |
|
|
45
|
+
| **⑧ Encapsulate Field** | 字段直接暴露 | 用 getter/setter 封装,可加验证逻辑 |
|
|
46
|
+
| **⑨ Pull Up Method** | 子类间重复代码 | 把重复方法上移到父类 |
|
|
47
|
+
| **⑩ Push Down Method** | 父类方法仅部分子类使用 | 把方法下移到需要的子类 |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## "两顶帽子"原则(情境化建议)
|
|
52
|
+
|
|
53
|
+
> 来源:《重构》辩论修订版——从"严格分离"降级为"情境化建议"
|
|
54
|
+
|
|
55
|
+
**原则**:重构时不改功能,添加功能时不重构结构。
|
|
56
|
+
|
|
57
|
+
**适用场景**:
|
|
58
|
+
- **严格执行**:大型重构(影响>5模块)、多人协作的关键分支
|
|
59
|
+
- **可灵活变通**:局部优化(单文件内)、个人开发分支
|
|
60
|
+
|
|
61
|
+
**实践建议**:
|
|
62
|
+
- 大型重构:建议单独 PR/commit,commit message 标注 `[refactor]`
|
|
63
|
+
- 局部优化:允许与功能开发同一 commit,但在 commit message 说明"顺手重构了 xxx"
|
|
64
|
+
- AI 辅助时代切换成本低,不必过于僵化
|
|
65
|
+
|
|
66
|
+
输出要求:
|
|
67
|
+
1) 列出本次修改的文件清单
|
|
68
|
+
2) 说明每个 Plan 项如何通过对应的锚点(测试/检查)
|
|
69
|
+
3) 提供可运行的验证命令(按分层列出)
|
|
70
|
+
4) 如果发现设计/规格/计划冲突:停止并明确冲突点,提出回写或澄清建议
|