Coding agents begin at AGENTS.md. This page owns the maintained development environment, commands, and contribution conventions; State of Work owns claims about present delivery.
Contributions are accepted and distributed under MPL-2.0. There is no CLA or private
relicensing grant, and no Signed-off-by trailer is required. See
ADR 00 for the contribution policy and LICENSE for the
binding terms.
- Python is
>=3.12,<3.15;.python-versionpins 3.13 for repository and release checks. Useuvfor dependencies and commands. - Host operation targets a free and open-source Linux stack with systemd, cgroup v2, and rootless Podman/Quadlet. Most repository tests use isolated substitutes and do not prove that a real host works; Summoning owns the live-host prerequisites and rite.
- Frontend work uses Node.js 24.18.0 (
.nvmrc) and npm 11.16.0 (frontend/package.json): supported ranges are 24.18.x-or-newer within Node 24 and 11.16.x-or-newer within npm 11.
Install only what the change needs:
make install
make frontend-install # Frontend changes only
make helpmake install creates or updates .venv from uv.lock, including the local
postgres-binary convenience extra. make frontend-install runs npm ci from the frontend lock.
make init materializes local host layout; it is not a development bootstrap. Use it only for
Summoning or deliberate host-initialization testing.
make lint RUFF_TARGETS="src/lychd tests"
make format-check FORMAT_TARGETS="src/lychd tests"
make type-check TYPECHECK_TARGETS="src/lychd"
make test PYTEST_TARGETS="tests/unit"
make checkOmit a target variable for the repository-wide default. make check runs the complete
non-mutating Python lint, format, type, and test suite—not frontend checks. Use make format only
when you intend to change files.
Tests run in parallel by default. Use N=0 for serial execution, K="expression" for pytest
name selection, and VERBOSE=1 for raw output and long tracebacks. Pytest scratch data defaults to
.cache/pytest; set PYTEST_BASETEMP to another current-user-owned directory when isolation
requires it.
Disposable PostgreSQL receipts are an explicit host-integration profile, not part of ordinary
make check:
make test-containersThat target installs the separate container-test dependency group, requires a working
Docker-compatible daemon, and may pull the pinned pgvector image. Ryuk remains unprivileged by
default. A rootless compatibility environment may deliberately opt in with
TESTCONTAINERS_RYUK_PRIVILEGED=true make test-containers; do not export that setting as a normal
repository default.
For frontend changes, run:
make frontend-check
make frontend-buildBoth regenerate the Litestar OpenAPI contract. The build updates the tracked static Altar in
src/lychd/public/; review and commit it with its source change.
For documentation changes, run:
uv run zensical build --cleanmake docs serves the Hexanomicon at http://localhost:7778 for local inspection.
Start with the closest test that can fail, then widen by boundary:
- Pure domain or utility changes: the matching
tests/unit/subtree. - Database, filesystem, service wiring, or cross-layer changes: matching
tests/integration/tests plus affected unit tests. - Architecture, packaging, public contracts, or documentation topology:
tests/architecture/. - Web contracts or projections: matching
tests/web/tests; addmake frontend-checkwhen the OpenAPI contract or client changes. - Frontend source:
make frontend-checkandmake frontend-build.
Run make check before review when practical. Report skipped host checks: tests, generated plans,
and mocks are not live systemd, Podman, PostgreSQL, GPU, or model-engine receipts.
- Python: Support the declared range, use PEP 695 generics, and keep boot-hook imports lazy where startup order requires it.
- Paths: Do not hardcode user paths such as
~/.config/.... Use thePATH_*authorities insrc/lychd/system/constants.py. - Boundaries: Domain computes intent without host mutation; system services own filesystem, process, systemd, and other effects. Backend route/repository law is in ADR 11.
- Dependencies: Use
uv addoruv removewith the correct dependency group and commit the resultingpyproject.tomlanduv.lockchanges together. Frontend dependencies must likewise update bothfrontend/package.jsonandfrontend/package-lock.json. - Frontend: Follow ADR 15. The Altar is a Svelte 5/SvelteKit
static SPA served by Litestar; do not add SvelteKit server routes, a JavaScript production
server, or handwritten mirrors of generated OpenAPI transport contracts. Coding agents must
also follow the frontend scope before touching
frontend/**. - Logging: Use
structlogwith stable semantic event names. Make fatal initialization errors useful; shared configuration captures exceptions and tracebacks. - Documentation: Follow ADR 01 §Documentation Topology. Root files are thin entry doors; ADRs own accepted decisions, the lexicon owns canonical terms, compositions own native reference application contracts, worked examples, and their local current-material statement, while State of Work owns the shared whole-system evidence envelope. xDDD establishes vocabulary and boundaries in the owning documentation before implementation. Myth is constitutional telos, not evidence that a feature ships. If code changes system truth, update its owning documentation and routing links in the same change.
Keep each contribution cohesive: one reviewable intent, its tests, generated artifacts, and documentation made necessary by changed truth. Do not mix unrelated cleanup into behavior work. Inspect the complete diff and retain third-party notices when dependencies or adapted source change.
A review description should state:
- what behavior or boundary changed;
- which checks ran and their results;
- which live-host or external checks did not run;
- which documentation, generated contracts, or delivery claims changed.
Review against the owning source, test, ADR, and State of Work entry rather than against prose elsewhere that merely repeats them.