@mrciphersmith/keryx 0.3.5 → 0.3.6

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 (76) hide show
  1. package/dist/cli.js +872 -316
  2. package/docs/README.md +2 -0
  3. package/package.json +1 -1
  4. package/src/gdskills/bundled/install-manifest.json +319 -76
  5. package/src/gdskills/bundled/stacks/django/agent-refs.json +3 -0
  6. package/src/gdskills/bundled/stacks/django/governance/eval.json +1763 -0
  7. package/src/gdskills/bundled/stacks/django/governance/scout.json +40 -0
  8. package/src/gdskills/bundled/stacks/django/pack.json +43 -0
  9. package/src/gdskills/bundled/stacks/django/rules/coding-style.mdc +80 -0
  10. package/src/gdskills/bundled/stacks/django/rules/patterns.mdc +92 -0
  11. package/src/gdskills/bundled/stacks/django/rules/security.mdc +92 -0
  12. package/src/gdskills/bundled/stacks/django/rules/testing.mdc +89 -0
  13. package/src/gdskills/bundled/stacks/django/skills/django-build-fix/SKILL.md +149 -0
  14. package/src/gdskills/bundled/stacks/django/skills/django-build-fix/evals.json +49 -0
  15. package/src/gdskills/bundled/stacks/django/skills/django-code-review/SKILL.md +137 -0
  16. package/src/gdskills/bundled/stacks/django/skills/django-code-review/evals.json +48 -0
  17. package/src/gdskills/bundled/stacks/django/skills/django-implementation/SKILL.md +147 -0
  18. package/src/gdskills/bundled/stacks/django/skills/django-implementation/evals.json +75 -0
  19. package/src/gdskills/bundled/stacks/django/skills/django-migrate/SKILL.md +166 -0
  20. package/src/gdskills/bundled/stacks/django/skills/django-migrate/evals.json +49 -0
  21. package/src/gdskills/bundled/stacks/django/skills/django-testing/SKILL.md +130 -0
  22. package/src/gdskills/bundled/stacks/django/skills/django-testing/evals.json +48 -0
  23. package/src/gdskills/bundled/stacks/fastapi/agent-refs.json +3 -0
  24. package/src/gdskills/bundled/stacks/fastapi/governance/eval.json +1777 -0
  25. package/src/gdskills/bundled/stacks/fastapi/governance/scout.json +34 -0
  26. package/src/gdskills/bundled/stacks/fastapi/pack.json +43 -0
  27. package/src/gdskills/bundled/stacks/fastapi/rules/coding-style.mdc +68 -0
  28. package/src/gdskills/bundled/stacks/fastapi/rules/patterns.mdc +108 -0
  29. package/src/gdskills/bundled/stacks/fastapi/rules/security.mdc +99 -0
  30. package/src/gdskills/bundled/stacks/fastapi/rules/testing.mdc +85 -0
  31. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/SKILL.md +157 -0
  32. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/evals.json +76 -0
  33. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/SKILL.md +150 -0
  34. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/evals.json +74 -0
  35. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/SKILL.md +158 -0
  36. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/evals.json +75 -0
  37. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/SKILL.md +146 -0
  38. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/evals.json +74 -0
  39. package/src/gdskills/bundled/stacks/java-kotlin-spring/agent-refs.json +3 -0
  40. package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/eval.json +2194 -0
  41. package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/scout.json +39 -0
  42. package/src/gdskills/bundled/stacks/java-kotlin-spring/pack.json +40 -0
  43. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/coding-style.mdc +67 -0
  44. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/patterns.mdc +65 -0
  45. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/security.mdc +69 -0
  46. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/testing.mdc +80 -0
  47. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/SKILL.md +144 -0
  48. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/evals.json +74 -0
  49. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/SKILL.md +129 -0
  50. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/evals.json +74 -0
  51. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/SKILL.md +147 -0
  52. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/evals.json +75 -0
  53. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/SKILL.md +139 -0
  54. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/evals.json +74 -0
  55. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/SKILL.md +128 -0
  56. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/evals.json +73 -0
  57. package/src/gdskills/bundled/stacks/python/agent-refs.json +2 -1
  58. package/src/gdskills/bundled/stacks/python/pack.json +1 -1
  59. package/src/gdskills/bundled/stacks/rust/agent-refs.json +3 -0
  60. package/src/gdskills/bundled/stacks/rust/governance/eval.json +1823 -0
  61. package/src/gdskills/bundled/stacks/rust/governance/scout.json +32 -0
  62. package/src/gdskills/bundled/stacks/rust/pack.json +42 -0
  63. package/src/gdskills/bundled/stacks/rust/rules/coding-style.mdc +93 -0
  64. package/src/gdskills/bundled/stacks/rust/rules/patterns.mdc +85 -0
  65. package/src/gdskills/bundled/stacks/rust/rules/security.mdc +85 -0
  66. package/src/gdskills/bundled/stacks/rust/rules/testing.mdc +82 -0
  67. package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/SKILL.md +141 -0
  68. package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/evals.json +78 -0
  69. package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/SKILL.md +127 -0
  70. package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/evals.json +72 -0
  71. package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/SKILL.md +133 -0
  72. package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/evals.json +79 -0
  73. package/src/gdskills/bundled/stacks/rust/skills/rust-testing/SKILL.md +130 -0
  74. package/src/gdskills/bundled/stacks/rust/skills/rust-testing/evals.json +75 -0
  75. package/src/gdskills/bundled/agents/python-build-fixer.md +0 -52
  76. package/src/gdskills/bundled/agents/python-code-auditor.md +0 -49
@@ -0,0 +1,39 @@
1
+ [
2
+ {
3
+ "query": "Use when a Gradle or Maven build for a Java/Kotlin Spring Boot project fails -- compile errors, dependency/version conflicts, Spring context startup failures (missing bean, ambiguous bean, circular dependency), Kotlin/Java interop issues, checkstyle/ktlint/detekt findings, and a failing test run.",
4
+ "decision": "create",
5
+ "topMatch": "django/django-build-fix",
6
+ "recordedAt": "2026-09-25T18:06:23.531Z",
7
+ "skillName": "java-kotlin-spring-build-fix"
8
+ },
9
+ {
10
+ "query": "Use when reviewing a Java or Kotlin Spring Boot change for framework-specific risks -- field injection, @Transactional self-invocation, entities leaked across the API boundary, N+1 query patterns, missing Bean Validation, and overly permissive Spring Security configuration. Read-only, no edits.",
11
+ "decision": "fork",
12
+ "topMatch": "java-kotlin-spring/java-kotlin-spring-implementation",
13
+ "recordedAt": "2026-09-25T18:06:23.850Z",
14
+ "skillName": "java-kotlin-spring-code-review",
15
+ "justification": "top match java-kotlin-spring/java-kotlin-spring-implementation is this same pack's implementation skill, sharing Spring-specific domain vocabulary (constructor injection, @Transactional, Spring Data JPA, Bean Validation) because review necessarily checks for the same pitfalls implementation should avoid, not because the two are redundant; decision is fork since they cover disjoint workflows (writing new code vs. read-only review of an existing diff)."
16
+ },
17
+ {
18
+ "query": "Use when writing a controller, service, or repository class in a Java or Kotlin backend built on Spring Boot -- wiring dependencies through a class's own constructor, splitting request handling across layers, marshaling a request payload into a validated object, deciding where a transaction boundary starts, and authoring a Spring Data repository method. Covers writing/extending production code, not an existing diff's risks (that's the pack's own review skill) or fixing a broken build (that's its own build-fix skill).",
19
+ "decision": "create",
20
+ "topMatch": "java-kotlin-spring/java-kotlin-spring-code-review",
21
+ "recordedAt": "2026-09-25T18:06:24.162Z",
22
+ "skillName": "java-kotlin-spring-implementation"
23
+ },
24
+ {
25
+ "query": "Use when writing or reviewing a versioned database schema migration for a Spring Boot project using Flyway or Liquibase -- new migration file naming/ordering, never editing an already-applied migration, and verifying with flywayMigrate/flywayValidate or the project's configured equivalent.",
26
+ "decision": "create",
27
+ "topMatch": "quality/deprecation-path",
28
+ "recordedAt": "2026-09-25T18:06:24.476Z",
29
+ "skillName": "java-kotlin-spring-migrate"
30
+ },
31
+ {
32
+ "query": "Use when a Java or Kotlin Spring Boot test suite needs writing, extending, or fixing -- JUnit 5, Mockito/MockK, the narrowest Spring test slice (@WebMvcTest/@DataJpaTest/@SpringBootTest), MockMvc, Awaitility instead of Thread.sleep, and Testcontainers for repository tests.",
33
+ "decision": "fork",
34
+ "topMatch": "java-kotlin-spring/java-kotlin-spring-implementation",
35
+ "recordedAt": "2026-09-25T18:06:24.794Z",
36
+ "skillName": "java-kotlin-spring-testing",
37
+ "justification": "top match java-kotlin-spring/java-kotlin-spring-implementation is this same pack's implementation skill, sharing Spring-specific domain vocabulary (Spring Boot, JPA repository, service layer) because tests necessarily exercise the same layered architecture implementation builds, not because the two are redundant; decision is fork since they cover disjoint workflows (writing production code vs. writing JUnit5/MockMvc/Testcontainers tests for it)."
38
+ }
39
+ ]
@@ -0,0 +1,40 @@
1
+ {
2
+ "id": "java-kotlin-spring",
3
+ "family": "framework",
4
+ "modules": ["java-kotlin-spring-rules", "java-kotlin-spring-skills"],
5
+ "detectionMarkers": ["spring-boot", "spring"],
6
+ "provenance": {
7
+ "origin": "authored",
8
+ "sourceRef": "flow 335, Wave 4 batch 3"
9
+ },
10
+ "stability": "experimental",
11
+ "skills": {
12
+ "implement": ["java-kotlin-spring-implementation"],
13
+ "test": ["java-kotlin-spring-testing"],
14
+ "review": ["java-kotlin-spring-code-review"],
15
+ "build-fix": ["java-kotlin-spring-build-fix"],
16
+ "migrate": ["java-kotlin-spring-migrate"]
17
+ },
18
+ "agentProfile": {
19
+ "displayName": "Java/Kotlin + Spring",
20
+ "auditFocus": [
21
+ "field-level @Autowired injection instead of constructor injection with final fields (Java) or val properties (Kotlin)",
22
+ "a public method calling another @Transactional method on `this` within the same class, relying on the self-invocation proxy that Spring's AOP-based transaction management cannot intercept",
23
+ "a controller/service returning a JPA entity directly instead of a DTO, leaking persistence internals and lazy-loading traps across the API boundary",
24
+ "a lazy-loaded association accessed in a loop with no @EntityGraph/fetch join, producing an N+1 query pattern",
25
+ "a request DTO with no Bean Validation (jakarta.validation) annotations, or a controller that trusts unvalidated input",
26
+ "a SecurityFilterChain/authorization rule that is overly permissive, or CSRF disabled on a session-based (cookie-authenticated) endpoint with no compensating control"
27
+ ],
28
+ "buildCommands": [
29
+ "./gradlew build (or mvn verify, matching the project's build tool)",
30
+ "./gradlew test (or mvn test)",
31
+ "./gradlew check (or the project's configured lint/static-analysis task, when configured)"
32
+ ],
33
+ "fixGuardrails": [
34
+ "Never switch field @Autowired injection back in to work around a wiring error instead of fixing the constructor/bean definition.",
35
+ "Never widen a SecurityFilterChain rule (e.g. permitAll on a protected path) just to make a 403 disappear.",
36
+ "Never disable a failing test or a Bean Validation constraint to reach a green build.",
37
+ "Never add a broad exception handler that swallows the root cause instead of fixing it."
38
+ ]
39
+ }
40
+ }
@@ -0,0 +1,67 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.java", "**/*.kt", "**/*.kts"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Java/Kotlin + Spring coding style
9
+
10
+ Narrows `core-common-rules`' stack-agnostic style rules to current Spring
11
+ Boot 3.x idiom, for both Java and Kotlin sources. Applies only to
12
+ `*.java`/`*.kt`/`*.kts` files — everything not Spring/Java/Kotlin-specific
13
+ still comes from the common rules this file `extends`.
14
+
15
+ ## Dependency injection
16
+
17
+ - Prefer constructor injection over field injection: a Java `@Service`
18
+ declares its dependencies as `private final` fields set in the
19
+ constructor (no `@Autowired` needed on the constructor once there is
20
+ only one), or a Kotlin class declares them as constructor `val`
21
+ properties. Field-level `@Autowired` is discouraged — it hides the
22
+ dependency graph, prevents the field from being `final`/`val`, and
23
+ makes the class impossible to construct without the Spring container in
24
+ a plain unit test.
25
+ - A class with more than 4-5 constructor dependencies is a signal the
26
+ class has too many responsibilities, not a reason to fall back to field
27
+ injection to make the constructor shorter.
28
+
29
+ ## Layered architecture
30
+
31
+ - Keep the controller/service/repository layers distinct: a
32
+ `@RestController` parses/validates the request and delegates to a
33
+ `@Service`; business logic and transaction boundaries live in the
34
+ service layer; a `@Repository`/Spring Data interface is the only layer
35
+ that talks to persistence. Do not put query logic in a controller or
36
+ HTTP concerns in a service.
37
+ - Expose a request/response DTO at the API boundary, never a JPA `@Entity`
38
+ directly — an entity carries lazy associations and persistence-specific
39
+ fields that leak internal structure and can trigger
40
+ `LazyInitializationException` when serialized outside a transaction.
41
+
42
+ ## Naming and structure
43
+
44
+ - Java: standard `PascalCase` for types, `camelCase` for members/methods,
45
+ packages lowercase with no underscores.
46
+ - Kotlin: `PascalCase` for classes, `camelCase` for functions/properties;
47
+ prefer a `data class` for a DTO/value-holder instead of a plain class
48
+ with manually written `equals`/`hashCode`/`toString`.
49
+ - Kotlin null-safety: model an optional field as a nullable type (`String?`)
50
+ and handle it with `?.`/`?:`/`requireNotNull`, not `!!` — a `!!` on
51
+ anything that can plausibly be null at runtime (a request field, a
52
+ lookup result) reintroduces the NPE the type system exists to prevent.
53
+
54
+ ## Bean Validation and DTOs
55
+
56
+ - Annotate request DTO fields with `jakarta.validation` constraints
57
+ (`@NotNull`, `@NotBlank`, `@Size`, `@Email`, etc.) and mark the
58
+ controller parameter `@Valid`/`@Validated` — validation belongs on the
59
+ DTO at the boundary, not re-implemented as manual `if` checks inside
60
+ the service.
61
+
62
+ ## Formatting
63
+
64
+ - Follow the project's configured formatter (`spotless`, `ktlint`,
65
+ google-java-format, or whatever `build.gradle(.kts)`/`pom.xml` already
66
+ wires up) rather than hand-formatting around it; do not introduce a
67
+ second formatter into a project that has already standardized on one.
@@ -0,0 +1,65 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.java", "**/*.kt", "**/*.kts"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Java/Kotlin + Spring patterns
9
+
10
+ Narrows `core-common-rules`' stack-agnostic design guidance to idiomatic
11
+ Spring Boot 3.x design and its common anti-patterns, for both Java and
12
+ Kotlin. Applies only to `*.java`/`*.kt`/`*.kts` files.
13
+
14
+ ## Transaction boundaries and the self-invocation pitfall
15
+
16
+ - `@Transactional` is placed on the outermost service method that defines
17
+ the unit of work, not scattered on every repository call.
18
+ - Spring's declarative transactions are proxy-based (AOP): a call from
19
+ one method to another `@Transactional` method **on the same class**,
20
+ through `this`, bypasses the proxy entirely — the annotation is
21
+ silently ignored, no new transaction starts and no rollback happens on
22
+ that inner call. Split the self-invoking method out into a separate
23
+ bean the caller depends on (constructor-injected), so the call crosses
24
+ a real proxy boundary, instead of calling `this.otherTransactionalMethod()`.
25
+ - Keep a `@Transactional` method free of unrelated I/O (HTTP calls,
26
+ file access) that would hold the transaction/connection open longer
27
+ than necessary.
28
+
29
+ ## Spring Data JPA query patterns
30
+
31
+ - Watch for N+1: iterating a collection and accessing a lazy association
32
+ per item issues one query per item. Fix with `@EntityGraph` on the
33
+ repository method, a JPQL `JOIN FETCH`, or a projection that selects
34
+ only the fields actually needed — do not switch every association to
35
+ `FetchType.EAGER` as a blanket fix, which just moves the N+1 into every
36
+ unrelated query that loads the entity.
37
+ - Prefer a derived query method or `@Query` with named parameters over
38
+ building JPQL/native SQL by string concatenation.
39
+ - Use a projection (an interface or DTO) for a read path that only needs
40
+ a subset of an entity's fields, instead of loading the full entity
41
+ graph and mapping it down in the service layer.
42
+
43
+ ## Dependency injection and bean design
44
+
45
+ - Define an interface at the consumer boundary (the package/module that
46
+ calls through it) when a component genuinely has more than one
47
+ implementation or needs to be mocked across module boundaries; do not
48
+ add an interface with a single Spring-managed implementation "for
49
+ testability" when constructor injection with a concrete class already
50
+ gives a test the same seam via a test double.
51
+ - Favor constructor injection producing an immutable, fully-initialized
52
+ bean over setter injection or field injection, which both allow a bean
53
+ to exist in a partially-configured state.
54
+
55
+ ## Anti-patterns to flag
56
+
57
+ - A "god service" that accumulates unrelated business logic across
58
+ multiple domains — split by bounded responsibility, mirroring the
59
+ controller/service/repository layering above.
60
+ - Catching a broad `Exception`/`RuntimeException` in a service method
61
+ only to log and swallow it, instead of letting it propagate to a
62
+ `@ControllerAdvice`/`@ExceptionHandler` that maps it to the right HTTP
63
+ response.
64
+ - A `@RestController` method containing business/query logic directly
65
+ instead of delegating to a service — controllers should stay thin.
@@ -0,0 +1,69 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.java", "**/*.kt", "**/*.kts"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Java/Kotlin + Spring security
9
+
10
+ Narrows `core-common-rules`' stack-agnostic security rules to Spring Boot
11
+ 3.x-specific, OWASP-relevant risks. Broadly scoped to all Java/Kotlin
12
+ sources for data-access and secrets guidance below, with extra emphasis
13
+ on controller/security-config files for the HTTP-facing rules.
14
+
15
+ ## Spring Security configuration
16
+
17
+ - Configure security with a `SecurityFilterChain` `@Bean` returned from a
18
+ `@Configuration` class (`http.build()` on an `HttpSecurity` you have
19
+ customized) — this is the current Spring Boot 3.x idiom. Do not extend
20
+ `WebSecurityConfigurerAdapter`; it was removed in Spring Security 6 /
21
+ Spring Boot 3 and any code still referencing it is targeting an old
22
+ major version.
23
+ - Scope authorization rules explicitly (`authorizeHttpRequests` with
24
+ path/role matchers) rather than leaving a catch-all `permitAll()` that
25
+ was only meant for one endpoint during development.
26
+
27
+ ## CSRF
28
+
29
+ - A stateless, token-authenticated API (bearer JWT/OAuth2, no session
30
+ cookie) legitimately disables CSRF protection (`csrf(AbstractHttpConfigurer::disable)`)
31
+ because CSRF exploits ambient cookie auth, which does not apply here —
32
+ state this reasoning explicitly when disabling it.
33
+ - A session-cookie-authenticated endpoint (browser form login, `JSESSIONID`)
34
+ must keep CSRF protection enabled; disabling it there reopens the exact
35
+ attack the stateless-API exception does not apply to.
36
+
37
+ ## SQL and data access
38
+
39
+ - Use Spring Data JPA derived queries or parameterized `@Query`
40
+ (JPQL/native, with named or positional bind parameters), never
41
+ string-concatenated or `String.format`-built SQL/JPQL with any
42
+ user-influenced value — parameterization is the injection defense, not
43
+ an input-validation substitute for it.
44
+ - The same applies to `JdbcTemplate`/`NamedParameterJdbcTemplate`: use its
45
+ parameter-binding API, never interpolate a value into the SQL string.
46
+
47
+ ## Input validation as the DTO boundary defense
48
+
49
+ - Validate untrusted input at the DTO boundary with `jakarta.validation`
50
+ annotations plus `@Valid`/`@Validated` on the controller method — this
51
+ is the primary injection/malformed-input defense point for request
52
+ data, on top of (not instead of) parameterized queries downstream.
53
+
54
+ ## Secrets and configuration
55
+
56
+ - Never hard-code a credential, API key, or signing secret in source or
57
+ in `application.yml`/`application.properties` committed to the repo —
58
+ load it from environment variables, a config server, or the secret
59
+ store the project already uses (Spring's externalized configuration
60
+ supports both cleanly).
61
+ - Do not log a request/response body that may carry credentials, tokens,
62
+ or PII at `INFO`/`DEBUG` level without redaction.
63
+
64
+ ## Dependency hygiene
65
+
66
+ - Run the project's configured dependency-vulnerability check (OWASP
67
+ Dependency-Check plugin, `./gradlew dependencyCheckAnalyze`, or
68
+ whatever the build already wires up) when introducing or bumping a
69
+ dependency, rather than skipping it because "it's just a minor bump."
@@ -0,0 +1,80 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.java", "**/*.kt", "**/*.kts"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Java/Kotlin + Spring testing
9
+
10
+ Narrows `core-common-rules`' stack-agnostic testing rules to JUnit 5 +
11
+ Spring Boot Test conventions, for both Java and Kotlin. Applies only to
12
+ `*.java`/`*.kt`/`*.kts` files.
13
+
14
+ ## Layout and naming
15
+
16
+ - Tests live under `src/test/java` or `src/test/kotlin`, mirroring the
17
+ package of the class under test, named `<Type>Test` (unit) or
18
+ `<Type>IT`/`<Type>IntegrationTest` (integration) — match whichever
19
+ convention the project already uses.
20
+ - Prefer a plain, dependency-free unit test (construct the class
21
+ directly, pass mocks/fakes to the constructor) for logic that does not
22
+ need the Spring container; reserve `@SpringBootTest` for genuine
23
+ integration coverage — a full context load per test class is slow and
24
+ is not a substitute for testing a service's logic in isolation.
25
+
26
+ ## Test slices
27
+
28
+ - Use the narrowest Spring test slice that covers what is being tested:
29
+ `@WebMvcTest` for a controller (with `MockMvc`), `@DataJpaTest` for a
30
+ repository, `@SpringBootTest` only when the interaction across the
31
+ whole wired context is actually what is under test.
32
+ - For a repository/integration test that needs a real database, prefer
33
+ Testcontainers over an in-memory substitute (H2 standing in for
34
+ Postgres/MySQL) when the project already uses Testcontainers — an
35
+ in-memory DB can silently pass a query that the real production
36
+ database would reject or execute differently.
37
+
38
+ ## Mocking
39
+
40
+ - Mock/stub only the collaborators the class under test actually depends
41
+ on (Mockito's `@Mock`/`@InjectMocks`, or MockK for Kotlin) — do not
42
+ reach for `@MockitoBean`/`@SpringBootTest` just to avoid constructing a
43
+ plain dependency by hand when the class was designed for constructor
44
+ injection. `@MockitoBean` is the current annotation for mocking a bean
45
+ inside a Spring test slice; Spring Boot's own `@MockBean` is deprecated
46
+ since Boot 3.4 and removed in 4.x, so only reach for it on a project
47
+ still pinned below 3.4.
48
+ - Assert on behavior/interactions relevant to the test (`verify(...)`),
49
+ not on incidental implementation details that would make the test
50
+ brittle to a harmless refactor.
51
+
52
+ ## Assertions and determinism
53
+
54
+ - Use the project's already-configured assertion library (AssertJ,
55
+ JUnit's own assertions, or Kotlin's `kotlin.test`) — do not introduce a
56
+ second one into a project that has standardized.
57
+ - Never synchronize with `Thread.sleep`/`delay` to wait for an async
58
+ result — use Awaitility (`await().atMost(...).until(...)`), a
59
+ `CompletableFuture`/coroutine join, or a `CountDownLatch`, so the test
60
+ is deterministic and not flaky under CI load.
61
+ - A test covering validation should assert on the specific constraint
62
+ violation/exception type, not just that "some" exception was thrown.
63
+
64
+ ## Fixtures and lifecycle
65
+
66
+ - Prefer a builder or a test-fixture factory method for constructing
67
+ entities/DTOs with sensible defaults, overriding only the fields the
68
+ test cares about, over duplicating a large constructor call in every
69
+ test method.
70
+ - Use `@BeforeEach`/`@AfterEach` (or Kotlin's equivalents) for
71
+ per-test setup/teardown; reserve `@BeforeAll`/`@AfterAll` for
72
+ genuinely expensive, safely-shared setup (a Testcontainers instance).
73
+
74
+ ## Coverage expectations
75
+
76
+ - New behavior gets a new test in the same change; a bug fix gets a
77
+ regression test that fails before the fix and passes after.
78
+ - Run the project's build-tool test task (`./gradlew test` or `mvn test`)
79
+ for any change touching test files, and its integration-test task
80
+ separately when one is configured, before reporting done.
@@ -0,0 +1,144 @@
1
+ ---
2
+ name: java-kotlin-spring-build-fix
3
+ description: "Use when a Gradle or Maven build for a Java/Kotlin Spring Boot project fails -- compile errors, dependency/version conflicts, Spring context startup failures (missing bean, ambiguous bean, circular dependency), Kotlin/Java interop issues, checkstyle/ktlint/detekt findings, and a failing test run."
4
+ triggers:
5
+ - "./gradlew build is failing"
6
+ - "mvn compile is failing with a dependency conflict"
7
+ - "Spring context fails to start -- no qualifying bean"
8
+ - "resolve this circular bean dependency in Spring"
9
+ - "ktlint is failing on this Kotlin file"
10
+ - "this Spring Boot test run is failing to build"
11
+ metadata:
12
+ origin: authored
13
+ category: build-fix
14
+ version: "1.0.0"
15
+ compatible_harnesses: "claude,codex,cursor,zed,opencode"
16
+ license: "MIT"
17
+ ---
18
+
19
+ # Java/Kotlin + Spring build fix
20
+
21
+ Resolve a Gradle/Maven build failure for a Java or Kotlin Spring Boot
22
+ project — a compile error, a dependency/version conflict, a Spring
23
+ context startup failure (missing/ambiguous bean, circular dependency), a
24
+ Kotlin/Java interop issue, a checkstyle/ktlint/detekt finding, or a
25
+ failing test run — with the smallest change that fixes the actual root
26
+ cause. `rules/coding-style.mdc` and `rules/security.mdc` govern what a
27
+ "correct" fix looks like; this skill never reaches for a suppression
28
+ instead of a fix.
29
+
30
+ ## Workflow
31
+
32
+ ### Step 1: Reproduce and classify
33
+
34
+ ```bash
35
+ ./gradlew build # or: mvn verify
36
+ ```
37
+
38
+ Run the project's configured static-analysis task if present
39
+ (`./gradlew check`, `checkstyle`, `ktlint`, `detekt`). Read the exact
40
+ error text and classify it:
41
+
42
+ - **Compile error** (undefined symbol, type mismatch, wrong arg count,
43
+ Kotlin/Java interop nullability mismatch).
44
+ - **Dependency/version conflict** (Gradle/Maven resolution failure,
45
+ transitive version clash, a missing dependency declaration).
46
+ - **Spring context startup failure** — `NoSuchBeanDefinitionException`
47
+ (no qualifying bean), `NoUniqueBeanDefinitionException` (ambiguous
48
+ bean, needs `@Qualifier`/`@Primary`), or a circular bean dependency
49
+ (`BeanCurrentlyInCreationException`).
50
+ - **Static-analysis finding** (checkstyle/ktlint/detekt rule violation).
51
+ - **Failing test run** (a test failure surfaced through the build task).
52
+
53
+ ### Step 2: Fix by category
54
+
55
+ **Dependency/version conflict:** check the build tool's own dependency
56
+ tree (`./gradlew dependencies` or `mvn dependency:tree`) to see what is
57
+ actually pulling in the conflicting version before bumping anything by
58
+ hand. Align on the version the project's dependency-management/BOM
59
+ (`spring-boot-dependencies`, a Gradle platform) already declares when one
60
+ exists, rather than pinning an arbitrary version that happens to compile.
61
+
62
+ **Missing/ambiguous bean:** for "no qualifying bean," check that the
63
+ class is actually component-scanned (package location, `@Component`/
64
+ `@Service`/`@Repository`/`@Configuration` present) and that any required
65
+ `@ConditionalOn...` conditions are met. For "no unique bean," add
66
+ `@Qualifier`/`@Primary` to disambiguate rather than deleting one of the
67
+ legitimate implementations.
68
+
69
+ **Circular bean dependency:** find the actual cycle (two beans each
70
+ requiring the other in their constructors) and break it by extracting
71
+ the shared behavior into a third bean, or by refactoring so one
72
+ dependency is no longer needed at construction time — do not reach for
73
+ `@Lazy` as a first resort; it defers the problem rather than fixing the
74
+ design that created the cycle, though it is an acceptable last resort
75
+ when the cycle is genuinely unavoidable and the reason is stated in the
76
+ report.
77
+
78
+ **Kotlin/Java interop:** a platform type (`String!`) flowing from Java
79
+ into Kotlin that later NPEs, or a Kotlin nullable type mismatching a
80
+ Java `@NonNull`/`@Nullable` annotation — fix by making the Kotlin side's
81
+ nullability match what the Java API actually guarantees (check for
82
+ JSR-305/`@NonNull` annotations on the Java side), not by adding a blanket
83
+ `!!` at the interop boundary.
84
+
85
+ **Static-analysis finding:** fix the underlying issue the finding names.
86
+ Never add a suppression (`// noinspection`, `@SuppressWarnings`, a
87
+ ktlint/detekt `// ktlint-disable`/baseline entry) whose only purpose is
88
+ to make the checker stop complaining without addressing what it found.
89
+
90
+ **Failing test run:** read the actual assertion failure or stack trace;
91
+ fix the root cause in test or source per the failure's own evidence — do
92
+ not delete or `@Disabled` the test to reach a green build.
93
+
94
+ ### Step 3: Verify
95
+
96
+ ```bash
97
+ ./gradlew build # or: mvn verify
98
+ ./gradlew test # or: mvn test
99
+ ```
100
+
101
+ Re-run the project's static-analysis task if it was part of the original
102
+ failure. All must exit 0 before reporting done.
103
+
104
+ ### Step 4: Report
105
+
106
+ ```
107
+ Fixed: NoUniqueBeanDefinitionException for PaymentGateway (two implementations)
108
+ - Root cause: StripeGateway and MockGateway both @Component-scanned with no @Primary
109
+ - Added @Primary to StripeGateway; ./gradlew build/test both pass
110
+ ```
111
+
112
+ State the root cause in one sentence, not just "fixed the error."
113
+
114
+ ## Rules
115
+
116
+ - Find and fix the smallest change that addresses the actual root cause —
117
+ never widen a fix beyond what the failure requires.
118
+ - NEVER add a suppression annotation/comment/baseline entry to silence a
119
+ static-analysis finding instead of fixing what it found.
120
+ - NEVER delete or `@Disabled` a failing test to reach a green build.
121
+ - NEVER pin an arbitrary dependency version to make a conflict disappear
122
+ without checking the dependency tree/BOM first.
123
+ - Reach for `@Lazy` on a circular bean dependency only as a last resort,
124
+ with the reason stated in the report — prefer breaking the actual cycle.
125
+
126
+ ## Red Flags
127
+
128
+ | Rationalization | Why it is wrong |
129
+ |---|---|
130
+ | "I'll add `@SuppressWarnings` here so the linter stops complaining" | Silences the finding without fixing the issue it caught; check what it actually found instead |
131
+ | "I'll just mark the failing test `@Disabled` for now" | Hides a real regression or a genuinely broken feature; fix the root cause or say explicitly why the test itself is wrong |
132
+ | "I'll add `@Lazy` to break this bean cycle, it's the fastest fix" | Defers bean initialization instead of fixing the design that created a two-way dependency; acceptable only as a stated last resort, not the default |
133
+ | "I'll bump this dependency to whatever version compiles" | Picks a version by trial and error instead of checking what the project's BOM/dependency tree actually resolves to, risking a different conflict later |
134
+
135
+ ## Verification
136
+
137
+ Do not report the fix done until all of the following hold:
138
+
139
+ - `./gradlew build`/`mvn verify` and the test task both exit 0.
140
+ - The project's static-analysis task (if configured) exits 0.
141
+ - The change is the smallest one that addresses the stated root cause —
142
+ no unrelated files touched.
143
+ - The report states the root cause in one sentence, not just "build now
144
+ passes."
@@ -0,0 +1,74 @@
1
+ {
2
+ "triggers": {
3
+ "positive": [
4
+ "Our CI just started failing on ./gradlew assemble -- the log points to two different versions of jackson-databind on the classpath. How do I track down which dependency is pulling in the wrong one?",
5
+ "After adding a second implementation of PaymentGateway, the app won't boot anymore and the stack trace mentions NoUniqueBeanDefinitionException. What's going on?",
6
+ "mvn verify is failing with a circular bean dependency",
7
+ "Our lint step is red because of a ktlint violation in OrderMapper.kt -- can you clean it up?",
8
+ "`./gradlew test` won't even compile -- there's a type mismatch somewhere in the OrderServiceTest sources. Can you track it down?",
9
+ "NoSuchBeanDefinitionException on startup, fix this Spring build"
10
+ ],
11
+ "negative": [
12
+ "npm install is failing with a peer dependency conflict",
13
+ "cargo build is failing for this Rust crate",
14
+ "go build is failing with an undefined symbol",
15
+ "Implement a new feature in this Spring service",
16
+ "Review this Spring diff for concurrency bugs",
17
+ "Write JUnit tests for this Spring controller"
18
+ ]
19
+ },
20
+ "scenarios": [
21
+ {
22
+ "id": "no-suppresswarnings-suppression",
23
+ "prompt": "checkstyle is flagging an unused import in my Java code after a refactor. How should I fix it?",
24
+ "strictness": "high",
25
+ "expected_behavior": [
26
+ {
27
+ "grader": "judge",
28
+ "rubric": "A correct answer removes the actual unused import that checkstyle flagged, rather than suppressing the finding with @SuppressWarnings or a checkstyle-disable comment.",
29
+ "pass_criteria": [
30
+ "States that the fix is to remove the specific unused import statement, not merely 'clean up imports' in the abstract.",
31
+ "Does not rely on @SuppressWarnings or a checkstyle-disable comment/baseline entry as the fix for this finding.",
32
+ "Either names re-running checkstyle to confirm the finding clears, or does not suggest skipping verification."
33
+ ],
34
+ "fail_criteria": [
35
+ "Recommends adding @SuppressWarnings or a checkstyle-disable comment/baseline entry to silence the unused-import finding instead of removing the import."
36
+ ]
37
+ }
38
+ ],
39
+ "calibration": {
40
+ "known_right": "That means the refactor left an import statement that nothing in the file references anymore. The fix is simply to delete that import line -- most IDEs will highlight it directly, or you can match it against checkstyle's reported line number. There's no suppression needed here; an unused import is dead weight with no runtime cost either way, so removing it is strictly better than silencing the finding. Re-run checkstyle afterward to confirm it's clear and that the refactor didn't leave any other unused imports nearby.",
41
+ "known_wrong": "Easiest fix is to add `@SuppressWarnings(\"unused\")` above the class, or add a checkstyle-disable comment around the import block -- that stops checkstyle from flagging it without you needing to hunt down which specific import is unused. You can leave the import in place in case the code changes again later and needs it back.",
42
+ "vague": "Clean up the imports so checkstyle stops complaining about this file.",
43
+ "subtle_wrong": "Rather than deleting the import outright, add a checkstyle-disable comment (`// CHECKSTYLE:OFF: UnusedImports`) around that line -- that way if a later change in this file ends up needing the same import again, it's already there and won't need to be re-added. It keeps the diff smaller than fully removing and potentially re-adding the import later."
44
+ },
45
+ "anti_patterns": ["@SuppressWarnings"]
46
+ },
47
+ {
48
+ "id": "circular-bean-dependency",
49
+ "prompt": "Spring fails to start with BeanCurrentlyInCreationException -- OrderService and PaymentService each require the other in their constructors. How do I fix this?",
50
+ "strictness": "high",
51
+ "expected_behavior": [
52
+ {
53
+ "grader": "judge",
54
+ "rubric": "A correct answer identifies this as a genuine circular bean dependency and fixes it by breaking the cycle -- extracting the shared behavior into a third bean, or refactoring so one side no longer needs the other at construction time -- treating @Lazy only as a stated last resort rather than the default fix.",
55
+ "pass_criteria": [
56
+ "Identifies the actual cycle: OrderService and PaymentService each depend on the other through their constructors.",
57
+ "Proposes breaking the cycle as the primary fix direction -- extracting shared behavior into a third bean, or removing the unnecessary constructor-time dependency on one side -- not just deferring it.",
58
+ "Treats @Lazy (if mentioned at all) as an explicitly-stated last resort for a case where the cycle is genuinely unavoidable, not as the default or preferred fix."
59
+ ],
60
+ "fail_criteria": [
61
+ "Recommends @Lazy on one of the constructor dependencies as the fix, presented as the default or preferred solution rather than an explicitly-flagged last resort for an unavoidable cycle."
62
+ ]
63
+ }
64
+ ],
65
+ "calibration": {
66
+ "known_right": "This means OrderService's constructor needs a PaymentService, and PaymentService's constructor needs an OrderService -- Spring can't construct either one first because each is waiting on the other. The real fix is to break the cycle rather than paper over it: look at what each side actually calls on the other, and pull that shared behavior into a third bean that both OrderService and PaymentService depend on instead of depending on each other directly. Often one side only needs a narrow slice of the other's behavior (e.g. OrderService only needs PaymentService to charge a card, PaymentService only needs OrderService to look up an order) -- extracting those specific operations into a shared collaborator usually removes the cycle entirely. Reach for @Lazy on one of the constructor parameters only if you've confirmed the cycle really is structurally unavoidable and say so explicitly in the fix -- it defers when the proxy is resolved rather than fixing the design that created the two-way dependency, so it should be the fallback, not the first move.",
67
+ "known_wrong": "The fastest fix is to add `@Lazy` to the PaymentService parameter in OrderService's constructor -- that breaks the immediate circular-creation error because Spring injects a proxy instead of eagerly resolving the real bean, and you don't have to restructure anything. This is the standard way to handle a circular dependency in Spring, so I'd just do that and move on.",
68
+ "vague": "You've got a circular dependency between these two services -- restructure things so they don't need each other directly.",
69
+ "subtle_wrong": "Add `@Lazy` to the PaymentService constructor parameter in OrderService -- that's the standard, low-risk way to resolve `BeanCurrentlyInCreationException` without a bigger refactor, since Spring just defers resolving the real bean until it's first used. If you want to clean the design up later you could look at extracting shared logic into a third bean, but for getting the context started again, @Lazy here is the right call."
70
+ },
71
+ "anti_patterns": ["@Lazy"]
72
+ }
73
+ ]
74
+ }