Skip to main content

Component Overview

Work-Wiki provides three complementary visualization components, each operating at a different granularity:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     THREE VISUALIZATION COMPONENTS                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   COMPONENT 1: GitBlameViewer                                                   β”‚
β”‚   Granularity:  LINE-LEVEL                                                      β”‚
β”‚   View:         Who wrote each line?                                            β”‚
β”‚   AI Extension: AI attribution per commit line                                  β”‚
β”‚                                                                                 β”‚
β”‚   COMPONENT 2: GitDiffViewer                                                    β”‚
β”‚   Granularity:  HUNK-LEVEL                                                      β”‚
β”‚   View:         What changed in each hunk?                                      β”‚
β”‚   AI Extension: AI attribution per diff hunk                                    β”‚
β”‚                                                                                 β”‚
β”‚   COMPONENT 3: GitBranchDiagramViewer                                           β”‚
β”‚   Granularity:  COMMIT-LEVEL                                                    β”‚
β”‚   View:         Branch history with micro-saves                                 β”‚
β”‚   AI Extension: Micro-save badges + Draft nodes                                 β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

GitBlameViewer: Line-Level Attribution

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     GITBLAMEVIEWER ARCHITECTURE                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   Key Methods:                                                                  β”‚
β”‚   β”œβ”€β”€ loadData()              - Fetch blame + AI attribution                    β”‚
β”‚   β”œβ”€β”€ render()                - Render blame table                              β”‚
β”‚   β”œβ”€β”€ fetchWorkWikiAttributions() - Load AI data async                          β”‚
β”‚   β”œβ”€β”€ getIndicatorColor()     - 4-tier color mapping                            β”‚
β”‚   └── renderLine()            - Render individual line                          β”‚
β”‚                                                                                 β”‚
β”‚   Data Flow:                                                                    β”‚
β”‚                                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     invoke()    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚   β”‚ loadData()  │────────────────▢│  git_blame      β”‚                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                 β”‚  (Tauri cmd)    β”‚                          β”‚
β”‚          β”‚                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚          β”‚ Phase 1                         β”‚                                   β”‚
β”‚          β–Ό                                 β”‚                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚                                   β”‚
β”‚   β”‚  render()   β”‚β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                                                              β”‚
β”‚          β”‚                                                                     β”‚
β”‚          β”‚ Phase 2 (async)                                                     β”‚
β”‚          β–Ό                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     invoke()    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚ fetchWorkWikiAttributions() │────────────────▢│ work_wiki_get_ai_       β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β”‚ attributions_batch      β”‚  β”‚
β”‚                  β”‚                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                  β”‚                                             β”‚               β”‚
β”‚                  β–Ό                                             β”‚               β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                              β”‚               β”‚
β”‚   β”‚  render()   β”‚β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β”‚   β”‚  (with AI)  β”‚                                                              β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                              β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Two-Phase Data Loading

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     TWO-PHASE DATA LOADING                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   PHASE 1: Immediate (Core Blame Data)                                         β”‚
β”‚                                                                                 β”‚
β”‚       async loadData() {                                                        β”‚
β”‚         // 1. Fetch core blame data from git                                    β”‚
β”‚         this.data = await invoke('git_blame', {                                 β”‚
β”‚           filePath: this.filePath,                                              β”‚
β”‚           repoPath: this.repoPath                                               β”‚
β”‚         });                                                                     β”‚
β”‚                                                                                 β”‚
β”‚         // 2. Render IMMEDIATELY (user sees data fast)                          β”‚
β”‚         this.render();  // <-- Phase 1 complete                                 β”‚
β”‚       }                                                                         β”‚
β”‚                                                                                 β”‚
β”‚       β”‚ t=50ms                                                                  β”‚
β”‚       β–Ό                                                                         β”‚
β”‚                                                                                 β”‚
β”‚   PHASE 2: Deferred (AI Attribution)                                           β”‚
β”‚                                                                                 β”‚
β”‚       // Non-blocking: fetch AI attributions and re-render                      β”‚
β”‚       this.fetchWorkWikiAttributions(                                           β”‚
β”‚         this.data.commits.map(c => c.hash)                                      β”‚
β”‚       ).then(() => {                                                            β”‚
β”‚         this.render();  // <-- Phase 2 re-render with AI data                   β”‚
β”‚       });                                                                       β”‚
β”‚                                                                                 β”‚
β”‚       β”‚ t=150ms                                                                 β”‚
β”‚       β–Ό                                                                         β”‚
β”‚                                                                                 β”‚
β”‚   Timeline:                                                                     β”‚
β”‚       t=0ms       loadData() called                                             β”‚
β”‚       t=50ms      git_blame returns, Phase 1 render                             β”‚
β”‚       t=50ms      fetchWorkWikiAttributions() starts (async)                    β”‚
β”‚       t=150ms     AI data arrives, Phase 2 re-render                            β”‚
β”‚                                                                                 β”‚
β”‚   User Experience:                                                              β”‚
β”‚       - Blame data visible in 50ms                                              β”‚
β”‚       - AI indicators appear 100ms later                                        β”‚
β”‚       - No blocking, no spinner for AI data                                     β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Agent Tooltip Display

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     AGENT TOOLTIP DISPLAY                                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   Visual Example:                                                               β”‚
β”‚                                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚   β”‚ AI% β”‚ Author     β”‚ Time   β”‚ Line Content                      β”‚             β”‚
β”‚   β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€             β”‚
β”‚   β”‚ β—‰   β”‚ abc1234    β”‚ 2h ago β”‚ export function authenticate() {  β”‚             β”‚
β”‚   β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚     ↑                                                                           β”‚
β”‚     └── Hover shows: "AI: 67% (Claude, Gemini)"                                 β”‚
β”‚                                                                                 β”‚
β”‚   Implementation:                                                               β”‚
β”‚       title="AI: ${aiPct}%${agentNames ? ' (' + agentNames + ')' : ''}"         β”‚
β”‚                                                                                 β”‚
β”‚   Example Values:                                                               β”‚
β”‚       aiPct = 67                                                                β”‚
β”‚       agentNames = "Claude, Gemini"                                             β”‚
β”‚       Result: "AI: 67% (Claude, Gemini)"                                        β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

GitDiffViewer: Hunk-Level Attribution

hunkMeta Coordinate System

The GitDiffViewer introduces a novel coordinate system for hunk attribution:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     HUNKMETA COORDINATE SYSTEM                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   Problem: How to uniquely identify a hunk for AI attribution lookup?          β”‚
β”‚                                                                                 β”‚
β”‚   Diff lines have no inherent identity:                                         β”‚
β”‚   - Multiple files may have same line content                                   β”‚
β”‚   - Line numbers change between versions                                        β”‚
β”‚   - Hunk headers alone aren't unique across files                               β”‚
β”‚                                                                                 β”‚
β”‚   Solution: hunkMeta = { filePath, hunkIndex }                                  β”‚
β”‚                                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚  File: src/auth.ts                                                      β”‚  β”‚
β”‚   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚   β”‚                                                                         β”‚  β”‚
β”‚   β”‚  diff --git a/src/auth.ts b/src/auth.ts                                 β”‚  β”‚
β”‚   β”‚  @@ -1,5 +1,8 @@                                                        β”‚  β”‚
β”‚   β”‚     hunkMeta = { filePath: "src/auth.ts", hunkIndex: 0 }                β”‚  β”‚
β”‚   β”‚  +import { validateToken } from './auth';                               β”‚  β”‚
β”‚   β”‚  +import { refreshToken } from './refresh';                             β”‚  β”‚
β”‚   β”‚   function authenticate() {                                             β”‚  β”‚
β”‚   β”‚  @@ -20,3 +23,5 @@                                                      β”‚  β”‚
β”‚   β”‚     hunkMeta = { filePath: "src/auth.ts", hunkIndex: 1 }                β”‚  β”‚
β”‚   β”‚  +  const token = getToken();                                           β”‚  β”‚
β”‚   β”‚  +  validateToken(token);                                               β”‚  β”‚
β”‚   β”‚                                                                         β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚  File: src/api.ts                                                       β”‚  β”‚
β”‚   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚   β”‚                                                                         β”‚  β”‚
β”‚   β”‚  diff --git a/src/api.ts b/src/api.ts                                   β”‚  β”‚
β”‚   β”‚  @@ -1,3 +1,4 @@                                                        β”‚  β”‚
β”‚   β”‚     hunkMeta = { filePath: "src/api.ts", hunkIndex: 0 }                 β”‚  β”‚
β”‚   β”‚  +import { fetchData } from './fetch';                                  β”‚  β”‚
β”‚   β”‚                                                                         β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                                 β”‚
β”‚   Cache Key Format: "${filePath}:${hunkIndex}"                                  β”‚
β”‚                                                                                 β”‚
β”‚   Examples:                                                                     β”‚
β”‚   β”œβ”€β”€ "src/auth.ts:0"  -->  First hunk in auth.ts                               β”‚
β”‚   β”œβ”€β”€ "src/auth.ts:1"  -->  Second hunk in auth.ts                              β”‚
β”‚   └── "src/api.ts:0"   -->  First hunk in api.ts                                β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

GitBranchDiagramViewer: Commit-Level

Micro-Save Badge

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     MICRO-SAVE BADGE ANATOMY                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   SVG Structure:                                                                β”‚
β”‚                                                                                 β”‚
β”‚   <g class="micro-save-badge" transform="translate(x, y-7)">                    β”‚
β”‚     β”œβ”€β”€ <rect>   Pill-shaped background (rounded corners)                       β”‚
β”‚     β”‚            Semi-transparent fill with colored border                      β”‚
β”‚     β”‚                                                                           β”‚
β”‚     β”œβ”€β”€ <text>   Count display                                                  β”‚
β”‚     β”‚            Centered with text-anchor="middle"                             β”‚
β”‚     β”‚            Capped at "99+" for very high counts                           β”‚
β”‚     β”‚                                                                           β”‚
β”‚     └── <title>  Native SVG tooltip                                             β”‚
β”‚                  "Work-Wiki: N micro-save(s) before this commit"                β”‚
β”‚                                                                                 β”‚
β”‚   Width Calculation:                                                            β”‚
β”‚       1-9    --> 18px (single digit)                                            β”‚
β”‚       10-99  --> 22px (double digit)                                            β”‚
β”‚       100+   --> 28px (shows "99+")                                             β”‚
β”‚                                                                                 β”‚
β”‚   Visual Examples:                                                              β”‚
β”‚       [2]   <-- gray (1-3 saves, subtle)                                        β”‚
β”‚       [7]   <-- green (4-10 saves, normal)                                      β”‚
β”‚       [18]  <-- yellow (11-25 saves, complex)                                   β”‚
β”‚       [42]  <-- accent (25+ saves, major)                                       β”‚
β”‚       [99+] <-- accent (100+ saves, capped)                                     β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Draft Branch Node

The Draft Node represents uncommitted work - the β€œfuture” of the codebase:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     DRAFT NODE VISUAL STRUCTURE                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚             β”‚   β”‚                                                 β”‚        β”‚
β”‚   β”‚     ◐       β”‚   β”‚  .draft-node-info                               β”‚        β”‚
β”‚   β”‚             β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚        β”‚
β”‚   β”‚ (half-moon) β”‚   β”‚  β”‚                                           β”‚  β”‚        β”‚
β”‚   β”‚             β”‚   β”‚  β”‚  DRAFT                                    β”‚  β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚  .draft-node-title                        β”‚  β”‚        β”‚
β”‚   .draft-node-icon  β”‚  β”‚                                           β”‚  β”‚        β”‚
β”‚                     β”‚  β”‚  3 files | +145 -23                       β”‚  β”‚        β”‚
β”‚                     β”‚  β”‚  .draft-node-stats                        β”‚  β”‚        β”‚
β”‚                     β”‚  β”‚                                           β”‚  β”‚        β”‚
β”‚                     β”‚  β”‚  [AI] 8  [H] 4                            β”‚  β”‚        β”‚
β”‚                     β”‚  β”‚  .draft-node-attribution                  β”‚  β”‚        β”‚
β”‚                     β”‚  β”‚                                           β”‚  β”‚        β”‚
β”‚                     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚        β”‚
β”‚                     β”‚                                                 β”‚        β”‚
β”‚                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                                                 β”‚
β”‚   .draft-node-connector                                                         β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚   β”‚    :                                                            β”‚           β”‚
β”‚   β”‚    : (dashed line connecting to HEAD)                           β”‚           β”‚
β”‚   β”‚    :                                                            β”‚           β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β”‚                                                                                 β”‚
β”‚   Half-Moon Icon Meaning:                                                       β”‚
β”‚   β”œβ”€β”€ Full circle  = Complete (committed)                                      β”‚
β”‚   β”œβ”€β”€ Half circle  = In progress (uncommitted)                                 β”‚
β”‚   └── Empty circle = Planned (future)                                          β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Cross-Component Patterns

Consistent 4-Tier Color System

All three viewers implement the same color thresholds:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     4-TIER COLOR SYSTEM COMPARISON                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                 β”‚
β”‚   GitBlameViewer & GitDiffViewer (AI Percentage):                               β”‚
β”‚       0-25%  AI  -->  green                                                     β”‚
β”‚       26-50% AI  -->  yellow                                                    β”‚
β”‚       51-75% AI  -->  accent                                                    β”‚
β”‚       76-100% AI -->  purple                                                    β”‚
β”‚                                                                                 β”‚
β”‚   GitBranchDiagramViewer (Micro-Save Count):                                    β”‚
β”‚       1-3   saves  -->  gray                                                    β”‚
β”‚       4-10  saves  -->  green                                                   β”‚
β”‚       11-25 saves  -->  yellow                                                  β”‚
β”‚       25+   saves  -->  accent                                                  β”‚
β”‚                                                                                 β”‚
β”‚   Note: Different thresholds for count vs percentage,                           β”‚
β”‚         but same color vocabulary!                                              β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Map-Based O(1) Caching

All three viewers use the same caching pattern:
ViewerCache PropertyKey Format
GitBlameVieweraiAttributionCachecommit_hash
GitDiffViewerhunkAttributionsfilePath:hunkIndex
GitBranchDiagramViewercommitWorkCountscommit_hash

Two-Phase Rendering

All three viewers implement the same pattern:
async loadData() {
  // Phase 1: Core data (immediate)
  this.data = await invoke('core_command', ...);
  this.render();  // User sees data immediately

  // Phase 2: AI attribution (deferred)
  this.fetchWorkWikiData(...).then(() => {
    this.render();  // Re-render with AI data
  });
}

Component Comparison

AspectGitBlameViewerGitDiffViewerGitBranchDiagramViewer
GranularityLineHunkCommit
Cache Keycommit_hashfilePath:hunkIndexcommit_hash
Primary VisualAI % indicatorHunk AI badgeMicro-save badge
Novel FeatureAgent tooltiphunkMeta coordinateDraft node (half-moon)
Default AI DisplayEnabledEnabledDraft: Enabled

THE CENTER

Key Findings

  1. All viewers use two-phase rendering - Non-blocking UX
  2. Consistent 4-tier color vocabulary - Unified visual language
  3. Map-based O(1) caching everywhere - Performance
  4. hunkMeta is a novel coordinate system - Unique contribution
  5. Draft node uses half-moon icon - Intuitive β€œin progress”
  6. Agent names in tooltip - Native browser tooltip