chore: archive 15 completed OpenSpec changes

Move the following audited-and-implemented changes into
openspec/changes/archive/2026-06-12-completed-changes-archive/:

- backend-frontend-refactoring
- config-profile-git-mounts
- config-profile-includes-ui
- config-profile-multi-repo-mounts
- container-monitoring-notifications
- git-mount-url-validation
- home-path-expansion
- mobile-terminal-ux
- mount-specificity-ordering
- notification-center
- persistent-terminal-sessions
- session-list-overhaul
- ssh-key-mounting
- terminal-fullscreen-unified-header
- tool-session-progress-and-updates

Also regenerated .pi-map*.md files for openspec/changes so the
remaining active changes (multi-session-terminal-ux, reorganize-long-files,
working-copies, workspace-first-ui) reflect the new layout.
This commit is contained in:
Developer
2026-06-12 14:26:55 +00:00
parent 30549f4863
commit caadd59441
493 changed files with 3563 additions and 3490 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-06-03
@@ -0,0 +1,23 @@
# archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring (index)
dir: archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring
## role
This package serves as a completed historical archive of a structural refactoring initiative to decompose monolithic backend/frontend code into domain-based modular subpackages without changing behavior or API contracts.
## parent
index: archive/2026-06-12-completed-changes-archive/.pi-map.index.md
map: archive/2026-06-12-completed-changes-archive/.pi-map.md
## children
-
## files
- .openspec.yaml
- design.md
- proposal.md
- spec.md
- tasks.md
## links
index: archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring/.pi-map.index.md
map: archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring/.pi-map.md
## workflows
-
## dirty
-
@@ -0,0 +1,23 @@
# archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring
dir: archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring
index: archive/2026-06-12-completed-changes-archive/backend-frontend-refactoring/.pi-map.index.md
## role
This package serves as a completed historical archive of a structural refactoring initiative to decompose monolithic backend/frontend code into domain-based modular subpackages without changing behavior or API contracts.
## files
- .openspec.yaml | Defines an OpenSpec configuration file with schema type and creation date metadata
- design.md | Architecture design document for a large-scale backend/frontend refactoring to decompose monolithic modules into domain-based subpackages while preserving API contracts and behavior | dep: FastAPI, Pydantic, SQLAlchemy, Docker, cloudflared, React/TypeScript
- proposal.md | This file is a technical proposal document outlining a pure structural refactoring to split monolithic backend files and reorganize frontend code without changing any behavior.
- spec.md | Defines a pure structural refactoring specification for extracting schemas, splitting monolithic services, reorganizing frontend features, and standardizing naming conventions without changing any behavior or API contracts. | dep: Pydantic, FastAPI (implied by Depends, API routers), SQLAlchemy AsyncSession, React/TypeScript frontend, Docker, ruff, npm
- tasks.md | Defines a multi-phase refactoring plan to reorganize a Python/FastAPI backend and TypeScript frontend codebase into modular subpackages with verification steps | dep: FastAPI, Docker, pytest, ruff, py_compile, npm, TypeScript, React Router
## arch
Documentation-driven refactoring architecture using phased planning (proposal → design → spec → tasks) with OpenSpec schema validation, emphasizing pure structural changes with zero behavioral modification and comprehensive verification steps.
## tags
frontend, refactoring, defines, design, backend, monolithic, behavior, fastapi
## symbols
-
## workflows
-
## dirty
-
@@ -0,0 +1,319 @@
## Context
Current `dev` has all behavioral features from the overwritten `main` merge, but the code structure is pre-refactor:
- Monolithic `api/tool_instances.py` (~3000 lines)
- Monolithic `api/config_profiles.py` (~1000 lines)
- Monolithic `services/docker.py`
- No `schemas/` directory
- Flat frontend component structure with inconsistent naming
The `b6f89f9` merge from `main` had a clean refactoring that we need to redo, but adapted to our current reality.
## Goals / Non-Goals
**Goals:**
- Extract Pydantic schemas from API routers into `src/schemas/`
- Split `services/docker.py` into `services/docker/` package
- Extract instance lifecycle logic from `api/tool_instances.py` into `services/instance_lifecycle.py`
- Extract config profile business logic from `api/config_profiles.py` into `services/config_profiles.py`
- Add `get_current_user` auth dependency and migrate routers that need the full user object
- Reorganize frontend components into `features/` directories
- Standardize frontend API file naming to kebab-case
- Standardize frontend page naming to `*Page.tsx`
**Non-Goals:**
- Changing any API request/response shapes
- Changing any database schemas
- Adding new features
- Modifying frontend component behavior or styling
- Converting `ConfigProfile` mounts from JSON to relation tables (out of scope — would require migration)
## Decisions
### 0. Submodule Rule: Max 510 Files Per Directory
**Decision:** Every directory that functions as a Python module must contain at most 510 `.py` files. When a module grows beyond this, split it into a package with submodules.
**Rationale:** Prevents monolithic directories, makes navigation predictable, and keeps cognitive load bounded.
### 1. Schema Extraction: Domain Subpackages
**Decision:** Extract Pydantic models into `schemas/` subpackages by domain:
- `schemas/tool/` — tool_type.py, tool_instance.py
- `schemas/config/` — config_profile.py
- `schemas/user/` — user.py, user_config.py
- `schemas/project/` — project.py, git_repository.py, ssh_key.py
- `schemas/system/` — health.py
**Rationale:** Keeps schemas close to their domain. Each subpackage has ≤5 files.
### 2. API Router Subpackages
**Decision:** Split `api/` into domain subpackages:
- `api/tool/` — tool_instances.py, tool_types.py, tool_definitions.py, tool_types_validation.py, sessions.py
- `api/config/` — config_profiles.py, user_config.py
- `api/workspace/` — workspaces.py, workspace_files.py, workspace_git.py, workspace_instances.py
- `api/user/` — users.py, auth.py, ssh_keys.py
- `api/project/` — projects.py, git_repositories.py
- `api/system/` — health.py, events.py, notifications.py, dashboard.py, terminal.py, instance_proxy.py
**Rationale:** `api/` currently has ~22 files. Splitting into 6 subpackages keeps each at 26 files.
### 3. Service Subpackages
**Decision:** Split `services/` into subpackages:
- `services/docker/` — compose.py, container.py, config_staging.py, tunnel.py, __init__.py
- `services/instance/` — instance_lifecycle.py, lifecycle_hooks.py, health_monitor.py, event_bus.py
- `services/config/` — config_profile_resolver.py, config_profiles.py
- `services/git/` — clone.py, git_operations.py, git_service.py
- `services/build/` — docker_build.py, manifest_compiler.py
- `services/terminal/` — terminal_manager.py, terminal_session.py
- `services/shared/` — tunnel.py, notification_service.py, file_service.py, permission_fixer.py, readiness_probe.py, ssh_keys.py, workspace_manager.py, correlation.py
**Rationale:** `services/` currently has ~20 files. Subpackages keep each at ≤8 files.
### 4. Model Subpackages
**Decision:** Split `models/` into subpackages:
- `models/tool/` — tool_type.py, tool_instance.py, tool_definition_manifest.py
- `models/config/` — config_profile.py, config_include.py, config_mount.py
- `models/user/` — user.py, user_config.py, ssh_key.py
- `models/project/` — project.py, git_repository.py, workspace.py
- `models/system/` — health_check.py, notification.py, instance_event.py, terminal_session.py
- `models/base.py` stays at root
**Rationale:** `models/` currently has ~15 files. Subpackages keep each at ≤4 files.
### 5. Docker Service Split: Functional Boundaries
**Decision:** Split by responsibility:
- `compose.py` — compose file generation, modification, port injection, network injection
- `container.py` — container status, IP lookup, network connect, logs
- `config_staging.py` — staging config files into instance directories
- `tunnel.py` — extracting tunnel URLs from cloudflared output
**Rationale:** Each module has a single reason to change. `docker.py` mixed compose logic with container runtime queries.
### 6. Instance Lifecycle: Service Receives Raw Params, Not Request Objects
**Decision:** Service functions receive model instances and primitive parameters, not FastAPI request objects.
**Example:** `create_instance(session, user, project, repo, tool_type, data: CreateInstanceRequest)` → service extracts fields.
**Rationale:** Keeps service layer independent of HTTP framework. Easier to test.
### 7. Auth Pattern: Gradual Migration, Not Big Bang
**Decision:** Add `get_current_user` alongside existing `get_current_user_id`. Migrate routers incrementally.
**Rationale:** Reduces risk. Endpoints that only need the ID can keep the old pattern.
### 8. Frontend Naming: Align with `b6f89f9` Conventions
**Decision:** Use kebab-case for API files, PascalCase for page files with `Page` suffix, `features/` for component directories.
**Rationale:** Matches the `b6f89f9` structure that was already reviewed and accepted.
## Module Map
### Backend — Before
```
api/ (~22 .py files)
tool_instances.py (~3000 lines) — HTTP + Docker + Git + Lifecycle
config_profiles.py (~1000 lines) — HTTP + Validation + Defaults
tool_types.py (~500 lines) — HTTP + Schemas
health.py (~150 lines) — HTTP + Schemas
users.py (~100 lines) — HTTP + Schemas
...
services/ (~20 .py files)
docker.py (~600 lines) — Compose + Container + Tunnel
models/ (~15 .py files)
config_profile.py
tool_instance.py
...
```
### Backend — After
```
schemas/ (5 subpackages, ≤5 files each)
tool/
__init__.py
tool_type.py
tool_instance.py
config/
__init__.py
config_profile.py
user/
__init__.py
user.py
user_config.py
project/
__init__.py
project.py
git_repository.py
ssh_key.py
system/
__init__.py
health.py
api/ (6 subpackages, 26 files each)
tool/
__init__.py
tool_instances.py (~300 lines) — HTTP routing only
tool_types.py (~250 lines) — HTTP + validation
tool_definitions.py
tool_types_validation.py
sessions.py
config/
__init__.py
config_profiles.py (~200 lines) — HTTP routing only
user_config.py
workspace/
__init__.py
workspaces.py
workspace_files.py
workspace_git.py
workspace_instances.py
user/
__init__.py
users.py (~60 lines) — HTTP only
auth.py
ssh_keys.py
project/
__init__.py
projects.py
git_repositories.py
system/
__init__.py
health.py (~80 lines) — HTTP only
events.py
notifications.py
dashboard.py
terminal.py
instance_proxy.py
services/ (7 subpackages, ≤8 files each)
docker/
__init__.py (~40 lines) — Re-exports
compose.py (~240 lines) — Compose generation
container.py (~120 lines) — Container queries
config_staging.py (~80 lines) — File staging
tunnel.py (~150 lines) — Tunnel URL extraction
instance/
__init__.py
instance_lifecycle.py (~420 lines) — Create/Start/Stop/Restart/Delete
lifecycle_hooks.py
health_monitor.py
event_bus.py
config/
__init__.py
config_profile_resolver.py
config_profiles.py (~300 lines) — CRUD + Defaults
git/
__init__.py
clone.py
git_operations.py
git_service.py
build/
__init__.py
docker_build.py
manifest_compiler.py
terminal/
__init__.py
terminal_manager.py
terminal_session.py
shared/
__init__.py
tunnel.py
notification_service.py
file_service.py
permission_fixer.py
readiness_probe.py
ssh_keys.py
workspace_manager.py
correlation.py
models/ (5 subpackages + base.py)
tool/
__init__.py
tool_type.py
tool_instance.py
tool_definition_manifest.py
config/
__init__.py
config_profile.py
config_include.py
config_mount.py
user/
__init__.py
user.py
user_config.py
ssh_key.py
project/
__init__.py
project.py
git_repository.py
workspace.py
system/
__init__.py
health_check.py
notification.py
instance_event.py
terminal_session.py
base.py (stays at root)
```
### Frontend — Before
```
src/
api/
tool_types.ts
ssh_keys.ts
git_repositories.ts
sessions.ts
components/
git-toolbar.tsx
file-editor.tsx
commit-dialog.tsx
...
pages/
dashboard.tsx
projects.tsx
sessions.tsx
...
```
### Frontend — After
```
src/
api/
tool-types.ts
ssh-keys.ts
git-repositories.ts
sessions.ts
components/
features/
git/
GitToolbar.tsx
FileBrowser.tsx
FileEditor.tsx
CommitDialog.tsx
MergeDialog.tsx
WorkspaceSidebar.tsx
dashboard/
DashboardSummary.tsx
ActiveSessionsList.tsx
ProjectsSection.tsx
QuickCreateForm.tsx
RecentSessionsSection.tsx
project/
RepositoriesSettingsTab.tsx
tool-workshop/
ToolTypesTab.tsx
ProtectedRoute.tsx
AppShell.tsx
pages/
DashboardPage.tsx
ProjectsPage.tsx
SessionsPage.tsx
...
```
## Risks / Trade-offs
**[Risk] Import cycles during extraction** → **Mitigation:** Extract schemas first (no service dependencies), then services, then thin routers last. Use TYPE_CHECKING guards.
**[Risk] Merge conflicts with in-flight features** → **Mitigation:** Coordinate timing. This refactor should be the only large change on `dev` while it's in progress. Freeze other backend work.
**[Risk] Frontend renaming breaks imports** → **Mitigation:** Use `git mv` for renames so git tracks history. Update all imports in a single commit.
**[Risk] Missing re-export in docker/__init__.py breaks consumers** → **Mitigation:** After splitting, run a full import test across all backend files. Add any missing re-exports.
## Migration Plan
1. **Phase 1: Schemas** — Extract all Pydantic models into `schemas/`. Update imports in API routers. No logic changes.
2. **Phase 2: Services** — Split `docker.py`, extract `instance_lifecycle.py`, extract `config_profiles.py`. Update imports.
3. **Phase 3: Auth** — Add `get_current_user`, migrate routers that need the full user object.
4. **Phase 4: Frontend** — Rename files, move components, update imports.
5. **Phase 5: Verification** — Run full test suite, typecheck, build.
@@ -0,0 +1,52 @@
## Why
The `main` branch was previously merged into `dev` (commit `b6f89f9`) bringing a large structural refactoring: schema extraction, service splitting, auth dependency pattern changes, and frontend reorganization. This merge was later overwritten when `dev` was reset to a pre-merge clean state (`51a399c`).
We have since forward-ported all behavioral features (built-in tool type seeding, config profile defaults, unique constraints, SSH key mounting, terminal backend, etc.) onto the clean `dev` base. **The codebase now works functionally but lacks the structural cleanliness of the refactoring.**
Monolithic files make the backend harder to navigate, test, and maintain:
- `api/tool_instances.py` is ~3000 lines (mixing HTTP handling with Docker orchestration)
- `api/config_profiles.py` is ~1000 lines (mixing HTTP handling with business logic)
- `services/docker.py` is a monolith of ~600 lines covering compose, container, and tunnel logic
- Frontend API files use inconsistent naming (`tool_types.ts` vs `tool-types.ts`)
- Frontend components are flat in `components/` instead of organized by feature domain
## What Changes
Redo the structural refactoring from `b6f89f9`, **adapted to current dev reality**:
1. **Backend schema extraction** — Extract Pydantic request/response schemas from API routers into `apps/api/src/schemas/`
2. **Backend service splits** — Split `services/docker.py` into `services/docker/` package; extract `services/instance_lifecycle.py` and `services/config_profiles.py`
3. **Auth dependency refactor** — Change from `get_current_user_id` + manual `_get_user` calls to `get_current_user` dependency returning `User` directly
4. **Frontend reorganization** — Move components into `features/` directories; rename API files to kebab-case
**No behavioral changes.** This is a pure structural refactor. All existing endpoints, models, and UI flows remain identical.
## Capabilities
### New Capabilities
- None (pure refactor)
### Modified Capabilities
- `backend-structure`: Cleaner module boundaries, smaller files, separated concerns
- `frontend-structure`: Feature-organized components, consistent file naming
## Impact
- **Backend**: `apps/api/src/schemas/*` (new), `apps/api/src/services/docker/*` (new package), `apps/api/src/services/instance_lifecycle.py` (new), `apps/api/src/services/config_profiles.py` (new)
- **Backend**: `apps/api/src/api/*.py` (reduced in size, imports change)
- **Backend**: `apps/api/src/auth/dependencies.py` (new `get_current_user`)
- **Frontend**: `apps/web/src/components/features/*` (new directories), `apps/web/src/api/*` (renamed to kebab-case)
- **Frontend**: `apps/web/src/pages/*` (renamed to `*Page.tsx`)
## Exclusions (Already Done)
The following behavioral features from `b6f89f9` are **already present** in current `dev` and out of scope for this refactor:
- Built-in tool type seeding (`src/seeds/builtin_tool_types.py`)
- Config profile default management (endpoints + `UserConfig` properties)
- Config profile unique constraint (`uq_config_profiles_user_name`)
- SSH key mounting in instance lifecycle
- Terminal backend (WebSocket, session management)
- Tunnel URL regex fix
- Session auto-numbering
- Config profile resolver (`services/config_profile_resolver.py`)
@@ -0,0 +1,75 @@
## Scope
This change is a **pure structural refactoring** of the backend and frontend codebase. No API contracts, database schemas, or user-facing behaviors change.
### In Scope
1. **Schema extraction** (`apps/api/src/schemas/`)
- Extract Pydantic models from API routers into dedicated schema modules
- Schemas to extract: `tool_type`, `tool_instance`, `config_profile`, `user`, `user_config`, `project`, `ssh_key`, `git_repository`, `health`
- Each API router imports schemas from `src.schemas.*` instead of defining inline
2. **Docker service package** (`apps/api/src/services/docker/`)
- Split `services/docker.py` monolith into focused modules:
- `docker/compose.py` — compose file generation, modification, validation
- `docker/container.py` — container lifecycle (status, IP, network, logs)
- `docker/config_staging.py` — config file staging for instances
- `docker/tunnel.py` — tunnel URL extraction (moved from `services/tunnel.py`)
- `docker/__init__.py` — re-exports for backward compatibility
- Update all imports across the backend
3. **Instance lifecycle extraction** (`apps/api/src/services/instance_lifecycle.py`)
- Extract instance creation, start, stop, restart, and deletion logic from `api/tool_instances.py`
- The API router becomes thin: validates auth, calls service, returns response
- Service functions are async and receive `AsyncSession`, models, and raw parameters
4. **Config profile service extraction** (`apps/api/src/services/config_profiles.py`)
- Extract business logic from `api/config_profiles.py`: CRUD helpers, validation, default profile management
- API router delegates to service functions
5. **Auth dependency refactor** (`apps/api/src/auth/dependencies.py`)
- Add `get_current_user` dependency that returns a `User` model directly
- Update API routers to use `user: User = Depends(get_current_user)` where the full user object is needed
- Keep `get_current_user_id` for endpoints that only need the ID
6. **Frontend reorganization**
- Move components into `features/` directories by domain:
- `features/git/` — CommitDialog, FileBrowser, FileEditor, GitToolbar, MergeDialog, WorkspaceSidebar
- `features/dashboard/` — ActiveSessionsList, DashboardSummary, ProjectsSection, QuickCreateForm, RecentSessionsSection
- `features/project/` — RepositoriesSettingsTab
- `features/tool-workshop/` — ToolTypesTab (already exists)
- Rename API files from snake_case to kebab-case:
- `tool_types.ts``tool-types.ts`
- `ssh_keys.ts``ssh-keys.ts`
- `git_repositories.ts``git-repositories.ts`
- Rename page files to `*Page.tsx`:
- `dashboard.tsx``DashboardPage.tsx`
- `projects.tsx``ProjectsPage.tsx`
- etc.
### 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)
- Removing or modifying the `ConfigProfileInclude` model (already exists as a relation)
- Extracting `ConfigMount` into a separate model (current dev uses JSON arrays; this is a schema decision, not a refactor)
- Changes to `tool_definition_manifest` or `workspace` models
## Acceptance Criteria
1. All existing tests pass without modification (behavior unchanged)
2. All existing API endpoints return identical responses for identical requests
3. All frontend pages render identically
4. `docker compose up` starts successfully
5. Backend `ruff check` passes
6. Frontend `npm run typecheck` passes
7. Frontend `npm run build` passes
8. File sizes are reduced: no API router > 500 lines, no service > 400 lines
## Preconditions
- Current `dev` branch is stable and all behavioral forward-ports are complete
- All legacy `ToolConfig`/`ConfigFolder` code has been removed
- Database migrations are at a single head
@@ -0,0 +1,158 @@
## Phase 0: Submodule Infrastructure (Create Directories + __init__.py Files)
- [ ] 0.1 Create `apps/api/src/schemas/tool/__init__.py`
- [ ] 0.2 Create `apps/api/src/schemas/config/__init__.py`
- [ ] 0.3 Create `apps/api/src/schemas/user/__init__.py`
- [ ] 0.4 Create `apps/api/src/schemas/project/__init__.py`
- [ ] 0.5 Create `apps/api/src/schemas/system/__init__.py`
- [ ] 0.6 Create `apps/api/src/api/tool/__init__.py`
- [ ] 0.7 Create `apps/api/src/api/config/__init__.py`
- [ ] 0.8 Create `apps/api/src/api/workspace/__init__.py`
- [ ] 0.9 Create `apps/api/src/api/user/__init__.py`
- [ ] 0.10 Create `apps/api/src/api/project/__init__.py`
- [ ] 0.11 Create `apps/api/src/api/system/__init__.py`
- [ ] 0.12 Create `apps/api/src/services/instance/__init__.py`
- [ ] 0.13 Create `apps/api/src/services/config/__init__.py`
- [ ] 0.14 Create `apps/api/src/services/git/__init__.py`
- [ ] 0.15 Create `apps/api/src/services/build/__init__.py`
- [ ] 0.16 Create `apps/api/src/services/terminal/__init__.py`
- [ ] 0.17 Create `apps/api/src/services/shared/__init__.py`
- [ ] 0.18 Create `apps/api/src/models/tool/__init__.py`
- [ ] 0.19 Create `apps/api/src/models/config/__init__.py`
- [ ] 0.20 Create `apps/api/src/models/user/__init__.py`
- [ ] 0.21 Create `apps/api/src/models/project/__init__.py`
- [ ] 0.22 Create `apps/api/src/models/system/__init__.py`
## Phase 1: Model Subpackages
- [ ] 1.1 Move `models/tool_type.py``models/tool/tool_type.py`
- [ ] 1.2 Move `models/tool_instance.py``models/tool/tool_instance.py`
- [ ] 1.3 Move `models/tool_definition_manifest.py``models/tool/tool_definition_manifest.py`
- [ ] 1.4 Move `models/config_profile.py``models/config/config_profile.py`
- [ ] 1.5 Move `models/config_include.py` (if exists) → `models/config/config_include.py`
- [ ] 1.6 Move `models/config_mount.py` (if exists) → `models/config/config_mount.py`
- [ ] 1.7 Move `models/user.py``models/user/user.py`
- [ ] 1.8 Move `models/user_config.py``models/user/user_config.py`
- [ ] 1.9 Move `models/ssh_key.py``models/user/ssh_key.py`
- [ ] 1.10 Move `models/project.py``models/project/project.py`
- [ ] 1.11 Move `models/git_repository.py``models/project/git_repository.py`
- [ ] 1.12 Move `models/workspace.py``models/project/workspace.py`
- [ ] 1.13 Move `models/health_check.py``models/system/health_check.py`
- [ ] 1.14 Move `models/notification.py``models/system/notification.py`
- [ ] 1.15 Move `models/instance_event.py``models/system/instance_event.py`
- [ ] 1.16 Move `models/terminal_session.py``models/system/terminal_session.py`
- [ ] 1.17 Update `models/__init__.py` to import from subpackages
- [ ] 1.18 Update all backend imports to use `models.tool.tool_type` etc.
- [ ] 1.19 Verify `py_compile` and `ruff` pass
## Phase 2: Schema Extraction + Subpackages
- [ ] 2.1 Extract `schemas/tool/tool_type.py` from `api/tool_types.py`
- [ ] 2.2 Extract `schemas/tool/tool_instance.py` from `api/tool_instances.py`
- [ ] 2.3 Extract `schemas/config/config_profile.py` from `api/config_profiles.py`
- [ ] 2.4 Extract `schemas/system/health.py` from `api/health.py`
- [ ] 2.5 Extract `schemas/user/user.py` from `api/users.py`
- [ ] 2.6 Extract `schemas/user/user_config.py` from `api/user_config.py`
- [ ] 2.7 Extract `schemas/project/project.py` from `api/projects.py`
- [ ] 2.8 Extract `schemas/project/ssh_key.py` from `api/ssh_keys.py`
- [ ] 2.9 Extract `schemas/project/git_repository.py` from `api/git_repositories.py`
- [ ] 2.10 Update all API routers to import schemas from `src.schemas.*`
- [ ] 2.11 Verify `py_compile` and `ruff` pass
## Phase 3: Docker Service Package Split
- [ ] 3.1 Create `services/docker/__init__.py` with re-exports
- [ ] 3.2 Create `services/docker/compose.py` from `services/docker.py`
- [ ] 3.3 Create `services/docker/container.py` from `services/docker.py`
- [ ] 3.4 Create `services/docker/config_staging.py` from `services/docker.py`
- [ ] 3.5 Create `services/docker/tunnel.py` from `services/tunnel.py`
- [ ] 3.6 Remove `services/docker.py` after verifying imports
- [ ] 3.7 Update `services/tunnel.py` or remove if subsumed
- [ ] 3.8 Update all consumers to import from `services.docker`
- [ ] 3.9 Verify `py_compile` and `ruff` pass
## Phase 4: Service Subpackages
- [ ] 4.1 Move `services/lifecycle_hooks.py``services/instance/lifecycle_hooks.py`
- [ ] 4.2 Move `services/health_monitor.py``services/instance/health_monitor.py`
- [ ] 4.3 Move `services/event_bus.py``services/instance/event_bus.py`
- [ ] 4.4 Move `services/config_profile_resolver.py``services/config/config_profile_resolver.py`
- [ ] 4.5 Move `services/clone.py``services/git/clone.py`
- [ ] 4.6 Move `services/git_operations.py``services/git/git_operations.py`
- [ ] 4.7 Move `services/git_service.py``services/git/git_service.py`
- [ ] 4.8 Move `services/docker_build.py``services/build/docker_build.py`
- [ ] 4.9 Move `services/manifest_compiler.py``services/build/manifest_compiler.py`
- [ ] 4.10 Move `services/terminal_manager.py``services/terminal/terminal_manager.py`
- [ ] 4.11 Move `services/terminal_session.py``services/terminal/terminal_session.py`
- [ ] 4.12 Move `services/tunnel.py``services/shared/tunnel.py`
- [ ] 4.13 Move `services/notification_service.py``services/shared/notification_service.py`
- [ ] 4.14 Move `services/file_service.py``services/shared/file_service.py`
- [ ] 4.15 Move `services/permission_fixer.py``services/shared/permission_fixer.py`
- [ ] 4.16 Move `services/readiness_probe.py``services/shared/readiness_probe.py`
- [ ] 4.17 Move `services/ssh_keys.py``services/shared/ssh_keys.py`
- [ ] 4.18 Move `services/workspace_manager.py``services/shared/workspace_manager.py`
- [ ] 4.19 Move `services/correlation.py``services/shared/correlation.py`
- [ ] 4.20 Extract `services/instance/instance_lifecycle.py` from `api/tool_instances.py`
- [ ] 4.21 Extract `services/config/config_profiles.py` from `api/config_profiles.py`
- [ ] 4.22 Update all imports across the backend
- [ ] 4.23 Verify `py_compile` and `ruff` pass
## Phase 5: API Router Subpackages
- [ ] 5.1 Move `api/tool_instances.py``api/tool/tool_instances.py`
- [ ] 5.2 Move `api/tool_types.py``api/tool/tool_types.py`
- [ ] 5.3 Move `api/tool_definitions.py``api/tool/tool_definitions.py`
- [ ] 5.4 Move `api/tool_types_validation.py``api/tool/tool_types_validation.py`
- [ ] 5.5 Move sessions_router from `api/tool_instances.py``api/tool/sessions.py`
- [ ] 5.6 Move `api/config_profiles.py``api/config/config_profiles.py`
- [ ] 5.7 Move `api/user_config.py``api/config/user_config.py`
- [ ] 5.8 Move `api/workspaces.py``api/workspace/workspaces.py`
- [ ] 5.9 Move `api/workspace_files.py``api/workspace/workspace_files.py`
- [ ] 5.10 Move `api/workspace_git.py``api/workspace/workspace_git.py`
- [ ] 5.11 Move `api/workspace_instances.py``api/workspace/workspace_instances.py`
- [ ] 5.12 Move `api/users.py``api/user/users.py`
- [ ] 5.13 Move `api/auth.py``api/user/auth.py`
- [ ] 5.14 Move `api/ssh_keys.py``api/user/ssh_keys.py`
- [ ] 5.15 Move `api/projects.py``api/project/projects.py`
- [ ] 5.16 Move `api/git_repositories.py``api/project/git_repositories.py`
- [ ] 5.17 Move `api/health.py``api/system/health.py`
- [ ] 5.18 Move `api/events.py``api/system/events.py`
- [ ] 5.19 Move `api/notifications.py``api/system/notifications.py`
- [ ] 5.20 Move `api/dashboard.py``api/system/dashboard.py`
- [ ] 5.21 Move `api/terminal.py``api/system/terminal.py`
- [ ] 5.22 Move `api/instance_proxy.py``api/system/instance_proxy.py`
- [ ] 5.23 Update `main.py` to import from subpackages
- [ ] 5.24 Update all cross-router imports
- [ ] 5.25 Verify `py_compile` and `ruff` pass
## Phase 6: Auth Dependency Refactor
- [ ] 6.1 Add `get_current_user` to `auth/dependencies.py`
- [ ] 6.2 Migrate `api/user/users.py` to use `get_current_user`
- [ ] 6.3 Migrate `api/tool/sessions.py` to use `get_current_user`
- [ ] 6.4 Migrate other routers incrementally
- [ ] 6.5 Verify `py_compile` and `ruff` pass
## Phase 7: Frontend Reorganization
- [ ] 7.1 Rename API files to kebab-case
- [ ] 7.2 Rename page files to `*Page.tsx`
- [ ] 7.3 Move components into `features/` directories
- [ ] 7.4 Update `router.tsx`
- [ ] 7.5 Verify `npm run typecheck` passes
- [ ] 7.6 Verify `npm run build` passes
## Phase 8: Integration and Verification
- [ ] 8.1 Run backend tests: `docker exec hq-api pytest`
- [ ] 8.2 Run backend lint: `ruff check`
- [ ] 8.3 Run frontend typecheck: `npm run typecheck`
- [ ] 8.4 Run frontend build: `npm run build`
- [ ] 8.5 Run `docker compose up --build` and verify API starts
- [ ] 8.6 Verify key user flows manually
- [ ] 8.7 Verify no 404s or import errors in browser console
## Phase 9: Documentation
- [ ] 9.1 Update `AGENTS.md` with new module structure
- [ ] 9.2 Document `get_current_user` vs `get_current_user_id` pattern