red64-cli 0.3.0 → 0.6.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 (95) hide show
  1. package/README.md +194 -338
  2. package/dist/cli/parseArgs.d.ts.map +1 -1
  3. package/dist/cli/parseArgs.js +5 -13
  4. package/dist/cli/parseArgs.js.map +1 -1
  5. package/dist/components/init/types.d.ts +0 -2
  6. package/dist/components/init/types.d.ts.map +1 -1
  7. package/dist/components/screens/HelpScreen.d.ts.map +1 -1
  8. package/dist/components/screens/HelpScreen.js +0 -2
  9. package/dist/components/screens/HelpScreen.js.map +1 -1
  10. package/dist/components/screens/InitScreen.d.ts.map +1 -1
  11. package/dist/components/screens/InitScreen.js +5 -8
  12. package/dist/components/screens/InitScreen.js.map +1 -1
  13. package/dist/components/screens/StartScreen.d.ts.map +1 -1
  14. package/dist/components/screens/StartScreen.js +29 -8
  15. package/dist/components/screens/StartScreen.js.map +1 -1
  16. package/dist/components/screens/StatusScreen.d.ts.map +1 -1
  17. package/dist/components/screens/StatusScreen.js +16 -1
  18. package/dist/components/screens/StatusScreen.js.map +1 -1
  19. package/dist/services/AgentInvoker.d.ts.map +1 -1
  20. package/dist/services/AgentInvoker.js +76 -37
  21. package/dist/services/AgentInvoker.js.map +1 -1
  22. package/dist/services/ClaudeErrorDetector.d.ts +1 -1
  23. package/dist/services/ClaudeErrorDetector.d.ts.map +1 -1
  24. package/dist/services/ClaudeErrorDetector.js +1 -0
  25. package/dist/services/ClaudeErrorDetector.js.map +1 -1
  26. package/dist/services/ClaudeHealthCheck.d.ts +7 -0
  27. package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
  28. package/dist/services/ClaudeHealthCheck.js +76 -12
  29. package/dist/services/ClaudeHealthCheck.js.map +1 -1
  30. package/dist/services/ConfigService.d.ts +1 -0
  31. package/dist/services/ConfigService.d.ts.map +1 -1
  32. package/dist/services/ConfigService.js.map +1 -1
  33. package/dist/services/DockerRunner.js +1 -1
  34. package/dist/services/DockerRunner.js.map +1 -1
  35. package/dist/services/PhaseExecutor.d.ts.map +1 -1
  36. package/dist/services/PhaseExecutor.js +2 -1
  37. package/dist/services/PhaseExecutor.js.map +1 -1
  38. package/dist/services/TaskRunner.d.ts.map +1 -1
  39. package/dist/services/TaskRunner.js +2 -1
  40. package/dist/services/TaskRunner.js.map +1 -1
  41. package/dist/services/index.d.ts +1 -1
  42. package/dist/services/index.d.ts.map +1 -1
  43. package/dist/services/index.js +1 -1
  44. package/dist/services/index.js.map +1 -1
  45. package/dist/types/index.d.ts +4 -3
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/types/index.js.map +1 -1
  48. package/framework/stacks/c/code-quality.md +326 -0
  49. package/framework/stacks/c/coding-style.md +347 -0
  50. package/framework/stacks/c/conventions.md +513 -0
  51. package/framework/stacks/c/error-handling.md +350 -0
  52. package/framework/stacks/c/feedback.md +158 -0
  53. package/framework/stacks/c/memory-safety.md +408 -0
  54. package/framework/stacks/c/tech.md +122 -0
  55. package/framework/stacks/c/testing.md +472 -0
  56. package/framework/stacks/cpp/code-quality.md +282 -0
  57. package/framework/stacks/cpp/coding-style.md +363 -0
  58. package/framework/stacks/cpp/conventions.md +420 -0
  59. package/framework/stacks/cpp/error-handling.md +264 -0
  60. package/framework/stacks/cpp/feedback.md +104 -0
  61. package/framework/stacks/cpp/memory-safety.md +351 -0
  62. package/framework/stacks/cpp/tech.md +160 -0
  63. package/framework/stacks/cpp/testing.md +323 -0
  64. package/framework/stacks/java/code-quality.md +357 -0
  65. package/framework/stacks/java/coding-style.md +400 -0
  66. package/framework/stacks/java/conventions.md +437 -0
  67. package/framework/stacks/java/error-handling.md +408 -0
  68. package/framework/stacks/java/feedback.md +180 -0
  69. package/framework/stacks/java/tech.md +126 -0
  70. package/framework/stacks/java/testing.md +485 -0
  71. package/framework/stacks/javascript/async-patterns.md +216 -0
  72. package/framework/stacks/javascript/code-quality.md +182 -0
  73. package/framework/stacks/javascript/coding-style.md +293 -0
  74. package/framework/stacks/javascript/conventions.md +268 -0
  75. package/framework/stacks/javascript/error-handling.md +216 -0
  76. package/framework/stacks/javascript/feedback.md +80 -0
  77. package/framework/stacks/javascript/tech.md +114 -0
  78. package/framework/stacks/javascript/testing.md +209 -0
  79. package/framework/stacks/loco/code-quality.md +156 -0
  80. package/framework/stacks/loco/coding-style.md +247 -0
  81. package/framework/stacks/loco/error-handling.md +225 -0
  82. package/framework/stacks/loco/feedback.md +35 -0
  83. package/framework/stacks/loco/loco.md +342 -0
  84. package/framework/stacks/loco/structure.md +193 -0
  85. package/framework/stacks/loco/tech.md +129 -0
  86. package/framework/stacks/loco/testing.md +211 -0
  87. package/framework/stacks/rust/code-quality.md +370 -0
  88. package/framework/stacks/rust/coding-style.md +475 -0
  89. package/framework/stacks/rust/conventions.md +430 -0
  90. package/framework/stacks/rust/error-handling.md +399 -0
  91. package/framework/stacks/rust/feedback.md +152 -0
  92. package/framework/stacks/rust/memory-safety.md +398 -0
  93. package/framework/stacks/rust/tech.md +121 -0
  94. package/framework/stacks/rust/testing.md +528 -0
  95. package/package.json +14 -2
@@ -0,0 +1,408 @@
1
+ # Error Handling Patterns
2
+
3
+ Structured error handling for Java 21+ applications with Spring Boot, custom exception hierarchies, Problem Details (RFC 9457), and sealed result types.
4
+
5
+ ---
6
+
7
+ ## Philosophy
8
+
9
+ - **Fail fast**: Validate inputs early, throw immediately on invalid state
10
+ - **Unchecked over checked**: Prefer `RuntimeException` subclasses; checked exceptions create coupling
11
+ - **Centralized handling**: `@ControllerAdvice` at the API boundary, not scattered try/catch
12
+ - **Structured responses**: Problem Details (RFC 9457) for consistent, machine-readable error payloads
13
+
14
+ ---
15
+
16
+ ## Custom Exception Hierarchy
17
+
18
+ ### Base Exceptions
19
+
20
+ ```java
21
+ // src/main/java/com/example/common/exception/AppException.java
22
+ public abstract class AppException extends RuntimeException {
23
+
24
+ private final String errorCode;
25
+ private final int statusCode;
26
+ private final Map<String, Object> details;
27
+
28
+ protected AppException(String message, String errorCode, int statusCode) {
29
+ this(message, errorCode, statusCode, Map.of());
30
+ }
31
+
32
+ protected AppException(String message, String errorCode, int statusCode, Map<String, Object> details) {
33
+ super(message);
34
+ this.errorCode = errorCode;
35
+ this.statusCode = statusCode;
36
+ this.details = details;
37
+ }
38
+
39
+ public String getErrorCode() { return errorCode; }
40
+ public int getStatusCode() { return statusCode; }
41
+ public Map<String, Object> getDetails() { return details; }
42
+ }
43
+ ```
44
+
45
+ ### Concrete Exceptions
46
+
47
+ ```java
48
+ public class NotFoundException extends AppException {
49
+ public NotFoundException(String resource, Object identifier) {
50
+ super(
51
+ "%s not found: %s".formatted(resource, identifier),
52
+ "NOT_FOUND",
53
+ 404,
54
+ Map.of("resource", resource, "identifier", identifier.toString())
55
+ );
56
+ }
57
+ }
58
+
59
+ public class ConflictException extends AppException {
60
+ public ConflictException(String message) {
61
+ super(message, "CONFLICT", 409);
62
+ }
63
+ }
64
+
65
+ public class ValidationException extends AppException {
66
+ public ValidationException(String message, Map<String, String> fieldErrors) {
67
+ super(message, "VALIDATION_ERROR", 422, Map.of("fieldErrors", fieldErrors));
68
+ }
69
+
70
+ public ValidationException(String message) {
71
+ this(message, Map.of());
72
+ }
73
+ }
74
+
75
+ public class ForbiddenException extends AppException {
76
+ public ForbiddenException(String message) {
77
+ super(message, "FORBIDDEN", 403);
78
+ }
79
+ }
80
+
81
+ public class ExternalServiceException extends AppException {
82
+ public ExternalServiceException(String service, String message, Throwable cause) {
83
+ super("External service error (%s): %s".formatted(service, message), "EXTERNAL_SERVICE_ERROR", 502,
84
+ Map.of("service", service));
85
+ initCause(cause);
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### Usage in Services
91
+
92
+ ```java
93
+ @Service
94
+ public class UserService {
95
+
96
+ private final UserRepository userRepository;
97
+
98
+ public User getUser(Long id) {
99
+ return userRepository.findById(id)
100
+ .orElseThrow(() -> new NotFoundException("User", id));
101
+ }
102
+
103
+ public User createUser(CreateUserRequest request) {
104
+ userRepository.findByEmail(request.email()).ifPresent(existing -> {
105
+ throw new ConflictException("Email already registered: " + request.email());
106
+ });
107
+ var user = new User(request.email(), request.name());
108
+ return userRepository.save(user);
109
+ }
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Spring @ControllerAdvice (Problem Details)
116
+
117
+ ### Global Exception Handler
118
+
119
+ Spring Boot 3.x supports RFC 9457 Problem Details natively via `ProblemDetail`:
120
+
121
+ ```java
122
+ @RestControllerAdvice
123
+ public class GlobalExceptionHandler {
124
+
125
+ private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
126
+
127
+ @ExceptionHandler(AppException.class)
128
+ public ProblemDetail handleAppException(AppException ex, HttpServletRequest request) {
129
+ log.warn("app_error: code={}, message={}, path={}",
130
+ ex.getErrorCode(), ex.getMessage(), request.getRequestURI());
131
+
132
+ var problem = ProblemDetail.forStatusAndDetail(
133
+ HttpStatusCode.valueOf(ex.getStatusCode()),
134
+ ex.getMessage()
135
+ );
136
+ problem.setTitle(ex.getErrorCode());
137
+ problem.setProperty("errorCode", ex.getErrorCode());
138
+ if (!ex.getDetails().isEmpty()) {
139
+ problem.setProperty("details", ex.getDetails());
140
+ }
141
+ return problem;
142
+ }
143
+
144
+ @ExceptionHandler(MethodArgumentNotValidException.class)
145
+ public ProblemDetail handleValidation(MethodArgumentNotValidException ex) {
146
+ var fieldErrors = ex.getBindingResult().getFieldErrors().stream()
147
+ .collect(Collectors.toMap(
148
+ FieldError::getField,
149
+ fe -> fe.getDefaultMessage() != null ? fe.getDefaultMessage() : "invalid",
150
+ (a, b) -> a
151
+ ));
152
+
153
+ var problem = ProblemDetail.forStatusAndDetail(
154
+ HttpStatus.UNPROCESSABLE_ENTITY,
155
+ "Validation failed"
156
+ );
157
+ problem.setTitle("VALIDATION_ERROR");
158
+ problem.setProperty("fieldErrors", fieldErrors);
159
+ return problem;
160
+ }
161
+
162
+ @ExceptionHandler(Exception.class)
163
+ public ProblemDetail handleUnexpected(Exception ex, HttpServletRequest request) {
164
+ log.error("unhandled_error: path={}, method={}", request.getRequestURI(), request.getMethod(), ex);
165
+
166
+ var problem = ProblemDetail.forStatusAndDetail(
167
+ HttpStatus.INTERNAL_SERVER_ERROR,
168
+ "An unexpected error occurred"
169
+ );
170
+ problem.setTitle("INTERNAL_ERROR");
171
+ return problem;
172
+ }
173
+ }
174
+ ```
175
+
176
+ ### Enable Problem Details in Spring Boot
177
+
178
+ ```yaml
179
+ # application.yml
180
+ spring:
181
+ mvc:
182
+ problemdetails:
183
+ enabled: true
184
+ ```
185
+
186
+ ### Example Response (RFC 9457)
187
+
188
+ ```json
189
+ {
190
+ "type": "about:blank",
191
+ "title": "NOT_FOUND",
192
+ "status": 404,
193
+ "detail": "User not found: 42",
194
+ "instance": "/api/v1/users/42",
195
+ "errorCode": "NOT_FOUND",
196
+ "details": {
197
+ "resource": "User",
198
+ "identifier": "42"
199
+ }
200
+ }
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Checked vs Unchecked Exceptions
206
+
207
+ ### Decision Table
208
+
209
+ | Scenario | Exception Type | Rationale |
210
+ |---|---|---|
211
+ | Business logic violations | Unchecked (`AppException`) | Caller should not be forced to handle |
212
+ | Resource not found | Unchecked (`NotFoundException`) | Common flow, handled centrally |
213
+ | External service failure | Unchecked (`ExternalServiceException`) | Wrap and rethrow |
214
+ | File I/O (must handle) | Checked (wrap in unchecked) | Convert at boundary |
215
+ | Programmatic errors (bugs) | Unchecked (`IllegalStateException`) | Should never be caught |
216
+
217
+ ### Wrapping Checked Exceptions
218
+
219
+ ```java
220
+ // GOOD: Wrap checked exception at the boundary
221
+ public byte[] readConfig(Path path) {
222
+ try {
223
+ return Files.readAllBytes(path);
224
+ } catch (IOException e) {
225
+ throw new ConfigurationException("Failed to read config: " + path, e);
226
+ }
227
+ }
228
+
229
+ // BAD: Propagating checked exceptions through the entire call chain
230
+ public byte[] readConfig(Path path) throws IOException { // forces all callers to handle
231
+ return Files.readAllBytes(path);
232
+ }
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Result Pattern with Sealed Interfaces
238
+
239
+ For expected business outcomes where exceptions feel too heavy:
240
+
241
+ ```java
242
+ public sealed interface Result<T>
243
+ permits Result.Success, Result.Failure {
244
+
245
+ record Success<T>(T value) implements Result<T> {}
246
+ record Failure<T>(String error, String code) implements Result<T> {}
247
+
248
+ default T orElseThrow() {
249
+ return switch (this) {
250
+ case Success<T> s -> s.value();
251
+ case Failure<T> f -> throw new AppException(f.error(), f.code(), 400) {};
252
+ };
253
+ }
254
+
255
+ default <R> Result<R> map(Function<T, R> mapper) {
256
+ return switch (this) {
257
+ case Success<T> s -> new Success<>(mapper.apply(s.value()));
258
+ case Failure<T> f -> new Failure<>(f.error(), f.code());
259
+ };
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### Usage
265
+
266
+ ```java
267
+ public Result<User> createUser(CreateUserRequest request) {
268
+ if (userRepository.existsByEmail(request.email())) {
269
+ return new Result.Failure<>("Email already registered", "DUPLICATE_EMAIL");
270
+ }
271
+ var user = new User(request.email(), request.name());
272
+ return new Result.Success<>(userRepository.save(user));
273
+ }
274
+
275
+ // Caller
276
+ Result<User> result = userService.createUser(request);
277
+ return switch (result) {
278
+ case Result.Success<User> s -> ResponseEntity.created(uri).body(UserResponse.from(s.value()));
279
+ case Result.Failure<User> f -> ResponseEntity.status(409).body(ProblemDetail.forStatusAndDetail(
280
+ HttpStatus.CONFLICT, f.error()));
281
+ };
282
+ ```
283
+
284
+ ### When to Use Each
285
+
286
+ | Pattern | Use Case |
287
+ |---|---|
288
+ | Exceptions | Infrastructure errors, auth failures, unexpected failures |
289
+ | Result | Expected business outcomes (duplicate email, insufficient funds, validation) |
290
+
291
+ ---
292
+
293
+ ## Exception Chaining
294
+
295
+ Always preserve the original cause:
296
+
297
+ ```java
298
+ // GOOD: Chain with cause
299
+ try {
300
+ var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
301
+ } catch (IOException | InterruptedException e) {
302
+ throw new ExternalServiceException("payment-api", e.getMessage(), e);
303
+ }
304
+
305
+ // BAD: Losing the original cause
306
+ try {
307
+ var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
308
+ } catch (IOException e) {
309
+ throw new ExternalServiceException("payment-api", "request failed", null); // cause lost!
310
+ }
311
+ ```
312
+
313
+ ---
314
+
315
+ ## Retry with Resilience4j
316
+
317
+ ```java
318
+ @Service
319
+ public class PaymentClient {
320
+
321
+ private final RetryRegistry retryRegistry;
322
+
323
+ @Retry(name = "paymentService", fallbackMethod = "paymentFallback")
324
+ public PaymentResult charge(long amountCents, String token) {
325
+ // HTTP call to payment provider
326
+ return restClient.post()
327
+ .uri("/charges")
328
+ .body(new ChargeRequest(amountCents, token))
329
+ .retrieve()
330
+ .body(PaymentResult.class);
331
+ }
332
+
333
+ private PaymentResult paymentFallback(long amountCents, String token, Exception ex) {
334
+ log.error("payment_failed_after_retries: amount={}, error={}", amountCents, ex.getMessage());
335
+ throw new ExternalServiceException("payment", "Payment service unavailable", ex);
336
+ }
337
+ }
338
+ ```
339
+
340
+ ```yaml
341
+ # application.yml
342
+ resilience4j:
343
+ retry:
344
+ instances:
345
+ paymentService:
346
+ maxAttempts: 3
347
+ waitDuration: 1s
348
+ exponentialBackoffMultiplier: 2
349
+ retryExceptions:
350
+ - java.io.IOException
351
+ - org.springframework.web.client.ResourceAccessException
352
+ ignoreExceptions:
353
+ - com.example.common.exception.ValidationException
354
+ ```
355
+
356
+ ---
357
+
358
+ ## What Never to Catch
359
+
360
+ ```java
361
+ // BAD: Never catch Throwable -- includes OutOfMemoryError, StackOverflowError
362
+ try {
363
+ process();
364
+ } catch (Throwable t) {
365
+ log.error("Something happened", t);
366
+ }
367
+
368
+ // BAD: Never catch and silently swallow
369
+ try {
370
+ riskyOperation();
371
+ } catch (Exception e) {
372
+ // swallowed -- silent failure, impossible to debug
373
+ }
374
+
375
+ // BAD: Catching InterruptedException without restoring interrupt status
376
+ try {
377
+ Thread.sleep(1000);
378
+ } catch (InterruptedException e) {
379
+ // Thread interrupt flag is cleared -- must restore it
380
+ }
381
+
382
+ // GOOD: Restore interrupt status
383
+ try {
384
+ Thread.sleep(1000);
385
+ } catch (InterruptedException e) {
386
+ Thread.currentThread().interrupt();
387
+ throw new ServiceException("Operation interrupted", e);
388
+ }
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Anti-Patterns
394
+
395
+ | Anti-Pattern | Problem | Correct Approach |
396
+ |---|---|---|
397
+ | Catching `Throwable` | Catches `Error` (OOM, StackOverflow) | Catch specific exceptions |
398
+ | Empty catch blocks | Silent failures, impossible to debug | Log and rethrow or handle properly |
399
+ | Checked exceptions everywhere | Forces boilerplate on every caller | Wrap in `RuntimeException` subclass |
400
+ | Returning error codes/strings | No type safety, easy to ignore | Use `Result` type or throw |
401
+ | Stack traces in API responses | Security risk, bad UX | `ProblemDetail` with safe messages |
402
+ | `Exception` as method signature | Caller has no idea what to expect | Declare specific exceptions or use unchecked |
403
+ | `try/catch` around every method | Cluttered, hides control flow | Centralized `@ControllerAdvice` |
404
+ | `e.printStackTrace()` | Goes to stderr, not structured logging | Use SLF4J logger |
405
+
406
+ ---
407
+
408
+ _Errors are data. Classify them in a hierarchy, handle them centrally, and present them as Problem Details. Never swallow exceptions silently._
@@ -0,0 +1,180 @@
1
+ # Feedback Configuration
2
+
3
+ Project-specific commands for automated feedback during Java implementation with Gradle.
4
+
5
+ ---
6
+
7
+ ## Test Commands
8
+
9
+ Commands to run tests during implementation. The agent will use these to verify code changes.
10
+
11
+ ```yaml
12
+ # Primary test command (REQUIRED)
13
+ test: ./gradlew test
14
+
15
+ # Test with verbose output
16
+ test_verbose: ./gradlew test --info
17
+
18
+ # Run specific test class (use {class} as placeholder)
19
+ test_class: ./gradlew test --tests "{class}"
20
+
21
+ # Run tests matching pattern
22
+ test_pattern: ./gradlew test --tests "*{pattern}*"
23
+
24
+ # Run only unit tests (by directory convention)
25
+ test_unit: ./gradlew test --tests "com.example.unit.*"
26
+
27
+ # Run only integration tests
28
+ test_integration: ./gradlew test --tests "com.example.integration.*"
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Build Commands
34
+
35
+ Commands for compiling and packaging.
36
+
37
+ ```yaml
38
+ # Full build (compile + test + check)
39
+ build: ./gradlew build
40
+
41
+ # Compile only (no tests)
42
+ compile: ./gradlew compileJava
43
+
44
+ # Clean build
45
+ clean_build: ./gradlew clean build
46
+
47
+ # Build without tests (use sparingly)
48
+ build_skip_tests: ./gradlew build -x test
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Linting and Quality Commands
54
+
55
+ Commands for code quality checks.
56
+
57
+ ```yaml
58
+ # Run all verification tasks (checkstyle + spotbugs + tests)
59
+ check: ./gradlew check
60
+
61
+ # Checkstyle (style enforcement)
62
+ checkstyle: ./gradlew checkstyleMain checkstyleTest
63
+
64
+ # SpotBugs (bug detection)
65
+ spotbugs: ./gradlew spotbugsMain
66
+
67
+ # Spotless format check
68
+ format_check: ./gradlew spotlessCheck
69
+
70
+ # Spotless auto-format
71
+ format_fix: ./gradlew spotlessApply
72
+
73
+ # SonarQube analysis
74
+ sonar: ./gradlew sonar
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Coverage Commands
80
+
81
+ Commands for test coverage reporting.
82
+
83
+ ```yaml
84
+ # Generate coverage report
85
+ coverage: ./gradlew test jacocoTestReport
86
+
87
+ # Enforce coverage thresholds
88
+ coverage_verify: ./gradlew jacocoTestCoverageVerification
89
+
90
+ # Report location
91
+ coverage_report: build/reports/jacoco/test/html/index.html
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Database Commands
97
+
98
+ Commands for database migrations.
99
+
100
+ ```yaml
101
+ # Apply pending migrations
102
+ migrate: ./gradlew flywayMigrate
103
+
104
+ # Show migration status
105
+ migrate_info: ./gradlew flywayInfo
106
+
107
+ # Clean database (DANGER: drops all objects)
108
+ migrate_clean: ./gradlew flywayClean
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Development Server
114
+
115
+ Commands for starting the development server.
116
+
117
+ ```yaml
118
+ # Start dev server (Spring Boot)
119
+ dev_server: ./gradlew bootRun
120
+
121
+ # Dev server with specific profile
122
+ dev_server_profile: SPRING_PROFILES_ACTIVE=dev ./gradlew bootRun
123
+
124
+ # Dev server port
125
+ dev_port: 8080
126
+
127
+ # Dev server base URL
128
+ dev_url: http://localhost:8080
129
+
130
+ # API documentation URL
131
+ api_docs_url: http://localhost:8080/swagger-ui.html
132
+ ```
133
+
134
+ ---
135
+
136
+ ## UI Verification
137
+
138
+ Settings for agent-browser UI verification.
139
+
140
+ ```yaml
141
+ # Enable UI verification (typically false for API-only projects)
142
+ ui_verification_enabled: false
143
+
144
+ # Default wait time after navigation (milliseconds)
145
+ navigation_wait: 2000
146
+
147
+ # Screenshot directory
148
+ screenshot_dir: /tmp/ui-captures
149
+
150
+ # API documentation URL (for API projects)
151
+ api_docs_url: http://localhost:8080/swagger-ui.html
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Quick Reference
157
+
158
+ ```bash
159
+ # Full CI pipeline (what CI runs)
160
+ ./gradlew clean build check jacocoTestReport
161
+
162
+ # Quick local development cycle
163
+ ./gradlew spotlessApply && ./gradlew check
164
+
165
+ # Fast feedback (compile + single test)
166
+ ./gradlew compileJava && ./gradlew test --tests "UserServiceTest"
167
+
168
+ # Format, lint, test -- one command
169
+ ./gradlew spotlessApply check
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Notes
175
+
176
+ - Uses Gradle wrapper (`./gradlew`) for reproducible builds -- never use system Gradle
177
+ - Spotless replaces manual formatting discussions -- run `spotlessApply` before committing
178
+ - `./gradlew check` runs checkstyle, spotbugs, tests, and JaCoCo verification in one command
179
+ - For Spring Boot apps, `bootRun` uses virtual threads when `spring.threads.virtual.enabled=true`
180
+ - Testcontainers requires Docker to be running for integration tests
@@ -0,0 +1,126 @@
1
+ # Technology Stack
2
+
3
+ ## Architecture
4
+
5
+ Modern Java application with virtual-thread-first design. Spring Boot 3.x or Quarkus as web framework, PostgreSQL for persistence, Redis for caching, Docker for deployment.
6
+
7
+ ---
8
+
9
+ ## Core Technologies
10
+
11
+ - **Language**: Java 21+ (LTS)
12
+ - **Build Tool**: Gradle (Kotlin DSL) or Maven
13
+ - **Web Framework**: Spring Boot 3.x (enterprise) or Quarkus (cloud-native) or Micronaut
14
+ - **Database**: PostgreSQL with Spring Data JPA / Hibernate
15
+ - **Cache/Queue**: Redis with Spring Data Redis or Lettuce
16
+
17
+ ---
18
+
19
+ ## Key Libraries
20
+
21
+ ### Web & API
22
+ - **Spring Boot 3.x**: Production-ready framework with auto-configuration
23
+ - **Spring WebMVC**: Servlet-based web framework (virtual threads recommended)
24
+ - **Spring WebFlux**: Reactive web framework (when reactive streams required)
25
+ - **Jackson**: JSON serialization/deserialization
26
+ - **SpringDoc OpenAPI**: API documentation (Swagger UI)
27
+
28
+ ### Database & Storage
29
+ - **Spring Data JPA**: Repository abstraction over Hibernate
30
+ - **Hibernate 6.x**: ORM with Jakarta Persistence API
31
+ - **Flyway**: Database migrations (preferred) or Liquibase
32
+ - **jOOQ**: Type-safe SQL DSL (alternative to JPA for complex queries)
33
+ - **HikariCP**: Connection pooling (Spring Boot default)
34
+
35
+ ### Background Tasks
36
+ - **Spring Scheduler**: `@Scheduled` for cron-like jobs
37
+ - **Spring Integration**: Enterprise integration patterns
38
+ - **Spring Batch**: Large-scale batch processing
39
+
40
+ ### Deployment
41
+ - **Docker**: Containerized deployment (multi-stage builds)
42
+ - **Docker Compose**: Multi-service local development
43
+ - **GraalVM Native Image**: Optional ahead-of-time compilation (Quarkus/Micronaut)
44
+
45
+ ---
46
+
47
+ ## Development Standards
48
+
49
+ ### Code Quality
50
+ - **Spotless** or **google-java-format**: Code formatting
51
+ - **Checkstyle**: Style enforcement (Google or Sun conventions)
52
+ - **SpotBugs**: Static analysis for bug patterns
53
+ - **Error Prone**: Compile-time error detection (Google)
54
+ - **SonarQube**: Continuous code quality inspection
55
+
56
+ ### Security
57
+ - **Spring Security 6**: Authentication and authorization
58
+ - **OWASP Dependency-Check**: Dependency vulnerability scanning
59
+ - **Spring Vault**: Secrets management (when needed)
60
+
61
+ ### Testing
62
+ - **JUnit 5**: Test framework with `@Test`, `@ParameterizedTest`, `@Nested`
63
+ - **Mockito**: Mocking framework
64
+ - **AssertJ**: Fluent assertion library
65
+ - **Testcontainers**: Docker-based integration testing
66
+ - **Spring Boot Test**: `@SpringBootTest`, `@WebMvcTest`, `@DataJpaTest`
67
+ - **ArchUnit**: Architecture rule enforcement
68
+
69
+ ---
70
+
71
+ ## Development Environment
72
+
73
+ ### Required Tools
74
+ - Java 21+ (see `.java-version` or `.sdkmanrc`)
75
+ - Gradle 8.x or Maven 3.9+
76
+ - PostgreSQL 16+
77
+ - Redis 7+
78
+ - Docker & Docker Compose
79
+
80
+ ### Common Commands
81
+ ```bash
82
+ # Environment setup
83
+ ./gradlew build # Build project
84
+ ./gradlew dependencies # Show dependency tree
85
+
86
+ # Dev server
87
+ ./gradlew bootRun # Spring Boot
88
+ ./mvnw spring-boot:run # Maven alternative
89
+
90
+ # Tests
91
+ ./gradlew test # All tests
92
+ ./gradlew test --tests "*.unit.*" # Unit tests only
93
+ ./gradlew test jacocoTestReport # With coverage
94
+
95
+ # Code quality
96
+ ./gradlew checkstyleMain # Checkstyle
97
+ ./gradlew spotlessCheck # Format check
98
+ ./gradlew spotlessApply # Auto-format
99
+ ./gradlew spotbugsMain # SpotBugs analysis
100
+
101
+ # Database
102
+ ./gradlew flywayMigrate # Apply migrations
103
+ ./gradlew flywayInfo # Migration status
104
+
105
+ # Docker
106
+ docker compose up -d # Start services
107
+ docker compose logs -f app # Follow app logs
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Key Technical Decisions
113
+
114
+ | Decision | Rationale |
115
+ |----------|-----------|
116
+ | **Java 21 over 17** | Virtual threads, record patterns, pattern matching for switch, sequenced collections |
117
+ | **Gradle Kotlin DSL over Groovy** | Type-safe build scripts, IDE autocompletion, refactoring support |
118
+ | **Spring Boot 3.x over 2.x** | Jakarta EE 10, ProblemDetail support, virtual threads, GraalVM native |
119
+ | **Flyway over Liquibase** | SQL-based migrations, simpler mental model, widely adopted |
120
+ | **AssertJ over Hamcrest** | Fluent API, better error messages, IDE discoverability |
121
+ | **Testcontainers over H2** | Production-parity testing, real database behavior, Docker-based |
122
+ | **Virtual threads over reactive** | Simpler programming model, familiar blocking code, JVM-managed scalability |
123
+
124
+ ---
125
+
126
+ _Document standards and patterns, not every dependency. See individual steering files for detailed conventions._