# Contributing to Fester Thanks for your interest in improving Fester! This document covers the basics. ## ๐Ÿš€ Quick Start for Contributors ```bash # 1. Fork + clone git clone https://git.dcos.net/dcosnet/fester.git cd fester # 2. Bootstrap dev environment (creates venv, installs deps + dev tools) ./bootstrap.sh --dev # 3. Run the backend in dev mode (auto-reload on changes) ./run.sh --dev # 4. Run tests (when we have them) pytest # 5. Lint + format ruff check . ruff format . ``` ## ๐Ÿ—๏ธ Architecture Overview Read **[README.md](README.md)** first โ€” it has the full architecture diagram and project layout. The key insight: Fester has a strict separation between: - **EventBus** โ€” the singleton message bus (all events flow through it) - **Subscribers** โ€” bus listeners that index/journal/broadcast events (TimelineStore, cause_graph, FailurePropagator, the WS broadcaster) - **Routers** โ€” FastAPI APIRouters under `backend/api/` that expose REST endpoints - **UI** โ€” vanilla HTML/JS pages under `ui/` that subscribe to the WS stream and call REST endpoints When you add a new feature, ask: 1. Does this emit events? โ†’ Use `bus.emit(EventType.X, ...)` from `backend/events/schema.py` 2. Does this need persistence? โ†’ Add a method to `backend/storage/sqlite_db.py:Storage` 3. Does this need a UI? โ†’ Add a page under `ui/` and a nav entry in `ui/app.js:Fester.mountShell()` 4. Does this need a CLI command? โ†’ Add a subcommand to `cli/fester.py` ## ๐Ÿ“ Coding Standards ### Python - **Python 3.12+** โ€” use modern syntax (match statements, type hints, etc.) - **Type hints** โ€” add them to new code; don't worry about retrofitting old code - **Imports** โ€” use `from backend.X.Y import Z` (not bare `from X.Y import Z`) - **EventBus** โ€” always emit events via `bus.emit()`, never mutate state directly from a request handler - **Pydantic** โ€” use `BaseModel` for request bodies in routers - **Async** โ€” use `async def` for endpoints that touch the DB or do I/O ### JavaScript (UI) - **Vanilla JS** โ€” no frameworks (React, Vue, etc.). Keep it dependency-free. - **Shared shell** โ€” every page calls `Fester.mountShell('page-id')` to get the topbar + WS connection - **API calls** โ€” use `Fester.api(path, opts)` (returns parsed JSON) - **Toasts** โ€” use `Fester.toast(msg, kind)` for user notifications - **No build step** โ€” pages load directly via `