dev-playbooks 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.
Files changed (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/bin/devbooks.js +986 -0
  4. package/package.json +41 -0
  5. package/skills/Skill-Development-Guide.md +249 -0
  6. package/skills/Skills-Usage-Guide.md +447 -0
  7. package/skills/_shared/context-detection-template.md +315 -0
  8. package/skills/_shared/mcp-enhancement-template.md +144 -0
  9. package/skills/_shared/references/universal-gating-protocol.md +114 -0
  10. package/skills/_template/config-discovery-template.md +126 -0
  11. package/skills/devbooks-brownfield-bootstrap/SKILL.md +168 -0
  12. package/skills/devbooks-brownfield-bootstrap/references/10-glossary-template.md +42 -0
  13. package/skills/devbooks-brownfield-bootstrap/references/brownfield-bootstrap-prompt.md +115 -0
  14. package/skills/devbooks-brownfield-bootstrap/references/brownfield-bootstrap.md +96 -0
  15. package/skills/devbooks-brownfield-bootstrap/references/code-navigation-strategy.md +203 -0
  16. package/skills/devbooks-brownfield-bootstrap/scripts/cod-update.sh +357 -0
  17. package/skills/devbooks-brownfield-bootstrap/templates/project-profile-template.md +172 -0
  18. package/skills/devbooks-c4-map/SKILL.md +151 -0
  19. package/skills/devbooks-c4-map/references/c4-architecture-map-prompt.md +33 -0
  20. package/skills/devbooks-c4-map/references/layered-constraint-checklist.md +185 -0
  21. package/skills/devbooks-code-review/SKILL.md +175 -0
  22. package/skills/devbooks-code-review/references/code-review-prompt.md +100 -0
  23. package/skills/devbooks-code-review/references/code-smell-cheatsheet.md +498 -0
  24. package/skills/devbooks-code-review/references/pr-template-and-guidelines.md +321 -0
  25. package/skills/devbooks-code-review/references/resource-management-review-checklist.md +311 -0
  26. package/skills/devbooks-coder/SKILL.md +219 -0
  27. package/skills/devbooks-coder/references/code-implementation-prompt.md +74 -0
  28. package/skills/devbooks-coder/references/coding-style-guidelines.md +351 -0
  29. package/skills/devbooks-coder/references/error-code-standard.md +463 -0
  30. package/skills/devbooks-coder/references/logging-standard.md +329 -0
  31. package/skills/devbooks-coder/references/low-risk-modification-techniques.md +275 -0
  32. package/skills/devbooks-delivery-workflow/SKILL.md +217 -0
  33. package/skills/devbooks-delivery-workflow/references/9-change-verification-traceability-template.md +133 -0
  34. package/skills/devbooks-delivery-workflow/references/delivery-acceptance-workflow.md +177 -0
  35. package/skills/devbooks-delivery-workflow/references/prototype-production-dual-track.md +169 -0
  36. package/skills/devbooks-delivery-workflow/scripts/ac-trace-check.sh +330 -0
  37. package/skills/devbooks-delivery-workflow/scripts/audit-scope.sh +262 -0
  38. package/skills/devbooks-delivery-workflow/scripts/change-check.sh +1039 -0
  39. package/skills/devbooks-delivery-workflow/scripts/change-codemod-scaffold.sh +135 -0
  40. package/skills/devbooks-delivery-workflow/scripts/change-evidence.sh +152 -0
  41. package/skills/devbooks-delivery-workflow/scripts/change-scaffold.sh +467 -0
  42. package/skills/devbooks-delivery-workflow/scripts/change-spec-delta-scaffold.sh +135 -0
  43. package/skills/devbooks-delivery-workflow/scripts/constitution-check.sh +237 -0
  44. package/skills/devbooks-delivery-workflow/scripts/env-match-check.sh +128 -0
  45. package/skills/devbooks-delivery-workflow/scripts/fitness-check.sh +365 -0
  46. package/skills/devbooks-delivery-workflow/scripts/guardrail-check.sh +516 -0
  47. package/skills/devbooks-delivery-workflow/scripts/handoff-check.sh +141 -0
  48. package/skills/devbooks-delivery-workflow/scripts/hygiene-check.sh +340 -0
  49. package/skills/devbooks-delivery-workflow/scripts/migrate-from-openspec.sh +385 -0
  50. package/skills/devbooks-delivery-workflow/scripts/migrate-to-v2-gates.sh +202 -0
  51. package/skills/devbooks-delivery-workflow/scripts/progress-dashboard.sh +319 -0
  52. package/skills/devbooks-delivery-workflow/scripts/prototype-promote.sh +341 -0
  53. package/skills/devbooks-delivery-workflow/scripts/spec-preview.sh +203 -0
  54. package/skills/devbooks-delivery-workflow/scripts/spec-promote.sh +118 -0
  55. package/skills/devbooks-delivery-workflow/scripts/spec-rollback.sh +124 -0
  56. package/skills/devbooks-delivery-workflow/scripts/spec-stage.sh +117 -0
  57. package/skills/devbooks-delivery-workflow/scripts/verify-all.sh +78 -0
  58. package/skills/devbooks-delivery-workflow/scripts/verify-npm-package.sh +123 -0
  59. package/skills/devbooks-delivery-workflow/scripts/verify-openspec-free.sh +81 -0
  60. package/skills/devbooks-delivery-workflow/scripts/verify-slash-commands.sh +146 -0
  61. package/skills/devbooks-delivery-workflow/templates/handoff.md +50 -0
  62. package/skills/devbooks-design-backport/SKILL.md +73 -0
  63. package/skills/devbooks-design-backport/references/design-backport-prompt.md +132 -0
  64. package/skills/devbooks-design-doc/SKILL.md +121 -0
  65. package/skills/devbooks-design-doc/references/design-doc-prompt.md +188 -0
  66. package/skills/devbooks-design-doc/references/microservice-design-checklist.md +149 -0
  67. package/skills/devbooks-design-doc/references/privacy-compliance-checklist.md +240 -0
  68. package/skills/devbooks-entropy-monitor/SKILL.md +188 -0
  69. package/skills/devbooks-entropy-monitor/references/entropy-metrics-methodology.md +218 -0
  70. package/skills/devbooks-entropy-monitor/scripts/entropy-measure.sh +449 -0
  71. package/skills/devbooks-entropy-monitor/scripts/entropy-report.sh +303 -0
  72. package/skills/devbooks-entropy-monitor/templates/thresholds.json +99 -0
  73. package/skills/devbooks-federation/SKILL.md +264 -0
  74. package/skills/devbooks-federation/scripts/federation-check.sh +144 -0
  75. package/skills/devbooks-federation/templates/federation.yaml +89 -0
  76. package/skills/devbooks-impact-analysis/SKILL.md +135 -0
  77. package/skills/devbooks-impact-analysis/references/impact-analysis-prompt.md +82 -0
  78. package/skills/devbooks-impact-analysis/scripts/graph-cache.sh +214 -0
  79. package/skills/devbooks-implementation-plan/SKILL.md +83 -0
  80. package/skills/devbooks-implementation-plan/references/implementation-plan-prompt.md +95 -0
  81. package/skills/devbooks-index-bootstrap/SKILL.md +240 -0
  82. package/skills/devbooks-proposal-author/SKILL.md +83 -0
  83. package/skills/devbooks-proposal-author/references/proposal-authoring-prompt.md +66 -0
  84. package/skills/devbooks-proposal-challenger/SKILL.md +86 -0
  85. package/skills/devbooks-proposal-challenger/references/ethics-and-compliance-checklist.md +176 -0
  86. package/skills/devbooks-proposal-challenger/references/proposal-challenge-prompt.md +57 -0
  87. package/skills/devbooks-proposal-debate-workflow/SKILL.md +78 -0
  88. package/skills/devbooks-proposal-debate-workflow/references/11-proposal-debate-template.md +35 -0
  89. package/skills/devbooks-proposal-debate-workflow/references/proposal-debate-workflow.md +24 -0
  90. package/skills/devbooks-proposal-debate-workflow/scripts/proposal-debate-check.sh +102 -0
  91. package/skills/devbooks-proposal-judge/SKILL.md +78 -0
  92. package/skills/devbooks-proposal-judge/references/proposal-judge-prompt.md +37 -0
  93. package/skills/devbooks-router/SKILL.md +346 -0
  94. package/skills/devbooks-spec-contract/SKILL.md +191 -0
  95. package/skills/devbooks-spec-contract/references/api-design-guide.md +349 -0
  96. package/skills/devbooks-spec-contract/references/contract-and-data-definition-prompt.md +85 -0
  97. package/skills/devbooks-spec-contract/references/implicit-change-detection-prompt.md +183 -0
  98. package/skills/devbooks-spec-contract/references/spec-change-prompt.md +63 -0
  99. package/skills/devbooks-spec-contract/scripts/implicit-change-detect.sh +378 -0
  100. package/skills/devbooks-spec-gardener/SKILL.md +73 -0
  101. package/skills/devbooks-spec-gardener/references/spec-gardener-prompt.md +41 -0
  102. package/skills/devbooks-test-owner/SKILL.md +173 -0
  103. package/skills/devbooks-test-owner/references/9-change-verification-traceability-template.md +133 -0
  104. package/skills/devbooks-test-owner/references/async-system-test-strategy.md +316 -0
  105. package/skills/devbooks-test-owner/references/decoupling-techniques-cheatsheet.md +269 -0
  106. package/skills/devbooks-test-owner/references/test-code-prompt.md +171 -0
  107. package/skills/devbooks-test-owner/references/test-driven-development.md +351 -0
  108. package/skills/devbooks-test-owner/references/test-layering-strategy.md +281 -0
  109. package/skills/devbooks-test-reviewer/SKILL.md +189 -0
  110. package/templates/.devbooks/config.yaml +88 -0
  111. package/templates/claude-commands/devbooks/apply.md +38 -0
  112. package/templates/claude-commands/devbooks/archive.md +33 -0
  113. package/templates/claude-commands/devbooks/backport.md +19 -0
  114. package/templates/claude-commands/devbooks/bootstrap.md +20 -0
  115. package/templates/claude-commands/devbooks/c4.md +20 -0
  116. package/templates/claude-commands/devbooks/challenger.md +19 -0
  117. package/templates/claude-commands/devbooks/code.md +20 -0
  118. package/templates/claude-commands/devbooks/debate.md +20 -0
  119. package/templates/claude-commands/devbooks/delivery.md +20 -0
  120. package/templates/claude-commands/devbooks/design.md +20 -0
  121. package/templates/claude-commands/devbooks/entropy.md +19 -0
  122. package/templates/claude-commands/devbooks/federation.md +19 -0
  123. package/templates/claude-commands/devbooks/gardener.md +19 -0
  124. package/templates/claude-commands/devbooks/impact.md +19 -0
  125. package/templates/claude-commands/devbooks/index.md +19 -0
  126. package/templates/claude-commands/devbooks/judge.md +19 -0
  127. package/templates/claude-commands/devbooks/plan.md +20 -0
  128. package/templates/claude-commands/devbooks/proposal.md +20 -0
  129. package/templates/claude-commands/devbooks/quick.md +43 -0
  130. package/templates/claude-commands/devbooks/review.md +20 -0
  131. package/templates/claude-commands/devbooks/router.md +19 -0
  132. package/templates/claude-commands/devbooks/spec.md +20 -0
  133. package/templates/claude-commands/devbooks/test-review.md +19 -0
  134. package/templates/claude-commands/devbooks/test.md +20 -0
  135. package/templates/dev-playbooks/changes/.gitkeep +1 -0
  136. package/templates/dev-playbooks/constitution.md +116 -0
  137. package/templates/dev-playbooks/project.md +96 -0
  138. package/templates/dev-playbooks/scripts/.gitkeep +1 -0
  139. package/templates/dev-playbooks/specs/_meta/anti-patterns/.gitkeep +2 -0
  140. package/templates/dev-playbooks/specs/_meta/glossary.md +48 -0
  141. package/templates/dev-playbooks/specs/_meta/project-profile.md +79 -0
  142. package/templates/dev-playbooks/specs/architecture/fitness-rules.md +95 -0
@@ -0,0 +1,321 @@
1
+ # Pull Request Template and Guidelines
2
+
3
+ Inspired by VS Code’s `.github/pull_request_template.md`, this document defines a standard PR workflow.
4
+
5
+ ---
6
+
7
+ ## 1) PR template
8
+
9
+ ```markdown
10
+ ## Summary
11
+
12
+ <!-- Describe what this PR does in 1–3 sentences -->
13
+
14
+ ## Related Issues
15
+
16
+ <!-- Link issues using Fixes #123 or Relates to #456 -->
17
+
18
+ ## Changes
19
+
20
+ <!-- List the key changes -->
21
+
22
+ - [ ] Change 1
23
+ - [ ] Change 2
24
+ - [ ] Change 3
25
+
26
+ ## Type of Change
27
+
28
+ <!-- Select one -->
29
+
30
+ - [ ] Bug fix (non-breaking change which fixes an issue)
31
+ - [ ] New feature (non-breaking change which adds functionality)
32
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
33
+ - [ ] Documentation update
34
+ - [ ] Refactoring (no functional changes)
35
+
36
+ ## Test Plan
37
+
38
+ <!-- Describe how to test this change -->
39
+
40
+ 1. Step 1
41
+ 2. Step 2
42
+ 3. Expected result
43
+
44
+ ## Checklist
45
+
46
+ <!-- Confirm the following -->
47
+
48
+ - [ ] Code follows project conventions
49
+ - [ ] Relevant tests added/updated
50
+ - [ ] All tests pass (`npm test`)
51
+ - [ ] Relevant docs updated
52
+ - [ ] Commit messages follow Conventional Commits
53
+ - [ ] Self-reviewed; no debug statements left behind
54
+
55
+ ## Screenshots (if applicable)
56
+
57
+ <!-- If this includes UI changes, attach screenshots -->
58
+ ```
59
+
60
+ ---
61
+
62
+ ## 2) PR types and size
63
+
64
+ ### Type definitions
65
+
66
+ | Type | Prefix | Description |
67
+ |------|--------|-------------|
68
+ | Bug fix | `fix:` | Fixes issues in existing functionality |
69
+ | Feature | `feat:` | Adds new functionality |
70
+ | Refactor | `refactor:` | Code improvements without behavioral changes |
71
+ | Docs | `docs:` | Documentation-only changes |
72
+ | Test | `test:` | Adds or modifies tests |
73
+ | Build | `build:` | Build system or dependency changes |
74
+ | Performance | `perf:` | Performance optimizations |
75
+
76
+ ### Size guidance
77
+
78
+ | Size | Lines changed | Review time | Recommendation |
79
+ |------|--------------:|------------|----------------|
80
+ | XS | < 50 | ~15 minutes | Quick merge |
81
+ | S | 50–200 | ~30 minutes | Standard review |
82
+ | M | 200–500 | ~1 hour | Careful review |
83
+ | L | 500–1000 | 2+ hours | Consider splitting |
84
+ | XL | > 1000 | half day+ | **Must split** |
85
+
86
+ Principle: one PR does one thing; keep it atomic.
87
+
88
+ ---
89
+
90
+ ## 3) Commit conventions
91
+
92
+ ### Conventional Commits format
93
+
94
+ ```
95
+ <type>(<scope>): <subject>
96
+
97
+ <body>
98
+
99
+ <footer>
100
+ ```
101
+
102
+ ### Examples
103
+
104
+ ```
105
+ feat(auth): add OAuth2 login support
106
+
107
+ - Add OAuth2 provider configuration
108
+ - Implement token refresh mechanism
109
+ - Add logout cleanup logic
110
+
111
+ Closes #123
112
+ ```
113
+
114
+ ```
115
+ fix(api): handle null response from external service
116
+
117
+ The external API sometimes returns null instead of an empty array.
118
+ Added defensive check to prevent runtime errors.
119
+
120
+ Fixes #456
121
+ ```
122
+
123
+ ### Common types
124
+
125
+ | Type | Meaning | Example |
126
+ |------|---------|---------|
127
+ | `feat` | Feature | `feat(user): add profile edit` |
128
+ | `fix` | Bug fix | `fix(auth): correct token expiry` |
129
+ | `docs` | Docs | `docs(readme): update install guide` |
130
+ | `style` | Formatting | `style: fix indentation` |
131
+ | `refactor` | Refactor | `refactor(api): extract common logic` |
132
+ | `test` | Tests | `test(user): add unit tests` |
133
+ | `chore` | Misc | `chore(deps): update lodash` |
134
+
135
+ ---
136
+
137
+ ## 4) Review checklist
138
+
139
+ ### Author self-check
140
+
141
+ Before opening the PR, confirm:
142
+
143
+ ```bash
144
+ # 1) Lint/type checks
145
+ npm run lint
146
+ npm run compile
147
+
148
+ # 2) Tests
149
+ npm test
150
+
151
+ # 3) No debug code
152
+ rg 'console\\.(log|debug)|debugger' src/ --type ts
153
+
154
+ # 4) No accidental focused tests
155
+ rg '\\.only\\s*\\(' tests/ --type ts
156
+
157
+ # 5) No secrets
158
+ rg '(password|secret|token|key)\\s*[:=]' --type ts -i
159
+ ```
160
+
161
+ ### Reviewer checklist
162
+
163
+ When reviewing, focus on:
164
+
165
+ **Correctness**
166
+ - [ ] Does the code implement what the PR describes?
167
+ - [ ] Are edge cases handled?
168
+ - [ ] Are error cases handled?
169
+
170
+ **Code quality**
171
+ - [ ] Are names clear?
172
+ - [ ] Are functions too long?
173
+ - [ ] Is there duplicated code?
174
+ - [ ] Any obvious performance issues?
175
+
176
+ **Security**
177
+ - [ ] SQL injection risk?
178
+ - [ ] XSS risk?
179
+ - [ ] Sensitive data protected?
180
+
181
+ **Tests**
182
+ - [ ] Are there relevant tests?
183
+ - [ ] Do tests cover major paths?
184
+ - [ ] Are tests isolated and repeatable?
185
+
186
+ **Docs**
187
+ - [ ] Public API documented?
188
+ - [ ] README needs updates?
189
+ - [ ] Changelog needs updates?
190
+
191
+ ---
192
+
193
+ ## 5) PR workflow
194
+
195
+ ### Standard flow
196
+
197
+ ```
198
+ 1. Create a branch
199
+ git checkout -b feat/feature-name
200
+
201
+ 2. Develop and commit
202
+ git add .
203
+ git commit -m "feat(scope): description"
204
+
205
+ 3. Push branch
206
+ git push -u origin feat/feature-name
207
+
208
+ 4. Open PR
209
+ - Fill the PR template
210
+ - Link issues
211
+ - Request review
212
+
213
+ 5. Address review feedback
214
+ - Reply to comments
215
+ - Push fixes
216
+ - Re-request review
217
+
218
+ 6. Merge
219
+ - Squash and merge (recommended)
220
+ - Delete source branch
221
+ ```
222
+
223
+ ### Branch naming
224
+
225
+ | Type | Format | Example |
226
+ |------|--------|---------|
227
+ | Feature | `feat/<name>` | `feat/user-auth` |
228
+ | Fix | `fix/<issue-id>` | `fix/123-login-error` |
229
+ | Docs | `docs/<name>` | `docs/api-guide` |
230
+ | Refactor | `refactor/<name>` | `refactor/auth-service` |
231
+ | Hotfix | `hotfix/<name>` | `hotfix/security-patch` |
232
+
233
+ ---
234
+
235
+ ## 6) Review etiquette
236
+
237
+ ### Authors
238
+
239
+ - Provide sufficient context
240
+ - Respond to feedback promptly
241
+ - Respect reviewers’ time
242
+ - Avoid overly large PRs
243
+
244
+ ### Reviewers
245
+
246
+ - Review in a timely manner (within 24–48 hours)
247
+ - Provide constructive suggestions
248
+ - Explain “why”, not only “what”
249
+ - Differentiate “must fix” vs “nice to have”
250
+
251
+ ### Comment format
252
+
253
+ ```markdown
254
+ # Must fix
255
+ 🔴 **Must**: there is a security issue here; add input validation.
256
+
257
+ # Suggestion
258
+ 🟡 **Suggestion**: consider using `Array.from()` instead of spread.
259
+
260
+ # Question
261
+ 🔵 **Question**: what is the rationale for this timeout value?
262
+
263
+ # Praise
264
+ 🟢 **Praise**: nice abstraction!
265
+ ```
266
+
267
+ ---
268
+
269
+ ## 7) Automation checks
270
+
271
+ ### CI workflow example
272
+
273
+ ```yaml
274
+ # .github/workflows/pr-check.yml
275
+ name: PR Check
276
+
277
+ on:
278
+ pull_request:
279
+ branches: [main, develop]
280
+
281
+ jobs:
282
+ check:
283
+ runs-on: ubuntu-latest
284
+ steps:
285
+ - uses: actions/checkout@v4
286
+
287
+ - name: Setup Node
288
+ uses: actions/setup-node@v4
289
+ with:
290
+ node-version: '20'
291
+ cache: 'npm'
292
+
293
+ - name: Install
294
+ run: npm ci
295
+
296
+ - name: Lint
297
+ run: npm run lint
298
+
299
+ - name: Type Check
300
+ run: npm run compile
301
+
302
+ - name: Test
303
+ run: npm test
304
+
305
+ - name: Check for debug statements
306
+ run: |
307
+ if rg 'console\\.(log|debug)|debugger' src/ --type ts; then
308
+ echo "::error::Found debug statements"
309
+ exit 1
310
+ fi
311
+ ```
312
+
313
+ ### Required checks
314
+
315
+ | Check | Description |
316
+ |-------|-------------|
317
+ | Lint | ESLint rules pass |
318
+ | TypeScript | Type check passes |
319
+ | Tests | All tests pass |
320
+ | Coverage | Coverage not below baseline |
321
+ | Build | Build succeeds |
@@ -0,0 +1,311 @@
1
+ # Resource Management Review Checklist
2
+
3
+ Inspired by VS Code’s `code-no-potentially-unsafe-disposables` and `code-must-use-super-dispose` rules.
4
+
5
+ ---
6
+
7
+ ## 1) Common resource leak patterns
8
+
9
+ ### Subscription / listener leaks
10
+
11
+ ```typescript
12
+ // Bad: subscription is never removed
13
+ class MyComponent {
14
+ private handler = (e: Event) => { /* ... */ };
15
+
16
+ initialize() {
17
+ document.addEventListener('click', this.handler);
18
+ // Missing removeEventListener
19
+ }
20
+ }
21
+
22
+ // Good: use 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
+ ### Timer leaks
39
+
40
+ ```typescript
41
+ // Bad: timer is never cleared
42
+ class Poller {
43
+ start() {
44
+ setInterval(() => this.poll(), 1000);
45
+ // Missing cleanup
46
+ }
47
+ }
48
+
49
+ // Good: keep the handle and clear it in 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
+ ### Stream / connection leaks
67
+
68
+ ```typescript
69
+ // Bad: stream is not closed on error
70
+ async function readFile(path: string) {
71
+ const stream = fs.createReadStream(path);
72
+ const data = await streamToString(stream);
73
+ // If streamToString throws, the stream will remain open
74
+ return data;
75
+ }
76
+
77
+ // Good: use 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
+ // Better: use 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 pattern
97
+
98
+ ### Basic usage
99
+
100
+ ```typescript
101
+ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
102
+
103
+ class MyService extends Disposable {
104
+ // Must be readonly
105
+ private readonly _disposables = new DisposableStore();
106
+
107
+ constructor() {
108
+ super();
109
+
110
+ // Register subscription in the store
111
+ this._disposables.add(
112
+ eventEmitter.on('change', () => this.handleChange())
113
+ );
114
+
115
+ // Register timers/resources in the store
116
+ this._disposables.add(
117
+ new IntervalTimer(() => this.poll(), 1000)
118
+ );
119
+ }
120
+
121
+ override dispose() {
122
+ this._disposables.dispose();
123
+ super.dispose(); // Must call
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### Rules to check
129
+
130
+ | Rule | Detection pattern | Severity |
131
+ |------|-------------------|----------|
132
+ | `DisposableStore` must be `readonly` | `private\\s+(?!readonly)\\s*_?\\w*[Dd]isposable` | Error |
133
+ | `dispose()` must call `super.dispose()` | `override\\s+dispose\\(\\).*\\{(?![\\s\\S]*super\\.dispose)` | Error |
134
+ | Subscriptions must be registered | `.on\\(.*\\)` without `.add(` | Warning |
135
+ | Tests should check for leaks | missing `ensureNoDisposablesAreLeakedInTestSuite` | Warning |
136
+
137
+ ---
138
+
139
+ ## 3) Detecting leaks in tests
140
+
141
+ ### Using `ensureNoDisposablesAreLeakedInTestSuite`
142
+
143
+ ```typescript
144
+ import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
145
+
146
+ suite('MyService', () => {
147
+ // Enable leak detection at suite start
148
+ ensureNoDisposablesAreLeakedInTestSuite();
149
+
150
+ let service: MyService;
151
+
152
+ setup(() => {
153
+ service = new MyService();
154
+ });
155
+
156
+ teardown(() => {
157
+ service.dispose(); // Must clean up
158
+ });
159
+
160
+ test('should do something', () => {
161
+ // test code
162
+ });
163
+ });
164
+ ```
165
+
166
+ ### Common test leak patterns
167
+
168
+ ```typescript
169
+ // Bad: disposable created in a test is never disposed
170
+ test('creates disposable', () => {
171
+ const disposable = new MyDisposable();
172
+ // test ends, disposable not disposed -> leak
173
+ });
174
+
175
+ // Good: dispose in 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) Review checklist
190
+
191
+ ### Must check in code review
192
+
193
+ - [ ] **`DisposableStore` declarations**
194
+ - Is it `readonly`?
195
+ - Is it `private`?
196
+
197
+ - [ ] **`dispose()` method**
198
+ - Does it call `super.dispose()`?
199
+ - Does it clean up all known resources?
200
+ - Is cleanup defined in a base class when appropriate?
201
+
202
+ - [ ] **Subscriptions / listeners**
203
+ - Are they registered in a `DisposableStore`?
204
+ - Is there a corresponding cancellation/removal path?
205
+ - Is `AbortController` used where applicable?
206
+
207
+ - [ ] **Timers**
208
+ - Does `setInterval` have a corresponding `clearInterval`?
209
+ - Are `setTimeout` callbacks canceled on teardown/dispose?
210
+
211
+ - [ ] **Streams / connections**
212
+ - Are they closed in a `finally` block?
213
+ - Is `using` used when available?
214
+
215
+ - [ ] **Tests**
216
+ - Is `ensureNoDisposablesAreLeakedInTestSuite()` present?
217
+ - Does teardown dispose everything created by tests?
218
+
219
+ ---
220
+
221
+ ## 5) Automated detection
222
+
223
+ ### ESLint rule config
224
+
225
+ ```javascript
226
+ // eslint.config.js
227
+ module.exports = {
228
+ rules: {
229
+ // Custom rule: DisposableStore must be readonly
230
+ 'local/code-no-potentially-unsafe-disposables': 'error',
231
+
232
+ // Custom rule: dispose must call super
233
+ 'local/code-must-use-super-dispose': 'error',
234
+ }
235
+ };
236
+ ```
237
+
238
+ ### Grep / ripgrep commands
239
+
240
+ ```bash
241
+ # Detect non-readonly DisposableStore fields
242
+ rg 'private\\s+(?!readonly)\\s*_?\\w*[Dd]isposable' --type ts
243
+
244
+ # Detect dispose() methods missing super.dispose()
245
+ rg -U 'override\\s+dispose\\(\\).*?\\{[^}]*\\}' --type ts | grep -v 'super.dispose'
246
+
247
+ # Detect setInterval without clearInterval
248
+ rg 'setInterval\\(' --type ts -l | xargs -I {} sh -c 'rg -c "clearInterval" {} || echo "Missing clearInterval: {}"'
249
+ ```
250
+
251
+ ---
252
+
253
+ ## 6) Fix guide
254
+
255
+ ### Add a `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
+ ### Add test leak detection
286
+
287
+ ```typescript
288
+ // Before
289
+ suite('MyTest', () => {
290
+ test('does something', () => {
291
+ const obj = new MyDisposable();
292
+ // Not disposed
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
+ // Automatically disposed in teardown
309
+ });
310
+ });
311
+ ```