Files
Developer ee1fa6bee5 refactor: centralize types and extract seed data (Task 1.1)
- 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)
2026-06-02 18:56:54 +00:00

26 KiB
Raw Permalink Blame History

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 180)
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.pyschemas/tool_instance.py
  • Extract from api/git_repositories.pyschemas/git_repository.py
  • Extract from api/config_profiles.pyschemas/config_profile.py
  • Extract from api/tool_types.pyschemas/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.tsxAppShell.tsx
    • git-toolbar.tsxGitToolbar.tsx
    • file-editor.tsxFileEditor.tsx
    • instance-list.tsxInstanceList.tsx
    • terminal.tsxTerminalComponent.tsx
    • etc.
  • Rename page files to PascalCase:
    • dashboard.tsxDashboardPage.tsx
    • git-history.tsxGitHistoryPage.tsx
    • repo-workspace.tsxRepoWorkspacePage.tsx
    • etc.
  • Rename API files to kebab-case:
    • tool_types.tstool-types.ts
    • git_repositories.tsgit-repositories.ts
    • config_folders.tsconfig-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