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.
- package/CHANGELOG.md +69 -1
- package/README.md +23 -6
- package/dist/cli.js +2 -0
- package/dist/commands/ambient.js +5 -4
- package/dist/commands/init.js +4 -2
- package/dist/commands/memory.js +4 -4
- package/dist/commands/skills.d.ts +11 -0
- package/dist/commands/skills.js +116 -0
- package/dist/commands/uninstall.js +11 -1
- package/dist/plugins.js +67 -3
- package/dist/utils/installer.js +20 -2
- package/package.json +4 -2
- package/plugins/devflow-accessibility/.claude-plugin/plugin.json +22 -0
- package/plugins/devflow-ambient/.claude-plugin/plugin.json +4 -2
- package/plugins/devflow-ambient/README.md +8 -8
- package/plugins/devflow-ambient/commands/ambient.md +14 -14
- package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +16 -9
- package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +6 -2
- package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-code-review/.claude-plugin/plugin.json +13 -6
- package/plugins/devflow-code-review/agents/reviewer.md +8 -0
- package/plugins/devflow-code-review/commands/code-review-teams.md +11 -1
- package/plugins/devflow-code-review/commands/code-review.md +12 -2
- package/plugins/devflow-code-review/skills/architecture-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/complexity-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/consistency-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/database-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/dependencies-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/documentation-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/performance-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/regression-patterns/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/review-methodology/SKILL.md +1 -1
- package/plugins/devflow-code-review/skills/security-patterns/SKILL.md +1 -1
- package/plugins/devflow-core-skills/.claude-plugin/plugin.json +10 -7
- package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +5 -8
- package/plugins/devflow-debug/.claude-plugin/plugin.json +10 -3
- package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +22 -0
- package/plugins/devflow-go/.claude-plugin/plugin.json +22 -0
- package/plugins/devflow-go/skills/go/SKILL.md +187 -0
- package/plugins/devflow-go/skills/go/references/concurrency.md +312 -0
- package/plugins/devflow-go/skills/go/references/detection.md +129 -0
- package/plugins/devflow-go/skills/go/references/patterns.md +232 -0
- package/plugins/devflow-go/skills/go/references/violations.md +205 -0
- package/plugins/devflow-implement/.claude-plugin/plugin.json +19 -5
- package/plugins/devflow-implement/agents/coder.md +11 -6
- package/plugins/devflow-implement/skills/self-review/SKILL.md +1 -1
- package/plugins/devflow-java/.claude-plugin/plugin.json +22 -0
- package/plugins/devflow-java/skills/java/SKILL.md +183 -0
- package/plugins/devflow-java/skills/java/references/detection.md +120 -0
- package/plugins/devflow-java/skills/java/references/modern-java.md +270 -0
- package/plugins/devflow-java/skills/java/references/patterns.md +235 -0
- package/plugins/devflow-java/skills/java/references/violations.md +213 -0
- package/plugins/devflow-python/.claude-plugin/plugin.json +22 -0
- package/plugins/devflow-python/skills/python/SKILL.md +188 -0
- package/plugins/devflow-python/skills/python/references/async.md +220 -0
- package/plugins/devflow-python/skills/python/references/detection.md +128 -0
- package/plugins/devflow-python/skills/python/references/patterns.md +226 -0
- package/plugins/devflow-python/skills/python/references/violations.md +204 -0
- package/plugins/devflow-react/.claude-plugin/plugin.json +22 -0
- package/plugins/{devflow-core-skills → devflow-react}/skills/react/SKILL.md +1 -1
- package/plugins/{devflow-core-skills → devflow-react}/skills/react/references/patterns.md +3 -3
- package/plugins/devflow-resolve/.claude-plugin/plugin.json +13 -3
- package/plugins/devflow-resolve/skills/security-patterns/SKILL.md +1 -1
- package/plugins/devflow-rust/.claude-plugin/plugin.json +22 -0
- package/plugins/devflow-rust/skills/rust/SKILL.md +193 -0
- package/plugins/devflow-rust/skills/rust/references/detection.md +131 -0
- package/plugins/devflow-rust/skills/rust/references/ownership.md +242 -0
- package/plugins/devflow-rust/skills/rust/references/patterns.md +210 -0
- package/plugins/devflow-rust/skills/rust/references/violations.md +191 -0
- package/plugins/devflow-self-review/.claude-plugin/plugin.json +10 -3
- package/plugins/devflow-self-review/skills/self-review/SKILL.md +1 -1
- package/plugins/devflow-specify/.claude-plugin/plugin.json +15 -4
- package/plugins/devflow-typescript/.claude-plugin/plugin.json +22 -0
- package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
- package/scripts/hooks/{ambient-prompt.sh → ambient-prompt} +4 -4
- package/scripts/hooks/{background-memory-update.sh → background-memory-update} +3 -3
- package/scripts/hooks/{ensure-memory-gitignore.sh → ensure-memory-gitignore} +1 -1
- package/scripts/hooks/{pre-compact-memory.sh → pre-compact-memory} +2 -2
- package/scripts/hooks/run-hook +23 -0
- package/scripts/hooks/session-start-memory +151 -0
- package/scripts/hooks/{stop-update-memory.sh → stop-update-memory} +4 -4
- package/shared/agents/coder.md +11 -6
- package/shared/agents/reviewer.md +8 -0
- package/shared/skills/ambient-router/SKILL.md +16 -9
- package/shared/skills/ambient-router/references/skill-catalog.md +6 -2
- package/shared/skills/architecture-patterns/SKILL.md +1 -1
- package/shared/skills/complexity-patterns/SKILL.md +1 -1
- package/shared/skills/consistency-patterns/SKILL.md +1 -1
- package/shared/skills/database-patterns/SKILL.md +1 -1
- package/shared/skills/dependencies-patterns/SKILL.md +1 -1
- package/shared/skills/documentation-patterns/SKILL.md +1 -1
- package/shared/skills/go/SKILL.md +187 -0
- package/shared/skills/go/references/concurrency.md +312 -0
- package/shared/skills/go/references/detection.md +129 -0
- package/shared/skills/go/references/patterns.md +232 -0
- package/shared/skills/go/references/violations.md +205 -0
- package/shared/skills/java/SKILL.md +183 -0
- package/shared/skills/java/references/detection.md +120 -0
- package/shared/skills/java/references/modern-java.md +270 -0
- package/shared/skills/java/references/patterns.md +235 -0
- package/shared/skills/java/references/violations.md +213 -0
- package/shared/skills/performance-patterns/SKILL.md +1 -1
- package/shared/skills/python/SKILL.md +188 -0
- package/shared/skills/python/references/async.md +220 -0
- package/shared/skills/python/references/detection.md +128 -0
- package/shared/skills/python/references/patterns.md +226 -0
- package/shared/skills/python/references/violations.md +204 -0
- package/shared/skills/react/SKILL.md +1 -1
- package/shared/skills/react/references/patterns.md +3 -3
- package/shared/skills/regression-patterns/SKILL.md +1 -1
- package/shared/skills/review-methodology/SKILL.md +1 -1
- package/shared/skills/rust/SKILL.md +193 -0
- package/shared/skills/rust/references/detection.md +131 -0
- package/shared/skills/rust/references/ownership.md +242 -0
- package/shared/skills/rust/references/patterns.md +210 -0
- package/shared/skills/rust/references/violations.md +191 -0
- package/shared/skills/security-patterns/SKILL.md +1 -1
- package/shared/skills/self-review/SKILL.md +1 -1
- package/shared/skills/test-driven-development/SKILL.md +5 -8
- package/shared/skills/typescript/references/patterns.md +3 -3
- package/src/templates/settings.json +3 -3
- package/plugins/devflow-code-review/skills/react/SKILL.md +0 -276
- package/plugins/devflow-code-review/skills/react/references/patterns.md +0 -1331
- package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +0 -229
- package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +0 -171
- package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +0 -670
- package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +0 -419
- package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +0 -254
- package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +0 -184
- package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +0 -511
- package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +0 -453
- package/plugins/devflow-core-skills/skills/react/references/violations.md +0 -565
- package/plugins/devflow-implement/skills/accessibility/SKILL.md +0 -229
- package/plugins/devflow-implement/skills/accessibility/references/detection.md +0 -171
- package/plugins/devflow-implement/skills/accessibility/references/patterns.md +0 -670
- package/plugins/devflow-implement/skills/accessibility/references/violations.md +0 -419
- package/plugins/devflow-implement/skills/frontend-design/SKILL.md +0 -254
- package/plugins/devflow-implement/skills/frontend-design/references/detection.md +0 -184
- package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +0 -511
- package/plugins/devflow-implement/skills/frontend-design/references/violations.md +0 -453
- package/scripts/hooks/session-start-memory.sh +0 -126
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/SKILL.md +0 -0
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/detection.md +0 -0
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/patterns.md +0 -0
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/violations.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/SKILL.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/detection.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/patterns.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/violations.md +0 -0
- /package/plugins/{devflow-code-review → devflow-react}/skills/react/references/violations.md +0 -0
- /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/SKILL.md +0 -0
- /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/violations.md +0 -0
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: security-patterns
|
|
3
|
-
description:
|
|
3
|
+
description: This skill should be used when reviewing code for injection flaws, auth bypasses, or hardcoded secrets.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
allowed-tools: Read, Grep, Glob
|
|
6
6
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: self-review
|
|
3
|
-
description:
|
|
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
|
---
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: test-driven-development
|
|
3
|
-
description:
|
|
4
|
-
Enforce RED-GREEN-REFACTOR cycle during implementation. Write failing tests before
|
|
5
|
-
production code. Distinct from test-patterns (which reviews test quality) — this
|
|
6
|
-
skill enforces the TDD workflow during code generation.
|
|
3
|
+
description: This skill should be used when implementing new features, fixing bugs, or writing new code. Enforces RED-GREEN-REFACTOR.
|
|
7
4
|
user-invocable: false
|
|
8
5
|
allowed-tools: Read, Grep, Glob
|
|
9
6
|
activation:
|
|
@@ -94,7 +91,7 @@ See `references/rationalization-prevention.md` for extended examples with code.
|
|
|
94
91
|
|
|
95
92
|
## Process Enforcement
|
|
96
93
|
|
|
97
|
-
When implementing any feature under ambient BUILD/
|
|
94
|
+
When implementing any feature under ambient BUILD/GUIDED:
|
|
98
95
|
|
|
99
96
|
1. **Identify the first behavior** — What is the simplest thing this feature must do?
|
|
100
97
|
2. **Write the test** — Describe that behavior as a failing test
|
|
@@ -133,7 +130,7 @@ When skipping TDD, never rationalize. State clearly: "Skipping TDD because: [spe
|
|
|
133
130
|
|
|
134
131
|
## Integration with Ambient Mode
|
|
135
132
|
|
|
136
|
-
- **BUILD/
|
|
133
|
+
- **BUILD/GUIDED** → TDD enforced. Every new function/method gets test-first treatment.
|
|
137
134
|
- **BUILD/QUICK** → TDD skipped (trivial single-file edit).
|
|
138
|
-
- **BUILD/
|
|
139
|
-
- **DEBUG/
|
|
135
|
+
- **BUILD/ELEVATE** → TDD mentioned in nudge toward `/implement`.
|
|
136
|
+
- **DEBUG/GUIDED** → TDD applies to the fix: write a test that reproduces the bug first, then fix.
|
|
@@ -137,7 +137,7 @@ const isUndefined = (value: unknown): value is undefined =>
|
|
|
137
137
|
const isNullish = (value: unknown): value is null | undefined =>
|
|
138
138
|
value === null || value === undefined;
|
|
139
139
|
|
|
140
|
-
const isFunction = (value: unknown): value is
|
|
140
|
+
const isFunction = (value: unknown): value is (...args: unknown[]) => unknown =>
|
|
141
141
|
typeof value === 'function';
|
|
142
142
|
|
|
143
143
|
const isObject = (value: unknown): value is object =>
|
|
@@ -760,7 +760,7 @@ function debounce<T extends (...args: any[]) => any>(
|
|
|
760
760
|
fn: T,
|
|
761
761
|
delayMs: number
|
|
762
762
|
): (...args: Parameters<T>) => void {
|
|
763
|
-
let timeoutId:
|
|
763
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
764
764
|
|
|
765
765
|
return (...args: Parameters<T>) => {
|
|
766
766
|
if (timeoutId) clearTimeout(timeoutId);
|
|
@@ -774,7 +774,7 @@ function throttle<T extends (...args: any[]) => any>(
|
|
|
774
774
|
limitMs: number
|
|
775
775
|
): (...args: Parameters<T>) => void {
|
|
776
776
|
let lastRun = 0;
|
|
777
|
-
let timeoutId:
|
|
777
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
778
778
|
|
|
779
779
|
return (...args: Parameters<T>) => {
|
|
780
780
|
const now = Date.now();
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"hooks": [
|
|
10
10
|
{
|
|
11
11
|
"type": "command",
|
|
12
|
-
"command": "${DEVFLOW_DIR}/scripts/hooks/stop-update-memory
|
|
12
|
+
"command": "${DEVFLOW_DIR}/scripts/hooks/run-hook stop-update-memory",
|
|
13
13
|
"timeout": 10
|
|
14
14
|
}
|
|
15
15
|
]
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"hooks": [
|
|
21
21
|
{
|
|
22
22
|
"type": "command",
|
|
23
|
-
"command": "${DEVFLOW_DIR}/scripts/hooks/session-start-memory
|
|
23
|
+
"command": "${DEVFLOW_DIR}/scripts/hooks/run-hook session-start-memory",
|
|
24
24
|
"timeout": 10
|
|
25
25
|
}
|
|
26
26
|
]
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"hooks": [
|
|
32
32
|
{
|
|
33
33
|
"type": "command",
|
|
34
|
-
"command": "${DEVFLOW_DIR}/scripts/hooks/pre-compact-memory
|
|
34
|
+
"command": "${DEVFLOW_DIR}/scripts/hooks/run-hook pre-compact-memory",
|
|
35
35
|
"timeout": 10
|
|
36
36
|
}
|
|
37
37
|
]
|