Highlights — Phase 0 of `scythe inspect`
This release introduces a new product surface for scythe: live-database operational health checks. Static linting catches problems visible in the SQL text; `scythe inspect` catches the ones that only emerge in a running database — foreign keys without covering indexes, tables with policies but Row Level Security disabled, duplicate indexes. Same `Finding` shape, same human / SARIF 2.1.0 / JSON reporters, same severity model and exit-code semantics as `scythe audit`.
This is Phase 0 of a five-phase delivery. See `docs/guide/inspect.md` for the full roadmap through v0.14.0.
Phase 0 check catalog
| ID | Name | Severity | Detection |
|---|---|---|---|
| SC-INS01 | missing-fk-index | warn | Foreign-key columns without a covering index — sequential scan on every join. |
| SC-INS02 | policy-exists-rls-disabled | error | Table has `CREATE POLICY` definitions but `ROW LEVEL SECURITY` is disabled — policies never apply. |
| SC-INS03 | duplicate-index | warn | Two or more indexes on the same table have identical definitions modulo name. |
Detection patterns are clean-room reimplementations of the equivalent supabase/splinter lints (0001, 0006, 0009). No source copied; `ATTRIBUTIONS.md` updated.
What ships
- `scythe inspect ` subcommand with `--format`, `--severity`, `--exit-zero`, `--output`, `--dialect`, `--list-checks` flags. URL resolves from positional arg → `$DATABASE_URL` → `$SCYTHE_DATABASE_URL`.
- New `scythe-inspect` crate carrying a `DbDriver` async trait, a tokio-postgres-backed `PostgresDriver`, and a `MysqlDriver` stub (keeps the trait shape engine-agnostic ahead of Phase 3 MySQL work).
- Public `scythe-inspect` pre-commit hook published via `.pre-commit-hooks.yaml`. CI-mode hook: `always_run: true`, `pass_filenames: false`, requires `$DATABASE_URL` (or `$SCYTHE_DATABASE_URL`) in the hook environment. Phase 1 will add `scythe.toml` `[inspect]` URL sourcing so local pre-commit use becomes natural.
- New CI workflow `.github/workflows/inspect-live.yml` runs the live integration tests against a `postgres:16-alpine` service.
- New docs page `docs/guide/inspect.md` — quick-start, check catalog, severity/exit-code semantics, GitHub Actions recipe, phased roadmap.
Phased roadmap
| Phase | Release | Theme | Engines | Checks added |
|---|---|---|---|---|
| 0 | v0.10.0 (this) | MVP scaffold + 3 checks | PG (MySQL stub) | SC-INS01..03 |
| 1 | v0.11.0 | Full PG check pack + TOML rule registry + `--explain` + `[inspect]` config | PG | SC-INS04..10 |
| 2 | v0.12.0 | Schema drift — declared catalog vs live | PG | SC-DFT01..05 |
| 3 | v0.13.0 | MySQL driver + initial MySQL check pack | PG + MySQL | SC-INS-MY01..06 |
| 4 | v0.14.0 | Stats-based — unused indexes, slow queries via `pg_stat_*` | PG | SC-INS-STAT01..04 |
Upgrade notes
- Pin pre-commit hooks to `rev: v0.10.0` to pick up `scythe-inspect`.
- The `scythe-inspect` hook is CI-mode only at Phase 0 (needs `$DATABASE_URL` in env). Local pre-commit runs without the variable will fail loudly. This is intentional; Phase 1 makes local use natural.
- All workspace crate versions bumped 0.9.0 → 0.10.0; the new `scythe-inspect` crate ships at 0.10.0.
See `CHANGELOG.md` for the per-rule, per-flag, per-file breakdown.