> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monolex.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Git Backend Implementation

> Data processing pipelines, error handling, and optimization strategies

The Git backend implements sophisticated data processing pipelines that transform raw git data into frontend-ready structures for transparency visualization.

## Data Processing Pipelines

### Status Processing

```
╔════════════════════════════════════════════════════════════════════════════════╗
║                                                                                ║
║  STATUS PROCESSING PIPELINE                                                    ║
║                                                                                ║
╠════════════════════════════════════════════════════════════════════════════════╣
║                                                                                ║
║  INPUT: path (repository path)                                                 ║
║                                                                                ║
║  Step 1: Repository::open(path)                                                ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 2: Configure StatusOptions                                         │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   opts.include_untracked(true)                                          │   ║
║  │   opts.recurse_untracked_dirs(true)                                     │   ║
║  │   opts.include_ignored(false)                                           │   ║
║  │   opts.exclude_submodules(true)                                         │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  Step 3: repo.statuses(Some(&mut opts))                                        ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 4: Iterate and classify each entry                                 │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   for entry in statuses.iter() {                                        │   ║
║  │       let status = entry.status();                                      │   ║
║  │                                                                         │   ║
║  │       is_staged     │  is_unstaged   │  is_untracked                    │   ║
║  │       status.is_*   │  status.is_*   │  status.is_wt_new()              │   ║
║  │            │                │                │                          │   ║
║  │            v                v                v                          │   ║
║  │      staged.push     unstaged.push   untracked.push                     │   ║
║  │   }                                                                     │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 5: Get branch info + ahead/behind counts                           │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   branch = repo.head().shorthand()                                      │   ║
║  │   (ahead, behind) = get_ahead_behind(&repo)                             │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  OUTPUT: GitStatus {                                                           ║
║      branch, is_head_detached, ahead, behind,                                  ║
║      staged, unstaged, untracked                                               ║
║  }                                                                             ║
║                                                                                ║
╚════════════════════════════════════════════════════════════════════════════════╝
```

### Diff Parsing

The diff parser uses VTE callbacks to classify each line:

```
╔════════════════════════════════════════════════════════════════════════════════╗
║                                                                                ║
║  DIFF PARSING PIPELINE                                                         ║
║                                                                                ║
╠════════════════════════════════════════════════════════════════════════════════╣
║                                                                                ║
║  INPUT: path, file_path, staged (bool)                                         ║
║                                                                                ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 1: Setup diff options with pathspec                                │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   let mut diff_opts = DiffOptions::new();                               │   ║
║  │   diff_opts.pathspec(file_path);                                        │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 2: Get HEAD tree for comparison base                               │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   let head = repo.head()?;                                              │   ║
║  │   let head_tree = head.peel_to_tree()?;                                 │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 3: Choose diff method based on staged flag                         │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │                                                                         │   ║
║  │   if staged {                     } else {                              │   ║
║  │     diff_tree_to_index              diff_tree_to_workdir_with_index     │   ║
║  │   }                                 }                                   │   ║
║  │           │                                   │                         │   ║
║  │           v                                   v                         │   ║
║  │   Compare HEAD to index            Compare HEAD to working dir          │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 4: Parse diff using print callback                                 │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   diff.print(Patch, │delta, hunk, line│ {                               │   ║
║  │       match line.origin() {                                             │   ║
║  │           ┌────────────────────────────────────────────────┐            │   ║
║  │           │ Origin │ Line Type  │ Action                   │            │   ║
║  │           ├────────┼────────────┼──────────────────────────┤            │   ║
║  │           │ 'F'    │ "header"   │ File header              │            │   ║
║  │           │ 'H'    │ "header"   │ Hunk header              │            │   ║
║  │           │ '@'    │ "hunk"     │ Hunk marker              │            │   ║
║  │           │ '+'    │ "addition" │ Count additions          │            │   ║
║  │           │ '-'    │ "deletion" │ Count deletions          │            │   ║
║  │           │ ' '    │ "context"  │ Context line             │            │   ║
║  │           └────────────────────────────────────────────────┘            │   ║
║  │       }                                                                 │   ║
║  │   });                                                                   │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  OUTPUT: ParsedDiff {                                                          ║
║      path: file_path,                                                          ║
║      lines: Vec<ParsedDiffLine>,                                               ║
║      additions: count,                                                         ║
║      deletions: count                                                          ║
║  }                                                                             ║
║                                                                                ║
╚════════════════════════════════════════════════════════════════════════════════╝
```

### Commit Graph Generation

```
╔════════════════════════════════════════════════════════════════════════════════╗
║                                                                                ║
║  COMMIT GRAPH PIPELINE                                                         ║
║                                                                                ║
╠════════════════════════════════════════════════════════════════════════════════╣
║                                                                                ║
║  INPUT: path, limit (max commits to process)                                   ║
║                                                                                ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 1: Collect branch tips                                             │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   for branch in repo.branches()? {                                      │   ║
║  │       branch_tips.insert(tip_oid, branch_name);                         │   ║
║  │   }                                                                     │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 2: Walk commits from HEAD                                          │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   let mut revwalk = repo.revwalk()?;                                    │   ║
║  │   revwalk.push_head()?;                                                 │   ║
║  │   revwalk.set_sorting(Topological │ Time);                              │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 3: Assign columns to branches                                      │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │                                                                         │   ║
║  │   Column Assignment Algorithm:                                          │   ║
║  │   ┌───────────────────────────────────────────────────────────────────┐ │   ║
║  │   │  Column 0   │  Column 1   │  Column 2   │  Column N               │ │   ║
║  │   ├─────────────┼─────────────┼─────────────┼─────────────────────────┤ │   ║
║  │   │  main       │  feature-a  │  feature-b  │  ...                    │ │   ║
║  │   │  branch     │             │             │                         │ │   ║
║  │   └───────────────────────────────────────────────────────────────────┘ │   ║
║  │                                                                         │   ║
║  │   - Main branch gets column 0                                           │   ║
║  │   - Feature branches get 1, 2, ...                                      │   ║
║  │   - Reuse columns when branches merge                                   │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  ┌─────────────────────────────────────────────────────────────────────────┐   ║
║  │ Step 4: Build graph connections                                         │   ║
║  ├─────────────────────────────────────────────────────────────────────────┤   ║
║  │   for commit in commits {                                               │   ║
║  │       Condition            │ Connection Type                            │   ║
║  │       parents.len() > 1    │ "merge_left/right"                         │   ║
║  │       column changes       │ "branch_left/right"                        │   ║
║  │       otherwise            │ "straight"                                 │   ║
║  │   }                                                                     │   ║
║  └─────────────────────────────────────────────────────────────────────────┘   ║
║       │                                                                        ║
║       v                                                                        ║
║  OUTPUT: CommitGraph {                                                         ║
║      nodes: Vec<CommitGraphNode>,                                              ║
║      branches: Vec<BranchInfo>,                                                ║
║      total_commits,                                                            ║
║      max_columns                                                               ║
║  }                                                                             ║
║                                                                                ║
╚════════════════════════════════════════════════════════════════════════════════╝
```

## Error Handling

All errors are converted to String for IPC compatibility:

```
┌───────────────────────────────────────────────────────────────────────┐
│  ERROR HANDLING PATTERNS                                              │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  PATTERN 1: Direct conversion                                         │
│  ────────────────────────────                                         │
│  Repository::open(path).map_err(│e│ e.to_string())?                   │
│       └──► Error converted to String for IPC                          │
│                                                                       │
│  PATTERN 2: With custom context                                       │
│  ──────────────────────────────                                       │
│  Command::new("git")                                                  │
│       .output()                                                       │
│       .map_err(│e│ format!("Failed to run git: {}", e))?              │
│       └──► Add context to error message                               │
│                                                                       │
│  PATTERN 3: Check status and return stderr                            │
│  ──────────────────────────────────────────                           │
│  if !output.status.success() {                                        │
│       stderr = String::from_utf8_lossy(&output.stderr)                │
│       return Err(stderr.to_string())                                  │
│  }                                                                    │
│       └──► Capture git's actual error message                         │
│                                                                       │
│  All patterns ensure errors cross IPC boundary as readable strings    │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘
```

### Graceful Degradation

The backend returns partial data on non-critical errors:

```
╔═══════════════════════════════════════════════════════════════════════════════╗
║                                                                               ║
║  GRACEFUL DEGRADATION STRATEGY                                                ║
║                                                                               ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                               ║
║                    Operation                                                  ║
║                        │                                                      ║
║               ┌───────┴───────┐                                               ║
║               │               │                                               ║
║               v               v                                               ║
║            Success         Failure                                            ║
║               │               │                                               ║
║               v               v                                               ║
║           Use value      Try fallback 1                                       ║
║                              │                                                ║
║                      ┌───────┴───────┐                                        ║
║                      │               │                                        ║
║                      v               v                                        ║
║                   Success         Failure                                     ║
║                      │               │                                        ║
║                      v               v                                        ║
║                  Use value      Try fallback 2                                ║
║                                     │                                         ║
║                             ┌───────┴───────┐                                 ║
║                             │               │                                 ║
║                             v               v                                 ║
║                          Success         Failure                              ║
║                             │               │                                 ║
║                             v               v                                 ║
║                         Use value      Use default                            ║
║                                                                               ║
║  Result: Always return SOMETHING rather than fail completely                  ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝
```

## Data Transformation Chain

```
╔═══════════════════════════════════════════════════════════════════════════════╗
║                                                                               ║
║  DATA TRANSFORMATION CHAIN                                                    ║
║                                                                               ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                               ║
║  RAW GIT DATA                RUST PROCESSING              FRONTEND-READY      ║
║  ============                ===============              ==============      ║
║                                                                               ║
║  ┌────────────────────┐      ┌────────────────────┐      ┌──────────────────┐ ║
║  │ commit.author()    │ ───► │ GitCommitInfo.     │ ───► │ "John Doe"       │ ║
║  │ .name()            │      │ author             │      │                  │ ║
║  └────────────────────┘      └────────────────────┘      └──────────────────┘ ║
║                                                                               ║
║  ┌────────────────────┐      ┌────────────────────┐      ┌──────────────────┐ ║
║  │ commit.time()      │ ───► │ format_relative_   │ ───► │ "5m ago"         │ ║
║  │ .seconds()         │      │ time()             │      │                  │ ║
║  └────────────────────┘      └────────────────────┘      └──────────────────┘ ║
║                                                                               ║
║  ┌────────────────────┐      ┌────────────────────┐      ┌──────────────────┐ ║
║  │ diff.print()       │ ───► │ ParsedDiffLine     │ ───► │ Ready for CSS    │ ║
║  │ (raw callback)     │      │ with line_type     │      │ class binding    │ ║
║  └────────────────────┘      └────────────────────┘      └──────────────────┘ ║
║                                                                               ║
║  ┌────────────────────┐      ┌────────────────────┐      ┌──────────────────┐ ║
║  │ repo.branches()    │ ───► │ group_branches_    │ ───► │ "Today",         │ ║
║  │ (iterator)         │      │ by_time()          │      │ "Yesterday", ... │ ║
║  └────────────────────┘      └────────────────────┘      └──────────────────┘ ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝
```

## Optimization Strategies

### Batch API for IPC Reduction

Single call replaces 5 separate roundtrips:

```
BEFORE: 5 Separate IPC Calls
  - git_status
  - git_branches
  - git_log
  - worktree_list
  - stash_list

Total: 5 roundtrips, 5 repository opens

AFTER: Single Batch Call
  - git_full_refresh

Total: 1 roundtrip, 1 repository open

PERFORMANCE GAIN: ~5x reduction in IPC overhead
```

### Parsed Diff Optimization

```
BEFORE: Raw Diff + JS Parsing
  Backend sends raw diff string
  Frontend splits by lines, detects types, parses headers
  Cost: ~10ms per 1000-line diff

AFTER: Parsed Diff
  Backend sends ParsedDiff with line_type classification
  Frontend iterates array, applies CSS classes
  Cost: <1ms per 1000-line diff

PERFORMANCE GAIN: 5-10x improvement on large diffs
```

### Time Formatting in Rust

Relative time formatting moved from JavaScript to Rust:

| diff (seconds) | Output               |
| -------------- | -------------------- |
| \< 60          | "just now"           |
| \< 3600        | "{diff/60}m ago"     |
| \< 86400       | "{diff/3600}h ago"   |
| \< 604800      | "{diff/86400}d ago"  |
| \< 2592000     | "{diff/604800}w ago" |
| >= 2592000     | "YYYY-MM-DD" format  |

**Benefit**: Formatted strings sent over IPC, no JS computation

***

<Card title="THE CENTER" icon="circle-dot">
  These implementation patterns optimize for speed, structure, and completeness. Human should not wait to see AI work. Data must be ready for direct rendering. All relevant context must be included.
</Card>
