21 KiB
UX Disclosure Levels — Source-of-Truth Spec
Status: DRAFT r2 — generated by
/plan-design-review2026-05-07. r1 was the wrong direction (assumed flat sidebar layout). r2 documents the actual live UI: Mac-OS-style desktop with bottom dock + windowed apps. Approval pending. Drives: Phase 4.1 polish-sprint scope (filter onboarding to match existing dock-tier filtering) + Phase 4.2 PersonaSwitcher 2-tier work + downstream design polish work. Reference plan:~/.gstack/projects/marolinik-waggle-os/markomarkovic-main-design-20260506-175017.md
What this is
Waggle OS is a Mac-OS-style desktop running inside a Tauri 2.0 binary. The UI shell consists of:
- Desktop (
apps/web/src/components/os/Desktop.tsx) — full-bleed canvas - Bottom dock (
apps/web/src/components/os/Dock.tsx) — Mac-OS-style centered floating glass panel with app icons - Status bar (
apps/web/src/components/os/StatusBar.tsx) — top thin bar - Windowed apps (
apps/web/src/components/os/AppWindow.tsx) — apps open as draggable, resizable windows - Overlays (
apps/web/src/components/os/overlays/) — onboarding, persona switcher, workspace switcher, modals - Boot screen (
apps/web/src/components/os/BootScreen.tsx) — first-launch animation
The 3-level UX disclosure operates at the dock level: the dock filters which apps are visible based on the user's chosen UserTier (simple / professional / power), with an additional layer that hides specific entries below their minBillingTier (FREE / TRIAL / PRO / TEAMS / ENTERPRISE).
This spec documents that existing system as canonical and identifies gaps to close before pilot.
Naming alignment
Three names referenced different things historically:
Internal enum (UserTier) |
Display label (TIER_OPTIONS) | Brownfield doc name | This spec |
|---|---|---|---|
simple |
Essential | "simple" | Essential (simple) |
professional |
Standard | "advanced" | Standard (professional) |
power |
Everything | "pro" | Everything (power) |
Plus admin (UserTier only) which currently aliases to power's dock config.
Source of truth: apps/web/src/lib/dock-tiers.ts (TIER_DOCK_CONFIG const). Display labels were renamed in QW-5 to avoid collision with billing tiers (Pro $19, Teams $49). Internal enum values stay simple/professional/power for backward compatibility with stored user preferences.
Default
New user starts at Essential. The 8-step onboarding wizard's TierStep (step 3) preselects Essential. Trial users get the same Essential default with reveal moments to Standard. Power is opt-in only via Settings → Display.
Dock contents — already implemented in dock-tiers.ts
This is the EXISTING canonical filtering. Spec's job is to document and audit.
Essential (simple) — 5 dock items (verified)
TIER_DOCK_CONFIG.simple = [
{ key: 'home', appId: 'dashboard', icon: LayoutDashboard, label: 'Home', color: 'text-sky-400' },
{ key: 'chat', appId: 'chat', icon: MessageSquare, label: 'Chat', color: 'text-primary' },
{ key: 'files', appId: 'files', icon: FolderOpen, label: 'Files', color: 'text-amber-300' },
{ type: 'separator' },
{ key: 'vault', appId: 'vault', icon: Lock, label: 'Vault', color: 'text-amber-400' },
{ key: 'system', appId: 'settings', icon: Settings, label: 'Settings', color: 'text-muted-foreground' },
]
5 items + 1 separator. Memory is NOT in Essential — it's deliberately gated to Standard+ because the discovery moment for "Waggle remembers everything" is the chat surface (where context-restore + login briefing happens), not a separate Memory app.
Standard (professional) — 7 dock items (verified)
Adds Personas (agents) + Memory between Files and Vault. Same 5 from Essential plus:
{ key: 'agents', appId: 'agents', icon: Bot, label: 'Personas', color: 'text-orange-400' }, // after chat
{ key: 'memory', appId: 'memory', icon: Brain, label: 'Memory', color: 'text-amber-300' }, // after separator
Everything (power) — full configuration
Power dock adds Room, Waggle Dance, two zone-parents (Ops + Extend) with collapsible trays, plus Approvals (TEAMS-only) above Vault.
- Ops zone-parent (tray): Command Center, Timeline, Usage & Cost, Events & Logs, Scheduled Jobs
- Extend zone-parent (tray): Skills & Apps, Connectors, Team Governance (TEAMS-only)
- Plus Approvals (TEAMS-only)
Marketplace is a TAB inside Skills & Apps (per P31 comment), not a separate dock item — the spec leaves it that way.
Billing tier filtering layer
Per-entry minBillingTier runs ON TOP of UserTier filtering. Examples already in code:
governancerequiresTEAMSapprovalsrequiresTEAMS
Phase 4.1 may need to add minBillingTier: 'PRO' to dock entries for Pro-only features (skills marketplace? custom personas? — TBD per Open Q1 below).
Onboarding wizard — 8 steps already exist (audit)
Files: apps/web/src/components/os/overlays/onboarding/{Welcome, WhyWaggle, Tier, Import, Template, Persona, ApiKey, Ready}Step.tsx
| # | Step | Current behavior | Phase 4.1 audit |
|---|---|---|---|
| 1 | welcome | Hero card + brand + CTA | OK |
| 2 | why-waggle | 3 value props: Remembers everything / Workspace-native / Real tools | OK |
| 3 | tier | Pick Essential / Standard / Everything (Essential preselected) | OK — uses TIER_OPTIONS |
| 4 | memory-import | ChatGPT/Claude/Gemini/Perplexity/Cursor/Claude Code import + auto-detect | OK |
| 5 | template | Currently shows ALL 15 templates | GAP — should filter by tier |
| 6 | persona | Currently shows ALL 19 onboarding personas via getPersonasForTemplate() |
GAP — should filter by tier |
| 7 | api-key | Provider + key + vault auto-detect | OK; add Ollama default in Phase 4.1 (Open Q from brownfield doc) |
| 8 | ready | Summary + first-task + open workspace | OK |
The Phase 4.1 unblock is consistency: dock filters to 5 items at Essential, but onboarding template + persona steps show ALL options regardless of tier. That's an internal inconsistency the user feels — they pick Essential at step 3, then step 5 throws 15 templates at them.
Templates — filter for Essential — 3 of 15
When selectedTier === 'simple', TemplateStep.tsx should default to showing 3 templates with a "Show all 15 templates" toggle:
| ID | Display | Why at Essential | Recommended persona |
|---|---|---|---|
agency-consulting |
Consulting | Marko's archetype, Ljiljana's role, broadest professional services match | consultant |
research-project |
Research Hub | Universally useful (HR research, market research, due diligence) | researcher |
blank |
Blank Workspace | Universal escape — any user who doesn't fit a category | general-purpose |
The other 12 templates remain available via "Show all" toggle (no hard gating — users at Essential who want their domain template aren't blocked). Standard and Everything see all 15 by default.
Personas — filter for Essential — 4 of 22 (matches tier field already in code)
ALL_ONBOARDING_PERSONAS already declares 3 cohorts via the tier field:
tier='universal'(1): general-purposetier='knowledge'(4): researcher, writer, analyst, codertier='domain'(14): project-manager, executive-assistant, sales-rep, marketer, product-manager-senior, hr-manager, legal-professional, finance-owner, consultant, support-agent, ops-manager, data-engineer, recruiter, creative-director
When selectedTier === 'simple', PersonaStep.tsx should show universal + knowledge cohorts (5 personas: general-purpose, researcher, writer, analyst, coder) PLUS the recommended persona for the selected template (e.g. consultant if Consulting selected). getPersonasForTemplate() already does the recommended-first ordering — no logic change needed, just filter to universal+knowledge tiers when selectedTier === 'simple'.
Decision needed (Open Q): coder at Essential — keep or drop? Coder is in
tier='knowledge'cohort. Marko's quote: "this is not the target, unless you identify this tool can be useful for coders too, which I don't believe." Recommend dropping coder from Essential default (drop thetier='knowledge'filter to "knowledge minus coder" or renamecodertotier='domain'). Result: 4 personas at Essential (general-purpose, researcher, writer, analyst) + recommended-from-template.
The other 14 domain personas + 3 hidden meta-personas (planner, verifier, coordinator) stay accessible at Standard+.
planner, verifier, coordinator remain hidden from ALL_ONBOARDING_PERSONAS entirely (they're orchestration meta-personas, not user-facing).
Settings app — filter sections per tier
Current state: SettingsApp.tsx shows all sections regardless of UserTier. Phase 4.1 adds level filtering.
Settings at Essential
| Section | Shown |
|---|---|
| Profile | ✅ |
| Models (provider, API key, Ollama on/off) | ✅ |
| Display (theme, level toggle) | ✅ |
| Memory (view-only stats, opt-out delete path) | ✅ |
| Billing/Subscription | ✅ if user is Trial/Pro/Teams |
Hidden at Essential (visible at Standard+): Tools, Skills, Connectors, Personas (manage), MCP servers, Telemetry, Compliance (Everything+), Evolution (Everything+), Vault management (auto-managed at Essential), Team (TEAMS-only).
Display panel — the level toggle
Level toggle UI: 3-card chooser using existing TIER_OPTIONS array. Currently lives in TierStep.tsx for onboarding; Phase 4.1 adds the same chooser to Settings → Display so users can switch level post-onboarding.
Skills + connectors at Essential — personalize, don't cap
Reframe (2026-05-08, Marko): the previous version of this section proposed pre-installing only 5 skills + 3 connectors at Essential. That framing is wrong. Hiding 13 of 18 skills doesn't simplify — the agent already loads all 18 invisibly so the capability ceiling is unchanged either way; the user just feels it has less. Hiding 145 of 148 connectors doesn't simplify — connectors are zero-installed by default and only activate on user OAuth, so the configuration burden is identical either way; the user just can't find Linear or GitHub when they have those accounts. Capability is never the simplification target. Discoverability + first-screen relevance is.
Skills (built-in) — all 18 stay loaded
The starter pack at packages/sdk/src/starter-skills/ ships 18
skills that are auto-installed on first run by
packages/server/src/local/routes/skills.ts:54-63. They are loaded into
the agent regardless of tier. No tier-based gating on the loaded set.
What CAN vary by tier:
- Display surface of the skills picker UI (Settings → Skills tab, marketplace tab visibility) — currently TIER_DOCK_CONFIG already gates the marketplace dock entry.
- In-chat skill suggestions ("Try
draft-memofor that?") can be persona-aware so a Coder getscode-reviewand a Consultant getsresearch-synthesiswithout scrolling. Implementation: future Phase 4c — chat skill hint surface.
Connectors (MCP catalog) — all 148 reachable, recommendation per persona
The MCP catalog at packages/shared/src/mcp-catalog.ts has 148
connectors across 14 categories. Default install state: zero. Every
connector requires user OAuth.
What changes by persona (not by tier): the connector landing surface
inside ConnectorsApp + the optional onboarding "which tools?" step
recommend a primary set of 3–5 connectors based on the user's chosen
template + persona. Source of truth:
packages/shared/src/connector-recommendations.ts + the recommendConnectors()
helper. The full 148 stay browseable and searchable at every tier.
Examples (full table in connector-recommendations.ts):
| Persona | Primary recommendation |
|---|---|
| consultant | notion-mcp, gdrive-mcp, gmail-mcp, slack-mcp, figma |
| coder | github-mcp, slack-mcp, linear-mcp, sentry, gdrive-mcp |
| sales-rep | hubspot-mcp, salesforce-mcp, slack-mcp, gmail-mcp, notion-mcp |
| analyst | bigquery, postgres, gdrive-mcp, notion-mcp, excel |
| general-purpose / planner / verifier / coordinator | gdrive-mcp, gmail-mcp, notion-mcp (universal defaults) |
Validation: every recommended ID is asserted to exist in the catalog by
packages/shared/tests/connector-recommendations.test.ts. A typo'd or
removed connector ID is caught at CI before it ships an empty tile.
Net effect on the user
- A consultant who picked Essential during onboarding still has all
148 connectors reachable via
ConnectorsApp → All. The first thing they SEE is just notion / gdrive / gmail / slack / figma — the five most likely to matter for that role. - The same consultant on Standard or Everything sees the same 5 first; the only difference between tiers is which dock items are visible (chat / files / home / vault / settings + memory + agents at Standard + ops console + marketplace at Everything). Connector capability is identical across tiers.
Empty / loading / error / partial states for Essential surfaces
For each of the 5 dock-visible apps at Essential, specify what user sees in non-happy states.
Home (Dashboard) — Day 1, just after onboarding
- Empty: Grid layout with: workspace name + persona name top-left, "What's on your mind?" with chat input placeholder, 3 starter-prompt chips drawn from
TEMPLATES[selected].hint+ persona'sbestFor[0]example, "Waggle is learning your work" memory hint card. NOT "No items found." - Returning user: WorkspaceBriefing card shows context recap from last session ("Last session: drafted HR policy v3, saved 8 frames").
- Loading: subtle skeleton (matches existing chat shimmer pattern from M2-7).
- Error (memory unavailable): "Memory layer is initializing. You can start chatting; Waggle will remember once memory is ready." + retry button. NEVER show stack trace at Essential.
Chat (in-window app)
- Empty (new conversation): persona-aware welcome line (e.g. for consultant: "Hi — I'm here for your client work. What are we tackling?") + 3 quick-start chips from persona's
bestFor. - Loading (LLM call in flight): existing shimmer pattern.
- Error (API key invalid): "Looks like the API key needs attention. [Open Settings]" — NOT a 500 stack.
- Error (LLM rate limit / 429): "The model is busy. Trying again in 5s..." with retry counter.
- Error (network down): "Lost connection. Your message is saved; will retry when back online." + offline indicator.
Files
- Empty: "Drop files here, or browse from your computer." Drag-drop hint + button. (FileUploadZone component already exists.)
- Loading: skeleton rows.
- Error (storage quota): "You're using X of Y. Free tier supports Z files. [Upgrade]" — visible only when tier is Free + close to quota.
Vault (Essential)
- Empty: "Your API keys live here, encrypted on your device." + "Add a key" button.
- Editing: keys masked by default; reveal-on-click with confirmation.
Settings
- API key invalid: inline error on the field, not a modal. "Key looks invalid — try again." + provider docs link.
- Memory purge confirmation: double-confirm dialog with "Type DELETE to confirm" pattern (untechnical-but-decisive UX, prevents accidents). Required for pilot data handling per brownfield doc.
- Level switch (Essential → Standard): confirmation + "You'll see more apps in your dock. Switch back anytime in Settings → Display."
Responsive + a11y posture
Day 0 stance: Desktop-only (Win + Mac). Tauri binary. NO mobile/tablet responsive promises in launch comms. Dock has horizontal scroll fallback at <768px viewports (already implemented per L-01/R-1 comment in Dock.tsx:72).
A11y at Essential — non-negotiable (most already implemented):
- Existing Esc-to-skip in OnboardingWizard (verified at line 81) — keep
- Existing dock label visibility for new users (
useDockLabels<20 sessions or <7 days) — keep - Tab order: status bar → dock → desktop → workspace context
- Focus visible on every interactive element (waggle-theme.css ring tokens)
- 4.5:1 contrast minimum on body text — light mode currently broken (P0 from brownfield doc), must fix in Phase 4.1
- Touch targets: 44px min
- Screen reader landmarks:
<main>(Desktop),role="toolbar"(Dock),aria-labelper dock entry - Memory + workspace state announce on switch (
aria-live="polite")
Reveal moments — how a user discovers Standard / Everything
Three reveal triggers (least intrusive first):
- Tooltip on first attempt to access a hidden feature. E.g. user tries to spawn a multi-agent group from Chat — sees "Multi-agent groups need Standard. [Try Standard]". Standard switch is one-click + reversible.
- Settings → Display level toggle with
TIER_OPTIONSchooser — same UI as TierStep in onboarding. - Soft nudge after 7 days of consistent use: "You've been using Waggle daily. Standard adds Personas + Memory + agent workflows. Try it for 7 days." Dismissible. Once-per-user-lifetime.
Power level is opt-in only — never nudged. User must navigate Settings → Display → Everything explicitly.
What this spec does NOT cover (out of scope)
- Visual mockups of dock + windowed apps — the live UI is the visual reference; downstream
/design-reviewruns on the live binary. - Pixel-level component design — handled by
/design-consultation(recommend running before Phase 4.1 implementation). - Marketing-page (apps/www) design — separate spec.
- Tier billing UX (free vs Pro vs Teams) — handled by upgrade modal redesign (Phase 4.1 must-have, separate from level disclosure).
- New apps — this spec only covers filtering existing apps; the 26 existing apps are out of scope for "what to add."
Acceptance criteria
This spec is approved when:
- Marko reviews and signs off on the named selections (3 templates / 4 personas at Essential) and the Open Q answers.
- Phase 4.1 implementer has enough specificity to implement: (a) filter
TEMPLATESinTemplateStep.tsxwhentier === 'simple', (b) filterALL_ONBOARDING_PERSONASbytierfield whentier === 'simple', (c) filterSettingsApp.tsxsections per tier, (d) write empty/loading/error copy for the 5 Essential surfaces. - Open Questions 1-3 resolved.
Open Questions
- Coder at Essential — keep or drop? Recommend drop; Marko's quote supports it.
Pre-installed skills exact selection. 5 listed; confirm or swap.CLOSED 2026-05-08 — superseded by reframe: all 18 starter skills stay loaded, no tier-based gating. See "Skills + connectors at Essential — personalize, don't cap" above.Pre-installed connectors selection. 3 listed; confirm Gmail vs M365 default vs choose-during-onboarding.CLOSED 2026-05-08 — superseded byconnector-recommendations.ts(persona-aware primary set, full 148 stay reachable). Gmail vs M365 picker still belongs in onboarding "which tools?" step (Phase 4b).minBillingTieron dock entries — does Pro need any? E.g. should marketplace marketplace haveminBillingTier: 'PRO'? Defer to Stripe-products work in Phase 4.1.- Reveal nudge timing — 7 days or session-count-based? Recommend 7 days based on
useDockLabelsprecedent.
References (live code, not memory)
- Dock + tier config:
apps/web/src/lib/dock-tiers.ts(TIER_DOCK_CONFIG,getDockForTier,BILLING_TIER_ORDER,filterByBillingTier) - Dock component:
apps/web/src/components/os/Dock.tsx(rendersgetDockForTier(tier, billingTier), includes zone-parent tray pattern + horizontal scroll fallback) - Tier display labels:
apps/web/src/components/os/overlays/onboarding/constants.ts(TIER_OPTIONS) - Onboarding constants: same file (
TEMPLATES,ALL_ONBOARDING_PERSONAS,TEMPLATE_PERSONA,VALUE_PROPS,getPersonasForTemplate) - Persona canon:
packages/agent/src/persona-data.ts(22 personas total; 19 in onboarding picker; 3 meta-personas hidden) - Onboarding shell:
apps/web/src/components/os/overlays/OnboardingWizard.tsx(8-step shell withSTEP_NAMESconstant) - Theme:
apps/web/src/waggle-theme.css(Hive DS tokens) - Voice:
docs/BRAND-VOICE.md - Architecture:
docs/ARCHITECTURE.md
Revision log
- r1 (2026-05-07 14:09) — initial draft, wrong direction (assumed flat sidebar). Mockups also generated in wrong direction; discarded.
- r2 (2026-05-07 14:30) — corrected per Marko: documented the actual live Mac-OS-style dock + windowed apps + existing TIER_DOCK_CONFIG. Spec now AUDITS existing code instead of redesigning. 5 dock items at Essential matched against
TIER_DOCK_CONFIG.simple(correct). Memory pulled from Essential to Standard+ (matches code). Added zone-parent + minBillingTier handling. Onboarding gap identified: template+persona steps don't filter by tier. - r3 (2026-05-08) — reframed "Pre-installed skills/tools/connectors at Essential" section per Marko's pushback: capping skills/connectors at Essential reduces capability without simplifying anything (skills are auto-loaded regardless; connectors are zero-installed by default). Replaced with personalize-don't-cap framing: all 18 skills stay loaded, all 148 connectors stay reachable, persona-aware primary recommendation surface drives the connector landing tile. Source of truth:
packages/shared/src/connector-recommendations.ts(22-persona map + universal fallback, validated againstmcp-catalog.tsmembership in tests). Closed Q2 + Q3 against this approach. Phase 4b will wire ConnectorsApp landing + onboarding "which tools?" step; Phase 4c will add chat skill hints.