Thanks for taking the time to contribute! Whether it's a bug fix, a docs tweak, or a whole new feature, contributions are very welcome. This guide covers the workflow.
- Found a bug or have an idea? Open an issue first. For anything beyond a small fix, please discuss it in an issue before writing code — it saves everyone time and avoids surprises at review.
- Check the open issues to see if someone's already on it.
The dashboard uses uv for dependency management — a hashed
uv.lock pins every transitive dependency so installs are reproducible build-to-build. Its
Python tooling (ruff lint + format,
pre-commit) lives in the dev extra. Install uv, then from the
repo root:
uv sync --project build/dashboard --extra dev # deps + tooling into build/dashboard/.venv, from the lock
uv run --project build/dashboard pre-commit installmake test and make lint-py run through uv automatically (no venv to activate); pre-commit
then runs ruff (plus a few hygiene hooks) on your changed files. If you change dependencies in
build/dashboard/pyproject.toml, run uv lock and commit the updated uv.lock.
-
Fork the repo and create a branch off
main. -
Make your change. Keep it focused — one logical change per PR.
-
Run the full test suite locally:
make testThis runs everything CI does without a server or Docker:
- lint — every file surface gets a linter/formatter check (
make lintruns them all; run one withmake lint-<surface>):lint-sh(shellcheck + shfmt),lint-py(ruff),lint-js(Biome),lint-yaml(yamllint),lint-md(markdownlint),lint-proto(buf),lint-toml(taplo). The non-Python tools run vianpx/uvx/docker, so a contributor needs Node, uv, and Docker on PATH (plusshfmt);pre-commitruns the same checks on changed files. Link-checking (lychee) runs on a weekly schedule, not per-PR. - test-dashboard — the dashboard
pytestsuite (must stay ≥ the 80% total coverage gate). CI also runsmake test-patch-coverage(diff-cover): new/changed lines must be ≥ 90% covered vsorigin/develop— the real ratchet that stops coverage rotting at the margin. - test-stack — the
pitheadshell test suite. - test-compose —
docker-compose.ymlinterpolation validation. - test-integration-selftest — the integration harness's own pure logic.
- test-fakes — the tier-2 contract test (real dashboard clients vs controllable fakes).
- the test-inventory drift check — fails if a test was added/removed without
regenerating
docs/test-inventory.md(make test-inventory).
Bigger, infra-dependent suites run separately:
make test-mini-stack(tier-3 docker) andmake test-integration(tier-4 live, against a real box — start with--check). - lint — every file surface gets a linter/formatter check (
-
Add or update tests for your change — cover the intent (a behavior/contract), not just the line. The Testing Guide has per-change recipes; the Testing Strategy explains the tiers.
-
Update the docs in
docs/(and the README, if relevant) for any user-facing change, and runmake test-inventoryif you touched the test suites.
- Target the
mainbranch and fill out the PR template. - Link the issue your PR addresses (e.g.
Closes #123). - Make sure
make testpasses — CI will run the same checks. - PRs require review before merging; the right reviewers are requested automatically via CODEOWNERS.
- Match the surrounding code. Shell scripts should pass
shellcheck --severity=warning; Python is linted and formatted byruff(config inbuild/dashboard/pyproject.toml) — runmake lint-py, orcd build/dashboard && ruff formatto apply it. - Keep commits tidy and messages descriptive.
By contributing, you agree that your contributions are licensed under the project's MIT License. Thanks again! 🙌