@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
package/dist/commands/analyze.js
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const types_1 = require("../gamification/types");
|
|
22
|
-
const start_1 = require("./start");
|
|
23
|
-
const sessions_1 = require("../sessions");
|
|
24
|
-
const analysis_1 = require("../analysis");
|
|
25
|
-
const spiral_history_1 = require("../storage/spiral-history");
|
|
26
|
-
function createAnalyzeCommand() {
|
|
27
|
-
const cmd = new commander_1.Command('analyze')
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { writeFileSync } from 'fs';
|
|
4
|
+
import { getCommits, isGitRepo, getFileStats } from '../git.js';
|
|
5
|
+
import { analyzeCommits, calculateTracerMetrics, calculateInvestigationMetrics, calculateCohesionMetrics } from '../metrics/index.js';
|
|
6
|
+
import { formatOutput } from '../output/index.js';
|
|
7
|
+
import { formatJson } from '../output/json.js';
|
|
8
|
+
import { calculateFileChurn } from '../metrics/file-churn.js';
|
|
9
|
+
import { calculateTimeSpiral } from '../metrics/time-spiral.js';
|
|
10
|
+
import { calculateVelocityAnomaly } from '../metrics/velocity-anomaly.js';
|
|
11
|
+
import { calculateCodeStability } from '../metrics/code-stability.js';
|
|
12
|
+
import { calculateVibeScore } from '../score/index.js';
|
|
13
|
+
import { recordSession as recordGamificationSession } from '../gamification/profile.js';
|
|
14
|
+
import { LEVELS } from '../gamification/types.js';
|
|
15
|
+
import { loadSession, clearSession, LEVEL_INFO } from './start.js';
|
|
16
|
+
import { detectSessionBoundary, recordSession as recordSessionHistory, compareToBaseline, loadSessionHistory, } from '../sessions/index.js';
|
|
17
|
+
import { loadAllCommits, getCrossSessionSummary, } from '../analysis/index.js';
|
|
18
|
+
import { appendSpiral } from '../storage/spiral-history.js';
|
|
19
|
+
export function createAnalyzeCommand() {
|
|
20
|
+
const cmd = new Command('analyze')
|
|
28
21
|
.description('Analyze git history for vibe coding metrics')
|
|
29
22
|
.option('--since <date>', 'Start date for analysis (e.g., "1 week ago")')
|
|
30
23
|
.option('--until <date>', 'End date for analysis (default: now)')
|
|
@@ -41,21 +34,21 @@ function createAnalyzeCommand() {
|
|
|
41
34
|
});
|
|
42
35
|
return cmd;
|
|
43
36
|
}
|
|
44
|
-
async function runAnalyze(options) {
|
|
37
|
+
export async function runAnalyze(options) {
|
|
45
38
|
try {
|
|
46
39
|
const { since, until, format, repo, verbose, score, output, simple, allTime, scope } = options;
|
|
47
40
|
// Check for active session
|
|
48
|
-
const session =
|
|
41
|
+
const session = loadSession(repo);
|
|
49
42
|
// Validate format
|
|
50
43
|
const validFormats = ['terminal', 'json', 'markdown'];
|
|
51
44
|
if (!validFormats.includes(format)) {
|
|
52
|
-
console.error(
|
|
53
|
-
console.error(
|
|
45
|
+
console.error(chalk.red(`Invalid format: ${format}`));
|
|
46
|
+
console.error(chalk.gray(`Valid formats: ${validFormats.join(', ')}`));
|
|
54
47
|
process.exit(1);
|
|
55
48
|
}
|
|
56
49
|
// Check if repo is valid
|
|
57
|
-
if (!(await
|
|
58
|
-
console.error(
|
|
50
|
+
if (!(await isGitRepo(repo))) {
|
|
51
|
+
console.error(chalk.red(`Not a git repository: ${repo}`));
|
|
59
52
|
process.exit(1);
|
|
60
53
|
}
|
|
61
54
|
// Handle --all-time flag: use cached commits instead of git
|
|
@@ -64,30 +57,30 @@ async function runAnalyze(options) {
|
|
|
64
57
|
return;
|
|
65
58
|
}
|
|
66
59
|
if (verbose) {
|
|
67
|
-
console.error(
|
|
60
|
+
console.error(chalk.gray(`Analyzing repository: ${repo}`));
|
|
68
61
|
if (since)
|
|
69
|
-
console.error(
|
|
62
|
+
console.error(chalk.gray(`Since: ${since}`));
|
|
70
63
|
if (until)
|
|
71
|
-
console.error(
|
|
64
|
+
console.error(chalk.gray(`Until: ${until}`));
|
|
72
65
|
if (scope)
|
|
73
|
-
console.error(
|
|
66
|
+
console.error(chalk.gray(`Scope filter: ${scope}`));
|
|
74
67
|
}
|
|
75
68
|
// Get commits
|
|
76
|
-
let commits = await
|
|
69
|
+
let commits = await getCommits(repo, since, until);
|
|
77
70
|
// Apply scope filter if specified
|
|
78
71
|
if (scope) {
|
|
79
72
|
commits = commits.filter(c => c.scope === scope);
|
|
80
73
|
if (verbose) {
|
|
81
|
-
console.error(
|
|
74
|
+
console.error(chalk.gray(`Filtered to ${commits.length} commits in scope "${scope}"`));
|
|
82
75
|
}
|
|
83
76
|
}
|
|
84
77
|
if (commits.length === 0) {
|
|
85
78
|
if (format === 'terminal') {
|
|
86
|
-
console.log(
|
|
79
|
+
console.log(chalk.yellow('\nNo commits found in the specified range.\n'));
|
|
87
80
|
if (!since) {
|
|
88
|
-
console.log(
|
|
89
|
-
console.log(
|
|
90
|
-
console.log(
|
|
81
|
+
console.log(chalk.gray('Try specifying a date range:'));
|
|
82
|
+
console.log(chalk.gray(' vibe-check --since "1 week ago"'));
|
|
83
|
+
console.log(chalk.gray(' vibe-check --since "2025-11-01"'));
|
|
91
84
|
}
|
|
92
85
|
}
|
|
93
86
|
else if (format === 'json') {
|
|
@@ -99,10 +92,10 @@ async function runAnalyze(options) {
|
|
|
99
92
|
process.exit(0);
|
|
100
93
|
}
|
|
101
94
|
if (verbose) {
|
|
102
|
-
console.error(
|
|
95
|
+
console.error(chalk.gray(`Found ${commits.length} commits`));
|
|
103
96
|
}
|
|
104
97
|
// Analyze commits (semantic metrics)
|
|
105
|
-
const result =
|
|
98
|
+
const result = analyzeCommits(commits);
|
|
106
99
|
// Build enhanced result
|
|
107
100
|
const resultV2 = {
|
|
108
101
|
...result,
|
|
@@ -112,15 +105,15 @@ async function runAnalyze(options) {
|
|
|
112
105
|
const needsEnhanced = score || session !== null;
|
|
113
106
|
if (needsEnhanced) {
|
|
114
107
|
if (verbose) {
|
|
115
|
-
console.error(
|
|
108
|
+
console.error(chalk.gray('Computing semantic-free metrics...'));
|
|
116
109
|
}
|
|
117
110
|
// Get file stats for semantic-free metrics
|
|
118
|
-
const fileStats = await
|
|
111
|
+
const fileStats = await getFileStats(repo, since, until);
|
|
119
112
|
// Calculate semantic-free metrics
|
|
120
|
-
const fileChurn =
|
|
121
|
-
const timeSpiral =
|
|
122
|
-
const velocityAnomaly =
|
|
123
|
-
const codeStability =
|
|
113
|
+
const fileChurn = calculateFileChurn(commits, fileStats.filesPerCommit);
|
|
114
|
+
const timeSpiral = calculateTimeSpiral(commits);
|
|
115
|
+
const velocityAnomaly = calculateVelocityAnomaly(commits);
|
|
116
|
+
const codeStability = calculateCodeStability(commits, fileStats.lineStats);
|
|
124
117
|
resultV2.semanticFreeMetrics = {
|
|
125
118
|
fileChurn,
|
|
126
119
|
timeSpiral,
|
|
@@ -128,24 +121,34 @@ async function runAnalyze(options) {
|
|
|
128
121
|
codeStability,
|
|
129
122
|
};
|
|
130
123
|
// Calculate VibeScore
|
|
131
|
-
const vibeScore =
|
|
124
|
+
const vibeScore = calculateVibeScore({
|
|
132
125
|
fileChurn,
|
|
133
126
|
timeSpiral,
|
|
134
127
|
velocityAnomaly,
|
|
135
128
|
codeStability,
|
|
136
129
|
});
|
|
137
130
|
resultV2.vibeScore = vibeScore;
|
|
131
|
+
// Calculate enhanced metrics (v2.2.0)
|
|
132
|
+
const sorted = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
133
|
+
const tracers = calculateTracerMetrics(sorted);
|
|
134
|
+
const investigation = calculateInvestigationMetrics(sorted);
|
|
135
|
+
const cohesion = calculateCohesionMetrics(sorted, fileStats.filesPerCommit);
|
|
136
|
+
resultV2.enhancedMetrics = {
|
|
137
|
+
tracers,
|
|
138
|
+
investigation,
|
|
139
|
+
cohesion,
|
|
140
|
+
};
|
|
138
141
|
}
|
|
139
142
|
// Write to file if requested (always JSON format)
|
|
140
143
|
if (output) {
|
|
141
|
-
const jsonOutput =
|
|
142
|
-
|
|
144
|
+
const jsonOutput = formatJson(resultV2);
|
|
145
|
+
writeFileSync(output, jsonOutput);
|
|
143
146
|
if (verbose) {
|
|
144
|
-
console.error(
|
|
147
|
+
console.error(chalk.gray(`Results written to: ${output}`));
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
// Output result to console
|
|
148
|
-
const formattedOutput =
|
|
151
|
+
const formattedOutput = formatOutput(resultV2, format, { simple });
|
|
149
152
|
console.log(formattedOutput);
|
|
150
153
|
// Get metrics for session tracking
|
|
151
154
|
const trustPassRate = result.metrics.trustPassRate.value;
|
|
@@ -153,11 +156,11 @@ async function runAnalyze(options) {
|
|
|
153
156
|
const spiralCount = result.fixChains.filter(fc => fc.isSpiral).length;
|
|
154
157
|
// Record detected spirals to history for personalized coaching
|
|
155
158
|
for (const chain of result.fixChains.filter(fc => fc.isSpiral)) {
|
|
156
|
-
|
|
159
|
+
appendSpiral(chain.pattern || 'OTHER', chain.component, chain.duration, chain.commits);
|
|
157
160
|
}
|
|
158
161
|
// Session comparison (if manual session was active via `start`)
|
|
159
162
|
if (session && format === 'terminal') {
|
|
160
|
-
const levelInfo =
|
|
163
|
+
const levelInfo = LEVEL_INFO[session.level];
|
|
161
164
|
// Parse expectations (already in percentage form like ">65%")
|
|
162
165
|
const expectTrust = parseFloat(levelInfo.expectTrust.replace(/[><%]/g, ''));
|
|
163
166
|
const expectRework = parseFloat(levelInfo.expectRework.replace(/[<%]/g, ''));
|
|
@@ -165,82 +168,82 @@ async function runAnalyze(options) {
|
|
|
165
168
|
const startTime = new Date(session.startedAt);
|
|
166
169
|
const duration = Math.round((Date.now() - startTime.getTime()) / 60000);
|
|
167
170
|
console.log('');
|
|
168
|
-
console.log(
|
|
171
|
+
console.log(chalk.bold.cyan('SESSION COMPLETE'));
|
|
169
172
|
console.log('');
|
|
170
173
|
console.log(` Declared: Level ${session.level} - ${levelInfo.name} (${levelInfo.trust} trust)`);
|
|
171
174
|
console.log(` Duration: ${duration} min, ${commits.length} commits`);
|
|
172
175
|
console.log('');
|
|
173
176
|
// Compare trust pass rate
|
|
174
177
|
const trustOk = trustPassRate >= expectTrust;
|
|
175
|
-
const trustIcon = trustOk ?
|
|
178
|
+
const trustIcon = trustOk ? chalk.green('✓') : chalk.yellow('⚠');
|
|
176
179
|
const trustExpect = `expected ${levelInfo.expectTrust}`;
|
|
177
180
|
console.log(` Trust Pass: ${Math.round(trustPassRate)}% (${trustExpect}) ${trustIcon}`);
|
|
178
181
|
// Compare rework ratio
|
|
179
182
|
const reworkOk = reworkRatio <= expectRework;
|
|
180
|
-
const reworkIcon = reworkOk ?
|
|
183
|
+
const reworkIcon = reworkOk ? chalk.green('✓') : chalk.yellow('⚠');
|
|
181
184
|
const reworkExpect = `expected ${levelInfo.expectRework}`;
|
|
182
185
|
console.log(` Rework: ${Math.round(reworkRatio)}% (${reworkExpect}) ${reworkIcon}`);
|
|
183
186
|
console.log('');
|
|
184
187
|
// Verdict
|
|
185
188
|
if (trustOk && reworkOk) {
|
|
186
|
-
console.log(
|
|
189
|
+
console.log(chalk.green(` ✓ Level ${session.level} was appropriate for this work`));
|
|
187
190
|
}
|
|
188
191
|
else if (!trustOk && !reworkOk) {
|
|
189
192
|
const suggestedLevel = Math.max(0, session.level - 2);
|
|
190
|
-
console.log(
|
|
191
|
-
console.log(
|
|
193
|
+
console.log(chalk.yellow(` ⚠ Level ${session.level} was too optimistic`));
|
|
194
|
+
console.log(chalk.gray(` Consider Level ${suggestedLevel} for similar tasks`));
|
|
192
195
|
}
|
|
193
196
|
else if (!trustOk) {
|
|
194
197
|
const suggestedLevel = Math.max(0, session.level - 1);
|
|
195
|
-
console.log(
|
|
196
|
-
console.log(
|
|
198
|
+
console.log(chalk.yellow(` ⚠ Trust was lower than expected`));
|
|
199
|
+
console.log(chalk.gray(` Consider Level ${suggestedLevel} for similar tasks`));
|
|
197
200
|
}
|
|
198
201
|
else {
|
|
199
202
|
// High trust but also high rework - likely iteration pattern
|
|
200
|
-
console.log(
|
|
201
|
-
console.log(
|
|
203
|
+
console.log(chalk.blue(` ℹ Good trust but high iteration`));
|
|
204
|
+
console.log(chalk.gray(` This might be expected for exploratory work`));
|
|
202
205
|
}
|
|
203
206
|
console.log('');
|
|
204
207
|
// Clear the session
|
|
205
|
-
|
|
208
|
+
clearSession(repo);
|
|
206
209
|
}
|
|
207
210
|
// Automatic session detection and baseline comparison (if no manual session)
|
|
208
211
|
if (!session && format === 'terminal' && commits.length >= 3) {
|
|
209
212
|
// Detect session boundary
|
|
210
|
-
const sessionInfo =
|
|
213
|
+
const sessionInfo = detectSessionBoundary(commits, repo);
|
|
211
214
|
// Calculate duration
|
|
212
215
|
const sessionDuration = Math.round((result.period.to.getTime() - sessionInfo.sessionStart.getTime()) / 60000);
|
|
213
216
|
// Record this session to history
|
|
214
|
-
(
|
|
217
|
+
recordSessionHistory(repo, sessionInfo.sessionStart, result.period.to, commits.length, trustPassRate, reworkRatio, spiralCount, resultV2.vibeScore?.value);
|
|
215
218
|
// Compare to baseline
|
|
216
|
-
const comparison =
|
|
219
|
+
const comparison = compareToBaseline(repo, trustPassRate, reworkRatio, commits.length, sessionDuration);
|
|
217
220
|
// Show baseline comparison
|
|
218
221
|
if (comparison.hasBaseline && comparison.comparison) {
|
|
219
222
|
console.log('');
|
|
220
|
-
console.log(
|
|
223
|
+
console.log(chalk.bold.cyan('VS YOUR BASELINE'));
|
|
221
224
|
console.log('');
|
|
222
225
|
const trustDelta = comparison.comparison.trustDelta;
|
|
223
226
|
const reworkDelta = comparison.comparison.reworkDelta;
|
|
224
227
|
const trustSign = trustDelta >= 0 ? '+' : '';
|
|
225
228
|
const reworkSign = reworkDelta >= 0 ? '+' : '';
|
|
226
|
-
const trustColor = trustDelta >= 0 ?
|
|
227
|
-
const reworkColor = reworkDelta <= 0 ?
|
|
229
|
+
const trustColor = trustDelta >= 0 ? chalk.green : chalk.yellow;
|
|
230
|
+
const reworkColor = reworkDelta <= 0 ? chalk.green : chalk.yellow;
|
|
228
231
|
console.log(` Trust: ${Math.round(trustPassRate)}% ${trustColor(`(${trustSign}${Math.round(trustDelta)}% vs avg ${comparison.baseline.trustPassRate}%)`)}`);
|
|
229
232
|
console.log(` Rework: ${Math.round(reworkRatio)}% ${reworkColor(`(${reworkSign}${Math.round(reworkDelta)}% vs avg ${comparison.baseline.reworkRatio}%)`)}`);
|
|
230
233
|
console.log('');
|
|
231
|
-
const verdictColor = comparison.comparison.verdict === 'above' ?
|
|
232
|
-
comparison.comparison.verdict === 'below' ?
|
|
233
|
-
|
|
234
|
+
const verdictColor = comparison.comparison.verdict === 'above' ? chalk.green :
|
|
235
|
+
comparison.comparison.verdict === 'below' ? chalk.yellow :
|
|
236
|
+
chalk.gray;
|
|
234
237
|
console.log(verdictColor(` ${comparison.comparison.message}`));
|
|
235
238
|
console.log('');
|
|
236
239
|
}
|
|
237
240
|
else {
|
|
238
241
|
// Building baseline
|
|
239
|
-
const history =
|
|
242
|
+
const history = loadSessionHistory(repo);
|
|
240
243
|
const sessionsNeeded = 5 - history.sessions.length;
|
|
241
244
|
if (sessionsNeeded > 0) {
|
|
242
245
|
console.log('');
|
|
243
|
-
console.log(
|
|
246
|
+
console.log(chalk.gray(` Building your baseline... ${history.sessions.length}/5 sessions recorded`));
|
|
244
247
|
console.log('');
|
|
245
248
|
}
|
|
246
249
|
}
|
|
@@ -249,7 +252,7 @@ async function runAnalyze(options) {
|
|
|
249
252
|
if (format === 'terminal' && resultV2.vibeScore) {
|
|
250
253
|
const vibeScorePercent = Math.round(resultV2.vibeScore.value * 100);
|
|
251
254
|
// Use metric-based rating (quality grade) for session recording
|
|
252
|
-
const gamificationResult = (
|
|
255
|
+
const gamificationResult = recordGamificationSession(vibeScorePercent, result.overall, commits.length, spiralCount, result.period.from, result.period.to, result.fixChains, // Pass fix chains for pattern memory
|
|
253
256
|
// Pass real metrics for dashboard visualization
|
|
254
257
|
{
|
|
255
258
|
iterationVelocity: result.metrics.iterationVelocity.value,
|
|
@@ -260,77 +263,49 @@ async function runAnalyze(options) {
|
|
|
260
263
|
});
|
|
261
264
|
// Show gamification summary
|
|
262
265
|
console.log();
|
|
263
|
-
console.log(
|
|
264
|
-
const levelInfo =
|
|
266
|
+
console.log(chalk.cyan('─'.repeat(64)));
|
|
267
|
+
const levelInfo = LEVELS.find(l => l.level === gamificationResult.profile.xp.level);
|
|
265
268
|
const { streak, xp } = gamificationResult.profile;
|
|
266
269
|
// Handle duplicate analysis (no XP awarded)
|
|
267
270
|
if (gamificationResult.isDuplicate) {
|
|
268
271
|
const streakFire = '🔥'.repeat(Math.min(streak.current, 5));
|
|
269
272
|
const streakText = streak.current > 0 ? `${streakFire} ${streak.current}-day streak` : '';
|
|
270
273
|
console.log(` ${streakText}`);
|
|
271
|
-
console.log(` ${levelInfo.icon} Level ${xp.level} ${xp.levelName} ${
|
|
272
|
-
console.log(
|
|
273
|
-
console.log(
|
|
274
|
-
console.log(
|
|
274
|
+
console.log(` ${levelInfo.icon} Level ${xp.level} ${xp.levelName} ${chalk.gray(`(${xp.currentLevelXP}/${xp.nextLevelXP} XP)`)}`);
|
|
275
|
+
console.log(chalk.gray(` ℹ Already analyzed this period (no XP awarded)`));
|
|
276
|
+
console.log(chalk.gray(` Make new commits to earn XP!`));
|
|
277
|
+
console.log(chalk.cyan('─'.repeat(64)));
|
|
275
278
|
console.log();
|
|
276
279
|
return;
|
|
277
280
|
}
|
|
278
281
|
// Streak line
|
|
279
282
|
const streakFire = '🔥'.repeat(Math.min(streak.current, 5));
|
|
280
283
|
const streakText = streak.current > 0
|
|
281
|
-
? `${streakFire} ${streak.current}-day streak${gamificationResult.streakExtended ?
|
|
282
|
-
:
|
|
284
|
+
? `${streakFire} ${streak.current}-day streak${gamificationResult.streakExtended ? chalk.yellow(' (+1!)') : ''}`
|
|
285
|
+
: chalk.gray('Start a streak by running vibe-check daily!');
|
|
283
286
|
console.log(` ${streakText}`);
|
|
284
287
|
// XP line
|
|
285
288
|
const xpGained = gamificationResult.xpEarned;
|
|
286
|
-
console.log(` ${levelInfo.icon} Level ${xp.level} ${xp.levelName} ${
|
|
289
|
+
console.log(` ${levelInfo.icon} Level ${xp.level} ${xp.levelName} ${chalk.gray(`(${xp.currentLevelXP}/${xp.nextLevelXP} XP)`)} ${chalk.green(`+${xpGained} XP`)}`);
|
|
287
290
|
// Level up celebration
|
|
288
291
|
if (gamificationResult.leveledUp) {
|
|
289
292
|
console.log();
|
|
290
|
-
console.log(
|
|
293
|
+
console.log(chalk.bold.magenta(` 🎉 LEVEL UP! You are now ${gamificationResult.newLevel}!`));
|
|
291
294
|
}
|
|
292
295
|
// Personal best
|
|
293
296
|
if (gamificationResult.isPersonalBest) {
|
|
294
|
-
console.log(
|
|
297
|
+
console.log(chalk.bold.yellow(` 🏆 NEW PERSONAL BEST: ${vibeScorePercent}%`));
|
|
295
298
|
}
|
|
296
299
|
// Achievement unlocks
|
|
297
300
|
if (gamificationResult.achievementsUnlocked.length > 0) {
|
|
298
301
|
console.log();
|
|
299
302
|
for (const ach of gamificationResult.achievementsUnlocked) {
|
|
300
|
-
console.log(
|
|
301
|
-
console.log(
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
console.log(chalk_1.default.cyan('─'.repeat(64)));
|
|
305
|
-
// Display pending nudges from learning system
|
|
306
|
-
const { formatNudgesForCli } = require('../learning/nudges');
|
|
307
|
-
const nudgeLines = formatNudgesForCli(2);
|
|
308
|
-
if (nudgeLines.length > 0) {
|
|
309
|
-
for (const line of nudgeLines) {
|
|
310
|
-
console.log(line);
|
|
311
|
-
}
|
|
312
|
-
console.log(chalk_1.default.cyan('─'.repeat(64)));
|
|
313
|
-
}
|
|
314
|
-
// Surface relevant lessons if spirals were detected
|
|
315
|
-
if (spiralCount > 0) {
|
|
316
|
-
const { surfaceLessonsForPattern, formatSurfacedLesson } = require('../learning/surfacing');
|
|
317
|
-
// Get patterns from detected spirals
|
|
318
|
-
const spiralPatterns = result.fixChains
|
|
319
|
-
.filter(fc => fc.isSpiral && fc.pattern)
|
|
320
|
-
.map(fc => fc.pattern);
|
|
321
|
-
const uniquePatterns = [...new Set(spiralPatterns)];
|
|
322
|
-
for (const pattern of uniquePatterns.slice(0, 2)) {
|
|
323
|
-
const surfaced = surfaceLessonsForPattern(pattern);
|
|
324
|
-
if (surfaced.length > 0) {
|
|
325
|
-
const lessonLines = formatSurfacedLesson(surfaced[0]);
|
|
326
|
-
for (const line of lessonLines) {
|
|
327
|
-
console.log(line);
|
|
328
|
-
}
|
|
329
|
-
console.log(chalk_1.default.cyan('─'.repeat(64)));
|
|
330
|
-
}
|
|
303
|
+
console.log(chalk.bold.green(` 🏆 ACHIEVEMENT UNLOCKED: ${ach.icon} ${ach.name}`));
|
|
304
|
+
console.log(chalk.gray(` ${ach.description}`));
|
|
331
305
|
}
|
|
332
306
|
}
|
|
333
|
-
console.log(
|
|
307
|
+
console.log(chalk.cyan('─'.repeat(64)));
|
|
308
|
+
console.log(chalk.gray(` Run ${chalk.white('vibe-check profile')} to see your full stats`));
|
|
334
309
|
console.log();
|
|
335
310
|
}
|
|
336
311
|
// Exit with appropriate code based on overall rating
|
|
@@ -340,13 +315,13 @@ async function runAnalyze(options) {
|
|
|
340
315
|
}
|
|
341
316
|
catch (error) {
|
|
342
317
|
if (error instanceof Error) {
|
|
343
|
-
console.error(
|
|
318
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
344
319
|
if (options.verbose) {
|
|
345
|
-
console.error(
|
|
320
|
+
console.error(chalk.gray(error.stack));
|
|
346
321
|
}
|
|
347
322
|
}
|
|
348
323
|
else {
|
|
349
|
-
console.error(
|
|
324
|
+
console.error(chalk.red('An unexpected error occurred'));
|
|
350
325
|
}
|
|
351
326
|
process.exit(1);
|
|
352
327
|
}
|
|
@@ -357,10 +332,10 @@ async function runAnalyze(options) {
|
|
|
357
332
|
async function runAllTimeAnalysis(options) {
|
|
358
333
|
const { format, repo, verbose, scope } = options;
|
|
359
334
|
// Load all commits from cache
|
|
360
|
-
let commits =
|
|
335
|
+
let commits = loadAllCommits(repo);
|
|
361
336
|
if (commits.length === 0) {
|
|
362
|
-
console.log(
|
|
363
|
-
console.log(
|
|
337
|
+
console.log(chalk.yellow('\nNo cached commits found.'));
|
|
338
|
+
console.log(chalk.gray('Run `vibe-check timeline` first to build the commit cache.\n'));
|
|
364
339
|
return;
|
|
365
340
|
}
|
|
366
341
|
// Apply scope filter if specified
|
|
@@ -368,51 +343,51 @@ async function runAllTimeAnalysis(options) {
|
|
|
368
343
|
commits = commits.filter(c => c.scope === scope);
|
|
369
344
|
}
|
|
370
345
|
if (verbose) {
|
|
371
|
-
console.error(
|
|
346
|
+
console.error(chalk.gray(`Loaded ${commits.length} commits from cache`));
|
|
372
347
|
}
|
|
373
348
|
// Get cross-session summary
|
|
374
|
-
const summary =
|
|
349
|
+
const summary = getCrossSessionSummary(commits);
|
|
375
350
|
if (format === 'json') {
|
|
376
351
|
console.log(JSON.stringify(summary, null, 2));
|
|
377
352
|
return;
|
|
378
353
|
}
|
|
379
354
|
// Terminal output
|
|
380
355
|
console.log('');
|
|
381
|
-
console.log(
|
|
382
|
-
console.log(
|
|
383
|
-
console.log(
|
|
356
|
+
console.log(chalk.bold.cyan('═'.repeat(64)));
|
|
357
|
+
console.log(chalk.bold.cyan(' ALL-TIME ANALYSIS'));
|
|
358
|
+
console.log(chalk.bold.cyan('═'.repeat(64)));
|
|
384
359
|
console.log('');
|
|
385
360
|
// Date range
|
|
386
361
|
if (summary.dateRange) {
|
|
387
362
|
const from = summary.dateRange.from.toLocaleDateString();
|
|
388
363
|
const to = summary.dateRange.to.toLocaleDateString();
|
|
389
|
-
console.log(
|
|
364
|
+
console.log(chalk.white(` Period: ${from} - ${to}`));
|
|
390
365
|
}
|
|
391
|
-
console.log(
|
|
366
|
+
console.log(chalk.white(` Total commits: ${summary.totalCommits}`));
|
|
392
367
|
console.log('');
|
|
393
368
|
// By type
|
|
394
|
-
console.log(
|
|
369
|
+
console.log(chalk.bold.white(' By Type:'));
|
|
395
370
|
const typeEntries = Object.entries(summary.byType).sort((a, b) => b[1] - a[1]);
|
|
396
371
|
for (const [type, count] of typeEntries) {
|
|
397
372
|
const pct = ((count / summary.totalCommits) * 100).toFixed(0);
|
|
398
373
|
const bar = '█'.repeat(Math.round(count / summary.totalCommits * 20));
|
|
399
|
-
console.log(` ${type.padEnd(10)} ${String(count).padStart(4)} (${pct.padStart(2)}%) ${
|
|
374
|
+
console.log(` ${type.padEnd(10)} ${String(count).padStart(4)} (${pct.padStart(2)}%) ${chalk.cyan(bar)}`);
|
|
400
375
|
}
|
|
401
376
|
console.log('');
|
|
402
377
|
// By scope (top 10)
|
|
403
378
|
if (summary.byScope.length > 0) {
|
|
404
|
-
console.log(
|
|
379
|
+
console.log(chalk.bold.white(' Top Scopes:'));
|
|
405
380
|
for (const scopeStats of summary.byScope.slice(0, 10)) {
|
|
406
381
|
const spiralPct = (scopeStats.spiralRatio * 100).toFixed(0);
|
|
407
|
-
const riskIcon = scopeStats.spiralRatio >= 0.5 ?
|
|
408
|
-
scopeStats.spiralRatio >= 0.3 ?
|
|
409
|
-
|
|
382
|
+
const riskIcon = scopeStats.spiralRatio >= 0.5 ? chalk.red('⚠') :
|
|
383
|
+
scopeStats.spiralRatio >= 0.3 ? chalk.yellow('●') :
|
|
384
|
+
chalk.green('●');
|
|
410
385
|
console.log(` ${riskIcon} ${scopeStats.scope.padEnd(20)} ${String(scopeStats.commitCount).padStart(4)} commits, ${spiralPct}% fixes`);
|
|
411
386
|
}
|
|
412
387
|
console.log('');
|
|
413
388
|
}
|
|
414
389
|
// Peak hours
|
|
415
|
-
console.log(
|
|
390
|
+
console.log(chalk.bold.white(' Peak Hours:'));
|
|
416
391
|
const peakHours = Object.entries(summary.byHour)
|
|
417
392
|
.map(([h, c]) => ({ hour: parseInt(h), count: c }))
|
|
418
393
|
.sort((a, b) => b.count - a.count)
|
|
@@ -420,21 +395,21 @@ async function runAllTimeAnalysis(options) {
|
|
|
420
395
|
for (const { hour, count } of peakHours) {
|
|
421
396
|
const hourStr = hour < 12 ? `${hour}am` : hour === 12 ? '12pm' : `${hour - 12}pm`;
|
|
422
397
|
const bar = '█'.repeat(Math.round(count / summary.totalCommits * 30));
|
|
423
|
-
console.log(` ${hourStr.padEnd(5)} ${String(count).padStart(4)} ${
|
|
398
|
+
console.log(` ${hourStr.padEnd(5)} ${String(count).padStart(4)} ${chalk.cyan(bar)}`);
|
|
424
399
|
}
|
|
425
400
|
console.log('');
|
|
426
401
|
// Problematic scopes warning
|
|
427
402
|
const problematic = summary.byScope.filter(s => s.commitCount >= 3 && s.spiralRatio >= 0.5);
|
|
428
403
|
if (problematic.length > 0) {
|
|
429
|
-
console.log(
|
|
404
|
+
console.log(chalk.bold.yellow(' ⚠ High-Risk Scopes (>50% fixes):'));
|
|
430
405
|
for (const scopeStats of problematic.slice(0, 5)) {
|
|
431
406
|
const spiralPct = (scopeStats.spiralRatio * 100).toFixed(0);
|
|
432
|
-
console.log(
|
|
407
|
+
console.log(chalk.yellow(` ${scopeStats.scope}: ${spiralPct}% fixes (${scopeStats.fixCount}/${scopeStats.commitCount})`));
|
|
433
408
|
}
|
|
434
|
-
console.log(
|
|
409
|
+
console.log(chalk.gray(' Consider adding tracer tests for these areas.'));
|
|
435
410
|
console.log('');
|
|
436
411
|
}
|
|
437
|
-
console.log(
|
|
412
|
+
console.log(chalk.gray(' Use --scope <name> to drill into a specific scope'));
|
|
438
413
|
console.log('');
|
|
439
414
|
}
|
|
440
415
|
//# sourceMappingURL=analyze.js.map
|