Component Overview
Work-Wiki provides three complementary visualization components, each operating at a different granularity:Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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:Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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:Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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:Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 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:| Viewer | Cache Property | Key Format |
|---|---|---|
| GitBlameViewer | aiAttributionCache | commit_hash |
| GitDiffViewer | hunkAttributions | filePath:hunkIndex |
| GitBranchDiagramViewer | commitWorkCounts | commit_hash |
Two-Phase Rendering
All three viewers implement the same pattern:Copy
┌───────────────────────────────────────────────────────────────────────┐
│ TWO-PHASE RENDERING PATTERN │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ loadData() │
│ │ │
│ ├──► PHASE 1: Core data (immediate) │
│ │ │ │
│ │ ├── invoke('core_command', ...) │
│ │ │ │
│ │ └── render() ─► User sees data immediately │
│ │ │
│ └──► PHASE 2: AI attribution (deferred, non-blocking) │
│ │ │
│ ├── fetchWorkWikiData(...) ─► Runs async │
│ │ │
│ └── .then() → render() ─► Re-render with AI data │
│ │
│ Result: Fast initial load, AI data appears without blocking │
│ │
└───────────────────────────────────────────────────────────────────────┘
Component Comparison
| Aspect | GitBlameViewer | GitDiffViewer | GitBranchDiagramViewer |
|---|---|---|---|
| Granularity | Line | Hunk | Commit |
| Cache Key | commit_hash | filePath:hunkIndex | commit_hash |
| Primary Visual | AI % indicator | Hunk AI badge | Micro-save badge |
| Novel Feature | Agent tooltip | hunkMeta coordinate | Draft node (half-moon) |
| Default AI Display | Enabled | Enabled | Draft: Enabled |
THE CENTER
Key Findings
- All viewers use two-phase rendering - Non-blocking UX
- Consistent 4-tier color vocabulary - Unified visual language
- Map-based O(1) caching everywhere - Performance
- hunkMeta is a novel coordinate system - Unique contribution
- Draft node uses half-moon icon - Intuitive “in progress”
- Agent names in tooltip - Native browser tooltip