@boshu2/vibe-check 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/.agents/bundles/ml-learning-loop-complete-plan-2025-11-28.md +908 -0
  2. package/.agents/bundles/unified-vibe-system-plan-phase1-2025-11-28.md +962 -0
  3. package/.agents/bundles/unified-vibe-system-research-2025-11-28.md +1003 -0
  4. package/.agents/bundles/vibe-check-ecosystem-plan-2025-11-29.md +635 -0
  5. package/.agents/bundles/vibe-check-gamification-complete-2025-11-29.md +132 -0
  6. package/.agents/bundles/vibe-score-scientific-framework-2025-11-28.md +602 -0
  7. package/.vibe-check/calibration.json +38 -0
  8. package/.vibe-check/latest.json +114 -0
  9. package/CHANGELOG.md +47 -0
  10. package/CLAUDE.md +178 -0
  11. package/README.md +222 -7
  12. package/action.yml +270 -0
  13. package/dashboard/app.js +494 -0
  14. package/dashboard/index.html +235 -0
  15. package/dashboard/styles.css +647 -0
  16. package/dist/calibration/ece.d.ts +26 -0
  17. package/dist/calibration/ece.d.ts.map +1 -0
  18. package/dist/calibration/ece.js +93 -0
  19. package/dist/calibration/ece.js.map +1 -0
  20. package/dist/calibration/index.d.ts +3 -0
  21. package/dist/calibration/index.d.ts.map +1 -0
  22. package/dist/calibration/index.js +15 -0
  23. package/dist/calibration/index.js.map +1 -0
  24. package/dist/calibration/storage.d.ts +34 -0
  25. package/dist/calibration/storage.d.ts.map +1 -0
  26. package/dist/calibration/storage.js +188 -0
  27. package/dist/calibration/storage.js.map +1 -0
  28. package/dist/cli.js +31 -76
  29. package/dist/cli.js.map +1 -1
  30. package/dist/commands/analyze.d.ts +16 -0
  31. package/dist/commands/analyze.d.ts.map +1 -0
  32. package/dist/commands/analyze.js +256 -0
  33. package/dist/commands/analyze.js.map +1 -0
  34. package/dist/commands/index.d.ts +5 -0
  35. package/dist/commands/index.d.ts.map +1 -0
  36. package/dist/commands/index.js +13 -0
  37. package/dist/commands/index.js.map +1 -0
  38. package/dist/commands/init-hook.d.ts +3 -0
  39. package/dist/commands/init-hook.d.ts.map +1 -0
  40. package/dist/commands/init-hook.js +161 -0
  41. package/dist/commands/init-hook.js.map +1 -0
  42. package/dist/commands/level.d.ts +3 -0
  43. package/dist/commands/level.d.ts.map +1 -0
  44. package/dist/commands/level.js +277 -0
  45. package/dist/commands/level.js.map +1 -0
  46. package/dist/commands/profile.d.ts +4 -0
  47. package/dist/commands/profile.d.ts.map +1 -0
  48. package/dist/commands/profile.js +143 -0
  49. package/dist/commands/profile.js.map +1 -0
  50. package/dist/gamification/achievements.d.ts +15 -0
  51. package/dist/gamification/achievements.d.ts.map +1 -0
  52. package/dist/gamification/achievements.js +273 -0
  53. package/dist/gamification/achievements.js.map +1 -0
  54. package/dist/gamification/index.d.ts +8 -0
  55. package/dist/gamification/index.d.ts.map +1 -0
  56. package/dist/gamification/index.js +30 -0
  57. package/dist/gamification/index.js.map +1 -0
  58. package/dist/gamification/profile.d.ts +46 -0
  59. package/dist/gamification/profile.d.ts.map +1 -0
  60. package/dist/gamification/profile.js +272 -0
  61. package/dist/gamification/profile.js.map +1 -0
  62. package/dist/gamification/streaks.d.ts +26 -0
  63. package/dist/gamification/streaks.d.ts.map +1 -0
  64. package/dist/gamification/streaks.js +132 -0
  65. package/dist/gamification/streaks.js.map +1 -0
  66. package/dist/gamification/types.d.ts +111 -0
  67. package/dist/gamification/types.d.ts.map +1 -0
  68. package/dist/gamification/types.js +26 -0
  69. package/dist/gamification/types.js.map +1 -0
  70. package/dist/gamification/xp.d.ts +37 -0
  71. package/dist/gamification/xp.d.ts.map +1 -0
  72. package/dist/gamification/xp.js +115 -0
  73. package/dist/gamification/xp.js.map +1 -0
  74. package/dist/git.d.ts +11 -0
  75. package/dist/git.d.ts.map +1 -1
  76. package/dist/git.js +52 -0
  77. package/dist/git.js.map +1 -1
  78. package/dist/metrics/code-stability.d.ts +13 -0
  79. package/dist/metrics/code-stability.d.ts.map +1 -0
  80. package/dist/metrics/code-stability.js +74 -0
  81. package/dist/metrics/code-stability.js.map +1 -0
  82. package/dist/metrics/file-churn.d.ts +8 -0
  83. package/dist/metrics/file-churn.d.ts.map +1 -0
  84. package/dist/metrics/file-churn.js +75 -0
  85. package/dist/metrics/file-churn.js.map +1 -0
  86. package/dist/metrics/time-spiral.d.ts +8 -0
  87. package/dist/metrics/time-spiral.d.ts.map +1 -0
  88. package/dist/metrics/time-spiral.js +69 -0
  89. package/dist/metrics/time-spiral.js.map +1 -0
  90. package/dist/metrics/velocity-anomaly.d.ts +13 -0
  91. package/dist/metrics/velocity-anomaly.d.ts.map +1 -0
  92. package/dist/metrics/velocity-anomaly.js +67 -0
  93. package/dist/metrics/velocity-anomaly.js.map +1 -0
  94. package/dist/output/index.d.ts +6 -3
  95. package/dist/output/index.d.ts.map +1 -1
  96. package/dist/output/index.js +4 -3
  97. package/dist/output/index.js.map +1 -1
  98. package/dist/output/json.d.ts +2 -2
  99. package/dist/output/json.d.ts.map +1 -1
  100. package/dist/output/json.js +54 -0
  101. package/dist/output/json.js.map +1 -1
  102. package/dist/output/markdown.d.ts +2 -2
  103. package/dist/output/markdown.d.ts.map +1 -1
  104. package/dist/output/markdown.js +34 -1
  105. package/dist/output/markdown.js.map +1 -1
  106. package/dist/output/terminal.d.ts +6 -2
  107. package/dist/output/terminal.d.ts.map +1 -1
  108. package/dist/output/terminal.js +131 -3
  109. package/dist/output/terminal.js.map +1 -1
  110. package/dist/recommend/index.d.ts +3 -0
  111. package/dist/recommend/index.d.ts.map +1 -0
  112. package/dist/recommend/index.js +14 -0
  113. package/dist/recommend/index.js.map +1 -0
  114. package/dist/recommend/ordered-logistic.d.ts +49 -0
  115. package/dist/recommend/ordered-logistic.d.ts.map +1 -0
  116. package/dist/recommend/ordered-logistic.js +153 -0
  117. package/dist/recommend/ordered-logistic.js.map +1 -0
  118. package/dist/recommend/questions.d.ts +19 -0
  119. package/dist/recommend/questions.d.ts.map +1 -0
  120. package/dist/recommend/questions.js +73 -0
  121. package/dist/recommend/questions.js.map +1 -0
  122. package/dist/score/index.d.ts +21 -0
  123. package/dist/score/index.d.ts.map +1 -0
  124. package/dist/score/index.js +48 -0
  125. package/dist/score/index.js.map +1 -0
  126. package/dist/score/weights.d.ts +16 -0
  127. package/dist/score/weights.d.ts.map +1 -0
  128. package/dist/score/weights.js +28 -0
  129. package/dist/score/weights.js.map +1 -0
  130. package/dist/types.d.ts +83 -0
  131. package/dist/types.d.ts.map +1 -1
  132. package/hooks/pre-push +103 -0
  133. package/package.json +10 -9
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ACHIEVEMENTS = void 0;
4
+ exports.checkAchievements = checkAchievements;
5
+ exports.getAchievement = getAchievement;
6
+ exports.getAllAchievements = getAllAchievements;
7
+ // All available achievements
8
+ exports.ACHIEVEMENTS = [
9
+ // Streak achievements
10
+ {
11
+ id: 'first_check',
12
+ name: 'First Blood',
13
+ description: 'Run your first vibe-check',
14
+ icon: '🩸',
15
+ category: 'sessions',
16
+ condition: 'Complete 1 session',
17
+ },
18
+ {
19
+ id: 'week_warrior',
20
+ name: 'Week Warrior',
21
+ description: 'Maintain a 7-day streak',
22
+ icon: '⚔️',
23
+ category: 'streak',
24
+ condition: '7-day streak',
25
+ },
26
+ {
27
+ id: 'fortnight_force',
28
+ name: 'Fortnight Force',
29
+ description: 'Maintain a 14-day streak',
30
+ icon: '🛡️',
31
+ category: 'streak',
32
+ condition: '14-day streak',
33
+ },
34
+ {
35
+ id: 'monthly_master',
36
+ name: 'Monthly Master',
37
+ description: 'Maintain a 30-day streak',
38
+ icon: '👑',
39
+ category: 'streak',
40
+ condition: '30-day streak',
41
+ },
42
+ // Score achievements
43
+ {
44
+ id: 'elite_vibes',
45
+ name: 'Elite Vibes',
46
+ description: 'Achieve ELITE rating in a session',
47
+ icon: '✨',
48
+ category: 'score',
49
+ condition: 'Get ELITE rating',
50
+ },
51
+ {
52
+ id: 'consistent_high',
53
+ name: 'High Roller',
54
+ description: 'Get HIGH or better for 5 consecutive sessions',
55
+ icon: '🎰',
56
+ category: 'score',
57
+ condition: '5 consecutive HIGH+ sessions',
58
+ },
59
+ {
60
+ id: 'perfect_week',
61
+ name: 'Perfect Week',
62
+ description: 'ELITE rating every day for a week',
63
+ icon: '💎',
64
+ category: 'score',
65
+ condition: '7 consecutive ELITE sessions',
66
+ },
67
+ {
68
+ id: 'score_90',
69
+ name: 'Ninety Club',
70
+ description: 'Achieve a Vibe Score of 90% or higher',
71
+ icon: '🏅',
72
+ category: 'score',
73
+ condition: 'Vibe Score ≥ 90%',
74
+ },
75
+ // Session milestones
76
+ {
77
+ id: 'ten_sessions',
78
+ name: 'Getting Started',
79
+ description: 'Complete 10 vibe-check sessions',
80
+ icon: '📊',
81
+ category: 'sessions',
82
+ condition: '10 sessions',
83
+ },
84
+ {
85
+ id: 'fifty_sessions',
86
+ name: 'Regular',
87
+ description: 'Complete 50 vibe-check sessions',
88
+ icon: '📈',
89
+ category: 'sessions',
90
+ condition: '50 sessions',
91
+ },
92
+ {
93
+ id: 'hundred_sessions',
94
+ name: 'Centurion',
95
+ description: 'Complete 100 vibe-check sessions',
96
+ icon: '💯',
97
+ category: 'sessions',
98
+ condition: '100 sessions',
99
+ },
100
+ // Special achievements
101
+ {
102
+ id: 'zen_master',
103
+ name: 'Zen Master',
104
+ description: '0 debug spirals in a 50+ commit session',
105
+ icon: '🧘',
106
+ category: 'special',
107
+ condition: '50+ commits, 0 spirals',
108
+ },
109
+ {
110
+ id: 'trust_builder',
111
+ name: 'Trust Builder',
112
+ description: 'Maintain 90%+ Trust Pass Rate for 10 sessions',
113
+ icon: '🏗️',
114
+ category: 'special',
115
+ condition: '10 sessions with 90%+ trust',
116
+ },
117
+ {
118
+ id: 'comeback_kid',
119
+ name: 'Comeback Kid',
120
+ description: 'Go from LOW to ELITE in the same week',
121
+ icon: '🔄',
122
+ category: 'special',
123
+ condition: 'LOW → ELITE in 7 days',
124
+ },
125
+ {
126
+ id: 'early_bird',
127
+ name: 'Early Bird',
128
+ description: 'Run vibe-check before 7 AM',
129
+ icon: '🌅',
130
+ category: 'special',
131
+ condition: 'Session before 7 AM',
132
+ },
133
+ {
134
+ id: 'night_owl',
135
+ name: 'Night Owl',
136
+ description: 'Run vibe-check after midnight',
137
+ icon: '🦉',
138
+ category: 'special',
139
+ condition: 'Session after midnight',
140
+ },
141
+ {
142
+ id: 'thousand_commits',
143
+ name: 'Thousand Strong',
144
+ description: 'Analyze 1000 total commits',
145
+ icon: '🎯',
146
+ category: 'special',
147
+ condition: '1000 commits analyzed',
148
+ },
149
+ // Hidden achievements
150
+ {
151
+ id: 'perfect_score',
152
+ name: '???',
153
+ description: 'Achieve a perfect 100% Vibe Score',
154
+ icon: '🌟',
155
+ category: 'special',
156
+ condition: '???',
157
+ hidden: true,
158
+ },
159
+ {
160
+ id: 'spiral_survivor',
161
+ name: '???',
162
+ description: 'Recover from 5+ spirals to ELITE in same session',
163
+ icon: '🌀',
164
+ category: 'special',
165
+ condition: '???',
166
+ hidden: true,
167
+ },
168
+ ];
169
+ /**
170
+ * Check which achievements are newly unlocked based on current state
171
+ */
172
+ function checkAchievements(sessions, streak, xp, currentSession, unlockedIds) {
173
+ const newlyUnlocked = [];
174
+ const now = new Date().toISOString();
175
+ for (const achievement of exports.ACHIEVEMENTS) {
176
+ // Skip already unlocked
177
+ if (unlockedIds.includes(achievement.id))
178
+ continue;
179
+ const unlocked = checkAchievementCondition(achievement.id, sessions, streak, xp, currentSession);
180
+ if (unlocked) {
181
+ newlyUnlocked.push({
182
+ ...achievement,
183
+ unlockedAt: now,
184
+ });
185
+ }
186
+ }
187
+ return newlyUnlocked;
188
+ }
189
+ function checkAchievementCondition(id, sessions, streak, _xp, current) {
190
+ const totalSessions = sessions.length + 1; // Include current
191
+ switch (id) {
192
+ // Session count
193
+ case 'first_check':
194
+ return totalSessions >= 1;
195
+ case 'ten_sessions':
196
+ return totalSessions >= 10;
197
+ case 'fifty_sessions':
198
+ return totalSessions >= 50;
199
+ case 'hundred_sessions':
200
+ return totalSessions >= 100;
201
+ // Streak
202
+ case 'week_warrior':
203
+ return streak.current >= 7;
204
+ case 'fortnight_force':
205
+ return streak.current >= 14;
206
+ case 'monthly_master':
207
+ return streak.current >= 30;
208
+ // Score
209
+ case 'elite_vibes':
210
+ return current.overall === 'ELITE';
211
+ case 'score_90':
212
+ return current.vibeScore >= 90;
213
+ case 'perfect_score':
214
+ return current.vibeScore === 100;
215
+ // Consecutive sessions
216
+ case 'consistent_high': {
217
+ const last5 = [...sessions.slice(-4), current];
218
+ return last5.length >= 5 &&
219
+ last5.every(s => s.overall === 'ELITE' || s.overall === 'HIGH');
220
+ }
221
+ case 'perfect_week': {
222
+ const last7 = [...sessions.slice(-6), current];
223
+ return last7.length >= 7 && last7.every(s => s.overall === 'ELITE');
224
+ }
225
+ // Special
226
+ case 'zen_master':
227
+ return current.commits >= 50 && current.spirals === 0;
228
+ case 'trust_builder': {
229
+ // Would need trust pass rate in session record
230
+ return false; // TODO: Implement when trust is tracked
231
+ }
232
+ case 'comeback_kid': {
233
+ const weekAgo = new Date();
234
+ weekAgo.setDate(weekAgo.getDate() - 7);
235
+ const weekSessions = sessions.filter(s => new Date(s.date) >= weekAgo);
236
+ const hadLow = weekSessions.some(s => s.overall === 'LOW');
237
+ return hadLow && current.overall === 'ELITE';
238
+ }
239
+ case 'early_bird': {
240
+ const hour = new Date(current.timestamp).getHours();
241
+ return hour < 7;
242
+ }
243
+ case 'night_owl': {
244
+ const hour = new Date(current.timestamp).getHours();
245
+ return hour >= 0 && hour < 5;
246
+ }
247
+ case 'thousand_commits': {
248
+ const totalCommits = sessions.reduce((sum, s) => sum + s.commits, 0) + current.commits;
249
+ return totalCommits >= 1000;
250
+ }
251
+ case 'spiral_survivor':
252
+ return current.spirals >= 5 && current.overall === 'ELITE';
253
+ default:
254
+ return false;
255
+ }
256
+ }
257
+ /**
258
+ * Get achievement by ID
259
+ */
260
+ function getAchievement(id) {
261
+ return exports.ACHIEVEMENTS.find(a => a.id === id);
262
+ }
263
+ /**
264
+ * Get all achievements with unlock status
265
+ */
266
+ function getAllAchievements(unlockedAchievements) {
267
+ const unlockedIds = new Set(unlockedAchievements.map(a => a.id));
268
+ return exports.ACHIEVEMENTS.map(a => {
269
+ const unlocked = unlockedAchievements.find(u => u.id === a.id);
270
+ return unlocked || { ...a, unlockedAt: undefined };
271
+ });
272
+ }
273
+ //# sourceMappingURL=achievements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"achievements.js","sourceRoot":"","sources":["../../src/gamification/achievements.ts"],"names":[],"mappings":";;;AA4KA,8CA+BC;AA4FD,wCAEC;AAKD,gDAOC;AAnTD,6BAA6B;AAChB,QAAA,YAAY,GAAmD;IAC1E,sBAAsB;IACtB;QACE,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,2BAA2B;QACxC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,oBAAoB;KAChC;IACD;QACE,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,yBAAyB;QACtC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,cAAc;KAC1B;IACD;QACE,EAAE,EAAE,iBAAiB;QACrB,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,0BAA0B;QACvC,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,eAAe;KAC3B;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,0BAA0B;QACvC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,eAAe;KAC3B;IAED,qBAAqB;IACrB;QACE,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,mCAAmC;QAChD,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,kBAAkB;KAC9B;IACD;QACE,EAAE,EAAE,iBAAiB;QACrB,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,+CAA+C;QAC5D,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,8BAA8B;KAC1C;IACD;QACE,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,mCAAmC;QAChD,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,8BAA8B;KAC1C;IACD;QACE,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,uCAAuC;QACpD,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,kBAAkB;KAC9B;IAED,qBAAqB;IACrB;QACE,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,iCAAiC;QAC9C,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,aAAa;KACzB;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,iCAAiC;QAC9C,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,aAAa;KACzB;IACD;QACE,EAAE,EAAE,kBAAkB;QACtB,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,kCAAkC;QAC/C,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,cAAc;KAC1B;IAED,uBAAuB;IACvB;QACE,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,yCAAyC;QACtD,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,wBAAwB;KACpC;IACD;QACE,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,+CAA+C;QAC5D,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,6BAA6B;KACzC;IACD;QACE,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,uCAAuC;QACpD,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,uBAAuB;KACnC;IACD;QACE,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,4BAA4B;QACzC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,qBAAqB;KACjC;IACD;QACE,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,+BAA+B;QAC5C,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,wBAAwB;KACpC;IACD;QACE,EAAE,EAAE,kBAAkB;QACtB,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,4BAA4B;QACzC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,uBAAuB;KACnC;IAED,sBAAsB;IACtB;QACE,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,mCAAmC;QAChD,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,KAAK;QAChB,MAAM,EAAE,IAAI;KACb;IACD;QACE,EAAE,EAAE,iBAAiB;QACrB,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,kDAAkD;QAC/D,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,KAAK;QAChB,MAAM,EAAE,IAAI;KACb;CACF,CAAC;AAEF;;GAEG;AACH,SAAgB,iBAAiB,CAC/B,QAAyB,EACzB,MAAmB,EACnB,EAAW,EACX,cAA6B,EAC7B,WAAqB;IAErB,MAAM,aAAa,GAAkB,EAAE,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,KAAK,MAAM,WAAW,IAAI,oBAAY,EAAE,CAAC;QACvC,wBAAwB;QACxB,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAAE,SAAS;QAEnD,MAAM,QAAQ,GAAG,yBAAyB,CACxC,WAAW,CAAC,EAAE,EACd,QAAQ,EACR,MAAM,EACN,EAAE,EACF,cAAc,CACf,CAAC;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,aAAa,CAAC,IAAI,CAAC;gBACjB,GAAG,WAAW;gBACd,UAAU,EAAE,GAAG;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,yBAAyB,CAChC,EAAU,EACV,QAAyB,EACzB,MAAmB,EACnB,GAAY,EACZ,OAAsB;IAEtB,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAE,kBAAkB;IAE9D,QAAQ,EAAE,EAAE,CAAC;QACX,gBAAgB;QAChB,KAAK,aAAa;YAChB,OAAO,aAAa,IAAI,CAAC,CAAC;QAC5B,KAAK,cAAc;YACjB,OAAO,aAAa,IAAI,EAAE,CAAC;QAC7B,KAAK,gBAAgB;YACnB,OAAO,aAAa,IAAI,EAAE,CAAC;QAC7B,KAAK,kBAAkB;YACrB,OAAO,aAAa,IAAI,GAAG,CAAC;QAE9B,SAAS;QACT,KAAK,cAAc;YACjB,OAAO,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;QAC7B,KAAK,iBAAiB;YACpB,OAAO,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAC9B,KAAK,gBAAgB;YACnB,OAAO,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAE9B,QAAQ;QACR,KAAK,aAAa;YAChB,OAAO,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;QACrC,KAAK,UAAU;YACb,OAAO,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;QACjC,KAAK,eAAe;YAClB,OAAO,OAAO,CAAC,SAAS,KAAK,GAAG,CAAC;QAEnC,uBAAuB;QACvB,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC;gBACjB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QACtE,CAAC;QAED,UAAU;QACV,KAAK,YAAY;YACf,OAAO,OAAO,CAAC,OAAO,IAAI,EAAE,IAAI,OAAO,CAAC,OAAO,KAAK,CAAC,CAAC;QAExD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,+CAA+C;YAC/C,OAAO,KAAK,CAAC,CAAC,wCAAwC;QACxD,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;YAC3B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YACvC,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC;YAC3D,OAAO,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;QAC/C,CAAC;QAED,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;YACpD,OAAO,IAAI,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;YACpD,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;YACvF,OAAO,YAAY,IAAI,IAAI,CAAC;QAC9B,CAAC;QAED,KAAK,iBAAiB;YACpB,OAAO,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;QAE7D;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,EAAU;IACvC,OAAO,oBAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAA4B,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,oBAAmC;IACpE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEjE,OAAO,oBAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC1B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/D,OAAO,QAAQ,IAAI,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export * from './types';
2
+ export * from './streaks';
3
+ export * from './xp';
4
+ export * from './achievements';
5
+ export * from './profile';
6
+ export { LEVELS, XP_REWARDS } from './types';
7
+ export { ACHIEVEMENTS } from './achievements';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gamification/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,MAAM,CAAC;AACrB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAG1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ // Gamification Module - Main Export
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.ACHIEVEMENTS = exports.XP_REWARDS = exports.LEVELS = void 0;
19
+ __exportStar(require("./types"), exports);
20
+ __exportStar(require("./streaks"), exports);
21
+ __exportStar(require("./xp"), exports);
22
+ __exportStar(require("./achievements"), exports);
23
+ __exportStar(require("./profile"), exports);
24
+ // Re-export commonly used items for convenience
25
+ var types_1 = require("./types");
26
+ Object.defineProperty(exports, "LEVELS", { enumerable: true, get: function () { return types_1.LEVELS; } });
27
+ Object.defineProperty(exports, "XP_REWARDS", { enumerable: true, get: function () { return types_1.XP_REWARDS; } });
28
+ var achievements_1 = require("./achievements");
29
+ Object.defineProperty(exports, "ACHIEVEMENTS", { enumerable: true, get: function () { return achievements_1.ACHIEVEMENTS; } });
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gamification/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;;AAEpC,0CAAwB;AACxB,4CAA0B;AAC1B,uCAAqB;AACrB,iDAA+B;AAC/B,4CAA0B;AAE1B,gDAAgD;AAChD,iCAA6C;AAApC,+FAAA,MAAM,OAAA;AAAE,mGAAA,UAAU,OAAA;AAC3B,+CAA8C;AAArC,4GAAA,YAAY,OAAA"}
@@ -0,0 +1,46 @@
1
+ import { UserProfile, SessionRecord, Achievement } from './types';
2
+ /**
3
+ * Get profile directory path (in user's home directory)
4
+ */
5
+ export declare function getProfileDir(): string;
6
+ /**
7
+ * Get profile file path
8
+ */
9
+ export declare function getProfilePath(): string;
10
+ /**
11
+ * Create initial profile
12
+ */
13
+ export declare function createInitialProfile(): UserProfile;
14
+ /**
15
+ * Load profile from disk
16
+ */
17
+ export declare function loadProfile(): UserProfile;
18
+ /**
19
+ * Save profile to disk
20
+ */
21
+ export declare function saveProfile(profile: UserProfile): void;
22
+ /**
23
+ * Record a new session and update all gamification state
24
+ */
25
+ export declare function recordSession(vibeScore: number, overall: 'ELITE' | 'HIGH' | 'MEDIUM' | 'LOW', commits: number, spirals: number, periodFrom?: Date, periodTo?: Date): {
26
+ profile: UserProfile;
27
+ xpEarned: number;
28
+ leveledUp: boolean;
29
+ newLevel?: string;
30
+ achievementsUnlocked: Achievement[];
31
+ streakExtended: boolean;
32
+ isPersonalBest: boolean;
33
+ isDuplicate: boolean;
34
+ };
35
+ /**
36
+ * Get achievement counts
37
+ */
38
+ export declare function getAchievementCounts(profile: UserProfile): {
39
+ unlocked: number;
40
+ total: number;
41
+ };
42
+ /**
43
+ * Get recent sessions (last N days)
44
+ */
45
+ export declare function getRecentSessions(profile: UserProfile, days: number): SessionRecord[];
46
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/gamification/profile.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,EACX,aAAa,EAGb,WAAW,EACZ,MAAM,SAAS,CAAC;AAQjB;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,WAAW,CA4BlD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,WAAW,CAczC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAUtD;AAyCD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,EAC5C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,IAAI,EACjB,QAAQ,CAAC,EAAE,IAAI,GACd;IACD,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,WAAW,EAAE,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;CACtB,CA+FA;AAkCD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAK9F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAKrF"}
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getProfileDir = getProfileDir;
37
+ exports.getProfilePath = getProfilePath;
38
+ exports.createInitialProfile = createInitialProfile;
39
+ exports.loadProfile = loadProfile;
40
+ exports.saveProfile = saveProfile;
41
+ exports.recordSession = recordSession;
42
+ exports.getAchievementCounts = getAchievementCounts;
43
+ exports.getRecentSessions = getRecentSessions;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const os = __importStar(require("os"));
47
+ const streaks_1 = require("./streaks");
48
+ const xp_1 = require("./xp");
49
+ const achievements_1 = require("./achievements");
50
+ const PROFILE_DIR = '.vibe-check';
51
+ const PROFILE_FILE = 'profile.json';
52
+ /**
53
+ * Get profile directory path (in user's home directory)
54
+ */
55
+ function getProfileDir() {
56
+ return path.join(os.homedir(), PROFILE_DIR);
57
+ }
58
+ /**
59
+ * Get profile file path
60
+ */
61
+ function getProfilePath() {
62
+ return path.join(getProfileDir(), PROFILE_FILE);
63
+ }
64
+ /**
65
+ * Create initial profile
66
+ */
67
+ function createInitialProfile() {
68
+ const now = new Date().toISOString();
69
+ return {
70
+ version: '1.0.0',
71
+ createdAt: now,
72
+ updatedAt: now,
73
+ streak: (0, streaks_1.createInitialStreak)(),
74
+ xp: (0, xp_1.createInitialXP)(),
75
+ achievements: [],
76
+ sessions: [],
77
+ preferences: {
78
+ weeklyGoal: 5,
79
+ showNotifications: true,
80
+ publicProfile: false,
81
+ },
82
+ stats: {
83
+ totalSessions: 0,
84
+ totalCommitsAnalyzed: 0,
85
+ avgVibeScore: 0,
86
+ bestVibeScore: 0,
87
+ totalSpiralsDetected: 0,
88
+ spiralsAvoided: 0,
89
+ },
90
+ };
91
+ }
92
+ /**
93
+ * Load profile from disk
94
+ */
95
+ function loadProfile() {
96
+ const filePath = getProfilePath();
97
+ if (fs.existsSync(filePath)) {
98
+ try {
99
+ const data = fs.readFileSync(filePath, 'utf-8');
100
+ const profile = JSON.parse(data);
101
+ return migrateProfile(profile);
102
+ }
103
+ catch {
104
+ return createInitialProfile();
105
+ }
106
+ }
107
+ return createInitialProfile();
108
+ }
109
+ /**
110
+ * Save profile to disk
111
+ */
112
+ function saveProfile(profile) {
113
+ const dirPath = getProfileDir();
114
+ const filePath = getProfilePath();
115
+ if (!fs.existsSync(dirPath)) {
116
+ fs.mkdirSync(dirPath, { recursive: true });
117
+ }
118
+ profile.updatedAt = new Date().toISOString();
119
+ fs.writeFileSync(filePath, JSON.stringify(profile, null, 2));
120
+ }
121
+ /**
122
+ * Check if a period was already analyzed (to prevent XP gaming)
123
+ */
124
+ function isPeriodDuplicate(sessions, periodFrom, periodTo) {
125
+ const fromTime = periodFrom.getTime();
126
+ const toTime = periodTo.getTime();
127
+ // Check recent sessions (last 50) for matching periods
128
+ const recentSessions = sessions.slice(-50);
129
+ for (const session of recentSessions) {
130
+ if (session.periodFrom && session.periodTo) {
131
+ const sessionFrom = new Date(session.periodFrom).getTime();
132
+ const sessionTo = new Date(session.periodTo).getTime();
133
+ // Check for exact match or significant overlap (>80%)
134
+ if (sessionFrom === fromTime && sessionTo === toTime) {
135
+ return true;
136
+ }
137
+ // Check for significant overlap
138
+ const overlapStart = Math.max(fromTime, sessionFrom);
139
+ const overlapEnd = Math.min(toTime, sessionTo);
140
+ const overlap = Math.max(0, overlapEnd - overlapStart);
141
+ const currentDuration = toTime - fromTime;
142
+ if (currentDuration > 0 && overlap / currentDuration > 0.8) {
143
+ return true;
144
+ }
145
+ }
146
+ }
147
+ return false;
148
+ }
149
+ /**
150
+ * Record a new session and update all gamification state
151
+ */
152
+ function recordSession(vibeScore, overall, commits, spirals, periodFrom, periodTo) {
153
+ const profile = loadProfile();
154
+ const now = new Date();
155
+ // Check for duplicate period (anti-gaming)
156
+ const isDuplicate = periodFrom && periodTo
157
+ ? isPeriodDuplicate(profile.sessions, periodFrom, periodTo)
158
+ : false;
159
+ if (isDuplicate) {
160
+ // Return current profile without awarding XP
161
+ return {
162
+ profile,
163
+ xpEarned: 0,
164
+ leveledUp: false,
165
+ achievementsUnlocked: [],
166
+ streakExtended: false,
167
+ isPersonalBest: false,
168
+ isDuplicate: true,
169
+ };
170
+ }
171
+ // Update streak
172
+ const oldStreak = profile.streak.current;
173
+ profile.streak = (0, streaks_1.updateStreak)(profile.streak, now);
174
+ const streakExtended = profile.streak.current > oldStreak;
175
+ // Check achievements (before recording session)
176
+ const sessionRecord = {
177
+ date: now.toISOString().split('T')[0],
178
+ timestamp: now.toISOString(),
179
+ vibeScore,
180
+ overall,
181
+ commits,
182
+ spirals,
183
+ xpEarned: 0, // Will be updated
184
+ achievementsUnlocked: [],
185
+ periodFrom: periodFrom?.toISOString(),
186
+ periodTo: periodTo?.toISOString(),
187
+ };
188
+ const newAchievements = (0, achievements_1.checkAchievements)(profile.sessions, profile.streak, profile.xp, sessionRecord, profile.achievements.map(a => a.id));
189
+ // Calculate and add XP
190
+ const xpEarned = (0, xp_1.calculateSessionXP)(sessionRecord, profile.streak, newAchievements.length);
191
+ sessionRecord.xpEarned = xpEarned;
192
+ sessionRecord.achievementsUnlocked = newAchievements.map(a => a.id);
193
+ const { xp: newXP, leveledUp, newLevel } = (0, xp_1.addXP)(profile.xp, xpEarned);
194
+ profile.xp = newXP;
195
+ // Add achievements to profile
196
+ profile.achievements.push(...newAchievements);
197
+ // Add session to history (keep last 100)
198
+ profile.sessions.push(sessionRecord);
199
+ if (profile.sessions.length > 100) {
200
+ profile.sessions = profile.sessions.slice(-100);
201
+ }
202
+ // Update stats
203
+ const isPersonalBest = vibeScore > profile.stats.bestVibeScore;
204
+ profile.stats.totalSessions += 1;
205
+ profile.stats.totalCommitsAnalyzed += commits;
206
+ profile.stats.bestVibeScore = Math.max(profile.stats.bestVibeScore, vibeScore);
207
+ profile.stats.totalSpiralsDetected += spirals;
208
+ if (spirals === 0 && commits >= 10) {
209
+ profile.stats.spiralsAvoided += 1;
210
+ }
211
+ // Recalculate average
212
+ const allScores = profile.sessions.map(s => s.vibeScore);
213
+ profile.stats.avgVibeScore = Math.round(allScores.reduce((a, b) => a + b, 0) / allScores.length);
214
+ // Save profile
215
+ saveProfile(profile);
216
+ return {
217
+ profile,
218
+ xpEarned,
219
+ leveledUp,
220
+ newLevel: newLevel?.name,
221
+ achievementsUnlocked: newAchievements,
222
+ streakExtended,
223
+ isPersonalBest,
224
+ isDuplicate: false,
225
+ };
226
+ }
227
+ /**
228
+ * Migrate old profile versions
229
+ */
230
+ function migrateProfile(profile) {
231
+ // Add migrations here as schema evolves
232
+ if (!profile.version) {
233
+ profile.version = '1.0.0';
234
+ }
235
+ // Ensure all fields exist
236
+ if (!profile.preferences) {
237
+ profile.preferences = {
238
+ weeklyGoal: 5,
239
+ showNotifications: true,
240
+ publicProfile: false,
241
+ };
242
+ }
243
+ if (!profile.stats) {
244
+ profile.stats = {
245
+ totalSessions: profile.sessions?.length || 0,
246
+ totalCommitsAnalyzed: 0,
247
+ avgVibeScore: 0,
248
+ bestVibeScore: 0,
249
+ totalSpiralsDetected: 0,
250
+ spiralsAvoided: 0,
251
+ };
252
+ }
253
+ return profile;
254
+ }
255
+ /**
256
+ * Get achievement counts
257
+ */
258
+ function getAchievementCounts(profile) {
259
+ return {
260
+ unlocked: profile.achievements.length,
261
+ total: achievements_1.ACHIEVEMENTS.length,
262
+ };
263
+ }
264
+ /**
265
+ * Get recent sessions (last N days)
266
+ */
267
+ function getRecentSessions(profile, days) {
268
+ const cutoff = new Date();
269
+ cutoff.setDate(cutoff.getDate() - days);
270
+ return profile.sessions.filter(s => new Date(s.date) >= cutoff);
271
+ }
272
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/gamification/profile.ts"],"names":[],"mappings":"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"}