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

8.5 KiB

SDD Proposal: Repository Restructuring and Modularization

Overview

The Headquarter codebase has grown organically over ~6 months of active development. What began as a lean full-stack application has accumulated structural debt: monolithic files, mixed concerns, duplicated types, inconsistent naming, and a single 2,844-line stylesheet. This proposal plans a phased refactoring to establish clear module boundaries, enforce a ~200-line-per-file target (hard limit 300), and standardize naming conventions across the entire repo.

Motivation:

  • Files over 400 lines are difficult to reason about, test, and review
  • Pages mix data fetching, state management, form logic, and UI rendering
  • A single stylesheet makes theme changes risky and component isolation impossible
  • Backend routers contain business logic that should live in services
  • Duplicate types (Session, ToolInstance) create drift between API and state layers
  • Naming inconsistencies make file discovery harder for new contributors

Desired outcome: A codebase where every file has a single, obvious responsibility; imports follow predictable patterns; and a new developer can locate any functionality within 30 seconds.


Scope

In Scope

  1. Frontend type consolidation

    • Move all domain types from api/*.ts into types/ with clear domain grouping
    • Remove duplication between api/sessions.ts and state/sessions.tsx
    • Standardize type naming and export patterns
  2. Frontend page decomposition

    • Extract inline components (e.g., FileBrowser from repo-workspace.tsx)
    • Split "list + form + dialog" pages into container + presentational components
    • Extract reusable loading/error/retry UI patterns into shared components
  3. Frontend style system restructure

    • Split styles.css into: tokens, global, layout, components, pages, syntax-highlight
    • Remove unused CSS classes (verified by grep/build)
    • Keep visual output pixel-identical (no design changes)
  4. Frontend component organization

    • Group domain-specific components under components/features/{domain}/
    • Keep generic UI primitives at components/ui/
    • Rename page component files to match exported names (e.g., git-history.tsxGitHistoryPage.tsx or rename component)
  5. Backend router decomposition

    • Extract business logic from tool_instances.py, git_repositories.py, config_profiles.py
    • Move helper functions (_get_user, _get_owned_project) to shared dependencies
    • Split large routers by sub-resource (CRUD vs. operations vs. files)
  6. Backend service decomposition

    • Split services/docker.py into compose, container, tunnel, config-staging modules
    • Ensure no service module exceeds 300 lines
  7. Backend seed data extraction

    • Move hardcoded seed data from main.py to seeds/builtin_tool_types.py
  8. Naming convention standardization

    • Frontend React components: PascalCase files matching component name
    • Frontend hooks: camelCase (useTheme.ts)
    • Frontend utilities/api: kebab-case
    • Backend modules: snake_case
    • Document conventions in docs/development/naming.md

Out of Scope (Non-Goals)

  1. No behavior changes — All user-facing functionality stays identical; this is pure restructuring
  2. No new features — We are not adding capabilities, only reorganizing existing ones
  3. No technology swaps — Keeping React 18, Vite, FastAPI, SQLAlchemy, xterm as-is
  4. No test rewrites — Existing tests should pass after path updates; we are not changing test frameworks or strategies
  5. No database migrations — Model files stay in place; only code organization changes
  6. No build system changes — Keep existing vite.config.ts, tsconfig.json, pyproject.toml
  7. No CI/CD changes — Existing quality gates (typecheck, lint, pytest) must continue to pass
  8. No documentation overhaul — We will add a naming conventions doc, but not rewrite all docs

Risks and Mitigations

Risk Likelihood Impact Mitigation
Import path breakage High Medium Use IDE/automated refactor for import rewrites; run full typecheck after every phase
CSS regression Medium High Split styles incrementally; verify each page visually after each CSS file split; keep original styles.css as backup during migration
Lost git history Medium Low Use git mv for file moves; avoid copy-delete patterns
Test failures from path changes High Low Update test imports alongside source imports; run test suite after each phase
Scope creep Medium High Strict non-goals list; pause between phases; require explicit approval to expand scope
Merge conflicts with active development Medium High Coordinate timing; prefer short phases with quick PRs; avoid refactoring files with active feature branches
Reviewer fatigue Medium Medium Auto-forecast at 400 lines; split into chained PRs; each PR limited to one concern
Accidental behavior change Low High Pure cut-paste with no logic changes; reviewer checks for any non-import diffs

High-Level Approach

We will execute in 5 phases, each producing an independent, reviewable PR:

Phase 1: Safe Foundations (est. +200/-150 lines, 1 PR)

  • Consolidate types: create types/index.ts with all domain types
  • Update imports in all consumers
  • Extract FileBrowser from repo-workspace.tsx
  • Move seed data from main.py to seeds/
  • Extract shared auth dependencies

Phase 2: Style System Restructure (est. +50/-2,700 lines, 1 PR)

  • Split styles.css into 6 files under styles/
  • Update main.tsx to import new style entry point
  • Verify no visual regressions

Phase 3: Backend Router Decomposition (est. +800/-1,500 lines, 2-3 chained PRs)

  • PR 3a: Extract shared dependencies and helpers
  • PR 3b: Split tool_instances.py → router + services
  • PR 3c: Split git_repositories.py and config_profiles.py

Phase 4: Frontend Page Decomposition (est. +600/-1,200 lines, 2-3 chained PRs)

  • PR 4a: Split tool-workshop.tsx into feature components
  • PR 4b: Split sessions.tsx, dashboard.tsx, repo-workspace.tsx
  • PR 4c: Rename page components and files for consistency

Phase 5: Testing & Polish (est. +300/-50 lines, 1 PR)

  • Add tests for extracted components
  • Document naming conventions
  • Final cleanup: remove dead code, unused exports

Total estimated churn: ~2,000 lines added, ~5,700 lines removed (net: files become smaller and more numerous)


Acceptance Criteria

Overall

  • No file in src/ exceeds 300 lines (exceptions: auto-generated migration files)
  • tsc --noEmit passes with zero errors
  • eslint passes with zero warnings
  • All existing tests pass (frontend: vitest; backend: pytest)
  • No visual regressions in key pages (verified manually or via existing e2e)
  • No behavior changes — all user flows work identically

Per Phase

  • Phase 1: All types centralized; zero duplicated type definitions; seed data extracted
  • Phase 2: styles.css deleted; styles split by concern; no visual regressions
  • Phase 3: No router exceeds 300 lines; business logic lives in services; no inline Docker/git ops in routers
  • Phase 4: No page exceeds 300 lines; inline components extracted; naming consistent
  • Phase 5: Naming convention doc exists; extracted components have basic tests

Review Workload Forecast

Phase Est. Changed Lines PR Strategy
Phase 1 ~350 Single PR
Phase 2 ~2,750 Single PR (mostly CSS reorganization)
Phase 3a ~400 Single PR
Phase 3b ~800 Single PR
Phase 3c ~700 Single PR
Phase 4a ~500 Single PR
Phase 4b ~600 Single PR
Phase 4c ~350 Single PR
Phase 5 ~350 Single PR

All PRs are under the 400-line review budget. Phases 2 and 3/4 may require careful review focus due to file move volume, but each PR stays within the limit.


Open Questions

  1. Should we adopt CSS Modules for component styles, or keep global CSS with BEM-like naming?
  2. Should backend routers be versioned under api/v1/ now, or keep flat api/ structure?
  3. Should extracted frontend feature components live in components/features/ or features/ at root?
  4. Do we want to introduce barrel exports (index.ts) for each domain module?
  5. Should we run this refactor in a feature branch, or merge each phase to main immediately?

Proposal prepared for SDD review. Next phase: Spec writing with detailed requirements and scenarios.