cc-codeconductor 1.4.1 → 1.5.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 (219) hide show
  1. package/README.md +61 -13
  2. package/dist/core/verification/rdd-receipt.d.ts +39 -0
  3. package/dist/core/verification/verification-runner.d.ts +8 -2
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +1257 -330
  6. package/dist/library.js +267 -26
  7. package/dist/validation/schemas.d.ts +521 -26
  8. package/docs/generated/cli.md +20 -0
  9. package/package.json +1 -1
  10. package/presets/agy/AGENTS.md +6 -0
  11. package/presets/agy/README.md +1 -1
  12. package/presets/agy/hooks.json +1 -1
  13. package/presets/agy/scripts/invoke-hook.cjs +20 -5
  14. package/presets/agy/settings.json +1 -1
  15. package/presets/agy/skills/api-versioning/SKILL.md +394 -0
  16. package/presets/agy/skills/astro/SKILL.md +318 -0
  17. package/presets/agy/skills/auth-token-inspector/SKILL.md +30 -0
  18. package/presets/agy/skills/cc-pagespeed/SKILL.md +2 -3
  19. package/presets/agy/skills/code-review/SKILL.md +207 -0
  20. package/presets/agy/skills/django-orm/SKILL.md +460 -0
  21. package/presets/agy/skills/django-uv/SKILL.md +405 -0
  22. package/presets/agy/skills/drizzle-schema-architect/SKILL.md +50 -0
  23. package/presets/agy/skills/fastapi-pydantic-strict/SKILL.md +43 -0
  24. package/presets/agy/skills/jpa-nplusone-detector/SKILL.md +45 -0
  25. package/presets/agy/skills/jpa-postgres/SKILL.md +623 -0
  26. package/presets/agy/skills/livewire-alpine-bridge/SKILL.md +35 -0
  27. package/presets/agy/skills/nextjs-typescript/SKILL.md +390 -0
  28. package/presets/agy/skills/python/SKILL.md +611 -0
  29. package/presets/agy/skills/seo-analytics-injector/SKILL.md +43 -0
  30. package/presets/agy/skills/spring-auth-auditor/SKILL.md +29 -0
  31. package/presets/agy/skills/spring-boot-feature/SKILL.md +563 -0
  32. package/presets/agy/skills/spring-boot-testing-strategy/SKILL.md +475 -0
  33. package/presets/agy/skills/tailwind-responsive-auditor/SKILL.md +29 -0
  34. package/presets/agy/skills/tdd-mutation-tester/SKILL.md +27 -0
  35. package/presets/agy/workflows/cc-handoff.md +2 -1
  36. package/presets/agy/workflows/cc-odd.md +15 -0
  37. package/presets/agy/workflows/cc-pagespeed.md +2 -3
  38. package/presets/agy/workflows/cc-review.md +31 -0
  39. package/presets/agy/workflows/cc-security.md +1 -1
  40. package/presets/claude/CLAUDE.md +6 -0
  41. package/presets/claude/commands/cc/handoff.md +2 -1
  42. package/presets/claude/commands/cc/odd.md +15 -0
  43. package/presets/claude/commands/cc/review.md +33 -0
  44. package/presets/claude/settings.json +2 -2
  45. package/presets/claude/skills/android/SKILL.md +1 -1
  46. package/presets/claude/skills/api-versioning/SKILL.md +1 -1
  47. package/presets/claude/skills/astro/SKILL.md +318 -0
  48. package/presets/claude/skills/auth-token-inspector/SKILL.md +30 -0
  49. package/presets/claude/skills/code-review/SKILL.md +207 -0
  50. package/presets/claude/skills/django-orm/SKILL.md +1 -1
  51. package/presets/claude/skills/django-testing/SKILL.md +1 -1
  52. package/presets/claude/skills/django-uv/SKILL.md +405 -0
  53. package/presets/claude/skills/drizzle-schema-architect/SKILL.md +50 -0
  54. package/presets/claude/skills/fastapi-pydantic-strict/SKILL.md +43 -0
  55. package/presets/claude/skills/jpa-nplusone-detector/SKILL.md +45 -0
  56. package/presets/claude/skills/jpa-postgres/SKILL.md +1 -1
  57. package/presets/claude/skills/livewire-alpine-bridge/SKILL.md +35 -0
  58. package/presets/claude/skills/nextjs-typescript/SKILL.md +390 -0
  59. package/presets/claude/skills/pagespeed-perf/SKILL.md +1 -1
  60. package/presets/claude/skills/python/SKILL.md +1 -1
  61. package/presets/claude/skills/python-django-stack/SKILL.md +1 -1
  62. package/presets/claude/skills/python-fastapi-stack/SKILL.md +1 -1
  63. package/presets/claude/skills/security/SKILL.md +1 -1
  64. package/presets/claude/skills/seo-analytics-injector/SKILL.md +43 -0
  65. package/presets/claude/skills/spring-auth-auditor/SKILL.md +29 -0
  66. package/presets/claude/skills/spring-boot-feature/SKILL.md +1 -1
  67. package/presets/claude/skills/spring-boot-kotlin/SKILL.md +1 -1
  68. package/presets/claude/skills/spring-boot-testing-strategy/SKILL.md +475 -0
  69. package/presets/claude/skills/sqlalchemy/SKILL.md +1 -1
  70. package/presets/claude/skills/tailwind-responsive-auditor/SKILL.md +29 -0
  71. package/presets/claude/skills/tdd-mutation-tester/SKILL.md +27 -0
  72. package/presets/claude/skills/testing-strategy/SKILL.md +1 -1
  73. package/presets/codex/AGENTS.md +6 -0
  74. package/presets/codex/skills/android/SKILL.md +1 -1
  75. package/presets/codex/skills/api-versioning/SKILL.md +1 -1
  76. package/presets/codex/skills/astro/SKILL.md +318 -0
  77. package/presets/codex/skills/auth-token-inspector/SKILL.md +30 -0
  78. package/presets/codex/skills/cc-handoff/SKILL.md +3 -1
  79. package/presets/codex/skills/cc-odd/SKILL.md +25 -0
  80. package/presets/codex/skills/cc-openspec/SKILL.md +5 -1
  81. package/presets/codex/skills/cc-pagespeed/SKILL.md +2 -3
  82. package/presets/codex/skills/cc-review/SKILL.md +31 -0
  83. package/presets/codex/skills/cc-security/SKILL.md +1 -1
  84. package/presets/codex/skills/cc-spec-mutation/SKILL.md +5 -0
  85. package/presets/codex/skills/cc-tdd-cycle/SKILL.md +8 -0
  86. package/presets/codex/skills/code-review/SKILL.md +207 -0
  87. package/presets/codex/skills/django-orm/SKILL.md +1 -1
  88. package/presets/codex/skills/django-testing/SKILL.md +1 -1
  89. package/presets/codex/skills/django-uv/SKILL.md +405 -0
  90. package/presets/codex/skills/drizzle-schema-architect/SKILL.md +50 -0
  91. package/presets/codex/skills/fastapi-pydantic-strict/SKILL.md +43 -0
  92. package/presets/codex/skills/jpa-nplusone-detector/SKILL.md +45 -0
  93. package/presets/codex/skills/jpa-postgres/SKILL.md +1 -1
  94. package/presets/codex/skills/livewire-alpine-bridge/SKILL.md +35 -0
  95. package/presets/codex/skills/nextjs-typescript/SKILL.md +390 -0
  96. package/presets/codex/skills/pagespeed-perf/SKILL.md +1 -1
  97. package/presets/codex/skills/python/SKILL.md +1 -1
  98. package/presets/codex/skills/python-django-stack/SKILL.md +1 -1
  99. package/presets/codex/skills/python-fastapi-stack/SKILL.md +1 -1
  100. package/presets/codex/skills/security-ai-llm/SKILL.md +43 -0
  101. package/presets/codex/skills/security-blue-team/SKILL.md +43 -0
  102. package/presets/codex/skills/security-cloud/SKILL.md +43 -0
  103. package/presets/codex/skills/security-crypto/SKILL.md +43 -0
  104. package/presets/codex/skills/security-exploit-dev/SKILL.md +45 -0
  105. package/presets/codex/skills/security-grc/SKILL.md +43 -0
  106. package/presets/codex/skills/security-incident-response/SKILL.md +45 -0
  107. package/presets/codex/skills/security-log-analysis/SKILL.md +43 -0
  108. package/presets/codex/skills/security-malware-analysis/SKILL.md +44 -0
  109. package/presets/codex/skills/security-mobile/SKILL.md +43 -0
  110. package/presets/codex/skills/security-network/SKILL.md +43 -0
  111. package/presets/codex/skills/security-ot-ics/SKILL.md +43 -0
  112. package/presets/codex/skills/security-recon/SKILL.md +45 -0
  113. package/presets/codex/skills/security-red-team/SKILL.md +44 -0
  114. package/presets/codex/skills/security-reverse-engineering/SKILL.md +44 -0
  115. package/presets/codex/skills/security-soc-automation/SKILL.md +43 -0
  116. package/presets/codex/skills/security-threat-hunting/SKILL.md +43 -0
  117. package/presets/codex/skills/security-vuln-assessment/SKILL.md +45 -0
  118. package/presets/codex/skills/security-web/SKILL.md +44 -0
  119. package/presets/codex/skills/seo-analytics-injector/SKILL.md +43 -0
  120. package/presets/codex/skills/spring-auth-auditor/SKILL.md +29 -0
  121. package/presets/codex/skills/spring-boot-feature/SKILL.md +2 -2
  122. package/presets/codex/skills/spring-boot-kotlin/SKILL.md +1 -1
  123. package/presets/codex/skills/spring-boot-testing-strategy/SKILL.md +475 -0
  124. package/presets/codex/skills/sqlalchemy/SKILL.md +1 -1
  125. package/presets/codex/skills/tailwind-responsive-auditor/SKILL.md +29 -0
  126. package/presets/codex/skills/tdd-mutation-tester/SKILL.md +27 -0
  127. package/presets/codex/skills/testing-strategy/SKILL.md +1 -1
  128. package/presets/cursor/AGENTS.md +6 -0
  129. package/presets/cursor/commands/cc/handoff.md +3 -1
  130. package/presets/cursor/commands/cc/odd.md +20 -0
  131. package/presets/cursor/commands/cc/openspec.md +5 -1
  132. package/presets/cursor/commands/cc/pagespeed.md +2 -3
  133. package/presets/cursor/commands/cc/review.md +31 -0
  134. package/presets/cursor/commands/cc/security.md +1 -1
  135. package/presets/cursor/commands/cc/spec-mutation.md +5 -0
  136. package/presets/cursor/commands/cc/tdd-cycle.md +8 -0
  137. package/presets/cursor/skills/android/SKILL.md +1 -1
  138. package/presets/cursor/skills/api-versioning/SKILL.md +2 -1
  139. package/presets/cursor/skills/astro/SKILL.md +1 -1
  140. package/presets/cursor/skills/auth-token-inspector/SKILL.md +1 -1
  141. package/presets/cursor/skills/code-review/SKILL.md +1 -1
  142. package/presets/cursor/skills/django-orm/SKILL.md +3 -5
  143. package/presets/cursor/skills/django-testing/SKILL.md +1 -1
  144. package/presets/cursor/skills/django-uv/SKILL.md +1 -1
  145. package/presets/cursor/skills/drizzle-schema-architect/SKILL.md +1 -1
  146. package/presets/cursor/skills/fastapi-pydantic-strict/SKILL.md +1 -1
  147. package/presets/cursor/skills/jpa-nplusone-detector/SKILL.md +1 -1
  148. package/presets/cursor/skills/jpa-postgres/SKILL.md +2 -4
  149. package/presets/cursor/skills/livewire-alpine-bridge/SKILL.md +1 -1
  150. package/presets/cursor/skills/nextjs-typescript/SKILL.md +1 -1
  151. package/presets/cursor/skills/pagespeed-perf/SKILL.md +1 -1
  152. package/presets/cursor/skills/python/SKILL.md +6 -7
  153. package/presets/cursor/skills/python-django-stack/SKILL.md +1 -1
  154. package/presets/cursor/skills/python-fastapi-stack/SKILL.md +1 -1
  155. package/presets/cursor/skills/security/SKILL.md +1 -1
  156. package/presets/cursor/skills/seo-analytics-injector/SKILL.md +1 -1
  157. package/presets/cursor/skills/spring-auth-auditor/SKILL.md +1 -1
  158. package/presets/cursor/skills/spring-boot-feature/SKILL.md +2 -4
  159. package/presets/cursor/skills/spring-boot-kotlin/SKILL.md +1 -1
  160. package/presets/cursor/skills/spring-boot-testing-strategy/SKILL.md +1 -1
  161. package/presets/cursor/skills/sqlalchemy/SKILL.md +1 -1
  162. package/presets/cursor/skills/tailwind-responsive-auditor/SKILL.md +1 -1
  163. package/presets/cursor/skills/tdd-mutation-tester/SKILL.md +1 -1
  164. package/presets/gemini/GEMINI.md +6 -0
  165. package/presets/gemini/commands/cc/handoff.toml +3 -1
  166. package/presets/gemini/commands/cc/odd.toml +20 -0
  167. package/presets/gemini/commands/cc/openspec.toml +5 -1
  168. package/presets/gemini/commands/cc/pagespeed.toml +2 -3
  169. package/presets/gemini/commands/cc/review.toml +31 -0
  170. package/presets/gemini/commands/cc/security.toml +1 -1
  171. package/presets/gemini/commands/cc/spec-mutation.toml +5 -0
  172. package/presets/gemini/commands/cc/tdd-cycle.toml +8 -0
  173. package/presets/opencode/README.md +45 -52
  174. package/presets/opencode/agents/implementer.md +2 -0
  175. package/presets/opencode/agents/reviewer.md +2 -0
  176. package/presets/opencode/agents/tester.md +2 -0
  177. package/presets/opencode/commands/cc-handoff.md +2 -1
  178. package/presets/opencode/commands/cc-odd.md +15 -0
  179. package/presets/opencode/commands/cc-pagespeed.md +2 -3
  180. package/presets/opencode/commands/cc-review.md +31 -0
  181. package/presets/opencode/commands/cc-security.md +1 -1
  182. package/presets/opencode/opencode.jsonc +1 -1
  183. package/presets/opencode/skills/android/SKILL.md +1 -1
  184. package/presets/opencode/skills/api-versioning/SKILL.md +2 -1
  185. package/presets/opencode/skills/astro/SKILL.md +1 -1
  186. package/presets/opencode/skills/auth-token-inspector/SKILL.md +1 -1
  187. package/presets/opencode/skills/code-review/SKILL.md +1 -1
  188. package/presets/opencode/skills/django-orm/SKILL.md +3 -3
  189. package/presets/opencode/skills/django-testing/SKILL.md +1 -1
  190. package/presets/opencode/skills/django-uv/SKILL.md +1 -1
  191. package/presets/opencode/skills/drizzle-schema-architect/SKILL.md +1 -1
  192. package/presets/opencode/skills/fastapi-pydantic-strict/SKILL.md +1 -1
  193. package/presets/opencode/skills/jpa-nplusone-detector/SKILL.md +1 -1
  194. package/presets/opencode/skills/jpa-postgres/SKILL.md +2 -1
  195. package/presets/opencode/skills/livewire-alpine-bridge/SKILL.md +1 -1
  196. package/presets/opencode/skills/nextjs-typescript/SKILL.md +1 -1
  197. package/presets/opencode/skills/pagespeed-perf/SKILL.md +1 -1
  198. package/presets/opencode/skills/python/SKILL.md +6 -5
  199. package/presets/opencode/skills/python-django-stack/SKILL.md +1 -1
  200. package/presets/opencode/skills/python-fastapi-stack/SKILL.md +1 -1
  201. package/presets/opencode/skills/security/SKILL.md +1 -1
  202. package/presets/opencode/skills/seo-analytics-injector/SKILL.md +1 -1
  203. package/presets/opencode/skills/spring-auth-auditor/SKILL.md +1 -1
  204. package/presets/opencode/skills/spring-boot-feature/SKILL.md +2 -1
  205. package/presets/opencode/skills/spring-boot-kotlin/SKILL.md +1 -1
  206. package/presets/opencode/skills/spring-boot-testing-strategy/SKILL.md +1 -1
  207. package/presets/opencode/skills/sqlalchemy/SKILL.md +1 -1
  208. package/presets/opencode/skills/tailwind-responsive-auditor/SKILL.md +1 -1
  209. package/presets/opencode/skills/tdd-mutation-tester/SKILL.md +1 -1
  210. package/presets/pi/AGENTS.md +6 -0
  211. package/presets/seo-hotel/skills/astro-seo/SKILL.md +1 -1
  212. package/presets/seo-hotel/skills/geo-readiness/SKILL.md +1 -1
  213. package/presets/seo-hotel/skills/off-page/SKILL.md +1 -1
  214. package/presets/seo-hotel/skills/schema-validator/SKILL.md +1 -1
  215. package/presets/seo-hotel/skills/seo-audit/SKILL.md +1 -1
  216. package/presets/shared/invoke-hook.cjs +20 -5
  217. package/src/presets/models/roles.yml +28 -28
  218. package/src/presets/shared-skills.yml +58 -22
  219. package/src/presets/targets/pi.yml +1 -0
@@ -0,0 +1,475 @@
1
+ ---
2
+ id: spring-boot-testing-strategy
3
+ name: spring-boot-testing-strategy
4
+ description: >
5
+ Provides expert knowledge of the testing pyramid, test design principles, MockK patterns, and integration testing conventions for Spring Boot + Kotlin projects.
6
+
7
+ user-invokable: true
8
+ license: MIT
9
+ metadata:
10
+ author: lgzarturo
11
+ category: testing
12
+
13
+ compatibility:
14
+ tools: [claude, codex, gemini, agy, opencode]
15
+ stacks:
16
+ languages: [kotlin, java]
17
+ frameworks: [spring-boot, kotest, mockk, junit5, mockk, testcontainers, assertj]
18
+ databases: [postgresql, sqlite, h2]
19
+
20
+ risk:
21
+ level: low
22
+ can_execute_shell: false
23
+ can_modify_files: true
24
+ requires_network: false
25
+
26
+ inputs: []
27
+
28
+ outputs: []
29
+
30
+ quality:
31
+ reviewed_by: codeconductor-core
32
+ version: 0.1.0
33
+ ---
34
+
35
+ # Testing Strategy
36
+
37
+ ## Testing Pyramid
38
+
39
+ ```text
40
+ /\
41
+ / \
42
+ / E2E\ 10% — full API, happy path + main error cases
43
+ /------\
44
+ / Integ \ 20% — components with real dependencies (DB, HTTP)
45
+ /----------\
46
+ / Unit \ 70% — isolated, mocked dependencies, fast
47
+ /______________\
48
+ ```
49
+
50
+ Unit tests are the foundation. They are fast, deterministic, and cheap to run.
51
+ Integration tests validate that components work together. E2E tests validate
52
+ that the system works end to end — keep them minimal.
53
+
54
+ If you find yourself writing more integration tests than unit tests, the code
55
+ under test has too many responsibilities bundled together.
56
+
57
+ ## Test Naming Convention
58
+
59
+ Format: `should [expected behavior] when [condition]`
60
+
61
+ ```kotlin
62
+ @Test
63
+ fun `should return user when found by id`() { ... }
64
+
65
+ @Test
66
+ fun `should return 404 when user does not exist`() { ... }
67
+
68
+ @Test
69
+ fun `should throw ConflictException when email already exists`() { ... }
70
+
71
+ @Test
72
+ fun `should not return deleted users in list`() { ... }
73
+ ```
74
+
75
+ Group related tests with `@Nested`:
76
+
77
+ ```kotlin
78
+ @ExtendWith(MockKExtension::class)
79
+ class UserServiceTest {
80
+
81
+ @Nested
82
+ inner class GetById {
83
+ @Test
84
+ fun `should return user when found`() { ... }
85
+
86
+ @Test
87
+ fun `should return NotFound when user does not exist`() { ... }
88
+ }
89
+
90
+ @Nested
91
+ inner class Create {
92
+ @Test
93
+ fun `should create and return user when email is unique`() { ... }
94
+
95
+ @Test
96
+ fun `should throw ConflictException when email already exists`() { ... }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Unit Test Structure (AAA)
102
+
103
+ Every test follows Arrange → Act → Assert. Use blank lines to separate each
104
+ phase.
105
+
106
+ ```kotlin
107
+ @Test
108
+ fun `should return user when found by id`() {
109
+ // Arrange
110
+ val userId = UUID.randomUUID()
111
+ val user = User(id = userId, email = "user@example.com", name = "Test User")
112
+ every { userRepository.findById(userId) } returns Optional.of(user)
113
+
114
+ // Act
115
+ val result = userService.getById(userId)
116
+
117
+ // Assert
118
+ assertThat(result).isInstanceOf(UserResult.Found::class.java)
119
+ val found = result as UserResult.Found
120
+ assertThat(found.user.id).isEqualTo(userId)
121
+ verify(exactly = 1) { userRepository.findById(userId) }
122
+ }
123
+ ```
124
+
125
+ No inline comments between phases once the structure is clear. The blank lines
126
+ are enough.
127
+
128
+ ## What NOT to Test
129
+
130
+ **Framework wiring.** Spring handles dependency injection. Do not write tests
131
+ that verify `@Autowired` works.
132
+
133
+ **JPA mapping.** Do not test that `@Column(name = "email")` maps to the right
134
+ column. That is Hibernate's job.
135
+
136
+ **Trivial getters and setters.** A data class property has no logic. There is
137
+ nothing to test.
138
+
139
+ **Private methods directly.** Private methods are implementation details. Test
140
+ them through the public behavior that uses them. If a private method is complex
141
+ enough to need its own test, it should be extracted into a separate class.
142
+
143
+ **Implementation, not behavior.** Tests that verify HOW something is done (mock
144
+ call order, internal state) are brittle. Test WHAT the output or side effect is.
145
+
146
+ ```kotlin
147
+ // bad — tests implementation detail
148
+ verify { userRepository.findById(any()) }
149
+ verify { cacheService.put(any(), any()) }
150
+ verify(ordering = Ordering.ORDERED) { // this is too coupled to internals
151
+ userRepository.findById(userId)
152
+ cacheService.put(userId, user)
153
+ }
154
+
155
+ // good — tests observable behavior
156
+ assertThat(result).isEqualTo(expectedUser)
157
+ ```
158
+
159
+ ## MockK Patterns
160
+
161
+ ### Basic Setup
162
+
163
+ ```kotlin
164
+ @ExtendWith(MockKExtension::class)
165
+ class UserServiceTest {
166
+
167
+ @MockK
168
+ private lateinit var userRepository: UserRepository
169
+
170
+ @MockK
171
+ private lateinit var emailService: EmailService
172
+
173
+ private lateinit var userService: UserService
174
+
175
+ @BeforeEach
176
+ fun setUp() {
177
+ userService = UserService(userRepository, emailService)
178
+ }
179
+ }
180
+ ```
181
+
182
+ ### Stubbing
183
+
184
+ ```kotlin
185
+ // Return value
186
+ every { userRepository.findById(userId) } returns Optional.of(user)
187
+
188
+ // Return null (for nullable return types)
189
+ every { userRepository.findByEmail(any()) } returns null
190
+
191
+ // Throw exception
192
+ every { userRepository.save(any()) } throws DataIntegrityViolationException("Duplicate")
193
+
194
+ // Return different values on successive calls
195
+ every { userRepository.findById(any()) } returnsMany listOf(Optional.of(user), Optional.empty())
196
+
197
+ // Answer with computation
198
+ every { userRepository.save(any()) } answers { firstArg() }
199
+ ```
200
+
201
+ ### Verification
202
+
203
+ ```kotlin
204
+ // Verify called exactly once with specific argument
205
+ verify(exactly = 1) { userRepository.findById(userId) }
206
+
207
+ // Verify called with any argument
208
+ verify { emailService.sendWelcome(any()) }
209
+
210
+ // Verify never called
211
+ verify(exactly = 0) { emailService.sendWelcome(any()) }
212
+
213
+ // Verify called with specific argument
214
+ verify { emailService.sendWelcome(match { it.email == "user@example.com" }) }
215
+ ```
216
+
217
+ ### Relaxed Mocks
218
+
219
+ ```kotlin
220
+ // relaxed = true — returns default values (null, 0, false, empty list)
221
+ // Use only when you do not care about the return value of any method
222
+ val logger = mockk<Logger>(relaxed = true)
223
+ ```
224
+
225
+ Do not use `relaxed = true` on mocks where you need to verify behavior — a
226
+ relaxed mock does not fail on unexpected calls, which can hide bugs.
227
+
228
+ ### Coroutines
229
+
230
+ ```kotlin
231
+ // Stubbing suspend functions
232
+ coEvery { userRepository.findById(userId) } returns user
233
+
234
+ // Verifying suspend functions
235
+ coVerify(exactly = 1) { userRepository.findById(userId) }
236
+ ```
237
+
238
+ ### Argument Matchers
239
+
240
+ ```kotlin
241
+ // Any value
242
+ every { service.process(any()) } returns result
243
+
244
+ // Specific type
245
+ every { service.process(any<UserRequest>()) } returns result
246
+
247
+ // Custom predicate
248
+ every { service.notify(match { it.email.endsWith("@example.com") }) } just Runs
249
+
250
+ // Capture for assertion
251
+ val slot = slot<User>()
252
+ every { userRepository.save(capture(slot)) } returns savedUser
253
+ // ... trigger the action ...
254
+ assertThat(slot.captured.email).isEqualTo("expected@example.com")
255
+ ```
256
+
257
+ ## Integration Test Patterns
258
+
259
+ ### Controller Tests with MockMvc
260
+
261
+ ```kotlin
262
+ @SpringBootTest
263
+ @AutoConfigureMockMvc
264
+ class UserControllerTest {
265
+
266
+ @Autowired
267
+ private lateinit var mockMvc: MockMvc
268
+
269
+ @Autowired
270
+ private lateinit var objectMapper: ObjectMapper
271
+
272
+ @Test
273
+ fun `should return 200 with user when found`() {
274
+ mockMvc.perform(
275
+ get("/api/v1/users/${existingUser.id}")
276
+ .contentType(MediaType.APPLICATION_JSON)
277
+ )
278
+ .andExpect(status().isOk)
279
+ .andExpect(jsonPath("$.email").value(existingUser.email))
280
+ .andExpect(jsonPath("$.id").value(existingUser.id.toString()))
281
+ }
282
+
283
+ @Test
284
+ fun `should return 400 when request body is invalid`() {
285
+ val invalidRequest = mapOf("email" to "not-an-email")
286
+
287
+ mockMvc.perform(
288
+ post("/api/v1/users")
289
+ .contentType(MediaType.APPLICATION_JSON)
290
+ .content(objectMapper.writeValueAsString(invalidRequest))
291
+ )
292
+ .andExpect(status().isBadRequest)
293
+ .andExpect(jsonPath("$.code").value("VALIDATION_ERROR"))
294
+ }
295
+
296
+ @Test
297
+ fun `should return 404 when user is not found`() {
298
+ mockMvc.perform(get("/api/v1/users/${UUID.randomUUID()}"))
299
+ .andExpect(status().isNotFound)
300
+ }
301
+ }
302
+ ```
303
+
304
+ `@AutoConfigureMockMvc` configures MockMvc without starting a real HTTP server.
305
+ The test is faster than `RANDOM_PORT` but still tests the full Spring MVC stack.
306
+
307
+ Use `RANDOM_PORT` only when you need real HTTP (e.g., testing HTTP client
308
+ behavior, WebSockets, or SSE).
309
+
310
+ ### Database Tests with Testcontainers
311
+
312
+ ```kotlin
313
+ @SpringBootTest
314
+ @Testcontainers
315
+ class UserRepositoryIntegrationTest {
316
+
317
+ companion object {
318
+ @Container
319
+ @JvmStatic
320
+ val postgres = PostgreSQLContainer<Nothing>("postgres:16").apply {
321
+ withDatabaseName("testdb")
322
+ withUsername("test")
323
+ withPassword("test")
324
+ }
325
+
326
+ @DynamicPropertySource
327
+ @JvmStatic
328
+ fun overrideProperties(registry: DynamicPropertyRegistry) {
329
+ registry.add("spring.datasource.url", postgres::getJdbcUrl)
330
+ registry.add("spring.datasource.username", postgres::getUsername)
331
+ registry.add("spring.datasource.password", postgres::getPassword)
332
+ }
333
+ }
334
+
335
+ @Autowired
336
+ private lateinit var userRepository: UserRepository
337
+
338
+ @Test
339
+ fun `should enforce unique email at database level`() {
340
+ userRepository.save(User(email = "unique@example.com", name = "First"))
341
+ assertThrows<DataIntegrityViolationException> {
342
+ userRepository.save(User(email = "unique@example.com", name = "Second"))
343
+ }
344
+ }
345
+ }
346
+ ```
347
+
348
+ Share the container across test classes using a base class with `@Container` on
349
+ a static field. Testcontainers reuses the same container if the configuration is
350
+ identical.
351
+
352
+ ### Seed Data with @Sql
353
+
354
+ ```kotlin
355
+ @SpringBootTest
356
+ @AutoConfigureMockMvc
357
+ @Sql("/test-data/users.sql") // runs before each test in this class
358
+ class UserControllerTest { ... }
359
+
360
+ // Or per-test
361
+ @Test
362
+ @Sql("/test-data/users-with-orders.sql")
363
+ fun `should return orders when user has orders`() { ... }
364
+ ```
365
+
366
+ SQL files go in `src/test/resources/test-data/`. Use descriptive names that
367
+ explain what state they create, not what feature they serve.
368
+
369
+ ## Test Data Factories
370
+
371
+ Never hardcode UUIDs or share mutable state between tests.
372
+
373
+ ```kotlin
374
+ object UserTestFactory {
375
+
376
+ fun create(
377
+ id: UUID = UUID.randomUUID(),
378
+ email: String = "user-${UUID.randomUUID()}@example.com",
379
+ name: String = "Test User",
380
+ role: UserRole = UserRole.USER
381
+ ): User = User(
382
+ id = id,
383
+ email = email,
384
+ name = name,
385
+ role = role
386
+ )
387
+
388
+ fun createRequest(
389
+ email: String = "user-${UUID.randomUUID()}@example.com",
390
+ name: String = "Test User"
391
+ ): CreateUserRequest = CreateUserRequest(
392
+ email = email,
393
+ name = name
394
+ )
395
+
396
+ fun createAdmin(): User = create(role = UserRole.ADMIN)
397
+
398
+ fun createList(count: Int): List<User> = (1..count).map { create() }
399
+ }
400
+ ```
401
+
402
+ Usage in tests:
403
+
404
+ ```kotlin
405
+ val user = UserTestFactory.create(email = "specific@example.com")
406
+ val admin = UserTestFactory.createAdmin()
407
+ val users = UserTestFactory.createList(5)
408
+ ```
409
+
410
+ Default values use `UUID.randomUUID()` to ensure tests do not share state
411
+ through hardcoded IDs or emails.
412
+
413
+ ## When Tests Are Required
414
+
415
+ **New behavior.** Every new feature requires at minimum one unit test and one
416
+ integration test covering the happy path. Edge cases and error paths require
417
+ additional unit tests.
418
+
419
+ **Bug fix.** Write a regression test that reproduces the bug before fixing it.
420
+ The test must fail before the fix and pass after. This prevents the bug from
421
+ reappearing silently.
422
+
423
+ ```kotlin
424
+ // Example: bug where findByEmail returned deleted users
425
+ @Test
426
+ fun `should not return deleted user — regression for bug #42`() {
427
+ val user = userRepository.save(UserTestFactory.create(email = "gone@example.com"))
428
+ userRepository.delete(user)
429
+ val result = userRepository.findByEmail("gone@example.com")
430
+ assertThat(result).isNull()
431
+ }
432
+ ```
433
+
434
+ **Refactor.** Do not write new tests. The existing tests must pass unchanged. If
435
+ they do not, the refactor changed behavior — that is a bug.
436
+
437
+ **High-risk paths.** Security, payment processing, data migrations, and
438
+ permission checks require contract tests in addition to unit and integration
439
+ tests. These paths have severe consequences if broken.
440
+
441
+ ## CI Integration
442
+
443
+ Tests must run in CI on every pull request. The pipeline must fail if any test
444
+ fails.
445
+
446
+ Recommended test execution order:
447
+
448
+ 1. Unit tests (fastest — fail fast)
449
+ 2. Integration tests with H2 (`@DataJpaTest`)
450
+ 3. Integration tests with Testcontainers (slowest — run last)
451
+
452
+ Separate test tasks in Gradle:
453
+
454
+ ```kotlin
455
+ // build.gradle.kts
456
+ tasks.register<Test>("integrationTest") {
457
+ description = "Runs integration tests"
458
+ group = "verification"
459
+ useJUnitPlatform {
460
+ includeTags("integration")
461
+ }
462
+ shouldRunAfter(tasks.test)
463
+ }
464
+ ```
465
+
466
+ Tag integration tests:
467
+
468
+ ```kotlin
469
+ @Tag("integration")
470
+ @SpringBootTest
471
+ class UserRepositoryIntegrationTest { ... }
472
+ ```
473
+
474
+ Do not mix unit and integration test tags in the same class. A test class is
475
+ either one or the other.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: sqlalchemy
3
- name: SQLAlchemy
3
+ name: sqlalchemy
4
4
  description: >
5
5
  SQLAlchemy 2.x patterns for async FastAPI projects: models, sessions, queries,
6
6
  bulk operations, transactions, and Alembic migrations.
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: tailwind-responsive-auditor
3
+ name: tailwind-responsive-auditor
4
+ description: >
5
+ Audits Tailwind CSS usage ensuring mobile-first responsive utilities and clean classes.
6
+ user-invokable: true
7
+ license: MIT
8
+ metadata:
9
+ author: lgzarturo
10
+ category: frontend
11
+ compatibility:
12
+ tools: [claude, codex, gemini, agy, opencode]
13
+ stacks:
14
+ languages: [typescript, javascript, html]
15
+ frameworks: [astro, nextjs, react, tailwindcss]
16
+ ---
17
+ # Tailwind Responsive Auditor
18
+
19
+ ## Core Principles
20
+
21
+ 1. **Mobile-First Design**: Always apply styles for mobile first (without breakpoints), then override them for larger screens (`sm:`, `md:`, `lg:`, `xl:`).
22
+ 2. **Class Deduplication**: Avoid redundant classes (e.g. `w-full w-auto` or `text-red-500 text-blue-500`).
23
+ 3. **No Arbitrary Values**: Avoid using arbitrary values like `w-[327px]` or `bg-[#f0f0f0]` unless absolutely necessary. Rely on the configured Tailwind theme.
24
+
25
+ ## Audit Checklist
26
+
27
+ - Do not use desktop-first design (e.g., max-width utilities should be avoided unless specified).
28
+ - Ensure that elements have responsive margins, padding, and layout flex/grid direction where needed.
29
+ - Alert on duplicate or conflicting utility classes in component files.
@@ -0,0 +1,27 @@
1
+ ---
2
+ id: tdd-mutation-tester
3
+ name: tdd-mutation-tester
4
+ description: >
5
+ Performs simple mutation testing to verify test coverage and assertions.
6
+ user-invokable: true
7
+ license: MIT
8
+ metadata:
9
+ author: lgzarturo
10
+ category: testing
11
+ compatibility:
12
+ tools: [claude, codex, gemini, agy, opencode]
13
+ stacks:
14
+ languages: [typescript, javascript, python, kotlin, java, php]
15
+ ---
16
+ # TDD Mutation Tester
17
+
18
+ ## Core Principles
19
+
20
+ 1. **Verify Assertion Quality**: Coverage percentage can be misleading. Tests must fail when business logic changes.
21
+ 2. **Mutation Process**:
22
+ - Locate the core logic implemented by the `implementer`.
23
+ - Temporarily mutate a logical operator (e.g. swap `>` for `<`, `==` for `!=`, `+` for `-`, or invert a boolean).
24
+ - Run the test suite.
25
+ - **Expected Result**: At least one test MUST fail.
26
+ - **Clean Up**: Revert the mutated symbol immediately after running the test.
27
+ 3. **Scorecard**: If the test suite passes even with mutated business logic, report a "0 in Real Coverage" on the scorecard and return the task for better test assertions.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: testing-strategy
3
- name: Testing Strategy
3
+ name: testing-strategy
4
4
  description: >
5
5
  Provides expert knowledge of the testing pyramid, test design principles,
6
6
  MockK patterns, and integration testing conventions for Spring Boot + Kotlin
@@ -459,6 +459,12 @@ docs | test **Risk:** low | medium | high **Scope:** [files or modules affected]
459
459
  **Agent:** [agent name] **Requires review:** yes | no
460
460
  ```
461
461
 
462
+ ## Receipt integrity
463
+
464
+ - For any implementation, test, review, handoff, or delivery decision, capture or verify the current RDD receipt with `bun run dev rdd`.
465
+ - A receipt is valid only for its exact candidate. If code, tests, contracts, or runner configuration changed, repeat the affected verification.
466
+ - TDD and Mutation Testing retain their existing gates; RDD verifies that their observed evidence still belongs to the current candidate.
467
+
462
468
  <!-- CODECONDUCTOR:END managed -->
463
469
 
464
470
  ---
@@ -30,7 +30,9 @@ errors instead of pasting dumps. If unresolved credential material remains, stop
30
30
  and wait for a human (CCEP `stopOnHighRisk`).
31
31
 
32
32
  Include: goal, Task Card status (no secret fields), files touched, test
33
- pass/fail (not log dumps), open questions, and the next `/cc:` command.
33
+ pass/fail (not log dumps), open questions, the next `/cc:` command, plus links
34
+ to the Delivery Ledger and verification evidence when they exist. Do not repeat
35
+ the original request or transcript.
34
36
 
35
37
  Do not edit source or tests.
36
38
 
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Create or resume an opt-in Delivery Ledger for substantial authorized work.
3
+ ---
4
+
5
+ # /cc:odd
6
+
7
+ ## Step 0 — CCEP Bootstrap
8
+
9
+ ```bash
10
+ bun run dev ccep parse --command odd "$ARGUMENTS"
11
+ bun run dev ccep resolve --command odd "$ARGUMENTS"
12
+ bun run dev ccep profile --command odd
13
+ ```
14
+
15
+ Create a ledger only after authorization and tracked coordination. Read-only and small work do not create state.
16
+
17
+ When ODD has verification evidence, include its RDD receipt in the ledger
18
+ handoff. On resume, verify it against the workspace before relying on a prior
19
+ test or review result. If it is stale, keep the ledger and repeat only the
20
+ invalidated verification.
@@ -135,6 +135,10 @@ npx cc-codeconductor openspec archive <itemId>
135
135
 
136
136
  `start` moves the card `pending → doing` and the item `PLANNED → IN_PROGRESS`. `done` marks the card complete, updates Progress, and moves the item to `REVIEW` when every card is done and review is required. `archive` requires all cards done (and review evidence when Global review is required) and moves `openspec/changes/<slug>` to `archive/`.
137
137
 
138
+ For test and implementation cards, `done` also requires a current RDD-backed
139
+ RED or GREEN receipt respectively. Do not reuse evidence after candidate files
140
+ change; capture and verify the matching receipt again.
141
+
138
142
  ---
139
143
 
140
144
  ## Step 5 — Model matrix and execute loop
@@ -207,4 +211,4 @@ Report completion: Task Cards executed, scorecard verdict, change folder path, f
207
211
 
208
212
  ## Skill
209
213
 
210
- Apply `.claude/skills/openspec/SKILL.md` for backlog format rules and state transitions.
214
+ Apply `.cursor/skills/openspec/SKILL.md` for backlog format rules and state transitions.
@@ -63,9 +63,8 @@ the following steps in order:
63
63
  the output filename: `{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`.
64
64
 
65
65
  2. **Collect** — Call the PageSpeed Insights API for the requested strategy
66
- (`mobile`, `desktop`, or `both`). Prefer the Bun scripts in
67
- `~/.claude/skills/pagespeed-perf/scripts/run.ts` if Bun is available.
68
- Otherwise, use `WebFetch` to call the PSI endpoint directly.
66
+ (`mobile`, `desktop`, or `both`) using `WebFetch` to call the PSI endpoint
67
+ directly.
69
68
 
70
69
  3. **Analyze** — Extract Core Web Vitals (LCP, INP, CLS, FCP, TTFB, TBT),
71
70
  identify the LCP element, enumerate third-party scripts by blocking time,
@@ -113,6 +113,37 @@ Evaluate the diff against the following checklist:
113
113
 
114
114
  ---
115
115
 
116
+ ## Severity Rubric
117
+
118
+ Classify every finding using these concrete anchors — not general judgment —
119
+ so the same finding gets the same category on any run.
120
+
121
+ **CRITICAL** (always):
122
+
123
+ - Unauthenticated access to a protected resource
124
+ - Injection (SQL, command, XSS) reachable from untrusted input
125
+ - A secret or credential present in the diff
126
+ - A destructive operation with no confirmation
127
+ - The build or test suite is broken
128
+ - A direct contradiction of an explicit acceptance criterion
129
+
130
+ **WARNING**:
131
+
132
+ - Missing test for a new branch or edge case
133
+ - An error is silently swallowed — no log, no propagation
134
+ - A change outside the declared scope
135
+ - Inconsistent with an established pattern already in the module
136
+ - Missing input validation in an internal function (not exposed at a trust boundary)
137
+
138
+ **SUGGESTION**:
139
+
140
+ - Style or naming
141
+ - Minor readability
142
+ - Speculative refactor that wasn't requested
143
+ - Non-blocking micro-optimization
144
+
145
+ ---
146
+
116
147
  ## Step 3 — Review Report
117
148
 
118
149
  Produce a structured Review Report with findings in three categories:
@@ -62,7 +62,7 @@ If `graphify-out/graph.json` exists, run `graphify query "$ARGUMENTS"` (and
62
62
  `graphify path` / `graphify explain` when needed). Then invoke `repo-explorer`
63
63
  to map modules, conventions, and impact radius. Do not write code in this step.
64
64
  Record a Repo Map artifact before intake. Load the matching `security-*` skill
65
- for the named domain (see `.claude/skills/security-*/SKILL.md`). Keep the OWASP
65
+ for the named domain (see `.cursor/skills/security-*/SKILL.md`). Keep the OWASP
66
66
  `security` skill for application-security reviews.
67
67
 
68
68
  ---
@@ -129,6 +129,11 @@ Verdict is binary: PASS continues to the mutation gate; REJECT returns to the
129
129
 
130
130
  ## Stage 5 — Mutation gate (`mutation_testing`)
131
131
 
132
+ RDD complements this gate: capture the candidate receipt before Mutation Testing
133
+ and verify it after the runner restores production source. A survivor opens a
134
+ new tester/reviewer-approved test revision; it never makes an earlier receipt
135
+ valid again.
136
+
132
137
  Run the deterministic AST mutator shipped with this preset:
133
138
 
134
139
  ```bash