Foundations & UI
Nav Sheet Redesign
Post-ship refinement of the R&D Q Command Center: drop the redundant Home tab, restore live indicators to the bottom nav, remove the now-duplicate in-sheet segment toggle, and make the app-wide Q WebSocket honest about its connection state.
Situation
On-device feedback after shipping the Q Command Center flagged three UI issues: the bottom nav's Home tab is redundant (the feed is always the backdrop), the nav lost the running-count/active-loop indicators the old tray used to show, and the Intel/Loops sheet still carries its own segment toggle that now duplicates the nav's job.
A correctness gap rode along: the Q WebSocket only connected while R&D was open, so nav indicators couldn't be live app-wide, and a task delegated while Q was offline could sit unsent with no drain-on-reconnect.
Key decisions
Nav: Intel · Loops · R&D, no Home
Home is removed; tapping the already-active tab closes its surface back to the feed instead of opening it again.
Nav carries the indicators
Intel gets an amber "live" pill (running digs > 0), Loops an oxblood count badge (active loops > 0), R&D an oxblood queued badge plus a green Q-presence dot.
In-sheet toggle removed
The Intel|Loops tablist inside TraySheet is deleted — the nav is now the only segment switcher; the sheet just renders whichever segment it's opened to. R&D keeps its own fuller full-screen surface, unmerged.
App-wide Q socket
connectQ() moves from RndView's mount to the app-level mount so nav indicators stay live regardless of which surface is open; the DO is hibernatable so this is cheap.
Explicit WS connection states
A client state machine (connecting | online | q_offline | reconnecting) replaces an implicit connected/disconnected assumption, rendered truthfully in both the nav dot and the R&D presence chip.
Drain-on-connect
When the Q peer connects, the DO queries D1 for tasks still in awaiting_plan/approved and re-sends the corresponding delegate/approve frames, so a task assigned while Q was offline is never stranded.
Architecture
intelLive, loopsCount, rndQueued, presence) passed down from +page.runningCount(), active-loop count, rnd.sitrep.queued.length) and owns active-tab-closes nav logic.role="tablist" Intel|Loops toggle; body becomes a plain labelled region driven by the segment prop.connState store derived from WS lifecycle + DO presence frames; qsocket.ts exposes onopen/onclose lifecycle callbacks.awaiting_plan/approved tasks to the newly-connected Q peer.Risks & guardrails
Duplicate delegation on reconnect
Drain is guarded to only re-send tasks still in awaiting_plan/approved at drain time (re-queried, not cached), so a task already past that gate isn't re-driven; a mid-plan race is accepted as low-risk since Q simply re-plans.
Colour-only signalling
The green presence dot is decorative and paired with a text chip in R&D so state isn't conveyed by colour alone.
Focus/a11y after toggle removal
The sheet keeps its dialog semantics (trapFocus, Escape, scrim, restoreFocus) even after the tablist is removed — initial focus moves to the container or first item instead of a tab.
Delivery
Task 1
BottomNav — drop Home, add indicators + presence dot.
Task 2
+page wiring — active-tab-closes + indicator sourcing.
Task 3
App-wide socket + pure connection-state model.
Task 4
TraySheet — remove the in-sheet Intel|Loops toggle.
Task 5
Drain-on-connect (DO).
Task 6
Design-consistency + a11y pass + full verification.
Out of scope
docs/superpowers/specs/2026-06-17-rnd-nav-sheet-redesign-design.mdplan ·
docs/superpowers/plans/2026-06-17-rnd-nav-sheet-redesign.md