@c0x12c/ai-toolkit 1.15.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 (255) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/README.md +439 -0
  4. package/VERSION +1 -0
  5. package/agents/design-critic.md +127 -0
  6. package/agents/idea-killer.md +72 -0
  7. package/agents/infrastructure-expert.md +49 -0
  8. package/agents/micronaut-backend-expert.md +45 -0
  9. package/agents/phase-reviewer.md +150 -0
  10. package/agents/research-planner.md +70 -0
  11. package/agents/solution-architect-cto.md +49 -0
  12. package/agents/sre-architect.md +49 -0
  13. package/agents/team-coordinator.md +111 -0
  14. package/bin/cli.js +780 -0
  15. package/claude-md/00-header.md +39 -0
  16. package/claude-md/01-core.md +105 -0
  17. package/claude-md/05-database.md +20 -0
  18. package/claude-md/11-backend-micronaut.md +19 -0
  19. package/claude-md/20-frontend-react.md +44 -0
  20. package/claude-md/25-ux-design.md +56 -0
  21. package/claude-md/30-infrastructure.md +24 -0
  22. package/claude-md/30-project-mgmt.md +119 -0
  23. package/claude-md/40-product.md +39 -0
  24. package/claude-md/50-ops.md +34 -0
  25. package/claude-md/60-research.md +27 -0
  26. package/claude-md/90-footer.md +21 -0
  27. package/commands/spartan/brainstorm.md +134 -0
  28. package/commands/spartan/brownfield.md +157 -0
  29. package/commands/spartan/build.md +435 -0
  30. package/commands/spartan/careful.md +94 -0
  31. package/commands/spartan/commit-message.md +112 -0
  32. package/commands/spartan/content.md +17 -0
  33. package/commands/spartan/context-save.md +161 -0
  34. package/commands/spartan/contribute.md +140 -0
  35. package/commands/spartan/daily.md +42 -0
  36. package/commands/spartan/debug.md +308 -0
  37. package/commands/spartan/deep-dive.md +55 -0
  38. package/commands/spartan/deploy.md +207 -0
  39. package/commands/spartan/e2e.md +264 -0
  40. package/commands/spartan/env-setup.md +166 -0
  41. package/commands/spartan/epic.md +199 -0
  42. package/commands/spartan/fe-review.md +181 -0
  43. package/commands/spartan/figma-to-code.md +260 -0
  44. package/commands/spartan/forensics.md +46 -0
  45. package/commands/spartan/freeze.md +84 -0
  46. package/commands/spartan/fundraise.md +53 -0
  47. package/commands/spartan/gate-review.md +229 -0
  48. package/commands/spartan/gsd-upgrade.md +376 -0
  49. package/commands/spartan/guard.md +42 -0
  50. package/commands/spartan/init-project.md +178 -0
  51. package/commands/spartan/init-rules.md +298 -0
  52. package/commands/spartan/interview.md +154 -0
  53. package/commands/spartan/kickoff.md +73 -0
  54. package/commands/spartan/kotlin-service.md +109 -0
  55. package/commands/spartan/lean-canvas.md +222 -0
  56. package/commands/spartan/lint-rules.md +122 -0
  57. package/commands/spartan/map-codebase.md +124 -0
  58. package/commands/spartan/migration.md +82 -0
  59. package/commands/spartan/next-app.md +317 -0
  60. package/commands/spartan/next-feature.md +212 -0
  61. package/commands/spartan/onboard.md +326 -0
  62. package/commands/spartan/outreach.md +16 -0
  63. package/commands/spartan/phase.md +142 -0
  64. package/commands/spartan/pitch.md +18 -0
  65. package/commands/spartan/plan.md +210 -0
  66. package/commands/spartan/pr-ready.md +202 -0
  67. package/commands/spartan/project.md +106 -0
  68. package/commands/spartan/qa.md +222 -0
  69. package/commands/spartan/research.md +254 -0
  70. package/commands/spartan/review.md +132 -0
  71. package/commands/spartan/scan-rules.md +173 -0
  72. package/commands/spartan/sessions.md +143 -0
  73. package/commands/spartan/spec.md +131 -0
  74. package/commands/spartan/startup.md +257 -0
  75. package/commands/spartan/team.md +570 -0
  76. package/commands/spartan/teardown.md +161 -0
  77. package/commands/spartan/testcontainer.md +97 -0
  78. package/commands/spartan/tf-cost.md +123 -0
  79. package/commands/spartan/tf-deploy.md +116 -0
  80. package/commands/spartan/tf-drift.md +100 -0
  81. package/commands/spartan/tf-import.md +107 -0
  82. package/commands/spartan/tf-module.md +121 -0
  83. package/commands/spartan/tf-plan.md +100 -0
  84. package/commands/spartan/tf-review.md +106 -0
  85. package/commands/spartan/tf-scaffold.md +109 -0
  86. package/commands/spartan/tf-security.md +147 -0
  87. package/commands/spartan/think.md +221 -0
  88. package/commands/spartan/unfreeze.md +13 -0
  89. package/commands/spartan/update.md +134 -0
  90. package/commands/spartan/ux.md +1233 -0
  91. package/commands/spartan/validate.md +193 -0
  92. package/commands/spartan/web-to-prd.md +706 -0
  93. package/commands/spartan/workstreams.md +109 -0
  94. package/commands/spartan/write.md +16 -0
  95. package/commands/spartan.md +386 -0
  96. package/frameworks/00-framework-comparison-guide.md +317 -0
  97. package/frameworks/01-lean-canvas.md +196 -0
  98. package/frameworks/02-design-sprint.md +304 -0
  99. package/frameworks/03-foundation-sprint.md +337 -0
  100. package/frameworks/04-business-model-canvas.md +391 -0
  101. package/frameworks/05-customer-development.md +426 -0
  102. package/frameworks/06-jobs-to-be-done.md +358 -0
  103. package/frameworks/07-mom-test.md +392 -0
  104. package/frameworks/08-value-proposition-canvas.md +488 -0
  105. package/frameworks/09-javelin-board.md +428 -0
  106. package/frameworks/10-build-measure-learn.md +467 -0
  107. package/frameworks/11-mvp-approaches.md +533 -0
  108. package/frameworks/think-before-build.md +593 -0
  109. package/lib/assembler.js +197 -0
  110. package/lib/assembler.test.js +159 -0
  111. package/lib/detector.js +166 -0
  112. package/lib/detector.test.js +221 -0
  113. package/lib/packs.js +16 -0
  114. package/lib/resolver.js +272 -0
  115. package/lib/resolver.test.js +298 -0
  116. package/lib/worktree.sh +104 -0
  117. package/package.json +50 -0
  118. package/packs/backend-micronaut.yaml +35 -0
  119. package/packs/backend-nodejs.yaml +15 -0
  120. package/packs/backend-python.yaml +15 -0
  121. package/packs/core.yaml +37 -0
  122. package/packs/database.yaml +21 -0
  123. package/packs/frontend-react.yaml +24 -0
  124. package/packs/infrastructure.yaml +40 -0
  125. package/packs/ops.yaml +16 -0
  126. package/packs/packs.compiled.json +371 -0
  127. package/packs/product.yaml +22 -0
  128. package/packs/project-mgmt.yaml +24 -0
  129. package/packs/research.yaml +39 -0
  130. package/packs/shared-backend.yaml +14 -0
  131. package/packs/ux-design.yaml +21 -0
  132. package/rules/backend-micronaut/API_DESIGN.md +313 -0
  133. package/rules/backend-micronaut/BATCH_PROCESSING.md +92 -0
  134. package/rules/backend-micronaut/CONTROLLERS.md +388 -0
  135. package/rules/backend-micronaut/KOTLIN.md +414 -0
  136. package/rules/backend-micronaut/RETROFIT_PLACEMENT.md +290 -0
  137. package/rules/backend-micronaut/SERVICES_AND_BEANS.md +325 -0
  138. package/rules/core/NAMING_CONVENTIONS.md +208 -0
  139. package/rules/core/SKILL_AUTHORING.md +174 -0
  140. package/rules/core/TIMEZONE.md +316 -0
  141. package/rules/database/ORM_AND_REPO.md +289 -0
  142. package/rules/database/SCHEMA.md +146 -0
  143. package/rules/database/TRANSACTIONS.md +311 -0
  144. package/rules/frontend-react/FRONTEND.md +344 -0
  145. package/rules/infrastructure/MODULES.md +260 -0
  146. package/rules/infrastructure/NAMING.md +196 -0
  147. package/rules/infrastructure/PROVIDERS.md +309 -0
  148. package/rules/infrastructure/SECURITY.md +310 -0
  149. package/rules/infrastructure/STATE_AND_BACKEND.md +237 -0
  150. package/rules/infrastructure/STRUCTURE.md +234 -0
  151. package/rules/infrastructure/VARIABLES.md +285 -0
  152. package/rules/shared-backend/ARCHITECTURE.md +46 -0
  153. package/rules/ux-design/DESIGN_PROCESS.md +176 -0
  154. package/skills/api-endpoint-creator/SKILL.md +455 -0
  155. package/skills/api-endpoint-creator/error-handling-guide.md +244 -0
  156. package/skills/api-endpoint-creator/examples.md +522 -0
  157. package/skills/api-endpoint-creator/testing-patterns.md +302 -0
  158. package/skills/article-writing/SKILL.md +109 -0
  159. package/skills/article-writing/examples.md +59 -0
  160. package/skills/backend-api-design/SKILL.md +84 -0
  161. package/skills/backend-api-design/code-patterns.md +138 -0
  162. package/skills/brainstorm/SKILL.md +95 -0
  163. package/skills/browser-qa/SKILL.md +87 -0
  164. package/skills/browser-qa/playwright-snippets.md +110 -0
  165. package/skills/ci-cd-patterns/SKILL.md +108 -0
  166. package/skills/ci-cd-patterns/workflows.md +149 -0
  167. package/skills/competitive-teardown/SKILL.md +93 -0
  168. package/skills/competitive-teardown/example-analysis.md +50 -0
  169. package/skills/content-engine/SKILL.md +131 -0
  170. package/skills/content-engine/examples.md +72 -0
  171. package/skills/database-patterns/SKILL.md +72 -0
  172. package/skills/database-patterns/code-templates.md +114 -0
  173. package/skills/database-table-creator/SKILL.md +141 -0
  174. package/skills/database-table-creator/examples.md +552 -0
  175. package/skills/database-table-creator/kotlin-templates.md +400 -0
  176. package/skills/database-table-creator/migration-template.sql +68 -0
  177. package/skills/database-table-creator/validation-checklist.md +337 -0
  178. package/skills/deep-research/SKILL.md +80 -0
  179. package/skills/design-intelligence/SKILL.md +268 -0
  180. package/skills/design-workflow/SKILL.md +127 -0
  181. package/skills/design-workflow/checklists.md +45 -0
  182. package/skills/idea-validation/SKILL.md +129 -0
  183. package/skills/idea-validation/example-report.md +50 -0
  184. package/skills/investor-materials/SKILL.md +122 -0
  185. package/skills/investor-materials/example-outline.md +70 -0
  186. package/skills/investor-outreach/SKILL.md +112 -0
  187. package/skills/investor-outreach/examples.md +76 -0
  188. package/skills/kotlin-best-practices/SKILL.md +58 -0
  189. package/skills/kotlin-best-practices/code-patterns.md +132 -0
  190. package/skills/market-research/SKILL.md +99 -0
  191. package/skills/security-checklist/SKILL.md +65 -0
  192. package/skills/security-checklist/audit-reference.md +95 -0
  193. package/skills/service-debugging/SKILL.md +116 -0
  194. package/skills/service-debugging/common-issues.md +65 -0
  195. package/skills/startup-pipeline/SKILL.md +152 -0
  196. package/skills/terraform-best-practices/SKILL.md +244 -0
  197. package/skills/terraform-module-creator/SKILL.md +284 -0
  198. package/skills/terraform-review/SKILL.md +222 -0
  199. package/skills/terraform-security-audit/SKILL.md +280 -0
  200. package/skills/terraform-service-scaffold/SKILL.md +574 -0
  201. package/skills/testing-strategies/SKILL.md +116 -0
  202. package/skills/testing-strategies/examples.md +103 -0
  203. package/skills/testing-strategies/integration-test-setup.md +71 -0
  204. package/skills/ui-ux-pro-max/SKILL.md +238 -0
  205. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  206. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  207. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  208. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  209. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  210. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  211. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  212. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  213. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  214. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  215. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  216. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  217. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  218. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  219. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  220. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  221. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  222. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  223. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  224. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  225. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  226. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  227. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  228. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  229. package/skills/ui-ux-pro-max/python-setup.md +146 -0
  230. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  231. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  232. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
  233. package/skills/web-to-prd/SKILL.md +478 -0
  234. package/templates/build-config.yaml +44 -0
  235. package/templates/commands-config.yaml +55 -0
  236. package/templates/competitor-analysis.md +60 -0
  237. package/templates/content/AGENT_TEMPLATE.md +47 -0
  238. package/templates/content/COMMAND_TEMPLATE.md +27 -0
  239. package/templates/content/RULE_TEMPLATE.md +40 -0
  240. package/templates/content/SKILL_TEMPLATE.md +41 -0
  241. package/templates/design-config.md +105 -0
  242. package/templates/design-doc.md +207 -0
  243. package/templates/epic.md +100 -0
  244. package/templates/feature-spec.md +181 -0
  245. package/templates/idea-canvas.md +47 -0
  246. package/templates/implementation-plan.md +159 -0
  247. package/templates/prd-template.md +86 -0
  248. package/templates/preamble.md +89 -0
  249. package/templates/project-readme.md +35 -0
  250. package/templates/quality-gates.md +230 -0
  251. package/templates/spartan-config.yaml +164 -0
  252. package/templates/user-interview.md +69 -0
  253. package/templates/validation-checklist.md +108 -0
  254. package/templates/workflow-backend-micronaut.md +409 -0
  255. package/templates/workflow-frontend-react.md +233 -0
@@ -0,0 +1,313 @@
1
+ # API Design Rules
2
+
3
+ > Full guide: use `/backend-api-design` or `/testing-strategies` skill
4
+
5
+ ---
6
+
7
+ ## RPC Style — No REST Verbs
8
+
9
+ All mutations use `@Post`. Never use `@Put`, `@Delete`, or `@Patch`.
10
+
11
+ | Action | HTTP Method | Example |
12
+ |--------|-------------|---------|
13
+ | Read one | `@Get` | `@Get("/item")` |
14
+ | Read list | `@Get` | `@Get("/items")` |
15
+ | Create | `@Post` | `@Post` |
16
+ | Update | `@Post("/update")` | `@Post("/update")` |
17
+ | Delete | `@Post("/delete")` | `@Post("/delete")` |
18
+ | Custom action | `@Post("/close")` | `@Post("/close")` |
19
+
20
+ ### Bad — REST Verbs (NEVER use these)
21
+
22
+ ```kotlin
23
+ // ❌ BAD — REST verbs
24
+ @Patch("/{id}")
25
+ suspend fun update(@PathVariable id: UUID, @Body request: UpdateRequest): Response
26
+
27
+ @Delete("/{id}")
28
+ suspend fun delete(@PathVariable id: UUID): Boolean
29
+
30
+ @Put("/{id}")
31
+ suspend fun replace(@PathVariable id: UUID, @Body request: ReplaceRequest): Response
32
+ ```
33
+
34
+ ### Good — RPC-Style
35
+
36
+ ```kotlin
37
+ // ✅ GOOD — RPC-style
38
+ @Post("/update")
39
+ suspend fun update(@QueryValue id: UUID, @Body request: UpdateRequest): Response
40
+
41
+ @Post("/delete")
42
+ suspend fun delete(@QueryValue id: UUID): Boolean
43
+ ```
44
+
45
+ ---
46
+
47
+ ## URL Design
48
+
49
+ ### NEVER Use Path Parameters
50
+
51
+ **Do NOT use path parameters (e.g., `/{id}`, `/{userId}`). Always use query parameters.**
52
+
53
+ Why:
54
+ - Query parameters are more explicit and self-documenting
55
+ - Easier to add optional parameters without breaking API
56
+ - Consistent pattern across all endpoints
57
+ - Simpler routing configuration
58
+ - Better for caching and logging
59
+
60
+ #### Bad - Path Parameters
61
+ ```kotlin
62
+ // DON'T DO THIS
63
+ @Get("/employees/{id}")
64
+ suspend fun getEmployee(@PathVariable id: UUID): EmployeeResponse
65
+
66
+ @Get("/employees/{id}/metrics")
67
+ suspend fun getMetrics(@PathVariable id: UUID): MetricsResponse
68
+
69
+ @Delete("/employees/{id}")
70
+ suspend fun deleteEmployee(@PathVariable id: UUID): Boolean
71
+ ```
72
+
73
+ #### Good - Query Parameters
74
+ ```kotlin
75
+ // DO THIS
76
+ @Get("/employee")
77
+ suspend fun getEmployee(@QueryValue id: UUID): EmployeeResponse
78
+
79
+ @Get("/employee/metrics")
80
+ suspend fun getMetrics(@QueryValue id: UUID): MetricsResponse
81
+
82
+ @Post("/employee/delete")
83
+ suspend fun deleteEmployee(@QueryValue id: UUID): Boolean
84
+ ```
85
+
86
+ ### Endpoint Naming
87
+
88
+ Use singular nouns for single resource, plural for collections:
89
+
90
+ ```kotlin
91
+ // Collection endpoints (plural)
92
+ @Get("/employees") // List employees
93
+ @Get("/organizations") // List organizations
94
+
95
+ // Single resource endpoints (singular)
96
+ @Get("/employee") // Get one employee (with ?id=xxx)
97
+ @Get("/organization") // Get one organization (with ?id=xxx)
98
+ ```
99
+
100
+ Use verb sub-paths for actions:
101
+
102
+ ```kotlin
103
+ // Actions use sub-paths, not HTTP verbs alone
104
+ @Post("/employee/delete") // Delete employee
105
+ @Post("/employee/restore") // Restore employee
106
+ @Post("/sync/employees") // Trigger employee sync
107
+ @Post("/sync/github") // Trigger GitHub sync
108
+ ```
109
+
110
+ ### Controller Organization
111
+
112
+ Group related endpoints under common prefixes:
113
+
114
+ ```kotlin
115
+ @Controller("/api/v1/admin")
116
+ class AdminController {
117
+ // Sync operations
118
+ @Post("/sync/employees")
119
+ @Post("/sync/github")
120
+
121
+ // Employee operations
122
+ @Get("/employees")
123
+ @Get("/employee")
124
+ @Get("/employee/metrics")
125
+ }
126
+ ```
127
+
128
+ ### Request/Response Patterns
129
+
130
+ Required vs optional query parameters:
131
+
132
+ ```kotlin
133
+ // Required parameter - no default, will fail if missing
134
+ @Get("/employee")
135
+ suspend fun getEmployee(
136
+ @QueryValue id: UUID // Required - no ? nullable
137
+ ): EmployeeResponse
138
+
139
+ // Optional parameters - nullable with defaults
140
+ @Get("/employees")
141
+ suspend fun listEmployees(
142
+ @QueryValue search: String?, // Optional
143
+ @QueryValue status: String?, // Optional
144
+ @QueryValue page: Int?, // Optional, default in code
145
+ @QueryValue limit: Int? // Optional, default in code
146
+ ): EmployeeListResponse {
147
+ val effectivePage = page ?: 1
148
+ val effectiveLimit = limit ?: 20
149
+ // ...
150
+ }
151
+ ```
152
+
153
+ Consistent pagination pattern:
154
+
155
+ ```kotlin
156
+ // Request
157
+ @Get("/employees")
158
+ suspend fun listEmployees(
159
+ @QueryValue page: Int?, // 1-based page number
160
+ @QueryValue limit: Int? // Items per page (max 100)
161
+ )
162
+
163
+ // Response
164
+ data class EmployeeListResponse(
165
+ val items: List<EmployeeResponse>,
166
+ val total: Int,
167
+ val page: Int,
168
+ val limit: Int,
169
+ val hasMore: Boolean
170
+ )
171
+ ```
172
+
173
+ ### Quick Reference
174
+
175
+ | Rule | Example |
176
+ |------|---------|
177
+ | No path params | `@Get("/employee")` with `@QueryValue id` |
178
+ | Plural for lists | `@Get("/employees")` |
179
+ | Singular for single | `@Get("/employee")` |
180
+ | Actions as sub-paths | `@Post("/employee/delete")` |
181
+ | Query params for all IDs | `?id=xxx` not `/{id}` |
182
+
183
+ ---
184
+
185
+ ## Model Location
186
+
187
+ ### Rule: All API models live in `module-client` ONLY
188
+
189
+ **NEVER duplicate request or response models across modules.**
190
+
191
+ ```
192
+ module-client/src/main/kotlin/com/yourcompany/client/
193
+ ├── request/ # API request models
194
+ │ ├── conversation/
195
+ │ ├── message/
196
+ │ └── {domain}/
197
+ └── response/ # API response models
198
+ ├── conversation/
199
+ ├── message/
200
+ ├── attachment/
201
+ └── {domain}/
202
+ ```
203
+
204
+ ### NEVER create request/response models in module-api or module-impl
205
+
206
+ ```kotlin
207
+ // WRONG:
208
+ // module-communication/module-api/model/response/ConversationResponse.kt
209
+ package com.yourcompany.communication.model.response
210
+ data class ConversationResponse(...) // DON'T DO THIS
211
+
212
+ // CORRECT:
213
+ // module-client/response/conversation/ConversationResponse.kt
214
+ package com.yourcompany.client.response.conversation
215
+ data class ConversationResponse(...) // PUT IT HERE
216
+ ```
217
+
218
+ ### Import from module-client
219
+
220
+ ```kotlin
221
+ // In ConversationManager.kt or any other file
222
+ import com.yourcompany.client.response.conversation.ConversationResponse
223
+ import com.yourcompany.client.request.conversation.CreateConversationRequest
224
+ ```
225
+
226
+ ### Add module-client dependency
227
+
228
+ ```gradle
229
+ dependencies {
230
+ implementation(project(":module-client"))
231
+ }
232
+ ```
233
+
234
+ ### Naming
235
+
236
+ | Type | Pattern | Example |
237
+ |------|---------|---------|
238
+ | Response | `{Entity}Response` | `ConversationResponse` |
239
+ | List response | `{Entity}ListResponse` | `ConversationListResponse` |
240
+ | Item in list | `{Entity}Item` | `ConversationItem` |
241
+ | Brief/summary | `{Entity}Brief` | `ContactBrief` |
242
+ | Request | `{Action}{Entity}Request` | `CreateConversationRequest` |
243
+
244
+ ### Request Validation Annotations
245
+
246
+ All required fields in request DTOs MUST have validation annotations:
247
+
248
+ ```kotlin
249
+ import jakarta.validation.constraints.NotBlank
250
+ import jakarta.validation.constraints.NotNull
251
+
252
+ data class CreateItemRequest(
253
+ @field:NotBlank(message = "name is required")
254
+ val name: String, // String → @field:NotBlank
255
+
256
+ @field:NotNull(message = "amount is required")
257
+ val amount: BigDecimal, // Non-String → @field:NotNull
258
+
259
+ val note: String? = null // Optional → no annotation
260
+ )
261
+ ```
262
+
263
+ **Message format:** snake_case field name + " is required" (e.g., `"participant_id is required"`).
264
+
265
+ Response DTOs do NOT need validation annotations.
266
+
267
+ Why this matters:
268
+ - Single source of truth
269
+ - No sync issues between duplicates
270
+ - Clear ownership
271
+ - Easier refactoring
272
+
273
+ ---
274
+
275
+ ## Specs Must Include Frontend
276
+
277
+ ### Rule: Every spec that touches the UI MUST have a "Frontend Changes" section
278
+
279
+ When writing a spec (`/spec`), if the feature touches anything the user sees, you MUST include:
280
+
281
+ ### What to put in the Frontend Changes section
282
+
283
+ 1. **Files to change** - List every frontend file that needs edits (components, types, API clients, pages)
284
+ 2. **TypeScript type changes** - Show the before/after for any type changes (interfaces, enums)
285
+ 3. **Component changes** - Describe what each component gains or loses:
286
+ - New UI elements (inputs, buttons, badges, columns)
287
+ - Where they go in the layout (which card, which section, before/after what)
288
+ - State management (new state? uses existing parent state?)
289
+ 4. **API client changes** - New methods on the API client, with function signature
290
+ 5. **UI behavior** - How the user interacts with the new stuff:
291
+ - What triggers actions (click, enter key, toggle)
292
+ - Validation (what's rejected, what error shows)
293
+ - Save flow (which button, which API call)
294
+ - Default values for new fields
295
+
296
+ ### When does this apply?
297
+
298
+ - New API endpoint that returns data shown in UI
299
+ - Changes to existing API response shape (new fields)
300
+ - New config/settings the admin can change
301
+ - Any feature the user mentioned UI/UX for
302
+
303
+ ### When does this NOT apply?
304
+
305
+ - Pure backend changes (scheduler fixes, sync logic, internal refactors)
306
+ - Features with no UI component at all
307
+
308
+ ### Why this rule exists
309
+
310
+ Frontend gets forgotten in specs. Then during implementation, the FE work is vague and inconsistent. Specifying FE changes upfront means:
311
+ - The plan phase knows exactly which FE files to touch
312
+ - The implementation team doesn't have to guess UI layout
313
+ - Type changes are designed alongside API changes (no mismatches)
@@ -0,0 +1,92 @@
1
+ # Batch Processing Patterns
2
+
3
+ ## Core Rule
4
+
5
+ Any operation that processes a dataset that could grow beyond memory MUST use chunked pagination with safety guards.
6
+
7
+ ---
8
+
9
+ ## The Pattern
10
+
11
+ ```kotlin
12
+ companion object {
13
+ const val CHUNK_SIZE = 500
14
+ const val MAX_CHUNKS = 100 // Prevents infinite loops / OOM
15
+ }
16
+
17
+ suspend fun processAllUsers(action: suspend (User) -> Unit): BatchResult {
18
+ var offset = 0
19
+ var chunksProcessed = 0
20
+ val failures = mutableListOf<BatchFailure>()
21
+
22
+ while (chunksProcessed < MAX_CHUNKS) {
23
+ val chunk = userRepository.findAll(limit = CHUNK_SIZE, offset = offset)
24
+ if (chunk.isEmpty()) break
25
+
26
+ chunk.forEach { user ->
27
+ runCatching { action(user) }
28
+ .onFailure { e ->
29
+ logger.warn("Failed to process user ${user.id}", e)
30
+ failures.add(BatchFailure(userId = user.id, error = e.message))
31
+ }
32
+ }
33
+
34
+ if (chunk.size < CHUNK_SIZE) break // Last page
35
+ offset += CHUNK_SIZE
36
+ chunksProcessed++
37
+ }
38
+
39
+ return BatchResult(processed = offset, failures = failures)
40
+ }
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Rules
46
+
47
+ - Always define `CHUNK_SIZE` and `MAX_CHUNKS` as named constants (see KOTLIN.md § No Magic Numbers)
48
+ - `MAX_CHUNKS` guard prevents runaway loops if the dataset keeps growing
49
+ - Early exit when `chunk.size < CHUNK_SIZE` (last page)
50
+ - Never `findAll()` without limit — always paginate
51
+ - Log + collect failures per item, don't abort the whole batch for one bad record
52
+ - Return a result with failure count so the caller can decide
53
+ - Small fixed-size lists (< 100 items) don't need chunking
54
+
55
+ ---
56
+
57
+ ## Cancellation Check
58
+
59
+ For long-running jobs, check cancellation inside the loop:
60
+
61
+ ```kotlin
62
+ while (chunksProcessed < MAX_CHUNKS) {
63
+ if (context.isCancelled(selfId, initiatorId)) {
64
+ logger.info("Batch cancelled after $chunksProcessed chunks")
65
+ break
66
+ }
67
+ // ... process chunk
68
+ }
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Bad Patterns
74
+
75
+ ```kotlin
76
+ // WRONG — loads entire table into memory
77
+ val allUsers = userRepository.findAll() // 2M users → OOM
78
+ allUsers.forEach { sendEmail(it) }
79
+
80
+ // WRONG — no safety limit
81
+ var offset = 0
82
+ while (true) { // Never terminates if new records keep appearing
83
+ val chunk = repo.findAll(limit = 500, offset = offset)
84
+ if (chunk.isEmpty()) break
85
+ offset += 500
86
+ }
87
+
88
+ // WRONG — one bad record kills the whole batch
89
+ chunk.forEach { user ->
90
+ action(user) // Throws on user #47 → users #48-500 never processed
91
+ }
92
+ ```