chase-rs/AGENTS.md

181 lines
5.6 KiB
Markdown
Raw Permalink Normal View History

2026-03-09 09:59:10 +01:00
# 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:
```rust
#[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