Source code for reci.validation.rules

"""Validation rule registry and runner."""

from __future__ import annotations

from collections.abc import Callable, Iterable
from typing import Any

from reci.validation.report import Finding, Severity, ValidationReport

RuleFunc = Callable[..., Iterable[Finding]]

_RULES: dict[str, RuleFunc] = {}


[docs] def register_rule(rule_id: str): """Decorator to register a validation rule function.""" def decorator(fn: RuleFunc) -> RuleFunc: _RULES[rule_id] = fn return fn return decorator
# Import rule modules to trigger registration def _ensure_rules_loaded() -> None: from reci.validation.rules import dag, flow, config_rules, purity, action # noqa: F401
[docs] def run_all_rules( graph, config: dict[str, Any], *, severity_overrides: dict[str, str] | None = None, disabled_rules: set[str] | None = None, ) -> ValidationReport: """Run all registered rules and return a merged report.""" _ensure_rules_loaded() severity_overrides = severity_overrides or {} disabled_rules = disabled_rules or set() findings: list[Finding] = [] for rule_id, fn in _RULES.items(): if rule_id in disabled_rules: continue for finding in fn(graph, config): # Apply severity override if finding.rule_id in severity_overrides: override = severity_overrides[finding.rule_id] if override == "off": continue finding = Finding( rule_id=finding.rule_id, severity=Severity(override), message=finding.message, location=finding.location, suggestion=finding.suggestion, fixable=finding.fixable, ) findings.append(finding) return ValidationReport(findings=findings)