## Scope This change is a **pure structural refactoring** to split monolithic pages and routers into focused components and services. No API contracts, database schemas, or user-facing behaviors change. ### In Scope #### 1. Frontend Page Extraction Split the following pages into a thin page shell + extracted components: **`pages/ToolWorkshopPage.tsx` (1,269 → ~80 lines)** - Extract `ToolTypesTab` → `components/features/tool-workshop/ToolTypesTab.tsx` - Extract `ToolConfigsTab` → `components/features/tool-workshop/ToolConfigsTab.tsx` - Extract `ConfigFoldersTab` → `components/features/tool-workshop/ConfigFoldersTab.tsx` - Page becomes: tab switcher only, imports the 3 tabs **`pages/ConfigProfilesPage.tsx` (1,611 → ~80 lines)** - Extract `ConfigProfileListView` → list view + mobile list view - Extract `ConfigProfileDetailView` → detail view with edit toggle - Extract `ConfigProfileEditForm` → edit/create form - Extract `ConfigProfileMobileView` → mobile view state machine wrapper - Page becomes: router between list/detail/edit views **`pages/TerminalPage.tsx` (571 → ~80 lines)** - Extract `TerminalSessionManager` → session tabs + auto-create logic - Extract `TerminalKeyboardShortcuts` → shortcut handler hook (already exists, just use it) - Extract `MobileTerminalOverlay` → mobile overlay toolbar + tabs - Page becomes: choose between desktop (`TerminalComponent` + `TerminalSessionTabs`) and mobile (`MobileTerminalOverlay` + `TerminalComponent`) wrappers **`pages/SettingsPage.tsx` (284 → ~80 lines)** - Extract `SettingsNavigation` → settings nav sidebar - Extract `GeneralSettingsTab`, `SSHKeysTab` (already separate pages, but move sections into components if inline) - Page becomes: nav + `` for nested routes **`pages/SshKeysPage.tsx` (277 → ~80 lines)** - Extract `SSHKeyList` → list with actions - Extract `SSHKeyCreateForm` → create form - Page becomes: layout wrapper + conditionally render list or form **`pages/RepoWorkspacePage.tsx` (505 → ~150 lines)** - Extract `WorkspaceLayout` → sidebar + main content layout - Page becomes: data loader + layout wrapper **`pages/ProjectsPage.tsx` (433 → ~100 lines)** - Extract `ProjectList` → list with cards - Extract `ProjectCreateDialog` → create form in dialog - Extract `ProjectEditDialog` → edit form in dialog - Page becomes: data loader + layout + dialog state manager #### 2. CSS Reorganization **`styles.css` (5,683 lines → deleted)** - Restore `styles/` directory with extracted files: - `styles/tokens.css` — CSS custom properties (colors, spacing, typography) - `styles/global.css` — global reset, body, shell layout - `styles/utilities.css` — utility classes (.stack, .card, .muted, etc.) - `styles/syntax-highlight.css` — code highlighting - Restore `styles/pages/*.css` — page-specific styles: - `styles/pages/dashboard.css` - `styles/pages/projects.css` - `styles/pages/sessions.css` - `styles/pages/settings.css` - `styles/pages/ssh-keys.css` - `styles/pages/git-history.css` - `styles/pages/repo-workspace.css` - Restore component CSS modules: - `components/features/terminal/TerminalComponent.module.css` - `components/features/git/GitToolbar.module.css` - `components/features/git/CommitDialog.module.css` - `components/features/git/MergeDialog.module.css` - `components/features/git/FileEditor.module.css` - `components/features/git/FileBrowser.module.css` - `components/features/git/FileViewer.module.css` - `components/features/git/CommitPanel.module.css` - `components/features/session/InstanceList.module.css` - `components/features/settings/SettingsTabLayout.module.css` - `components/layout/AppShell.module.css` - Update all component imports to use `import styles from './ComponentName.module.css'` - Update `main.tsx` to import `styles/tokens.css`, `styles/global.css`, `styles/utilities.css`, `styles/syntax-highlight.css` - Update each page to import its `styles/pages/*.css` - Delete monolithic `styles.css` #### 3. Backend Router Slimming **`api/tool/tool_instances.py` (2,900 → ~300 lines)** - Extract terminal WebSocket handlers → `api/tool/terminal.py` (~400 lines) - Extract instance lifecycle (create/start/stop/delete/restart) → `api/tool/tool_lifecycle.py` (~600 lines) - Keep in `tool_instances.py`: CRUD endpoints (GET list, GET detail, POST, PATCH, DELETE) + instance proxy endpoint **`api/project/git_repositories.py` (1,588 → ~300 lines)** - Extract git command orchestration into `services/git/operations.py` - Router keeps: auth, parameter validation, response building, error handling - Service functions: `clone_repo`, `fetch_repo`, `pull_repo`, `push_repo`, `merge_repo`, etc. **`api/config/config_profiles.py` (842 → ~200 lines)** - Extract resolver orchestration into `services/config/resolver_service.py` - Extract CRUD helpers into `services/config/crud_service.py` - Router keeps: endpoint definitions, auth, input validation ### Out of Scope - Any new features or behavioral changes - Database schema changes (no migrations) - API contract changes (same endpoints, same request/response shapes) - Frontend UI behavior changes (same components, same interactions) - Moving existing `features/` components (already organized) - Renaming files (naming already done) - Changing any CSS rules (only moving them) ## Acceptance Criteria 1. All pages ≤ 150 lines (except `RepoWorkspacePage` which may stay at ~150) 2. All API routers ≤ 400 lines 3. No monolithic `styles.css` — all CSS in `styles/` directory or `.module.css` files 4. All existing tests pass without modification (behavior unchanged) 5. All existing API endpoints return identical responses 6. Frontend `npm run typecheck` passes 7. Frontend `npm run build` passes 8. Backend `py_compile` passes on all files 9. No import errors in browser console 10. File count increases (more files, smaller files) ## Preconditions - `dev` branch is stable (all fixes from this session are committed) - Backend compiles (`py_compile` pass) - Frontend typechecks and builds (`tsc`, `vite build` pass) - Current tests pass (or known failures are documented)