Files
foxhunt/docs/plans/2026-03-03-fxt-dashboard-design.md
jgrusewski 5b328750a4 docs: fxt dashboard & CLI completion design
Ratatui streaming dashboard (fxt watch) with 4 tabs, stub command
wiring plan, and new ApproveModel/RejectModel proto RPCs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:14:02 +01:00

6.2 KiB

FXT Dashboard & CLI Completion Design

Goal

Finalize fxt as a fully functional CLI with a live streaming dashboard (fxt watch) and all stub commands wired to real gRPC backends.

Workstream 1: fxt watch — Ratatui Streaming Dashboard

Architecture

Single-binary TUI using ratatui + crossterm. Event loop:

tokio::select! {
    msg = grpc_rx.recv()       => update state, mark dirty
    key = crossterm_events()   => handle tab switch / scroll / quit
    _ = tick_interval.tick()   => if dirty { render frame }
}

Tick rate: 200ms (5 fps). Only re-render when dirty.

Tabs

Tab 1 — Training (default)

┌─ Training ──────────────────────────────────────┐
│ Model    Epoch  Loss     LR       ETA   GPU     │
│ DQN      34/100 0.0023   1e-4     12m   78%     │
│ PPO      12/50  -0.451   3e-4     8m    82%     │
│ TFT      7/200  0.0891   5e-4     45m   91%     │
├─────────────────────────────────────────────────┤
│ Loss ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁▂▃▄▅  (last 200 epochs)   │
│ GPU% ████████████░░░░░░░░  78%                   │
└─────────────────────────────────────────────────┘

Feeds: StreamTrainingMetrics

Tab 2 — Trading

┌─ Trading ───────────────────────────────────────┐
│ Symbol   Side  Qty   Entry    PnL     Status    │
│ ES.FUT   LONG  2     5,432    +$340   OPEN      │
│ NQ.FUT   SHORT 1     19,876   -$120   OPEN      │
├─────────────────────────────────────────────────┤
│ Recent Fills                                     │
│ 14:32:01  BUY  ES.FUT  2 @ 5,432  FILLED       │
│ 14:31:45  SELL NQ.FUT  1 @ 19,876 FILLED       │
├─────────────────────────────────────────────────┤
│ Day PnL: +$220  |  Realized: +$580  Unreal: -$360│
└─────────────────────────────────────────────────┘

Feeds: StreamTradingUpdates

Tab 3 — Risk

┌─ Risk ──────────────────────────────────────────┐
│ Portfolio VaR (95%): $2,340    Max DD: -3.2%    │
│ Kelly Fraction: 0.34          Leverage: 1.8x    │
├─────────────────────────────────────────────────┤
│ Circuit Breakers                                 │
│ ● Daily Loss      OK    ($220 / $5,000 limit)  │
│ ● Drawdown        OK    (3.2% / 10% limit)     │
│ ● Volatility      OK    (VIX 18.3 / 40 limit)  │
│ ○ Kill Switch     ARMED                         │
└─────────────────────────────────────────────────┘

Feeds: StreamRiskMetrics

Tab 4 — System

┌─ System ────────────────────────────────────────┐
│ Service              Status    Latency   Uptime │
│ api-gateway          ● UP      2ms       14d    │
│ trading-service      ● UP      1ms       14d    │
│ ml-training          ● UP      3ms       6h     │
│ trading-agent        ● UP      1ms       14d    │
├─────────────────────────────────────────────────┤
│ GPU: ████████████░░░░ 78%  VRAM: 32/48 GB      │
│ CPU: ██████░░░░░░░░░░ 38%  RAM:  42/128 GB     │
└─────────────────────────────────────────────────┘

Feeds: StreamSystemHealth, StreamGpuMetrics

Key Bindings

1-4 switch tabs, j/k scroll, q quit

State Model

Single DashboardState with per-tab substates. Ring buffers (200 points) for chart data.

gRPC Streams

One tokio::spawn per stream, all feed a single mpsc::channel<StreamEvent>. Reconnect with exponential backoff (1s→30s).

Dependencies

ratatui = "0.29", crossterm = "0.28" in bin/fxt/Cargo.toml.

Workstream 2: Wire Stub Commands

A. Uncomment Only

Command Fix
fxt tune start --watch Uncomment pub mod tune_stream; in commands/mod.rs:27. Full implementation exists.

B. Wire to Existing RPCs

Command Current Fix
fxt model list Placeholder text Call MLTrainingService::ListModels. Display table.
fxt agent allocate-portfolio Hardcoded mock assets Replace mock block (agent.rs:192-212) with GetSelectedAssets(selection_id).
fxt auth login (non-interactive) Simulated JWT Use same LoginClient as interactive path, pass args.

C. New Proto RPCs

Command RPC Proto Request Response
fxt model approve ApproveModel ml_training.proto {model_id, promoted_to} {success, message}
fxt model reject RejectModel ml_training.proto {model_id, reason} {success, message}

Server handlers in ml_training_service/: move checkpoint, update DB status.

Workstream 3: Testing

  • Unit: state update functions with mock StreamEvent data
  • Unit: all fixed commands with mock gRPC servers
  • Integration: spawn mock server, run dashboard 2s, assert no panic
  • Existing tests: 134 fxt tests must stay green

Not In Scope

  • Custom themes / color configuration
  • Mouse support
  • Persisted layout preferences
  • Log file export from dashboard