@boshu2/vibe-check 1.8.1 → 2.2.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/.agents/plans/2025-12-27-vibe-check-evolution-plan.md +383 -0
- package/.agents/research/2025-12-27-vibe-check-evolution.md +352 -0
- package/.claude/settings.local.json +9 -3
- package/CHANGELOG.md +43 -0
- package/CLAUDE.md +201 -26
- package/Makefile +4 -4
- package/README.md +95 -0
- package/bin/vibe-check.js +1 -1
- package/claude-progress.json +18 -0
- package/dist/analysis/cross-session-analysis.d.ts +1 -1
- package/dist/analysis/cross-session-analysis.d.ts.map +1 -1
- package/dist/analysis/cross-session-analysis.js +9 -18
- package/dist/analysis/cross-session-analysis.js.map +1 -1
- package/dist/analysis/index.d.ts +1 -1
- package/dist/analysis/index.d.ts.map +1 -1
- package/dist/analysis/index.js +1 -11
- package/dist/analysis/index.js.map +1 -1
- package/dist/analyzers/audit.d.ts +28 -0
- package/dist/analyzers/audit.d.ts.map +1 -0
- package/dist/analyzers/audit.js +86 -0
- package/dist/analyzers/audit.js.map +1 -0
- package/dist/analyzers/eldritch.d.ts +40 -0
- package/dist/analyzers/eldritch.d.ts.map +1 -0
- package/dist/analyzers/eldritch.js +202 -0
- package/dist/analyzers/eldritch.js.map +1 -0
- package/dist/analyzers/modularity.d.ts +67 -0
- package/dist/analyzers/modularity.d.ts.map +1 -0
- package/dist/analyzers/modularity.js +254 -0
- package/dist/analyzers/modularity.js.map +1 -0
- package/dist/analyzers/patterns.d.ts +1 -1
- package/dist/analyzers/patterns.d.ts.map +1 -1
- package/dist/analyzers/patterns.js +4 -10
- package/dist/analyzers/patterns.js.map +1 -1
- package/dist/analyzers/quality.d.ts +1 -1
- package/dist/analyzers/quality.d.ts.map +1 -1
- package/dist/analyzers/quality.js +5 -12
- package/dist/analyzers/quality.js.map +1 -1
- package/dist/analyzers/sessions.d.ts +1 -1
- package/dist/analyzers/sessions.d.ts.map +1 -1
- package/dist/analyzers/sessions.js +1 -4
- package/dist/analyzers/sessions.js.map +1 -1
- package/dist/cli.js +21 -20
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +124 -149
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +102 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/cache.js +31 -70
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +22 -58
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/forensics.d.ts +10 -2
- package/dist/commands/forensics.d.ts.map +1 -1
- package/dist/commands/forensics.js +91 -51
- package/dist/commands/forensics.js.map +1 -1
- package/dist/commands/index.d.ts +15 -13
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +15 -33
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init-hook.js +26 -32
- package/dist/commands/init-hook.js.map +1 -1
- package/dist/commands/insights.js +39 -45
- package/dist/commands/insights.js.map +1 -1
- package/dist/commands/modularity.d.ts +27 -0
- package/dist/commands/modularity.d.ts.map +1 -0
- package/dist/commands/modularity.js +182 -0
- package/dist/commands/modularity.js.map +1 -0
- package/dist/commands/pipeline.js +39 -78
- package/dist/commands/pipeline.js.map +1 -1
- package/dist/commands/profile.js +68 -74
- package/dist/commands/profile.js.map +1 -1
- package/dist/commands/session.js +88 -129
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/sessions.d.ts +1 -1
- package/dist/commands/sessions.d.ts.map +1 -1
- package/dist/commands/sessions.js +42 -49
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/start.js +22 -67
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/timeline.js +74 -81
- package/dist/commands/timeline.js.map +1 -1
- package/dist/commands/watch.js +54 -60
- package/dist/commands/watch.js.map +1 -1
- package/dist/gamification/achievements.d.ts +1 -1
- package/dist/gamification/achievements.d.ts.map +1 -1
- package/dist/gamification/achievements.js +7 -13
- package/dist/gamification/achievements.js.map +1 -1
- package/dist/gamification/index.d.ts +8 -8
- package/dist/gamification/index.d.ts.map +1 -1
- package/dist/gamification/index.js +8 -28
- package/dist/gamification/index.js.map +1 -1
- package/dist/gamification/profile.d.ts +2 -2
- package/dist/gamification/profile.d.ts.map +1 -1
- package/dist/gamification/profile.js +21 -64
- package/dist/gamification/profile.js.map +1 -1
- package/dist/gamification/stats.d.ts +1 -1
- package/dist/gamification/stats.d.ts.map +1 -1
- package/dist/gamification/stats.js +4 -10
- package/dist/gamification/stats.js.map +1 -1
- package/dist/gamification/streaks.d.ts +1 -1
- package/dist/gamification/streaks.d.ts.map +1 -1
- package/dist/gamification/streaks.js +8 -18
- package/dist/gamification/streaks.js.map +1 -1
- package/dist/gamification/types.js +3 -6
- package/dist/gamification/types.js.map +1 -1
- package/dist/gamification/xp.d.ts +1 -1
- package/dist/gamification/xp.d.ts.map +1 -1
- package/dist/gamification/xp.js +29 -38
- package/dist/gamification/xp.js.map +1 -1
- package/dist/git.d.ts +1 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +23 -29
- package/dist/git.js.map +1 -1
- package/dist/inner-loop/context-amnesia.d.ts +2 -2
- package/dist/inner-loop/context-amnesia.d.ts.map +1 -1
- package/dist/inner-loop/context-amnesia.js +7 -10
- package/dist/inner-loop/context-amnesia.js.map +1 -1
- package/dist/inner-loop/index.d.ts +7 -7
- package/dist/inner-loop/index.d.ts.map +1 -1
- package/dist/inner-loop/index.js +18 -45
- package/dist/inner-loop/index.js.map +1 -1
- package/dist/inner-loop/instruction-drift.d.ts +2 -2
- package/dist/inner-loop/instruction-drift.d.ts.map +1 -1
- package/dist/inner-loop/instruction-drift.js +5 -10
- package/dist/inner-loop/instruction-drift.js.map +1 -1
- package/dist/inner-loop/logging-only.d.ts +2 -2
- package/dist/inner-loop/logging-only.d.ts.map +1 -1
- package/dist/inner-loop/logging-only.js +9 -17
- package/dist/inner-loop/logging-only.js.map +1 -1
- package/dist/inner-loop/tests-passing-lie.d.ts +2 -2
- package/dist/inner-loop/tests-passing-lie.d.ts.map +1 -1
- package/dist/inner-loop/tests-passing-lie.js +12 -17
- package/dist/inner-loop/tests-passing-lie.js.map +1 -1
- package/dist/inner-loop/types.js +1 -4
- package/dist/inner-loop/types.js.map +1 -1
- package/dist/insights/generators.d.ts +4 -4
- package/dist/insights/generators.d.ts.map +1 -1
- package/dist/insights/generators.js +9 -20
- package/dist/insights/generators.js.map +1 -1
- package/dist/insights/index.d.ts +4 -4
- package/dist/insights/index.d.ts.map +1 -1
- package/dist/insights/index.js +23 -27
- package/dist/insights/index.js.map +1 -1
- package/dist/insights/types.js +1 -2
- package/dist/insights/types.js.map +1 -1
- package/dist/metrics/code-stability.d.ts +1 -1
- package/dist/metrics/code-stability.d.ts.map +1 -1
- package/dist/metrics/code-stability.js +1 -4
- package/dist/metrics/code-stability.js.map +1 -1
- package/dist/metrics/cohesion.d.ts +27 -0
- package/dist/metrics/cohesion.d.ts.map +1 -0
- package/dist/metrics/cohesion.js +134 -0
- package/dist/metrics/cohesion.js.map +1 -0
- package/dist/metrics/file-churn.d.ts +1 -1
- package/dist/metrics/file-churn.d.ts.map +1 -1
- package/dist/metrics/file-churn.js +1 -4
- package/dist/metrics/file-churn.js.map +1 -1
- package/dist/metrics/flow.d.ts +1 -1
- package/dist/metrics/flow.d.ts.map +1 -1
- package/dist/metrics/flow.js +1 -4
- package/dist/metrics/flow.js.map +1 -1
- package/dist/metrics/index.d.ts +10 -2
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +51 -20
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/investigation.d.ts +25 -0
- package/dist/metrics/investigation.d.ts.map +1 -0
- package/dist/metrics/investigation.js +115 -0
- package/dist/metrics/investigation.js.map +1 -0
- package/dist/metrics/rework.d.ts +1 -1
- package/dist/metrics/rework.d.ts.map +1 -1
- package/dist/metrics/rework.js +1 -4
- package/dist/metrics/rework.js.map +1 -1
- package/dist/metrics/spirals.d.ts +1 -1
- package/dist/metrics/spirals.d.ts.map +1 -1
- package/dist/metrics/spirals.js +5 -10
- package/dist/metrics/spirals.js.map +1 -1
- package/dist/metrics/time-spiral.d.ts +1 -1
- package/dist/metrics/time-spiral.d.ts.map +1 -1
- package/dist/metrics/time-spiral.js +1 -4
- package/dist/metrics/time-spiral.js.map +1 -1
- package/dist/metrics/tracers.d.ts +28 -0
- package/dist/metrics/tracers.d.ts.map +1 -0
- package/dist/metrics/tracers.js +117 -0
- package/dist/metrics/tracers.js.map +1 -0
- package/dist/metrics/trust.d.ts +1 -1
- package/dist/metrics/trust.d.ts.map +1 -1
- package/dist/metrics/trust.js +3 -6
- package/dist/metrics/trust.js.map +1 -1
- package/dist/metrics/velocity-anomaly.d.ts +1 -1
- package/dist/metrics/velocity-anomaly.d.ts.map +1 -1
- package/dist/metrics/velocity-anomaly.js +3 -6
- package/dist/metrics/velocity-anomaly.js.map +1 -1
- package/dist/metrics/velocity.d.ts +1 -1
- package/dist/metrics/velocity.d.ts.map +1 -1
- package/dist/metrics/velocity.js +6 -10
- package/dist/metrics/velocity.js.map +1 -1
- package/dist/output/index.d.ts +4 -4
- package/dist/output/index.d.ts.map +1 -1
- package/dist/output/index.js +10 -18
- package/dist/output/index.js.map +1 -1
- package/dist/output/json.d.ts +1 -1
- package/dist/output/json.d.ts.map +1 -1
- package/dist/output/json.js +1 -4
- package/dist/output/json.js.map +1 -1
- package/dist/output/markdown.d.ts +1 -1
- package/dist/output/markdown.d.ts.map +1 -1
- package/dist/output/markdown.js +5 -8
- package/dist/output/markdown.js.map +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/output/terminal.d.ts.map +1 -1
- package/dist/output/terminal.js +88 -62
- package/dist/output/terminal.js.map +1 -1
- package/dist/output/timeline-html.d.ts +1 -1
- package/dist/output/timeline-html.d.ts.map +1 -1
- package/dist/output/timeline-html.js +5 -8
- package/dist/output/timeline-html.js.map +1 -1
- package/dist/output/timeline-markdown.d.ts +1 -1
- package/dist/output/timeline-markdown.d.ts.map +1 -1
- package/dist/output/timeline-markdown.js +5 -8
- package/dist/output/timeline-markdown.js.map +1 -1
- package/dist/output/timeline.d.ts +1 -1
- package/dist/output/timeline.d.ts.map +1 -1
- package/dist/output/timeline.js +46 -52
- package/dist/output/timeline.js.map +1 -1
- package/dist/patterns/detour.d.ts +1 -1
- package/dist/patterns/detour.d.ts.map +1 -1
- package/dist/patterns/detour.js +1 -4
- package/dist/patterns/detour.js.map +1 -1
- package/dist/patterns/flow-state.d.ts +1 -1
- package/dist/patterns/flow-state.d.ts.map +1 -1
- package/dist/patterns/flow-state.js +1 -4
- package/dist/patterns/flow-state.js.map +1 -1
- package/dist/patterns/index.d.ts +7 -7
- package/dist/patterns/index.d.ts.map +1 -1
- package/dist/patterns/index.js +7 -21
- package/dist/patterns/index.js.map +1 -1
- package/dist/patterns/intervention-effectiveness.d.ts +1 -1
- package/dist/patterns/intervention-effectiveness.d.ts.map +1 -1
- package/dist/patterns/intervention-effectiveness.js +3 -8
- package/dist/patterns/intervention-effectiveness.js.map +1 -1
- package/dist/patterns/late-night.d.ts +1 -1
- package/dist/patterns/late-night.d.ts.map +1 -1
- package/dist/patterns/late-night.js +1 -4
- package/dist/patterns/late-night.js.map +1 -1
- package/dist/patterns/post-delete-sprint.d.ts +1 -1
- package/dist/patterns/post-delete-sprint.d.ts.map +1 -1
- package/dist/patterns/post-delete-sprint.js +1 -4
- package/dist/patterns/post-delete-sprint.js.map +1 -1
- package/dist/patterns/spiral-regression.d.ts +1 -1
- package/dist/patterns/spiral-regression.d.ts.map +1 -1
- package/dist/patterns/spiral-regression.js +3 -8
- package/dist/patterns/spiral-regression.js.map +1 -1
- package/dist/patterns/thrashing.d.ts +1 -1
- package/dist/patterns/thrashing.d.ts.map +1 -1
- package/dist/patterns/thrashing.js +3 -6
- package/dist/patterns/thrashing.js.map +1 -1
- package/dist/score/index.d.ts +3 -3
- package/dist/score/index.d.ts.map +1 -1
- package/dist/score/index.js +4 -10
- package/dist/score/index.js.map +1 -1
- package/dist/score/weights.js +2 -6
- package/dist/score/weights.js.map +1 -1
- package/dist/sessions/index.js +9 -51
- package/dist/sessions/index.js.map +1 -1
- package/dist/storage/atomic.js +10 -51
- package/dist/storage/atomic.js.map +1 -1
- package/dist/storage/commit-log.d.ts +1 -1
- package/dist/storage/commit-log.d.ts.map +1 -1
- package/dist/storage/commit-log.js +11 -51
- package/dist/storage/commit-log.js.map +1 -1
- package/dist/storage/index.d.ts +5 -5
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +5 -37
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/schema.js +4 -9
- package/dist/storage/schema.js.map +1 -1
- package/dist/storage/spiral-history.js +14 -57
- package/dist/storage/spiral-history.js.map +1 -1
- package/dist/storage/timeline-store.d.ts +2 -2
- package/dist/storage/timeline-store.d.ts.map +1 -1
- package/dist/storage/timeline-store.js +17 -61
- package/dist/storage/timeline-store.js.map +1 -1
- package/dist/types.d.ts +36 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/docs/ENHANCEMENT-PLAN.md +379 -0
- package/feature-list.json +6 -0
- package/package.json +8 -7
- package/.claude/skills/typescript-review.md +0 -152
- package/dist/calibration/ece.d.ts +0 -26
- package/dist/calibration/ece.d.ts.map +0 -1
- package/dist/calibration/ece.js +0 -93
- package/dist/calibration/ece.js.map +0 -1
- package/dist/calibration/index.d.ts +0 -3
- package/dist/calibration/index.d.ts.map +0 -1
- package/dist/calibration/index.js +0 -15
- package/dist/calibration/index.js.map +0 -1
- package/dist/calibration/storage.d.ts +0 -34
- package/dist/calibration/storage.d.ts.map +0 -1
- package/dist/calibration/storage.js +0 -188
- package/dist/calibration/storage.js.map +0 -1
- package/dist/commands/intervene.d.ts +0 -15
- package/dist/commands/intervene.d.ts.map +0 -1
- package/dist/commands/intervene.js +0 -183
- package/dist/commands/intervene.js.map +0 -1
- package/dist/commands/learn.d.ts +0 -3
- package/dist/commands/learn.d.ts.map +0 -1
- package/dist/commands/learn.js +0 -161
- package/dist/commands/learn.js.map +0 -1
- package/dist/commands/lesson.d.ts +0 -8
- package/dist/commands/lesson.d.ts.map +0 -1
- package/dist/commands/lesson.js +0 -206
- package/dist/commands/lesson.js.map +0 -1
- package/dist/commands/level.d.ts +0 -3
- package/dist/commands/level.d.ts.map +0 -1
- package/dist/commands/level.js +0 -277
- package/dist/commands/level.js.map +0 -1
- package/dist/gamification/badges.d.ts +0 -29
- package/dist/gamification/badges.d.ts.map +0 -1
- package/dist/gamification/badges.js +0 -114
- package/dist/gamification/badges.js.map +0 -1
- package/dist/gamification/challenges.d.ts +0 -42
- package/dist/gamification/challenges.d.ts.map +0 -1
- package/dist/gamification/challenges.js +0 -184
- package/dist/gamification/challenges.js.map +0 -1
- package/dist/gamification/hall-of-fame.d.ts +0 -17
- package/dist/gamification/hall-of-fame.d.ts.map +0 -1
- package/dist/gamification/hall-of-fame.js +0 -64
- package/dist/gamification/hall-of-fame.js.map +0 -1
- package/dist/gamification/intervention-memory.d.ts +0 -61
- package/dist/gamification/intervention-memory.d.ts.map +0 -1
- package/dist/gamification/intervention-memory.js +0 -229
- package/dist/gamification/intervention-memory.js.map +0 -1
- package/dist/gamification/leaderboards.d.ts +0 -49
- package/dist/gamification/leaderboards.d.ts.map +0 -1
- package/dist/gamification/leaderboards.js +0 -179
- package/dist/gamification/leaderboards.js.map +0 -1
- package/dist/gamification/pattern-memory.d.ts +0 -45
- package/dist/gamification/pattern-memory.d.ts.map +0 -1
- package/dist/gamification/pattern-memory.js +0 -188
- package/dist/gamification/pattern-memory.js.map +0 -1
- package/dist/gamification/share.d.ts +0 -29
- package/dist/gamification/share.d.ts.map +0 -1
- package/dist/gamification/share.js +0 -57
- package/dist/gamification/share.js.map +0 -1
- package/dist/learning/cadence.d.ts +0 -15
- package/dist/learning/cadence.d.ts.map +0 -1
- package/dist/learning/cadence.js +0 -130
- package/dist/learning/cadence.js.map +0 -1
- package/dist/learning/index.d.ts +0 -19
- package/dist/learning/index.d.ts.map +0 -1
- package/dist/learning/index.js +0 -35
- package/dist/learning/index.js.map +0 -1
- package/dist/learning/lessons-storage.d.ts +0 -48
- package/dist/learning/lessons-storage.d.ts.map +0 -1
- package/dist/learning/lessons-storage.js +0 -266
- package/dist/learning/lessons-storage.js.map +0 -1
- package/dist/learning/lessons-types.d.ts +0 -83
- package/dist/learning/lessons-types.d.ts.map +0 -1
- package/dist/learning/lessons-types.js +0 -15
- package/dist/learning/lessons-types.js.map +0 -1
- package/dist/learning/nudges.d.ts +0 -20
- package/dist/learning/nudges.d.ts.map +0 -1
- package/dist/learning/nudges.js +0 -68
- package/dist/learning/nudges.js.map +0 -1
- package/dist/learning/retrospective.d.ts +0 -27
- package/dist/learning/retrospective.d.ts.map +0 -1
- package/dist/learning/retrospective.js +0 -184
- package/dist/learning/retrospective.js.map +0 -1
- package/dist/learning/storage.d.ts +0 -44
- package/dist/learning/storage.d.ts.map +0 -1
- package/dist/learning/storage.js +0 -194
- package/dist/learning/storage.js.map +0 -1
- package/dist/learning/surfacing.d.ts +0 -36
- package/dist/learning/surfacing.d.ts.map +0 -1
- package/dist/learning/surfacing.js +0 -255
- package/dist/learning/surfacing.js.map +0 -1
- package/dist/learning/synthesis.d.ts +0 -17
- package/dist/learning/synthesis.d.ts.map +0 -1
- package/dist/learning/synthesis.js +0 -293
- package/dist/learning/synthesis.js.map +0 -1
- package/dist/learning/types.d.ts +0 -60
- package/dist/learning/types.d.ts.map +0 -1
- package/dist/learning/types.js +0 -17
- package/dist/learning/types.js.map +0 -1
- package/dist/recommend/index.d.ts +0 -3
- package/dist/recommend/index.d.ts.map +0 -1
- package/dist/recommend/index.js +0 -14
- package/dist/recommend/index.js.map +0 -1
- package/dist/recommend/ordered-logistic.d.ts +0 -49
- package/dist/recommend/ordered-logistic.d.ts.map +0 -1
- package/dist/recommend/ordered-logistic.js +0 -153
- package/dist/recommend/ordered-logistic.js.map +0 -1
- package/dist/recommend/questions.d.ts +0 -19
- package/dist/recommend/questions.d.ts.map +0 -1
- package/dist/recommend/questions.js +0 -73
- package/dist/recommend/questions.js.map +0 -1
|
@@ -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":"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"}
|
|
@@ -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"}
|
|
@@ -0,0 +1,254 @@
|
|
|
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
|
+
import * as fs from 'fs';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
import { scanDirectory } from './audit.js';
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// PATTERN DETECTION
|
|
19
|
+
// ============================================================================
|
|
20
|
+
const PATTERN_MATCHERS = [
|
|
21
|
+
{ pattern: 'test', test: (f) => /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(f) },
|
|
22
|
+
{ pattern: 'generated', test: (f) => /\.generated\.(ts|tsx)$/.test(f) },
|
|
23
|
+
{ pattern: 'types', test: (f, c) => /types?\.(ts|d\.ts)$/.test(f) || (c.match(/^export (type|interface)/gm)?.length || 0) > 10 },
|
|
24
|
+
{ pattern: 'controller', test: (f, c) => /Controller\.(ts|tsx)$/.test(f) || c.includes('reconcile') && c.includes('class') },
|
|
25
|
+
{ pattern: 'store', test: (f) => /(Store|Repository)\.(ts|tsx)$/.test(f) },
|
|
26
|
+
{ pattern: 'routes', test: (f, c) => /routes?\.(ts|tsx)$/.test(f) || (c.includes('router.') && c.includes('app.')) },
|
|
27
|
+
{ pattern: 'state-machine', test: (f, c) => /Lifecycle\.(ts|tsx)$/.test(f) || c.includes('transition') && c.includes('state') },
|
|
28
|
+
{ pattern: 'middleware', test: (f) => /middleware/i.test(f) },
|
|
29
|
+
{ pattern: 'component', test: (f, c) => /\.(tsx|jsx)$/.test(f) && c.includes('export') && (c.includes('function') || c.includes('const')) },
|
|
30
|
+
{ pattern: 'utility', test: (f) => /(utils?|helpers?|lib)\.(ts|js)$/.test(f) },
|
|
31
|
+
];
|
|
32
|
+
function detectPattern(file, content) {
|
|
33
|
+
for (const { pattern, test } of PATTERN_MATCHERS) {
|
|
34
|
+
if (test(file, content))
|
|
35
|
+
return pattern;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// PATTERN-SPECIFIC THRESHOLDS
|
|
41
|
+
// ============================================================================
|
|
42
|
+
const PATTERN_THRESHOLDS = {
|
|
43
|
+
controller: { yellow: 800, red: 1200 },
|
|
44
|
+
store: { yellow: 1500, red: 2500 },
|
|
45
|
+
routes: { yellow: 1000, red: 1500 },
|
|
46
|
+
types: { yellow: 800, red: 1200 },
|
|
47
|
+
'state-machine': { yellow: 600, red: 900 },
|
|
48
|
+
test: { yellow: Infinity, red: Infinity }, // Tests exempt
|
|
49
|
+
generated: { yellow: Infinity, red: Infinity }, // Generated exempt
|
|
50
|
+
component: { yellow: 250, red: 400 },
|
|
51
|
+
middleware: { yellow: 400, red: 600 },
|
|
52
|
+
utility: { yellow: 150, red: 250 },
|
|
53
|
+
default: { yellow: 300, red: 500 },
|
|
54
|
+
};
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// ANALYSIS FUNCTIONS
|
|
57
|
+
// ============================================================================
|
|
58
|
+
function countSections(content) {
|
|
59
|
+
// Look for section dividers: // ==== or /* ==== or // ----
|
|
60
|
+
const sectionMatches = content.match(/\/\/\s*={4,}|\/\*\s*={4,}|\/\/\s*-{4,}/g);
|
|
61
|
+
return sectionMatches?.length || 0;
|
|
62
|
+
}
|
|
63
|
+
function countExports(content) {
|
|
64
|
+
const exportMatches = content.match(/^export\s+(const|function|class|interface|type|enum|default)/gm);
|
|
65
|
+
return exportMatches?.length || 0;
|
|
66
|
+
}
|
|
67
|
+
function countImports(content) {
|
|
68
|
+
const importMatches = content.match(/^import\s+/gm);
|
|
69
|
+
return importMatches?.length || 0;
|
|
70
|
+
}
|
|
71
|
+
function hasNestedClasses(content) {
|
|
72
|
+
// Look for class definitions that aren't at the top level
|
|
73
|
+
const classCount = (content.match(/\bclass\s+\w+/g) || []).length;
|
|
74
|
+
return classCount > 1;
|
|
75
|
+
}
|
|
76
|
+
function countMethods(content) {
|
|
77
|
+
// Count method-like patterns
|
|
78
|
+
const methodMatches = content.match(/^\s+(async\s+)?(private\s+|public\s+|protected\s+)?\w+\s*\([^)]*\)\s*[:{]/gm);
|
|
79
|
+
return methodMatches?.length || 0;
|
|
80
|
+
}
|
|
81
|
+
function hasSingleResponsibility(content, file) {
|
|
82
|
+
// Heuristic: if there are multiple unrelated concepts, it's probably not SRP
|
|
83
|
+
// Look for warning signs: multiple "Manager", "Handler", "Service" in one file
|
|
84
|
+
const concepts = (content.match(/class\s+\w*(Manager|Handler|Service|Controller|Store)/g) || []).length;
|
|
85
|
+
if (concepts > 1)
|
|
86
|
+
return false;
|
|
87
|
+
// Check file name for warning signs
|
|
88
|
+
if (/(utils?|helpers?|misc|common)\.ts$/i.test(file))
|
|
89
|
+
return false;
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
function analyzeFile(filePath, rootDir) {
|
|
93
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
94
|
+
const lines = content.split('\n').length;
|
|
95
|
+
const relPath = path.relative(rootDir, filePath);
|
|
96
|
+
const pattern = detectPattern(relPath, content);
|
|
97
|
+
// Check for exemptions
|
|
98
|
+
if (pattern === 'test') {
|
|
99
|
+
return { file: relPath, lines, reason: 'Test files are exempt' };
|
|
100
|
+
}
|
|
101
|
+
if (pattern === 'generated') {
|
|
102
|
+
return { file: relPath, lines, reason: 'Generated files are exempt' };
|
|
103
|
+
}
|
|
104
|
+
// Analyze structure
|
|
105
|
+
const details = {
|
|
106
|
+
hasSections: countSections(content) > 0,
|
|
107
|
+
sectionCount: countSections(content),
|
|
108
|
+
exportCount: countExports(content),
|
|
109
|
+
importCount: countImports(content),
|
|
110
|
+
hasNestedClasses: hasNestedClasses(content),
|
|
111
|
+
methodCount: countMethods(content),
|
|
112
|
+
};
|
|
113
|
+
// Calculate score
|
|
114
|
+
const { score, flags } = calculateScore(lines, pattern, details, content, relPath);
|
|
115
|
+
return {
|
|
116
|
+
file: relPath,
|
|
117
|
+
lines,
|
|
118
|
+
pattern,
|
|
119
|
+
score,
|
|
120
|
+
rating: scoreToRating(score),
|
|
121
|
+
flags,
|
|
122
|
+
details,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function calculateScore(lines, pattern, details, content, file) {
|
|
126
|
+
let score = 10;
|
|
127
|
+
const flags = [];
|
|
128
|
+
const thresholds = PATTERN_THRESHOLDS[pattern || 'default'];
|
|
129
|
+
// 1. Size penalty (relative to pattern threshold)
|
|
130
|
+
if (lines > thresholds.red) {
|
|
131
|
+
score -= 3;
|
|
132
|
+
}
|
|
133
|
+
else if (lines > thresholds.yellow) {
|
|
134
|
+
score -= 1;
|
|
135
|
+
}
|
|
136
|
+
// 2. Single Responsibility (+2 if yes, -2 if no)
|
|
137
|
+
if (!hasSingleResponsibility(content, file)) {
|
|
138
|
+
score -= 2;
|
|
139
|
+
flags.push('no-single-responsibility');
|
|
140
|
+
}
|
|
141
|
+
// 3. Internal Structure (+2 if organized)
|
|
142
|
+
if (lines > 300) {
|
|
143
|
+
if (details.hasSections || details.hasNestedClasses) {
|
|
144
|
+
score += 1; // Bonus for organization in large files
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
score -= 2;
|
|
148
|
+
flags.push('no-internal-structure');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// 4. Coupling check (high imports = high coupling)
|
|
152
|
+
if (details.importCount > 15) {
|
|
153
|
+
score -= 1;
|
|
154
|
+
flags.push('high-coupling');
|
|
155
|
+
}
|
|
156
|
+
else if (details.importCount > 25) {
|
|
157
|
+
score -= 2;
|
|
158
|
+
}
|
|
159
|
+
// 5. Export surface (bloated API)
|
|
160
|
+
if (details.exportCount > 20 && pattern !== 'types') {
|
|
161
|
+
score -= 1;
|
|
162
|
+
flags.push('low-cohesion');
|
|
163
|
+
}
|
|
164
|
+
// 6. Pattern bonus (recognized patterns get benefit of the doubt)
|
|
165
|
+
if (pattern && ['controller', 'store', 'routes', 'state-machine'].includes(pattern)) {
|
|
166
|
+
score += 1; // These patterns legitimately tend to be larger
|
|
167
|
+
}
|
|
168
|
+
// 7. Utility grab-bag detection
|
|
169
|
+
if (/(utils?|helpers?)\.ts$/i.test(file) && details.exportCount > 10) {
|
|
170
|
+
score -= 2;
|
|
171
|
+
flags.push('utility-grab-bag');
|
|
172
|
+
}
|
|
173
|
+
// Clamp score
|
|
174
|
+
return { score: Math.max(0, Math.min(10, score)), flags };
|
|
175
|
+
}
|
|
176
|
+
function scoreToRating(score) {
|
|
177
|
+
if (score >= 9)
|
|
178
|
+
return 'elite';
|
|
179
|
+
if (score >= 7)
|
|
180
|
+
return 'good';
|
|
181
|
+
if (score >= 5)
|
|
182
|
+
return 'acceptable';
|
|
183
|
+
if (score >= 3)
|
|
184
|
+
return 'needs-work';
|
|
185
|
+
return 'poor';
|
|
186
|
+
}
|
|
187
|
+
export function analyzeModularity(rootDir, options = {}) {
|
|
188
|
+
const { minLines = 100, includeAll = false, patterns } = options;
|
|
189
|
+
const allFiles = scanDirectory(rootDir);
|
|
190
|
+
const files = [];
|
|
191
|
+
const exempted = [];
|
|
192
|
+
let totalLines = 0;
|
|
193
|
+
for (const filePath of allFiles) {
|
|
194
|
+
const result = analyzeFile(filePath, rootDir);
|
|
195
|
+
if ('reason' in result) {
|
|
196
|
+
// Exempted file
|
|
197
|
+
exempted.push(result);
|
|
198
|
+
totalLines += result.lines;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
totalLines += result.lines;
|
|
202
|
+
// Apply filters
|
|
203
|
+
if (!includeAll && result.lines < minLines)
|
|
204
|
+
continue;
|
|
205
|
+
if (patterns && result.pattern && !patterns.includes(result.pattern))
|
|
206
|
+
continue;
|
|
207
|
+
files.push(result);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Sort by score (worst first) then by lines (largest first)
|
|
211
|
+
files.sort((a, b) => {
|
|
212
|
+
if (a.score !== b.score)
|
|
213
|
+
return a.score - b.score;
|
|
214
|
+
return b.lines - a.lines;
|
|
215
|
+
});
|
|
216
|
+
// Calculate summary
|
|
217
|
+
const summary = calculateSummary(files, allFiles.length, totalLines);
|
|
218
|
+
return { files, summary, exempted };
|
|
219
|
+
}
|
|
220
|
+
function calculateSummary(files, totalFiles, totalLines) {
|
|
221
|
+
const distribution = { elite: 0, good: 0, acceptable: 0, needsWork: 0, poor: 0 };
|
|
222
|
+
let scoreSum = 0;
|
|
223
|
+
for (const file of files) {
|
|
224
|
+
scoreSum += file.score;
|
|
225
|
+
switch (file.rating) {
|
|
226
|
+
case 'elite':
|
|
227
|
+
distribution.elite++;
|
|
228
|
+
break;
|
|
229
|
+
case 'good':
|
|
230
|
+
distribution.good++;
|
|
231
|
+
break;
|
|
232
|
+
case 'acceptable':
|
|
233
|
+
distribution.acceptable++;
|
|
234
|
+
break;
|
|
235
|
+
case 'needs-work':
|
|
236
|
+
distribution.needsWork++;
|
|
237
|
+
break;
|
|
238
|
+
case 'poor':
|
|
239
|
+
distribution.poor++;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
totalFiles,
|
|
245
|
+
totalLines,
|
|
246
|
+
avgScore: files.length > 0 ? Math.round((scoreSum / files.length) * 10) / 10 : 10,
|
|
247
|
+
distribution,
|
|
248
|
+
largestFiles: files
|
|
249
|
+
.sort((a, b) => b.lines - a.lines)
|
|
250
|
+
.slice(0, 5)
|
|
251
|
+
.map(f => ({ file: f.file, lines: f.lines, score: f.score })),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=modularity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modularity.js","sourceRoot":"","sources":["../../src/analyzers/modularity.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/analyzers/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/analyzers/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,eAAe,CAAC;IAC9B,cAAc,EAAE,kBAAkB,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,GAAG,IAAI,CAoCxE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,GAAE,MAAW,GACrB,eAAe,CAmBjB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,GAAE,MAAU,GACpB,kBAAkB,CAiBpB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,sBAAsB,CAMxE"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Pattern Detection Analyzer (VIBE-045)
|
|
4
3
|
*
|
|
@@ -9,18 +8,13 @@
|
|
|
9
8
|
*
|
|
10
9
|
* Proven algorithm from release-engineering retrospective (475 commits analyzed).
|
|
11
10
|
*/
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.detectDebugSpirals = detectDebugSpirals;
|
|
14
|
-
exports.detectVagueCommits = detectVagueCommits;
|
|
15
|
-
exports.detectContextAmnesia = detectContextAmnesia;
|
|
16
|
-
exports.detectPatterns = detectPatterns;
|
|
17
11
|
/**
|
|
18
12
|
* Detect "take N" pattern indicating debug spirals.
|
|
19
13
|
*
|
|
20
14
|
* A debug spiral is detected when 3+ commits match the pattern "take N" or similar
|
|
21
15
|
* retry patterns, indicating the developer is stuck in a fix-retry loop.
|
|
22
16
|
*/
|
|
23
|
-
function detectDebugSpirals(commits) {
|
|
17
|
+
export function detectDebugSpirals(commits) {
|
|
24
18
|
const takePattern = /^take\s*[0-9]+$/i;
|
|
25
19
|
const retryPatterns = [
|
|
26
20
|
/^(fix|try|attempt)\s*#?\d+$/i, // "fix 2", "try #3"
|
|
@@ -52,7 +46,7 @@ function detectDebugSpirals(commits) {
|
|
|
52
46
|
* Threshold: < 20 characters is considered vague.
|
|
53
47
|
* Examples: "ci", "v3", "blah", "take 2", "fix"
|
|
54
48
|
*/
|
|
55
|
-
function detectVagueCommits(commits, threshold = 20) {
|
|
49
|
+
export function detectVagueCommits(commits, threshold = 20) {
|
|
56
50
|
const vagueCommits = commits.filter((c) => c.message.trim().length < threshold);
|
|
57
51
|
// Get example vague messages (deduplicated, max 10)
|
|
58
52
|
const examples = [
|
|
@@ -75,7 +69,7 @@ function detectVagueCommits(commits, threshold = 20) {
|
|
|
75
69
|
*
|
|
76
70
|
* Reports scopes that appear in 5+ commits.
|
|
77
71
|
*/
|
|
78
|
-
function detectContextAmnesia(commits, minVisits = 5) {
|
|
72
|
+
export function detectContextAmnesia(commits, minVisits = 5) {
|
|
79
73
|
const scopeCounts = new Map();
|
|
80
74
|
for (const commit of commits) {
|
|
81
75
|
if (commit.scope) {
|
|
@@ -93,7 +87,7 @@ function detectContextAmnesia(commits, minVisits = 5) {
|
|
|
93
87
|
/**
|
|
94
88
|
* Run all pattern detection on a set of commits.
|
|
95
89
|
*/
|
|
96
|
-
function detectPatterns(commits) {
|
|
90
|
+
export function detectPatterns(commits) {
|
|
97
91
|
return {
|
|
98
92
|
debugSpirals: detectDebugSpirals(commits),
|
|
99
93
|
vagueCommits: detectVagueCommits(commits),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/analyzers/patterns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/analyzers/patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/analyzers/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/analyzers/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,kBAAkB,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAmBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAW,GACrB,OAAO,CAGT;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAW,GACrB,OAAO,CAGT;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,GAAE,MAAW,EAC3B,oBAAoB,GAAE,MAAW,GAChC,cAAc,CAyChB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,OAAO,GAClB,OAAO,GAAG,UAAU,GAAG,WAAW,CAgBpC"}
|