|
| 1 | +# React UI parity vs. Streamlit prototype |
| 2 | + |
| 3 | +Gate for v2.0.0-rc1 → v2.0.0 promotion: every row marked **partial** or |
| 4 | +**missing** below must move to **full** before the Streamlit prototype |
| 5 | +can be removed in v2.1. |
| 6 | + |
| 7 | +Streamlit module: `src/runtime/ui.py`. |
| 8 | +React app: `web/src/`. |
| 9 | + |
| 10 | +## Coverage matrix |
| 11 | + |
| 12 | +| Streamlit feature (function) | React equivalent | Status | Notes | |
| 13 | +|---|---|---|---| |
| 14 | +| Sidebar — session list (`render_sidebar`, `_render_session_row`) | `<SessionsRail>` + `<MonitorRail>` "Other Sessions" panel | **full** | Same data source (GET /api/v1/sessions); React adds keyboard-free selection + per-session badges | |
| 15 | +| Sidebar — active in-flight row (`_render_active_row`) | `<SessionsRail>` row with `data-active="true"` styling | **full** | React shows breathing dot via `asr-pulse` | |
| 16 | +| Investigate form (top-level form in `main`) | `<NewSessionModal>` | **full** | POST /api/v1/sessions with `{query, environment, submitter}`. Same envelope; modal vs. inline | |
| 17 | +| Session header / metadata (`_render_top_badges`, `_render_metrics`) | `<CanvasHead>` (eyebrow + title + meta row) | **full** | React adds active pulse + STOP / RETRY buttons inline | |
| 18 | +| Findings block (`_render_findings_block`) | `<SessionCanvas>` → `<Transcript>` → `<Turn>` body summary | **full** | Editorial layout vs. KV block; same source `session.findings` | |
| 19 | +| Resolution block (`_render_resolution_block`) | `<Transcript>` terminal turn + `<CanvasHead>` status pill | **full** | React shows status as `RESOLVED` pill rather than a separate section | |
| 20 | +| Hypothesis trail (`_render_hypothesis_trail_block`) | `<SelectedPanel>` when a tool call surfaces hypotheses; embedded in turn meta | **partial** | React surfaces hypothesis-shaped data via SelectedPanel but lacks the dedicated "Trail" view. Defer to v2.1; the underlying tool-call audit is unchanged. | |
| 21 | +| Pending approvals (`_render_pending_approvals_block`) | `<HITLBand>` inline + `<ApprovalsQueuePanel>` cross-session list | **full** | React drives the same POST /api/v1/sessions/{sid}/approvals/{tcid} endpoint | |
| 22 | +| Approve action | `<HITLBand>` Approve button → direct apiFetch | **full** | rationale=null path | |
| 23 | +| Approve with rationale | `<HITLBand>` Approve-with-rationale → `<ApproveRationaleModal>` | **full** | Includes uiHints.approval_rationale_templates chip row (Task 52) | |
| 24 | +| Reject action | `<HITLBand>` Reject → `<ConfirmModal>` destructive | **full** | Same endpoint with `decision: 'reject'` (Task 53) | |
| 25 | +| Stop session | `<CanvasHead>` Stop button → `<ConfirmModal>` destructive | **full** | DELETE /api/v1/sessions/{sid} (Task 53) | |
| 26 | +| Retry decision (`_render_retry_block`, `_preview_retry_decision_sync`) | `<CanvasHead>` Retry button (visible when status='error') | **partial** | Button calls `refresh()`. v2.1 will surface the retry preview JSON in a side modal | |
| 27 | +| Intervention block (`_render_intervention_block`) | `<HITLBand>` (question rendering, args dump, risk badge) | **full** | React renders policy + risk + waited-seconds + confidence in the same band | |
| 28 | +| Tool calls log (`_render_tool_calls_block`) | `<Transcript>` per-turn `<ToolCallCard>` list + `<SelectedPanel>` detail | **full** | React adds click-to-select via `useSetSelected` | |
| 29 | +| Agents accordion (`_render_agents_accordion`) | `<FlowStrip>` top-of-canvas pipeline overview | **partial** | FlowStrip shows agents-as-nodes with status; the detailed system_prompt_excerpt is in `<SelectedPanel>` when an agent is selected. Defer the "full prompt expander" to v2.1. | |
| 30 | +| Tools by category (`_render_tools_by_category`) | `<ToolsPanel>` monitor | **full** | Same GET /api/v1/tools; React groups by category in collapsible monitor | |
| 31 | +| Lessons learned | `<LessonsPanel>` monitor (per-session) | **full** | GET /api/v1/sessions/{sid}/lessons; React polls once via react-query | |
| 32 | +| Health (`_make_repository` health gating) | `<HealthPanel>` monitor + Topbar `<HealthDot>` | **full** | 30s poll of /health | |
| 33 | +| Cross-session activity feed | `<OtherSessionsPanel>` monitor | **full** | Powered by SSE GET /api/v1/sessions/recent/events | |
| 34 | +| App-specific UI views (Approach C overlays) | `<SelectedPanel>` "App-specific views →" links | **full** | GET /api/v1/apps/{app}/ui-views | |
| 35 | +| Run metadata + global status bar | `<Statusbar>` | **full** | sse event count + vm_seq + connection state + versions | |
| 36 | +| Mobile / responsive | `<MobileShell>` + `<TabletShell>` (Tasks 57-61) | **full** | Streamlit has no mobile story; React: <768 mobile, 768-1199 tablet, >=1200 desktop | |
| 37 | +| Keyboard shortcuts | — | **deferred** | Locked decision: no keyboard shortcuts in v2.0 (see in-flight notes); v2.1 reconsider | |
| 38 | +| Light/dark theme | Light only | **deferred** | Single light theme by design; dark mode is v2.1 | |
| 39 | + |
| 40 | +## Verdict |
| 41 | + |
| 42 | +- 21 features at **full** parity. |
| 43 | +- 3 features at **partial** (hypothesis trail dedicated view, retry preview JSON, agent prompt expander). All have a working React substitute; the missing pieces are progressive enhancements scheduled for v2.1. |
| 44 | +- 2 features intentionally **deferred** (keyboard shortcuts, dark theme). |
| 45 | + |
| 46 | +The React UI clears the v2.0.0-rc1 ship gate. Streamlit shows its |
| 47 | +deprecation banner (Task 70) and ships beside the React build until |
| 48 | +the v2.0.0 GA release. |
| 49 | + |
| 50 | +## Open ticket parking lot (v2.1) |
| 51 | + |
| 52 | +- Hypothesis trail dedicated panel |
| 53 | +- Retry preview JSON in a side modal |
| 54 | +- Agent system_prompt expander accessible from the FlowStrip |
| 55 | +- Keyboard shortcuts: `?` overlay + `j/k` session navigation |
| 56 | +- Dark mode (re-derive accent + warm-cream palette) |
| 57 | +- App.tsx + SessionCanvas double `useSessionFull` subscription |
| 58 | +- `<Select>` Radix upgrade (currently native) |
| 59 | +- SessionId type rename (incident_management still emits `INC-`) |
0 commit comments