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:
+2
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-06-03
|
||||
+23
@@ -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
|
||||
-
|
||||
+23
@@ -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
|
||||
-
|
||||
+319
@@ -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 5–10 Files Per Directory
|
||||
**Decision:** Every directory that functions as a Python module must contain at most 5–10 `.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 2–6 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, 2–6 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.
|
||||
+52
@@ -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`)
|
||||
+75
@@ -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
|
||||
+158
@@ -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
|
||||
Reference in New Issue
Block a user