Spec: docs/superpowers/specs/2026-08-23-web-ui-rewrite-design.md § Client.
Depends on #536 (shell).
The bulk of the port: /setup, /activity, /insights, /rules, /venues, /gates as client views over #534's API, plus charts and live updates.
This issue is the parity gate. #540 and #541 delete the old renderers, and neither may proceed until this closes — D2 (#435) requires parity with the TUI's read surface before the write surface widens, and tests/commands/test_tui.py is the record of what each screen shows and when.
Charts
Hand-written SVG path generation. An equity curve is a polyline; a charting library does not clear the dependency bar, which admits code only when getting it wrong ourselves would undermine keel's principles — not when it would be convenient.
Live updates
EventSource (SSE), native. live.js owns the subscription and its reconnect behaviour. The agent runs daily, so this is for status and freshness rather than a ticking price feed — but a dashboard that silently goes stale is worse than one that says when it last heard anything, which is why as_of is in the payload.
/setup keeps its gate
/setup is the one view with a write surface today (#469), routing only through keel.commands.setup.ACTIONS. Porting it must not widen that by a single action, and the test asserting ACTIONS is disjoint from keel/capabilities.py's eleven capability-increasing actions stays green. A client that hides a button is not a gate; refusal is the server's job, with the #436 human gate in front.
Acceptance
Spec:
docs/superpowers/specs/2026-08-23-web-ui-rewrite-design.md§ Client.Depends on #536 (shell).
The bulk of the port:
/setup,/activity,/insights,/rules,/venues,/gatesas client views over #534's API, plus charts and live updates.This issue is the parity gate. #540 and #541 delete the old renderers, and neither may proceed until this closes — D2 (#435) requires parity with the TUI's read surface before the write surface widens, and
tests/commands/test_tui.pyis the record of what each screen shows and when.Charts
Hand-written SVG path generation. An equity curve is a polyline; a charting library does not clear the dependency bar, which admits code only when getting it wrong ourselves would undermine keel's principles — not when it would be convenient.
Live updates
EventSource(SSE), native.live.jsowns the subscription and its reconnect behaviour. The agent runs daily, so this is for status and freshness rather than a ticking price feed — but a dashboard that silently goes stale is worse than one that says when it last heard anything, which is whyas_ofis in the payload./setupkeeps its gate/setupis the one view with a write surface today (#469), routing only throughkeel.commands.setup.ACTIONS. Porting it must not widen that by a single action, and the test assertingACTIONSis disjoint fromkeel/capabilities.py's eleven capability-increasing actions stays green. A client that hides a button is not a gate; refusal is the server's job, with the #436 human gate in front.Acceptance
js/external/is still empty.EventSource; a dropped connection is visible, not silent./setupactions are unchanged in number and gating; the disjointness test is untouched.aria-liveregion where its content changes underneath a reader.tests/commands/test_tui.pyis recorded in the PR — it is what Delete the curses TUI — after parity, never before #541 depends on.