@boshu2/vibe-check 1.0.1 → 1.1.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 (128) 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 +46 -0
  10. package/CLAUDE.md +178 -0
  11. package/README.md +265 -63
  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 +30 -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 +4 -0
  35. package/dist/commands/index.d.ts.map +1 -0
  36. package/dist/commands/index.js +11 -0
  37. package/dist/commands/index.js.map +1 -0
  38. package/dist/commands/level.d.ts +3 -0
  39. package/dist/commands/level.d.ts.map +1 -0
  40. package/dist/commands/level.js +277 -0
  41. package/dist/commands/level.js.map +1 -0
  42. package/dist/commands/profile.d.ts +4 -0
  43. package/dist/commands/profile.d.ts.map +1 -0
  44. package/dist/commands/profile.js +143 -0
  45. package/dist/commands/profile.js.map +1 -0
  46. package/dist/gamification/achievements.d.ts +15 -0
  47. package/dist/gamification/achievements.d.ts.map +1 -0
  48. package/dist/gamification/achievements.js +273 -0
  49. package/dist/gamification/achievements.js.map +1 -0
  50. package/dist/gamification/index.d.ts +8 -0
  51. package/dist/gamification/index.d.ts.map +1 -0
  52. package/dist/gamification/index.js +30 -0
  53. package/dist/gamification/index.js.map +1 -0
  54. package/dist/gamification/profile.d.ts +46 -0
  55. package/dist/gamification/profile.d.ts.map +1 -0
  56. package/dist/gamification/profile.js +272 -0
  57. package/dist/gamification/profile.js.map +1 -0
  58. package/dist/gamification/streaks.d.ts +26 -0
  59. package/dist/gamification/streaks.d.ts.map +1 -0
  60. package/dist/gamification/streaks.js +132 -0
  61. package/dist/gamification/streaks.js.map +1 -0
  62. package/dist/gamification/types.d.ts +111 -0
  63. package/dist/gamification/types.d.ts.map +1 -0
  64. package/dist/gamification/types.js +26 -0
  65. package/dist/gamification/types.js.map +1 -0
  66. package/dist/gamification/xp.d.ts +37 -0
  67. package/dist/gamification/xp.d.ts.map +1 -0
  68. package/dist/gamification/xp.js +115 -0
  69. package/dist/gamification/xp.js.map +1 -0
  70. package/dist/git.d.ts +11 -0
  71. package/dist/git.d.ts.map +1 -1
  72. package/dist/git.js +52 -0
  73. package/dist/git.js.map +1 -1
  74. package/dist/metrics/code-stability.d.ts +13 -0
  75. package/dist/metrics/code-stability.d.ts.map +1 -0
  76. package/dist/metrics/code-stability.js +74 -0
  77. package/dist/metrics/code-stability.js.map +1 -0
  78. package/dist/metrics/file-churn.d.ts +8 -0
  79. package/dist/metrics/file-churn.d.ts.map +1 -0
  80. package/dist/metrics/file-churn.js +75 -0
  81. package/dist/metrics/file-churn.js.map +1 -0
  82. package/dist/metrics/time-spiral.d.ts +8 -0
  83. package/dist/metrics/time-spiral.d.ts.map +1 -0
  84. package/dist/metrics/time-spiral.js +69 -0
  85. package/dist/metrics/time-spiral.js.map +1 -0
  86. package/dist/metrics/velocity-anomaly.d.ts +13 -0
  87. package/dist/metrics/velocity-anomaly.d.ts.map +1 -0
  88. package/dist/metrics/velocity-anomaly.js +67 -0
  89. package/dist/metrics/velocity-anomaly.js.map +1 -0
  90. package/dist/output/index.d.ts +6 -3
  91. package/dist/output/index.d.ts.map +1 -1
  92. package/dist/output/index.js +4 -3
  93. package/dist/output/index.js.map +1 -1
  94. package/dist/output/json.d.ts +2 -2
  95. package/dist/output/json.d.ts.map +1 -1
  96. package/dist/output/json.js +54 -0
  97. package/dist/output/json.js.map +1 -1
  98. package/dist/output/markdown.d.ts +2 -2
  99. package/dist/output/markdown.d.ts.map +1 -1
  100. package/dist/output/markdown.js +34 -1
  101. package/dist/output/markdown.js.map +1 -1
  102. package/dist/output/terminal.d.ts +6 -2
  103. package/dist/output/terminal.d.ts.map +1 -1
  104. package/dist/output/terminal.js +131 -3
  105. package/dist/output/terminal.js.map +1 -1
  106. package/dist/recommend/index.d.ts +3 -0
  107. package/dist/recommend/index.d.ts.map +1 -0
  108. package/dist/recommend/index.js +14 -0
  109. package/dist/recommend/index.js.map +1 -0
  110. package/dist/recommend/ordered-logistic.d.ts +49 -0
  111. package/dist/recommend/ordered-logistic.d.ts.map +1 -0
  112. package/dist/recommend/ordered-logistic.js +153 -0
  113. package/dist/recommend/ordered-logistic.js.map +1 -0
  114. package/dist/recommend/questions.d.ts +19 -0
  115. package/dist/recommend/questions.d.ts.map +1 -0
  116. package/dist/recommend/questions.js +73 -0
  117. package/dist/recommend/questions.js.map +1 -0
  118. package/dist/score/index.d.ts +21 -0
  119. package/dist/score/index.d.ts.map +1 -0
  120. package/dist/score/index.js +48 -0
  121. package/dist/score/index.js.map +1 -0
  122. package/dist/score/weights.d.ts +16 -0
  123. package/dist/score/weights.d.ts.map +1 -0
  124. package/dist/score/weights.js +28 -0
  125. package/dist/score/weights.js.map +1 -0
  126. package/dist/types.d.ts +83 -0
  127. package/dist/types.d.ts.map +1 -1
  128. package/package.json +10 -9
@@ -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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"}
@@ -0,0 +1,26 @@
1
+ import { StreakState } from './types';
2
+ /**
3
+ * Create initial streak state
4
+ */
5
+ export declare function createInitialStreak(): StreakState;
6
+ /**
7
+ * Update streak based on new session
8
+ */
9
+ export declare function updateStreak(streak: StreakState, sessionDate: Date): StreakState;
10
+ /**
11
+ * Check if streak is at risk (not checked in today)
12
+ */
13
+ export declare function isStreakAtRisk(streak: StreakState): boolean;
14
+ /**
15
+ * Get days until streak expires
16
+ */
17
+ export declare function getDaysUntilExpiry(streak: StreakState): number;
18
+ /**
19
+ * Format streak for display
20
+ */
21
+ export declare function formatStreak(streak: StreakState): string;
22
+ /**
23
+ * Format weekly progress for display
24
+ */
25
+ export declare function formatWeeklyProgress(streak: StreakState): string;
26
+ //# sourceMappingURL=streaks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaks.d.ts","sourceRoot":"","sources":["../../src/gamification/streaks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,WAAW,CASjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,GAAG,WAAW,CAiDhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAK3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAc9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAexD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAKhE"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createInitialStreak = createInitialStreak;
4
+ exports.updateStreak = updateStreak;
5
+ exports.isStreakAtRisk = isStreakAtRisk;
6
+ exports.getDaysUntilExpiry = getDaysUntilExpiry;
7
+ exports.formatStreak = formatStreak;
8
+ exports.formatWeeklyProgress = formatWeeklyProgress;
9
+ /**
10
+ * Create initial streak state
11
+ */
12
+ function createInitialStreak() {
13
+ return {
14
+ current: 0,
15
+ longest: 0,
16
+ lastActiveDate: '',
17
+ weeklyGoal: 5,
18
+ weeklyProgress: 0,
19
+ freezesRemaining: 1,
20
+ };
21
+ }
22
+ /**
23
+ * Update streak based on new session
24
+ */
25
+ function updateStreak(streak, sessionDate) {
26
+ const today = formatDate(sessionDate);
27
+ const yesterday = formatDate(new Date(sessionDate.getTime() - 24 * 60 * 60 * 1000));
28
+ const twoDaysAgo = formatDate(new Date(sessionDate.getTime() - 2 * 24 * 60 * 60 * 1000));
29
+ // Already checked in today
30
+ if (streak.lastActiveDate === today) {
31
+ return streak;
32
+ }
33
+ let newCurrent = streak.current;
34
+ let freezesRemaining = streak.freezesRemaining;
35
+ let lastFreezeUsed = streak.lastFreezeUsed;
36
+ if (streak.lastActiveDate === yesterday) {
37
+ // Consecutive day - extend streak
38
+ newCurrent = streak.current + 1;
39
+ }
40
+ else if (streak.lastActiveDate === twoDaysAgo && freezesRemaining > 0) {
41
+ // Missed one day but have freeze
42
+ newCurrent = streak.current + 1;
43
+ freezesRemaining -= 1;
44
+ lastFreezeUsed = yesterday;
45
+ }
46
+ else if (streak.lastActiveDate === '') {
47
+ // First ever session
48
+ newCurrent = 1;
49
+ }
50
+ else {
51
+ // Streak broken
52
+ newCurrent = 1;
53
+ }
54
+ // Update weekly progress
55
+ const weekStart = getWeekStart(sessionDate);
56
+ const lastActiveWeekStart = streak.lastActiveDate
57
+ ? getWeekStart(new Date(streak.lastActiveDate))
58
+ : '';
59
+ const weeklyProgress = weekStart === lastActiveWeekStart
60
+ ? streak.weeklyProgress + (streak.lastActiveDate === today ? 0 : 1)
61
+ : 1;
62
+ return {
63
+ current: newCurrent,
64
+ longest: Math.max(streak.longest, newCurrent),
65
+ lastActiveDate: today,
66
+ weeklyGoal: streak.weeklyGoal,
67
+ weeklyProgress,
68
+ freezesRemaining,
69
+ lastFreezeUsed,
70
+ };
71
+ }
72
+ /**
73
+ * Check if streak is at risk (not checked in today)
74
+ */
75
+ function isStreakAtRisk(streak) {
76
+ if (streak.current === 0)
77
+ return false;
78
+ const today = formatDate(new Date());
79
+ return streak.lastActiveDate !== today;
80
+ }
81
+ /**
82
+ * Get days until streak expires
83
+ */
84
+ function getDaysUntilExpiry(streak) {
85
+ if (streak.current === 0)
86
+ return 0;
87
+ const today = new Date();
88
+ today.setHours(0, 0, 0, 0);
89
+ const lastActive = new Date(streak.lastActiveDate);
90
+ lastActive.setHours(0, 0, 0, 0);
91
+ const diffDays = Math.floor((today.getTime() - lastActive.getTime()) / (24 * 60 * 60 * 1000));
92
+ if (diffDays === 0)
93
+ return 2; // Checked in today, expires day after tomorrow
94
+ if (diffDays === 1)
95
+ return 1; // Checked in yesterday, expires tomorrow
96
+ return 0; // Already expired or will expire today
97
+ }
98
+ /**
99
+ * Format streak for display
100
+ */
101
+ function formatStreak(streak) {
102
+ if (streak.current === 0) {
103
+ return 'No active streak';
104
+ }
105
+ const isPersonalBest = streak.current === streak.longest && streak.current > 1;
106
+ const fire = '🔥'.repeat(Math.min(streak.current, 5));
107
+ let text = `${fire} ${streak.current}-day streak`;
108
+ if (isPersonalBest && streak.current > 7) {
109
+ text += ' (Personal best!)';
110
+ }
111
+ return text;
112
+ }
113
+ /**
114
+ * Format weekly progress for display
115
+ */
116
+ function formatWeeklyProgress(streak) {
117
+ const filled = '█'.repeat(streak.weeklyProgress);
118
+ const empty = '░'.repeat(Math.max(0, streak.weeklyGoal - streak.weeklyProgress));
119
+ return `${streak.weeklyProgress}/${streak.weeklyGoal} days ${filled}${empty}`;
120
+ }
121
+ // Helper functions
122
+ function formatDate(date) {
123
+ return date.toISOString().split('T')[0];
124
+ }
125
+ function getWeekStart(date) {
126
+ const d = new Date(date);
127
+ const day = d.getDay();
128
+ const diff = d.getDate() - day + (day === 0 ? -6 : 1); // Monday start
129
+ d.setDate(diff);
130
+ return formatDate(d);
131
+ }
132
+ //# sourceMappingURL=streaks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaks.js","sourceRoot":"","sources":["../../src/gamification/streaks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ export interface StreakState {
2
+ current: number;
3
+ longest: number;
4
+ lastActiveDate: string;
5
+ weeklyGoal: number;
6
+ weeklyProgress: number;
7
+ freezesRemaining: number;
8
+ lastFreezeUsed?: string;
9
+ }
10
+ export interface XPState {
11
+ total: number;
12
+ level: number;
13
+ levelName: string;
14
+ currentLevelXP: number;
15
+ nextLevelXP: number;
16
+ lastSessionXP: number;
17
+ }
18
+ export interface Achievement {
19
+ id: string;
20
+ name: string;
21
+ description: string;
22
+ icon: string;
23
+ category: 'streak' | 'score' | 'sessions' | 'special';
24
+ condition: string;
25
+ unlockedAt?: string;
26
+ progress?: number;
27
+ hidden?: boolean;
28
+ }
29
+ export interface SessionRecord {
30
+ date: string;
31
+ timestamp: string;
32
+ vibeScore: number;
33
+ overall: 'ELITE' | 'HIGH' | 'MEDIUM' | 'LOW';
34
+ commits: number;
35
+ spirals: number;
36
+ xpEarned: number;
37
+ achievementsUnlocked: string[];
38
+ periodFrom?: string;
39
+ periodTo?: string;
40
+ }
41
+ export interface UserProfile {
42
+ version: string;
43
+ createdAt: string;
44
+ updatedAt: string;
45
+ streak: StreakState;
46
+ xp: XPState;
47
+ achievements: Achievement[];
48
+ sessions: SessionRecord[];
49
+ preferences: {
50
+ weeklyGoal: number;
51
+ showNotifications: boolean;
52
+ publicProfile: boolean;
53
+ };
54
+ stats: {
55
+ totalSessions: number;
56
+ totalCommitsAnalyzed: number;
57
+ avgVibeScore: number;
58
+ bestVibeScore: number;
59
+ totalSpiralsDetected: number;
60
+ spiralsAvoided: number;
61
+ };
62
+ }
63
+ export declare const LEVELS: readonly [{
64
+ readonly level: 1;
65
+ readonly name: "Novice";
66
+ readonly icon: "🌱";
67
+ readonly minXP: 0;
68
+ readonly maxXP: 100;
69
+ }, {
70
+ readonly level: 2;
71
+ readonly name: "Apprentice";
72
+ readonly icon: "🌿";
73
+ readonly minXP: 100;
74
+ readonly maxXP: 300;
75
+ }, {
76
+ readonly level: 3;
77
+ readonly name: "Practitioner";
78
+ readonly icon: "🌳";
79
+ readonly minXP: 300;
80
+ readonly maxXP: 600;
81
+ }, {
82
+ readonly level: 4;
83
+ readonly name: "Expert";
84
+ readonly icon: "🌲";
85
+ readonly minXP: 600;
86
+ readonly maxXP: 1000;
87
+ }, {
88
+ readonly level: 5;
89
+ readonly name: "Master";
90
+ readonly icon: "🎋";
91
+ readonly minXP: 1000;
92
+ readonly maxXP: 2000;
93
+ }, {
94
+ readonly level: 6;
95
+ readonly name: "Grandmaster";
96
+ readonly icon: "🏔️";
97
+ readonly minXP: 2000;
98
+ readonly maxXP: number;
99
+ }];
100
+ export declare const XP_REWARDS: {
101
+ readonly dailyCheckIn: 10;
102
+ readonly eliteSession: 50;
103
+ readonly highSession: 25;
104
+ readonly mediumSession: 10;
105
+ readonly lowSession: 5;
106
+ readonly streakBonus: 5;
107
+ readonly achievementBase: 25;
108
+ readonly noSpirals: 15;
109
+ readonly perfectTrust: 20;
110
+ };
111
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gamification/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAElB,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAG1B,WAAW,EAAE;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IAGF,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAGD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOT,CAAC;AAGX,eAAO,MAAM,UAAU;;;;;;;;;;CAUb,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ // Gamification Types for Vibe-Check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.XP_REWARDS = exports.LEVELS = void 0;
5
+ // Level progression
6
+ exports.LEVELS = [
7
+ { level: 1, name: 'Novice', icon: '🌱', minXP: 0, maxXP: 100 },
8
+ { level: 2, name: 'Apprentice', icon: '🌿', minXP: 100, maxXP: 300 },
9
+ { level: 3, name: 'Practitioner', icon: '🌳', minXP: 300, maxXP: 600 },
10
+ { level: 4, name: 'Expert', icon: '🌲', minXP: 600, maxXP: 1000 },
11
+ { level: 5, name: 'Master', icon: '🎋', minXP: 1000, maxXP: 2000 },
12
+ { level: 6, name: 'Grandmaster', icon: '🏔️', minXP: 2000, maxXP: Infinity },
13
+ ];
14
+ // XP rewards
15
+ exports.XP_REWARDS = {
16
+ dailyCheckIn: 10,
17
+ eliteSession: 50,
18
+ highSession: 25,
19
+ mediumSession: 10,
20
+ lowSession: 5,
21
+ streakBonus: 5, // Per day of streak
22
+ achievementBase: 25, // Base for achievements
23
+ noSpirals: 15, // Bonus for 0 spirals
24
+ perfectTrust: 20, // 100% trust pass rate
25
+ };
26
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/gamification/types.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;AA0EpC,oBAAoB;AACP,QAAA,MAAM,GAAG;IACpB,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;IAC9D,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;IACpE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;IACtE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE;IACjE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAClE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE;CACpE,CAAC;AAEX,aAAa;AACA,QAAA,UAAU,GAAG;IACxB,YAAY,EAAE,EAAE;IAChB,YAAY,EAAE,EAAE;IAChB,WAAW,EAAE,EAAE;IACf,aAAa,EAAE,EAAE;IACjB,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC,EAAY,oBAAoB;IAC9C,eAAe,EAAE,EAAE,EAAO,wBAAwB;IAClD,SAAS,EAAE,EAAE,EAAa,sBAAsB;IAChD,YAAY,EAAE,EAAE,EAAU,uBAAuB;CACzC,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { XPState, LEVELS, SessionRecord, StreakState } from './types';
2
+ /**
3
+ * Create initial XP state
4
+ */
5
+ export declare function createInitialXP(): XPState;
6
+ /**
7
+ * Calculate XP earned from a session
8
+ */
9
+ export declare function calculateSessionXP(session: SessionRecord, streak: StreakState, achievementsUnlocked: number): number;
10
+ /**
11
+ * Add XP and handle level ups
12
+ */
13
+ export declare function addXP(currentXP: XPState, earnedXP: number): {
14
+ xp: XPState;
15
+ leveledUp: boolean;
16
+ newLevel?: typeof LEVELS[number];
17
+ };
18
+ /**
19
+ * Get level for given XP amount
20
+ */
21
+ export declare function getLevelForXP(xp: number): {
22
+ level: number;
23
+ levelInfo: typeof LEVELS[number];
24
+ };
25
+ /**
26
+ * Format XP progress for display
27
+ */
28
+ export declare function formatXPProgress(xp: XPState): string;
29
+ /**
30
+ * Format level for compact display
31
+ */
32
+ export declare function formatLevel(xp: XPState): string;
33
+ /**
34
+ * Get progress percentage to next level
35
+ */
36
+ export declare function getLevelProgress(xp: XPState): number;
37
+ //# sourceMappingURL=xp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xp.d.ts","sourceRoot":"","sources":["../../src/gamification/xp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAc,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAElF;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CASzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,WAAW,EACnB,oBAAoB,EAAE,MAAM,GAC3B,MAAM,CAkCR;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;CAAE,CAoBjI;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;CAAE,CAO7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAG/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAGpD"}