Foundations & UI
UI Coherence
Makes the task-scoped Q conversation coherent with the home feed — gates the addressee selector out of non-home composers, fixes Q persona rendering, unifies auto-speak onto the shared TTS path, and matches the composer layout to home's.
Situation
Folding conversational Q into the home feed (Slice 1) exposed seams in the task-scoped Q chat that opens from the R&D Sit Rep: the addressee selector leaked into composers where it has no meaning, the Sit Rep still offered a redundant general "Talk to Q" entry, Q's persona/message-prop rendering was inconsistent with the feed, the plan block was always expanded, speech truncation clipped Q's replies too aggressively, and Q's auto-speak used the replay path instead of the shared TTS owner.
Grounding corrections surfaced during planning: truncateSpeech actually lives in the Worker repo (not web-only), and the composer's stacked-instead-of-row layout was a real missing display:flex, not a symptom worth dismissing.
Key decisions
Gate the addressee selector
Composer gains a showAddressee prop (default false); only the home feed passes true, so the selector no longer renders in the 4 non-home composers.
Remove the redundant general Q entry
The Sit Rep's openQConversation(null) "Talk to Q" button is deleted since general Q now lives in the home feed; task-scoped Q rows are unaffected.
Fix Q persona + message props
toMsg() now carries persona: 'q' and passes showMeta/streaming/clamped to MessageView, so Q's task chat renders consistently with the feed instead of a bare "MALLORY" byline.
Unify auto-speak onto speakText, not the turnRouter
Auto-speak swaps from togglePlay (replay path) to speakText, the same entrypoint the voice canvas uses — but the turnRouter/submit rewire is deliberately dropped since nothing reads turnRouter while the text panel is open (inert change, real risk of racing the canvas's own bind).
Soften speech truncation
truncateSpeech's default cap rises from 220 to 600 characters — a one-line Worker change (src/lib/qvoice.ts), the only non-web change in this pass.
Composer visually matches home
QConversation's .composer-wrap gets home's <footer> flex layout (display:flex; align-items:flex-end; gap:0.5rem) so mic/textarea/send sit in a row instead of stacking.
Architecture
showAddressee prop gating .addressee-bar.speakText auto-speak, matched composer layout.truncateSpeech default cap raised 220 → 600 (Worker, one-line change).Risks & guardrails
No surprise mic re-arm
speakText's re-arm branch only fires when voiceActive is true, which is false in the text panel, so swapping the TTS call introduces no unexpected mic behaviour.
Auto-speak seed preserved
The spokenId seed (last existing message id on mount) is kept so opening a task never speaks its historical tail — only newly-arrived lines.
turnRouter rewire explicitly dropped
Recorded in-spec so a later reader doesn't mistake the omission for an oversight: the only live-consumer divergence was the TTS path, so that's the only thing changed.
Delivery
Task 1
Worker — soften truncateSpeech default cap 220 → 600.
Task 2
Composer — gate the addressee selector behind showAddressee.
Task 3
RndView — remove the redundant general "Talk to Q" button.
Task 4
QConversation — Q persona, feed-consistent message props, unified auto-speak.
Task 5
QConversation — collapse the task plan block (collapsed by default).
Task 6
QConversation — make the composer lay out like the home footer.
Task 7
Verification — suites, type-check, browser behaviour + visual comparison.
Out of scope
docs/superpowers/specs/2026-06-22-ui-coherence-design.mdplan ·
docs/superpowers/plans/2026-06-22-ui-coherence.md