# check-safety Standalone Go module: BlockNinja static safety/lint runner. ~25 checks across the consolidated tree. ## Layout ``` check-safety/ ├── main.go # CLI entry, orders all checks ├── check_*.go # one per check, wires its rule to the runner ├── .go # rule implementation (errleak.go, colors.go, ...) ├── *_test.go # unit tests per rule ├── golden_test.go # snapshot test that runs the whole binary on fixtures ├── testdata/golden/ # snapshot fixtures + expected stdout/exit ├── internal/helpers/ # vendored from cms/backend/internal/helpers (LogDeferredError) └── internal/theme/ # vendored from cms/backend/internal/theme (Theme struct + helpers) ``` ## Invariants when editing - This is **standalone** — no imports from sibling repos (CMS, orchestrator, plugins). The two vendored packages above are the only CMS surfaces it depends on, and they are intentional copies. - `blockNinjaRepoRoot()` and `orchestratorRepoRoot()` in `lint_pipeline.go` hardcode the consolidated layout (`~/src/blockninja/{cms,orchestrator}`). Update them if the tree layout changes. - Golden tests are characterisation tests — if you intentionally change a check's output, run `make test-update` and commit the new fixture. - The CMS Makefile's `safety-check` and `install-safety-checker` targets shell out into this directory (`cd ../check-safety`). Keep the CLI contract stable: `check-safety [--flags]`. ## Adding a check 1. New `check_.go` with a `runCheck(rep *reporter, ...)` func. 2. New `.go` for the actual rule logic. 3. Add `_test.go` for unit coverage. 4. Wire into `main.go`'s ordered check list. Numbered comments at the top of `main.go` should stay in sync. 5. If the check is deterministic, add a fixture under `testdata/golden//` and `make test-update`. ## Why vendored, not imported `internal/helpers` and `internal/theme` are inside CMS's `internal/` tree. Go's internal-package rule blocks cross-module imports of `internal/...`. Options were: refactor CMS to make them public (large blast radius), use a `replace` directive (still blocked by internal rule), or vendor (chosen). Drift between CMS and the vendored copies is the whole point of check 21 (preset validation against `theme.Theme`) — it surfaces schema changes.