ai-wrapped 0.0.1
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.
- package/.0spec/config.toml +50 -0
- package/.0spec/flows/ai-stats-build.toml +291 -0
- package/.0spec/flows/ai-stats-fix.toml +285 -0
- package/.0spec/flows/ai-stats.toml +400 -0
- package/.github/workflows/publish.yml +28 -0
- package/CLAUDE.md +111 -0
- package/README.md +64 -0
- package/bun.lock +635 -0
- package/electrobun.config.ts +25 -0
- package/package.json +36 -0
- package/public/tray-icon.png +0 -0
- package/src/bun/aggregator.test.ts +49 -0
- package/src/bun/aggregator.ts +130 -0
- package/src/bun/discovery/claude.ts +18 -0
- package/src/bun/discovery/codex.ts +20 -0
- package/src/bun/discovery/copilot.ts +13 -0
- package/src/bun/discovery/droid.ts +13 -0
- package/src/bun/discovery/gemini.ts +13 -0
- package/src/bun/discovery/index.ts +28 -0
- package/src/bun/discovery/opencode.ts +13 -0
- package/src/bun/discovery/types.ts +13 -0
- package/src/bun/discovery/utils.ts +48 -0
- package/src/bun/index.ts +722 -0
- package/src/bun/normalizer.test.ts +101 -0
- package/src/bun/normalizer.ts +454 -0
- package/src/bun/parsers/claude.ts +234 -0
- package/src/bun/parsers/codex.test.ts +180 -0
- package/src/bun/parsers/codex.ts +435 -0
- package/src/bun/parsers/copilot.ts +4 -0
- package/src/bun/parsers/droid.ts +4 -0
- package/src/bun/parsers/gemini.ts +4 -0
- package/src/bun/parsers/generic.test.ts +97 -0
- package/src/bun/parsers/generic.ts +260 -0
- package/src/bun/parsers/index.ts +37 -0
- package/src/bun/parsers/opencode.ts +4 -0
- package/src/bun/parsers/types.ts +23 -0
- package/src/bun/pricing.ts +52 -0
- package/src/bun/scan.ts +77 -0
- package/src/bun/session-schema.ts +1 -0
- package/src/bun/store.ts +283 -0
- package/src/mainview/App.tsx +42 -0
- package/src/mainview/components/AgentBadge.tsx +17 -0
- package/src/mainview/components/Dashboard.tsx +229 -0
- package/src/mainview/components/DashboardCharts.tsx +499 -0
- package/src/mainview/components/EmptyState.tsx +17 -0
- package/src/mainview/components/Sidebar.tsx +30 -0
- package/src/mainview/components/StatsCards.tsx +118 -0
- package/src/mainview/hooks/useDashboardData.ts +315 -0
- package/src/mainview/hooks/useRPC.ts +29 -0
- package/src/mainview/index.css +195 -0
- package/src/mainview/index.html +12 -0
- package/src/mainview/index.ts +12 -0
- package/src/mainview/lib/constants.ts +32 -0
- package/src/mainview/lib/formatters.ts +82 -0
- package/src/shared/constants.ts +1 -0
- package/src/shared/schema.ts +71 -0
- package/src/shared/session-types.ts +61 -0
- package/src/shared/types.ts +59 -0
- package/src/types/electrobun-bun.d.ts +117 -0
- package/src/types/electrobun-root.d.ts +3 -0
- package/src/types/electrobun-view.d.ts +38 -0
- package/tsconfig.json +18 -0
- package/tsconfig.typecheck.json +11 -0
- package/vite.config.ts +23 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# ai-stats — AI analytics dashboard desktop app (Electrobun)
|
|
2
|
+
|
|
3
|
+
[settings]
|
|
4
|
+
default_team = "global"
|
|
5
|
+
default_model = "claude-opus-4-6"
|
|
6
|
+
bypass_permissions = true
|
|
7
|
+
fail_fast = true
|
|
8
|
+
retries = 1
|
|
9
|
+
|
|
10
|
+
[settings.doctor]
|
|
11
|
+
enabled = true
|
|
12
|
+
agent = "doctor"
|
|
13
|
+
|
|
14
|
+
# ─── Teams ──────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
[teams.global]
|
|
17
|
+
description = "Single agent — general tasks"
|
|
18
|
+
agents = ["claude-agent"]
|
|
19
|
+
|
|
20
|
+
[teams.research]
|
|
21
|
+
description = "Research & analysis"
|
|
22
|
+
agents = ["planner-claude"]
|
|
23
|
+
rules = "Analyze documentation, produce structured reference material. No code changes."
|
|
24
|
+
|
|
25
|
+
[teams.planners]
|
|
26
|
+
description = "Architecture & planning"
|
|
27
|
+
agents = ["planner-claude"]
|
|
28
|
+
rules = "Design architecture, produce implementation specs. No implementation."
|
|
29
|
+
|
|
30
|
+
[teams.implementors]
|
|
31
|
+
description = "Implementation team"
|
|
32
|
+
agents = ["coder-codex"]
|
|
33
|
+
|
|
34
|
+
[teams.reviewers]
|
|
35
|
+
description = "QA & review"
|
|
36
|
+
agents = ["reviewer-codex"]
|
|
37
|
+
rules = "Review code, run tests, verify builds. Output structured QA verdicts."
|
|
38
|
+
|
|
39
|
+
# ─── Agents ─────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
[agents.claude-agent]
|
|
42
|
+
engine = "claude"
|
|
43
|
+
model = "claude-opus-4-6"
|
|
44
|
+
timeout = 600
|
|
45
|
+
|
|
46
|
+
[agents.doctor]
|
|
47
|
+
engine = "claude"
|
|
48
|
+
model = "haiku"
|
|
49
|
+
timeout = 30
|
|
50
|
+
max_turns = 3
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
[flow]
|
|
2
|
+
name = "ai-stats-build"
|
|
3
|
+
description = "Build ai-stats from existing architecture spec — scaffold through commit"
|
|
4
|
+
|
|
5
|
+
# NOTE: ARCHITECTURE.md (1462 lines), SESSION_FORMATS.md, and AGENT_SESSIONS_REFERENCE.md
|
|
6
|
+
# are pre-seeded in the project root from prior research/planning runs.
|
|
7
|
+
# No consolidation stage needed — ARCHITECTURE.md is the authoritative spec.
|
|
8
|
+
|
|
9
|
+
# ─── Phase 1: Scaffold ─────────────────────────────────
|
|
10
|
+
|
|
11
|
+
[[stages]]
|
|
12
|
+
id = "scaffold"
|
|
13
|
+
name = "Project Scaffold"
|
|
14
|
+
type = "seq"
|
|
15
|
+
team = "implementors"
|
|
16
|
+
prompt = """
|
|
17
|
+
Read ARCHITECTURE.md in the project root — it is the authoritative spec.
|
|
18
|
+
|
|
19
|
+
Create the project scaffold as specified in Section 1 (Project Structure) and Section 9 (Build & Dev Workflow).
|
|
20
|
+
|
|
21
|
+
Constraints:
|
|
22
|
+
- Use Electrobun react-tailwind-vite pattern (Vite builds to dist/, copy config maps to views/)
|
|
23
|
+
- Remove "type": "module" and "module" from package.json if present
|
|
24
|
+
- SQLite via bun:sqlite (built into Bun, no extra deps)
|
|
25
|
+
- Tailwind v4 via @tailwindcss/vite plugin
|
|
26
|
+
- Use concurrently for dev:hmr script
|
|
27
|
+
|
|
28
|
+
Only skeleton — stub files with empty exports/components. No business logic.
|
|
29
|
+
|
|
30
|
+
Verify:
|
|
31
|
+
- `bun install` succeeds
|
|
32
|
+
- Vite build compiles without errors
|
|
33
|
+
- Main process file parses without errors
|
|
34
|
+
"""
|
|
35
|
+
output = { format = "markdown", name = "scaffold.md" }
|
|
36
|
+
|
|
37
|
+
[[stages]]
|
|
38
|
+
id = "qa-scaffold"
|
|
39
|
+
name = "QA Scaffold"
|
|
40
|
+
type = "seq"
|
|
41
|
+
team = "reviewers"
|
|
42
|
+
depends_on = ["scaffold"]
|
|
43
|
+
input_from = ["scaffold"]
|
|
44
|
+
prompt = """
|
|
45
|
+
Read ARCHITECTURE.md for the expected project structure.
|
|
46
|
+
|
|
47
|
+
Verify the scaffold:
|
|
48
|
+
1. `bun install` succeeds
|
|
49
|
+
2. Vite build compiles without errors
|
|
50
|
+
3. All files from Section 1 of ARCHITECTURE.md exist (check file tree)
|
|
51
|
+
4. package.json has correct scripts (dev, dev:hmr, build)
|
|
52
|
+
5. electrobun.config.ts is valid
|
|
53
|
+
6. No "type": "module" in package.json
|
|
54
|
+
|
|
55
|
+
Output JSON: { "verdict": "pass" or "fail", "issues": [...] }
|
|
56
|
+
"""
|
|
57
|
+
output = { format = "json", name = "qa-scaffold.json" }
|
|
58
|
+
|
|
59
|
+
[[stages]]
|
|
60
|
+
id = "fix-scaffold"
|
|
61
|
+
name = "Fix Scaffold Issues"
|
|
62
|
+
type = "loop"
|
|
63
|
+
team = "implementors"
|
|
64
|
+
depends_on = ["qa-scaffold"]
|
|
65
|
+
input_from = ["qa-scaffold"]
|
|
66
|
+
prompt = "Fix all issues from QA report."
|
|
67
|
+
max_loops = 2
|
|
68
|
+
loop_to = "qa-scaffold"
|
|
69
|
+
condition = "qa-scaffold.verdict != 'pass'"
|
|
70
|
+
output = { format = "diff", name = "scaffold-fixes.diff" }
|
|
71
|
+
|
|
72
|
+
# ─── Phase 2: Parsers & Data Layer ─────────────────────
|
|
73
|
+
|
|
74
|
+
[[stages]]
|
|
75
|
+
id = "data-layer"
|
|
76
|
+
name = "Session Parsers + SQLite + RPC"
|
|
77
|
+
type = "seq"
|
|
78
|
+
team = "implementors"
|
|
79
|
+
depends_on = ["fix-scaffold"]
|
|
80
|
+
prompt = """
|
|
81
|
+
Read ARCHITECTURE.md (Sections 2-6) and SESSION_FORMATS.md in the project root. Implement:
|
|
82
|
+
|
|
83
|
+
1. Session discovery (src/bun/discovery/):
|
|
84
|
+
- Discover Claude Code sessions: ~/.claude/projects/*/*.jsonl
|
|
85
|
+
- Discover Codex CLI sessions: ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl
|
|
86
|
+
- Discover other agents if present (Gemini, Copilot, OpenCode)
|
|
87
|
+
- Return file paths with agent source type
|
|
88
|
+
|
|
89
|
+
2. JSONL parsers (src/bun/parsers/):
|
|
90
|
+
- Claude Code parser — handle nested message.content, uuid/parentUuid threading
|
|
91
|
+
- Codex CLI parser — handle top-level content, delta streaming chunks
|
|
92
|
+
- Generic parser fallback
|
|
93
|
+
- All parsers produce normalized SessionEvent[]
|
|
94
|
+
|
|
95
|
+
3. Normalizer (src/bun/normalizer.ts):
|
|
96
|
+
- Map raw event types to SessionEventKind (user, assistant, tool_call, tool_result, error, meta)
|
|
97
|
+
- Extract text from various content formats
|
|
98
|
+
- Handle timestamp format variations (ISO 8601, epoch seconds/ms)
|
|
99
|
+
|
|
100
|
+
4. SQLite database (src/bun/db.ts):
|
|
101
|
+
- Tables as specified in Section 3 of ARCHITECTURE.md
|
|
102
|
+
- Migration/init, upsert parsed sessions, query functions
|
|
103
|
+
|
|
104
|
+
5. RPC types (src/shared/types.ts) + wiring (src/bun/index.ts):
|
|
105
|
+
- As specified in Section 6 of ARCHITECTURE.md
|
|
106
|
+
|
|
107
|
+
Verify:
|
|
108
|
+
- TypeScript compiles without errors
|
|
109
|
+
- DB initializes and creates tables
|
|
110
|
+
- At least one real session file parses successfully
|
|
111
|
+
"""
|
|
112
|
+
output = { format = "markdown", name = "data-layer.md" }
|
|
113
|
+
|
|
114
|
+
[[stages]]
|
|
115
|
+
id = "qa-data"
|
|
116
|
+
name = "QA Data Layer"
|
|
117
|
+
type = "seq"
|
|
118
|
+
team = "reviewers"
|
|
119
|
+
depends_on = ["data-layer"]
|
|
120
|
+
input_from = ["data-layer"]
|
|
121
|
+
prompt = """
|
|
122
|
+
Read ARCHITECTURE.md for the expected schema and RPC surface.
|
|
123
|
+
|
|
124
|
+
Verify the data layer:
|
|
125
|
+
1. SQLite schema matches Section 3 of ARCHITECTURE.md
|
|
126
|
+
2. Session discovery finds real session files on this machine
|
|
127
|
+
3. At least one Claude Code and one Codex session parses without errors
|
|
128
|
+
4. Normalized events have correct kind, text, timestamps
|
|
129
|
+
5. RPC types are complete and type-safe
|
|
130
|
+
6. TypeScript compiles
|
|
131
|
+
|
|
132
|
+
Output JSON: { "verdict": "pass" or "fail", "issues": [...] }
|
|
133
|
+
"""
|
|
134
|
+
output = { format = "json", name = "qa-data.json" }
|
|
135
|
+
|
|
136
|
+
[[stages]]
|
|
137
|
+
id = "fix-data"
|
|
138
|
+
name = "Fix Data Layer Issues"
|
|
139
|
+
type = "loop"
|
|
140
|
+
team = "implementors"
|
|
141
|
+
depends_on = ["qa-data"]
|
|
142
|
+
input_from = ["qa-data"]
|
|
143
|
+
prompt = "Fix all issues from QA report."
|
|
144
|
+
max_loops = 2
|
|
145
|
+
loop_to = "qa-data"
|
|
146
|
+
condition = "qa-data.verdict != 'pass'"
|
|
147
|
+
output = { format = "diff", name = "data-fixes.diff" }
|
|
148
|
+
|
|
149
|
+
# ─── Phase 3: Dashboard UI ─────────────────────────────
|
|
150
|
+
|
|
151
|
+
[[stages]]
|
|
152
|
+
id = "dashboard-ui"
|
|
153
|
+
name = "Dashboard UI Components"
|
|
154
|
+
type = "seq"
|
|
155
|
+
team = "implementors"
|
|
156
|
+
depends_on = ["fix-data"]
|
|
157
|
+
prompt = """
|
|
158
|
+
Read ARCHITECTURE.md Section 7 (Component Tree). Implement the React dashboard UI:
|
|
159
|
+
|
|
160
|
+
1. App shell (App.tsx) — sidebar nav + main content area
|
|
161
|
+
2. Dashboard page — summary cards (total sessions, total events, tool calls today) + charts
|
|
162
|
+
3. Charts — session count over time (line), events by agent (bar), tool call frequency (bar), model usage (pie)
|
|
163
|
+
4. Session browser page — filterable list of all sessions, search by repo/agent/date
|
|
164
|
+
5. Session detail page — event timeline with kind icons, expandable tool call details
|
|
165
|
+
6. Settings page — configure watched directories, rescan interval
|
|
166
|
+
7. useRPC hook — typed wrapper around Electroview RPC calls
|
|
167
|
+
|
|
168
|
+
Use Tailwind v4 for all styling. Dark theme by default.
|
|
169
|
+
Use Recharts for charts.
|
|
170
|
+
|
|
171
|
+
Verify:
|
|
172
|
+
- Vite build compiles without errors
|
|
173
|
+
- All components render (no runtime crashes on import)
|
|
174
|
+
"""
|
|
175
|
+
output = { format = "markdown", name = "dashboard-ui.md" }
|
|
176
|
+
|
|
177
|
+
[[stages]]
|
|
178
|
+
id = "qa-ui"
|
|
179
|
+
name = "QA Dashboard UI"
|
|
180
|
+
type = "seq"
|
|
181
|
+
team = "reviewers"
|
|
182
|
+
depends_on = ["dashboard-ui"]
|
|
183
|
+
input_from = ["dashboard-ui"]
|
|
184
|
+
prompt = """
|
|
185
|
+
Read ARCHITECTURE.md Section 7 for expected components.
|
|
186
|
+
|
|
187
|
+
Verify the dashboard UI:
|
|
188
|
+
1. Vite build compiles without errors
|
|
189
|
+
2. All pages/components exist per spec
|
|
190
|
+
3. RPC hooks are properly typed
|
|
191
|
+
4. Tailwind classes are valid
|
|
192
|
+
5. Dark theme is consistent
|
|
193
|
+
6. No hardcoded data — all data comes through RPC
|
|
194
|
+
|
|
195
|
+
Output JSON: { "verdict": "pass" or "fail", "issues": [...] }
|
|
196
|
+
"""
|
|
197
|
+
output = { format = "json", name = "qa-ui.json" }
|
|
198
|
+
|
|
199
|
+
[[stages]]
|
|
200
|
+
id = "fix-ui"
|
|
201
|
+
name = "Fix UI Issues"
|
|
202
|
+
type = "loop"
|
|
203
|
+
team = "implementors"
|
|
204
|
+
depends_on = ["qa-ui"]
|
|
205
|
+
input_from = ["qa-ui"]
|
|
206
|
+
prompt = "Fix all issues from QA report."
|
|
207
|
+
max_loops = 2
|
|
208
|
+
loop_to = "qa-ui"
|
|
209
|
+
condition = "qa-ui.verdict != 'pass'"
|
|
210
|
+
output = { format = "diff", name = "ui-fixes.diff" }
|
|
211
|
+
|
|
212
|
+
# ─── Phase 4: Native Integration ───────────────────────
|
|
213
|
+
|
|
214
|
+
[[stages]]
|
|
215
|
+
id = "native"
|
|
216
|
+
name = "Tray, Menu & Window Polish"
|
|
217
|
+
type = "seq"
|
|
218
|
+
team = "implementors"
|
|
219
|
+
depends_on = ["fix-ui"]
|
|
220
|
+
prompt = """
|
|
221
|
+
Read ARCHITECTURE.md Section 11 (Main Process Behavior). Implement native desktop integration:
|
|
222
|
+
|
|
223
|
+
1. System tray:
|
|
224
|
+
- Show app icon in tray
|
|
225
|
+
- Tray menu: quick stats (today's sessions/events), "Show Dashboard", "Rescan Sessions", "Quit"
|
|
226
|
+
- Clicking tray icon shows/hides main window
|
|
227
|
+
|
|
228
|
+
2. Application menu:
|
|
229
|
+
- Standard Edit menu (undo, redo, cut, copy, paste, selectAll)
|
|
230
|
+
- File menu: "Rescan Sessions" action, "Quit"
|
|
231
|
+
- View menu: "Toggle Dark Mode"
|
|
232
|
+
|
|
233
|
+
3. Window behavior:
|
|
234
|
+
- Close button minimizes to tray (on macOS)
|
|
235
|
+
- Proper quit via menu or tray
|
|
236
|
+
|
|
237
|
+
Verify:
|
|
238
|
+
- Main process starts without errors
|
|
239
|
+
- Tray icon appears
|
|
240
|
+
- Menu items are functional
|
|
241
|
+
"""
|
|
242
|
+
output = { format = "markdown", name = "native.md" }
|
|
243
|
+
|
|
244
|
+
[[stages]]
|
|
245
|
+
id = "qa-native"
|
|
246
|
+
name = "QA Native Integration"
|
|
247
|
+
type = "seq"
|
|
248
|
+
team = "reviewers"
|
|
249
|
+
depends_on = ["native"]
|
|
250
|
+
input_from = ["native"]
|
|
251
|
+
prompt = """
|
|
252
|
+
Verify native integration:
|
|
253
|
+
1. Tray icon creates without errors
|
|
254
|
+
2. Application menu has all required items
|
|
255
|
+
3. Menu actions are wired to handlers
|
|
256
|
+
4. Window close behavior is correct
|
|
257
|
+
5. Main process starts and creates window + tray
|
|
258
|
+
|
|
259
|
+
Output JSON: { "verdict": "pass" or "fail", "issues": [...] }
|
|
260
|
+
"""
|
|
261
|
+
output = { format = "json", name = "qa-native.json" }
|
|
262
|
+
|
|
263
|
+
[[stages]]
|
|
264
|
+
id = "fix-native"
|
|
265
|
+
name = "Fix Native Issues"
|
|
266
|
+
type = "loop"
|
|
267
|
+
team = "implementors"
|
|
268
|
+
depends_on = ["qa-native"]
|
|
269
|
+
input_from = ["qa-native"]
|
|
270
|
+
prompt = "Fix all issues from QA report."
|
|
271
|
+
max_loops = 2
|
|
272
|
+
loop_to = "qa-native"
|
|
273
|
+
condition = "qa-native.verdict != 'pass'"
|
|
274
|
+
output = { format = "diff", name = "native-fixes.diff" }
|
|
275
|
+
|
|
276
|
+
# ─── Phase 5: Final ────────────────────────────────────
|
|
277
|
+
|
|
278
|
+
[[stages]]
|
|
279
|
+
id = "commit"
|
|
280
|
+
name = "Final Commit"
|
|
281
|
+
type = "seq"
|
|
282
|
+
team = "global"
|
|
283
|
+
depends_on = ["fix-native"]
|
|
284
|
+
prompt = """
|
|
285
|
+
Review git diff. Stage all new/modified files. Commit with descriptive message:
|
|
286
|
+
"feat: ai-stats — Electrobun desktop dashboard for AI agent session analytics"
|
|
287
|
+
|
|
288
|
+
Do NOT push.
|
|
289
|
+
"""
|
|
290
|
+
tools = ["Read", "Glob", "Grep", "Bash"]
|
|
291
|
+
output = { format = "markdown", name = "commit.md" }
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
[flow]
|
|
2
|
+
name = "ai-stats-fix"
|
|
3
|
+
description = "Fix ai-stats: remove SQLite, simplify to JSON store, Spotify Wrapped-style dashboard"
|
|
4
|
+
|
|
5
|
+
# ─── Phase 1: Rip out SQLite, replace with JSON file store ─────
|
|
6
|
+
|
|
7
|
+
[[stages]]
|
|
8
|
+
id = "json-store"
|
|
9
|
+
name = "Replace SQLite with JSON File Store"
|
|
10
|
+
type = "seq"
|
|
11
|
+
team = "implementors"
|
|
12
|
+
prompt = """
|
|
13
|
+
The app currently uses SQLite (bun:sqlite) for all data storage. This causes crashes
|
|
14
|
+
(UNIQUE constraint errors on events.id) and is overkill. Replace it entirely.
|
|
15
|
+
|
|
16
|
+
**What to do:**
|
|
17
|
+
|
|
18
|
+
1. Delete `src/bun/db.ts` entirely.
|
|
19
|
+
|
|
20
|
+
2. Create `src/bun/store.ts` — a simple JSON file store:
|
|
21
|
+
- Data dir: `~/.ai-stats/` (create with mkdirSync recursive)
|
|
22
|
+
- Files:
|
|
23
|
+
- `~/.ai-stats/scan-state.json` — record of parsed files: `Record<filePath, { source, fileSize, mtimeMs, parsedAt }>`
|
|
24
|
+
- `~/.ai-stats/daily.json` — daily aggregates: `Record<date, { bySource: Record<source, DayStats>, byModel: Record<model, DayStats>, totals: DayStats }>`
|
|
25
|
+
where DayStats = `{ sessions, messages, toolCalls, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, reasoningTokens, costUsd, durationMs }`
|
|
26
|
+
- `~/.ai-stats/settings.json` — app settings
|
|
27
|
+
- Read/write with Bun.file() / Bun.write() + JSON.parse/stringify
|
|
28
|
+
- No locking needed — single process app
|
|
29
|
+
- Load lazily on first access, cache in memory, flush on write
|
|
30
|
+
|
|
31
|
+
3. Update `src/bun/scan.ts`:
|
|
32
|
+
- Remove all DB imports
|
|
33
|
+
- Use the new store for scan state checks (skip already-parsed files by path+mtime+size)
|
|
34
|
+
- After parsing sessions, aggregate into daily.json instead of SQLite
|
|
35
|
+
- Do NOT store individual sessions or events — only aggregate stats per day
|
|
36
|
+
- Each scan: discover files → parse → compute daily aggregates → merge into daily.json
|
|
37
|
+
|
|
38
|
+
4. Update `src/bun/aggregator.ts`:
|
|
39
|
+
- Implement actual aggregation: take parsed sessions, group by date, accumulate stats
|
|
40
|
+
- Merge into existing daily.json (additive for new dates, replace for re-scanned dates)
|
|
41
|
+
|
|
42
|
+
5. Update `src/bun/index.ts` (main process):
|
|
43
|
+
- Remove `import { openDatabase } from "./db"` and all `db.` calls
|
|
44
|
+
- Import from `./store` instead
|
|
45
|
+
- Update RPC handlers to read from JSON store
|
|
46
|
+
|
|
47
|
+
6. Update `src/shared/types.ts` — simplify RPC:
|
|
48
|
+
- REMOVE these RPCs: getSessions, getSession, getSessionEvents, getDistinctModels, getDistinctRepos, getDbStats, vacuumDatabase
|
|
49
|
+
- KEEP these RPCs: getDashboardSummary, getDailyTimeline, triggerScan, getScanStatus, getTrayStats, getSettings, updateSettings
|
|
50
|
+
- getDashboardSummary reads from daily.json and computes totals
|
|
51
|
+
- getDailyTimeline reads date range from daily.json
|
|
52
|
+
|
|
53
|
+
7. Update `src/shared/schema.ts`:
|
|
54
|
+
- Remove `Session`, `SessionEvent`, `SessionFilters`, `ScanState` interfaces (no longer exposed to frontend)
|
|
55
|
+
- Keep `TokenUsage`, `DashboardSummary`, `DailyAggregate`, `TrayStats`, `SessionSource`
|
|
56
|
+
|
|
57
|
+
8. Remove `bun:sqlite` from any imports. Remove sqlite-related deps from package.json if any.
|
|
58
|
+
|
|
59
|
+
**Verify:**
|
|
60
|
+
- `bun install` succeeds
|
|
61
|
+
- Vite build compiles without errors
|
|
62
|
+
- No references to bun:sqlite remain
|
|
63
|
+
- No references to db.ts remain
|
|
64
|
+
"""
|
|
65
|
+
output = { format = "markdown", name = "json-store.md" }
|
|
66
|
+
|
|
67
|
+
[[stages]]
|
|
68
|
+
id = "qa-store"
|
|
69
|
+
name = "QA JSON Store"
|
|
70
|
+
type = "seq"
|
|
71
|
+
team = "reviewers"
|
|
72
|
+
depends_on = ["json-store"]
|
|
73
|
+
input_from = ["json-store"]
|
|
74
|
+
prompt = """
|
|
75
|
+
Verify the SQLite removal and JSON store replacement:
|
|
76
|
+
|
|
77
|
+
1. `bun:sqlite` is not imported anywhere: `grep -r "bun:sqlite" src/`
|
|
78
|
+
2. `db.ts` does not exist
|
|
79
|
+
3. `src/bun/store.ts` exists and implements read/write for scan-state.json, daily.json, settings.json
|
|
80
|
+
4. `src/bun/scan.ts` uses store, not db
|
|
81
|
+
5. `src/bun/index.ts` uses store, not db
|
|
82
|
+
6. RPC types in shared/types.ts have no session/event RPCs
|
|
83
|
+
7. schema.ts has no Session/SessionEvent/SessionFilters interfaces
|
|
84
|
+
8. Vite build compiles without errors
|
|
85
|
+
9. TypeScript has no type errors (check with `bunx tsc --noEmit` or esbuild)
|
|
86
|
+
|
|
87
|
+
Output JSON: { "verdict": "pass" or "fail", "issues": [...] }
|
|
88
|
+
"""
|
|
89
|
+
output = { format = "json", name = "qa-store.json" }
|
|
90
|
+
|
|
91
|
+
[[stages]]
|
|
92
|
+
id = "fix-store"
|
|
93
|
+
name = "Fix Store Issues"
|
|
94
|
+
type = "loop"
|
|
95
|
+
team = "implementors"
|
|
96
|
+
depends_on = ["qa-store"]
|
|
97
|
+
input_from = ["qa-store"]
|
|
98
|
+
prompt = "Fix all issues from QA report."
|
|
99
|
+
max_loops = 2
|
|
100
|
+
loop_to = "qa-store"
|
|
101
|
+
condition = "qa-store.verdict != 'pass'"
|
|
102
|
+
output = { format = "diff", name = "store-fixes.diff" }
|
|
103
|
+
|
|
104
|
+
# ─── Phase 2: Spotify Wrapped-style UI ─────────────────────
|
|
105
|
+
|
|
106
|
+
[[stages]]
|
|
107
|
+
id = "wrapped-ui"
|
|
108
|
+
name = "Spotify Wrapped Dashboard"
|
|
109
|
+
type = "seq"
|
|
110
|
+
team = "implementors"
|
|
111
|
+
depends_on = ["fix-store"]
|
|
112
|
+
prompt = """
|
|
113
|
+
Transform the dashboard into a Spotify Wrapped-style visual experience. This should feel like
|
|
114
|
+
an annual review / "Your Year in Code" summary — bold typography, gradient backgrounds,
|
|
115
|
+
animated stat reveals, and visual flair.
|
|
116
|
+
|
|
117
|
+
**Delete these files** (session detail features removed):
|
|
118
|
+
- src/mainview/components/SessionDetail.tsx
|
|
119
|
+
- src/mainview/components/SessionList.tsx
|
|
120
|
+
- src/mainview/components/SessionListItem.tsx
|
|
121
|
+
- src/mainview/components/EventTimeline.tsx
|
|
122
|
+
- src/mainview/components/EventItem.tsx
|
|
123
|
+
- src/mainview/components/FilterBar.tsx
|
|
124
|
+
- src/mainview/components/SearchInput.tsx
|
|
125
|
+
- src/mainview/hooks/useSessionDetail.ts
|
|
126
|
+
- src/mainview/hooks/useSessions.ts
|
|
127
|
+
- src/mainview/lib/filters.ts
|
|
128
|
+
- All *.test.tsx files
|
|
129
|
+
|
|
130
|
+
**Redesign App.tsx:**
|
|
131
|
+
- Remove sidebar navigation — single-page "Wrapped" scroll experience
|
|
132
|
+
- Remove "sessions" and "session-detail" views entirely
|
|
133
|
+
- Keep a small gear icon for settings (modal overlay, not separate page)
|
|
134
|
+
- Full-screen scrollable cards
|
|
135
|
+
|
|
136
|
+
**Create new Wrapped-style Dashboard (replace existing Dashboard.tsx, DashboardCharts.tsx, StatsCards.tsx):**
|
|
137
|
+
|
|
138
|
+
The dashboard is a vertical scroll of full-width "cards" — each card fills most of the viewport
|
|
139
|
+
and showcases one stat category with bold visuals:
|
|
140
|
+
|
|
141
|
+
Card 1: "Your AI Coding Year" hero
|
|
142
|
+
- Big animated counter: total sessions, total cost, total tokens
|
|
143
|
+
- Gradient background (dark purple → blue → teal)
|
|
144
|
+
- Date range shown subtly
|
|
145
|
+
|
|
146
|
+
Card 2: "Time Spent Coding with AI"
|
|
147
|
+
- Total hours/days spent
|
|
148
|
+
- Average session duration
|
|
149
|
+
- Longest session highlight
|
|
150
|
+
- Animated circular progress ring
|
|
151
|
+
|
|
152
|
+
Card 3: "Your Top Models"
|
|
153
|
+
- Ranked list of models by usage (tokens or cost)
|
|
154
|
+
- Horizontal bar chart with model colors
|
|
155
|
+
- Percentage breakdown
|
|
156
|
+
|
|
157
|
+
Card 4: "Your Agents"
|
|
158
|
+
- Agent breakdown (Claude, Codex, Gemini, etc.)
|
|
159
|
+
- Each agent gets an icon/emoji and stats
|
|
160
|
+
- Donut chart showing distribution
|
|
161
|
+
|
|
162
|
+
Card 5: "Daily Activity"
|
|
163
|
+
- Heatmap-style grid (like GitHub contribution graph) or area chart
|
|
164
|
+
- Shows daily token usage or session count over time
|
|
165
|
+
|
|
166
|
+
Card 6: "Cost Breakdown"
|
|
167
|
+
- Total spend with big number
|
|
168
|
+
- Daily average
|
|
169
|
+
- Most expensive day
|
|
170
|
+
- Trend line
|
|
171
|
+
|
|
172
|
+
Card 7: "Your Top Repos"
|
|
173
|
+
- List of repos by session count and cost
|
|
174
|
+
- Bar chart
|
|
175
|
+
|
|
176
|
+
**Visual style:**
|
|
177
|
+
- Dark theme default — deep navy/charcoal backgrounds
|
|
178
|
+
- Each card has a subtle gradient or accent color
|
|
179
|
+
- Use CSS animations for number counters (count up on scroll into view)
|
|
180
|
+
- Large typography (3xl-6xl for hero numbers)
|
|
181
|
+
- Rounded cards with glassmorphism borders (subtle white/10 border, backdrop-blur)
|
|
182
|
+
- Recharts for data visualization where needed
|
|
183
|
+
- Smooth scroll-snap between cards
|
|
184
|
+
- Responsive — works on smaller windows too
|
|
185
|
+
|
|
186
|
+
**Data source:**
|
|
187
|
+
- All data comes from RPC `getDashboardSummary` and `getDailyTimeline`
|
|
188
|
+
- No session-level data needed
|
|
189
|
+
|
|
190
|
+
**Hooks:**
|
|
191
|
+
- Keep `useDashboardData.ts` but simplify to only fetch summary + timeline
|
|
192
|
+
- Remove session-related hooks
|
|
193
|
+
- Update `useRPC.ts` to remove session RPCs
|
|
194
|
+
|
|
195
|
+
**Update Sidebar.tsx:**
|
|
196
|
+
- Remove it entirely or replace with a minimal floating nav
|
|
197
|
+
- Just a small settings gear + app title
|
|
198
|
+
|
|
199
|
+
**Verify:**
|
|
200
|
+
- Vite build compiles
|
|
201
|
+
- No imports of deleted files remain
|
|
202
|
+
- No TypeScript errors
|
|
203
|
+
"""
|
|
204
|
+
output = { format = "markdown", name = "wrapped-ui.md" }
|
|
205
|
+
|
|
206
|
+
[[stages]]
|
|
207
|
+
id = "qa-wrapped"
|
|
208
|
+
name = "QA Wrapped UI"
|
|
209
|
+
type = "seq"
|
|
210
|
+
team = "reviewers"
|
|
211
|
+
depends_on = ["wrapped-ui"]
|
|
212
|
+
input_from = ["wrapped-ui"]
|
|
213
|
+
prompt = """
|
|
214
|
+
Verify the Wrapped UI transformation:
|
|
215
|
+
|
|
216
|
+
1. Deleted files are gone (SessionDetail, SessionList, EventTimeline, etc.)
|
|
217
|
+
2. No imports of deleted files remain anywhere
|
|
218
|
+
3. Sidebar is removed or minimal
|
|
219
|
+
4. App.tsx has no "sessions" or "session-detail" views
|
|
220
|
+
5. Dashboard renders a scroll of visual cards (check component structure)
|
|
221
|
+
6. RPC calls are only getDashboardSummary and getDailyTimeline
|
|
222
|
+
7. Vite build compiles
|
|
223
|
+
8. TypeScript has no errors
|
|
224
|
+
9. All Recharts imports are valid
|
|
225
|
+
10. CSS uses dark theme with gradients
|
|
226
|
+
|
|
227
|
+
Output JSON: { "verdict": "pass" or "fail", "issues": [...] }
|
|
228
|
+
"""
|
|
229
|
+
output = { format = "json", name = "qa-wrapped.json" }
|
|
230
|
+
|
|
231
|
+
[[stages]]
|
|
232
|
+
id = "fix-wrapped"
|
|
233
|
+
name = "Fix Wrapped UI Issues"
|
|
234
|
+
type = "loop"
|
|
235
|
+
team = "implementors"
|
|
236
|
+
depends_on = ["qa-wrapped"]
|
|
237
|
+
input_from = ["qa-wrapped"]
|
|
238
|
+
prompt = "Fix all issues from QA report."
|
|
239
|
+
max_loops = 2
|
|
240
|
+
loop_to = "qa-wrapped"
|
|
241
|
+
condition = "qa-wrapped.verdict != 'pass'"
|
|
242
|
+
output = { format = "diff", name = "wrapped-fixes.diff" }
|
|
243
|
+
|
|
244
|
+
# ─── Phase 3: Integration test + commit ─────────────────────
|
|
245
|
+
|
|
246
|
+
[[stages]]
|
|
247
|
+
id = "integration"
|
|
248
|
+
name = "Integration Smoke Test"
|
|
249
|
+
type = "seq"
|
|
250
|
+
team = "implementors"
|
|
251
|
+
depends_on = ["fix-wrapped"]
|
|
252
|
+
prompt = """
|
|
253
|
+
Final integration check:
|
|
254
|
+
|
|
255
|
+
1. Run `bun install` — must succeed
|
|
256
|
+
2. Run Vite build — must succeed with no errors
|
|
257
|
+
3. Run `bunx tsc --noEmit` or esbuild check — no type errors
|
|
258
|
+
4. Verify no references to:
|
|
259
|
+
- bun:sqlite
|
|
260
|
+
- db.ts
|
|
261
|
+
- SessionDetail, SessionList, EventTimeline, EventItem
|
|
262
|
+
- querySessions, getSessionEvents, getSession
|
|
263
|
+
5. Verify ~/.ai-stats/ directory structure works:
|
|
264
|
+
- The store module can create the directory
|
|
265
|
+
- Can write and read JSON files
|
|
266
|
+
6. Fix any remaining issues.
|
|
267
|
+
|
|
268
|
+
Report what you found and fixed.
|
|
269
|
+
"""
|
|
270
|
+
output = { format = "markdown", name = "integration.md" }
|
|
271
|
+
|
|
272
|
+
[[stages]]
|
|
273
|
+
id = "commit"
|
|
274
|
+
name = "Final Commit"
|
|
275
|
+
type = "seq"
|
|
276
|
+
team = "global"
|
|
277
|
+
depends_on = ["integration"]
|
|
278
|
+
prompt = """
|
|
279
|
+
Review git diff. Stage all new/modified files and deleted files. Commit with message:
|
|
280
|
+
"refactor: remove SQLite, add JSON store, Spotify Wrapped-style dashboard"
|
|
281
|
+
|
|
282
|
+
Do NOT push.
|
|
283
|
+
"""
|
|
284
|
+
tools = ["Read", "Glob", "Grep", "Bash"]
|
|
285
|
+
output = { format = "markdown", name = "commit.md" }
|