provisioning-code/AGENTS.md

7.5 KiB

AGENTS.md - Agentic Coding Guidelines

Guidelines for AI agents and autonomous developers operating in this repository.

Build/Test/Lint Commands

Quick Commands

# 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 <test_name> -- --nocapture

# Run a single test in a specific crate
cd platform && cargo test --package <crate_name> <test_name>

# 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

# 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<T>
  • 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<T> from fallible functions; define type Result<T> = std::result::Result<T, Error>

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

cargo +nightly fmt --all              # Format all projects
cargo fmt --package <crate>           # 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 <name> -- --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/