Files
waggle-os/docs/ux-refactor/wave-U-spec-2026-07-06.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

6.8 KiB

Wave U — R14-V2 convergent fixes: state honesty round 2 + felt interaction

R14-V2: design 7.5 · kw 7.4 · competitor 7.3 · a11y 7.2 · brand 7.5 (min 7.2, avg 7.38; V1 was 7.0/7.08 — the regime responds to fixes). This wave ships the seven convergent asks. Same vocabulary + honesty contract as waves P-T. Surgical; both themes; testids/aria survive. NO cross-lane files. Per-lane gate: related vitest green + eslint on touched files. Orchestrator: full gates + kit-v3 capture + R15-V3.

Verification context (read before "re-fixing" anything): the agents hover tier, bee response, chat action-row reveal, and marketplace NL bridge ALL work in the live product — R13/R14 capture scripts missed them (now fixed in kit v3). Wave U items below are the judges' ESCALATIONS, not regressions. Do not rebuild what Wave T built — strengthen exactly what each item names.

Lane A — workspace shelf loading truth (5/5 judges, HIGH)

Files: apps/AllWorkspacesApp.tsx (+test).

  1. The shelf renders "No workspaces yet — Create your first workspace" for ~0.5s before data lands. Loading, empty, and error are THREE distinct states: while the workspace query is unresolved, render 3 skeleton cards matching the fixed-slot card geometry (min-h 132, identity/tag/preview/metrics slot shimmer); the empty state (with its Create CTA) may render ONLY after a resolved, genuinely-empty answer. Follow the memory surface's cache pattern (memory-list-cache.ts): seed from session cache so a revisit shows last-known cards instantly.
  2. Card kebab + row affordances: visible at rest at low opacity (the chat action-row pattern from Wave T Lane E: rest ~0.6 → hover/focus-within 1.0) — hover-only reveal excludes keyboard/touch (a11y). Keep the existing hover tier as-is.

Lane B — briefing interruption discipline (4/5 judges, HIGH)

Files: os/AppShell.tsx (briefing gating only), os/overlays/LoginBriefing.tsx (numbers reconciliation only), tests.

  1. The "Catching you up" modal must fire ONLY on true session start AND only when Home is the landing surface. In-session navigation to Home (s02: Settings→Home) must never pop it. Gate on both (a) once per app session (in-memory flag, not localStorage — a new session should show it again) and (b) the first mounted surface being Home. When suppressed by (b), do NOT drop the content — the home hero already tells the story (judges call the modal+hero a "double catch-up").
  2. Numbers reconciliation: the modal says "2 workspaces" while the home hero says "6 workspaces waiting" — the modal filters test/canned workspaces, the hero doesn't (or vice versa). Find both sources, make them share ONE filtered count. Never present two different truths about the same store in the same viewport.

Lane C — marketplace NL: run the promise (4/5 judges)

Files: apps/MarketplaceApp.tsx, tests (+ the search box component if it lives in a marketplace-owned file — verify with grep; if the search box is shared outside marketplace, wire from MarketplaceApp side only).

  1. When the debounced query is natural-language (≥3 words) and name-filtering finds nothing: AUTO-RUN the semantic skill-match (the Search-button path) after a ~600ms settle, rendering ranked results inline under a quiet "Matched to your request" section label. No dead-end frame: while matching, show the BeeLoader (components/ui/BeeLoader.tsx) + "Matching skills to this job…".
  2. Restyle the no-match composition: kill the gray "No job matches … by name" line as the lead voice. If semantic matching also finds nothing, show 2-3 nearest catalog entries ("Closest in the catalog") + the Free Zone escape as a real button, not a text link.
  3. Keep the existing filter behavior for 1-2 word queries exactly as-is.

Lane D — boot warm-start (competitor HIGH)

Files: os/AppShell.tsx (boot hold logic), BootScreen component, tests.

  1. Returning users wait ~3.5s of branded boot before every session vs ~1s time-to-content on Claude/ChatGPT. The boot screen's minimum display time should be perceptual, not fixed: when the shell's data dependencies (onboarding known + briefing prefetch fired + workspace store warm) resolve early, exit boot at ~800ms-1s (enough for the brand moment, no dead air). Keep the current longer hold ONLY while dependencies are genuinely unresolved. Do NOT remove the boot screen or its choreography — shorten its floor.
  2. Verify the exit is choreographed (existing fade), not a hard cut, at the shorter floor. Reduced-motion: instant swap stays.

Lane E — a11y text floor + micro-motion tier (a11y HIGH + competitor)

Files: apps/agents/SuggestedAgentCards.tsx (text tokens only), apps/SettingsApp.tsx / model-gate/ModelGate.tsx (light amber tier labels only), apps/memory/MemoryCenterTab.tsx

  • apps/memory/MemoryTrustManage.tsx (tab-swap motion + loading skeleton only), tests. NOTE: this lane touches settings + memory files that no other Wave U lane touches — verify with git status before editing that no other lane claimed them.
  1. Agent-card second lines (the whisper tier) probe ~2.3:1 in dark — lift informative text to ≥4.5:1 both themes (token step, not new colors). Compute in lane notes.
  2. Light-theme amber tier labels in Model Pilot ("Primary/Fallback/Budget Saver") probe ~3.1:1 — one token step darker in light. Compute in lane notes.
  3. Memory "Loading memories…" generic spinner → skeleton rows (the surface's own row heights) with BeeLoader only if a full-surface wait is unavoidable.
  4. One micro-motion tier on panel swaps: Memory Trust↔Memories tab change gets a ~150ms fade-slide (motion-safe gated); same token timing as the Wave T hover tier. Do NOT add route-level transitions (out of scope).

Lane F — chat action row: Claude-level presence (4/5 judges, medium but daily)

Files: apps/ChatApp.tsx + the message action-row component, tests.

  1. The Wave T reveal works (verified) but under-reads: raise rest opacity one step (0.6 → 0.75), bump icon size 14→16px and row height accordingly, and give the revealed state a surface (subtle --surface-2 pill behind the icons) so the row reads as a toolbar, not floating glyphs. Keep the 150ms reveal + focus-within parity exactly as shipped.
  2. Send-button micro-pulse when it fills honey (brand ask): one ~200ms scale pulse on the empty→ready transition, motion-safe gated, once per transition (no loop).

Deferred

Memories-tab composition depth (needs product thought, not polish); route-level shared-element transitions; onboarding chip-style unification (design minor); BeeLoader adoption beyond marketplace/memory loading states.

Per-lane gate

Related vitest green + eslint; NO cross-lane files; contrast math in lane notes where demanded. Orchestrator after merge: web tsc + full vitest + browser QA + kit-v3 capture + R15-V3 judge round.