devflow-kit 1.1.0 → 1.2.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 +39 -0
- package/README.md +23 -6
- package/dist/plugins.js +67 -3
- package/package.json +2 -1
- package/plugins/devflow-accessibility/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-ambient/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +1 -1
- package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +4 -0
- package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -4
- 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-core-skills/.claude-plugin/plugin.json +2 -6
- package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-go/.claude-plugin/plugin.json +15 -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 +1 -3
- package/plugins/devflow-implement/agents/coder.md +11 -6
- package/plugins/devflow-java/.claude-plugin/plugin.json +15 -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 +15 -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 +15 -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 +1 -1
- package/plugins/devflow-rust/.claude-plugin/plugin.json +15 -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 +1 -1
- package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-typescript/.claude-plugin/plugin.json +15 -0
- package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
- package/shared/agents/coder.md +11 -6
- package/shared/agents/reviewer.md +8 -0
- package/shared/skills/ambient-router/SKILL.md +1 -1
- package/shared/skills/ambient-router/references/skill-catalog.md +4 -0
- 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/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/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/typescript/references/patterns.md +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/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,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,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devflow-self-review",
|
|
3
3
|
"description": "Self-review workflow: Simplifier + Scrutinizer for code quality",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"agents": ["simplifier", "scrutinizer", "validator"],
|
|
6
6
|
"skills": ["self-review", "core-patterns"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devflow-typescript",
|
|
3
|
+
"description": "TypeScript language patterns - type safety, generics, utility types, type guards",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "DevFlow Contributors",
|
|
6
|
+
"email": "dean@keren.dev"
|
|
7
|
+
},
|
|
8
|
+
"version": "1.2.0",
|
|
9
|
+
"homepage": "https://github.com/dean0x/devflow",
|
|
10
|
+
"repository": "https://github.com/dean0x/devflow",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": ["typescript", "types", "generics", "type-safety"],
|
|
13
|
+
"agents": [],
|
|
14
|
+
"skills": ["typescript"]
|
|
15
|
+
}
|
package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md
RENAMED
|
@@ -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();
|
package/shared/agents/coder.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: Coder
|
|
3
3
|
description: Autonomous task implementation on feature branch. Implements, tests, and commits.
|
|
4
4
|
model: inherit
|
|
5
|
-
skills: core-patterns, git-safety, implementation-patterns, git-workflow,
|
|
5
|
+
skills: core-patterns, git-safety, implementation-patterns, git-workflow, test-patterns, input-validation
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Coder Agent
|
|
@@ -33,11 +33,16 @@ You receive from orchestrator:
|
|
|
33
33
|
|
|
34
34
|
2. **Reference handoff** (if PRIOR_PHASE_SUMMARY provided): Use summary to validate your understanding of prior work, not as the sole source of truth. The actual code is authoritative.
|
|
35
35
|
|
|
36
|
-
3. **Load domain skills**: Based on DOMAIN hint,
|
|
37
|
-
- `backend
|
|
38
|
-
- `
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
36
|
+
3. **Load domain skills**: Based on DOMAIN hint and files in scope, dynamically load relevant language/ecosystem skills by reading their SKILL.md. Only load skills that are installed:
|
|
37
|
+
- `backend` (TypeScript): Read `~/.claude/skills/typescript/SKILL.md`, `~/.claude/skills/input-validation/SKILL.md`
|
|
38
|
+
- `backend` (Go): Read `~/.claude/skills/go/SKILL.md`
|
|
39
|
+
- `backend` (Java): Read `~/.claude/skills/java/SKILL.md`
|
|
40
|
+
- `backend` (Python): Read `~/.claude/skills/python/SKILL.md`
|
|
41
|
+
- `backend` (Rust): Read `~/.claude/skills/rust/SKILL.md`
|
|
42
|
+
- `frontend`: Read `~/.claude/skills/react/SKILL.md`, `~/.claude/skills/typescript/SKILL.md`, `~/.claude/skills/accessibility/SKILL.md`, `~/.claude/skills/frontend-design/SKILL.md`
|
|
43
|
+
- `tests`: Read `~/.claude/skills/test-patterns/SKILL.md`, `~/.claude/skills/typescript/SKILL.md`
|
|
44
|
+
- `fullstack`: Combine backend + frontend skills
|
|
45
|
+
- If a Read fails (skill not installed), skip it silently and continue.
|
|
41
46
|
|
|
42
47
|
4. **Implement the plan**: Work through execution steps systematically, creating and modifying files. Follow existing patterns. Type everything. Use Result types if codebase uses them.
|
|
43
48
|
|
|
@@ -34,6 +34,10 @@ The orchestrator provides:
|
|
|
34
34
|
| `react` | `~/.claude/skills/react/SKILL.md` |
|
|
35
35
|
| `accessibility` | `~/.claude/skills/accessibility/SKILL.md` |
|
|
36
36
|
| `frontend-design` | `~/.claude/skills/frontend-design/SKILL.md` |
|
|
37
|
+
| `go` | `~/.claude/skills/go/SKILL.md` |
|
|
38
|
+
| `java` | `~/.claude/skills/java/SKILL.md` |
|
|
39
|
+
| `python` | `~/.claude/skills/python/SKILL.md` |
|
|
40
|
+
| `rust` | `~/.claude/skills/rust/SKILL.md` |
|
|
37
41
|
|
|
38
42
|
## Responsibilities
|
|
39
43
|
|
|
@@ -117,3 +121,7 @@ Report format for `{output_path}`:
|
|
|
117
121
|
| react | If .tsx/.jsx files changed |
|
|
118
122
|
| accessibility | If .tsx/.jsx files changed |
|
|
119
123
|
| frontend-design | If .tsx/.jsx/.css/.scss files changed |
|
|
124
|
+
| go | If .go files changed |
|
|
125
|
+
| java | If .java files changed |
|
|
126
|
+
| python | If .py files changed |
|
|
127
|
+
| rust | If .rs files changed |
|
|
@@ -54,7 +54,7 @@ Based on classified intent, read the following skills to inform your response.
|
|
|
54
54
|
|
|
55
55
|
| Intent | Primary Skills | Secondary (if file type matches) |
|
|
56
56
|
|--------|---------------|----------------------------------|
|
|
57
|
-
| **BUILD** | test-driven-development, implementation-patterns | typescript (.ts), react (.tsx/.jsx), frontend-design (CSS/UI), input-validation (forms/API), security-patterns (auth/crypto) |
|
|
57
|
+
| **BUILD** | test-driven-development, implementation-patterns | typescript (.ts), react (.tsx/.jsx), go (.go), java (.java), python (.py), rust (.rs), frontend-design (CSS/UI), input-validation (forms/API), security-patterns (auth/crypto) |
|
|
58
58
|
| **DEBUG** | test-patterns, core-patterns | git-safety (if git operations involved) |
|
|
59
59
|
| **REVIEW** | self-review, core-patterns | test-patterns |
|
|
60
60
|
| **PLAN** | implementation-patterns | core-patterns |
|
|
@@ -16,6 +16,10 @@ These skills may be loaded during STANDARD-depth ambient routing.
|
|
|
16
16
|
| react | React components in scope | `*.tsx`, `*.jsx` |
|
|
17
17
|
| frontend-design | UI/styling work | `*.css`, `*.scss`, `*.tsx` with styling keywords |
|
|
18
18
|
| input-validation | Forms, APIs, user input | Files with form/input/validation keywords |
|
|
19
|
+
| go | Go files in scope | `*.go` |
|
|
20
|
+
| java | Java files in scope | `*.java` |
|
|
21
|
+
| python | Python files in scope | `*.py` |
|
|
22
|
+
| rust | Rust files in scope | `*.rs` |
|
|
19
23
|
| security-patterns | Auth, crypto, secrets | Files with auth/token/crypto/password keywords |
|
|
20
24
|
|
|
21
25
|
### DEBUG Intent
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: go
|
|
3
|
+
description: This skill should be used when the user works with Go files (.go), asks about "error handling", "interfaces", "goroutines", "channels", "packages", or discusses Go idioms and concurrency. Provides patterns for error handling, interface design, concurrency, and package organization.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
allowed-tools: Read, Grep, Glob
|
|
6
|
+
activation:
|
|
7
|
+
file-patterns:
|
|
8
|
+
- "**/*.go"
|
|
9
|
+
exclude:
|
|
10
|
+
- "vendor/**"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Go Patterns
|
|
14
|
+
|
|
15
|
+
Reference for Go-specific patterns, idioms, and best practices.
|
|
16
|
+
|
|
17
|
+
## Iron Law
|
|
18
|
+
|
|
19
|
+
> **ERRORS ARE VALUES**
|
|
20
|
+
>
|
|
21
|
+
> Never ignore errors. `if err != nil` is correctness, not boilerplate. Every error
|
|
22
|
+
> return must be checked, wrapped with context, or explicitly documented as intentionally
|
|
23
|
+
> ignored with `_ = fn()`. Silent error swallowing causes cascading failures.
|
|
24
|
+
|
|
25
|
+
## When This Skill Activates
|
|
26
|
+
|
|
27
|
+
- Working with Go codebases
|
|
28
|
+
- Designing interfaces and packages
|
|
29
|
+
- Implementing concurrent code
|
|
30
|
+
- Handling errors
|
|
31
|
+
- Structuring Go projects
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Error Handling
|
|
36
|
+
|
|
37
|
+
### Wrap Errors with Context
|
|
38
|
+
|
|
39
|
+
```go
|
|
40
|
+
// BAD: return err
|
|
41
|
+
// GOOD: return fmt.Errorf("reading config %s: %w", path, err)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Sentinel Errors for Expected Conditions
|
|
45
|
+
|
|
46
|
+
```go
|
|
47
|
+
var ErrNotFound = errors.New("not found")
|
|
48
|
+
|
|
49
|
+
func FindUser(id string) (*User, error) {
|
|
50
|
+
u, err := db.Get(id)
|
|
51
|
+
if err != nil {
|
|
52
|
+
return nil, fmt.Errorf("finding user %s: %w", id, err)
|
|
53
|
+
}
|
|
54
|
+
if u == nil {
|
|
55
|
+
return nil, ErrNotFound
|
|
56
|
+
}
|
|
57
|
+
return u, nil
|
|
58
|
+
}
|
|
59
|
+
// Caller: if errors.Is(err, ErrNotFound) { ... }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Interface Design
|
|
65
|
+
|
|
66
|
+
### Accept Interfaces, Return Structs
|
|
67
|
+
|
|
68
|
+
```go
|
|
69
|
+
// BAD: func NewService(repo *PostgresRepo) *Service
|
|
70
|
+
// GOOD: func NewService(repo Repository) *Service
|
|
71
|
+
|
|
72
|
+
type Repository interface {
|
|
73
|
+
FindByID(ctx context.Context, id string) (*Entity, error)
|
|
74
|
+
Save(ctx context.Context, entity *Entity) error
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Keep Interfaces Small
|
|
79
|
+
|
|
80
|
+
```go
|
|
81
|
+
// BAD: 10-method interface
|
|
82
|
+
// GOOD: single-method interfaces composed as needed
|
|
83
|
+
type Reader interface { Read(p []byte) (n int, err error) }
|
|
84
|
+
type Writer interface { Write(p []byte) (n int, err error) }
|
|
85
|
+
type ReadWriter interface { Reader; Writer }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Concurrency
|
|
91
|
+
|
|
92
|
+
### Use Context for Cancellation
|
|
93
|
+
|
|
94
|
+
```go
|
|
95
|
+
func Process(ctx context.Context, items []Item) error {
|
|
96
|
+
g, ctx := errgroup.WithContext(ctx)
|
|
97
|
+
for _, item := range items {
|
|
98
|
+
g.Go(func() error {
|
|
99
|
+
return processItem(ctx, item)
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
return g.Wait()
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Channel Direction
|
|
107
|
+
|
|
108
|
+
```go
|
|
109
|
+
// Declare direction in function signatures
|
|
110
|
+
func producer(ch chan<- int) { ch <- 42 }
|
|
111
|
+
func consumer(ch <-chan int) { v := <-ch; _ = v }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Package Design
|
|
117
|
+
|
|
118
|
+
### Organize by Domain, Not by Type
|
|
119
|
+
|
|
120
|
+
```go
|
|
121
|
+
// BAD: models/, controllers/, services/
|
|
122
|
+
// GOOD: user/, order/, payment/
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Export Only What's Needed
|
|
126
|
+
|
|
127
|
+
```go
|
|
128
|
+
// Internal helpers stay unexported (lowercase)
|
|
129
|
+
func (s *Service) validate(u *User) error { ... }
|
|
130
|
+
|
|
131
|
+
// Public API is exported (uppercase)
|
|
132
|
+
func (s *Service) CreateUser(ctx context.Context, req CreateUserReq) (*User, error) { ... }
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Zero Values
|
|
138
|
+
|
|
139
|
+
```go
|
|
140
|
+
// Use zero values as valid defaults
|
|
141
|
+
var mu sync.Mutex // Ready to use
|
|
142
|
+
var buf bytes.Buffer // Ready to use
|
|
143
|
+
var wg sync.WaitGroup // Ready to use
|
|
144
|
+
|
|
145
|
+
// Design types with useful zero values
|
|
146
|
+
type Config struct {
|
|
147
|
+
Timeout time.Duration // zero = no timeout
|
|
148
|
+
Retries int // zero = no retries
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Anti-Patterns
|
|
155
|
+
|
|
156
|
+
| Pattern | Bad | Good |
|
|
157
|
+
|---------|-----|------|
|
|
158
|
+
| Ignoring error | `val, _ := fn()` | `val, err := fn(); if err != nil { ... }` |
|
|
159
|
+
| Naked return | `return` in named returns | Explicit `return val, err` |
|
|
160
|
+
| init() abuse | Complex `init()` functions | Explicit initialization in `main()` or constructors |
|
|
161
|
+
| Interface pollution | Defining interfaces before use | Define interfaces at the consumer site |
|
|
162
|
+
| Goroutine leak | `go fn()` without lifecycle | Use context, errgroup, or done channels |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Extended References
|
|
167
|
+
|
|
168
|
+
For additional patterns and examples:
|
|
169
|
+
- `references/violations.md` - Common Go violations
|
|
170
|
+
- `references/patterns.md` - Extended Go patterns
|
|
171
|
+
- `references/detection.md` - Detection patterns for Go issues
|
|
172
|
+
- `references/concurrency.md` - Advanced concurrency patterns
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Checklist
|
|
177
|
+
|
|
178
|
+
- [ ] All errors checked or explicitly ignored with `_ =`
|
|
179
|
+
- [ ] Errors wrapped with `fmt.Errorf("context: %w", err)`
|
|
180
|
+
- [ ] Interfaces defined at consumer, not producer
|
|
181
|
+
- [ ] Interfaces kept small (1-3 methods)
|
|
182
|
+
- [ ] Context passed as first parameter
|
|
183
|
+
- [ ] Goroutines have clear lifecycle/cancellation
|
|
184
|
+
- [ ] Channel direction specified in signatures
|
|
185
|
+
- [ ] Zero values are useful defaults
|
|
186
|
+
- [ ] Packages organized by domain
|
|
187
|
+
- [ ] No `init()` with side effects
|