check-safety/CLAUDE.md
Alex Dunmow cd88c808b0 initial: standalone check-safety module hoisted from CMS
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>
2026-06-06 13:04:02 +08:00

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() 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 <target-dir> [--flags].

Adding a check

  1. New check_<name>.go with a runCheck<Name>(rep *reporter, ...) func.
  2. New <rule>.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/<case>/ 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.