devflow-kit 1.0.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +35 -11
  3. package/dist/cli.js +5 -1
  4. package/dist/commands/ambient.d.ts +18 -0
  5. package/dist/commands/ambient.js +136 -0
  6. package/dist/commands/init.d.ts +2 -0
  7. package/dist/commands/init.js +97 -10
  8. package/dist/commands/memory.d.ts +22 -0
  9. package/dist/commands/memory.js +175 -0
  10. package/dist/commands/uninstall.js +72 -5
  11. package/dist/plugins.js +74 -3
  12. package/dist/utils/post-install.d.ts +12 -0
  13. package/dist/utils/post-install.js +82 -1
  14. package/dist/utils/safe-delete-install.d.ts +7 -0
  15. package/dist/utils/safe-delete-install.js +40 -5
  16. package/package.json +2 -1
  17. package/plugins/devflow-accessibility/.claude-plugin/plugin.json +15 -0
  18. package/plugins/devflow-ambient/.claude-plugin/plugin.json +7 -0
  19. package/plugins/devflow-ambient/README.md +49 -0
  20. package/plugins/devflow-ambient/commands/ambient.md +110 -0
  21. package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +89 -0
  22. package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +68 -0
  23. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
  24. package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -4
  25. package/plugins/devflow-code-review/agents/reviewer.md +8 -0
  26. package/plugins/devflow-code-review/commands/code-review-teams.md +11 -1
  27. package/plugins/devflow-code-review/commands/code-review.md +12 -2
  28. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +3 -6
  29. package/plugins/devflow-core-skills/skills/docs-framework/SKILL.md +10 -6
  30. package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +139 -0
  31. package/plugins/devflow-core-skills/skills/test-driven-development/references/rationalization-prevention.md +111 -0
  32. package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
  33. package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +15 -0
  34. package/plugins/devflow-go/.claude-plugin/plugin.json +15 -0
  35. package/plugins/devflow-go/skills/go/SKILL.md +187 -0
  36. package/plugins/devflow-go/skills/go/references/concurrency.md +312 -0
  37. package/plugins/devflow-go/skills/go/references/detection.md +129 -0
  38. package/plugins/devflow-go/skills/go/references/patterns.md +232 -0
  39. package/plugins/devflow-go/skills/go/references/violations.md +205 -0
  40. package/plugins/devflow-implement/.claude-plugin/plugin.json +1 -3
  41. package/plugins/devflow-implement/agents/coder.md +11 -6
  42. package/plugins/devflow-java/.claude-plugin/plugin.json +15 -0
  43. package/plugins/devflow-java/skills/java/SKILL.md +183 -0
  44. package/plugins/devflow-java/skills/java/references/detection.md +120 -0
  45. package/plugins/devflow-java/skills/java/references/modern-java.md +270 -0
  46. package/plugins/devflow-java/skills/java/references/patterns.md +235 -0
  47. package/plugins/devflow-java/skills/java/references/violations.md +213 -0
  48. package/plugins/devflow-python/.claude-plugin/plugin.json +15 -0
  49. package/plugins/devflow-python/skills/python/SKILL.md +188 -0
  50. package/plugins/devflow-python/skills/python/references/async.md +220 -0
  51. package/plugins/devflow-python/skills/python/references/detection.md +128 -0
  52. package/plugins/devflow-python/skills/python/references/patterns.md +226 -0
  53. package/plugins/devflow-python/skills/python/references/violations.md +204 -0
  54. package/plugins/devflow-react/.claude-plugin/plugin.json +15 -0
  55. package/plugins/{devflow-core-skills → devflow-react}/skills/react/SKILL.md +1 -1
  56. package/plugins/{devflow-core-skills → devflow-react}/skills/react/references/patterns.md +3 -3
  57. package/plugins/devflow-resolve/.claude-plugin/plugin.json +1 -1
  58. package/plugins/devflow-rust/.claude-plugin/plugin.json +15 -0
  59. package/plugins/devflow-rust/skills/rust/SKILL.md +193 -0
  60. package/plugins/devflow-rust/skills/rust/references/detection.md +131 -0
  61. package/plugins/devflow-rust/skills/rust/references/ownership.md +242 -0
  62. package/plugins/devflow-rust/skills/rust/references/patterns.md +210 -0
  63. package/plugins/devflow-rust/skills/rust/references/violations.md +191 -0
  64. package/plugins/devflow-self-review/.claude-plugin/plugin.json +1 -1
  65. package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
  66. package/plugins/devflow-typescript/.claude-plugin/plugin.json +15 -0
  67. package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
  68. package/scripts/hooks/ambient-prompt.sh +48 -0
  69. package/scripts/hooks/background-memory-update.sh +49 -8
  70. package/scripts/hooks/ensure-memory-gitignore.sh +17 -0
  71. package/scripts/hooks/pre-compact-memory.sh +12 -6
  72. package/scripts/hooks/session-start-memory.sh +50 -8
  73. package/scripts/hooks/stop-update-memory.sh +10 -6
  74. package/shared/agents/coder.md +11 -6
  75. package/shared/agents/reviewer.md +8 -0
  76. package/shared/skills/ambient-router/SKILL.md +89 -0
  77. package/shared/skills/ambient-router/references/skill-catalog.md +68 -0
  78. package/shared/skills/docs-framework/SKILL.md +10 -6
  79. package/shared/skills/go/SKILL.md +187 -0
  80. package/shared/skills/go/references/concurrency.md +312 -0
  81. package/shared/skills/go/references/detection.md +129 -0
  82. package/shared/skills/go/references/patterns.md +232 -0
  83. package/shared/skills/go/references/violations.md +205 -0
  84. package/shared/skills/java/SKILL.md +183 -0
  85. package/shared/skills/java/references/detection.md +120 -0
  86. package/shared/skills/java/references/modern-java.md +270 -0
  87. package/shared/skills/java/references/patterns.md +235 -0
  88. package/shared/skills/java/references/violations.md +213 -0
  89. package/shared/skills/python/SKILL.md +188 -0
  90. package/shared/skills/python/references/async.md +220 -0
  91. package/shared/skills/python/references/detection.md +128 -0
  92. package/shared/skills/python/references/patterns.md +226 -0
  93. package/shared/skills/python/references/violations.md +204 -0
  94. package/shared/skills/react/SKILL.md +1 -1
  95. package/shared/skills/react/references/patterns.md +3 -3
  96. package/shared/skills/rust/SKILL.md +193 -0
  97. package/shared/skills/rust/references/detection.md +131 -0
  98. package/shared/skills/rust/references/ownership.md +242 -0
  99. package/shared/skills/rust/references/patterns.md +210 -0
  100. package/shared/skills/rust/references/violations.md +191 -0
  101. package/shared/skills/test-driven-development/SKILL.md +139 -0
  102. package/shared/skills/test-driven-development/references/rationalization-prevention.md +111 -0
  103. package/shared/skills/typescript/references/patterns.md +3 -3
  104. package/src/templates/managed-settings.json +14 -0
  105. package/plugins/devflow-code-review/skills/react/SKILL.md +0 -276
  106. package/plugins/devflow-code-review/skills/react/references/patterns.md +0 -1331
  107. package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +0 -229
  108. package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +0 -171
  109. package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +0 -670
  110. package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +0 -419
  111. package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +0 -254
  112. package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +0 -184
  113. package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +0 -511
  114. package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +0 -453
  115. package/plugins/devflow-core-skills/skills/react/references/violations.md +0 -565
  116. package/plugins/devflow-implement/skills/accessibility/SKILL.md +0 -229
  117. package/plugins/devflow-implement/skills/accessibility/references/detection.md +0 -171
  118. package/plugins/devflow-implement/skills/accessibility/references/patterns.md +0 -670
  119. package/plugins/devflow-implement/skills/accessibility/references/violations.md +0 -419
  120. package/plugins/devflow-implement/skills/frontend-design/SKILL.md +0 -254
  121. package/plugins/devflow-implement/skills/frontend-design/references/detection.md +0 -184
  122. package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +0 -511
  123. package/plugins/devflow-implement/skills/frontend-design/references/violations.md +0 -453
  124. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/SKILL.md +0 -0
  125. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/detection.md +0 -0
  126. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/patterns.md +0 -0
  127. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/violations.md +0 -0
  128. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/SKILL.md +0 -0
  129. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/detection.md +0 -0
  130. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/patterns.md +0 -0
  131. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/violations.md +0 -0
  132. /package/plugins/{devflow-code-review → devflow-react}/skills/react/references/violations.md +0 -0
  133. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/SKILL.md +0 -0
  134. /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, &notFound) {
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
+ ```
@@ -0,0 +1,183 @@
1
+ ---
2
+ name: java
3
+ description: This skill should be used when the user works with Java files (.java), asks about "records", "sealed classes", "Optional", "streams", "composition over inheritance", or discusses modern Java patterns and API design. Provides patterns for type system usage, error handling, immutability, and concurrency.
4
+ user-invocable: false
5
+ allowed-tools: Read, Grep, Glob
6
+ activation:
7
+ file-patterns:
8
+ - "**/*.java"
9
+ exclude:
10
+ - "**/build/**"
11
+ - "**/target/**"
12
+ ---
13
+
14
+ # Java Patterns
15
+
16
+ Reference for modern Java patterns, type system, and best practices.
17
+
18
+ ## Iron Law
19
+
20
+ > **FAVOR COMPOSITION OVER INHERITANCE**
21
+ >
22
+ > Delegation and interfaces over class hierarchies. Inheritance creates tight coupling,
23
+ > breaks encapsulation, and makes refactoring dangerous. Use interfaces for polymorphism,
24
+ > records for data, and sealed classes for restricted hierarchies. Extend only when the
25
+ > "is-a" relationship is genuinely invariant.
26
+
27
+ ## When This Skill Activates
28
+
29
+ - Working with Java codebases
30
+ - Designing APIs with modern Java features
31
+ - Using records, sealed classes, Optional
32
+ - Implementing concurrent code
33
+ - Structuring Java packages
34
+
35
+ ---
36
+
37
+ ## Type System (Modern Java)
38
+
39
+ ### Records for Data
40
+
41
+ ```java
42
+ // BAD: Mutable POJO with getters/setters
43
+ // GOOD: Immutable record
44
+ public record User(String name, String email, Instant createdAt) {
45
+ public User {
46
+ Objects.requireNonNull(name, "name must not be null");
47
+ Objects.requireNonNull(email, "email must not be null");
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### Sealed Classes for Restricted Hierarchies
53
+
54
+ ```java
55
+ public sealed interface Result<T> permits Success, Failure {
56
+ record Success<T>(T value) implements Result<T> {}
57
+ record Failure<T>(String error) implements Result<T> {}
58
+ }
59
+
60
+ // Exhaustive pattern matching (Java 21+)
61
+ switch (result) {
62
+ case Success<User> s -> handleSuccess(s.value());
63
+ case Failure<User> f -> handleError(f.error());
64
+ }
65
+ ```
66
+
67
+ ### Optional for Absent Values
68
+
69
+ ```java
70
+ // BAD: return null;
71
+ // GOOD:
72
+ public Optional<User> findById(String id) {
73
+ return Optional.ofNullable(userMap.get(id));
74
+ }
75
+
76
+ // BAD: if (optional.isPresent()) optional.get()
77
+ // GOOD:
78
+ optional.map(User::name).orElse("Anonymous");
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Error Handling
84
+
85
+ ### Custom Exceptions with Context
86
+
87
+ ```java
88
+ public class EntityNotFoundException extends RuntimeException {
89
+ private final String entityType;
90
+ private final String entityId;
91
+
92
+ public EntityNotFoundException(String entityType, String entityId) {
93
+ super("%s with id %s not found".formatted(entityType, entityId));
94
+ this.entityType = entityType;
95
+ this.entityId = entityId;
96
+ }
97
+ }
98
+ ```
99
+
100
+ ### Try-with-Resources
101
+
102
+ ```java
103
+ // Always use try-with-resources for AutoCloseable
104
+ try (var conn = dataSource.getConnection();
105
+ var stmt = conn.prepareStatement(sql)) {
106
+ stmt.setString(1, id);
107
+ return mapResult(stmt.executeQuery());
108
+ }
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Immutability
114
+
115
+ ```java
116
+ // Prefer unmodifiable collections
117
+ List<String> names = List.of("Alice", "Bob");
118
+ Map<String, Integer> scores = Map.of("Alice", 100, "Bob", 95);
119
+
120
+ // Defensive copies in constructors
121
+ public final class Team {
122
+ private final List<String> members;
123
+ public Team(List<String> members) {
124
+ this.members = List.copyOf(members);
125
+ }
126
+ public List<String> members() { return members; }
127
+ }
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Composition Over Inheritance
133
+
134
+ ```java
135
+ // BAD: class UserService extends BaseService extends AbstractDAO
136
+ // GOOD: compose via constructor injection
137
+ public class UserService {
138
+ private final UserRepository repository;
139
+ private final EventPublisher events;
140
+
141
+ public UserService(UserRepository repository, EventPublisher events) {
142
+ this.repository = repository;
143
+ this.events = events;
144
+ }
145
+ }
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Anti-Patterns
151
+
152
+ | Pattern | Bad | Good |
153
+ |---------|-----|------|
154
+ | Returning null | `return null` | `return Optional.empty()` |
155
+ | Checked exception abuse | `throws Exception` | Specific exceptions or unchecked |
156
+ | Raw types | `List list` | `List<User> list` |
157
+ | Deep inheritance | 4+ level hierarchy | Interfaces + composition |
158
+ | Mutable data objects | `setName()/getName()` | Records or immutable classes |
159
+
160
+ ---
161
+
162
+ ## Extended References
163
+
164
+ For additional patterns and examples:
165
+ - `references/violations.md` - Common Java violations
166
+ - `references/patterns.md` - Extended Java patterns
167
+ - `references/detection.md` - Detection patterns for Java issues
168
+ - `references/modern-java.md` - Modern Java features (17-21+)
169
+
170
+ ---
171
+
172
+ ## Checklist
173
+
174
+ - [ ] Records for pure data types
175
+ - [ ] Sealed interfaces for type hierarchies
176
+ - [ ] Optional instead of null returns
177
+ - [ ] Composition over inheritance
178
+ - [ ] Try-with-resources for all AutoCloseable
179
+ - [ ] Immutable collections (List.of, Map.of)
180
+ - [ ] No raw generic types
181
+ - [ ] Custom exceptions with context
182
+ - [ ] Streams for collection transforms
183
+ - [ ] Constructor injection for dependencies