Files
headquarter/openspec/changes/workspace-first-ui/spec.md
T
alex e7587ca9f5 feat: workspace-first UI refresh - PR-1 backend endpoints
- Add FileService for workspace-scoped file operations
- Add GitOperations service for workspace-scoped git commands
- Add workspace_files API: GET/POST /workspaces/{id}/files
- Add workspace_git API: status, branches, commit, push, pull, fetch, checkout, history
- Add workspace_instances API: list instances per workspace
- Add top-level POST /workspaces/ (accepts repo_id directly)
- Enrich GET /projects/ with nested repositories and workspaces
- Register all new routers in main.py
- 23 tests passing (17 existing + 6 new)

Quality gates: ruff clean
2026-06-01 16:47:09 +02:00

18 KiB
Raw Blame History

Spec: Workspace-First UI Refresh

Status

Field Value
Phase Spec
Based on Proposal
Next Design

Overview

Replace the old "Repository Workspace" (direct repo file browser) with a Workspace-First model. The workspace detail page becomes the primary work surface. Projects page shows inline repos + workspaces. Old repo-workspace.tsx is deleted.

Decisions

# Question Answer
1 URL structure /workspaces/:id (flat)
2 Sidebar nav order Workspaces → Projects
3 New Workspace flow Inline form on project page
4 Branch switching Dropdown in workspace header
5 Empty tool state "Start a tool" prompt card
6 Mobile tabs Files / Git / Tools / Settings
7 Git toolbar Collapsible top bar on Files tab
8 Git tab content History, diff, full commit log

User Flows

Flow 1: Open a Project

  1. User clicks "Projects" in sidebar
  2. Sees project cards with inline repositories
  3. Each repo shows its workspaces as clickable cards
  4. User clicks a workspace → navigates to /workspaces/:id

Flow 2: Work in a Workspace

  1. User is on /workspaces/:id
  2. Files tab (default): File tree (left) + file viewer/editor (right). Git toolbar at top.
  3. User edits a file, commits via git toolbar
  4. Git tab: Full history, diff view, detailed commit log
  5. Tools tab: See running instances, click "Start Tool" → inline modal
  6. Settings tab: Sync workspace, rename, delete

Flow 3: Create a Workspace

  1. User on Projects page, expands a repo
  2. Clicks "+ New Workspace" next to a repo
  3. Inline form appears: name input, branch dropdown
  4. Submits → workspace created, appears in list

Flow 4: Start a Tool

  1. User on workspace detail, Tools tab
  2. If no instances: "Start a tool on this workspace" card
  3. If instances: list of cards + "Start Another" button
  4. Click → inline modal: tool type picker, config profile (optional)
  5. Submit → instance created, appears in list with status

Backend API

New Endpoints (workspace-scoped)

All endpoints operate on the workspace clone path (workspace.path).

# Files
GET    /workspaces/{workspace_id}/files?path=&branch=
       → List directory entries
GET    /workspaces/{workspace_id}/files/content?path=&branch=
       → Get file content
POST   /workspaces/{workspace_id}/files/content
       Body: { path, content, message }
       → Commit file change

# Git
GET    /workspaces/{workspace_id}/git/status
       → { modified, added, deleted, untracked, branch }
GET    /workspaces/{workspace_id}/git/branches
       → { branches, default_branch, current_branch }
POST   /workspaces/{workspace_id}/git/commit
       Body: { message, files? }
       → Commit staged changes
POST   /workspaces/{workspace_id}/git/push
       → Push current branch
POST   /workspaces/{workspace_id}/git/pull
       → Pull current branch
POST   /workspaces/{workspace_id}/git/fetch
       → Fetch from origin
POST   /workspaces/{workspace_id}/git/checkout
       Body: { branch }
       → Switch branch
GET    /workspaces/{workspace_id}/git/history
       Query: ?path=&limit=50
       → Commit history for file or entire repo

# Tools (instances on this workspace)
GET    /workspaces/{workspace_id}/instances
       → List tool instances using this workspace
POST   /workspaces/{workspace_id}/instances
       Body: { tool_type_id, display_name?, config_profile_id? }
       → Create instance on this workspace

Existing Endpoints (unchanged)

GET    /workspaces/
POST   /workspaces/ (body: { repo_id, name, branch })
DELETE /workspaces/{id}
POST   /workspaces/{id}/sync
PATCH  /workspaces/{id}

Note: POST /workspaces/ now accepts repo_id directly instead of nested under /projects/{pid}/repositories/{rid}/workspaces.

Modified Endpoints

GET /projects/
    → Now includes `repositories` array with `workspaces` sub-array

Database Schema

No changes. Existing workspaces table is sufficient.

Frontend Routes

/                     → Dashboard (unchanged)
/workspaces           → All workspaces list (refreshed)
/workspaces/:id       → Workspace detail (NEW, replaces repo-workspace)
/projects             → Projects list (refreshed)
/projects/:id         → Project detail with repos + workspaces (NEW)
/sessions             → Sessions list (unchanged)
/settings             → Settings (unchanged)

UI Components

WorkspaceDetailPage (/workspaces/:id)

┌──────────────────────────────────────────────────────────────┐
│ Breadcrumb: Projects > {project} > {repo} > {workspace}      │
│ [Branch ▼ main]  [Sync]  [Start Tool]  [Settings]           │
├──────────────────────────────────────────────────────────────┤
│ Tab bar: [Files] [Git] [Tools] [Settings]                   │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  {Active Tab Content}                                       │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Files Tab (default)

┌──────────────────────────────────────────────────────────────┐
│ Git Toolbar (collapsible)                                    │
│ [Modified: 3] [Staged: 2]  [Commit ▼] [Push] [Pull] [Fetch] │
├──────────────┬───────────────────────────────────────────────┤
│              │                                               │
│  File Tree   │  File Viewer / Editor                         │
│  (workspace  │                                               │
│   path)      │  Breadcrumbs: src > utils > helpers.ts        │
│              │                                               │
│  📁 src/     │  [Edit] [History]                             │
│  📄 README   │                                               │
│              │  export function ...                          │
│              │                                               │
└──────────────┴───────────────────────────────────────────────┘

Git Toolbar: Collapsible bar above file content. Shows:

  • Status counters: Modified, Added, Deleted, Untracked
  • Commit button (with message input when expanded)
  • Push, Pull, Fetch buttons
  • Branch selector dropdown

Git Tab

┌──────────────────────────────────────────────────────────────┐
│ Branch: [main ▼]  [New Branch]  [Merge]  [Compare]          │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Commit History                                              │
│  ┌────────────────────────────────────────────────────┐     │
│  │ ● abc123 Fix auth middleware                        │     │
│  │ ● def456 Add user profile page                      │     │
│  │ ● 789abc Initial commit                             │     │
│  └────────────────────────────────────────────────────┘     │
│                                                              │
│  [Show Diff] [Checkout] [Revert]                           │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Tools Tab

┌──────────────────────────────────────────────────────────────┐
│ Active Tool Instances                                        │
│                                                              │
│  ┌─────────────┐  ┌─────────────┐  [+ Start Tool]          │
│  │ Code Server │  │ Terminal    │                            │
│  │ ● Running   │  │ ● Stopped   │                            │
│  │ [Open] [Stop│  │ [Start] [×] │                            │
│  └─────────────┘  └─────────────┘                            │
│                                                              │
│  ─ or ─                                                      │
│                                                              │
│  ┌────────────────────────────────────────────────────┐     │
│  │  No tools running on this workspace                │     │
│  │  Start a tool to begin coding                      │     │
│  │            [Start Tool]                            │     │
│  └────────────────────────────────────────────────────┘     │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Settings Tab

┌──────────────────────────────────────────────────────────────┐
│ Workspace Settings                                           │
│                                                              │
│  Name: [my-feature-branch        ]                          │
│  Branch: main (tracks origin/main)                          │
│  Path: /data/working-copies/{repo-id}/{name}                │
│  Created: 2024-01-15                                        │
│  Last Sync: 2024-01-20 14:32                                │
│                                                              │
│  [Rename] [Sync Now] [Delete Workspace]                     │
│                                                              │
└──────────────────────────────────────────────────────────────┘

ProjectsPage (/projects)

┌──────────────────────────────────────────────────────────────┐
│ Projects                                    [+ New Project] │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌────────────────────────────────────────────────────┐     │
│  │ My Web App                                         │     │
│  │ A full-stack application                           │     │
│  ├────────────────────────────────────────────────────┤     │
│  │ Repositories:                                      │     │
│  │                                                    │     │
│  │ ▼ frontend (git@github.com:me/frontend.git)        │     │
│  │   ┌──────────┐ ┌─────────────┐ [+ New Workspace]  │     │
│  │   │ main     │ │ feature-ui  │                    │     │
│  │   │ ● 2 inst │ │ ● 0 inst    │                    │     │
│  │   └──────────┘ └─────────────┘                    │     │
│  │                                                    │     │
│  │ ▶ backend (git@github.com:me/backend.git)          │     │
│  │   ┌──────────┐ [+ New Workspace]                   │     │
│  │   │ main     │                                     │     │
│  │   │ ● 1 inst │                                     │     │
│  │   └──────────┘                                     │     │
│  │                                                    │     │
│  │ [Edit Project] [Delete]                            │     │
│  └────────────────────────────────────────────────────┘     │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Workspace Card: Small card showing:

  • Name
  • Status badge (ready/syncing/error)
  • Instance count (dot + number)
  • Click navigates to /workspaces/:id

New Workspace Button: Inline form on click:

[Name: __________] [Branch: main ▼] [Create] [Cancel]

Mobile Layout

Bottom tab bar (4 tabs, always visible):

┌────────────────────────────────────┐
│ {Tab Content - full screen}        │
│                                    │
│                                    │
│                                    │
├────────────────────────────────────┤
│ 📁 Files  🔀 Git  🛠 Tools  ⚙ Settings│
└────────────────────────────────────┘

Files tab: File tree full screen, tap file → viewer overlay Git tab: Commit history list, tap commit → diff overlay Tools tab: Instance cards stacked vertically Settings tab: Same as desktop settings, scrollable

State & Data Flow

Workspace Detail Page

useWorkspace(workspaceId) → fetch /workspaces/{id}
useWorkspaceFiles(workspaceId, path?, branch?) → fetch /workspaces/{id}/files
useWorkspaceGitStatus(workspaceId) → fetch /workspaces/{id}/git/status
useWorkspaceInstances(workspaceId) → fetch /workspaces/{id}/instances

All hooks poll/refetch on:

  • Tab switch
  • User action (commit, push, etc.)
  • 30s background refresh

Projects Page

useProjects() → fetch /projects/
useProjectWorkspaces(projectId) → derived from project.repositories.workspaces

Error Handling

Scenario UX
Workspace not found 404 page with "Workspace not found" + link to workspaces
Git operation fails Toast with git stderr, retry button
File read fails "File not found" in viewer, check if on correct branch
No tool types available "No tools configured" + link to Tool Workshop
Workspace path missing "Workspace files not found — try syncing"

Accessibility

  • Tab bar: role="tablist", keyboard arrow navigation
  • File tree: role="tree", arrow key expansion
  • Git toolbar: All buttons have aria-label
  • Focus management: Modal traps focus, returns on close

Performance

  • File tree: Virtualized for repos > 1000 files
  • Git history: Paginated (50 commits per page)
  • Image files: Lazy loaded in viewer
  • Polling: 30s for instances, 10s for git status when visible

Acceptance Criteria

  • repo-workspace.tsx and related components deleted
  • /projects/:id route shows project detail, not file browser
  • /workspaces/:id route shows workspace detail page
  • File browser reads from workspace clone path
  • File viewer/editor works on workspace files
  • Git toolbar on Files tab supports commit/push/pull/fetch
  • Git tab shows commit history with diff
  • Tools tab lists instances + spawn modal
  • Settings tab shows workspace info + rename/sync/delete
  • Projects page shows inline repos + workspace cards
  • Inline "New Workspace" form on project page
  • Mobile: 4-tab bottom navigation
  • All existing tests pass or updated
  • ruff clean, TypeScript clean, eslint clean