339 lines
21 KiB
Markdown
339 lines
21 KiB
Markdown
# UX Disclosure Levels — Source-of-Truth Spec
|
||
|
||
> **Status:** DRAFT r2 — generated by `/plan-design-review` 2026-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)
|
||
|
||
```typescript
|
||
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:
|
||
|
||
```typescript
|
||
{ 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:
|
||
- `governance` requires `TEAMS`
|
||
- `approvals` requires `TEAMS`
|
||
|
||
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-purpose
|
||
- `tier='knowledge'` (4): researcher, writer, analyst, coder
|
||
- `tier='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 the `tier='knowledge'` filter to "knowledge minus coder" or rename `coder` to `tier='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-memo` for that?") can be
|
||
persona-aware so a Coder gets `code-review` and a Consultant gets
|
||
`research-synthesis` without 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's `bestFor[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-label` per 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):
|
||
|
||
1. **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.
|
||
2. **Settings → Display level toggle** with `TIER_OPTIONS` chooser — same UI as TierStep in onboarding.
|
||
3. **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-review` runs 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:
|
||
1. Marko reviews and signs off on the named selections (3 templates / 4 personas at Essential) and the Open Q answers.
|
||
2. Phase 4.1 implementer has enough specificity to implement: (a) filter `TEMPLATES` in `TemplateStep.tsx` when `tier === 'simple'`, (b) filter `ALL_ONBOARDING_PERSONAS` by `tier` field when `tier === 'simple'`, (c) filter `SettingsApp.tsx` sections per tier, (d) write empty/loading/error copy for the 5 Essential surfaces.
|
||
3. Open Questions 1-3 resolved.
|
||
|
||
## Open Questions
|
||
|
||
1. **Coder at Essential — keep or drop?** Recommend drop; Marko's quote supports it.
|
||
2. ~~**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.
|
||
3. ~~**Pre-installed connectors selection.** 3 listed; confirm Gmail vs M365 default vs choose-during-onboarding.~~ **CLOSED 2026-05-08** — superseded by `connector-recommendations.ts` (persona-aware primary set, full 148 stay reachable). Gmail vs M365 picker still belongs in onboarding "which tools?" step (Phase 4b).
|
||
4. **`minBillingTier` on dock entries — does Pro need any?** E.g. should marketplace marketplace have `minBillingTier: 'PRO'`? Defer to Stripe-products work in Phase 4.1.
|
||
5. **Reveal nudge timing — 7 days or session-count-based?** Recommend 7 days based on `useDockLabels` precedent.
|
||
|
||
## 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` (renders `getDockForTier(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 with `STEP_NAMES` constant)
|
||
- 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 against `mcp-catalog.ts` membership 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.
|