chase-rs/AGENTS.md
2026-03-09 11:12:18 +01:00

5.6 KiB

AGENTS.md

This file provides guidance to coding agents collaborating on this repository.

Mission

Chase-rs is an efficient implementation of the chase algorithm in Rust for advanced reasoning engines. Priorities, in order:

  1. Correctness of reasoning (sound and complete chase).
  2. Termination guarantees (restricted chase for existential rules).
  3. Performance and scalability.
  4. Clear, maintainable, idiomatic Rust code.

Core Rules

  • Use English for code, comments, docs, and tests.
  • Keep all chase state inside well-defined structs; avoid global mutable state.
  • Prefer small, focused changes over large refactoring.
  • Add comments only when they clarify non-obvious behavior.
  • Follow Rust idioms: use Result for errors, iterators over manual loops, etc.

Quick examples:

  • Good: add a new chase variant by implementing a trait or strategy pattern.
  • Bad: add global configuration that affects all chase instances.

Repository Layout

  • src/: core implementation.
  • src/chase/: chase algorithm modules.
    • term.rs: terms (constants, nulls, variables).
    • atom.rs: atoms (predicate applied to terms).
    • instance.rs: database instance (set of facts).
    • rule.rs: TGDs (tuple-generating dependencies).
    • substitution.rs: variable bindings and unification.
    • engine.rs: core chase algorithm.
  • tests/: integration, regression, and property-based tests.

Architecture Constraints

  • Instance holds the database state (set of ground atoms).
  • Rule represents tuple-generating dependencies (TGDs).
  • The chase engine is stateless; state is passed explicitly.
  • New chase variants should be composable with existing infrastructure.
  • Existential variables generate labeled nulls (Term::Null).

Rust Conventions

  • Target stable Rust (edition 2024, rust-version 1.92).
  • Use #[derive(...)] for common traits where appropriate.
  • Prefer &str over String in function parameters when ownership isn't needed.
  • Use impl Trait for return types when the concrete type is an implementation detail.
  • Run cargo clippy and address warnings before committing.

Required Validation

Run these checks for any non-trivial change:

  1. cargo test (all unit and integration tests)
  2. cargo clippy (lint checks)
  3. cargo fmt --check (formatting)

For performance-sensitive changes:

  1. Add benchmarks if they don't exist
  2. Compare before/after performance

First Contribution Flow

Use this sequence for your first change:

  1. Read src/chase/mod.rs and the relevant module files.
  2. Implement the smallest possible code change.
  3. Add or update tests that fail before and pass after.
  4. Run cargo test.
  5. Run cargo clippy and fix any warnings.
  6. Update docs if public API behavior changed.

Example scopes that are good first tasks:

  • Add tests for an edge case in unification.
  • Implement a new utility method on Instance or Atom.
  • Add support for equality-generating dependencies (EGDs).
  • Improve error handling with proper Result types.

Testing Expectations

  • No chase logic change is complete without tests.
  • Unit tests go in #[cfg(test)] mod tests within each module.
  • Integration tests go in tests/integration_tests.rs.
  • Regression tests for bug fixes go in tests/regression_tests.rs.
  • Property-based tests go in tests/property_tests.rs.
  • Do not merge code that breaks existing tests.

Minimal unit-test checklist:

  1. Create an Instance with relevant facts.
  2. Define rules using RuleBuilder.
  3. Run chase(instance, &rules).
  4. Assert on result.terminated, result.instance, and derived facts.

Example test skeleton:

#[test]
fn test_example() {
    let instance: Instance = vec![
        Atom::new("Pred", vec![Term::constant("a")]),
    ].into_iter().collect();

    let rule = RuleBuilder::new()
        .when("Pred", vec![Term::var("X")])
        .then("Derived", vec![Term::var("X")])
        .build();

    let result = chase(instance, &[rule]);

    assert!(result.terminated);
    assert_eq!(result.instance.facts_for_predicate("Derived").len(), 1);
}

Change Design Checklist

Before coding:

  1. Confirm whether the change affects chase semantics or termination.
  2. Identify affected tests.
  3. Consider impact on API stability.

Before submitting:

  1. Verify cargo test passes.
  2. Verify cargo clippy has no warnings.
  3. Ensure tests were added/updated where relevant.

Review Guidelines (P0/P1 Focus)

Review output should be concise and only include critical issues.

  • P0: must-fix defects (incorrect reasoning, non-termination, soundness bugs).
  • P1: high-priority defects (likely functional bug, performance regression, API breakage).

Do not include:

  • style-only nitpicks,
  • praise/summary of what is already good,
  • exhaustive restatement of the patch.

Use this review format:

  1. Severity (P0/P1)
  2. File:line
  3. Issue
  4. Why it matters
  5. Minimal fix direction

Practical Notes for Agents

  • Prefer targeted edits over broad mechanical rewrites.
  • If you detect contradictory repository conventions, follow existing code and update docs accordingly.
  • When uncertain about correctness, add/extend tests first, then optimize.
  • The chase algorithm has well-defined semantics; consult database theory literature if needed.

Commit and PR Hygiene

  • Keep commits scoped to one logical change.
  • PR descriptions should include:
    1. behavioral change summary,
    2. tests added/updated,
    3. performance impact (if applicable),
    4. API changes (if any).

Suggested PR checklist:

  • Tests added/updated for behavior changes
  • cargo test passes
  • cargo clippy has no warnings
  • cargo fmt applied