Static safety/lint runner for the BlockNinja codebase. ~25 invariant
checks across Go and frontend sources. Was at git.dev.alexdunmow.com:block/ninja
in backend/cmd/check-safety/ until the 2026-06-06 consolidation moved
the BlockNinja repos under a shared ~/src/blockninja/ parent.
This repo is the standalone extraction:
- Own go.mod (git.dev.alexdunmow.com/block/check-safety, go 1.26.4)
- Vendored internal/{helpers,theme} from CMS (Go's internal/ rule
blocks cross-module imports; vendoring is the workaround)
- CLI contract unchanged: `check-safety <target-dir> [--flags]`
- CMS Makefile shells into ../check-safety for safety-check /
install-safety-checker targets
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2.3 KiB
2.3 KiB
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
├── <rule>.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()andorchestratorRepoRoot()inlint_pipeline.gohardcode 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-updateand commit the new fixture. - The CMS Makefile's
safety-checkandinstall-safety-checkertargets shell out into this directory (cd ../check-safety). Keep the CLI contract stable:check-safety <target-dir> [--flags].
Adding a check
- New
check_<name>.gowith arunCheck<Name>(rep *reporter, ...)func. - New
<rule>.gofor the actual rule logic. - Add
_test.gofor unit coverage. - Wire into
main.go's ordered check list. Numbered comments at the top ofmain.goshould stay in sync. - If the check is deterministic, add a fixture under
testdata/golden/<case>/andmake 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.