ee1fa6bee5
- Create types/ directory with centralized domain types: session, tool-instance, tool-type, git-repository, config-folder, tool-config, project, user, api-response - Remove inline type definitions from API modules; re-export from types/ for backward compatibility - Update state/sessions.tsx to import Session from types/session.ts - Update all consumer components/pages to import from types/ - Extract seed_builtin_tool_types from main.py to seeds/builtin_tool_types.py - Create types/index.ts barrel export Quality gates: tsc (pass), eslint (pass), Python syntax (pass)
676 lines
26 KiB
Markdown
676 lines
26 KiB
Markdown
# Tasks: Repository Restructuring and Modularization
|
||
|
||
## Overview
|
||
|
||
9 reviewable PRs (all ≤ 400 lines changed) implementing the full restructure. Each task is a standalone merge to `main`. Dependencies are explicit. Review workload is protected.
|
||
|
||
**Conventions:**
|
||
- `+N/-M` = lines added / removed in the PR
|
||
- `Files: N` = number of files touched
|
||
- `Deps:` = must-merge tasks before this one
|
||
|
||
---
|
||
|
||
## Phase 1: Safe Foundations
|
||
|
||
### Task 1.1: Centralize Types and Extract Seed Data
|
||
**PR label:** `refactor: centralize types and extract seed data`
|
||
**Estimated:** +180 / −120 lines across 15 files
|
||
**Deps:** None
|
||
|
||
**What:**
|
||
- Create `types/` directory with domain type files
|
||
- Move types out of `api/sessions.ts`, `api/tool-types.ts`, `api/git-repositories.ts`, `api/config-folders.ts`
|
||
- Move `Session` definition from `state/sessions.tsx` to `types/session.ts`
|
||
- Move `ToolInstance` definition from `api/sessions.ts` to `types/tool-instance.ts`
|
||
- Move hardcoded seed data from `main.py` to `seeds/builtin_tool_types.py`
|
||
- Create `types/index.ts` barrel export
|
||
- Update all consumers to import from `types/`
|
||
|
||
**Files:**
|
||
```
|
||
NEW: types/session.ts (from api/sessions.ts + state/sessions.tsx)
|
||
NEW: types/tool-instance.ts (from api/sessions.ts)
|
||
NEW: types/tool-type.ts (from api/tool-types.ts)
|
||
NEW: types/git-repository.ts (from api/git-repositories.ts)
|
||
NEW: types/config-folder.ts (from api/config-folders.ts)
|
||
NEW: types/project.ts (from types.ts)
|
||
NEW: types/user.ts (from types.ts)
|
||
NEW: types/api-response.ts (new generic types)
|
||
NEW: types/index.ts (barrel)
|
||
NEW: seeds/builtin_tool_types.py (from main.py)
|
||
MOD: api/sessions.ts (remove inline types, import from types/)
|
||
MOD: api/tool-types.ts (remove inline types, import from types/)
|
||
MOD: api/git-repositories.ts (remove inline types, import from types/)
|
||
MOD: api/config-folders.ts (remove inline types, import from types/)
|
||
MOD: state/sessions.tsx (import Session from types/)
|
||
MOD: types.ts (remove moved types)
|
||
MOD: main.py (import seed data from seeds/)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `grep -n "interface Session" apps/web/src` returns exactly 1 result (in `types/session.ts`)
|
||
- [ ] `grep -n "interface ToolInstance" apps/web/src` returns exactly 1 result
|
||
- [ ] `tsc --noEmit` passes with zero errors
|
||
- [ ] `pytest` passes
|
||
- [ ] No behavior changes
|
||
|
||
---
|
||
|
||
### Task 1.2: Extract FileBrowser and Shared UI Components
|
||
**PR label:** `refactor: extract FileBrowser and shared UI primitives`
|
||
**Estimated:** +150 / −80 lines across 8 files
|
||
**Deps:** 1.1
|
||
|
||
**What:**
|
||
- Extract `FileBrowser` component from inline definition in `repo-workspace.tsx`
|
||
- Create `components/features/git/FileBrowser.tsx`
|
||
- Create `components/ui/LoadingState.tsx` (reusable loading pattern)
|
||
- Create `components/ui/ErrorState.tsx` (reusable error+retry pattern)
|
||
- Create `components/ui/index.ts` barrel
|
||
- Update `repo-workspace.tsx` to import `FileBrowser`
|
||
- Update pages that use loading/error patterns to use new components
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/git/FileBrowser.tsx (from repo-workspace.tsx)
|
||
NEW: components/ui/LoadingState.tsx
|
||
NEW: components/ui/ErrorState.tsx
|
||
NEW: components/ui/StatusBadge.tsx
|
||
NEW: components/ui/index.ts (barrel)
|
||
MOD: pages/repo-workspace.tsx (remove inline FileBrowser, import)
|
||
MOD: pages/dashboard.tsx (use LoadingState, ErrorState)
|
||
MOD: pages/sessions.tsx (use LoadingState, ErrorState)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `grep -n "const FileBrowser" pages/repo-workspace.tsx` returns zero results
|
||
- [ ] FileBrowser renders correctly in repo workspace
|
||
- [ ] `tsc --noEmit` passes
|
||
- [ ] `eslint` passes
|
||
|
||
---
|
||
|
||
## Phase 2: Style System
|
||
|
||
### Task 2.1: Extract Global and Token Styles
|
||
**PR label:** `refactor: split styles.css — global styles and tokens`
|
||
**Estimated:** +120 / −50 lines across 5 files
|
||
**Deps:** 1.2
|
||
|
||
**What:**
|
||
- Create `styles/tokens.css` — CSS variables + dark theme
|
||
- Create `styles/global.css` — reset, body, shell layout
|
||
- Create `styles/utilities.css` — .stack, .row, .truncate, etc.
|
||
- Create `styles/syntax-highlight.css` — Prism.js overrides
|
||
- Update `main.tsx` to import the 4 new files
|
||
- Do NOT delete `styles.css` yet
|
||
|
||
**Files:**
|
||
```
|
||
NEW: styles/tokens.css (from styles.css lines 1–80)
|
||
NEW: styles/global.css (from styles.css: body, .shell, .shell-header, etc.)
|
||
NEW: styles/utilities.css (from styles.css: .stack, .row, .truncate, etc.)
|
||
NEW: styles/syntax-highlight.css (from styles.css: Prism overrides)
|
||
MOD: main.tsx (add imports for new style files)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] All 4 new CSS files exist and contain only their concern
|
||
- [ ] `npm run build` succeeds
|
||
- [ ] No visual regressions on shell layout
|
||
- [ ] `styles.css` still exists (deleted in Task 2.3)
|
||
|
||
---
|
||
|
||
### Task 2.2: Extract Component CSS Modules (Part 1 — Terminal + Git)
|
||
**PR label:** `refactor: extract CSS modules for terminal and git components`
|
||
**Estimated:** +280 / −200 lines across 14 files
|
||
**Deps:** 2.1
|
||
|
||
**What:**
|
||
- Create `.module.css` files for terminal and git components
|
||
- Extract styles from `styles.css` for: Terminal, GitToolbar, FileBrowser, FileEditor, CommitPanel, CommitDialog, MergeDialog
|
||
- Update components to import their `.module.css`
|
||
- Convert global class names to camelCase module classes
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/terminal/TerminalComponent.module.css
|
||
NEW: components/features/git/GitToolbar.module.css
|
||
NEW: components/features/git/FileBrowser.module.css
|
||
NEW: components/features/git/FileEditor.module.css
|
||
NEW: components/features/git/CommitPanel.module.css
|
||
NEW: components/features/git/CommitDialog.module.css
|
||
NEW: components/features/git/MergeDialog.module.css
|
||
MOD: components/terminal.tsx (import module, use styles.*)
|
||
MOD: components/git-toolbar.tsx (import module, use styles.*)
|
||
MOD: components/features/git/FileBrowser.tsx
|
||
MOD: components/file-editor.tsx
|
||
MOD: styles.css (remove extracted sections)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] Terminal renders identically
|
||
- [ ] Git toolbar, file browser, file editor render identically
|
||
- [ ] Commit panel and dialogs render identically
|
||
- [ ] `npm run build` succeeds
|
||
- [ ] `eslint` passes
|
||
|
||
---
|
||
|
||
### Task 2.3: Extract Component CSS Modules (Part 2 — Session + Settings + Layout) + Delete styles.css
|
||
**PR label:** `refactor: extract CSS modules for session/settings + delete monolithic styles.css`
|
||
**Estimated:** +250 / −2,500 lines across 12 files
|
||
**Deps:** 2.2
|
||
|
||
**What:**
|
||
- Create `.module.css` files for: InstanceList, AppShell, Navigation, SettingsTabLayout
|
||
- Create `styles/pages/sessions.css`, `styles/pages/repo-workspace.css`, `styles/pages/tool-workshop.css`
|
||
- Extract remaining component styles from `styles.css`
|
||
- Update components to import modules
|
||
- **Delete `styles.css`**
|
||
- Verify no remaining references to `styles.css`
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/session/InstanceList.module.css
|
||
NEW: components/layout/AppShell.module.css
|
||
NEW: components/layout/Navigation.module.css
|
||
NEW: components/features/settings/SettingsTabLayout.module.css
|
||
NEW: styles/pages/sessions.css
|
||
NEW: styles/pages/repo-workspace.css
|
||
NEW: styles/pages/tool-workshop.css
|
||
MOD: components/instance-list.tsx
|
||
MOD: components/app-shell.tsx
|
||
MOD: components/settings-tab-layout.tsx
|
||
MOD: pages/sessions.tsx
|
||
MOD: pages/repo-workspace.tsx
|
||
DEL: styles.css
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `test -f styles.css` fails (file deleted)
|
||
- [ ] All pages render identically
|
||
- [ ] `npm run build` succeeds
|
||
- [ ] No unstyled components
|
||
- [ ] `eslint` passes
|
||
|
||
---
|
||
|
||
## Phase 3: Backend Decomposition
|
||
|
||
### Task 3.1: Extract Shared Auth Dependencies
|
||
**PR label:** `refactor: extract shared auth dependencies`
|
||
**Estimated:** +90 / −150 lines across 10 files
|
||
**Deps:** 1.1
|
||
|
||
**What:**
|
||
- Create `auth/dependencies.py` with `get_current_user()`, `get_owned_project()`, `get_owned_repository()`
|
||
- Find and remove duplicated `_get_user()` / `_get_owned_project()` helpers from all routers
|
||
- Update routers to import from `auth.dependencies`
|
||
- Ensure dependency signatures match across all routers
|
||
|
||
**Files:**
|
||
```
|
||
NEW: auth/dependencies.py (consolidated from router files)
|
||
MOD: api/tool_instances.py (remove inline helpers, import)
|
||
MOD: api/git_repositories.py (remove inline helpers, import)
|
||
MOD: api/config_profiles.py (remove inline helpers, import)
|
||
MOD: api/ssh_keys.py (remove inline helpers, import)
|
||
MOD: api/projects.py (remove inline helpers, import)
|
||
MOD: api/tool_configs.py (remove inline helpers, import)
|
||
MOD: api/config_folders.py (remove inline helpers, import)
|
||
MOD: api/terminal.py (remove inline helpers, import)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `grep -rn "def _get_user" apps/api/src/api/` returns zero results
|
||
- [ ] `grep -rn "def _get_owned_project" apps/api/src/api/` returns zero results
|
||
- [ ] All integration tests pass
|
||
- [ ] `pytest` passes
|
||
|
||
---
|
||
|
||
### Task 3.2: Create Pydantic Schemas Directory
|
||
**PR label:** `refactor: extract pydantic schemas from routers`
|
||
**Estimated:** +200 / −100 lines across 8 files
|
||
**Deps:** 3.1
|
||
|
||
**What:**
|
||
- Create `schemas/` directory
|
||
- Extract request/response models from `api/tool_instances.py` → `schemas/tool_instance.py`
|
||
- Extract from `api/git_repositories.py` → `schemas/git_repository.py`
|
||
- Extract from `api/config_profiles.py` → `schemas/config_profile.py`
|
||
- Extract from `api/tool_types.py` → `schemas/tool_type.py`
|
||
- Update routers to import schemas
|
||
- Keep schema imports backward-compatible (routers still work)
|
||
|
||
**Files:**
|
||
```
|
||
NEW: schemas/tool_instance.py
|
||
NEW: schemas/git_repository.py
|
||
NEW: schemas/config_profile.py
|
||
NEW: schemas/tool_type.py
|
||
NEW: schemas/ssh_key.py
|
||
NEW: schemas/project.py
|
||
MOD: api/tool_instances.py (remove inline schemas, import)
|
||
MOD: api/git_repositories.py (remove inline schemas, import)
|
||
MOD: api/config_profiles.py (remove inline schemas, import)
|
||
MOD: api/tool_types.py (remove inline schemas, import)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] No Pydantic `BaseModel` definitions in router files
|
||
- [ ] `pytest` passes
|
||
- [ ] All API endpoints return correct response shapes
|
||
|
||
---
|
||
|
||
### Task 3.3: Split services/docker.py into Focused Modules
|
||
**PR label:** `refactor: split services/docker.py into focused modules`
|
||
**Estimated:** +350 / −300 lines across 6 files
|
||
**Deps:** 3.2
|
||
|
||
**What:**
|
||
- Create `services/docker/compose.py` — compose file generation + modification
|
||
- Create `services/docker/container.py` — container lifecycle (create, start, stop, restart, remove)
|
||
- Create `services/docker/tunnel.py` — Cloudflare tunnel create/recreate/health
|
||
- Create `services/docker/config_staging.py` — config folder file writing
|
||
- Create `services/docker/__init__.py` barrel
|
||
- Delete `services/docker.py`
|
||
- Update `api/tool_instances.py` to import from `services.docker`
|
||
|
||
**Files:**
|
||
```
|
||
NEW: services/docker/__init__.py
|
||
NEW: services/docker/compose.py
|
||
NEW: services/docker/container.py
|
||
NEW: services/docker/tunnel.py
|
||
NEW: services/docker/config_staging.py
|
||
MOD: api/tool_instances.py (update imports)
|
||
DEL: services/docker.py
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `test -f services/docker.py` fails (deleted)
|
||
- [ ] Each new module ≤ 300 lines
|
||
- [ ] `pytest` passes
|
||
- [ ] Tool instance create/start/stop/restart still works
|
||
|
||
---
|
||
|
||
### Task 3.4: Slim tool_instances.py Router
|
||
**PR label:** `refactor: slim tool_instances router to HTTP-only concerns`
|
||
**Estimated:** +80 / −700 lines across 3 files
|
||
**Deps:** 3.3
|
||
|
||
**What:**
|
||
- Remove all business logic from `api/tool_instances.py`
|
||
- Move compose generation calls to `services.docker.compose`
|
||
- Move container lifecycle calls to `services.docker.container`
|
||
- Move tunnel calls to `services.docker.tunnel`
|
||
- Move config staging calls to `services.docker.config_staging`
|
||
- Router should only: validate input, call service, return response
|
||
- Target: ~250 lines
|
||
|
||
**Files:**
|
||
```
|
||
MOD: api/tool_instances.py (remove ~700 lines of logic, keep ~250 of routing)
|
||
MOD: services/docker/compose.py (may need minor adjustments)
|
||
MOD: services/docker/container.py (may need minor adjustments)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `api/tool_instances.py` ≤ 300 lines
|
||
- [ ] `grep -n "subprocess" api/tool_instances.py` returns zero results
|
||
- [ ] `grep -n "docker" api/tool_instances.py` returns only import lines
|
||
- [ ] `pytest` passes, especially tool instance integration tests
|
||
|
||
---
|
||
|
||
### Task 3.5: Slim git_repositories.py and config_profiles.py Routers
|
||
**PR label:** `refactor: slim git_repositories and config_profiles routers`
|
||
**Estimated:** +100 / −600 lines across 6 files
|
||
**Deps:** 3.4
|
||
|
||
**What:**
|
||
- Extract git control logic from `api/git_repositories.py` to `services/git/control.py` (already exists, use more)
|
||
- Extract file browsing logic to thin handlers delegating to `services/git/files.py`
|
||
- Extract config profile resolution logic to `services/profile_resolver.py`
|
||
- Slim both routers to ~250 lines each
|
||
- Ensure routers contain only route definitions and thin handlers
|
||
|
||
**Files:**
|
||
```
|
||
MOD: api/git_repositories.py (remove business logic, delegate)
|
||
MOD: api/config_profiles.py (remove business logic, delegate)
|
||
MOD: services/git/control.py (may expand)
|
||
MOD: services/git/files.py (may expand)
|
||
MOD: services/profile_resolver.py (may expand)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `api/git_repositories.py` ≤ 300 lines
|
||
- [ ] `api/config_profiles.py` ≤ 300 lines
|
||
- [ ] `pytest` passes
|
||
- [ ] Git operations (branch, commit, push, pull) still work
|
||
|
||
---
|
||
|
||
## Phase 4: Frontend Page Decomposition
|
||
|
||
### Task 4.1: Split tool-workshop.tsx into Tab Components
|
||
**PR label:** `refactor: split tool-workshop page into tab components`
|
||
**Estimated:** +280 / −450 lines across 6 files
|
||
**Deps:** 2.3
|
||
|
||
**What:**
|
||
- Create `components/features/tool-workshop/ToolTypesTab.tsx`
|
||
- Create `components/features/tool-workshop/ToolConfigsTab.tsx`
|
||
- Create `components/features/tool-workshop/ConfigFoldersTab.tsx`
|
||
- Create `components/features/tool-workshop/index.ts` barrel
|
||
- Slim `pages/tool-workshop.tsx` to tab switcher + layout only (~100 lines)
|
||
- Each tab manages its own form state and API calls
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/tool-workshop/ToolTypesTab.tsx
|
||
NEW: components/features/tool-workshop/ToolConfigsTab.tsx
|
||
NEW: components/features/tool-workshop/ConfigFoldersTab.tsx
|
||
NEW: components/features/tool-workshop/index.ts
|
||
MOD: pages/tool-workshop.tsx (remove inline tabs, compose imports)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `pages/tool-workshop.tsx` ≤ 150 lines
|
||
- [ ] All 3 tabs function identically
|
||
- [ ] `tsc --noEmit` passes
|
||
- [ ] `eslint` passes
|
||
|
||
---
|
||
|
||
### Task 4.2: Extract SessionsPage Components
|
||
**PR label:** `refactor: extract sessions page components`
|
||
**Estimated:** +220 / −350 lines across 7 files
|
||
**Deps:** 4.1
|
||
|
||
**What:**
|
||
- Create `components/features/session/SessionList.tsx`
|
||
- Create `components/features/session/SessionCard.tsx`
|
||
- Create `components/features/session/CreateSessionForm.tsx`
|
||
- Create `components/features/session/index.ts` barrel
|
||
- Slim `pages/sessions.tsx` to layout + composition
|
||
- Extract inline stop/delete confirmation into reusable `ConfirmDialog` in `components/ui/`
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/session/SessionList.tsx
|
||
NEW: components/features/session/SessionCard.tsx
|
||
NEW: components/features/session/CreateSessionForm.tsx
|
||
NEW: components/features/session/index.ts
|
||
NEW: components/ui/ConfirmDialog.tsx
|
||
MOD: pages/sessions.tsx (remove inline lists/forms, compose)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `pages/sessions.tsx` ≤ 200 lines
|
||
- [ ] Session list, create form, and cards work identically
|
||
- [ ] `tsc --noEmit` passes
|
||
|
||
---
|
||
|
||
### Task 4.3: Extract Dashboard and RepoWorkspace Components
|
||
**PR label:** `refactor: extract dashboard and repo-workspace components`
|
||
**Estimated:** +200 / −300 lines across 8 files
|
||
**Deps:** 4.2
|
||
|
||
**What:**
|
||
- Create `components/features/dashboard/DashboardSummary.tsx`
|
||
- Create `components/features/dashboard/QuickActions.tsx`
|
||
- Create `components/features/dashboard/ActiveSessionsList.tsx`
|
||
- Create `components/features/dashboard/index.ts` barrel
|
||
- Slim `pages/dashboard.tsx` to layout + composition
|
||
- Slim `pages/repo-workspace.tsx` further (FileBrowser already extracted in 1.2)
|
||
- Extract `InstanceList` inline create dialog to `components/features/session/CreateInstanceDialog.tsx`
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/dashboard/DashboardSummary.tsx
|
||
NEW: components/features/dashboard/QuickActions.tsx
|
||
NEW: components/features/dashboard/ActiveSessionsList.tsx
|
||
NEW: components/features/dashboard/index.ts
|
||
NEW: components/features/session/CreateInstanceDialog.tsx
|
||
MOD: pages/dashboard.tsx (slim to ~120 lines)
|
||
MOD: pages/repo-workspace.tsx (slim further)
|
||
MOD: components/instance-list.tsx (extract create dialog)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `pages/dashboard.tsx` ≤ 150 lines
|
||
- [ ] Dashboard renders identically
|
||
- [ ] `tsc --noEmit` passes
|
||
|
||
---
|
||
|
||
### Task 4.4: Rename All Files to Naming Convention
|
||
**PR label:** `refactor: rename files to PascalCase components and kebab-case APIs`
|
||
**Estimated:** +30 / −0 lines across 40 files (mostly `git mv`)
|
||
**Deps:** 4.3
|
||
|
||
**What:**
|
||
- Rename component files to PascalCase matching exported name:
|
||
- `app-shell.tsx` → `AppShell.tsx`
|
||
- `git-toolbar.tsx` → `GitToolbar.tsx`
|
||
- `file-editor.tsx` → `FileEditor.tsx`
|
||
- `instance-list.tsx` → `InstanceList.tsx`
|
||
- `terminal.tsx` → `TerminalComponent.tsx`
|
||
- etc.
|
||
- Rename page files to PascalCase:
|
||
- `dashboard.tsx` → `DashboardPage.tsx`
|
||
- `git-history.tsx` → `GitHistoryPage.tsx`
|
||
- `repo-workspace.tsx` → `RepoWorkspacePage.tsx`
|
||
- etc.
|
||
- Rename API files to kebab-case:
|
||
- `tool_types.ts` → `tool-types.ts`
|
||
- `git_repositories.ts` → `git-repositories.ts`
|
||
- `config_folders.ts` → `config-folders.ts`
|
||
- etc.
|
||
- Update `router.tsx` to import new page paths
|
||
- Update all imports across the codebase
|
||
|
||
**Files:**
|
||
```
|
||
# Component renames (git mv)
|
||
components/app-shell.tsx → components/layout/AppShell.tsx
|
||
components/git-toolbar.tsx → components/features/git/GitToolbar.tsx
|
||
components/file-editor.tsx → components/features/git/FileEditor.tsx
|
||
components/instance-list.tsx → components/features/session/InstanceList.tsx
|
||
components/terminal.tsx → components/features/terminal/TerminalComponent.tsx
|
||
components/code-editor.tsx → components/ui/CodeEditor.tsx
|
||
components/commit-dialog.tsx → components/features/git/CommitDialog.tsx
|
||
components/commit-panel.tsx → components/features/git/CommitPanel.tsx
|
||
components/merge-dialog.tsx → components/features/git/MergeDialog.tsx
|
||
components/protected-route.tsx → components/ProtectedRoute.tsx
|
||
components/repositories-settings-tab.tsx → components/features/project/RepositoriesSettingsTab.tsx
|
||
components/repository-create-dialog.tsx → components/features/project/RepositoryCreateDialog.tsx
|
||
components/settings-tab-layout.tsx → components/features/settings/SettingsTabLayout.tsx
|
||
components/syntax-highlighter.tsx → components/features/git/SyntaxHighlighter.tsx
|
||
components/workspace-header.tsx → components/features/workspace/WorkspaceHeader.tsx
|
||
components/icon.tsx → components/ui/Icon.tsx
|
||
|
||
# Page renames (git mv)
|
||
pages/dashboard.tsx → pages/DashboardPage.tsx
|
||
pages/git-history.tsx → pages/GitHistoryPage.tsx
|
||
pages/git-repositories.tsx → pages/GitRepositoriesPage.tsx
|
||
pages/profile.tsx → pages/ProfilePage.tsx
|
||
pages/project-settings.tsx → pages/ProjectSettingsPage.tsx
|
||
pages/projects.tsx → pages/ProjectsPage.tsx
|
||
pages/repo-workspace.tsx → pages/RepoWorkspacePage.tsx
|
||
pages/sessions.tsx → pages/SessionsPage.tsx
|
||
pages/settings.tsx → pages/SettingsPage.tsx
|
||
pages/ssh-keys.tsx → pages/SshKeysPage.tsx
|
||
pages/terminal.tsx → pages/TerminalPage.tsx
|
||
pages/tool-configs.tsx → pages/ToolConfigsPage.tsx
|
||
pages/tool-types.tsx → pages/ToolTypesPage.tsx
|
||
pages/tool-workshop.tsx → pages/ToolWorkshopPage.tsx
|
||
pages/placeholder.tsx → pages/PlaceholderPage.tsx
|
||
|
||
# API renames (git mv)
|
||
api/tool_types.ts → api/tool-types.ts
|
||
api/git_repositories.ts → api/git-repositories.ts
|
||
api/config_folders.ts → api/config-folders.ts
|
||
api/tool_configs.ts → api/tool-configs.ts
|
||
api/ssh_keys.ts → api/ssh-keys.ts
|
||
api/user_config.ts → api/user-config.ts
|
||
|
||
# Updated imports
|
||
MOD: router.tsx
|
||
MOD: all page files (update relative imports)
|
||
MOD: all component files (update relative imports)
|
||
MOD: all test files (update imports)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] All component files match exported component name (case-insensitive)
|
||
- [ ] All page files end with `Page.tsx`
|
||
- [ ] All API files use kebab-case
|
||
- [ ] `tsc --noEmit` passes
|
||
- [ ] `eslint` passes
|
||
- [ ] `vitest run` passes
|
||
- [ ] Router resolves all routes
|
||
|
||
---
|
||
|
||
## Phase 5: Testing and Polish
|
||
|
||
### Task 5.1: Add Tests for Extracted Components
|
||
**PR label:** `test: add tests for extracted components`
|
||
**Estimated:** +250 / −0 lines across 8 files
|
||
**Deps:** 4.4
|
||
|
||
**What:**
|
||
- Add `components/features/git/FileBrowser.test.tsx`
|
||
- Add `components/ui/LoadingState.test.tsx`
|
||
- Add `components/ui/ErrorState.test.tsx`
|
||
- Add `components/features/tool-workshop/ToolTypesTab.test.tsx`
|
||
- Add `components/features/session/SessionList.test.tsx`
|
||
- Add `pages/DashboardPage.test.tsx` (replace failing `projects.test.tsx` pattern)
|
||
- Ensure tests use `MemoryRouter` where needed
|
||
- Mock API calls consistently
|
||
|
||
**Files:**
|
||
```
|
||
NEW: components/features/git/FileBrowser.test.tsx
|
||
NEW: components/ui/LoadingState.test.tsx
|
||
NEW: components/ui/ErrorState.test.tsx
|
||
NEW: components/features/tool-workshop/ToolTypesTab.test.tsx
|
||
NEW: components/features/session/SessionList.test.tsx
|
||
NEW: pages/DashboardPage.test.tsx
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] All new tests pass (`vitest run`)
|
||
- [ ] No test file exceeds 200 lines
|
||
- [ ] Tests cover render, basic interaction, and error states
|
||
|
||
---
|
||
|
||
### Task 5.2: Documentation and Cleanup
|
||
**PR label:** `docs: add naming conventions doc and final cleanup`
|
||
**Estimated:** +120 / −50 lines across 6 files
|
||
**Deps:** 5.1
|
||
|
||
**What:**
|
||
- Write `docs/development/naming.md` with full naming convention table
|
||
- Remove dead CSS classes (verified by grep for unused selectors)
|
||
- Remove unused exports (check `eslint` `report-unused-disable-directives`)
|
||
- Add verification script to `package.json`: `"check-structure": "node scripts/check-structure.js"`
|
||
- Final quality gate run
|
||
|
||
**Files:**
|
||
```
|
||
NEW: docs/development/naming.md
|
||
NEW: scripts/check-structure.js (verifies file sizes, naming, barrels)
|
||
MOD: package.json (add check-structure script)
|
||
MOD: styles/global.css (remove dead rules if any)
|
||
MOD: various files (remove unused exports)
|
||
```
|
||
|
||
**Acceptance criteria:**
|
||
- [ ] `docs/development/naming.md` exists and is complete
|
||
- [ ] `npm run check-structure` passes
|
||
- [ ] No file in `src/` exceeds 300 lines
|
||
- [ ] `tsc --noEmit` passes
|
||
- [ ] `eslint` passes
|
||
- [ ] `vitest run` passes
|
||
- [ ] `pytest` passes
|
||
|
||
---
|
||
|
||
## Task Dependency Graph
|
||
|
||
```
|
||
1.1 (Types + Seeds) ──┐
|
||
├──→ 1.2 (FileBrowser + UI) ──→ 2.1 (Global Styles)
|
||
│
|
||
3.1 (Auth deps) ──→ 3.2 (Schemas) ─┤
|
||
│ │
|
||
└──→ 3.3 (Docker split) ──→ 3.4 (tool_instances slim)
|
||
│
|
||
└──→ 3.5 (git + profiles slim)
|
||
│
|
||
2.2 (Terminal/Git CSS) ──→ 2.3 (Session/Settings CSS + delete styles.css) ────────────────┘ │
|
||
│
|
||
4.1 (tool-workshop split) ──→ 4.2 (sessions split) ──→ 4.3 (dashboard/workspace split) ──→ 4.4 (rename files)
|
||
│
|
||
5.1 (tests) ──→ 5.2 (docs + cleanup) ────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Review Workload Summary
|
||
|
||
| Task | Est. Lines | Status |
|
||
|------|-----------|--------|
|
||
| 1.1 | +180 / −120 | ✅ Under 400 |
|
||
| 1.2 | +150 / −80 | ✅ Under 400 |
|
||
| 2.1 | +120 / −50 | ✅ Under 400 |
|
||
| 2.2 | +280 / −200 | ✅ Under 400 |
|
||
| 2.3 | +250 / −2,500 | ✅ Under 400 (mostly deletions) |
|
||
| 3.1 | +90 / −150 | ✅ Under 400 |
|
||
| 3.2 | +200 / −100 | ✅ Under 400 |
|
||
| 3.3 | +350 / −300 | ✅ Under 400 |
|
||
| 3.4 | +80 / −700 | ✅ Under 400 |
|
||
| 3.5 | +100 / −600 | ✅ Under 400 |
|
||
| 4.1 | +280 / −450 | ✅ Under 400 |
|
||
| 4.2 | +220 / −350 | ✅ Under 400 |
|
||
| 4.3 | +200 / −300 | ✅ Under 400 |
|
||
| 4.4 | +30 / −0 | ✅ Under 400 (git mv mostly) |
|
||
| 5.1 | +250 / −0 | ✅ Under 400 |
|
||
| 5.2 | +120 / −50 | ✅ Under 400 |
|
||
|
||
**All 16 tasks are under the 400-line review budget.**
|
||
|
||
---
|
||
|
||
## Quality Gates (Per Task)
|
||
|
||
Every task MUST pass:
|
||
1. `npm run typecheck` (frontend) — zero errors
|
||
2. `npm run lint` (frontend) — zero warnings
|
||
3. `pytest` (backend) — zero failures
|
||
4. File size check — no file > 300 lines
|
||
5. For frontend tasks: visual sanity check (build succeeds)
|
||
6. Commit with conventional format: `refactor: phase N — description`
|
||
|
||
---
|
||
|
||
## Task Execution Notes
|
||
|
||
- **Use `git mv`** for all file renames to preserve history
|
||
- **Update imports with IDE refactor** when possible (VS Code "Move to new file", PyCharm refactor)
|
||
- **No logic changes** — pure cut-paste-reorganize
|
||
- **Merge to `main` immediately** after each task passes quality gates
|
||
- **Pause between phases** (after Tasks 1.2, 2.3, 3.5, 4.4) to verify stability
|