@boshu2/vibe-check 1.6.2 → 1.8.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.
Files changed (156) hide show
  1. package/.agents/bundles/actionable-coaching-plan-2025-12-02.md +209 -0
  2. package/.agents/bundles/automatic-learning-cadence-plan-2025-12-02.md +1297 -0
  3. package/.agents/bundles/automatic-learning-cadence-research-2025-12-02.md +481 -0
  4. package/.agents/bundles/dashboard-data-quality-plan.md +458 -0
  5. package/.agents/bundles/rating-scoring-alignment-plan.md +427 -0
  6. package/.agents/bundles/rpi-session-capture-plan-2025-12-02.md +693 -0
  7. package/.agents/bundles/rpi-session-capture-research-2025-12-02.md +433 -0
  8. package/.agents/bundles/session-integration-plan-2025-12-02.md +144 -0
  9. package/.agents/plans/git-forensics-enhancement-2025-12-05.md +493 -0
  10. package/.claude/skills/typescript-review.md +152 -0
  11. package/CHANGELOG.md +53 -0
  12. package/CLAUDE.md +79 -3
  13. package/Makefile +160 -0
  14. package/README.md +141 -155
  15. package/SECURITY.md +5 -1
  16. package/assets/logo-dark.svg +47 -0
  17. package/assets/logo.svg +47 -0
  18. package/claude-progress.json +54 -4
  19. package/claude-progress.txt +114 -0
  20. package/dashboard/app.js +699 -66
  21. package/dashboard/chart.min.js +20 -0
  22. package/dashboard/dashboard-data.js +764 -0
  23. package/dashboard/dashboard-data.json +182 -71
  24. package/dashboard/index.html +139 -14
  25. package/dashboard/styles.css +579 -4
  26. package/dist/analyzers/patterns.d.ts +62 -0
  27. package/dist/analyzers/patterns.d.ts.map +1 -0
  28. package/dist/analyzers/patterns.js +103 -0
  29. package/dist/analyzers/patterns.js.map +1 -0
  30. package/dist/analyzers/quality.d.ts +58 -0
  31. package/dist/analyzers/quality.d.ts.map +1 -0
  32. package/dist/analyzers/quality.js +114 -0
  33. package/dist/analyzers/quality.js.map +1 -0
  34. package/dist/analyzers/sessions.d.ts +45 -0
  35. package/dist/analyzers/sessions.d.ts.map +1 -0
  36. package/dist/analyzers/sessions.js +123 -0
  37. package/dist/analyzers/sessions.js.map +1 -0
  38. package/dist/cli.js +5 -1
  39. package/dist/cli.js.map +1 -1
  40. package/dist/commands/analyze.d.ts.map +1 -1
  41. package/dist/commands/analyze.js +43 -2
  42. package/dist/commands/analyze.js.map +1 -1
  43. package/dist/commands/dashboard.js +4 -1
  44. package/dist/commands/dashboard.js.map +1 -1
  45. package/dist/commands/forensics.d.ts +29 -0
  46. package/dist/commands/forensics.d.ts.map +1 -0
  47. package/dist/commands/forensics.js +213 -0
  48. package/dist/commands/forensics.js.map +1 -0
  49. package/dist/commands/index.d.ts +5 -1
  50. package/dist/commands/index.d.ts.map +1 -1
  51. package/dist/commands/index.js +13 -3
  52. package/dist/commands/index.js.map +1 -1
  53. package/dist/commands/insights.d.ts +3 -0
  54. package/dist/commands/insights.d.ts.map +1 -0
  55. package/dist/commands/insights.js +120 -0
  56. package/dist/commands/insights.js.map +1 -0
  57. package/dist/commands/learn.d.ts +3 -0
  58. package/dist/commands/learn.d.ts.map +1 -0
  59. package/dist/commands/learn.js +161 -0
  60. package/dist/commands/learn.js.map +1 -0
  61. package/dist/commands/lesson.d.ts +8 -0
  62. package/dist/commands/lesson.d.ts.map +1 -0
  63. package/dist/commands/lesson.js +206 -0
  64. package/dist/commands/lesson.js.map +1 -0
  65. package/dist/commands/pipeline.d.ts +3 -0
  66. package/dist/commands/pipeline.d.ts.map +1 -0
  67. package/dist/commands/pipeline.js +485 -0
  68. package/dist/commands/pipeline.js.map +1 -0
  69. package/dist/commands/profile.d.ts +0 -1
  70. package/dist/commands/profile.d.ts.map +1 -1
  71. package/dist/commands/profile.js +3 -206
  72. package/dist/commands/profile.js.map +1 -1
  73. package/dist/commands/session.d.ts +51 -0
  74. package/dist/commands/session.d.ts.map +1 -0
  75. package/dist/commands/session.js +599 -0
  76. package/dist/commands/session.js.map +1 -0
  77. package/dist/commands/sessions.d.ts +20 -0
  78. package/dist/commands/sessions.d.ts.map +1 -0
  79. package/dist/commands/sessions.js +201 -0
  80. package/dist/commands/sessions.js.map +1 -0
  81. package/dist/commands/watch.d.ts.map +1 -1
  82. package/dist/commands/watch.js +48 -7
  83. package/dist/commands/watch.js.map +1 -1
  84. package/dist/gamification/index.d.ts +1 -3
  85. package/dist/gamification/index.d.ts.map +1 -1
  86. package/dist/gamification/index.js +2 -5
  87. package/dist/gamification/index.js.map +1 -1
  88. package/dist/gamification/pattern-memory.d.ts +1 -1
  89. package/dist/gamification/pattern-memory.d.ts.map +1 -1
  90. package/dist/gamification/pattern-memory.js.map +1 -1
  91. package/dist/gamification/profile.d.ts +2 -2
  92. package/dist/gamification/profile.d.ts.map +1 -1
  93. package/dist/gamification/profile.js +2 -15
  94. package/dist/gamification/profile.js.map +1 -1
  95. package/dist/gamification/types.d.ts +8 -2
  96. package/dist/gamification/types.d.ts.map +1 -1
  97. package/dist/gamification/types.js.map +1 -1
  98. package/dist/insights/index.d.ts.map +1 -1
  99. package/dist/insights/index.js +16 -4
  100. package/dist/insights/index.js.map +1 -1
  101. package/dist/insights/types.d.ts +14 -0
  102. package/dist/insights/types.d.ts.map +1 -1
  103. package/dist/learning/cadence.d.ts +15 -0
  104. package/dist/learning/cadence.d.ts.map +1 -0
  105. package/dist/learning/cadence.js +130 -0
  106. package/dist/learning/cadence.js.map +1 -0
  107. package/dist/learning/index.d.ts +19 -0
  108. package/dist/learning/index.d.ts.map +1 -0
  109. package/dist/learning/index.js +35 -0
  110. package/dist/learning/index.js.map +1 -0
  111. package/dist/learning/lessons-storage.d.ts +48 -0
  112. package/dist/learning/lessons-storage.d.ts.map +1 -0
  113. package/dist/learning/lessons-storage.js +266 -0
  114. package/dist/learning/lessons-storage.js.map +1 -0
  115. package/dist/learning/lessons-types.d.ts +83 -0
  116. package/dist/learning/lessons-types.d.ts.map +1 -0
  117. package/dist/learning/lessons-types.js +15 -0
  118. package/dist/learning/lessons-types.js.map +1 -0
  119. package/dist/learning/nudges.d.ts +20 -0
  120. package/dist/learning/nudges.d.ts.map +1 -0
  121. package/dist/learning/nudges.js +68 -0
  122. package/dist/learning/nudges.js.map +1 -0
  123. package/dist/learning/retrospective.d.ts +27 -0
  124. package/dist/learning/retrospective.d.ts.map +1 -0
  125. package/dist/learning/retrospective.js +184 -0
  126. package/dist/learning/retrospective.js.map +1 -0
  127. package/dist/learning/storage.d.ts +44 -0
  128. package/dist/learning/storage.d.ts.map +1 -0
  129. package/dist/learning/storage.js +194 -0
  130. package/dist/learning/storage.js.map +1 -0
  131. package/dist/learning/surfacing.d.ts +36 -0
  132. package/dist/learning/surfacing.d.ts.map +1 -0
  133. package/dist/learning/surfacing.js +255 -0
  134. package/dist/learning/surfacing.js.map +1 -0
  135. package/dist/learning/synthesis.d.ts +17 -0
  136. package/dist/learning/synthesis.d.ts.map +1 -0
  137. package/dist/learning/synthesis.js +293 -0
  138. package/dist/learning/synthesis.js.map +1 -0
  139. package/dist/learning/types.d.ts +60 -0
  140. package/dist/learning/types.d.ts.map +1 -0
  141. package/dist/learning/types.js +17 -0
  142. package/dist/learning/types.js.map +1 -0
  143. package/dist/storage/index.d.ts +1 -0
  144. package/dist/storage/index.d.ts.map +1 -1
  145. package/dist/storage/index.js +11 -1
  146. package/dist/storage/index.js.map +1 -1
  147. package/dist/storage/spiral-history.d.ts +62 -0
  148. package/dist/storage/spiral-history.d.ts.map +1 -0
  149. package/dist/storage/spiral-history.js +265 -0
  150. package/dist/storage/spiral-history.js.map +1 -0
  151. package/docs/ARCHITECTURE.md +2 -10
  152. package/docs/GAMIFICATION.md +19 -266
  153. package/docs/METRICS.md +528 -0
  154. package/docs/VIBE-ECOSYSTEM.md +12 -78
  155. package/feature-list.json +141 -68
  156. package/package.json +1 -1
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * Pattern Detection Analyzer (VIBE-045)
4
+ *
5
+ * Analyzes git history to detect failure patterns:
6
+ * - Debug spirals ("take N" pattern)
7
+ * - Vague commits (<20 chars)
8
+ * - Context amnesia (repeated scope visits)
9
+ *
10
+ * Proven algorithm from release-engineering retrospective (475 commits analyzed).
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.detectDebugSpirals = detectDebugSpirals;
14
+ exports.detectVagueCommits = detectVagueCommits;
15
+ exports.detectContextAmnesia = detectContextAmnesia;
16
+ exports.detectPatterns = detectPatterns;
17
+ /**
18
+ * Detect "take N" pattern indicating debug spirals.
19
+ *
20
+ * A debug spiral is detected when 3+ commits match the pattern "take N" or similar
21
+ * retry patterns, indicating the developer is stuck in a fix-retry loop.
22
+ */
23
+ function detectDebugSpirals(commits) {
24
+ const takePattern = /^take\s*[0-9]+$/i;
25
+ const retryPatterns = [
26
+ /^(fix|try|attempt)\s*#?\d+$/i, // "fix 2", "try #3"
27
+ /^(wip|temp|test)\s*\d*$/i, // "wip", "wip2"
28
+ /^v\d+$/i, // "v2", "v3"
29
+ takePattern,
30
+ ];
31
+ const spiralCommits = commits.filter((c) => retryPatterns.some((pattern) => pattern.test(c.message.trim())));
32
+ if (spiralCommits.length < 3) {
33
+ return null;
34
+ }
35
+ // Sort by date to calculate duration
36
+ const sorted = [...spiralCommits].sort((a, b) => a.date.getTime() - b.date.getTime());
37
+ const first = sorted[0];
38
+ const last = sorted[sorted.length - 1];
39
+ const durationMinutes = (last.date.getTime() - first.date.getTime()) / (60 * 1000);
40
+ // Get unique dates
41
+ const dates = [...new Set(sorted.map((c) => c.date.toISOString().split('T')[0]))];
42
+ return {
43
+ count: spiralCommits.length,
44
+ durationMinutes: Math.round(durationMinutes * 10) / 10,
45
+ commits: spiralCommits.map((c) => c.hash),
46
+ dates,
47
+ };
48
+ }
49
+ /**
50
+ * Detect vague commits - messages that are too short to be meaningful.
51
+ *
52
+ * Threshold: < 20 characters is considered vague.
53
+ * Examples: "ci", "v3", "blah", "take 2", "fix"
54
+ */
55
+ function detectVagueCommits(commits, threshold = 20) {
56
+ const vagueCommits = commits.filter((c) => c.message.trim().length < threshold);
57
+ // Get example vague messages (deduplicated, max 10)
58
+ const examples = [
59
+ ...new Set(vagueCommits.map((c) => c.message.trim())),
60
+ ].slice(0, 10);
61
+ return {
62
+ count: vagueCommits.length,
63
+ percentage: commits.length > 0
64
+ ? Math.round((vagueCommits.length / commits.length) * 1000) / 10
65
+ : 0,
66
+ threshold,
67
+ examples,
68
+ };
69
+ }
70
+ /**
71
+ * Detect context amnesia - repeatedly returning to the same scope/component.
72
+ *
73
+ * This indicates the developer keeps revisiting the same area, possibly
74
+ * due to incomplete understanding or forgotten context.
75
+ *
76
+ * Reports scopes that appear in 5+ commits.
77
+ */
78
+ function detectContextAmnesia(commits, minVisits = 5) {
79
+ const scopeCounts = new Map();
80
+ for (const commit of commits) {
81
+ if (commit.scope) {
82
+ const current = scopeCounts.get(commit.scope) || 0;
83
+ scopeCounts.set(commit.scope, current + 1);
84
+ }
85
+ }
86
+ // Filter to scopes with high visit counts, sorted descending
87
+ const scopes = Array.from(scopeCounts.entries())
88
+ .filter(([, count]) => count >= minVisits)
89
+ .sort((a, b) => b[1] - a[1])
90
+ .map(([name, visits]) => ({ name, visits }));
91
+ return { scopes };
92
+ }
93
+ /**
94
+ * Run all pattern detection on a set of commits.
95
+ */
96
+ function detectPatterns(commits) {
97
+ return {
98
+ debugSpirals: detectDebugSpirals(commits),
99
+ vagueCommits: detectVagueCommits(commits),
100
+ contextAmnesia: detectContextAmnesia(commits),
101
+ };
102
+ }
103
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/analyzers/patterns.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAkCH,gDAoCC;AAQD,gDAsBC;AAUD,oDAoBC;AAKD,wCAMC;AAjHD;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,OAAiB;IAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC;IACvC,MAAM,aAAa,GAAG;QACpB,8BAA8B,EAAE,oBAAoB;QACpD,0BAA0B,EAAE,gBAAgB;QAC5C,SAAS,EAAE,aAAa;QACxB,WAAW;KACZ,CAAC;IAEF,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACzC,aAAa,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAChE,CAAC;IAEF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qCAAqC;IACrC,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAC9C,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,MAAM,eAAe,GACnB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAE7D,mBAAmB;IACnB,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElF,OAAO;QACL,KAAK,EAAE,aAAa,CAAC,MAAM;QAC3B,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC,GAAG,EAAE;QACtD,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACzC,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAChC,OAAiB,EACjB,YAAoB,EAAE;IAEtB,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,SAAS,CAC3C,CAAC;IAEF,oDAAoD;IACpD,MAAM,QAAQ,GAAG;QACf,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;KACtD,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEf,OAAO;QACL,KAAK,EAAE,YAAY,CAAC,MAAM;QAC1B,UAAU,EACR,OAAO,CAAC,MAAM,GAAG,CAAC;YAChB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE;YAChE,CAAC,CAAC,CAAC;QACP,SAAS;QACT,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,oBAAoB,CAClC,OAAiB,EACjB,YAAoB,CAAC;IAErB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE9C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACnD,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;SAC7C,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,SAAS,CAAC;SACzC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAE/C,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,OAAiB;IAC9C,OAAO;QACL,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC;QACzC,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC;QACzC,cAAc,EAAE,oBAAoB,CAAC,OAAO,CAAC;KAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Quality Metrics Analyzer (VIBE-045)
3
+ *
4
+ * Calculates commit message quality metrics:
5
+ * - Conventional commits percentage
6
+ * - Descriptive commits percentage
7
+ * - Vague commits percentage
8
+ *
9
+ * Proven algorithm from release-engineering retrospective.
10
+ */
11
+ import { Commit } from '../types';
12
+ export interface QualityMetrics {
13
+ totalCommits: number;
14
+ conventionalCommits: {
15
+ count: number;
16
+ percentage: number;
17
+ };
18
+ descriptiveCommits: {
19
+ count: number;
20
+ percentage: number;
21
+ minLength: number;
22
+ };
23
+ vagueCommits: {
24
+ count: number;
25
+ percentage: number;
26
+ threshold: number;
27
+ };
28
+ }
29
+ /**
30
+ * Check if a commit message follows conventional commit format.
31
+ *
32
+ * Format: type(scope?): description
33
+ * Examples: "feat: add login", "fix(auth): handle token expiry"
34
+ */
35
+ export declare function isConventionalCommit(message: string): boolean;
36
+ /**
37
+ * Check if a commit message is descriptive (meaningful length).
38
+ *
39
+ * A descriptive commit has at least 20 characters in the first line.
40
+ */
41
+ export declare function isDescriptiveCommit(message: string, minLength?: number): boolean;
42
+ /**
43
+ * Check if a commit message is vague (too short to be meaningful).
44
+ *
45
+ * Threshold: < 20 characters
46
+ */
47
+ export declare function isVagueCommit(message: string, threshold?: number): boolean;
48
+ /**
49
+ * Calculate quality metrics for a set of commits.
50
+ */
51
+ export declare function calculateQualityMetrics(commits: Commit[], vagueThreshold?: number, descriptiveMinLength?: number): QualityMetrics;
52
+ /**
53
+ * Generate a recommendation based on quality metrics.
54
+ *
55
+ * Returns 'sweep' if cleanup is recommended, 'maintain' if quality is acceptable.
56
+ */
57
+ export declare function getRecommendation(metrics: QualityMetrics, hasSpirals: boolean): 'sweep' | 'maintain' | 'celebrate';
58
+ //# sourceMappingURL=quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/analyzers/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,kBAAkB,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAmBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAW,GACrB,OAAO,CAGT;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAW,GACrB,OAAO,CAGT;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,GAAE,MAAW,EAC3B,oBAAoB,GAAE,MAAW,GAChC,cAAc,CAyChB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,OAAO,GAClB,OAAO,GAAG,UAAU,GAAG,WAAW,CAgBpC"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ /**
3
+ * Quality Metrics Analyzer (VIBE-045)
4
+ *
5
+ * Calculates commit message quality metrics:
6
+ * - Conventional commits percentage
7
+ * - Descriptive commits percentage
8
+ * - Vague commits percentage
9
+ *
10
+ * Proven algorithm from release-engineering retrospective.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.isConventionalCommit = isConventionalCommit;
14
+ exports.isDescriptiveCommit = isDescriptiveCommit;
15
+ exports.isVagueCommit = isVagueCommit;
16
+ exports.calculateQualityMetrics = calculateQualityMetrics;
17
+ exports.getRecommendation = getRecommendation;
18
+ /**
19
+ * Conventional commit types as per spec.
20
+ */
21
+ const CONVENTIONAL_TYPES = [
22
+ 'feat',
23
+ 'fix',
24
+ 'docs',
25
+ 'style',
26
+ 'refactor',
27
+ 'perf',
28
+ 'test',
29
+ 'build',
30
+ 'ci',
31
+ 'chore',
32
+ 'revert',
33
+ ];
34
+ /**
35
+ * Check if a commit message follows conventional commit format.
36
+ *
37
+ * Format: type(scope?): description
38
+ * Examples: "feat: add login", "fix(auth): handle token expiry"
39
+ */
40
+ function isConventionalCommit(message) {
41
+ const conventionalPattern = new RegExp(`^(${CONVENTIONAL_TYPES.join('|')})(\\([^)]+\\))?:\\s*.+`, 'i');
42
+ return conventionalPattern.test(message.trim());
43
+ }
44
+ /**
45
+ * Check if a commit message is descriptive (meaningful length).
46
+ *
47
+ * A descriptive commit has at least 20 characters in the first line.
48
+ */
49
+ function isDescriptiveCommit(message, minLength = 20) {
50
+ const firstLine = message.trim().split('\n')[0];
51
+ return firstLine.length >= minLength;
52
+ }
53
+ /**
54
+ * Check if a commit message is vague (too short to be meaningful).
55
+ *
56
+ * Threshold: < 20 characters
57
+ */
58
+ function isVagueCommit(message, threshold = 20) {
59
+ const firstLine = message.trim().split('\n')[0];
60
+ return firstLine.length < threshold;
61
+ }
62
+ /**
63
+ * Calculate quality metrics for a set of commits.
64
+ */
65
+ function calculateQualityMetrics(commits, vagueThreshold = 20, descriptiveMinLength = 20) {
66
+ const total = commits.length;
67
+ if (total === 0) {
68
+ return {
69
+ totalCommits: 0,
70
+ conventionalCommits: { count: 0, percentage: 0 },
71
+ descriptiveCommits: { count: 0, percentage: 0, minLength: descriptiveMinLength },
72
+ vagueCommits: { count: 0, percentage: 0, threshold: vagueThreshold },
73
+ };
74
+ }
75
+ const conventionalCount = commits.filter((c) => isConventionalCommit(c.message)).length;
76
+ const descriptiveCount = commits.filter((c) => isDescriptiveCommit(c.message, descriptiveMinLength)).length;
77
+ const vagueCount = commits.filter((c) => isVagueCommit(c.message, vagueThreshold)).length;
78
+ return {
79
+ totalCommits: total,
80
+ conventionalCommits: {
81
+ count: conventionalCount,
82
+ percentage: Math.round((conventionalCount / total) * 1000) / 10,
83
+ },
84
+ descriptiveCommits: {
85
+ count: descriptiveCount,
86
+ percentage: Math.round((descriptiveCount / total) * 1000) / 10,
87
+ minLength: descriptiveMinLength,
88
+ },
89
+ vagueCommits: {
90
+ count: vagueCount,
91
+ percentage: Math.round((vagueCount / total) * 1000) / 10,
92
+ threshold: vagueThreshold,
93
+ },
94
+ };
95
+ }
96
+ /**
97
+ * Generate a recommendation based on quality metrics.
98
+ *
99
+ * Returns 'sweep' if cleanup is recommended, 'maintain' if quality is acceptable.
100
+ */
101
+ function getRecommendation(metrics, hasSpirals) {
102
+ // Sweep if: >50% vague commits OR any debug spirals
103
+ if (metrics.vagueCommits.percentage > 50 || hasSpirals) {
104
+ return 'sweep';
105
+ }
106
+ // Celebrate if: >80% conventional AND <10% vague
107
+ if (metrics.conventionalCommits.percentage > 80 &&
108
+ metrics.vagueCommits.percentage < 10) {
109
+ return 'celebrate';
110
+ }
111
+ // Otherwise maintain current practices
112
+ return 'maintain';
113
+ }
114
+ //# sourceMappingURL=quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.js","sourceRoot":"","sources":["../../src/analyzers/quality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Session Detection Algorithm (VIBE-046)
3
+ *
4
+ * Identifies work sessions from git history using configurable time gap threshold.
5
+ * Proven algorithm from release-engineering retrospective (46 sessions detected from 475 commits).
6
+ *
7
+ * Default threshold: 90 minutes between commits starts a new session.
8
+ */
9
+ import { Commit } from '../types';
10
+ export interface DetectedSession {
11
+ sessionId: number;
12
+ startDate: Date;
13
+ endDate: Date;
14
+ durationMinutes: number;
15
+ commits: Commit[];
16
+ commitCount: number;
17
+ }
18
+ export interface SessionStats {
19
+ totalSessions: number;
20
+ totalCommits: number;
21
+ avgCommitsPerSession: number;
22
+ avgDurationMinutes: number;
23
+ medianDurationMinutes: number;
24
+ longestSessionMinutes: number;
25
+ shortestSessionMinutes: number;
26
+ }
27
+ export interface SessionDetectionResult {
28
+ sessions: DetectedSession[];
29
+ stats: SessionStats;
30
+ analysisRange: {
31
+ from: Date;
32
+ to: Date;
33
+ };
34
+ }
35
+ /**
36
+ * Detect work sessions from a list of commits.
37
+ *
38
+ * A new session starts when the gap between consecutive commits exceeds the threshold.
39
+ *
40
+ * @param commits List of commits (will be sorted by date)
41
+ * @param gapThresholdMinutes Minutes between commits to start new session (default: 90)
42
+ * @returns Session detection result with sessions and statistics
43
+ */
44
+ export declare function detectSessions(commits: Commit[], gapThresholdMinutes?: number): SessionDetectionResult;
45
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/analyzers/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE;QACb,IAAI,EAAE,IAAI,CAAC;QACX,EAAE,EAAE,IAAI,CAAC;KACV,CAAC;CACH;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EAAE,EACjB,mBAAmB,GAAE,MAAW,GAC/B,sBAAsB,CAkExB"}
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ /**
3
+ * Session Detection Algorithm (VIBE-046)
4
+ *
5
+ * Identifies work sessions from git history using configurable time gap threshold.
6
+ * Proven algorithm from release-engineering retrospective (46 sessions detected from 475 commits).
7
+ *
8
+ * Default threshold: 90 minutes between commits starts a new session.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.detectSessions = detectSessions;
12
+ /**
13
+ * Detect work sessions from a list of commits.
14
+ *
15
+ * A new session starts when the gap between consecutive commits exceeds the threshold.
16
+ *
17
+ * @param commits List of commits (will be sorted by date)
18
+ * @param gapThresholdMinutes Minutes between commits to start new session (default: 90)
19
+ * @returns Session detection result with sessions and statistics
20
+ */
21
+ function detectSessions(commits, gapThresholdMinutes = 90) {
22
+ if (commits.length === 0) {
23
+ return {
24
+ sessions: [],
25
+ stats: {
26
+ totalSessions: 0,
27
+ totalCommits: 0,
28
+ avgCommitsPerSession: 0,
29
+ avgDurationMinutes: 0,
30
+ medianDurationMinutes: 0,
31
+ longestSessionMinutes: 0,
32
+ shortestSessionMinutes: 0,
33
+ },
34
+ analysisRange: {
35
+ from: new Date(),
36
+ to: new Date(),
37
+ },
38
+ };
39
+ }
40
+ // Sort commits by date (oldest first)
41
+ const sortedCommits = [...commits].sort((a, b) => a.date.getTime() - b.date.getTime());
42
+ const gapThresholdMs = gapThresholdMinutes * 60 * 1000;
43
+ const sessions = [];
44
+ let currentSessionCommits = [];
45
+ let sessionId = 1;
46
+ for (const commit of sortedCommits) {
47
+ if (currentSessionCommits.length === 0) {
48
+ // Start first session
49
+ currentSessionCommits = [commit];
50
+ }
51
+ else {
52
+ const lastCommit = currentSessionCommits[currentSessionCommits.length - 1];
53
+ const gap = commit.date.getTime() - lastCommit.date.getTime();
54
+ if (gap > gapThresholdMs) {
55
+ // Gap exceeded - save current session and start new one
56
+ sessions.push(createSession(sessionId, currentSessionCommits));
57
+ sessionId++;
58
+ currentSessionCommits = [commit];
59
+ }
60
+ else {
61
+ // Continue current session
62
+ currentSessionCommits.push(commit);
63
+ }
64
+ }
65
+ }
66
+ // Don't forget the last session
67
+ if (currentSessionCommits.length > 0) {
68
+ sessions.push(createSession(sessionId, currentSessionCommits));
69
+ }
70
+ // Calculate statistics
71
+ const stats = calculateStats(sessions);
72
+ return {
73
+ sessions,
74
+ stats,
75
+ analysisRange: {
76
+ from: sortedCommits[0].date,
77
+ to: sortedCommits[sortedCommits.length - 1].date,
78
+ },
79
+ };
80
+ }
81
+ function createSession(sessionId, commits) {
82
+ const startDate = commits[0].date;
83
+ const endDate = commits[commits.length - 1].date;
84
+ const durationMinutes = (endDate.getTime() - startDate.getTime()) / (60 * 1000);
85
+ return {
86
+ sessionId,
87
+ startDate,
88
+ endDate,
89
+ durationMinutes: Math.round(durationMinutes * 10) / 10, // Round to 1 decimal
90
+ commits,
91
+ commitCount: commits.length,
92
+ };
93
+ }
94
+ function calculateStats(sessions) {
95
+ if (sessions.length === 0) {
96
+ return {
97
+ totalSessions: 0,
98
+ totalCommits: 0,
99
+ avgCommitsPerSession: 0,
100
+ avgDurationMinutes: 0,
101
+ medianDurationMinutes: 0,
102
+ longestSessionMinutes: 0,
103
+ shortestSessionMinutes: 0,
104
+ };
105
+ }
106
+ const totalCommits = sessions.reduce((sum, s) => sum + s.commitCount, 0);
107
+ const durations = sessions.map((s) => s.durationMinutes).sort((a, b) => a - b);
108
+ // Calculate median
109
+ const mid = Math.floor(durations.length / 2);
110
+ const medianDuration = durations.length % 2 === 0
111
+ ? (durations[mid - 1] + durations[mid]) / 2
112
+ : durations[mid];
113
+ return {
114
+ totalSessions: sessions.length,
115
+ totalCommits,
116
+ avgCommitsPerSession: Math.round((totalCommits / sessions.length) * 10) / 10,
117
+ avgDurationMinutes: Math.round((durations.reduce((sum, d) => sum + d, 0) / durations.length) * 10) / 10,
118
+ medianDurationMinutes: Math.round(medianDuration * 10) / 10,
119
+ longestSessionMinutes: durations[durations.length - 1],
120
+ shortestSessionMinutes: durations[0],
121
+ };
122
+ }
123
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/analyzers/sessions.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -18,10 +18,14 @@ program.addCommand((0, commands_1.createStartCommand)());
18
18
  program.addCommand((0, commands_1.createProfileCommand)());
19
19
  program.addCommand((0, commands_1.createInitHookCommand)());
20
20
  program.addCommand((0, commands_1.createWatchCommand)());
21
- program.addCommand((0, commands_1.createInterveneCommand)());
22
21
  program.addCommand((0, commands_1.createTimelineCommand)());
23
22
  program.addCommand((0, commands_1.createCacheCommand)());
24
23
  program.addCommand((0, commands_1.createDashboardCommand)());
24
+ program.addCommand((0, commands_1.createSessionCommand)());
25
+ program.addCommand((0, commands_1.createInsightsCommand)());
26
+ program.addCommand((0, commands_1.createPipelineCommand)());
27
+ program.addCommand((0, commands_1.createSessionsCommand)());
28
+ program.addCommand((0, commands_1.createForensicsCommand)());
25
29
  // Default behavior: if no subcommand, run analyze with passed options
26
30
  // This maintains backwards compatibility with v1.x usage
27
31
  program
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,yCAA8O;AAE9O,8DAA8D;AAC9D,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE/C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,OAAO,CAAC,OAAO,CAAC;KAChB,uBAAuB,EAAE;KACzB,kBAAkB,EAAE,CAAC;AAExB,kBAAkB;AAClB,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,iCAAsB,GAAE,CAAC,CAAC;AAC7C,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,iCAAsB,GAAE,CAAC,CAAC;AAE7C,sEAAsE;AACtE,yDAAyD;AACzD,OAAO;KACJ,MAAM,CAAC,gBAAgB,EAAE,8CAA8C,CAAC;KACxE,MAAM,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,yCAAyC,EAAE,UAAU,CAAC;KACpF,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC7D,MAAM,CAAC,eAAe,EAAE,qBAAqB,EAAE,KAAK,CAAC;KACrD,MAAM,CAAC,SAAS,EAAE,4CAA4C,EAAE,KAAK,CAAC;KACtE,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;KAC3D,MAAM,CAAC,cAAc,EAAE,mCAAmC,EAAE,KAAK,CAAC;KAClE,MAAM,CAAC,YAAY,EAAE,0DAA0D,CAAC;KAChF,MAAM,CAAC,iBAAiB,EAAE,yDAAyD,CAAC;KACpF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,wDAAwD;IACxD,MAAM,IAAA,qBAAU,EAAC;QACf,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,yCAAyU;AAEzU,8DAA8D;AAC9D,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE/C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,OAAO,CAAC,OAAO,CAAC;KAChB,uBAAuB,EAAE;KACzB,kBAAkB,EAAE,CAAC;AAExB,kBAAkB;AAClB,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,iCAAsB,GAAE,CAAC,CAAC;AAC7C,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,gCAAqB,GAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,IAAA,iCAAsB,GAAE,CAAC,CAAC;AAE7C,sEAAsE;AACtE,yDAAyD;AACzD,OAAO;KACJ,MAAM,CAAC,gBAAgB,EAAE,8CAA8C,CAAC;KACxE,MAAM,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,yCAAyC,EAAE,UAAU,CAAC;KACpF,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC7D,MAAM,CAAC,eAAe,EAAE,qBAAqB,EAAE,KAAK,CAAC;KACrD,MAAM,CAAC,SAAS,EAAE,4CAA4C,EAAE,KAAK,CAAC;KACtE,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;KAC3D,MAAM,CAAC,cAAc,EAAE,mCAAmC,EAAE,KAAK,CAAC;KAClE,MAAM,CAAC,YAAY,EAAE,0DAA0D,CAAC;KAChF,MAAM,CAAC,iBAAiB,EAAE,yDAAyD,CAAC;KACpF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,wDAAwD;IACxD,MAAM,IAAA,qBAAU,EAAC;QACf,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgCpC,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAkB9C;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6UvE"}
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAkB9C;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgYvE"}
@@ -22,6 +22,7 @@ const types_1 = require("../gamification/types");
22
22
  const start_1 = require("./start");
23
23
  const sessions_1 = require("../sessions");
24
24
  const analysis_1 = require("../analysis");
25
+ const spiral_history_1 = require("../storage/spiral-history");
25
26
  function createAnalyzeCommand() {
26
27
  const cmd = new commander_1.Command('analyze')
27
28
  .description('Analyze git history for vibe coding metrics')
@@ -150,6 +151,10 @@ async function runAnalyze(options) {
150
151
  const trustPassRate = result.metrics.trustPassRate.value;
151
152
  const reworkRatio = result.metrics.reworkRatio.value;
152
153
  const spiralCount = result.fixChains.filter(fc => fc.isSpiral).length;
154
+ // Record detected spirals to history for personalized coaching
155
+ for (const chain of result.fixChains.filter(fc => fc.isSpiral)) {
156
+ (0, spiral_history_1.appendSpiral)(chain.pattern || 'OTHER', chain.component, chain.duration, chain.commits);
157
+ }
153
158
  // Session comparison (if manual session was active via `start`)
154
159
  if (session && format === 'terminal') {
155
160
  const levelInfo = start_1.LEVEL_INFO[session.level];
@@ -243,8 +248,16 @@ async function runAnalyze(options) {
243
248
  // Record session and show gamification (only for terminal format with score)
244
249
  if (format === 'terminal' && resultV2.vibeScore) {
245
250
  const vibeScorePercent = Math.round(resultV2.vibeScore.value * 100);
246
- const gamificationResult = (0, profile_1.recordSession)(vibeScorePercent, result.overall, commits.length, spiralCount, result.period.from, result.period.to, result.fixChains // Pass fix chains for pattern memory
247
- );
251
+ // Use metric-based rating (quality grade) for session recording
252
+ const gamificationResult = (0, profile_1.recordSession)(vibeScorePercent, result.overall, commits.length, spiralCount, result.period.from, result.period.to, result.fixChains, // Pass fix chains for pattern memory
253
+ // Pass real metrics for dashboard visualization
254
+ {
255
+ iterationVelocity: result.metrics.iterationVelocity.value,
256
+ reworkRatio: result.metrics.reworkRatio.value,
257
+ trustPassRate: result.metrics.trustPassRate.value,
258
+ flowEfficiency: result.metrics.flowEfficiency.value,
259
+ debugSpiralDuration: result.metrics.debugSpiralDuration.value,
260
+ });
248
261
  // Show gamification summary
249
262
  console.log();
250
263
  console.log(chalk_1.default.cyan('─'.repeat(64)));
@@ -289,6 +302,34 @@ async function runAnalyze(options) {
289
302
  }
290
303
  }
291
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
+ }
331
+ }
332
+ }
292
333
  console.log(chalk_1.default.gray(` Run ${chalk_1.default.white('vibe-check profile')} to see your full stats`));
293
334
  console.log();
294
335
  }