dsh-ecc-skills 0.4.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 (278) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +99 -0
  3. package/cordis.patch.yml +5 -0
  4. package/lib/index.js +195 -0
  5. package/package.json +46 -0
  6. package/skills/accessibility/SKILL.md +147 -0
  7. package/skills/agent-architecture-audit/SKILL.md +257 -0
  8. package/skills/agent-eval/SKILL.md +147 -0
  9. package/skills/agent-harness-construction/SKILL.md +74 -0
  10. package/skills/agent-introspection-debugging/SKILL.md +154 -0
  11. package/skills/agent-payment-x402/SKILL.md +225 -0
  12. package/skills/agent-self-evaluation/SKILL.md +182 -0
  13. package/skills/agent-sort/SKILL.md +216 -0
  14. package/skills/agentic-engineering/SKILL.md +64 -0
  15. package/skills/agentic-os/SKILL.md +388 -0
  16. package/skills/ai-first-engineering/SKILL.md +52 -0
  17. package/skills/ai-regression-testing/SKILL.md +386 -0
  18. package/skills/android-clean-architecture/SKILL.md +340 -0
  19. package/skills/angular-developer/SKILL.md +155 -0
  20. package/skills/api-connector-builder/SKILL.md +121 -0
  21. package/skills/api-design/SKILL.md +524 -0
  22. package/skills/architecture-decision-records/SKILL.md +180 -0
  23. package/skills/article-writing/SKILL.md +80 -0
  24. package/skills/automation-audit-ops/SKILL.md +143 -0
  25. package/skills/autonomous-agent-harness/SKILL.md +274 -0
  26. package/skills/autonomous-loops/SKILL.md +611 -0
  27. package/skills/backend-patterns/SKILL.md +562 -0
  28. package/skills/benchmark/SKILL.md +95 -0
  29. package/skills/benchmark-methodology/SKILL.md +191 -0
  30. package/skills/benchmark-optimization-loop/SKILL.md +71 -0
  31. package/skills/blender-motion-state-inspection/SKILL.md +165 -0
  32. package/skills/blueprint/SKILL.md +106 -0
  33. package/skills/brand-discovery/SKILL.md +145 -0
  34. package/skills/brand-voice/SKILL.md +98 -0
  35. package/skills/browser-qa/SKILL.md +105 -0
  36. package/skills/bun-runtime/SKILL.md +85 -0
  37. package/skills/canary-watch/SKILL.md +108 -0
  38. package/skills/carrier-relationship-management/SKILL.md +212 -0
  39. package/skills/cisco-ios-patterns/SKILL.md +164 -0
  40. package/skills/ck/SKILL.md +148 -0
  41. package/skills/claude-devfleet/SKILL.md +112 -0
  42. package/skills/click-path-audit/SKILL.md +245 -0
  43. package/skills/clickhouse-io/SKILL.md +445 -0
  44. package/skills/code-tour/SKILL.md +254 -0
  45. package/skills/codebase-onboarding/SKILL.md +234 -0
  46. package/skills/codehealth-mcp/SKILL.md +167 -0
  47. package/skills/coding-standards/SKILL.md +551 -0
  48. package/skills/competitive-platform-analysis/SKILL.md +214 -0
  49. package/skills/competitive-report-structure/SKILL.md +162 -0
  50. package/skills/compose-multiplatform-patterns/SKILL.md +300 -0
  51. package/skills/config-gc/SKILL.md +120 -0
  52. package/skills/configure-ecc/SKILL.md +206 -0
  53. package/skills/connections-optimizer/SKILL.md +190 -0
  54. package/skills/content-engine/SKILL.md +132 -0
  55. package/skills/content-hash-cache-pattern/SKILL.md +162 -0
  56. package/skills/context-budget/SKILL.md +136 -0
  57. package/skills/continuous-agent-loop/SKILL.md +46 -0
  58. package/skills/contract-first/SKILL.md +287 -0
  59. package/skills/cost-aware-llm-pipeline/SKILL.md +184 -0
  60. package/skills/cost-tracking/SKILL.md +97 -0
  61. package/skills/council/SKILL.md +204 -0
  62. package/skills/council-multi-model/SKILL.md +167 -0
  63. package/skills/cpp-coding-standards/SKILL.md +724 -0
  64. package/skills/cpp-testing/SKILL.md +325 -0
  65. package/skills/crosspost/SKILL.md +112 -0
  66. package/skills/csharp-testing/SKILL.md +322 -0
  67. package/skills/customer-billing-ops/SKILL.md +141 -0
  68. package/skills/customs-trade-compliance/SKILL.md +263 -0
  69. package/skills/dart-flutter-patterns/SKILL.md +564 -0
  70. package/skills/dashboard-builder/SKILL.md +109 -0
  71. package/skills/data-scraper-agent/SKILL.md +765 -0
  72. package/skills/data-throughput-accelerator/SKILL.md +74 -0
  73. package/skills/database-migrations/SKILL.md +430 -0
  74. package/skills/deep-research/SKILL.md +160 -0
  75. package/skills/defi-amm-security/SKILL.md +167 -0
  76. package/skills/delivery-gate/SKILL.md +126 -0
  77. package/skills/deployment-patterns/SKILL.md +428 -0
  78. package/skills/design-system/SKILL.md +83 -0
  79. package/skills/dev-team/SKILL.md +203 -0
  80. package/skills/django-celery/SKILL.md +458 -0
  81. package/skills/django-patterns/SKILL.md +735 -0
  82. package/skills/django-security/SKILL.md +644 -0
  83. package/skills/django-tdd/SKILL.md +730 -0
  84. package/skills/django-verification/SKILL.md +470 -0
  85. package/skills/dmux-workflows/SKILL.md +192 -0
  86. package/skills/docker-patterns/SKILL.md +520 -0
  87. package/skills/documentation-lookup/SKILL.md +91 -0
  88. package/skills/dotnet-patterns/SKILL.md +322 -0
  89. package/skills/dynamic-workflow-mode/SKILL.md +124 -0
  90. package/skills/e2e-testing/SKILL.md +327 -0
  91. package/skills/ecc-tools-cost-audit/SKILL.md +161 -0
  92. package/skills/email-ops/SKILL.md +122 -0
  93. package/skills/energy-procurement/SKILL.md +228 -0
  94. package/skills/enterprise-agent-ops/SKILL.md +51 -0
  95. package/skills/error-handling/SKILL.md +377 -0
  96. package/skills/eval-harness/SKILL.md +271 -0
  97. package/skills/evm-token-decimals/SKILL.md +131 -0
  98. package/skills/exa-search/SKILL.md +108 -0
  99. package/skills/fal-ai-media/SKILL.md +289 -0
  100. package/skills/fastapi-patterns/SKILL.md +514 -0
  101. package/skills/finance-billing-ops/SKILL.md +128 -0
  102. package/skills/flox-environments/SKILL.md +497 -0
  103. package/skills/flutter-dart-code-review/SKILL.md +436 -0
  104. package/skills/foundation-models-on-device/SKILL.md +243 -0
  105. package/skills/frontend-a11y/SKILL.md +446 -0
  106. package/skills/frontend-design-direction/SKILL.md +93 -0
  107. package/skills/frontend-patterns/SKILL.md +657 -0
  108. package/skills/fsharp-testing/SKILL.md +281 -0
  109. package/skills/gan-style-harness/SKILL.md +279 -0
  110. package/skills/generating-python-installer/SKILL.md +820 -0
  111. package/skills/git-workflow/SKILL.md +716 -0
  112. package/skills/github-ops/SKILL.md +145 -0
  113. package/skills/golang-patterns/SKILL.md +676 -0
  114. package/skills/golang-testing/SKILL.md +721 -0
  115. package/skills/google-workspace-ops/SKILL.md +96 -0
  116. package/skills/growth-log/SKILL.md +128 -0
  117. package/skills/healthcare-cdss-patterns/SKILL.md +246 -0
  118. package/skills/healthcare-emr-patterns/SKILL.md +160 -0
  119. package/skills/healthcare-eval-harness/SKILL.md +208 -0
  120. package/skills/healthcare-phi-compliance/SKILL.md +146 -0
  121. package/skills/hermes-imports/SKILL.md +89 -0
  122. package/skills/hexagonal-architecture/SKILL.md +277 -0
  123. package/skills/hipaa-compliance/SKILL.md +79 -0
  124. package/skills/homelab-network-readiness/SKILL.md +170 -0
  125. package/skills/homelab-network-setup/SKILL.md +130 -0
  126. package/skills/homelab-pihole-dns/SKILL.md +275 -0
  127. package/skills/homelab-vlan-segmentation/SKILL.md +312 -0
  128. package/skills/homelab-wireguard-vpn/SKILL.md +306 -0
  129. package/skills/hookify-rules/SKILL.md +128 -0
  130. package/skills/inherit-legacy-style/SKILL.md +157 -0
  131. package/skills/intent-driven-development/SKILL.md +360 -0
  132. package/skills/inventory-demand-planning/SKILL.md +247 -0
  133. package/skills/investor-materials/SKILL.md +97 -0
  134. package/skills/investor-outreach/SKILL.md +92 -0
  135. package/skills/ios-icon-gen/SKILL.md +158 -0
  136. package/skills/iterative-retrieval/SKILL.md +212 -0
  137. package/skills/ito-baskets/SKILL.md +263 -0
  138. package/skills/ito-compute/SKILL.md +151 -0
  139. package/skills/ito-inference/SKILL.md +119 -0
  140. package/skills/ito-training/SKILL.md +123 -0
  141. package/skills/java-coding-standards/SKILL.md +384 -0
  142. package/skills/jira-integration/SKILL.md +303 -0
  143. package/skills/jpa-patterns/SKILL.md +152 -0
  144. package/skills/knowledge-ops/SKILL.md +155 -0
  145. package/skills/kotlin-coroutines-flows/SKILL.md +285 -0
  146. package/skills/kotlin-exposed-patterns/SKILL.md +720 -0
  147. package/skills/kotlin-ktor-patterns/SKILL.md +690 -0
  148. package/skills/kotlin-patterns/SKILL.md +712 -0
  149. package/skills/kotlin-testing/SKILL.md +825 -0
  150. package/skills/kubernetes-patterns/SKILL.md +756 -0
  151. package/skills/laravel-patterns/SKILL.md +416 -0
  152. package/skills/laravel-plugin-discovery/SKILL.md +230 -0
  153. package/skills/laravel-security/SKILL.md +948 -0
  154. package/skills/laravel-tdd/SKILL.md +675 -0
  155. package/skills/laravel-verification/SKILL.md +180 -0
  156. package/skills/latency-critical-systems/SKILL.md +75 -0
  157. package/skills/lead-intelligence/SKILL.md +322 -0
  158. package/skills/liquid-glass-design/SKILL.md +279 -0
  159. package/skills/living-docs-governance/SKILL.md +137 -0
  160. package/skills/llm-trading-agent-security/SKILL.md +147 -0
  161. package/skills/logistics-exception-management/SKILL.md +222 -0
  162. package/skills/loop-design-check/SKILL.md +143 -0
  163. package/skills/mailtrap-email-integration/SKILL.md +77 -0
  164. package/skills/make-interfaces-feel-better/SKILL.md +152 -0
  165. package/skills/manim-video/SKILL.md +90 -0
  166. package/skills/market-research/SKILL.md +76 -0
  167. package/skills/marketing-campaign/SKILL.md +114 -0
  168. package/skills/mcp-server-patterns/SKILL.md +70 -0
  169. package/skills/messages-ops/SKILL.md +105 -0
  170. package/skills/ml-adoption-playbook/SKILL.md +57 -0
  171. package/skills/mle-workflow/SKILL.md +348 -0
  172. package/skills/motion-advanced/SKILL.md +597 -0
  173. package/skills/motion-foundations/SKILL.md +300 -0
  174. package/skills/motion-patterns/SKILL.md +435 -0
  175. package/skills/motion-ui/SKILL.md +576 -0
  176. package/skills/mysql-patterns/SKILL.md +413 -0
  177. package/skills/nanoclaw-repl/SKILL.md +34 -0
  178. package/skills/nasiko-control-plane/SKILL.md +49 -0
  179. package/skills/nestjs-patterns/SKILL.md +231 -0
  180. package/skills/netmiko-ssh-automation/SKILL.md +174 -0
  181. package/skills/network-bgp-diagnostics/SKILL.md +168 -0
  182. package/skills/network-config-validation/SKILL.md +211 -0
  183. package/skills/network-interface-health/SKILL.md +153 -0
  184. package/skills/nextjs-turbopack/SKILL.md +58 -0
  185. package/skills/nodejs-keccak256/SKILL.md +103 -0
  186. package/skills/nutrient-document-processing/SKILL.md +168 -0
  187. package/skills/nuxt4-patterns/SKILL.md +101 -0
  188. package/skills/opensource-pipeline/SKILL.md +256 -0
  189. package/skills/orch-add-feature/SKILL.md +45 -0
  190. package/skills/orch-build-mvp/SKILL.md +49 -0
  191. package/skills/orch-change-feature/SKILL.md +43 -0
  192. package/skills/orch-fix-defect/SKILL.md +43 -0
  193. package/skills/orch-pipeline/SKILL.md +121 -0
  194. package/skills/orch-refine-code/SKILL.md +44 -0
  195. package/skills/parallel-execution-optimizer/SKILL.md +74 -0
  196. package/skills/perl-patterns/SKILL.md +505 -0
  197. package/skills/perl-security/SKILL.md +504 -0
  198. package/skills/perl-testing/SKILL.md +476 -0
  199. package/skills/plan-canvas/SKILL.md +196 -0
  200. package/skills/plankton-code-quality/SKILL.md +237 -0
  201. package/skills/postgres-patterns/SKILL.md +148 -0
  202. package/skills/prediction-market-oracle-research/SKILL.md +64 -0
  203. package/skills/prediction-market-risk-review/SKILL.md +61 -0
  204. package/skills/prisma-patterns/SKILL.md +401 -0
  205. package/skills/product-capability/SKILL.md +142 -0
  206. package/skills/product-lens/SKILL.md +93 -0
  207. package/skills/production-audit/SKILL.md +207 -0
  208. package/skills/production-scheduling/SKILL.md +238 -0
  209. package/skills/project-flow-ops/SKILL.md +112 -0
  210. package/skills/prompt-optimizer/SKILL.md +398 -0
  211. package/skills/python-patterns/SKILL.md +751 -0
  212. package/skills/python-testing/SKILL.md +817 -0
  213. package/skills/pytorch-patterns/SKILL.md +397 -0
  214. package/skills/quality-nonconformance/SKILL.md +260 -0
  215. package/skills/quarkus-patterns/SKILL.md +723 -0
  216. package/skills/quarkus-security/SKILL.md +468 -0
  217. package/skills/quarkus-tdd/SKILL.md +812 -0
  218. package/skills/quarkus-verification/SKILL.md +481 -0
  219. package/skills/ralphinho-rfc-pipeline/SKILL.md +68 -0
  220. package/skills/react-native-patterns/SKILL.md +326 -0
  221. package/skills/react-patterns/SKILL.md +342 -0
  222. package/skills/react-performance/SKILL.md +575 -0
  223. package/skills/react-testing/SKILL.md +424 -0
  224. package/skills/recsys-pipeline-architect/SKILL.md +115 -0
  225. package/skills/recursive-decision-ledger/SKILL.md +81 -0
  226. package/skills/redis-patterns/SKILL.md +404 -0
  227. package/skills/regex-vs-llm-structured-text/SKILL.md +221 -0
  228. package/skills/remotion-video-creation/SKILL.md +43 -0
  229. package/skills/repo-scan/SKILL.md +170 -0
  230. package/skills/research-ops/SKILL.md +113 -0
  231. package/skills/returns-reverse-logistics/SKILL.md +240 -0
  232. package/skills/rules-distill/SKILL.md +265 -0
  233. package/skills/rust-patterns/SKILL.md +500 -0
  234. package/skills/rust-testing/SKILL.md +501 -0
  235. package/skills/safety-guard/SKILL.md +76 -0
  236. package/skills/santa-method/SKILL.md +307 -0
  237. package/skills/scientific-db-pubmed-database/SKILL.md +176 -0
  238. package/skills/scientific-db-uspto-database/SKILL.md +178 -0
  239. package/skills/scientific-pkg-gget/SKILL.md +167 -0
  240. package/skills/scientific-thinking-literature-review/SKILL.md +193 -0
  241. package/skills/scientific-thinking-scholar-evaluation/SKILL.md +161 -0
  242. package/skills/search-first/SKILL.md +183 -0
  243. package/skills/security-bounty-hunter/SKILL.md +100 -0
  244. package/skills/security-scan/SKILL.md +166 -0
  245. package/skills/seo/SKILL.md +155 -0
  246. package/skills/skill-scout/SKILL.md +141 -0
  247. package/skills/skill-stocktake/SKILL.md +195 -0
  248. package/skills/social-graph-ranker/SKILL.md +155 -0
  249. package/skills/social-publisher/SKILL.md +130 -0
  250. package/skills/springboot-patterns/SKILL.md +315 -0
  251. package/skills/springboot-security/SKILL.md +273 -0
  252. package/skills/springboot-tdd/SKILL.md +159 -0
  253. package/skills/springboot-verification/SKILL.md +232 -0
  254. package/skills/swift-actor-persistence/SKILL.md +144 -0
  255. package/skills/swift-concurrency-6-2/SKILL.md +216 -0
  256. package/skills/swift-protocol-di-testing/SKILL.md +191 -0
  257. package/skills/swiftui-patterns/SKILL.md +259 -0
  258. package/skills/taste/SKILL.md +264 -0
  259. package/skills/tdd-workflow/SKILL.md +583 -0
  260. package/skills/team-agent-orchestration/SKILL.md +111 -0
  261. package/skills/team-builder/SKILL.md +169 -0
  262. package/skills/terminal-opener/SKILL.md +55 -0
  263. package/skills/terminal-ops/SKILL.md +110 -0
  264. package/skills/tinystruct-patterns/SKILL.md +279 -0
  265. package/skills/token-budget-advisor/SKILL.md +134 -0
  266. package/skills/ui-demo/SKILL.md +466 -0
  267. package/skills/ui-to-vue/SKILL.md +135 -0
  268. package/skills/uncloud/SKILL.md +344 -0
  269. package/skills/unified-memory/SKILL.md +170 -0
  270. package/skills/unified-notifications-ops/SKILL.md +188 -0
  271. package/skills/verification-loop/SKILL.md +129 -0
  272. package/skills/video-editing/SKILL.md +311 -0
  273. package/skills/videodb/SKILL.md +375 -0
  274. package/skills/vite-patterns/SKILL.md +450 -0
  275. package/skills/vue-patterns/SKILL.md +471 -0
  276. package/skills/windows-desktop-e2e/SKILL.md +888 -0
  277. package/skills/workspace-surface-audit/SKILL.md +126 -0
  278. package/skills/x-api/SKILL.md +235 -0
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: springboot-tdd
3
+ description: Test-driven development for Spring Boot using JUnit 5, Mockito, MockMvc, Testcontainers, and JaCoCo. Use when adding features, fixing bugs, or refactoring.
4
+ metadata:
5
+ origin: ECC
6
+ ---
7
+
8
+ # Spring Boot TDD Workflow
9
+
10
+ TDD guidance for Spring Boot services with 80%+ coverage (unit + integration).
11
+
12
+ ## When to Use
13
+
14
+ - New features or endpoints
15
+ - Bug fixes or refactors
16
+ - Adding data access logic or security rules
17
+
18
+ ## Workflow
19
+
20
+ 1) Write tests first (they should fail)
21
+ 2) Implement minimal code to pass
22
+ 3) Refactor with tests green
23
+ 4) Enforce coverage (JaCoCo)
24
+
25
+ ## Unit Tests (JUnit 5 + Mockito)
26
+
27
+ ```java
28
+ @ExtendWith(MockitoExtension.class)
29
+ class MarketServiceTest {
30
+ @Mock MarketRepository repo;
31
+ @InjectMocks MarketService service;
32
+
33
+ @Test
34
+ void createsMarket() {
35
+ CreateMarketRequest req = new CreateMarketRequest("name", "desc", Instant.now(), List.of("cat"));
36
+ when(repo.save(any())).thenAnswer(inv -> inv.getArgument(0));
37
+
38
+ Market result = service.create(req);
39
+
40
+ assertThat(result.name()).isEqualTo("name");
41
+ verify(repo).save(any());
42
+ }
43
+ }
44
+ ```
45
+
46
+ Patterns:
47
+ - Arrange-Act-Assert
48
+ - Avoid partial mocks; prefer explicit stubbing
49
+ - Use `@ParameterizedTest` for variants
50
+
51
+ ## Web Layer Tests (MockMvc)
52
+
53
+ ```java
54
+ @WebMvcTest(MarketController.class)
55
+ class MarketControllerTest {
56
+ @Autowired MockMvc mockMvc;
57
+ @MockBean MarketService marketService;
58
+
59
+ @Test
60
+ void returnsMarkets() throws Exception {
61
+ when(marketService.list(any())).thenReturn(Page.empty());
62
+
63
+ mockMvc.perform(get("/api/markets"))
64
+ .andExpect(status().isOk())
65
+ .andExpect(jsonPath("$.content").isArray());
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## Integration Tests (SpringBootTest)
71
+
72
+ ```java
73
+ @SpringBootTest
74
+ @AutoConfigureMockMvc
75
+ @ActiveProfiles("test")
76
+ class MarketIntegrationTest {
77
+ @Autowired MockMvc mockMvc;
78
+
79
+ @Test
80
+ void createsMarket() throws Exception {
81
+ mockMvc.perform(post("/api/markets")
82
+ .contentType(MediaType.APPLICATION_JSON)
83
+ .content("""
84
+ {"name":"Test","description":"Desc","endDate":"2030-01-01T00:00:00Z","categories":["general"]}
85
+ """))
86
+ .andExpect(status().isCreated());
87
+ }
88
+ }
89
+ ```
90
+
91
+ ## Persistence Tests (DataJpaTest)
92
+
93
+ ```java
94
+ @DataJpaTest
95
+ @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
96
+ @Import(TestContainersConfig.class)
97
+ class MarketRepositoryTest {
98
+ @Autowired MarketRepository repo;
99
+
100
+ @Test
101
+ void savesAndFinds() {
102
+ MarketEntity entity = new MarketEntity();
103
+ entity.setName("Test");
104
+ repo.save(entity);
105
+
106
+ Optional<MarketEntity> found = repo.findByName("Test");
107
+ assertThat(found).isPresent();
108
+ }
109
+ }
110
+ ```
111
+
112
+ ## Testcontainers
113
+
114
+ - Use reusable containers for Postgres/Redis to mirror production
115
+ - Wire via `@DynamicPropertySource` to inject JDBC URLs into Spring context
116
+
117
+ ## Coverage (JaCoCo)
118
+
119
+ Maven snippet:
120
+ ```xml
121
+ <plugin>
122
+ <groupId>org.jacoco</groupId>
123
+ <artifactId>jacoco-maven-plugin</artifactId>
124
+ <version>0.8.14</version>
125
+ <executions>
126
+ <execution>
127
+ <goals><goal>prepare-agent</goal></goals>
128
+ </execution>
129
+ <execution>
130
+ <id>report</id>
131
+ <phase>verify</phase>
132
+ <goals><goal>report</goal></goals>
133
+ </execution>
134
+ </executions>
135
+ </plugin>
136
+ ```
137
+
138
+ ## Assertions
139
+
140
+ - Prefer AssertJ (`assertThat`) for readability
141
+ - For JSON responses, use `jsonPath`
142
+ - For exceptions: `assertThatThrownBy(...)`
143
+
144
+ ## Test Data Builders
145
+
146
+ ```java
147
+ class MarketBuilder {
148
+ private String name = "Test";
149
+ MarketBuilder withName(String name) { this.name = name; return this; }
150
+ Market build() { return new Market(null, name, MarketStatus.ACTIVE); }
151
+ }
152
+ ```
153
+
154
+ ## CI Commands
155
+
156
+ - Maven: `mvn -T 4 test` or `mvn verify`
157
+ - Gradle: `./gradlew test jacocoTestReport`
158
+
159
+ **Remember**: Keep tests fast, isolated, and deterministic. Test behavior, not implementation details.
@@ -0,0 +1,232 @@
1
+ ---
2
+ name: springboot-verification
3
+ description: "Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR."
4
+ metadata:
5
+ origin: ECC
6
+ ---
7
+
8
+ # Spring Boot Verification Loop
9
+
10
+ Run before PRs, after major changes, and pre-deploy.
11
+
12
+ ## When to Activate
13
+
14
+ - Before opening a pull request for a Spring Boot service
15
+ - After major refactoring or dependency upgrades
16
+ - Pre-deployment verification for staging or production
17
+ - Running full build → lint → test → security scan pipeline
18
+ - Validating test coverage meets thresholds
19
+
20
+ ## Phase 1: Build
21
+
22
+ ```bash
23
+ mvn -T 4 clean verify -DskipTests
24
+ # or
25
+ ./gradlew clean assemble -x test
26
+ ```
27
+
28
+ If build fails, stop and fix.
29
+
30
+ ## Phase 2: Static Analysis
31
+
32
+ Maven (common plugins):
33
+ ```bash
34
+ mvn -T 4 spotbugs:check pmd:check checkstyle:check
35
+ ```
36
+
37
+ Gradle (if configured):
38
+ ```bash
39
+ ./gradlew checkstyleMain pmdMain spotbugsMain
40
+ ```
41
+
42
+ ## Phase 3: Tests + Coverage
43
+
44
+ ```bash
45
+ mvn -T 4 test
46
+ mvn jacoco:report # verify 80%+ coverage
47
+ # or
48
+ ./gradlew test jacocoTestReport
49
+ ```
50
+
51
+ Report:
52
+ - Total tests, passed/failed
53
+ - Coverage % (lines/branches)
54
+
55
+ ### Unit Tests
56
+
57
+ Test service logic in isolation with mocked dependencies:
58
+
59
+ ```java
60
+ @ExtendWith(MockitoExtension.class)
61
+ class UserServiceTest {
62
+
63
+ @Mock private UserRepository userRepository;
64
+ @InjectMocks private UserService userService;
65
+
66
+ @Test
67
+ void createUser_validInput_returnsUser() {
68
+ var dto = new CreateUserDto("Alice", "alice@example.com");
69
+ var expected = new User(1L, "Alice", "alice@example.com");
70
+ when(userRepository.save(any(User.class))).thenReturn(expected);
71
+
72
+ var result = userService.create(dto);
73
+
74
+ assertThat(result.name()).isEqualTo("Alice");
75
+ verify(userRepository).save(any(User.class));
76
+ }
77
+
78
+ @Test
79
+ void createUser_duplicateEmail_throwsException() {
80
+ var dto = new CreateUserDto("Alice", "existing@example.com");
81
+ when(userRepository.existsByEmail(dto.email())).thenReturn(true);
82
+
83
+ assertThatThrownBy(() -> userService.create(dto))
84
+ .isInstanceOf(DuplicateEmailException.class);
85
+ }
86
+ }
87
+ ```
88
+
89
+ ### Integration Tests with Testcontainers
90
+
91
+ Test against a real database instead of H2:
92
+
93
+ ```java
94
+ @SpringBootTest
95
+ @Testcontainers
96
+ class UserRepositoryIntegrationTest {
97
+
98
+ @Container
99
+ static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
100
+ .withDatabaseName("testdb");
101
+
102
+ @DynamicPropertySource
103
+ static void configureProperties(DynamicPropertyRegistry registry) {
104
+ registry.add("spring.datasource.url", postgres::getJdbcUrl);
105
+ registry.add("spring.datasource.username", postgres::getUsername);
106
+ registry.add("spring.datasource.password", postgres::getPassword);
107
+ }
108
+
109
+ @Autowired private UserRepository userRepository;
110
+
111
+ @Test
112
+ void findByEmail_existingUser_returnsUser() {
113
+ userRepository.save(new User("Alice", "alice@example.com"));
114
+
115
+ var found = userRepository.findByEmail("alice@example.com");
116
+
117
+ assertThat(found).isPresent();
118
+ assertThat(found.get().getName()).isEqualTo("Alice");
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### API Tests with MockMvc
124
+
125
+ Test controller layer with full Spring context:
126
+
127
+ ```java
128
+ @WebMvcTest(UserController.class)
129
+ class UserControllerTest {
130
+
131
+ @Autowired private MockMvc mockMvc;
132
+ @MockBean private UserService userService;
133
+
134
+ @Test
135
+ void createUser_validInput_returns201() throws Exception {
136
+ var user = new UserDto(1L, "Alice", "alice@example.com");
137
+ when(userService.create(any())).thenReturn(user);
138
+
139
+ mockMvc.perform(post("/api/users")
140
+ .contentType(MediaType.APPLICATION_JSON)
141
+ .content("""
142
+ {"name": "Alice", "email": "alice@example.com"}
143
+ """))
144
+ .andExpect(status().isCreated())
145
+ .andExpect(jsonPath("$.name").value("Alice"));
146
+ }
147
+
148
+ @Test
149
+ void createUser_invalidEmail_returns400() throws Exception {
150
+ mockMvc.perform(post("/api/users")
151
+ .contentType(MediaType.APPLICATION_JSON)
152
+ .content("""
153
+ {"name": "Alice", "email": "not-an-email"}
154
+ """))
155
+ .andExpect(status().isBadRequest());
156
+ }
157
+ }
158
+ ```
159
+
160
+ ## Phase 4: Security Scan
161
+
162
+ ```bash
163
+ # Dependency CVEs
164
+ mvn org.owasp:dependency-check-maven:check
165
+ # or
166
+ ./gradlew dependencyCheckAnalyze
167
+
168
+ # Secrets in source
169
+ grep -rn "password\s*=\s*\"" src/ --include="*.java" --include="*.yml" --include="*.properties"
170
+ grep -rn "sk-\|api_key\|secret" src/ --include="*.java" --include="*.yml"
171
+
172
+ # Secrets (git history)
173
+ git secrets --scan # if configured
174
+ ```
175
+
176
+ ### Common Security Findings
177
+
178
+ ```
179
+ # Check for System.out.println (use logger instead)
180
+ grep -rn "System\.out\.print" src/main/ --include="*.java"
181
+
182
+ # Check for raw exception messages in responses
183
+ grep -rn "e\.getMessage()" src/main/ --include="*.java"
184
+
185
+ # Check for wildcard CORS
186
+ grep -rn "allowedOrigins.*\*" src/main/ --include="*.java"
187
+ ```
188
+
189
+ ## Phase 5: Lint/Format (optional gate)
190
+
191
+ ```bash
192
+ mvn spotless:apply # if using Spotless plugin
193
+ ./gradlew spotlessApply
194
+ ```
195
+
196
+ ## Phase 6: Diff Review
197
+
198
+ ```bash
199
+ git diff --stat
200
+ git diff
201
+ ```
202
+
203
+ Checklist:
204
+ - No debugging logs left (`System.out`, `log.debug` without guards)
205
+ - Meaningful errors and HTTP statuses
206
+ - Transactions and validation present where needed
207
+ - Config changes documented
208
+
209
+ ## Output Template
210
+
211
+ ```
212
+ VERIFICATION REPORT
213
+ ===================
214
+ Build: [PASS/FAIL]
215
+ Static: [PASS/FAIL] (spotbugs/pmd/checkstyle)
216
+ Tests: [PASS/FAIL] (X/Y passed, Z% coverage)
217
+ Security: [PASS/FAIL] (CVE findings: N)
218
+ Diff: [X files changed]
219
+
220
+ Overall: [READY / NOT READY]
221
+
222
+ Issues to Fix:
223
+ 1. ...
224
+ 2. ...
225
+ ```
226
+
227
+ ## Continuous Mode
228
+
229
+ - Re-run phases on significant changes or every 30–60 minutes in long sessions
230
+ - Keep a short loop: `mvn -T 4 test` + spotbugs for quick feedback
231
+
232
+ **Remember**: Fast feedback beats late surprises. Keep the gate strict—treat warnings as defects in production systems.
@@ -0,0 +1,144 @@
1
+ ---
2
+ name: swift-actor-persistence
3
+ description: Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design. Use when persisting data in Swift and a data race or thread-safety problem needs designing out.
4
+ metadata:
5
+ origin: ECC
6
+ ---
7
+
8
+ # Swift Actors for Thread-Safe Persistence
9
+
10
+ Patterns for building thread-safe data persistence layers using Swift actors. Combines in-memory caching with file-backed storage, leveraging the actor model to eliminate data races at compile time.
11
+
12
+ ## When to Activate
13
+
14
+ - Building a data persistence layer in Swift 5.5+
15
+ - Need thread-safe access to shared mutable state
16
+ - Want to eliminate manual synchronization (locks, DispatchQueues)
17
+ - Building offline-first apps with local storage
18
+
19
+ ## Core Pattern
20
+
21
+ ### Actor-Based Repository
22
+
23
+ The actor model guarantees serialized access — no data races, enforced by the compiler.
24
+
25
+ ```swift
26
+ public actor LocalRepository<T: Codable & Identifiable> where T.ID == String {
27
+ private var cache: [String: T] = [:]
28
+ private let fileURL: URL
29
+
30
+ public init(directory: URL = .documentsDirectory, filename: String = "data.json") {
31
+ self.fileURL = directory.appendingPathComponent(filename)
32
+ // Synchronous load during init (actor isolation not yet active)
33
+ self.cache = Self.loadSynchronously(from: fileURL)
34
+ }
35
+
36
+ // MARK: - Public API
37
+
38
+ public func save(_ item: T) throws {
39
+ cache[item.id] = item
40
+ try persistToFile()
41
+ }
42
+
43
+ public func delete(_ id: String) throws {
44
+ cache[id] = nil
45
+ try persistToFile()
46
+ }
47
+
48
+ public func find(by id: String) -> T? {
49
+ cache[id]
50
+ }
51
+
52
+ public func loadAll() -> [T] {
53
+ Array(cache.values)
54
+ }
55
+
56
+ // MARK: - Private
57
+
58
+ private func persistToFile() throws {
59
+ let data = try JSONEncoder().encode(Array(cache.values))
60
+ try data.write(to: fileURL, options: .atomic)
61
+ }
62
+
63
+ private static func loadSynchronously(from url: URL) -> [String: T] {
64
+ guard let data = try? Data(contentsOf: url),
65
+ let items = try? JSONDecoder().decode([T].self, from: data) else {
66
+ return [:]
67
+ }
68
+ return Dictionary(uniqueKeysWithValues: items.map { ($0.id, $0) })
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### Usage
74
+
75
+ All calls are automatically async due to actor isolation:
76
+
77
+ ```swift
78
+ let repository = LocalRepository<Question>()
79
+
80
+ // Read — fast O(1) lookup from in-memory cache
81
+ let question = await repository.find(by: "q-001")
82
+ let allQuestions = await repository.loadAll()
83
+
84
+ // Write — updates cache and persists to file atomically
85
+ try await repository.save(newQuestion)
86
+ try await repository.delete("q-001")
87
+ ```
88
+
89
+ ### Combining with @Observable ViewModel
90
+
91
+ ```swift
92
+ @Observable
93
+ final class QuestionListViewModel {
94
+ private(set) var questions: [Question] = []
95
+ private let repository: LocalRepository<Question>
96
+
97
+ init(repository: LocalRepository<Question> = LocalRepository()) {
98
+ self.repository = repository
99
+ }
100
+
101
+ func load() async {
102
+ questions = await repository.loadAll()
103
+ }
104
+
105
+ func add(_ question: Question) async throws {
106
+ try await repository.save(question)
107
+ questions = await repository.loadAll()
108
+ }
109
+ }
110
+ ```
111
+
112
+ ## Key Design Decisions
113
+
114
+ | Decision | Rationale |
115
+ |----------|-----------|
116
+ | Actor (not class + lock) | Compiler-enforced thread safety, no manual synchronization |
117
+ | In-memory cache + file persistence | Fast reads from cache, durable writes to disk |
118
+ | Synchronous init loading | Avoids async initialization complexity |
119
+ | Dictionary keyed by ID | O(1) lookups by identifier |
120
+ | Generic over `Codable & Identifiable` | Reusable across any model type |
121
+ | Atomic file writes (`.atomic`) | Prevents partial writes on crash |
122
+
123
+ ## Best Practices
124
+
125
+ - **Use `Sendable` types** for all data crossing actor boundaries
126
+ - **Keep the actor's public API minimal** — only expose domain operations, not persistence details
127
+ - **Use `.atomic` writes** to prevent data corruption if the app crashes mid-write
128
+ - **Load synchronously in `init`** — async initializers add complexity with minimal benefit for local files
129
+ - **Combine with `@Observable`** ViewModels for reactive UI updates
130
+
131
+ ## Anti-Patterns to Avoid
132
+
133
+ - Using `DispatchQueue` or `NSLock` instead of actors for new Swift concurrency code
134
+ - Exposing the internal cache dictionary to external callers
135
+ - Making the file URL configurable without validation
136
+ - Forgetting that all actor method calls are `await` — callers must handle async context
137
+ - Using `nonisolated` to bypass actor isolation (defeats the purpose)
138
+
139
+ ## When to Use
140
+
141
+ - Local data storage in iOS/macOS apps (user data, settings, cached content)
142
+ - Offline-first architectures that sync to a server later
143
+ - Any shared mutable state that multiple parts of the app access concurrently
144
+ - Replacing legacy `DispatchQueue`-based thread safety with modern Swift concurrency