devflow-kit 1.1.0 → 1.3.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 (152) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/README.md +23 -6
  3. package/dist/cli.js +2 -0
  4. package/dist/commands/ambient.js +5 -4
  5. package/dist/commands/init.js +4 -2
  6. package/dist/commands/memory.js +4 -4
  7. package/dist/commands/skills.d.ts +11 -0
  8. package/dist/commands/skills.js +116 -0
  9. package/dist/commands/uninstall.js +11 -1
  10. package/dist/plugins.js +67 -3
  11. package/dist/utils/installer.js +20 -2
  12. package/package.json +4 -2
  13. package/plugins/devflow-accessibility/.claude-plugin/plugin.json +22 -0
  14. package/plugins/devflow-ambient/.claude-plugin/plugin.json +4 -2
  15. package/plugins/devflow-ambient/README.md +8 -8
  16. package/plugins/devflow-ambient/commands/ambient.md +14 -14
  17. package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +16 -9
  18. package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +6 -2
  19. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
  20. package/plugins/devflow-code-review/.claude-plugin/plugin.json +13 -6
  21. package/plugins/devflow-code-review/agents/reviewer.md +8 -0
  22. package/plugins/devflow-code-review/commands/code-review-teams.md +11 -1
  23. package/plugins/devflow-code-review/commands/code-review.md +12 -2
  24. package/plugins/devflow-code-review/skills/architecture-patterns/SKILL.md +1 -1
  25. package/plugins/devflow-code-review/skills/complexity-patterns/SKILL.md +1 -1
  26. package/plugins/devflow-code-review/skills/consistency-patterns/SKILL.md +1 -1
  27. package/plugins/devflow-code-review/skills/database-patterns/SKILL.md +1 -1
  28. package/plugins/devflow-code-review/skills/dependencies-patterns/SKILL.md +1 -1
  29. package/plugins/devflow-code-review/skills/documentation-patterns/SKILL.md +1 -1
  30. package/plugins/devflow-code-review/skills/performance-patterns/SKILL.md +1 -1
  31. package/plugins/devflow-code-review/skills/regression-patterns/SKILL.md +1 -1
  32. package/plugins/devflow-code-review/skills/review-methodology/SKILL.md +1 -1
  33. package/plugins/devflow-code-review/skills/security-patterns/SKILL.md +1 -1
  34. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +10 -7
  35. package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +5 -8
  36. package/plugins/devflow-debug/.claude-plugin/plugin.json +10 -3
  37. package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +22 -0
  38. package/plugins/devflow-go/.claude-plugin/plugin.json +22 -0
  39. package/plugins/devflow-go/skills/go/SKILL.md +187 -0
  40. package/plugins/devflow-go/skills/go/references/concurrency.md +312 -0
  41. package/plugins/devflow-go/skills/go/references/detection.md +129 -0
  42. package/plugins/devflow-go/skills/go/references/patterns.md +232 -0
  43. package/plugins/devflow-go/skills/go/references/violations.md +205 -0
  44. package/plugins/devflow-implement/.claude-plugin/plugin.json +19 -5
  45. package/plugins/devflow-implement/agents/coder.md +11 -6
  46. package/plugins/devflow-implement/skills/self-review/SKILL.md +1 -1
  47. package/plugins/devflow-java/.claude-plugin/plugin.json +22 -0
  48. package/plugins/devflow-java/skills/java/SKILL.md +183 -0
  49. package/plugins/devflow-java/skills/java/references/detection.md +120 -0
  50. package/plugins/devflow-java/skills/java/references/modern-java.md +270 -0
  51. package/plugins/devflow-java/skills/java/references/patterns.md +235 -0
  52. package/plugins/devflow-java/skills/java/references/violations.md +213 -0
  53. package/plugins/devflow-python/.claude-plugin/plugin.json +22 -0
  54. package/plugins/devflow-python/skills/python/SKILL.md +188 -0
  55. package/plugins/devflow-python/skills/python/references/async.md +220 -0
  56. package/plugins/devflow-python/skills/python/references/detection.md +128 -0
  57. package/plugins/devflow-python/skills/python/references/patterns.md +226 -0
  58. package/plugins/devflow-python/skills/python/references/violations.md +204 -0
  59. package/plugins/devflow-react/.claude-plugin/plugin.json +22 -0
  60. package/plugins/{devflow-core-skills → devflow-react}/skills/react/SKILL.md +1 -1
  61. package/plugins/{devflow-core-skills → devflow-react}/skills/react/references/patterns.md +3 -3
  62. package/plugins/devflow-resolve/.claude-plugin/plugin.json +13 -3
  63. package/plugins/devflow-resolve/skills/security-patterns/SKILL.md +1 -1
  64. package/plugins/devflow-rust/.claude-plugin/plugin.json +22 -0
  65. package/plugins/devflow-rust/skills/rust/SKILL.md +193 -0
  66. package/plugins/devflow-rust/skills/rust/references/detection.md +131 -0
  67. package/plugins/devflow-rust/skills/rust/references/ownership.md +242 -0
  68. package/plugins/devflow-rust/skills/rust/references/patterns.md +210 -0
  69. package/plugins/devflow-rust/skills/rust/references/violations.md +191 -0
  70. package/plugins/devflow-self-review/.claude-plugin/plugin.json +10 -3
  71. package/plugins/devflow-self-review/skills/self-review/SKILL.md +1 -1
  72. package/plugins/devflow-specify/.claude-plugin/plugin.json +15 -4
  73. package/plugins/devflow-typescript/.claude-plugin/plugin.json +22 -0
  74. package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
  75. package/scripts/hooks/{ambient-prompt.sh → ambient-prompt} +4 -4
  76. package/scripts/hooks/{background-memory-update.sh → background-memory-update} +3 -3
  77. package/scripts/hooks/{ensure-memory-gitignore.sh → ensure-memory-gitignore} +1 -1
  78. package/scripts/hooks/{pre-compact-memory.sh → pre-compact-memory} +2 -2
  79. package/scripts/hooks/run-hook +23 -0
  80. package/scripts/hooks/session-start-memory +151 -0
  81. package/scripts/hooks/{stop-update-memory.sh → stop-update-memory} +4 -4
  82. package/shared/agents/coder.md +11 -6
  83. package/shared/agents/reviewer.md +8 -0
  84. package/shared/skills/ambient-router/SKILL.md +16 -9
  85. package/shared/skills/ambient-router/references/skill-catalog.md +6 -2
  86. package/shared/skills/architecture-patterns/SKILL.md +1 -1
  87. package/shared/skills/complexity-patterns/SKILL.md +1 -1
  88. package/shared/skills/consistency-patterns/SKILL.md +1 -1
  89. package/shared/skills/database-patterns/SKILL.md +1 -1
  90. package/shared/skills/dependencies-patterns/SKILL.md +1 -1
  91. package/shared/skills/documentation-patterns/SKILL.md +1 -1
  92. package/shared/skills/go/SKILL.md +187 -0
  93. package/shared/skills/go/references/concurrency.md +312 -0
  94. package/shared/skills/go/references/detection.md +129 -0
  95. package/shared/skills/go/references/patterns.md +232 -0
  96. package/shared/skills/go/references/violations.md +205 -0
  97. package/shared/skills/java/SKILL.md +183 -0
  98. package/shared/skills/java/references/detection.md +120 -0
  99. package/shared/skills/java/references/modern-java.md +270 -0
  100. package/shared/skills/java/references/patterns.md +235 -0
  101. package/shared/skills/java/references/violations.md +213 -0
  102. package/shared/skills/performance-patterns/SKILL.md +1 -1
  103. package/shared/skills/python/SKILL.md +188 -0
  104. package/shared/skills/python/references/async.md +220 -0
  105. package/shared/skills/python/references/detection.md +128 -0
  106. package/shared/skills/python/references/patterns.md +226 -0
  107. package/shared/skills/python/references/violations.md +204 -0
  108. package/shared/skills/react/SKILL.md +1 -1
  109. package/shared/skills/react/references/patterns.md +3 -3
  110. package/shared/skills/regression-patterns/SKILL.md +1 -1
  111. package/shared/skills/review-methodology/SKILL.md +1 -1
  112. package/shared/skills/rust/SKILL.md +193 -0
  113. package/shared/skills/rust/references/detection.md +131 -0
  114. package/shared/skills/rust/references/ownership.md +242 -0
  115. package/shared/skills/rust/references/patterns.md +210 -0
  116. package/shared/skills/rust/references/violations.md +191 -0
  117. package/shared/skills/security-patterns/SKILL.md +1 -1
  118. package/shared/skills/self-review/SKILL.md +1 -1
  119. package/shared/skills/test-driven-development/SKILL.md +5 -8
  120. package/shared/skills/typescript/references/patterns.md +3 -3
  121. package/src/templates/settings.json +3 -3
  122. package/plugins/devflow-code-review/skills/react/SKILL.md +0 -276
  123. package/plugins/devflow-code-review/skills/react/references/patterns.md +0 -1331
  124. package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +0 -229
  125. package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +0 -171
  126. package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +0 -670
  127. package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +0 -419
  128. package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +0 -254
  129. package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +0 -184
  130. package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +0 -511
  131. package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +0 -453
  132. package/plugins/devflow-core-skills/skills/react/references/violations.md +0 -565
  133. package/plugins/devflow-implement/skills/accessibility/SKILL.md +0 -229
  134. package/plugins/devflow-implement/skills/accessibility/references/detection.md +0 -171
  135. package/plugins/devflow-implement/skills/accessibility/references/patterns.md +0 -670
  136. package/plugins/devflow-implement/skills/accessibility/references/violations.md +0 -419
  137. package/plugins/devflow-implement/skills/frontend-design/SKILL.md +0 -254
  138. package/plugins/devflow-implement/skills/frontend-design/references/detection.md +0 -184
  139. package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +0 -511
  140. package/plugins/devflow-implement/skills/frontend-design/references/violations.md +0 -453
  141. package/scripts/hooks/session-start-memory.sh +0 -126
  142. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/SKILL.md +0 -0
  143. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/detection.md +0 -0
  144. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/patterns.md +0 -0
  145. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/violations.md +0 -0
  146. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/SKILL.md +0 -0
  147. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/detection.md +0 -0
  148. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/patterns.md +0 -0
  149. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/violations.md +0 -0
  150. /package/plugins/{devflow-code-review → devflow-react}/skills/react/references/violations.md +0 -0
  151. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/SKILL.md +0 -0
  152. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/violations.md +0 -0
@@ -0,0 +1,242 @@
1
+ # Rust Ownership Deep Dive
2
+
3
+ Advanced ownership patterns, lifetime elision, interior mutability, and pinning.
4
+
5
+ ## Lifetime Elision Rules
6
+
7
+ The compiler applies three rules to infer lifetimes. When they don't resolve, annotate manually.
8
+
9
+ ### Rule 1: Each Reference Parameter Gets Its Own Lifetime
10
+
11
+ ```rust
12
+ // Compiler sees: fn first(s: &str) -> &str
13
+ // Compiler infers: fn first<'a>(s: &'a str) -> &'a str
14
+ fn first(s: &str) -> &str {
15
+ &s[..1]
16
+ }
17
+ ```
18
+
19
+ ### Rule 2: Single Input Lifetime Applies to All Outputs
20
+
21
+ ```rust
22
+ // One input reference — output borrows from it
23
+ fn trim(s: &str) -> &str {
24
+ s.trim()
25
+ }
26
+ ```
27
+
28
+ ### Rule 3: &self Lifetime Applies to All Outputs in Methods
29
+
30
+ ```rust
31
+ impl Config {
32
+ // &self lifetime flows to return
33
+ fn database_url(&self) -> &str {
34
+ &self.db_url
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### When Elision Fails
40
+
41
+ ```rust
42
+ // Two input lifetimes — compiler can't decide which output borrows from
43
+ // Must annotate: output borrows from `a`, not `b`
44
+ fn longest<'a>(a: &'a str, b: &str) -> &'a str {
45
+ if a.len() >= b.len() { a } else { a }
46
+ }
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Interior Mutability
52
+
53
+ Mutate data behind a shared reference when ownership rules are too strict.
54
+
55
+ ### Cell — Copy Types Only
56
+
57
+ ```rust
58
+ use std::cell::Cell;
59
+
60
+ struct Counter {
61
+ count: Cell<u32>, // Mutate through &self
62
+ }
63
+
64
+ impl Counter {
65
+ fn increment(&self) {
66
+ self.count.set(self.count.get() + 1);
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### RefCell — Runtime Borrow Checking
72
+
73
+ ```rust
74
+ use std::cell::RefCell;
75
+
76
+ struct Cache {
77
+ data: RefCell<HashMap<String, String>>,
78
+ }
79
+
80
+ impl Cache {
81
+ fn get_or_insert(&self, key: &str, value: &str) -> String {
82
+ let mut data = self.data.borrow_mut(); // Panics if already borrowed
83
+ data.entry(key.to_string())
84
+ .or_insert_with(|| value.to_string())
85
+ .clone()
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### Mutex — Thread-Safe Interior Mutability
91
+
92
+ ```rust
93
+ use std::sync::Mutex;
94
+
95
+ struct SharedState {
96
+ data: Mutex<Vec<String>>,
97
+ }
98
+
99
+ impl SharedState {
100
+ fn push(&self, item: String) -> Result<(), AppError> {
101
+ let mut data = self.data.lock()
102
+ .map_err(|_| AppError::LockPoisoned)?;
103
+ data.push(item);
104
+ Ok(())
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### Decision Guide
110
+
111
+ | Type | Thread-Safe | Cost | Use Case |
112
+ |------|-------------|------|----------|
113
+ | `Cell<T>` | No | Zero | Copy types, single-threaded |
114
+ | `RefCell<T>` | No | Runtime borrow check | Non-Copy, single-threaded |
115
+ | `Mutex<T>` | Yes | Lock overhead | Multi-threaded mutation |
116
+ | `RwLock<T>` | Yes | Lock overhead | Multi-threaded, read-heavy |
117
+ | `Atomic*` | Yes | Hardware atomic | Counters, flags |
118
+
119
+ ---
120
+
121
+ ## Cow — Clone on Write
122
+
123
+ Defer cloning until mutation is actually needed.
124
+
125
+ ```rust
126
+ use std::borrow::Cow;
127
+
128
+ // Returns borrowed if no processing needed, owned if modified
129
+ fn normalize_path(path: &str) -> Cow<'_, str> {
130
+ if path.contains("//") {
131
+ Cow::Owned(path.replace("//", "/"))
132
+ } else {
133
+ Cow::Borrowed(path)
134
+ }
135
+ }
136
+
137
+ // Function accepts both owned and borrowed transparently
138
+ fn process(input: Cow<'_, str>) {
139
+ println!("{}", input); // No allocation if already borrowed
140
+ }
141
+ ```
142
+
143
+ ### Cow in APIs
144
+
145
+ ```rust
146
+ // Accept Cow for flexible ownership — caller decides allocation
147
+ pub fn log_message(msg: Cow<'_, str>) {
148
+ eprintln!("[LOG] {}", msg);
149
+ }
150
+
151
+ // Caller with borrowed data — zero-copy
152
+ log_message(Cow::Borrowed("static message"));
153
+
154
+ // Caller with owned data — no extra clone
155
+ log_message(Cow::Owned(format!("dynamic: {}", value)));
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Pin for Async and Self-Referential Types
161
+
162
+ ### Why Pin Exists
163
+
164
+ Self-referential structs break if moved in memory. `Pin` guarantees the value won't move.
165
+
166
+ ```rust
167
+ use std::pin::Pin;
168
+ use std::future::Future;
169
+
170
+ // Async functions return self-referential futures
171
+ // Pin ensures the future stays in place while polled
172
+ fn fetch_data(url: &str) -> Pin<Box<dyn Future<Output = Result<Data, Error>> + '_>> {
173
+ Box::pin(async move {
174
+ let response = reqwest::get(url).await?;
175
+ let data = response.json::<Data>().await?;
176
+ Ok(data)
177
+ })
178
+ }
179
+ ```
180
+
181
+ ### Pin in Practice
182
+
183
+ ```rust
184
+ use tokio::pin;
185
+
186
+ async fn process_stream(stream: impl Stream<Item = Data>) {
187
+ // pin! macro pins the stream to the stack
188
+ pin!(stream);
189
+
190
+ while let Some(item) = stream.next().await {
191
+ handle(item).await;
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### When You Need Pin
197
+
198
+ | Scenario | Need Pin? |
199
+ |----------|-----------|
200
+ | Returning `async` blocks as trait objects | Yes |
201
+ | Implementing `Future` manually | Yes |
202
+ | Using `tokio::select!` on futures | Yes (automatically handled) |
203
+ | Normal async/await | No (compiler handles it) |
204
+ | Storing futures in collections | Yes (`Pin<Box<dyn Future>>`) |
205
+
206
+ ---
207
+
208
+ ## Ownership Transfer Patterns
209
+
210
+ ### Take Pattern — Move Out of Option
211
+
212
+ ```rust
213
+ struct Connection {
214
+ session: Option<Session>,
215
+ }
216
+
217
+ impl Connection {
218
+ fn close(&mut self) -> Option<Session> {
219
+ self.session.take() // Moves out, leaves None
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### Swap Pattern — Replace In Place
225
+
226
+ ```rust
227
+ use std::mem;
228
+
229
+ fn rotate_buffer(current: &mut Vec<u8>, new_data: Vec<u8>) -> Vec<u8> {
230
+ mem::replace(current, new_data) // Returns old, installs new
231
+ }
232
+ ```
233
+
234
+ ### Entry Pattern — Conditional Insertion
235
+
236
+ ```rust
237
+ use std::collections::HashMap;
238
+
239
+ fn get_or_create(map: &mut HashMap<String, Vec<Item>>, key: &str) -> &mut Vec<Item> {
240
+ map.entry(key.to_string()).or_insert_with(Vec::new)
241
+ }
242
+ ```
@@ -0,0 +1,210 @@
1
+ # Rust Extended Patterns
2
+
3
+ Extended correct patterns for Rust. Reference from main SKILL.md.
4
+
5
+ ## Typestate Pattern
6
+
7
+ Encode valid state transitions in the type system so invalid sequences don't compile.
8
+
9
+ ```rust
10
+ // States are zero-sized types — no runtime cost
11
+ struct Draft;
12
+ struct Published;
13
+ struct Archived;
14
+
15
+ struct Article<State> {
16
+ title: String,
17
+ body: String,
18
+ _state: std::marker::PhantomData<State>,
19
+ }
20
+
21
+ impl Article<Draft> {
22
+ pub fn new(title: String, body: String) -> Self {
23
+ Article { title, body, _state: std::marker::PhantomData }
24
+ }
25
+
26
+ pub fn publish(self) -> Article<Published> {
27
+ Article { title: self.title, body: self.body, _state: std::marker::PhantomData }
28
+ }
29
+ }
30
+
31
+ impl Article<Published> {
32
+ pub fn archive(self) -> Article<Archived> {
33
+ Article { title: self.title, body: self.body, _state: std::marker::PhantomData }
34
+ }
35
+ }
36
+
37
+ // article.archive() on Draft won't compile — transition enforced at compile time
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Error Handling Hierarchy
43
+
44
+ Layer errors from specific to general using `thiserror` for libraries and `anyhow` for applications.
45
+
46
+ ```rust
47
+ // Library: precise, typed errors
48
+ #[derive(thiserror::Error, Debug)]
49
+ pub enum RepoError {
50
+ #[error("entity {entity} with id {id} not found")]
51
+ NotFound { entity: &'static str, id: String },
52
+ #[error("duplicate key: {0}")]
53
+ Duplicate(String),
54
+ #[error("connection failed")]
55
+ Connection(#[from] sqlx::Error),
56
+ }
57
+
58
+ // Application: ergonomic error propagation
59
+ use anyhow::{Context, Result};
60
+
61
+ fn run() -> Result<()> {
62
+ let config = load_config()
63
+ .context("failed to load configuration")?;
64
+ let db = connect_db(&config.database_url)
65
+ .context("failed to connect to database")?;
66
+ serve(db, config.port)
67
+ .context("server exited with error")
68
+ }
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Trait Objects vs Generics
74
+
75
+ ### Use Generics for Performance (Monomorphization)
76
+
77
+ ```rust
78
+ fn largest<T: PartialOrd>(list: &[T]) -> Option<&T> {
79
+ list.iter().reduce(|a, b| if a >= b { a } else { b })
80
+ }
81
+ ```
82
+
83
+ ### Use Trait Objects for Heterogeneous Collections
84
+
85
+ ```rust
86
+ trait Handler: Send + Sync {
87
+ fn handle(&self, request: &Request) -> Response;
88
+ }
89
+
90
+ struct Router {
91
+ routes: Vec<Box<dyn Handler>>, // Different concrete types in one Vec
92
+ }
93
+ ```
94
+
95
+ ### Decision Guide
96
+
97
+ | Criteria | Generics | Trait Objects |
98
+ |----------|----------|--------------|
99
+ | Known types at compile time | Yes | No |
100
+ | Heterogeneous collection | No | Yes |
101
+ | Performance-critical | Yes | Acceptable overhead |
102
+ | Binary size concern | Increases | Minimal |
103
+
104
+ ---
105
+
106
+ ## Smart Pointers
107
+
108
+ ### Box — Heap Allocation
109
+
110
+ ```rust
111
+ // Recursive types require indirection
112
+ enum List<T> {
113
+ Cons(T, Box<List<T>>),
114
+ Nil,
115
+ }
116
+ ```
117
+
118
+ ### Rc/Arc — Shared Ownership
119
+
120
+ ```rust
121
+ use std::sync::Arc;
122
+
123
+ // Shared read-only config across threads
124
+ let config = Arc::new(load_config()?);
125
+ let config_clone = Arc::clone(&config);
126
+ tokio::spawn(async move {
127
+ use_config(&config_clone).await;
128
+ });
129
+ ```
130
+
131
+ ### When to Use Each
132
+
133
+ | Pointer | Use Case |
134
+ |---------|----------|
135
+ | `Box<T>` | Single owner, heap allocation, recursive types |
136
+ | `Rc<T>` | Multiple owners, single-threaded |
137
+ | `Arc<T>` | Multiple owners, multi-threaded |
138
+ | `Cow<'a, T>` | Clone-on-write, flexible borrowing |
139
+
140
+ ---
141
+
142
+ ## From/Into Conversions
143
+
144
+ ```rust
145
+ // Implement From for automatic Into
146
+ impl From<CreateUserRequest> for User {
147
+ fn from(req: CreateUserRequest) -> Self {
148
+ User {
149
+ id: Uuid::new_v4(),
150
+ name: req.name,
151
+ email: req.email,
152
+ created_at: Utc::now(),
153
+ }
154
+ }
155
+ }
156
+
157
+ // Callers get Into for free
158
+ fn save_user(user: impl Into<User>) -> Result<(), DbError> {
159
+ let user: User = user.into();
160
+ // ...
161
+ Ok(())
162
+ }
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Derive and Trait Best Practices
168
+
169
+ ```rust
170
+ // Derive the standard set for data types
171
+ #[derive(Debug, Clone, PartialEq, Eq, Hash)]
172
+ pub struct UserId(String);
173
+
174
+ // Derive serde for serialization boundaries
175
+ #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
176
+ pub struct ApiResponse<T> {
177
+ pub data: T,
178
+ pub metadata: Metadata,
179
+ }
180
+ ```
181
+
182
+ ### Trait Implementation Order Convention
183
+
184
+ 1. Standard library traits (`Debug`, `Display`, `Clone`, `PartialEq`)
185
+ 2. Conversion traits (`From`, `Into`, `TryFrom`)
186
+ 3. Iterator traits (`Iterator`, `IntoIterator`)
187
+ 4. Serde traits (`Serialize`, `Deserialize`)
188
+ 5. Custom traits (domain-specific)
189
+
190
+ ---
191
+
192
+ ## Module Organization
193
+
194
+ ```
195
+ src/
196
+ ├── lib.rs # Public API re-exports
197
+ ├── error.rs # Crate-level error types
198
+ ├── domain/
199
+ │ ├── mod.rs # Domain re-exports
200
+ │ ├── user.rs # User entity and logic
201
+ │ └── order.rs # Order entity and logic
202
+ ├── repo/
203
+ │ ├── mod.rs # Repository trait definitions
204
+ │ └── postgres.rs # Concrete implementation
205
+ └── api/
206
+ ├── mod.rs # Route registration
207
+ └── handlers.rs # HTTP handlers
208
+ ```
209
+
210
+ Keep `lib.rs` thin — re-export only the public API. Internal modules use `pub(crate)`.
@@ -0,0 +1,191 @@
1
+ # Rust Violation Examples
2
+
3
+ Extended violation patterns for Rust reviews. Reference from main SKILL.md.
4
+
5
+ ## Unwrap Abuse
6
+
7
+ ### Unwrap in Library Code
8
+
9
+ ```rust
10
+ // VIOLATION: Panics on None — caller has no way to handle failure
11
+ pub fn get_username(users: &HashMap<u64, String>, id: u64) -> &str {
12
+ users.get(&id).unwrap() // Panics if id not found
13
+ }
14
+
15
+ // VIOLATION: Unwrap on parse without context
16
+ let port: u16 = std::env::var("PORT").unwrap().parse().unwrap();
17
+ ```
18
+
19
+ ### Expect Without Useful Message
20
+
21
+ ```rust
22
+ // VIOLATION: Message doesn't help diagnose the problem
23
+ let config = load_config().expect("failed");
24
+
25
+ // CORRECT: Actionable message
26
+ let config = load_config().expect("failed to load config from config.toml — does file exist?");
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Unnecessary Cloning
32
+
33
+ ### Clone to Satisfy Borrow Checker
34
+
35
+ ```rust
36
+ // VIOLATION: Cloning to work around borrow issues
37
+ fn process_items(items: &Vec<Item>) {
38
+ let cloned = items.clone(); // Entire Vec cloned
39
+ for item in &cloned {
40
+ println!("{}", item.name);
41
+ }
42
+ }
43
+
44
+ // CORRECT: Just borrow
45
+ fn process_items(items: &[Item]) {
46
+ for item in items {
47
+ println!("{}", item.name);
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### Clone in Hot Loop
53
+
54
+ ```rust
55
+ // VIOLATION: Allocating on every iteration
56
+ for record in &records {
57
+ let key = record.id.clone(); // String allocation per iteration
58
+ map.insert(key, record);
59
+ }
60
+
61
+ // CORRECT: Borrow or use references
62
+ for record in &records {
63
+ map.insert(&record.id, record);
64
+ }
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Stringly-Typed APIs
70
+
71
+ ### String Where Enum Belongs
72
+
73
+ ```rust
74
+ // VIOLATION: Any typo compiles and fails at runtime
75
+ fn set_status(status: &str) {
76
+ match status {
77
+ "active" => { /* ... */ }
78
+ "inactive" => { /* ... */ }
79
+ _ => panic!("unknown status"), // Runtime failure
80
+ }
81
+ }
82
+
83
+ // CORRECT: Compiler enforces valid values
84
+ enum Status { Active, Inactive }
85
+
86
+ fn set_status(status: Status) {
87
+ match status {
88
+ Status::Active => { /* ... */ }
89
+ Status::Inactive => { /* ... */ }
90
+ } // Exhaustive — no default needed
91
+ }
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Unsafe Without Justification
97
+
98
+ ### Bare Unsafe Block
99
+
100
+ ```rust
101
+ // VIOLATION: No safety comment explaining invariants
102
+ unsafe {
103
+ let ptr = data.as_ptr();
104
+ std::ptr::copy_nonoverlapping(ptr, dest, len);
105
+ }
106
+
107
+ // CORRECT: Document why this is safe
108
+ // SAFETY: `data` is guaranteed to be valid for `len` bytes because
109
+ // it was allocated by `Vec::with_capacity(len)` and filled by `read_exact`.
110
+ // `dest` is a valid pointer from `alloc::alloc(layout)` with matching size.
111
+ unsafe {
112
+ std::ptr::copy_nonoverlapping(data.as_ptr(), dest, len);
113
+ }
114
+ ```
115
+
116
+ ### Unnecessary Unsafe
117
+
118
+ ```rust
119
+ // VIOLATION: Using unsafe when safe alternative exists
120
+ unsafe fn get_element(slice: &[u8], index: usize) -> u8 {
121
+ *slice.get_unchecked(index)
122
+ }
123
+
124
+ // CORRECT: Safe indexing with bounds check
125
+ fn get_element(slice: &[u8], index: usize) -> Option<u8> {
126
+ slice.get(index).copied()
127
+ }
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Ignoring Results
133
+
134
+ ### Discarding Write Errors
135
+
136
+ ```rust
137
+ // VIOLATION: Write failure silently ignored
138
+ let _ = file.write_all(data);
139
+ let _ = file.flush();
140
+
141
+ // CORRECT: Propagate errors
142
+ file.write_all(data)?;
143
+ file.flush()?;
144
+ ```
145
+
146
+ ### Ignoring Lock Poisoning
147
+
148
+ ```rust
149
+ // VIOLATION: Silently ignoring poisoned mutex
150
+ let guard = mutex.lock().unwrap_or_else(|e| e.into_inner());
151
+
152
+ // CORRECT: Handle or propagate the poison
153
+ let guard = mutex.lock().map_err(|_| AppError::LockPoisoned)?;
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Concurrency Violations
159
+
160
+ ### Shared Mutable State Without Synchronization
161
+
162
+ ```rust
163
+ // VIOLATION: Data race potential — no synchronization
164
+ static mut COUNTER: u64 = 0;
165
+
166
+ fn increment() {
167
+ unsafe { COUNTER += 1; } // Undefined behavior under concurrency
168
+ }
169
+
170
+ // CORRECT: Use atomic or mutex
171
+ use std::sync::atomic::{AtomicU64, Ordering};
172
+ static COUNTER: AtomicU64 = AtomicU64::new(0);
173
+
174
+ fn increment() {
175
+ COUNTER.fetch_add(1, Ordering::Relaxed);
176
+ }
177
+ ```
178
+
179
+ ### Blocking in Async Context
180
+
181
+ ```rust
182
+ // VIOLATION: Blocks the async runtime thread
183
+ async fn read_file(path: &str) -> Result<String, io::Error> {
184
+ std::fs::read_to_string(path) // Blocking call in async fn
185
+ }
186
+
187
+ // CORRECT: Use async file I/O or spawn_blocking
188
+ async fn read_file(path: &str) -> Result<String, io::Error> {
189
+ tokio::fs::read_to_string(path).await
190
+ }
191
+ ```
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "devflow-self-review",
3
3
  "description": "Self-review workflow: Simplifier + Scrutinizer for code quality",
4
- "version": "1.1.0",
5
- "agents": ["simplifier", "scrutinizer", "validator"],
6
- "skills": ["self-review", "core-patterns"]
4
+ "version": "1.3.0",
5
+ "agents": [
6
+ "simplifier",
7
+ "scrutinizer",
8
+ "validator"
9
+ ],
10
+ "skills": [
11
+ "self-review",
12
+ "core-patterns"
13
+ ]
7
14
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: self-review
3
- description: Self-review framework evaluating implementation quality against 9 pillars (correctness, completeness, security, performance, maintainability, testing, documentation, error handling, simplicity). Fixes P0/P1 issues immediately rather than reporting them. Used by the Scrutinizer agent as a quality gate.
3
+ description: This skill should be used when evaluating implementation quality before submission, checking correctness, security, and simplicity.
4
4
  user-invocable: false
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash
6
6
  ---
@@ -5,11 +5,22 @@
5
5
  "name": "DevFlow Contributors",
6
6
  "email": "dean@keren.dev"
7
7
  },
8
- "version": "1.1.0",
8
+ "version": "1.3.0",
9
9
  "homepage": "https://github.com/dean0x/devflow",
10
10
  "repository": "https://github.com/dean0x/devflow",
11
11
  "license": "MIT",
12
- "keywords": ["specification", "requirements", "planning", "issues", "github"],
13
- "agents": ["skimmer", "synthesizer"],
14
- "skills": ["agent-teams"]
12
+ "keywords": [
13
+ "specification",
14
+ "requirements",
15
+ "planning",
16
+ "issues",
17
+ "github"
18
+ ],
19
+ "agents": [
20
+ "skimmer",
21
+ "synthesizer"
22
+ ],
23
+ "skills": [
24
+ "agent-teams"
25
+ ]
15
26
  }