Adds a real-time view of actual routing tasks to the TUI dashboard: backend: - events.py: in-memory decision-event broker (pure stdlib, thread-safe). Bounded ring buffer + fan-out queues. persist_route_decision publishes here after each write so the TUI sees decisions without polling. - dispatcher.py: GET /events/decisions SSE endpoint — replays recent decisions then streams live ones with :heartbeat keepalive. Wired into persist_route_decision's write path. tui: - tui.py: DashboardApp now consumes /events/decisions via a background thread (call_from_thread). Decisions table updates live without waiting for the 5s /metrics poll. New columns: id, kind, category, tier, ctx, selected, est $. Number keys 1-6 cycle panels. - tui_screens.py: DecisionDetailScreen modal — press Enter or e on any decision row to see the full JSON (runner-ups, rejected reason, feature flags, confidence, context size). - tui_model.py: pure data layer extracted from tui.py — build_model, build_category_breakdown, decision_row. Testable without a terminal. - tui_sse.py: background-thread SSE consumer with reconnect. 17 new tests (events broker, SSE endpoint, TUI data model, detail popup, live decision handling). 562 total, all passing. lsp_diagnostics clean.
1.9 KiB
1.9 KiB