Repository Agents Guide
Purpose: onboarding/runbook for agentic coding assistants operating in this repo. Keep changes small, verifiable, and consistent with CI.
- Environment
- Python: project requires
>=3.12(pyproject.toml); CI uses Python3.12(.github/workflows/unit-tests.yml). - Note:
.python-versioncurrently pins3.13; when reproducing CI issues, prefer Python3.12. - Tooling:
uvis the expected runner for installs, lint, type-check, and tests.
- Install / sync (matches CI)
uv sync --all-extras --frozen
- Lint / format / type-check / security Pre-commit and CI expect these tools:
- Lint + auto-fix + format (ruff):
uv run ruff . --fix
- Type-check (basedpyright):
uv run basedpyright -p pyproject.toml --level error
- Security scan (bandit):
uv run bandit -c pyproject.toml -r .
- Run the full pre-commit suite locally:
pre-commit run --all-files
- Install the git hooks locally:
pre-commit install
- Tests CI runs unit tests only:
uv run pytest tests/unit -q
Running a single test (preferred patterns):
- Single file:
uv run pytest tests/unit/path/to/test_file.py -q
- Single test by nodeid:
uv run pytest tests/unit/path/to/test_file.py::test_name -q
- Quick selection by substring/expression:
uv run pytest -k "unique_substring" -q
Optional (not in CI):
- Integration tests (exist under
tests/integration):
uv run pytest tests/integration -q
- Database + migrations (Alembic)
- Config:
alembic.ini, migration env:migrations/env.py. - Common commands:
uv run alembic current
uv run alembic history
uv run alembic upgrade head
uv run alembic downgrade -1
uv run alembic revision --autogenerate -m "your message"
Note: migrations/env.py imports models via wildcard to register tables with SQLModel.metadata.
- “Full verification” (recommended before PR)
uv run ruff . --fix && uv run basedpyright -p pyproject.toml --level error && uv run bandit -c pyproject.toml -r . && uv run pytest tests/unit -q
- Code style (repo conventions)
- Formatting: let
ruff-formathandle layout; don’t hand-align or fight the formatter. - Line length: follow ruff defaults/config; keep long expressions readable.
- Imports:
- Use 3 groups separated by a blank line: stdlib, third-party, local.
- Prefer absolute imports within the repo.
- Avoid wildcard imports, except for the SQLModel “model registration” pattern noted below.
- Avoid circular imports; use local imports inside functions for optional/late-bound deps.
- Naming:
- Modules/packages:
lower_snake_case. - Classes:
PascalCase. - Functions/vars:
snake_case. - Constants:
UPPER_SNAKE_CASE. - Tests:
tests/unit/.../test_*.pyanddef test_*().
- Modules/packages:
- Types:
- Add precise types on public functions/methods and data models.
- Prefer
collections.abc(Sequence,Iterable, etc.) overtypinglegacy aliases. - Avoid
Anyunless required by a third-party API; when unavoidable, keep theAnylocal. - Type-checker is
basedpyright; follow existing patterns like# pyright: ignore[...]with a short justification. - Prefer
str | NoneoverOptional[str](Python 3.12+).
- Errors:
- No bare
except:; catch specific exceptions orException as exc. - Preserve tracebacks:
raiseorraise NewError(...) from exc. - For FastAPI endpoints, use
raise HTTPExceptionwith appropriate status codes.
- No bare
- Logging:
- Prefer opentelemetry span loggers and structured, actionable messages.
- Don’t log secrets (API keys, tokens, passwords) or entire request bodies by default.
- Async:
- Use
async deffor IO-bound code; don’t block the event loop (use executors for blocking work). - Always
awaitcoroutines; keep lifespans/startup logic minimal.
- Use
Repo layout conventions (as seen in this codebase):
- HTTP endpoints live in
routers/*and are included frommain.py. - DB models live under
database/*/models.pyusing SQLModel. - Cross-cutting auth lives in
middlewares/auth.pyandsecurity/*.
- SQLModel / Alembic repo-specific patterns
- Model registration:
database/general.pyandmigrations/env.pyusefrom ...models import *soSQLModel.metadatasees all tables.- If you add a new model module, ensure it is imported in those aggregation points.
- Keep the existing
# noqa: F403annotations and add a short “why” if you introduce a new one.
- Unit tests use SQLite. If you introduce Postgres-only types, add a SQLite compile shim (see
tests/unit/fixtures/session_fixture.pymappingJSONB->JSON).
- Testing conventions
- Tests should be deterministic and isolated.
- Prefer fixtures from
tests/unit/fixtures/*viatests/unit/conftest.py(it usespytest_plugins). - When touching DB-related code, ensure tests don’t depend on external Postgres; unit tests use SQLite fixtures.
- Security / secrets / env
- Do not commit secrets;
.envis local-only;.env.exampleis the safe template. - Treat these as sensitive:
SECRET_KEY,PROVIDER_API_KEY,FREE_PROVIDER_API_KEY,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY. banditexcludestests/andmigrations/(see[tool.bandit]inpyproject.toml).
- Repo automation files (read before changing workflows)
pyproject.toml: dependencies + tool configuration (bandit, basedpyright)..pre-commit-config.yaml: ruff, bandit, basedpyright, and unit tests..github/workflows/unit-tests.yml: CI usesuv sync --all-extras --frozenthenuv run pytest tests/unit -q.
- Cursor / Copilot rules
- Cursor rules: no
.cursor/rules/and no.cursorrulesfound at repo root. - Copilot instructions: no
.github/copilot-instructions.mdfound.
- When blocked
- If a change impacts secrets, auth, production config, billing, or data retention: stop and ask a targeted question.
- If a check fails: rerun the exact failing command locally and report the minimal failing output needed to diagnose.
- Agent workflow (practical default)
uv sync --all-extras --frozen- Make the smallest change that satisfies the request.
uv run ruff . --fixuv run basedpyright -p pyproject.toml --level error- Run the narrowest relevant test(s) (
pytestnodeid preferred).
If you see anything missing or a CI mismatch, update this document and add a short note in the PR describing why the agent workflow changed.