Skip to content
Menu

Documentation

Contribution Guide

Sandloom enforces its conventions in CI. The quality gates must be green before any commit; pre-commit hooks run the fast ones automatically. To get a working checkout, start with Set up the repository.

Branches and owner review

Use a short-lived branch and open a PR against main. Final review and manual merge belong to @Maryarty. See branches and owner review for the workflow, protection configuration and verification procedure.

CI profiles

Automatic PR checks use Python 3.12 and select checks by changed area. The full compatibility matrix and heavy scenarios run explicitly before release. See CI profiles and minute budget for the exact split and commands.

The website publishing guide covers the unified site, GitHub Pages and DNS setup separately from package publishing.

Quality gates

Run from the repository root:

docker compose -f deploy/compose/test.yml up -d --wait   # test Postgres + Redis
uv sync                                                  # pinned dev tools
uv run sandloom test <module>                                 # iterate: module tests, fast suite, gates
uv run sandloom test --full                                   # once, at the end: full suite + gates

sandloom test runs the tests in parallel, then ruff, ruff format, mypy, sandloom check, the architecture tests, lint-imports and the contract and route snapshots; sandloom test --plan prints the steps. Do not re-run a serial pytest -q after each fix. See Testing and the CLI reference.

uv sync installs the dev dependency group (ruff, mypy, pytest pinned exactly and locked in uv.lock); CI uses uv sync --frozen and the hooks uv run --locked. Bump a tool by editing its pin, running uv lock, and fixing its new findings in the same change.

Lint suppressions are ratcheted — new # noqa markers fail unless argued in review, and BLE001 / bandit markers must carry a reason: see Lint policy.

Guarantee ledger. Every guarantee and capability is an entry in guarantees.yml with the tests that prove it (reference); tests/architecture/test_guarantee_ledger.py gates it. Every change that removes or infers a declaration (a marker, a dependency, a policy flag) keeps the ledger green and either shows the same enforcing tests passing (uv run pytest -m guarantees src) or justifies each changed enforcing test in the PR; deleting an entry needs a removed: record with the reason and the owner's approval.

When GitHub Actions cannot run, verify a branch/PR with the local Docker CI runner before merging: tools/ci/ci_local.sh <git-ref> reproduces the CI jobs (act + a fallback runner) on an exported ref — see Local CI runner. SBOM, SAST baseline and PR dependency review: Supply-chain gates.

The one rule that matters

Modules are atomic and isolated. A business module may import only the public sandloom.sdk modules, generated contract stubs and contract DTOs, and its own package. Never import one business module from another. AST-based architecture checks block violations (sandloom check, SANDLOOM-C001 / SANDLOOM-C002). See Modules.

Adding a module — the golden path

uv run sandloom add module <snake_case_name>
uv run sandloom test <snake_case_name>

The module is discovered: no SANDLOOM_MODULES or testpaths edit is needed. Then generate its migration in its own chain (sandloom migrate new) and replace the example domain. Full walkthrough: Add a module and the tutorial.

Documentation

Docs live in docs/ and build with Zensical:

uv sync --extra docs
uv run --extra docs python tools/docs/docs_site.py serve
uv run --extra docs python tools/docs/docs_site.py build

The SDK reference pages are generated from the sandloom.sdk modules (their __all__, __beginner__ and docstrings); the configuration reference is generated from the settings model and the error catalogue from the error-code registry. llms.txt and processed Markdown copies are generated by Zensical. CI uploads the built site as an artifact. Deployments are separate from documentation builds. When you change the public surface, update the docstrings and run sandloom docs --write; don't hand-write a second copy.

Published documentation is English. Historical reviews/design drafts preserve their original language and date; they are evidence, not the current reference. CHANGELOG.md is the authoritative implementation changelog; the portal changelog is a reader-facing digest and must be reconciled before tagging a release. Do not infer release readiness from an old benchmark or design note.

Conventions recap

  • Event channels are versioned: <module>.<event>.v1.
  • API layer: no sqlalchemy imports, no ORM models — DTOs + services that use db().
  • Reference other modules' entities by plain UUID; no cross-module FKs.
  • Never call db.commit() / db.rollback() — the Unit of Work owns the boundary.
  • See Versioning & Stability for the public-API and event-schema compatibility policy.