@mrciphersmith/keryx 0.3.3 → 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 (140) hide show
  1. package/dist/cli.js +996 -366
  2. package/docs/README.md +2 -0
  3. package/package.json +1 -1
  4. package/src/gdskills/bundled/install-manifest.json +520 -48
  5. package/src/gdskills/bundled/stacks/csharp-dotnet/agent-refs.json +4 -0
  6. package/src/gdskills/bundled/stacks/csharp-dotnet/governance/eval.json +1881 -0
  7. package/src/gdskills/bundled/stacks/csharp-dotnet/governance/scout.json +33 -0
  8. package/src/gdskills/bundled/stacks/csharp-dotnet/pack.json +38 -0
  9. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/coding-style.mdc +100 -0
  10. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/patterns.mdc +107 -0
  11. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/security.mdc +86 -0
  12. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/testing.mdc +89 -0
  13. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/SKILL.md +143 -0
  14. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/evals.json +77 -0
  15. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/SKILL.md +121 -0
  16. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/evals.json +77 -0
  17. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/SKILL.md +134 -0
  18. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/evals.json +76 -0
  19. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/SKILL.md +130 -0
  20. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/evals.json +77 -0
  21. package/src/gdskills/bundled/stacks/django/agent-refs.json +3 -0
  22. package/src/gdskills/bundled/stacks/django/governance/eval.json +1763 -0
  23. package/src/gdskills/bundled/stacks/django/governance/scout.json +40 -0
  24. package/src/gdskills/bundled/stacks/django/pack.json +43 -0
  25. package/src/gdskills/bundled/stacks/django/rules/coding-style.mdc +80 -0
  26. package/src/gdskills/bundled/stacks/django/rules/patterns.mdc +92 -0
  27. package/src/gdskills/bundled/stacks/django/rules/security.mdc +92 -0
  28. package/src/gdskills/bundled/stacks/django/rules/testing.mdc +89 -0
  29. package/src/gdskills/bundled/stacks/django/skills/django-build-fix/SKILL.md +149 -0
  30. package/src/gdskills/bundled/stacks/django/skills/django-build-fix/evals.json +49 -0
  31. package/src/gdskills/bundled/stacks/django/skills/django-code-review/SKILL.md +137 -0
  32. package/src/gdskills/bundled/stacks/django/skills/django-code-review/evals.json +48 -0
  33. package/src/gdskills/bundled/stacks/django/skills/django-implementation/SKILL.md +147 -0
  34. package/src/gdskills/bundled/stacks/django/skills/django-implementation/evals.json +75 -0
  35. package/src/gdskills/bundled/stacks/django/skills/django-migrate/SKILL.md +166 -0
  36. package/src/gdskills/bundled/stacks/django/skills/django-migrate/evals.json +49 -0
  37. package/src/gdskills/bundled/stacks/django/skills/django-testing/SKILL.md +130 -0
  38. package/src/gdskills/bundled/stacks/django/skills/django-testing/evals.json +48 -0
  39. package/src/gdskills/bundled/stacks/fastapi/agent-refs.json +3 -0
  40. package/src/gdskills/bundled/stacks/fastapi/governance/eval.json +1777 -0
  41. package/src/gdskills/bundled/stacks/fastapi/governance/scout.json +34 -0
  42. package/src/gdskills/bundled/stacks/fastapi/pack.json +43 -0
  43. package/src/gdskills/bundled/stacks/fastapi/rules/coding-style.mdc +68 -0
  44. package/src/gdskills/bundled/stacks/fastapi/rules/patterns.mdc +108 -0
  45. package/src/gdskills/bundled/stacks/fastapi/rules/security.mdc +99 -0
  46. package/src/gdskills/bundled/stacks/fastapi/rules/testing.mdc +85 -0
  47. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/SKILL.md +157 -0
  48. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/evals.json +76 -0
  49. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/SKILL.md +150 -0
  50. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/evals.json +74 -0
  51. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/SKILL.md +158 -0
  52. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/evals.json +75 -0
  53. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/SKILL.md +146 -0
  54. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/evals.json +74 -0
  55. package/src/gdskills/bundled/stacks/flutter-dart/agent-refs.json +4 -0
  56. package/src/gdskills/bundled/stacks/flutter-dart/governance/eval.json +1849 -0
  57. package/src/gdskills/bundled/stacks/flutter-dart/governance/scout.json +33 -0
  58. package/src/gdskills/bundled/stacks/flutter-dart/pack.json +41 -0
  59. package/src/gdskills/bundled/stacks/flutter-dart/rules/coding-style.mdc +98 -0
  60. package/src/gdskills/bundled/stacks/flutter-dart/rules/patterns.mdc +88 -0
  61. package/src/gdskills/bundled/stacks/flutter-dart/rules/security.mdc +91 -0
  62. package/src/gdskills/bundled/stacks/flutter-dart/rules/testing.mdc +101 -0
  63. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/SKILL.md +134 -0
  64. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/evals.json +79 -0
  65. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/SKILL.md +124 -0
  66. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/evals.json +74 -0
  67. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/SKILL.md +139 -0
  68. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/evals.json +77 -0
  69. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/SKILL.md +134 -0
  70. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/evals.json +74 -0
  71. package/src/gdskills/bundled/stacks/java-kotlin-spring/agent-refs.json +3 -0
  72. package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/eval.json +2194 -0
  73. package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/scout.json +39 -0
  74. package/src/gdskills/bundled/stacks/java-kotlin-spring/pack.json +40 -0
  75. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/coding-style.mdc +67 -0
  76. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/patterns.mdc +65 -0
  77. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/security.mdc +69 -0
  78. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/testing.mdc +80 -0
  79. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/SKILL.md +144 -0
  80. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/evals.json +74 -0
  81. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/SKILL.md +129 -0
  82. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/evals.json +74 -0
  83. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/SKILL.md +147 -0
  84. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/evals.json +75 -0
  85. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/SKILL.md +139 -0
  86. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/evals.json +74 -0
  87. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/SKILL.md +128 -0
  88. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/evals.json +73 -0
  89. package/src/gdskills/bundled/stacks/kotlin-android/agent-refs.json +4 -0
  90. package/src/gdskills/bundled/stacks/kotlin-android/governance/eval.json +1889 -0
  91. package/src/gdskills/bundled/stacks/kotlin-android/governance/scout.json +34 -0
  92. package/src/gdskills/bundled/stacks/kotlin-android/pack.json +38 -0
  93. package/src/gdskills/bundled/stacks/kotlin-android/rules/coding-style.mdc +89 -0
  94. package/src/gdskills/bundled/stacks/kotlin-android/rules/patterns.mdc +96 -0
  95. package/src/gdskills/bundled/stacks/kotlin-android/rules/security.mdc +90 -0
  96. package/src/gdskills/bundled/stacks/kotlin-android/rules/testing.mdc +89 -0
  97. package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/SKILL.md +150 -0
  98. package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/evals.json +77 -0
  99. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/SKILL.md +151 -0
  100. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/evals.json +76 -0
  101. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/SKILL.md +139 -0
  102. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/evals.json +78 -0
  103. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/SKILL.md +131 -0
  104. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/evals.json +77 -0
  105. package/src/gdskills/bundled/stacks/python/agent-refs.json +2 -1
  106. package/src/gdskills/bundled/stacks/python/pack.json +1 -1
  107. package/src/gdskills/bundled/stacks/rust/agent-refs.json +3 -0
  108. package/src/gdskills/bundled/stacks/rust/governance/eval.json +1823 -0
  109. package/src/gdskills/bundled/stacks/rust/governance/scout.json +32 -0
  110. package/src/gdskills/bundled/stacks/rust/pack.json +42 -0
  111. package/src/gdskills/bundled/stacks/rust/rules/coding-style.mdc +93 -0
  112. package/src/gdskills/bundled/stacks/rust/rules/patterns.mdc +85 -0
  113. package/src/gdskills/bundled/stacks/rust/rules/security.mdc +85 -0
  114. package/src/gdskills/bundled/stacks/rust/rules/testing.mdc +82 -0
  115. package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/SKILL.md +141 -0
  116. package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/evals.json +78 -0
  117. package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/SKILL.md +127 -0
  118. package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/evals.json +72 -0
  119. package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/SKILL.md +133 -0
  120. package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/evals.json +79 -0
  121. package/src/gdskills/bundled/stacks/rust/skills/rust-testing/SKILL.md +130 -0
  122. package/src/gdskills/bundled/stacks/rust/skills/rust-testing/evals.json +75 -0
  123. package/src/gdskills/bundled/stacks/swift-ios/agent-refs.json +4 -0
  124. package/src/gdskills/bundled/stacks/swift-ios/governance/eval.json +1803 -0
  125. package/src/gdskills/bundled/stacks/swift-ios/governance/scout.json +32 -0
  126. package/src/gdskills/bundled/stacks/swift-ios/pack.json +38 -0
  127. package/src/gdskills/bundled/stacks/swift-ios/rules/coding-style.mdc +92 -0
  128. package/src/gdskills/bundled/stacks/swift-ios/rules/patterns.mdc +112 -0
  129. package/src/gdskills/bundled/stacks/swift-ios/rules/security.mdc +78 -0
  130. package/src/gdskills/bundled/stacks/swift-ios/rules/testing.mdc +90 -0
  131. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/SKILL.md +144 -0
  132. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/evals.json +75 -0
  133. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/SKILL.md +122 -0
  134. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/evals.json +75 -0
  135. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/SKILL.md +131 -0
  136. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/evals.json +75 -0
  137. package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/SKILL.md +149 -0
  138. package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/evals.json +76 -0
  139. package/src/gdskills/bundled/agents/python-build-fixer.md +0 -52
  140. package/src/gdskills/bundled/agents/python-code-auditor.md +0 -49
@@ -0,0 +1,74 @@
1
+ {
2
+ "triggers": {
3
+ "positive": [
4
+ "We're adding an order_status column to the orders table -- what does a properly versioned Flyway script for that look like?",
5
+ "Write a Liquibase changeset to add an index on the orders table",
6
+ "Before this runs against the shared staging database, can you check whether my new V12 migration script is safe?",
7
+ "I need to rename the customer_email column without breaking rows that are mid-deploy -- what's the safe multi-step Flyway approach for that?",
8
+ "Flyway is refusing to start up because it says the checksum on V7 doesn't match what's recorded in the history table -- how do I resolve that safely?",
9
+ "We're dropping a legacy is_archived flag from the schema -- what should the migration script for that look like?",
10
+ "Write a Flyway migration that backfills a new not-null column"
11
+ ],
12
+ "negative": [
13
+ "Write a Django migration for this new model field",
14
+ "Add a Rails ActiveRecord migration for this column",
15
+ "Implement a new Spring service method that reads from this table",
16
+ "Review this Spring controller for entity leakage",
17
+ "Fix this failing Gradle build for the Spring project",
18
+ "Write JUnit tests for this Spring repository"
19
+ ]
20
+ },
21
+ "scenarios": [
22
+ {
23
+ "id": "never-edit-applied-migration",
24
+ "prompt": "I found a typo in a column name inside V7__add_users_table.sql, which has already been applied in staging. Should I just fix the typo in that file?",
25
+ "strictness": "high",
26
+ "expected_behavior": [
27
+ {
28
+ "grader": "judge",
29
+ "rubric": "A correct answer refuses to edit V7__add_users_table.sql directly because it has already been applied, explaining that changing an applied migration's content changes its checksum and will fail validation in any environment that already ran it. It directs adding a new migration (e.g. a rename statement) instead.",
30
+ "pass_criteria": [
31
+ "States explicitly that V7__add_users_table.sql must not be edited because it has already been applied in staging.",
32
+ "Explains the concrete consequence: editing it changes its checksum, which will fail Flyway/Liquibase validation in staging (or anywhere else it already ran).",
33
+ "Directs creating a new migration (e.g. a rename/correction statement in a new versioned file) as the fix instead."
34
+ ],
35
+ "fail_criteria": [
36
+ "Recommends editing V7__add_users_table.sql directly to fix the typo, with no new migration created."
37
+ ]
38
+ }
39
+ ],
40
+ "calibration": {
41
+ "known_right": "No -- don't edit V7__add_users_table.sql. Flyway records a checksum for every migration it has applied, and once V7 has run in staging, changing its file content (even a one-character typo fix) changes that checksum. The next time Flyway validates against staging, it'll detect the mismatch and fail -- staging has a different version of V7 recorded than what's now on disk. Instead, add a new migration (say V13__rename_users_typo_column.sql) that does the correction with an ALTER TABLE ... RENAME COLUMN statement. That way every environment, no matter which point it's already migrated to, gets the fix applied cleanly as a new step rather than needing V7 itself to change underneath it.",
42
+ "known_wrong": "Since it's just a typo and hasn't gone to production yet, I'd just fix it directly in V7__add_users_table.sql -- staging can just re-run the migration or you can manually correct the column name there once. It's a one-character change, adding a whole new migration file for something this small feels like overkill.",
43
+ "vague": "You probably shouldn't touch a migration that's already been applied -- handle the typo the right way instead.",
44
+ "subtle_wrong": "Since it's only in staging and not production yet, you can edit V7__add_users_table.sql directly and then just re-apply Flyway's `repair` command in staging to reset the checksum before running the corrected migration again -- that gets the file itself clean without needing an extra V13 migration cluttering up the history for what's really just a typo fix."
45
+ },
46
+ "anti_patterns": ["v7__add_users_table.sql"]
47
+ },
48
+ {
49
+ "id": "verify-before-reporting-done",
50
+ "prompt": "I wrote a new Flyway migration that adds a NOT NULL column with a default value to the orders table. It looks correct to me -- is writing the SQL enough, or do I need to do anything else before considering this done?",
51
+ "strictness": "high",
52
+ "expected_behavior": [
53
+ {
54
+ "grader": "judge",
55
+ "rubric": "A correct answer states that the migration must actually be run against a real database with a real migration command (flywayMigrate, with flywayValidate, or the project's equivalent) before being considered done -- reading the SQL and judging it correct by eye is not sufficient, since a migration can fail on the real database (constraint conflicts, backfill issues) even when the SQL looks right.",
56
+ "pass_criteria": [
57
+ "States that reading/reviewing the SQL is not sufficient on its own -- the migration must actually be executed with a real migration command.",
58
+ "Names a concrete command (flywayMigrate/flywayValidate, or the project's Liquibase equivalent) to run against a local/test database.",
59
+ "Gives a concrete reason verification matters here specifically -- e.g. a NOT NULL column addition can fail against existing rows with no default applied correctly, or a constraint conflict only surfaces at execution time."
60
+ ],
61
+ "fail_criteria": [
62
+ "States or implies that reading the SQL and confirming it looks correct is sufficient, with no actual migration command needing to be run before considering the work done."
63
+ ]
64
+ }
65
+ ],
66
+ "calibration": {
67
+ "known_right": "Reading the SQL isn't enough here -- run it. Execute `flywayMigrate` (or your build tool's equivalent, e.g. `./gradlew flywayMigrate`) against a local or test database that has representative existing data, then `flywayValidate` to confirm the applied state matches what's on disk. This matters especially for a NOT NULL column with a default: the syntax can look completely correct while still failing against existing rows if the default isn't actually being applied the way you expect on this database engine, or if there's a constraint you didn't account for. Only after it actually runs cleanly against a real database should you consider this done -- never claim a migration is correct purely from reading the SQL.",
68
+ "known_wrong": "If the SQL syntax looks right and follows the same pattern as your other migrations, that's good enough -- you don't need to actually run it locally first, since ADD COLUMN ... NOT NULL DEFAULT ... is a pretty standard, low-risk statement. Just commit it and let it apply automatically when the app starts up in the next environment; if something's actually wrong you'll find out then.",
69
+ "vague": "Make sure the migration actually works before you call it done, not just that it reads fine.",
70
+ "subtle_wrong": "The SQL pattern here is common enough (ADD COLUMN with NOT NULL and a DEFAULT) that as long as it matches how earlier migrations in this project added similar columns, you can be confident it'll apply cleanly -- I'd skip a separate local run for something this standard and just let flywayMigrate pick it up the first time the app boots against the target database, same as any other migration."
71
+ }
72
+ }
73
+ ]
74
+ }
@@ -0,0 +1,128 @@
1
+ ---
2
+ name: java-kotlin-spring-testing
3
+ description: "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."
4
+ triggers:
5
+ - "write JUnit tests for this Spring service"
6
+ - "add MockMvc tests for this Spring controller"
7
+ - "write a @DataJpaTest for this repository"
8
+ - "fix this failing Spring Boot test"
9
+ - "add Mockito tests for this Java class"
10
+ - "write MockK tests for this Kotlin Spring service"
11
+ - "add a Testcontainers integration test for this repository"
12
+ metadata:
13
+ origin: authored
14
+ category: test
15
+ version: "1.0.0"
16
+ compatible_harnesses: "claude,codex,cursor,zed,opencode"
17
+ license: "MIT"
18
+ ---
19
+
20
+ # Java/Kotlin + Spring testing (JUnit 5 + Spring Boot Test)
21
+
22
+ Write, extend, or fix a Java or Kotlin Spring Boot test suite: JUnit 5,
23
+ Mockito/MockK, the narrowest applicable Spring test slice, MockMvc,
24
+ Awaitility, and Testcontainers. `rules/testing.mdc` carries the full rule
25
+ set this skill's checklist is built from — read it, not just this
26
+ summary, before writing tests.
27
+
28
+ ## Workflow
29
+
30
+ ### Step 1: Discover the project's test conventions
31
+
32
+ 1. Read `pom.xml`/`build.gradle(.kts)` to confirm the test dependencies
33
+ already present: JUnit 5, Mockito or MockK, AssertJ, Testcontainers,
34
+ Awaitility.
35
+ 2. Find the layout: `src/test/java` or `src/test/kotlin`, mirroring the
36
+ main package, named `<Type>Test`/`<Type>IT`. Match whichever the
37
+ project already uses.
38
+ 3. Read 1-2 neighboring test classes for: assertion style already in
39
+ use, whether `@SpringBootTest` or a narrower slice
40
+ (`@WebMvcTest`/`@DataJpaTest`) is the norm, and existing
41
+ fixture/builder helpers for entities and DTOs.
42
+
43
+ ### Step 2: Plan test cases and pick the right slice
44
+
45
+ **Plain unit test (no Spring container):** for a service's business
46
+ logic with mocked collaborators — the default choice when the class was
47
+ designed with constructor injection, since it can be constructed
48
+ directly with `Mockito.mock(...)`/MockK mocks passed to the constructor.
49
+
50
+ **`@WebMvcTest`:** for a controller — loads only the web layer, use
51
+ `MockMvc` to exercise request/response mapping, status codes, and
52
+ validation errors, with the service layer mocked via `@MockitoBean`
53
+ (Spring Boot's own `@MockBean` is deprecated as of Boot 3.4 and removed
54
+ in 4.x -- use `@MockitoBean` unless the project is pinned below 3.4).
55
+
56
+ **`@DataJpaTest`:** for a repository — loads only the JPA slice against
57
+ an embedded/test database, verifies query methods (including
58
+ `@EntityGraph`/`JOIN FETCH` actually avoid N+1 where that matters).
59
+
60
+ **`@SpringBootTest`:** only when the interaction across the whole wired
61
+ context is genuinely what is under test — it is the slowest option and
62
+ not a substitute for testing a service in isolation.
63
+
64
+ Cover: happy path, validation-failure cases (Bean Validation constraint
65
+ violations), the self-invocation `@Transactional` boundary if the change
66
+ touches one, and any N+1-prone query path.
67
+
68
+ ### Step 3: Write
69
+
70
+ 1. Create/extend the test file at the project's own convention path.
71
+ 2. Construct the class under test directly when possible (Mockito
72
+ `@Mock`/`@InjectMocks` or manual construction with mocks passed to the
73
+ constructor); reach for `@MockitoBean` only inside a Spring test slice
74
+ (`@MockBean` only on a project still pinned below Spring Boot 3.4).
75
+ 3. For a controller test, assert status code, response body shape, and
76
+ that a Bean Validation failure returns the expected 400 response.
77
+ 4. For a repository test needing a real database, use Testcontainers
78
+ when the project already has it wired up, rather than substituting an
79
+ in-memory database that may not reject what production would.
80
+ 5. Never wait for an async result with `Thread.sleep`/`delay` — use
81
+ Awaitility's `await().atMost(...).until(...)`, a `CompletableFuture`
82
+ join, or a `CountDownLatch`.
83
+
84
+ ### Step 4: Run and fix
85
+
86
+ ```bash
87
+ ./gradlew test # or: mvn test
88
+ ```
89
+
90
+ Fix failing tests (max 3 iterations) — fix the test, not the source under
91
+ test, unless the test itself has correctly caught a real bug (say so in
92
+ the report rather than silently changing production code).
93
+
94
+ ### Step 5: Report
95
+
96
+ ```
97
+ Generated: OrderServiceTest, OrderControllerTest (MockMvc), OrderRepositoryTest (@DataJpaTest)
98
+ - 9 test cases, all passing under ./gradlew test
99
+ ```
100
+
101
+ ## Rules
102
+
103
+ - ALWAYS match the project's existing test-slice, mocking, and assertion
104
+ conventions found in Step 1, not a different project's style.
105
+ - NEVER modify source code — only test files.
106
+ - NEVER use `Thread.sleep`/`delay` to wait for an async result.
107
+ - ALWAYS choose the narrowest Spring test slice that covers what is being
108
+ tested, not `@SpringBootTest` by default.
109
+
110
+ ## Red Flags
111
+
112
+ | Rationalization | Why it is wrong |
113
+ |---|---|
114
+ | "I'll add `Thread.sleep(500)` so the async call finishes before I assert" | Non-deterministic under load; use Awaitility or a real join/latch so the test cannot flake |
115
+ | "I'll just use `@SpringBootTest` for everything, it's simpler than picking a slice" | Loads the entire context for every test class, slowing the suite for no coverage benefit when a narrower slice (`@WebMvcTest`/`@DataJpaTest`) already isolates what's under test |
116
+ | "I'll swap in an in-memory H2 database instead of Testcontainers, it's faster" | An in-memory substitute can silently accept a query the real production database would reject or execute differently; use Testcontainers when the project already has it |
117
+ | "This test keeps failing intermittently, I'll just retry it in CI config" | Retrying hides a real determinism bug (often a missing join/await); fix the wait mechanism instead |
118
+
119
+ ## Verification
120
+
121
+ Do not report the work done until all of the following hold:
122
+
123
+ - The test file sits at the project's own convention path, matching the
124
+ slice/assertion style read in Step 1.
125
+ - `./gradlew test`/`mvn test` exits 0 with every generated test passing.
126
+ - `git status` shows only test files added or modified; no source file
127
+ under test changed.
128
+ - No async wait in a new/changed test uses `Thread.sleep`/`delay`.
@@ -0,0 +1,73 @@
1
+ {
2
+ "triggers": {
3
+ "positive": [
4
+ "OrderCalculator has zero test coverage right now -- can you set up a JUnit 5 suite that exercises the discount logic?",
5
+ "I want to verify the /orders endpoint returns a 404 with the right error body when the order doesn't exist -- what's the MockMvc setup for that?",
6
+ "How do I verify my custom findOverdueInvoices query actually returns the right rows, using an in-memory database slice?",
7
+ "OrderServiceTest started failing after yesterday's refactor and I can't tell if it's a real regression or a stale mock -- can you dig in?",
8
+ "PricingEngine has a couple of external collaborators I'd rather not spin up for a unit test -- can you mock those out and cover the tax calculation paths?",
9
+ "InventoryService is written in Kotlin and calls two collaborators I want stubbed out -- what does a solid mocking-based unit test for it look like?",
10
+ "I don't trust the H2 in-memory results for this repository's native query -- can we spin up a real Postgres container for the test instead?"
11
+ ],
12
+ "negative": [
13
+ "Write pytest tests for this Python function",
14
+ "Add Jest tests for this React component",
15
+ "Write table-driven Go tests for this parser",
16
+ "Add Rust unit tests for this crate",
17
+ "Review this Spring service for goroutine-style concurrency issues",
18
+ "Implement a new Spring Boot endpoint that calls this repository"
19
+ ]
20
+ },
21
+ "scenarios": [
22
+ {
23
+ "id": "no-sleep-awaitility",
24
+ "prompt": "My Spring test kicks off an async @Async method and I want to wait for it to finish before asserting. What's the right way in this Spring Boot test?",
25
+ "strictness": "high",
26
+ "expected_behavior": [
27
+ {
28
+ "grader": "judge",
29
+ "rubric": "A correct answer waits for the async result using an actual synchronization/polling mechanism -- Awaitility's await().atMost(...).until(...), a CompletableFuture join, or a CountDownLatch -- rather than a fixed Thread.sleep delay used as the wait mechanism, whether alone or as extra insurance alongside a real wait.",
30
+ "pass_criteria": [
31
+ "Names a concrete synchronization mechanism -- Awaitility, a CompletableFuture join, or a CountDownLatch -- shown concretely, not just 'wait for it to finish' in the abstract.",
32
+ "Explains why this is reliable/deterministic compared to a fixed delay (it doesn't depend on how long the async method happens to take)."
33
+ ],
34
+ "fail_criteria": [
35
+ "Recommends Thread.sleep as the wait mechanism, whether as the sole way to wait or as additional insurance alongside a real synchronization mechanism. Mentioning Thread.sleep only to warn against it is not a failure."
36
+ ]
37
+ }
38
+ ],
39
+ "calibration": {
40
+ "known_right": "Use Awaitility: `await().atMost(Duration.ofSeconds(2)).until(() -> repository.findById(id).isPresent())` (or whatever condition marks the async work as done) -- it polls the condition instead of guessing a fixed delay, so the test passes as soon as the condition is true and fails clearly if it never becomes true within the timeout. If the @Async method itself returns a `CompletableFuture`, you can instead just call `.get(2, TimeUnit.SECONDS)` on it directly in the test and assert on the result once it resolves. Either way, avoid Thread.sleep for this -- a fixed sleep either wastes time when the async work finishes early or flakes under CI load when it doesn't finish within your guessed window.",
41
+ "known_wrong": "Easiest way is to just add `Thread.sleep(500)` right after triggering the async call, then run your assertions -- that gives it enough time to complete in almost every case without pulling in Awaitility or restructuring the method to return a Future just for a test. If it's still flaky in CI sometimes, bump it up to `Thread.sleep(2000)`.",
42
+ "vague": "Wait for the async method to actually finish before asserting instead of just guessing how long it'll take.",
43
+ "subtle_wrong": "Use Awaitility for the polling: `await().atMost(Duration.ofSeconds(2)).until(() -> repository.findById(id).isPresent())` -- that's the reliable part. If it's still occasionally flaky in CI, add a small `Thread.sleep(200)` right before the await() call too, just to give the async method a head start before polling begins."
44
+ },
45
+ "anti_patterns": ["Thread.sleep"]
46
+ },
47
+ {
48
+ "id": "narrowest-test-slice",
49
+ "prompt": "I need to add tests for a new Spring @RestController that calls a service to fetch an order. Should I use @SpringBootTest?",
50
+ "strictness": "high",
51
+ "expected_behavior": [
52
+ {
53
+ "grader": "judge",
54
+ "rubric": "A correct answer recommends the narrowest slice that actually covers a controller -- @WebMvcTest with MockMvc and the service mocked via @MockitoBean -- instead of @SpringBootTest, and explains that @SpringBootTest loads the whole application context and is unnecessary/slower for testing just the web layer's request/response mapping.",
55
+ "pass_criteria": [
56
+ "Recommends @WebMvcTest (with MockMvc) rather than @SpringBootTest for testing this controller.",
57
+ "States that the service dependency should be mocked (e.g. via @MockitoBean, or @MockBean only on a project pinned below Spring Boot 3.4) rather than using the real service or the full application context.",
58
+ "States a concrete reason @SpringBootTest is the wrong choice here -- it loads the entire application context and is slower/broader than what testing a controller's request/response mapping needs."
59
+ ],
60
+ "fail_criteria": [
61
+ "Recommends @SpringBootTest as the right or default choice for testing this controller's request/response mapping, without a stated reason the wider context is actually needed here."
62
+ ]
63
+ }
64
+ ],
65
+ "calibration": {
66
+ "known_right": "No -- for testing a single controller's request/response mapping, `@WebMvcTest(OrderController.class)` is the better fit. It loads only the web layer (Spring MVC infrastructure, your controller, message converters, validation), not the full application context, so it starts faster and keeps the test focused on what a controller test should actually check: routing, status codes, request/response body shape, and validation errors. Mock the service dependency with `@MockitoBean` (Spring Boot's own `@MockBean` is deprecated since Boot 3.4 and removed in 4.x -- only use it on a project still pinned below 3.4) and use `MockMvc` to perform the request and assert on the result -- you don't need a real service implementation or a database for this. Reach for `@SpringBootTest` only when you actually need the full wired context -- for example, a true end-to-end test spanning multiple layers -- which isn't what's being described here.",
67
+ "known_wrong": "Yes, just use `@SpringBootTest` -- it boots the full application context so you know everything is wired correctly, including the real service and repository, which gives you more confidence than a narrower slice would. You can autowire the real `OrderController` and `MockMvc` through `@AutoConfigureMockMvc` and test it the same way; there's no real downside to using the full context by default, it's simpler to reach for one annotation everywhere instead of picking between different test slices.",
68
+ "vague": "Pick whichever Spring test setup makes sense for testing this controller and keep it reasonably fast.",
69
+ "subtle_wrong": "You could use @WebMvcTest, but honestly @SpringBootTest with @AutoConfigureMockMvc works just as well here and is one less thing to think about when choosing between slices -- it's a bit slower per test class, but for a single new controller that's not going to matter much, and you still get MockMvc the same way. I'd just default to @SpringBootTest for controller tests going forward unless the suite's startup time becomes a real problem."
70
+ }
71
+ }
72
+ ]
73
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "agents": [],
3
+ "note": "no pair -- honest DeepSeek deepseek-chat runner+judge gate (trials=10, strictness=high, flow 336) fails all 4 skills on trigger accuracy alone, never on behavior (every behavior scenario clears the 0.8 floor, mostly 1.0/1.0): compose-implementation TP 3/7 FP 0/7, kotlin-android-testing TP 3/7 FP 0/7, kotlin-android-code-review TP 4/7 FP 0/7, kotlin-android-build-fix TP 4/7 FP 0/7 (this pack's best trigger recall of the four batch-4 packs, and zero false positives across all 4 skills, but still short of the pass bar). Genuine routing weakness against a crowded catalog, not an authoring defect -- stays experimental per flow 336's stack-pack-lessons.md rule against tuning descriptions to restate failing eval prompts."
4
+ }