ee1fa6bee5
- 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)
173 lines
8.5 KiB
Markdown
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.*
|