# Project Guide ## Project - Python clean architecture template - FastAPI is the current HTTP adapter - The web layer must stay replaceable - Repository and usecase instances are created once at startup - Config comes from YAML plus env into one dataclass tree - Logs metrics and traces stay behind interfaces and use OTel adapters - Request logging middleware is used - Metrics middleware is used - Custom trace middleware is not used - API versioning lives under `/api/v1` ## Structure - `domain/` core model and domain errors - `domain/error.py` domain errors - `domain/user.py` example domain model - `usecase/` interfaces and usecases - `usecase/interface.py` repository and observability interfaces - `usecase/user.py` example user usecase - `repository/` repository implementations - `repository/user.py` example in-memory repository - `adapter/config/` config models and loader - `adapter/otel/` logger metrics tracer and OTel setup - `adapter/di/` container and startup wiring - `adapter/http/fastapi/` app dependencies lifespan middleware routers - `config/` app YAML and OTel collector config - `docs/` ADR files - `tasks.md` task list - `main.py` local entrypoint ## Boundaries - Keep dependency direction inward - `domain` imports nothing internal - `usecase` may import `domain` - `repository` may import `usecase` and `domain` - `adapter` may import `usecase` and `domain` - Do not import FastAPI into `domain` or `usecase` - Do not import OpenTelemetry into `domain` or `usecase` - Keep HTTP models and middleware inside `adapter/http/fastapi/` ## Workflow - Use dir `tasks/` for planning - Do not use Beads - Do not use `bd` - Use `uv` for Python commands and dependency management - Prefer delegation for implementation - After implementation, run `Code-Reviewer` agent - Pass errors to `test-engineer` agent to capture - Delegate `Feature-Developer` agent fix the errors - Repeat the cycle until no errors remain - Ensure all tests pass ## Makefile - `make install` install deps with `uv` - `make run` start the app locally - `make run-otel` start the app with OTel env - `make lint` run `ruff` - `make typecheck` run `mypy` - `make test` run `pytest` - `make pre-commit` run lint typecheck test - `make compose-build` build the containers - `make compose-up` start app and collector - `make compose-down` stop the stack - `make compose-logs` show app and collector logs - `make compose-ps` show compose status ## Runtime - Local run needs `APP_API_TOKEN` and `APP_SIGNING_KEY` - Base config lives in `config/app.yaml` - Env overrides come from shell vars or `.env` - OTel collector config lives in `config/otel-collector.yaml` ## Style - Comments are short and have no trailing period - Error messages are short and have no trailing period - Use single-word comments when possible - Use single-word error messages when possible - Keep names simple - Keep adapters thin - Keep `__init__.py` empty - Prefer explicit wiring over magic - Do not expand scope without user approval - Do not `from __future__ import annotations` - Do not `from importlib import import_module` - Do not `importlib` - Do not `cast`