Keelhouse — User Flow Report

2026-07-18 · Source-and-test audit of desktop Tauri app flows, with packaged-launch evidence called out separately.

userflowflow-app-shellflow-navigationflow-ai-chatflow-errors

Summary

The shell has a coherent desktop frame: title bar, project rail, tool surfaces, conversation, editor, browser preview, terminal tray, dialogs, and accessible empty/loading/error states. Source and automated gates are strong: 305 test files/916 tests, production build, Chrome contract, module-size ratchet, and daily-driver metrics passed. The audit found two implementation gaps and several validation gaps that should remain roadmap work.

HIGH — Missing flow: no “Open in New Window” chat action exists in the current context/menu assembly, while the roadmap still treats multi-window chat as open.
HIGH — Missing flow: chat messages expose Copy, Fork, and Bookmark, but no edit, regenerate, or version-pager path. Users cannot correct a prompt in place or compare alternate answers.
MEDIUM — Unverified flow: packaged OpenCode execution, third-party OAuth consent, and provider credential validation still require an operator-consented native run; source tests do not establish those real paths.

Flow: First launch to first task

Pattern source: flow-app-shell + flow-errors · Entry point: packaged app launch or an empty workspace.

Steps

  1. 1Open the app

    The workbench shell mounts with title bar, project rail, conversation area, tool area, and bottom utility tray. Empty surfaces provide project/chat entry actions rather than blank panes.

    Primary action: Open Project… → native folder picker and workspace load.

  2. 2Create, clone, or open a project

    Project creation and clone dialogs preserve the created path, expose progress, and offer retry/open-without-Git branches. The project switcher also exposes New Project and Open Project.

    Primary action: New Project… / Clone Repository… → project setup then workspace.

    If creation, Git initialization, or opening fails → retain the path and show Retry, Open without Git, or Retry opening.
  3. 3Start the first task

    New Task routes to the active project, or opens project selection when no project is active. The empty chat offers clickable suggestions and the composer.

    Primary action: Send → streaming assistant turn.

    If no active project → Open Project flow; no silent task creation.

Screen inventory

ScreenPurposePrimary actionStates
Workbench shellOrient the user and host surfacesOpen Project / New TaskEmpty suggestions; launch error alert; crash recovery notice
ProjectCreationDialogCreate folder and optional Git repositoryCreate projectCreating, initializing, opening, retry, open without Git
CloneRepositoryDialogClone into a chosen destinationCloneProgress, cancellation, error, open project

Anti-pattern audit

CheckVerdictNote
No blank shell panesPASSEmpty chat, editor, browser, and project surfaces have purposeful actions or copy.
Multi-step workflow avoids an oversized modalWARNCreation and clone are multi-phase dialogs. They are usable and recoverable, but a full-surface route would reduce modal density.
Failures preserve user work and offer recoveryPASSCreation retains path; Git/open failures expose retry alternatives.
Packaged project-entry flow is executedWARNPackaged startup/window paint was captured outside the sandbox; full operator-driven create/clone/open interaction remains unverified.

Flow: Navigate projects, tasks, and commands

Pattern source: flow-navigation · Entry point: title-bar project control, rail, keyboard shortcut, or context menu.

Steps

  1. 1Choose a project or session

    The project switcher filters open/recent projects, marks the current project, supports arrows/Enter/Escape, and exposes New/Open Project actions.

    Primary action: Switch Project… → selected workspace.

  2. 2Switch tools from the rail

    Projects, Git, Browser, Settings, and Files are represented by labeled tabs. Collapsed mode keeps visually hidden labels and tooltips for icon-only controls.

    Primary action: Files / Git / Browser → corresponding dock surface.

  3. 3Search tasks or run a command

    The command/search dialog groups chat results as Tasks and actions as Commands, with a listbox, keyboard navigation, loading text, and an unavailable-search state.

    Primary action: Run → command action or selected task.

Screen inventory

ScreenPurposePrimary actionStates
ProjectSwitcherMove between workspace contextChoose project/sessionFiltered list; current item; empty list; keyboard escape
WorkspaceSideRailChange the active tool surfaceSelect rail tabCollapsed/expanded; selected tab; disabled/empty tool contents
SearchCommandDialogFind tasks and invoke actionsRun selected resultLoading; no match; chat search unavailable

Anti-pattern audit

CheckVerdictNote
Every navigation path has a visible destinationPASSRail, project switcher, title-bar actions, command palette, and context menus route to named surfaces.
Keyboard and pointer paths agreePASSSwitcher and command dialog implement arrows/Enter/Escape; controls are real buttons.
Deep-link/back-forward semanticsWARNThis is a native desktop app with no browser URL state; reopening a prior task depends on persisted app records, not a shareable route.
Open chat in a separate windowFAILNo “Open in New Window” action or multi-window routing is present in the source; roadmap cards remain open.

Flow: Run an agent turn and recover it

Pattern source: flow-ai-chat + flow-errors · Entry point: empty composer or an existing conversation.

Steps

  1. 1Compose a request

    The composer supports attachments, context, permissions, goal, provider/model/reasoning pickers, keyboard submit, and an Add menu rendered through a portal.

    Primary action: Send → active run.

  2. 2Watch the streamed turn

    The thread is a log with polite live announcements, aria-busy while active, turn grouping, activity timeline, tool details, approval controls, minimap, and Jump to latest.

    Primary action: Stop → terminate active run.

    If a tool needs permission → Deny, Allow once, or Allow for session; the approval row stays expanded.
  3. 3Review and reuse output

    Assistant markdown supports code highlighting/copy. Message actions support Copy, Fork, and Bookmark; file tool cards can open a review surface.

    Primary action: Fork chat from this message → branch conversation.

  4. 4Recover a failed run

    Error messages expose Retry when a retry prompt exists; the composer remains available after completion/error.

    Primary action: Retry → a new run from the saved prompt.

Screen inventory

ScreenPurposePrimary actionStates
AgentComposerSurfaceEnter task and configure runSend / StopEmpty; attachments; disabled while sending; provider/model controls
ChatThreadSurfaceRead streamed turns and activityApprove tool / Jump latestRunning, complete, error, approval pending, empty suggestions
ChatMessageArticleReview and act on a messageCopy / Fork / Bookmark / RetryAssistant, user, tool, error, focused message

Anti-pattern audit

CheckVerdictNote
Streaming has visible progress and stopPASSLive status, activity timeline, running tool rows, aria-busy, and Stop are implemented.
Composer remains useful during generationWARNInitial send disables composer while active; there is no queue/interject path for a long run.
Errors are actionable and retryablePASSRetry is conditional on a persisted retry prompt; tool approvals have explicit decisions.
Edit/regenerate/version historyFAILNo edit-message, regenerate, alternate-answer pager, or explanation of branch semantics exists.
Citations/feedback for grounded answersWARNMarkdown and code copy exist, but citation/source cards and answer feedback controls are absent; treat as a product decision.

Flow: Work in editor, browser, Git, and terminal

Pattern source: flow-app-shell + flow-errors · Entry point: Files/Git/Browser rail or bottom utility tray.

Steps

  1. 1Open a file and edit

    The editor maintains tabs, snapshots, cursor state, load/save state, and dirty buffers. Search, diff review, reveal, and external open are available.

    Primary action: Save → persisted file or conflict recovery.

  2. 2Resolve a save failure

    Save errors show the cause and offer Retry. Conflicts branch to Reload or Overwrite; external open is offered when supported.

    Primary action: Retry / Reload / Overwrite → restored editor state.

  3. 3Inspect browser, Git, or terminal output

    Tool docks and the utility tray preserve the conversation shell while switching context; terminal actions include clear, paste, focus, restart, and worktree persistence.

    Primary action: Open Browser / Git / Terminal → selected dock.

Screen inventory

ScreenPurposePrimary actionStates
Editor surfaceEdit and review workspace filesSave / search / diffLoading, dirty, saved, conflict, save error
Browser previewInspect the project previewOpen/reload previewNo URL/server, loading, runtime error
Utility tray/terminalRun and observe shell workFocus, paste, restart, resizeClosed/open, active panes, launch failure

Anti-pattern audit

CheckVerdictNote
Independent scroll regionsPASSConversation scrolling and tool/editor surfaces are separately owned; Jump to latest is explicit.
Save errors explain safe choicesPASSConflict UI distinguishes Reload from Overwrite and retains recovery error text.
Terminal input works for international textWARNRoadmap still calls out native Option-dead-key é, CJK IME, and visual fallback as unverified.
Long-running background work remains observableWARNIn-surface activity exists; daily-driver and packaged timing/notification coverage is not equivalent to a background notification contract.

Flow: Configure providers and MCP/OAuth

Pattern source: flow-navigation + flow-ai-chat + flow-errors · Entry point: Settings rail or command palette.

Steps

  1. 1Choose provider defaults

    Settings lists Codex, Gemini, Claude, and OpenCode model fields. Native provider keys are write-only in Keychain; OpenCode delegates authentication to its own runtime.

    Primary action: Save key → Keychain state becomes configured.

  2. 2Configure and check an MCP server

    MCP rows expose enabled state, transport/target/auth summary, Check, Remove, and OAuth actions. Validation status and OAuth message are shown inline.

    Primary action: Check → target status.

  3. 3Authorize or disconnect OAuth

    OAuth rows expose Authorize/Reauthorize, pending state, connected state, and Disconnect. The source has explicit OAuth status plumbing.

    Primary action: Authorize → external consent flow, then connected state.

    If consent is denied or provider credentials are invalid → error copy should preserve the selected server and allow retry; packaged execution remains to be run.

Screen inventory

ScreenPurposePrimary actionStates
ConnectionSettingsPanelConfigure provider, project, and MCP connection inputsSave/check/authorizeKeychain empty/configured; inline alert; validation; OAuth pending/connected/error
Provider rowSet model and credential presenceSave key / ClearWrite-only secret; disabled actions; save failure
MCP rowControl server and auth stateCheck / AuthorizeEnabled; checking; OAuth pending/connected; remove

Anti-pattern audit

CheckVerdictNote
Secrets are not echoed backPASSProvider text is password input and presence is represented as Keychain configured/empty.
Auth state is visible and reversiblePASSAuthorize/Reauthorize, connected status, and Disconnect are explicit.
Errors retain context and recoveryWARNInline error plumbing exists, but packaged OpenCode execution, OAuth consent, and provider credential validation remain unexecuted.
Provider setup is verified in the native appWARNSource/test evidence is not a substitute for the operator-consented packaged run listed in ROADMAP.md.

Flow: Destructive and recovery actions

Pattern source: flow-errors + flow-navigation · Entry point: session/project context menu, editor conflict, crash or launch notice.

Steps

  1. 1Manage a session

    Session context actions include rename, export, stop, fork, checkpoint capture/restore, pin, archive, and delete, with eligibility based on active/running state.

    Primary action: Archive / Delete / Restore checkpoint → updated session state.

  2. 2Recover a launch or process failure

    Launch failures expose Open Project and Use Shell profile. Crash notices are dismissible status notices. Terminal panes can be restarted.

    Primary action: Use Shell profile / Restart pane → alternate execution path.

  3. 3Protect dirty work during restore

    Checkpoint restore blocks when a dirty editor buffer would be overwritten and names the protected path, requiring save or discard first.

    Primary action: Save or discard the dirty buffer → safe restore.

Screen inventory

ScreenPurposePrimary actionStates
Session context menuOperate on a conversationFork/archive/delete/exportActive/running gating; checkpoint protection
AppNoticesSurface global recoveryOpen project / shell profileCrash status; action status; launch alert
EditorSaveErrorResolve persistence conflictRetry/reload/overwriteConflict, saving, recovery error

Anti-pattern audit

CheckVerdictNote
Destructive actions have confirmation or undoWARNEligibility gating is explicit, but this audit did not find a consistent undo affordance in the context-menu assembly; verify delete/archive confirmation in packaged use.
Dirty work is protectedPASSCheckpoint restore names the protected dirty path and blocks unsafe replacement.
Global errors state cause, fix, and work safetyWARNLaunchError renders the backend message plus two recovery buttons, but does not consistently explain cause, safety, or a direct Retry action.
Failures are visually announcedPASSSave and launch errors use role=alert; recovery/action notices use role=status.

Open questions & parked items