rust-rule-engine 1.19.1

A blazing-fast Rust rule engine with RETE algorithm, backward chaining inference, and GRL (Grule Rule Language) syntax. Features: forward/backward chaining, pattern matching, unification, O(1) rule indexing, TMS, expression evaluation, method calls, streaming with Redis state backend, watermarking, and custom functions. Production-ready for business rules, expert systems, real-time stream processing, and decision automation.
Documentation
# Agent Guidelines for rust-rule-engine

This document provides guidelines for AI coding agents working on the `rust-rule-engine` codebase.

## Project Overview

A production-ready Rust rule engine (v1.16.1) featuring:
- RETE-UL algorithm for forward chaining
- Backward chaining inference (goal-driven reasoning)
- GRL (Grule Rule Language) parser
- Streaming event processing with Redis state backend
- Plugin system with 44+ actions and 33+ functions
- Truth Maintenance System (TMS)

**Repository:** https://github.com/KSD-CO/rust-rule-engine
**License:** MIT
**Rust Edition:** 2021

## Build Commands

### Standard Build & Test
```bash
cargo build --verbose --all-features          # Build with all features
cargo test --verbose --all-features           # Run all tests
cargo clippy --all-targets --all-features -- -D warnings  # Lint
cargo fmt                                     # Format code
```

### Makefile Shortcuts
```bash
make ci                # Full CI pipeline (fmt-check, clippy, build, test, test-features, doc-test)
make check             # Quick check (fmt, clippy, test)
make test              # Run all tests with all features
make clippy            # Run clippy with -D warnings
make fmt               # Format code
make fmt-check         # Check formatting without modifying
make build             # Build project
make doc-test          # Run documentation tests
make test-features     # Test all feature combinations
```

### Running a Single Test
```bash
# Run a specific test by name
cargo test test_name --all-features

# Run tests in a specific file
cargo test --test grl_harness --all-features

# Run a single test with output
cargo test test_name --all-features -- --nocapture

# Run tests matching a pattern
cargo test backward --all-features

# Run doc tests only
cargo test --doc
```

### Feature Flags
```bash
# Test with specific features
cargo test --no-default-features --lib                          # No features
cargo test --features backward-chaining --lib                   # Backward chaining only
cargo test --features streaming --lib                           # Streaming only
cargo test --features "backward-chaining,streaming" --lib       # Multiple features
```

### Examples
```bash
# Run all examples (26 total)
make all

# Run by category
make getting-started        # 4 examples
make rete-engine           # 5 examples
make advanced-features     # 6 examples
make performance           # 3 examples (runs in --release mode)
make backward-chaining     # 4 examples (requires backward-chaining feature)
make module-system         # 2 examples

# Run individual example
cargo run --example grule_demo
cargo run --features backward-chaining --example simple_query_demo
cargo run --release --example quick_engine_comparison
```

### Benchmarks
```bash
cargo bench                                      # Run all benchmarks
cargo bench --bench engine_comparison_benchmark  # Specific benchmark
```

## Code Style Guidelines

### General Conventions

**Rust Edition:** 2021 with standard Rust formatting (no custom rustfmt.toml)

**Linting:**
- Clippy with `-D warnings` (all warnings are errors in CI)
- `#![warn(clippy::all)]` in lib.rs
- Use `#[allow(clippy::lint_name)]` sparingly and only when justified

**Documentation:**
- Use `///` for public API documentation
- Use `//!` for module-level documentation
- Include examples in doc comments where helpful
- Missing docs warning is currently disabled but documentation is encouraged

### Import Style

**Order (as used in the codebase):**
1. Crate-level imports (`crate::` or `super::`)
2. External crate imports (chrono, regex, log, etc.)
3. Standard library imports (`std::`)

**Pattern:**
```rust
// 1. Crate-level imports first
use crate::engine::{
    agenda::AgendaManager,
    facts::Facts,
    knowledge_base::KnowledgeBase,
};
use crate::errors::{Result, RuleEngineError};
use crate::types::{ActionType, Value};

// 2. External crate imports
use chrono::{DateTime, Utc};
use log::info;

// 3. Standard library imports
use std::collections::HashMap;
use std::time::{Duration, Instant};
```

**Note:** Use blank lines to separate the three groups for clarity.

### Naming Conventions

**Types:** PascalCase
```rust
struct RustRuleEngine { }
enum Value { }
type CustomFunction = Box<dyn Fn(...) -> Result<Value>>;
```

**Functions/Methods:** snake_case
```rust
pub fn execute_with_callback(&mut self) -> Result<GruleExecutionResult>
pub fn to_string(&self) -> String
```

**Constants:** SCREAMING_SNAKE_CASE
```rust
const MAX_CYCLES: usize = 100;
```

**Modules:** snake_case (single word preferred)
```rust
pub mod engine;
pub mod backward;
pub mod streaming;
```

### Type Usage

**Prefer explicit types for public APIs:**
```rust
pub fn new(name: &str) -> Self
pub fn execute(&mut self, facts: &Facts) -> Result<GruleExecutionResult>
```

**Use type aliases for complex types:**
```rust
pub type Result<T> = std::result::Result<T, RuleEngineError>;
pub type CustomFunction = Box<dyn Fn(&[Value], &Facts) -> Result<Value> + Send + Sync>;
```

**Prefer owned types in structs, borrowed in function parameters:**
```rust
pub struct Rule {
    pub name: String,              // Owned
    pub conditions: Vec<Condition>, // Owned
}

pub fn add_rule(&mut self, rule: Rule) -> Result<()>  // Owned
pub fn evaluate(&self, facts: &Facts) -> Result<bool> // Borrowed
```

### Error Handling

**Use `thiserror` for error definitions:**
```rust
use thiserror::Error;

#[derive(Error, Debug)]
pub enum RuleEngineError {
    #[error("Parse error: {message}")]
    ParseError { message: String },
    
    #[error("IO error: {0}")]
    IoError(#[from] std::io::Error),
    
    #[error("Type mismatch: expected {expected}, got {actual}")]
    TypeMismatch { expected: String, actual: String },
}
```

**Use `Result<T>` type alias:**
```rust
pub type Result<T> = std::result::Result<T, RuleEngineError>;

pub fn parse_rules(input: &str) -> Result<Vec<Rule>> {
    // Implementation
}
```

**Propagate errors with `?` operator:**
```rust
let rules = GRLParser::parse_rules(&content)?;
let value = facts.get("field")?;
```

### Module Organization

**Structure:**
```
src/
├── lib.rs                 # Public API re-exports
├── errors.rs              # Error types
├── types.rs               # Core type definitions
├── engine/                # Forward chaining engine
│   ├── mod.rs
│   ├── engine.rs
│   ├── facts.rs
│   └── knowledge_base.rs
├── backward/              # Backward chaining (feature-gated)
├── rete/                  # RETE algorithm
├── streaming/             # Streaming (feature-gated)
└── parser/                # GRL parser
```

**Re-exports in lib.rs:**
```rust
pub use errors::{Result, RuleEngineError};
pub use types::{Value, Operator};
pub use engine::engine::RustRuleEngine;
pub use parser::grl::GRLParser;
```

### Feature Gates

**Conditional compilation:**
```rust
#[cfg(feature = "backward-chaining")]
pub mod backward;

#[cfg(feature = "streaming")]
pub mod streaming;
```

**Optional dependencies:**
```rust
// In Cargo.toml
[dependencies]
tokio = { version = "1.42", features = ["full"], optional = true }

[features]
streaming = ["tokio"]
```

### Testing

**Test organization:**
- Unit tests: Inline with `#[cfg(test)]` modules
- Integration tests: `tests/` directory
- Doc tests: In doc comments

**Test style:**
```rust
#[test]
fn test_name() -> Result<(), Box<dyn std::error::Error>> {
    let facts = Facts::new();
    facts.set("field", Value::Number(42.0));
    
    assert_eq!(facts.get("field")?, Value::Number(42.0));
    Ok(())
}
```

**Use `#[allow(clippy::lint)]` for test-specific patterns:**
```rust
#![allow(clippy::unnecessary_get_then_check)]
```

## Dependencies Philosophy

**Minimize dependencies:** The project recently reduced from 12 to 7 core dependencies (v1.16.1), preferring standard library over external crates:
- `std::thread::available_parallelism()` instead of `num_cpus`
- `std::sync::OnceLock` instead of `once_cell`
- `std::collections::hash_map::RandomState` instead of `fastrand`

**Core dependencies (only add if necessary):**
- serde/serde_json - serialization
- regex - pattern matching
- thiserror - error handling
- chrono - date/time
- log - logging facade
- nom - parser combinators

## Performance Considerations

- Use indexing for O(1) lookups (alpha/beta memory)
- Leverage parallel execution where appropriate
- Benchmark changes with criterion (see `benches/`)
- Profile memory usage for large-scale scenarios

## CI/CD

GitHub Actions workflow runs on:
- Push to `main`
- Pull requests to `main`
- Tags matching `v*.*.*`

**CI checks:**
1. Format check (`cargo fmt -- --check`)
2. Clippy (`-D warnings`)
3. Build (`--all-features`)
4. Tests (`--all-features`)
5. Feature combination tests (5 combinations)
6. Doc tests

**Before committing:**
```bash
make ci  # Runs full CI pipeline locally
```