- Add/modify routes and endpoints
- Implement service layer logic
- Write tests (maintain async patterns)
- Update docs (README, docstrings)
- Fix lint/format errors
- Refactor within architectural patterns
- Optimize queries
- Database schema (no Alembic - manual updates)
- Dependencies (requirements*.txt)
- CI/CD (.github/workflows/)
- Docker (Dockerfile, compose.yaml)
- Environment variables
- API contracts (breaking changes)
- Global error handling
- .env files (secrets)
- Production configs (without approval)
- Core architecture (layered pattern)
- Async/await patterns (mandatory)
- Type hints (mandatory)
- Pydantic model (
models/player_model.py):
class PlayerStatsModel(MainModel):
wins: int
losses: int- Service method (
services/player_service.py):
async def get_player_stats_async(
async_session: AsyncSession,
player_id: int
) -> PlayerStatsModel:
# Logic with error handling
...- Route (
routes/player_route.py):
@api_router.get(
"/players/{player_id}/stats",
response_model=PlayerStatsModel,
status_code=200
)
async def get_stats(
player_id: int,
async_session: AsyncSession = Depends(generate_async_session)
):
return await player_service.get_player_stats_async(
async_session, player_id
)- Tests (
tests/test_main.py):
def test_request_get_player_id_existing_stats_response_status_ok(client):
"""GET /players/{player_id}/stats with existing ID returns 200 OK"""
...- Validate:
flake8 .→black .→pytest
No Alembic migrations:
- Update
schemas/player_schema.py(SQLAlchemy ORM) - Manually update
storage/players-sqlite3.db - Preserve 26 players
- Update
models/player_model.pyif API changes - Update services
- Add tests
- Routes: HTTP concerns (validation, status codes)
- Services: Business logic, transactions
- Separation: Test logic without HTTP
- FastAPI: Concurrent requests
- SQLAlchemy: Non-blocking I/O
- Never mix sync/async DB access
- API: JavaScript conventions
- Python: snake_case (Pythonic)
- Consistency across comparison repos
Naming Pattern:
test_request_{method}_{resource}_{param_or_context}_response_{outcome}
players(collection) vsplayer(single resource)- Examples:
test_request_get_players_response_status_ok,test_request_post_player_body_empty_response_status_unprocessable
Guidelines:
- Use
tests/player_stub.pyfor data - Test real DB (fixtures handle setup)
- Cover: happy paths + errors + edges
- Cache tests: verify
X-Cacheheader - Docstrings: Single-line, concise, no "Expected:" prefix
- Check
.github/copilot-instructions.mdfor commands - Read existing tests for behavior patterns
- Consider cache invalidation (player data changes)
- Remember: 80% coverage requirement
- Schema changes = manual DB updates
- Query results:
.scalars()for ORM objects - Cache key:
"players"(hardcoded) test_main.py: Excluded from Black- SQLAlchemy errors: Catch + rollback in services
- Validation errors: 422 (not 400)
- Test naming:
test_request_{method}_{resource}_{context}_response_{outcome}pattern
For comprehensive onboarding, see .github/copilot-instructions.md (auto-loaded). This file provides agent-specific autonomy boundaries and workflows.