@tplog/hasapi 0.1.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 +54 -0
- package/bin/hasapi.mjs +292 -0
- package/hasapi-skills/README.md +56 -0
- package/hasapi-skills/_shared/common.md +240 -0
- package/hasapi-skills/_shared/custom-risks-guide.md +48 -0
- package/hasapi-skills/_shared/decay-risks.md +294 -0
- package/hasapi-skills/_shared/remedy-guide.md +37 -0
- package/hasapi-skills/_shared/source-coverage.md +248 -0
- package/hasapi-skills/_shared/test-decay-risks.md +246 -0
- package/hasapi-skills/hasapi-audit/SKILL.md +42 -0
- package/hasapi-skills/hasapi-audit/architecture-guide.md +195 -0
- package/hasapi-skills/hasapi-audit/onboarding-guide.md +89 -0
- package/hasapi-skills/hasapi-debt/SKILL.md +35 -0
- package/hasapi-skills/hasapi-debt/debt-guide.md +125 -0
- package/hasapi-skills/hasapi-diagnosing-bugs/SKILL.md +134 -0
- package/hasapi-skills/hasapi-diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/hasapi-skills/hasapi-grilling/SKILL.md +10 -0
- package/hasapi-skills/hasapi-handoff/SKILL.md +16 -0
- package/hasapi-skills/hasapi-health/SKILL.md +37 -0
- package/hasapi-skills/hasapi-health/health-guide.md +89 -0
- package/hasapi-skills/hasapi-implement/SKILL.md +15 -0
- package/hasapi-skills/hasapi-resolving-merge-conflicts/SKILL.md +14 -0
- package/hasapi-skills/hasapi-review/SKILL.md +37 -0
- package/hasapi-skills/hasapi-review/pr-review-guide.md +163 -0
- package/hasapi-skills/hasapi-setup/SKILL.md +121 -0
- package/hasapi-skills/hasapi-setup/domain.md +51 -0
- package/hasapi-skills/hasapi-setup/issue-tracker-github.md +22 -0
- package/hasapi-skills/hasapi-setup/issue-tracker-gitlab.md +23 -0
- package/hasapi-skills/hasapi-setup/issue-tracker-local.md +19 -0
- package/hasapi-skills/hasapi-setup/triage-labels.md +15 -0
- package/hasapi-skills/hasapi-sweep/SKILL.md +38 -0
- package/hasapi-skills/hasapi-sweep/sweep-guide.md +264 -0
- package/hasapi-skills/hasapi-tdd/SKILL.md +108 -0
- package/hasapi-skills/hasapi-tdd/mocking.md +59 -0
- package/hasapi-skills/hasapi-tdd/refactoring.md +10 -0
- package/hasapi-skills/hasapi-tdd/tests.md +61 -0
- package/hasapi-skills/hasapi-test/SKILL.md +36 -0
- package/hasapi-skills/hasapi-test/test-guide.md +147 -0
- package/hasapi-skills/hasapi-to-issues/SKILL.md +84 -0
- package/hasapi-skills/hasapi-to-prd/SKILL.md +75 -0
- package/package.json +39 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Custom Risk Loading Guide
|
|
2
|
+
|
|
3
|
+
When `.brooks-lint.yaml` contains a `custom_risks` map, this guide governs how those
|
|
4
|
+
risks are loaded and scanned. Custom risks use `Cx` codes (C1, C2, …) — no conflict with
|
|
5
|
+
the standard R1–R6 and T1–T6 namespaces.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Loading
|
|
10
|
+
|
|
11
|
+
1. For each entry in `custom_risks`, validate that it has:
|
|
12
|
+
- `name` — non-empty string
|
|
13
|
+
- `question` — the diagnostic question to ask
|
|
14
|
+
- `symptoms` — non-empty list of symptom patterns
|
|
15
|
+
- `severity` — map with at least one of: `critical`, `warning`, `suggestion`
|
|
16
|
+
|
|
17
|
+
2. Register each valid entry as a `Cx` code alongside R1–R6 / T1–T6. Once loaded,
|
|
18
|
+
`Cx` codes become valid targets for `disable`, `focus`, and `severity` fields in
|
|
19
|
+
the same config file.
|
|
20
|
+
|
|
21
|
+
3. Report any validation errors as config warnings (do not abort the review):
|
|
22
|
+
- Missing required field: `"Config warning: C1 missing 'symptoms'"`
|
|
23
|
+
- Invalid code format (must be `C` followed by digits): skip, note error
|
|
24
|
+
- Code conflicts with R/T namespace: skip, note error
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Scanning
|
|
29
|
+
|
|
30
|
+
During the analysis, treat each custom risk as an additional step after the standard
|
|
31
|
+
process:
|
|
32
|
+
|
|
33
|
+
- Use `question` as the diagnostic question
|
|
34
|
+
- Use `symptoms` as the symptom lookup list
|
|
35
|
+
- Use the `severity` map for tier classification
|
|
36
|
+
- Apply the Iron Law: `Source` field should be `"[Project-defined risk] — <risk name>"`
|
|
37
|
+
- Include custom risk findings in the Health Score (same deduction rules as R/T codes)
|
|
38
|
+
- In the report, custom findings appear after standard findings under a
|
|
39
|
+
**### Project-Specific Risks** sub-heading
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Config Validation additions
|
|
44
|
+
|
|
45
|
+
The following codes are valid in `disable`, `focus`, and `severity`:
|
|
46
|
+
- Standard: `R1`–`R6`, `T1`–`T6`
|
|
47
|
+
- Custom: any `Cx` code defined in `custom_risks`
|
|
48
|
+
- Any other code: skip it and emit `"Config warning: X is not a valid risk code"`
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# Decay Risk Reference
|
|
2
|
+
|
|
3
|
+
Six patterns that cause software to degrade. Apply the Iron Law to each finding.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Risk 1: Cognitive Overload
|
|
8
|
+
|
|
9
|
+
**Diagnostic question:** How much mental effort does a human need to understand this?
|
|
10
|
+
|
|
11
|
+
Cognitive load beyond working memory causes mistakes, avoidance, and blocks the refactoring that would fix it.
|
|
12
|
+
|
|
13
|
+
### Symptoms
|
|
14
|
+
|
|
15
|
+
- Function longer than 20 lines where multiple levels of abstraction are mixed together
|
|
16
|
+
- Nesting depth greater than 3 levels
|
|
17
|
+
- Parameter list with more than 4 parameters
|
|
18
|
+
- Magic numbers or unexplained constants
|
|
19
|
+
- Variable names that require reading the implementation to understand (e.g., `d`, `tmp2`, `flag`)
|
|
20
|
+
- Boolean expressions with 3 or more conditions combined
|
|
21
|
+
- Train-wreck chains: `a.getB().getC().doD()`
|
|
22
|
+
- Code names that do not match what the business calls the same concept
|
|
23
|
+
- Flag Arguments: a boolean parameter that makes the function do two fundamentally different
|
|
24
|
+
things depending on its value — a sign the function has two responsibilities
|
|
25
|
+
- Primitive Obsession: domain concepts represented as primitive types (`String email`,
|
|
26
|
+
`int orderId`, `double money`) rather than purpose-built value types — forces callers to know
|
|
27
|
+
which string is an email and which is a name
|
|
28
|
+
- Shallow module: the interface or documentation of a component is more complex relative to
|
|
29
|
+
the functionality it provides
|
|
30
|
+
|
|
31
|
+
### Sources
|
|
32
|
+
|
|
33
|
+
| Symptom | Book | Principle / Smell |
|
|
34
|
+
|---------|------|-------------------|
|
|
35
|
+
| Long Method | Fowler — Refactoring | Long Method |
|
|
36
|
+
| Long Parameter List | Fowler — Refactoring | Long Parameter List |
|
|
37
|
+
| Message Chains | Fowler — Refactoring | Message Chains |
|
|
38
|
+
| Flag Arguments | Fowler — Refactoring | Flag Arguments |
|
|
39
|
+
| Primitive Obsession | Fowler — Refactoring | Primitive Obsession |
|
|
40
|
+
| Function length and nesting | McConnell — Code Complete | Ch. 7: High-Quality Routines |
|
|
41
|
+
| Variable naming | McConnell — Code Complete | Ch. 11: The Power of Variable Names |
|
|
42
|
+
| Magic numbers | McConnell — Code Complete | Ch. 12: Fundamental Data Types |
|
|
43
|
+
| Domain name mismatch | Evans — Domain-Driven Design | Ubiquitous Language |
|
|
44
|
+
| Shallow Module | Ousterhout — A Philosophy of Software Design | Ch. 4: Modules Should Be Deep |
|
|
45
|
+
|
|
46
|
+
### Severity Guide
|
|
47
|
+
|
|
48
|
+
- 🔴 Critical: function > 50 lines, nesting > 5, or virtually no meaningful names
|
|
49
|
+
- 🟡 Warning: function 20–50 lines, nesting 4–5, some unclear names
|
|
50
|
+
- 🟢 Suggestion: minor naming issues, 1–2 magic numbers, isolated train-wreck chains
|
|
51
|
+
|
|
52
|
+
### What Not to Flag
|
|
53
|
+
|
|
54
|
+
- Linear code with clear names and guard clauses is not automatically high cognitive load
|
|
55
|
+
- Internal implementation detail hidden behind a deep, simple module boundary is not a shallow-module problem
|
|
56
|
+
- Domain-specific terminology should not be flagged if it matches how experts actually speak
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Risk 2: Change Propagation
|
|
61
|
+
|
|
62
|
+
**Diagnostic question:** How many unrelated things break when you change one thing?
|
|
63
|
+
|
|
64
|
+
Each change ripples to unrelated modules, slowing velocity and multiplying regression risk.
|
|
65
|
+
|
|
66
|
+
### Symptoms
|
|
67
|
+
|
|
68
|
+
- Modifying one feature requires touching more than 3 files in unrelated modules
|
|
69
|
+
- One class changes for multiple different business reasons (e.g., `UserService` changes for
|
|
70
|
+
billing logic AND notification logic AND profile logic)
|
|
71
|
+
- A method uses more data from another class than from its own class
|
|
72
|
+
- Two classes know each other's internal state directly
|
|
73
|
+
- Changing one module requires recompiling or retesting many unrelated modules
|
|
74
|
+
- **Hyrum's Law**: with sufficient callers, every observable behavior — including
|
|
75
|
+
implementation details, error message text, coincidental call ordering, and undocumented
|
|
76
|
+
side effects — becomes an implicit contract that callers depend on, even though it was
|
|
77
|
+
never guaranteed by the declared API
|
|
78
|
+
- **Orthogonality violation**: changing one dimension of a feature forces edits in
|
|
79
|
+
unrelated dimensions — adding a new payment type should not require touching logging,
|
|
80
|
+
caching, or notification code, but in a non-orthogonal design it does
|
|
81
|
+
- Information Leakage: a design decision (e.g., a file format, protocol detail, or data
|
|
82
|
+
shape) is encoded in more than one module, so changing it requires coordinated edits
|
|
83
|
+
in multiple places even though only one module "owns" the concept
|
|
84
|
+
|
|
85
|
+
### Sources
|
|
86
|
+
|
|
87
|
+
| Symptom | Book | Principle / Smell |
|
|
88
|
+
|---------|------|-------------------|
|
|
89
|
+
| Shotgun Surgery | Fowler — Refactoring | Shotgun Surgery |
|
|
90
|
+
| Divergent Change | Fowler — Refactoring | Divergent Change |
|
|
91
|
+
| Feature Envy | Fowler — Refactoring | Feature Envy |
|
|
92
|
+
| Inappropriate Intimacy | Fowler — Refactoring | Inappropriate Intimacy |
|
|
93
|
+
| Orthogonality violation | Hunt & Thomas — The Pragmatic Programmer | Ch. 2: Orthogonality |
|
|
94
|
+
| DIP violation | Martin — Clean Architecture | Dependency Inversion Principle |
|
|
95
|
+
| High change propagation radius | Brooks — The Mythical Man-Month | Ch. 2: Brooks's Law (communication overhead) |
|
|
96
|
+
| Hyrum's Law | Winters et al. — Software Engineering at Google | Ch. 1: Hyrum's Law |
|
|
97
|
+
| Information Leakage | Ousterhout — A Philosophy of Software Design | Ch. 5: Information Hiding and Leakage |
|
|
98
|
+
|
|
99
|
+
### Severity Guide
|
|
100
|
+
|
|
101
|
+
- 🔴 Critical: one change touches > 5 files, or there is a structural dependency inversion (domain depends on infrastructure)
|
|
102
|
+
- 🟡 Warning: one change touches 3–5 files, mild coupling between modules
|
|
103
|
+
- 🟢 Suggestion: minor coupling, easily isolatable
|
|
104
|
+
|
|
105
|
+
### What Not to Flag
|
|
106
|
+
|
|
107
|
+
- A composition root wiring concrete dependencies is not a DIP violation by itself
|
|
108
|
+
- A stable public API with intentionally supported behavior is not automatically Hyrum's Law debt
|
|
109
|
+
- Similar edits inside one bounded context may be normal coordinated change, not shotgun surgery
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Risk 3: Knowledge Duplication
|
|
114
|
+
|
|
115
|
+
**Diagnostic question:** Is the same decision expressed in more than one place?
|
|
116
|
+
|
|
117
|
+
Multiple copies drift apart silently. DRY is about decisions, not code lines.
|
|
118
|
+
|
|
119
|
+
### Symptoms
|
|
120
|
+
|
|
121
|
+
- Same logic copy-pasted across multiple files or functions
|
|
122
|
+
- Same concept named differently in different parts of the codebase
|
|
123
|
+
(e.g., `user`, `account`, `member`, `customer` all referring to the same domain entity)
|
|
124
|
+
- Parallel class hierarchies that must change in sync
|
|
125
|
+
(e.g., adding a new payment type requires adding a class in 3 different hierarchies)
|
|
126
|
+
- Configuration values repeated as literals in multiple places
|
|
127
|
+
- Two modules that implement the same algorithm independently
|
|
128
|
+
|
|
129
|
+
### Sources
|
|
130
|
+
|
|
131
|
+
| Symptom | Book | Principle / Smell |
|
|
132
|
+
|---------|------|-------------------|
|
|
133
|
+
| Code duplication | Fowler — Refactoring | Duplicate Code |
|
|
134
|
+
| Parallel Inheritance | Fowler — Refactoring | Parallel Inheritance Hierarchies |
|
|
135
|
+
| DRY violation | Hunt & Thomas — The Pragmatic Programmer | DRY: Don't Repeat Yourself |
|
|
136
|
+
| Inconsistent naming | Evans — Domain-Driven Design | Ubiquitous Language |
|
|
137
|
+
| Alternative Classes | Fowler — Refactoring | Alternative Classes with Different Interfaces |
|
|
138
|
+
|
|
139
|
+
### Severity Guide
|
|
140
|
+
|
|
141
|
+
- 🔴 Critical: core business logic duplicated across modules, or same domain concept named 3+ different ways
|
|
142
|
+
- 🟡 Warning: utility code duplicated, naming inconsistent within a subsystem
|
|
143
|
+
- 🟢 Suggestion: minor literal duplication, single naming inconsistency
|
|
144
|
+
|
|
145
|
+
### What Not to Flag
|
|
146
|
+
|
|
147
|
+
- Repetition across separate bounded contexts is not automatically duplicate knowledge
|
|
148
|
+
- Temporary duplication during an active extraction or migration is not necessarily debt
|
|
149
|
+
- Shared protocol constants repeated at explicit boundaries may be acceptable when local ownership is clearer
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Risk 4: Accidental Complexity
|
|
154
|
+
|
|
155
|
+
**Diagnostic question:** Is the code more complex than the problem it solves?
|
|
156
|
+
|
|
157
|
+
Accidental complexity accumulates addition by addition until developers fight scaffolding more than solving the problem.
|
|
158
|
+
|
|
159
|
+
### Symptoms
|
|
160
|
+
|
|
161
|
+
- Abstractions built "for future use" with no current consumer
|
|
162
|
+
(e.g., a plugin system for a use case that has only one known implementation)
|
|
163
|
+
- Classes that barely justify their existence (wrap a single method call)
|
|
164
|
+
- Classes that only delegate to another class without adding behavior (pure middle-men)
|
|
165
|
+
- Second attempt at a system that is significantly more elaborate than the first,
|
|
166
|
+
adding generality for requirements that do not yet exist
|
|
167
|
+
- Switch statements that signal missing polymorphism
|
|
168
|
+
- Configuration options that have never been changed from their defaults
|
|
169
|
+
- Framework code larger than the application it powers
|
|
170
|
+
- Code grown under sustained tactical shortcuts: each workaround seemed small, but
|
|
171
|
+
accumulated shortcuts mean every new feature requires fighting the existing structure
|
|
172
|
+
|
|
173
|
+
### Sources
|
|
174
|
+
|
|
175
|
+
| Symptom | Book | Principle / Smell |
|
|
176
|
+
|---------|------|-------------------|
|
|
177
|
+
| Speculative Generality | Fowler — Refactoring | Speculative Generality |
|
|
178
|
+
| Lazy Class | Fowler — Refactoring | Lazy Class |
|
|
179
|
+
| Middle Man | Fowler — Refactoring | Middle Man |
|
|
180
|
+
| Switch Statements | Fowler — Refactoring | Switch Statements |
|
|
181
|
+
| Second System Effect | Brooks — The Mythical Man-Month | Ch. 5: The Second-System Effect |
|
|
182
|
+
| YAGNI violations | McConnell — Code Complete | Ch. 5: Design in Construction |
|
|
183
|
+
| Over-engineering | Hunt & Thomas — The Pragmatic Programmer | Topic 4: Good-Enough Software |
|
|
184
|
+
| Tactical programming debt | Ousterhout — A Philosophy of Software Design | Ch. 3: Strategic vs. Tactical Programming |
|
|
185
|
+
|
|
186
|
+
### Severity Guide
|
|
187
|
+
|
|
188
|
+
- 🔴 Critical: an entire subsystem built around a speculative requirement, or framework overhead dominates domain logic
|
|
189
|
+
- 🟡 Warning: several unnecessary abstractions or wrapper classes, unused configuration systems
|
|
190
|
+
- 🟢 Suggestion: one or two lazy classes or middle-man patterns in non-critical paths
|
|
191
|
+
|
|
192
|
+
### What Not to Flag
|
|
193
|
+
|
|
194
|
+
- A switch over an external protocol, wire format, or closed enum is not automatically missing polymorphism
|
|
195
|
+
- Thin wrappers that absorb vendor churn or hide instability may be justified
|
|
196
|
+
- A larger second version is not second-system effect unless the added generality exceeds present needs
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Risk 5: Dependency Disorder
|
|
201
|
+
|
|
202
|
+
**Diagnostic question:** Do dependencies flow in a consistent, predictable direction?
|
|
203
|
+
|
|
204
|
+
When business logic depends on infrastructure, infrastructure changes cascade into domain changes. Cycles prevent isolation.
|
|
205
|
+
|
|
206
|
+
### Symptoms
|
|
207
|
+
|
|
208
|
+
- Circular dependencies between modules or packages
|
|
209
|
+
- High-level business logic directly imports from low-level infrastructure
|
|
210
|
+
(e.g., a domain service imports from a specific database driver)
|
|
211
|
+
- Stable, widely-used components depend on unstable, frequently-changing ones
|
|
212
|
+
- Abstract components depending on concrete implementations
|
|
213
|
+
- Law of Demeter violations: `order.getCustomer().getAddress().getCity()`
|
|
214
|
+
- Module fan-out greater than 5 (imports from more than 5 other modules)
|
|
215
|
+
- A module implements an interface but only uses a subset of its methods, or must
|
|
216
|
+
provide stub implementations for methods it does not need (ISP violation: fat interface
|
|
217
|
+
forces unwanted dependencies on callers)
|
|
218
|
+
- The system feels like "one mind did not design this" — different modules use
|
|
219
|
+
incompatible architectural patterns with no clear rule for which to use where
|
|
220
|
+
- Direct version-pinned dependencies on transitive packages (diamond dependency risk);
|
|
221
|
+
upgrading one library requires coordinating multiple unrelated teams or repositories
|
|
222
|
+
|
|
223
|
+
### Sources
|
|
224
|
+
|
|
225
|
+
| Symptom | Book | Principle / Smell |
|
|
226
|
+
|---------|------|-------------------|
|
|
227
|
+
| Dependency cycles | Martin — Clean Architecture | Acyclic Dependencies Principle (ADP) |
|
|
228
|
+
| DIP violation | Martin — Clean Architecture | Dependency Inversion Principle (DIP) |
|
|
229
|
+
| Instability direction | Martin — Clean Architecture | Stable Dependencies Principle (SDP) |
|
|
230
|
+
| Abstraction mismatch | Martin — Clean Architecture | Stable Abstractions Principle (SAP) |
|
|
231
|
+
| ISP violation | Martin — Clean Architecture | Interface Segregation Principle (ISP) |
|
|
232
|
+
| Conceptual integrity | Brooks — The Mythical Man-Month | Ch. 4: Conceptual Integrity |
|
|
233
|
+
| Law of Demeter | Hunt & Thomas — The Pragmatic Programmer | Ch. 5: Decoupling and the Law of Demeter |
|
|
234
|
+
| SOLID violations | Martin — Clean Architecture | Single Responsibility, Open/Closed Principles |
|
|
235
|
+
| Diamond dependency / upgrade blockage | Winters et al. — Software Engineering at Google | Ch. 21: Dependency Management |
|
|
236
|
+
|
|
237
|
+
### Severity Guide
|
|
238
|
+
|
|
239
|
+
- 🔴 Critical: dependency cycles present, or domain layer directly depends on infrastructure layer
|
|
240
|
+
- 🟡 Warning: several SDP or DIP violations but no cycles; conceptual inconsistency across modules
|
|
241
|
+
- 🟢 Suggestion: minor Demeter violations, slightly elevated fan-out in isolated modules
|
|
242
|
+
|
|
243
|
+
### What Not to Flag
|
|
244
|
+
|
|
245
|
+
- High fan-out in an orchestration layer or composition root is not automatically disorder
|
|
246
|
+
- Adapter modules may depend on both domain and infrastructure when they explicitly translate across the boundary
|
|
247
|
+
- A stable facade over many leaf dependencies can be healthy if dependency policy is clear
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Risk 6: Domain Model Distortion
|
|
252
|
+
|
|
253
|
+
**Diagnostic question:** Does the code faithfully represent the problem it is solving?
|
|
254
|
+
|
|
255
|
+
Code that mismatches business language forces mental translation. Over time it models schemas instead of the domain, with logic bleeding into service layers.
|
|
256
|
+
|
|
257
|
+
### Symptoms
|
|
258
|
+
|
|
259
|
+
- Business logic scattered across service layers while domain objects have only getters and setters
|
|
260
|
+
(anemic domain model)
|
|
261
|
+
- Code variable, class, or method names that do not match what business stakeholders call the concept
|
|
262
|
+
- A class whose only purpose is to hold data with no behavior (pure data bag)
|
|
263
|
+
- A subclass that ignores or overrides most of its parent's behavior (refuses the inheritance)
|
|
264
|
+
- Bounded context boundaries crossed without any translation or anti-corruption layer
|
|
265
|
+
- Methods that are more interested in the data of another class than their own
|
|
266
|
+
(domain logic in the wrong place)
|
|
267
|
+
- A subclass overrides most parent methods with incompatible behavior or throws exceptions
|
|
268
|
+
where the parent contract guarantees success (LSP violation: substitution breaks callers)
|
|
269
|
+
- Value Objects treated as Entities: a concept defined entirely by its attributes (e.g., Money,
|
|
270
|
+
Email, Address) is given a mutable ID and lifecycle instead of being replaced when changed
|
|
271
|
+
|
|
272
|
+
### Sources
|
|
273
|
+
|
|
274
|
+
| Symptom | Book | Principle / Smell |
|
|
275
|
+
|---------|------|-------------------|
|
|
276
|
+
| Anemic Domain Model | Evans — Domain-Driven Design | Domain Model pattern |
|
|
277
|
+
| Ubiquitous Language drift | Evans — Domain-Driven Design | Ubiquitous Language |
|
|
278
|
+
| Bounded context violation | Evans — Domain-Driven Design | Bounded Context |
|
|
279
|
+
| Data Class | Fowler — Refactoring | Data Class |
|
|
280
|
+
| Refused Bequest | Fowler — Refactoring | Refused Bequest |
|
|
281
|
+
| Feature Envy | Fowler — Refactoring | Feature Envy |
|
|
282
|
+
| LSP violation | Martin — Clean Architecture | Liskov Substitution Principle (LSP) |
|
|
283
|
+
|
|
284
|
+
### Severity Guide
|
|
285
|
+
|
|
286
|
+
- 🔴 Critical: domain logic entirely in service layer, domain objects are pure data bags with no behavior
|
|
287
|
+
- 🟡 Warning: partial anemia, some naming inconsistency between code and domain language
|
|
288
|
+
- 🟢 Suggestion: minor naming drift in non-core areas, isolated cases of Feature Envy
|
|
289
|
+
|
|
290
|
+
### What Not to Flag
|
|
291
|
+
|
|
292
|
+
- CRUD-heavy workflows may legitimately use transaction scripts instead of rich domain objects
|
|
293
|
+
- DTOs, persistence records, and API payload models are allowed to be data-only
|
|
294
|
+
- Shared infrastructure language should not be mistaken for domain drift if the business model itself is simple
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Remedy Guide — Actionable Fix Mode
|
|
2
|
+
|
|
3
|
+
When `--fix` is active, enhance every finding's Remedy field to be directly actionable:
|
|
4
|
+
|
|
5
|
+
## Remedy Enhancement Rules
|
|
6
|
+
|
|
7
|
+
For each finding, the Remedy must include:
|
|
8
|
+
1. **Target**: exact file path and function/class name
|
|
9
|
+
2. **Action**: specific refactoring operation (e.g., "Extract lines 45-67 into a new
|
|
10
|
+
function `calculateShippingCost(items, config)`")
|
|
11
|
+
3. **Rationale**: one sentence explaining why this specific fix (not just "refactor")
|
|
12
|
+
|
|
13
|
+
## Fixability Classification
|
|
14
|
+
|
|
15
|
+
Classify each finding after writing the enhanced Remedy:
|
|
16
|
+
|
|
17
|
+
| Tier | Criteria | Report label |
|
|
18
|
+
|------|---------|-------------|
|
|
19
|
+
| Quick fix | Single-file, mechanical: rename, extract constant, reorder imports | `[quick-fix]` |
|
|
20
|
+
| Guided fix | Requires a design choice: where to split, what interface shape | `[guided]` |
|
|
21
|
+
| Manual | Cross-module, needs domain knowledge or team discussion | `[manual]` |
|
|
22
|
+
|
|
23
|
+
Append the label to the finding title: `**R1 — Long function in OrderService [quick-fix]**`
|
|
24
|
+
|
|
25
|
+
## Output Addition
|
|
26
|
+
|
|
27
|
+
After the standard report, add a **Fix Summary** section:
|
|
28
|
+
|
|
29
|
+
| Finding | Tier | Target File | Action |
|
|
30
|
+
|---------|------|------------|--------|
|
|
31
|
+
| R1 — Long function | quick-fix | src/order.ts:45 | Extract `calculateTotal()` |
|
|
32
|
+
| R5 — Circular dep | manual | src/models/ ↔ src/services/ | Introduce interface boundary |
|
|
33
|
+
|
|
34
|
+
## What NOT to do
|
|
35
|
+
- Do NOT modify any files. Phase 1 is diagnosis + actionable plan only.
|
|
36
|
+
- Do NOT generate diffs or code blocks. The Remedy text IS the deliverable.
|
|
37
|
+
- Do NOT re-score. The Health Score reflects current state, not projected state.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
---
|
|
2
|
+
books:
|
|
3
|
+
- The Mythical Man-Month
|
|
4
|
+
- Code Complete
|
|
5
|
+
- Refactoring
|
|
6
|
+
- Clean Architecture
|
|
7
|
+
- The Pragmatic Programmer
|
|
8
|
+
- Domain-Driven Design
|
|
9
|
+
- A Philosophy of Software Design
|
|
10
|
+
- Software Engineering at Google
|
|
11
|
+
- xUnit Test Patterns
|
|
12
|
+
- The Art of Unit Testing
|
|
13
|
+
- Working Effectively with Legacy Code
|
|
14
|
+
- How Google Tests Software
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Source Coverage Matrix
|
|
18
|
+
|
|
19
|
+
Use this file after selecting a mode and before writing findings.
|
|
20
|
+
It exists to prevent shallow "book-name citation" reviews.
|
|
21
|
+
|
|
22
|
+
## Review Discipline
|
|
23
|
+
|
|
24
|
+
- Cite a book only when the observed symptom actually matches that book's principle.
|
|
25
|
+
- A threshold crossing is a hint, not a verdict. Check context, intent, and blast radius.
|
|
26
|
+
- Look for justified tradeoffs before flagging a smell as debt.
|
|
27
|
+
- Prefer concrete architectural or domain consequences over abstract style complaints.
|
|
28
|
+
- If two books pull in different directions, state the tradeoff instead of pretending there is no tension.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Frederick Brooks — *The Mythical Man-Month*
|
|
33
|
+
|
|
34
|
+
**Encoded today**
|
|
35
|
+
- Change propagation as communication overhead
|
|
36
|
+
- Second-System Effect
|
|
37
|
+
- Conceptual Integrity
|
|
38
|
+
|
|
39
|
+
**Do not ignore**
|
|
40
|
+
- Whether the design shows a single coherent idea or competing local optimizations
|
|
41
|
+
- Whether cross-team coordination cost is becoming part of feature cost
|
|
42
|
+
|
|
43
|
+
**Do not over-flag**
|
|
44
|
+
- Large systems are not automatically second systems
|
|
45
|
+
- Multi-module designs are acceptable when they preserve conceptual integrity
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Steve McConnell — *Code Complete*
|
|
50
|
+
|
|
51
|
+
**Encoded today**
|
|
52
|
+
- Routine length, nesting, naming, and magic numbers
|
|
53
|
+
- Construction-phase YAGNI checks
|
|
54
|
+
- Defensive programming and error-handling discipline (guard clauses, input validation,
|
|
55
|
+
explicit error paths, assertions for invariants)
|
|
56
|
+
|
|
57
|
+
**Do not ignore**
|
|
58
|
+
- Whether low-level readability choices compound into operational risk
|
|
59
|
+
- Whether missing error handling makes failure modes invisible to maintainers
|
|
60
|
+
|
|
61
|
+
**Do not over-flag**
|
|
62
|
+
- Small, explicit guard clauses are not cognitive overload
|
|
63
|
+
- A long routine may be acceptable when it is linear, well-named, and single-purpose
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Martin Fowler — *Refactoring*
|
|
68
|
+
|
|
69
|
+
**Encoded today**
|
|
70
|
+
- Long Method, Long Parameter List, Message Chains
|
|
71
|
+
- Shotgun Surgery, Divergent Change, Feature Envy, Inappropriate Intimacy
|
|
72
|
+
- Duplicate Code, Speculative Generality, Lazy Class, Middle Man, Data Class
|
|
73
|
+
- Flag Arguments: boolean parameters that split a function into two behaviors
|
|
74
|
+
- Primitive Obsession: domain concepts expressed as raw primitive types instead of value types
|
|
75
|
+
|
|
76
|
+
**Do not ignore**
|
|
77
|
+
- Whether the code smell is local or systemic
|
|
78
|
+
- Whether a refactoring target has a natural home in the model
|
|
79
|
+
|
|
80
|
+
**Do not over-flag**
|
|
81
|
+
- Temporary duplication during an active extraction is not always debt
|
|
82
|
+
- A data-focused structure is acceptable when it is intentionally a DTO or boundary record
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Robert C. Martin — *Clean Architecture*
|
|
87
|
+
|
|
88
|
+
**Encoded today**
|
|
89
|
+
- DIP, ADP, SDP, SAP, and layering direction
|
|
90
|
+
- ISP: fat interfaces that force callers to depend on methods they do not use
|
|
91
|
+
- LSP: subclasses that break the behavioral contract of their parent type
|
|
92
|
+
- SRP and OCP: classes with multiple reasons to change; modules closed to modification
|
|
93
|
+
but open to extension via abstraction
|
|
94
|
+
|
|
95
|
+
**Do not ignore**
|
|
96
|
+
- Policy vs detail boundaries
|
|
97
|
+
- Whether dependency arrows preserve replaceability and testability
|
|
98
|
+
|
|
99
|
+
**Do not over-flag**
|
|
100
|
+
- Composition roots may depend on concrete infrastructure by design
|
|
101
|
+
- Thin adapter layers can import both directions when they are explicitly boundary glue
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Andrew Hunt & David Thomas — *The Pragmatic Programmer*
|
|
106
|
+
|
|
107
|
+
**Encoded today**
|
|
108
|
+
- Orthogonality
|
|
109
|
+
- DRY
|
|
110
|
+
- Law of Demeter
|
|
111
|
+
|
|
112
|
+
**Do not ignore**
|
|
113
|
+
- Whether knowledge duplication is really duplicated decision-making
|
|
114
|
+
- Whether coupling is accidental or a deliberate local simplification
|
|
115
|
+
|
|
116
|
+
**Do not over-flag**
|
|
117
|
+
- Similar code in different bounded contexts is not automatically a DRY violation
|
|
118
|
+
- Direct object access inside a cohesive aggregate is not always a Demeter problem
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Eric Evans — *Domain-Driven Design*
|
|
123
|
+
|
|
124
|
+
**Encoded today**
|
|
125
|
+
- Ubiquitous Language
|
|
126
|
+
- Bounded Context
|
|
127
|
+
- Anemic Domain Model
|
|
128
|
+
- Entity vs Value Object: objects with identity and lifecycle vs. objects defined solely by
|
|
129
|
+
their attributes (Money, Email, Address should be immutable value types, not mutable entities)
|
|
130
|
+
- Aggregate Roots: who owns the invariant boundary; cross-aggregate access only through the root
|
|
131
|
+
|
|
132
|
+
**Do not ignore**
|
|
133
|
+
- Aggregate boundaries, invariant ownership, and anti-corruption layers
|
|
134
|
+
- Whether names match the business language used by experts
|
|
135
|
+
|
|
136
|
+
**Do not over-flag**
|
|
137
|
+
- CRUD-heavy workflows may legitimately use transaction scripts
|
|
138
|
+
- Thin entities are acceptable when the domain itself is simple
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## John Ousterhout — *A Philosophy of Software Design*
|
|
143
|
+
|
|
144
|
+
**Encoded today**
|
|
145
|
+
- Deep vs shallow modules
|
|
146
|
+
- Strategic vs tactical programming
|
|
147
|
+
- Information Leakage: a design decision encoded in more than one module, creating
|
|
148
|
+
change coupling even when no explicit import exists between the modules
|
|
149
|
+
|
|
150
|
+
**Do not ignore**
|
|
151
|
+
- Interface complexity relative to hidden complexity
|
|
152
|
+
- Whether repeated tactical patches are raising long-term cognitive load
|
|
153
|
+
- Whether a "helper" exposes internal design decisions that callers should not know
|
|
154
|
+
|
|
155
|
+
**Do not over-flag**
|
|
156
|
+
- Internal implementation complexity is fine when the interface stays simple
|
|
157
|
+
- A small wrapper is acceptable when it meaningfully absorbs volatility
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Titus Winters, Tom Manshreck, Hyrum Wright — *Software Engineering at Google*
|
|
162
|
+
|
|
163
|
+
**Encoded today**
|
|
164
|
+
- Hyrum's Law
|
|
165
|
+
- Dependency management and upgrade blockage
|
|
166
|
+
- Code sustainability: whether code as written can be maintained, migrated, and upgraded
|
|
167
|
+
over a multi-year horizon without heroic effort
|
|
168
|
+
- Backward compatibility: whether API changes preserve existing callers or force
|
|
169
|
+
coordinated upgrades across the organization
|
|
170
|
+
|
|
171
|
+
**Do not ignore**
|
|
172
|
+
- De facto APIs created by observable behavior
|
|
173
|
+
- The maintenance cost of exposing too much surface area
|
|
174
|
+
- Whether the dependency graph will allow independent upgrades over time
|
|
175
|
+
|
|
176
|
+
**Do not over-flag**
|
|
177
|
+
- A stable public API is not a liability if it is intentionally supported
|
|
178
|
+
- Fan-out alone is not disorder when dependency policy is explicit and governed
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Gerard Meszaros — *xUnit Test Patterns*
|
|
183
|
+
|
|
184
|
+
**Encoded today**
|
|
185
|
+
- Assertion Roulette, Mystery Guest, General Fixture
|
|
186
|
+
- Eager Test, Lazy Test, Test Code Duplication, Behavior Verification
|
|
187
|
+
- Erratic Test: tests that produce non-deterministic results due to shared state,
|
|
188
|
+
time dependence, or ordering assumptions between tests
|
|
189
|
+
|
|
190
|
+
**Do not ignore**
|
|
191
|
+
- Whether test failures are diagnosable
|
|
192
|
+
- Whether the suite shape amplifies maintenance cost
|
|
193
|
+
|
|
194
|
+
**Do not over-flag**
|
|
195
|
+
- Multiple assertions are acceptable when they express one behavior with one failure story
|
|
196
|
+
- Shared fixtures are acceptable when every field is relevant to the scenario
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Roy Osherove — *The Art of Unit Testing*
|
|
201
|
+
|
|
202
|
+
**Encoded today**
|
|
203
|
+
- Test naming discipline
|
|
204
|
+
- Test isolation
|
|
205
|
+
- Mock usage guidelines
|
|
206
|
+
- Completeness of edge-path tests
|
|
207
|
+
|
|
208
|
+
**Do not ignore**
|
|
209
|
+
- Whether tests verify behavior rather than wiring
|
|
210
|
+
- Whether seams are used to simplify tests, or production code is being contorted for testability
|
|
211
|
+
|
|
212
|
+
**Do not over-flag**
|
|
213
|
+
- A mock is acceptable when the dependency is nondeterministic and the assertion still verifies behavior
|
|
214
|
+
- Naming conventions are guidance; clarity is the goal
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Michael Feathers — *Working Effectively with Legacy Code*
|
|
219
|
+
|
|
220
|
+
**Encoded today**
|
|
221
|
+
- Legacy code as code without tests
|
|
222
|
+
- Sensing and Separation
|
|
223
|
+
- Seams
|
|
224
|
+
- Characterization Tests
|
|
225
|
+
|
|
226
|
+
**Do not ignore**
|
|
227
|
+
- Whether the team can change a risky area safely today
|
|
228
|
+
- Whether the code offers any seam for isolating behavior under change
|
|
229
|
+
|
|
230
|
+
**Do not over-flag**
|
|
231
|
+
- Untested code is not automatically legacy if it is stable and not under active change
|
|
232
|
+
- Characterization tests are most important before modifying unclear existing behavior
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Google Engineering — *How Google Tests Software*
|
|
237
|
+
|
|
238
|
+
**Encoded today**
|
|
239
|
+
- Change coverage vs line coverage
|
|
240
|
+
- Pyramid shape and suite portfolio economics
|
|
241
|
+
|
|
242
|
+
**Do not ignore**
|
|
243
|
+
- Whether the suite reflects business risk, not just percentages
|
|
244
|
+
- Whether expensive tests dominate feedback loops
|
|
245
|
+
|
|
246
|
+
**Do not over-flag**
|
|
247
|
+
- A non-70:20:10 ratio can be healthy when justified by platform constraints or product risk
|
|
248
|
+
- High coverage is useful when paired with meaningful branch and change protection
|