# normalize-rules/src
Source files for the `normalize-rules` crate.
- `lib.rs` — crate root; re-exports public API from runner, loader, and service modules, including `collect_fact_diagnostics_incremental` for the daemon/LSP incremental eval path.
- `runner.rs` — unified rule management: `RuleKind`, `RulesRunConfig`, `run_rules_report()`, `run_sarif_tools()` (runs `[[rules.sarif-tools]]` entries; when a tool's `watch` globs are set, checks the SQLite findings cache keyed by max mtime of watched files — hit skips the tool, miss runs and stores results), `apply_native_rules_config()`, `collect_fact_diagnostics()` (full-eval), `collect_fact_diagnostics_incremental()` (uses per-rule `ENGINE_CACHE` backed by `CachedRuleEngine` from `normalize-facts-rules-interpret`; primes engines on first call and runs delta-only re-derivation for changed files on subsequent calls), and helpers `enable_disable`/`show_rule`/`list_tags`/`add_rule`/`update_rules`/`remove_rule`. Also exposes `show_rule_structured()` → `RuleInfoReport` and `list_tags_structured()` → `RulesTagsReport` — the structured report variants used by the `rules show` and `rules tags` CLI commands for machine-readable JSON output. `SendableEngine` wraps `CachedRuleEngine` to allow storage in a `static Mutex` (Engine contains JIT raw pointers; the Mutex guarantees serial access). `RuleEntry` includes a `recommended` field. Lock file field is `content_hash` (uses `DefaultHasher`). `enable_disable` returns `Err` on inline-table `[rules]` rather than panicking. `global_allow` is applied to native-rule issues. `try_rules_via_daemon()` — checks if the daemon socket exists and routes rule evaluation through it (using `RunRules` request with `filter_ids`, `filter_rule`, and `engine` parameters) for cached results; covers syntax, fact, and native engines. Falls back to local eval on non-Unix or when daemon is unavailable. `run_rules_report()` tries the daemon for all cacheable engines first, falling back to local evaluation only when the daemon is unavailable.
- `loader.rs` — `format_diagnostic` helper for rendering fact-rule diagnostics to text. Dylib rule pack discovery and loading have been removed; this module no longer performs any dynamic library loading.
- `cmd_rules.rs` — syntax rule execution: `run_syntax_rules()` loads and runs tree-sitter syntax rules, returning raw `Finding` values. Accepts an optional explicit file list (`files: Option<&[PathBuf]>`) and `PathFilter` for pre-walk scoping.
- `service.rs` — `RulesService` with `#[cli]` server-less registration. `load_rules_config()` merges global + project config via `normalize_core::Merge`. Includes `RulesValidateReport`, `validate` (always returns `Ok`; callers check `report.valid`), `setup`, `--fix` (loop capped at 100 iterations), and `compile` / `RulesCompileReport` / `CompileError` / `CompileWarning` for static validation of `.dl` files (`normalize rules compile`). `RuleShowReport` holds formatted output for `enable`/`disable`/`add`/`update`/`remove`; `rules show` now returns `RuleInfoReport` and `rules tags` returns `RulesTagsReport` — both are structured types suitable for agent JSON consumption. `RulesTagsReport` always includes the `rules` array populated (the former `--show-rules` flag that cleared the array on default has been removed). The native engine block is skipped when `report.daemon_cached` is true (daemon already served native results). Otherwise it runs `missing-summary` and `stale-summary` as separate parallel tasks (each reads its own `filenames` and `paths` from config) alongside `stale-doc`, `check-examples`, `check-refs`, `ratchet`, and `budget`. `rules run` accepts `--only` and `--exclude` glob flags to filter which files produce diagnostics. These are compiled into a `PathFilter` early and threaded to syntax rules (pre-walk filtering in `collect_source_files`) and native advisory rules (pre-filtered file list via `filtered_gitignore_walk`). A post-walk safety net filter ensures correctness for all engines. `--files` accepts an explicit list of file paths, bypassing the file tree walker entirely for hook-grade latency. `normalize rules test <file>` runs syntax rules against a single source file and checks inline `// error[rule-id]` annotations; returns `RulesTestReport` with pass/fail and per-mismatch details (unexpected finding or expected finding missing); exits 1 on any mismatch. `normalize rules test-fixtures` runs fixture-based tests (see `FixtureExpectedFinding`, `RulesFixtureTestReport`): discovers `.input.<ext>` + `.expected.json` pairs (single-file) or `<case>/input/` + `<case>/expected.json` directories (multi-file) under `.normalize/rule-tests/`; `--update` rewrites `expected.json` with actual findings for bootstrap. `message` field in `expected.json` is a substring match against the actual diagnostic.
- `setup.rs` — interactive rule setup wizard used by both `normalize rules setup` and `normalize init --setup`; groups violations by tag/category with qualitative impact labels.