P0 — collapse Quick/Full Chat into one adaptive Copilot and add screenshot CI #359

Open
opened 2026-09-08 02:03:39 +00:00 by nsaspy · 0 comments
Owner

Parent: #323
Research: docs/research/002-unified-copilot-voice-visual-ci.md
Start from current exact head; do not assume the research baseline remains HEAD.

Goal

Make Quick Copilot the canonical Zara desktop chat surface and establish deterministic screenshot evidence in the same first implementation slice.

This issue intentionally combines presentation consolidation with visual CI so every later UI iteration has inspectable rendered evidence.

Current defect

DesktopController owns both FullChatWindow and QuickCopilotWindow, synchronizes both against one ConversationService, and performs Quick -> Full handoff by opening the same conversation in another top-level window. The old design decision is no longer desired.

Quick also permanently renders redundant product/status chrome and only projects a bounded recent message subset.

Required architecture

Replace the normal two-chat-window path with one process-owned adaptive CopilotWindow or equivalent.

Presentation modes:

compact <-> expanded

Visibility remains ordinary show/hide state.

Requirements:

  • exactly one normal desktop chat renderer;
  • same conversation ID/messages/composer survive compact <-> expanded;
  • no message/context copying;
  • no Full Chat handoff action in the primary UX;
  • extract/reuse history/conversation-management functionality from windows/chat.py rather than losing it;
  • preserve daemon-client/QtRuntimeBridge boundary;
  • preserve cancellation, streaming, errors, provider/runtime state, tool/context integration points;
  • preserve close-to-hide behavior;
  • save compact and expanded geometry independently;
  • avoid brittle native-window flag churn; test any required flag transitions explicitly.

Native UI overhaul

Normal healthy compact mode should prioritize chat + composer.

Remove/demote permanent:

  • separate ZARA and Quick Copilot title chrome;
  • Full Chat button;
  • full-width healthy runtime rail;
  • unnecessary card shells/margins/gaps;
  • always-visible provider/model text when healthy.

Use:

  • natural conversation title;
  • compact connection/runtime indicator;
  • tight message grouping/readable max width;
  • bottom-anchored composer;
  • subtle accessible scroll behavior;
  • local turn/error state near affected content;
  • accessible names/focus/contrast for icon controls.

Screenshot CI

Add deterministic UI fixtures using fake conversation/runtime state only. No network, real daemon, provider, microphone, tray, or wall-clock-dependent content.

Qt supports rendering a widget tree to a pixmap via QWidget.grab(); pytest-qt also exposes widget screenshot support. Prefer the simplest deterministic repository-native approach.

Write stable artifacts under:

artifacts/ui/

At minimum generate:

  • copilot-empty-compact.png
  • copilot-short-chat-compact.png
  • copilot-long-wrap-compact.png
  • copilot-streaming.png
  • copilot-error.png
  • copilot-disconnected.png
  • copilot-tool-running.png
  • copilot-tool-approval.png
  • copilot-voice-listening.png
  • copilot-voice-partial.png
  • copilot-expanded.png
  • copilot-history.png
  • copilot-smallest-supported.png

Also emit artifacts/ui/manifest.json containing fixture/state, dimensions, theme, source commit and path.

Use a controlled Xvfb/Nix Qt+font environment for review renders when practical. Do not initially make byte-exact PNG equality the only gate.

Structural CI assertions

Hard-gate at least:

  • composer is visible and inside viewport at minimum size;
  • no key child controls overlap;
  • useful message viewport remains nonzero;
  • compact/expanded transitions preserve conversation and draft state;
  • history selection works in expanded mode;
  • long text is bounded/wrapped rather than widening/clipping the window;
  • runtime/error detail cannot create pathological geometry;
  • repeated mode transitions do not leak/recreate duplicate chat windows.

Always upload screenshot artifacts even on failure through the existing artifacts/ CI path.

Visual reviewer rubric

Record/review screenshots for:

  • excessive gaps;
  • clipping/overlap;
  • awkward message width;
  • hidden composer;
  • oversized chrome;
  • bad empty state;
  • duplicated status information;
  • broken resize behavior;
  • contrast/readability issues.

Qt behavioral tests are not sufficient evidence of visual quality.

Migration

Temporary compatibility wrappers are acceptable during the branch, but completion removes the normal process-owned FullChatWindow + QuickCopilotWindow duality.

Update the old desktop architecture documentation so it no longer claims separate Quick and Full windows are the target design.

TDD / RAGE

Follow .rage.toml Auto-RAGE from exact start SHA, RED-first tests, screenshot evidence, adversarial review, full repo/Nix gate and exact-head Actions.

Acceptance

A single Zara chat window can be summoned compactly and expanded into full history without handoff or duplicated renderer state, the UI is visibly tighter/native-feeling, and CI publishes deterministic screenshots for the required states.

Parent: #323 Research: `docs/research/002-unified-copilot-voice-visual-ci.md` Start from current exact head; do not assume the research baseline remains HEAD. ## Goal Make Quick Copilot the canonical Zara desktop chat surface and establish deterministic screenshot evidence in the same first implementation slice. This issue intentionally combines presentation consolidation with visual CI so every later UI iteration has inspectable rendered evidence. ## Current defect `DesktopController` owns both `FullChatWindow` and `QuickCopilotWindow`, synchronizes both against one `ConversationService`, and performs Quick -> Full handoff by opening the same conversation in another top-level window. The old design decision is no longer desired. Quick also permanently renders redundant product/status chrome and only projects a bounded recent message subset. ## Required architecture Replace the normal two-chat-window path with one process-owned adaptive `CopilotWindow` or equivalent. Presentation modes: ```text compact <-> expanded ``` Visibility remains ordinary show/hide state. Requirements: - exactly one normal desktop chat renderer; - same conversation ID/messages/composer survive compact <-> expanded; - no message/context copying; - no `Full Chat` handoff action in the primary UX; - extract/reuse history/conversation-management functionality from `windows/chat.py` rather than losing it; - preserve daemon-client/`QtRuntimeBridge` boundary; - preserve cancellation, streaming, errors, provider/runtime state, tool/context integration points; - preserve close-to-hide behavior; - save compact and expanded geometry independently; - avoid brittle native-window flag churn; test any required flag transitions explicitly. ## Native UI overhaul Normal healthy compact mode should prioritize chat + composer. Remove/demote permanent: - separate `ZARA` and `Quick Copilot` title chrome; - `Full Chat` button; - full-width healthy runtime rail; - unnecessary card shells/margins/gaps; - always-visible provider/model text when healthy. Use: - natural conversation title; - compact connection/runtime indicator; - tight message grouping/readable max width; - bottom-anchored composer; - subtle accessible scroll behavior; - local turn/error state near affected content; - accessible names/focus/contrast for icon controls. ## Screenshot CI Add deterministic UI fixtures using fake conversation/runtime state only. No network, real daemon, provider, microphone, tray, or wall-clock-dependent content. Qt supports rendering a widget tree to a pixmap via `QWidget.grab()`; `pytest-qt` also exposes widget screenshot support. Prefer the simplest deterministic repository-native approach. Write stable artifacts under: ```text artifacts/ui/ ``` At minimum generate: - `copilot-empty-compact.png` - `copilot-short-chat-compact.png` - `copilot-long-wrap-compact.png` - `copilot-streaming.png` - `copilot-error.png` - `copilot-disconnected.png` - `copilot-tool-running.png` - `copilot-tool-approval.png` - `copilot-voice-listening.png` - `copilot-voice-partial.png` - `copilot-expanded.png` - `copilot-history.png` - `copilot-smallest-supported.png` Also emit `artifacts/ui/manifest.json` containing fixture/state, dimensions, theme, source commit and path. Use a controlled Xvfb/Nix Qt+font environment for review renders when practical. Do not initially make byte-exact PNG equality the only gate. ## Structural CI assertions Hard-gate at least: - composer is visible and inside viewport at minimum size; - no key child controls overlap; - useful message viewport remains nonzero; - compact/expanded transitions preserve conversation and draft state; - history selection works in expanded mode; - long text is bounded/wrapped rather than widening/clipping the window; - runtime/error detail cannot create pathological geometry; - repeated mode transitions do not leak/recreate duplicate chat windows. Always upload screenshot artifacts even on failure through the existing `artifacts/` CI path. ## Visual reviewer rubric Record/review screenshots for: - excessive gaps; - clipping/overlap; - awkward message width; - hidden composer; - oversized chrome; - bad empty state; - duplicated status information; - broken resize behavior; - contrast/readability issues. Qt behavioral tests are not sufficient evidence of visual quality. ## Migration Temporary compatibility wrappers are acceptable during the branch, but completion removes the normal process-owned `FullChatWindow` + `QuickCopilotWindow` duality. Update the old desktop architecture documentation so it no longer claims separate Quick and Full windows are the target design. ## TDD / RAGE Follow `.rage.toml` Auto-RAGE from exact start SHA, RED-first tests, screenshot evidence, adversarial review, full repo/Nix gate and exact-head Actions. ## Acceptance A single Zara chat window can be summoned compactly and expanded into full history without handoff or duplicated renderer state, the UI is visibly tighter/native-feeling, and CI publishes deterministic screenshots for the required states.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/zara#359
No description provided.