Contributing¶
Development workflow and expectations for anyone working on Familiar-Connect.
Environment setup¶
Dependencies are managed with uv. Make sure uv is current before anything else:
uv self update
Install the project and its dev + docs dependency groups:
uv sync --dev --group docs
See Installation for the runtime prerequisites (libopus, Discord token, OpenRouter key, Cartesia key, etc.).
TDD workflow¶
Always follow red / green TDD:
- Write a failing test first (red).
- Write the minimum code to make it pass (green).
- Refactor if needed.
Import errors do not count as red. A test that fails due to an ImportError or ModuleNotFoundError is not a valid red test — the module or function under test must exist before the test can legitimately fail for the right reason.
After every code change¶
Run the same four checks CI runs:
uv sync --dev # keep dependencies in sync
uv run ruff check # lint
uv run ruff format # format
uv run ty check # type-check
uv run pytest # run the suite
These are cheap and fast on a clean working tree. If any fail locally, CI will fail the same way — fix the root cause before pushing.
Tests marked @pytest.mark.integration hit live external services (e.g. OpenRouter) and are skipped by default. Run them explicitly with:
uv run pytest -m integration # requires OPENROUTER_API_KEY etc. in the env
Ruff banned-api rule: bootstrap → runtime is one-way¶
Familiar-Connect splits its modules into two worlds:
- Runtime (
src/familiar_connect/excluding thebootstrap/subpackage) — the code that runs on every Discord message or voice turn. Latency-sensitive, always-on. - Bootstrap (
src/familiar_connect/bootstrap/) — one-shot operator utilities like the character-card unpacker and the SillyTavern lorebook importer. Run by a human, once, to populatedata/familiars/<id>/. Never invoked by the runtime reply pipeline.
A ruff banned-api rule enforces that the runtime never imports from bootstrap. Bootstrap may import runtime types (e.g. MemoryStore); the reverse is forbidden. If you need a helper that both sides use, it belongs in a neutral module (neither in bootstrap/ nor inside the reply path), not in bootstrap/.
See the Bootstrapping guide for what lives in bootstrap/ today.
Docs build & preview¶
The docs site is built with mkdocs-material. Local preview:
uv run mkdocs serve
Strict build (fails on broken internal links — this is what CI runs):
uv run mkdocs build --strict
Commit style¶
- Conventional prefix (
feat:,fix:,docs:,refactor:,test:,chore:) followed by an imperative description. - Body explains the why, not the what — the diff already shows the what.
- Keep commits focused. A bug fix shouldn't drag a refactor with it; a refactor shouldn't drag a bug fix with it.
Scope discipline¶
- Don't add features, refactor code, or "improve" things beyond what the task asked for. A bug fix doesn't need surrounding cleanup. A simple feature doesn't need extra configurability.
- Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal guarantees. Validate only at system boundaries (user input, external APIs).
- Don't create helpers or abstractions for one-time operations. Three similar lines is better than a premature abstraction.
- Don't design for hypothetical future requirements. Design decisions is where rejected ideas live; before designing something new, check whether it's already there.
Where things live¶
- Architecture overview — the big picture, the pipeline diagram, the component map.
- Context pipeline — how providers, processors, and the budgeter fit together.
- Memory — the per-familiar memory directory and
MemoryStore. - Configuration model — the two-level config split, slash commands, on-disk layout.
- Security — credential storage, path-traversal defences, logging rules.
- Design decisions — ideas considered and rejected.
- Roadmap — planned work with per-item rationale.