@boshu2/vibe-check 1.5.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 (147) 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 +191 -9
  17. package/claude-progress.txt +257 -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/timeline.d.ts +14 -0
  49. package/dist/commands/timeline.d.ts.map +1 -0
  50. package/dist/commands/timeline.js +462 -0
  51. package/dist/commands/timeline.js.map +1 -0
  52. package/dist/git.d.ts +24 -0
  53. package/dist/git.d.ts.map +1 -1
  54. package/dist/git.js +94 -0
  55. package/dist/git.js.map +1 -1
  56. package/dist/insights/generators.d.ts +44 -0
  57. package/dist/insights/generators.d.ts.map +1 -0
  58. package/dist/insights/generators.js +289 -0
  59. package/dist/insights/generators.js.map +1 -0
  60. package/dist/insights/index.d.ts +16 -0
  61. package/dist/insights/index.d.ts.map +1 -0
  62. package/dist/insights/index.js +171 -0
  63. package/dist/insights/index.js.map +1 -0
  64. package/dist/insights/types.d.ts +93 -0
  65. package/dist/insights/types.d.ts.map +1 -0
  66. package/dist/insights/types.js +6 -0
  67. package/dist/insights/types.js.map +1 -0
  68. package/dist/output/timeline-html.d.ts +6 -0
  69. package/dist/output/timeline-html.d.ts.map +1 -0
  70. package/dist/output/timeline-html.js +389 -0
  71. package/dist/output/timeline-html.js.map +1 -0
  72. package/dist/output/timeline-markdown.d.ts +6 -0
  73. package/dist/output/timeline-markdown.d.ts.map +1 -0
  74. package/dist/output/timeline-markdown.js +167 -0
  75. package/dist/output/timeline-markdown.js.map +1 -0
  76. package/dist/output/timeline.d.ts +9 -0
  77. package/dist/output/timeline.d.ts.map +1 -0
  78. package/dist/output/timeline.js +318 -0
  79. package/dist/output/timeline.js.map +1 -0
  80. package/dist/patterns/detour.d.ts +32 -0
  81. package/dist/patterns/detour.d.ts.map +1 -0
  82. package/dist/patterns/detour.js +137 -0
  83. package/dist/patterns/detour.js.map +1 -0
  84. package/dist/patterns/flow-state.d.ts +16 -0
  85. package/dist/patterns/flow-state.d.ts.map +1 -0
  86. package/dist/patterns/flow-state.js +40 -0
  87. package/dist/patterns/flow-state.js.map +1 -0
  88. package/dist/patterns/index.d.ts +8 -0
  89. package/dist/patterns/index.d.ts.map +1 -0
  90. package/dist/patterns/index.js +22 -0
  91. package/dist/patterns/index.js.map +1 -0
  92. package/dist/patterns/intervention-effectiveness.d.ts +42 -0
  93. package/dist/patterns/intervention-effectiveness.d.ts.map +1 -0
  94. package/dist/patterns/intervention-effectiveness.js +196 -0
  95. package/dist/patterns/intervention-effectiveness.js.map +1 -0
  96. package/dist/patterns/late-night.d.ts +30 -0
  97. package/dist/patterns/late-night.d.ts.map +1 -0
  98. package/dist/patterns/late-night.js +141 -0
  99. package/dist/patterns/late-night.js.map +1 -0
  100. package/dist/patterns/post-delete-sprint.d.ts +28 -0
  101. package/dist/patterns/post-delete-sprint.d.ts.map +1 -0
  102. package/dist/patterns/post-delete-sprint.js +85 -0
  103. package/dist/patterns/post-delete-sprint.js.map +1 -0
  104. package/dist/patterns/spiral-regression.d.ts +49 -0
  105. package/dist/patterns/spiral-regression.d.ts.map +1 -0
  106. package/dist/patterns/spiral-regression.js +219 -0
  107. package/dist/patterns/spiral-regression.js.map +1 -0
  108. package/dist/patterns/thrashing.d.ts +25 -0
  109. package/dist/patterns/thrashing.d.ts.map +1 -0
  110. package/dist/patterns/thrashing.js +111 -0
  111. package/dist/patterns/thrashing.js.map +1 -0
  112. package/dist/storage/atomic.d.ts +40 -0
  113. package/dist/storage/atomic.d.ts.map +1 -0
  114. package/dist/storage/atomic.js +155 -0
  115. package/dist/storage/atomic.js.map +1 -0
  116. package/dist/storage/commit-log.d.ts +35 -0
  117. package/dist/storage/commit-log.d.ts.map +1 -0
  118. package/dist/storage/commit-log.js +128 -0
  119. package/dist/storage/commit-log.js.map +1 -0
  120. package/dist/storage/index.d.ts +5 -0
  121. package/dist/storage/index.d.ts.map +1 -0
  122. package/dist/storage/index.js +33 -0
  123. package/dist/storage/index.js.map +1 -0
  124. package/dist/storage/schema.d.ts +32 -0
  125. package/dist/storage/schema.d.ts.map +1 -0
  126. package/dist/storage/schema.js +37 -0
  127. package/dist/storage/schema.js.map +1 -0
  128. package/dist/storage/timeline-store.d.ts +117 -0
  129. package/dist/storage/timeline-store.d.ts.map +1 -0
  130. package/dist/storage/timeline-store.js +438 -0
  131. package/dist/storage/timeline-store.js.map +1 -0
  132. package/dist/types.d.ts +96 -0
  133. package/dist/types.d.ts.map +1 -1
  134. package/docs/ARCHITECTURE.md +458 -0
  135. package/docs/DATA-ARCHITECTURE.md +565 -0
  136. package/docs/GAMIFICATION.md +564 -0
  137. package/docs/JSON-STORAGE-PATTERNS.md +512 -0
  138. package/docs/METRICS-EXPLAINED.md +394 -0
  139. package/docs/UNIFIED-ECOSYSTEM.md +560 -0
  140. package/docs/VIBE-ECOSYSTEM.md +406 -0
  141. package/feature-list.json +48 -0
  142. package/package.json +2 -1
  143. package/vitest.config.ts +1 -5
  144. package/.vibe-check/calibration.json +0 -38
  145. package/.vibe-check/latest.json +0 -114
  146. package/.vibe-check/sessions.json +0 -44
  147. package/PLAN-ultimate-game.md +0 -1362
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectThrashing = detectThrashing;
4
+ const date_fns_1 = require("date-fns");
5
+ /**
6
+ * Detect thrashing patterns in commits.
7
+ *
8
+ * Definition: Same file touched 5+ times in 2 hours, low net change
9
+ * Value: Identify incomplete understanding
10
+ */
11
+ function detectThrashing(events, filesPerCommit, lineStatsPerCommit) {
12
+ if (events.length < 5) {
13
+ return {
14
+ detected: false,
15
+ files: [],
16
+ totalThrashingMinutes: 0,
17
+ message: 'Not enough commits to detect thrashing',
18
+ };
19
+ }
20
+ // Track file touches within 2-hour windows
21
+ const fileTouches = new Map();
22
+ for (const event of events) {
23
+ const files = filesPerCommit.get(event.hash) || [];
24
+ for (const file of files) {
25
+ if (!fileTouches.has(file)) {
26
+ fileTouches.set(file, { commits: [], timestamps: [] });
27
+ }
28
+ const touches = fileTouches.get(file);
29
+ touches.commits.push(event.hash);
30
+ touches.timestamps.push(event.timestamp);
31
+ }
32
+ }
33
+ // Find files with 5+ touches in any 2-hour window
34
+ const thrashingFiles = [];
35
+ for (const [file, touches] of fileTouches) {
36
+ // Skip config files and lock files
37
+ if (file.includes('package-lock') || file.includes('yarn.lock') ||
38
+ file.endsWith('.json') && !file.includes('src/')) {
39
+ continue;
40
+ }
41
+ // Check for 5+ touches within 2 hours
42
+ if (touches.commits.length >= 5) {
43
+ // Find the densest 2-hour window
44
+ let maxTouchesInWindow = 0;
45
+ let windowCommits = [];
46
+ for (let i = 0; i < touches.timestamps.length; i++) {
47
+ const windowStart = touches.timestamps[i];
48
+ const commitsInWindow = [];
49
+ for (let j = i; j < touches.timestamps.length; j++) {
50
+ const gap = (0, date_fns_1.differenceInMinutes)(touches.timestamps[j], windowStart);
51
+ if (gap <= 120) {
52
+ commitsInWindow.push(touches.commits[j]);
53
+ }
54
+ }
55
+ if (commitsInWindow.length > maxTouchesInWindow) {
56
+ maxTouchesInWindow = commitsInWindow.length;
57
+ windowCommits = commitsInWindow;
58
+ }
59
+ }
60
+ if (maxTouchesInWindow >= 5) {
61
+ // Calculate net change for this file
62
+ let totalAdditions = 0;
63
+ let totalDeletions = 0;
64
+ for (const commitHash of windowCommits) {
65
+ const stats = lineStatsPerCommit.get(commitHash);
66
+ if (stats) {
67
+ // This is total stats for commit, not per-file
68
+ // For simplicity, we'll estimate based on commit count
69
+ totalAdditions += stats.additions;
70
+ totalDeletions += stats.deletions;
71
+ }
72
+ }
73
+ const netChange = totalAdditions - totalDeletions;
74
+ const totalChurn = totalAdditions + totalDeletions;
75
+ // Efficiency: how much of the work was "kept"
76
+ // Low efficiency (high churn, low net) = thrashing
77
+ const efficiency = totalChurn > 0
78
+ ? Math.round((Math.abs(netChange) / totalChurn) * 100)
79
+ : 0;
80
+ // Only flag if efficiency is low (< 50%)
81
+ if (efficiency < 50) {
82
+ thrashingFiles.push({
83
+ path: file,
84
+ touchCount: maxTouchesInWindow,
85
+ commits: windowCommits,
86
+ netChange,
87
+ efficiency,
88
+ });
89
+ }
90
+ }
91
+ }
92
+ }
93
+ // Sort by touch count (worst thrashing first)
94
+ thrashingFiles.sort((a, b) => b.touchCount - a.touchCount);
95
+ // Calculate total thrashing time (rough estimate)
96
+ const totalThrashingMinutes = thrashingFiles.reduce((sum, f) => {
97
+ // Estimate 5 minutes per touch for thrashing files
98
+ return sum + (f.touchCount * 5);
99
+ }, 0);
100
+ const detected = thrashingFiles.length > 0;
101
+ const message = detected
102
+ ? `${thrashingFiles.length} file${thrashingFiles.length > 1 ? 's' : ''} with repeated edits (potential confusion)`
103
+ : 'No thrashing detected';
104
+ return {
105
+ detected,
106
+ files: thrashingFiles.slice(0, 5), // Top 5 worst
107
+ totalThrashingMinutes,
108
+ message,
109
+ };
110
+ }
111
+ //# sourceMappingURL=thrashing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thrashing.js","sourceRoot":"","sources":["../../src/patterns/thrashing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Ensure .gitignore exists in a directory.
3
+ * Creates one if missing to prevent accidental commits.
4
+ */
5
+ export declare function ensureGitignore(dir: string): void;
6
+ /**
7
+ * Write data atomically using temp file + rename pattern.
8
+ * This prevents corruption if the process is killed mid-write.
9
+ */
10
+ export declare function atomicWriteSync(filePath: string, data: string): void;
11
+ /**
12
+ * Append a line to a file (for NDJSON).
13
+ * Creates file if it doesn't exist.
14
+ */
15
+ export declare function appendLineSync(filePath: string, line: string): void;
16
+ /**
17
+ * Result of reading NDJSON with error info
18
+ */
19
+ export interface NdjsonReadResult<T> {
20
+ items: T[];
21
+ errors: number;
22
+ total: number;
23
+ }
24
+ /**
25
+ * Read NDJSON file and parse each line.
26
+ * Returns empty array if file doesn't exist.
27
+ * Skips malformed lines gracefully instead of failing.
28
+ */
29
+ export declare function readNdjsonSync<T>(filePath: string): T[];
30
+ /**
31
+ * Read NDJSON file with detailed error reporting.
32
+ * Use this when you need to know about parse failures.
33
+ */
34
+ export declare function readNdjsonWithErrors<T>(filePath: string): NdjsonReadResult<T>;
35
+ /**
36
+ * Safely read and parse JSON with fallback.
37
+ * Returns fallback if file doesn't exist or is corrupted.
38
+ */
39
+ export declare function safeReadJsonSync<T>(filePath: string, fallback: T): T;
40
+ //# sourceMappingURL=atomic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../../src/storage/atomic.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAUjD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAYpE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,CAGvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAyB7E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAuBpE"}
@@ -0,0 +1,155 @@
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.ensureGitignore = ensureGitignore;
37
+ exports.atomicWriteSync = atomicWriteSync;
38
+ exports.appendLineSync = appendLineSync;
39
+ exports.readNdjsonSync = readNdjsonSync;
40
+ exports.readNdjsonWithErrors = readNdjsonWithErrors;
41
+ exports.safeReadJsonSync = safeReadJsonSync;
42
+ /**
43
+ * Atomic file operations for safe JSON storage
44
+ */
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const crypto_1 = require("crypto");
48
+ const GITIGNORE_CONTENT = `# vibe-check local data
49
+ # This directory contains personal productivity data
50
+ # Do NOT commit to version control
51
+
52
+ *
53
+ !.gitignore
54
+ `;
55
+ /**
56
+ * Ensure .gitignore exists in a directory.
57
+ * Creates one if missing to prevent accidental commits.
58
+ */
59
+ function ensureGitignore(dir) {
60
+ const gitignorePath = path.join(dir, '.gitignore');
61
+ if (!fs.existsSync(dir)) {
62
+ fs.mkdirSync(dir, { recursive: true });
63
+ }
64
+ if (!fs.existsSync(gitignorePath)) {
65
+ fs.writeFileSync(gitignorePath, GITIGNORE_CONTENT, 'utf-8');
66
+ }
67
+ }
68
+ /**
69
+ * Write data atomically using temp file + rename pattern.
70
+ * This prevents corruption if the process is killed mid-write.
71
+ */
72
+ function atomicWriteSync(filePath, data) {
73
+ const dir = path.dirname(filePath);
74
+ const tempPath = path.join(dir, `.${path.basename(filePath)}.${(0, crypto_1.randomBytes)(6).toString('hex')}.tmp`);
75
+ // Ensure directory exists with .gitignore
76
+ ensureGitignore(dir);
77
+ // Write to temp file
78
+ fs.writeFileSync(tempPath, data, 'utf-8');
79
+ // Atomic rename (POSIX guarantees atomicity)
80
+ fs.renameSync(tempPath, filePath);
81
+ }
82
+ /**
83
+ * Append a line to a file (for NDJSON).
84
+ * Creates file if it doesn't exist.
85
+ */
86
+ function appendLineSync(filePath, line) {
87
+ const dir = path.dirname(filePath);
88
+ // Ensure directory exists with .gitignore
89
+ ensureGitignore(dir);
90
+ // Append with newline
91
+ fs.appendFileSync(filePath, line + '\n', 'utf-8');
92
+ }
93
+ /**
94
+ * Read NDJSON file and parse each line.
95
+ * Returns empty array if file doesn't exist.
96
+ * Skips malformed lines gracefully instead of failing.
97
+ */
98
+ function readNdjsonSync(filePath) {
99
+ const result = readNdjsonWithErrors(filePath);
100
+ return result.items;
101
+ }
102
+ /**
103
+ * Read NDJSON file with detailed error reporting.
104
+ * Use this when you need to know about parse failures.
105
+ */
106
+ function readNdjsonWithErrors(filePath) {
107
+ if (!fs.existsSync(filePath)) {
108
+ return { items: [], errors: 0, total: 0 };
109
+ }
110
+ const content = fs.readFileSync(filePath, 'utf-8');
111
+ const lines = content.split('\n').filter(line => line.trim().length > 0);
112
+ const items = [];
113
+ let errors = 0;
114
+ for (const line of lines) {
115
+ try {
116
+ items.push(JSON.parse(line));
117
+ }
118
+ catch {
119
+ // Skip malformed lines - they may be from interrupted writes
120
+ errors++;
121
+ }
122
+ }
123
+ if (errors > 0) {
124
+ console.warn(`Warning: Skipped ${errors}/${lines.length} malformed lines in ${filePath}`);
125
+ }
126
+ return { items, errors, total: lines.length };
127
+ }
128
+ /**
129
+ * Safely read and parse JSON with fallback.
130
+ * Returns fallback if file doesn't exist or is corrupted.
131
+ */
132
+ function safeReadJsonSync(filePath, fallback) {
133
+ if (!fs.existsSync(filePath)) {
134
+ return fallback;
135
+ }
136
+ try {
137
+ const content = fs.readFileSync(filePath, 'utf-8');
138
+ return JSON.parse(content);
139
+ }
140
+ catch (error) {
141
+ // Log corruption but don't crash
142
+ console.warn(`Warning: Could not parse ${filePath}, using fallback`);
143
+ // Backup corrupted file for debugging
144
+ const backupPath = `${filePath}.corrupted.${Date.now()}`;
145
+ try {
146
+ fs.renameSync(filePath, backupPath);
147
+ console.warn(`Corrupted file backed up to: ${backupPath}`);
148
+ }
149
+ catch {
150
+ // Ignore backup failures
151
+ }
152
+ return fallback;
153
+ }
154
+ }
155
+ //# sourceMappingURL=atomic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic.js","sourceRoot":"","sources":["../../src/storage/atomic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { Commit } from '../types';
2
+ /**
3
+ * Stored commit format (minimal for storage efficiency)
4
+ */
5
+ export interface StoredCommit {
6
+ h: string;
7
+ d: string;
8
+ m: string;
9
+ t: string;
10
+ s: string | null;
11
+ a: string;
12
+ }
13
+ /**
14
+ * Get commit log file path
15
+ */
16
+ export declare function getCommitLogPath(repoPath?: string): string;
17
+ /**
18
+ * Append new commits to the log.
19
+ * Skips commits that already exist (by hash).
20
+ */
21
+ export declare function appendCommits(commits: Commit[], repoPath?: string): number;
22
+ /**
23
+ * Read all commits from the log.
24
+ */
25
+ export declare function readCommitLog(repoPath?: string): Commit[];
26
+ /**
27
+ * Get the most recent commit hash from the log.
28
+ * Returns empty string if log is empty.
29
+ */
30
+ export declare function getLastLoggedCommitHash(repoPath?: string): string;
31
+ /**
32
+ * Get commit count in the log.
33
+ */
34
+ export declare function getCommitLogCount(repoPath?: string): number;
35
+ //# sourceMappingURL=commit-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit-log.d.ts","sourceRoot":"","sources":["../../src/storage/commit-log.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMlC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjB,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAEzE;AA8BD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAoBzF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,EAAE,CAIxE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAOhF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAI1E"}
@@ -0,0 +1,128 @@
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.getCommitLogPath = getCommitLogPath;
37
+ exports.appendCommits = appendCommits;
38
+ exports.readCommitLog = readCommitLog;
39
+ exports.getLastLoggedCommitHash = getLastLoggedCommitHash;
40
+ exports.getCommitLogCount = getCommitLogCount;
41
+ /**
42
+ * Append-only commit log using NDJSON format.
43
+ * This is the source of truth - timeline.json is derived from this.
44
+ */
45
+ const path = __importStar(require("path"));
46
+ const atomic_1 = require("./atomic");
47
+ const STORE_DIR = '.vibe-check';
48
+ const COMMIT_LOG_FILE = 'commits.ndjson';
49
+ /**
50
+ * Get commit log file path
51
+ */
52
+ function getCommitLogPath(repoPath = process.cwd()) {
53
+ return path.join(repoPath, STORE_DIR, COMMIT_LOG_FILE);
54
+ }
55
+ /**
56
+ * Convert Commit to StoredCommit (compressed format)
57
+ */
58
+ function toStoredCommit(commit) {
59
+ return {
60
+ h: commit.hash,
61
+ d: commit.date.toISOString(),
62
+ m: commit.message,
63
+ t: commit.type,
64
+ s: commit.scope,
65
+ a: commit.author,
66
+ };
67
+ }
68
+ /**
69
+ * Convert StoredCommit back to Commit
70
+ */
71
+ function fromStoredCommit(stored) {
72
+ return {
73
+ hash: stored.h,
74
+ date: new Date(stored.d),
75
+ message: stored.m,
76
+ type: stored.t,
77
+ scope: stored.s,
78
+ author: stored.a,
79
+ };
80
+ }
81
+ /**
82
+ * Append new commits to the log.
83
+ * Skips commits that already exist (by hash).
84
+ */
85
+ function appendCommits(commits, repoPath = process.cwd()) {
86
+ const logPath = getCommitLogPath(repoPath);
87
+ // Load existing hashes to prevent duplicates
88
+ const existingHashes = new Set((0, atomic_1.readNdjsonSync)(logPath).map(c => c.h));
89
+ let appendedCount = 0;
90
+ for (const commit of commits) {
91
+ if (!existingHashes.has(commit.hash)) {
92
+ const stored = toStoredCommit(commit);
93
+ (0, atomic_1.appendLineSync)(logPath, JSON.stringify(stored));
94
+ existingHashes.add(commit.hash);
95
+ appendedCount++;
96
+ }
97
+ }
98
+ return appendedCount;
99
+ }
100
+ /**
101
+ * Read all commits from the log.
102
+ */
103
+ function readCommitLog(repoPath = process.cwd()) {
104
+ const logPath = getCommitLogPath(repoPath);
105
+ const stored = (0, atomic_1.readNdjsonSync)(logPath);
106
+ return stored.map(fromStoredCommit);
107
+ }
108
+ /**
109
+ * Get the most recent commit hash from the log.
110
+ * Returns empty string if log is empty.
111
+ */
112
+ function getLastLoggedCommitHash(repoPath = process.cwd()) {
113
+ const commits = readCommitLog(repoPath);
114
+ if (commits.length === 0)
115
+ return '';
116
+ // Sort by date descending and return most recent
117
+ const sorted = commits.sort((a, b) => b.date.getTime() - a.date.getTime());
118
+ return sorted[0].hash;
119
+ }
120
+ /**
121
+ * Get commit count in the log.
122
+ */
123
+ function getCommitLogCount(repoPath = process.cwd()) {
124
+ const logPath = getCommitLogPath(repoPath);
125
+ const commits = (0, atomic_1.readNdjsonSync)(logPath);
126
+ return commits.length;
127
+ }
128
+ //# sourceMappingURL=commit-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit-log.js","sourceRoot":"","sources":["../../src/storage/commit-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { TimelineStore, StoredSession, StoredInsight, PatternStats, TrendData, WeekTrend, MonthTrend, loadStore, saveStore, createInitialStore, updateStore, getLastCommitHash, getStorePath, getStoreDir, } from './timeline-store';
2
+ export { atomicWriteSync, appendLineSync, readNdjsonSync, readNdjsonWithErrors, safeReadJsonSync, ensureGitignore, NdjsonReadResult, } from './atomic';
3
+ export { StoredCommit, getCommitLogPath, appendCommits, readCommitLog, getLastLoggedCommitHash, getCommitLogCount, } from './commit-log';
4
+ export { SchemaVersion, CURRENT_SCHEMA_VERSION, VersionedStore, migrateStore, needsMigration, } from './schema';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,UAAU,CAAC"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.needsMigration = exports.migrateStore = exports.CURRENT_SCHEMA_VERSION = exports.getCommitLogCount = exports.getLastLoggedCommitHash = exports.readCommitLog = exports.appendCommits = exports.getCommitLogPath = exports.ensureGitignore = exports.safeReadJsonSync = exports.readNdjsonWithErrors = exports.readNdjsonSync = exports.appendLineSync = exports.atomicWriteSync = exports.getStoreDir = exports.getStorePath = exports.getLastCommitHash = exports.updateStore = exports.createInitialStore = exports.saveStore = exports.loadStore = void 0;
4
+ // Timeline store (computed view)
5
+ var timeline_store_1 = require("./timeline-store");
6
+ Object.defineProperty(exports, "loadStore", { enumerable: true, get: function () { return timeline_store_1.loadStore; } });
7
+ Object.defineProperty(exports, "saveStore", { enumerable: true, get: function () { return timeline_store_1.saveStore; } });
8
+ Object.defineProperty(exports, "createInitialStore", { enumerable: true, get: function () { return timeline_store_1.createInitialStore; } });
9
+ Object.defineProperty(exports, "updateStore", { enumerable: true, get: function () { return timeline_store_1.updateStore; } });
10
+ Object.defineProperty(exports, "getLastCommitHash", { enumerable: true, get: function () { return timeline_store_1.getLastCommitHash; } });
11
+ Object.defineProperty(exports, "getStorePath", { enumerable: true, get: function () { return timeline_store_1.getStorePath; } });
12
+ Object.defineProperty(exports, "getStoreDir", { enumerable: true, get: function () { return timeline_store_1.getStoreDir; } });
13
+ // Atomic file operations
14
+ var atomic_1 = require("./atomic");
15
+ Object.defineProperty(exports, "atomicWriteSync", { enumerable: true, get: function () { return atomic_1.atomicWriteSync; } });
16
+ Object.defineProperty(exports, "appendLineSync", { enumerable: true, get: function () { return atomic_1.appendLineSync; } });
17
+ Object.defineProperty(exports, "readNdjsonSync", { enumerable: true, get: function () { return atomic_1.readNdjsonSync; } });
18
+ Object.defineProperty(exports, "readNdjsonWithErrors", { enumerable: true, get: function () { return atomic_1.readNdjsonWithErrors; } });
19
+ Object.defineProperty(exports, "safeReadJsonSync", { enumerable: true, get: function () { return atomic_1.safeReadJsonSync; } });
20
+ Object.defineProperty(exports, "ensureGitignore", { enumerable: true, get: function () { return atomic_1.ensureGitignore; } });
21
+ // Commit log (NDJSON source of truth)
22
+ var commit_log_1 = require("./commit-log");
23
+ Object.defineProperty(exports, "getCommitLogPath", { enumerable: true, get: function () { return commit_log_1.getCommitLogPath; } });
24
+ Object.defineProperty(exports, "appendCommits", { enumerable: true, get: function () { return commit_log_1.appendCommits; } });
25
+ Object.defineProperty(exports, "readCommitLog", { enumerable: true, get: function () { return commit_log_1.readCommitLog; } });
26
+ Object.defineProperty(exports, "getLastLoggedCommitHash", { enumerable: true, get: function () { return commit_log_1.getLastLoggedCommitHash; } });
27
+ Object.defineProperty(exports, "getCommitLogCount", { enumerable: true, get: function () { return commit_log_1.getCommitLogCount; } });
28
+ // Schema versioning
29
+ var schema_1 = require("./schema");
30
+ Object.defineProperty(exports, "CURRENT_SCHEMA_VERSION", { enumerable: true, get: function () { return schema_1.CURRENT_SCHEMA_VERSION; } });
31
+ Object.defineProperty(exports, "migrateStore", { enumerable: true, get: function () { return schema_1.migrateStore; } });
32
+ Object.defineProperty(exports, "needsMigration", { enumerable: true, get: function () { return schema_1.needsMigration; } });
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":";;;AAAA,iCAAiC;AACjC,mDAe0B;AAPxB,2GAAA,SAAS,OAAA;AACT,2GAAA,SAAS,OAAA;AACT,oHAAA,kBAAkB,OAAA;AAClB,6GAAA,WAAW,OAAA;AACX,mHAAA,iBAAiB,OAAA;AACjB,8GAAA,YAAY,OAAA;AACZ,6GAAA,WAAW,OAAA;AAGb,yBAAyB;AACzB,mCAQkB;AAPhB,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AACd,wGAAA,cAAc,OAAA;AACd,8GAAA,oBAAoB,OAAA;AACpB,0GAAA,gBAAgB,OAAA;AAChB,yGAAA,eAAe,OAAA;AAIjB,sCAAsC;AACtC,2CAOsB;AALpB,8GAAA,gBAAgB,OAAA;AAChB,2GAAA,aAAa,OAAA;AACb,2GAAA,aAAa,OAAA;AACb,qHAAA,uBAAuB,OAAA;AACvB,+GAAA,iBAAiB,OAAA;AAGnB,oBAAoB;AACpB,mCAMkB;AAJhB,gHAAA,sBAAsB,OAAA;AAEtB,sGAAA,YAAY,OAAA;AACZ,wGAAA,cAAc,OAAA"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Schema versioning and migration utilities
3
+ */
4
+ export type SchemaVersion = '1.0.0' | '1.1.0' | '2.0.0';
5
+ export declare const CURRENT_SCHEMA_VERSION: SchemaVersion;
6
+ /**
7
+ * Base interface for all versioned stores
8
+ */
9
+ export interface VersionedStore {
10
+ version: SchemaVersion;
11
+ lastUpdated: string;
12
+ }
13
+ /**
14
+ * Migration function type
15
+ */
16
+ export type MigrationFn<T> = (store: T) => T;
17
+ /**
18
+ * Migration registry
19
+ */
20
+ export interface MigrationRegistry<T> {
21
+ '1.0.0_to_1.1.0'?: MigrationFn<T>;
22
+ '1.1.0_to_2.0.0'?: MigrationFn<T>;
23
+ }
24
+ /**
25
+ * Apply migrations to bring store to current version
26
+ */
27
+ export declare function migrateStore<T extends VersionedStore>(store: T, migrations: MigrationRegistry<T>): T;
28
+ /**
29
+ * Check if store needs migration
30
+ */
31
+ export declare function needsMigration(store: VersionedStore): boolean;
32
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/storage/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAExD,eAAO,MAAM,sBAAsB,EAAE,aAAuB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAClC,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,cAAc,EACnD,KAAK,EAAE,CAAC,EACR,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC/B,CAAC,CAqBH;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAE7D"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * Schema versioning and migration utilities
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CURRENT_SCHEMA_VERSION = void 0;
7
+ exports.migrateStore = migrateStore;
8
+ exports.needsMigration = needsMigration;
9
+ exports.CURRENT_SCHEMA_VERSION = '2.0.0';
10
+ /**
11
+ * Apply migrations to bring store to current version
12
+ */
13
+ function migrateStore(store, migrations) {
14
+ let currentStore = store;
15
+ // Migration path
16
+ const migrationPath = [
17
+ '1.0.0_to_1.1.0',
18
+ '1.1.0_to_2.0.0',
19
+ ];
20
+ for (const migrationKey of migrationPath) {
21
+ const [fromVersion] = migrationKey.split('_to_');
22
+ if (currentStore.version === fromVersion) {
23
+ const migration = migrations[migrationKey];
24
+ if (migration) {
25
+ currentStore = migration(currentStore);
26
+ }
27
+ }
28
+ }
29
+ return currentStore;
30
+ }
31
+ /**
32
+ * Check if store needs migration
33
+ */
34
+ function needsMigration(store) {
35
+ return store.version !== exports.CURRENT_SCHEMA_VERSION;
36
+ }
37
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/storage/schema.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AA8BH,oCAwBC;AAKD,wCAEC;AAzDY,QAAA,sBAAsB,GAAkB,OAAO,CAAC;AAuB7D;;GAEG;AACH,SAAgB,YAAY,CAC1B,KAAQ,EACR,UAAgC;IAEhC,IAAI,YAAY,GAAG,KAAK,CAAC;IAEzB,iBAAiB;IACjB,MAAM,aAAa,GAAsC;QACvD,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;IAEF,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,GAAI,YAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE7D,IAAI,YAAY,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;YAC3C,IAAI,SAAS,EAAE,CAAC;gBACd,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,KAAqB;IAClD,OAAO,KAAK,CAAC,OAAO,KAAK,8BAAsB,CAAC;AAClD,CAAC"}