# UI overhaul session — 2026-03-21

## What we did

### ASCII banner
- Added a figlet-style "yslow" ASCII art banner displayed at startup in both modes.

### Restructured into `ui/` package
- Moved one-shot mode out of `__init__.py` into its own file.
- Created `ui/` package with:
  - `common.py` — shared console, banner, formatting helpers, probe rendering
  - `check.py` — one-shot mode (`check()`)
  - `watch.py` — continuous mode (`watch()`, `WatchState`, issue history)
- Created `runner.py` — `run_once()` extracted from UI code where it didn't belong.
- Renamed `MonitorState` → `WatchState`, `monitor()` → `watch()`, `oneshot()` → `check()` to match CLI verbs (`yslow` = check, `yslow -w` = watch).

### Snapshot tests
- Added `tests/test_snapshots.py` with `--snapshot-update` flag for regeneration.
- One snapshot file per scenario per mode (6 files in `tests/snapshots/`).
- Tests call the real `check()` and `render()` functions, capturing stdout — no knowledge of internal rendering structure.
- Uses `Console(color_system=None)` for plain-text snapshots (also tests the pipe-to-file path).
- Three scenarios: all good, one issue, everything failed.

### Swapped issue/probe ordering
- Both modes now show issues/status before probe detail stats.

### Migrated to rich
- Replaced hand-rolled ANSI escape codes with `rich.Console`.
- Colors: green checkmark for healthy, red warning for issues, yellow for unstable, dim for secondary info (banner, probes).
- `console.clear()` replaces raw `\033[2J\033[H`.
- Auto-strips formatting when piped to a file (rich's TTY detection).

### Spinners
- Replaced the countdown timer (`Next check in 30s`) with rich `console.status()` spinners.
- `checking...` spinner while probes run (both modes).
- `rechecking in {interval}s...` spinner while waiting (watch mode).

### Structured Issue model
- Split `Issue.description` into `location`, `problem`, `diagnosis` fields.
- Updated `diagnosis.py` with structured fields for all issue types.
- `Issue.message` property still produces a readable single-line string from the fields.

### Issue table (rich Table)
- Built `render_issues()` using `rich.Table` with columns: location, problem, diagnosis, value.
- Watch mode history table adds count + timing columns.

## Open question / next steps

The issue table and probe stats sections feel redundant — they show overlapping information (e.g., "LAN: high latency to gateway, 45ms" in the issue table vs "LAN: 45.0 ms rtt" in the probe stats). Unifying them into a single view would be cleaner but the right design isn't obvious yet. The table stuff may get reverted while this is figured out.

Possible directions:
- Single table that shows probes with inline issue annotations
- Issues as the primary view, probes only shown in a `--verbose` mode
- Probes as the primary table with issue indicators (color/icons) on problem rows
