Skip to content

refactor: wave 3b — split api/routes.py (704 LOC) into a package#51

Merged
ty13r merged 1 commit intomainfrom
refactor/wave-3b-routes-split
Apr 19, 2026
Merged

refactor: wave 3b — split api/routes.py (704 LOC) into a package#51
ty13r merged 1 commit intomainfrom
refactor/wave-3b-routes-split

Conversation

@ty13r
Copy link
Copy Markdown
Owner

@ty13r ty13r commented Apr 19, 2026

Summary

Wave 3b — splits api/routes.py (704 LOC) into a package. Follows the same pattern as Wave 3a (queries split): decompose by concern, preserve every public URL, re-target test patches.

Submodule LOC Owns
__init__.py 22 Barrel: single APIRouter(prefix="/api") that includes the sub-routers
_helpers.py 126 classify_run_via_taxonomist — shared between evolve handlers, not a route itself
evolve.py 214 POST /api/evolve + POST /api/evolve/from-parent — endpoints that start runs
runs.py 402 POST /api/runs/{id}/cancel + every GET for reading run state

Largest submodule is 402 LOC — under the 500-LOC ceiling in docs/clean-code.md §2.

Also cleaned up

  • classify_run_via_taxonomist was the last broad except Exception still using logger.warning(..., exc) with redundant exc formatting. Fixed to logger.exception(...) with a clear noqa rationale.
  • _classify_run_via_taxonomist (module-private) renamed to classify_run_via_taxonomist since it's now cross-module.

Test patches

Tests that used patch("skillforge.api.routes.get_run", ...) etc. were patching the import side of the old monolith. Updated to target the new symbol location — ...routes.evolve.get_run for POST-endpoint tests, ...routes.runs.get_run for GET-endpoint tests. No test logic changed, just the patch target strings.

Test plan

  • uv run ruff check skillforge — clean
  • uv run mypy skillforge — 64 files pass
  • uv run pytest tests/ — 403 passed, 2 skipped, 0 failed
  • Frontend untouched, still green

What's next

Remaining hotspots (agents/spawner.py 805, agents/breeder.py 619, engine/variant_evolution.py 622, agents/managed_agents.py 605) are agent / engine logic — trickier than routes+queries. Those are being deferred so we can move to Wave 4 (frontend API layer with TanStack Query) which is a cleaner Pareto win than splitting well-tested agent code.

🤖 Generated with Claude Code

api/routes.py was 704 LOC, the second-biggest backend file after
queries.py (split in wave 3a). Split by lifecycle concern:

  routes/
    __init__.py    (22)  barrel: single APIRouter(prefix="/api") that
                         includes the sub-routers
    _helpers.py   (126)  classify_run_via_taxonomist — shared between
                         evolve handlers, not a route itself
    evolve.py     (214)  POST /api/evolve + POST /api/evolve/from-parent
                         — endpoints that START runs
    runs.py       (402)  POST /api/runs/{id}/cancel + every GET for
                         reading run state

Largest submodule is now 402 LOC, under the 500-LOC ceiling in
docs/clean-code.md §2. Also cleaned up one residual broad except in
classify_run_via_taxonomist (logger.warning -> logger.exception).

Test patches retargeted
-----------------------
Tests that used `patch("skillforge.api.routes.get_run", ...)` etc.
were patching the import side of the old monolith. They're updated to
target the new symbol location — `...routes.evolve.get_run` for tests
hitting POST endpoints and `...routes.runs.get_run` for tests hitting
GET endpoints.

QA
--
  ruff check skillforge     - clean
  mypy skillforge           - 64 files pass
  pytest tests/             - 403 passed, 2 skipped, 0 failed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ty13r ty13r merged commit f6f999a into main Apr 19, 2026
2 checks passed
@ty13r ty13r deleted the refactor/wave-3b-routes-split branch April 19, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant