@boshu2/vibe-check 1.4.0 → 1.6.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 (188) hide show
  1. package/.agents/bundles/insight-mining-dashboard-research-2025-11-30.md +400 -0
  2. package/.agents/bundles/storage-enhancement-research-2025-11-30.md +292 -0
  3. package/.agents/bundles/timeline-feature-research-complete-2025-11-30.md +301 -0
  4. package/.agents/plans/insight-dashboard-plan-2025-11-30.md +1130 -0
  5. package/.agents/plans/json-storage-enhancement-plan.md +717 -0
  6. package/.agents/plans/storage-hardening-and-cache-plan.md +592 -0
  7. package/.agents/plans/test-coverage-gaps-plan.md +1117 -0
  8. package/.agents/plans/timeline-feature-plan.md +193 -0
  9. package/.agents/plans/vibe_timeline_research_findings.md +553 -0
  10. package/.claude/settings.local.json +1 -0
  11. package/.vibe-check/.gitignore +6 -0
  12. package/CHANGELOG.md +46 -0
  13. package/CLAUDE.md +24 -0
  14. package/CONTRIBUTING.md +227 -0
  15. package/README.md +200 -143
  16. package/claude-progress.json +200 -12
  17. package/claude-progress.txt +310 -0
  18. package/dashboard/app.js +75 -2
  19. package/dashboard/dashboard-data.json +653 -0
  20. package/dashboard/index.html +13 -0
  21. package/dashboard/styles.css +61 -0
  22. package/dist/analysis/cross-session-analysis.d.ts +68 -0
  23. package/dist/analysis/cross-session-analysis.d.ts.map +1 -0
  24. package/dist/analysis/cross-session-analysis.js +174 -0
  25. package/dist/analysis/cross-session-analysis.js.map +1 -0
  26. package/dist/analysis/index.d.ts +2 -0
  27. package/dist/analysis/index.d.ts.map +1 -0
  28. package/dist/analysis/index.js +12 -0
  29. package/dist/analysis/index.js.map +1 -0
  30. package/dist/cli.js +10 -1
  31. package/dist/cli.js.map +1 -1
  32. package/dist/commands/analyze.d.ts +2 -0
  33. package/dist/commands/analyze.d.ts.map +1 -1
  34. package/dist/commands/analyze.js +105 -2
  35. package/dist/commands/analyze.js.map +1 -1
  36. package/dist/commands/cache.d.ts +6 -0
  37. package/dist/commands/cache.d.ts.map +1 -0
  38. package/dist/commands/cache.js +168 -0
  39. package/dist/commands/cache.js.map +1 -0
  40. package/dist/commands/dashboard.d.ts +8 -0
  41. package/dist/commands/dashboard.d.ts.map +1 -0
  42. package/dist/commands/dashboard.js +109 -0
  43. package/dist/commands/dashboard.js.map +1 -0
  44. package/dist/commands/index.d.ts +3 -0
  45. package/dist/commands/index.d.ts.map +1 -1
  46. package/dist/commands/index.js +8 -1
  47. package/dist/commands/index.js.map +1 -1
  48. package/dist/commands/profile.d.ts.map +1 -1
  49. package/dist/commands/profile.js +140 -31
  50. package/dist/commands/profile.js.map +1 -1
  51. package/dist/commands/timeline.d.ts +14 -0
  52. package/dist/commands/timeline.d.ts.map +1 -0
  53. package/dist/commands/timeline.js +462 -0
  54. package/dist/commands/timeline.js.map +1 -0
  55. package/dist/gamification/badges.d.ts +29 -0
  56. package/dist/gamification/badges.d.ts.map +1 -0
  57. package/dist/gamification/badges.js +114 -0
  58. package/dist/gamification/badges.js.map +1 -0
  59. package/dist/gamification/challenges.d.ts +42 -0
  60. package/dist/gamification/challenges.d.ts.map +1 -0
  61. package/dist/gamification/challenges.js +184 -0
  62. package/dist/gamification/challenges.js.map +1 -0
  63. package/dist/gamification/hall-of-fame.d.ts +17 -0
  64. package/dist/gamification/hall-of-fame.d.ts.map +1 -0
  65. package/dist/gamification/hall-of-fame.js +64 -0
  66. package/dist/gamification/hall-of-fame.js.map +1 -0
  67. package/dist/gamification/leaderboards.d.ts +49 -0
  68. package/dist/gamification/leaderboards.d.ts.map +1 -0
  69. package/dist/gamification/leaderboards.js +179 -0
  70. package/dist/gamification/leaderboards.js.map +1 -0
  71. package/dist/gamification/share.d.ts +29 -0
  72. package/dist/gamification/share.d.ts.map +1 -0
  73. package/dist/gamification/share.js +57 -0
  74. package/dist/gamification/share.js.map +1 -0
  75. package/dist/gamification/stats.d.ts +34 -0
  76. package/dist/gamification/stats.d.ts.map +1 -0
  77. package/dist/gamification/stats.js +91 -0
  78. package/dist/gamification/stats.js.map +1 -0
  79. package/dist/gamification/streaks.d.ts +9 -1
  80. package/dist/gamification/streaks.d.ts.map +1 -1
  81. package/dist/gamification/streaks.js +37 -4
  82. package/dist/gamification/streaks.js.map +1 -1
  83. package/dist/gamification/types.d.ts +35 -0
  84. package/dist/gamification/types.d.ts.map +1 -1
  85. package/dist/gamification/types.js +11 -3
  86. package/dist/gamification/types.js.map +1 -1
  87. package/dist/gamification/xp.d.ts +6 -2
  88. package/dist/gamification/xp.d.ts.map +1 -1
  89. package/dist/gamification/xp.js +27 -5
  90. package/dist/gamification/xp.js.map +1 -1
  91. package/dist/git.d.ts +24 -0
  92. package/dist/git.d.ts.map +1 -1
  93. package/dist/git.js +94 -0
  94. package/dist/git.js.map +1 -1
  95. package/dist/insights/generators.d.ts +44 -0
  96. package/dist/insights/generators.d.ts.map +1 -0
  97. package/dist/insights/generators.js +289 -0
  98. package/dist/insights/generators.js.map +1 -0
  99. package/dist/insights/index.d.ts +16 -0
  100. package/dist/insights/index.d.ts.map +1 -0
  101. package/dist/insights/index.js +171 -0
  102. package/dist/insights/index.js.map +1 -0
  103. package/dist/insights/types.d.ts +93 -0
  104. package/dist/insights/types.d.ts.map +1 -0
  105. package/dist/insights/types.js +6 -0
  106. package/dist/insights/types.js.map +1 -0
  107. package/dist/output/terminal.d.ts.map +1 -1
  108. package/dist/output/terminal.js +39 -0
  109. package/dist/output/terminal.js.map +1 -1
  110. package/dist/output/timeline-html.d.ts +6 -0
  111. package/dist/output/timeline-html.d.ts.map +1 -0
  112. package/dist/output/timeline-html.js +389 -0
  113. package/dist/output/timeline-html.js.map +1 -0
  114. package/dist/output/timeline-markdown.d.ts +6 -0
  115. package/dist/output/timeline-markdown.d.ts.map +1 -0
  116. package/dist/output/timeline-markdown.js +167 -0
  117. package/dist/output/timeline-markdown.js.map +1 -0
  118. package/dist/output/timeline.d.ts +9 -0
  119. package/dist/output/timeline.d.ts.map +1 -0
  120. package/dist/output/timeline.js +318 -0
  121. package/dist/output/timeline.js.map +1 -0
  122. package/dist/patterns/detour.d.ts +32 -0
  123. package/dist/patterns/detour.d.ts.map +1 -0
  124. package/dist/patterns/detour.js +137 -0
  125. package/dist/patterns/detour.js.map +1 -0
  126. package/dist/patterns/flow-state.d.ts +16 -0
  127. package/dist/patterns/flow-state.d.ts.map +1 -0
  128. package/dist/patterns/flow-state.js +40 -0
  129. package/dist/patterns/flow-state.js.map +1 -0
  130. package/dist/patterns/index.d.ts +8 -0
  131. package/dist/patterns/index.d.ts.map +1 -0
  132. package/dist/patterns/index.js +22 -0
  133. package/dist/patterns/index.js.map +1 -0
  134. package/dist/patterns/intervention-effectiveness.d.ts +42 -0
  135. package/dist/patterns/intervention-effectiveness.d.ts.map +1 -0
  136. package/dist/patterns/intervention-effectiveness.js +196 -0
  137. package/dist/patterns/intervention-effectiveness.js.map +1 -0
  138. package/dist/patterns/late-night.d.ts +30 -0
  139. package/dist/patterns/late-night.d.ts.map +1 -0
  140. package/dist/patterns/late-night.js +141 -0
  141. package/dist/patterns/late-night.js.map +1 -0
  142. package/dist/patterns/post-delete-sprint.d.ts +28 -0
  143. package/dist/patterns/post-delete-sprint.d.ts.map +1 -0
  144. package/dist/patterns/post-delete-sprint.js +85 -0
  145. package/dist/patterns/post-delete-sprint.js.map +1 -0
  146. package/dist/patterns/spiral-regression.d.ts +49 -0
  147. package/dist/patterns/spiral-regression.d.ts.map +1 -0
  148. package/dist/patterns/spiral-regression.js +219 -0
  149. package/dist/patterns/spiral-regression.js.map +1 -0
  150. package/dist/patterns/thrashing.d.ts +25 -0
  151. package/dist/patterns/thrashing.d.ts.map +1 -0
  152. package/dist/patterns/thrashing.js +111 -0
  153. package/dist/patterns/thrashing.js.map +1 -0
  154. package/dist/storage/atomic.d.ts +40 -0
  155. package/dist/storage/atomic.d.ts.map +1 -0
  156. package/dist/storage/atomic.js +155 -0
  157. package/dist/storage/atomic.js.map +1 -0
  158. package/dist/storage/commit-log.d.ts +35 -0
  159. package/dist/storage/commit-log.d.ts.map +1 -0
  160. package/dist/storage/commit-log.js +128 -0
  161. package/dist/storage/commit-log.js.map +1 -0
  162. package/dist/storage/index.d.ts +5 -0
  163. package/dist/storage/index.d.ts.map +1 -0
  164. package/dist/storage/index.js +33 -0
  165. package/dist/storage/index.js.map +1 -0
  166. package/dist/storage/schema.d.ts +32 -0
  167. package/dist/storage/schema.d.ts.map +1 -0
  168. package/dist/storage/schema.js +37 -0
  169. package/dist/storage/schema.js.map +1 -0
  170. package/dist/storage/timeline-store.d.ts +117 -0
  171. package/dist/storage/timeline-store.d.ts.map +1 -0
  172. package/dist/storage/timeline-store.js +438 -0
  173. package/dist/storage/timeline-store.js.map +1 -0
  174. package/dist/types.d.ts +96 -0
  175. package/dist/types.d.ts.map +1 -1
  176. package/docs/ARCHITECTURE.md +458 -0
  177. package/docs/DATA-ARCHITECTURE.md +565 -0
  178. package/docs/GAMIFICATION.md +564 -0
  179. package/docs/JSON-STORAGE-PATTERNS.md +512 -0
  180. package/docs/METRICS-EXPLAINED.md +394 -0
  181. package/docs/UNIFIED-ECOSYSTEM.md +560 -0
  182. package/docs/VIBE-ECOSYSTEM.md +406 -0
  183. package/feature-list.json +103 -1
  184. package/package.json +2 -1
  185. package/vitest.config.ts +1 -5
  186. package/.vibe-check/calibration.json +0 -38
  187. package/.vibe-check/latest.json +0 -114
  188. package/.vibe-check/sessions.json +0 -34
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatTimelineTerminal = formatTimelineTerminal;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const date_fns_1 = require("date-fns");
9
+ /**
10
+ * Format timeline for terminal output
11
+ */
12
+ function formatTimelineTerminal(timeline, options = {}) {
13
+ const lines = [];
14
+ // Header
15
+ lines.push('');
16
+ lines.push(chalk_1.default.bold.cyan('═'.repeat(64)));
17
+ lines.push(chalk_1.default.bold.cyan(' VIBE-CHECK TIMELINE'));
18
+ const dateRange = `${(0, date_fns_1.format)(timeline.from, 'MMM d')} - ${(0, date_fns_1.format)(timeline.to, 'MMM d')} (${timeline.totalDays} days)`;
19
+ lines.push(chalk_1.default.bold.cyan(` ${dateRange}`));
20
+ lines.push(chalk_1.default.bold.cyan('═'.repeat(64)));
21
+ // Trend line
22
+ lines.push('');
23
+ const trendBar = buildTrendSparkline(timeline.trend);
24
+ const activeHours = Math.round(timeline.totalActiveMinutes / 60);
25
+ lines.push(` ${chalk_1.default.gray('TREND')} ${trendBar} ` +
26
+ chalk_1.default.gray(`Active: ~${activeHours}h Commits: ${timeline.totalCommits} Features: ${timeline.totalFeatures}`));
27
+ // Days
28
+ for (const day of timeline.days) {
29
+ lines.push('');
30
+ lines.push(formatDayHeader(day));
31
+ lines.push(formatDaySummary(day));
32
+ // Check if this day should be expanded
33
+ const expandValue = options.expand;
34
+ const shouldExpand = expandValue === true ||
35
+ expandValue === 'all' ||
36
+ expandValue === '' ||
37
+ expandValue === 'true' ||
38
+ (typeof expandValue === 'string' && day.displayDate.toLowerCase().includes(expandValue.toLowerCase()));
39
+ if (shouldExpand) {
40
+ // Show session details
41
+ for (const session of day.sessions) {
42
+ lines.push(formatSessionDetail(session));
43
+ }
44
+ }
45
+ else {
46
+ // Show session highlights
47
+ for (const session of day.sessions) {
48
+ lines.push(formatSessionHighlight(session));
49
+ }
50
+ }
51
+ }
52
+ // Insights section
53
+ const insights = generateInsights(timeline);
54
+ if (insights.length > 0) {
55
+ lines.push('');
56
+ lines.push(chalk_1.default.bold.cyan('═'.repeat(64)));
57
+ lines.push(chalk_1.default.bold.white(' INSIGHTS'));
58
+ lines.push('');
59
+ for (const insight of insights) {
60
+ lines.push(` ${insight}`);
61
+ }
62
+ }
63
+ lines.push('');
64
+ lines.push(chalk_1.default.bold.cyan('═'.repeat(64)));
65
+ lines.push(chalk_1.default.gray(` Run with ${chalk_1.default.white('--expand')} to see session details`));
66
+ lines.push('');
67
+ return lines.join('\n');
68
+ }
69
+ /**
70
+ * Build a sparkline from scores
71
+ */
72
+ function buildTrendSparkline(scores) {
73
+ const bars = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
74
+ return scores
75
+ .map(score => {
76
+ if (score === null)
77
+ return chalk_1.default.gray('▁');
78
+ // Score is 0-100, map to bar index
79
+ const idx = Math.min(7, Math.floor(score / 12.5));
80
+ const bar = bars[idx];
81
+ if (score >= 80)
82
+ return chalk_1.default.green(bar);
83
+ if (score >= 60)
84
+ return chalk_1.default.blue(bar);
85
+ if (score >= 40)
86
+ return chalk_1.default.yellow(bar);
87
+ return chalk_1.default.red(bar);
88
+ })
89
+ .join('');
90
+ }
91
+ /**
92
+ * Format day header
93
+ */
94
+ function formatDayHeader(day) {
95
+ const ratingStr = formatRating(day.dayRating);
96
+ const ratingPercent = day.dayScore !== null ? `${day.dayScore}%` : '';
97
+ const trophy = day.dayRating === 'ELITE' ? ' 🏆' : '';
98
+ return chalk_1.default.bold(` 📅 ${day.displayDate} ${'─'.repeat(30)} ${ratingPercent} ${ratingStr}${trophy}`);
99
+ }
100
+ /**
101
+ * Format day summary line
102
+ */
103
+ function formatDaySummary(day) {
104
+ const sessionCount = day.sessions.length;
105
+ const spiralText = day.spiralCount === 0
106
+ ? chalk_1.default.green('0 spirals')
107
+ : chalk_1.default.yellow(`${day.spiralCount} spiral${day.spiralCount > 1 ? 's' : ''}`);
108
+ return chalk_1.default.gray(` ${sessionCount} session${sessionCount > 1 ? 's' : ''}, ` +
109
+ `${day.totalCommits} commits, ${spiralText}, ` +
110
+ chalk_1.default.green(`+${day.totalXp} XP`));
111
+ }
112
+ /**
113
+ * Format session highlight (collapsed view)
114
+ */
115
+ function formatSessionHighlight(session) {
116
+ const timeRange = `${(0, date_fns_1.format)(session.start, 'HH:mm')}-${(0, date_fns_1.format)(session.end, 'HH:mm')}`;
117
+ const durationStr = formatDuration(session.duration);
118
+ // Get main work summary
119
+ const featCount = session.commits.filter(c => c.type === 'feat').length;
120
+ const fixCount = session.commits.filter(c => c.type === 'fix').length;
121
+ let workSummary = '';
122
+ if (featCount > 0) {
123
+ const firstFeat = session.commits.find(c => c.type === 'feat');
124
+ workSummary = firstFeat ? truncate(firstFeat.subject, 35) : `${featCount} features`;
125
+ }
126
+ else if (fixCount > 0) {
127
+ workSummary = `${fixCount} fix${fixCount > 1 ? 'es' : ''}`;
128
+ }
129
+ else {
130
+ const first = session.commits[0];
131
+ workSummary = truncate(first.subject, 35);
132
+ }
133
+ // Status icon
134
+ const icon = getSessionIcon(session);
135
+ return chalk_1.default.gray(` ${icon} ${workSummary} (${timeRange}, ${durationStr})`);
136
+ }
137
+ /**
138
+ * Format session detail (expanded view)
139
+ */
140
+ function formatSessionDetail(session) {
141
+ const lines = [];
142
+ const timeRange = `${(0, date_fns_1.format)(session.start, 'HH:mm')}-${(0, date_fns_1.format)(session.end, 'HH:mm')}`;
143
+ const durationStr = formatDuration(session.duration);
144
+ // Session header
145
+ const ratingStr = formatRating(session.overall);
146
+ const flowIcon = session.flowState ? ' 🌊' : '';
147
+ lines.push(chalk_1.default.white(` ┌─ Session ${timeRange} (${durationStr}) ${ratingStr}${flowIcon}`));
148
+ // List commits
149
+ for (const commit of session.commits) {
150
+ const typeIcon = getTypeIcon(commit.type);
151
+ const spiralMark = commit.spiralDepth > 0 ? chalk_1.default.yellow(` [spiral ${commit.spiralDepth}]`) : '';
152
+ lines.push(chalk_1.default.gray(` │ ${typeIcon} ${truncate(commit.subject, 45)}${spiralMark}`));
153
+ }
154
+ // Session footer with metrics
155
+ const trustStr = `Trust: ${session.trustPassRate}%`;
156
+ const reworkStr = `Rework: ${Math.round(session.reworkRatio)}%`;
157
+ lines.push(chalk_1.default.gray(` └─ ${trustStr}, ${reworkStr}`));
158
+ return lines.join('\n');
159
+ }
160
+ /**
161
+ * Get icon for session based on its characteristics
162
+ */
163
+ function getSessionIcon(session) {
164
+ if (session.flowState)
165
+ return '🌊';
166
+ if (session.spirals.length > 0)
167
+ return '⚠';
168
+ if (session.overall === 'ELITE')
169
+ return '✓';
170
+ return '○';
171
+ }
172
+ /**
173
+ * Get icon for commit type
174
+ */
175
+ function getTypeIcon(type) {
176
+ switch (type) {
177
+ case 'feat': return '●';
178
+ case 'fix': return '○';
179
+ case 'docs': return '◇';
180
+ case 'refactor': return '◆';
181
+ case 'test': return '◎';
182
+ default: return '○';
183
+ }
184
+ }
185
+ /**
186
+ * Format rating with color
187
+ */
188
+ function formatRating(rating) {
189
+ switch (rating) {
190
+ case 'ELITE': return chalk_1.default.green.bold('ELITE');
191
+ case 'HIGH': return chalk_1.default.blue.bold('HIGH');
192
+ case 'MEDIUM': return chalk_1.default.yellow.bold('MEDIUM');
193
+ case 'LOW': return chalk_1.default.red.bold('LOW');
194
+ }
195
+ }
196
+ /**
197
+ * Format duration in human-readable form
198
+ */
199
+ function formatDuration(minutes) {
200
+ if (minutes < 60)
201
+ return `${minutes}m`;
202
+ const hours = Math.floor(minutes / 60);
203
+ const mins = minutes % 60;
204
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
205
+ }
206
+ /**
207
+ * Truncate string with ellipsis
208
+ */
209
+ function truncate(str, maxLen) {
210
+ if (str.length <= maxLen)
211
+ return str;
212
+ return str.substring(0, maxLen - 1) + '…';
213
+ }
214
+ /**
215
+ * Generate insights from timeline data
216
+ */
217
+ function generateInsights(timeline) {
218
+ const insights = [];
219
+ // Post-delete sprint (Phase 2) - show first as it's the killer insight
220
+ if (timeline.postDeleteSprint?.detected) {
221
+ insights.push(chalk_1.default.magenta(`⚡ Post-delete sprint: ${timeline.postDeleteSprint.message}`));
222
+ }
223
+ // Flow states
224
+ if (timeline.flowStates > 0) {
225
+ const avgFlowDuration = timeline.sessions
226
+ .filter(s => s.flowState)
227
+ .reduce((sum, s) => sum + s.duration, 0) / timeline.flowStates;
228
+ insights.push(`🌊 Flow states: ${timeline.flowStates} detected (avg ${Math.round(avgFlowDuration)} min)`);
229
+ }
230
+ // Thrashing (Phase 2)
231
+ if (timeline.thrashing?.detected) {
232
+ insights.push(chalk_1.default.yellow(`🔄 Thrashing: ${timeline.thrashing.message}`));
233
+ // Show worst thrashing file
234
+ const worstFile = timeline.thrashing.files[0];
235
+ if (worstFile) {
236
+ insights.push(chalk_1.default.gray(` └─ ${truncate(worstFile.path, 40)}: ${worstFile.touchCount} edits, ${worstFile.efficiency}% efficiency`));
237
+ }
238
+ }
239
+ // Phase 3: Detours (code added then deleted)
240
+ if (timeline.detours?.detected) {
241
+ insights.push(chalk_1.default.yellow(timeline.detours.message));
242
+ // Show top detour details
243
+ const topDetour = timeline.detours.detours[0];
244
+ if (topDetour) {
245
+ insights.push(chalk_1.default.gray(` └─ ${topDetour.scope}: ${topDetour.linesAdded} lines built, ${topDetour.linesDeleted} deleted`));
246
+ }
247
+ }
248
+ // Phase 3: Late-night spirals
249
+ if (timeline.lateNightSpirals?.detected) {
250
+ insights.push(chalk_1.default.yellow(timeline.lateNightSpirals.message));
251
+ }
252
+ // Spirals
253
+ if (timeline.totalSpirals > 0) {
254
+ insights.push(chalk_1.default.yellow(`⚠ Debug spirals: ${timeline.totalSpirals} detected`));
255
+ }
256
+ // Productivity ratio
257
+ const wallClockHours = timeline.totalDays * 24;
258
+ const activeHours = timeline.totalActiveMinutes / 60;
259
+ const efficiencyPercent = Math.round((activeHours / wallClockHours) * 100);
260
+ insights.push(chalk_1.default.gray(`⏱ Active time: ${Math.round(activeHours)}h of ${wallClockHours}h (${efficiencyPercent}% efficiency)`));
261
+ // Best day
262
+ const bestDay = timeline.days.reduce((best, day) => (day.dayScore || 0) > (best.dayScore || 0) ? day : best);
263
+ if (bestDay.dayScore && bestDay.dayScore >= 80) {
264
+ insights.push(chalk_1.default.green(`🏆 Best day: ${bestDay.displayDate} (${bestDay.dayScore}%)`));
265
+ }
266
+ // Feature velocity
267
+ if (timeline.totalFeatures > 0) {
268
+ const featuresPerHour = timeline.totalFeatures / (timeline.totalActiveMinutes / 60);
269
+ insights.push(chalk_1.default.gray(`⚡ Feature velocity: ${featuresPerHour.toFixed(1)} features/hour`));
270
+ }
271
+ // Recommendation based on patterns
272
+ const recommendation = generateRecommendation(timeline);
273
+ if (recommendation) {
274
+ insights.push('');
275
+ insights.push(chalk_1.default.cyan(`💡 ${recommendation}`));
276
+ }
277
+ return insights;
278
+ }
279
+ /**
280
+ * Generate a recommendation based on detected patterns
281
+ */
282
+ function generateRecommendation(timeline) {
283
+ // Late-night spirals - strongest signal for behavior change
284
+ if (timeline.lateNightSpirals?.detected && timeline.lateNightSpirals.spirals.length > 0) {
285
+ const totalTime = timeline.lateNightSpirals.totalDuration;
286
+ if (totalTime > 30) {
287
+ return 'Late-night debugging is rarely efficient - sleep on it and tackle with fresh eyes';
288
+ }
289
+ }
290
+ // Detours detected - learn from experiments
291
+ if (timeline.detours?.detected && timeline.detours.totalTimeLost > 60) {
292
+ return 'Significant detour detected - try smaller experiments or spikes before committing';
293
+ }
294
+ // Post-delete sprint detected - reinforce the pattern
295
+ if (timeline.postDeleteSprint?.detected) {
296
+ return 'Trust simplification impulses - deletion often unlocks velocity';
297
+ }
298
+ // Thrashing detected - suggest stepping back
299
+ if (timeline.thrashing?.detected && timeline.thrashing.files.length > 2) {
300
+ return 'Multiple files with repeated edits - consider stepping back to design';
301
+ }
302
+ // Many spirals - suggest tracer tests
303
+ if (timeline.totalSpirals > 2) {
304
+ return 'Multiple debug spirals - try writing a tracer test before the next feature';
305
+ }
306
+ // Flow states detected - show what works
307
+ if (timeline.flowStates > 0) {
308
+ const flowSessions = timeline.sessions.filter(s => s.flowState);
309
+ const avgTime = flowSessions.reduce((sum, s) => {
310
+ const hour = s.start.getHours();
311
+ return sum + hour;
312
+ }, 0) / flowSessions.length;
313
+ const peakHour = Math.round(avgTime);
314
+ return `Flow states peak around ${peakHour}:00 - protect this time`;
315
+ }
316
+ return null;
317
+ }
318
+ //# sourceMappingURL=timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/output/timeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { TimelineEvent } from '../types';
2
+ export interface DetourResult {
3
+ detected: boolean;
4
+ detours: Detour[];
5
+ totalTimeLost: number;
6
+ message: string;
7
+ }
8
+ export interface Detour {
9
+ scope: string;
10
+ filesAffected: string[];
11
+ linesAdded: number;
12
+ linesDeleted: number;
13
+ startTime: Date;
14
+ endTime: Date;
15
+ duration: number;
16
+ }
17
+ /**
18
+ * Detect detours: code added then deleted within the analysis window.
19
+ *
20
+ * Definition: Code added then deleted in same analysis window
21
+ * Value: Track wasted time, learn from experiments
22
+ *
23
+ * How it works:
24
+ * 1. Track files/scopes with significant additions
25
+ * 2. Look for later commits that delete from same files/scopes
26
+ * 3. If deletions exceed 50% of additions, it's a detour
27
+ */
28
+ export declare function detectDetour(events: TimelineEvent[], filesPerCommit: Map<string, string[]>, lineStatsPerCommit: Map<string, {
29
+ additions: number;
30
+ deletions: number;
31
+ }>): DetourResult;
32
+ //# sourceMappingURL=detour.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detour.d.ts","sourceRoot":"","sources":["../../src/patterns/detour.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EAAE,EACvB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,GACxE,YAAY,CA6Gd"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectDetour = detectDetour;
4
+ /**
5
+ * Detect detours: code added then deleted within the analysis window.
6
+ *
7
+ * Definition: Code added then deleted in same analysis window
8
+ * Value: Track wasted time, learn from experiments
9
+ *
10
+ * How it works:
11
+ * 1. Track files/scopes with significant additions
12
+ * 2. Look for later commits that delete from same files/scopes
13
+ * 3. If deletions exceed 50% of additions, it's a detour
14
+ */
15
+ function detectDetour(events, filesPerCommit, lineStatsPerCommit) {
16
+ const detours = [];
17
+ // Group commits by scope (use scope or infer from files)
18
+ const scopeHistory = new Map();
19
+ // Build history per scope
20
+ for (const event of events) {
21
+ const scope = event.scope || inferScope(event, filesPerCommit);
22
+ if (!scope)
23
+ continue;
24
+ const stats = lineStatsPerCommit.get(event.hash);
25
+ if (!stats)
26
+ continue;
27
+ if (!scopeHistory.has(scope)) {
28
+ scopeHistory.set(scope, {
29
+ additions: 0,
30
+ deletions: 0,
31
+ files: new Set(),
32
+ firstAddTime: event.timestamp,
33
+ lastDeleteTime: event.timestamp,
34
+ addCommits: [],
35
+ deleteCommits: [],
36
+ });
37
+ }
38
+ const history = scopeHistory.get(scope);
39
+ history.additions += stats.additions;
40
+ history.deletions += stats.deletions;
41
+ // Track files touched
42
+ const files = filesPerCommit.get(event.hash) || [];
43
+ for (const file of files) {
44
+ history.files.add(file);
45
+ }
46
+ // Track commit types
47
+ if (stats.additions > stats.deletions) {
48
+ if (history.addCommits.length === 0) {
49
+ history.firstAddTime = event.timestamp;
50
+ }
51
+ history.addCommits.push(event);
52
+ }
53
+ else if (stats.deletions > stats.additions * 2) {
54
+ // Significant deletion
55
+ history.lastDeleteTime = event.timestamp;
56
+ history.deleteCommits.push(event);
57
+ }
58
+ }
59
+ // Identify detours: scopes where we added then deleted significantly
60
+ for (const [scope, history] of scopeHistory.entries()) {
61
+ // Skip if no significant additions followed by deletions
62
+ if (history.addCommits.length === 0 || history.deleteCommits.length === 0) {
63
+ continue;
64
+ }
65
+ // Check if deletions happened AFTER additions
66
+ const lastAdd = history.addCommits[history.addCommits.length - 1];
67
+ const hasDeleteAfterAdd = history.deleteCommits.some(d => d.timestamp > lastAdd.timestamp);
68
+ if (!hasDeleteAfterAdd)
69
+ continue;
70
+ // Detour threshold: deleted >50% of what was added
71
+ const netDeletionRatio = history.deletions / Math.max(history.additions, 1);
72
+ if (netDeletionRatio < 0.5)
73
+ continue;
74
+ // This is a detour
75
+ const duration = Math.round((history.lastDeleteTime.getTime() - history.firstAddTime.getTime()) / (1000 * 60));
76
+ detours.push({
77
+ scope,
78
+ filesAffected: Array.from(history.files),
79
+ linesAdded: history.additions,
80
+ linesDeleted: history.deletions,
81
+ startTime: history.firstAddTime,
82
+ endTime: history.lastDeleteTime,
83
+ duration,
84
+ });
85
+ }
86
+ // Calculate total time lost
87
+ const totalTimeLost = detours.reduce((sum, d) => sum + d.duration, 0);
88
+ // Generate message
89
+ let message = '';
90
+ if (detours.length > 0) {
91
+ const topDetour = detours.sort((a, b) => b.duration - a.duration)[0];
92
+ message = `🚧 ${detours.length} detour${detours.length > 1 ? 's' : ''} detected: ` +
93
+ `${topDetour.scope} took ${formatDuration(topDetour.duration)} ` +
94
+ `(${topDetour.linesAdded} lines added, then ${topDetour.linesDeleted} deleted)`;
95
+ }
96
+ return {
97
+ detected: detours.length > 0,
98
+ detours,
99
+ totalTimeLost,
100
+ message,
101
+ };
102
+ }
103
+ /**
104
+ * Infer scope from files touched by a commit
105
+ */
106
+ function inferScope(event, filesPerCommit) {
107
+ const files = filesPerCommit.get(event.hash) || [];
108
+ if (files.length === 0)
109
+ return null;
110
+ // Find common directory or file pattern
111
+ const commonParts = files[0].split('/');
112
+ for (let i = 1; i < files.length; i++) {
113
+ const parts = files[i].split('/');
114
+ let j = 0;
115
+ while (j < commonParts.length && j < parts.length && commonParts[j] === parts[j]) {
116
+ j++;
117
+ }
118
+ commonParts.length = j;
119
+ }
120
+ // Return the deepest meaningful directory
121
+ if (commonParts.length >= 2) {
122
+ return commonParts.slice(0, 2).join('/');
123
+ }
124
+ return commonParts[0] || null;
125
+ }
126
+ /**
127
+ * Format duration for display
128
+ */
129
+ function formatDuration(minutes) {
130
+ if (minutes < 60) {
131
+ return `${minutes}m`;
132
+ }
133
+ const hours = Math.floor(minutes / 60);
134
+ const mins = minutes % 60;
135
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
136
+ }
137
+ //# sourceMappingURL=detour.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detour.js","sourceRoot":"","sources":["../../src/patterns/detour.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { TimelineEvent } from '../types';
2
+ export interface FlowStateResult {
3
+ detected: boolean;
4
+ duration: number;
5
+ commits: number;
6
+ velocity: number;
7
+ peakType: string;
8
+ }
9
+ /**
10
+ * Detect flow state in a session.
11
+ *
12
+ * Definition: 5+ non-fix commits, no gap >30m, duration >45m
13
+ * Value: Shows when you're in the zone
14
+ */
15
+ export declare function detectFlowState(events: TimelineEvent[], sessionDuration: number): FlowStateResult;
16
+ //# sourceMappingURL=flow-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-state.d.ts","sourceRoot":"","sources":["../../src/patterns/flow-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EAAE,EACvB,eAAe,EAAE,MAAM,GACtB,eAAe,CAkCjB"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectFlowState = detectFlowState;
4
+ /**
5
+ * Detect flow state in a session.
6
+ *
7
+ * Definition: 5+ non-fix commits, no gap >30m, duration >45m
8
+ * Value: Shows when you're in the zone
9
+ */
10
+ function detectFlowState(events, sessionDuration) {
11
+ // Count non-fix commits
12
+ const nonFixCommits = events.filter(e => e.type !== 'fix');
13
+ const nonFixCount = nonFixCommits.length;
14
+ // Find max gap between consecutive commits
15
+ let maxGap = 0;
16
+ for (let i = 1; i < events.length; i++) {
17
+ maxGap = Math.max(maxGap, events[i].gapMinutes);
18
+ }
19
+ // Check flow state conditions
20
+ const detected = nonFixCount >= 5 && maxGap <= 30 && sessionDuration >= 45;
21
+ // Calculate velocity (commits per hour)
22
+ const velocity = sessionDuration > 0
23
+ ? (events.length / sessionDuration) * 60
24
+ : 0;
25
+ // Find peak commit type during flow
26
+ const typeCounts = {};
27
+ for (const event of nonFixCommits) {
28
+ typeCounts[event.type] = (typeCounts[event.type] || 0) + 1;
29
+ }
30
+ const peakType = Object.entries(typeCounts)
31
+ .sort((a, b) => b[1] - a[1])[0]?.[0] || 'other';
32
+ return {
33
+ detected,
34
+ duration: sessionDuration,
35
+ commits: events.length,
36
+ velocity: Math.round(velocity * 10) / 10,
37
+ peakType,
38
+ };
39
+ }
40
+ //# sourceMappingURL=flow-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-state.js","sourceRoot":"","sources":["../../src/patterns/flow-state.ts"],"names":[],"mappings":";;AAgBA,0CAqCC;AA3CD;;;;;GAKG;AACH,SAAgB,eAAe,CAC7B,MAAuB,EACvB,eAAuB;IAEvB,wBAAwB;IACxB,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IAEzC,2CAA2C;IAC3C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,WAAW,IAAI,CAAC,IAAI,MAAM,IAAI,EAAE,IAAI,eAAe,IAAI,EAAE,CAAC;IAE3E,wCAAwC;IACxC,MAAM,QAAQ,GAAG,eAAe,GAAG,CAAC;QAClC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE;QACxC,CAAC,CAAC,CAAC,CAAC;IAEN,oCAAoC;IACpC,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACxC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;IAElD,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,MAAM,CAAC,MAAM;QACtB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,GAAG,EAAE;QACxC,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { detectFlowState, FlowStateResult } from './flow-state';
2
+ export { detectPostDeleteSprint, PostDeleteSprintResult } from './post-delete-sprint';
3
+ export { detectThrashing, ThrashingResult, ThrashingFile } from './thrashing';
4
+ export { detectDetour, DetourResult, Detour } from './detour';
5
+ export { detectLateNightSpiral, LateNightSpiralResult, LateNightSpiral } from './late-night';
6
+ export { detectRegressions, analyzeRecoveryTimeTrend, getAllRecoveryTrends, RegressionAlert, RegressionAnalysis, } from './spiral-regression';
7
+ export { calculateEffectiveness, getRecommendation, compareInterventions, InterventionScore, EffectivenessAnalysis, } from './intervention-effectiveness';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compareInterventions = exports.getRecommendation = exports.calculateEffectiveness = exports.getAllRecoveryTrends = exports.analyzeRecoveryTimeTrend = exports.detectRegressions = exports.detectLateNightSpiral = exports.detectDetour = exports.detectThrashing = exports.detectPostDeleteSprint = exports.detectFlowState = void 0;
4
+ var flow_state_1 = require("./flow-state");
5
+ Object.defineProperty(exports, "detectFlowState", { enumerable: true, get: function () { return flow_state_1.detectFlowState; } });
6
+ var post_delete_sprint_1 = require("./post-delete-sprint");
7
+ Object.defineProperty(exports, "detectPostDeleteSprint", { enumerable: true, get: function () { return post_delete_sprint_1.detectPostDeleteSprint; } });
8
+ var thrashing_1 = require("./thrashing");
9
+ Object.defineProperty(exports, "detectThrashing", { enumerable: true, get: function () { return thrashing_1.detectThrashing; } });
10
+ var detour_1 = require("./detour");
11
+ Object.defineProperty(exports, "detectDetour", { enumerable: true, get: function () { return detour_1.detectDetour; } });
12
+ var late_night_1 = require("./late-night");
13
+ Object.defineProperty(exports, "detectLateNightSpiral", { enumerable: true, get: function () { return late_night_1.detectLateNightSpiral; } });
14
+ var spiral_regression_1 = require("./spiral-regression");
15
+ Object.defineProperty(exports, "detectRegressions", { enumerable: true, get: function () { return spiral_regression_1.detectRegressions; } });
16
+ Object.defineProperty(exports, "analyzeRecoveryTimeTrend", { enumerable: true, get: function () { return spiral_regression_1.analyzeRecoveryTimeTrend; } });
17
+ Object.defineProperty(exports, "getAllRecoveryTrends", { enumerable: true, get: function () { return spiral_regression_1.getAllRecoveryTrends; } });
18
+ var intervention_effectiveness_1 = require("./intervention-effectiveness");
19
+ Object.defineProperty(exports, "calculateEffectiveness", { enumerable: true, get: function () { return intervention_effectiveness_1.calculateEffectiveness; } });
20
+ Object.defineProperty(exports, "getRecommendation", { enumerable: true, get: function () { return intervention_effectiveness_1.getRecommendation; } });
21
+ Object.defineProperty(exports, "compareInterventions", { enumerable: true, get: function () { return intervention_effectiveness_1.compareInterventions; } });
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":";;;AAAA,2CAAgE;AAAvD,6GAAA,eAAe,OAAA;AACxB,2DAAsF;AAA7E,4HAAA,sBAAsB,OAAA;AAC/B,yCAA8E;AAArE,4GAAA,eAAe,OAAA;AACxB,mCAA8D;AAArD,sGAAA,YAAY,OAAA;AACrB,2CAA6F;AAApF,mHAAA,qBAAqB,OAAA;AAC9B,yDAM6B;AAL3B,sHAAA,iBAAiB,OAAA;AACjB,6HAAA,wBAAwB,OAAA;AACxB,yHAAA,oBAAoB,OAAA;AAItB,2EAMsC;AALpC,oIAAA,sBAAsB,OAAA;AACtB,+HAAA,iBAAiB,OAAA;AACjB,kIAAA,oBAAoB,OAAA"}