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,498 @@
1
+ # Core Code Smells Cheat Sheet (Top 8 + Module Cycles)
2
+
3
+ > Source: *Refactoring: Improving the Design of Existing Code (2nd Edition)* (debate-revised summary)
4
+ > This reduces the original 22 smells down to 8 high-frequency, high-impact smells for day-to-day reviews.
5
+
6
+ ---
7
+
8
+ ## Quick Index
9
+
10
+ | # | Smell | One-line description | Severity |
11
+ |---|-------|----------------------|----------|
12
+ | 1 | Duplicated Code | The same logic appears in multiple places | Blocker |
13
+ | 2 | Long Method | A function is too long to understand easily | Blocker |
14
+ | 3 | Large Class | A class takes on too many responsibilities | Warning |
15
+ | 4 | Long Parameter List | Too many parameters make calls fragile | Blocker |
16
+ | 5 | Divergent Change | One class changes for multiple reasons | Warning |
17
+ | 6 | Shotgun Surgery | One change requires touching many places | Blocker |
18
+ | 7 | Feature Envy | A method depends too much on another class | Warning |
19
+ | 8 | Primitive Obsession | Domain concepts are modeled as primitives | Warning |
20
+ | 9 | **Module Cycle** | A→B→A blocks independent build/test | **Blocker** |
21
+
22
+ ---
23
+
24
+ ## 1. Duplicated Code
25
+
26
+ **Signals:**
27
+ - Similarity > 80% appears in 2+ places
28
+ - Copy/paste with only variable names changed
29
+ - Duplicate logic across sibling subclasses
30
+
31
+ **Why it matters:**
32
+ - Easy to miss one site when changing behavior
33
+ - Increases code size and reduces readability
34
+ - Violates DRY
35
+
36
+ **Refactorings:**
37
+ 1. **Duplicates within one class** → Extract Method
38
+ 2. **Duplicates across sibling subclasses** → Extract Method → Pull Up Method
39
+ 3. **Duplicates across unrelated classes** → Extract Class (shared component)
40
+
41
+ **Example:**
42
+ ```python
43
+ # Smell: duplicated validation logic
44
+ def create_user(email):
45
+ if not email or '@' not in email:
46
+ raise ValueError("Invalid email")
47
+ # ...
48
+
49
+ def update_email(email):
50
+ if not email or '@' not in email: # duplicated!
51
+ raise ValueError("Invalid email")
52
+ # ...
53
+
54
+ # Refactor: extract a helper
55
+ def validate_email(email):
56
+ if not email or '@' not in email:
57
+ raise ValueError("Invalid email")
58
+
59
+ def create_user(email):
60
+ validate_email(email)
61
+ # ...
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 2. Long Method
67
+
68
+ **Signals:**
69
+ - **P95 < 50 lines** (use as a discussion trigger, not a hard rule)
70
+ - You need to scroll to read the full function
71
+ - The function contains large comment blocks explaining “what this part does”
72
+ - Cyclomatic complexity > 10
73
+
74
+ **Why it matters:**
75
+ - Hard to understand the overall intent
76
+ - Hard to test (too many branches)
77
+ - Hard to reuse partial logic
78
+
79
+ **Refactorings:**
80
+ 1. **Comments are a signal** → Extract Method (use the comment as the method name)
81
+ 2. **Too many temporaries** → Replace Temp with Query
82
+ 3. **Complex conditionals** → Decompose Conditional
83
+
84
+ **Example:**
85
+ ```python
86
+ # Smell: long method
87
+ def process_order(order):
88
+ # validate order
89
+ if not order.items:
90
+ raise ValueError("Empty order")
91
+ if order.total < 0:
92
+ raise ValueError("Invalid total")
93
+
94
+ # calculate discount
95
+ discount = 0
96
+ if order.customer.is_vip:
97
+ discount = order.total * 0.1
98
+ elif order.total > 1000:
99
+ discount = order.total * 0.05
100
+
101
+ # update inventory
102
+ for item in order.items:
103
+ stock = get_stock(item.product_id)
104
+ stock.quantity -= item.quantity
105
+ save_stock(stock)
106
+
107
+ # ... 50 more lines
108
+
109
+ # Refactor: extract helpers
110
+ def process_order(order):
111
+ validate_order(order)
112
+ discount = calculate_discount(order)
113
+ update_inventory(order)
114
+ # ...
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 3. Large Class
120
+
121
+ **Signals:**
122
+ - **P95 < 500 lines**
123
+ - > 10 instance fields
124
+ - > 20 methods
125
+ - Multiple groups of fields with shared prefixes (e.g., `billing_*`, `shipping_*`)
126
+
127
+ **Why it matters:**
128
+ - Violates SRP (Single Responsibility Principle)
129
+ - Hard to test (too many dependencies)
130
+ - Change impact becomes unpredictable
131
+
132
+ **Refactorings:**
133
+ 1. **Responsibilities can be separated** → Extract Class
134
+ 2. **There are true subtypes** → Extract Subclass
135
+ 3. **Consumers only need a subset** → Extract Interface
136
+
137
+ ---
138
+
139
+ ## 4. Long Parameter List
140
+
141
+ **Signals:**
142
+ - More than 5 parameters
143
+ - Call sites often mix up parameter order
144
+ - Multiple functions share the same parameter “bundle”
145
+
146
+ **Why it matters:**
147
+ - Easy to pass the wrong argument
148
+ - Hard to remember the signature
149
+ - The bundle is often a hidden domain concept
150
+
151
+ **Refactorings:**
152
+ 1. **Arguments can be obtained from an object** → Preserve Whole Object
153
+ 2. **Arguments always travel together** → Introduce Parameter Object
154
+
155
+ **Example:**
156
+ ```python
157
+ # Smell: too many parameters
158
+ def create_address(street, city, state, zip_code, country, apt_number):
159
+ pass
160
+
161
+ # Refactor: introduce a parameter object
162
+ @dataclass
163
+ class Address:
164
+ street: str
165
+ city: str
166
+ state: str
167
+ zip_code: str
168
+ country: str
169
+ apt_number: str = None
170
+
171
+ def create_address(address: Address):
172
+ pass
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 5. Divergent Change
178
+
179
+ **Signals:**
180
+ - Database changes require editing this class
181
+ - UI changes also require editing this class
182
+ - Business rule changes require editing this class too
183
+ - “Every requirement change touches this file”
184
+
185
+ **Why it matters:**
186
+ - One class carries multiple change axes
187
+ - Unrelated edits interfere with each other
188
+ - Hard to test one dimension in isolation
189
+
190
+ **Refactorings:**
191
+ - Extract Class (split by reason-to-change)
192
+
193
+ **Compared to Shotgun Surgery:**
194
+ - Divergent Change: one class responds to many changes
195
+ - Shotgun Surgery: one change requires touching many classes
196
+ - They are dual problems with opposite fixes
197
+
198
+ ---
199
+
200
+ ## 6. Shotgun Surgery
201
+
202
+ **Signals:**
203
+ - One requirement forces edits in 3+ classes/files
204
+ - “Fixing one place means changing lots of other places”
205
+ - Easy to miss one spot and ship a bug
206
+
207
+ **Why it matters:**
208
+ - Changes are easy to overlook
209
+ - Logic is scattered and hard to reason about
210
+ - Test coverage becomes expensive
211
+
212
+ **Refactorings:**
213
+ 1. **Logic should be centralized** → Move Method / Move Field
214
+ 2. **Over-fragmented code** → Inline Class (merge first, then re-split intentionally)
215
+
216
+ ---
217
+
218
+ ## 7. Feature Envy
219
+
220
+ **Signals:**
221
+ - A method calls other classes more than it uses its own class
222
+ - A method reads many fields from another class
223
+ - “This method feels like it belongs elsewhere”
224
+
225
+ **Why it matters:**
226
+ - Violates “data and behavior belong together”
227
+ - Increases coupling
228
+ - Blurs responsibility boundaries
229
+
230
+ **Refactorings:**
231
+ - Move Method (move closer to the data it uses)
232
+
233
+ **Common exceptions (not Feature Envy):**
234
+ - Strategy pattern (strategy accessing context)
235
+ - Visitor pattern (visitor accessing elements)
236
+ - If this is intentional, document it as a pattern choice
237
+
238
+ ---
239
+
240
+ ## 8. Primitive Obsession
241
+
242
+ **Signals:**
243
+ - `string` used for phone numbers, emails, money
244
+ - `int` used for status codes or type codes
245
+ - Business rules are duplicated across the codebase (e.g., email validation)
246
+
247
+ **Why it matters:**
248
+ - Poor type safety (a `string` can be anything)
249
+ - Business rules can’t be centralized
250
+ - Domain language drifts away from the project glossary
251
+
252
+ **Refactorings:**
253
+ - Replace Data Value with Object
254
+ - Replace Type Code with Class/Subclass
255
+
256
+ **Scope guidance (debate-revised):**
257
+ - **Must encapsulate:** domain concepts (Money, Email, UserId, PhoneNumber)
258
+ - **Optional encapsulation:** technical types (coordinates, colors, simple configs)
259
+
260
+ **Example:**
261
+ ```python
262
+ # Smell: primitives used for domain concepts
263
+ def transfer(from_account: str, to_account: str, amount: float):
264
+ pass # amount can be negative? which currency?
265
+
266
+ # Refactor: encapsulate into a value object
267
+ @dataclass(frozen=True)
268
+ class Money:
269
+ amount: Decimal
270
+ currency: str
271
+
272
+ def __post_init__(self):
273
+ if self.amount < 0:
274
+ raise ValueError("Amount cannot be negative")
275
+
276
+ def transfer(from_account: AccountId, to_account: AccountId, amount: Money):
277
+ pass
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Smells Removed (after debate)
283
+
284
+ The following concepts were removed after an Advocate/Skeptic/Judge debate:
285
+
286
+ | Original smell | Why it was removed |
287
+ |---------------|--------------------|
288
+ | Parallel Inheritance Hierarchies | Deep inheritance is rare in modern codebases |
289
+ | Lazy Class | Conflicts with SRP; small classes can be good design |
290
+ | Speculative Generality | Too subjective to enforce consistently |
291
+ | Temporary Field | Low frequency in typical codebases |
292
+ | Message Chains | Fluent functional chains are common now |
293
+ | Middle Man | Can be a valid anti-corruption layer in layered designs |
294
+ | Alternative Classes with Different Interfaces | Typically covered by terminology/interface consistency checks |
295
+ | Incomplete Library Class | Third-party code can’t be refactored |
296
+ | Data Class | DTO layers often intentionally allow anemic structures |
297
+ | Refused Bequest | Inheritance usage has declined significantly |
298
+ | Comments | “Why” comments can be valuable |
299
+
300
+ ---
301
+
302
+ ## Quick Decision Flow
303
+
304
+ ```
305
+ Spot suspicious code
306
+ |
307
+ +-- Duplicate? ------------------> Extract Method
308
+ |
309
+ +-- Function > 50 lines? --------> Extract Method + Decompose Conditional
310
+ |
311
+ +-- Class > 500 lines? ----------> Extract Class
312
+ |
313
+ +-- Parameters > 5? -------------> Introduce Parameter Object
314
+ |
315
+ +-- One change touches many? ----> Move Method/Field (centralize logic)
316
+ |
317
+ +-- One class changes for many reasons?
318
+ | -> Extract Class (split change axes)
319
+ |
320
+ +-- Method uses other class a lot?
321
+ | -> Move Method
322
+ |
323
+ +-- Domain concepts are strings?
324
+ -> Replace Data Value with Object
325
+ ```
326
+
327
+ ---
328
+
329
+ ## 9. Module Cycle
330
+
331
+ > Source: *Clean Architecture* (debate-revised) — a consensus “keep” rule
332
+
333
+ **Signals:**
334
+ - Module A depends on B, and B depends on A (direct cycle)
335
+ - Indirect cycles like A→B→C→A
336
+ - You can’t build/test a module independently
337
+ - “Changing one module forces changing another”
338
+
339
+ **Why it matters:**
340
+ - Blocks independent testing (you must mock multiple sides)
341
+ - Blocks independent deployment/release
342
+ - Strong signal of architecture erosion
343
+ - Refactor cost grows nonlinearly
344
+
345
+ **Detection tools:**
346
+ ```bash
347
+ # JavaScript/TypeScript
348
+ npx madge --circular src/
349
+
350
+ # Java
351
+ jdeps -R -summary target/classes | grep cycle
352
+
353
+ # Go
354
+ go mod graph | tsort 2>&1 | grep -i cycle
355
+
356
+ # Python
357
+ pydeps --show-cycles src/
358
+ ```
359
+
360
+ **Refactorings:**
361
+ 1. **Dependency inversion** → extract interfaces into a separate module; both sides depend on the interface
362
+ 2. **Callbacks/events** → A calls B, and B notifies A via callback/event instead of direct dependency
363
+ 3. **Extract a shared module** → move common dependencies into module C
364
+
365
+ **Example:**
366
+ ```python
367
+ # Smell: cyclic imports
368
+ # order.py
369
+ from payment import PaymentService # Order → Payment
370
+
371
+ # payment.py
372
+ from order import Order # Payment → Order (cycle!)
373
+
374
+ # Refactor: dependency inversion
375
+ # interfaces.py (independent module)
376
+ class OrderInterface(ABC):
377
+ @abstractmethod
378
+ def get_total(self) -> Money: ...
379
+
380
+ # order.py
381
+ class Order(OrderInterface): # implements the interface
382
+ pass
383
+
384
+ # payment.py
385
+ from interfaces import OrderInterface # depend on the interface only
386
+ class PaymentService:
387
+ def charge(self, order: OrderInterface): ...
388
+ ```
389
+
390
+ **CI integration suggestion:**
391
+ ```yaml
392
+ # .github/workflows/ci.yml
393
+ - name: Check circular dependencies
394
+ run: |
395
+ npx madge --circular src/ && echo "No cycles found" || exit 1
396
+ ```
397
+
398
+ ---
399
+
400
+ ## References
401
+
402
+ - *Refactoring: Improving the Design of Existing Code* (2nd Edition) — Martin Fowler
403
+ - *Clean Architecture* — Robert C. Martin (Chapter: Component Coupling)
404
+ - Dev Playbooks debate-revised evaluation notes
405
+ - `devbooks-code-review` checklists
406
+
407
+ ---
408
+
409
+ ## 10. VS Code-style Code Hygiene Checks
410
+
411
+ > Inspired by VS Code custom ESLint rules as automated review items.
412
+
413
+ ### Do-not-commit patterns (Blocker)
414
+
415
+ | Pattern | Detection command | Why it matters |
416
+ |---------|-------------------|----------------|
417
+ | `test.only` / `describe.only` | `rg '\\.only\\s*\\(' tests/` | Skips other tests |
418
+ | `console.log` / `console.debug` | `rg 'console\\.(log\\|debug)' src/` | Debug leftovers |
419
+ | `debugger` | `rg 'debugger' src/` | Breakpoints left in code |
420
+ | `@ts-ignore` | `rg '@ts-ignore' src/` | Hides type errors |
421
+ | `as any` | `rg 'as any' src/` | Bypasses type safety |
422
+ | `TODO` without an issue | `rg 'TODO(?!.*#\\d+)' src/` | Untracked work |
423
+
424
+ ### Resource management checks (Warning)
425
+
426
+ | Pattern | How to detect | Preferred fix |
427
+ |---------|---------------|---------------|
428
+ | Non-`readonly` `DisposableStore` | `rg 'private\\s+(?!readonly)\\s*_?\\w*[Dd]isposable'` | Use `readonly` |
429
+ | `dispose()` missing `super.dispose()` | Review `override dispose` | Must call `super.dispose()` |
430
+ | `setInterval` without cleanup | Find `setInterval` without `clearInterval` | Clear in `dispose()` |
431
+ | Listener without removal | Find `addEventListener` without `removeEventListener` | Use `AbortController` |
432
+
433
+ ### Layering constraints checks
434
+
435
+ ```bash
436
+ # Verify forbidden cross-layer imports
437
+ # base must not depend on platform/editor/workbench
438
+ rg "from ['\\\"](vs/(platform|editor|workbench))" src/vs/base/
439
+
440
+ # platform must not depend on editor/workbench
441
+ rg "from ['\\\"](vs/(editor|workbench))" src/vs/platform/
442
+
443
+ # common must not depend on browser/node
444
+ rg "from ['\\\"].*(browser|node)" src/**/common/
445
+ ```
446
+
447
+ ### Type safety checks
448
+
449
+ ```typescript
450
+ // Avoid: empty-object assertions
451
+ const config = {} as Config; // bad
452
+
453
+ // Avoid: non-null assertions
454
+ const name = user!.name; // bad
455
+
456
+ // Avoid: any
457
+ function process(data: any) { } // bad
458
+
459
+ // Prefer: unknown or concrete types
460
+ function process(data: unknown) { } // ok
461
+ ```
462
+
463
+ ### Automation script example
464
+
465
+ ```bash
466
+ #!/usr/bin/env bash
467
+ # hygiene-check.sh
468
+
469
+ set -euo pipefail
470
+
471
+ echo "=== Code hygiene checks ==="
472
+
473
+ # 1) Debugging statements
474
+ if rg -l 'console\\.(log|debug)|debugger' src/ --type ts 2>/dev/null; then
475
+ echo "ERROR: found debugging statements"
476
+ exit 1
477
+ fi
478
+
479
+ # 2) test.only / describe.only
480
+ if rg -l '\\.only\\s*\\(' tests/ --type ts 2>/dev/null; then
481
+ echo "ERROR: found test.only / describe.only"
482
+ exit 1
483
+ fi
484
+
485
+ # 3) @ts-ignore occurrences
486
+ count=$(rg -c '@ts-ignore' src/ --type ts 2>/dev/null | wc -l)
487
+ if [ "${count}" -gt 0 ]; then
488
+ echo "WARN: found ${count} files with @ts-ignore"
489
+ fi
490
+
491
+ # 4) any occurrences
492
+ count=$(rg -c ': any[^a-z]' src/ --type ts 2>/dev/null | wc -l)
493
+ if [ "${count}" -gt 0 ]; then
494
+ echo "WARN: found ${count} files with ': any'"
495
+ fi
496
+
497
+ echo "OK: hygiene checks passed"
498
+ ```