feat(v1.0): Web Dashboard + VS Code Extension#5
Conversation
## Web Dashboard (v1.0) - React 18 + TypeScript + Vite frontend - Node.js proxy server for daemon IPC - 7 pages: Dashboard, Timeline, Sessions, Search, Blame, Evidence, Diagnostics - Real-time WebSocket updates - Virtual scrolling for 10K+ events - Terminal Noir dark theme with Framer Motion animations ## VS Code Extension (v0.8) - Inline blame on hover with rich hover cards - Gutter icons for AI-written lines (green/yellow/gray confidence) - Timeline sidebar in Explorer panel - IPC client for daemon communication ## CLI Dashboard Commands - `diachron dashboard start` - Start web dashboard at localhost:3947 - `diachron dashboard stop` - Stop dashboard - `diachron dashboard status` - Check status - Automatic browser opening, PID management, health checks ## Documentation - Updated README with v1.0 features - Dashboard pages table with descriptions - VS Code installation instructions - Updated roadmap showing v0.4-v1.0 complete Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary of ChangesHello @wolfiesch, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request marks a significant milestone with the release of Diachron v1.0, transforming how users interact with AI provenance data. It introduces a powerful web-based dashboard for detailed visualization and management, alongside a tightly integrated VS Code extension that brings AI attribution directly into the developer's workflow. These additions greatly enhance the platform's usability and provide deeper insights into AI-assisted code development. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
⚡ Benchmark Results
|
There was a problem hiding this comment.
Code Review
This is a major feature release, introducing a web dashboard and a VS Code extension. The changes are extensive and well-structured. I've found a few issues, including some critical type mismatches in the new dashboard frontend that would lead to runtime errors, and some performance inefficiencies in the dashboard's proxy server. I've also noted a couple of medium-severity issues related to robustness in the VS Code extension and the CLI. Overall, this is a great step forward for the project. My comments focus on improving correctness, performance, and robustness.
| export interface EvidenceSummary { | ||
| files_changed: number; | ||
| lines_added: number; | ||
| lines_removed: number; | ||
| tool_operations: number; | ||
| sessions: number; | ||
| total_events: number; | ||
| coverage_pct: number; | ||
| } |
There was a problem hiding this comment.
The EvidenceSummary type incorrectly includes total_events and coverage_pct. These properties exist on the parent EvidencePackResult type, not on the summary object within it. This will cause a runtime error in Evidence.tsx where result.summary.coverage_pct is accessed. These properties should be removed from this interface.
export interface EvidenceSummary {
files_changed: number;
lines_added: number;
lines_removed: number;
tool_operations: number;
sessions: number;
}| export interface VerificationStatus { | ||
| chain_valid: boolean; | ||
| tests_passed: boolean | null; | ||
| build_passed: boolean | null; | ||
| human_reviewed: boolean; | ||
| } |
There was a problem hiding this comment.
The property names in VerificationStatus do not match the backend data structure. chain_valid should be chain_verified, and build_passed should be build_succeeded. This mismatch will cause the verification status to be displayed incorrectly in Evidence.tsx.
export interface VerificationStatus {
chain_verified: boolean;
tests_passed: boolean | null;
build_succeeded: boolean | null;
human_reviewed: boolean;
}| // Diagnostics | ||
| app.get('/api/diagnostics', asyncHandler(async (_req, res) => { | ||
| const diagnostics = await getDiagnostics(); | ||
| res.json(diagnostics); | ||
| })); | ||
|
|
||
| // Timeline events | ||
| app.get('/api/events', asyncHandler(async (req, res) => { | ||
| const { since, file, limit } = req.query; | ||
| const events = await queryTimeline({ | ||
| since: since as string | undefined, | ||
| file_filter: file as string | undefined, | ||
| limit: limit ? parseInt(limit as string, 10) : 100, | ||
| }); | ||
| res.json(events); | ||
| })); | ||
|
|
||
| // Get single event by ID | ||
| app.get('/api/events/:id', asyncHandler(async (req, res) => { | ||
| const eventId = parseInt(req.params.id as string, 10); | ||
| const events = await queryTimeline({ limit: 1000 }); | ||
| const event = events.find((e) => e.id === eventId); | ||
|
|
||
| if (event) { | ||
| res.json(event); | ||
| } else { | ||
| res.status(404).json({ error: 'Event not found' }); | ||
| } | ||
| })); | ||
|
|
||
| // Sessions (aggregated from events) | ||
| app.get('/api/sessions', asyncHandler(async (_req, res) => { | ||
| const events = await queryTimeline({ limit: 1000 }); | ||
|
|
||
| // Group events by session_id | ||
| const sessionMap = new Map<string, StoredEvent[]>(); | ||
| for (const event of events) { | ||
| const sid = event.session_id || 'unknown'; | ||
| if (!sessionMap.has(sid)) { | ||
| sessionMap.set(sid, []); | ||
| } | ||
| sessionMap.get(sid)!.push(event); | ||
| } | ||
|
|
||
| // Convert to session summaries | ||
| const sessions = Array.from(sessionMap.entries()).map(([session_id, sessionEvents]) => { | ||
| const sorted = sessionEvents.sort((a, b) => | ||
| new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() | ||
| ); | ||
| return { | ||
| session_id, | ||
| event_count: sessionEvents.length, | ||
| first_event: sorted[0]?.timestamp, | ||
| last_event: sorted[sorted.length - 1]?.timestamp, | ||
| tools: [...new Set(sessionEvents.map((e) => e.tool_name))], | ||
| files: [...new Set(sessionEvents.filter((e) => e.file_path).map((e) => e.file_path))], | ||
| }; | ||
| }); | ||
|
|
There was a problem hiding this comment.
The endpoints for getting a single event (/api/events/:id), all sessions (/api/sessions), and a single session (/api/sessions/:id) are implemented inefficiently. They all fetch a large number of events (limit: 1000) from the daemon and then perform filtering and aggregation in the Node.js proxy. This will lead to performance and memory issues as the number of events grows.
These operations should be pushed down to the daemon, which can perform them much more efficiently with direct database access. I recommend adding new IPC messages to the daemon for:
- Fetching a single event by ID.
- Fetching an aggregated list of sessions.
- Fetching all events for a specific session ID.
This will significantly improve the scalability of the dashboard.
dashboard/package.json
Outdated
| }, | ||
| "devDependencies": { | ||
| "@types/cors": "^2.8.17", | ||
| "@types/express": "^5.0.0", |
There was a problem hiding this comment.
The version for @types/express is set to ^5.0.0, which does not seem to be a valid version range for this package. The latest version for Express 4.x is 4.17.x. This should be corrected to avoid potential installation issues.
| "@types/express": "^5.0.0", | |
| "@types/express": "^4.17.21", |
| private extractLineNumbers(blame: BlameMatch): number[] { | ||
| const lines: number[] = []; | ||
|
|
||
| // Try to parse from diff_summary | ||
| // Format might be: "+12 lines at 38-50" or "modify lines 10-20" | ||
| if (blame.event.diff_summary) { | ||
| const rangeMatch = blame.event.diff_summary.match(/(?:lines?\s+)?(\d+)(?:-(\d+))?/i); | ||
| if (rangeMatch) { | ||
| const start = parseInt(rangeMatch[1], 10); | ||
| const end = rangeMatch[2] ? parseInt(rangeMatch[2], 10) : start; | ||
| for (let i = start; i <= end; i++) { | ||
| lines.push(i); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return lines; | ||
| } |
There was a problem hiding this comment.
The extractLineNumbers function relies on a regular expression to parse line numbers from the diff_summary string. This is fragile and might break if the format of diff_summary changes in the daemon. A more robust solution would be to have the daemon provide structured line number information (e.g., start and end lines) as part of the event data. This would make the extension more resilient to changes in the daemon's summary formatting.
rust/cli/src/main.rs
Outdated
| // Wait for server to be ready | ||
| std::thread::sleep(Duration::from_secs(2)); | ||
|
|
There was a problem hiding this comment.
The dashboard start command uses a fixed std::thread::sleep(Duration::from_secs(2)) to wait for the dashboard server to become available before checking its status. This can create a race condition; the server might take longer to start on a slow machine, causing the command to fail incorrectly. A more robust approach would be to poll the http://localhost:{port}/api/health endpoint in a loop with a timeout, rather than using a fixed sleep.
Fixes based on code review comments: ## Critical Fixes - Fix EvidenceSummary type: remove duplicate total_events, coverage_pct (these exist on parent EvidencePackResult, not the summary) - Fix VerificationStatus field names: chain_valid→chain_verified, build_passed→build_succeeded (match Rust daemon types) - Update Evidence.tsx to use corrected field paths ## Medium Priority Fixes - Fix @types/express version: ^5.0.0 → ^4.17.21 (valid version) - Replace fixed 2s sleep with polling loop (up to 10s with 500ms intervals) for more reliable dashboard startup detection ## Deferred (TODO comments added) - Proxy endpoint efficiency: /api/events/:id and /api/sessions fetch all events and filter in JS - should add daemon IPC messages for efficiency - VS Code extractLineNumbers: fragile regex parsing of diff_summary - daemon should provide structured line numbers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
⚡ Benchmark Results
|
Summary
🎉 Diachron v1.0 Release - The complete AI provenance tracking platform.
diachron dashboard start/stop/statusfor easy dashboard managementWhat's New
Web Dashboard (v1.0)
Tech Stack: React 18, TypeScript, Vite, TanStack Query, Tailwind CSS, Framer Motion
VS Code Extension (v0.8)
CLI Dashboard Commands
Test plan
npm run buildin dashboard/)diachron dashboard start/stop/status)/api/health,/api/events)🤖 Generated with Claude Code