agentic-team-templates 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,299 @@
1
+ # Rust Ecosystem and Tooling
2
+
3
+ The Rust ecosystem is mature and opinionated. The toolchain is best-in-class. Know the tools and the community-standard crates.
4
+
5
+ ## Cargo
6
+
7
+ ### Cargo.toml Best Practices
8
+
9
+ ```toml
10
+ [package]
11
+ name = "my-crate"
12
+ version = "0.1.0"
13
+ edition = "2021"
14
+ rust-version = "1.75" # Minimum supported Rust version (MSRV)
15
+ description = "A brief description"
16
+ license = "MIT OR Apache-2.0"
17
+ repository = "https://github.com/user/repo"
18
+
19
+ [dependencies]
20
+ serde = { version = "1", features = ["derive"] }
21
+ tokio = { version = "1", features = ["full"] }
22
+
23
+ [dev-dependencies]
24
+ criterion = { version = "0.5", features = ["html_reports"] }
25
+ proptest = "1"
26
+ tempfile = "3"
27
+
28
+ [profile.release]
29
+ lto = true # Link-time optimization
30
+ codegen-units = 1 # Slower compile, better optimization
31
+ strip = true # Strip debug symbols from binary
32
+
33
+ [profile.dev]
34
+ opt-level = 0 # Fast compile for development
35
+
36
+ # Feature flags must be additive
37
+ [features]
38
+ default = []
39
+ metrics = ["prometheus"]
40
+ tracing = ["tracing-subscriber", "tracing-opentelemetry"]
41
+ ```
42
+
43
+ ### Workspace Management
44
+
45
+ ```toml
46
+ # Root Cargo.toml
47
+ [workspace]
48
+ members = ["crates/*"]
49
+ resolver = "2"
50
+
51
+ # Share dependencies across workspace
52
+ [workspace.dependencies]
53
+ serde = { version = "1", features = ["derive"] }
54
+ tokio = { version = "1", features = ["full"] }
55
+ anyhow = "1"
56
+
57
+ # In member Cargo.toml:
58
+ [dependencies]
59
+ serde = { workspace = true }
60
+ tokio = { workspace = true }
61
+ ```
62
+
63
+ ### Essential Cargo Commands
64
+
65
+ ```bash
66
+ cargo build --release # Optimized build
67
+ cargo test -- --nocapture # Show println! output in tests
68
+ cargo doc --open # Build and open docs
69
+ cargo tree # Dependency tree
70
+ cargo tree -d # Show duplicate dependencies
71
+ cargo update # Update Cargo.lock to latest compatible
72
+ cargo audit # Check for known vulnerabilities
73
+ cargo deny check # License and advisory checks
74
+ cargo expand # Show macro expansion
75
+ cargo outdated # Show outdated dependencies
76
+ ```
77
+
78
+ ## Linting and Formatting
79
+
80
+ ### Clippy Configuration
81
+
82
+ ```toml
83
+ # clippy.toml or .clippy.toml
84
+ cognitive-complexity-threshold = 25
85
+ too-many-arguments-threshold = 7
86
+ type-complexity-threshold = 250
87
+ ```
88
+
89
+ ```rust
90
+ // In lib.rs or main.rs — project-wide lint configuration
91
+ #![warn(clippy::all, clippy::pedantic)]
92
+ #![allow(clippy::module_name_repetitions)] // Allow if your API style needs it
93
+ #![deny(clippy::unwrap_used)] // No unwrap in library code
94
+ #![deny(unsafe_code)] // Deny unsafe unless explicitly needed
95
+
96
+ // Per-module overrides when justified
97
+ #[allow(clippy::cast_possible_truncation)]
98
+ // Justification: value is guaranteed < 256 by the protocol spec
99
+ fn protocol_byte(value: u32) -> u8 {
100
+ value as u8
101
+ }
102
+ ```
103
+
104
+ ### rustfmt
105
+
106
+ ```toml
107
+ # rustfmt.toml
108
+ edition = "2021"
109
+ max_width = 100
110
+ use_field_init_shorthand = true
111
+ use_try_shorthand = true
112
+ imports_granularity = "Crate"
113
+ group_imports = "StdExternalCrate"
114
+ ```
115
+
116
+ ## Essential Crates
117
+
118
+ ### Serialization
119
+ - **serde** + **serde_json** — the serialization framework, period
120
+ - **toml** — config files
121
+ - **bincode** — compact binary format
122
+
123
+ ### Async Runtime
124
+ - **tokio** — the dominant async runtime (multi-threaded, work-stealing)
125
+ - **async-std** — alternative, closer to std API
126
+
127
+ ### Web
128
+ - **axum** — ergonomic web framework built on Tower and Hyper
129
+ - **reqwest** — HTTP client
130
+ - **tonic** — gRPC
131
+
132
+ ### Database
133
+ - **sqlx** — compile-time checked SQL queries
134
+ - **diesel** — ORM with type-safe query builder
135
+ - **sea-orm** — async ORM built on sqlx
136
+
137
+ ### Error Handling
138
+ - **thiserror** — derive Error for library error types
139
+ - **anyhow** — flexible error handling for applications
140
+
141
+ ### CLI
142
+ - **clap** — argument parsing (derive or builder API)
143
+
144
+ ### Observability
145
+ - **tracing** — structured, async-aware instrumentation
146
+ - **metrics** — application metrics
147
+ - **opentelemetry** — distributed tracing
148
+
149
+ ### Testing
150
+ - **proptest** — property-based testing
151
+ - **criterion** — statistical benchmarking
152
+ - **mockall** — mocking framework
153
+ - **wiremock** — HTTP mocking for integration tests
154
+ - **tempfile** — temporary files and directories for tests
155
+ - **insta** — snapshot testing
156
+
157
+ ## CI/CD
158
+
159
+ ### GitHub Actions
160
+
161
+ ```yaml
162
+ name: CI
163
+
164
+ on: [push, pull_request]
165
+
166
+ env:
167
+ CARGO_TERM_COLOR: always
168
+ RUSTFLAGS: "-Dwarnings"
169
+
170
+ jobs:
171
+ check:
172
+ runs-on: ubuntu-latest
173
+ steps:
174
+ - uses: actions/checkout@v4
175
+ - uses: dtolnay/rust-toolchain@stable
176
+ with:
177
+ components: rustfmt, clippy
178
+ - uses: Swatinem/rust-cache@v2
179
+
180
+ - run: cargo fmt -- --check
181
+ - run: cargo clippy --all-targets --all-features
182
+ - run: cargo test --all-features
183
+ - run: cargo doc --no-deps --all-features
184
+
185
+ # Miri for crates with unsafe code
186
+ miri:
187
+ runs-on: ubuntu-latest
188
+ steps:
189
+ - uses: actions/checkout@v4
190
+ - uses: dtolnay/rust-toolchain@nightly
191
+ with:
192
+ components: miri
193
+ - run: cargo +nightly miri test
194
+
195
+ # Security audit
196
+ audit:
197
+ runs-on: ubuntu-latest
198
+ steps:
199
+ - uses: actions/checkout@v4
200
+ - uses: rustsec/audit-check@v2
201
+ ```
202
+
203
+ ### Makefile
204
+
205
+ ```makefile
206
+ .PHONY: check test lint fmt doc
207
+
208
+ check: fmt lint test
209
+
210
+ fmt:
211
+ cargo fmt -- --check
212
+
213
+ lint:
214
+ cargo clippy --all-targets --all-features -- -D warnings
215
+
216
+ test:
217
+ cargo test --all-features
218
+
219
+ doc:
220
+ cargo doc --no-deps --all-features --open
221
+
222
+ audit:
223
+ cargo audit
224
+ cargo deny check
225
+
226
+ bench:
227
+ cargo bench
228
+
229
+ coverage:
230
+ cargo tarpaulin --out Html --output-dir target/coverage
231
+ ```
232
+
233
+ ## Documentation
234
+
235
+ ```rust
236
+ //! # My Crate
237
+ //!
238
+ //! `my_crate` provides utilities for processing data efficiently.
239
+ //!
240
+ //! ## Quick Start
241
+ //!
242
+ //! ```rust
243
+ //! use my_crate::process;
244
+ //!
245
+ //! let result = process("input data")?;
246
+ //! println!("{result}");
247
+ //! # Ok::<(), my_crate::Error>(())
248
+ //! ```
249
+
250
+ /// Processes the input data and returns a formatted result.
251
+ ///
252
+ /// # Arguments
253
+ ///
254
+ /// * `input` - A string slice containing the raw data
255
+ ///
256
+ /// # Errors
257
+ ///
258
+ /// Returns [`Error::InvalidInput`] if the input is malformed.
259
+ ///
260
+ /// # Examples
261
+ ///
262
+ /// ```
263
+ /// use my_crate::process;
264
+ ///
265
+ /// let output = process("valid input").unwrap();
266
+ /// assert_eq!(output, "processed: valid input");
267
+ /// ```
268
+ pub fn process(input: &str) -> Result<String, Error> {
269
+ // ...
270
+ }
271
+
272
+ // Document panic conditions
273
+ /// # Panics
274
+ ///
275
+ /// Panics if `divisor` is zero.
276
+ pub fn divide(a: i64, divisor: i64) -> i64 {
277
+ assert_ne!(divisor, 0, "divisor must be non-zero");
278
+ a / divisor
279
+ }
280
+
281
+ // Document safety requirements for unsafe functions
282
+ /// # Safety
283
+ ///
284
+ /// - `ptr` must be valid for reads of `len` bytes
285
+ /// - `ptr` must be properly aligned for `T`
286
+ /// - The memory referenced must not be mutated during the lifetime of the returned slice
287
+ pub unsafe fn from_raw_parts<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
288
+ std::slice::from_raw_parts(ptr, len)
289
+ }
290
+ ```
291
+
292
+ ## Dependency Hygiene
293
+
294
+ - **Audit regularly**: `cargo audit` for security advisories
295
+ - **Check licenses**: `cargo deny check licenses`
296
+ - **Minimize dependencies**: Every dependency is attack surface and compile time
297
+ - **Pin workspace deps**: Use `[workspace.dependencies]` for consistency
298
+ - **Review before adding**: Check maintenance status, download counts, and bus factor
299
+ - **Feature flags**: Only enable features you actually use
@@ -0,0 +1,190 @@
1
+ # Rust Error Handling
2
+
3
+ Rust has no exceptions. `Result<T, E>` and `Option<T>` are the error handling primitives. The `?` operator propagates errors ergonomically, but every error path is still an explicit decision.
4
+
5
+ ## Custom Error Types
6
+
7
+ ### Using thiserror (Libraries)
8
+
9
+ ```rust
10
+ use thiserror::Error;
11
+
12
+ #[derive(Debug, Error)]
13
+ pub enum AppError {
14
+ #[error("configuration error: {message}")]
15
+ Config { message: String },
16
+
17
+ #[error("database query failed")]
18
+ Database(#[from] sqlx::Error),
19
+
20
+ #[error("request to {url} failed")]
21
+ Http {
22
+ url: String,
23
+ #[source]
24
+ source: reqwest::Error,
25
+ },
26
+
27
+ #[error("record not found: {entity} with id {id}")]
28
+ NotFound { entity: &'static str, id: String },
29
+
30
+ #[error("validation failed: {0}")]
31
+ Validation(String),
32
+ }
33
+ ```
34
+
35
+ ### Using anyhow (Applications)
36
+
37
+ ```rust
38
+ use anyhow::{Context, Result, bail, ensure};
39
+
40
+ fn load_config(path: &Path) -> Result<Config> {
41
+ let contents = fs::read_to_string(path)
42
+ .with_context(|| format!("reading config from {}", path.display()))?;
43
+
44
+ let config: Config = toml::from_str(&contents)
45
+ .context("parsing config TOML")?;
46
+
47
+ ensure!(!config.database_url.is_empty(), "database_url must not be empty");
48
+
49
+ if config.port == 0 {
50
+ bail!("port must be non-zero");
51
+ }
52
+
53
+ Ok(config)
54
+ }
55
+ ```
56
+
57
+ ### When to Use Which
58
+
59
+ - **thiserror** — libraries, reusable crates, when callers need to match on error variants
60
+ - **anyhow** — applications, binaries, when you just need to propagate context up to main
61
+ - **Manual impl** — when you need full control or minimal dependencies
62
+
63
+ ### Manual Error Implementation
64
+
65
+ ```rust
66
+ #[derive(Debug)]
67
+ pub enum StorageError {
68
+ Io(std::io::Error),
69
+ Serialization(serde_json::Error),
70
+ NotFound { key: String },
71
+ }
72
+
73
+ impl fmt::Display for StorageError {
74
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75
+ match self {
76
+ Self::Io(e) => write!(f, "storage I/O error: {e}"),
77
+ Self::Serialization(e) => write!(f, "serialization error: {e}"),
78
+ Self::NotFound { key } => write!(f, "key not found: {key}"),
79
+ }
80
+ }
81
+ }
82
+
83
+ impl std::error::Error for StorageError {
84
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
85
+ match self {
86
+ Self::Io(e) => Some(e),
87
+ Self::Serialization(e) => Some(e),
88
+ Self::NotFound { .. } => None,
89
+ }
90
+ }
91
+ }
92
+
93
+ impl From<std::io::Error> for StorageError {
94
+ fn from(e: std::io::Error) -> Self {
95
+ Self::Io(e)
96
+ }
97
+ }
98
+ ```
99
+
100
+ ## The ? Operator
101
+
102
+ ```rust
103
+ // ? is sugar for early return on Err/None
104
+ // It calls From::from() on the error, enabling automatic conversion
105
+
106
+ fn process(path: &Path) -> Result<Data, AppError> {
107
+ let raw = fs::read(path)?; // io::Error -> AppError via From
108
+ let parsed = serde_json::from_slice(&raw)?; // serde::Error -> AppError via From
109
+ Ok(parsed)
110
+ }
111
+
112
+ // ? works with Option too
113
+ fn first_word(s: &str) -> Option<&str> {
114
+ let end = s.find(' ')?; // Returns None if no space
115
+ Some(&s[..end])
116
+ }
117
+ ```
118
+
119
+ ## Option Patterns
120
+
121
+ ```rust
122
+ // Prefer combinators over match when they're clearer
123
+ let name = user.name.as_deref().unwrap_or("anonymous");
124
+
125
+ let parsed = input
126
+ .strip_prefix("v")
127
+ .and_then(|s| s.parse::<u32>().ok());
128
+
129
+ // Use match when you need complex logic per variant
130
+ match config.log_level {
131
+ Some(level) => logger.set_level(level),
132
+ None => logger.set_level(Level::Info),
133
+ }
134
+
135
+ // Use if let for single-variant checks
136
+ if let Some(token) = headers.get("Authorization") {
137
+ authenticate(token)?;
138
+ }
139
+ ```
140
+
141
+ ## Panic Policy
142
+
143
+ ```rust
144
+ // Panics are for bugs, not for expected error conditions.
145
+
146
+ // Acceptable: debug assertions
147
+ debug_assert!(index < len, "index {index} out of bounds for length {len}");
148
+
149
+ // Acceptable: unreachable code paths that truly can't happen
150
+ match state {
151
+ State::Ready => process(),
152
+ State::Done => return,
153
+ // If we've exhaustively handled all variants and the compiler
154
+ // still wants a branch, use unreachable!() — but only when
155
+ // you can prove it's unreachable.
156
+ }
157
+
158
+ // Acceptable: unwrap() in tests
159
+ #[cfg(test)]
160
+ fn setup() -> TestDb {
161
+ TestDb::new().unwrap() // Fine in tests
162
+ }
163
+
164
+ // Never acceptable: unwrap() in library code without a VERY good reason
165
+ // Never acceptable: panic!() for user input validation
166
+ // Never acceptable: todo!() in shipped code
167
+ ```
168
+
169
+ ## Anti-Patterns
170
+
171
+ ```rust
172
+ // Never: Silencing errors
173
+ let _ = write!(f, "data"); // The write might fail — handle it or explain why not
174
+
175
+ // Never: unwrap() with no context
176
+ let config = load_config().unwrap(); // What failed? Where? Why?
177
+ // At minimum:
178
+ let config = load_config().expect("loading config from default path");
179
+
180
+ // Never: Stringly-typed errors
181
+ fn process() -> Result<(), String> { // Don't use String as an error type
182
+ Err("something went wrong".into())
183
+ }
184
+
185
+ // Never: Catching panics as error handling
186
+ let result = std::panic::catch_unwind(|| dangerous_code()); // This is not error handling
187
+
188
+ // Never: .ok() to discard error information without justification
189
+ let maybe = fallible_operation().ok(); // Why is the error not important?
190
+ ```
@@ -0,0 +1,142 @@
1
+ # Rust Expert
2
+
3
+ Guidelines for principal-level Rust engineering. Ownership, zero-cost abstractions, and fearless concurrency — wielded with precision.
4
+
5
+ ## Scope
6
+
7
+ This ruleset applies to:
8
+ - Systems programming and embedded targets
9
+ - Web services and async runtimes (Tokio, async-std)
10
+ - CLI tools and developer utilities
11
+ - Libraries and crates published to crates.io
12
+ - WebAssembly targets
13
+ - FFI and interop with C/C++
14
+ - Performance-critical applications
15
+
16
+ ## Core Philosophy
17
+
18
+ Rust gives you power without sacrificing safety. The compiler is your closest collaborator — work with it, not against it.
19
+
20
+ - **If it compiles, it's probably correct.** The borrow checker isn't an obstacle — it's catching bugs that would have been CVEs in another language. Trust it.
21
+ - **Zero-cost abstractions are the point.** You should never have to choose between expressiveness and performance. If the abstraction has runtime cost, question whether it's the right abstraction.
22
+ - **Make illegal states unrepresentable.** Use the type system to encode invariants. If a state shouldn't exist, make it impossible to construct.
23
+ - **Explicit over implicit.** Lifetimes, ownership, error handling — Rust surfaces what other languages hide. This is a feature, not a flaw.
24
+ - **Unsafe is a scalpel, not a sledgehammer.** Every `unsafe` block is a proof obligation. If you can't explain exactly why it's sound, don't write it.
25
+ - **If you don't know, say so.** The Rust ecosystem is vast and evolving. Admitting uncertainty is better than guessing wrong about soundness.
26
+
27
+ ## Key Principles
28
+
29
+ ### 1. Ownership Is the Architecture
30
+
31
+ Ownership isn't just memory management — it's your design tool:
32
+ - Who owns this data? Who borrows it? For how long?
33
+ - These questions force you to design clear APIs with explicit lifetimes and responsibilities
34
+ - If you're fighting the borrow checker, the design likely needs rethinking — not an `unsafe` escape hatch
35
+
36
+ ### 2. Types Encode Invariants
37
+
38
+ ```rust
39
+ // Make illegal states unrepresentable
40
+ // Bad: bool flags that can be inconsistent
41
+ struct Connection {
42
+ is_connected: bool,
43
+ is_authenticated: bool, // Can this be true if is_connected is false?
44
+ }
45
+
46
+ // Good: State machine as an enum
47
+ enum Connection {
48
+ Disconnected,
49
+ Connected(TcpStream),
50
+ Authenticated { stream: TcpStream, token: AuthToken },
51
+ }
52
+ // It's impossible to be Authenticated without a stream
53
+ ```
54
+
55
+ ### 3. Error Handling Is Explicit
56
+
57
+ ```rust
58
+ // Rust has no exceptions. Result and Option are the tools.
59
+ // The ? operator is syntactic sugar, not an excuse to ignore errors.
60
+
61
+ fn load_config(path: &Path) -> Result<Config, ConfigError> {
62
+ let contents = fs::read_to_string(path)
63
+ .map_err(|e| ConfigError::ReadFailed { path: path.to_owned(), source: e })?;
64
+ let config: Config = toml::from_str(&contents)
65
+ .map_err(|e| ConfigError::ParseFailed { source: e })?;
66
+ config.validate()?;
67
+ Ok(config)
68
+ }
69
+ ```
70
+
71
+ ### 4. Clippy Is Non-Negotiable
72
+
73
+ ```bash
74
+ # In CI, always:
75
+ cargo clippy -- -D warnings
76
+ # Clippy catches real bugs, not just style nits. Treat warnings as errors.
77
+ ```
78
+
79
+ ## Project Structure
80
+
81
+ ```
82
+ my-project/
83
+ ├── Cargo.toml # Workspace or package manifest
84
+ ├── Cargo.lock # Committed for binaries, not for libraries
85
+ ├── src/
86
+ │ ├── main.rs # Binary entry point (or lib.rs for libraries)
87
+ │ ├── lib.rs # Library root — public API surface
88
+ │ ├── config.rs # Configuration loading and validation
89
+ │ ├── error.rs # Error types for this crate
90
+ │ └── domain/ # Core business logic modules
91
+ │ ├── mod.rs
92
+ │ └── ...
93
+ ├── tests/ # Integration tests (separate compilation unit)
94
+ │ └── integration_test.rs
95
+ ├── benches/ # Benchmarks
96
+ │ └── benchmark.rs
97
+ ├── examples/ # Runnable examples
98
+ │ └── basic_usage.rs
99
+ └── build.rs # Build script (if needed)
100
+ ```
101
+
102
+ ### Workspace Layout (Multi-Crate)
103
+
104
+ ```
105
+ workspace/
106
+ ├── Cargo.toml # [workspace] members
107
+ ├── crates/
108
+ │ ├── core/ # Domain logic — no IO, no async
109
+ │ │ ├── Cargo.toml
110
+ │ │ └── src/lib.rs
111
+ │ ├── api/ # HTTP handlers, routes
112
+ │ │ ├── Cargo.toml
113
+ │ │ └── src/lib.rs
114
+ │ ├── db/ # Database access
115
+ │ │ ├── Cargo.toml
116
+ │ │ └── src/lib.rs
117
+ │ └── cli/ # Binary entry point
118
+ │ ├── Cargo.toml
119
+ │ └── src/main.rs
120
+ ```
121
+
122
+ ### Layout Rules
123
+
124
+ - `lib.rs` defines the public API — only `pub` items here are your contract
125
+ - `mod.rs` or file-per-module — be consistent within a project
126
+ - Integration tests in `tests/` are separate compilation units — they test your public API
127
+ - `Cargo.lock` is committed for binaries and applications, not for libraries
128
+ - Feature flags in `Cargo.toml` must be additive — enabling a feature must not break existing code
129
+
130
+ ## Definition of Done
131
+
132
+ A Rust feature is complete when:
133
+ - [ ] `cargo build` compiles with zero warnings
134
+ - [ ] `cargo clippy -- -D warnings` passes
135
+ - [ ] `cargo test` passes (including doc tests)
136
+ - [ ] `cargo fmt -- --check` passes
137
+ - [ ] No `unwrap()` or `expect()` in library code without justification
138
+ - [ ] All `unsafe` blocks have `// SAFETY:` comments explaining the invariants
139
+ - [ ] Error types are meaningful and implement `std::error::Error`
140
+ - [ ] Public API has doc comments with examples
141
+ - [ ] No unnecessary allocations in hot paths
142
+ - [ ] `cargo deny check` passes (license and advisory audit)