Skip to main content

Cross-Viewer Integration

The Git and Wiki viewer systems achieve complete decoupling through shared base classes and IPC boundaries. Viewers communicate through inheritance and events, never direct imports.

Base Class Hierarchy

                     WikiBaseViewer (abstract)

            ┌─────────────────┼─────────────────┐
            │                 │                 │
     Protected Members        │      Protected Methods
     ──────────────────       │      ───────────────────
     container: Element       │      initBase()
     projectSlug: string      │      loadDocuments()
     category: string         │      loadDocumentContent()
     settings: Record         │      graduateDocument()
                              │      renderDocumentInline()
            ┌─────────────────┴─────────────────┐
            │                                   │
       ┌────┼────┬────┬────┬────┬────┐         │
       │    │    │    │    │    │    │         │
       ▼    ▼    ▼    ▼    ▼    ▼    ▼         │
     Onit Docs Prep Res Prove Uni ...          │

                     All inherit ALL
                     protected methods
All Wiki viewers inherit document loading, graduation workflows, and accordion rendering. The same pattern applies to Git viewers through GitBaseViewer.

IPC Command Consistency

┌──────────────────────────────────────────────────────────────┐
│  WIKI IPC COMMANDS                                           │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Command              │ Used By           │ Parameters      │
│  ─────────────────────┼───────────────────┼────────────────│
│  wiki_list_documents  │ All 6 WikiViewers │ { path, cat }  │
│  wiki_read_document   │ All 6 WikiViewers │ { path }       │
│  wiki_graduate_doc    │ Onit, Prep, Docs  │ { wip, slug }  │
│  load_folder          │ WikiResearch      │ { path, depth }│
│                                                              │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│  GIT IPC COMMANDS                                            │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Command              │ Used By           │ Parameters      │
│  ─────────────────────┼───────────────────┼────────────────│
│  git_full_refresh     │ GitTab            │ { path, limit }│
│  git_log              │ Multiple viewers  │ { path, ... }  │
│  git_blame            │ GitBlameViewer    │ { path, file } │
│  git_diff             │ GitDiffViewer     │ { path, hash } │
│  git_stash_*          │ GitStashViewer    │ { path, id }   │
│  git_reflog           │ GitReflogViewer   │ { path, limit }│
│  git_heatmap_data     │ GitHeatmapViewer  │ { path, since }│
│                                                              │
└──────────────────────────────────────────────────────────────┘

IPC Parameter Patterns

Pattern 1: Path Resolution All commands accept path: string as first parameter. The Rust backend resolves protocol paths internally via resolve_protocol_path_internal(). Pattern 2: Automatic Case Conversion TypeScript camelCase automatically converts to Rust snake_case:
{ wipPath: string, projectSlug: string }
Tauri IPC
{ wip_path: String, project_slug: String }
Pattern 3: Optional Parameters Rust uses Option<T> for optional fields, allowing frontend to omit parameters.

Tab Management Integration

┌──────────────────────────────────────────────────────────────┐
│  TAB MANAGER INTEGRATION                                     │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Method                               Returns                │
│  ────────────────────────────────────────────────────────────│
│  openFileInTab(path, focus)           tabId | null           │
│  setTabViewerType(tabId, type)        void                   │
│  getActiveContainer()                 HTMLElement | null     │
│  getActiveTabId()                     string | null          │
│  closeTab(tabId)                      void                   │
│                                                              │
│  Usage Pattern (shared by GitTab and WikiTab):              │
│  ────────────────────────────────────────────────────────────│
│                                                              │
│  1. Get tabManager                                           │
│  2. Create virtual path                                      │
│  3. openFileInTab(virtualPath)                               │
│  4. setTabViewerType(tabId, type)                            │
│  5. getActiveContainer()                                     │
│  6. Clear container                                          │
│  7. viewer.init()                                            │
│                                                              │
│  Virtual Path Patterns:                                      │
│  ──────────────────────                                      │
│  Git:  {repoPath}/.{viewerType}                              │
│        e.g., /path/to/repo/.git-dashboard                    │
│                                                              │
│  Wiki: wiki://{projectSlug}/{category}                       │
│        e.g., wiki://monolex-006/research                     │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Dependency Graph

                 ┌──────────────────┐
                 │  @tauri-apps/api │
                 │  (IPC Layer)     │
                 └────────┬─────────┘

     ┌────────────────────┼────────────────────┐
     │                    │                    │
     ▼                    │                    ▼
┌──────────────┐          │          ┌──────────────┐
│WikiBaseViewer│          │          │GitBaseViewer │
│(abstract)    │          │          │(abstract)    │
└──────┬───────┘          │          └──────┬───────┘
       │                  │                 │
  ┌────┼────┬────┬────┐   │   ┌────┬────┬───┼────┬────┐
  │    │    │    │    │   │   │    │    │   │    │    │
  ▼    ▼    ▼    ▼    ▼   │   ▼    ▼    ▼   ▼    ▼    ▼
Onit Docs Prep Res Prove  │ Blame Diff Stash Remote ...

                          └─────────────────┘

LEGEND:
  ─▶ = imports (allowed)
  ═══ = no cross-links between siblings (decoupled)

KEY OBSERVATIONS:
  • All arrows point DOWN/RIGHT (no circular deps)
  • No arrows between sibling viewers
  • Only upward dependency: Base + IPC
All viewers are decoupled - they import only their base class and IPC. No viewer imports another viewer directly.

Heatmap Color System

The heatmap visualization translates temporal data (commit ages) into immediate visual perception. Humans instantly identify “hot” areas of recent activity vs “cold” stable code.

HSL Color Space Architecture

┌──────────────────────────────────────────────────────────────┐
│  HSL COLOR SPACE FOR HEATMAP                                 │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  HSL = Hue, Saturation, Lightness                            │
│                                                              │
│  HUE WHEEL (degrees):                                        │
│  ────────────────────                                        │
│                                                              │
│         0°       60°      120°     180°     240°     360°    │
│         RED     YELLOW   GREEN    CYAN     BLUE     RED      │
│         │        │        │        │        │        │       │
│         ▼        ▼        ▼        ▼        ▼        ▼       │
│      ████     ████     ████     ████     ████     ████       │
│                                                              │
│  HEATMAP MAPPING (0° to 240° only):                          │
│  ──────────────────────────────────                          │
│                                                              │
│  Age: 0.0 ───────────────────────────────────── 1.0          │
│       (newest)                              (oldest)         │
│         │                                      │             │
│         ▼                                      ▼             │
│  Hue:  0°                                    240°            │
│       (RED)                                 (BLUE)           │
│         │                                      │             │
│         ▼                                      ▼             │
│      "HOT"                                  "COLD"           │
│   Recent changes                          Old/stable         │
│                                                              │
│  ████ ─── ████ ─── ████ ─── ████ ─── ████ ─── ████          │
│  RED     YELLOW   GREEN    CYAN     L-BLUE   BLUE            │
│  0°      60°      120°     180°     200°     240°            │
│                                                              │
│  FORMULA: hue = age * 240                                    │
│                                                              │
│    age = 0.0  → hue = 0   (red)                              │
│    age = 0.25 → hue = 60  (yellow)                           │
│    age = 0.5  → hue = 120 (green)                            │
│    age = 0.75 → hue = 180 (cyan)                             │
│    age = 1.0  → hue = 240 (blue)                             │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Age-to-Color Pipeline

// Normalize age to 0.0-1.0 range
const range = maxDate - minDate;
if (range === 0) {
  return `hsl(120, 70%, 50%)`; // All same date = green
}

// Calculate normalized age
const age = (maxDate - commitDate) / range;

// Map age to hue: 0 (red) to 240 (blue)
const hue = age * 240;

// Apply settings
const saturation = settings.colorSaturation || 70;
const lightness = settings.colorLightness || 50;

return `hsl(${hue}, ${saturation}%, ${lightness}%)`;

Visual Perception Mapping

Human Perception                AI Quantification
────────────────                ─────────────────

████████  "This is hot,         { age: 0.0, hue: 0,
(RED)     recently changed"       stability: "volatile" }

████████  "This is cold,        { age: 1.0, hue: 240,
(BLUE)    stable code"            stability: "stable" }

            ┌──────────────────┐
            │  FEEDBACK LOOP   │
            └─────────┬────────┘

  Color patterns guide both Human attention
  and AI stability analysis to the same areas

Blame Gutter Modes

The blame viewer supports three distinct gutter display modes with different information densities.

Mode Comparison

┌──────────────────────────────────────────────────────────────┐
│  MODE 1: COMPACT (minimal width ~80px)                       │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────┬──────────────────────────────────────────────┐│
│  │ Author   │ Line  Code                                   ││
│  ├──────────┼──────────────────────────────────────────────┤│
│  │ Alice    │  1    import React from 'react';             ││
│  │ Bob      │  2    import { useState } from 'react';      ││
│  │ Alice    │  3                                           ││
│  │ Claude   │  4    function App() {                       ││
│  └──────────┴──────────────────────────────────────────────┘│
│                                                              │
│  Fields: author (8 chars truncated)                          │
│  Use Case: Narrow screens, quick overview                    │
│                                                              │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│  MODE 2: STANDARD (balanced width ~160px)                    │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────┬────────────┬─────────────────────────────────┐│
│  │ Author   │ Date       │ Line  Code                      ││
│  ├──────────┼────────────┼─────────────────────────────────┤│
│  │ Alice    │ 2025-01-15 │  1    import React...           ││
│  │ Bob      │ 2025-01-10 │  2    import { useState...      ││
│  │ Alice    │ 2025-01-15 │  3                              ││
│  │ Claude   │ 2025-01-16 │  4    function App() {          ││
│  └──────────┴────────────┴─────────────────────────────────┘│
│                                                              │
│  Fields: author (12 chars) + date                            │
│  Use Case: Default view, balanced information                │
│                                                              │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│  MODE 3: DETAILED (full info ~320px)                         │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────┬────────┬─────────┬──────────┬────────────────┐│
│  │ Author   │ Date   │ Hash    │ Message  │ Line  Code     ││
│  ├──────────┼────────┼─────────┼──────────┼────────────────┤│
│  │ Alice    │ 01-15  │ abc1234 │ Add imp  │  1    import...││
│  │ Bob      │ 01-10  │ def5678 │ Add use  │  2    import...││
│  │ Alice    │ 01-15  │ abc1234 │ Add imp  │  3             ││
│  │ Claude   │ 01-16  │ ghi9012 │ Create   │  4    func...  ││
│  └──────────┴────────┴─────────┴──────────┴────────────────┘│
│                                                              │
│  Fields: author (15 chars) + date + hash + message           │
│  Use Case: Deep investigation, commit archaeology            │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Mode Implementation

private renderGutter(line: BlameLine): string {
  switch (this.settings.gutterMode) {
    case 'compact':
      return this.renderGutterCompact(line);
    case 'detailed':
      return this.renderGutterDetailed(line);
    case 'standard':
    default:
      return this.renderGutterStandard(line);
  }
}
Each mode has its own render function with different field selections.

Information Density Matrix

╔═══════════════════════════════════════════════════════════════╗
║  GUTTER MODE INFORMATION DENSITY                              ║
╠═══════════════════════════════════════════════════════════════╣
║                                                               ║
║  ┌─────────┬────────┬──────┬──────┬─────────┬──────────────┐ ║
║  │ Mode    │ Author │ Date │ Hash │ Message │ Est Width    │ ║
║  ├─────────┼────────┼──────┼──────┼─────────┼──────────────┤ ║
║  │ Compact │ 8 char │  -   │  -   │    -    │   ~80px      │ ║
║  │ Standard│ 12 chr │  Y   │  -   │    -    │   ~160px     │ ║
║  │ Detailed│ 15 chr │  Y   │ 7chr │  20chr  │   ~320px     │ ║
║  └─────────┴────────┴──────┴──────┴─────────┴──────────────┘ ║
║                                                               ║
║  SHARED ACROSS ALL MODES:                                     ║
║  ─────────────────────────                                    ║
║  ├── Same HSL color coding (age-based)                        ║
║  ├── Same line number display                                 ║
║  └── Same hover tooltips for truncated content                ║
║                                                               ║
╚═══════════════════════════════════════════════════════════════╝

Fresh Diff Computation

Diff viewer always computes fresh diffs via IPC, never using cached commit data. Each view request triggers a new Git computation.

Data Flow

┌──────────────────────────────────────────────────────────────┐
│  FRESH DIFF COMPUTATION - NO CACHING                         │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌────────────────┐                                          │
│  │  User Action   │                                          │
│  │  (View Commit) │                                          │
│  └───────┬────────┘                                          │
│          │                                                   │
│          ▼                                                   │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  TypeScript: loadDiff()                                │ │
│  │                                                        │ │
│  │  async loadDiff(): Promise<void> {                     │ │
│  │    // ALWAYS compute fresh diff via IPC - NO CACHING   │ │
│  │    const diffResult = await invoke<DiffResult>(        │ │
│  │      "git_show_commit_diff",                           │ │
│  │      { path: this.repoPath, commitHash }               │ │
│  │    );                                                  │ │
│  │                                                        │ │
│  │    this.diffData = diffResult;                         │ │
│  │    this.parseDiff(diffResult.diff);                    │ │
│  │    this.render();                                      │ │
│  │  }                                                     │ │
│  │                                                        │ │
│  │  ⚠️ NOTE: No cache check, no localStorage, no memo     │ │
│  └────────────────────────────────────────────────────────┘ │
│          │                                                   │
│          │ IPC invoke()                                      │
│          ▼                                                   │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  Rust: git_show_commit_diff                            │ │
│  │                                                        │ │
│  │  #[tauri::command]                                     │ │
│  │  pub fn git_show_commit_diff(path, commit_hash) {      │ │
│  │                                                        │ │
│  │    // FRESH: Open repository from disk                 │ │
│  │    let repo = Repository::open(path)?;                 │ │
│  │                                                        │ │
│  │    // FRESH: Find commit in actual Git objects         │ │
│  │    let commit = repo.find_commit(...)?;                │ │
│  │                                                        │ │
│  │    // FRESH: Compute diff tree-to-tree                 │ │
│  │    let diff = repo.diff_tree_to_tree(...)?;            │ │
│  │                                                        │ │
│  │    // Return computed diff (never cached)              │ │
│  │    Ok(DiffResult { ... })                              │ │
│  │  }                                                     │ │
│  └────────────────────────────────────────────────────────┘ │
│          │                                                   │
│          ▼                                                   │
│  ┌────────────────┐                                          │
│  │  Render Diff   │                                          │
│  │  (fresh data)  │                                          │
│  └────────────────┘                                          │
│                                                              │
│  CACHE ABSENCE PROOF:                                        │
│  ─────────────────────                                       │
│  ✗ No localStorage.getItem() in loadDiff()                   │
│  ✗ No Map/Object cache in viewer class                       │
│  ✗ No memoization wrapper                                    │
│  ✗ No conditional "if cached, return cache"                  │
│  ✓ ALWAYS invoke() IPC on every call                         │
│                                                              │
└──────────────────────────────────────────────────────────────┘
This ensures users always see the most current state of the repository without stale data.

Architectural Patterns

Four core patterns enable the cross-viewer system: Pattern 1: Abstract Base Class
  • Purpose: Share common functionality without coupling
  • Implementation: WikiBaseViewer, GitBaseViewer
  • Benefits: Single point of change, subclass focus on specific logic
Pattern 2: IPC Boundary
  • Purpose: Isolate frontend from backend implementation
  • Implementation: invoke() calls to Rust commands
  • Benefits: Backend changes don’t require frontend changes
Pattern 3: Virtual Path Tab Reuse
  • Purpose: Avoid duplicate tabs for same viewer/context
  • Implementation: Unique path patterns per viewer type
  • Benefits: Memory efficiency, consistent state
Pattern 4: Dynamic Import
  • Purpose: Load viewer code only when needed
  • Implementation: import() in viewerMap/switch statement
  • Benefits: Faster initial load, reduced memory footprint

THE CENTER

Cross-viewer integration and heatmap systems directly enable the Human ◈ AI feedback loop: TRANSPARENCY Complete Q.E.D proofs make all architectural claims verifiable. Humans can see exactly what was proven vs refuted. VISUALIZATION ASCII diagrams and code graphs present complex relationships in human-understandable form. Color systems translate temporal data into immediate perception. FEEDBACK The gap registry provides actionable items. Humans can direct AI to address specific gaps. Shared patterns allow improvements to propagate across all viewers. Integration is THE CENTER’s infrastructure - the plumbing that makes the Human ◈ AI feedback loop flow smoothly.

Verified Claims

  • Cross-viewer decoupling through base classes (Q.E.D)
  • IPC parameter consistency across all commands (Q.E.D)
  • HSL age-based color mapping (Q.E.D)
  • Blame gutter three modes implementation (Q.E.D)
  • Fresh diff computation without caching (Q.E.D)