-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add local dashboard SPA with React + Vite #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+11,382
β112
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
b5f8181
feat: add local dashboard SPA with React + Vite
WellDunDun 5ec0ec5
fix: address CodeRabbit review feedback for local dashboard
WellDunDun 4f20227
fix: address second round CodeRabbit review feedback
WellDunDun 4c65a75
Merge remote-tracking branch 'origin/dev' into WellDunDun/local-dashbβ¦
WellDunDun efbfa5c
feat: align local dashboard SPA with SQLite v2 data architecture
WellDunDun df7ad87
Merge origin/dev into WellDunDun/local-dashboard-spa
WellDunDun a56aead
fix: address CodeRabbit review feedback on local dashboard SPA
WellDunDun b3560a7
fix: sort imports to satisfy Biome organizeImports lint
WellDunDun 515db2b
fix: address CodeRabbit nitpicks β cross-platform dev script, stricteβ¦
WellDunDun 675d64d
fix: add UNKNOWN status filter and extract header height CSS variable
WellDunDun 3638582
fix: hoist sidebar collapse state to layout and add UNKNOWN filter style
WellDunDun 86b3bcf
Merge remote-tracking branch 'origin/dev' into WellDunDun/local-dashbβ¦
WellDunDun 788ca66
feat: serve SPA as default dashboard, legacy at /legacy/
WellDunDun 86a6bfe
feat: add shadcn theming with dark/light toggle and selftune branding
WellDunDun 775364f
fix: path traversal check and 404 for missing skills
WellDunDun cd6eebc
fix: biome formatting β semicolons, import order, line length
WellDunDun 5c0cb5a
fix: address CodeRabbit review β dedupe polling, fix stale closures, β¦
WellDunDun b447874
fix: address CodeRabbit review round 2 β shared sorting, DnD fixes, Tβ¦
WellDunDun 6d8d514
feat: add evidence viewer, evolution timeline, and enhanced skill report
WellDunDun 8a97b9e
fix: address CodeRabbit review round 3 β DnD/sort conflict, theme lisβ¦
WellDunDun 339f545
feat: show selftune version in sidebar footer
WellDunDun 83c3c13
fix: biome formatting in dashboard-server β line length wrapping
WellDunDun db59a86
fix: address CodeRabbit review round 4 β dedupe formatRate, STATUS_COβ¦
WellDunDun 61720d8
fix: remove redundant items prop from Select to avoid duplication
WellDunDun f32e062
fix: add sortableKeyboardCoordinates to KeyboardSensor for proper keyβ¦
WellDunDun 0e357bf
feat: Linear-style dashboard UX β collapsible sidebar, direct skill lβ¦
WellDunDun 0e54720
fix: address CodeRabbit review β accessibility, semantics, state reset
WellDunDun bbbb0d7
feat: add TanStack Query and optimize SQL queries for dashboard perfoβ¦
WellDunDun c6918c2
chore: track root bun.lock for reproducible installs
WellDunDun 37363f9
fix: address CodeRabbit review β collapsible sync, drag handle dedup,β¦
WellDunDun a2d84f7
fix: address CodeRabbit nitpicks β version pinning, changelog clarityβ¦
WellDunDun d68a473
fix: address CodeRabbit round 3 β deps, async fs, type safety, determβ¦
WellDunDun 95a2c1e
fix: resolve Biome lint and format errors in CI
WellDunDun 845bb66
fix: address CodeRabbit round 4 β CTE subqueries, type alignment, scoβ¦
WellDunDun dbdc702
fix: address CodeRabbit round 5 β startup guard, 404 heuristic, deterβ¦
WellDunDun 24f64d7
fix: address CodeRabbit round 6 β db guard, refresh throttle, deferreβ¦
WellDunDun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| dist/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| # Local Dashboard SPA β Handoff | ||
|
|
||
| ## Architecture | ||
|
|
||
| React SPA built with Vite + TypeScript that consumes the **SQLite-backed v2 API endpoints** from the dashboard server. The server materializes JSONL logs into a local SQLite database (`~/.selftune/selftune.db`) and serves pre-aggregated query results. | ||
|
|
||
| ### Data flow | ||
|
|
||
| ```text | ||
| JSONL logs β materializeIncremental() β SQLite β getOverviewPayload() / getSkillReportPayload() β /api/v2/* β SPA | ||
| ``` | ||
|
|
||
| ## What is implemented | ||
|
|
||
| - **Two routes**: | ||
| - `/` β Overview with KPI section cards (with info tooltips), skill health grid with status filters (healthy/warning/critical/unknown), evolution feed (ActivityTimeline), unmatched queries, onboarding banner (dismissible, localStorage-persisted) | ||
| - `/skills/:name` β Per-skill drilldown with usage stats (with info tooltips), invocation records, EvidenceViewer (collapsible evidence entries with markdown rendering, context banner), EvolutionTimeline (vertical timeline with pass-rate deltas, lifecycle legend), pending proposals, tab descriptions via hover tooltips | ||
| - **UX helpers**: `InfoTip` component for glossary tooltips on all metrics, lifecycle legend in evolution timeline, evidence context banner, onboarding flow for first-time users | ||
| - **Data layer**: TanStack Query (`@tanstack/react-query`) with smart caching, fetching from v2 endpoints backed by SQLite materialized queries | ||
| - `GET /api/v2/overview` β combined `getOverviewPayload()` + `getSkillsList()` | ||
| - `GET /api/v2/skills/:name` β `getSkillReportPayload()` + evolution audit + pending proposals | ||
| - **Live updates**: 15-second polling interval via TanStack Query `refetchInterval` (replaced old SSE approach) | ||
| - **Caching**: `staleTime` of 10s (overview) / 30s (skill report) for instant back-navigation; `gcTime` of 5 minutes; automatic background refetch on window focus | ||
| - **Loading/error/empty/not-found states** on every route | ||
| - **UI framework**: shadcn/ui components with dark/light theme toggle, TanStack Table for data grids | ||
| - **Design**: selftune branding, collapsible sidebar, Tailwind v4 | ||
|
|
||
| ## How to run | ||
|
|
||
| ```bash | ||
| # Terminal 1: Start the dashboard server | ||
| selftune dashboard --port 7888 | ||
|
|
||
| # Terminal 2: Start the SPA dev server (proxies /api to port 7888) | ||
| cd apps/local-dashboard | ||
| bun install | ||
| bunx vite | ||
| # β opens at http://localhost:5199 | ||
| ``` | ||
|
|
||
| ## What was rebased / changed | ||
|
|
||
| - **SPA types**: Rewritten to match `queries.ts` payload shapes (`OverviewResponse`, `SkillReportResponse`, `SkillSummary`, `EvidenceEntry`) | ||
| - **API layer**: Now calls `/api/v2/overview` and `/api/v2/skills/:name` instead of `/api/data` + `/api/evaluations/:name` | ||
| - **SSE removed**: Replaced with 15s polling (SQLite reads are cheap, SSE was complex) | ||
| - **Overview page**: Uses `SkillSummary[]` from `getSkillsList()` for skill cards (pre-aggregated pass rate, check count, sessions) | ||
| - **Skill report page**: Single fetch to v2 endpoint instead of parallel overview + evaluations fetch. Shows evidence entries, evolution audit history per skill | ||
| - **Hooks**: Migrated to TanStack Query β `useOverview` uses `useQuery` with `refetchInterval`, `useSkillReport` uses `useQuery` with smart retry (skips retry on 404). Manual polling, request deduplication, and stale-request guards replaced by TanStack Query built-ins. | ||
|
|
||
| ## Query optimizations | ||
|
|
||
| - **Pending proposals**: Replaced `NOT IN` subquery + JS `Set` dedup with `LEFT JOIN + IS NULL + GROUP BY` in both `queries.ts` and `dashboard-server.ts` | ||
| - **Evidence query bounded**: Added `LIMIT 200` to `getSkillReportPayload()` evidence query (was unbounded) | ||
| - **Indexes**: 16 indexes defined in `schema.ts` covering all frequent filter/join columns (`skill_name`, `session_id`, `proposal_id`, `timestamp`, `query+triggered`) | ||
|
|
||
| ## What now uses SQLite / materialized queries | ||
|
|
||
| - **Overview**: `getOverviewPayload(db)` for evolution, unmatched queries, pending proposals, counts; `getSkillsList(db)` for per-skill aggregated stats | ||
| - **Skill report**: `getSkillReportPayload(db, skillName)` for usage stats, recent invocations, evidence; direct SQL for evolution audit + pending proposals per skill | ||
| - **Server**: `materializeIncremental(db)` runs at startup and refreshes every 15s on v2 endpoint access | ||
|
|
||
| ## What still depends on old dashboard code | ||
|
|
||
| - The old v1 endpoints (`/api/data`, `/api/events`, `/api/evaluations/:name`) still work and are used by the legacy `dashboard/index.html` | ||
| - Badge endpoints (`/badge/:name`) and report HTML endpoints (`/report/:name`) use the old `computeStatus` + JSONL reader path | ||
| - Action endpoints (`/api/actions/*`) are unchanged | ||
|
|
||
| ## What remains before this can become default | ||
|
|
||
| 1. ~~**Serve built SPA from dashboard-server**~~: Done β `/` serves SPA, old dashboard at `/legacy/` | ||
| 2. ~~**Production build**~~: Done β `bun run build:dashboard` in root package.json | ||
| 3. **Regression detection**: The SQLite layer doesn't compute regression detection yet β `deriveStatus()` currently only uses pass rate + check count. Add a `regression_detected` column to skill summaries when the monitoring snapshot computation moves to SQLite. | ||
| 4. **Monitoring snapshot migration**: Move `computeMonitoringSnapshot()` logic into the SQLite materializer or a query helper (window sessions, false negative rate, baseline comparison) | ||
| 5. **Actions integration**: Wire up watch/evolve/rollback buttons in the SPA to `/api/actions/*` | ||
| 6. **Migrate badge/report endpoints**: Switch to SQLite-backed queries |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.