<!-- source: openspec/current/studio-workspace/flows.md -->

---
title: Studio Workspace — Flows
status: stable
owner: pavel
audience: [pavel, ai, engineer]
tldr: Sequenced user flows for the workspace — authoring loop, canvas creation, settings entry, and sidebar navigation.
---
# Studio Workspace — flows

> Sequenced user flows for the workspace surface.
> Why / what lives in [`narrative.md`](narrative.md). Route contracts in [`spec.md`](spec.md).

---

> **RAP-1170 Wave 1 (2026-05-22) — schema rename.** Sequence diagrams
> below reference `canvas_sessions` and related tables. Treat each
> as a pointer to its post-Wave-1 equivalent (`ideas`, `messages`,
> `files`, `spec_invitees`). The user-facing flow steps are unchanged
> — only the DB anchors moved. See `db/entities.md § Project → spec
> → idea hierarchy`.

---

## Authoring flow (v1)

```
/ (dashboard)
  └─► "New canvas" or click recent
/canvases
  └─► click canvas
/spec/[id]
  ├─► describe change in chat (or paste Linear issue body)
  ├─► iterate on staged proposal.md / design.md / tasks.md
  └─► "Promote to /openspec/changes" action
      └─► writes openspec/changes/<slug>/{proposal,design,tasks}.md
          └─► review + commit + PR (off-platform — git workflow)
```

The promote action is one-way in v1 — see `muse.md § Promote to spec`. After promotion, further edits happen through git, not by re-prompting the canvas.

---

## Canvas lifecycle FSM

The canvas chat surface coordinates a non-trivial conversation lifecycle managed by the XState v5 `canvasMachine`:

```
idle → sending → streaming → settling → idle  (happy path)
                                         ↑
       sending or streaming → error ──────── (DISMISS_ERROR or new TURN_REQUEST)
```

The `canvasMachine` parent orchestrates three long-lived children:

```
canvasMachine
├── invoke "realtime"     → supabaseRealtimeBridge
├── invoke "chat"         → chatMachine (messages / artifacts / files / costCents / six action wrappers)
├── invoke "instructions" → instructionsMachine
└── invoke "participants" → participantsMachine

canvasMachine states: connecting → connected → reconnecting
```

See `spec.md § Canvas conversation lifecycle FSM` and `spec.md § Canvas state orchestration` for the full contract.

---

## Canvas file lifecycle (project mode)

```
draft canvas
  └─► "Convert to project"  ──► creates canvas/<slug> branch on GitHub
                                 per-row getFileContent('main') + atomic createTreeCommit
                                 flips canvas_sessions.mode = 'project'

project canvas
  ├─► "Save file"           ──► Octokit putFile with optimistic concurrency on base_sha
  ├─► "Save all pending"    ──► N=1: delegates to saveFileAction
  │                             N>1: single createTreeCommit then re-anchor each row
  └─► "Open PR"             ──► createPullRequest canvas/<slug> → main (idempotent on 422)
```

---

## Settings entry flow

```
/settings
  ├─► Profile card          (full_name, avatar_url — Supabase Auth user_metadata)
  ├─► API key card          (anthropic_api_key — user_metadata)
  ├─► Workspace preferences (defaultPersona, canvasChatWidth, defaultGithubRepo, locale)
  ├─► Appearance card
  └─► Integrations card     (Linear OAuth connect / disconnect)
```

---

## Inbox acceptance flow (state machine)

```
new
  └─► "Mark reviewing" ──► reviewing
        ├─► "Accept"   ──► [createCanvasAction] → accepted_pending_invite
        │                    └─► [inviteToCanvasAction] → accepted
        └─► "Decline"  ──► declined

accepted_pending_invite
  └─► "Retry invite"  ──► [inviteToCanvasAction] → accepted

accepted     → canvas link only (no further transitions)
declined     → no actions (terminal)
```

---

## Sidebar nav flow

```
<StudioSidebar>  (apps/studio/src/components/studio-sidebar.tsx)

  [Workspace]
    Dashboard   /
    Canvases    /canvases  (also active: /spec/*)
    Projects    /projects  (also active: /projects/*)
    Inbox       /inbox     (also active: /inbox/*)

  [Build]
    Forge       /tasks     (also active: /tasks/*, /forge/*)
    Templates   /templates (also active: /templates/*)
    Network     /network   (also active: /network/*)

  [Admin — platform_owner only]
    Control     /control   (also active: /control/*)
    Settings    /settings
```

Active state: `--sidebar-accent` background + 2 px `--sidebar-primary` (terracotta) left rule.
