Contributing¶
Dev workflow and expectations.
Environment setup¶
Dependencies via uv. Update uv first:
uv self update
If uv self update fails (pip-installed uv, or GitHub API rate limits from cloud/sandbox egress IPs), upgrade from PyPI instead:
python3 -m pip install --user --upgrade uv
Install project + dev + docs groups plus the local-turn (numpy + huggingface_hub, imported by test collection) and local-embed (fastembed, needed at runtime) extras:
uv sync --dev --group docs --extra local-turn --extra local-embed
See Installation for runtime prerequisites (libopus, Discord token, OpenRouter key, Cartesia key, etc.).
TDD workflow¶
Red / green TDD:
- Failing test first (red).
- Minimum code to pass (green).
- Refactor if needed.
Import errors don't count as red. A test failing on ImportError / ModuleNotFoundError is not a valid red — the module or function must exist before the test can fail for the right reason.
After every code change¶
Run the same four checks CI runs:
uv sync --dev --extra local-turn --extra local-embed # sync deps
uv run ruff check # lint
uv run ruff format # format
uv run ty check # type-check
uv run pytest # run suite
Or run scripts/ci-local.sh for all of the above in one pass — the same job CI runs.
Cheap on a clean tree. Local failures fail CI the same way — fix root cause before pushing.
Tests marked @pytest.mark.integration hit live services (e.g. OpenRouter) and skip by default. Run explicitly:
uv run pytest -m integration # needs OPENROUTER_API_KEY etc. in env
Docs build & preview¶
Built with mkdocs-material. Local preview:
uv run mkdocs serve
Strict build (fails on broken internal links — what CI runs):
uv run mkdocs build --strict
Commit style¶
- Conventional prefix (
feat:,fix:,docs:,refactor:,test:,chore:) + imperative description. - Body explains why, not what — diff shows the what.
- Keep commits focused. Bug fix shouldn't drag a refactor; refactor shouldn't drag a bug fix.
Scope discipline¶
- No features, refactors, or "improvements" beyond the task. Bug fixes don't need surrounding cleanup. Simple features don't need extra configurability.
- No error handling, fallbacks, or validation for scenarios that can't happen. Trust internal guarantees. Validate only at system boundaries (user input, external APIs).
- No helpers / abstractions for one-time ops. Three similar lines beats a premature abstraction.
- No design for hypothetical future requirements. Design decisions holds rejected ideas — check there first.
Where things live¶
- Architecture overview — big picture, component map.
- Configuration model — two-level config split, on-disk layout.
- Security — credential storage, logging rules.
- Design decisions — rejected ideas.