agentic-team-templates 0.10.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-team-templates",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "AI coding assistant templates for Cursor IDE. Pre-configured rules and guidelines that help AI assistants write better code. - use at your own risk",
5
5
  "keywords": [
6
6
  "cursor",
package/src/index.js CHANGED
@@ -56,6 +56,10 @@ const TEMPLATES = {
56
56
  description: 'Mobile applications (React Native, Flutter, native iOS/Android)',
57
57
  rules: ['navigation.md', 'offline-first.md', 'overview.md', 'performance.md', 'testing.md']
58
58
  },
59
+ 'rust-expert': {
60
+ description: 'Principal-level Rust engineering (ownership, concurrency, unsafe, traits, async)',
61
+ rules: ['concurrency.md', 'ecosystem-and-tooling.md', 'error-handling.md', 'overview.md', 'ownership-and-borrowing.md', 'performance-and-unsafe.md', 'testing.md', 'traits-and-generics.md']
62
+ },
59
63
  'platform-engineering': {
60
64
  description: 'Internal developer platforms, infrastructure automation, and reliability engineering',
61
65
  rules: ['ci-cd.md', 'developer-experience.md', 'infrastructure-as-code.md', 'kubernetes.md', 'observability.md', 'overview.md', 'security.md', 'testing.md']
package/src/index.test.js CHANGED
@@ -82,6 +82,7 @@ describe('Constants', () => {
82
82
  'javascript-expert',
83
83
  'ml-ai',
84
84
  'mobile',
85
+ 'rust-expert',
85
86
  'platform-engineering',
86
87
  'product-manager',
87
88
  'qa-engineering',
@@ -0,0 +1,250 @@
1
+ # Rust Concurrency
2
+
3
+ Rust prevents data races at compile time through ownership and the `Send`/`Sync` marker traits. Fearless concurrency is real — but it doesn't mean you can ignore deadlocks, race conditions at the logic level, or performance pitfalls.
4
+
5
+ ## Send and Sync
6
+
7
+ ```rust
8
+ // Send: safe to transfer ownership to another thread
9
+ // Sync: safe to share references (&T) between threads
10
+ // These are auto-traits — the compiler derives them automatically
11
+
12
+ // Most types are Send + Sync
13
+ // Rc<T> is NOT Send or Sync — use Arc<T> for multi-threaded code
14
+ // RefCell<T> is Send but NOT Sync — use Mutex<T> for multi-threaded code
15
+ // Raw pointers are neither — wrap them in types that uphold invariants
16
+ ```
17
+
18
+ ## Threading
19
+
20
+ ### std::thread
21
+
22
+ ```rust
23
+ use std::thread;
24
+
25
+ // Scoped threads (Go 1.63+) — borrows from the parent stack are allowed
26
+ let mut data = vec![1, 2, 3, 4];
27
+ thread::scope(|s| {
28
+ let (left, right) = data.split_at_mut(2);
29
+
30
+ s.spawn(|| {
31
+ left.iter_mut().for_each(|x| *x *= 2);
32
+ });
33
+ s.spawn(|| {
34
+ right.iter_mut().for_each(|x| *x *= 3);
35
+ });
36
+ });
37
+ // Both threads are guaranteed to finish before scope exits
38
+ // No Arc, no clone, no join handles to manage
39
+ assert_eq!(data, [2, 4, 9, 12]);
40
+ ```
41
+
42
+ ### Shared State with Arc + Mutex
43
+
44
+ ```rust
45
+ use std::sync::{Arc, Mutex};
46
+
47
+ let counter = Arc::new(Mutex::new(0));
48
+ let mut handles = vec![];
49
+
50
+ for _ in 0..10 {
51
+ let counter = Arc::clone(&counter);
52
+ handles.push(thread::spawn(move || {
53
+ let mut num = counter.lock().unwrap();
54
+ *num += 1;
55
+ }));
56
+ }
57
+
58
+ for handle in handles {
59
+ handle.join().unwrap();
60
+ }
61
+ ```
62
+
63
+ ### RwLock for Read-Heavy Workloads
64
+
65
+ ```rust
66
+ use std::sync::RwLock;
67
+
68
+ let config = Arc::new(RwLock::new(Config::default()));
69
+
70
+ // Multiple readers — no blocking
71
+ let cfg = config.read().unwrap();
72
+ println!("{}", cfg.setting);
73
+
74
+ // Single writer — exclusive access
75
+ let mut cfg = config.write().unwrap();
76
+ cfg.setting = new_value;
77
+ ```
78
+
79
+ ## Channels
80
+
81
+ ```rust
82
+ use std::sync::mpsc;
83
+
84
+ // Multiple producers, single consumer
85
+ let (tx, rx) = mpsc::channel();
86
+
87
+ let tx2 = tx.clone(); // Clone sender for second producer
88
+
89
+ thread::spawn(move || {
90
+ tx.send(Message::Data(vec![1, 2, 3])).unwrap();
91
+ });
92
+
93
+ thread::spawn(move || {
94
+ tx2.send(Message::Data(vec![4, 5, 6])).unwrap();
95
+ });
96
+
97
+ // Receive all messages
98
+ for msg in rx {
99
+ process(msg);
100
+ }
101
+
102
+ // crossbeam-channel for multi-producer multi-consumer, select!, bounded channels
103
+ use crossbeam_channel::{bounded, select};
104
+
105
+ let (tx, rx) = bounded(100); // Backpressure at 100 items
106
+
107
+ select! {
108
+ recv(rx) -> msg => handle(msg.unwrap()),
109
+ default(Duration::from_secs(1)) => println!("timeout"),
110
+ }
111
+ ```
112
+
113
+ ## Async/Await
114
+
115
+ ### Tokio Runtime
116
+
117
+ ```rust
118
+ #[tokio::main]
119
+ async fn main() -> Result<()> {
120
+ let listener = TcpListener::bind("0.0.0.0:8080").await?;
121
+
122
+ loop {
123
+ let (stream, addr) = listener.accept().await?;
124
+ tokio::spawn(async move {
125
+ if let Err(e) = handle_connection(stream).await {
126
+ eprintln!("connection error from {addr}: {e}");
127
+ }
128
+ });
129
+ }
130
+ }
131
+ ```
132
+
133
+ ### Async Patterns
134
+
135
+ ```rust
136
+ // Concurrent execution with join
137
+ let (users, posts) = tokio::join!(
138
+ fetch_users(&client),
139
+ fetch_posts(&client),
140
+ );
141
+
142
+ // Race — first to complete wins
143
+ tokio::select! {
144
+ result = fetch_data() => handle_data(result),
145
+ _ = tokio::time::sleep(Duration::from_secs(5)) => {
146
+ return Err(anyhow!("fetch timed out"));
147
+ }
148
+ }
149
+
150
+ // Bounded concurrency with semaphore
151
+ use tokio::sync::Semaphore;
152
+
153
+ let semaphore = Arc::new(Semaphore::new(10));
154
+ let mut handles = vec![];
155
+
156
+ for url in urls {
157
+ let permit = semaphore.clone().acquire_owned().await?;
158
+ handles.push(tokio::spawn(async move {
159
+ let result = fetch(url).await;
160
+ drop(permit); // Release when done
161
+ result
162
+ }));
163
+ }
164
+
165
+ // Stream processing
166
+ use tokio_stream::StreamExt;
167
+
168
+ let mut stream = tokio_stream::iter(items)
169
+ .map(|item| async move { process(item).await })
170
+ .buffer_unordered(10); // Process up to 10 concurrently
171
+
172
+ while let Some(result) = stream.next().await {
173
+ handle(result?);
174
+ }
175
+ ```
176
+
177
+ ### Async Traits
178
+
179
+ ```rust
180
+ // Since Rust 1.75: async fn in traits works natively
181
+ pub trait Repository {
182
+ async fn find_by_id(&self, id: &str) -> Result<Option<Entity>>;
183
+ async fn save(&self, entity: &Entity) -> Result<()>;
184
+ }
185
+
186
+ // For trait objects (dyn), use the async-trait crate or
187
+ // return Pin<Box<dyn Future>> manually
188
+ ```
189
+
190
+ ### Cancellation Safety
191
+
192
+ ```rust
193
+ // tokio::select! can cancel futures — understand what that means
194
+ // A future dropped mid-execution won't run its remaining code
195
+
196
+ // Cancellation-safe: reading from a channel (no partial state)
197
+ // NOT cancellation-safe: reading into a buffer (partial read lost)
198
+
199
+ tokio::select! {
200
+ // Safe: mpsc::Receiver::recv is cancellation-safe
201
+ msg = rx.recv() => { ... }
202
+
203
+ // DANGEROUS if buf has partial state from a previous iteration
204
+ n = reader.read(&mut buf) => { ... }
205
+ }
206
+
207
+ // When in doubt, consult tokio's docs for each method's cancellation safety
208
+ ```
209
+
210
+ ## Atomics
211
+
212
+ ```rust
213
+ use std::sync::atomic::{AtomicU64, Ordering};
214
+
215
+ static REQUEST_COUNT: AtomicU64 = AtomicU64::new(0);
216
+
217
+ fn handle_request() {
218
+ REQUEST_COUNT.fetch_add(1, Ordering::Relaxed);
219
+ }
220
+
221
+ // Ordering guide:
222
+ // Relaxed — no ordering guarantees, just atomicity (counters)
223
+ // Acquire — subsequent reads see writes before the Release
224
+ // Release — previous writes are visible to Acquire loads
225
+ // SeqCst — total order, strongest guarantee, rarely needed
226
+ // If unsure, use SeqCst and optimize later with profiling data
227
+ ```
228
+
229
+ ## Anti-Patterns
230
+
231
+ ```rust
232
+ // Never: Holding a MutexGuard across an await point
233
+ let guard = mutex.lock().await;
234
+ do_async_work().await; // Deadlock risk — guard is held across await
235
+ drop(guard);
236
+ // Instead: lock, extract data, drop guard, then await
237
+
238
+ // Never: Spawning tasks without cancellation or shutdown strategy
239
+ tokio::spawn(async { loop { do_work().await; } }); // How does this stop?
240
+
241
+ // Never: Blocking in async context
242
+ std::thread::sleep(Duration::from_secs(1)); // Blocks the executor thread!
243
+ tokio::time::sleep(Duration::from_secs(1)).await; // Use this instead
244
+
245
+ // For CPU-bound work in async context:
246
+ tokio::task::spawn_blocking(|| expensive_computation()).await?;
247
+
248
+ // Never: Using std::sync::Mutex in async code (blocks the executor)
249
+ // Use tokio::sync::Mutex instead when you must hold across awaits
250
+ ```
@@ -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