tribunal-kit 4.5.0 → 4.6.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.
Files changed (217) hide show
  1. package/.agent/.shared/ui-ux-pro-max/README.md +4 -4
  2. package/.agent/ARCHITECTURE.md +279 -277
  3. package/.agent/GEMINI.md +127 -121
  4. package/.agent/agents/accessibility-reviewer.md +187 -187
  5. package/.agent/agents/ai-code-reviewer.md +199 -199
  6. package/.agent/agents/api-architect.md +71 -66
  7. package/.agent/agents/backend-specialist.md +219 -215
  8. package/.agent/agents/cloud-engineer.md +98 -0
  9. package/.agent/agents/code-archaeologist.md +168 -161
  10. package/.agent/agents/database-architect.md +184 -184
  11. package/.agent/agents/db-latency-auditor.md +213 -216
  12. package/.agent/agents/debugger.md +198 -191
  13. package/.agent/agents/dependency-reviewer.md +106 -103
  14. package/.agent/agents/devops-engineer.md +218 -218
  15. package/.agent/agents/documentation-writer.md +209 -201
  16. package/.agent/agents/explorer-agent.md +167 -160
  17. package/.agent/agents/frontend-reviewer.md +162 -160
  18. package/.agent/agents/frontend-specialist.md +257 -248
  19. package/.agent/agents/game-developer.md +48 -48
  20. package/.agent/agents/logic-reviewer.md +118 -116
  21. package/.agent/agents/mobile-developer.md +197 -200
  22. package/.agent/agents/mobile-reviewer.md +159 -162
  23. package/.agent/agents/orchestrator.md +187 -181
  24. package/.agent/agents/penetration-tester.md +160 -157
  25. package/.agent/agents/performance-optimizer.md +183 -183
  26. package/.agent/agents/performance-reviewer.md +178 -178
  27. package/.agent/agents/precedence-reviewer.md +251 -250
  28. package/.agent/agents/product-manager.md +149 -142
  29. package/.agent/agents/product-owner.md +81 -80
  30. package/.agent/agents/project-planner.md +152 -142
  31. package/.agent/agents/qa-automation-engineer.md +216 -225
  32. package/.agent/agents/resilience-reviewer.md +88 -88
  33. package/.agent/agents/schema-reviewer.md +67 -67
  34. package/.agent/agents/security-auditor.md +180 -174
  35. package/.agent/agents/seo-specialist.md +188 -193
  36. package/.agent/agents/sql-reviewer.md +159 -161
  37. package/.agent/agents/supervisor-agent.md +173 -184
  38. package/.agent/agents/swarm-worker-contracts.md +170 -166
  39. package/.agent/agents/swarm-worker-registry.md +92 -92
  40. package/.agent/agents/system-architect.md +85 -0
  41. package/.agent/agents/test-coverage-reviewer.md +158 -160
  42. package/.agent/agents/test-engineer.md +118 -118
  43. package/.agent/agents/throughput-optimizer.md +291 -299
  44. package/.agent/agents/type-safety-reviewer.md +182 -175
  45. package/.agent/agents/ui-ux-auditor.md +300 -292
  46. package/.agent/agents/vitals-reviewer.md +223 -223
  47. package/.agent/mcp_config.json +37 -40
  48. package/.agent/patterns/generator.md +11 -9
  49. package/.agent/patterns/inversion.md +14 -12
  50. package/.agent/patterns/pipeline.md +11 -9
  51. package/.agent/patterns/reviewer.md +15 -13
  52. package/.agent/patterns/tool-wrapper.md +11 -9
  53. package/.agent/routing_index.json +654 -0
  54. package/.agent/rules/GEMINI.md +358 -352
  55. package/.agent/scripts/compile_router.py +112 -0
  56. package/.agent/scripts/migrate_skills_frontmatter.py +64 -0
  57. package/.agent/scripts/strengthen_skills.js +1 -1
  58. package/.agent/skills/advanced-rag-pipelines/SKILL.md +56 -0
  59. package/.agent/skills/agent-organizer/SKILL.md +156 -150
  60. package/.agent/skills/agentic-patterns/SKILL.md +313 -315
  61. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +190 -184
  62. package/.agent/skills/api-patterns/SKILL.md +253 -247
  63. package/.agent/skills/api-security-auditor/SKILL.md +195 -193
  64. package/.agent/skills/app-builder/SKILL.md +573 -572
  65. package/.agent/skills/app-builder/templates/SKILL.md +108 -115
  66. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -76
  67. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -92
  68. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -88
  69. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -88
  70. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -83
  71. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -90
  72. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -90
  73. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +126 -122
  74. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +127 -122
  75. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +172 -169
  76. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +139 -134
  77. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -83
  78. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +122 -119
  79. package/.agent/skills/appflow-wireframe/SKILL.md +146 -145
  80. package/.agent/skills/architecture/SKILL.md +226 -219
  81. package/.agent/skills/authentication-best-practices/SKILL.md +197 -189
  82. package/.agent/skills/backend-security-expert/SKILL.md +16 -2
  83. package/.agent/skills/bash-linux/SKILL.md +179 -179
  84. package/.agent/skills/behavioral-modes/SKILL.md +239 -223
  85. package/.agent/skills/brainstorming/SKILL.md +498 -486
  86. package/.agent/skills/browser-native-ai/SKILL.md +57 -4
  87. package/.agent/skills/building-native-ui/SKILL.md +202 -202
  88. package/.agent/skills/cicd-pro/SKILL.md +442 -0
  89. package/.agent/skills/clean-code/SKILL.md +400 -381
  90. package/.agent/skills/cloud-architect/SKILL.md +439 -0
  91. package/.agent/skills/code-review-checklist/SKILL.md +203 -194
  92. package/.agent/skills/config-validator/SKILL.md +165 -165
  93. package/.agent/skills/containerization-pro/SKILL.md +452 -0
  94. package/.agent/skills/csharp-developer/SKILL.md +518 -518
  95. package/.agent/skills/data-validation-schemas/SKILL.md +333 -328
  96. package/.agent/skills/database-design/SKILL.md +247 -240
  97. package/.agent/skills/deployment-procedures/SKILL.md +172 -169
  98. package/.agent/skills/devops-engineer/SKILL.md +345 -345
  99. package/.agent/skills/devops-incident-responder/SKILL.md +143 -137
  100. package/.agent/skills/doc.md +209 -177
  101. package/.agent/skills/documentation-templates/SKILL.md +291 -279
  102. package/.agent/skills/edge-computing/SKILL.md +183 -181
  103. package/.agent/skills/error-resilience/SKILL.md +411 -428
  104. package/.agent/skills/extract-design-system/SKILL.md +160 -158
  105. package/.agent/skills/framer-motion-expert/SKILL.md +253 -244
  106. package/.agent/skills/frontend-design/SKILL.md +208 -201
  107. package/.agent/skills/frontend-security-expert/SKILL.md +16 -3
  108. package/.agent/skills/game-design-expert/SKILL.md +132 -129
  109. package/.agent/skills/game-engineering-expert/SKILL.md +148 -146
  110. package/.agent/skills/generative-ui-expert/SKILL.md +57 -1
  111. package/.agent/skills/geo-fundamentals/SKILL.md +148 -147
  112. package/.agent/skills/git-pro/SKILL.md +435 -0
  113. package/.agent/skills/github-operations/SKILL.md +335 -329
  114. package/.agent/skills/gsap-core/SKILL.md +319 -308
  115. package/.agent/skills/gsap-frameworks/SKILL.md +213 -207
  116. package/.agent/skills/gsap-performance/SKILL.md +139 -133
  117. package/.agent/skills/gsap-plugins/SKILL.md +486 -480
  118. package/.agent/skills/gsap-react/SKILL.md +202 -189
  119. package/.agent/skills/gsap-scrolltrigger/SKILL.md +357 -350
  120. package/.agent/skills/gsap-timeline/SKILL.md +165 -161
  121. package/.agent/skills/gsap-utils/SKILL.md +344 -338
  122. package/.agent/skills/harness-protocol/SKILL.md +48 -0
  123. package/.agent/skills/i18n-localization/SKILL.md +174 -163
  124. package/.agent/skills/intelligent-routing/SKILL.md +202 -246
  125. package/.agent/skills/knowledge-graph/SKILL.md +60 -52
  126. package/.agent/skills/lint-and-validate/SKILL.md +261 -261
  127. package/.agent/skills/llm-engineering/SKILL.md +400 -394
  128. package/.agent/skills/local-first/SKILL.md +178 -178
  129. package/.agent/skills/mcp-builder/SKILL.md +143 -142
  130. package/.agent/skills/mobile-design/SKILL.md +272 -263
  131. package/.agent/skills/monorepo-management/SKILL.md +335 -334
  132. package/.agent/skills/motion-engineering/SKILL.md +266 -234
  133. package/.agent/skills/nextjs-react-expert/SKILL.md +236 -234
  134. package/.agent/skills/nodejs-best-practices/SKILL.md +547 -548
  135. package/.agent/skills/observability/SKILL.md +343 -343
  136. package/.agent/skills/parallel-agents/SKILL.md +143 -146
  137. package/.agent/skills/performance-profiling/SKILL.md +259 -267
  138. package/.agent/skills/plan-writing/SKILL.md +150 -142
  139. package/.agent/skills/platform-engineer/SKILL.md +148 -147
  140. package/.agent/skills/playwright-best-practices/SKILL.md +188 -187
  141. package/.agent/skills/powershell-windows/SKILL.md +162 -162
  142. package/.agent/skills/project-idioms/SKILL.md +137 -137
  143. package/.agent/skills/python-patterns/SKILL.md +260 -259
  144. package/.agent/skills/python-pro/SKILL.md +324 -323
  145. package/.agent/skills/react-specialist/SKILL.md +305 -277
  146. package/.agent/skills/readme-builder/SKILL.md +310 -300
  147. package/.agent/skills/realtime-patterns/SKILL.md +323 -319
  148. package/.agent/skills/red-team-tactics/SKILL.md +231 -218
  149. package/.agent/skills/rust-pro/SKILL.md +671 -673
  150. package/.agent/skills/seo-fundamentals/SKILL.md +179 -179
  151. package/.agent/skills/server-management/SKILL.md +218 -214
  152. package/.agent/skills/shadcn-ui-expert/SKILL.md +231 -231
  153. package/.agent/skills/skill-creator/SKILL.md +87 -86
  154. package/.agent/skills/sql-pro/SKILL.md +629 -629
  155. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +97 -97
  156. package/.agent/skills/swiftui-expert/SKILL.md +204 -201
  157. package/.agent/skills/system-design-pro/SKILL.md +345 -0
  158. package/.agent/skills/systematic-debugging/SKILL.md +153 -142
  159. package/.agent/skills/tailwind-patterns/SKILL.md +610 -566
  160. package/.agent/skills/tdd-workflow/SKILL.md +169 -161
  161. package/.agent/skills/test-result-analyzer/SKILL.md +313 -309
  162. package/.agent/skills/testing-patterns/SKILL.md +566 -579
  163. package/.agent/skills/trend-researcher/SKILL.md +243 -237
  164. package/.agent/skills/typescript-advanced/SKILL.md +336 -335
  165. package/.agent/skills/ui-ux-pro-max/SKILL.md +590 -562
  166. package/.agent/skills/ui-ux-researcher/SKILL.md +244 -244
  167. package/.agent/skills/vue-expert/SKILL.md +294 -275
  168. package/.agent/skills/vulnerability-scanner/SKILL.md +416 -404
  169. package/.agent/skills/web-accessibility-auditor/SKILL.md +219 -218
  170. package/.agent/skills/web-design-guidelines/SKILL.md +192 -186
  171. package/.agent/skills/webapp-testing/SKILL.md +167 -169
  172. package/.agent/skills/webgpu-performance/SKILL.md +56 -2
  173. package/.agent/skills/whimsy-injector/SKILL.md +346 -325
  174. package/.agent/skills/workflow-optimizer/SKILL.md +231 -229
  175. package/.agent/workflows/acf.md +141 -0
  176. package/.agent/workflows/api-tester.md +176 -151
  177. package/.agent/workflows/audit.md +150 -127
  178. package/.agent/workflows/brainstorm.md +134 -110
  179. package/.agent/workflows/changelog.md +140 -112
  180. package/.agent/workflows/create.md +168 -124
  181. package/.agent/workflows/debug.md +190 -165
  182. package/.agent/workflows/deploy.md +201 -180
  183. package/.agent/workflows/enhance.md +154 -128
  184. package/.agent/workflows/fix.md +136 -114
  185. package/.agent/workflows/generate.md +198 -183
  186. package/.agent/workflows/marathon.md +37 -11
  187. package/.agent/workflows/migrate.md +184 -160
  188. package/.agent/workflows/orchestrate.md +192 -168
  189. package/.agent/workflows/performance-benchmarker.md +135 -114
  190. package/.agent/workflows/plan.md +196 -173
  191. package/.agent/workflows/preview.md +103 -80
  192. package/.agent/workflows/refactor.md +192 -161
  193. package/.agent/workflows/review-ai.md +125 -101
  194. package/.agent/workflows/review.md +141 -116
  195. package/.agent/workflows/session.md +122 -94
  196. package/.agent/workflows/status.md +101 -79
  197. package/.agent/workflows/strengthen-skills.md +164 -138
  198. package/.agent/workflows/super-prompt.md +24 -0
  199. package/.agent/workflows/swarm.md +193 -179
  200. package/.agent/workflows/test.md +211 -189
  201. package/.agent/workflows/tribunal-backend.md +136 -105
  202. package/.agent/workflows/tribunal-database.md +122 -95
  203. package/.agent/workflows/tribunal-frontend.md +221 -96
  204. package/.agent/workflows/tribunal-full.md +129 -100
  205. package/.agent/workflows/tribunal-mobile.md +122 -95
  206. package/.agent/workflows/tribunal-performance.md +136 -110
  207. package/.agent/workflows/tribunal-speed.md +209 -183
  208. package/.agent/workflows/ui-ux-pro-max.md +145 -122
  209. package/README.md +107 -55
  210. package/bin/mcp-server.js +159 -0
  211. package/bin/tribunal-kit.js +105 -29
  212. package/bin/wrapper.js +16 -7
  213. package/mcp_config.json +9 -0
  214. package/package.json +94 -86
  215. package/scripts/changelog.js +4 -3
  216. package/scripts/validate-payload.js +6 -1
  217. package/scripts/postinstall.js +0 -127
@@ -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.