heyiam 0.2.0 → 0.2.2

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 (47) hide show
  1. package/dist/analyzer.d.ts +2 -0
  2. package/dist/analyzer.js +1 -1
  3. package/dist/analyzer.js.map +1 -1
  4. package/dist/auth.js +11 -9
  5. package/dist/auth.js.map +1 -1
  6. package/dist/bridge.js +24 -20
  7. package/dist/bridge.js.map +1 -1
  8. package/dist/db.d.ts +2 -0
  9. package/dist/db.js +22 -9
  10. package/dist/db.js.map +1 -1
  11. package/dist/demo-data.d.ts +95 -0
  12. package/dist/demo-data.js +1947 -0
  13. package/dist/demo-data.js.map +1 -0
  14. package/dist/demo-seed.d.ts +17 -0
  15. package/dist/demo-seed.js +311 -0
  16. package/dist/demo-seed.js.map +1 -0
  17. package/dist/export.d.ts +3 -2
  18. package/dist/export.js +40 -23
  19. package/dist/export.js.map +1 -1
  20. package/dist/index.js +10 -3
  21. package/dist/index.js.map +1 -1
  22. package/dist/llm/triage.js +13 -7
  23. package/dist/llm/triage.js.map +1 -1
  24. package/dist/public/assets/index-C-GP5fBe.js +21 -0
  25. package/dist/public/assets/index-DdllsgZR.css +1 -0
  26. package/dist/public/dist/assets/index-C-GP5fBe.js +21 -0
  27. package/dist/public/dist/assets/index-DdllsgZR.css +1 -0
  28. package/dist/public/dist/favicon.svg +5 -0
  29. package/dist/public/dist/heyi-am-screenshot.png +0 -0
  30. package/dist/public/dist/icons.svg +24 -0
  31. package/dist/public/dist/index.html +14 -0
  32. package/dist/public/favicon.svg +5 -0
  33. package/dist/public/heyi-am-screenshot.png +0 -0
  34. package/dist/public/icons.svg +24 -0
  35. package/dist/public/index.html +14 -0
  36. package/dist/routes/context.js +25 -8
  37. package/dist/routes/context.js.map +1 -1
  38. package/dist/routes/projects.js +21 -9
  39. package/dist/routes/projects.js.map +1 -1
  40. package/dist/routes/publish.js +23 -33
  41. package/dist/routes/publish.js.map +1 -1
  42. package/dist/server.d.ts +3 -1
  43. package/dist/server.js +25 -17
  44. package/dist/server.js.map +1 -1
  45. package/dist/settings.js +10 -8
  46. package/dist/settings.js.map +1 -1
  47. package/package.json +3 -4
@@ -0,0 +1,1947 @@
1
+ // Demo data for marketing videos and screenshots.
2
+ // All data is fictional — no real names, paths, or PII.
3
+ // ── Helpers ──────────────────────────────────────────────────
4
+ function isoDate(month, day, hour = 10, min = 0) {
5
+ return `2026-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}T${String(hour).padStart(2, '0')}:${String(min).padStart(2, '0')}:00.000Z`;
6
+ }
7
+ // ── Project metadata ─────────────────────────────────────────
8
+ export const DEMO_PROJECTS = {
9
+ budgetwise: {
10
+ dirName: '-Users-alex-Dev-budgetwise',
11
+ name: 'budgetwise',
12
+ cwd: '/Users/alex/Dev/budgetwise',
13
+ skills: ['TypeScript', 'React', 'Next.js', 'Prisma', 'PostgreSQL', 'Tailwind CSS', 'Stripe API'],
14
+ },
15
+ shellhook: {
16
+ dirName: '-Users-alex-Dev-shellhook',
17
+ name: 'shellhook',
18
+ cwd: '/Users/alex/Dev/shellhook',
19
+ skills: ['Rust', 'CLI design', 'TOML parsing', 'Git internals', 'Shell scripting'],
20
+ },
21
+ pixelboard: {
22
+ dirName: '-Users-alex-Dev-pixelboard',
23
+ name: 'pixelboard',
24
+ cwd: '/Users/alex/Dev/pixelboard',
25
+ skills: ['TypeScript', 'WebSocket', 'Canvas API', 'Redis', 'Express'],
26
+ },
27
+ };
28
+ // ── Budgetwise sessions (28) ─────────────────────────────────
29
+ const budgetwiseSessions = [
30
+ {
31
+ id: 'demo-a1b2-c3d4',
32
+ title: 'Set up Prisma schema with User, Account, and Transaction models',
33
+ date: isoDate(2, 3, 9, 15),
34
+ endTime: isoDate(2, 3, 10, 42),
35
+ durationMinutes: 72,
36
+ wallClockMinutes: 87,
37
+ turns: 45,
38
+ linesOfCode: 680,
39
+ status: 'enhanced',
40
+ projectName: '-Users-alex-Dev-budgetwise',
41
+ source: 'claude',
42
+ cwd: '/Users/alex/Dev/budgetwise',
43
+ rawLog: ['Set up Prisma schema', 'Created User model', 'Added Account model with balance tracking', 'Transaction model with polymorphic types'],
44
+ skills: ['TypeScript', 'Prisma', 'PostgreSQL'],
45
+ executionPath: [
46
+ { stepNumber: 1, title: 'Schema design', description: 'Sketched out the core models — User, Account, Transaction. Decided on a discriminated union for transaction types instead of STI.' },
47
+ { stepNumber: 2, title: 'Prisma setup', description: 'Initialized Prisma with PostgreSQL, wrote the schema file with proper relations and indexes.' },
48
+ { stepNumber: 3, title: 'Migration', description: 'Ran the initial migration, fixed a cascade delete issue on Account -> Transaction.' },
49
+ { stepNumber: 4, title: 'Seed data', description: 'Created a seed script with realistic test data — multiple accounts, mixed transaction types.' },
50
+ ],
51
+ toolBreakdown: [
52
+ { tool: 'Edit', count: 18 },
53
+ { tool: 'Read', count: 12 },
54
+ { tool: 'Bash', count: 9 },
55
+ { tool: 'Write', count: 4 },
56
+ { tool: 'Grep', count: 2 },
57
+ ],
58
+ filesChanged: [
59
+ { path: 'prisma/schema.prisma', additions: 142, deletions: 0 },
60
+ { path: 'prisma/seed.ts', additions: 89, deletions: 0 },
61
+ { path: 'src/lib/db.ts', additions: 34, deletions: 0 },
62
+ { path: 'prisma/migrations/20260203_init/migration.sql', additions: 415, deletions: 0 },
63
+ ],
64
+ turnTimeline: [
65
+ { timestamp: isoDate(2, 3, 9, 15), type: 'prompt', content: 'Set up a Prisma schema for a personal finance app. I need User, Account, and Transaction models.' },
66
+ { timestamp: isoDate(2, 3, 9, 18), type: 'response', content: 'Created the initial schema with three models and their relations.' },
67
+ { timestamp: isoDate(2, 3, 9, 25), type: 'tool', content: 'Edit prisma/schema.prisma' },
68
+ { timestamp: isoDate(2, 3, 9, 40), type: 'prompt', content: 'Transactions need to support different types — income, expense, transfer. Use a discriminated union, not single-table inheritance.' },
69
+ ],
70
+ toolCalls: 45,
71
+ qaPairs: [
72
+ { question: 'Why did you choose a discriminated union over single-table inheritance for transaction types?', answer: 'STI would have left nullable columns everywhere — transferTo only makes sense for transfers, recurringSchedule only for recurring. The union pattern keeps each type clean and the TypeScript compiler catches missing fields.' },
73
+ { question: 'How does the cascade delete work between Account and Transaction?', answer: 'Deleting an account cascades to its transactions. Initially had it set to restrict, but that made account cleanup impossible without manual transaction deletion first.' },
74
+ ],
75
+ isOrchestrated: true,
76
+ children: [
77
+ { sessionId: 'demo-sub1-schema', role: 'backend-dev', durationMinutes: 35, linesOfCode: 280, date: isoDate(2, 3, 9, 18) },
78
+ { sessionId: 'demo-sub2-schema', role: 'backend-dev', durationMinutes: 25, linesOfCode: 142, date: isoDate(2, 3, 9, 18) },
79
+ { sessionId: 'demo-sub3-schema', role: 'qa-engineer', durationMinutes: 20, linesOfCode: 89, date: isoDate(2, 3, 9, 19) },
80
+ { sessionId: 'demo-sub4-schema', role: 'security-engineer', durationMinutes: 15, linesOfCode: 45, date: isoDate(2, 3, 9, 19) },
81
+ { sessionId: 'demo-sub5-schema', role: 'code-reviewer', durationMinutes: 22, linesOfCode: 30, date: isoDate(2, 3, 10, 0) },
82
+ { sessionId: 'demo-sub6-schema', role: 'frontend-dev', durationMinutes: 18, linesOfCode: 120, date: isoDate(2, 3, 10, 0) },
83
+ { sessionId: 'demo-sub7-schema', role: 'qa-engineer', durationMinutes: 12, linesOfCode: 60, date: isoDate(2, 3, 10, 1) },
84
+ ],
85
+ },
86
+ {
87
+ id: 'demo-e5f6-g7h8',
88
+ title: 'Build transaction list page with infinite scroll',
89
+ date: isoDate(2, 5, 14, 0),
90
+ endTime: isoDate(2, 5, 15, 22),
91
+ durationMinutes: 65,
92
+ wallClockMinutes: 82,
93
+ turns: 38,
94
+ linesOfCode: 520,
95
+ status: 'enhanced',
96
+ projectName: '-Users-alex-Dev-budgetwise',
97
+ source: 'claude',
98
+ cwd: '/Users/alex/Dev/budgetwise',
99
+ rawLog: ['Transaction list page', 'Infinite scroll with cursor pagination', 'Filter by account and date range'],
100
+ skills: ['React', 'Next.js', 'TypeScript', 'Tailwind CSS'],
101
+ executionPath: [
102
+ { stepNumber: 1, title: 'API route', description: 'Built the /api/transactions endpoint with cursor-based pagination. Returns 50 items per page with a nextCursor field.' },
103
+ { stepNumber: 2, title: 'List component', description: 'React component with IntersectionObserver for infinite scroll. Debounced the observer to avoid rapid re-fetches.' },
104
+ { stepNumber: 3, title: 'Filters', description: 'Added account selector and date range picker. Filters reset the cursor and refetch.' },
105
+ ],
106
+ toolBreakdown: [
107
+ { tool: 'Edit', count: 15 },
108
+ { tool: 'Read', count: 10 },
109
+ { tool: 'Bash', count: 8 },
110
+ { tool: 'Write', count: 3 },
111
+ ],
112
+ filesChanged: [
113
+ { path: 'src/app/api/transactions/route.ts', additions: 78, deletions: 0 },
114
+ { path: 'src/components/TransactionList.tsx', additions: 195, deletions: 0 },
115
+ { path: 'src/components/TransactionFilters.tsx', additions: 112, deletions: 0 },
116
+ { path: 'src/hooks/useInfiniteTransactions.ts', additions: 65, deletions: 0 },
117
+ ],
118
+ turnTimeline: [],
119
+ toolCalls: 36,
120
+ qaPairs: [
121
+ { question: 'Why cursor-based pagination instead of offset?', answer: 'Offset pagination breaks when transactions are added or deleted between pages — you either skip items or show duplicates. Cursor pagination is stable because it anchors to a specific row.' },
122
+ ],
123
+ isOrchestrated: true,
124
+ children: [
125
+ { sessionId: 'demo-sub1-txlist', role: 'frontend-dev', durationMinutes: 30, linesOfCode: 295, date: isoDate(2, 5, 14, 5) },
126
+ { sessionId: 'demo-sub2-txlist', role: 'backend-dev', durationMinutes: 20, linesOfCode: 178, date: isoDate(2, 5, 14, 5) },
127
+ { sessionId: 'demo-sub3-txlist', role: 'qa-engineer', durationMinutes: 15, linesOfCode: 65, date: isoDate(2, 5, 14, 6) },
128
+ { sessionId: 'demo-sub4-txlist', role: 'ux-designer', durationMinutes: 18, linesOfCode: 40, date: isoDate(2, 5, 14, 6) },
129
+ { sessionId: 'demo-sub5-txlist', role: 'code-reviewer', durationMinutes: 12, linesOfCode: 20, date: isoDate(2, 5, 14, 40) },
130
+ ],
131
+ },
132
+ {
133
+ id: 'demo-i9j0-k1l2',
134
+ title: 'Implement recurring transaction detection algorithm',
135
+ date: isoDate(2, 7, 10, 30),
136
+ durationMinutes: 88,
137
+ wallClockMinutes: 105,
138
+ turns: 62,
139
+ linesOfCode: 890,
140
+ status: 'enhanced',
141
+ projectName: '-Users-alex-Dev-budgetwise',
142
+ source: 'claude',
143
+ cwd: '/Users/alex/Dev/budgetwise',
144
+ rawLog: ['Recurring transaction detection', 'Pattern matching on amount + merchant', 'Frequency analysis'],
145
+ skills: ['TypeScript', 'PostgreSQL', 'Algorithm design'],
146
+ executionPath: [
147
+ { stepNumber: 1, title: 'Analysis', description: 'Grouped transactions by normalized merchant name + amount. Looked for regular intervals (weekly, biweekly, monthly).' },
148
+ { stepNumber: 2, title: 'Detection logic', description: 'Wrote the interval detection — tolerance window of +/- 3 days for monthly, +/- 1 day for weekly. Three consecutive matches = recurring.' },
149
+ { stepNumber: 3, title: 'Database query', description: 'Optimized the grouping query with a partial index on merchant_normalized. Brought detection from 2s to 120ms on 10k transactions.' },
150
+ { stepNumber: 4, title: 'Tests', description: 'Edge cases: transactions that change amount slightly over time, merchants with similar names, gaps in recurring series.' },
151
+ ],
152
+ toolBreakdown: [
153
+ { tool: 'Edit', count: 22 },
154
+ { tool: 'Read', count: 14 },
155
+ { tool: 'Bash', count: 16 },
156
+ { tool: 'Grep', count: 5 },
157
+ { tool: 'Write', count: 3 },
158
+ ],
159
+ filesChanged: [
160
+ { path: 'src/lib/recurring-detection.ts', additions: 245, deletions: 0 },
161
+ { path: 'src/lib/recurring-detection.test.ts', additions: 310, deletions: 0 },
162
+ { path: 'prisma/schema.prisma', additions: 12, deletions: 3 },
163
+ { path: 'src/app/api/recurring/route.ts', additions: 45, deletions: 0 },
164
+ ],
165
+ turnTimeline: [],
166
+ toolCalls: 60,
167
+ qaPairs: [
168
+ { question: 'How do you handle transactions where the amount changes slightly (e.g., variable utility bills)?', answer: 'Added a tolerance parameter — if amounts are within 15% of the median for that merchant, they still count as recurring. The user can adjust the threshold.' },
169
+ ],
170
+ isOrchestrated: true,
171
+ children: [
172
+ { sessionId: 'demo-sub1-recur', role: 'backend-dev', durationMinutes: 45, linesOfCode: 445, date: isoDate(2, 7, 10, 35) },
173
+ { sessionId: 'demo-sub2-recur', role: 'backend-dev', durationMinutes: 30, linesOfCode: 245, date: isoDate(2, 7, 10, 35) },
174
+ { sessionId: 'demo-sub3-recur', role: 'qa-engineer', durationMinutes: 25, linesOfCode: 310, date: isoDate(2, 7, 10, 36) },
175
+ { sessionId: 'demo-sub4-recur', role: 'security-engineer', durationMinutes: 20, linesOfCode: 45, date: isoDate(2, 7, 10, 36) },
176
+ { sessionId: 'demo-sub5-recur', role: 'code-reviewer', durationMinutes: 15, linesOfCode: 20, date: isoDate(2, 7, 11, 10) },
177
+ { sessionId: 'demo-sub6-recur', role: 'backend-dev', durationMinutes: 15, linesOfCode: 90, date: isoDate(2, 7, 11, 10) },
178
+ ],
179
+ },
180
+ {
181
+ id: 'demo-m3n4-o5p6',
182
+ title: 'Add Stripe integration for premium features',
183
+ date: isoDate(2, 10, 9, 0),
184
+ durationMinutes: 55,
185
+ wallClockMinutes: 70,
186
+ turns: 35,
187
+ linesOfCode: 420,
188
+ status: 'draft',
189
+ projectName: '-Users-alex-Dev-budgetwise',
190
+ source: 'claude',
191
+ cwd: '/Users/alex/Dev/budgetwise',
192
+ rawLog: ['Stripe checkout session', 'Webhook handler for payment events', 'Premium feature gating'],
193
+ skills: ['TypeScript', 'Stripe API', 'Next.js'],
194
+ executionPath: [],
195
+ toolBreakdown: [
196
+ { tool: 'Edit', count: 14 },
197
+ { tool: 'Read', count: 8 },
198
+ { tool: 'Bash', count: 6 },
199
+ { tool: 'Write', count: 4 },
200
+ ],
201
+ filesChanged: [
202
+ { path: 'src/app/api/stripe/checkout/route.ts', additions: 67, deletions: 0 },
203
+ { path: 'src/app/api/stripe/webhook/route.ts', additions: 98, deletions: 0 },
204
+ { path: 'src/lib/stripe.ts', additions: 45, deletions: 0 },
205
+ { path: 'src/middleware.ts', additions: 23, deletions: 5 },
206
+ ],
207
+ turnTimeline: [],
208
+ toolCalls: 32,
209
+ },
210
+ {
211
+ id: 'demo-q7r8-s9t0',
212
+ title: 'Design dashboard layout with spending charts',
213
+ date: isoDate(2, 12, 11, 0),
214
+ durationMinutes: 45,
215
+ wallClockMinutes: 52,
216
+ turns: 28,
217
+ linesOfCode: 380,
218
+ status: 'draft',
219
+ projectName: '-Users-alex-Dev-budgetwise',
220
+ source: 'claude',
221
+ cwd: '/Users/alex/Dev/budgetwise',
222
+ rawLog: ['Dashboard layout', 'Monthly spending chart', 'Category breakdown pie chart'],
223
+ skills: ['React', 'Tailwind CSS', 'Chart.js'],
224
+ executionPath: [],
225
+ toolBreakdown: [
226
+ { tool: 'Edit', count: 12 },
227
+ { tool: 'Read', count: 6 },
228
+ { tool: 'Write', count: 5 },
229
+ ],
230
+ filesChanged: [
231
+ { path: 'src/app/dashboard/page.tsx', additions: 145, deletions: 0 },
232
+ { path: 'src/components/SpendingChart.tsx', additions: 120, deletions: 0 },
233
+ { path: 'src/components/CategoryBreakdown.tsx', additions: 95, deletions: 0 },
234
+ ],
235
+ turnTimeline: [],
236
+ toolCalls: 23,
237
+ },
238
+ {
239
+ id: 'demo-u1v2-w3x4',
240
+ title: 'Fix currency formatting edge cases in locale-aware display',
241
+ date: isoDate(2, 13, 15, 30),
242
+ durationMinutes: 18,
243
+ wallClockMinutes: 22,
244
+ turns: 12,
245
+ linesOfCode: 85,
246
+ status: 'draft',
247
+ projectName: '-Users-alex-Dev-budgetwise',
248
+ source: 'cursor',
249
+ cwd: '/Users/alex/Dev/budgetwise',
250
+ rawLog: ['Fix Intl.NumberFormat for JPY', 'Handle zero-decimal currencies'],
251
+ skills: ['TypeScript'],
252
+ executionPath: [],
253
+ toolBreakdown: [
254
+ { tool: 'Edit', count: 5 },
255
+ { tool: 'Read', count: 4 },
256
+ { tool: 'Bash', count: 3 },
257
+ ],
258
+ filesChanged: [
259
+ { path: 'src/lib/currency.ts', additions: 32, deletions: 8 },
260
+ { path: 'src/lib/currency.test.ts', additions: 45, deletions: 0 },
261
+ ],
262
+ turnTimeline: [],
263
+ toolCalls: 12,
264
+ },
265
+ {
266
+ id: 'demo-y5z6-a7b8',
267
+ title: 'Add account balance reconciliation checks',
268
+ date: isoDate(2, 14, 10, 0),
269
+ durationMinutes: 42,
270
+ wallClockMinutes: 55,
271
+ turns: 30,
272
+ linesOfCode: 310,
273
+ status: 'draft',
274
+ projectName: '-Users-alex-Dev-budgetwise',
275
+ source: 'claude',
276
+ cwd: '/Users/alex/Dev/budgetwise',
277
+ rawLog: ['Balance reconciliation', 'Detect drift between computed and stored balance'],
278
+ skills: ['TypeScript', 'PostgreSQL', 'Prisma'],
279
+ executionPath: [],
280
+ toolBreakdown: [
281
+ { tool: 'Edit', count: 10 },
282
+ { tool: 'Read', count: 8 },
283
+ { tool: 'Bash', count: 7 },
284
+ ],
285
+ filesChanged: [
286
+ { path: 'src/lib/reconciliation.ts', additions: 120, deletions: 0 },
287
+ { path: 'src/lib/reconciliation.test.ts', additions: 165, deletions: 0 },
288
+ { path: 'src/app/api/accounts/reconcile/route.ts', additions: 25, deletions: 0 },
289
+ ],
290
+ turnTimeline: [],
291
+ toolCalls: 25,
292
+ },
293
+ {
294
+ id: 'demo-c9d0-e1f2',
295
+ title: 'Build CSV import for bank statements',
296
+ date: isoDate(2, 17, 9, 45),
297
+ durationMinutes: 78,
298
+ wallClockMinutes: 95,
299
+ turns: 52,
300
+ linesOfCode: 640,
301
+ status: 'draft',
302
+ projectName: '-Users-alex-Dev-budgetwise',
303
+ source: 'claude',
304
+ cwd: '/Users/alex/Dev/budgetwise',
305
+ rawLog: ['CSV parser', 'Column mapping UI', 'Duplicate detection on import'],
306
+ skills: ['TypeScript', 'React', 'Next.js'],
307
+ executionPath: [],
308
+ toolBreakdown: [
309
+ { tool: 'Edit', count: 20 },
310
+ { tool: 'Read', count: 12 },
311
+ { tool: 'Bash', count: 10 },
312
+ { tool: 'Write', count: 5 },
313
+ ],
314
+ filesChanged: [
315
+ { path: 'src/lib/csv-parser.ts', additions: 180, deletions: 0 },
316
+ { path: 'src/components/ImportWizard.tsx', additions: 245, deletions: 0 },
317
+ { path: 'src/app/api/import/route.ts', additions: 95, deletions: 0 },
318
+ { path: 'src/lib/csv-parser.test.ts', additions: 120, deletions: 0 },
319
+ ],
320
+ turnTimeline: [],
321
+ toolCalls: 47,
322
+ isOrchestrated: true,
323
+ children: [
324
+ { sessionId: 'demo-sub1-csv', role: 'backend-dev', durationMinutes: 40, linesOfCode: 280, date: isoDate(2, 17, 9, 50) },
325
+ { sessionId: 'demo-sub2-csv', role: 'frontend-dev', durationMinutes: 35, linesOfCode: 245, date: isoDate(2, 17, 9, 50) },
326
+ { sessionId: 'demo-sub3-csv', role: 'qa-engineer', durationMinutes: 25, linesOfCode: 120, date: isoDate(2, 17, 9, 51) },
327
+ { sessionId: 'demo-sub4-csv', role: 'code-reviewer', durationMinutes: 15, linesOfCode: 30, date: isoDate(2, 17, 10, 25) },
328
+ { sessionId: 'demo-sub5-csv', role: 'backend-dev', durationMinutes: 15, linesOfCode: 95, date: isoDate(2, 17, 10, 25) },
329
+ ],
330
+ },
331
+ {
332
+ id: 'demo-g3h4-i5j6',
333
+ title: 'Implement budget categories with monthly limits',
334
+ date: isoDate(2, 19, 13, 0),
335
+ durationMinutes: 58,
336
+ wallClockMinutes: 68,
337
+ turns: 40,
338
+ linesOfCode: 480,
339
+ status: 'draft',
340
+ projectName: '-Users-alex-Dev-budgetwise',
341
+ source: 'claude',
342
+ cwd: '/Users/alex/Dev/budgetwise',
343
+ rawLog: ['Budget categories', 'Monthly spending limits', 'Overspend alerts'],
344
+ skills: ['TypeScript', 'Prisma', 'React'],
345
+ executionPath: [],
346
+ toolBreakdown: [
347
+ { tool: 'Edit', count: 16 },
348
+ { tool: 'Read', count: 10 },
349
+ { tool: 'Bash', count: 8 },
350
+ ],
351
+ filesChanged: [
352
+ { path: 'prisma/schema.prisma', additions: 28, deletions: 2 },
353
+ { path: 'src/app/api/budgets/route.ts', additions: 85, deletions: 0 },
354
+ { path: 'src/components/BudgetManager.tsx', additions: 210, deletions: 0 },
355
+ { path: 'src/lib/budget-alerts.ts', additions: 75, deletions: 0 },
356
+ ],
357
+ turnTimeline: [],
358
+ toolCalls: 34,
359
+ },
360
+ {
361
+ id: 'demo-k7l8-m9n0',
362
+ title: 'Add email notifications for budget overspend',
363
+ date: isoDate(2, 20, 16, 0),
364
+ durationMinutes: 32,
365
+ wallClockMinutes: 38,
366
+ turns: 20,
367
+ linesOfCode: 210,
368
+ status: 'draft',
369
+ projectName: '-Users-alex-Dev-budgetwise',
370
+ source: 'claude',
371
+ cwd: '/Users/alex/Dev/budgetwise',
372
+ rawLog: ['Email notifications', 'Resend integration', 'Template for budget alerts'],
373
+ skills: ['TypeScript', 'Next.js'],
374
+ executionPath: [],
375
+ toolBreakdown: [
376
+ { tool: 'Edit', count: 8 },
377
+ { tool: 'Read', count: 5 },
378
+ { tool: 'Bash', count: 4 },
379
+ { tool: 'Write', count: 3 },
380
+ ],
381
+ filesChanged: [
382
+ { path: 'src/lib/email.ts', additions: 65, deletions: 0 },
383
+ { path: 'src/emails/budget-alert.tsx', additions: 85, deletions: 0 },
384
+ { path: 'src/app/api/notifications/route.ts', additions: 45, deletions: 0 },
385
+ ],
386
+ turnTimeline: [],
387
+ toolCalls: 20,
388
+ },
389
+ {
390
+ id: 'demo-o1p2-q3r4',
391
+ title: 'Write E2E tests for transaction CRUD flow',
392
+ date: isoDate(2, 21, 10, 0),
393
+ durationMinutes: 48,
394
+ wallClockMinutes: 55,
395
+ turns: 33,
396
+ linesOfCode: 410,
397
+ status: 'draft',
398
+ projectName: '-Users-alex-Dev-budgetwise',
399
+ source: 'claude',
400
+ cwd: '/Users/alex/Dev/budgetwise',
401
+ rawLog: ['Playwright E2E tests', 'Transaction create/read/update/delete', 'Test fixtures'],
402
+ skills: ['TypeScript', 'Playwright', 'Testing'],
403
+ executionPath: [],
404
+ toolBreakdown: [
405
+ { tool: 'Edit', count: 14 },
406
+ { tool: 'Read', count: 8 },
407
+ { tool: 'Bash', count: 12 },
408
+ { tool: 'Write', count: 3 },
409
+ ],
410
+ filesChanged: [
411
+ { path: 'tests/transactions.spec.ts', additions: 280, deletions: 0 },
412
+ { path: 'tests/fixtures/test-data.ts', additions: 85, deletions: 0 },
413
+ { path: 'playwright.config.ts', additions: 35, deletions: 0 },
414
+ ],
415
+ turnTimeline: [],
416
+ toolCalls: 37,
417
+ },
418
+ {
419
+ id: 'demo-s5t6-u7v8',
420
+ title: 'Optimize transaction queries with composite indexes',
421
+ date: isoDate(2, 24, 14, 30),
422
+ durationMinutes: 25,
423
+ wallClockMinutes: 30,
424
+ turns: 15,
425
+ linesOfCode: 120,
426
+ status: 'draft',
427
+ projectName: '-Users-alex-Dev-budgetwise',
428
+ source: 'claude',
429
+ cwd: '/Users/alex/Dev/budgetwise',
430
+ rawLog: ['EXPLAIN ANALYZE on slow queries', 'Added composite index on (account_id, created_at)', 'Removed unused index'],
431
+ skills: ['PostgreSQL', 'Prisma'],
432
+ executionPath: [],
433
+ toolBreakdown: [
434
+ { tool: 'Read', count: 6 },
435
+ { tool: 'Bash', count: 8 },
436
+ { tool: 'Edit', count: 4 },
437
+ ],
438
+ filesChanged: [
439
+ { path: 'prisma/schema.prisma', additions: 8, deletions: 3 },
440
+ { path: 'prisma/migrations/20260224_indexes/migration.sql', additions: 12, deletions: 0 },
441
+ ],
442
+ turnTimeline: [],
443
+ toolCalls: 18,
444
+ },
445
+ {
446
+ id: 'demo-w9x0-y1z2',
447
+ title: 'Add dark mode with system preference detection',
448
+ date: isoDate(2, 25, 11, 0),
449
+ durationMinutes: 35,
450
+ wallClockMinutes: 42,
451
+ turns: 22,
452
+ linesOfCode: 280,
453
+ status: 'draft',
454
+ projectName: '-Users-alex-Dev-budgetwise',
455
+ source: 'cursor',
456
+ cwd: '/Users/alex/Dev/budgetwise',
457
+ rawLog: ['Dark mode toggle', 'CSS variables', 'System preference media query'],
458
+ skills: ['React', 'Tailwind CSS', 'CSS'],
459
+ executionPath: [],
460
+ toolBreakdown: [
461
+ { tool: 'Edit', count: 12 },
462
+ { tool: 'Read', count: 6 },
463
+ ],
464
+ filesChanged: [
465
+ { path: 'src/app/globals.css', additions: 95, deletions: 12 },
466
+ { path: 'src/components/ThemeToggle.tsx', additions: 48, deletions: 0 },
467
+ { path: 'src/hooks/useTheme.ts', additions: 35, deletions: 0 },
468
+ { path: 'tailwind.config.ts', additions: 8, deletions: 2 },
469
+ ],
470
+ turnTimeline: [],
471
+ toolCalls: 18,
472
+ },
473
+ {
474
+ id: 'demo-a3b4-c5d6',
475
+ title: 'Build account settings page with profile editing',
476
+ date: isoDate(2, 26, 9, 30),
477
+ durationMinutes: 40,
478
+ wallClockMinutes: 48,
479
+ turns: 25,
480
+ linesOfCode: 350,
481
+ status: 'draft',
482
+ projectName: '-Users-alex-Dev-budgetwise',
483
+ source: 'claude',
484
+ cwd: '/Users/alex/Dev/budgetwise',
485
+ rawLog: ['Settings page', 'Profile form with validation', 'Currency preference'],
486
+ skills: ['React', 'Next.js', 'TypeScript'],
487
+ executionPath: [],
488
+ toolBreakdown: [
489
+ { tool: 'Edit', count: 11 },
490
+ { tool: 'Read', count: 7 },
491
+ { tool: 'Write', count: 3 },
492
+ ],
493
+ filesChanged: [
494
+ { path: 'src/app/settings/page.tsx', additions: 165, deletions: 0 },
495
+ { path: 'src/components/ProfileForm.tsx', additions: 120, deletions: 0 },
496
+ { path: 'src/app/api/settings/route.ts', additions: 55, deletions: 0 },
497
+ ],
498
+ turnTimeline: [],
499
+ toolCalls: 21,
500
+ },
501
+ {
502
+ id: 'demo-e7f8-g9h0',
503
+ title: 'Implement transaction search with full-text index',
504
+ date: isoDate(3, 1, 10, 0),
505
+ durationMinutes: 52,
506
+ wallClockMinutes: 65,
507
+ turns: 36,
508
+ linesOfCode: 390,
509
+ status: 'draft',
510
+ projectName: '-Users-alex-Dev-budgetwise',
511
+ source: 'claude',
512
+ cwd: '/Users/alex/Dev/budgetwise',
513
+ rawLog: ['Full-text search on transaction descriptions', 'PostgreSQL tsvector', 'Search results UI'],
514
+ skills: ['PostgreSQL', 'TypeScript', 'React'],
515
+ executionPath: [],
516
+ toolBreakdown: [
517
+ { tool: 'Edit', count: 13 },
518
+ { tool: 'Read', count: 9 },
519
+ { tool: 'Bash', count: 8 },
520
+ ],
521
+ filesChanged: [
522
+ { path: 'prisma/schema.prisma', additions: 6, deletions: 0 },
523
+ { path: 'src/app/api/transactions/search/route.ts', additions: 85, deletions: 0 },
524
+ { path: 'src/components/TransactionSearch.tsx', additions: 145, deletions: 0 },
525
+ { path: 'prisma/migrations/20260301_fts/migration.sql', additions: 22, deletions: 0 },
526
+ ],
527
+ turnTimeline: [],
528
+ toolCalls: 30,
529
+ },
530
+ {
531
+ id: 'demo-i1j2-k3l4',
532
+ title: 'Add plaid integration for bank account linking',
533
+ date: isoDate(3, 3, 13, 15),
534
+ durationMinutes: 90,
535
+ wallClockMinutes: 115,
536
+ turns: 68,
537
+ linesOfCode: 780,
538
+ status: 'draft',
539
+ projectName: '-Users-alex-Dev-budgetwise',
540
+ source: 'claude',
541
+ cwd: '/Users/alex/Dev/budgetwise',
542
+ rawLog: ['Plaid Link integration', 'Token exchange flow', 'Transaction sync webhook', 'Error handling for expired tokens'],
543
+ skills: ['TypeScript', 'Next.js', 'Plaid API'],
544
+ executionPath: [],
545
+ toolBreakdown: [
546
+ { tool: 'Edit', count: 24 },
547
+ { tool: 'Read', count: 15 },
548
+ { tool: 'Bash', count: 12 },
549
+ { tool: 'Write', count: 6 },
550
+ ],
551
+ filesChanged: [
552
+ { path: 'src/lib/plaid.ts', additions: 145, deletions: 0 },
553
+ { path: 'src/app/api/plaid/link/route.ts', additions: 65, deletions: 0 },
554
+ { path: 'src/app/api/plaid/webhook/route.ts', additions: 120, deletions: 0 },
555
+ { path: 'src/components/PlaidLink.tsx', additions: 85, deletions: 0 },
556
+ { path: 'src/lib/plaid.test.ts', additions: 180, deletions: 0 },
557
+ ],
558
+ turnTimeline: [],
559
+ toolCalls: 57,
560
+ isOrchestrated: true,
561
+ children: [
562
+ { sessionId: 'demo-sub1-plaid', role: 'backend-dev', durationMinutes: 45, linesOfCode: 330, date: isoDate(3, 3, 13, 20) },
563
+ { sessionId: 'demo-sub2-plaid', role: 'frontend-dev', durationMinutes: 25, linesOfCode: 170, date: isoDate(3, 3, 13, 20) },
564
+ { sessionId: 'demo-sub3-plaid', role: 'security-engineer', durationMinutes: 30, linesOfCode: 210, date: isoDate(3, 3, 13, 21) },
565
+ { sessionId: 'demo-sub4-plaid', role: 'qa-engineer', durationMinutes: 35, linesOfCode: 180, date: isoDate(3, 3, 13, 21) },
566
+ { sessionId: 'demo-sub5-plaid', role: 'code-reviewer', durationMinutes: 12, linesOfCode: 45, date: isoDate(3, 3, 14, 0) },
567
+ { sessionId: 'demo-sub6-plaid', role: 'security-red-teamer', durationMinutes: 10, linesOfCode: 30, date: isoDate(3, 3, 14, 0) },
568
+ { sessionId: 'demo-sub7-plaid', role: 'backend-dev', durationMinutes: 20, linesOfCode: 140, date: isoDate(3, 3, 14, 1) },
569
+ { sessionId: 'demo-sub8-plaid', role: 'qa-engineer', durationMinutes: 18, linesOfCode: 90, date: isoDate(3, 3, 14, 1) },
570
+ ],
571
+ },
572
+ {
573
+ id: 'demo-m5n6-o7p8',
574
+ title: 'Fix timezone bug in monthly spending aggregation',
575
+ date: isoDate(3, 4, 16, 45),
576
+ durationMinutes: 15,
577
+ wallClockMinutes: 18,
578
+ turns: 8,
579
+ linesOfCode: 45,
580
+ status: 'draft',
581
+ projectName: '-Users-alex-Dev-budgetwise',
582
+ source: 'claude',
583
+ cwd: '/Users/alex/Dev/budgetwise',
584
+ rawLog: ['Fix: spending totals were wrong near month boundaries', 'Use UTC consistently'],
585
+ skills: ['TypeScript', 'PostgreSQL'],
586
+ executionPath: [],
587
+ toolBreakdown: [
588
+ { tool: 'Edit', count: 3 },
589
+ { tool: 'Read', count: 4 },
590
+ { tool: 'Bash', count: 2 },
591
+ ],
592
+ filesChanged: [
593
+ { path: 'src/lib/aggregation.ts', additions: 12, deletions: 8 },
594
+ { path: 'src/lib/aggregation.test.ts', additions: 25, deletions: 0 },
595
+ ],
596
+ turnTimeline: [],
597
+ toolCalls: 9,
598
+ },
599
+ {
600
+ id: 'demo-q9r0-s1t2',
601
+ title: 'Add transaction tagging and custom categories',
602
+ date: isoDate(3, 6, 10, 30),
603
+ durationMinutes: 62,
604
+ wallClockMinutes: 75,
605
+ turns: 42,
606
+ linesOfCode: 520,
607
+ status: 'draft',
608
+ projectName: '-Users-alex-Dev-budgetwise',
609
+ source: 'claude',
610
+ cwd: '/Users/alex/Dev/budgetwise',
611
+ rawLog: ['Transaction tags', 'Custom categories', 'Auto-categorization rules'],
612
+ skills: ['TypeScript', 'Prisma', 'React'],
613
+ executionPath: [],
614
+ toolBreakdown: [
615
+ { tool: 'Edit', count: 18 },
616
+ { tool: 'Read', count: 11 },
617
+ { tool: 'Bash', count: 7 },
618
+ ],
619
+ filesChanged: [
620
+ { path: 'prisma/schema.prisma', additions: 22, deletions: 0 },
621
+ { path: 'src/components/TagEditor.tsx', additions: 145, deletions: 0 },
622
+ { path: 'src/lib/auto-categorize.ts', additions: 95, deletions: 0 },
623
+ { path: 'src/app/api/categories/route.ts', additions: 68, deletions: 0 },
624
+ ],
625
+ turnTimeline: [],
626
+ toolCalls: 36,
627
+ },
628
+ {
629
+ id: 'demo-u3v4-w5x6',
630
+ title: 'Build spending insights with trend analysis',
631
+ date: isoDate(3, 8, 9, 0),
632
+ durationMinutes: 70,
633
+ wallClockMinutes: 85,
634
+ turns: 48,
635
+ linesOfCode: 620,
636
+ status: 'draft',
637
+ projectName: '-Users-alex-Dev-budgetwise',
638
+ source: 'claude',
639
+ cwd: '/Users/alex/Dev/budgetwise',
640
+ rawLog: ['Spending trends', 'Month-over-month comparison', 'Anomaly detection for unusual spending'],
641
+ skills: ['TypeScript', 'React', 'Chart.js'],
642
+ executionPath: [],
643
+ toolBreakdown: [
644
+ { tool: 'Edit', count: 20 },
645
+ { tool: 'Read', count: 12 },
646
+ { tool: 'Bash', count: 9 },
647
+ ],
648
+ filesChanged: [
649
+ { path: 'src/components/SpendingInsights.tsx', additions: 210, deletions: 0 },
650
+ { path: 'src/lib/trend-analysis.ts', additions: 185, deletions: 0 },
651
+ { path: 'src/lib/anomaly-detection.ts', additions: 110, deletions: 0 },
652
+ { path: 'src/lib/trend-analysis.test.ts', additions: 115, deletions: 0 },
653
+ ],
654
+ turnTimeline: [],
655
+ toolCalls: 41,
656
+ isOrchestrated: true,
657
+ children: [
658
+ { sessionId: 'demo-sub1-insights', role: 'backend-dev', durationMinutes: 35, linesOfCode: 285, date: isoDate(3, 8, 9, 5) },
659
+ { sessionId: 'demo-sub2-insights', role: 'frontend-dev', durationMinutes: 30, linesOfCode: 210, date: isoDate(3, 8, 9, 5) },
660
+ { sessionId: 'demo-sub3-insights', role: 'qa-engineer', durationMinutes: 20, linesOfCode: 115, date: isoDate(3, 8, 9, 6) },
661
+ { sessionId: 'demo-sub4-insights', role: 'code-reviewer', durationMinutes: 12, linesOfCode: 20, date: isoDate(3, 8, 9, 6) },
662
+ ],
663
+ },
664
+ {
665
+ id: 'demo-y7z8-a9b0',
666
+ title: 'Add data export with PDF report generation',
667
+ date: isoDate(3, 10, 14, 0),
668
+ durationMinutes: 55,
669
+ wallClockMinutes: 68,
670
+ turns: 35,
671
+ linesOfCode: 450,
672
+ status: 'draft',
673
+ projectName: '-Users-alex-Dev-budgetwise',
674
+ source: 'cursor',
675
+ cwd: '/Users/alex/Dev/budgetwise',
676
+ rawLog: ['PDF report generation', 'Monthly statement template', 'CSV export option'],
677
+ skills: ['TypeScript', 'Next.js', 'PDF generation'],
678
+ executionPath: [],
679
+ toolBreakdown: [
680
+ { tool: 'Edit', count: 15 },
681
+ { tool: 'Read', count: 8 },
682
+ { tool: 'Bash', count: 7 },
683
+ { tool: 'Write', count: 4 },
684
+ ],
685
+ filesChanged: [
686
+ { path: 'src/lib/pdf-report.ts', additions: 165, deletions: 0 },
687
+ { path: 'src/app/api/export/pdf/route.ts', additions: 85, deletions: 0 },
688
+ { path: 'src/app/api/export/csv/route.ts', additions: 55, deletions: 0 },
689
+ { path: 'src/components/ExportDialog.tsx', additions: 95, deletions: 0 },
690
+ ],
691
+ turnTimeline: [],
692
+ toolCalls: 34,
693
+ },
694
+ {
695
+ id: 'demo-c1d2-e3f4',
696
+ title: 'Implement multi-currency support with exchange rates',
697
+ date: isoDate(3, 12, 10, 15),
698
+ durationMinutes: 82,
699
+ wallClockMinutes: 100,
700
+ turns: 55,
701
+ linesOfCode: 710,
702
+ status: 'draft',
703
+ projectName: '-Users-alex-Dev-budgetwise',
704
+ source: 'claude',
705
+ cwd: '/Users/alex/Dev/budgetwise',
706
+ rawLog: ['Multi-currency accounts', 'Exchange rate API integration', 'Conversion logic'],
707
+ skills: ['TypeScript', 'Prisma', 'PostgreSQL'],
708
+ executionPath: [],
709
+ toolBreakdown: [
710
+ { tool: 'Edit', count: 22 },
711
+ { tool: 'Read', count: 14 },
712
+ { tool: 'Bash', count: 11 },
713
+ { tool: 'Write', count: 4 },
714
+ ],
715
+ filesChanged: [
716
+ { path: 'src/lib/exchange-rates.ts', additions: 120, deletions: 0 },
717
+ { path: 'prisma/schema.prisma', additions: 18, deletions: 4 },
718
+ { path: 'src/lib/currency-conversion.ts', additions: 95, deletions: 0 },
719
+ { path: 'src/components/CurrencySelector.tsx', additions: 75, deletions: 0 },
720
+ { path: 'src/lib/exchange-rates.test.ts', additions: 140, deletions: 0 },
721
+ ],
722
+ turnTimeline: [],
723
+ toolCalls: 51,
724
+ isOrchestrated: true,
725
+ children: [
726
+ { sessionId: 'demo-sub1-curr', role: 'backend-dev', durationMinutes: 45, linesOfCode: 320, date: isoDate(3, 12, 10, 20) },
727
+ { sessionId: 'demo-sub2-curr', role: 'frontend-dev', durationMinutes: 30, linesOfCode: 175, date: isoDate(3, 12, 10, 20) },
728
+ { sessionId: 'demo-sub3-curr', role: 'backend-dev', durationMinutes: 25, linesOfCode: 195, date: isoDate(3, 12, 10, 21) },
729
+ { sessionId: 'demo-sub4-curr', role: 'qa-engineer', durationMinutes: 28, linesOfCode: 140, date: isoDate(3, 12, 10, 21) },
730
+ { sessionId: 'demo-sub5-curr', role: 'security-engineer', durationMinutes: 15, linesOfCode: 60, date: isoDate(3, 12, 10, 50) },
731
+ { sessionId: 'demo-sub6-curr', role: 'code-reviewer', durationMinutes: 12, linesOfCode: 35, date: isoDate(3, 12, 10, 50) },
732
+ ],
733
+ },
734
+ {
735
+ id: 'demo-g5h6-i7j8',
736
+ title: 'Fix N+1 query in account list with transaction counts',
737
+ date: isoDate(3, 14, 15, 0),
738
+ durationMinutes: 12,
739
+ wallClockMinutes: 15,
740
+ turns: 6,
741
+ linesOfCode: 28,
742
+ status: 'draft',
743
+ projectName: '-Users-alex-Dev-budgetwise',
744
+ source: 'claude',
745
+ cwd: '/Users/alex/Dev/budgetwise',
746
+ rawLog: ['Fix N+1 query', 'Use _count in Prisma include'],
747
+ skills: ['Prisma', 'PostgreSQL'],
748
+ executionPath: [],
749
+ toolBreakdown: [
750
+ { tool: 'Read', count: 3 },
751
+ { tool: 'Edit', count: 2 },
752
+ { tool: 'Bash', count: 2 },
753
+ ],
754
+ filesChanged: [
755
+ { path: 'src/app/api/accounts/route.ts', additions: 8, deletions: 12 },
756
+ ],
757
+ turnTimeline: [],
758
+ toolCalls: 7,
759
+ },
760
+ {
761
+ id: 'demo-k9l0-m1n2',
762
+ title: 'Add two-factor authentication with TOTP',
763
+ date: isoDate(3, 16, 9, 0),
764
+ durationMinutes: 68,
765
+ wallClockMinutes: 80,
766
+ turns: 44,
767
+ linesOfCode: 560,
768
+ status: 'draft',
769
+ projectName: '-Users-alex-Dev-budgetwise',
770
+ source: 'claude',
771
+ cwd: '/Users/alex/Dev/budgetwise',
772
+ rawLog: ['TOTP-based 2FA', 'QR code generation', 'Backup codes', 'Recovery flow'],
773
+ skills: ['TypeScript', 'Next.js', 'Security'],
774
+ executionPath: [],
775
+ toolBreakdown: [
776
+ { tool: 'Edit', count: 18 },
777
+ { tool: 'Read', count: 10 },
778
+ { tool: 'Bash', count: 9 },
779
+ { tool: 'Write', count: 5 },
780
+ ],
781
+ filesChanged: [
782
+ { path: 'src/lib/totp.ts', additions: 95, deletions: 0 },
783
+ { path: 'src/app/settings/security/page.tsx', additions: 180, deletions: 0 },
784
+ { path: 'src/app/api/auth/2fa/setup/route.ts', additions: 75, deletions: 0 },
785
+ { path: 'src/app/api/auth/2fa/verify/route.ts', additions: 55, deletions: 0 },
786
+ { path: 'src/lib/backup-codes.ts', additions: 45, deletions: 0 },
787
+ ],
788
+ turnTimeline: [],
789
+ toolCalls: 42,
790
+ },
791
+ {
792
+ id: 'demo-o3p4-q5r6',
793
+ title: 'Refactor API routes to use middleware pattern',
794
+ date: isoDate(3, 18, 11, 30),
795
+ durationMinutes: 45,
796
+ wallClockMinutes: 55,
797
+ turns: 30,
798
+ linesOfCode: 340,
799
+ status: 'draft',
800
+ projectName: '-Users-alex-Dev-budgetwise',
801
+ source: 'claude',
802
+ cwd: '/Users/alex/Dev/budgetwise',
803
+ rawLog: ['Extract auth middleware', 'Rate limiting middleware', 'Error handling wrapper'],
804
+ skills: ['TypeScript', 'Next.js'],
805
+ executionPath: [],
806
+ toolBreakdown: [
807
+ { tool: 'Edit', count: 16 },
808
+ { tool: 'Read', count: 12 },
809
+ { tool: 'Grep', count: 5 },
810
+ ],
811
+ filesChanged: [
812
+ { path: 'src/lib/middleware/auth.ts', additions: 55, deletions: 0 },
813
+ { path: 'src/lib/middleware/rate-limit.ts', additions: 45, deletions: 0 },
814
+ { path: 'src/lib/middleware/error-handler.ts', additions: 38, deletions: 0 },
815
+ { path: 'src/app/api/transactions/route.ts', additions: 12, deletions: 35 },
816
+ { path: 'src/app/api/accounts/route.ts', additions: 10, deletions: 28 },
817
+ ],
818
+ turnTimeline: [],
819
+ toolCalls: 33,
820
+ },
821
+ {
822
+ id: 'demo-s7t8-u9v0',
823
+ title: 'Add mobile-responsive layout with bottom navigation',
824
+ date: isoDate(3, 20, 14, 0),
825
+ durationMinutes: 38,
826
+ wallClockMinutes: 45,
827
+ turns: 24,
828
+ linesOfCode: 290,
829
+ status: 'draft',
830
+ projectName: '-Users-alex-Dev-budgetwise',
831
+ source: 'cursor',
832
+ cwd: '/Users/alex/Dev/budgetwise',
833
+ rawLog: ['Mobile layout', 'Bottom nav bar', 'Responsive breakpoints'],
834
+ skills: ['React', 'Tailwind CSS', 'CSS'],
835
+ executionPath: [],
836
+ toolBreakdown: [
837
+ { tool: 'Edit', count: 10 },
838
+ { tool: 'Read', count: 6 },
839
+ ],
840
+ filesChanged: [
841
+ { path: 'src/components/BottomNav.tsx', additions: 85, deletions: 0 },
842
+ { path: 'src/app/layout.tsx', additions: 25, deletions: 8 },
843
+ { path: 'src/app/globals.css', additions: 45, deletions: 5 },
844
+ ],
845
+ turnTimeline: [],
846
+ toolCalls: 16,
847
+ },
848
+ {
849
+ id: 'demo-w1x2-y3z4',
850
+ title: 'Set up CI pipeline with GitHub Actions',
851
+ date: isoDate(3, 22, 9, 0),
852
+ durationMinutes: 28,
853
+ wallClockMinutes: 35,
854
+ turns: 18,
855
+ linesOfCode: 185,
856
+ status: 'draft',
857
+ projectName: '-Users-alex-Dev-budgetwise',
858
+ source: 'claude',
859
+ cwd: '/Users/alex/Dev/budgetwise',
860
+ rawLog: ['GitHub Actions workflow', 'Lint + test + build', 'PostgreSQL service container'],
861
+ skills: ['GitHub Actions', 'CI/CD', 'PostgreSQL'],
862
+ executionPath: [],
863
+ toolBreakdown: [
864
+ { tool: 'Write', count: 3 },
865
+ { tool: 'Edit', count: 5 },
866
+ { tool: 'Read', count: 4 },
867
+ { tool: 'Bash', count: 6 },
868
+ ],
869
+ filesChanged: [
870
+ { path: '.github/workflows/ci.yml', additions: 95, deletions: 0 },
871
+ { path: '.github/workflows/deploy.yml', additions: 65, deletions: 0 },
872
+ { path: 'package.json', additions: 5, deletions: 2 },
873
+ ],
874
+ turnTimeline: [],
875
+ toolCalls: 18,
876
+ },
877
+ {
878
+ id: 'demo-a5b6-c7d8',
879
+ title: 'Write API documentation with OpenAPI spec',
880
+ date: isoDate(3, 24, 10, 0),
881
+ durationMinutes: 42,
882
+ wallClockMinutes: 50,
883
+ turns: 26,
884
+ linesOfCode: 380,
885
+ status: 'draft',
886
+ projectName: '-Users-alex-Dev-budgetwise',
887
+ source: 'gemini',
888
+ cwd: '/Users/alex/Dev/budgetwise',
889
+ rawLog: ['OpenAPI spec', 'Swagger UI integration', 'Request/response schemas'],
890
+ skills: ['TypeScript', 'OpenAPI'],
891
+ executionPath: [],
892
+ toolBreakdown: [
893
+ { tool: 'Write', count: 4 },
894
+ { tool: 'Edit', count: 8 },
895
+ { tool: 'Read', count: 6 },
896
+ ],
897
+ filesChanged: [
898
+ { path: 'docs/openapi.yaml', additions: 285, deletions: 0 },
899
+ { path: 'src/app/api/docs/route.ts', additions: 45, deletions: 0 },
900
+ { path: 'package.json', additions: 3, deletions: 1 },
901
+ ],
902
+ turnTimeline: [],
903
+ toolCalls: 18,
904
+ },
905
+ {
906
+ id: 'demo-e9f0-g1h2',
907
+ title: 'Performance audit and bundle size optimization',
908
+ date: isoDate(3, 26, 15, 0),
909
+ durationMinutes: 35,
910
+ wallClockMinutes: 42,
911
+ turns: 22,
912
+ linesOfCode: 95,
913
+ status: 'draft',
914
+ projectName: '-Users-alex-Dev-budgetwise',
915
+ source: 'claude',
916
+ cwd: '/Users/alex/Dev/budgetwise',
917
+ rawLog: ['Bundle analysis', 'Lazy load Chart.js', 'Tree-shake unused Tailwind'],
918
+ skills: ['Next.js', 'Performance', 'Webpack'],
919
+ executionPath: [],
920
+ toolBreakdown: [
921
+ { tool: 'Bash', count: 10 },
922
+ { tool: 'Edit', count: 6 },
923
+ { tool: 'Read', count: 5 },
924
+ ],
925
+ filesChanged: [
926
+ { path: 'next.config.ts', additions: 15, deletions: 3 },
927
+ { path: 'src/components/SpendingChart.tsx', additions: 8, deletions: 4 },
928
+ { path: 'tailwind.config.ts', additions: 5, deletions: 2 },
929
+ ],
930
+ turnTimeline: [],
931
+ toolCalls: 21,
932
+ },
933
+ ];
934
+ // ── Shellhook sessions (12) ─────────────────────────────────
935
+ const shellhookSessions = [
936
+ {
937
+ id: 'demo-sh01-aa01',
938
+ title: 'Scaffold Rust CLI with clap and project structure',
939
+ date: isoDate(1, 15, 10, 0),
940
+ durationMinutes: 45,
941
+ wallClockMinutes: 55,
942
+ turns: 30,
943
+ linesOfCode: 420,
944
+ status: 'draft',
945
+ projectName: '-Users-alex-Dev-shellhook',
946
+ source: 'claude',
947
+ cwd: '/Users/alex/Dev/shellhook',
948
+ rawLog: ['cargo init', 'clap argument parser', 'Subcommand structure: init, add, remove, list, run'],
949
+ skills: ['Rust', 'CLI design'],
950
+ executionPath: [],
951
+ toolBreakdown: [
952
+ { tool: 'Write', count: 6 },
953
+ { tool: 'Edit', count: 10 },
954
+ { tool: 'Bash', count: 12 },
955
+ { tool: 'Read', count: 4 },
956
+ ],
957
+ filesChanged: [
958
+ { path: 'src/main.rs', additions: 85, deletions: 0 },
959
+ { path: 'src/cli.rs', additions: 120, deletions: 0 },
960
+ { path: 'src/lib.rs', additions: 15, deletions: 0 },
961
+ { path: 'Cargo.toml', additions: 22, deletions: 0 },
962
+ ],
963
+ turnTimeline: [],
964
+ toolCalls: 32,
965
+ },
966
+ {
967
+ id: 'demo-sh02-bb02',
968
+ title: 'Implement TOML config parser for hook definitions',
969
+ date: isoDate(1, 17, 14, 0),
970
+ durationMinutes: 58,
971
+ wallClockMinutes: 70,
972
+ turns: 38,
973
+ linesOfCode: 510,
974
+ status: 'draft',
975
+ projectName: '-Users-alex-Dev-shellhook',
976
+ source: 'claude',
977
+ cwd: '/Users/alex/Dev/shellhook',
978
+ rawLog: ['TOML config format design', 'Serde deserialization', 'Config validation'],
979
+ skills: ['Rust', 'TOML parsing'],
980
+ executionPath: [],
981
+ toolBreakdown: [
982
+ { tool: 'Edit', count: 14 },
983
+ { tool: 'Read', count: 8 },
984
+ { tool: 'Bash', count: 10 },
985
+ { tool: 'Write', count: 3 },
986
+ ],
987
+ filesChanged: [
988
+ { path: 'src/config.rs', additions: 185, deletions: 0 },
989
+ { path: 'src/config_test.rs', additions: 210, deletions: 0 },
990
+ { path: 'Cargo.toml', additions: 4, deletions: 1 },
991
+ { path: 'tests/fixtures/valid.toml', additions: 35, deletions: 0 },
992
+ ],
993
+ turnTimeline: [],
994
+ toolCalls: 35,
995
+ },
996
+ {
997
+ id: 'demo-sh03-cc03',
998
+ title: 'Build git hook installer that symlinks to shellhook runner',
999
+ date: isoDate(1, 20, 10, 30),
1000
+ durationMinutes: 72,
1001
+ wallClockMinutes: 88,
1002
+ turns: 48,
1003
+ linesOfCode: 580,
1004
+ status: 'draft',
1005
+ projectName: '-Users-alex-Dev-shellhook',
1006
+ source: 'claude',
1007
+ cwd: '/Users/alex/Dev/shellhook',
1008
+ rawLog: ['Git hook installation', 'Symlink strategy', 'Backup existing hooks', 'Cross-platform path handling'],
1009
+ skills: ['Rust', 'Git internals', 'Shell scripting'],
1010
+ executionPath: [],
1011
+ toolBreakdown: [
1012
+ { tool: 'Edit', count: 18 },
1013
+ { tool: 'Read', count: 10 },
1014
+ { tool: 'Bash', count: 14 },
1015
+ { tool: 'Grep', count: 3 },
1016
+ ],
1017
+ filesChanged: [
1018
+ { path: 'src/installer.rs', additions: 220, deletions: 0 },
1019
+ { path: 'src/runner.rs', additions: 145, deletions: 0 },
1020
+ { path: 'src/installer_test.rs', additions: 180, deletions: 0 },
1021
+ ],
1022
+ turnTimeline: [],
1023
+ toolCalls: 45,
1024
+ isOrchestrated: true,
1025
+ children: [
1026
+ { sessionId: 'demo-sub1-hook', role: 'backend-dev', durationMinutes: 40, linesOfCode: 320, date: isoDate(1, 20, 10, 35) },
1027
+ { sessionId: 'demo-sub2-hook', role: 'qa-engineer', durationMinutes: 25, linesOfCode: 180, date: isoDate(1, 20, 10, 35) },
1028
+ { sessionId: 'demo-sub3-hook', role: 'backend-dev', durationMinutes: 20, linesOfCode: 145, date: isoDate(1, 20, 10, 36) },
1029
+ { sessionId: 'demo-sub4-hook', role: 'security-engineer', durationMinutes: 15, linesOfCode: 80, date: isoDate(1, 20, 11, 5) },
1030
+ { sessionId: 'demo-sub5-hook', role: 'code-reviewer', durationMinutes: 10, linesOfCode: 35, date: isoDate(1, 20, 11, 5) },
1031
+ ],
1032
+ },
1033
+ {
1034
+ id: 'demo-sh04-dd04',
1035
+ title: 'Refactor CLI argument parser to support subcommands',
1036
+ date: isoDate(1, 22, 15, 0),
1037
+ durationMinutes: 35,
1038
+ wallClockMinutes: 42,
1039
+ turns: 22,
1040
+ linesOfCode: 280,
1041
+ status: 'draft',
1042
+ projectName: '-Users-alex-Dev-shellhook',
1043
+ source: 'claude',
1044
+ cwd: '/Users/alex/Dev/shellhook',
1045
+ rawLog: ['Refactor clap to use derive API', 'Add init, add, remove, list subcommands'],
1046
+ skills: ['Rust', 'CLI design'],
1047
+ executionPath: [],
1048
+ toolBreakdown: [
1049
+ { tool: 'Edit', count: 12 },
1050
+ { tool: 'Read', count: 6 },
1051
+ { tool: 'Bash', count: 5 },
1052
+ ],
1053
+ filesChanged: [
1054
+ { path: 'src/cli.rs', additions: 95, deletions: 65 },
1055
+ { path: 'src/main.rs', additions: 45, deletions: 30 },
1056
+ { path: 'src/commands/mod.rs', additions: 25, deletions: 0 },
1057
+ ],
1058
+ turnTimeline: [],
1059
+ toolCalls: 23,
1060
+ },
1061
+ {
1062
+ id: 'demo-sh05-ee05',
1063
+ title: 'Add hook execution with timeout and error handling',
1064
+ date: isoDate(1, 25, 9, 0),
1065
+ durationMinutes: 65,
1066
+ wallClockMinutes: 78,
1067
+ turns: 42,
1068
+ linesOfCode: 490,
1069
+ status: 'draft',
1070
+ projectName: '-Users-alex-Dev-shellhook',
1071
+ source: 'claude',
1072
+ cwd: '/Users/alex/Dev/shellhook',
1073
+ rawLog: ['Hook execution engine', 'Configurable timeouts', 'Stderr/stdout capture', 'Exit code propagation'],
1074
+ skills: ['Rust', 'Shell scripting'],
1075
+ executionPath: [],
1076
+ toolBreakdown: [
1077
+ { tool: 'Edit', count: 16 },
1078
+ { tool: 'Read', count: 9 },
1079
+ { tool: 'Bash', count: 12 },
1080
+ ],
1081
+ filesChanged: [
1082
+ { path: 'src/executor.rs', additions: 195, deletions: 0 },
1083
+ { path: 'src/executor_test.rs', additions: 165, deletions: 0 },
1084
+ { path: 'src/runner.rs', additions: 45, deletions: 12 },
1085
+ ],
1086
+ turnTimeline: [],
1087
+ toolCalls: 37,
1088
+ },
1089
+ {
1090
+ id: 'demo-sh06-ff06',
1091
+ title: 'Implement hook ordering with dependency resolution',
1092
+ date: isoDate(1, 28, 11, 0),
1093
+ durationMinutes: 55,
1094
+ wallClockMinutes: 65,
1095
+ turns: 36,
1096
+ linesOfCode: 420,
1097
+ status: 'draft',
1098
+ projectName: '-Users-alex-Dev-shellhook',
1099
+ source: 'claude',
1100
+ cwd: '/Users/alex/Dev/shellhook',
1101
+ rawLog: ['Topological sort for hook dependencies', 'Cycle detection', 'Parallel execution for independent hooks'],
1102
+ skills: ['Rust', 'Algorithm design'],
1103
+ executionPath: [],
1104
+ toolBreakdown: [
1105
+ { tool: 'Edit', count: 14 },
1106
+ { tool: 'Read', count: 8 },
1107
+ { tool: 'Bash', count: 10 },
1108
+ ],
1109
+ filesChanged: [
1110
+ { path: 'src/ordering.rs', additions: 165, deletions: 0 },
1111
+ { path: 'src/ordering_test.rs', additions: 185, deletions: 0 },
1112
+ { path: 'src/config.rs', additions: 22, deletions: 5 },
1113
+ ],
1114
+ turnTimeline: [],
1115
+ toolCalls: 32,
1116
+ },
1117
+ {
1118
+ id: 'demo-sh07-gg07',
1119
+ title: 'Add colored output and progress indicators',
1120
+ date: isoDate(2, 1, 14, 30),
1121
+ durationMinutes: 22,
1122
+ wallClockMinutes: 28,
1123
+ turns: 14,
1124
+ linesOfCode: 165,
1125
+ status: 'draft',
1126
+ projectName: '-Users-alex-Dev-shellhook',
1127
+ source: 'cursor',
1128
+ cwd: '/Users/alex/Dev/shellhook',
1129
+ rawLog: ['Colored terminal output', 'Progress spinners for long hooks', 'Respect NO_COLOR env var'],
1130
+ skills: ['Rust', 'CLI design'],
1131
+ executionPath: [],
1132
+ toolBreakdown: [
1133
+ { tool: 'Edit', count: 8 },
1134
+ { tool: 'Read', count: 4 },
1135
+ { tool: 'Bash', count: 3 },
1136
+ ],
1137
+ filesChanged: [
1138
+ { path: 'src/output.rs', additions: 95, deletions: 0 },
1139
+ { path: 'src/runner.rs', additions: 35, deletions: 10 },
1140
+ { path: 'Cargo.toml', additions: 3, deletions: 0 },
1141
+ ],
1142
+ turnTimeline: [],
1143
+ toolCalls: 15,
1144
+ },
1145
+ {
1146
+ id: 'demo-sh08-hh08',
1147
+ title: 'Fix path resolution on Windows with UNC paths',
1148
+ date: isoDate(2, 3, 10, 0),
1149
+ durationMinutes: 28,
1150
+ wallClockMinutes: 35,
1151
+ turns: 18,
1152
+ linesOfCode: 145,
1153
+ status: 'draft',
1154
+ projectName: '-Users-alex-Dev-shellhook',
1155
+ source: 'claude',
1156
+ cwd: '/Users/alex/Dev/shellhook',
1157
+ rawLog: ['Windows UNC path handling', 'Cross-platform path normalization'],
1158
+ skills: ['Rust', 'Cross-platform'],
1159
+ executionPath: [],
1160
+ toolBreakdown: [
1161
+ { tool: 'Edit', count: 7 },
1162
+ { tool: 'Read', count: 5 },
1163
+ { tool: 'Bash', count: 6 },
1164
+ ],
1165
+ filesChanged: [
1166
+ { path: 'src/paths.rs', additions: 65, deletions: 8 },
1167
+ { path: 'src/paths_test.rs', additions: 72, deletions: 0 },
1168
+ ],
1169
+ turnTimeline: [],
1170
+ toolCalls: 18,
1171
+ },
1172
+ {
1173
+ id: 'demo-sh09-ii09',
1174
+ title: 'Add shellhook init command with interactive setup',
1175
+ date: isoDate(2, 5, 13, 0),
1176
+ durationMinutes: 40,
1177
+ wallClockMinutes: 48,
1178
+ turns: 26,
1179
+ linesOfCode: 320,
1180
+ status: 'draft',
1181
+ projectName: '-Users-alex-Dev-shellhook',
1182
+ source: 'claude',
1183
+ cwd: '/Users/alex/Dev/shellhook',
1184
+ rawLog: ['Interactive init command', 'Detect existing hooks', 'Generate starter config'],
1185
+ skills: ['Rust', 'CLI design', 'Git internals'],
1186
+ executionPath: [],
1187
+ toolBreakdown: [
1188
+ { tool: 'Edit', count: 12 },
1189
+ { tool: 'Read', count: 7 },
1190
+ { tool: 'Bash', count: 8 },
1191
+ { tool: 'Write', count: 2 },
1192
+ ],
1193
+ filesChanged: [
1194
+ { path: 'src/commands/init.rs', additions: 145, deletions: 0 },
1195
+ { path: 'src/commands/init_test.rs', additions: 120, deletions: 0 },
1196
+ { path: 'templates/default.toml', additions: 35, deletions: 0 },
1197
+ ],
1198
+ turnTimeline: [],
1199
+ toolCalls: 29,
1200
+ },
1201
+ {
1202
+ id: 'demo-sh10-jj10',
1203
+ title: 'Write integration tests with temp git repos',
1204
+ date: isoDate(2, 8, 10, 0),
1205
+ durationMinutes: 52,
1206
+ wallClockMinutes: 62,
1207
+ turns: 34,
1208
+ linesOfCode: 445,
1209
+ status: 'draft',
1210
+ projectName: '-Users-alex-Dev-shellhook',
1211
+ source: 'claude',
1212
+ cwd: '/Users/alex/Dev/shellhook',
1213
+ rawLog: ['Integration test harness', 'Temp git repo fixtures', 'Test all hook lifecycle operations'],
1214
+ skills: ['Rust', 'Testing', 'Git internals'],
1215
+ executionPath: [],
1216
+ toolBreakdown: [
1217
+ { tool: 'Edit', count: 16 },
1218
+ { tool: 'Read', count: 8 },
1219
+ { tool: 'Bash', count: 14 },
1220
+ { tool: 'Write', count: 4 },
1221
+ ],
1222
+ filesChanged: [
1223
+ { path: 'tests/integration/lifecycle.rs', additions: 225, deletions: 0 },
1224
+ { path: 'tests/integration/helpers.rs', additions: 85, deletions: 0 },
1225
+ { path: 'tests/integration/mod.rs', additions: 10, deletions: 0 },
1226
+ ],
1227
+ turnTimeline: [],
1228
+ toolCalls: 42,
1229
+ },
1230
+ {
1231
+ id: 'demo-sh11-kk11',
1232
+ title: 'Add shell completion generation for bash/zsh/fish',
1233
+ date: isoDate(2, 10, 15, 0),
1234
+ durationMinutes: 18,
1235
+ wallClockMinutes: 22,
1236
+ turns: 10,
1237
+ linesOfCode: 85,
1238
+ status: 'draft',
1239
+ projectName: '-Users-alex-Dev-shellhook',
1240
+ source: 'claude',
1241
+ cwd: '/Users/alex/Dev/shellhook',
1242
+ rawLog: ['clap_complete for shell completions', 'Generate for bash, zsh, fish'],
1243
+ skills: ['Rust', 'CLI design', 'Shell scripting'],
1244
+ executionPath: [],
1245
+ toolBreakdown: [
1246
+ { tool: 'Edit', count: 5 },
1247
+ { tool: 'Read', count: 3 },
1248
+ { tool: 'Bash', count: 4 },
1249
+ ],
1250
+ filesChanged: [
1251
+ { path: 'src/commands/completions.rs', additions: 45, deletions: 0 },
1252
+ { path: 'src/cli.rs', additions: 12, deletions: 2 },
1253
+ { path: 'Cargo.toml', additions: 2, deletions: 0 },
1254
+ ],
1255
+ turnTimeline: [],
1256
+ toolCalls: 12,
1257
+ },
1258
+ {
1259
+ id: 'demo-sh12-ll12',
1260
+ title: 'Publish to crates.io with README and changelog',
1261
+ date: isoDate(2, 12, 9, 0),
1262
+ durationMinutes: 22,
1263
+ wallClockMinutes: 28,
1264
+ turns: 14,
1265
+ linesOfCode: 180,
1266
+ status: 'draft',
1267
+ projectName: '-Users-alex-Dev-shellhook',
1268
+ source: 'gemini',
1269
+ cwd: '/Users/alex/Dev/shellhook',
1270
+ rawLog: ['Cargo.toml metadata', 'README with usage examples', 'CHANGELOG.md'],
1271
+ skills: ['Rust', 'Documentation'],
1272
+ executionPath: [],
1273
+ toolBreakdown: [
1274
+ { tool: 'Write', count: 3 },
1275
+ { tool: 'Edit', count: 5 },
1276
+ { tool: 'Read', count: 3 },
1277
+ { tool: 'Bash', count: 4 },
1278
+ ],
1279
+ filesChanged: [
1280
+ { path: 'Cargo.toml', additions: 18, deletions: 3 },
1281
+ { path: 'README.md', additions: 120, deletions: 0 },
1282
+ { path: 'CHANGELOG.md', additions: 42, deletions: 0 },
1283
+ ],
1284
+ turnTimeline: [],
1285
+ toolCalls: 15,
1286
+ },
1287
+ ];
1288
+ // ── Pixelboard sessions (6) ─────────────────────────────────
1289
+ const pixelboardSessions = [
1290
+ {
1291
+ id: 'demo-pb01-aa01',
1292
+ title: 'Set up Express server with WebSocket upgrade handling',
1293
+ date: isoDate(3, 15, 10, 0),
1294
+ durationMinutes: 48,
1295
+ wallClockMinutes: 58,
1296
+ turns: 32,
1297
+ linesOfCode: 380,
1298
+ status: 'draft',
1299
+ projectName: '-Users-alex-Dev-pixelboard',
1300
+ source: 'claude',
1301
+ cwd: '/Users/alex/Dev/pixelboard',
1302
+ rawLog: ['Express + ws server', 'WebSocket upgrade on /ws', 'Room-based connection management'],
1303
+ skills: ['TypeScript', 'Express', 'WebSocket'],
1304
+ executionPath: [],
1305
+ toolBreakdown: [
1306
+ { tool: 'Write', count: 5 },
1307
+ { tool: 'Edit', count: 12 },
1308
+ { tool: 'Bash', count: 8 },
1309
+ { tool: 'Read', count: 4 },
1310
+ ],
1311
+ filesChanged: [
1312
+ { path: 'src/server.ts', additions: 125, deletions: 0 },
1313
+ { path: 'src/ws/connection-manager.ts', additions: 145, deletions: 0 },
1314
+ { path: 'src/ws/protocol.ts', additions: 65, deletions: 0 },
1315
+ { path: 'package.json', additions: 28, deletions: 0 },
1316
+ ],
1317
+ turnTimeline: [],
1318
+ toolCalls: 29,
1319
+ },
1320
+ {
1321
+ id: 'demo-pb02-bb02',
1322
+ title: 'Build Canvas rendering layer with pressure-sensitive drawing',
1323
+ date: isoDate(3, 17, 14, 0),
1324
+ durationMinutes: 65,
1325
+ wallClockMinutes: 78,
1326
+ turns: 44,
1327
+ linesOfCode: 580,
1328
+ status: 'draft',
1329
+ projectName: '-Users-alex-Dev-pixelboard',
1330
+ source: 'claude',
1331
+ cwd: '/Users/alex/Dev/pixelboard',
1332
+ rawLog: ['Canvas 2D rendering', 'Pressure-sensitive strokes', 'Smooth curve interpolation'],
1333
+ skills: ['TypeScript', 'Canvas API'],
1334
+ executionPath: [],
1335
+ toolBreakdown: [
1336
+ { tool: 'Edit', count: 18 },
1337
+ { tool: 'Read', count: 8 },
1338
+ { tool: 'Bash', count: 6 },
1339
+ { tool: 'Write', count: 3 },
1340
+ ],
1341
+ filesChanged: [
1342
+ { path: 'src/client/canvas-renderer.ts', additions: 245, deletions: 0 },
1343
+ { path: 'src/client/stroke-engine.ts', additions: 185, deletions: 0 },
1344
+ { path: 'src/client/input-handler.ts', additions: 95, deletions: 0 },
1345
+ ],
1346
+ turnTimeline: [],
1347
+ toolCalls: 35,
1348
+ },
1349
+ {
1350
+ id: 'demo-pb03-cc03',
1351
+ title: 'Implement CRDT-based state sync for concurrent edits',
1352
+ date: isoDate(3, 19, 10, 0),
1353
+ durationMinutes: 85,
1354
+ wallClockMinutes: 105,
1355
+ turns: 58,
1356
+ linesOfCode: 720,
1357
+ status: 'draft',
1358
+ projectName: '-Users-alex-Dev-pixelboard',
1359
+ source: 'claude',
1360
+ cwd: '/Users/alex/Dev/pixelboard',
1361
+ rawLog: ['CRDT for stroke ordering', 'Vector clock for causal ordering', 'Conflict resolution for overlapping strokes'],
1362
+ skills: ['TypeScript', 'CRDT', 'WebSocket'],
1363
+ executionPath: [],
1364
+ toolBreakdown: [
1365
+ { tool: 'Edit', count: 22 },
1366
+ { tool: 'Read', count: 12 },
1367
+ { tool: 'Bash', count: 14 },
1368
+ { tool: 'Write', count: 4 },
1369
+ ],
1370
+ filesChanged: [
1371
+ { path: 'src/sync/crdt.ts', additions: 285, deletions: 0 },
1372
+ { path: 'src/sync/vector-clock.ts', additions: 95, deletions: 0 },
1373
+ { path: 'src/sync/crdt.test.ts', additions: 240, deletions: 0 },
1374
+ { path: 'src/ws/protocol.ts', additions: 35, deletions: 8 },
1375
+ ],
1376
+ turnTimeline: [],
1377
+ toolCalls: 52,
1378
+ isOrchestrated: true,
1379
+ children: [
1380
+ { sessionId: 'demo-sub1-crdt', role: 'backend-dev', durationMinutes: 50, linesOfCode: 380, date: isoDate(3, 18, 11, 5) },
1381
+ { sessionId: 'demo-sub2-crdt', role: 'frontend-dev', durationMinutes: 40, linesOfCode: 240, date: isoDate(3, 18, 11, 5) },
1382
+ { sessionId: 'demo-sub3-crdt', role: 'backend-dev', durationMinutes: 35, linesOfCode: 290, date: isoDate(3, 18, 11, 6) },
1383
+ { sessionId: 'demo-sub4-crdt', role: 'qa-engineer', durationMinutes: 30, linesOfCode: 200, date: isoDate(3, 18, 11, 6) },
1384
+ { sessionId: 'demo-sub5-crdt', role: 'security-engineer', durationMinutes: 25, linesOfCode: 150, date: isoDate(3, 18, 11, 6) },
1385
+ { sessionId: 'demo-sub6-crdt', role: 'code-reviewer', durationMinutes: 15, linesOfCode: 60, date: isoDate(3, 18, 11, 40) },
1386
+ { sessionId: 'demo-sub7-crdt', role: 'frontend-dev', durationMinutes: 20, linesOfCode: 170, date: isoDate(3, 18, 11, 40) },
1387
+ { sessionId: 'demo-sub8-crdt', role: 'qa-engineer', durationMinutes: 18, linesOfCode: 120, date: isoDate(3, 18, 11, 41) },
1388
+ { sessionId: 'demo-sub9-crdt', role: 'security-red-teamer', durationMinutes: 12, linesOfCode: 40, date: isoDate(3, 18, 11, 41) },
1389
+ { sessionId: 'demo-sub10-crdt', role: 'backend-dev', durationMinutes: 22, linesOfCode: 180, date: isoDate(3, 18, 11, 41) },
1390
+ ],
1391
+ },
1392
+ {
1393
+ id: 'demo-pb04-dd04',
1394
+ title: 'Fix WebSocket reconnection race condition',
1395
+ date: isoDate(3, 21, 16, 0),
1396
+ durationMinutes: 25,
1397
+ wallClockMinutes: 30,
1398
+ turns: 16,
1399
+ linesOfCode: 120,
1400
+ status: 'draft',
1401
+ projectName: '-Users-alex-Dev-pixelboard',
1402
+ source: 'claude',
1403
+ cwd: '/Users/alex/Dev/pixelboard',
1404
+ rawLog: ['Race condition: reconnect while old connection still closing', 'Add connection state machine'],
1405
+ skills: ['TypeScript', 'WebSocket'],
1406
+ executionPath: [],
1407
+ toolBreakdown: [
1408
+ { tool: 'Edit', count: 6 },
1409
+ { tool: 'Read', count: 5 },
1410
+ { tool: 'Bash', count: 4 },
1411
+ ],
1412
+ filesChanged: [
1413
+ { path: 'src/client/ws-client.ts', additions: 55, deletions: 22 },
1414
+ { path: 'src/client/ws-client.test.ts', additions: 65, deletions: 0 },
1415
+ ],
1416
+ turnTimeline: [],
1417
+ toolCalls: 15,
1418
+ },
1419
+ {
1420
+ id: 'demo-pb05-ee05',
1421
+ title: 'Add Redis pub/sub for multi-server board state',
1422
+ date: isoDate(3, 23, 10, 30),
1423
+ durationMinutes: 55,
1424
+ wallClockMinutes: 65,
1425
+ turns: 36,
1426
+ linesOfCode: 380,
1427
+ status: 'draft',
1428
+ projectName: '-Users-alex-Dev-pixelboard',
1429
+ source: 'claude',
1430
+ cwd: '/Users/alex/Dev/pixelboard',
1431
+ rawLog: ['Redis pub/sub for cross-server sync', 'Board state persistence', 'Connection handoff on reconnect'],
1432
+ skills: ['TypeScript', 'Redis', 'WebSocket'],
1433
+ executionPath: [],
1434
+ toolBreakdown: [
1435
+ { tool: 'Edit', count: 14 },
1436
+ { tool: 'Read', count: 8 },
1437
+ { tool: 'Bash', count: 10 },
1438
+ { tool: 'Write', count: 2 },
1439
+ ],
1440
+ filesChanged: [
1441
+ { path: 'src/store/redis-adapter.ts', additions: 145, deletions: 0 },
1442
+ { path: 'src/store/board-state.ts', additions: 95, deletions: 0 },
1443
+ { path: 'src/ws/connection-manager.ts', additions: 45, deletions: 15 },
1444
+ { path: 'docker-compose.yml', additions: 18, deletions: 0 },
1445
+ ],
1446
+ turnTimeline: [],
1447
+ toolCalls: 34,
1448
+ },
1449
+ {
1450
+ id: 'demo-pb06-ff06',
1451
+ title: 'Build toolbar UI with tool selection and color picker',
1452
+ date: isoDate(3, 25, 14, 0),
1453
+ durationMinutes: 38,
1454
+ wallClockMinutes: 45,
1455
+ turns: 24,
1456
+ linesOfCode: 310,
1457
+ status: 'draft',
1458
+ projectName: '-Users-alex-Dev-pixelboard',
1459
+ source: 'cursor',
1460
+ cwd: '/Users/alex/Dev/pixelboard',
1461
+ rawLog: ['Drawing toolbar', 'Tool selection (pen, eraser, shapes)', 'Color picker with recent colors'],
1462
+ skills: ['TypeScript', 'Canvas API', 'CSS'],
1463
+ executionPath: [],
1464
+ toolBreakdown: [
1465
+ { tool: 'Edit', count: 10 },
1466
+ { tool: 'Read', count: 5 },
1467
+ { tool: 'Write', count: 3 },
1468
+ ],
1469
+ filesChanged: [
1470
+ { path: 'src/client/toolbar.ts', additions: 145, deletions: 0 },
1471
+ { path: 'src/client/color-picker.ts', additions: 85, deletions: 0 },
1472
+ { path: 'src/client/styles.css', additions: 65, deletions: 0 },
1473
+ ],
1474
+ turnTimeline: [],
1475
+ toolCalls: 18,
1476
+ },
1477
+ ];
1478
+ // ── All sessions ─────────────────────────────────────────────
1479
+ export const DEMO_SESSIONS = [
1480
+ ...budgetwiseSessions,
1481
+ ...shellhookSessions,
1482
+ ...pixelboardSessions,
1483
+ ];
1484
+ // ── Search results ───────────────────────────────────────────
1485
+ export const DEMO_SEARCH_RESULTS = [
1486
+ {
1487
+ sessionId: 'demo-a1b2-c3d4',
1488
+ title: 'Set up Prisma schema with User, Account, and Transaction models',
1489
+ projectDir: '-Users-alex-Dev-budgetwise',
1490
+ projectName: 'budgetwise',
1491
+ source: 'claude',
1492
+ date: isoDate(2, 3, 9, 15),
1493
+ durationMinutes: 72,
1494
+ turns: 45,
1495
+ linesOfCode: 680,
1496
+ skills: ['TypeScript', 'Prisma', 'PostgreSQL'],
1497
+ snippet: 'Created User model with email/password, Account with balance tracking, and <mark>Transaction</mark> with discriminated union for type safety',
1498
+ score: 0.95,
1499
+ },
1500
+ {
1501
+ sessionId: 'demo-i9j0-k1l2',
1502
+ title: 'Implement recurring transaction detection algorithm',
1503
+ projectDir: '-Users-alex-Dev-budgetwise',
1504
+ projectName: 'budgetwise',
1505
+ source: 'claude',
1506
+ date: isoDate(2, 7, 10, 30),
1507
+ durationMinutes: 88,
1508
+ turns: 62,
1509
+ linesOfCode: 890,
1510
+ skills: ['TypeScript', 'PostgreSQL', 'Algorithm design'],
1511
+ snippet: 'Grouped transactions by normalized merchant + amount, detected <mark>recurring</mark> patterns with tolerance windows',
1512
+ score: 0.91,
1513
+ },
1514
+ {
1515
+ sessionId: 'demo-sh03-cc03',
1516
+ title: 'Build git hook installer that symlinks to shellhook runner',
1517
+ projectDir: '-Users-alex-Dev-shellhook',
1518
+ projectName: 'shellhook',
1519
+ source: 'claude',
1520
+ date: isoDate(1, 20, 10, 30),
1521
+ durationMinutes: 72,
1522
+ turns: 48,
1523
+ linesOfCode: 580,
1524
+ skills: ['Rust', 'Git internals', 'Shell scripting'],
1525
+ snippet: 'Symlink-based <mark>hook installation</mark> with backup of existing hooks and cross-platform path handling',
1526
+ score: 0.88,
1527
+ },
1528
+ {
1529
+ sessionId: 'demo-pb03-cc03',
1530
+ title: 'Implement CRDT-based state sync for concurrent edits',
1531
+ projectDir: '-Users-alex-Dev-pixelboard',
1532
+ projectName: 'pixelboard',
1533
+ source: 'claude',
1534
+ date: isoDate(3, 19, 10, 0),
1535
+ durationMinutes: 85,
1536
+ turns: 58,
1537
+ linesOfCode: 720,
1538
+ skills: ['TypeScript', 'CRDT', 'WebSocket'],
1539
+ snippet: 'Vector clock for causal ordering, <mark>CRDT</mark> conflict resolution for overlapping strokes from concurrent users',
1540
+ score: 0.87,
1541
+ },
1542
+ {
1543
+ sessionId: 'demo-c9d0-e1f2',
1544
+ title: 'Build CSV import for bank statements',
1545
+ projectDir: '-Users-alex-Dev-budgetwise',
1546
+ projectName: 'budgetwise',
1547
+ source: 'claude',
1548
+ date: isoDate(2, 17, 9, 45),
1549
+ durationMinutes: 78,
1550
+ turns: 52,
1551
+ linesOfCode: 640,
1552
+ skills: ['TypeScript', 'React', 'Next.js'],
1553
+ snippet: 'Column mapping UI for <mark>CSV import</mark>, duplicate detection on transaction hash',
1554
+ score: 0.84,
1555
+ },
1556
+ {
1557
+ sessionId: 'demo-pb04-dd04',
1558
+ title: 'Fix WebSocket reconnection race condition',
1559
+ projectDir: '-Users-alex-Dev-pixelboard',
1560
+ projectName: 'pixelboard',
1561
+ source: 'claude',
1562
+ date: isoDate(3, 21, 16, 0),
1563
+ durationMinutes: 25,
1564
+ turns: 16,
1565
+ linesOfCode: 120,
1566
+ skills: ['TypeScript', 'WebSocket'],
1567
+ snippet: 'Race condition when <mark>reconnecting</mark> while old connection still in CLOSING state — added state machine',
1568
+ score: 0.82,
1569
+ },
1570
+ {
1571
+ sessionId: 'demo-m3n4-o5p6',
1572
+ title: 'Add Stripe integration for premium features',
1573
+ projectDir: '-Users-alex-Dev-budgetwise',
1574
+ projectName: 'budgetwise',
1575
+ source: 'claude',
1576
+ date: isoDate(2, 10, 9, 0),
1577
+ durationMinutes: 55,
1578
+ turns: 35,
1579
+ linesOfCode: 420,
1580
+ skills: ['TypeScript', 'Stripe API', 'Next.js'],
1581
+ snippet: 'Checkout session creation, <mark>webhook</mark> handler for payment events, premium feature gating middleware',
1582
+ score: 0.79,
1583
+ },
1584
+ {
1585
+ sessionId: 'demo-sh06-ff06',
1586
+ title: 'Implement hook ordering with dependency resolution',
1587
+ projectDir: '-Users-alex-Dev-shellhook',
1588
+ projectName: 'shellhook',
1589
+ source: 'claude',
1590
+ date: isoDate(1, 28, 11, 0),
1591
+ durationMinutes: 55,
1592
+ turns: 36,
1593
+ linesOfCode: 420,
1594
+ skills: ['Rust', 'Algorithm design'],
1595
+ snippet: 'Topological sort for <mark>hook dependencies</mark>, cycle detection, parallel execution for independent hooks',
1596
+ score: 0.76,
1597
+ },
1598
+ {
1599
+ sessionId: 'demo-k9l0-m1n2',
1600
+ title: 'Add two-factor authentication with TOTP',
1601
+ projectDir: '-Users-alex-Dev-budgetwise',
1602
+ projectName: 'budgetwise',
1603
+ source: 'claude',
1604
+ date: isoDate(3, 16, 9, 0),
1605
+ durationMinutes: 68,
1606
+ turns: 44,
1607
+ linesOfCode: 560,
1608
+ skills: ['TypeScript', 'Next.js', 'Security'],
1609
+ snippet: 'TOTP-based <mark>2FA</mark> with QR code generation, backup codes, and recovery flow',
1610
+ score: 0.73,
1611
+ },
1612
+ {
1613
+ sessionId: 'demo-sh02-bb02',
1614
+ title: 'Implement TOML config parser for hook definitions',
1615
+ projectDir: '-Users-alex-Dev-shellhook',
1616
+ projectName: 'shellhook',
1617
+ source: 'claude',
1618
+ date: isoDate(1, 17, 14, 0),
1619
+ durationMinutes: 58,
1620
+ turns: 38,
1621
+ linesOfCode: 510,
1622
+ skills: ['Rust', 'TOML parsing'],
1623
+ snippet: 'Serde deserialization of <mark>TOML config</mark> with validation, typed hook definitions, test fixtures',
1624
+ score: 0.70,
1625
+ },
1626
+ ];
1627
+ // ── Transcript ───────────────────────────────────────────────
1628
+ export const DEMO_TRANSCRIPT = {
1629
+ messages: [
1630
+ {
1631
+ id: 'msg-001',
1632
+ timestamp: isoDate(2, 3, 9, 15),
1633
+ role: 'user',
1634
+ blocks: [
1635
+ {
1636
+ type: 'text',
1637
+ text: 'Set up a Prisma schema for a personal finance app. I need User, Account, and Transaction models. Transactions should support different types — income, expense, and transfer. Use a discriminated union pattern, not single-table inheritance.',
1638
+ },
1639
+ ],
1640
+ },
1641
+ {
1642
+ id: 'msg-002',
1643
+ timestamp: isoDate(2, 3, 9, 16),
1644
+ role: 'assistant',
1645
+ model: 'claude-opus-4-0-20250514',
1646
+ blocks: [
1647
+ {
1648
+ type: 'thinking',
1649
+ text: 'The user wants a Prisma schema with three models. They specifically want a discriminated union for transaction types, which means separate models for each type with a shared interface. Let me check if there is an existing schema file first.',
1650
+ },
1651
+ {
1652
+ type: 'tool_call',
1653
+ toolCallId: 'tc-001',
1654
+ toolName: 'Read',
1655
+ input: 'prisma/schema.prisma',
1656
+ output: 'File not found: prisma/schema.prisma',
1657
+ },
1658
+ {
1659
+ type: 'tool_call',
1660
+ toolCallId: 'tc-002',
1661
+ toolName: 'Bash',
1662
+ input: 'npx prisma init --datasource-provider postgresql',
1663
+ output: '✔ Your Prisma schema was created at prisma/schema.prisma\n✔ .env file created',
1664
+ },
1665
+ {
1666
+ type: 'text',
1667
+ text: 'Initialized Prisma with PostgreSQL. Now I will write the schema with the three models. For the discriminated union, I will use an enum `TransactionType` with a `type` field on the Transaction model, plus optional relation fields that are only populated for specific types.',
1668
+ },
1669
+ ],
1670
+ },
1671
+ {
1672
+ id: 'msg-003',
1673
+ timestamp: isoDate(2, 3, 9, 20),
1674
+ role: 'assistant',
1675
+ model: 'claude-opus-4-0-20250514',
1676
+ blocks: [
1677
+ {
1678
+ type: 'tool_call',
1679
+ toolCallId: 'tc-003',
1680
+ toolName: 'Edit',
1681
+ input: 'prisma/schema.prisma',
1682
+ output: 'File updated: prisma/schema.prisma (+142 lines)',
1683
+ },
1684
+ {
1685
+ type: 'text',
1686
+ text: 'Here is the schema. Key design decisions:\n\n1. `TransactionType` enum with INCOME, EXPENSE, and TRANSFER variants\n2. Transfer-specific fields (`transferToAccountId`, `transferToAccount`) are nullable — only populated when type is TRANSFER\n3. `Account.balance` is a computed field derived from transactions, not stored directly\n4. Composite index on `(accountId, createdAt)` for the transaction list query\n5. Unique constraint on `User.email`\n\nThe balance reconciliation will be a separate concern — for now the schema supports it by making all transactions immutable (no update, only create and soft-delete via a `deletedAt` field).',
1687
+ },
1688
+ ],
1689
+ },
1690
+ {
1691
+ id: 'msg-004',
1692
+ timestamp: isoDate(2, 3, 9, 25),
1693
+ role: 'user',
1694
+ blocks: [
1695
+ {
1696
+ type: 'text',
1697
+ text: 'Looks good but drop the soft delete. Use hard deletes with an audit log table instead. Also add a `recurringSchedule` field for transactions that repeat — nullable, only for recurring ones.',
1698
+ },
1699
+ ],
1700
+ },
1701
+ {
1702
+ id: 'msg-005',
1703
+ timestamp: isoDate(2, 3, 9, 27),
1704
+ role: 'assistant',
1705
+ model: 'claude-opus-4-0-20250514',
1706
+ blocks: [
1707
+ {
1708
+ type: 'text',
1709
+ text: 'Good call on the audit log — soft deletes would complicate every query. I will add a `TransactionAuditLog` table and a `recurringSchedule` JSON field.',
1710
+ },
1711
+ {
1712
+ type: 'tool_call',
1713
+ toolCallId: 'tc-004',
1714
+ toolName: 'Edit',
1715
+ input: 'prisma/schema.prisma',
1716
+ output: 'File updated: prisma/schema.prisma (+28 -12 lines)',
1717
+ },
1718
+ ],
1719
+ },
1720
+ {
1721
+ id: 'msg-006',
1722
+ timestamp: isoDate(2, 3, 9, 35),
1723
+ role: 'user',
1724
+ blocks: [
1725
+ {
1726
+ type: 'text',
1727
+ text: 'Run the migration and create a seed script with some test data.',
1728
+ },
1729
+ ],
1730
+ },
1731
+ {
1732
+ id: 'msg-007',
1733
+ timestamp: isoDate(2, 3, 9, 37),
1734
+ role: 'assistant',
1735
+ model: 'claude-opus-4-0-20250514',
1736
+ blocks: [
1737
+ {
1738
+ type: 'tool_call',
1739
+ toolCallId: 'tc-005',
1740
+ toolName: 'Bash',
1741
+ input: 'npx prisma migrate dev --name init',
1742
+ output: 'Applying migration `20260203091500_init`\n\nThe following migration has been created and applied:\nmigrations/20260203091500_init/migration.sql\n\nYour database is now in sync with your schema.',
1743
+ },
1744
+ {
1745
+ type: 'tool_call',
1746
+ toolCallId: 'tc-006',
1747
+ toolName: 'Edit',
1748
+ input: 'prisma/seed.ts',
1749
+ output: 'File created: prisma/seed.ts (+89 lines)',
1750
+ },
1751
+ {
1752
+ type: 'tool_call',
1753
+ toolCallId: 'tc-007',
1754
+ toolName: 'Bash',
1755
+ input: 'npx tsx prisma/seed.ts',
1756
+ output: 'Seeded: 2 users, 4 accounts, 47 transactions',
1757
+ },
1758
+ {
1759
+ type: 'text',
1760
+ text: 'Migration applied and seed data created. The seed script creates two users, each with checking and savings accounts, and a mix of income, expense, and transfer transactions spanning the last 3 months.',
1761
+ },
1762
+ ],
1763
+ },
1764
+ {
1765
+ id: 'msg-008',
1766
+ timestamp: isoDate(2, 3, 9, 45),
1767
+ role: 'user',
1768
+ blocks: [
1769
+ {
1770
+ type: 'text',
1771
+ text: 'Now set up the Prisma client singleton so we can use it across the app.',
1772
+ },
1773
+ ],
1774
+ },
1775
+ {
1776
+ id: 'msg-009',
1777
+ timestamp: isoDate(2, 3, 9, 47),
1778
+ role: 'assistant',
1779
+ model: 'claude-opus-4-0-20250514',
1780
+ blocks: [
1781
+ {
1782
+ type: 'tool_call',
1783
+ toolCallId: 'tc-008',
1784
+ toolName: 'Grep',
1785
+ input: 'PrismaClient',
1786
+ output: 'prisma/seed.ts:1: import { PrismaClient } from \'@prisma/client\'',
1787
+ },
1788
+ {
1789
+ type: 'tool_call',
1790
+ toolCallId: 'tc-009',
1791
+ toolName: 'Edit',
1792
+ input: 'src/lib/db.ts',
1793
+ output: 'File created: src/lib/db.ts (+34 lines)',
1794
+ },
1795
+ {
1796
+ type: 'text',
1797
+ text: 'Created the client singleton at `src/lib/db.ts`. It reuses the client in development (attached to `globalThis` to survive hot reloads) and creates a fresh instance in production. The client is typed and exported as `prisma`.',
1798
+ },
1799
+ ],
1800
+ },
1801
+ ],
1802
+ meta: {
1803
+ totalMessages: 9,
1804
+ totalTokens: { input: 12480, output: 8920 },
1805
+ models: ['claude-opus-4-0-20250514'],
1806
+ duration: { activeMinutes: 72, wallClockMinutes: 87 },
1807
+ },
1808
+ };
1809
+ // ── Dashboard ────────────────────────────────────────────────
1810
+ function computeProjectStats(sessions, proj) {
1811
+ const projSessions = sessions.filter((s) => s.projectName === proj.dirName);
1812
+ const totalLoc = projSessions.reduce((sum, s) => sum + s.linesOfCode, 0);
1813
+ const totalDuration = projSessions.reduce((sum, s) => sum + s.durationMinutes, 0);
1814
+ const totalTurns = projSessions.reduce((sum, s) => sum + s.turns, 0);
1815
+ const latestDate = projSessions
1816
+ .map((s) => s.date)
1817
+ .sort()
1818
+ .pop() ?? '';
1819
+ const enhancedCount = projSessions.filter((s) => s.status === 'enhanced').length;
1820
+ return {
1821
+ projectDir: proj.dirName,
1822
+ projectName: proj.name,
1823
+ sessionCount: projSessions.length,
1824
+ totalLoc,
1825
+ totalDuration,
1826
+ totalTurns,
1827
+ skills: [...proj.skills],
1828
+ latestDate,
1829
+ enhancedAt: enhancedCount > 0 ? isoDate(3, 28, 12, 0) : null,
1830
+ };
1831
+ }
1832
+ export const DEMO_DASHBOARD = {
1833
+ stats: {
1834
+ sessionCount: DEMO_SESSIONS.length,
1835
+ projectCount: 3,
1836
+ sourceCount: 3,
1837
+ enhancedCount: 3,
1838
+ },
1839
+ projects: [
1840
+ computeProjectStats(DEMO_SESSIONS, DEMO_PROJECTS.budgetwise),
1841
+ computeProjectStats(DEMO_SESSIONS, DEMO_PROJECTS.shellhook),
1842
+ computeProjectStats(DEMO_SESSIONS, DEMO_PROJECTS.pixelboard),
1843
+ ],
1844
+ sync: { status: 'done', phase: 'done', current: DEMO_SESSIONS.length, total: DEMO_SESSIONS.length },
1845
+ isEmpty: false,
1846
+ onboardingComplete: true,
1847
+ };
1848
+ // ── Enhance result ───────────────────────────────────────────
1849
+ export const DEMO_ENHANCE_RESULT = {
1850
+ narrative: `Started with a basic Prisma schema but realized halfway through that I needed polymorphic transaction types. The AI kept suggesting single-table inheritance but I pushed back — went with a discriminated union pattern instead. Nullable fields for transfer-specific data, hard deletes with an audit log.
1851
+
1852
+ The recurring transaction detection was the hardest part. Had to figure out the right tolerance windows — monthly transactions drift by a few days, weekly ones are more precise. Settled on three consecutive interval matches before marking something as recurring. The partial index on merchant_normalized brought the detection query from 2 seconds to 120ms on 10k transactions.
1853
+
1854
+ Plaid integration went smoother than expected. The token exchange flow is straightforward, but the webhook handling needed careful idempotency — Plaid sends duplicate webhooks, so I used a processed-events table keyed on webhook ID. The CSV import was the fallback path for banks Plaid doesn't support.
1855
+
1856
+ Biggest lesson: I spent too long on the dashboard charts before the core transaction logic was solid. Should have built the spending insights and budget alerts first — those drove most of the schema changes that rippled through the whole codebase.`,
1857
+ arc: [
1858
+ { phase: 1, title: 'Foundation', description: 'Schema design, Prisma setup, and core transaction CRUD. Established the discriminated union pattern for transaction types.' },
1859
+ { phase: 2, title: 'Data pipeline', description: 'CSV import, Plaid integration, and recurring detection. Focused on getting real data flowing through the system.' },
1860
+ { phase: 3, title: 'Intelligence layer', description: 'Budget categories, spending insights, and anomaly detection. The analysis features that make the data useful.' },
1861
+ { phase: 4, title: 'Polish', description: 'Multi-currency, 2FA, performance optimization, dark mode. Hardening for real-world use.' },
1862
+ ],
1863
+ skills: ['TypeScript', 'React', 'Next.js', 'Prisma', 'PostgreSQL', 'Tailwind CSS', 'Stripe API', 'Plaid API', 'Chart.js', 'Playwright'],
1864
+ timeline: [
1865
+ {
1866
+ period: 'Feb 3 – Feb 14',
1867
+ label: 'Foundation',
1868
+ sessions: [
1869
+ { sessionId: 'demo-a1b2-c3d4', title: 'Set up Prisma schema with User, Account, and Transaction models', featured: true, tag: 'schema' },
1870
+ { sessionId: 'demo-e5f6-g7h8', title: 'Build transaction list page with infinite scroll', featured: true, tag: 'frontend' },
1871
+ { sessionId: 'demo-i9j0-k1l2', title: 'Implement recurring transaction detection algorithm', featured: true, tag: 'algorithm' },
1872
+ { sessionId: 'demo-m3n4-o5p6', title: 'Add Stripe integration for premium features', featured: false },
1873
+ { sessionId: 'demo-q7r8-s9t0', title: 'Design dashboard layout with spending charts', featured: false },
1874
+ { sessionId: 'demo-u1v2-w3x4', title: 'Fix currency formatting edge cases in locale-aware display', featured: false },
1875
+ { sessionId: 'demo-y5z6-a7b8', title: 'Add account balance reconciliation checks', featured: false },
1876
+ ],
1877
+ },
1878
+ {
1879
+ period: 'Feb 17 – Feb 26',
1880
+ label: 'Data pipeline',
1881
+ sessions: [
1882
+ { sessionId: 'demo-c9d0-e1f2', title: 'Build CSV import for bank statements', featured: true, tag: 'import' },
1883
+ { sessionId: 'demo-g3h4-i5j6', title: 'Implement budget categories with monthly limits', featured: true, tag: 'budgets' },
1884
+ { sessionId: 'demo-k7l8-m9n0', title: 'Add email notifications for budget overspend', featured: false },
1885
+ { sessionId: 'demo-o1p2-q3r4', title: 'Write E2E tests for transaction CRUD flow', featured: false },
1886
+ { sessionId: 'demo-s5t6-u7v8', title: 'Optimize transaction queries with composite indexes', featured: false },
1887
+ { sessionId: 'demo-w9x0-y1z2', title: 'Add dark mode with system preference detection', featured: false },
1888
+ { sessionId: 'demo-a3b4-c5d6', title: 'Build account settings page with profile editing', featured: false },
1889
+ ],
1890
+ },
1891
+ {
1892
+ period: 'Mar 1 – Mar 14',
1893
+ label: 'Intelligence + integrations',
1894
+ sessions: [
1895
+ { sessionId: 'demo-e7f8-g9h0', title: 'Implement transaction search with full-text index', featured: false },
1896
+ { sessionId: 'demo-i1j2-k3l4', title: 'Add plaid integration for bank account linking', featured: true, tag: 'integration' },
1897
+ { sessionId: 'demo-m5n6-o7p8', title: 'Fix timezone bug in monthly spending aggregation', featured: false },
1898
+ { sessionId: 'demo-q9r0-s1t2', title: 'Add transaction tagging and custom categories', featured: false },
1899
+ { sessionId: 'demo-u3v4-w5x6', title: 'Build spending insights with trend analysis', featured: true, tag: 'insights' },
1900
+ { sessionId: 'demo-y7z8-a9b0', title: 'Add data export with PDF report generation', featured: false },
1901
+ { sessionId: 'demo-c1d2-e3f4', title: 'Implement multi-currency support with exchange rates', featured: true, tag: 'currency' },
1902
+ { sessionId: 'demo-g5h6-i7j8', title: 'Fix N+1 query in account list with transaction counts', featured: false },
1903
+ ],
1904
+ },
1905
+ {
1906
+ period: 'Mar 16 – Mar 26',
1907
+ label: 'Hardening',
1908
+ sessions: [
1909
+ { sessionId: 'demo-k9l0-m1n2', title: 'Add two-factor authentication with TOTP', featured: true, tag: 'security' },
1910
+ { sessionId: 'demo-o3p4-q5r6', title: 'Refactor API routes to use middleware pattern', featured: false },
1911
+ { sessionId: 'demo-s7t8-u9v0', title: 'Add mobile-responsive layout with bottom navigation', featured: false },
1912
+ { sessionId: 'demo-w1x2-y3z4', title: 'Set up CI pipeline with GitHub Actions', featured: false },
1913
+ { sessionId: 'demo-a5b6-c7d8', title: 'Write API documentation with OpenAPI spec', featured: false },
1914
+ { sessionId: 'demo-e9f0-g1h2', title: 'Performance audit and bundle size optimization', featured: false },
1915
+ ],
1916
+ },
1917
+ ],
1918
+ questions: [
1919
+ { id: 'q-001', category: 'architecture', question: 'Why a discriminated union over Prisma\'s built-in polymorphic relations?', context: 'The schema uses nullable transfer-specific fields with a type enum rather than separate tables per transaction type.' },
1920
+ { id: 'q-002', category: 'pattern', question: 'How does the recurring detection handle irregular intervals like "every other Friday"?', context: 'The algorithm uses tolerance windows for matching, but biweekly patterns on specific weekdays may need special handling.' },
1921
+ { id: 'q-003', category: 'evolution', question: 'What drove the decision to add Plaid after building CSV import?', context: 'CSV import was built first (Feb 17), Plaid integration came later (Mar 3). Was CSV a deliberate fallback or did Plaid scope grow?' },
1922
+ { id: 'q-004', category: 'architecture', question: 'How do you handle the balance consistency problem between computed and cached values?', context: 'Account balances are derived from transactions, but caching them introduces potential drift.' },
1923
+ { id: 'q-005', category: 'pattern', question: 'What is the retry strategy for failed Plaid webhook processing?', context: 'The processed-events table handles deduplication, but what happens when webhook processing fails midway?' },
1924
+ ],
1925
+ };
1926
+ // ── Source audit ──────────────────────────────────────────────
1927
+ export const DEMO_SOURCE_AUDIT = {
1928
+ sources: [
1929
+ {
1930
+ name: 'Claude Code',
1931
+ path: '~/.claude/projects',
1932
+ dateRange: 'Jan 15 \u2013 Mar 28, 2026',
1933
+ liveCount: 38,
1934
+ archivedCount: 12,
1935
+ health: 'healthy',
1936
+ },
1937
+ {
1938
+ name: 'Cursor',
1939
+ path: '~/.cursor/sessions',
1940
+ dateRange: 'Feb 1 \u2013 Mar 20, 2026',
1941
+ liveCount: 8,
1942
+ archivedCount: 0,
1943
+ health: 'healthy',
1944
+ },
1945
+ ],
1946
+ };
1947
+ //# sourceMappingURL=demo-data.js.map