tribunal-kit 4.5.1 → 4.6.1

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.
Files changed (214) hide show
  1. package/.agent/.shared/ui-ux-pro-max/README.md +4 -4
  2. package/.agent/ARCHITECTURE.md +282 -277
  3. package/.agent/agents/accessibility-reviewer.md +187 -187
  4. package/.agent/agents/ai-code-reviewer.md +199 -199
  5. package/.agent/agents/api-architect.md +71 -66
  6. package/.agent/agents/backend-specialist.md +219 -215
  7. package/.agent/agents/cloud-engineer.md +98 -0
  8. package/.agent/agents/code-archaeologist.md +168 -161
  9. package/.agent/agents/database-architect.md +184 -184
  10. package/.agent/agents/db-latency-auditor.md +213 -216
  11. package/.agent/agents/debugger.md +198 -191
  12. package/.agent/agents/dependency-reviewer.md +106 -103
  13. package/.agent/agents/devops-engineer.md +218 -218
  14. package/.agent/agents/documentation-writer.md +209 -201
  15. package/.agent/agents/explorer-agent.md +167 -160
  16. package/.agent/agents/frontend-reviewer.md +162 -160
  17. package/.agent/agents/frontend-specialist.md +257 -248
  18. package/.agent/agents/game-developer.md +48 -48
  19. package/.agent/agents/logic-reviewer.md +118 -116
  20. package/.agent/agents/mobile-developer.md +197 -200
  21. package/.agent/agents/mobile-reviewer.md +159 -162
  22. package/.agent/agents/orchestrator.md +187 -181
  23. package/.agent/agents/penetration-tester.md +160 -157
  24. package/.agent/agents/performance-optimizer.md +183 -183
  25. package/.agent/agents/performance-reviewer.md +178 -178
  26. package/.agent/agents/precedence-reviewer.md +251 -250
  27. package/.agent/agents/product-manager.md +149 -142
  28. package/.agent/agents/product-owner.md +81 -80
  29. package/.agent/agents/project-planner.md +152 -142
  30. package/.agent/agents/qa-automation-engineer.md +216 -225
  31. package/.agent/agents/resilience-reviewer.md +88 -88
  32. package/.agent/agents/schema-reviewer.md +67 -67
  33. package/.agent/agents/security-auditor.md +180 -174
  34. package/.agent/agents/seo-specialist.md +188 -193
  35. package/.agent/agents/sql-reviewer.md +159 -161
  36. package/.agent/agents/supervisor-agent.md +173 -184
  37. package/.agent/agents/swarm-worker-contracts.md +170 -166
  38. package/.agent/agents/swarm-worker-registry.md +92 -92
  39. package/.agent/agents/system-architect.md +85 -0
  40. package/.agent/agents/test-coverage-reviewer.md +158 -160
  41. package/.agent/agents/test-engineer.md +118 -118
  42. package/.agent/agents/throughput-optimizer.md +291 -299
  43. package/.agent/agents/type-safety-reviewer.md +182 -175
  44. package/.agent/agents/ui-ux-auditor.md +300 -292
  45. package/.agent/agents/vitals-reviewer.md +223 -223
  46. package/.agent/mcp_config.json +37 -40
  47. package/.agent/patterns/generator.md +11 -9
  48. package/.agent/patterns/inversion.md +14 -12
  49. package/.agent/patterns/pipeline.md +11 -9
  50. package/.agent/patterns/reviewer.md +15 -13
  51. package/.agent/patterns/tool-wrapper.md +11 -9
  52. package/.agent/routing_index.json +714 -0
  53. package/.agent/rules/GEMINI.md +359 -352
  54. package/.agent/scripts/compile_router.py +112 -0
  55. package/.agent/scripts/migrate_skills_frontmatter.py +64 -0
  56. package/.agent/scripts/strengthen_skills.js +1 -1
  57. package/.agent/skills/advanced-rag-pipelines/SKILL.md +56 -0
  58. package/.agent/skills/agent-organizer/SKILL.md +156 -150
  59. package/.agent/skills/agentic-patterns/SKILL.md +313 -315
  60. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +190 -184
  61. package/.agent/skills/api-patterns/SKILL.md +253 -247
  62. package/.agent/skills/api-security-auditor/SKILL.md +195 -193
  63. package/.agent/skills/app-builder/SKILL.md +573 -572
  64. package/.agent/skills/app-builder/templates/SKILL.md +108 -115
  65. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -76
  66. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -92
  67. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -88
  68. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -88
  69. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -83
  70. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -90
  71. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -90
  72. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +126 -122
  73. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +127 -122
  74. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +172 -169
  75. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +139 -134
  76. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -83
  77. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +122 -119
  78. package/.agent/skills/appflow-wireframe/SKILL.md +146 -145
  79. package/.agent/skills/architecture/SKILL.md +226 -219
  80. package/.agent/skills/authentication-best-practices/SKILL.md +197 -189
  81. package/.agent/skills/backend-security-expert/SKILL.md +16 -2
  82. package/.agent/skills/bash-linux/SKILL.md +179 -179
  83. package/.agent/skills/behavioral-modes/SKILL.md +239 -223
  84. package/.agent/skills/brainstorming/SKILL.md +498 -486
  85. package/.agent/skills/browser-native-ai/SKILL.md +57 -4
  86. package/.agent/skills/building-native-ui/SKILL.md +202 -202
  87. package/.agent/skills/cicd-pro/SKILL.md +442 -0
  88. package/.agent/skills/clean-code/SKILL.md +400 -381
  89. package/.agent/skills/cloud-architect/SKILL.md +439 -0
  90. package/.agent/skills/code-review-checklist/SKILL.md +203 -194
  91. package/.agent/skills/config-validator/SKILL.md +165 -165
  92. package/.agent/skills/containerization-pro/SKILL.md +452 -0
  93. package/.agent/skills/csharp-developer/SKILL.md +518 -518
  94. package/.agent/skills/data-validation-schemas/SKILL.md +333 -328
  95. package/.agent/skills/database-design/SKILL.md +247 -240
  96. package/.agent/skills/deployment-procedures/SKILL.md +172 -169
  97. package/.agent/skills/devops-engineer/SKILL.md +345 -345
  98. package/.agent/skills/devops-incident-responder/SKILL.md +143 -137
  99. package/.agent/skills/documentation-templates/SKILL.md +291 -279
  100. package/.agent/skills/edge-computing/SKILL.md +183 -181
  101. package/.agent/skills/emil-design-eng/SKILL.md +147 -0
  102. package/.agent/skills/error-resilience/SKILL.md +411 -428
  103. package/.agent/skills/extract-design-system/SKILL.md +160 -158
  104. package/.agent/skills/framer-motion-expert/SKILL.md +253 -244
  105. package/.agent/skills/frontend-design/SKILL.md +208 -201
  106. package/.agent/skills/frontend-security-expert/SKILL.md +16 -3
  107. package/.agent/skills/game-design-expert/SKILL.md +132 -129
  108. package/.agent/skills/game-engineering-expert/SKILL.md +148 -146
  109. package/.agent/skills/generative-ui-expert/SKILL.md +57 -1
  110. package/.agent/skills/geo-fundamentals/SKILL.md +148 -147
  111. package/.agent/skills/git-pro/SKILL.md +435 -0
  112. package/.agent/skills/github-operations/SKILL.md +335 -329
  113. package/.agent/skills/gsap-core/SKILL.md +319 -308
  114. package/.agent/skills/gsap-frameworks/SKILL.md +213 -207
  115. package/.agent/skills/gsap-performance/SKILL.md +139 -133
  116. package/.agent/skills/gsap-plugins/SKILL.md +486 -480
  117. package/.agent/skills/gsap-react/SKILL.md +202 -189
  118. package/.agent/skills/gsap-scrolltrigger/SKILL.md +357 -350
  119. package/.agent/skills/gsap-timeline/SKILL.md +165 -161
  120. package/.agent/skills/gsap-utils/SKILL.md +344 -338
  121. package/.agent/skills/harness-protocol/SKILL.md +48 -0
  122. package/.agent/skills/i18n-localization/SKILL.md +174 -163
  123. package/.agent/skills/intelligent-routing/SKILL.md +202 -246
  124. package/.agent/skills/knowledge-graph/SKILL.md +60 -52
  125. package/.agent/skills/lint-and-validate/SKILL.md +261 -261
  126. package/.agent/skills/llm-engineering/SKILL.md +400 -394
  127. package/.agent/skills/local-first/SKILL.md +178 -178
  128. package/.agent/skills/mcp-builder/SKILL.md +143 -142
  129. package/.agent/skills/mobile-design/SKILL.md +272 -263
  130. package/.agent/skills/monorepo-management/SKILL.md +335 -334
  131. package/.agent/skills/motion-engineering/SKILL.md +266 -234
  132. package/.agent/skills/nextjs-react-expert/SKILL.md +236 -234
  133. package/.agent/skills/nodejs-best-practices/SKILL.md +547 -548
  134. package/.agent/skills/observability/SKILL.md +343 -343
  135. package/.agent/skills/parallel-agents/SKILL.md +143 -146
  136. package/.agent/skills/performance-profiling/SKILL.md +259 -267
  137. package/.agent/skills/plan-writing/SKILL.md +150 -142
  138. package/.agent/skills/platform-engineer/SKILL.md +148 -147
  139. package/.agent/skills/playwright-best-practices/SKILL.md +188 -187
  140. package/.agent/skills/powershell-windows/SKILL.md +162 -162
  141. package/.agent/skills/project-idioms/SKILL.md +137 -137
  142. package/.agent/skills/python-patterns/SKILL.md +260 -259
  143. package/.agent/skills/python-pro/SKILL.md +324 -323
  144. package/.agent/skills/react-specialist/SKILL.md +305 -277
  145. package/.agent/skills/readme-builder/SKILL.md +310 -300
  146. package/.agent/skills/realtime-patterns/SKILL.md +323 -319
  147. package/.agent/skills/red-team-tactics/SKILL.md +231 -218
  148. package/.agent/skills/review-animations/SKILL.md +72 -0
  149. package/.agent/skills/review-animations/STANDARDS.md +73 -0
  150. package/.agent/skills/rust-pro/SKILL.md +671 -673
  151. package/.agent/skills/seo-fundamentals/SKILL.md +179 -179
  152. package/.agent/skills/server-management/SKILL.md +218 -214
  153. package/.agent/skills/shadcn-ui-expert/SKILL.md +231 -231
  154. package/.agent/skills/skill-creator/SKILL.md +87 -86
  155. package/.agent/skills/sql-pro/SKILL.md +629 -629
  156. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +97 -97
  157. package/.agent/skills/swiftui-expert/SKILL.md +204 -201
  158. package/.agent/skills/system-design-pro/SKILL.md +345 -0
  159. package/.agent/skills/systematic-debugging/SKILL.md +153 -142
  160. package/.agent/skills/tailwind-patterns/SKILL.md +610 -566
  161. package/.agent/skills/tdd-workflow/SKILL.md +169 -161
  162. package/.agent/skills/test-result-analyzer/SKILL.md +313 -309
  163. package/.agent/skills/testing-patterns/SKILL.md +566 -579
  164. package/.agent/skills/trend-researcher/SKILL.md +243 -237
  165. package/.agent/skills/typescript-advanced/SKILL.md +336 -335
  166. package/.agent/skills/ui-ux-pro-max/SKILL.md +590 -562
  167. package/.agent/skills/ui-ux-researcher/SKILL.md +244 -244
  168. package/.agent/skills/vue-expert/SKILL.md +294 -275
  169. package/.agent/skills/vulnerability-scanner/SKILL.md +416 -404
  170. package/.agent/skills/web-accessibility-auditor/SKILL.md +219 -218
  171. package/.agent/skills/web-design-guidelines/SKILL.md +192 -186
  172. package/.agent/skills/webapp-testing/SKILL.md +167 -169
  173. package/.agent/skills/webgpu-performance/SKILL.md +56 -2
  174. package/.agent/skills/whimsy-injector/SKILL.md +346 -325
  175. package/.agent/skills/workflow-optimizer/SKILL.md +231 -229
  176. package/.agent/workflows/acf.md +141 -0
  177. package/.agent/workflows/api-tester.md +176 -151
  178. package/.agent/workflows/audit.md +150 -127
  179. package/.agent/workflows/brainstorm.md +134 -110
  180. package/.agent/workflows/changelog.md +140 -112
  181. package/.agent/workflows/create.md +168 -124
  182. package/.agent/workflows/debug.md +190 -165
  183. package/.agent/workflows/deploy.md +201 -180
  184. package/.agent/workflows/enhance.md +154 -128
  185. package/.agent/workflows/fix.md +136 -114
  186. package/.agent/workflows/generate.md +198 -183
  187. package/.agent/workflows/marathon.md +37 -11
  188. package/.agent/workflows/migrate.md +184 -160
  189. package/.agent/workflows/orchestrate.md +192 -168
  190. package/.agent/workflows/performance-benchmarker.md +135 -114
  191. package/.agent/workflows/plan.md +196 -173
  192. package/.agent/workflows/preview.md +103 -80
  193. package/.agent/workflows/refactor.md +192 -161
  194. package/.agent/workflows/review-ai.md +125 -101
  195. package/.agent/workflows/review.md +141 -116
  196. package/.agent/workflows/session.md +122 -94
  197. package/.agent/workflows/status.md +101 -79
  198. package/.agent/workflows/strengthen-skills.md +164 -138
  199. package/.agent/workflows/super-prompt.md +24 -0
  200. package/.agent/workflows/swarm.md +193 -179
  201. package/.agent/workflows/test.md +211 -189
  202. package/.agent/workflows/tribunal-backend.md +136 -105
  203. package/.agent/workflows/tribunal-database.md +129 -95
  204. package/.agent/workflows/tribunal-frontend.md +140 -96
  205. package/.agent/workflows/tribunal-full.md +131 -100
  206. package/.agent/workflows/tribunal-mobile.md +129 -95
  207. package/.agent/workflows/tribunal-performance.md +136 -110
  208. package/.agent/workflows/tribunal-speed.md +209 -183
  209. package/.agent/workflows/ui-ux-pro-max.md +155 -122
  210. package/README.md +107 -55
  211. package/mcp_config.json +1 -3
  212. package/package.json +94 -94
  213. package/.agent/GEMINI.md +0 -121
  214. package/.agent/skills/doc.md +0 -177
@@ -1,677 +1,673 @@
1
- ---
2
- name: rust-pro
3
- description: Master Rust 1.75+ with modern async patterns, ownership/borrowing, lifetimes, traits, error handling with thiserror/anyhow, async Tokio runtime, axum web framework, serde serialization, and systems programming. Use when building Rust services, CLI tools, WebAssembly, or performance-critical systems.
4
- allowed-tools: Read, Write, Edit, Glob, Grep
5
- version: 2.0.0
6
- last-updated: 2026-03-30
7
- applies-to-model: gemini-2.5-pro, claude-3-7-sonnet
8
- ---
9
-
10
- # Rust Pro — Rust 1.75+ Systems Mastery
11
-
12
- ---
13
-
14
- ## Ownership & Borrowing
15
-
16
- ### The Three Rules
17
-
18
- ```rust
19
- // Rule 1: Each value has exactly ONE owner
20
- let s1 = String::from("hello");
21
- let s2 = s1; // s1 is MOVED to s2 — s1 is no longer valid
22
- // println!("{s1}"); // ❌ compile error: value borrowed after move
23
-
24
- // Rule 2: You can have EITHER one mutable reference OR any number of immutable references
25
- let mut data = vec![1, 2, 3];
26
- let r1 = &data; // ✅ immutable borrow
27
- let r2 = &data; // ✅ second immutable borrow — fine
28
- // let r3 = &mut data; // ❌ compile error: cannot borrow as mutable while immutable borrows exist
29
- println!("{r1:?} {r2:?}");
30
- // r1 and r2 go out of scope here (NLL — Non-Lexical Lifetimes)
31
- let r3 = &mut data; // ✅ now fine — no immutable borrows active
32
- r3.push(4);
33
-
34
- // Rule 3: References must always be valid (no dangling pointers)
35
- // fn dangling() -> &String { // ❌ compile error
36
- // let s = String::from("hello");
37
- // &s // s is dropped at end of function — reference would dangle
38
- // }
39
- fn not_dangling() -> String {
40
- String::from("hello") // ✅ return owned value
41
- }
42
- ```
43
-
44
- ### Common Ownership Patterns
45
-
46
- ```rust
47
- // Clone when you need independent copies (has a cost — measure)
48
- let original = vec![1, 2, 3];
49
- let copy = original.clone(); // deep copy — both are independent
50
-
51
- // Rc<T> — shared ownership (single-threaded)
52
- use std::rc::Rc;
53
- let shared = Rc::new(vec![1, 2, 3]);
54
- let also_shared = Rc::clone(&shared); // cheap reference count increment
55
- // Both shared and also_shared point to the same data
56
-
57
- // Arc<T> — shared ownership (thread-safe)
58
- use std::sync::Arc;
59
- let thread_safe = Arc::new(vec![1, 2, 3]);
60
- let for_thread = Arc::clone(&thread_safe);
61
- std::thread::spawn(move || {
62
- println!("{for_thread:?}");
63
- });
64
-
65
- // Cow<T> — Clone on Write (zero-copy when not modified)
66
- use std::borrow::Cow;
67
- fn process(input: &str) -> Cow<'_, str> {
68
- if input.contains("bad") {
69
- Cow::Owned(input.replace("bad", "good")) // allocated only if needed
70
- } else {
71
- Cow::Borrowed(input) // zero-copy
72
- }
73
- }
74
- ```
75
-
76
- ---
77
-
78
- ## Lifetimes
79
-
80
- ```rust
81
- // Lifetime annotations tell the compiler how long references are valid
82
- // They DON'T change how long values live — they DESCRIBE existing relationships
83
-
84
- // ✅ Explicit lifetime: return value lives as long as the input
85
- fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
86
- if x.len() > y.len() { x } else { y }
87
- }
88
-
89
- // Struct with references (requires lifetime annotation)
90
- struct Config<'a> {
91
- name: &'a str,
92
- version: &'a str,
93
- }
94
-
95
- impl<'a> Config<'a> {
96
- fn display(&self) -> String {
97
- format!("{} v{}", self.name, self.version)
98
- }
99
- }
100
-
101
- // 'static lifetime — lives for the entire program
102
- let s: &'static str = "I live forever"; // string literals are 'static
103
- // Owned types satisfy 'static (they own their data)
104
- fn takes_static(s: String) { /* String is 'static because it owns its data */ }
105
-
106
- // ❌ HALLUCINATION TRAP: Lifetime elision rules handle most cases
107
- // Don't add lifetimes unless the compiler asks for them
108
- // The compiler tells you exactly which annotations are needed
109
- ```
110
-
111
- ---
112
-
113
- ## Error Handling
114
-
115
- ### The `?` Operator & Result
116
-
117
- ```rust
118
- use std::fs;
119
- use std::io;
120
-
121
- // ✅ Propagate errors with ?
122
- fn read_config(path: &str) -> Result<Config, io::Error> {
123
- let content = fs::read_to_string(path)?; // returns early on error
124
- let config: Config = serde_json::from_str(&content)?;
125
- Ok(config)
126
- }
127
-
128
- // ❌ HALLUCINATION TRAP: NEVER use .unwrap() in production code
129
- // .unwrap() panics on error — crashes the entire program
130
- // ❌ let file = File::open("config.json").unwrap();
131
- // ✅ let file = File::open("config.json")?;
132
- // ✅ let file = File::open("config.json").unwrap_or_default();
133
- // ✅ let file = File::open("config.json").map_err(|e| AppError::Io(e))?;
134
- ```
135
-
136
- ### thiserror (Library Errors)
137
-
138
- ```rust
139
- // thiserror — for library code (structured error types)
140
- use thiserror::Error;
141
-
142
- #[derive(Debug, Error)]
143
- pub enum AppError {
144
- #[error("Database error: {0}")]
145
- Database(#[from] sqlx::Error),
146
-
147
- #[error("Validation error: {field} — {message}")]
148
- Validation { field: String, message: String },
149
-
150
- #[error("Not found: {0}")]
151
- NotFound(String),
152
-
153
- #[error("Unauthorized")]
154
- Unauthorized,
155
-
156
- #[error("IO error: {0}")]
157
- Io(#[from] std::io::Error),
158
-
159
- #[error("JSON error: {0}")]
160
- Json(#[from] serde_json::Error),
161
- }
162
-
163
- // #[from] auto-implements From<sqlx::Error> for AppError
164
- // So sqlx errors can be propagated with ? automatically
165
- ```
166
-
167
- ### anyhow (Application Errors)
168
-
169
- ```rust
170
- // anyhow — for application code (quick error propagation)
171
- use anyhow::{Context, Result, bail, ensure};
172
-
173
- fn load_config(path: &str) -> Result<Config> {
174
- let content = fs::read_to_string(path)
175
- .context(format!("Failed to read config from {path}"))?;
176
-
177
- let config: Config = serde_json::from_str(&content)
178
- .context("Invalid JSON in config file")?;
179
-
180
- ensure!(config.port > 0, "Port must be positive, got {}", config.port);
181
-
182
- if config.name.is_empty() {
183
- bail!("Config name cannot be empty");
184
- }
185
-
186
- Ok(config)
187
- }
188
-
189
- // Use thiserror for libraries, anyhow for applications
190
- // ❌ HALLUCINATION TRAP: Don't use anyhow in library crates
191
- // Libraries should expose structured error types (thiserror)
192
- // anyhow erases type information — callers can't match on specific errors
193
- ```
194
-
195
- ---
196
-
197
- ## Traits
198
-
199
- ### Defining & Implementing
200
-
201
- ```rust
202
- trait Summarizable {
203
- fn summary(&self) -> String;
204
-
205
- // Default implementation
206
- fn preview(&self) -> String {
207
- let s = self.summary();
208
- if s.len() > 50 {
209
- format!("{}...", &s[..50])
210
- } else {
211
- s
212
- }
213
- }
214
- }
215
-
216
- struct Article {
217
- title: String,
218
- body: String,
219
- author: String,
220
- }
221
-
222
- impl Summarizable for Article {
223
- fn summary(&self) -> String {
224
- format!("{} by {} — {}", self.title, self.author, &self.body[..100.min(self.body.len())])
225
- }
226
- }
227
-
228
- // Trait bounds
229
- fn notify(item: &impl Summarizable) {
230
- println!("Breaking: {}", item.summary());
231
- }
232
-
233
- // Equivalent with generics (more flexible)
234
- fn notify_generic<T: Summarizable + std::fmt::Display>(item: &T) {
235
- println!("Breaking: {}", item.summary());
236
- }
237
-
238
- // where clause (cleaner for complex bounds)
239
- fn process<T, U>(t: &T, u: &U) -> String
240
- where
241
- T: Summarizable + Clone,
242
- U: std::fmt::Debug + Send,
243
- {
244
- format!("{} — {:?}", t.summary(), u)
245
- }
246
-
247
- // Return impl Trait (hide concrete type)
248
- fn make_summarizer() -> impl Summarizable {
249
- Article { title: "News".into(), body: "Content".into(), author: "Author".into() }
250
- }
251
- ```
252
-
253
- ### Common Standard Traits
254
-
255
- ```rust
256
- // Derive common traits
257
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
258
- struct Point {
259
- x: i32,
260
- y: i32,
261
- }
262
-
263
- // Display — for user-facing output
264
- use std::fmt;
265
- impl fmt::Display for Point {
266
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267
- write!(f, "({}, {})", self.x, self.y)
268
- }
269
- }
270
-
271
- // From/Into — type conversion
272
- impl From<(i32, i32)> for Point {
273
- fn from((x, y): (i32, i32)) -> Self {
274
- Point { x, y }
275
- }
276
- }
277
- let p: Point = (10, 20).into(); // uses From automatically
278
-
279
- // Iterator
280
- struct Counter { count: u32, max: u32 }
281
- impl Iterator for Counter {
282
- type Item = u32;
283
- fn next(&mut self) -> Option<Self::Item> {
284
- if self.count < self.max {
285
- self.count += 1;
286
- Some(self.count)
287
- } else {
288
- None
289
- }
290
- }
291
- }
292
- ```
293
-
294
- ---
295
-
296
- ## Async with Tokio
297
-
298
- ### Runtime Setup
299
-
300
- ```rust
301
- // Cargo.toml
302
- // [dependencies]
303
- // tokio = { version = "1", features = ["full"] }
304
-
305
- #[tokio::main]
306
- async fn main() {
307
- let result = fetch_data("https://api.example.com/data").await;
308
- println!("{result:?}");
309
- }
310
-
311
- // For library code — don't use #[tokio::main], let the caller choose the runtime
312
- pub async fn fetch_data(url: &str) -> Result<String> {
313
- let response = reqwest::get(url).await?;
314
- let body = response.text().await?;
315
- Ok(body)
316
- }
317
- ```
318
-
319
- ### Concurrent Tasks
320
-
321
- ```rust
322
- use tokio::task;
323
-
324
- // Spawn concurrent tasks
325
- async fn parallel_fetch() -> Result<(Users, Posts)> {
326
- let users_handle = task::spawn(async { fetch_users().await });
327
- let posts_handle = task::spawn(async { fetch_posts().await });
328
-
329
- let users = users_handle.await??; // first ? for JoinError, second for app error
330
- let posts = posts_handle.await??;
331
-
332
- Ok((users, posts))
333
- }
334
-
335
- // tokio::join! — run concurrently, wait for all
336
- async fn fetch_all() -> Result<(Users, Posts, Analytics)> {
337
- let (users, posts, analytics) = tokio::join!(
338
- fetch_users(),
339
- fetch_posts(),
340
- fetch_analytics(),
341
- );
342
- Ok((users?, posts?, analytics?))
343
- }
344
-
345
- // tokio::select! — race multiple futures, take first to complete
346
- async fn fetch_with_timeout(url: &str) -> Result<String> {
347
- tokio::select! {
348
- result = fetch_data(url) => result,
349
- _ = tokio::time::sleep(Duration::from_secs(5)) => {
350
- Err(anyhow!("Request timed out after 5s"))
351
- }
352
- }
353
- }
354
-
355
- // ❌ HALLUCINATION TRAP: tokio::spawn requires 'static + Send
356
- // You cannot spawn a task referencing local variables without Arc/clone
357
- // ❌ let data = &local_data;
358
- // tokio::spawn(async { process(data) }); // ❌ data doesn't live long enough
359
- // ✅ let data = Arc::new(local_data);
360
- // let data_clone = Arc::clone(&data);
361
- // tokio::spawn(async move { process(&data_clone) });
362
- ```
363
-
364
- ### Channels
365
-
366
- ```rust
367
- use tokio::sync::{mpsc, oneshot, broadcast};
368
-
369
- // mpsc — Multiple Producer, Single Consumer
370
- async fn worker_pattern() {
371
- let (tx, mut rx) = mpsc::channel::<String>(32); // buffer size
372
-
373
- tokio::spawn(async move {
374
- tx.send("hello".to_string()).await.unwrap();
375
- tx.send("world".to_string()).await.unwrap();
376
- });
377
-
378
- while let Some(msg) = rx.recv().await {
379
- println!("Got: {msg}");
380
- }
381
- }
382
-
383
- // oneshot — single response (request/response pattern)
384
- async fn request_response() {
385
- let (tx, rx) = oneshot::channel::<String>();
386
-
387
- tokio::spawn(async move {
388
- let result = expensive_computation().await;
389
- tx.send(result).unwrap();
390
- });
391
-
392
- let response = rx.await.unwrap();
393
- }
394
-
395
- // Mutex (async-safe)
396
- use tokio::sync::Mutex;
397
- let shared_state = Arc::new(Mutex::new(Vec::new()));
398
-
399
- let state = Arc::clone(&shared_state);
400
- tokio::spawn(async move {
401
- let mut guard = state.lock().await;
402
- guard.push("item");
403
- }); // lock released when guard is dropped
404
- ```
405
-
406
- ---
407
-
408
- ## Axum Web Framework
409
-
410
- ### Basic Server
411
-
412
- ```rust
413
- use axum::{
414
- extract::{Path, Query, State, Json},
415
- http::StatusCode,
416
- response::IntoResponse,
417
- routing::{get, post, delete},
418
- Router,
419
- };
420
- use serde::{Deserialize, Serialize};
421
-
422
- #[derive(Clone)]
423
- struct AppState {
424
- db: sqlx::PgPool,
425
- }
426
-
427
- #[tokio::main]
428
- async fn main() {
429
- let pool = sqlx::PgPool::connect("postgres://localhost/mydb").await.unwrap();
430
- let state = AppState { db: pool };
431
-
432
- let app = Router::new()
433
- .route("/users", get(list_users).post(create_user))
434
- .route("/users/{id}", get(get_user).delete(delete_user))
435
- .with_state(state);
436
-
437
- let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
438
- axum::serve(listener, app).await.unwrap();
439
- }
440
-
441
- // ❌ HALLUCINATION TRAP: axum 0.7+ uses {id} not :id for path params
442
- // ❌ .route("/users/:id", ...) ← old syntax
443
- // ✅ .route("/users/{id}", ...) ← axum 0.7+
444
- ```
445
-
446
- ### Handlers
447
-
448
- ```rust
449
- #[derive(Deserialize)]
450
- struct ListParams {
451
- page: Option<u32>,
452
- limit: Option<u32>,
453
- }
454
-
455
- async fn list_users(
456
- State(state): State<AppState>,
457
- Query(params): Query<ListParams>,
458
- ) -> Result<Json<Vec<User>>, AppError> {
459
- let page = params.page.unwrap_or(1);
460
- let limit = params.limit.unwrap_or(20).min(100);
461
- let offset = (page - 1) * limit;
462
-
463
- let users = sqlx::query_as!(
464
- User,
465
- "SELECT id, name, email FROM users ORDER BY id LIMIT $1 OFFSET $2",
466
- limit as i64,
467
- offset as i64,
468
- )
469
- .fetch_all(&state.db)
470
- .await?;
471
-
472
- Ok(Json(users))
473
- }
474
-
475
- #[derive(Deserialize)]
476
- struct CreateUserPayload {
477
- name: String,
478
- email: String,
479
- }
480
-
481
- async fn create_user(
482
- State(state): State<AppState>,
483
- Json(payload): Json<CreateUserPayload>,
484
- ) -> Result<(StatusCode, Json<User>), AppError> {
485
- let user = sqlx::query_as!(
486
- User,
487
- "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email",
488
- payload.name,
489
- payload.email,
490
- )
491
- .fetch_one(&state.db)
492
- .await?;
493
-
494
- Ok((StatusCode::CREATED, Json(user)))
495
- }
496
-
497
- async fn get_user(
498
- State(state): State<AppState>,
499
- Path(id): Path<i32>,
500
- ) -> Result<Json<User>, AppError> {
501
- let user = sqlx::query_as!(User, "SELECT id, name, email FROM users WHERE id = $1", id)
502
- .fetch_optional(&state.db)
503
- .await?
504
- .ok_or(AppError::NotFound(format!("User {id}")))?;
505
-
506
- Ok(Json(user))
507
- }
508
- ```
509
-
510
- ### Error Handling in Axum
511
-
512
- ```rust
513
- use axum::response::{IntoResponse, Response};
514
-
515
- #[derive(Debug, thiserror::Error)]
516
- pub enum AppError {
517
- #[error("Not found: {0}")]
518
- NotFound(String),
519
- #[error("Validation: {0}")]
520
- Validation(String),
521
- #[error("Database: {0}")]
522
- Database(#[from] sqlx::Error),
523
- #[error("Internal: {0}")]
524
- Internal(#[from] anyhow::Error),
525
- }
526
-
527
- impl IntoResponse for AppError {
528
- fn into_response(self) -> Response {
529
- let (status, message) = match &self {
530
- AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
531
- AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
532
- AppError::Database(e) => {
533
- tracing::error!("DB error: {e}"); // log internal details
534
- (StatusCode::INTERNAL_SERVER_ERROR, "Database error".to_string())
535
- }
536
- AppError::Internal(e) => {
537
- tracing::error!("Internal error: {e}");
538
- (StatusCode::INTERNAL_SERVER_ERROR, "Internal error".to_string())
539
- }
540
- };
541
-
542
- (status, Json(serde_json::json!({ "error": message }))).into_response()
543
- }
544
- }
545
- ```
546
-
547
- ---
548
-
549
- ## Serde (Serialization)
550
-
551
- ```rust
552
- use serde::{Deserialize, Serialize};
553
-
554
- #[derive(Debug, Serialize, Deserialize)]
555
- #[serde(rename_all = "camelCase")] // JSON uses camelCase
556
- struct UserResponse {
557
- user_id: i32, // serialized as "userId"
558
- full_name: String, // serialized as "fullName"
559
- email: String,
560
-
561
- #[serde(skip_serializing_if = "Option::is_none")]
562
- phone: Option<String>, // omitted from JSON if None
563
-
564
- #[serde(default)] // defaults to 0 if missing in input
565
- login_count: u32,
566
-
567
- #[serde(rename = "type")] // rename for reserved keywords
568
- user_type: String,
569
-
570
- #[serde(skip)] // never serialized/deserialized
571
- internal_token: String,
572
- }
573
-
574
- // Enum serialization
575
- #[derive(Serialize, Deserialize)]
576
- #[serde(tag = "type", content = "data")] // adjacently tagged
577
- enum Event {
578
- #[serde(rename = "user_created")]
579
- UserCreated { id: i32, name: String },
580
- #[serde(rename = "user_deleted")]
581
- UserDeleted { id: i32 },
582
- }
583
- // Serializes as: {"type": "user_created", "data": {"id": 1, "name": "Alice"}}
584
- ```
585
-
586
- ---
587
-
588
- ## Iterator Patterns
589
-
590
- ```rust
591
- let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
592
-
593
- // Chain operations (lazy — no allocation until collect)
594
- let result: Vec<i32> = numbers.iter()
595
- .filter(|&&n| n % 2 == 0) // keep even
596
- .map(|&n| n * n) // square
597
- .take(3) // first 3
598
- .collect(); // [4, 16, 36]
599
-
600
- // fold (reduce)
601
- let sum: i32 = numbers.iter().fold(0, |acc, &n| acc + n);
602
-
603
- // find / position
604
- let first_even = numbers.iter().find(|&&n| n % 2 == 0); // Some(&2)
605
- let pos = numbers.iter().position(|&n| n > 5); // Some(5)
606
-
607
- // chunk / window
608
- let chunks: Vec<&[i32]> = numbers.chunks(3).collect();
609
- // [[1,2,3], [4,5,6], [7,8,9], [10]]
610
-
611
- let windows: Vec<&[i32]> = numbers.windows(3).collect();
612
- // [[1,2,3], [2,3,4], [3,4,5], ...]
613
-
614
- // Collecting into HashMap
615
- use std::collections::HashMap;
616
- let word_counts: HashMap<&str, usize> = words.iter()
617
- .fold(HashMap::new(), |mut map, word| {
618
- *map.entry(word.as_str()).or_insert(0) += 1;
619
- map
620
- });
621
- ```
622
-
623
-
624
-
625
-
626
- ---
627
-
628
-
629
-
630
- AI coding assistants often fall into specific bad habits when dealing with this domain. These are strictly forbidden:
631
-
632
- 1. **Over-engineering:** Proposing complex abstractions or distributed systems when a simpler approach suffices.
633
- 2. **Hallucinated Libraries/Methods:** Using non-existent methods or packages. Always `// VERIFY` or check `package.json` / `requirements.txt`.
634
- 3. **Skipping Edge Cases:** Writing the "happy path" and ignoring error handling, timeouts, or data validation.
635
- 4. **Context Amnesia:** Forgetting the user's constraints and offering generic advice instead of tailored solutions.
636
- 5. **Silent Degradation:** Catching and suppressing errors without logging or re-raising.
637
-
638
- ---
639
-
640
-
641
-
642
- **Slash command: `/review` or `/tribunal-full`**
643
- **Active reviewers: `logic-reviewer` · `security-auditor`**
644
-
645
- ### ❌ Forbidden AI Tropes
646
-
647
- 1. **Blind Assumptions:** Never make an assumption without documenting it clearly with `// VERIFY: [reason]`.
648
- 2. **Silent Degradation:** Catching and suppressing errors without logging or handling.
649
- 3. **Context Amnesia:** Forgetting the user's constraints and offering generic advice instead of tailored solutions.
650
-
651
-
652
-
653
- Review these questions before confirming output:
654
- ```
655
- ✅ Did I rely ONLY on real, verified tools and methods?
656
- ✅ Is this solution appropriately scoped to the user's constraints?
657
- ✅ Did I handle potential failure modes and edge cases?
658
- ✅ Have I avoided generic boilerplate that doesn't add value?
659
- ```
660
-
661
- ### 🛑 Verification-Before-Completion (VBC) Protocol
662
-
663
- **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
664
- - ❌ **Forbidden:** Declaring a task complete because the output "looks correct."
665
- - ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.
666
-
667
-
668
- ## Pre-Flight Checklist
669
- - [ ] Have I reviewed the user's specific constraints and requests?
670
- - [ ] Have I checked the environment for relevant existing implementations?
671
-
672
- ## VBC Protocol (Verification-Before-Completion)
673
- You MUST verify existing code signatures and variables before attempting to modify or call them. No hallucination is permitted.
1
+ ---
2
+ name: rust-pro
3
+ description: Master Rust 1.75+ with modern async patterns, ownership/borrowing, lifetimes, traits, error handling with thiserror/anyhow, async Tokio runtime, axum web framework, serde serialization, and systems programming. Use when building Rust services, CLI tools, WebAssembly, or performance-critical systems.
4
+ allowed-tools: Read, Write, Edit, Glob, Grep
5
+ version: 2.0.0
6
+ last-updated: 2026-03-30
7
+ applies-to-model: gemini-2.5-pro, claude-3-7-sonnet
8
+ routing:
9
+ domain: general
10
+ tier: basic
11
+ ---
674
12
 
13
+ # Rust Pro — Rust 1.75+ Systems Mastery
14
+
15
+ ---
16
+
17
+ ## Ownership & Borrowing
18
+
19
+ ### The Three Rules
20
+
21
+ ```rust
22
+ // Rule 1: Each value has exactly ONE owner
23
+ let s1 = String::from("hello");
24
+ let s2 = s1; // s1 is MOVED to s2 — s1 is no longer valid
25
+ // println!("{s1}"); // ❌ compile error: value borrowed after move
26
+
27
+ // Rule 2: You can have EITHER one mutable reference OR any number of immutable references
28
+ let mut data = vec![1, 2, 3];
29
+ let r1 = &data; // ✅ immutable borrow
30
+ let r2 = &data; // ✅ second immutable borrow — fine
31
+ // let r3 = &mut data; // ❌ compile error: cannot borrow as mutable while immutable borrows exist
32
+ println!("{r1:?} {r2:?}");
33
+ // r1 and r2 go out of scope here (NLL — Non-Lexical Lifetimes)
34
+ let r3 = &mut data; // ✅ now fine — no immutable borrows active
35
+ r3.push(4);
36
+
37
+ // Rule 3: References must always be valid (no dangling pointers)
38
+ // fn dangling() -> &String { // ❌ compile error
39
+ // let s = String::from("hello");
40
+ // &s // s is dropped at end of function — reference would dangle
41
+ // }
42
+ fn not_dangling() -> String {
43
+ String::from("hello") // ✅ return owned value
44
+ }
45
+ ```
46
+
47
+ ### Common Ownership Patterns
48
+
49
+ ```rust
50
+ // Clone when you need independent copies (has a cost — measure)
51
+ let original = vec![1, 2, 3];
52
+ let copy = original.clone(); // deep copy — both are independent
53
+
54
+ // Rc<T> — shared ownership (single-threaded)
55
+ use std::rc::Rc;
56
+ let shared = Rc::new(vec![1, 2, 3]);
57
+ let also_shared = Rc::clone(&shared); // cheap reference count increment
58
+ // Both shared and also_shared point to the same data
59
+
60
+ // Arc<T> — shared ownership (thread-safe)
61
+ use std::sync::Arc;
62
+ let thread_safe = Arc::new(vec![1, 2, 3]);
63
+ let for_thread = Arc::clone(&thread_safe);
64
+ std::thread::spawn(move || {
65
+ println!("{for_thread:?}");
66
+ });
67
+
68
+ // Cow<T> — Clone on Write (zero-copy when not modified)
69
+ use std::borrow::Cow;
70
+ fn process(input: &str) -> Cow<'_, str> {
71
+ if input.contains("bad") {
72
+ Cow::Owned(input.replace("bad", "good")) // allocated only if needed
73
+ } else {
74
+ Cow::Borrowed(input) // zero-copy
75
+ }
76
+ }
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Lifetimes
82
+
83
+ ```rust
84
+ // Lifetime annotations tell the compiler how long references are valid
85
+ // They DON'T change how long values live — they DESCRIBE existing relationships
86
+
87
+ // ✅ Explicit lifetime: return value lives as long as the input
88
+ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
89
+ if x.len() > y.len() { x } else { y }
90
+ }
91
+
92
+ // Struct with references (requires lifetime annotation)
93
+ struct Config<'a> {
94
+ name: &'a str,
95
+ version: &'a str,
96
+ }
97
+
98
+ impl<'a> Config<'a> {
99
+ fn display(&self) -> String {
100
+ format!("{} v{}", self.name, self.version)
101
+ }
102
+ }
103
+
104
+ // 'static lifetime — lives for the entire program
105
+ let s: &'static str = "I live forever"; // string literals are 'static
106
+ // Owned types satisfy 'static (they own their data)
107
+ fn takes_static(s: String) { /* String is 'static because it owns its data */ }
108
+
109
+ // ❌ HALLUCINATION TRAP: Lifetime elision rules handle most cases
110
+ // Don't add lifetimes unless the compiler asks for them
111
+ // The compiler tells you exactly which annotations are needed
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Error Handling
117
+
118
+ ### The `?` Operator & Result
119
+
120
+ ```rust
121
+ use std::fs;
122
+ use std::io;
123
+
124
+ // ✅ Propagate errors with ?
125
+ fn read_config(path: &str) -> Result<Config, io::Error> {
126
+ let content = fs::read_to_string(path)?; // returns early on error
127
+ let config: Config = serde_json::from_str(&content)?;
128
+ Ok(config)
129
+ }
130
+
131
+ // ❌ HALLUCINATION TRAP: NEVER use .unwrap() in production code
132
+ // .unwrap() panics on error — crashes the entire program
133
+ // ❌ let file = File::open("config.json").unwrap();
134
+ // ✅ let file = File::open("config.json")?;
135
+ // ✅ let file = File::open("config.json").unwrap_or_default();
136
+ // ✅ let file = File::open("config.json").map_err(|e| AppError::Io(e))?;
137
+ ```
138
+
139
+ ### thiserror (Library Errors)
140
+
141
+ ```rust
142
+ // thiserror — for library code (structured error types)
143
+ use thiserror::Error;
144
+
145
+ #[derive(Debug, Error)]
146
+ pub enum AppError {
147
+ #[error("Database error: {0}")]
148
+ Database(#[from] sqlx::Error),
149
+
150
+ #[error("Validation error: {field} — {message}")]
151
+ Validation { field: String, message: String },
152
+
153
+ #[error("Not found: {0}")]
154
+ NotFound(String),
155
+
156
+ #[error("Unauthorized")]
157
+ Unauthorized,
158
+
159
+ #[error("IO error: {0}")]
160
+ Io(#[from] std::io::Error),
161
+
162
+ #[error("JSON error: {0}")]
163
+ Json(#[from] serde_json::Error),
164
+ }
165
+
166
+ // #[from] auto-implements From<sqlx::Error> for AppError
167
+ // So sqlx errors can be propagated with ? automatically
168
+ ```
169
+
170
+ ### anyhow (Application Errors)
171
+
172
+ ```rust
173
+ // anyhow — for application code (quick error propagation)
174
+ use anyhow::{Context, Result, bail, ensure};
175
+
176
+ fn load_config(path: &str) -> Result<Config> {
177
+ let content = fs::read_to_string(path)
178
+ .context(format!("Failed to read config from {path}"))?;
179
+
180
+ let config: Config = serde_json::from_str(&content)
181
+ .context("Invalid JSON in config file")?;
182
+
183
+ ensure!(config.port > 0, "Port must be positive, got {}", config.port);
184
+
185
+ if config.name.is_empty() {
186
+ bail!("Config name cannot be empty");
187
+ }
188
+
189
+ Ok(config)
190
+ }
191
+
192
+ // Use thiserror for libraries, anyhow for applications
193
+ // ❌ HALLUCINATION TRAP: Don't use anyhow in library crates
194
+ // Libraries should expose structured error types (thiserror)
195
+ // anyhow erases type information — callers can't match on specific errors
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Traits
201
+
202
+ ### Defining & Implementing
203
+
204
+ ```rust
205
+ trait Summarizable {
206
+ fn summary(&self) -> String;
207
+
208
+ // Default implementation
209
+ fn preview(&self) -> String {
210
+ let s = self.summary();
211
+ if s.len() > 50 {
212
+ format!("{}...", &s[..50])
213
+ } else {
214
+ s
215
+ }
216
+ }
217
+ }
218
+
219
+ struct Article {
220
+ title: String,
221
+ body: String,
222
+ author: String,
223
+ }
224
+
225
+ impl Summarizable for Article {
226
+ fn summary(&self) -> String {
227
+ format!("{} by {} — {}", self.title, self.author, &self.body[..100.min(self.body.len())])
228
+ }
229
+ }
230
+
231
+ // Trait bounds
232
+ fn notify(item: &impl Summarizable) {
233
+ println!("Breaking: {}", item.summary());
234
+ }
235
+
236
+ // Equivalent with generics (more flexible)
237
+ fn notify_generic<T: Summarizable + std::fmt::Display>(item: &T) {
238
+ println!("Breaking: {}", item.summary());
239
+ }
240
+
241
+ // where clause (cleaner for complex bounds)
242
+ fn process<T, U>(t: &T, u: &U) -> String
243
+ where
244
+ T: Summarizable + Clone,
245
+ U: std::fmt::Debug + Send,
246
+ {
247
+ format!("{} — {:?}", t.summary(), u)
248
+ }
249
+
250
+ // Return impl Trait (hide concrete type)
251
+ fn make_summarizer() -> impl Summarizable {
252
+ Article { title: "News".into(), body: "Content".into(), author: "Author".into() }
253
+ }
254
+ ```
255
+
256
+ ### Common Standard Traits
257
+
258
+ ```rust
259
+ // Derive common traits
260
+ #[derive(Debug, Clone, PartialEq, Eq, Hash)]
261
+ struct Point {
262
+ x: i32,
263
+ y: i32,
264
+ }
265
+
266
+ // Display — for user-facing output
267
+ use std::fmt;
268
+ impl fmt::Display for Point {
269
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270
+ write!(f, "({}, {})", self.x, self.y)
271
+ }
272
+ }
273
+
274
+ // From/Into — type conversion
275
+ impl From<(i32, i32)> for Point {
276
+ fn from((x, y): (i32, i32)) -> Self {
277
+ Point { x, y }
278
+ }
279
+ }
280
+ let p: Point = (10, 20).into(); // uses From automatically
281
+
282
+ // Iterator
283
+ struct Counter { count: u32, max: u32 }
284
+ impl Iterator for Counter {
285
+ type Item = u32;
286
+ fn next(&mut self) -> Option<Self::Item> {
287
+ if self.count < self.max {
288
+ self.count += 1;
289
+ Some(self.count)
290
+ } else {
291
+ None
292
+ }
293
+ }
294
+ }
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Async with Tokio
300
+
301
+ ### Runtime Setup
302
+
303
+ ```rust
304
+ // Cargo.toml
305
+ // [dependencies]
306
+ // tokio = { version = "1", features = ["full"] }
307
+
308
+ #[tokio::main]
309
+ async fn main() {
310
+ let result = fetch_data("https://api.example.com/data").await;
311
+ println!("{result:?}");
312
+ }
313
+
314
+ // For library code — don't use #[tokio::main], let the caller choose the runtime
315
+ pub async fn fetch_data(url: &str) -> Result<String> {
316
+ let response = reqwest::get(url).await?;
317
+ let body = response.text().await?;
318
+ Ok(body)
319
+ }
320
+ ```
321
+
322
+ ### Concurrent Tasks
323
+
324
+ ```rust
325
+ use tokio::task;
326
+
327
+ // Spawn concurrent tasks
328
+ async fn parallel_fetch() -> Result<(Users, Posts)> {
329
+ let users_handle = task::spawn(async { fetch_users().await });
330
+ let posts_handle = task::spawn(async { fetch_posts().await });
331
+
332
+ let users = users_handle.await??; // first ? for JoinError, second for app error
333
+ let posts = posts_handle.await??;
334
+
335
+ Ok((users, posts))
336
+ }
337
+
338
+ // tokio::join! — run concurrently, wait for all
339
+ async fn fetch_all() -> Result<(Users, Posts, Analytics)> {
340
+ let (users, posts, analytics) = tokio::join!(
341
+ fetch_users(),
342
+ fetch_posts(),
343
+ fetch_analytics(),
344
+ );
345
+ Ok((users?, posts?, analytics?))
346
+ }
347
+
348
+ // tokio::select! — race multiple futures, take first to complete
349
+ async fn fetch_with_timeout(url: &str) -> Result<String> {
350
+ tokio::select! {
351
+ result = fetch_data(url) => result,
352
+ _ = tokio::time::sleep(Duration::from_secs(5)) => {
353
+ Err(anyhow!("Request timed out after 5s"))
354
+ }
355
+ }
356
+ }
357
+
358
+ // ❌ HALLUCINATION TRAP: tokio::spawn requires 'static + Send
359
+ // You cannot spawn a task referencing local variables without Arc/clone
360
+ // ❌ let data = &local_data;
361
+ // tokio::spawn(async { process(data) }); // ❌ data doesn't live long enough
362
+ // ✅ let data = Arc::new(local_data);
363
+ // let data_clone = Arc::clone(&data);
364
+ // tokio::spawn(async move { process(&data_clone) });
365
+ ```
366
+
367
+ ### Channels
368
+
369
+ ```rust
370
+ use tokio::sync::{mpsc, oneshot, broadcast};
371
+
372
+ // mpsc — Multiple Producer, Single Consumer
373
+ async fn worker_pattern() {
374
+ let (tx, mut rx) = mpsc::channel::<String>(32); // buffer size
375
+
376
+ tokio::spawn(async move {
377
+ tx.send("hello".to_string()).await.unwrap();
378
+ tx.send("world".to_string()).await.unwrap();
379
+ });
380
+
381
+ while let Some(msg) = rx.recv().await {
382
+ println!("Got: {msg}");
383
+ }
384
+ }
385
+
386
+ // oneshot — single response (request/response pattern)
387
+ async fn request_response() {
388
+ let (tx, rx) = oneshot::channel::<String>();
389
+
390
+ tokio::spawn(async move {
391
+ let result = expensive_computation().await;
392
+ tx.send(result).unwrap();
393
+ });
394
+
395
+ let response = rx.await.unwrap();
396
+ }
397
+
398
+ // Mutex (async-safe)
399
+ use tokio::sync::Mutex;
400
+ let shared_state = Arc::new(Mutex::new(Vec::new()));
401
+
402
+ let state = Arc::clone(&shared_state);
403
+ tokio::spawn(async move {
404
+ let mut guard = state.lock().await;
405
+ guard.push("item");
406
+ }); // lock released when guard is dropped
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Axum Web Framework
412
+
413
+ ### Basic Server
414
+
415
+ ```rust
416
+ use axum::{
417
+ extract::{Path, Query, State, Json},
418
+ http::StatusCode,
419
+ response::IntoResponse,
420
+ routing::{get, post, delete},
421
+ Router,
422
+ };
423
+ use serde::{Deserialize, Serialize};
424
+
425
+ #[derive(Clone)]
426
+ struct AppState {
427
+ db: sqlx::PgPool,
428
+ }
429
+
430
+ #[tokio::main]
431
+ async fn main() {
432
+ let pool = sqlx::PgPool::connect("postgres://localhost/mydb").await.unwrap();
433
+ let state = AppState { db: pool };
434
+
435
+ let app = Router::new()
436
+ .route("/users", get(list_users).post(create_user))
437
+ .route("/users/{id}", get(get_user).delete(delete_user))
438
+ .with_state(state);
439
+
440
+ let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
441
+ axum::serve(listener, app).await.unwrap();
442
+ }
443
+
444
+ // ❌ HALLUCINATION TRAP: axum 0.7+ uses {id} not :id for path params
445
+ // ❌ .route("/users/:id", ...) ← old syntax
446
+ // ✅ .route("/users/{id}", ...) ← axum 0.7+
447
+ ```
448
+
449
+ ### Handlers
450
+
451
+ ```rust
452
+ #[derive(Deserialize)]
453
+ struct ListParams {
454
+ page: Option<u32>,
455
+ limit: Option<u32>,
456
+ }
457
+
458
+ async fn list_users(
459
+ State(state): State<AppState>,
460
+ Query(params): Query<ListParams>,
461
+ ) -> Result<Json<Vec<User>>, AppError> {
462
+ let page = params.page.unwrap_or(1);
463
+ let limit = params.limit.unwrap_or(20).min(100);
464
+ let offset = (page - 1) * limit;
465
+
466
+ let users = sqlx::query_as!(
467
+ User,
468
+ "SELECT id, name, email FROM users ORDER BY id LIMIT $1 OFFSET $2",
469
+ limit as i64,
470
+ offset as i64,
471
+ )
472
+ .fetch_all(&state.db)
473
+ .await?;
474
+
475
+ Ok(Json(users))
476
+ }
477
+
478
+ #[derive(Deserialize)]
479
+ struct CreateUserPayload {
480
+ name: String,
481
+ email: String,
482
+ }
483
+
484
+ async fn create_user(
485
+ State(state): State<AppState>,
486
+ Json(payload): Json<CreateUserPayload>,
487
+ ) -> Result<(StatusCode, Json<User>), AppError> {
488
+ let user = sqlx::query_as!(
489
+ User,
490
+ "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email",
491
+ payload.name,
492
+ payload.email,
493
+ )
494
+ .fetch_one(&state.db)
495
+ .await?;
496
+
497
+ Ok((StatusCode::CREATED, Json(user)))
498
+ }
499
+
500
+ async fn get_user(
501
+ State(state): State<AppState>,
502
+ Path(id): Path<i32>,
503
+ ) -> Result<Json<User>, AppError> {
504
+ let user = sqlx::query_as!(User, "SELECT id, name, email FROM users WHERE id = $1", id)
505
+ .fetch_optional(&state.db)
506
+ .await?
507
+ .ok_or(AppError::NotFound(format!("User {id}")))?;
508
+
509
+ Ok(Json(user))
510
+ }
511
+ ```
512
+
513
+ ### Error Handling in Axum
514
+
515
+ ```rust
516
+ use axum::response::{IntoResponse, Response};
517
+
518
+ #[derive(Debug, thiserror::Error)]
519
+ pub enum AppError {
520
+ #[error("Not found: {0}")]
521
+ NotFound(String),
522
+ #[error("Validation: {0}")]
523
+ Validation(String),
524
+ #[error("Database: {0}")]
525
+ Database(#[from] sqlx::Error),
526
+ #[error("Internal: {0}")]
527
+ Internal(#[from] anyhow::Error),
528
+ }
529
+
530
+ impl IntoResponse for AppError {
531
+ fn into_response(self) -> Response {
532
+ let (status, message) = match &self {
533
+ AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
534
+ AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
535
+ AppError::Database(e) => {
536
+ tracing::error!("DB error: {e}"); // log internal details
537
+ (StatusCode::INTERNAL_SERVER_ERROR, "Database error".to_string())
538
+ }
539
+ AppError::Internal(e) => {
540
+ tracing::error!("Internal error: {e}");
541
+ (StatusCode::INTERNAL_SERVER_ERROR, "Internal error".to_string())
542
+ }
543
+ };
544
+
545
+ (status, Json(serde_json::json!({ "error": message }))).into_response()
546
+ }
547
+ }
548
+ ```
549
+
550
+ ---
551
+
552
+ ## Serde (Serialization)
553
+
554
+ ```rust
555
+ use serde::{Deserialize, Serialize};
556
+
557
+ #[derive(Debug, Serialize, Deserialize)]
558
+ #[serde(rename_all = "camelCase")] // JSON uses camelCase
559
+ struct UserResponse {
560
+ user_id: i32, // serialized as "userId"
561
+ full_name: String, // serialized as "fullName"
562
+ email: String,
563
+
564
+ #[serde(skip_serializing_if = "Option::is_none")]
565
+ phone: Option<String>, // omitted from JSON if None
566
+
567
+ #[serde(default)] // defaults to 0 if missing in input
568
+ login_count: u32,
569
+
570
+ #[serde(rename = "type")] // rename for reserved keywords
571
+ user_type: String,
572
+
573
+ #[serde(skip)] // never serialized/deserialized
574
+ internal_token: String,
575
+ }
576
+
577
+ // Enum serialization
578
+ #[derive(Serialize, Deserialize)]
579
+ #[serde(tag = "type", content = "data")] // adjacently tagged
580
+ enum Event {
581
+ #[serde(rename = "user_created")]
582
+ UserCreated { id: i32, name: String },
583
+ #[serde(rename = "user_deleted")]
584
+ UserDeleted { id: i32 },
585
+ }
586
+ // Serializes as: {"type": "user_created", "data": {"id": 1, "name": "Alice"}}
587
+ ```
588
+
589
+ ---
590
+
591
+ ## Iterator Patterns
592
+
593
+ ```rust
594
+ let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
595
+
596
+ // Chain operations (lazy — no allocation until collect)
597
+ let result: Vec<i32> = numbers.iter()
598
+ .filter(|&&n| n % 2 == 0) // keep even
599
+ .map(|&n| n * n) // square
600
+ .take(3) // first 3
601
+ .collect(); // [4, 16, 36]
602
+
603
+ // fold (reduce)
604
+ let sum: i32 = numbers.iter().fold(0, |acc, &n| acc + n);
605
+
606
+ // find / position
607
+ let first_even = numbers.iter().find(|&&n| n % 2 == 0); // Some(&2)
608
+ let pos = numbers.iter().position(|&n| n > 5); // Some(5)
609
+
610
+ // chunk / window
611
+ let chunks: Vec<&[i32]> = numbers.chunks(3).collect();
612
+ // [[1,2,3], [4,5,6], [7,8,9], [10]]
613
+
614
+ let windows: Vec<&[i32]> = numbers.windows(3).collect();
615
+ // [[1,2,3], [2,3,4], [3,4,5], ...]
616
+
617
+ // Collecting into HashMap
618
+ use std::collections::HashMap;
619
+ let word_counts: HashMap<&str, usize> = words.iter()
620
+ .fold(HashMap::new(), |mut map, word| {
621
+ *map.entry(word.as_str()).or_insert(0) += 1;
622
+ map
623
+ });
624
+ ```
625
+
626
+ ---
627
+
628
+ AI coding assistants often fall into specific bad habits when dealing with this domain. These are strictly forbidden:
629
+
630
+ 1. **Over-engineering:** Proposing complex abstractions or distributed systems when a simpler approach suffices.
631
+ 2. **Hallucinated Libraries/Methods:** Using non-existent methods or packages. Always `// VERIFY` or check `package.json` / `requirements.txt`.
632
+ 3. **Skipping Edge Cases:** Writing the "happy path" and ignoring error handling, timeouts, or data validation.
633
+ 4. **Context Amnesia:** Forgetting the user's constraints and offering generic advice instead of tailored solutions.
634
+ 5. **Silent Degradation:** Catching and suppressing errors without logging or re-raising.
635
+
636
+ ---
637
+
638
+ **Slash command: `/review` or `/tribunal-full`**
639
+ **Active reviewers: `logic-reviewer` · `security-auditor`**
640
+
641
+ ### ❌ Forbidden AI Tropes
642
+
643
+ 1. **Blind Assumptions:** Never make an assumption without documenting it clearly with `// VERIFY: [reason]`.
644
+ 2. **Silent Degradation:** Catching and suppressing errors without logging or handling.
645
+ 3. **Context Amnesia:** Forgetting the user's constraints and offering generic advice instead of tailored solutions.
646
+
647
+ Review these questions before confirming output:
648
+
649
+ ```
650
+ ✅ Did I rely ONLY on real, verified tools and methods?
651
+ ✅ Is this solution appropriately scoped to the user's constraints?
652
+ ✅ Did I handle potential failure modes and edge cases?
653
+ ✅ Have I avoided generic boilerplate that doesn't add value?
654
+ ```
655
+
656
+ ### 🛑 Verification-Before-Completion (VBC) Protocol
657
+
658
+ **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
659
+
660
+ - ❌ **Forbidden:** Declaring a task complete because the output "looks correct."
661
+ - ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.
662
+
663
+ ## Pre-Flight Checklist
664
+
665
+ - [ ] Have I reviewed the user's specific constraints and requests?
666
+ - [ ] Have I checked the environment for relevant existing implementations?
667
+
668
+ ## VBC Protocol (Verification-Before-Completion)
669
+
670
+ You MUST verify existing code signatures and variables before attempting to modify or call them. No hallucination is permitted.
675
671
 
676
672
  ---
677
673
 
@@ -701,6 +697,7 @@ AI coding assistants often fall into specific bad habits when dealing with this
701
697
  ### ✅ Pre-Flight Self-Audit
702
698
 
703
699
  Review these questions before confirming output:
700
+
704
701
  ```
705
702
  ✅ Did I rely ONLY on real, verified tools and methods?
706
703
  ✅ Is this solution appropriately scoped to the user's constraints?
@@ -711,5 +708,6 @@ Review these questions before confirming output:
711
708
  ### 🛑 Verification-Before-Completion (VBC) Protocol
712
709
 
713
710
  **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
711
+
714
712
  - ❌ **Forbidden:** Declaring a task complete because the output "looks correct."
715
713
  - ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.