@boshu2/vibe-check 2.0.0 → 2.2.1

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 (61) hide show
  1. package/.agents/plans/2025-12-27-vibe-check-evolution-plan.md +383 -0
  2. package/.agents/research/2025-12-27-vibe-check-evolution.md +352 -0
  3. package/.claude/settings.local.json +8 -2
  4. package/CHANGELOG.md +33 -0
  5. package/CLAUDE.md +201 -26
  6. package/README.md +140 -0
  7. package/dist/analyzers/eldritch.d.ts +40 -0
  8. package/dist/analyzers/eldritch.d.ts.map +1 -0
  9. package/dist/analyzers/eldritch.js +202 -0
  10. package/dist/analyzers/eldritch.js.map +1 -0
  11. package/dist/analyzers/modularity.d.ts +67 -0
  12. package/dist/analyzers/modularity.d.ts.map +1 -0
  13. package/dist/analyzers/modularity.js +254 -0
  14. package/dist/analyzers/modularity.js.map +1 -0
  15. package/dist/cli.js +2 -1
  16. package/dist/cli.js.map +1 -1
  17. package/dist/commands/analyze.d.ts.map +1 -1
  18. package/dist/commands/analyze.js +11 -1
  19. package/dist/commands/analyze.js.map +1 -1
  20. package/dist/commands/audit.d.ts.map +1 -1
  21. package/dist/commands/audit.js +25 -0
  22. package/dist/commands/audit.js.map +1 -1
  23. package/dist/commands/forensics.d.ts +8 -0
  24. package/dist/commands/forensics.d.ts.map +1 -1
  25. package/dist/commands/forensics.js +51 -4
  26. package/dist/commands/forensics.js.map +1 -1
  27. package/dist/commands/index.d.ts +1 -0
  28. package/dist/commands/index.d.ts.map +1 -1
  29. package/dist/commands/index.js +1 -0
  30. package/dist/commands/index.js.map +1 -1
  31. package/dist/commands/modularity.d.ts +27 -0
  32. package/dist/commands/modularity.d.ts.map +1 -0
  33. package/dist/commands/modularity.js +182 -0
  34. package/dist/commands/modularity.js.map +1 -0
  35. package/dist/git.d.ts.map +1 -1
  36. package/dist/git.js +8 -2
  37. package/dist/git.js.map +1 -1
  38. package/dist/metrics/cohesion.d.ts +27 -0
  39. package/dist/metrics/cohesion.d.ts.map +1 -0
  40. package/dist/metrics/cohesion.js +134 -0
  41. package/dist/metrics/cohesion.js.map +1 -0
  42. package/dist/metrics/index.d.ts +8 -0
  43. package/dist/metrics/index.d.ts.map +1 -1
  44. package/dist/metrics/index.js +36 -0
  45. package/dist/metrics/index.js.map +1 -1
  46. package/dist/metrics/investigation.d.ts +25 -0
  47. package/dist/metrics/investigation.d.ts.map +1 -0
  48. package/dist/metrics/investigation.js +115 -0
  49. package/dist/metrics/investigation.js.map +1 -0
  50. package/dist/metrics/tracers.d.ts +28 -0
  51. package/dist/metrics/tracers.d.ts.map +1 -0
  52. package/dist/metrics/tracers.js +117 -0
  53. package/dist/metrics/tracers.js.map +1 -0
  54. package/dist/output/terminal.d.ts.map +1 -1
  55. package/dist/output/terminal.js +34 -1
  56. package/dist/output/terminal.js.map +1 -1
  57. package/dist/types.d.ts +36 -1
  58. package/dist/types.d.ts.map +1 -1
  59. package/docs/ENHANCEMENT-PLAN.md +32 -14
  60. package/package.json +1 -1
  61. package/.claude/skills/typescript-review.md +0 -152
package/README.md CHANGED
@@ -73,12 +73,38 @@ npx @boshu2/vibe-check dashboard
73
73
 
74
74
  ## What It Measures
75
75
 
76
+ ### Core Metrics
77
+
76
78
  | Metric | Question | Target |
77
79
  |--------|----------|--------|
78
80
  | **Trust Pass Rate** | Does the code stick? | >95% |
79
81
  | **Rework Ratio** | Building or debugging? | <30% |
80
82
  | **Debug Spirals** | Are you stuck? | 0 active |
81
83
 
84
+ ### Enhanced Metrics (v2.2.0)
85
+
86
+ Three deeper metrics for understanding development habits:
87
+
88
+ | Metric | Question | Target |
89
+ |--------|----------|--------|
90
+ | **Tracer Bullet Ratio** | Are you validating assumptions? | >20% |
91
+ | **Investigation Time** | How much hidden debugging? | 0 min |
92
+ | **Domain Cohesion** | Are changes focused? | >80% |
93
+
94
+ **Tracer Bullets** — Use `tracer:` or `tb:` prefix for validation commits:
95
+
96
+ ```
97
+ tracer(auth): validate OAuth token refresh
98
+ tb(api): test streaming endpoint response
99
+ ```
100
+
101
+ - Tracers **before features** = proactive validation ✅
102
+ - Tracers **before fixes** = reactive debugging ❌ (too late!)
103
+
104
+ **Investigation Gaps** — Detects hidden debugging time (15-120 min gaps followed by fix commits).
105
+
106
+ **Domain Cohesion** — Measures how scattered changes are. Single-domain commits indicate clean vertical slices.
107
+
82
108
  ---
83
109
 
84
110
  ## The 12 Failure Patterns
@@ -187,6 +213,34 @@ vibe-check profile # XP and achievements
187
213
  vibe-check insights # Your spiral patterns
188
214
  ```
189
215
 
216
+ ### Code Quality
217
+
218
+ ```bash
219
+ vibe-check audit # Scan for monoliths, test gaps, TODOs, eldritch horrors
220
+ vibe-check modularity # Pattern-aware modularity analysis
221
+ vibe-check modularity --verbose # Detailed breakdown with metrics
222
+ vibe-check modularity -f json # JSON output for CI integration
223
+ ```
224
+
225
+ #### Audit Command (v2.2.0)
226
+
227
+ The `audit` command now includes **Eldritch Horror Detection**—identifying oversized functions that are symptomatic of AI-generated code gone wrong:
228
+
229
+ ```
230
+ 👹 Eldritch Horrors (oversized functions):
231
+ src/services/auth.ts:45
232
+ handleAuthentication: 523 lines (CRITICAL)
233
+ src/api/routes.ts:120
234
+ processRequest: 287 lines (warning)
235
+ ```
236
+
237
+ | Severity | Threshold | What It Means |
238
+ |----------|-----------|---------------|
239
+ | Warning | >200 lines | Hard to understand |
240
+ | Critical | >500 lines | Impossible to maintain |
241
+
242
+ Supports: TypeScript, JavaScript, Python, Go
243
+
190
244
  ### Tools
191
245
 
192
246
  ```bash
@@ -241,6 +295,92 @@ When inner loop issues are detected:
241
295
 
242
296
  ---
243
297
 
298
+ ## Modularity Analysis
299
+
300
+ Goes beyond simple LOC counting to assess whether large files are well-organized or problematic.
301
+
302
+ ```bash
303
+ vibe-check modularity
304
+ ```
305
+
306
+ ```
307
+ 📐 Modularity Analysis
308
+ ────────────────────────────────────────────────────────────
309
+
310
+ Analyzed 584 files (195,345 lines)
311
+ Average modularity score: 9.5/10
312
+
313
+ Score Distribution:
314
+ Elite (9-10): ████████████████░░░░ 82%
315
+ Good (7-8): ███░░░░░░░░░░░░░░░░░ 15%
316
+ Acceptable (5-6): ░░░░░░░░░░░░░░░░░░░░ 2%
317
+ Needs Work (3-4): ░░░░░░░░░░░░░░░░░░░░ 1%
318
+ Poor (0-2): ░░░░░░░░░░░░░░░░░░░░ 0%
319
+
320
+ ⚠️ Files Needing Attention (8):
321
+
322
+ 6/10 stores/network.js 1023 lines [state-machine]
323
+ ⚠ no sections/organization
324
+ 5/10 server/WebSocketGateway.ts 702 lines
325
+ ⚠ no sections/organization
326
+ 4/10 client/App.tsx 568 lines [component]
327
+ ⚠ no sections/organization, ⚠ high coupling
328
+
329
+ 👍 Good modularity. Minor improvements possible.
330
+ ```
331
+
332
+ ### Pattern-Aware Scoring
333
+
334
+ A 2,500-line file can score **10/10** if well-organized. A 300-line file can score **4/10** if it's a mess.
335
+
336
+ | Factor | Impact | What It Checks |
337
+ |--------|--------|----------------|
338
+ | **Pattern Match** | +1 | Is it a controller/store/routes/state-machine? |
339
+ | **Internal Sections** | +1/-2 | Does it use `// ====` dividers or nested classes? |
340
+ | **Single Responsibility** | +2/-2 | Can purpose be described in one sentence? |
341
+ | **Coupling** | -1/-2 | >15 imports = high coupling warning |
342
+ | **Export Surface** | -1 | >20 exports = bloated API |
343
+
344
+ ### Pattern-Specific Thresholds
345
+
346
+ Different file types have different acceptable sizes:
347
+
348
+ | Pattern | Yellow | Red | Why |
349
+ |---------|--------|-----|-----|
350
+ | `store` | 1,500 | 2,500 | Data layer naturally groups many methods |
351
+ | `controller` | 800 | 1,200 | K8s-style with reconciliation loops |
352
+ | `routes` | 1,000 | 1,500 | Vertical slice entry points |
353
+ | `component` | 250 | 400 | React components should stay focused |
354
+ | `utility` | 150 | 250 | Utilities should be smallest |
355
+
356
+ ### Automatic Exemptions
357
+
358
+ These patterns skip modularity checks:
359
+ - `*.test.ts` — Tests can be comprehensive
360
+ - `*.generated.ts` — Generated files
361
+ - Type definition files — Central types are OK to be large
362
+
363
+ ### Forensics Integration
364
+
365
+ Modularity is also included in `vibe-check forensics` for complete code health analysis:
366
+
367
+ ```bash
368
+ vibe-check forensics
369
+ ```
370
+
371
+ ```
372
+ Modularity Health:
373
+ Average Score: 9.5/10 (303 files analyzed)
374
+ ⚠️ 8 files need attention:
375
+ 6/10 stores/network.js 1023 lines (no-internal-structure)
376
+ 5/10 server/WebSocketGateway.ts 702 lines
377
+ ...
378
+ ```
379
+
380
+ Poor modularity (score <5) triggers the **SWEEP** recommendation alongside commit pattern issues.
381
+
382
+ ---
383
+
244
384
  ## For Autonomous Agents
245
385
 
246
386
  vibe-check measures **human-AI collaboration sessions**—the inner loop where you're working with an AI assistant.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Eldritch Horror Detector
3
+ *
4
+ * Detects oversized functions that are symptomatic of the "Eldritch Horror"
5
+ * middle loop failure pattern from vibe coding. This pattern occurs when
6
+ * AI generates monolithic functions that are impossible to understand.
7
+ *
8
+ * Thresholds:
9
+ * - Warning: Functions > 200 lines
10
+ * - Critical: Functions > 500 lines
11
+ *
12
+ * Detection is heuristic-based (not full AST parsing) to keep it fast
13
+ * and work across multiple languages.
14
+ */
15
+ export interface EldritchHorror {
16
+ file: string;
17
+ functionName: string;
18
+ lineStart: number;
19
+ lineCount: number;
20
+ severity: 'warning' | 'critical';
21
+ }
22
+ export interface EldritchHorrorResult {
23
+ detected: boolean;
24
+ horrors: EldritchHorror[];
25
+ totalCount: number;
26
+ criticalCount: number;
27
+ warningCount: number;
28
+ }
29
+ /**
30
+ * Detect oversized functions in source files.
31
+ *
32
+ * @param files - List of file paths to analyze
33
+ * @returns Detection result with list of horrors
34
+ */
35
+ export declare function detectEldritchHorrors(files: string[]): EldritchHorrorResult;
36
+ /**
37
+ * Run eldritch horror detection on a directory.
38
+ */
39
+ export declare function scanForHorrors(dir: string): EldritchHorrorResult;
40
+ //# sourceMappingURL=eldritch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eldritch.d.ts","sourceRoot":"","sources":["../../src/analyzers/eldritch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,GAAG,UAAU,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAuB3E;AA8HD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAGhE"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Eldritch Horror Detector
3
+ *
4
+ * Detects oversized functions that are symptomatic of the "Eldritch Horror"
5
+ * middle loop failure pattern from vibe coding. This pattern occurs when
6
+ * AI generates monolithic functions that are impossible to understand.
7
+ *
8
+ * Thresholds:
9
+ * - Warning: Functions > 200 lines
10
+ * - Critical: Functions > 500 lines
11
+ *
12
+ * Detection is heuristic-based (not full AST parsing) to keep it fast
13
+ * and work across multiple languages.
14
+ */
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+ const WARNING_THRESHOLD = 200;
18
+ const CRITICAL_THRESHOLD = 500;
19
+ // Pattern matchers for function declarations across languages
20
+ const FUNCTION_PATTERNS = {
21
+ // JavaScript/TypeScript
22
+ jsFunction: /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(/,
23
+ jsArrow: /^\s*(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(/,
24
+ jsMethod: /^\s*(?:async\s+)?(\w+)\s*\([^)]*\)\s*{/,
25
+ jsClass: /^\s*(?:export\s+)?class\s+(\w+)/,
26
+ // Python
27
+ pyFunction: /^\s*(?:async\s+)?def\s+(\w+)\s*\(/,
28
+ pyClass: /^\s*class\s+(\w+)/,
29
+ // Go
30
+ goFunction: /^\s*func\s+(?:\([^)]+\)\s+)?(\w+)\s*\(/,
31
+ };
32
+ /**
33
+ * Detect oversized functions in source files.
34
+ *
35
+ * @param files - List of file paths to analyze
36
+ * @returns Detection result with list of horrors
37
+ */
38
+ export function detectEldritchHorrors(files) {
39
+ const horrors = [];
40
+ for (const file of files) {
41
+ try {
42
+ const content = fs.readFileSync(file, 'utf-8');
43
+ const fileHorrors = analyzeFile(file, content);
44
+ horrors.push(...fileHorrors);
45
+ }
46
+ catch {
47
+ // Skip files that can't be read
48
+ }
49
+ }
50
+ const criticalCount = horrors.filter((h) => h.severity === 'critical').length;
51
+ const warningCount = horrors.filter((h) => h.severity === 'warning').length;
52
+ return {
53
+ detected: horrors.length > 0,
54
+ horrors: horrors.sort((a, b) => b.lineCount - a.lineCount),
55
+ totalCount: horrors.length,
56
+ criticalCount,
57
+ warningCount,
58
+ };
59
+ }
60
+ /**
61
+ * Analyze a single file for oversized functions.
62
+ */
63
+ function analyzeFile(filePath, content) {
64
+ const horrors = [];
65
+ const lines = content.split('\n');
66
+ const ext = path.extname(filePath).toLowerCase();
67
+ // Determine which patterns to use based on file extension
68
+ const patterns = getPatterns(ext);
69
+ let currentFunction = null;
70
+ for (let i = 0; i < lines.length; i++) {
71
+ const line = lines[i];
72
+ const lineNum = i + 1;
73
+ // Check if this line starts a new function
74
+ for (const pattern of patterns) {
75
+ const match = line.match(pattern);
76
+ if (match) {
77
+ // If we were tracking a function, close it out
78
+ if (currentFunction) {
79
+ const lineCount = lineNum - currentFunction.startLine;
80
+ if (lineCount >= WARNING_THRESHOLD) {
81
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
82
+ }
83
+ }
84
+ currentFunction = {
85
+ name: match[1] || 'anonymous',
86
+ startLine: lineNum,
87
+ braceDepth: countBraces(line),
88
+ };
89
+ break;
90
+ }
91
+ }
92
+ // Track brace depth
93
+ if (currentFunction && !line.match(/^\s*\/\//)) {
94
+ currentFunction.braceDepth += countBraces(line);
95
+ // Check for function end (Python uses indentation, others use braces)
96
+ if (ext === '.py') {
97
+ // For Python, check if we hit a line with less indentation
98
+ // This is a simplified heuristic
99
+ if (i + 1 < lines.length) {
100
+ const nextLine = lines[i + 1];
101
+ if (nextLine.match(/^(?:def|class|@|\S)/) && !nextLine.match(/^\s*#/)) {
102
+ const lineCount = lineNum - currentFunction.startLine + 1;
103
+ if (lineCount >= WARNING_THRESHOLD) {
104
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
105
+ }
106
+ currentFunction = null;
107
+ }
108
+ }
109
+ }
110
+ else if (currentFunction.braceDepth <= 0) {
111
+ // For brace-based languages, function ends when braces balance
112
+ const lineCount = lineNum - currentFunction.startLine + 1;
113
+ if (lineCount >= WARNING_THRESHOLD) {
114
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
115
+ }
116
+ currentFunction = null;
117
+ }
118
+ }
119
+ }
120
+ // Handle function that extends to end of file
121
+ if (currentFunction) {
122
+ const lineCount = lines.length - currentFunction.startLine + 1;
123
+ if (lineCount >= WARNING_THRESHOLD) {
124
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
125
+ }
126
+ }
127
+ return horrors;
128
+ }
129
+ function getPatterns(ext) {
130
+ switch (ext) {
131
+ case '.ts':
132
+ case '.tsx':
133
+ case '.js':
134
+ case '.jsx':
135
+ return [
136
+ FUNCTION_PATTERNS.jsFunction,
137
+ FUNCTION_PATTERNS.jsArrow,
138
+ FUNCTION_PATTERNS.jsMethod,
139
+ ];
140
+ case '.py':
141
+ return [FUNCTION_PATTERNS.pyFunction];
142
+ case '.go':
143
+ return [FUNCTION_PATTERNS.goFunction];
144
+ default:
145
+ // Default to JS-like patterns
146
+ return [FUNCTION_PATTERNS.jsFunction, FUNCTION_PATTERNS.jsMethod];
147
+ }
148
+ }
149
+ function countBraces(line) {
150
+ // Simple brace counting (doesn't handle strings/comments perfectly)
151
+ let count = 0;
152
+ for (const char of line) {
153
+ if (char === '{')
154
+ count++;
155
+ if (char === '}')
156
+ count--;
157
+ }
158
+ return count;
159
+ }
160
+ function createHorror(file, functionName, lineStart, lineCount) {
161
+ return {
162
+ file,
163
+ functionName,
164
+ lineStart,
165
+ lineCount,
166
+ severity: lineCount >= CRITICAL_THRESHOLD ? 'critical' : 'warning',
167
+ };
168
+ }
169
+ /**
170
+ * Run eldritch horror detection on a directory.
171
+ */
172
+ export function scanForHorrors(dir) {
173
+ const files = scanDirectory(dir);
174
+ return detectEldritchHorrors(files);
175
+ }
176
+ // Utility to scan directory (matching audit.ts pattern)
177
+ const IGNORE_DIRS = ['node_modules', 'dist', 'coverage', '.git', '.vibe-check', '__pycache__'];
178
+ function scanDirectory(dir) {
179
+ const results = [];
180
+ try {
181
+ const list = fs.readdirSync(dir);
182
+ for (const file of list) {
183
+ const filePath = path.join(dir, file);
184
+ const stat = fs.statSync(filePath);
185
+ if (stat && stat.isDirectory()) {
186
+ if (!IGNORE_DIRS.includes(file) && !file.startsWith('.')) {
187
+ results.push(...scanDirectory(filePath));
188
+ }
189
+ }
190
+ else {
191
+ if (file.match(/\.(ts|js|jsx|tsx|py|go)$/)) {
192
+ results.push(filePath);
193
+ }
194
+ }
195
+ }
196
+ }
197
+ catch {
198
+ // Silently skip unreadable directories
199
+ }
200
+ return results;
201
+ }
202
+ //# sourceMappingURL=eldritch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eldritch.js","sourceRoot":"","sources":["../../src/analyzers/eldritch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAkB7B,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,8DAA8D;AAC9D,MAAM,iBAAiB,GAAG;IACxB,wBAAwB;IACxB,UAAU,EAAE,sDAAsD;IAClE,OAAO,EAAE,mEAAmE;IAC5E,QAAQ,EAAE,wCAAwC;IAClD,OAAO,EAAE,iCAAiC;IAE1C,SAAS;IACT,UAAU,EAAE,mCAAmC;IAC/C,OAAO,EAAE,mBAAmB;IAE5B,KAAK;IACL,UAAU,EAAE,wCAAwC;CACrD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAe;IACnD,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IAE5E,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;QAC5B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;QAC1D,UAAU,EAAE,OAAO,CAAC,MAAM;QAC1B,aAAa;QACb,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,QAAgB,EAAE,OAAe;IACpD,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAEjD,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,eAAe,GAAmE,IAAI,CAAC;IAE3F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtB,2CAA2C;QAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,KAAK,EAAE,CAAC;gBACV,+CAA+C;gBAC/C,IAAI,eAAe,EAAE,CAAC;oBACpB,MAAM,SAAS,GAAG,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC;oBACtD,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;wBACnC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;oBACnG,CAAC;gBACH,CAAC;gBAED,eAAe,GAAG;oBAChB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,WAAW;oBAC7B,SAAS,EAAE,OAAO;oBAClB,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC;iBAC9B,CAAC;gBACF,MAAM;YACR,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,eAAe,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/C,eAAe,CAAC,UAAU,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;YAEhD,sEAAsE;YACtE,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;gBAClB,2DAA2D;gBAC3D,iCAAiC;gBACjC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;oBACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBAC9B,IAAI,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;wBACtE,MAAM,SAAS,GAAG,OAAO,GAAG,eAAe,CAAC,SAAS,GAAG,CAAC,CAAC;wBAC1D,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;4BACnC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;wBACnG,CAAC;wBACD,eAAe,GAAG,IAAI,CAAC;oBACzB,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IAAI,eAAe,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC;gBAC3C,+DAA+D;gBAC/D,MAAM,SAAS,GAAG,OAAO,GAAG,eAAe,CAAC,SAAS,GAAG,CAAC,CAAC;gBAC1D,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;oBACnC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;gBACnG,CAAC;gBACD,eAAe,GAAG,IAAI,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,eAAe,CAAC,SAAS,GAAG,CAAC,CAAC;QAC/D,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,KAAK,CAAC;QACX,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACT,OAAO;gBACL,iBAAiB,CAAC,UAAU;gBAC5B,iBAAiB,CAAC,OAAO;gBACzB,iBAAiB,CAAC,QAAQ;aAC3B,CAAC;QACJ,KAAK,KAAK;YACR,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACxC,KAAK,KAAK;YACR,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACxC;YACE,8BAA8B;YAC9B,OAAO,CAAC,iBAAiB,CAAC,UAAU,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,oEAAoE;IACpE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CACnB,IAAY,EACZ,YAAoB,EACpB,SAAiB,EACjB,SAAiB;IAEjB,OAAO;QACL,IAAI;QACJ,YAAY;QACZ,SAAS;QACT,SAAS;QACT,QAAQ,EAAE,SAAS,IAAI,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KACnE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,wDAAwD;AACxD,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAE/F,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAEjC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnC,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC/B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzD,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC;oBAC3C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Modularity Analyzer
3
+ *
4
+ * Pattern-aware modularity assessment that goes beyond simple LOC counting.
5
+ * Recognizes that a well-organized 2,500-line file can be more maintainable
6
+ * than a poorly-structured 300-line file.
7
+ *
8
+ * Based on research into:
9
+ * - K8s-style controller patterns
10
+ * - Cohesion metrics (LCOM)
11
+ * - Coupling analysis (CBO, fan-in/fan-out)
12
+ * - Single Responsibility Principle indicators
13
+ */
14
+ export interface ModularityResult {
15
+ files: FileModularity[];
16
+ summary: ModularitySummary;
17
+ exempted: ExemptedFile[];
18
+ }
19
+ export interface FileModularity {
20
+ file: string;
21
+ lines: number;
22
+ pattern: FilePattern | null;
23
+ score: number;
24
+ rating: ModularityRating;
25
+ flags: ModularityFlag[];
26
+ details: ModularityDetails;
27
+ }
28
+ export interface ModularityDetails {
29
+ hasSections: boolean;
30
+ sectionCount: number;
31
+ exportCount: number;
32
+ importCount: number;
33
+ hasNestedClasses: boolean;
34
+ methodCount: number;
35
+ }
36
+ export interface ModularitySummary {
37
+ totalFiles: number;
38
+ totalLines: number;
39
+ avgScore: number;
40
+ distribution: {
41
+ elite: number;
42
+ good: number;
43
+ acceptable: number;
44
+ needsWork: number;
45
+ poor: number;
46
+ };
47
+ largestFiles: {
48
+ file: string;
49
+ lines: number;
50
+ score: number;
51
+ }[];
52
+ }
53
+ export interface ExemptedFile {
54
+ file: string;
55
+ lines: number;
56
+ reason: string;
57
+ }
58
+ export type ModularityRating = 'elite' | 'good' | 'acceptable' | 'needs-work' | 'poor';
59
+ export type ModularityFlag = 'no-single-responsibility' | 'no-internal-structure' | 'high-coupling' | 'low-cohesion' | 'missing-tests' | 'god-class' | 'utility-grab-bag';
60
+ export type FilePattern = 'controller' | 'store' | 'routes' | 'types' | 'state-machine' | 'test' | 'generated' | 'component' | 'middleware' | 'utility';
61
+ export interface ModularityOptions {
62
+ minLines?: number;
63
+ includeAll?: boolean;
64
+ patterns?: FilePattern[];
65
+ }
66
+ export declare function analyzeModularity(rootDir: string, options?: ModularityOptions): ModularityResult;
67
+ //# sourceMappingURL=modularity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modularity.d.ts","sourceRoot":"","sources":["../../src/analyzers/modularity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAChE;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC;AAEvF,MAAM,MAAM,cAAc,GACtB,0BAA0B,GAC1B,uBAAuB,GACvB,eAAe,GACf,cAAc,GACd,eAAe,GACf,WAAW,GACX,kBAAkB,CAAC;AAEvB,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,OAAO,GACP,QAAQ,GACR,OAAO,GACP,eAAe,GACf,MAAM,GACN,WAAW,GACX,WAAW,GACX,YAAY,GACZ,SAAS,CAAC;AAyMd,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAoClB"}