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,232 @@
|
|
|
1
|
+
# Go Correct Patterns
|
|
2
|
+
|
|
3
|
+
Extended correct patterns for Go development. Reference from main SKILL.md.
|
|
4
|
+
|
|
5
|
+
## Table-Driven Tests
|
|
6
|
+
|
|
7
|
+
```go
|
|
8
|
+
func TestAdd(t *testing.T) {
|
|
9
|
+
tests := []struct {
|
|
10
|
+
name string
|
|
11
|
+
a, b int
|
|
12
|
+
expected int
|
|
13
|
+
}{
|
|
14
|
+
{"positive numbers", 2, 3, 5},
|
|
15
|
+
{"negative numbers", -1, -2, -3},
|
|
16
|
+
{"zero", 0, 0, 0},
|
|
17
|
+
{"mixed signs", -1, 3, 2},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
for _, tt := range tests {
|
|
21
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
22
|
+
result := Add(tt.a, tt.b)
|
|
23
|
+
if result != tt.expected {
|
|
24
|
+
t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, result, tt.expected)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Functional Options
|
|
34
|
+
|
|
35
|
+
```go
|
|
36
|
+
type Server struct {
|
|
37
|
+
addr string
|
|
38
|
+
timeout time.Duration
|
|
39
|
+
logger *slog.Logger
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type Option func(*Server)
|
|
43
|
+
|
|
44
|
+
func WithAddr(addr string) Option {
|
|
45
|
+
return func(s *Server) { s.addr = addr }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func WithTimeout(d time.Duration) Option {
|
|
49
|
+
return func(s *Server) { s.timeout = d }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func WithLogger(l *slog.Logger) Option {
|
|
53
|
+
return func(s *Server) { s.logger = l }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func NewServer(opts ...Option) *Server {
|
|
57
|
+
s := &Server{
|
|
58
|
+
addr: ":8080", // sensible default
|
|
59
|
+
timeout: 30 * time.Second, // sensible default
|
|
60
|
+
logger: slog.Default(),
|
|
61
|
+
}
|
|
62
|
+
for _, opt := range opts {
|
|
63
|
+
opt(s)
|
|
64
|
+
}
|
|
65
|
+
return s
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Usage
|
|
69
|
+
srv := NewServer(
|
|
70
|
+
WithAddr(":9090"),
|
|
71
|
+
WithTimeout(60 * time.Second),
|
|
72
|
+
)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Custom Error Types
|
|
78
|
+
|
|
79
|
+
```go
|
|
80
|
+
type ValidationError struct {
|
|
81
|
+
Field string
|
|
82
|
+
Message string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func (e *ValidationError) Error() string {
|
|
86
|
+
return fmt.Sprintf("validation failed on %s: %s", e.Field, e.Message)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
type NotFoundError struct {
|
|
90
|
+
Resource string
|
|
91
|
+
ID string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func (e *NotFoundError) Error() string {
|
|
95
|
+
return fmt.Sprintf("%s %s not found", e.Resource, e.ID)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Usage with errors.As
|
|
99
|
+
func handleErr(err error) {
|
|
100
|
+
var validErr *ValidationError
|
|
101
|
+
if errors.As(err, &validErr) {
|
|
102
|
+
log.Printf("bad input: field=%s msg=%s", validErr.Field, validErr.Message)
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
var notFound *NotFoundError
|
|
106
|
+
if errors.As(err, ¬Found) {
|
|
107
|
+
log.Printf("missing: %s/%s", notFound.Resource, notFound.ID)
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
log.Printf("unexpected: %v", err)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Middleware Pattern
|
|
117
|
+
|
|
118
|
+
```go
|
|
119
|
+
type Middleware func(http.Handler) http.Handler
|
|
120
|
+
|
|
121
|
+
func Logging(logger *slog.Logger) Middleware {
|
|
122
|
+
return func(next http.Handler) http.Handler {
|
|
123
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
124
|
+
start := time.Now()
|
|
125
|
+
next.ServeHTTP(w, r)
|
|
126
|
+
logger.Info("request",
|
|
127
|
+
"method", r.Method,
|
|
128
|
+
"path", r.URL.Path,
|
|
129
|
+
"duration", time.Since(start),
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func Recovery() Middleware {
|
|
136
|
+
return func(next http.Handler) http.Handler {
|
|
137
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
138
|
+
defer func() {
|
|
139
|
+
if err := recover(); err != nil {
|
|
140
|
+
w.WriteHeader(http.StatusInternalServerError)
|
|
141
|
+
slog.Error("panic recovered", "error", err)
|
|
142
|
+
}
|
|
143
|
+
}()
|
|
144
|
+
next.ServeHTTP(w, r)
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Chain composes middleware in order
|
|
150
|
+
func Chain(handler http.Handler, middlewares ...Middleware) http.Handler {
|
|
151
|
+
for i := len(middlewares) - 1; i >= 0; i-- {
|
|
152
|
+
handler = middlewares[i](handler)
|
|
153
|
+
}
|
|
154
|
+
return handler
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Usage
|
|
158
|
+
mux := http.NewServeMux()
|
|
159
|
+
mux.HandleFunc("/api/users", handleUsers)
|
|
160
|
+
handler := Chain(mux, Recovery(), Logging(logger))
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Graceful Shutdown
|
|
166
|
+
|
|
167
|
+
```go
|
|
168
|
+
func main() {
|
|
169
|
+
srv := &http.Server{Addr: ":8080", Handler: mux}
|
|
170
|
+
|
|
171
|
+
go func() {
|
|
172
|
+
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
|
173
|
+
slog.Error("server error", "error", err)
|
|
174
|
+
}
|
|
175
|
+
}()
|
|
176
|
+
|
|
177
|
+
quit := make(chan os.Signal, 1)
|
|
178
|
+
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
179
|
+
<-quit
|
|
180
|
+
|
|
181
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
182
|
+
defer cancel()
|
|
183
|
+
|
|
184
|
+
if err := srv.Shutdown(ctx); err != nil {
|
|
185
|
+
slog.Error("shutdown error", "error", err)
|
|
186
|
+
}
|
|
187
|
+
slog.Info("server stopped")
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Constructor Pattern
|
|
194
|
+
|
|
195
|
+
```go
|
|
196
|
+
// Validate at construction - enforce invariants
|
|
197
|
+
func NewUser(name, email string) (*User, error) {
|
|
198
|
+
if name == "" {
|
|
199
|
+
return nil, &ValidationError{Field: "name", Message: "required"}
|
|
200
|
+
}
|
|
201
|
+
if !strings.Contains(email, "@") {
|
|
202
|
+
return nil, &ValidationError{Field: "email", Message: "invalid format"}
|
|
203
|
+
}
|
|
204
|
+
return &User{
|
|
205
|
+
ID: uuid.New().String(),
|
|
206
|
+
Name: name,
|
|
207
|
+
Email: email,
|
|
208
|
+
CreatedAt: time.Now(),
|
|
209
|
+
}, nil
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Structured Logging with slog
|
|
216
|
+
|
|
217
|
+
```go
|
|
218
|
+
func ProcessOrder(ctx context.Context, orderID string) error {
|
|
219
|
+
logger := slog.With("order_id", orderID, "trace_id", traceID(ctx))
|
|
220
|
+
|
|
221
|
+
logger.Info("processing order")
|
|
222
|
+
|
|
223
|
+
items, err := fetchItems(ctx, orderID)
|
|
224
|
+
if err != nil {
|
|
225
|
+
logger.Error("failed to fetch items", "error", err)
|
|
226
|
+
return fmt.Errorf("fetching items for order %s: %w", orderID, err)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
logger.Info("items fetched", "count", len(items))
|
|
230
|
+
return nil
|
|
231
|
+
}
|
|
232
|
+
```
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Go Violation Examples
|
|
2
|
+
|
|
3
|
+
Extended violation patterns for Go reviews. Reference from main SKILL.md.
|
|
4
|
+
|
|
5
|
+
## Error Handling Violations
|
|
6
|
+
|
|
7
|
+
### Ignored Errors
|
|
8
|
+
|
|
9
|
+
```go
|
|
10
|
+
// VIOLATION: Silently discarding error
|
|
11
|
+
data, _ := json.Marshal(user)
|
|
12
|
+
w.Write(data)
|
|
13
|
+
|
|
14
|
+
// VIOLATION: Error ignored in deferred call
|
|
15
|
+
defer file.Close() // Close() returns error
|
|
16
|
+
|
|
17
|
+
// VIOLATION: Swallowing error with log
|
|
18
|
+
if err != nil {
|
|
19
|
+
log.Println("something failed") // Error details lost
|
|
20
|
+
return nil
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Unwrapped Errors
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
// VIOLATION: No context on error
|
|
28
|
+
func LoadConfig(path string) (*Config, error) {
|
|
29
|
+
data, err := os.ReadFile(path)
|
|
30
|
+
if err != nil {
|
|
31
|
+
return nil, err // Caller has no idea what failed
|
|
32
|
+
}
|
|
33
|
+
var cfg Config
|
|
34
|
+
if err := json.Unmarshal(data, &cfg); err != nil {
|
|
35
|
+
return nil, err // Which unmarshal? What file?
|
|
36
|
+
}
|
|
37
|
+
return &cfg, nil
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Goroutine Leak Violations
|
|
44
|
+
|
|
45
|
+
### Fire-and-Forget Goroutine
|
|
46
|
+
|
|
47
|
+
```go
|
|
48
|
+
// VIOLATION: No way to stop or wait for this goroutine
|
|
49
|
+
func StartPoller() {
|
|
50
|
+
go func() {
|
|
51
|
+
for {
|
|
52
|
+
poll()
|
|
53
|
+
time.Sleep(10 * time.Second)
|
|
54
|
+
}
|
|
55
|
+
}()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// VIOLATION: Goroutine blocks forever on channel nobody reads
|
|
59
|
+
func process(items []Item) {
|
|
60
|
+
ch := make(chan Result)
|
|
61
|
+
for _, item := range items {
|
|
62
|
+
go func(i Item) {
|
|
63
|
+
ch <- compute(i) // Blocks if nobody reads
|
|
64
|
+
}(item)
|
|
65
|
+
}
|
|
66
|
+
// Only reads first result - rest leak
|
|
67
|
+
result := <-ch
|
|
68
|
+
_ = result
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Missing Context Cancellation
|
|
73
|
+
|
|
74
|
+
```go
|
|
75
|
+
// VIOLATION: Goroutine ignores context
|
|
76
|
+
func Fetch(ctx context.Context, url string) ([]byte, error) {
|
|
77
|
+
ch := make(chan []byte, 1)
|
|
78
|
+
go func() {
|
|
79
|
+
resp, _ := http.Get(url) // Ignores ctx cancellation
|
|
80
|
+
body, _ := io.ReadAll(resp.Body)
|
|
81
|
+
ch <- body
|
|
82
|
+
}()
|
|
83
|
+
return <-ch, nil
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Interface Pollution Violations
|
|
90
|
+
|
|
91
|
+
### Premature Interface Definition
|
|
92
|
+
|
|
93
|
+
```go
|
|
94
|
+
// VIOLATION: Interface defined at producer, not consumer
|
|
95
|
+
package user
|
|
96
|
+
|
|
97
|
+
type UserStore interface { // Only one implementation exists
|
|
98
|
+
Get(id string) (*User, error)
|
|
99
|
+
Save(u *User) error
|
|
100
|
+
Delete(id string) error
|
|
101
|
+
List() ([]*User, error)
|
|
102
|
+
Count() (int, error)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
type PostgresStore struct{ db *sql.DB }
|
|
106
|
+
|
|
107
|
+
func (s *PostgresStore) Get(id string) (*User, error) { ... }
|
|
108
|
+
// ... implements all 5 methods
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### God Interface
|
|
112
|
+
|
|
113
|
+
```go
|
|
114
|
+
// VIOLATION: Interface too large - impossible to mock cleanly
|
|
115
|
+
type Service interface {
|
|
116
|
+
CreateUser(ctx context.Context, u *User) error
|
|
117
|
+
GetUser(ctx context.Context, id string) (*User, error)
|
|
118
|
+
UpdateUser(ctx context.Context, u *User) error
|
|
119
|
+
DeleteUser(ctx context.Context, id string) error
|
|
120
|
+
ListUsers(ctx context.Context) ([]*User, error)
|
|
121
|
+
SendEmail(ctx context.Context, to string, body string) error
|
|
122
|
+
GenerateReport(ctx context.Context) ([]byte, error)
|
|
123
|
+
ProcessPayment(ctx context.Context, amt int) error
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Naked Return Violations
|
|
130
|
+
|
|
131
|
+
```go
|
|
132
|
+
// VIOLATION: Naked returns obscure what's being returned
|
|
133
|
+
func divide(a, b float64) (result float64, err error) {
|
|
134
|
+
if b == 0 {
|
|
135
|
+
err = errors.New("division by zero")
|
|
136
|
+
return // What is result here? Zero - but not obvious
|
|
137
|
+
}
|
|
138
|
+
result = a / b
|
|
139
|
+
return // Have to trace back to find return values
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## init() Abuse Violations
|
|
146
|
+
|
|
147
|
+
```go
|
|
148
|
+
// VIOLATION: Side effects in init - runs on import
|
|
149
|
+
func init() {
|
|
150
|
+
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
|
|
151
|
+
if err != nil {
|
|
152
|
+
log.Fatal(err) // Crashes on import
|
|
153
|
+
}
|
|
154
|
+
globalDB = db
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// VIOLATION: Registration magic in init
|
|
158
|
+
func init() {
|
|
159
|
+
http.HandleFunc("/health", healthCheck) // Hidden route registration
|
|
160
|
+
prometheus.MustRegister(requestCounter) // Panics if called twice
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Mutex Violations
|
|
167
|
+
|
|
168
|
+
```go
|
|
169
|
+
// VIOLATION: Copying mutex (passes by value)
|
|
170
|
+
type Cache struct {
|
|
171
|
+
mu sync.Mutex
|
|
172
|
+
data map[string]string
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
func process(c Cache) { // c is a COPY - mutex is copied too
|
|
176
|
+
c.mu.Lock()
|
|
177
|
+
defer c.mu.Unlock()
|
|
178
|
+
c.data["key"] = "val"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// VIOLATION: Forgetting to unlock
|
|
182
|
+
func (c *Cache) Get(key string) string {
|
|
183
|
+
c.mu.Lock()
|
|
184
|
+
if val, ok := c.data[key]; ok {
|
|
185
|
+
return val // Mutex never unlocked!
|
|
186
|
+
}
|
|
187
|
+
c.mu.Unlock()
|
|
188
|
+
return ""
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Slice and Map Violations
|
|
195
|
+
|
|
196
|
+
```go
|
|
197
|
+
// VIOLATION: Nil map write (runtime panic)
|
|
198
|
+
var m map[string]int
|
|
199
|
+
m["key"] = 1 // panic: assignment to entry in nil map
|
|
200
|
+
|
|
201
|
+
// VIOLATION: Sharing slice backing array
|
|
202
|
+
func getFirstThree(s []int) []int {
|
|
203
|
+
return s[:3] // Shares backing array - mutations leak
|
|
204
|
+
}
|
|
205
|
+
```
|
|
@@ -5,16 +5,30 @@
|
|
|
5
5
|
"name": "DevFlow Contributors",
|
|
6
6
|
"email": "dean@keren.dev"
|
|
7
7
|
},
|
|
8
|
-
"version": "1.
|
|
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": [
|
|
13
|
-
|
|
12
|
+
"keywords": [
|
|
13
|
+
"implementation",
|
|
14
|
+
"coding",
|
|
15
|
+
"workflow",
|
|
16
|
+
"agents",
|
|
17
|
+
"agentic",
|
|
18
|
+
"pr"
|
|
19
|
+
],
|
|
20
|
+
"agents": [
|
|
21
|
+
"git",
|
|
22
|
+
"skimmer",
|
|
23
|
+
"synthesizer",
|
|
24
|
+
"coder",
|
|
25
|
+
"simplifier",
|
|
26
|
+
"scrutinizer",
|
|
27
|
+
"shepherd",
|
|
28
|
+
"validator"
|
|
29
|
+
],
|
|
14
30
|
"skills": [
|
|
15
|
-
"accessibility",
|
|
16
31
|
"agent-teams",
|
|
17
|
-
"frontend-design",
|
|
18
32
|
"implementation-patterns",
|
|
19
33
|
"self-review"
|
|
20
34
|
]
|
|
@@ -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
|
|
|
@@ -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
|
---
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devflow-java",
|
|
3
|
+
"description": "Java language patterns - records, sealed classes, composition, modern Java features",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "DevFlow Contributors",
|
|
6
|
+
"email": "dean@keren.dev"
|
|
7
|
+
},
|
|
8
|
+
"version": "1.3.0",
|
|
9
|
+
"homepage": "https://github.com/dean0x/devflow",
|
|
10
|
+
"repository": "https://github.com/dean0x/devflow",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"java",
|
|
14
|
+
"records",
|
|
15
|
+
"sealed-classes",
|
|
16
|
+
"composition"
|
|
17
|
+
],
|
|
18
|
+
"agents": [],
|
|
19
|
+
"skills": [
|
|
20
|
+
"java"
|
|
21
|
+
]
|
|
22
|
+
}
|