Files
headquarter/openspec/changes/repo-restructure/proposal.md
T
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

173 lines
8.5 KiB
Markdown

# 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.tsx``GitHistoryPage.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.*