pub struct RuleEngine<M: PatternMatcher> { /* private fields */ }Expand description
Rule engine for loading and evaluating rules
The engine is generic over the pattern matcher implementation, allowing different matching strategies to be used (regex, literal, etc.).
§Example
use skill_veil_core::rules::{default_external_rule_dirs, RuleEngine};
use skill_veil_core::adapters::{RegexPatternMatcher, StdFileSystemProvider};
use std::sync::Arc;
// Compose adapters at the application boundary; the engine receives
// them through the injected ports.
let fs = StdFileSystemProvider::new();
let runtime_dirs = default_external_rule_dirs();
let engine = RuleEngine::with_defaults_and_matcher(
Arc::new(RegexPatternMatcher::new()),
&fs,
&runtime_dirs,
)
.unwrap();
assert!(engine.rule_count() > 0);Implementations§
Source§impl<M: PatternMatcher> RuleEngine<M>
impl<M: PatternMatcher> RuleEngine<M>
Sourcepub fn with_matcher(matcher: Arc<M>) -> Self
pub fn with_matcher(matcher: Arc<M>) -> Self
Create a new rule engine with a custom pattern matcher.
Sourcepub fn set_checksum_policy(&mut self, policy: ChecksumPolicy)
pub fn set_checksum_policy(&mut self, policy: ChecksumPolicy)
Override the integrity verification policy for external rule
pack bodies. See ChecksumPolicy for the three modes. Default
is WarnOnMissing.
Sourcepub fn set_strict_mode(&mut self, strict: bool)
pub fn set_strict_mode(&mut self, strict: bool)
Toggle strict mode. When enabled, loading an external pack with a
duplicate rule id returns RuleError::DuplicateUserRule instead of
emitting a tracing::warn!() and skipping.
Sourcepub fn with_defaults_and_matcher<F: FileSystemProvider>(
matcher: Arc<M>,
runtime_overlay_fs: &F,
runtime_overlay_dirs: &[PathBuf],
) -> Result<Self, RuleError>
pub fn with_defaults_and_matcher<F: FileSystemProvider>( matcher: Arc<M>, runtime_overlay_fs: &F, runtime_overlay_dirs: &[PathBuf], ) -> Result<Self, RuleError>
Create a rule engine with built-in rules plus an optional runtime
overlay loaded through the injected FileSystemProvider.
§Load order contract
Built-in rules are loaded first, runtime overrides second. The non-strict duplicate-skip means inverting the order would silently discard canonical detections.
§Hexagonal boundary
runtime_overlay_fs and runtime_overlay_dirs are injected so the
domain layer never instantiates a concrete adapter. Production
callers compose them in the application layer (typically
Scanner::with_std_adapters) by pairing StdFileSystemProvider
with default_external_rule_dirs().
Sourcepub fn load_from_dir<F: FileSystemProvider>(
&mut self,
fs: &F,
dir: impl AsRef<Path>,
) -> Result<(), RuleError>
pub fn load_from_dir<F: FileSystemProvider>( &mut self, fs: &F, dir: impl AsRef<Path>, ) -> Result<(), RuleError>
Load rules from a directory through a FileSystemProvider. Going
through the port preserves the hexagonal contract: this loader
reads YAML rule packs from disk, but the domain layer never
reaches std::fs directly.
Sourcepub fn load_rules_file<F: FileSystemProvider>(
&mut self,
fs: &F,
path: impl AsRef<Path>,
) -> Result<(), RuleError>
pub fn load_rules_file<F: FileSystemProvider>( &mut self, fs: &F, path: impl AsRef<Path>, ) -> Result<(), RuleError>
Load rules from a YAML file.
In strict mode (default — see RuleEngine.strict_mode doc-comment
for rationale), an ID that collides with an already-loaded rule
(built-in or earlier-loaded external) returns
RuleError::DuplicateUserRule { id, path }. The pre-flight at the
time of the round-5 strict-mode flip showed 0 collisions between
the embedded builtin_rules.yaml and the rules/official/ packs.
Callers that intentionally want the legacy “warn-and-skip” behaviour
(e.g. tooling that loads many overlapping experimental packs) must
opt out via set_strict_mode(false).
Sourcepub fn add_rule(&mut self, rule: Rule) -> Result<(), RuleError>
pub fn add_rule(&mut self, rule: Rule) -> Result<(), RuleError>
Add a single rule.
Skips the rule if one with the same ID already exists.
Sourcepub fn evaluate(&self, doc: &SkillDocument) -> Vec<Finding>
pub fn evaluate(&self, doc: &SkillDocument) -> Vec<Finding>
Evaluate all rules against a document.
Sourcepub fn rule_count(&self) -> usize
pub fn rule_count(&self) -> usize
Get rule count.
Sourcepub fn test_rule(
&self,
rule_id: &str,
content: &str,
parser: &dyn MarkdownParser,
) -> Result<Vec<Finding>, RuleError>
pub fn test_rule( &self, rule_id: &str, content: &str, parser: &dyn MarkdownParser, ) -> Result<Vec<Finding>, RuleError>
Test a rule against sample content.
The caller injects the MarkdownParser adapter so the domain layer
stays free of concrete adapter dependencies. Production callers in
the CLI pass &PulldownMarkdownParser::new(); tests pass whichever
parser their fixture exercises.