# IUV-M03 Design: Provider-first intelligent flow + drill-down main menu

**Issue:** #438
**Branch:** `feat/install-ux-intent`
**Date:** 2026-04-05

## 1. New first-run state machine

The linear 12-stage interrogation is replaced with a menu-driven architecture.

### Flow overview

```
Welcome banner
  |
  v
Detect existing install (auto)
  |
  v
Main Menu (loop)
  |-- Quick Start        -> provider key + admin creds -> finalize
  |-- Providers          -> LLM API key config
  |-- Agent Identity     -> intent intake + naming (deterministic)
  |-- Skills             -> recommended / custom selection
  |-- Gateway            -> port, storage tier, hostname, CORS
  |-- Advanced           -> SOUL.md, USER.md, TOOLS.md, runtimes, hooks
  |-- Finish & Apply     -> finalize + gateway bootstrap
  v
Done
```

### Menu navigation

- Main menu is a `select` prompt. Each option drills into a sub-flow.
- Completing a section returns to the main menu.
- Menu items show completion state: `[done]` hint after configuration.
- `Finish & Apply` is always last and requires at minimum a provider key (or explicit skip).
- The menu tracks configured sections in `WizardState.completedSections`.

### Headless bypass

When `MOSAIC_ASSUME_YES=1` or `!process.stdin.isTTY`, the entire menu is skipped.
The wizard runs: defaults + env var overrides -> finalize -> gateway config -> bootstrap.
This preserves full backward compatibility with `tools/install.sh --yes`.

## 2. Quick Start path

Target: 3-5 questions max. Under 90 seconds for a returning user.

### Questions asked

1. **Provider API key** (Anthropic/OpenAI) - `text` prompt with paste support
2. **Admin email** - `text` prompt
3. **Admin password** - masked + confirmed

### Questions skipped (with defaults)

| Setting                      | Default                         | Rationale              |
| ---------------------------- | ------------------------------- | ---------------------- |
| Agent name                   | "Mosaic"                        | Generic but branded    |
| Port                         | 14242                           | Standard default       |
| Storage tier                 | local                           | No external deps       |
| Hostname                     | localhost                       | Dev-first              |
| CORS origin                  | http://localhost:3000           | Standard web UI port   |
| Skills                       | recommended set                 | Curated by maintainers |
| Runtimes                     | auto-detected                   | No user input needed   |
| Communication style          | direct                          | Most popular choice    |
| SOUL.md / USER.md / TOOLS.md | template defaults               | Can customize later    |
| Hooks                        | auto-install if Claude detected | Safe default           |

### Flow

```
Quick Start selected
  -> "Paste your LLM API key (Anthropic recommended):"
  -> [auto-detect provider from key prefix: sk-ant-* = Anthropic, sk-* = OpenAI]
  -> Apply all defaults
  -> Run finalize (sync framework, write configs, link assets, sync skills)
  -> Run gateway config (headless-style with defaults + provided key)
  -> "Admin email:"
  -> "Admin password:" (masked + confirm)
  -> Run gateway bootstrap
  -> Done
```

## 3. Provider-first flow

Provider configuration (currently buried in gateway-config stage as "ANTHROPIC_API_KEY")
moves to a dedicated top-level menu item and is the first question in Quick Start.

### Provider detection

The API key prefix determines the provider:

- `sk-ant-api03-*` -> Anthropic (Claude)
- `sk-*` -> OpenAI
- Empty/skipped -> no provider (gateway starts without LLM access)

### Storage

The provider key is stored in the gateway `.env` as `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`.
For Quick Start, this replaces the old interactive prompt in `collectAndWriteConfig`.

### Menu section: "Providers"

In the drill-down menu, "Providers" lets users:

1. Enter/change their API key
2. See which provider was detected
3. Optionally configure a second provider

For v0.0.27, we support Anthropic and OpenAI keys only. The key is stored
in `WizardState` and written during finalize.

## 4. Intent intake + naming (deterministic fallback - Option B)

### Rationale

At install time, the LLM provider may not be configured yet (chicken-and-egg).
We use **Option B: deterministic advisor** for the install wizard.

### Flow (Agent Identity menu section)

```
1. "What will this agent primarily help you with?"
   -> Select from presets:
      - General purpose assistant
      - Software development
      - DevOps & infrastructure
      - Research & analysis
      - Content & writing
      - Custom (free text description)

2. System proposes a thematic name based on selection:
   - General purpose -> "Mosaic"
   - Software development -> "Forge"
   - DevOps & infrastructure -> "Sentinel"
   - Research & analysis -> "Atlas"
   - Content & writing -> "Muse"
   - Custom -> "Mosaic" (default)

3. "Your agent will be named 'Forge'. Press Enter to accept or type a new name:"
   -> User confirms or overrides
```

### Storage

- Agent name -> `WizardState.soul.agentName` -> written to SOUL.md
- Intent category -> `WizardState.agentIntent` (new field) -> written to `~/.config/mosaic/agent.json`

### Post-install LLM-powered intake (future)

A future `mosaic configure identity` command can use the configured LLM to:

- Accept free-text intent description
- Generate an expounded persona
- Propose a contextual name

This is explicitly out of scope for the install wizard.

## 5. Headless backward-compat

### Supported env vars (unchanged)

| Variable                   | Used by                                        |
| -------------------------- | ---------------------------------------------- |
| `MOSAIC_ASSUME_YES=1`      | Skip all prompts, use defaults + env overrides |
| `MOSAIC_ADMIN_NAME`        | Gateway bootstrap                              |
| `MOSAIC_ADMIN_EMAIL`       | Gateway bootstrap                              |
| `MOSAIC_ADMIN_PASSWORD`    | Gateway bootstrap                              |
| `MOSAIC_GATEWAY_PORT`      | Gateway config                                 |
| `MOSAIC_HOSTNAME`          | Gateway config (CORS derivation)               |
| `MOSAIC_CORS_ORIGIN`       | Gateway config (full override)                 |
| `MOSAIC_STORAGE_TIER`      | Gateway config (local/team)                    |
| `MOSAIC_DATABASE_URL`      | Gateway config (team tier)                     |
| `MOSAIC_VALKEY_URL`        | Gateway config (team tier)                     |
| `MOSAIC_ANTHROPIC_API_KEY` | Provider config                                |

### New env vars

| Variable              | Purpose                                   |
| --------------------- | ----------------------------------------- |
| `MOSAIC_AGENT_NAME`   | Override agent name in headless mode      |
| `MOSAIC_AGENT_INTENT` | Override intent category in headless mode |

### `tools/install.sh --yes`

The install script sets `MOSAIC_ASSUME_YES=1` and passes through env vars.
No changes needed to the script itself. The new wizard detects headless mode
at the top of `runWizard` and runs a linear path identical to the old flow.

## 6. Explicit non-goals

- **No GUI** — this is a terminal wizard only
- **No multi-user install** — single-user, single-machine
- **No registry changes** — npm publish flow is unchanged
- **No LLM calls during install** — deterministic fallback only
- **No new dependencies** — uses existing @clack/prompts and picocolors
- **No changes to gateway API** — only the wizard orchestration changes
- **No changes to tools/install.sh** — headless compat maintained via env vars

## 7. Implementation plan

### Files to modify

1. `packages/mosaic/src/types.ts` — add `MenuSection`, `AgentIntent`, `completedSections`, `agentIntent`, `providerKey`, `providerType` to WizardState
2. `packages/mosaic/src/wizard.ts` — replace linear flow with menu loop
3. `packages/mosaic/src/stages/mode-select.ts` — becomes the main menu
4. `packages/mosaic/src/stages/provider-setup.ts` — new: provider key collection
5. `packages/mosaic/src/stages/agent-intent.ts` — new: intent intake + naming
6. `packages/mosaic/src/stages/menu-gateway.ts` — new: gateway sub-menu wrapper
7. `packages/mosaic/src/stages/quick-start.ts` — new: quick start linear path
8. `packages/mosaic/src/constants.ts` — add intent presets and name mappings
9. `packages/mosaic/package.json` — version bump 0.0.26 -> 0.0.27

### Files to add (tests)

1. `packages/mosaic/src/stages/wizard-menu.spec.ts` — menu navigation tests
2. `packages/mosaic/src/stages/quick-start.spec.ts` — quick start path tests
3. `packages/mosaic/src/stages/agent-intent.spec.ts` — intent + naming tests
4. `packages/mosaic/src/stages/provider-setup.spec.ts` — provider detection tests

### Migration strategy

The existing stage functions remain intact. The menu system wraps them —
each menu item calls the appropriate stage function(s). The linear headless
path calls them in the same order as before.
