> ## 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.

# Complete Pipeline Architecture

> 10-stage rendering pipeline from PTY to User with control points marked

# Complete Pipeline Architecture

The Monolex terminal rendering pipeline consists of 10 distinct stages spanning three process boundaries. This document shows **where** each control mechanism operates and **why** both Hz Detection and ACK Gating are necessary.

## The Complete Pipeline

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│                     MONOLEX RENDERING PIPELINE (Accurate)                       │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [1] PTY DAEMON (pty-daemon-rust)                                       │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  Shell (bash/zsh) → PTY Master → Raw bytes                               │   │
│  │                                                                          │   │
│  │  • Always running (no gating here)                                       │   │
│  │  • Produces raw byte stream with ANSI escape sequences                   │   │
│  │  • Output rate depends on shell activity (ls, cat, etc.)                 │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     ▼ Unix Socket (per-session)                 │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [2] ATOMIC-STATE.feed() (Input Stage)                                  │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  Data Input Handler              │   │
│  │                                                                          │   │
│  │  ┌────────────────────────────────────────────────────────────────────┐ │   │
│  │  │  input_buffer.extend_from_slice(data)                              │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  ends_with_incomplete_sequence?                                    │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── YES → return (wait for more data)                        │ │   │
│  │  │       │                                                            │ │   │
│  │  │       └── NO → process_complete_data()                             │ │   │
│  │  │                    │                                               │ │   │
│  │  │                    ▼                                               │ │   │
│  │  │              ┌─────────────────────────────────────────┐           │ │   │
│  │  │              │  BSU/ESU Detection                      │           │ │   │
│  │  │              │  • detect_bsu() → syncing = true        │           │ │   │
│  │  │              │  • detect_esu() → syncing = false       │           │ │   │
│  │  │              │  • detect_cursor_visibility()           │           │ │   │
│  │  │              │  • detect_erase() → implicit_syncing    │           │ │   │
│  │  │              └─────────────────────────────────────────┘           │ │   │
│  │  └────────────────────────────────────────────────────────────────────┘ │   │
│  │                                                                          │   │
│  │  • Always runs when data arrives (no Hz gating)                          │   │
│  │  • Buffering ensures complete ANSI sequences                             │   │
│  │  • Sets sync flags that block pull()                                     │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     ▼                                           │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [3] VTE / ALACRITTY (Parse & Grid Storage)                             │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  VTE Parser Processing     │   │
│  │                                                                          │   │
│  │  ┌────────────────────────────────────────────────────────────────────┐ │   │
│  │  │  vte::Parser                                                       │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  Alacritty Term                                                    │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── handle_print() → Cell write                              │ │   │
│  │  │       ├── handle_csi() → Cursor move, erase, scroll                │ │   │
│  │  │       ├── handle_osc() → Title, colors                             │ │   │
│  │  │       └── handle_esc() → Modes, charset                            │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  Grid<Cell> (Ring buffer storage)                                  │ │   │
│  │  │       • history lines (scrollback)                                 │ │   │
│  │  │       • screen lines (viewport)                                    │ │   │
│  │  └────────────────────────────────────────────────────────────────────┘ │   │
│  │                                                                          │   │
│  │  • Always runs when feed() has complete data (no Hz gating)              │   │
│  │  • VTE parsing is CPU-intensive for large outputs                        │   │
│  │  • Grid is the source of truth for terminal state                        │   │
│  │  • Sets pending_data = true after processing                             │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     │ pending_data = true                       │
│                                     ▼                                           │
│                                                                                 │
│  ╔═════════════════════════════════════════════════════════════════════════╗   │
│  ║  [4] TICK INTERVAL (Hz Detection Control Point)                         ║   │
│  ║  ══════════════════════════════════════════════════════════════════════ ║   │
│  ║                                                                          ║   │
│  ║  Timer-driven update check                       ║   │
│  ║                                                                          ║   │
│  ║  ┌────────────────────────────────────────────────────────────────────┐ ║   │
│  ║  │                                                                    │ ║   │
│  ║  │   tick_interval = display_timing.frames(3)                         │ ║   │
│  ║  │                                                                    │ ║   │
│  ║  │   60Hz: frames(3) = 50ms  → tick 20x/sec                          │ ║   │
│  ║  │   30Hz: frames(3) = 100ms → tick 10x/sec                          │ ║   │
│  ║  │                                                                    │ ║   │
│  ║  │   ◄══ Hz DETECTION CONTROLS THIS GATE                              │ ║   │
│  ║  │       "How often do we even TRY to render?"                        │ ║   │
│  ║  │                                                                    │ ║   │
│  ║  └────────────────────────────────────────────────────────────────────┘ ║   │
│  ║                                                                          ║   │
│  ║  • This is the UPSTREAM control point                                    ║   │
│  ║  • Reduces frequency of ALL downstream operations                        ║   │
│  ║  • "Know beforehand, run slower"                                          ║   │
│  ║                                                                          ║   │
│  ╚════════════════════════════════════╦════════════════════════════════════╝   │
│                                       │                                         │
│                                       ▼ (on each tick)                          │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [5] ATOMIC-STATE.tick() (Timeout Checks)                               │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  Timeout Checker                           │   │
│  │                                                                          │   │
│  │  ┌────────────────────────────────────────────────────────────────────┐ │   │
│  │  │  Check sync_deadline (BSU timeout)                                 │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  Check implicit_deadline (erase pattern timeout)                   │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  Check cursor_hide_deadline (ink redraw timeout)                   │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  Check ack_deadline (ACK timeout → force unblock)                  │ │   │
│  │  └────────────────────────────────────────────────────────────────────┘ │   │
│  │                                                                          │   │
│  │  • Runs on every tick (frequency controlled by Hz)                       │   │
│  │  • Cost: ~33-55ns per call (very cheap)                                  │   │
│  │  • Clears expired deadlines to unblock pull()                            │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     ▼                                           │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [6] ATOMIC-STATE.pull() (Output Generation)                            │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  Output Generator     │   │
│  │                                                                          │   │
│  │  ┌────────────────────────────────────────────────────────────────────┐ │   │
│  │  │                                                                    │ │   │
│  │  │  ╔══════════════════════════════════════════════════════════════╗ │ │   │
│  │  │  ║  GATING CHECKS (return None if any true)                     ║ │ │   │
│  │  │  ╠══════════════════════════════════════════════════════════════╣ │ │   │
│  │  │  ║                                                              ║ │ │   │
│  │  │  ║  [Check 1] waiting_ack?      ◄── ACK CONTROL POINT          ║ │ │   │
│  │  │  ║            │                                                 ║ │ │   │
│  │  │  ║            └── "Frontend hasn't processed last frame yet"   ║ │ │   │
│  │  │  ║                                                              ║ │ │   │
│  │  │  ║  [Check 2] syncing?          ← BSU active                   ║ │ │   │
│  │  │  ║  [Check 3] cursor_hidden?    ← Ink redraw active            ║ │ │   │
│  │  │  ║  [Check 4] implicit_syncing? ← Erase pattern active         ║ │ │   │
│  │  │  ║  [Check 5] !pending_data?    ← Nothing new to send          ║ │ │   │
│  │  │  ║                                                              ║ │ │   │
│  │  │  ╚══════════════════════════════════════════════════════════════╝ │ │   │
│  │  │       │                                                            │ │   │
│  │  │       │ (all checks pass)                                          │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  build_update()                                                    │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── read_alacritty_grid()                                    │ │   │
│  │  │       │       └── Read all cells from Grid                         │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── compute line hashes                                      │ │   │
│  │  │       │       └── FxHash for each line                             │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── determine DiffHint                                       │ │   │
│  │  │       │       ├── Full (ybase changed)                             │ │   │
│  │  │       │       ├── Partial (some lines changed)                     │ │   │
│  │  │       │       ├── None (no changes)                                │ │   │
│  │  │       │       └── Skip (ybase oscillation)                         │ │   │
│  │  │       │                                                            │ │   │
│  │  │       └── Build GridUpdate struct                                  │ │   │
│  │  │                                                                    │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  waiting_ack = true  (block next emit until ACK)                   │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  return Some(GridUpdate)                                           │ │   │
│  │  │                                                                    │ │   │
│  │  └────────────────────────────────────────────────────────────────────┘ │   │
│  │                                                                          │   │
│  │  • Runs on every tick (frequency controlled by Hz)                       │   │
│  │  • Cost: ~200µs per call (expensive - hash computation)                  │   │
│  │  • ACK gating happens HERE, not at emit                                  │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     │ Some(GridUpdate)                          │
│                                     ▼                                           │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [7] EMIT (IPC Transmission)                                            │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  Send to Display                               │   │
│  │                                                                          │   │
│  │  ┌────────────────────────────────────────────────────────────────────┐ │   │
│  │  │  GridUpdate.to_binary()                                            │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼ Binary encoding (3.4x smaller than JSON)                   │ │   │
│  │  │                                                                    │ │   │
│  │  │  binary_channel.send(data)                                         │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼ Tauri Binary Channel (fast path)                           │ │   │
│  │  └────────────────────────────────────────────────────────────────────┘ │   │
│  │                                                                          │   │
│  │  • Only runs when pull() returns Some                                    │   │
│  │  • Cost: ~50µs per call (serialization + IPC)                            │   │
│  │  • NO additional gating here - all gating done in pull()                 │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     ▼ Tauri IPC                                 │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [8] WEBKIT / FRONTEND                                                  │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  Display Buffer Handler                                                │   │
│  │                                                                          │   │
│  │  ┌────────────────────────────────────────────────────────────────────┐ │   │
│  │  │  onGridUpdate(data)                                                │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  decodeBinaryProtocol()                                            │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ▼                                                            │ │   │
│  │  │  GridBufferInjector.inject()                                       │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── Write to xterm.js BufferLine arrays                      │ │   │
│  │  │       │       └── Direct buffer manipulation (22x faster)          │ │   │
│  │  │       │                                                            │ │   │
│  │  │       ├── Update ybase/ydisp                                       │ │   │
│  │  │       │                                                            │ │   │
│  │  │       └── renderService.refresh()                                  │ │   │
│  │  │                │                                                   │ │   │
│  │  │                ▼                                                   │ │   │
│  │  │       WebGL Renderer (requestAnimationFrame)                       │ │   │
│  │  │                │                                                   │ │   │
│  │  │                ├── RAF rate depends on system load                 │ │   │
│  │  │                ├── 60fps normal, 30fps under load                  │ │   │
│  │  │                └── This is what DisplayTiming measures             │ │   │
│  │  │                                                                    │ │   │
│  │  └────────────────────────────────────────────────────────────────────┘ │   │
│  │       │                                                                  │   │
│  │       ▼                                                                  │   │
│  │  invoke('ack_grid_update')  → sends ACK back to Rust                    │   │
│  │                                                                          │   │
│  └──────────────────────────────────┬──────────────────────────────────────┘   │
│                                     │                                           │
│                                     │ ACK                                       │
│                                     ▼                                           │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │  [9] USER                                                               │   │
│  │  ══════════════════════════════════════════════════════════════════════ │   │
│  │                                                                          │   │
│  │  👁️ Sees rendered terminal output                                        │   │
│  │                                                                          │   │
│  │  ⌨️ Types input → goes to PTY Daemon → Shell                             │   │
│  │                                                                          │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
```

## The Key Insight

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│                                                                                 │
│   Stages [1], [2], [3] are INPUT-DRIVEN (run when data arrives)                │
│                                                                                 │
│   Stages [4], [5], [6], [7] are TIMER-DRIVEN (run on tick)                     │
│                                                                                 │
│   ─────────────────────────────────────────────────────────────────────────    │
│                                                                                 │
│   Hz Detection controls the TIMER RATE                                          │
│   → Affects all timer-driven stages                                             │
│   → "How often do we poll for updates?"                                         │
│                                                                                 │
│   ACK Gating is a CONDITIONAL CHECK inside pull()                              │
│   → Only affects whether emit happens                                           │
│   → "Can we send this update?"                                                  │
│                                                                                 │
│   ─────────────────────────────────────────────────────────────────────────    │
│                                                                                 │
│   Without Hz Detection:                                                         │
│     tick() runs 20x/sec → pull() called 20x → ACK blocks 10x → emit 10x        │
│     → 10 "wasted" pull() calls (returned None)                                  │
│     → Rust CPU still processes 20 ticks/sec                                     │
│                                                                                 │
│   With Hz Detection:                                                            │
│     tick() runs 10x/sec → pull() called 10x → ACK rarely blocks → emit 10x     │
│     → 0 "wasted" pull() calls                                                   │
│     → Rust CPU only processes 10 ticks/sec (50% reduction)                      │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
```

## Control Point Summary

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│                         CONTROL POINTS IN PIPELINE                              │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  [1] PTY      [2] feed()    [3] VTE    [4] tick    [5] tick()   [6] pull()     │
│    ○─────────────○─────────────○──────────●──────────○────────────●─────────►   │
│                                           │                       │             │
│                              Hz Detection ┘            ACK Gating ┘             │
│                              (tick frequency)        (emit permission)          │
│                                                                                 │
│  ○ = Always runs (no gating)                                                    │
│  ● = Gated (controlled)                                                         │
│                                                                                 │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  Hz Detection Gate [4]:                                                         │
│  ─────────────────────                                                          │
│  • Controls HOW OFTEN we attempt to render                                      │
│  • 60Hz → 20 attempts/sec                                                       │
│  • 30Hz → 10 attempts/sec                                                       │
│  • Affects: [5] tick(), [6] pull(), [7] emit                                    │
│  • Savings: Rust CPU cycles                                                     │
│                                                                                 │
│  ACK Gate [6]:                                                                  │
│  ─────────────                                                                  │
│  • Controls WHETHER we can emit on this attempt                                 │
│  • waiting_ack=true → return None (no emit)                                     │
│  • waiting_ack=false → build update, emit                                       │
│  • Affects: [7] emit only                                                       │
│  • Savings: IPC calls, frontend overload prevention                             │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
```

## Scenario Comparison: 30fps Frontend

<Tabs>
  <Tab title="WITHOUT Hz Detection">
    ```
    ┌─────────────────────────────────────────────────────────────────────────────────┐
    │  WITHOUT Hz Detection (ACK only)                                                │
    ├─────────────────────────────────────────────────────────────────────────────────┤
    │                                                                                 │
    │  tick_interval = 50ms (fixed at 60Hz assumption)                                │
    │                                                                                 │
    │  Time    tick()   pull()           waiting_ack   emit()   Result                │
    │  ────────────────────────────────────────────────────────────────────────────   │
    │   0ms    ✓        → build_update   false→true    ✓        Frame sent            │
    │  50ms    ✓        → return None    true          ✗        WASTED TICK           │
    │ 100ms    ✓        → return None    true          ✗        WASTED TICK           │
    │ 110ms    [ACK received]            true→false              Unblocked             │
    │ 150ms    ✓        → build_update   false→true    ✓        Frame sent            │
    │ 200ms    ✓        → return None    true          ✗        WASTED TICK           │
    │ ...                                                                             │
    │                                                                                 │
    │  Result: 20 tick() calls/sec, only 10 useful                                    │
    │  Wasted: 10 tick() + 10 pull() attempts → unnecessary CPU                       │
    │                                                                                 │
    └─────────────────────────────────────────────────────────────────────────────────┘
    ```
  </Tab>

  <Tab title="WITH Hz Detection + ACK">
    ```
    ┌─────────────────────────────────────────────────────────────────────────────────┐
    │  WITH Hz Detection + ACK                                                        │
    ├─────────────────────────────────────────────────────────────────────────────────┤
    │                                                                                 │
    │  tick_interval = 100ms (adapted to measured 30Hz)                               │
    │                                                                                 │
    │  Time    tick()   pull()           waiting_ack   emit()   Result                │
    │  ────────────────────────────────────────────────────────────────────────────   │
    │   0ms    ✓        → build_update   false→true    ✓        Frame sent            │
    │  80ms    [ACK received]            true→false              Unblocked             │
    │ 100ms    ✓        → build_update   false→true    ✓        Frame sent            │
    │ 180ms    [ACK received]            true→false              Unblocked             │
    │ 200ms    ✓        → build_update   false→true    ✓        Frame sent            │
    │ ...                                                                             │
    │                                                                                 │
    │  Result: 10 tick() calls/sec, all 10 useful                                     │
    │  Wasted: 0 (tick interval matches ACK cycle)                                    │
    │                                                                                 │
    └─────────────────────────────────────────────────────────────────────────────────┘
    ```
  </Tab>
</Tabs>

## Per-Stage Cost Analysis

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│  COST DISTRIBUTION BY PIPELINE STAGE                                            │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  Stage [1-3]: PTY → Alacritty                                                   │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: Variable (depends on PTY output volume)                                  │
│  Controlled by: NEITHER (always runs when data arrives)                         │
│  Note: This is input-driven, not timer-driven                                   │
│                                                                                 │
│  Stage [4]: tick_interval.tick()                                                │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: ~5µs per wake (tokio timer wheel overhead)                               │
│  Controlled by: HZ DETECTION                                                    │
│  60Hz: 20 wakes/sec = 100µs/sec                                                 │
│  30Hz: 10 wakes/sec = 50µs/sec                                                  │
│                                                                                 │
│  Stage [5]: state.tick()                                                        │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: ~33-55ns per call (timeout checks)                                       │
│  Controlled by: HZ DETECTION                                                    │
│  60Hz: 20 calls × 55ns = 1.1µs/sec                                              │
│  30Hz: 10 calls × 55ns = 0.55µs/sec                                             │
│                                                                                 │
│  Stage [6]: state.pull() + hash computation                                     │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: ~200µs per call (grid read + hash calculation)                           │
│  Controlled by: HZ DETECTION                                                    │
│  60Hz: 20 calls × 200µs = 4ms/sec                                               │
│  30Hz: 10 calls × 200µs = 2ms/sec                                               │
│  Note: This is the MOST EXPENSIVE Rust-side operation                           │
│                                                                                 │
│  Stage [7]: waiting_ack check                                                   │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: ~1ns (single boolean check)                                              │
│  Controlled by: ACK GATING                                                      │
│  Note: Negligible cost, but determines emit() permission                        │
│                                                                                 │
│  Stage [8]: emit()                                                              │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: ~50µs per call (serialization + IPC)                                     │
│  Controlled by: BOTH (Hz limits frequency, ACK blocks when busy)                │
│  60Hz + ACK: ~10 calls × 50µs = 500µs/sec                                       │
│  30Hz + ACK: ~10 calls × 50µs = 500µs/sec                                       │
│                                                                                 │
│  Stage [9-10]: Frontend inject() + ack()                                        │
│  ═══════════════════════════════════════════════════════════════════════════   │
│  Cost: ~2ms per inject (buffer manipulation + WebGL render)                     │
│  Controlled by: ACK GATING (frontend processes at its own rate)                 │
│  Note: Limited by WebKit RAF rate, not by emit rate                             │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
```

## Cost Summary

| Operation     | Cost per Call | 60Hz Cost/sec | 30Hz Cost/sec | Savings      |
| ------------- | ------------- | ------------- | ------------- | ------------ |
| tick() wake   | \~5µs         | 100µs         | 50µs          | 50µs         |
| state.tick()  | \~55ns        | 1.1µs         | 0.55µs        | 0.55µs       |
| pull() + hash | \~200µs       | 4ms           | 2ms           | **2ms**      |
| emit attempt  | \~50µs        | 1ms           | 0.5ms         | 0.5ms        |
| **Total**     |               | **\~5.1ms**   | **\~2.55ms**  | **\~2.55ms** |

## Why Both Mechanisms Are Needed

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│                                                                                 │
│  Hz Detection alone:                                                            │
│  ───────────────────                                                            │
│  • Reduces tick frequency based on MEASURED display rate                        │
│  • But if measurement is wrong, could overwhelm frontend                        │
│  • Needs ACK as safety net                                                      │
│                                                                                 │
│  ACK alone:                                                                     │
│  ──────────                                                                     │
│  • Prevents frontend overload (backpressure)                                    │
│  • But Rust still does unnecessary work (wasted ticks)                          │
│  • Needs Hz Detection to reduce base rate                                       │
│                                                                                 │
│  Together:                                                                      │
│  ─────────                                                                      │
│  • Hz Detection = "Don't try too often" (proactive)                            │
│  • ACK = "Don't send if not ready" (reactive)                                  │
│  • Optimal efficiency with safety fallback                                      │
│                                                                                 │
│  ═══════════════════════════════════════════════════════════════════════════   │
│                                                                                 │
│  Hz Detection: "Know beforehand, run slower" (proactive rate adaptation)        │
│  ACK Only:     "Run fast, wait when blocked" (reactive backpressure)            │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘
```

## Analogy

| Mechanism        | Analogy                                                               |
| ---------------- | --------------------------------------------------------------------- |
| **Hz Detection** | Factory production speed control - "Produce only what can be shipped" |
| **ACK Gating**   | Shipping gate check - "Don't ship if warehouse is full"               |
| **Both**         | Lean manufacturing - match production to actual demand                |

## Summary

<CardGroup cols={2}>
  <Card title="9-Stage Pipeline" icon="diagram-project">
    From PTY daemon through Rust backend to WebKit frontend, each stage with specific responsibilities.
  </Card>

  <Card title="Two Control Points" icon="sliders">
    Hz Detection at Stage \[4] (upstream), ACK Gating at Stage \[6] (downstream).
  </Card>

  <Card title="Stage [6] Most Expensive" icon="microchip">
    pull() + hash computation costs \~200µs per call - the main target for Hz optimization.
  </Card>

  <Card title="50% Rust Savings" icon="arrow-down">
    60Hz to 30Hz reduces Rust-side cost from 5.1ms to 2.55ms per second.
  </Card>
</CardGroup>

## Related

* [Dual-Loop Architecture](/terminal/adaptive-timing/dual-loop) - Data Loop vs Render Loop
* [Control Layers](/terminal/adaptive-timing/control-layers) - Hz (Outer) vs ACK (Inner) in detail
* [Overview](/terminal/adaptive-timing/overview) - Adaptive timing system overview
