provisioning-code/AGENTS.md

220 lines
7.5 KiB
Markdown

# 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 <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
```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<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
```bash
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/`