@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,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Cohesion Score
|
|
3
|
+
*
|
|
4
|
+
* Measures how scattered or focused changes are across domains.
|
|
5
|
+
* Well-organized code changes should touch few domains per commit.
|
|
6
|
+
* Scattered changes indicate coupling or lack of vertical slices.
|
|
7
|
+
*
|
|
8
|
+
* From the Enhancement Plan:
|
|
9
|
+
* - ELITE: >80% cohesion (mostly 1-domain commits)
|
|
10
|
+
* - HIGH: >60% cohesion
|
|
11
|
+
* - MEDIUM: >40% cohesion
|
|
12
|
+
* - LOW: <40% cohesion
|
|
13
|
+
*
|
|
14
|
+
* Domain extraction:
|
|
15
|
+
* - src/fleet/... → "fleet"
|
|
16
|
+
* - src/missions/... → "missions"
|
|
17
|
+
* - server/... → "server"
|
|
18
|
+
*/
|
|
19
|
+
const SCATTERED_THRESHOLD = 3; // 3+ domains = scattered
|
|
20
|
+
/**
|
|
21
|
+
* Calculate domain cohesion from commits and file statistics.
|
|
22
|
+
*
|
|
23
|
+
* @param commits - The commits to analyze
|
|
24
|
+
* @param filesPerCommit - Map of commit hash -> files changed
|
|
25
|
+
*/
|
|
26
|
+
export function calculateCohesionMetrics(commits, filesPerCommit) {
|
|
27
|
+
if (commits.length === 0) {
|
|
28
|
+
return emptyCohesionMetrics();
|
|
29
|
+
}
|
|
30
|
+
let cohesiveCommits = 0;
|
|
31
|
+
let scatteredCommits = 0;
|
|
32
|
+
let totalDomains = 0;
|
|
33
|
+
const scatteredList = [];
|
|
34
|
+
for (const commit of commits) {
|
|
35
|
+
const files = filesPerCommit.get(commit.hash) || [];
|
|
36
|
+
const domains = extractDomains(files);
|
|
37
|
+
const domainCount = domains.length;
|
|
38
|
+
totalDomains += domainCount;
|
|
39
|
+
if (domainCount <= 1) {
|
|
40
|
+
cohesiveCommits++;
|
|
41
|
+
}
|
|
42
|
+
else if (domainCount >= SCATTERED_THRESHOLD) {
|
|
43
|
+
scatteredCommits++;
|
|
44
|
+
scatteredList.push({ hash: commit.hash, domains });
|
|
45
|
+
}
|
|
46
|
+
// 2 domains = neither cohesive nor scattered
|
|
47
|
+
}
|
|
48
|
+
const avgDomainsPerCommit = commits.length > 0 ? totalDomains / commits.length : 0;
|
|
49
|
+
const cohesionScore = commits.length > 0 ? (cohesiveCommits / commits.length) * 100 : 0;
|
|
50
|
+
const rating = getRating(cohesionScore);
|
|
51
|
+
return {
|
|
52
|
+
value: Math.round(cohesionScore * 10) / 10,
|
|
53
|
+
unit: '%',
|
|
54
|
+
rating,
|
|
55
|
+
description: getDescription(rating, cohesiveCommits, scatteredCommits, commits.length),
|
|
56
|
+
avgDomainsPerCommit: Math.round(avgDomainsPerCommit * 10) / 10,
|
|
57
|
+
cohesiveCommits,
|
|
58
|
+
scatteredCommits,
|
|
59
|
+
cohesionScore: Math.round(cohesionScore * 10) / 10,
|
|
60
|
+
scatteredList: scatteredList.slice(0, 5), // Limit to top 5 for output
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extract unique domains from a list of file paths.
|
|
65
|
+
*
|
|
66
|
+
* Domain rules:
|
|
67
|
+
* - src/X/... → X is the domain
|
|
68
|
+
* - server/X/... → X is the domain
|
|
69
|
+
* - client/X/... → X is the domain
|
|
70
|
+
* - packages/X/... → X is the domain
|
|
71
|
+
* - Top-level directories are domains (e.g., dashboard/, tests/)
|
|
72
|
+
*/
|
|
73
|
+
function extractDomains(files) {
|
|
74
|
+
const domains = new Set();
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
const domain = extractDomain(file);
|
|
77
|
+
if (domain) {
|
|
78
|
+
domains.add(domain);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return Array.from(domains);
|
|
82
|
+
}
|
|
83
|
+
function extractDomain(filePath) {
|
|
84
|
+
const parts = filePath.split('/').filter((p) => p.length > 0);
|
|
85
|
+
if (parts.length === 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
// Skip hidden files and common non-domain paths
|
|
89
|
+
if (parts[0].startsWith('.') || parts[0] === 'node_modules') {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
// If starts with src/, server/, client/, packages/ - use the second part
|
|
93
|
+
const containerDirs = ['src', 'server', 'client', 'packages', 'lib', 'app', 'domains'];
|
|
94
|
+
if (containerDirs.includes(parts[0]) && parts.length > 1) {
|
|
95
|
+
return parts[1].toLowerCase();
|
|
96
|
+
}
|
|
97
|
+
// Otherwise use the first directory as the domain
|
|
98
|
+
return parts[0].toLowerCase();
|
|
99
|
+
}
|
|
100
|
+
function getRating(cohesionScore) {
|
|
101
|
+
if (cohesionScore > 80)
|
|
102
|
+
return 'elite';
|
|
103
|
+
if (cohesionScore > 60)
|
|
104
|
+
return 'high';
|
|
105
|
+
if (cohesionScore > 40)
|
|
106
|
+
return 'medium';
|
|
107
|
+
return 'low';
|
|
108
|
+
}
|
|
109
|
+
function getDescription(rating, cohesive, scattered, total) {
|
|
110
|
+
switch (rating) {
|
|
111
|
+
case 'elite':
|
|
112
|
+
return `Excellent cohesion! ${cohesive}/${total} commits touch single domain.`;
|
|
113
|
+
case 'high':
|
|
114
|
+
return `Good cohesion. ${cohesive}/${total} single-domain commits.`;
|
|
115
|
+
case 'medium':
|
|
116
|
+
return `Moderate cohesion. ${scattered} scattered commits (3+ domains each).`;
|
|
117
|
+
case 'low':
|
|
118
|
+
return `Low cohesion. ${scattered} scattered commits. Consider vertical slices.`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function emptyCohesionMetrics() {
|
|
122
|
+
return {
|
|
123
|
+
value: 0,
|
|
124
|
+
unit: '%',
|
|
125
|
+
rating: 'low',
|
|
126
|
+
description: 'No commits found',
|
|
127
|
+
avgDomainsPerCommit: 0,
|
|
128
|
+
cohesiveCommits: 0,
|
|
129
|
+
scatteredCommits: 0,
|
|
130
|
+
cohesionScore: 0,
|
|
131
|
+
scatteredList: [],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=cohesion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cohesion.js","sourceRoot":"","sources":["../../src/metrics/cohesion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,mBAAmB,GAAG,CAAC,CAAC,CAAC,yBAAyB;AAExD;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAiB,EACjB,cAAqC;IAErC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,oBAAoB,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,aAAa,GAA+C,EAAE,CAAC;IAErE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACpD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;QAEnC,YAAY,IAAI,WAAW,CAAC;QAE5B,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;YACrB,eAAe,EAAE,CAAC;QACpB,CAAC;aAAM,IAAI,WAAW,IAAI,mBAAmB,EAAE,CAAC;YAC9C,gBAAgB,EAAE,CAAC;YACnB,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,6CAA6C;IAC/C,CAAC;IAED,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAExF,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAExC,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC,GAAG,EAAE;QAC1C,IAAI,EAAE,GAAG;QACT,MAAM;QACN,WAAW,EAAE,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC;QACtF,mBAAmB,EAAE,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,GAAG,EAAE;QAC9D,eAAe;QACf,gBAAgB;QAChB,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC,GAAG,EAAE;QAClD,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,4BAA4B;KACvE,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,cAAc,CAAC,KAAe;IACrC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gDAAgD;IAChD,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,cAAc,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yEAAyE;IACzE,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACvF,IAAI,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,CAAC;IAED,kDAAkD;IAClD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,SAAS,CAAC,aAAqB;IACtC,IAAI,aAAa,GAAG,EAAE;QAAE,OAAO,OAAO,CAAC;IACvC,IAAI,aAAa,GAAG,EAAE;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,aAAa,GAAG,EAAE;QAAE,OAAO,QAAQ,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CACrB,MAAc,EACd,QAAgB,EAChB,SAAiB,EACjB,KAAa;IAEb,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,uBAAuB,QAAQ,IAAI,KAAK,+BAA+B,CAAC;QACjF,KAAK,MAAM;YACT,OAAO,kBAAkB,QAAQ,IAAI,KAAK,yBAAyB,CAAC;QACtE,KAAK,QAAQ;YACX,OAAO,sBAAsB,SAAS,uCAAuC,CAAC;QAChF,KAAK,KAAK;YACR,OAAO,iBAAiB,SAAS,+CAA+C,CAAC;IACrF,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO;QACL,KAAK,EAAE,CAAC;QACR,IAAI,EAAE,GAAG;QACT,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,kBAAkB;QAC/B,mBAAmB,EAAE,CAAC;QACtB,eAAe,EAAE,CAAC;QAClB,gBAAgB,EAAE,CAAC;QACnB,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,EAAE;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-churn.d.ts","sourceRoot":"","sources":["../../src/metrics/file-churn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"file-churn.d.ts","sourceRoot":"","sources":["../../src/metrics/file-churn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAU,MAAM,aAAa,CAAC;AAiB9D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACpC,eAAe,CAuCjB"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateFileChurn = calculateFileChurn;
|
|
4
1
|
const ONE_HOUR_MS = 60 * 60 * 1000;
|
|
5
2
|
/**
|
|
6
3
|
* Churn threshold: 3+ touches to same file within 1 hour suggests thrashing.
|
|
@@ -19,7 +16,7 @@ const CHURN_THRESHOLD = 3;
|
|
|
19
16
|
* Files touched 3+ times within 1 hour indicate thrashing.
|
|
20
17
|
* Works WITHOUT semantic commits.
|
|
21
18
|
*/
|
|
22
|
-
function calculateFileChurn(commits, filesPerCommit) {
|
|
19
|
+
export function calculateFileChurn(commits, filesPerCommit) {
|
|
23
20
|
// Track file touch timestamps
|
|
24
21
|
const fileTouchTimes = new Map();
|
|
25
22
|
for (const commit of commits) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-churn.js","sourceRoot":"","sources":["../../src/metrics/file-churn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-churn.js","sourceRoot":"","sources":["../../src/metrics/file-churn.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics/flow.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/metrics/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/metrics/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,aAAa,CAAC;AAE7D,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,QAAQ,EAAE,GAClB,YAAY,CAwBd"}
|
package/dist/metrics/flow.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateFlowEfficiency = calculateFlowEfficiency;
|
|
4
|
-
function calculateFlowEfficiency(activeMinutes, spirals) {
|
|
1
|
+
export function calculateFlowEfficiency(activeMinutes, spirals) {
|
|
5
2
|
if (activeMinutes === 0) {
|
|
6
3
|
return {
|
|
7
4
|
value: 100,
|
package/dist/metrics/flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/metrics/flow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/metrics/flow.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,uBAAuB,CACrC,aAAqB,EACrB,OAAmB;IAEnB,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,GAAG;YACV,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,yBAAyB;SACvC,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,OAAO;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;SACzB,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAE3C,MAAM,UAAU,GAAG,CAAC,CAAC,aAAa,GAAG,aAAa,CAAC,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC;IAC3E,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAE5C,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;QACpC,IAAI,EAAE,GAAG;QACT,MAAM;QACN,WAAW,EAAE,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC;KACnD,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,UAAkB;IACnC,IAAI,UAAU,GAAG,EAAE;QAAE,OAAO,OAAO,CAAC;IACpC,IAAI,UAAU,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IACpC,IAAI,UAAU,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC;IACtC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,aAAqB;IAC3D,MAAM,UAAU,GACd,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,0BAA0B,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAEtF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,GAAG,UAAU,6BAA6B,CAAC;QACpD,KAAK,MAAM;YACT,OAAO,GAAG,UAAU,gBAAgB,CAAC;QACvC,KAAK,QAAQ;YACX,OAAO,GAAG,UAAU,kCAAkC,CAAC;QACzD,KAAK,KAAK;YACR,OAAO,GAAG,UAAU,gCAAgC,CAAC;IACzD,CAAC;AACH,CAAC"}
|
package/dist/metrics/index.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import { Commit, VibeCheckResult } from '../types';
|
|
1
|
+
import { Commit, VibeCheckResult } from '../types.js';
|
|
2
2
|
export declare function analyzeCommits(commits: Commit[]): VibeCheckResult;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Analyze commits with enhanced metrics (v2.2.0).
|
|
5
|
+
* Requires file stats for cohesion analysis.
|
|
6
|
+
*/
|
|
7
|
+
export declare function analyzeCommitsEnhanced(commits: Commit[], filesPerCommit: Map<string, string[]>): VibeCheckResult;
|
|
8
|
+
export { calculateActiveHours } from './velocity.js';
|
|
9
|
+
export { calculateTracerMetrics } from './tracers.js';
|
|
10
|
+
export { calculateInvestigationMetrics } from './investigation.js';
|
|
11
|
+
export { calculateCohesionMetrics } from './cohesion.js';
|
|
4
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAA+E,MAAM,aAAa,CAAC;AAcnI,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,eAAe,CAsDjE;AA4GD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACpC,eAAe,CAwBjB;AAED,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/metrics/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function analyzeCommits(commits) {
|
|
1
|
+
import { calculateIterationVelocity, calculateActiveHours } from './velocity.js';
|
|
2
|
+
import { calculateReworkRatio } from './rework.js';
|
|
3
|
+
import { calculateTrustPassRate } from './trust.js';
|
|
4
|
+
import { detectFixChains, calculateDebugSpiralDuration, calculatePatternSummary, } from './spirals.js';
|
|
5
|
+
import { calculateFlowEfficiency } from './flow.js';
|
|
6
|
+
import { calculateTracerMetrics } from './tracers.js';
|
|
7
|
+
import { calculateInvestigationMetrics } from './investigation.js';
|
|
8
|
+
import { calculateCohesionMetrics } from './cohesion.js';
|
|
9
|
+
export function analyzeCommits(commits) {
|
|
11
10
|
if (commits.length === 0) {
|
|
12
11
|
return emptyResult();
|
|
13
12
|
}
|
|
@@ -15,19 +14,19 @@ function analyzeCommits(commits) {
|
|
|
15
14
|
const sorted = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
16
15
|
const from = sorted[0].date;
|
|
17
16
|
const to = sorted[sorted.length - 1].date;
|
|
18
|
-
const activeHours =
|
|
17
|
+
const activeHours = calculateActiveHours(sorted);
|
|
19
18
|
// Count commit types
|
|
20
19
|
const commitCounts = countCommitTypes(sorted);
|
|
21
20
|
// Detect fix chains
|
|
22
|
-
const fixChains =
|
|
21
|
+
const fixChains = detectFixChains(sorted);
|
|
23
22
|
// Calculate all metrics
|
|
24
|
-
const iterationVelocity =
|
|
25
|
-
const reworkRatio =
|
|
26
|
-
const trustPassRate =
|
|
27
|
-
const debugSpiralDuration =
|
|
28
|
-
const flowEfficiency =
|
|
23
|
+
const iterationVelocity = calculateIterationVelocity(sorted);
|
|
24
|
+
const reworkRatio = calculateReworkRatio(sorted);
|
|
25
|
+
const trustPassRate = calculateTrustPassRate(sorted);
|
|
26
|
+
const debugSpiralDuration = calculateDebugSpiralDuration(fixChains);
|
|
27
|
+
const flowEfficiency = calculateFlowEfficiency(activeHours * 60, fixChains);
|
|
29
28
|
// Calculate pattern summary
|
|
30
|
-
const patterns =
|
|
29
|
+
const patterns = calculatePatternSummary(fixChains);
|
|
31
30
|
// Determine overall rating
|
|
32
31
|
const overall = calculateOverallRating([
|
|
33
32
|
iterationVelocity.rating,
|
|
@@ -61,6 +60,7 @@ function countCommitTypes(commits) {
|
|
|
61
60
|
feat: 0,
|
|
62
61
|
fix: 0,
|
|
63
62
|
docs: 0,
|
|
63
|
+
tracer: 0,
|
|
64
64
|
other: 0,
|
|
65
65
|
};
|
|
66
66
|
for (const commit of commits) {
|
|
@@ -74,6 +74,9 @@ function countCommitTypes(commits) {
|
|
|
74
74
|
case 'docs':
|
|
75
75
|
counts.docs++;
|
|
76
76
|
break;
|
|
77
|
+
case 'tracer':
|
|
78
|
+
counts.tracer++;
|
|
79
|
+
break;
|
|
77
80
|
default:
|
|
78
81
|
counts.other++;
|
|
79
82
|
}
|
|
@@ -108,6 +111,7 @@ function emptyResult() {
|
|
|
108
111
|
feat: 0,
|
|
109
112
|
fix: 0,
|
|
110
113
|
docs: 0,
|
|
114
|
+
tracer: 0,
|
|
111
115
|
other: 0,
|
|
112
116
|
},
|
|
113
117
|
metrics: {
|
|
@@ -151,6 +155,33 @@ function emptyResult() {
|
|
|
151
155
|
overall: 'HIGH',
|
|
152
156
|
};
|
|
153
157
|
}
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
/**
|
|
159
|
+
* Analyze commits with enhanced metrics (v2.2.0).
|
|
160
|
+
* Requires file stats for cohesion analysis.
|
|
161
|
+
*/
|
|
162
|
+
export function analyzeCommitsEnhanced(commits, filesPerCommit) {
|
|
163
|
+
// Get base result
|
|
164
|
+
const result = analyzeCommits(commits);
|
|
165
|
+
if (commits.length === 0) {
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
// Sort commits by date
|
|
169
|
+
const sorted = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
170
|
+
// Calculate enhanced metrics
|
|
171
|
+
const tracers = calculateTracerMetrics(sorted);
|
|
172
|
+
const investigation = calculateInvestigationMetrics(sorted);
|
|
173
|
+
const cohesion = calculateCohesionMetrics(sorted, filesPerCommit);
|
|
174
|
+
return {
|
|
175
|
+
...result,
|
|
176
|
+
enhancedMetrics: {
|
|
177
|
+
tracers,
|
|
178
|
+
investigation,
|
|
179
|
+
cohesion,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
export { calculateActiveHours } from './velocity.js';
|
|
184
|
+
export { calculateTracerMetrics } from './tracers.js';
|
|
185
|
+
export { calculateInvestigationMetrics } from './investigation.js';
|
|
186
|
+
export { calculateCohesionMetrics } from './cohesion.js';
|
|
156
187
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Investigation Gap Detection
|
|
3
|
+
*
|
|
4
|
+
* Surfaces hidden debugging time by analyzing gaps between commits.
|
|
5
|
+
* Long gaps (>15 min) followed by fix commits indicate investigation
|
|
6
|
+
* time that isn't captured in commit timestamps.
|
|
7
|
+
*
|
|
8
|
+
* From the Enhancement Plan:
|
|
9
|
+
* - Gap > 15 min AND < 2 hours (not a break)
|
|
10
|
+
* - Next commit is fix: type
|
|
11
|
+
* - Same component as previous commit (optional)
|
|
12
|
+
*
|
|
13
|
+
* This helps surface the "fix is quick; investigation burns time" problem.
|
|
14
|
+
*/
|
|
15
|
+
import { Commit, InvestigationMetrics } from '../types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Detect investigation gaps in commit history.
|
|
18
|
+
*
|
|
19
|
+
* An investigation gap is defined as:
|
|
20
|
+
* - Time gap > 15 min between commits
|
|
21
|
+
* - Time gap < 2 hours (not a break/new session)
|
|
22
|
+
* - The commit after the gap is a fix: commit
|
|
23
|
+
*/
|
|
24
|
+
export declare function calculateInvestigationMetrics(commits: Commit[]): InvestigationMetrics;
|
|
25
|
+
//# sourceMappingURL=investigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"investigation.d.ts","sourceRoot":"","sources":["../../src/metrics/investigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,MAAM,EAAU,oBAAoB,EAAoB,MAAM,aAAa,CAAC;AAKrF;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,oBAAoB,CA+CrF"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Investigation Gap Detection
|
|
3
|
+
*
|
|
4
|
+
* Surfaces hidden debugging time by analyzing gaps between commits.
|
|
5
|
+
* Long gaps (>15 min) followed by fix commits indicate investigation
|
|
6
|
+
* time that isn't captured in commit timestamps.
|
|
7
|
+
*
|
|
8
|
+
* From the Enhancement Plan:
|
|
9
|
+
* - Gap > 15 min AND < 2 hours (not a break)
|
|
10
|
+
* - Next commit is fix: type
|
|
11
|
+
* - Same component as previous commit (optional)
|
|
12
|
+
*
|
|
13
|
+
* This helps surface the "fix is quick; investigation burns time" problem.
|
|
14
|
+
*/
|
|
15
|
+
import { differenceInMinutes } from 'date-fns';
|
|
16
|
+
const MIN_GAP_MINUTES = 15; // Minimum gap to consider investigation
|
|
17
|
+
const MAX_GAP_MINUTES = 120; // Maximum gap before it's a break (2 hours)
|
|
18
|
+
/**
|
|
19
|
+
* Detect investigation gaps in commit history.
|
|
20
|
+
*
|
|
21
|
+
* An investigation gap is defined as:
|
|
22
|
+
* - Time gap > 15 min between commits
|
|
23
|
+
* - Time gap < 2 hours (not a break/new session)
|
|
24
|
+
* - The commit after the gap is a fix: commit
|
|
25
|
+
*/
|
|
26
|
+
export function calculateInvestigationMetrics(commits) {
|
|
27
|
+
if (commits.length < 2) {
|
|
28
|
+
return emptyInvestigationMetrics();
|
|
29
|
+
}
|
|
30
|
+
// Sort commits by date ascending
|
|
31
|
+
const sorted = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
32
|
+
const gaps = [];
|
|
33
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
34
|
+
const prevCommit = sorted[i - 1];
|
|
35
|
+
const currCommit = sorted[i];
|
|
36
|
+
const gapMinutes = differenceInMinutes(currCommit.date, prevCommit.date);
|
|
37
|
+
// Check if this is an investigation gap
|
|
38
|
+
if (gapMinutes >= MIN_GAP_MINUTES &&
|
|
39
|
+
gapMinutes <= MAX_GAP_MINUTES &&
|
|
40
|
+
currCommit.type === 'fix') {
|
|
41
|
+
gaps.push({
|
|
42
|
+
startCommit: prevCommit.hash,
|
|
43
|
+
endCommit: currCommit.hash,
|
|
44
|
+
gapMinutes,
|
|
45
|
+
followedByFix: true,
|
|
46
|
+
component: extractComponent(currCommit),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const totalMinutes = gaps.reduce((sum, g) => sum + g.gapMinutes, 0);
|
|
51
|
+
const longestGap = gaps.length > 0 ? Math.max(...gaps.map((g) => g.gapMinutes)) : 0;
|
|
52
|
+
const rating = getRating(totalMinutes);
|
|
53
|
+
return {
|
|
54
|
+
value: totalMinutes,
|
|
55
|
+
unit: 'min',
|
|
56
|
+
rating,
|
|
57
|
+
description: getDescription(rating, gaps.length, totalMinutes, longestGap),
|
|
58
|
+
gaps,
|
|
59
|
+
totalMinutes,
|
|
60
|
+
longestGap,
|
|
61
|
+
gapCount: gaps.length,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Extract component from a commit (scope or first significant word).
|
|
66
|
+
*/
|
|
67
|
+
function extractComponent(commit) {
|
|
68
|
+
if (commit.scope) {
|
|
69
|
+
return commit.scope.toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
// Extract from message: strip "fix: " prefix and get first word > 2 chars
|
|
72
|
+
const words = commit.message
|
|
73
|
+
.replace(/^fix\s*:?\s*/i, '')
|
|
74
|
+
.split(/\s+/)
|
|
75
|
+
.filter((w) => w.length > 2);
|
|
76
|
+
return words[0]?.toLowerCase() || 'unknown';
|
|
77
|
+
}
|
|
78
|
+
function getRating(totalMinutes) {
|
|
79
|
+
// No gaps is elite - either very fast debugging or good tracer usage
|
|
80
|
+
if (totalMinutes === 0)
|
|
81
|
+
return 'elite';
|
|
82
|
+
if (totalMinutes <= 30)
|
|
83
|
+
return 'high';
|
|
84
|
+
if (totalMinutes <= 60)
|
|
85
|
+
return 'medium';
|
|
86
|
+
return 'low';
|
|
87
|
+
}
|
|
88
|
+
function getDescription(rating, gapCount, totalMinutes, longestGap) {
|
|
89
|
+
if (gapCount === 0) {
|
|
90
|
+
return 'No investigation gaps detected. Fixes came quickly!';
|
|
91
|
+
}
|
|
92
|
+
switch (rating) {
|
|
93
|
+
case 'elite':
|
|
94
|
+
return `Minimal investigation time. ${gapCount} gap(s), ~${totalMinutes} min total.`;
|
|
95
|
+
case 'high':
|
|
96
|
+
return `Some investigation time. ${gapCount} gap(s) totaling ~${totalMinutes} min.`;
|
|
97
|
+
case 'medium':
|
|
98
|
+
return `Significant investigation. ${gapCount} gap(s), longest ${longestGap} min. Consider tracer tests.`;
|
|
99
|
+
case 'low':
|
|
100
|
+
return `Heavy investigation burden (~${totalMinutes} min). Tracer bullets could reduce this.`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function emptyInvestigationMetrics() {
|
|
104
|
+
return {
|
|
105
|
+
value: 0,
|
|
106
|
+
unit: 'min',
|
|
107
|
+
rating: 'elite',
|
|
108
|
+
description: 'No commits found',
|
|
109
|
+
gaps: [],
|
|
110
|
+
totalMinutes: 0,
|
|
111
|
+
longestGap: 0,
|
|
112
|
+
gapCount: 0,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=investigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"investigation.js","sourceRoot":"","sources":["../../src/metrics/investigation.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics/rework.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rework.d.ts","sourceRoot":"","sources":["../../src/metrics/rework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"rework.d.ts","sourceRoot":"","sources":["../../src/metrics/rework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAU,MAAM,aAAa,CAAC;AAE3D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,CAoBpE"}
|
package/dist/metrics/rework.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateReworkRatio = calculateReworkRatio;
|
|
4
|
-
function calculateReworkRatio(commits) {
|
|
1
|
+
export function calculateReworkRatio(commits) {
|
|
5
2
|
if (commits.length === 0) {
|
|
6
3
|
return {
|
|
7
4
|
value: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rework.js","sourceRoot":"","sources":["../../src/metrics/rework.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rework.js","sourceRoot":"","sources":["../../src/metrics/rework.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,OAAiB;IACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,kBAAkB;SAChC,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;IAClE,MAAM,KAAK,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;IAClD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAEhC,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QACxB,IAAI,EAAE,GAAG;QACT,MAAM;QACN,WAAW,EAAE,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,OAAO,CAAC;IAC/B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,QAAQ,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,KAAa,EAAE,KAAa;IAClE,MAAM,OAAO,GAAG,GAAG,KAAK,IAAI,KAAK,oBAAoB,CAAC;IAEtD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,GAAG,OAAO,2BAA2B,CAAC;QAC/C,KAAK,MAAM;YACT,OAAO,GAAG,OAAO,2BAA2B,CAAC;QAC/C,KAAK,QAAQ;YACX,OAAO,GAAG,OAAO,iDAAiD,CAAC;QACrE,KAAK,KAAK;YACR,OAAO,GAAG,OAAO,2CAA2C,CAAC;IACjE,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Commit, FixChain, MetricResult } from '../types';
|
|
1
|
+
import { Commit, FixChain, MetricResult } from '../types.js';
|
|
2
2
|
export declare function detectFixChains(commits: Commit[]): FixChain[];
|
|
3
3
|
export declare function calculateDebugSpiralDuration(chains: FixChain[]): MetricResult;
|
|
4
4
|
export declare function calculatePatternSummary(chains: FixChain[]): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spirals.d.ts","sourceRoot":"","sources":["../../src/metrics/spirals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"spirals.d.ts","sourceRoot":"","sources":["../../src/metrics/spirals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAU,MAAM,aAAa,CAAC;AAcrE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAyC7D;AA8CD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAsB7E;AAwBD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG;IAC3D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;CACzB,CAoBA"}
|
package/dist/metrics/spirals.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectFixChains = detectFixChains;
|
|
4
|
-
exports.calculateDebugSpiralDuration = calculateDebugSpiralDuration;
|
|
5
|
-
exports.calculatePatternSummary = calculatePatternSummary;
|
|
6
|
-
const date_fns_1 = require("date-fns");
|
|
1
|
+
import { differenceInMinutes } from 'date-fns';
|
|
7
2
|
const SPIRAL_THRESHOLD = 3; // 3+ consecutive fixes = spiral
|
|
8
3
|
// Pattern detection regexes
|
|
9
4
|
const PATTERNS = {
|
|
@@ -14,7 +9,7 @@ const PATTERNS = {
|
|
|
14
9
|
IMAGE_REGISTRY: /image|pull|registry|docker|tag/i,
|
|
15
10
|
GITOPS_DRIFT: /drift|sync|argocd|reconcil|outof/i,
|
|
16
11
|
};
|
|
17
|
-
function detectFixChains(commits) {
|
|
12
|
+
export function detectFixChains(commits) {
|
|
18
13
|
if (commits.length === 0)
|
|
19
14
|
return [];
|
|
20
15
|
// Sort by date ascending
|
|
@@ -68,7 +63,7 @@ function getComponent(commit) {
|
|
|
68
63
|
function createFixChain(commits, component) {
|
|
69
64
|
const firstCommit = commits[0].date;
|
|
70
65
|
const lastCommit = commits[commits.length - 1].date;
|
|
71
|
-
const duration =
|
|
66
|
+
const duration = differenceInMinutes(lastCommit, firstCommit);
|
|
72
67
|
// Detect pattern from commit messages
|
|
73
68
|
const allMessages = commits.map((c) => c.message).join(' ');
|
|
74
69
|
const pattern = detectPattern(allMessages);
|
|
@@ -90,7 +85,7 @@ function detectPattern(text) {
|
|
|
90
85
|
}
|
|
91
86
|
return null;
|
|
92
87
|
}
|
|
93
|
-
function calculateDebugSpiralDuration(chains) {
|
|
88
|
+
export function calculateDebugSpiralDuration(chains) {
|
|
94
89
|
const spirals = chains.filter((c) => c.isSpiral);
|
|
95
90
|
if (spirals.length === 0) {
|
|
96
91
|
return {
|
|
@@ -132,7 +127,7 @@ function getDescription(rating, spiralCount) {
|
|
|
132
127
|
return `${spiralText}, extended debugging. Use tracer tests before implementation`;
|
|
133
128
|
}
|
|
134
129
|
}
|
|
135
|
-
function calculatePatternSummary(chains) {
|
|
130
|
+
export function calculatePatternSummary(chains) {
|
|
136
131
|
const categories = {};
|
|
137
132
|
let total = 0;
|
|
138
133
|
let withTracer = 0;
|