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.
- package/package.json +1 -1
- package/src/index.js +36 -0
- package/src/index.test.js +9 -0
- package/templates/javascript-expert/.cursorrules/language-deep-dive.md +245 -0
- package/templates/javascript-expert/.cursorrules/node-patterns.md +184 -0
- package/templates/javascript-expert/.cursorrules/overview.md +130 -0
- package/templates/javascript-expert/.cursorrules/performance.md +203 -0
- package/templates/javascript-expert/.cursorrules/react-patterns.md +249 -0
- package/templates/javascript-expert/.cursorrules/testing.md +403 -0
- package/templates/javascript-expert/.cursorrules/tooling.md +176 -0
- package/templates/javascript-expert/CLAUDE.md +448 -0
- package/templates/rust-expert/.cursorrules/concurrency.md +250 -0
- package/templates/rust-expert/.cursorrules/ecosystem-and-tooling.md +299 -0
- package/templates/rust-expert/.cursorrules/error-handling.md +190 -0
- package/templates/rust-expert/.cursorrules/overview.md +142 -0
- package/templates/rust-expert/.cursorrules/ownership-and-borrowing.md +204 -0
- package/templates/rust-expert/.cursorrules/performance-and-unsafe.md +256 -0
- package/templates/rust-expert/.cursorrules/testing.md +300 -0
- package/templates/rust-expert/.cursorrules/traits-and-generics.md +236 -0
- package/templates/rust-expert/CLAUDE.md +283 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# Rust Expert Development Guide
|
|
2
|
+
|
|
3
|
+
Principal-level guidelines for Rust engineering. Ownership, zero-cost abstractions, and fearless concurrency — wielded with precision.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This guide applies to:
|
|
10
|
+
- Systems programming and embedded targets
|
|
11
|
+
- Web services and async runtimes (Tokio, async-std)
|
|
12
|
+
- CLI tools and developer utilities
|
|
13
|
+
- Libraries and crates published to crates.io
|
|
14
|
+
- WebAssembly targets
|
|
15
|
+
- FFI and interop with C/C++
|
|
16
|
+
|
|
17
|
+
### Core Philosophy
|
|
18
|
+
|
|
19
|
+
Rust gives you power without sacrificing safety. The compiler is your closest collaborator.
|
|
20
|
+
|
|
21
|
+
- **If it compiles, it's probably correct.** The borrow checker catches bugs that would be CVEs elsewhere.
|
|
22
|
+
- **Zero-cost abstractions are the point.** Never choose between expressiveness and performance.
|
|
23
|
+
- **Make illegal states unrepresentable.** Encode invariants in the type system.
|
|
24
|
+
- **Explicit over implicit.** Lifetimes, ownership, error handling — surfaced, not hidden.
|
|
25
|
+
- **Unsafe is a scalpel, not a sledgehammer.** Every `unsafe` block is a proof obligation.
|
|
26
|
+
- **If you don't know, say so.** Admitting uncertainty is better than guessing about soundness.
|
|
27
|
+
|
|
28
|
+
### Project Structure
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
project/
|
|
32
|
+
├── Cargo.toml
|
|
33
|
+
├── src/
|
|
34
|
+
│ ├── main.rs / lib.rs
|
|
35
|
+
│ ├── error.rs
|
|
36
|
+
│ └── domain/
|
|
37
|
+
├── tests/ # Integration tests
|
|
38
|
+
├── benches/ # Benchmarks
|
|
39
|
+
└── examples/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Ownership and Borrowing
|
|
45
|
+
|
|
46
|
+
### The Three Rules
|
|
47
|
+
|
|
48
|
+
1. Each value has exactly one owner
|
|
49
|
+
2. When the owner goes out of scope, the value is dropped
|
|
50
|
+
3. Either one `&mut T` OR any number of `&T` — never both
|
|
51
|
+
|
|
52
|
+
### Lifetimes
|
|
53
|
+
|
|
54
|
+
```rust
|
|
55
|
+
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
|
56
|
+
if x.len() > y.len() { x } else { y }
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Smart Pointers
|
|
61
|
+
|
|
62
|
+
- `Box<T>` — heap allocation, single owner
|
|
63
|
+
- `Rc<T>` — reference-counted, single-threaded
|
|
64
|
+
- `Arc<T>` — atomic reference-counted, thread-safe
|
|
65
|
+
- `Cow<'_, T>` — clone-on-write, avoid allocation when possible
|
|
66
|
+
|
|
67
|
+
### Interior Mutability
|
|
68
|
+
|
|
69
|
+
- `Cell<T>` — Copy types, single-threaded, zero overhead
|
|
70
|
+
- `RefCell<T>` — runtime borrow checking, single-threaded
|
|
71
|
+
- `Mutex<T>` / `RwLock<T>` — thread-safe
|
|
72
|
+
- `Atomic*` — lock-free primitives
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Error Handling
|
|
77
|
+
|
|
78
|
+
### thiserror (Libraries)
|
|
79
|
+
|
|
80
|
+
```rust
|
|
81
|
+
#[derive(Debug, Error)]
|
|
82
|
+
pub enum AppError {
|
|
83
|
+
#[error("database query failed")]
|
|
84
|
+
Database(#[from] sqlx::Error),
|
|
85
|
+
#[error("record not found: {entity} with id {id}")]
|
|
86
|
+
NotFound { entity: &'static str, id: String },
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### anyhow (Applications)
|
|
91
|
+
|
|
92
|
+
```rust
|
|
93
|
+
fn load_config(path: &Path) -> Result<Config> {
|
|
94
|
+
let contents = fs::read_to_string(path)
|
|
95
|
+
.with_context(|| format!("reading config from {}", path.display()))?;
|
|
96
|
+
Ok(toml::from_str(&contents).context("parsing config")?)
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Panic Policy
|
|
101
|
+
|
|
102
|
+
Panics are for bugs, not expected errors. No `unwrap()` in library code without justification. `todo!()` never ships.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Traits and Generics
|
|
107
|
+
|
|
108
|
+
### Small, Focused Traits
|
|
109
|
+
|
|
110
|
+
```rust
|
|
111
|
+
pub trait Validate {
|
|
112
|
+
fn validate(&self) -> Result<(), ValidationError>;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Define Interfaces at the Consumer
|
|
117
|
+
|
|
118
|
+
The consumer decides what it needs — don't force a God-trait on callers.
|
|
119
|
+
|
|
120
|
+
### Phantom Types for State Machines
|
|
121
|
+
|
|
122
|
+
```rust
|
|
123
|
+
struct Form<State> { data: FormData, _state: PhantomData<State> }
|
|
124
|
+
// Form<Unvalidated> can't call submit() — only Form<Validated> can
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Generics Rules
|
|
128
|
+
|
|
129
|
+
- `impl Trait` for simple bounds in function parameters
|
|
130
|
+
- `where` clauses for complex bounds
|
|
131
|
+
- Associated types when there's one implementation per Self type
|
|
132
|
+
- Generic parameters when multiple implementations per Self type
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Concurrency
|
|
137
|
+
|
|
138
|
+
### Threads
|
|
139
|
+
|
|
140
|
+
```rust
|
|
141
|
+
// Scoped threads (1.63+) — safe borrows from parent stack
|
|
142
|
+
thread::scope(|s| {
|
|
143
|
+
s.spawn(|| process(&data));
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Async/Await
|
|
148
|
+
|
|
149
|
+
```rust
|
|
150
|
+
// Concurrent execution
|
|
151
|
+
let (users, posts) = tokio::join!(fetch_users(), fetch_posts());
|
|
152
|
+
|
|
153
|
+
// Timeout
|
|
154
|
+
tokio::select! {
|
|
155
|
+
result = fetch_data() => handle(result),
|
|
156
|
+
_ = tokio::time::sleep(Duration::from_secs(5)) => bail!("timeout"),
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Key Rules
|
|
161
|
+
|
|
162
|
+
- Never hold a `MutexGuard` across an `.await` point
|
|
163
|
+
- Never block in async context — use `spawn_blocking` for CPU work
|
|
164
|
+
- Use `tokio::sync::Mutex` when you must hold across awaits
|
|
165
|
+
- Every spawned task needs a cancellation/shutdown strategy
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Testing
|
|
170
|
+
|
|
171
|
+
### Table-Style Tests
|
|
172
|
+
|
|
173
|
+
```rust
|
|
174
|
+
#[test]
|
|
175
|
+
fn test_parse_age() {
|
|
176
|
+
let cases = [("25", Ok(25)), ("-1", Err(..)), ("abc", Err(..))];
|
|
177
|
+
for (input, expected) in cases {
|
|
178
|
+
assert_eq!(parse_age(input), expected, "input: {input}");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Trait-Based Dependency Injection
|
|
184
|
+
|
|
185
|
+
```rust
|
|
186
|
+
trait Clock { fn now(&self) -> DateTime<Utc>; }
|
|
187
|
+
struct FakeClock(DateTime<Utc>);
|
|
188
|
+
impl Clock for FakeClock { fn now(&self) -> DateTime<Utc> { self.0 } }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Property-Based Testing
|
|
192
|
+
|
|
193
|
+
```rust
|
|
194
|
+
proptest! {
|
|
195
|
+
#[test]
|
|
196
|
+
fn round_trips(name in "[a-z]{1,50}", age in 0u32..150) {
|
|
197
|
+
let user = User { name, age };
|
|
198
|
+
let json = serde_json::to_string(&user)?;
|
|
199
|
+
let decoded: User = serde_json::from_str(&json)?;
|
|
200
|
+
assert_eq!(user, decoded);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Always Run
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
cargo test --all-features
|
|
209
|
+
cargo clippy -- -D warnings
|
|
210
|
+
cargo +nightly miri test # For crates with unsafe
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Performance and Unsafe
|
|
216
|
+
|
|
217
|
+
### Measure First
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
cargo bench
|
|
221
|
+
cargo flamegraph
|
|
222
|
+
cargo build --timings
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Key Patterns
|
|
226
|
+
|
|
227
|
+
- Preallocate with `Vec::with_capacity`
|
|
228
|
+
- Iterators over collect-then-iterate
|
|
229
|
+
- `Cow` for conditional allocation
|
|
230
|
+
- `SmallVec` for small stack-allocated collections
|
|
231
|
+
- `String::with_capacity` and `std::fmt::Write`
|
|
232
|
+
|
|
233
|
+
### Unsafe Rules
|
|
234
|
+
|
|
235
|
+
- Every `unsafe` block gets a `// SAFETY:` comment
|
|
236
|
+
- Wrap unsafe in safe abstractions with narrow interfaces
|
|
237
|
+
- Run Miri in CI for any crate with unsafe code
|
|
238
|
+
- `unsafe` doesn't fix design problems — it hides them
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Ecosystem and Tooling
|
|
243
|
+
|
|
244
|
+
### Essential Crates
|
|
245
|
+
|
|
246
|
+
| Domain | Crate |
|
|
247
|
+
|--------|-------|
|
|
248
|
+
| Serialization | serde, serde_json |
|
|
249
|
+
| Async | tokio |
|
|
250
|
+
| Web | axum, reqwest, tonic |
|
|
251
|
+
| Database | sqlx, diesel |
|
|
252
|
+
| Errors | thiserror, anyhow |
|
|
253
|
+
| CLI | clap |
|
|
254
|
+
| Observability | tracing, metrics |
|
|
255
|
+
| Testing | proptest, criterion, mockall, insta |
|
|
256
|
+
|
|
257
|
+
### CI Essentials
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
cargo fmt -- --check
|
|
261
|
+
cargo clippy --all-targets --all-features -- -D warnings
|
|
262
|
+
cargo test --all-features
|
|
263
|
+
cargo audit
|
|
264
|
+
cargo deny check
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Definition of Done
|
|
270
|
+
|
|
271
|
+
A Rust feature is complete when:
|
|
272
|
+
|
|
273
|
+
- [ ] `cargo build` compiles with zero warnings
|
|
274
|
+
- [ ] `cargo clippy -- -D warnings` passes
|
|
275
|
+
- [ ] `cargo test` passes (including doc tests)
|
|
276
|
+
- [ ] `cargo fmt -- --check` passes
|
|
277
|
+
- [ ] No `unwrap()` in library code without justification
|
|
278
|
+
- [ ] All `unsafe` blocks have `// SAFETY:` comments
|
|
279
|
+
- [ ] Error types implement `std::error::Error`
|
|
280
|
+
- [ ] Public API has doc comments with examples
|
|
281
|
+
- [ ] No unnecessary allocations in hot paths
|
|
282
|
+
- [ ] `cargo deny check` passes
|
|
283
|
+
- [ ] Code reviewed and approved
|