docs: add coding conventions reference
This commit is contained in:
67
docs/architecture/conventions.md
Normal file
67
docs/architecture/conventions.md
Normal file
@@ -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/<domain>/<id>/<event>`. 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.
|
||||
Reference in New Issue
Block a user