docs: the gate register, held to the effective config by a test
docs/gates.md lists every place a gate deliberately checks less than it could, each with its reason and the count measured when the row was written: - an ESLint rule off, at warn, or not applied, by scope; - a weak compiler flag, a ruff ignore, the basedpyright mode and baseline; - a knip exclusion, a lane that does not run everywhere; - an accepted CVE. gates.contract.test.ts reads the EFFECTIVE configuration and fails when a narrowing has no row: - ESLint's computed config per scope; - the three tsconfigs, ruff.toml, pyrightconfig, pytest.ini and knip.jsonc; - .trivyignore.yaml, where an entry also needs a statement and an expiry; - CI's pip-audit ignores. It also pins `--max-warnings 0`, which is what makes a warn-level rule fail. Seen red on a missing row, a new `off` rule and an allowlist entry without an expiry. CLAUDE.md gains the rule E32 exists for: a gate with any real hit is never switched off or narrowed, and an "enforced by" comment is checked by running the check. The gate descriptions there, in docs/development.md and in backend/app/README.md name the lanes as they now are, and the "directly" recipe points at the full list.
This commit is contained in:
+24
-11
@@ -39,36 +39,49 @@ decisions and the chosen patterns, rendered with the app's real CSS. It never re
|
||||
## The gate
|
||||
|
||||
A change is done when all of this is green. CI runs the same checks server-side
|
||||
(`.gitea/workflows/check.yml`), so "main is always green".
|
||||
(`.gitea/workflows/check.yml`), so "main is always green". What each gate deliberately does NOT
|
||||
check — and why — is the [gate register](gates.md); a test fails when a narrowing is missing from it.
|
||||
|
||||
**Backend**
|
||||
|
||||
```bash
|
||||
# lint + format check
|
||||
# lint + format check (ruff is pinned in backend/requirements-dev.txt)
|
||||
python -m ruff check --config backend/ruff.toml backend scripts
|
||||
python -m ruff format --check --config backend/ruff.toml backend scripts
|
||||
|
||||
# tests — pure-logic + the DB-backed integration lane, against an ephemeral Postgres.
|
||||
# The backend tree is bind-mounted, so it always tests your working files.
|
||||
# type check — in the test image (requirements.lock does not install on Windows); new errors only,
|
||||
# the pre-existing ones are in backend/.basedpyright/baseline.json
|
||||
docker compose -f backend/docker-compose.test.yml run --rm --no-deps --build test \
|
||||
python -m basedpyright --project pyrightconfig.json
|
||||
|
||||
# tests — pure-logic + the DB-backed integration lane, against an ephemeral Postgres, ending with the
|
||||
# coverage total. The backend tree is bind-mounted, so it always tests your working files.
|
||||
docker compose -f backend/docker-compose.test.yml up --build --abort-on-container-exit --exit-code-from test
|
||||
docker compose -f backend/docker-compose.test.yml down -v
|
||||
```
|
||||
|
||||
The test compose sets `SIFTLODE_TEST_REQUIRE_DB=1`, which turns a would-be silent skip (no DB, or no
|
||||
ffmpeg) into a hard failure — so the gate can't print green while the DB-backed tests were quietly not
|
||||
run. Tests that need a database take the `db` fixture (`backend/tests/conftest.py`); the rest are
|
||||
pure-logic and run without one.
|
||||
A missing database or ffmpeg is a hard error, not a skip — so the gate can't print green while the
|
||||
DB-backed tests were quietly not run (`SIFTLODE_TEST_REQUIRE_DB=0` is the explicit "pure-logic only"
|
||||
run for a machine without Postgres). Tests that need a database take the `db` fixture
|
||||
(`backend/tests/conftest.py`); the rest are pure-logic and run without one.
|
||||
|
||||
**Frontend** (from `frontend/`)
|
||||
|
||||
```bash
|
||||
node ../scripts/check-node-modules.mjs # node_modules == package-lock.json (else: npm ci)
|
||||
npm run typecheck # tsc x3 (app / node / e2e)
|
||||
npm run lint # eslint
|
||||
npm run lint # eslint (typed rules included; warnings fail)
|
||||
npm run format:check # prettier
|
||||
npm run knip # unused exports/deps
|
||||
npm run test # vitest
|
||||
npm run knip # unused files/exports/deps — and unused by what SHIPS (--production)
|
||||
npm run test # vitest (incl. the compiler, size/complexity and gate-register contracts)
|
||||
npx vite build # the production bundle (devOnlyGuard fails it on dev-only code)
|
||||
```
|
||||
|
||||
Coverage is reported, never enforced: `npm run test -- --coverage`, and the pytest lane's last line.
|
||||
The Playwright suite (`npm run e2e`) runs against the `:8080` stack built from your tree; the release
|
||||
requires it. Before an image is pushed, it is scanned with Trivy (HIGH/CRITICAL with a fix fails;
|
||||
exceptions in `.trivyignore.yaml`, each with a reason and an expiry).
|
||||
|
||||
## Branching
|
||||
|
||||
Trunk-based: branch off `main`, keep the branch gate-green, and land the whole change back to `main`
|
||||
|
||||
Reference in New Issue
Block a user