From 484235f74c11b7f4f465452e6cc70d31b3248caa Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 5 Apr 2026 09:39:47 -0400 Subject: [PATCH] docs: add coding conventions reference --- docs/architecture/conventions.md | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/architecture/conventions.md diff --git a/docs/architecture/conventions.md b/docs/architecture/conventions.md new file mode 100644 index 0000000..154bb4a --- /dev/null +++ b/docs/architecture/conventions.md @@ -0,0 +1,67 @@ +# Coding Conventions + +These are the rules a contributor needs in their head before touching Vigilar. +They are distilled from `CLAUDE.md` and from the patterns already in the codebase. + +## Language and style + +- Python 3.11+. +- Ruff for linting. Line length 100 (see `pyproject.toml`). +- Type hints on all public functions. Internal helpers may omit them when the + types are obvious from context. +- No docstrings unless the logic is non-obvious. Short, well-named functions + should speak for themselves. + +## String constants + +All string constants referenced in more than one place live in +`vigilar/constants.py`. The file uses `StrEnum` for enumerated values — +`ArmState`, `Severity`, `EventType`, `SensorType`, `AlertChannel`, +`RecordingTrigger`, and friends — and a `Topics` class for MQTT topic builders. + +If you are about to write `"MOTION_START"` or `"vigilar/camera/..."` in a second +place, stop and add it to the appropriate enum or the `Topics` class instead. +Defaults like `DEFAULT_IDLE_FPS` also live in this module. + +## Database access + +- SQLite in WAL mode, opened through `vigilar/storage/db.py`. +- SQLAlchemy Core expressions only — no mapped classes, no ORM session. +- Schema lives in `vigilar/storage/schema.py`. Named query helpers live in + `vigilar/storage/queries.py`. +- New tables go in `schema.py`. New query helpers go in `queries.py`. Do not + scatter ad-hoc SQL across subsystem code. + +## Processes and the MQTT bus + +- Each subsystem runs in its own `multiprocessing.Process`, spawned by the + supervisor in `vigilar/main.py` via the `SubsystemProcess` wrapper. Cameras + are the exception: `CameraManager` owns one child process per camera + directly. +- Subsystems communicate only through the local MQTT broker at + `127.0.0.1:1883`. No direct imports or function calls across subsystem + boundaries. +- Topic naming: `vigilar///`. Every topic comes from the + `Topics` class in `vigilar/constants.py` — do not construct topic strings + ad hoc. +- If you are tempted to reach into another subsystem directly, publish a + topic instead. + +## Configuration + +- `config/vigilar.toml` is the only config file the app reads at runtime. +- It is validated by Pydantic v2 models in `vigilar/config.py`. Add new fields + to the Pydantic models, not just to the TOML. +- Secrets are file paths, not inline values. Never put a key, password, or + token directly in the TOML. + +## Testing + +- `pytest` from the repo root. +- Tests live under `tests/`. + +## Committing + +- `ruff check vigilar/` must pass. +- `pytest` must pass. +- One logical change per commit. Commit often.