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.
- package/LICENSE +21 -0
- package/README.md +463 -0
- package/bin/devbooks.js +986 -0
- package/package.json +41 -0
- package/skills/Skill-Development-Guide.md +249 -0
- package/skills/Skills-Usage-Guide.md +447 -0
- package/skills/_shared/context-detection-template.md +315 -0
- package/skills/_shared/mcp-enhancement-template.md +144 -0
- package/skills/_shared/references/universal-gating-protocol.md +114 -0
- package/skills/_template/config-discovery-template.md +126 -0
- package/skills/devbooks-brownfield-bootstrap/SKILL.md +168 -0
- package/skills/devbooks-brownfield-bootstrap/references/10-glossary-template.md +42 -0
- package/skills/devbooks-brownfield-bootstrap/references/brownfield-bootstrap-prompt.md +115 -0
- package/skills/devbooks-brownfield-bootstrap/references/brownfield-bootstrap.md +96 -0
- package/skills/devbooks-brownfield-bootstrap/references/code-navigation-strategy.md +203 -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-architecture-map-prompt.md +33 -0
- package/skills/devbooks-c4-map/references/layered-constraint-checklist.md +185 -0
- package/skills/devbooks-code-review/SKILL.md +175 -0
- package/skills/devbooks-code-review/references/code-review-prompt.md +100 -0
- package/skills/devbooks-code-review/references/code-smell-cheatsheet.md +498 -0
- package/skills/devbooks-code-review/references/pr-template-and-guidelines.md +321 -0
- package/skills/devbooks-code-review/references/resource-management-review-checklist.md +311 -0
- package/skills/devbooks-coder/SKILL.md +219 -0
- package/skills/devbooks-coder/references/code-implementation-prompt.md +74 -0
- package/skills/devbooks-coder/references/coding-style-guidelines.md +351 -0
- package/skills/devbooks-coder/references/error-code-standard.md +463 -0
- package/skills/devbooks-coder/references/logging-standard.md +329 -0
- package/skills/devbooks-coder/references/low-risk-modification-techniques.md +275 -0
- package/skills/devbooks-delivery-workflow/SKILL.md +217 -0
- package/skills/devbooks-delivery-workflow/references/9-change-verification-traceability-template.md +133 -0
- package/skills/devbooks-delivery-workflow/references/delivery-acceptance-workflow.md +177 -0
- package/skills/devbooks-delivery-workflow/references/prototype-production-dual-track.md +169 -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 +1039 -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 +467 -0
- package/skills/devbooks-delivery-workflow/scripts/change-spec-delta-scaffold.sh +135 -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 +365 -0
- package/skills/devbooks-delivery-workflow/scripts/guardrail-check.sh +516 -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/design-backport-prompt.md +132 -0
- package/skills/devbooks-design-doc/SKILL.md +121 -0
- package/skills/devbooks-design-doc/references/design-doc-prompt.md +188 -0
- package/skills/devbooks-design-doc/references/microservice-design-checklist.md +149 -0
- package/skills/devbooks-design-doc/references/privacy-compliance-checklist.md +240 -0
- package/skills/devbooks-entropy-monitor/SKILL.md +188 -0
- package/skills/devbooks-entropy-monitor/references/entropy-metrics-methodology.md +218 -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/impact-analysis-prompt.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/implementation-plan-prompt.md +95 -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/proposal-authoring-prompt.md +66 -0
- package/skills/devbooks-proposal-challenger/SKILL.md +86 -0
- package/skills/devbooks-proposal-challenger/references/ethics-and-compliance-checklist.md +176 -0
- package/skills/devbooks-proposal-challenger/references/proposal-challenge-prompt.md +57 -0
- package/skills/devbooks-proposal-debate-workflow/SKILL.md +78 -0
- package/skills/devbooks-proposal-debate-workflow/references/11-proposal-debate-template.md +35 -0
- package/skills/devbooks-proposal-debate-workflow/references/proposal-debate-workflow.md +24 -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/proposal-judge-prompt.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-design-guide.md +349 -0
- package/skills/devbooks-spec-contract/references/contract-and-data-definition-prompt.md +85 -0
- package/skills/devbooks-spec-contract/references/implicit-change-detection-prompt.md +183 -0
- package/skills/devbooks-spec-contract/references/spec-change-prompt.md +63 -0
- package/skills/devbooks-spec-contract/scripts/implicit-change-detect.sh +378 -0
- package/skills/devbooks-spec-gardener/SKILL.md +73 -0
- package/skills/devbooks-spec-gardener/references/spec-gardener-prompt.md +41 -0
- package/skills/devbooks-test-owner/SKILL.md +173 -0
- package/skills/devbooks-test-owner/references/9-change-verification-traceability-template.md +133 -0
- package/skills/devbooks-test-owner/references/async-system-test-strategy.md +316 -0
- package/skills/devbooks-test-owner/references/decoupling-techniques-cheatsheet.md +269 -0
- package/skills/devbooks-test-owner/references/test-code-prompt.md +171 -0
- package/skills/devbooks-test-owner/references/test-driven-development.md +351 -0
- package/skills/devbooks-test-owner/references/test-layering-strategy.md +281 -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 +20 -0
- package/templates/claude-commands/devbooks/c4.md +20 -0
- package/templates/claude-commands/devbooks/challenger.md +19 -0
- package/templates/claude-commands/devbooks/code.md +20 -0
- package/templates/claude-commands/devbooks/debate.md +20 -0
- package/templates/claude-commands/devbooks/delivery.md +20 -0
- package/templates/claude-commands/devbooks/design.md +20 -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 +20 -0
- package/templates/claude-commands/devbooks/proposal.md +20 -0
- package/templates/claude-commands/devbooks/quick.md +43 -0
- package/templates/claude-commands/devbooks/review.md +20 -0
- package/templates/claude-commands/devbooks/router.md +19 -0
- package/templates/claude-commands/devbooks/spec.md +20 -0
- package/templates/claude-commands/devbooks/test-review.md +19 -0
- package/templates/claude-commands/devbooks/test.md +20 -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 +48 -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,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
|
+
```
|