# AGENTS.md - Agentic Coding Guidelines Guidelines for AI agents and autonomous developers operating in this repository. ## Build/Test/Lint Commands ### Quick Commands ```bash # Format Rust code just fmt cargo +nightly fmt --all # Lint Rust code cargo clippy --all-targets -- -D warnings # Run all tests for a single crate cd platform && cargo test --all-features # Run a single test cargo test -- --nocapture # Run a single test in a specific crate cd platform && cargo test --package # Build everything just build-all # Quick development build just dev-build # Run CI checks locally just ci-full # All checks: lint, fmt, test, audit just ci-fmt # Format checking just ci-lint-rust # Clippy linting just ci-test # Run all tests ``` ### Development Workflow ```bash # Incremental development build just build-incremental # Validate changes before commit just validate-all # Check build system health just build-check # Run tests with coverage just ci-test-coverage ``` ## Code Style Guidelines ### Rust (Primary Language) #### Imports - **Organization**: Use `group_imports = "StdExternalCrate"` (stdlib → external → crate) - **Style**: `use` statements grouped and reordered automatically by rustfmt - **Nightly features**: Enabled via `unstable_features = true` in `.rustfmt.toml` - **Public exports**: Re-export via `pub use` for ergonomic APIs (see `platform-config/src/lib.rs`) #### Formatting & Line Length - **Max line width**: 100 characters - **Tab style**: Spaces (4 per indentation) - **Newline style**: Unix (LF) - **Chain width**: 60 characters before wrapping - **Function parameters**: Use tall layout (`fn_params_layout = "Tall"`) - **Match arms**: Trailing commas disabled; match block structure preserved - **Comments**: Wrapped at 80 chars; normalized; doc attributes normalized #### Types & Naming - **Naming convention**: `snake_case` for functions/variables, `PascalCase` for types/traits - **Type complexity**: Limit to 500 (threshold: `.clippy.toml`) - **Cognitive complexity**: Limit to 25 (threshold: `.clippy.toml`) - **Nesting depth**: Max 5 levels (threshold: `.clippy.toml`) - **Generic types**: Use single-char names only in narrow scopes; prefer descriptive names #### Error Handling - **Pattern**: Use `thiserror` or `anyhow` for result types; define custom `Result` - **Custom errors**: Enum-based with `#[from]` derives (see `provctl-core/src/error.rs`) - **No panics**: Avoid `panic!()`, `unwrap()`, `todo!()`, `unimplemented!()` - **Error variants**: Include context (operation, resource, reason) in error kinds - **String errors**: Use structured enum variants, not bare strings - **Result type**: Always return `Result` from fallible functions; define `type Result = std::result::Result` #### Documentation - **Module docs**: Always include `//!` at crate/module start with purpose and features - **Examples**: Include `# Examples` sections (use `ignore` for untested code) - **Feature docs**: List capabilities, not obvious implementation details - **Code comments**: Only for "why", not "what" (code should be self-documenting) #### Traits & Impl Blocks - **Trait organization**: Group related impls together; separate concerns - **Method order**: Public API first, then private helpers - **Default implementations**: Use trait defaults to reduce boilerplate - **Associated types**: Prefer over generic parameters when type is determined by implementor ### Nushell Scripts Follows Nushell guidelines in `.claude/guidelines/nushell/`. Key points: - Structured data pipelines preferred - Error handling with `?` operator - Type annotations on function parameters - Module organization with clear public/private boundaries - Avoid shell anti-patterns; prefer Nushell idioms ### TOML Configuration - **Format checking**: `taplo format --check` - **Lint**: `taplo lint` - **Workspace**: All Rust projects use workspace Cargo.toml ## Architecture & Organization ### Workspace Structure ``` platform/ ├── Cargo.toml (workspace root with [workspace.dependencies]) ├── crates/ │ ├── platform-config/ (shared config loading) │ ├── service-clients/ (inter-service communication) │ ├── ai-service/ (AI integration) │ ├── orchestrator/ (workflow orchestration) │ └── ... └── prov-ecosystem/ └── crates/ (ecosystem services) ``` ### Module Organization - **Public modules**: Exported via `pub use` in `lib.rs` - **Private modules**: Implementation details not in public API - **Error modules**: Standalone `error.rs` with custom error types - **Hierarchy**: Clear parent-child relationships; avoid circular dependencies ### Configuration Management - **Formats**: Nickel (NCL) or TOML; auto-converted to JSON internally - **Loading hierarchy**: Environment variables → File-based → Defaults - **Trait pattern**: Implement `ConfigLoader` for service configs - **Validation**: Services validate configs on load via `ConfigValidator` ## Clippy & Linting Rules ### Required Settings - **Lint level**: `-D warnings` (deny all warnings) - **Clippy thresholds** (`.clippy.toml`): - Cognitive complexity: 25 - Type complexity: 500 - Nesting depth: 5 - Single-char bindings: 4 allowed ### Pre-commit Hooks - **Rust format**: `cargo +nightly fmt --all -- --check` (blocks commit if fails) - **Clippy**: `cargo clippy --all-targets -- -D warnings` (blocks commit if fails) - **Note**: Tests run in CI only; blocked on pre-push to prevent dev friction ## Git & Commit Workflow ### Forbidden - ❌ Force push (`--force`) - ❌ Hard reset/rebase without authorization - ❌ Branch creation outside established workflow ### Format Commands ```bash cargo +nightly fmt --all # Format all projects cargo fmt --package # Format single crate git diff --check # Verify no trailing whitespace ``` ## Testing Strategy ### Test Organization - **Unit tests**: In same file, `#[cfg(test)]` modules - **Integration tests**: Separate `tests/` directories - **Coverage**: Run via `cargo llvm-cov --all-features` - **CI**: All tests run with `--all-features` flag ### Test Patterns - Use descriptive names: `test_error_handling_on_missing_config` - Isolate state; use fixtures/builders for setup - Assert both success and error cases - Document non-obvious test scenarios ## Key Tools & Dependencies ### Core Stack - **Async runtime**: `tokio` (full features) - **Serialization**: `serde` + `serde_json` - **Error handling**: `thiserror`, `anyhow` - **Logging**: `tracing` + `tracing-subscriber` - **Web**: `axum`, `tower-http` - **CLI**: `clap` (derive macros) - **Database**: `sqlx`, `surrealdb` ### Build & Dev Tools - **Formatter**: `cargo +nightly fmt` - **Linter**: `cargo clippy` - **Test coverage**: `cargo-llvm-cov` - **TOML formatter**: `taplo` - **Task runner**: `just` (justfiles) - **Shell**: Nushell for scripts ## Implementation Checklist Before coding: 1. ✅ Check `.rustfmt.toml` for formatting rules 2. ✅ Verify error handling: custom enum, no panics 3. ✅ Add doc comments with examples 4. ✅ Organize imports per stdlib → external → crate 5. ✅ Test single function: `cargo test -- --nocapture` 6. ✅ Run clippy: `cargo clippy --all-targets -- -D warnings` 7. ✅ Format: `cargo +nightly fmt --all` ## References - Workspace: `platform/Cargo.toml` - Rustfmt config: `.rustfmt.toml` - Clippy config: `.clippy.toml` - Pre-commit: `.pre-commit-config.yaml` - CI recipes: `justfiles/ci.just` - Nushell guidelines: `.claude/guidelines/nushell/`