diff --git a/AGENTS.md b/AGENTS.md index 5c59269..fbb1593 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,91 +1,138 @@ -# CLAUDE.md +# Rustagent -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +Last verified: 2026-02-09 ## Project Overview -Rustagent is a Rust-based AI agent framework for autonomous task execution. It uses a two-phase approach: a Planning Agent that breaks down high-level goals into executable tasks, and the Ralph Loop that executes those tasks iteratively with tool access. +Rustagent is a Rust-based AI agent framework for autonomous task execution. The architecture has two layers: -## Development Commands +- **V1 (legacy)**: Planning Agent + Ralph Loop using flat JSON specs +- **V2 (current)**: Graph-based work tracking with typed agent profiles, SQLite persistence, and an agentic runtime loop -### Building and Running -```bash -cargo build # Compile in debug mode -cargo build --release # Compile optimized release build -cargo run -- init # Initialize a new spec directory -cargo run -- plan # Run the planning agent -cargo run -- run # Execute a spec with the Ralph loop -cargo check # Fast compilation check without producing binary -``` +V2 is the active development path. V1 modules (`planning/`, `ralph/`, `spec.rs`) remain for backward compatibility. -### Code Quality -```bash -cargo fmt # Format code using rustfmt -cargo clippy # Run Clippy linter for code improvements -``` +## Development Commands -### Testing ```bash -cargo test # Run test suite -cargo test # Run specific test by name +cargo build # Debug build +cargo build --release # Optimized release build +cargo check # Fast compilation check +cargo fmt # Format code +cargo clippy # Lint +cargo test # Run full test suite +cargo test # Run specific test by name +cargo doc --open # Generate and view documentation ``` -### Documentation +### V2 CLI Commands ```bash -cargo doc --open # Generate and view documentation +cargo run -- project add # Register a project +cargo run -- run --profile coder # Execute a goal with an agent +cargo run -- tasks # List tasks for current project +cargo run -- decisions # List decisions +cargo run -- status # Show project status +cargo run -- search # Full-text search graph nodes +cargo run -- sessions # View sessions and handoff notes +cargo run -- graph export # Export graph as TOML +cargo run -- graph import # Import TOML graph +cargo run -- graph adr # Export decisions as ADR markdown ``` ## Project Structure ``` src/ -├── main.rs # CLI entry point with init/plan/run commands -├── lib.rs # Library exports -├── config.rs # Configuration loading with env var substitution -├── logging.rs # File-based tracing with daily rotation -├── spec.rs # Specification data structures -├── llm/ -│ ├── mod.rs # LlmClient trait and Message types -│ ├── anthropic.rs # Anthropic (Claude) client -│ ├── openai.rs # OpenAI (GPT) client -│ ├── ollama.rs # Ollama (local models) client -│ ├── mock.rs # Mock client for testing -│ └── factory.rs # Client factory based on config -├── planning/ -│ └── mod.rs # Planning Agent implementation -├── ralph/ -│ └── mod.rs # Ralph Loop execution engine +├── main.rs # CLI entry point (clap), V1 + V2 commands +├── lib.rs # Library exports: all public modules +├── config.rs # Configuration loading with env var substitution +├── logging.rs # File-based tracing with daily rotation +├── spec.rs # V1 specification data structures +├── project.rs # Project type and ProjectStore (CRUD over SQLite) +├── db/ # Database layer (SQLite + WAL mode) +│ ├── mod.rs # Database wrapper with async access +│ └── migrations.rs # Schema versioning and migration framework +├── graph/ # Work graph model (see src/graph/AGENTS.md) +│ ├── mod.rs # Core types: NodeType, EdgeType, NodeStatus, GraphNode, GraphEdge +│ ├── store.rs # GraphStore trait + SqliteGraphStore implementation +│ ├── decay.rs # Node decay for context injection (Full/Summary/Minimal) +│ ├── dependency.rs # Dependency resolution helpers +│ ├── session.rs # Session management with handoff notes +│ ├── export.rs # ADR markdown export +│ └── interchange.rs # TOML import/export with content hashing +├── agent/ # Agent types and runtime (see src/agent/AGENTS.md) +│ ├── mod.rs # Agent trait, AgentId, AgentContext, AgentOutcome +│ ├── profile.rs # AgentProfile with inheritance and SecurityScope +│ ├── builtin_profiles.rs # 5 built-in profiles: planner, coder, reviewer, tester, researcher +│ └── runtime.rs # AgentRuntime: agentic loop with token budget and failure thresholds +├── context/ # Context building for agent prompts +│ ├── mod.rs # ContextBuilder + ReadAgentsMdTool +│ └── agents_md.rs # AGENTS.md file discovery and heading extraction +├── llm/ # LLM provider abstraction +│ ├── mod.rs # LlmClient trait, Message, Response (with token tracking) +│ ├── anthropic.rs # Anthropic (Claude) client +│ ├── openai.rs # OpenAI client +│ ├── ollama.rs # Ollama (local models) client +│ ├── mock.rs # Mock client for testing +│ ├── factory.rs # Client factory based on config +│ ├── error.rs # Provider-agnostic error types +│ └── retry.rs # Rate limit handling with retry logic +├── planning/ # V1 Planning Agent (interactive spec creation) +├── ralph/ # V1 Ralph Loop (spec-based task execution) ├── security/ -│ ├── mod.rs # Security validator for paths/commands -│ └── permission.rs # Permission handling (CLI prompts) +│ ├── mod.rs # SecurityValidator for paths/commands +│ ├── permission.rs # Permission handling (CLI prompts) +│ └── scope.rs # SecurityScope: per-agent path/command/network restrictions └── tools/ - ├── mod.rs # Tool trait and registry - ├── file.rs # read_file, write_file, list_files tools - ├── shell.rs # run_command tool - ├── signal.rs # signal_completion tool - ├── factory.rs # Tool registry factory + ├── mod.rs # Tool trait and ToolRegistry + ├── factory.rs # create_default_registry + create_v2_registry + ├── graph_tools.rs # 11 graph tools for agents (create, update, query, claim, etc.) + ├── file.rs # read_file, write_file, list_files + ├── shell.rs # run_command + ├── signal.rs # signal_completion └── permission_check.rs # File permission checking ``` -## Important Notes +## Key Dependencies -### Cargo Edition -The `Cargo.toml` specifies `edition = "2024"`, which requires Rust 1.85.0 or later. This is the recommended edition for new Rust projects as of 2025. +- `rusqlite` (bundled) + `tokio-rusqlite` for async SQLite +- `blake3` for content hashing (interchange format) +- `clap` (derive) for CLI +- `chrono` for timestamps (RFC 3339 everywhere) +- `uuid` v4 for ID generation -### LLM Providers -The project supports three LLM providers: -- **Anthropic** (Claude) - Default, uses tool calling API -- **OpenAI** (GPT-4) - Full tool calling with tool_call_id -- **Ollama** (Local) - For running local models +## Conventions -### Logging -Logs are written to `~/.local/state/rustagent/logs/` with daily rotation. Set `RUST_LOG=rustagent=debug` for verbose output. +### ID Scheme +- Projects/Goals: `ra-XXXX` (4 hex chars from UUID v4) +- Child nodes: `ra-XXXX.N` (dot-separated sequence) +- Edges: `e-XXXXXXXX` (8 hex chars) +- Sessions: `sess-XXXXXXXX` -### Version Control -This repository uses both Git and Jujutsu (`.jj/` directory present). Be aware of this dual VCS setup when making version control operations. +### Database +- All writes use `BEGIN IMMEDIATE` transactions +- WAL journal mode, foreign keys ON, busy timeout 5000ms +- Schema versioned via `schema_version` table; migrations are forward-only ### Architecture Patterns -- **Factory pattern**: Used for LLM clients and tool registry -- **Trait objects**: `dyn LlmClient` and `dyn Tool` for runtime polymorphism -- **Arc/RwLock**: Thread-safe shared state in tool registry +- **Factory pattern**: LLM clients (`create_client`), tool registries (`create_v2_registry`) +- **Trait objects**: `dyn LlmClient`, `dyn Tool`, `dyn GraphStore` for runtime polymorphism +- **Arc wrapping**: `Arc` shared across tools and runtime +- **async_trait**: All async traits use the `async_trait` crate - **anyhow::Result**: Unified error handling across the codebase + +### Agent Profile Resolution +Profiles resolve in order: project-level (`.rustagent/profiles/{name}.toml`) -> user-level (`~/.config/rustagent/profiles/{name}.toml`) -> built-in. Inheritance via `extends` field with cycle detection. + +## Important Notes + +### Cargo Edition +`edition = "2024"` requires Rust 1.85.0+. + +### Logging +Logs at `~/.local/state/rustagent/logs/` with daily rotation. Use `RUST_LOG=rustagent=debug`. + +### Database Location +Default database at `~/.local/share/rustagent/rustagent.db`. + +### Version Control +This repo uses both Git and Jujutsu (`.jj/` directory). Be aware of dual VCS. diff --git a/src/agent/AGENTS.md b/src/agent/AGENTS.md new file mode 100644 index 0000000..9443937 --- /dev/null +++ b/src/agent/AGENTS.md @@ -0,0 +1,33 @@ +# Agent Module + +Last verified: 2026-02-09 + +## Purpose +Defines the agent abstraction and runtime loop for autonomous task execution. Agents are configured via profiles that control their role, allowed tools, security scope, LLM settings, and resource budgets. + +## Contracts +- **Exposes**: `Agent` trait, `AgentProfile`, `AgentContext`, `AgentOutcome`, `AgentRuntime`, `resolve_profile()`, 5 built-in profiles +- **Guarantees**: Runtime stops on token budget exhaustion (returns `TokenBudgetExhausted`). Consecutive LLM/tool failures trigger `Blocked` outcome (configurable thresholds). Profile inheritance detects cycles. `signal_completion` tool ends the loop cleanly. +- **Expects**: An `Arc`, a `ToolRegistry`, and an `AgentContext` with work package tasks and graph store access. + +## Dependencies +- **Uses**: `llm::LlmClient`, `tools::ToolRegistry`, `context::ContextBuilder`, `graph::GraphNode`, `graph::store::GraphStore`, `security::SecurityScope` +- **Used by**: `main.rs` (V2 `run` command wires up the runtime) +- **Boundary**: Does NOT directly access the database; uses `GraphStore` trait + +## Key Decisions +- Profile resolution chain (project -> user -> built-in): Enables per-project customization without forking built-ins +- Inheritance via `extends`: system_prompt appends (child after parent), lists replace, optionals fall through +- SecurityScope per profile: Each agent type has explicit path/command/network restrictions +- Confusion counter pattern: Consecutive failures tracked separately for LLM and tool errors + +## Invariants +- AgentOutcome is always returned (never panics): Completed, Blocked, Failed, or TokenBudgetExhausted +- Token budget warning fires at 80% (configurable), hard stop at 100% +- Built-in profiles: planner (read-only, graph-only), coder (file+shell+graph), reviewer (read-only), tester (file+shell+graph), researcher (read-only) + +## Key Files +- `mod.rs` - Agent trait, AgentId, AgentContext, AgentOutcome enum +- `profile.rs` - AgentProfile struct, ProfileLlmConfig, resolve_profile() with cycle detection +- `builtin_profiles.rs` - planner(), coder(), reviewer(), tester(), researcher() +- `runtime.rs` - AgentRuntime, RuntimeConfig (defaults: 100 turns, 200k tokens, 3 failure threshold) diff --git a/src/agent/CLAUDE.md b/src/agent/CLAUDE.md new file mode 100644 index 0000000..f66a6ac --- /dev/null +++ b/src/agent/CLAUDE.md @@ -0,0 +1 @@ +Read @./AGENTS.md and treat its contents as if they were in CLAUDE.md diff --git a/src/graph/AGENTS.md b/src/graph/AGENTS.md new file mode 100644 index 0000000..07cb8f8 --- /dev/null +++ b/src/graph/AGENTS.md @@ -0,0 +1,34 @@ +# Graph Module + +Last verified: 2026-02-09 + +## Purpose +Provides a persistent, typed work graph for tracking goals, tasks, decisions, and their relationships. Replaces V1's flat JSON spec with a relational model that supports dependency resolution, atomic task claiming, and temporal decay for context injection. + +## Contracts +- **Exposes**: `GraphStore` trait (async CRUD for nodes/edges), `SqliteGraphStore` impl, `SessionStore`, `DecayConfig`, TOML interchange (export/import/diff), ADR export +- **Guarantees**: All writes are atomic (BEGIN IMMEDIATE). Task claiming is race-safe. Node status is validated against node type. Child IDs are hierarchical (`parent.seq`). FTS5 index stays in sync via triggers. +- **Expects**: A `Database` instance (from `db` module). Valid `project_id` for nodes. Parent node must exist before creating children. + +## Dependencies +- **Uses**: `db::Database`, `chrono`, `blake3` (interchange hashing), `uuid` (ID generation) +- **Used by**: `agent::runtime` (via `Arc`), `tools::graph_tools`, `main.rs` (CLI commands) +- **Boundary**: Does NOT depend on `llm`, `agent`, or `tools` + +## Key Decisions +- SQLite over external DB: Single-file persistence, no daemon, WAL for concurrent reads +- Hierarchical IDs (`ra-XXXX.N.M`): Encode parent-child without extra queries +- Trait-based store: `GraphStore` trait enables test doubles and future backends +- TOML interchange: Git-friendly, deterministic output via BTreeMap, content-hashed for change detection + +## Invariants +- Node status must be valid for its NodeType (enforced by `validate_status`) +- Every child node has a Contains edge to its parent (auto-created in `create_node`) +- Completing a task auto-promotes Pending dependents to Ready (inside same transaction) +- Decay levels: Full (<7d), Summary (7-30d), Minimal (>30d) -- configurable via DecayConfig + +## Key Files +- `mod.rs` - NodeType (7 variants), EdgeType (7 variants), NodeStatus (15 variants), GraphNode, GraphEdge +- `store.rs` - GraphStore trait (17 methods), SqliteGraphStore, NodeQuery, EdgeDirection, WorkGraph +- `session.rs` - Session, SessionStore, deterministic handoff note generation +- `interchange.rs` - TOML export/import, content hashing, conflict strategies (Skip/Overwrite/Error) diff --git a/src/graph/CLAUDE.md b/src/graph/CLAUDE.md new file mode 100644 index 0000000..f66a6ac --- /dev/null +++ b/src/graph/CLAUDE.md @@ -0,0 +1 @@ +Read @./AGENTS.md and treat its contents as if they were in CLAUDE.md