@boshu2/vibe-check 1.6.1 → 1.7.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 (107) hide show
  1. package/.agents/bundles/automatic-learning-cadence-plan-2025-12-02.md +1297 -0
  2. package/.agents/bundles/automatic-learning-cadence-research-2025-12-02.md +481 -0
  3. package/.agents/bundles/dashboard-data-quality-plan.md +458 -0
  4. package/.agents/bundles/rating-scoring-alignment-plan.md +427 -0
  5. package/.agents/bundles/rpi-session-capture-plan-2025-12-02.md +693 -0
  6. package/.agents/bundles/rpi-session-capture-research-2025-12-02.md +433 -0
  7. package/.agents/bundles/session-integration-plan-2025-12-02.md +144 -0
  8. package/CHANGELOG.md +17 -0
  9. package/CLAUDE.md +74 -2
  10. package/Makefile +173 -0
  11. package/README.md +35 -2
  12. package/claude-progress.json +34 -5
  13. package/claude-progress.txt +66 -0
  14. package/dashboard/app.js +699 -66
  15. package/dashboard/chart.min.js +20 -0
  16. package/dashboard/dashboard-data.js +764 -0
  17. package/dashboard/dashboard-data.json +182 -71
  18. package/dashboard/index.html +139 -14
  19. package/dashboard/styles.css +579 -4
  20. package/dist/cli.js +1 -1
  21. package/dist/cli.js.map +1 -1
  22. package/dist/commands/analyze.d.ts.map +1 -1
  23. package/dist/commands/analyze.js +38 -2
  24. package/dist/commands/analyze.js.map +1 -1
  25. package/dist/commands/dashboard.js +4 -1
  26. package/dist/commands/dashboard.js.map +1 -1
  27. package/dist/commands/index.d.ts +1 -1
  28. package/dist/commands/index.d.ts.map +1 -1
  29. package/dist/commands/index.js +3 -3
  30. package/dist/commands/index.js.map +1 -1
  31. package/dist/commands/learn.d.ts +3 -0
  32. package/dist/commands/learn.d.ts.map +1 -0
  33. package/dist/commands/learn.js +161 -0
  34. package/dist/commands/learn.js.map +1 -0
  35. package/dist/commands/lesson.d.ts +8 -0
  36. package/dist/commands/lesson.d.ts.map +1 -0
  37. package/dist/commands/lesson.js +206 -0
  38. package/dist/commands/lesson.js.map +1 -0
  39. package/dist/commands/profile.d.ts.map +1 -1
  40. package/dist/commands/profile.js +3 -202
  41. package/dist/commands/profile.js.map +1 -1
  42. package/dist/commands/session.d.ts +51 -0
  43. package/dist/commands/session.d.ts.map +1 -0
  44. package/dist/commands/session.js +561 -0
  45. package/dist/commands/session.js.map +1 -0
  46. package/dist/gamification/index.d.ts +1 -3
  47. package/dist/gamification/index.d.ts.map +1 -1
  48. package/dist/gamification/index.js +2 -5
  49. package/dist/gamification/index.js.map +1 -1
  50. package/dist/gamification/pattern-memory.d.ts +1 -1
  51. package/dist/gamification/pattern-memory.d.ts.map +1 -1
  52. package/dist/gamification/pattern-memory.js.map +1 -1
  53. package/dist/gamification/profile.d.ts +2 -2
  54. package/dist/gamification/profile.d.ts.map +1 -1
  55. package/dist/gamification/profile.js +2 -15
  56. package/dist/gamification/profile.js.map +1 -1
  57. package/dist/gamification/types.d.ts +8 -2
  58. package/dist/gamification/types.d.ts.map +1 -1
  59. package/dist/gamification/types.js.map +1 -1
  60. package/dist/insights/index.d.ts.map +1 -1
  61. package/dist/insights/index.js +16 -4
  62. package/dist/insights/index.js.map +1 -1
  63. package/dist/insights/types.d.ts +14 -0
  64. package/dist/insights/types.d.ts.map +1 -1
  65. package/dist/learning/cadence.d.ts +15 -0
  66. package/dist/learning/cadence.d.ts.map +1 -0
  67. package/dist/learning/cadence.js +130 -0
  68. package/dist/learning/cadence.js.map +1 -0
  69. package/dist/learning/index.d.ts +19 -0
  70. package/dist/learning/index.d.ts.map +1 -0
  71. package/dist/learning/index.js +35 -0
  72. package/dist/learning/index.js.map +1 -0
  73. package/dist/learning/lessons-storage.d.ts +48 -0
  74. package/dist/learning/lessons-storage.d.ts.map +1 -0
  75. package/dist/learning/lessons-storage.js +266 -0
  76. package/dist/learning/lessons-storage.js.map +1 -0
  77. package/dist/learning/lessons-types.d.ts +83 -0
  78. package/dist/learning/lessons-types.d.ts.map +1 -0
  79. package/dist/learning/lessons-types.js +15 -0
  80. package/dist/learning/lessons-types.js.map +1 -0
  81. package/dist/learning/nudges.d.ts +20 -0
  82. package/dist/learning/nudges.d.ts.map +1 -0
  83. package/dist/learning/nudges.js +68 -0
  84. package/dist/learning/nudges.js.map +1 -0
  85. package/dist/learning/retrospective.d.ts +27 -0
  86. package/dist/learning/retrospective.d.ts.map +1 -0
  87. package/dist/learning/retrospective.js +184 -0
  88. package/dist/learning/retrospective.js.map +1 -0
  89. package/dist/learning/storage.d.ts +44 -0
  90. package/dist/learning/storage.d.ts.map +1 -0
  91. package/dist/learning/storage.js +194 -0
  92. package/dist/learning/storage.js.map +1 -0
  93. package/dist/learning/surfacing.d.ts +36 -0
  94. package/dist/learning/surfacing.d.ts.map +1 -0
  95. package/dist/learning/surfacing.js +255 -0
  96. package/dist/learning/surfacing.js.map +1 -0
  97. package/dist/learning/synthesis.d.ts +17 -0
  98. package/dist/learning/synthesis.d.ts.map +1 -0
  99. package/dist/learning/synthesis.js +293 -0
  100. package/dist/learning/synthesis.js.map +1 -0
  101. package/dist/learning/types.d.ts +60 -0
  102. package/dist/learning/types.d.ts.map +1 -0
  103. package/dist/learning/types.js +17 -0
  104. package/dist/learning/types.js.map +1 -0
  105. package/docs/METRICS.md +528 -0
  106. package/feature-list.json +21 -0
  107. package/package.json +1 -1
@@ -0,0 +1,458 @@
1
+ # Dashboard Data Quality Fixes - Implementation Plan
2
+
3
+ **Type:** Plan
4
+ **Created:** 2025-11-30
5
+ **Loop:** Middle (bridges analysis to implementation)
6
+ **Tags:** dashboard, data-quality, metrics, rating
7
+
8
+ ---
9
+
10
+ ## Overview
11
+
12
+ Fix data quality issues in vibe-check dashboard:
13
+ 1. **Rating system mismatch** - ELITE rating shows for low scores (63%)
14
+ 2. **Mock data in visualizations** - Radar chart uses hardcoded values
15
+ 3. **Missing metric context** - Session records don't store actual metrics
16
+
17
+ ## Root Cause Analysis
18
+
19
+ ### Issue 1: Rating vs Score Disconnect
20
+
21
+ **Finding:** The `overall` rating (ELITE/HIGH/MEDIUM/LOW) is calculated from **metric ratings**, not the vibeScore percentage.
22
+
23
+ ```typescript
24
+ // src/metrics/index.ts:96-111
25
+ function calculateOverallRating(ratings: Rating[]): OverallRating {
26
+ const scores = { elite: 4, high: 3, medium: 2, low: 1 };
27
+ const avgScore = ratings.reduce((sum, r) => sum + scores[r], 0) / ratings.length;
28
+
29
+ if (avgScore >= 3.5) return 'ELITE'; // 5 metrics averaging 3.5+
30
+ // ...
31
+ }
32
+ ```
33
+
34
+ Meanwhile, `vibeScore` is calculated separately from semantic-free metrics (fileChurn, timeSpiral, etc.).
35
+
36
+ **Result:** A session can have vibeScore=63% but rating=ELITE if the individual metric ratings (velocity, rework, trust, spirals, flow) all score well.
37
+
38
+ **Decision:** This is actually **correct by design**. The vibeScore is a different measure than the overall rating. The issue is **display confusion** - we should clarify this in the UI.
39
+
40
+ ### Issue 2: Mock Data in Radar Chart
41
+
42
+ **Finding:** The main radar chart in `app.js:380-391` uses hardcoded mock data:
43
+ ```javascript
44
+ data: [92, 78, 85, 88, 95], // NOT REAL DATA
45
+ ```
46
+
47
+ And the session detail modal calculates fake metrics:
48
+ ```javascript
49
+ const velocity = Math.round(session.commits / 2); // fake
50
+ const trustRate = Math.max(0, 100 - (session.spirals * 10)); // fake
51
+ ```
52
+
53
+ **Solution:** We need to either:
54
+ 1. Store real metrics in SessionRecord (schema change)
55
+ 2. Re-calculate metrics from commits when building dashboard data
56
+
57
+ Option 2 is simpler and maintains backward compatibility.
58
+
59
+ ### Issue 3: Session Record Missing Metrics
60
+
61
+ **Finding:** `SessionRecord` in types stores minimal data:
62
+ ```typescript
63
+ interface SessionRecord {
64
+ vibeScore: number;
65
+ overall: string;
66
+ commits: number;
67
+ spirals: number;
68
+ xpEarned: number;
69
+ // NO: iterationVelocity, reworkRatio, trustPassRate, flowEfficiency
70
+ }
71
+ ```
72
+
73
+ **Solution:** Enhance SessionRecord to include metrics, and update dashboard to use them.
74
+
75
+ ---
76
+
77
+ ## Implementation Plan
78
+
79
+ ### Phase 1: Enhance SessionRecord (Store Real Metrics)
80
+
81
+ #### File: `src/gamification/types.ts:38-49`
82
+
83
+ **Before:**
84
+ ```typescript
85
+ export interface SessionRecord {
86
+ date: string;
87
+ timestamp: string;
88
+ vibeScore: number;
89
+ overall: 'ELITE' | 'HIGH' | 'MEDIUM' | 'LOW';
90
+ commits: number;
91
+ spirals: number;
92
+ xpEarned: number;
93
+ achievementsUnlocked: string[];
94
+ periodFrom?: string;
95
+ periodTo?: string;
96
+ }
97
+ ```
98
+
99
+ **After:**
100
+ ```typescript
101
+ export interface SessionRecord {
102
+ date: string;
103
+ timestamp: string;
104
+ vibeScore: number;
105
+ overall: 'ELITE' | 'HIGH' | 'MEDIUM' | 'LOW';
106
+ commits: number;
107
+ spirals: number;
108
+ xpEarned: number;
109
+ achievementsUnlocked: string[];
110
+ periodFrom?: string;
111
+ periodTo?: string;
112
+ // NEW: Store actual metric values for dashboard
113
+ metrics?: {
114
+ iterationVelocity: number; // commits/hour
115
+ reworkRatio: number; // % fix commits
116
+ trustPassRate: number; // % commits without immediate fix
117
+ flowEfficiency: number; // % time building vs debugging
118
+ debugSpiralDuration: number; // avg minutes in spirals
119
+ };
120
+ }
121
+ ```
122
+
123
+ **Validation:** TypeScript compile, existing sessions still load (metrics optional)
124
+
125
+ ---
126
+
127
+ ### Phase 2: Record Metrics During Analysis
128
+
129
+ #### File: `src/gamification/profile.ts` - `recordSession` function
130
+
131
+ **Find the recordSession function and add metrics parameter.**
132
+
133
+ **Before (around line 130):**
134
+ ```typescript
135
+ export function recordSession(
136
+ vibeScore: number,
137
+ overall: OverallRating,
138
+ commits: number,
139
+ spirals: number
140
+ ): { profile: UserProfile; achievements: Achievement[] } {
141
+ ```
142
+
143
+ **After:**
144
+ ```typescript
145
+ export interface RecordSessionOptions {
146
+ vibeScore: number;
147
+ overall: OverallRating;
148
+ commits: number;
149
+ spirals: number;
150
+ metrics?: {
151
+ iterationVelocity: number;
152
+ reworkRatio: number;
153
+ trustPassRate: number;
154
+ flowEfficiency: number;
155
+ debugSpiralDuration: number;
156
+ };
157
+ periodFrom?: string;
158
+ periodTo?: string;
159
+ }
160
+
161
+ export function recordSession(
162
+ options: RecordSessionOptions
163
+ ): { profile: UserProfile; achievements: Achievement[] } {
164
+ ```
165
+
166
+ **Then update the session creation to include metrics.**
167
+
168
+ ---
169
+
170
+ ### Phase 3: Pass Metrics from Analyze Command
171
+
172
+ #### File: `src/commands/analyze.ts` - around line 240
173
+
174
+ **Find where recordGamificationSession is called and pass metrics.**
175
+
176
+ **Before:**
177
+ ```typescript
178
+ recordGamificationSession(
179
+ Math.round(vibeScoreValue * 100),
180
+ result.overall,
181
+ commits.length,
182
+ spiralCount
183
+ );
184
+ ```
185
+
186
+ **After:**
187
+ ```typescript
188
+ recordGamificationSession({
189
+ vibeScore: Math.round(vibeScoreValue * 100),
190
+ overall: result.overall,
191
+ commits: commits.length,
192
+ spirals: spiralCount,
193
+ metrics: {
194
+ iterationVelocity: result.metrics.iterationVelocity.value,
195
+ reworkRatio: result.metrics.reworkRatio.value,
196
+ trustPassRate: result.metrics.trustPassRate.value,
197
+ flowEfficiency: result.metrics.flowEfficiency.value,
198
+ debugSpiralDuration: result.metrics.debugSpiralDuration.value,
199
+ },
200
+ periodFrom: result.period.from.toISOString(),
201
+ periodTo: result.period.to.toISOString(),
202
+ });
203
+ ```
204
+
205
+ ---
206
+
207
+ ### Phase 4: Update Dashboard Data Builder
208
+
209
+ #### File: `src/insights/index.ts` - `buildDashboardData` function
210
+
211
+ **Update sessions mapping to include metrics (around line 192):**
212
+
213
+ **Before:**
214
+ ```typescript
215
+ sessions: sessions.slice(-50).reverse().map(s => ({
216
+ date: s.date,
217
+ vibeScore: s.vibeScore,
218
+ rating: s.overall,
219
+ commits: s.commits,
220
+ spirals: s.spirals,
221
+ xpEarned: s.xpEarned,
222
+ })),
223
+ ```
224
+
225
+ **After:**
226
+ ```typescript
227
+ sessions: sessions.slice(-50).reverse().map(s => ({
228
+ date: s.date,
229
+ vibeScore: s.vibeScore,
230
+ rating: s.overall,
231
+ commits: s.commits,
232
+ spirals: s.spirals,
233
+ xpEarned: s.xpEarned,
234
+ metrics: s.metrics || null,
235
+ })),
236
+ ```
237
+
238
+ **Also add aggregate metrics for the main radar chart:**
239
+
240
+ ```typescript
241
+ // Calculate average metrics from recent sessions
242
+ const recentWithMetrics = sessions.filter(s => s.metrics).slice(-10);
243
+ const avgMetrics = recentWithMetrics.length > 0 ? {
244
+ iterationVelocity: avg(recentWithMetrics.map(s => s.metrics!.iterationVelocity)),
245
+ reworkRatio: avg(recentWithMetrics.map(s => s.metrics!.reworkRatio)),
246
+ trustPassRate: avg(recentWithMetrics.map(s => s.metrics!.trustPassRate)),
247
+ flowEfficiency: avg(recentWithMetrics.map(s => s.metrics!.flowEfficiency)),
248
+ debugSpiralDuration: avg(recentWithMetrics.map(s => s.metrics!.debugSpiralDuration)),
249
+ } : null;
250
+ ```
251
+
252
+ Add to charts section:
253
+ ```typescript
254
+ charts: {
255
+ scoreTrend,
256
+ ratingDistribution,
257
+ hourlyActivity,
258
+ scopeHealth,
259
+ avgMetrics, // NEW
260
+ },
261
+ ```
262
+
263
+ ---
264
+
265
+ ### Phase 5: Update Dashboard UI to Use Real Metrics
266
+
267
+ #### File: `dashboard/app.js` - `initRadarChart` function (line 374)
268
+
269
+ **Before:**
270
+ ```javascript
271
+ // Mock metrics data
272
+ this.charts.radar = new Chart(ctx, {
273
+ type: 'radar',
274
+ data: {
275
+ labels: ['Trust Pass', 'Velocity', 'Flow', 'Stability', 'No Spirals'],
276
+ datasets: [{
277
+ label: 'Current',
278
+ data: [92, 78, 85, 88, 95], // HARDCODED
279
+ ```
280
+
281
+ **After:**
282
+ ```javascript
283
+ initRadarChart() {
284
+ const canvas = document.getElementById('radarCanvas');
285
+ if (!canvas) return;
286
+ const ctx = canvas.getContext('2d');
287
+ if (!ctx) return;
288
+
289
+ // Use real metrics from dashboard data, or defaults
290
+ const metrics = this.dashboardData?.charts?.avgMetrics;
291
+ const data = metrics ? [
292
+ Math.min(100, metrics.trustPassRate),
293
+ Math.min(100, metrics.iterationVelocity * 10), // scale velocity to 0-100
294
+ Math.min(100, metrics.flowEfficiency),
295
+ Math.max(0, 100 - metrics.reworkRatio), // invert: lower rework = higher score
296
+ Math.max(0, 100 - metrics.debugSpiralDuration * 2), // scale spirals
297
+ ] : [80, 80, 80, 80, 80]; // default if no data
298
+
299
+ this.charts.radar = new Chart(ctx, {
300
+ // ...
301
+ datasets: [{
302
+ label: 'Average',
303
+ data: data,
304
+ // ...
305
+ }]
306
+ });
307
+ }
308
+ ```
309
+
310
+ ---
311
+
312
+ ### Phase 6: Update Session Detail Modal
313
+
314
+ #### File: `dashboard/app.js` - `showSessionDetail` function (line 843)
315
+
316
+ **Before:**
317
+ ```javascript
318
+ // Calculate derived metrics (mock values based on score)
319
+ const velocity = Math.round(session.commits / 2);
320
+ const trustRate = Math.max(0, 100 - (session.spirals * 10));
321
+ ```
322
+
323
+ **After:**
324
+ ```javascript
325
+ // Use real metrics if available, otherwise estimate
326
+ const metrics = session.metrics;
327
+ const velocity = metrics?.iterationVelocity?.toFixed(1) || `~${Math.round(session.commits / 2)}`;
328
+ const trustRate = metrics?.trustPassRate?.toFixed(0) || Math.max(0, 100 - (session.spirals * 10));
329
+ const reworkRatio = metrics?.reworkRatio?.toFixed(0) || '--';
330
+ const flowEff = metrics?.flowEfficiency?.toFixed(0) || '--';
331
+
332
+ document.getElementById('detailVelocity').textContent = `${velocity}/hr`;
333
+ document.getElementById('detailTrust').textContent = `${trustRate}%`;
334
+ ```
335
+
336
+ ---
337
+
338
+ ### Phase 7: Add Clarification to UI
339
+
340
+ #### File: `dashboard/index.html` - Stats card section
341
+
342
+ Add tooltip or subtitle explaining the difference:
343
+
344
+ **Before:**
345
+ ```html
346
+ <span class="stat-label">Current Vibe Score</span>
347
+ ```
348
+
349
+ **After:**
350
+ ```html
351
+ <span class="stat-label">Current Vibe Score</span>
352
+ <span class="stat-hint" title="Code pattern health (0-100%)">Pattern Score</span>
353
+ ```
354
+
355
+ Add CSS for hint:
356
+ ```css
357
+ .stat-hint {
358
+ font-size: 0.625rem;
359
+ color: var(--text-muted);
360
+ display: block;
361
+ }
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Implementation Order
367
+
368
+ | Step | Action | Files | Validation |
369
+ |------|--------|-------|------------|
370
+ | 1 | Add metrics to SessionRecord type | `types.ts` | `npm run build` |
371
+ | 2 | Update recordSession signature | `profile.ts` | `npm run build` |
372
+ | 3 | Pass metrics from analyze | `analyze.ts` | `npm run build` |
373
+ | 4 | Update dashboard data builder | `insights/index.ts` | `npm run build` |
374
+ | 5 | Use real data in radar chart | `app.js` | Visual check |
375
+ | 6 | Use real data in session modal | `app.js` | Visual check |
376
+ | 7 | Add UI clarification | `index.html`, `styles.css` | Visual check |
377
+ | 8 | Full test | All | `vibe-check dashboard` |
378
+
379
+ ---
380
+
381
+ ## Rollback Procedure
382
+
383
+ All changes are additive (new optional fields). To rollback:
384
+
385
+ ```bash
386
+ git checkout HEAD~1 -- src/gamification/types.ts
387
+ git checkout HEAD~1 -- src/gamification/profile.ts
388
+ git checkout HEAD~1 -- src/commands/analyze.ts
389
+ git checkout HEAD~1 -- src/insights/index.ts
390
+ git checkout HEAD~1 -- dashboard/app.js
391
+ npm run build
392
+ ```
393
+
394
+ ---
395
+
396
+ ## Validation Strategy
397
+
398
+ ### After Each Step
399
+ ```bash
400
+ npm run build # No TypeScript errors
401
+ npm test # Tests still pass
402
+ ```
403
+
404
+ ### After All Steps
405
+ ```bash
406
+ # Generate fresh dashboard data
407
+ node dist/cli.js dashboard --no-open
408
+
409
+ # Verify metrics are in output
410
+ cat dashboard/dashboard-data.json | grep -A5 '"metrics"'
411
+
412
+ # Open dashboard and verify:
413
+ # 1. Radar chart shows real values (not 92, 78, 85, 88, 95)
414
+ # 2. Session detail shows real metrics
415
+ # 3. UI clarifies score vs rating
416
+ ```
417
+
418
+ ---
419
+
420
+ ## Risk Assessment
421
+
422
+ | Risk | Level | Mitigation |
423
+ |------|-------|------------|
424
+ | Breaking existing profiles | Low | metrics field is optional |
425
+ | TypeScript errors | Low | Incremental compilation |
426
+ | Dashboard not loading | Medium | Keep old data format compatible |
427
+
428
+ ---
429
+
430
+ ## Files Changed Summary
431
+
432
+ | File | Change Type | Lines Changed |
433
+ |------|-------------|---------------|
434
+ | `src/gamification/types.ts` | Modify | +10 |
435
+ | `src/gamification/profile.ts` | Modify | +25 |
436
+ | `src/commands/analyze.ts` | Modify | +15 |
437
+ | `src/insights/index.ts` | Modify | +20 |
438
+ | `dashboard/app.js` | Modify | +30 |
439
+ | `dashboard/index.html` | Modify | +5 |
440
+ | `dashboard/styles.css` | Modify | +5 |
441
+
442
+ **Total:** ~110 lines changed across 7 files
443
+
444
+ ---
445
+
446
+ ## Approval Checklist
447
+
448
+ - [ ] Schema change is backward compatible (optional field)
449
+ - [ ] All TypeScript files will compile
450
+ - [ ] Dashboard handles missing metrics gracefully
451
+ - [ ] Real metrics flow from analyze → profile → dashboard
452
+ - [ ] UI clearly distinguishes vibeScore from rating
453
+
454
+ ---
455
+
456
+ ## Next Step
457
+
458
+ Once approved: Implement changes in order listed above.