create-shhs 1.0.0 → 1.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/INSTALLATION-GUIDE.md +424 -0
- package/README.md +16 -8
- package/UPDATE-GUIDE.md +500 -0
- package/bin/install.js +20 -0
- package/bin/update.js +396 -0
- package/package.json +8 -6
- package/template/.ai/.shhs-version +1 -0
- package/template/.ai/agents/architecture-reviewer.md +92 -0
- package/template/.ai/agents/fitness-enforcer.md +408 -0
- package/template/.ai/agents/knowledge-curator.md +242 -0
- package/template/.ai/architecture/governance/.gitkeep +7 -0
- package/template/.ai/architecture/governance/fitness/README.md +410 -0
- package/template/.ai/architecture/governance/fitness/config.json +48 -0
- package/template/.ai/architecture/governance/fitness/exemptions.json +20 -0
- package/template/.ai/architecture/governance/fitness/rules.json +102 -0
- package/template/.ai/governance/constitution.md +260 -0
- package/template/.ai/governance/definition-of-done.md +481 -0
- package/template/.ai/knowledge/knowledge-base.md +210 -0
- package/template/.ai/reports/fitness-results.json +201 -0
- package/template/.ai/skills/context7/skill.md +458 -0
- package/template/.ai/skills/playwright/skill.md +565 -0
- package/template/.ai/skills/tdd/skill.md +416 -0
- package/template/CLAUDE.md +51 -13
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# Fitness Functions — Usage Guide
|
|
2
|
+
|
|
3
|
+
**Purpose:** Automate enforcement of architectural constraints to prevent decay.
|
|
4
|
+
|
|
5
|
+
**Owner:** Fitness Enforcer Agent
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What Are Fitness Functions?
|
|
10
|
+
|
|
11
|
+
Architectural fitness functions are automated tests of structural properties.
|
|
12
|
+
|
|
13
|
+
Unlike traditional tests (which verify behavior), fitness functions verify **architecture compliance**.
|
|
14
|
+
|
|
15
|
+
**Examples:**
|
|
16
|
+
- "Presentation layer cannot import database layer"
|
|
17
|
+
- "No module may have >10 dependencies"
|
|
18
|
+
- "Domain boundaries must not leak"
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Directory Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
.ai/architecture/governance/fitness/
|
|
26
|
+
├── README.md # This file
|
|
27
|
+
├── config.json # Enforcement mode and settings
|
|
28
|
+
├── rules.json # Fitness function definitions
|
|
29
|
+
└── exemptions.json # Temporary overrides
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
### `config.json`
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mode": "PREVENT",
|
|
41
|
+
"exemptions_enabled": true,
|
|
42
|
+
"metrics_retention_days": 365,
|
|
43
|
+
"report_output": ".ai/reports/fitness-violations.json",
|
|
44
|
+
"trend_analysis_enabled": true
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Mode:**
|
|
49
|
+
- `DETECT`: Log violations, allow merge (for legacy codebases)
|
|
50
|
+
- `PREVENT`: Block merge on BLOCK-severity violations (for strict governance)
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Defining Fitness Rules
|
|
55
|
+
|
|
56
|
+
### `rules.json`
|
|
57
|
+
|
|
58
|
+
Each rule has:
|
|
59
|
+
|
|
60
|
+
| Field | Description |
|
|
61
|
+
|-------|-------------|
|
|
62
|
+
| `id` | Unique identifier (kebab-case) |
|
|
63
|
+
| `description` | Human-readable explanation |
|
|
64
|
+
| `condition` | What to measure |
|
|
65
|
+
| `threshold` | Acceptable limit |
|
|
66
|
+
| `severity` | `WARN` or `BLOCK` |
|
|
67
|
+
| `scope` | Glob pattern for files |
|
|
68
|
+
|
|
69
|
+
### Condition Types
|
|
70
|
+
|
|
71
|
+
#### 1. Import Pattern
|
|
72
|
+
|
|
73
|
+
Detects forbidden imports.
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"type": "import_pattern",
|
|
78
|
+
"pattern": "src/presentation/.*\\.ts imports (prisma|database).*"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### 2. Dependency Count
|
|
83
|
+
|
|
84
|
+
Counts direct dependencies per file.
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"type": "dependency_count",
|
|
89
|
+
"target": "file"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### 3. Centrality
|
|
94
|
+
|
|
95
|
+
Measures how many modules import a given module.
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"type": "centrality",
|
|
100
|
+
"metric": "incoming_dependencies_percentage"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### 4. Complexity
|
|
105
|
+
|
|
106
|
+
Cyclomatic complexity of functions.
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"type": "complexity",
|
|
111
|
+
"metric": "cyclomatic"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Example Rules
|
|
118
|
+
|
|
119
|
+
### Rule: No Cross-Domain Database Access
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"id": "cross-domain-db-access",
|
|
124
|
+
"description": "Domain modules must not directly access other domain databases",
|
|
125
|
+
"condition": {
|
|
126
|
+
"type": "import_pattern",
|
|
127
|
+
"pattern": "src/domain-a/.*\\.ts imports @prisma/client.*domain_b.*"
|
|
128
|
+
},
|
|
129
|
+
"threshold": 0,
|
|
130
|
+
"severity": "BLOCK",
|
|
131
|
+
"scope": "src/domain-*/**/*.ts"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Rule: Max Module Dependencies
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"id": "max-module-dependencies",
|
|
140
|
+
"description": "No module may have more than 10 direct dependencies",
|
|
141
|
+
"condition": {
|
|
142
|
+
"type": "dependency_count",
|
|
143
|
+
"target": "file"
|
|
144
|
+
},
|
|
145
|
+
"threshold": 10,
|
|
146
|
+
"severity": "WARN",
|
|
147
|
+
"scope": "src/**/*.ts"
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Exemptions
|
|
154
|
+
|
|
155
|
+
Temporary overrides for legacy code or justified exceptions.
|
|
156
|
+
|
|
157
|
+
### `exemptions.json`
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"exemptions": [
|
|
162
|
+
{
|
|
163
|
+
"rule_id": "cross-domain-db-access",
|
|
164
|
+
"file": "src/legacy/old-service.ts",
|
|
165
|
+
"reason": "Legacy code pending migration",
|
|
166
|
+
"expires": "2026-06-01",
|
|
167
|
+
"adr": "ADR-0042-legacy-migration-plan.md"
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Rules for Exemptions:**
|
|
174
|
+
- Must reference an ADR
|
|
175
|
+
- Must have expiration date
|
|
176
|
+
- Reviewed monthly
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Running Fitness Functions
|
|
181
|
+
|
|
182
|
+
### Manual Execution
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Run in DETECT mode (log violations)
|
|
186
|
+
fitness-enforcer --mode detect
|
|
187
|
+
|
|
188
|
+
# Run in PREVENT mode (block on violations)
|
|
189
|
+
fitness-enforcer --mode prevent
|
|
190
|
+
|
|
191
|
+
# Run for specific files
|
|
192
|
+
fitness-enforcer --files "src/domain-billing/**/*.ts"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### CI/CD Integration
|
|
196
|
+
|
|
197
|
+
Add to pull request pipeline:
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
# .github/workflows/fitness.yml
|
|
201
|
+
name: Architectural Fitness
|
|
202
|
+
|
|
203
|
+
on: pull_request
|
|
204
|
+
|
|
205
|
+
jobs:
|
|
206
|
+
fitness:
|
|
207
|
+
runs-on: ubuntu-latest
|
|
208
|
+
steps:
|
|
209
|
+
- uses: actions/checkout@v3
|
|
210
|
+
- name: Run Fitness Enforcer
|
|
211
|
+
run: |
|
|
212
|
+
npm run fitness:enforce
|
|
213
|
+
- name: Upload Report
|
|
214
|
+
uses: actions/upload-artifact@v3
|
|
215
|
+
with:
|
|
216
|
+
name: fitness-report
|
|
217
|
+
path: .ai/reports/fitness-violations.json
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Interpreting Reports
|
|
223
|
+
|
|
224
|
+
### Sample Report
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"timestamp": "2026-02-24T10:30:00Z",
|
|
229
|
+
"mode": "PREVENT",
|
|
230
|
+
"status": "FAIL",
|
|
231
|
+
"violations": [
|
|
232
|
+
{
|
|
233
|
+
"rule_id": "cross-domain-db-access",
|
|
234
|
+
"severity": "BLOCK",
|
|
235
|
+
"file": "src/domain-billing/services/invoice.service.ts",
|
|
236
|
+
"line": 42,
|
|
237
|
+
"measured_value": "import { PrismaClient } from '@prisma/client'",
|
|
238
|
+
"threshold": 0,
|
|
239
|
+
"remedy": "Use domain-user's public API instead of direct DB access"
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
"metrics": {
|
|
243
|
+
"total_violations": 1,
|
|
244
|
+
"block_violations": 1,
|
|
245
|
+
"warn_violations": 0
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Actions:**
|
|
251
|
+
- `BLOCK` violations → Fix before merge
|
|
252
|
+
- `WARN` violations → Log technical debt, plan remediation
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Gradual Adoption
|
|
257
|
+
|
|
258
|
+
For existing codebases with violations:
|
|
259
|
+
|
|
260
|
+
### Step 1: Baseline
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
fitness-enforcer --mode detect --baseline
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Creates `.ai/reports/fitness-baseline.json` with current violation counts.
|
|
267
|
+
|
|
268
|
+
### Step 2: Prevent New Violations
|
|
269
|
+
|
|
270
|
+
Switch to PREVENT mode but only for **new or modified files**.
|
|
271
|
+
|
|
272
|
+
### Step 3: Set Reduction Targets
|
|
273
|
+
|
|
274
|
+
Commit to reducing baseline violations by X% per month.
|
|
275
|
+
|
|
276
|
+
### Step 4: Tighten Thresholds
|
|
277
|
+
|
|
278
|
+
Once violations are controlled, lower thresholds progressively.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Common Violations and Fixes
|
|
283
|
+
|
|
284
|
+
### Violation: Cross-Domain Database Access
|
|
285
|
+
|
|
286
|
+
**Problem:**
|
|
287
|
+
```typescript
|
|
288
|
+
// domain-billing accesses domain-user DB directly
|
|
289
|
+
import { PrismaClient } from '@prisma/client';
|
|
290
|
+
const users = await prisma.users.findMany();
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Fix:**
|
|
294
|
+
```typescript
|
|
295
|
+
// Use domain-user's public service
|
|
296
|
+
import { UserService } from '@/domain-user/services';
|
|
297
|
+
const users = await UserService.getAll();
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Violation: Too Many Dependencies
|
|
301
|
+
|
|
302
|
+
**Problem:**
|
|
303
|
+
```typescript
|
|
304
|
+
// god-module.ts has 15 imports
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Fix:**
|
|
308
|
+
- Split into smaller modules by responsibility
|
|
309
|
+
- Extract cross-cutting concerns to shared utilities
|
|
310
|
+
|
|
311
|
+
### Violation: Presentation Layer Importing Database
|
|
312
|
+
|
|
313
|
+
**Problem:**
|
|
314
|
+
```typescript
|
|
315
|
+
// React component imports Prisma
|
|
316
|
+
import { PrismaClient } from '@prisma/client';
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Fix:**
|
|
320
|
+
```typescript
|
|
321
|
+
// Use application layer hook
|
|
322
|
+
import { useUsers } from '@/application/hooks/useUsers';
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Fitness Metrics Dashboard
|
|
328
|
+
|
|
329
|
+
Track architectural health over time.
|
|
330
|
+
|
|
331
|
+
### Metrics Collected
|
|
332
|
+
|
|
333
|
+
- Total violations (trend)
|
|
334
|
+
- BLOCK vs WARN ratio
|
|
335
|
+
- Dependency graph complexity
|
|
336
|
+
- Module coupling score
|
|
337
|
+
- Domain boundary leak count
|
|
338
|
+
|
|
339
|
+
### Visualization
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
fitness-enforcer --report dashboard
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Generates `.ai/reports/fitness-dashboard.html` with charts.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## When to Add New Fitness Functions
|
|
350
|
+
|
|
351
|
+
Add a fitness function when:
|
|
352
|
+
|
|
353
|
+
1. **Recurring Violation Pattern**
|
|
354
|
+
- Code reviews repeatedly catch the same structural issue
|
|
355
|
+
- Automate the check
|
|
356
|
+
|
|
357
|
+
2. **ADR Introduces Constraint**
|
|
358
|
+
- ADR mandates architectural rule
|
|
359
|
+
- Encode as fitness function
|
|
360
|
+
|
|
361
|
+
3. **Architectural Review Recommendation**
|
|
362
|
+
- Architecture Reviewer identifies decay pattern
|
|
363
|
+
- Prevent recurrence with fitness function
|
|
364
|
+
|
|
365
|
+
4. **Bounded Context Addition**
|
|
366
|
+
- New domain added
|
|
367
|
+
- Enforce boundary isolation
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Fitness Function Lifecycle
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
1. Identify architectural constraint
|
|
375
|
+
↓
|
|
376
|
+
2. Encode as fitness rule in rules.json
|
|
377
|
+
↓
|
|
378
|
+
3. Run in DETECT mode to establish baseline
|
|
379
|
+
↓
|
|
380
|
+
4. Switch to PREVENT mode for new code
|
|
381
|
+
↓
|
|
382
|
+
5. Review quarterly — adjust thresholds
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Integration with SHHS
|
|
388
|
+
|
|
389
|
+
Fitness Enforcer runs **after Static Reviewer, before Domain Architect**.
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
Developer → Static Reviewer → Fitness Enforcer → QA → Domain Architect
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Rationale:** Structural compliance must pass before behavioral testing.
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Support
|
|
400
|
+
|
|
401
|
+
For questions on fitness functions:
|
|
402
|
+
|
|
403
|
+
1. Consult this README
|
|
404
|
+
2. Review existing rules in `rules.json`
|
|
405
|
+
3. Check Architecture Review reports in `.ai/architecture/governance/`
|
|
406
|
+
4. Escalate to Architecture Reviewer for new constraint proposals
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
**END OF FITNESS FUNCTIONS GUIDE**
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"description": "Fitness Enforcer configuration",
|
|
4
|
+
"mode": "DETECT",
|
|
5
|
+
"mode_description": "DETECT mode logs violations but allows merge. PREVENT mode blocks merge on BLOCK-severity violations.",
|
|
6
|
+
"exemptions_enabled": true,
|
|
7
|
+
"metrics_retention_days": 365,
|
|
8
|
+
"report_output": ".ai/reports/fitness-violations.json",
|
|
9
|
+
"trend_analysis_enabled": true,
|
|
10
|
+
"settings": {
|
|
11
|
+
"fail_on_block_violations": false,
|
|
12
|
+
"fail_on_warn_violations": false,
|
|
13
|
+
"generate_html_report": true,
|
|
14
|
+
"html_report_path": ".ai/reports/fitness-dashboard.html",
|
|
15
|
+
"baseline_mode": false,
|
|
16
|
+
"baseline_path": ".ai/reports/fitness-baseline.json"
|
|
17
|
+
},
|
|
18
|
+
"tools": {
|
|
19
|
+
"dependency_analysis": {
|
|
20
|
+
"enabled": true,
|
|
21
|
+
"tool": "madge",
|
|
22
|
+
"options": {
|
|
23
|
+
"circular": true,
|
|
24
|
+
"exclude": "node_modules"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"complexity_analysis": {
|
|
28
|
+
"enabled": true,
|
|
29
|
+
"tool": "typescript-complexity",
|
|
30
|
+
"options": {
|
|
31
|
+
"threshold": 15
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"import_analysis": {
|
|
35
|
+
"enabled": true,
|
|
36
|
+
"tool": "eslint",
|
|
37
|
+
"options": {
|
|
38
|
+
"parser": "@typescript-eslint/parser"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"notes": [
|
|
43
|
+
"Start with DETECT mode for baseline establishment",
|
|
44
|
+
"Switch to PREVENT mode once violations are under control",
|
|
45
|
+
"Review exemptions monthly",
|
|
46
|
+
"Adjust thresholds based on trend analysis"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"description": "Temporary exemptions from fitness rules",
|
|
4
|
+
"exemptions": [],
|
|
5
|
+
"example_exemption": {
|
|
6
|
+
"rule_id": "cross-domain-db-access",
|
|
7
|
+
"file": "src/legacy/old-service.ts",
|
|
8
|
+
"reason": "Legacy code pending migration to new domain architecture",
|
|
9
|
+
"expires": "2026-06-01",
|
|
10
|
+
"adr": "ADR-0042-legacy-migration-plan.md",
|
|
11
|
+
"created_by": "architect@example.com",
|
|
12
|
+
"created_at": "2026-02-24"
|
|
13
|
+
},
|
|
14
|
+
"notes": [
|
|
15
|
+
"All exemptions must reference an ADR",
|
|
16
|
+
"All exemptions must have expiration date",
|
|
17
|
+
"Review exemptions monthly",
|
|
18
|
+
"Max 5 active exemptions per project (prevent abuse)"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"description": "Architectural fitness function rules",
|
|
4
|
+
"rules": [
|
|
5
|
+
{
|
|
6
|
+
"id": "cross-domain-db-access",
|
|
7
|
+
"description": "Domain modules must not directly access other domain databases",
|
|
8
|
+
"condition": {
|
|
9
|
+
"type": "import_pattern",
|
|
10
|
+
"pattern": "src/domain-([^/]+)/.*\\.(ts|js) imports (@prisma/client|typeorm|database).*domain-(?!\\1)[^/]+.*"
|
|
11
|
+
},
|
|
12
|
+
"threshold": 0,
|
|
13
|
+
"severity": "BLOCK",
|
|
14
|
+
"scope": "src/domain-*/**/*.{ts,js}",
|
|
15
|
+
"remedy": "Use the target domain's public service API instead of direct database access. Example: UserService.getOrdersByUser() instead of prisma.user_orders.findMany()"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "max-module-dependencies",
|
|
19
|
+
"description": "No module may have more than 10 direct dependencies",
|
|
20
|
+
"condition": {
|
|
21
|
+
"type": "dependency_count",
|
|
22
|
+
"target": "file"
|
|
23
|
+
},
|
|
24
|
+
"threshold": 10,
|
|
25
|
+
"severity": "WARN",
|
|
26
|
+
"scope": "src/**/*.{ts,js}",
|
|
27
|
+
"remedy": "Split into smaller, focused modules. Extract cross-cutting concerns to shared utilities."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "presentation-layer-isolation",
|
|
31
|
+
"description": "Presentation layer must not import database layer",
|
|
32
|
+
"condition": {
|
|
33
|
+
"type": "import_pattern",
|
|
34
|
+
"pattern": "src/presentation/.*\\.(ts|tsx|js|jsx) imports (prisma|typeorm|database|@prisma/client).*"
|
|
35
|
+
},
|
|
36
|
+
"threshold": 0,
|
|
37
|
+
"severity": "BLOCK",
|
|
38
|
+
"scope": "src/presentation/**/*.{ts,tsx,js,jsx}",
|
|
39
|
+
"remedy": "Use application layer hooks or services. Example: useUsers() hook instead of importing PrismaClient."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "module-centrality",
|
|
43
|
+
"description": "No module may be imported by >30% of codebase (god module detection)",
|
|
44
|
+
"condition": {
|
|
45
|
+
"type": "centrality",
|
|
46
|
+
"metric": "incoming_dependencies_percentage"
|
|
47
|
+
},
|
|
48
|
+
"threshold": 30,
|
|
49
|
+
"severity": "WARN",
|
|
50
|
+
"scope": "src/**/*.{ts,js}",
|
|
51
|
+
"remedy": "Refactor god module into smaller, specialized modules. Consider using dependency inversion."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "cyclomatic-complexity",
|
|
55
|
+
"description": "Function cyclomatic complexity must not exceed 15",
|
|
56
|
+
"condition": {
|
|
57
|
+
"type": "complexity",
|
|
58
|
+
"metric": "cyclomatic"
|
|
59
|
+
},
|
|
60
|
+
"threshold": 15,
|
|
61
|
+
"severity": "WARN",
|
|
62
|
+
"scope": "src/**/*.{ts,js}",
|
|
63
|
+
"remedy": "Extract complex conditionals into smaller functions. Apply Single Responsibility Principle."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "no-circular-dependencies",
|
|
67
|
+
"description": "No circular dependencies allowed between modules",
|
|
68
|
+
"condition": {
|
|
69
|
+
"type": "circular_dependency",
|
|
70
|
+
"scope": "module"
|
|
71
|
+
},
|
|
72
|
+
"threshold": 0,
|
|
73
|
+
"severity": "BLOCK",
|
|
74
|
+
"scope": "src/**/*.{ts,js}",
|
|
75
|
+
"remedy": "Break circular dependency by introducing interface/abstraction or restructuring module relationships."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "infrastructure-layer-isolation",
|
|
79
|
+
"description": "Domain layer must not import infrastructure layer",
|
|
80
|
+
"condition": {
|
|
81
|
+
"type": "import_pattern",
|
|
82
|
+
"pattern": "src/domain/.*\\.(ts|js) imports src/infrastructure/.*"
|
|
83
|
+
},
|
|
84
|
+
"threshold": 0,
|
|
85
|
+
"severity": "BLOCK",
|
|
86
|
+
"scope": "src/domain/**/*.{ts,js}",
|
|
87
|
+
"remedy": "Use dependency inversion. Define interfaces in domain layer, implement in infrastructure."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "max-file-length",
|
|
91
|
+
"description": "No file should exceed 500 lines (excluding comments)",
|
|
92
|
+
"condition": {
|
|
93
|
+
"type": "file_length",
|
|
94
|
+
"metric": "lines_of_code"
|
|
95
|
+
},
|
|
96
|
+
"threshold": 500,
|
|
97
|
+
"severity": "WARN",
|
|
98
|
+
"scope": "src/**/*.{ts,js,tsx,jsx}",
|
|
99
|
+
"remedy": "Split large files into smaller, cohesive modules."
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|