Contributing¶
This section documents the standard development workflow and quality bar for SilentSwarm changes.
Current topics¶
- Environment setup uses Python 3.11+ and editable installs from the repository root.
- Docstring style for public modules, classes, and functions.
- Code style expectations: keep changes focused, prefer existing package patterns, and avoid generated artifact churn.
- Testing expectations: add or update unit tests for new behavior; add integration coverage when behavior crosses leader/fellow/CLI boundaries.
- Documentation expectations: update the closest README or docs page whenever user-facing behavior, commands, config, or APIs change.
Setup¶
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e ".[dev,docs]"
python3 scripts/vendor_frontend.py # pinned UI libraries into the leader's templates/
Add ,runtime to the extras only on a GPU machine — that pulls PyTorch. The
leader is deliberately torch-free and must stay importable without it.
Repository layout¶
src/silent_swarm/
leader/ control plane (FastAPI + web UI) - see below
fellow/ the GPU worker: runner, heartbeat, signals, inventory, log shipper
runtime/ model execution; runtime/torch/ is the ONLY place torch is imported
shared/ contracts.py (leader/fellow/CLI wire types) and mesh.py
transport/ ZeroMQ PUSH/PULL tensor transport
cli/ the `swarm` CLI, one module per command group
bootstrap/ the fellow bootstrap entry point
The leader is the largest package, so it is grouped by domain rather than left
flat. app.py (the FastAPI app and its lifespan) and route_policy.py (the
authorization map covering every route) sit at the top; everything else lives in
the subpackage that owns it:
| Package | Owns |
|---|---|
accounts/ |
users, auth, admin user management, API tokens, the audit log |
pools/ |
the pool store and its HTTP surface |
buckets/ |
pool-scoped training sets and their HTTP surface |
cluster/ |
node lifecycle: bootstrap contract, join sessions, worker registry, signal hub, log buffers |
telemetry/ |
health windows, serving metrics, grades, metric history, VRAM budget, node replacement |
notify/ |
transactional email and operational alerts |
training/ |
jobs, layer partitioning, placement, checkpoints, job metrics |
serving/ |
servable-model export, catalog, inference broker |
web/ |
page builders and templates/ (hand-written HTML/CSS/JS, no framework) |
tests/unit/<area>/ mirrors this tree, subpackages included — a new test for
leader/telemetry/grades.py belongs in tests/unit/leader/telemetry/. Tests
that cut across the whole app (the route-policy sweep, CSRF enforcement, the
relay) sit at tests/unit/leader/, next to what they exercise in app.py.
Imports inside the leader are always absolute
(from silent_swarm.leader.pools.store import PoolStore); nothing is
re-exported from an __init__.py, so every import names the module it comes
from.
Validation¶
Everything CI runs, in the order it runs it:
python -m ruff check . # lint
python -m pytest tests/unit -q # fast suite, no cluster needed
python -m pytest tests/integration -q # leader/fellow/CLI boundaries
mkdocs build --strict # docs must build clean
A new leader API route also has to be classified in leader/route_policy.py —
unlisted routes are default-deny, and tests/unit/leader/test_route_policy.py
fails until you add them.
Changes that touch the web UI run the frontend job as well:
biome ci . # lints the templates JS
npx typescript@5.7.2 tsc -p jsconfig.json # // @ts-check + JSDoc, no build step
node scripts/frontend_smoke.mjs # boots the leader, loads every page
The smoke test fails on any console error, failed request, request to a non-vendored third-party host, or serious/critical axe-core accessibility violation — so a broken page or a regressed contrast ratio fails the build rather than reaching a screenshot.
Documentation screenshots¶
The User Guide carries a screenshot of every page. Regenerate them whenever the UI changes:
# a throwaway leader with its own state, models root, and cookies over http
SWARM_JOIN_STATE_DB=/tmp/guide.sqlite3 \
SWARM_SERVABLE_MODELS_ROOT=/tmp/guide-models \
SWARM_COOKIE_SECURE=0 \
python -m uvicorn silent_swarm.leader.app:app --port 8099
python scripts/screenshot_docs.py --base http://127.0.0.1:8099 \
--state-db /tmp/guide.sqlite3 --models-root /tmp/guide-models \
--out docs/06_user_guide/img
The script seeds a small but complete cluster — four heartbeating nodes, a
deployed two-stage model, an hour of metric history — because a page with no
data documents nothing. Needs playwright and a system Chromium.
Related repository folders¶
tests/src/docs/exp/
Documentation conventions¶
Moved here from the documentation home, which is for readers rather than authors:
- Document current behavior first.
- Keep navigation task-oriented and shallow.
- Prefer Mermaid diagrams for system flows and state machines.
- Keep historical planning separate from operator and developer docs.
- Keep links relative, and give a link the page's title as its text - a bare
some-file.mdreads as a directory listing, not as documentation. - Verify with
python -m mkdocs build --strict.
Building the docs locally¶
source .venv/bin/activate
pip install -e ".[docs]"
python -m mkdocs serve # live reload on http://127.0.0.1:8000
python -m mkdocs build --strict # what CI runs
A standalone mkdocs serve has no /vendor/ path, so the brand fonts fall back
to the system stack - that is expected, and the deployed site serves them from
the same origin as the app. See
The public web surface.