moai-adk 0.4.5__py3-none-any.whl → 0.20.1__py3-none-any.whl

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.

Potentially problematic release.


This version of moai-adk might be problematic. Click here for more details.

Files changed (433) hide show
  1. moai_adk/__init__.py +1 -1
  2. moai_adk/__main__.py +74 -1
  3. moai_adk/cli/commands/__init__.py +1 -1
  4. moai_adk/cli/commands/analyze.py +119 -0
  5. moai_adk/cli/commands/backup.py +25 -1
  6. moai_adk/cli/commands/doctor.py +31 -5
  7. moai_adk/cli/commands/improve_user_experience.py +307 -0
  8. moai_adk/cli/commands/init.py +111 -10
  9. moai_adk/cli/commands/status.py +33 -3
  10. moai_adk/cli/commands/update.py +921 -130
  11. moai_adk/cli/commands/validate_links.py +120 -0
  12. moai_adk/cli/prompts/init_prompts.py +22 -87
  13. moai_adk/core/analysis/__init__.py +9 -0
  14. moai_adk/core/analysis/session_analyzer.py +388 -0
  15. moai_adk/core/analysis/tag_chain_analyzer.py +344 -0
  16. moai_adk/core/analysis/tag_chain_repair.py +879 -0
  17. moai_adk/core/config/__init__.py +19 -0
  18. moai_adk/core/config/migration.py +235 -0
  19. moai_adk/core/git/__init__.py +1 -1
  20. moai_adk/core/git/branch.py +1 -1
  21. moai_adk/core/git/commit.py +1 -1
  22. moai_adk/core/git/manager.py +1 -1
  23. moai_adk/core/issue_creator.py +313 -0
  24. moai_adk/core/mcp/setup.py +56 -0
  25. moai_adk/core/mcp/setup_old.py +296 -0
  26. moai_adk/core/project/backup_utils.py +1 -1
  27. moai_adk/core/project/checker.py +2 -2
  28. moai_adk/core/project/detector.py +211 -12
  29. moai_adk/core/project/initializer.py +85 -15
  30. moai_adk/core/project/phase_executor.py +76 -13
  31. moai_adk/core/project/validator.py +13 -13
  32. moai_adk/core/quality/__init__.py +1 -1
  33. moai_adk/core/quality/trust_checker.py +1 -1
  34. moai_adk/core/quality/validators/__init__.py +1 -1
  35. moai_adk/core/quality/validators/base_validator.py +1 -1
  36. moai_adk/core/tags/__init__.py +86 -0
  37. moai_adk/core/tags/auto_corrector.py +693 -0
  38. moai_adk/core/tags/ci_validator.py +463 -0
  39. moai_adk/core/tags/cli.py +283 -0
  40. moai_adk/core/tags/generator.py +109 -0
  41. moai_adk/core/tags/inserter.py +99 -0
  42. moai_adk/core/tags/mapper.py +126 -0
  43. moai_adk/core/tags/parser.py +76 -0
  44. moai_adk/core/tags/policy_validator.py +580 -0
  45. moai_adk/core/tags/pre_commit_validator.py +421 -0
  46. moai_adk/core/tags/reporter.py +956 -0
  47. moai_adk/core/tags/rollback_manager.py +525 -0
  48. moai_adk/core/tags/tags.py +149 -0
  49. moai_adk/core/tags/validator.py +897 -0
  50. moai_adk/core/template/__init__.py +1 -1
  51. moai_adk/core/template/backup.py +1 -1
  52. moai_adk/core/template/merger.py +50 -1
  53. moai_adk/core/template/processor.py +119 -13
  54. moai_adk/core/template_engine.py +268 -0
  55. moai_adk/templates/.claude/agents/alfred/backend-expert.md +348 -0
  56. moai_adk/templates/.claude/agents/alfred/cc-manager.md +209 -944
  57. moai_adk/templates/.claude/agents/alfred/database-expert.md +352 -0
  58. moai_adk/templates/.claude/agents/alfred/debug-helper.md +34 -5
  59. moai_adk/templates/.claude/agents/alfred/devops-expert.md +464 -0
  60. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +38 -8
  61. moai_adk/templates/.claude/agents/alfred/format-expert.md +469 -0
  62. moai_adk/templates/.claude/agents/alfred/frontend-expert.md +357 -0
  63. moai_adk/templates/.claude/agents/alfred/git-manager.md +128 -9
  64. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +104 -6
  65. moai_adk/templates/.claude/agents/alfred/project-manager.md +88 -16
  66. moai_adk/templates/.claude/agents/alfred/quality-gate.md +36 -9
  67. moai_adk/templates/.claude/agents/alfred/security-expert.md +270 -0
  68. moai_adk/templates/.claude/agents/alfred/skill-factory.md +865 -0
  69. moai_adk/templates/.claude/agents/alfred/spec-builder.md +214 -43
  70. moai_adk/templates/.claude/agents/alfred/tag-agent.md +111 -9
  71. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +309 -160
  72. moai_adk/templates/.claude/agents/alfred/trust-checker.md +36 -7
  73. moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +605 -0
  74. moai_adk/templates/.claude/commands/alfred/0-project.md +393 -966
  75. moai_adk/templates/.claude/commands/alfred/1-plan.md +651 -367
  76. moai_adk/templates/.claude/commands/alfred/2-run.md +388 -241
  77. moai_adk/templates/.claude/commands/alfred/3-sync.md +1921 -410
  78. moai_adk/templates/.claude/commands/alfred/9-feedback.md +153 -0
  79. moai_adk/templates/.claude/commands/alfred/release-new.md +3604 -0
  80. moai_adk/templates/.claude/hooks/alfred/core/project.py +484 -20
  81. moai_adk/templates/.claude/hooks/alfred/core/timeout.py +136 -0
  82. moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +108 -0
  83. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +198 -0
  84. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +14 -6
  85. moai_adk/templates/.claude/hooks/alfred/post_tool__enable_streaming_ui.py +50 -0
  86. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +93 -0
  87. moai_adk/templates/.claude/hooks/alfred/post_tool__tag_auto_corrector.py +407 -0
  88. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +99 -0
  89. moai_adk/templates/.claude/hooks/alfred/pre_tool__realtime_tag_monitor.py +335 -0
  90. moai_adk/templates/.claude/hooks/alfred/pre_tool__tag_policy_validator.py +325 -0
  91. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +93 -0
  92. moai_adk/templates/.claude/hooks/alfred/session_start__auto_cleanup.py +580 -0
  93. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +298 -0
  94. moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +170 -0
  95. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/checkpoint.py +3 -3
  96. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/context.py +5 -5
  97. moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +749 -0
  98. moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +230 -0
  99. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +198 -0
  100. moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +21 -0
  101. moai_adk/templates/.claude/hooks/alfred/shared/handlers/daily_analysis.py +351 -0
  102. moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +154 -0
  103. moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +174 -0
  104. moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +87 -0
  105. moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +61 -0
  106. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +111 -0
  107. moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +1 -0
  108. moai_adk/templates/.claude/hooks/alfred/utils/hook_config.py +94 -0
  109. moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +161 -0
  110. moai_adk/templates/.claude/output-styles/alfred/alfred-moai-adk-beginner.md +267 -0
  111. moai_adk/templates/.claude/output-styles/alfred/keating-personal-tutor.md +440 -0
  112. moai_adk/templates/.claude/output-styles/alfred/r2d2-agentic-coding.md +583 -0
  113. moai_adk/templates/.claude/settings.json +96 -14
  114. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +70 -0
  115. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +62 -0
  116. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/reference.md +242 -0
  117. moai_adk/templates/.claude/skills/moai-alfred-ask-user-questions/SKILL.md +237 -0
  118. moai_adk/templates/.claude/skills/moai-alfred-ask-user-questions/examples.md +871 -0
  119. moai_adk/templates/.claude/skills/moai-alfred-ask-user-questions/reference.md +653 -0
  120. moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/README.md +162 -0
  121. moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/SKILL.md +227 -0
  122. moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/examples.md +354 -0
  123. moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/reference.md +158 -0
  124. moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/SKILL.md +179 -79
  125. moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/examples.md +117 -0
  126. moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/scripts/pre-review-check.sh +62 -0
  127. moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +132 -0
  128. moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +28 -0
  129. moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +444 -0
  130. moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +62 -0
  131. moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +28 -0
  132. moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +405 -0
  133. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +51 -0
  134. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +355 -0
  135. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +239 -0
  136. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +323 -0
  137. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +286 -0
  138. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +126 -0
  139. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +229 -0
  140. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +4 -0
  141. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +150 -0
  142. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +87 -73
  143. moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +29 -0
  144. moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +28 -0
  145. moai_adk/templates/.claude/skills/moai-alfred-personas/README.md +42 -0
  146. moai_adk/templates/.claude/skills/moai-alfred-personas/SKILL.md +429 -0
  147. moai_adk/templates/.claude/skills/moai-alfred-personas/examples.md +520 -0
  148. moai_adk/templates/.claude/skills/moai-alfred-personas/reference.md +405 -0
  149. moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +89 -0
  150. moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +122 -0
  151. moai_adk/templates/.claude/skills/moai-alfred-practices/reference.md +369 -0
  152. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +508 -0
  153. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +481 -0
  154. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +100 -0
  155. moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +77 -0
  156. moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +265 -0
  157. moai_adk/templates/.claude/skills/moai-alfred-rules/reference.md +539 -0
  158. moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +320 -0
  159. moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +4 -0
  160. moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +84 -0
  161. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +137 -0
  162. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +219 -0
  163. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples/validate-spec.sh +161 -0
  164. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +541 -0
  165. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +622 -0
  166. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +19 -0
  167. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +4 -0
  168. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +211 -0
  169. moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +288 -0
  170. moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +269 -0
  171. moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +32 -0
  172. moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +298 -0
  173. moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +26 -0
  174. moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +307 -0
  175. moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +21 -0
  176. moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +252 -0
  177. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +19 -0
  178. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +19 -0
  179. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +24 -0
  180. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +199 -0
  181. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +39 -0
  182. moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +316 -0
  183. moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +18 -0
  184. moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +263 -0
  185. moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +30 -0
  186. moai_adk/templates/.claude/skills/moai-cc-skill-factory/CHECKLIST.md +482 -0
  187. moai_adk/templates/.claude/skills/moai-cc-skill-factory/EXAMPLES.md +303 -0
  188. moai_adk/templates/.claude/skills/moai-cc-skill-factory/INTERACTIVE-DISCOVERY.md +524 -0
  189. moai_adk/templates/.claude/skills/moai-cc-skill-factory/METADATA.md +477 -0
  190. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PARALLEL-ANALYSIS-REPORT.md +429 -0
  191. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PYTHON-VERSION-MATRIX.md +391 -0
  192. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-FACTORY-WORKFLOW.md +431 -0
  193. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-UPDATE-ADVISOR.md +577 -0
  194. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL.md +273 -0
  195. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STEP-BY-STEP-GUIDE.md +466 -0
  196. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STRUCTURE.md +583 -0
  197. moai_adk/templates/.claude/skills/moai-cc-skill-factory/WEB-RESEARCH.md +526 -0
  198. moai_adk/templates/.claude/skills/moai-cc-skill-factory/reference.md +608 -0
  199. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/generate-structure.sh +328 -0
  200. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/validate-skill.sh +312 -0
  201. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/SKILL_TEMPLATE.md +245 -0
  202. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/examples-template.md +285 -0
  203. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/reference-template.md +278 -0
  204. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/scripts-template.sh +303 -0
  205. moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +291 -0
  206. moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +15 -0
  207. moai_adk/templates/.claude/skills/moai-change-logger/SKILL.md +563 -0
  208. moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +802 -0
  209. moai_adk/templates/.claude/skills/moai-design-systems/examples.md +1238 -0
  210. moai_adk/templates/.claude/skills/moai-design-systems/reference.md +673 -0
  211. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +234 -43
  212. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +1633 -0
  213. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +660 -0
  214. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +97 -69
  215. moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +29 -0
  216. moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +30 -0
  217. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +97 -72
  218. moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +29 -0
  219. moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +30 -0
  220. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +97 -74
  221. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +29 -0
  222. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +30 -0
  223. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +98 -74
  224. moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +29 -0
  225. moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +31 -0
  226. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +102 -73
  227. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +29 -0
  228. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +31 -0
  229. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +97 -73
  230. moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +29 -0
  231. moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +30 -0
  232. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +97 -67
  233. moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +29 -0
  234. moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +30 -0
  235. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +97 -79
  236. moai_adk/templates/.claude/skills/moai-domain-security/examples.md +29 -0
  237. moai_adk/templates/.claude/skills/moai-domain-security/reference.md +30 -0
  238. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +97 -71
  239. moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +29 -0
  240. moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +30 -0
  241. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +265 -64
  242. moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +1064 -0
  243. moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +1047 -0
  244. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +87 -78
  245. moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +29 -0
  246. moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +28 -0
  247. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +87 -70
  248. moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +29 -0
  249. moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +28 -0
  250. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +87 -86
  251. moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +29 -0
  252. moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +28 -0
  253. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +80 -62
  254. moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +29 -0
  255. moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +28 -0
  256. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +207 -50
  257. moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +29 -0
  258. moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +29 -0
  259. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +90 -71
  260. moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +29 -0
  261. moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +28 -0
  262. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +78 -58
  263. moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +29 -0
  264. moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +28 -0
  265. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +78 -51
  266. moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +29 -0
  267. moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +28 -0
  268. moai_adk/templates/.claude/skills/moai-foundation-trust/.!11330!examples.md +0 -0
  269. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +253 -32
  270. moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
  271. moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +1099 -0
  272. moai_adk/templates/.claude/skills/moai-jit-docs-enhanced/SKILL.md +460 -0
  273. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +98 -74
  274. moai_adk/templates/.claude/skills/moai-lang-c/examples.md +29 -0
  275. moai_adk/templates/.claude/skills/moai-lang-c/reference.md +31 -0
  276. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +98 -76
  277. moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +29 -0
  278. moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +31 -0
  279. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +2358 -70
  280. moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +29 -0
  281. moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +30 -0
  282. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +2962 -68
  283. moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +29 -0
  284. moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +30 -0
  285. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +1898 -70
  286. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +29 -0
  287. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +31 -0
  288. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +1465 -68
  289. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +29 -0
  290. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +31 -0
  291. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +2364 -66
  292. moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +29 -0
  293. moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +32 -0
  294. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +1630 -69
  295. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +29 -0
  296. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +31 -0
  297. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +89 -61
  298. moai_adk/templates/.claude/skills/moai-lang-php/examples.md +29 -0
  299. moai_adk/templates/.claude/skills/moai-lang-php/reference.md +30 -0
  300. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +735 -66
  301. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +624 -0
  302. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +316 -0
  303. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +97 -73
  304. moai_adk/templates/.claude/skills/moai-lang-r/examples.md +29 -0
  305. moai_adk/templates/.claude/skills/moai-lang-r/reference.md +30 -0
  306. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +98 -73
  307. moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +29 -0
  308. moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +31 -0
  309. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +1834 -70
  310. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +29 -0
  311. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +31 -0
  312. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +99 -74
  313. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +29 -0
  314. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +30 -0
  315. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +97 -74
  316. moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +29 -0
  317. moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +30 -0
  318. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +98 -74
  319. moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +29 -0
  320. moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +31 -0
  321. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +1959 -69
  322. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +29 -0
  323. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +30 -0
  324. moai_adk/templates/.claude/skills/moai-lang-template/SKILL.md +348 -0
  325. moai_adk/templates/.claude/skills/moai-lang-template/VARIABLES.md +98 -0
  326. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +1230 -66
  327. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +29 -0
  328. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +34 -0
  329. moai_adk/templates/.claude/skills/moai-learning-optimizer/SKILL.md +575 -0
  330. moai_adk/templates/.claude/skills/moai-project-batch-questions/README.md +50 -0
  331. moai_adk/templates/.claude/skills/moai-project-batch-questions/SKILL.md +304 -0
  332. moai_adk/templates/.claude/skills/moai-project-batch-questions/examples.md +417 -0
  333. moai_adk/templates/.claude/skills/moai-project-batch-questions/reference.md +704 -0
  334. moai_adk/templates/.claude/skills/moai-project-config-manager/README.md +87 -0
  335. moai_adk/templates/.claude/skills/moai-project-config-manager/SKILL.md +552 -0
  336. moai_adk/templates/.claude/skills/moai-project-config-manager/examples.md +1109 -0
  337. moai_adk/templates/.claude/skills/moai-project-config-manager/reference.md +514 -0
  338. moai_adk/templates/.claude/skills/moai-project-config-manager/validate.py +106 -0
  339. moai_adk/templates/.claude/skills/moai-project-documentation/README.md +11 -0
  340. moai_adk/templates/.claude/skills/moai-project-documentation/SKILL.md +622 -0
  341. moai_adk/templates/.claude/skills/moai-project-documentation/examples.md +20 -0
  342. moai_adk/templates/.claude/skills/moai-project-documentation/reference.md +12 -0
  343. moai_adk/templates/.claude/skills/moai-project-language-initializer/README.md +152 -0
  344. moai_adk/templates/.claude/skills/moai-project-language-initializer/SKILL.md +285 -0
  345. moai_adk/templates/.claude/skills/moai-project-language-initializer/examples.md +333 -0
  346. moai_adk/templates/.claude/skills/moai-project-language-initializer/reference.md +386 -0
  347. moai_adk/templates/.claude/skills/moai-project-template-optimizer/README.md +49 -0
  348. moai_adk/templates/.claude/skills/moai-project-template-optimizer/SKILL.md +319 -0
  349. moai_adk/templates/.claude/skills/moai-project-template-optimizer/examples.md +58 -0
  350. moai_adk/templates/.claude/skills/moai-project-template-optimizer/reference.md +123 -0
  351. moai_adk/templates/.claude/skills/moai-session-info/SKILL.md +314 -0
  352. moai_adk/templates/.claude/skills/moai-streaming-ui/SKILL.md +552 -0
  353. moai_adk/templates/.claude/skills/moai-tag-policy-validator/SKILL.md +570 -0
  354. moai_adk/templates/.git-hooks/pre-commit +66 -0
  355. moai_adk/templates/.git-hooks/pre-push +255 -0
  356. moai_adk/templates/.github/workflows/c-tag-validation.yml +11 -0
  357. moai_adk/templates/.github/workflows/cpp-tag-validation.yml +11 -0
  358. moai_adk/templates/.github/workflows/csharp-tag-validation.yml +11 -0
  359. moai_adk/templates/.github/workflows/dart-tag-validation.yml +11 -0
  360. moai_adk/templates/.github/workflows/go-tag-validation.yml +130 -0
  361. moai_adk/templates/.github/workflows/java-tag-validation.yml +11 -0
  362. moai_adk/templates/.github/workflows/javascript-tag-validation.yml +135 -0
  363. moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +11 -0
  364. moai_adk/templates/.github/workflows/moai-gitflow.yml +166 -3
  365. moai_adk/templates/.github/workflows/moai-release-create.yml +100 -0
  366. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +188 -0
  367. moai_adk/templates/.github/workflows/php-tag-validation.yml +11 -0
  368. moai_adk/templates/.github/workflows/python-tag-validation.yml +118 -0
  369. moai_adk/templates/.github/workflows/release.yml +118 -0
  370. moai_adk/templates/.github/workflows/ruby-tag-validation.yml +11 -0
  371. moai_adk/templates/.github/workflows/rust-tag-validation.yml +11 -0
  372. moai_adk/templates/.github/workflows/shell-tag-validation.yml +11 -0
  373. moai_adk/templates/.github/workflows/spec-issue-sync.yml +338 -0
  374. moai_adk/templates/.github/workflows/swift-tag-validation.yml +11 -0
  375. moai_adk/templates/.github/workflows/tag-report.yml +269 -0
  376. moai_adk/templates/.github/workflows/tag-validation.yml +186 -0
  377. moai_adk/templates/.github/workflows/typescript-tag-validation.yml +154 -0
  378. moai_adk/templates/.mcp.json +31 -0
  379. moai_adk/templates/.moai/config.json +80 -7
  380. moai_adk/templates/CLAUDE.md +562 -546
  381. moai_adk/utils/banner.py +5 -5
  382. moai_adk/utils/common.py +294 -0
  383. moai_adk/utils/link_validator.py +235 -0
  384. moai_adk/utils/logger.py +8 -8
  385. moai_adk/utils/user_experience.py +451 -0
  386. moai_adk-0.20.1.dist-info/METADATA +233 -0
  387. moai_adk-0.20.1.dist-info/RECORD +404 -0
  388. moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
  389. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -156
  390. moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -85
  391. moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
  392. moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -92
  393. moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -70
  394. moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -41
  395. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -636
  396. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -692
  397. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -470
  398. moai_adk/templates/.claude/skills/moai-alfred-debugger-pro/SKILL.md +0 -103
  399. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -103
  400. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -95
  401. moai_adk/templates/.claude/skills/moai-alfred-performance-optimizer/SKILL.md +0 -105
  402. moai_adk/templates/.claude/skills/moai-alfred-refactoring-coach/SKILL.md +0 -97
  403. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -97
  404. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -90
  405. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -99
  406. moai_adk/templates/.claude/skills/moai-alfred-tui-survey/SKILL.md +0 -87
  407. moai_adk/templates/.claude/skills/moai-alfred-tui-survey/examples.md +0 -62
  408. moai_adk/templates/.claude/skills/moai-claude-code/SKILL.md +0 -94
  409. moai_adk/templates/.claude/skills/moai-claude-code/examples.md +0 -513
  410. moai_adk/templates/.claude/skills/moai-claude-code/reference.md +0 -433
  411. moai_adk/templates/.claude/skills/moai-claude-code/templates/agent-full.md +0 -332
  412. moai_adk/templates/.claude/skills/moai-claude-code/templates/command-full.md +0 -384
  413. moai_adk/templates/.claude/skills/moai-claude-code/templates/plugin-full.json +0 -363
  414. moai_adk/templates/.claude/skills/moai-claude-code/templates/settings-full.json +0 -595
  415. moai_adk/templates/.claude/skills/moai-claude-code/templates/skill-full.md +0 -496
  416. moai_adk/templates/.claude/skills/moai-lang-clojure/SKILL.md +0 -100
  417. moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +0 -99
  418. moai_adk/templates/.claude/skills/moai-lang-haskell/SKILL.md +0 -100
  419. moai_adk/templates/.claude/skills/moai-lang-julia/SKILL.md +0 -98
  420. moai_adk/templates/.claude/skills/moai-lang-lua/SKILL.md +0 -98
  421. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
  422. moai_adk/templates/.moai/memory/development-guide.md +0 -344
  423. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
  424. moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
  425. moai_adk/templates/.moai/project/product.md +0 -161
  426. moai_adk/templates/.moai/project/structure.md +0 -156
  427. moai_adk/templates/.moai/project/tech.md +0 -227
  428. moai_adk/templates/__init__.py +0 -2
  429. moai_adk-0.4.5.dist-info/METADATA +0 -369
  430. moai_adk-0.4.5.dist-info/RECORD +0 -152
  431. {moai_adk-0.4.5.dist-info → moai_adk-0.20.1.dist-info}/WHEEL +0 -0
  432. {moai_adk-0.4.5.dist-info → moai_adk-0.20.1.dist-info}/entry_points.txt +0 -0
  433. {moai_adk-0.4.5.dist-info → moai_adk-0.20.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,99 +1,1660 @@
1
1
  ---
2
-
3
2
  name: moai-lang-kotlin
4
- description: Kotlin best practices with JUnit, Gradle, ktlint, coroutines, and extension functions. Use when writing or reviewing Kotlin code in project workflows.
3
+ version: 2.0.0
4
+ created: 2025-11-06
5
+ updated: 2025-11-06
6
+ status: active
7
+ description: "Kotlin best practices with Android development, Spring Boot backend, and modern coroutines for 2025"
8
+ keywords: [kotlin, programming, android, backend, spring, coroutines, kmp, mobile]
5
9
  allowed-tools:
6
10
  - Read
11
+ - Write
12
+ - Edit
7
13
  - Bash
14
+ - WebFetch
15
+ - WebSearch
8
16
  ---
9
17
 
10
- # Kotlin Expert
18
+ # Kotlin Development Mastery
19
+
20
+ **Modern Kotlin Development with 2025 Best Practices**
21
+
22
+ > Comprehensive Kotlin development guidance covering Android applications, Spring Boot backend services, KMP cross-platform development, and coroutine-based programming using the latest tools and frameworks.
23
+
24
+ ## What It Does
25
+
26
+ ### Android Development
27
+ - **Mobile App Development**: Jetpack Compose UI, MVVM architecture, modern Android patterns
28
+ - **Platform Integration**: Camera, location, notifications, background services
29
+ - **Performance Optimization**: Memory management, battery optimization, lifecycle awareness
30
+ - **Testing**: Unit tests, UI tests, integration tests with modern Android testing framework
31
+
32
+ ### Backend Development
33
+ - **API Development**: Spring Boot with Kotlin, Ktor, Micronaut for microservices
34
+ - **Database Integration**: Exposed, jOOQ, Spring Data with coroutine support
35
+ - **Async Programming**: Coroutines, Flow, structured concurrency
36
+ - **Testing**: MockK, Kotest, TestContainers with coroutine support
37
+
38
+ ### Cross-Platform Development
39
+ - **KMP Development**: Shared business logic across iOS, Android, Web, Desktop
40
+ - **Platform-Specific APIs**: Expect/actual implementations for platform differences
41
+ - **UI Development**: Compose Multiplatform for cross-platform UI
42
+ - **Testing**: Shared test suites across platforms
43
+
44
+ ## When to Use
45
+
46
+ ### Perfect Scenarios
47
+ - **Building Android applications with modern Jetpack Compose**
48
+ - **Developing backend microservices with Spring Boot and Ktor**
49
+ - **Creating cross-platform applications with Kotlin Multiplatform**
50
+ - **Implementing coroutine-based asynchronous programming**
51
+ - **Building reactive applications with Flow and structured concurrency**
52
+ - **Migrating Java codebases to Kotlin for modern development**
53
+ - **Developing Android libraries and SDKs**
54
+
55
+ ### Common Triggers
56
+ - "Create Android app with Kotlin"
57
+ - "Build Kotlin backend API"
58
+ - "Set up KMP project"
59
+ - "Implement coroutines in Kotlin"
60
+ - "Optimize Kotlin performance"
61
+ - "Test Kotlin application"
62
+ - "Kotlin best practices"
63
+
64
+ ## Tool Version Matrix (2025-11-06)
65
+
66
+ ### Core Kotlin
67
+ - **Kotlin**: 2.0.20 (current) / 1.9.24 (LTS)
68
+ - **Kotlin Multiplatform**: 2.0.20
69
+ - **Package Managers**: Gradle 8.8 with Kotlin DSL, Maven
70
+ - **Runtime**: JVM 17+, Android API 21+, iOS 13+, WebAssembly
71
+
72
+ ### Android Development
73
+ - **Android Studio**: Ladybug | 2024.2.1
74
+ - **Jetpack Compose**: 1.7.0
75
+ - **Compose BOM**: 2024.10.00
76
+ - **Android Gradle Plugin**: 8.7.0
77
+ - **KSP**: 2.0.20-1.0.25
78
+
79
+ ### Backend Frameworks
80
+ - **Spring Boot**: 3.3.x with Kotlin support
81
+ - **Ktor**: 2.3.x - Asynchronous HTTP framework
82
+ - **Micronaut**: 4.7.x - Cloud-native framework
83
+ - **Exposed**: 0.53.x - SQL framework
84
+ - **jOOQ**: 3.19.x - Type-safe SQL
85
+
86
+ ### Testing Tools
87
+ - **Kotest**: 5.9.x - Powerful testing framework
88
+ - **MockK**: 1.13.x - Mocking library for Kotlin
89
+ - **TestContainers**: 1.20.x - Integration testing
90
+ - **Espresso**: 3.6.x - Android UI testing
91
+ - **Compose Testing**: 1.7.0 - Compose UI testing
92
+
93
+ ### Mobile Development
94
+ - **Compose Multiplatform**: 1.7.0
95
+ - **KMP libraries**: Ktor Client, SQLDelight, Voyager
96
+
97
+ ## Ecosystem Overview
98
+
99
+ ### Package Management
100
+
101
+ ```bash
102
+ # Gradle Kotlin DSL project creation
103
+ gradle init --type kotlin-application --dsl kotlin --test-framework kotest --package com.example
104
+
105
+ # KMP project creation
106
+ curl -sSLO https://github.com/Kotlin/kmm-samples/archive/main.zip && unzip main.zip
107
+
108
+ # Dependency management with version catalogs
109
+ # gradle/libs.versions.toml
110
+ [versions]
111
+ kotlin = "2.0.20"
112
+ compose-bom = "2024.10.00"
113
+ ktor = "2.3.12"
114
+
115
+ [libraries]
116
+ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
117
+ ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
118
+
119
+ [bundles]
120
+ ktor = ["ktor-client-core", "ktor-client-logging"]
121
+ ```
122
+
123
+ ### Project Structure (2025 Best Practice)
124
+
125
+ ```
126
+ kotlin-project/
127
+ ├── gradle/
128
+ │ └── libs.versions.toml # Version catalog
129
+ ├── build.gradle.kts # Root build configuration
130
+ ├── settings.gradle.kts # Gradle settings
131
+ ├── gradlew # Gradle wrapper
132
+ └── src/
133
+ ├── commonMain/kotlin/ # Shared KMP code
134
+ │ └── com/example/
135
+ │ ├── data/ # Shared data models
136
+ │ ├── domain/ # Business logic
137
+ │ └── network/ # API clients
138
+ ├── androidMain/kotlin/ # Android-specific code
139
+ │ └── com/example/
140
+ │ ├── ui/ # Android UI
141
+ │ ├── platform/ # Android implementations
142
+ │ └── MainActivity.kt
143
+ ├── iosMain/kotlin/ # iOS-specific code
144
+ │ └── com/example/
145
+ │ └── platform/ # iOS implementations
146
+ ├── jvmMain/kotlin/ # JVM/Backend code
147
+ │ └── com/example/
148
+ │ ├── api/ # REST controllers
149
+ │ ├── service/ # Business services
150
+ │ └── Application.kt
151
+ └── commonTest/kotlin/ # Shared tests
152
+ └── com/example/
153
+ ```
154
+
155
+ ## Modern Development Patterns
156
+
157
+ ### Kotlin Language Features 2.0
158
+
159
+ ```kotlin
160
+ import kotlinx.coroutines.*
161
+ import kotlinx.coroutines.flow.*
162
+ import kotlin.coroutines.*
163
+ import kotlin.time.Duration.Companion.seconds
164
+
165
+ // Context receivers (Kotlin 2.0)
166
+ context(Logging)
167
+ suspend fun processUserData(userId: String) {
168
+ log("Processing user: $userId")
169
+ // Processing logic
170
+ }
171
+
172
+ // Sealed interfaces for better hierarchies
173
+ sealed interface NetworkResult<out T> {
174
+ data class Success<T>(val data: T) : NetworkResult<T>
175
+ data class Error(val exception: Throwable) : NetworkResult<Nothing>
176
+ object Loading : NetworkResult<Nothing>
177
+ }
178
+
179
+ // Extension functions for better APIs
180
+ inline fun <T, R> Result<T>.flatMap(transform: (value: T) -> Result<R>): Result<R> {
181
+ return fold(
182
+ onSuccess = { success -> transform(success) },
183
+ onFailure = { failure -> Result.failure(failure) }
184
+ )
185
+ }
186
+
187
+ // Higher-order functions for functional programming
188
+ inline fun <T> List<T>.filterAndMap(
189
+ crossinline predicate: (T) -> Boolean,
190
+ crossinline transform: (T) -> T
191
+ ): List<T> = this
192
+ .filter { predicate(it) }
193
+ .map { transform(it) }
11
194
 
12
- ## Skill Metadata
13
- | Field | Value |
14
- | ----- | ----- |
15
- | Allowed tools | Read (read_file), Bash (terminal) |
16
- | Auto-load | On demand when language keywords are detected |
17
- | Trigger cues | Kotlin code discussions, framework guidance, or file extensions such as .kt/.kts. |
18
- | Tier | 3 |
195
+ // Scope functions usage
196
+ class UserRepository {
197
+ private val users = mutableMapOf<String, User>()
198
+
199
+ fun createUser(name: String, email: String): User {
200
+ return User(name, email).also { user ->
201
+ users[user.id] = user
202
+ log("User created: ${user.id}")
203
+ }
204
+ }
205
+
206
+ fun findUser(id: String): User? = users[id]?.takeIf { it.isActive }
207
+ }
208
+ ```
209
+
210
+ ### Coroutines and Flow Patterns
211
+
212
+ ```kotlin
213
+ // Structured concurrency
214
+ class UserRepository(
215
+ private val api: UserApi,
216
+ private val database: UserDatabase
217
+ ) {
218
+ suspend fun getUserWithCache(id: String): User = coroutineScope {
219
+ val cached = async(Dispatchers.IO) { database.getUser(id) }
220
+ val network = async(Dispatchers.IO) { api.getUser(id) }
221
+
222
+ when (val user = cached.await()) {
223
+ null -> {
224
+ val networkUser = network.await()
225
+ database.saveUser(networkUser)
226
+ networkUser
227
+ }
228
+ else -> {
229
+ // Refresh in background
230
+ launch { database.saveUser(network.await()) }
231
+ user
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ // Flow operators for reactive streams
238
+ class MessageRepository {
239
+ private val _messages = MutableSharedFlow<Message>()
240
+ val messages: SharedFlow<Message> = _messages.asSharedFlow()
241
+
242
+ fun getFilteredMessages(filter: MessageFilter): Flow<Message> {
243
+ return messages
244
+ .filter { filter.matches(it) }
245
+ .debounce(300.milliseconds)
246
+ .distinctUntilChanged()
247
+ .catch { error ->
248
+ log("Error in message flow: ${error.message}")
249
+ emit(Message.Error(error))
250
+ }
251
+ }
252
+
253
+ // Cold flow with state
254
+ fun getStateFlow(): StateFlow<UiState> = channelFlow {
255
+ send(UiState.Loading)
256
+
257
+ try {
258
+ val data = fetchData()
259
+ send(UiState.Success(data))
260
+
261
+ // Continue listening for updates
262
+ dataUpdates.collect { update ->
263
+ send(UiState.Success(update))
264
+ }
265
+ } catch (e: Exception) {
266
+ send(UiState.Error(e))
267
+ }
268
+ }.stateIn(
269
+ scope = CoroutineScope(Dispatchers.Default + SupervisorJob()),
270
+ started = SharingStarted.WhileSubscribed(5000),
271
+ initialValue = UiState.Idle
272
+ )
273
+ }
274
+
275
+ // Exception handling with coroutines
276
+ suspend fun safeApiCall(apiCall: suspend () -> User): Result<User> {
277
+ return try {
278
+ Result.success(apiCall())
279
+ } catch (e: IOException) {
280
+ Result.failure(NetworkException("Network error", e))
281
+ } catch (e: HttpException) {
282
+ Result.failure(ServerException("Server error: ${e.code()}", e))
283
+ } catch (e: Exception) {
284
+ Result.failure(UnknownException("Unknown error", e))
285
+ }
286
+ }
287
+
288
+ // Timeout and retry patterns
289
+ suspend fun fetchWithRetryAndTimeout(
290
+ maxRetries: Int = 3,
291
+ timeout: Duration = 30.seconds
292
+ ): Data {
293
+ return retry(maxRetries) { attempt ->
294
+ if (attempt > 0) delay(1000 * attempt) // Exponential backoff
295
+
296
+ withTimeout(timeout) {
297
+ fetchData()
298
+ }
299
+ }
300
+ }
301
+
302
+ // Coroutine scope management
303
+ class MyViewModel(
304
+ private val repository: UserRepository
305
+ ) : ViewModel() {
306
+
307
+ private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
308
+ val uiState: StateFlow<UiState> = _uiState.asStateFlow()
309
+
310
+ fun loadUser(userId: String) {
311
+ viewModelScope.launch {
312
+ _uiState.value = UiState.Loading
313
+
314
+ repository.getUser(userId)
315
+ .catch { error -> _uiState.value = UiState.Error(error) }
316
+ .collect { user -> _uiState.value = UiState.Success(user) }
317
+ }
318
+ }
319
+
320
+ override fun onCleared() {
321
+ super.onCleared()
322
+ viewModelScope.cancel() // Cancel all coroutines
323
+ }
324
+ }
325
+ ```
326
+
327
+ ### Android Jetpack Compose Patterns
328
+
329
+ ```kotlin
330
+ @Composable
331
+ fun UserListScreen(
332
+ users: LazyPagingItems<User>,
333
+ onUserClick: (User) -> Unit,
334
+ modifier: Modifier = Modifier
335
+ ) {
336
+ LazyColumn(
337
+ modifier = modifier.fillMaxSize(),
338
+ contentPadding = PaddingValues(16.dp),
339
+ verticalArrangement = Arrangement.spacedBy(8.dp)
340
+ ) {
341
+ items(
342
+ count = users.itemCount,
343
+ key = users.itemKey { it.id }
344
+ ) { index ->
345
+ val user = users[index]
346
+
347
+ if (user != null) {
348
+ UserItem(
349
+ user = user,
350
+ onClick = { onUserClick(user) }
351
+ )
352
+ } else {
353
+ UserItemPlaceholder()
354
+ }
355
+ }
356
+
357
+ when (users.loadState.append) {
358
+ is LoadState.Loading -> item {
359
+ LoadingIndicator()
360
+ }
361
+ is LoadState.Error -> item {
362
+ ErrorMessage(
363
+ message = "Failed to load users",
364
+ onRetry = { users.retry() }
365
+ )
366
+ }
367
+ else -> {}
368
+ }
369
+ }
370
+ }
371
+
372
+ @Composable
373
+ private fun UserItem(
374
+ user: User,
375
+ onClick: () -> Unit,
376
+ modifier: Modifier = Modifier
377
+ ) {
378
+ Card(
379
+ onClick = onClick,
380
+ modifier = modifier.fillMaxWidth(),
381
+ elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
382
+ ) {
383
+ Row(
384
+ modifier = Modifier
385
+ .padding(16.dp)
386
+ .fillMaxWidth(),
387
+ verticalAlignment = Alignment.CenterVertically
388
+ ) {
389
+ AsyncImage(
390
+ model = user.avatarUrl,
391
+ contentDescription = "Avatar",
392
+ modifier = Modifier
393
+ .size(48.dp)
394
+ .clip(CircleShape),
395
+ contentScale = ContentScale.Crop
396
+ )
397
+
398
+ Spacer(modifier = Modifier.width(16.dp))
399
+
400
+ Column(modifier = Modifier.weight(1f)) {
401
+ Text(
402
+ text = user.name,
403
+ style = MaterialTheme.typography.titleMedium
404
+ )
405
+ Text(
406
+ text = user.email,
407
+ style = MaterialTheme.typography.bodyMedium,
408
+ color = MaterialTheme.colorScheme.onSurfaceVariant
409
+ )
410
+ }
411
+
412
+ Icon(
413
+ imageVector = Icons.Default.ChevronRight,
414
+ contentDescription = null,
415
+ tint = MaterialTheme.colorScheme.onSurfaceVariant
416
+ )
417
+ }
418
+ }
419
+ }
420
+
421
+ // State management with MVI
422
+ @Stable
423
+ sealed interface UserListUiState {
424
+ object Idle : UserListUiState
425
+ object Loading : UserListUiState
426
+ data class Success(val users: LazyPagingItems<User>) : UserListUiState
427
+ data class Error(val message: String) : UserListUiState
428
+ }
429
+
430
+ @Composable
431
+ fun rememberUserListUiState(
432
+ viewModel: UserListViewModel = hiltViewModel()
433
+ ): UserListUiState {
434
+ val uiState by viewModel.uiState.collectAsState()
435
+ return uiState
436
+ }
437
+
438
+ // Custom composables
439
+ @Composable
440
+ fun LoadingIndicator(
441
+ modifier: Modifier = Modifier
442
+ ) {
443
+ Box(
444
+ modifier = modifier.fillMaxWidth(),
445
+ contentAlignment = Alignment.Center
446
+ ) {
447
+ CircularProgressIndicator()
448
+ }
449
+ }
450
+
451
+ @Composable
452
+ fun ErrorMessage(
453
+ message: String,
454
+ onRetry: () -> Unit,
455
+ modifier: Modifier = Modifier
456
+ ) {
457
+ Column(
458
+ modifier = modifier
459
+ .fillMaxWidth()
460
+ .padding(16.dp),
461
+ horizontalAlignment = Alignment.CenterHorizontally
462
+ ) {
463
+ Text(
464
+ text = message,
465
+ style = MaterialTheme.typography.bodyMedium,
466
+ color = MaterialTheme.colorScheme.error,
467
+ textAlign = TextAlign.Center
468
+ )
469
+
470
+ Spacer(modifier = Modifier.height(8.dp))
471
+
472
+ Button(onClick = onRetry) {
473
+ Text("Retry")
474
+ }
475
+ }
476
+ }
477
+ ```
478
+
479
+ ### Spring Boot with Kotlin Patterns
480
+
481
+ ```kotlin
482
+ @SpringBootApplication
483
+ @EnableTransactionManagement
484
+ class Application {
485
+ @Bean
486
+ fun objectMapper(): ObjectMapper = jacksonObjectMapper()
487
+ .registerModules(JavaTimeModule(), KotlinModule.Builder().build())
488
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
489
+ }
19
490
 
20
- ## What it does
491
+ @Configuration
492
+ @EnableWebFluxSecurity
493
+ class SecurityConfig {
494
+
495
+ @Bean
496
+ fun securityWebFilterChain(
497
+ http: ServerHttpSecurity,
498
+ jwtDecoder: ReactiveJwtDecoder
499
+ ): SecurityWebFilterChain {
500
+ return http
501
+ .csrf { it.disable() }
502
+ .authorizeExchange { exchanges ->
503
+ exchanges
504
+ .pathMatchers("/api/auth/**").permitAll()
505
+ .pathMatchers("/api/public/**").permitAll()
506
+ .pathMatchers("/actuator/health").permitAll()
507
+ .pathMatchers("/api/admin/**").hasRole("ADMIN")
508
+ .anyExchange().authenticated()
509
+ }
510
+ .oauth2ResourceServer { oauth2 ->
511
+ oauth2.jwt { jwt -> jwt.jwtDecoder(jwtDecoder) }
512
+ }
513
+ .build()
514
+ }
515
+ }
21
516
 
22
- Provides Kotlin-specific expertise for TDD development, including JUnit testing, Gradle build system, ktlint linting, coroutines for concurrency, and extension functions.
517
+ // Repository with Coroutines
518
+ @Repository
519
+ interface UserRepository : ReactiveCrudRepository<User, Long> {
520
+ suspend fun findByUsername(username: String): User?
521
+ fun findByEmailContaining(email: String): Flow<User>
522
+ fun findByActiveTrue(): Flow<User>
523
+ }
23
524
 
24
- ## When to use
525
+ @Service
526
+ @Transactional
527
+ class UserService(
528
+ private val userRepository: UserRepository,
529
+ private val eventPublisher: ApplicationEventPublisher
530
+ ) {
531
+ suspend fun createUser(request: CreateUserRequest): User {
532
+ return userEntity.toUser().also { user ->
533
+ userRepository.save(userEntity)
534
+ eventPublisher.publishEvent(UserCreatedEvent(user.id))
535
+ }
536
+ }
537
+
538
+ fun searchUsers(query: String): Flow<User> {
539
+ return userRepository.findByEmailContaining(query)
540
+ .flowOn(Dispatchers.IO)
541
+ .catch { error ->
542
+ log.error("Error searching users", error)
543
+ throw UserSearchException("Failed to search users", error)
544
+ }
545
+ }
546
+ }
25
547
 
26
- - Engages when the conversation references Kotlin work, frameworks, or files like .kt/.kts.
27
- - “Writing Kotlin tests”, “How to use coroutines”, “Android patterns”
28
- - Automatically invoked when working with Kotlin/Android projects
29
- - Kotlin SPEC implementation (`/alfred:2-run`)
548
+ // REST Controller with Coroutines
549
+ @RestController
550
+ @RequestMapping("/api/users")
551
+ @Validated
552
+ class UserController(
553
+ private val userService: UserService
554
+ ) {
555
+ @GetMapping("/{id}")
556
+ suspend fun getUser(@PathVariable id: Long): ResponseEntity<UserDto> {
557
+ val user = userService.getUserById(id)
558
+ ?: throw UserNotFoundException("User not found: $id")
559
+
560
+ return ResponseEntity.ok(user.toDto())
561
+ }
562
+
563
+ @GetMapping
564
+ fun searchUsers(
565
+ @RequestParam query: String?,
566
+ @RequestParam(defaultValue = "0") page: Int,
567
+ @RequestParam(defaultValue = "20") size: Int
568
+ ): Flow<UserDto> {
569
+ return userService.searchUsers(query ?: "")
570
+ .map { it.toDto() }
571
+ .take(size.toLong())
572
+ .skip((page * size).toLong())
573
+ }
574
+
575
+ @PostMapping
576
+ @ResponseStatus(HttpStatus.CREATED)
577
+ suspend fun createUser(
578
+ @Valid @RequestBody request: CreateUserRequest
579
+ ): UserDto {
580
+ val user = userService.createUser(request)
581
+ return user.toDto()
582
+ }
583
+ }
30
584
 
31
- ## How it works
585
+ // Domain models with data classes
586
+ @Document
587
+ data class User(
588
+ @Id val id: String? = null,
589
+ val username: String,
590
+ val email: String,
591
+ val profile: UserProfile,
592
+ val preferences: UserPreferences,
593
+ val createdAt: Instant = Instant.now(),
594
+ val updatedAt: Instant = Instant.now(),
595
+ val active: Boolean = true
596
+ )
32
597
 
33
- **TDD Framework**:
34
- - **JUnit 5**: Unit testing with Kotlin extensions
35
- - **MockK**: Kotlin-friendly mocking library
36
- - **Kotest**: Kotlin-native testing framework
37
- - Test coverage ≥85% with JaCoCo
598
+ @Document
599
+ data class UserProfile(
600
+ val firstName: String,
601
+ val lastName: String,
602
+ val avatar: String? = null,
603
+ val bio: String? = null
604
+ )
38
605
 
39
- **Build Tools**:
40
- - **Gradle**: build.gradle.kts with Kotlin DSL
41
- - **Maven**: pom.xml alternative
42
- - Multi-platform support (JVM, Native, JS)
606
+ // Extension functions for DTOs
607
+ fun User.toDto() = UserDto(
608
+ id = id!!,
609
+ username = username,
610
+ email = email,
611
+ firstName = profile.firstName,
612
+ lastName = profile.lastName,
613
+ avatar = profile.avatar,
614
+ bio = profile.bio,
615
+ active = active
616
+ )
617
+ ```
618
+
619
+ ## Performance Considerations
620
+
621
+ ### Memory Optimization
622
+
623
+ ```kotlin
624
+ // Efficient collections usage
625
+ class PerformanceOptimized {
626
+
627
+ // Use primitive collections for performance
628
+ private val userIdSet = Object2IntOpenHashMap<User>()
629
+ private val activeUsers = BooleanArrayList()
630
+
631
+ // Lazy initialization with delegation
632
+ private val expensiveResource: ExpensiveResource by lazy {
633
+ createExpensiveResource()
634
+ }
635
+
636
+ // Efficient string processing
637
+ fun processLargeText(text: String): List<String> {
638
+ return text.lineSequence()
639
+ .filter { it.isNotBlank() }
640
+ .map { it.trim() }
641
+ .toList()
642
+ }
643
+
644
+ // Efficient data processing with sequences
645
+ fun processUsers(users: List<User>): List<UserDto> {
646
+ return users.asSequence()
647
+ .filter { it.active }
648
+ .sortedBy { it.username }
649
+ .map { it.toDto() }
650
+ .toList()
651
+ }
652
+ }
653
+
654
+ // Coroutine performance patterns
655
+ class PerformanceService {
656
+
657
+ // Limit concurrency
658
+ private val dispatcher = Dispatchers.IO.limitedParallelism(10)
659
+
660
+ suspend fun processItems(items: List<Item>): List<Result> {
661
+ return coroutineScope {
662
+ items.map { item ->
663
+ async(dispatcher) {
664
+ processItem(item)
665
+ }
666
+ }.awaitAll()
667
+ }
668
+ }
669
+
670
+ // Efficient flow processing
671
+ fun processLargeStream(): Flow<Result> {
672
+ return generateSequence { generateNextItem() }
673
+ .asFlow()
674
+ .flowOn(Dispatchers.Default)
675
+ .buffer(Channel.CONFLATED) // Keep only latest
676
+ .conflate() // Skip intermediate values if consumer is slow
677
+ }
678
+ }
679
+ ```
680
+
681
+ ### Kotlin/Native and KMP Performance
682
+
683
+ ```kotlin
684
+ // Expect/actual for platform-specific optimizations
685
+ expect class PlatformLogger() {
686
+ fun log(message: String)
687
+ fun logError(error: Throwable)
688
+ }
689
+
690
+ // JVM implementation
691
+ actual class PlatformLogger actual constructor() {
692
+ private val logger = LoggerFactory.getLogger(PlatformLogger::class.java)
693
+
694
+ actual fun log(message: String) {
695
+ logger.info(message)
696
+ }
697
+
698
+ actual fun logError(error: Throwable) {
699
+ logger.error("Error occurred", error)
700
+ }
701
+ }
43
702
 
44
- **Code Quality**:
45
- - **ktlint**: Kotlin linter with formatting
46
- - **detekt**: Static code analysis
47
- - **Android Lint**: Android-specific checks
703
+ // Native implementation
704
+ actual class PlatformLogger actual constructor() {
705
+ actual fun log(message: String) {
706
+ println("[INFO] $message")
707
+ }
708
+
709
+ actual fun logError(error: Throwable) {
710
+ println("[ERROR] ${error.message}")
711
+ }
712
+ }
48
713
 
49
- **Kotlin Features**:
50
- - **Coroutines**: Async programming with suspend functions
51
- - **Extension functions**: Add methods to existing classes
52
- - **Data classes**: Automatic equals/hashCode/toString
53
- - **Null safety**: Non-nullable types by default
54
- - **Smart casts**: Automatic type casting after checks
714
+ // Memory management in KMP
715
+ class SharedCache<K, V> {
716
+ private val cache = mutableMapOf<K, V>()
717
+ private val maxSize: Int
718
+
719
+ constructor(maxSize: Int = 100) {
720
+ this.maxSize = maxSize
721
+ }
722
+
723
+ fun get(key: K): V? = cache[key]
724
+
725
+ fun put(key: K, value: V) {
726
+ if (cache.size >= maxSize) {
727
+ val oldestKey = cache.keys.first()
728
+ cache.remove(oldestKey)
729
+ }
730
+ cache[key] = value
731
+ }
732
+
733
+ fun clear() {
734
+ cache.clear()
735
+ }
736
+ }
737
+ ```
55
738
 
56
- **Android Patterns**:
57
- - **Jetpack Compose**: Declarative UI
58
- - **ViewModel**: UI state management
59
- - **Room**: Database abstraction
60
- - **Retrofit**: Network requests
739
+ ### Profiling and Monitoring
61
740
 
62
- ## Examples
63
741
  ```bash
64
- ./gradlew test && ./gradlew ktlintCheck
742
+ # Kotlin coroutines debugging
743
+ # Add to build.gradle.kts
744
+ dependencies {
745
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-debug")
746
+ }
747
+
748
+ # Enable coroutine debugging
749
+ # VM options: -Dkotlinx.coroutines.debug=on
750
+
751
+ # Android Studio profiler
752
+ # CPU Profiler, Memory Profiler, Network Profiler
753
+
754
+ # JVM debugging with jstat/jmap
755
+ jstat -gc <pid> 1000 10
756
+ jmap -dump:format=b,file=heap.hprof <pid>
757
+
758
+ # Gradle build performance
759
+ ./gradlew build --scan
760
+ ./gradlew build --profile
761
+ ```
762
+
763
+ ## Testing Strategy
764
+
765
+ ### Kotest Configuration
766
+
767
+ ```kotlin
768
+ // build.gradle.kts
769
+ tasks.test {
770
+ useTestNG() // or useJUnitPlatform()
771
+
772
+ // Configure test execution
773
+ testLogging {
774
+ events("passed", "skipped", "failed")
775
+ showExceptions = true
776
+ showCauses = true
777
+ showStackTraces = true
778
+ }
779
+
780
+ // Parallel test execution
781
+ maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
782
+ }
783
+
784
+ // Test configuration
785
+ @TestConfiguration
786
+ class TestConfig {
787
+ @Bean
788
+ @Primary
789
+ fun userRepository(): UserRepository = mockk()
790
+ }
791
+
792
+ // Kotest test classes
793
+ class UserRepositoryTest : FunSpec({
794
+ val repository = mockk<UserRepository>()
795
+ val service = UserService(repository)
796
+
797
+ test("should create user successfully") {
798
+ // Given
799
+ val request = CreateUserRequest("testuser", "test@example.com")
800
+ val expectedUser = User("1", "testuser", "test@example.com")
801
+
802
+ coEvery { repository.findByUsername("testuser") } returns null
803
+ coEvery { repository.save(any()) } returns expectedUser
804
+
805
+ // When
806
+ val result = service.createUser(request)
807
+
808
+ // Then
809
+ result shouldBe expectedUser
810
+ coVerify { repository.save(any()) }
811
+ }
812
+
813
+ context("user search") {
814
+ test("should return users matching query") {
815
+ // Given
816
+ val users = flowOf(
817
+ User("1", "john@example.com"),
818
+ User("2", "jane@example.com")
819
+ )
820
+ every { repository.findByEmailContaining("john") } returns users
821
+
822
+ // When
823
+ val results = service.searchUsers("john").toList()
824
+
825
+ // Then
826
+ results shouldHaveSize 1
827
+ results.first().email shouldBe "john@example.com"
828
+ }
829
+ }
830
+ })
831
+ ```
832
+
833
+ ### Android Testing with Compose
834
+
835
+ ```kotlin
836
+ @RunWith(AndroidJUnit4::class)
837
+ class UserProfileScreenTest {
838
+
839
+ @get:Rule
840
+ val composeTestRule = createComposeRule()
841
+
842
+ @Test
843
+ fun userProfileScreen_displaysUserInformation() {
844
+ // Given
845
+ val user = User(
846
+ id = "1",
847
+ name = "John Doe",
848
+ email = "john@example.com",
849
+ avatar = "https://example.com/avatar.jpg"
850
+ )
851
+
852
+ // When
853
+ composeTestRule.setContent {
854
+ UserProfileScreen(
855
+ user = user,
856
+ onEditClick = {}
857
+ )
858
+ }
859
+
860
+ // Then
861
+ composeTestRule
862
+ .onNodeWithText("John Doe")
863
+ .assertIsDisplayed()
864
+
865
+ composeTestRule
866
+ .onNodeWithText("john@example.com")
867
+ .assertIsDisplayed()
868
+
869
+ composeTestRule
870
+ .onNodeWithContentDescription("User avatar")
871
+ .assertIsDisplayed()
872
+ }
873
+
874
+ @Test
875
+ fun userProfileScreen_whenEditClicked_callsOnEditClick() {
876
+ // Given
877
+ var editClicked = false
878
+ val user = User("1", "John Doe", "john@example.com")
879
+
880
+ // When
881
+ composeTestRule.setContent {
882
+ UserProfileScreen(
883
+ user = user,
884
+ onEditClick = { editClicked = true }
885
+ )
886
+ }
887
+
888
+ composeTestRule
889
+ .onNodeWithText("Edit")
890
+ .performClick()
891
+
892
+ // Then
893
+ assertTrue(editClicked)
894
+ }
895
+ }
896
+
897
+ // ViewModel testing
898
+ @ExtendWith(MockitoExtension::class)
899
+ class UserListViewModelTest {
900
+
901
+ @Mock
902
+ private lateinit var userRepository: UserRepository
903
+
904
+ private lateinit var viewModel: UserListViewModel
905
+
906
+ @Before
907
+ fun setup() {
908
+ viewModel = UserListViewModel(userRepository)
909
+ }
910
+
911
+ @Test
912
+ fun `loadUsers should update UI state with users`() = runTest {
913
+ // Given
914
+ val users = flowOf(
915
+ User("1", "User 1"),
916
+ User("2", "User 2")
917
+ )
918
+ whenever(userRepository.getUsers()).thenReturn(users)
919
+
920
+ // When
921
+ viewModel.loadUsers()
922
+
923
+ // Then
924
+ val state = viewModel.uiState.value
925
+ assertTrue(state is UserListUiState.Success)
926
+ assertEquals(2, (state as UserListUiState.Success).users.count())
927
+ }
928
+ }
929
+ ```
930
+
931
+ ### Integration Testing
932
+
933
+ ```kotlin
934
+ @SpringBootTest
935
+ @Testcontainers
936
+ @Transactional
937
+ class UserControllerIntegrationTest {
938
+
939
+ companion object {
940
+ @Container
941
+ @JvmStatic
942
+ val postgres = PostgreSQLContainer<Nothing>("postgres:16-alpine")
943
+ .apply {
944
+ withDatabaseName("testdb")
945
+ withUsername("test")
946
+ withPassword("test")
947
+ }
948
+
949
+ @JvmStatic
950
+ @DynamicPropertySource
951
+ fun postgresProperties(registry: DynamicPropertyRegistry) {
952
+ registry.add("spring.r2dbc.url") {
953
+ "r2dbc:postgresql://${postgres.host}:${postgres.firstMappedPort}/testdb"
954
+ }
955
+ registry.add("spring.r2dbc.username") { postgres.username }
956
+ registry.add("spring.r2dbc.password") { postgres.password }
957
+ }
958
+ }
959
+
960
+ @Autowired
961
+ private lateinit var webTestClient: WebTestClient
962
+
963
+ @Test
964
+ fun `should create and retrieve user`() {
965
+ // Given
966
+ val createUserRequest = CreateUserRequest(
967
+ username = "testuser",
968
+ email = "test@example.com"
969
+ )
970
+
971
+ // When
972
+ val createResponse = webTestClient.post()
973
+ .uri("/api/users")
974
+ .bodyValue(createUserRequest)
975
+ .exchange()
976
+ .expectStatus().isCreated
977
+ .expectBody(UserDto::class.java)
978
+ .returnResult()
979
+ .responseBody!!
980
+
981
+ // Then
982
+ val retrievedUser = webTestClient.get()
983
+ .uri("/api/users/${createResponse.id}")
984
+ .exchange()
985
+ .expectStatus().isOk
986
+ .expectBody(UserDto::class.java)
987
+ .returnResult()
988
+ .responseBody!!
989
+
990
+ assertEquals(createResponse.id, retrievedUser.id)
991
+ assertEquals(createResponse.username, retrievedUser.username)
992
+ }
993
+ }
994
+ ```
995
+
996
+ ## Security Best Practices
997
+
998
+ ### Input Validation and Sanitization
999
+
1000
+ ```kotlin
1001
+ // Data class with validation
1002
+ data class CreateUserRequest(
1003
+ @field:NotBlank(message = "Username is required")
1004
+ @field:Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
1005
+ @field:Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "Username can only contain letters, numbers, and underscores")
1006
+ val username: String,
1007
+
1008
+ @field:NotBlank(message = "Email is required")
1009
+ @field:Email(message = "Invalid email format")
1010
+ @field:Size(max = 100, message = "Email must be less than 100 characters")
1011
+ val email: String,
1012
+
1013
+ @field:NotBlank(message = "Password is required")
1014
+ @field:Size(min = 8, max = 128, message = "Password must be between 8 and 128 characters")
1015
+ @field:Pattern(
1016
+ regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]",
1017
+ message = "Password must contain at least one lowercase letter, one uppercase letter, one digit, and one special character"
1018
+ )
1019
+ val password: String
1020
+ ) {
1021
+ init {
1022
+ require(!email.lowercase().contains("@admin.com")) {
1023
+ "Admin email domains are not allowed"
1024
+ }
1025
+ }
1026
+ }
1027
+
1028
+ // Security service
1029
+ @Service
1030
+ class SecurityService {
1031
+ private val passwordEncoder = BCryptPasswordEncoder(12)
1032
+
1033
+ fun encodePassword(rawPassword: String): String {
1034
+ return passwordEncoder.encode(rawPassword)
1035
+ }
1036
+
1037
+ fun matches(rawPassword: String, encodedPassword: String): Boolean {
1038
+ return passwordEncoder.matches(rawPassword, encodedPassword)
1039
+ }
1040
+
1041
+ fun validateInput(input: String): String {
1042
+ return input
1043
+ .replace(Regex("<script.*?>.*?</script>"), "")
1044
+ .replace(Regex("javascript:"), "")
1045
+ .trim()
1046
+ }
1047
+ }
1048
+ ```
1049
+
1050
+ ### Authentication and Authorization
1051
+
1052
+ ```kotlin
1053
+ @Configuration
1054
+ @EnableWebFluxSecurity
1055
+ class SecurityConfig {
1056
+
1057
+ @Bean
1058
+ fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
1059
+ return http
1060
+ .csrf { it.disable() }
1061
+ .authorizeExchange { exchanges ->
1062
+ exchanges
1063
+ .pathMatchers("/api/auth/**").permitAll()
1064
+ .pathMatchers("/api/public/**").permitAll()
1065
+ .pathMatchers("/actuator/health").permitAll()
1066
+ .pathMatchers("/api/admin/**").hasRole("ADMIN")
1067
+ .anyExchange().authenticated()
1068
+ }
1069
+ .oauth2ResourceServer { oauth2 ->
1070
+ oauth2.jwt { jwt -> jwt.jwtDecoder(jwtDecoder()) }
1071
+ }
1072
+ .build()
1073
+ }
1074
+
1075
+ @Bean
1076
+ fun reactiveAuthenticationManager(
1077
+ userRepository: UserRepository,
1078
+ passwordService: PasswordService
1079
+ ): ReactiveAuthenticationManager {
1080
+ return UserDetailsRepositoryReactiveAuthenticationManager(
1081
+ userRepository.toUserDetailsService()
1082
+ ).apply {
1083
+ setPasswordEncoder(passwordService.encoder)
1084
+ }
1085
+ }
1086
+ }
1087
+
1088
+ // Method-level security
1089
+ @Service
1090
+ class DocumentService {
1091
+
1092
+ @PreAuthorize("hasRole('USER') and @documentSecurity.canRead(#documentId, authentication.name)")
1093
+ suspend fun getDocument(documentId: Long): Document {
1094
+ return documentRepository.findById(documentId)
1095
+ ?: throw DocumentNotFoundException("Document not found: $documentId")
1096
+ }
1097
+
1098
+ @PreAuthorize("hasRole('ADMIN') or @documentSecurity.isOwner(#documentId, authentication.name)")
1099
+ suspend fun updateDocument(documentId: Long, updateDto: DocumentUpdateDto): Document {
1100
+ val document = getDocument(documentId)
1101
+ if (!canUpdate(document, SecurityContextHolder.getContext().authentication.name)) {
1102
+ throw AccessDeniedException("Not authorized to update document")
1103
+ }
1104
+ return documentRepository.save(document.update(updateDto))
1105
+ }
1106
+ }
1107
+ ```
1108
+
1109
+ ## Integration Patterns
1110
+
1111
+ ### Database Integration with Exposed
1112
+
1113
+ ```kotlin
1114
+ object Users : Table("users") {
1115
+ val id = uuid("id").autoGenerate()
1116
+ val username = varchar("username", 50).uniqueIndex()
1117
+ val email = varchar("email", 100).uniqueIndex()
1118
+ val createdAt = datetime("created_at").defaultExpression(CurrentDateTime())
1119
+ val updatedAt = datetime("updated_at").defaultExpression(CurrentDateTime())
1120
+ val active = bool("active").default(true)
1121
+
1122
+ override val primaryKey = PrimaryKey(id)
1123
+ }
1124
+
1125
+ @Entity
1126
+ data class User(
1127
+ val id: UUID = UUID.randomUUID(),
1128
+ val username: String,
1129
+ val email: String,
1130
+ val createdAt: Instant = Instant.now(),
1131
+ val updatedAt: Instant = Instant.now(),
1132
+ val active: Boolean = true
1133
+ )
1134
+
1135
+ // Repository with Exposed
1136
+ class UserRepository(
1137
+ private val database: Database
1138
+ ) {
1139
+ suspend fun findById(id: UUID): User? = withContext(Dispatchers.IO) {
1140
+ transaction(database) {
1141
+ Users.select { Users.id eq id }
1142
+ .map { it.toUser() }
1143
+ .singleOrNull()
1144
+ }
1145
+ }
1146
+
1147
+ suspend fun save(user: User): User = withContext(Dispatchers.IO) {
1148
+ transaction(database) {
1149
+ Users.upsert {
1150
+ it[id] = user.id
1151
+ it[username] = user.username
1152
+ it[email] = user.email
1153
+ it[createdAt] = user.createdAt
1154
+ it[updatedAt] = Instant.now()
1155
+ it[active] = user.active
1156
+ }
1157
+ user.copy(updatedAt = Instant.now())
1158
+ }
1159
+ }
1160
+
1161
+ fun findAllActive(): Flow<User> = flow {
1162
+ transaction(database) {
1163
+ Users.select { Users.active eq true }
1164
+ .map { it.toUser() }
1165
+ .forEach { user -> emit(user) }
1166
+ }
1167
+ }.flowOn(Dispatchers.IO)
1168
+ }
1169
+
1170
+ private fun ResultRow.toUser() = User(
1171
+ id = this[Users.id],
1172
+ username = this[Users.username],
1173
+ email = this[Users.email],
1174
+ createdAt = this[Users.createdAt].toInstant(),
1175
+ updatedAt = this[Users.updatedAt].toInstant(),
1176
+ active = this[Users.active]
1177
+ )
1178
+ ```
1179
+
1180
+ ### Ktor Client Integration
1181
+
1182
+ ```kotlin
1183
+ // Ktor client configuration
1184
+ class ApiClient {
1185
+ private val httpClient = HttpClient(CIO) {
1186
+ install(ContentNegotiation) {
1187
+ json(
1188
+ Json {
1189
+ ignoreUnknownKeys = true
1190
+ isLenient = true
1191
+ }
1192
+ )
1193
+ }
1194
+
1195
+ install(Auth) {
1196
+ bearer {
1197
+ loadTokens {
1198
+ BearerTokens(accessToken = getAccessToken(), refreshToken = getRefreshToken())
1199
+ }
1200
+ refreshTokens {
1201
+ val refreshedTokens = refreshAccessToken()
1202
+ BearerTokens(
1203
+ accessToken = refreshedTokens.accessToken,
1204
+ refreshToken = refreshedTokens.refreshToken
1205
+ )
1206
+ }
1207
+ }
1208
+ }
1209
+
1210
+ defaultRequest {
1211
+ url("https://api.example.com/")
1212
+ }
1213
+ }
1214
+
1215
+ suspend fun getUsers(): List<User> = try {
1216
+ httpClient.get("users").body()
1217
+ } catch (e: ClientRequestException) {
1218
+ when (e.response.status) {
1219
+ HttpStatusCode.NotFound -> emptyList()
1220
+ HttpStatusCode.Unauthorized -> throw AuthenticationException()
1221
+ else -> throw ApiException("Failed to fetch users", e)
1222
+ }
1223
+ } catch (e: Exception) {
1224
+ throw NetworkException("Network error", e)
1225
+ }
1226
+
1227
+ suspend fun createUser(user: CreateUserRequest): User = httpClient.post("users") {
1228
+ contentType(ContentType.Application.Json)
1229
+ setBody(user)
1230
+ }.body()
1231
+ }
1232
+
1233
+ // Multiplatform API client
1234
+ class SharedApiClient(
1235
+ private val platform: Platform
1236
+ ) {
1237
+ private val httpClient = HttpClient {
1238
+ if (platform.isDebug) {
1239
+ install(Logging) {
1240
+ logger = Logger.DEFAULT
1241
+ level = LogLevel.INFO
1242
+ }
1243
+ }
1244
+
1245
+ expectSuccess = true
1246
+ install(ContentNegotiation) {
1247
+ json(Json {
1248
+ ignoreUnknownKeys = true
1249
+ useAlternativeNames = false
1250
+ })
1251
+ }
1252
+ }
1253
+
1254
+ suspend fun fetchData(): ApiResponse = httpClient.get("data").body()
1255
+ }
1256
+
1257
+ // Platform-specific implementations
1258
+ // JVM
1259
+ class AndroidPlatform : Platform {
1260
+ override val name: String = "Android ${Build.VERSION.SDK_INT}"
1261
+ override val isDebug: Boolean = BuildConfig.DEBUG
1262
+ }
1263
+
1264
+ // iOS
1265
+ class IOSPlatform : Platform {
1266
+ override val name: String = UIDevice.currentDevice.systemName()
1267
+ override val isDebug: Boolean = Platform.isDebugBinary
1268
+ }
1269
+
1270
+ actual fun getPlatform(): Platform =
1271
+ if (Platform.osFamily == OsFamily.IOS) IOSPlatform() else AndroidPlatform()
1272
+ ```
1273
+
1274
+ ### Message Queue Integration
1275
+
1276
+ ```kotlin
1277
+ // RabbitMQ with Spring Boot
1278
+ @Configuration
1279
+ class RabbitConfig {
1280
+
1281
+ @Bean
1282
+ fun userQueue(): Queue = QueueBuilder.durable("user.queue").build()
1283
+
1284
+ @Bean
1285
+ fun userExchange(): TopicExchange = TopicExchange("user.exchange")
1286
+
1287
+ @Bean
1288
+ fun userBinding(): Binding = BindingBuilder
1289
+ .bind(userQueue())
1290
+ .to(userExchange())
1291
+ .with("user.created")
1292
+ }
1293
+
1294
+ @Service
1295
+ class UserEventPublisher(
1296
+ private val rabbitTemplate: RabbitTemplate
1297
+ ) {
1298
+ fun publishUserCreated(user: User) {
1299
+ val event = UserCreatedEvent(
1300
+ userId = user.id,
1301
+ username = user.username,
1302
+ email = user.email,
1303
+ timestamp = Instant.now()
1304
+ )
1305
+
1306
+ rabbitTemplate.convertAndSend(
1307
+ "user.exchange",
1308
+ "user.created",
1309
+ event
1310
+ )
1311
+ }
1312
+ }
1313
+
1314
+ @Component
1315
+ class UserEventConsumer {
1316
+
1317
+ private val logger = LoggerFactory.getLogger(UserEventConsumer::class.java)
1318
+
1319
+ @RabbitListener(queues = ["user.queue"])
1320
+ fun handleUserCreated(event: UserCreatedEvent) {
1321
+ logger.info("Received user created event: $event")
1322
+
1323
+ // Process event
1324
+ sendWelcomeEmail(event.userId, event.email)
1325
+ createAuditRecord(event)
1326
+ }
1327
+
1328
+ private fun sendWelcomeEmail(userId: UUID, email: String) {
1329
+ // Implementation
1330
+ }
1331
+
1332
+ private fun createAuditRecord(event: UserCreatedEvent) {
1333
+ // Implementation
1334
+ }
1335
+ }
1336
+ ```
1337
+
1338
+ ## Modern Development Workflow
1339
+
1340
+ ### Gradle Configuration
1341
+
1342
+ ```kotlin
1343
+ // build.gradle.kts
1344
+ plugins {
1345
+ kotlin("multiplatform") version "2.0.20"
1346
+ kotlin("plugin.serialization") version "2.0.20"
1347
+ application
1348
+ id("org.springframework.boot") version "3.3.0"
1349
+ id("io.spring.dependency-management") version "1.1.5"
1350
+ id("com.google.cloud.tools.jib") version "3.4.1"
1351
+ }
1352
+
1353
+ kotlin {
1354
+ jvmToolchain(21)
1355
+
1356
+ jvm {
1357
+ withJava()
1358
+ testRuns.named("test") {
1359
+ executionTask.configure {
1360
+ useJUnitPlatform()
1361
+ }
1362
+ }
1363
+ }
1364
+
1365
+ js(IR) {
1366
+ browser {
1367
+ commonWebpackConfig {
1368
+ cssSupport {
1369
+ enabled.set(true)
1370
+ }
1371
+ }
1372
+ }
1373
+ }
1374
+
1375
+ listOf(
1376
+ iosX64(),
1377
+ iosArm64(),
1378
+ iosSimulatorArm64()
1379
+ ).forEach { iosTarget ->
1380
+ iosTarget.binaries.framework {
1381
+ baseName = "Shared"
1382
+ isStatic = true
1383
+ }
1384
+ }
1385
+
1386
+ sourceSets {
1387
+ commonMain.dependencies {
1388
+ implementation(kotlin("stdlib"))
1389
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
1390
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0")
1391
+ implementation("io.ktor:ktor-client-core:2.3.12")
1392
+ implementation("io.ktor:ktor-client-content-negotiation:2.3.12")
1393
+ implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.12")
1394
+ }
1395
+
1396
+ commonTest.dependencies {
1397
+ implementation(kotlin("test"))
1398
+ implementation(kotlin("test-coroutines"))
1399
+ }
1400
+
1401
+ jvmMain.dependencies {
1402
+ implementation("org.springframework.boot:spring-boot-starter-webflux")
1403
+ implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
1404
+ implementation("org.springframework.boot:spring-boot-starter-amqp")
1405
+ implementation("io.ktor:ktor-client-okhttp:2.3.12")
1406
+ }
1407
+
1408
+ androidMain.dependencies {
1409
+ implementation("io.ktor:ktor-client-android:2.3.12")
1410
+ }
1411
+
1412
+ iosMain.dependencies {
1413
+ implementation("io.ktor:ktor-client-darwin:2.3.12")
1414
+ }
1415
+ }
1416
+ }
1417
+
1418
+ application {
1419
+ mainClass.set("com.example.ApplicationKt")
1420
+ }
1421
+
1422
+ tasks.withType<KotlinCompile> {
1423
+ kotlinOptions {
1424
+ jvmTarget = "21"
1425
+ freeCompilerArgs += listOf(
1426
+ "-Xjsr305=strict",
1427
+ "-Xjvm-default=all",
1428
+ "-opt-in=kotlin.RequiresOptIn"
1429
+ )
1430
+ }
1431
+ }
1432
+
1433
+ // Jib configuration for containerization
1434
+ jib {
1435
+ from {
1436
+ image = "eclipse-temurin:21-jre-alpine"
1437
+ }
1438
+ to {
1439
+ image = "my-registry.com/kotlin-app:latest"
1440
+ }
1441
+ container {
1442
+ jvmFlags = listOf("-Xms512m", "-Xmx2g")
1443
+ ports = listOf("8080")
1444
+ environment = mapOf(
1445
+ "SPRING_PROFILES_ACTIVE" to "prod"
1446
+ )
1447
+ }
1448
+ }
1449
+ ```
1450
+
1451
+ ### Pre-commit Configuration
1452
+
1453
+ ```yaml
1454
+ # .pre-commit-config.yaml
1455
+ repos:
1456
+ - repo: https://github.com/pre-commit/pre-commit-hooks
1457
+ rev: v5.0.0
1458
+ hooks:
1459
+ - id: trailing-whitespace
1460
+ - id: end-of-file-fixer
1461
+ - id: check-yaml
1462
+ - id: check-added-large-files
1463
+ - id: check-merge-conflict
1464
+
1465
+ - repo: https://github.com/pinterest/ktlint
1466
+ rev: 1.2.1
1467
+ hooks:
1468
+ - id: ktlint
1469
+ args: ["--android", "--color"]
1470
+
1471
+ - repo: local
1472
+ hooks:
1473
+ - id: gradle-detekt
1474
+ name: Static analysis with Detekt
1475
+ entry: ./gradlew detekt
1476
+ language: system
1477
+ files: '\.(kt|kts)$'
1478
+ pass_filenames: false
1479
+
1480
+ - id: gradle-test
1481
+ name: Run tests
1482
+ entry: ./gradlew test
1483
+ language: system
1484
+ pass_filenames: false
1485
+ always_run: true
1486
+
1487
+ - id: gradle-check
1488
+ name: Run all checks
1489
+ entry: ./gradlew check
1490
+ language: system
1491
+ pass_filenames: false
1492
+ always_run: true
1493
+ ```
1494
+
1495
+ ### Docker Configuration
1496
+
1497
+ ```dockerfile
1498
+ # Multi-stage Docker build
1499
+ FROM eclipse-temurin:21-jdk-alpine AS builder
1500
+
1501
+ WORKDIR /app
1502
+
1503
+ # Copy gradle wrapper and cache dependencies
1504
+ COPY gradlew gradlew.bat gradle/ ./
1505
+ COPY build.gradle.kts settings.gradle.kts ./
1506
+
1507
+ RUN ./gradlew --no-daemon dependencies
1508
+
1509
+ # Copy source code
1510
+ COPY src/ ./src/
1511
+
1512
+ # Build application
1513
+ RUN ./gradlew --no-daemon bootJar -x test
1514
+
1515
+ # Runtime stage
1516
+ FROM eclipse-temurin:21-jre-alpine
1517
+
1518
+ RUN addgroup --system --gid 1001 appgroup && \
1519
+ adduser --system --uid 1001 --ingroup appgroup appuser && \
1520
+ mkdir -p /app && \
1521
+ chown -R appuser:appgroup /app
1522
+
1523
+ WORKDIR /app
1524
+
1525
+ COPY --from=builder /app/build/libs/*.jar app.jar
1526
+
1527
+ RUN chmod +x app.jar
1528
+
1529
+ USER appuser
1530
+
1531
+ EXPOSE 8080
1532
+
1533
+ ENV JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC -XX:+UseStringDeduplication"
1534
+
1535
+ ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
65
1536
  ```
66
1537
 
67
- ## Inputs
68
- - Language-specific source directories (e.g. `src/`, `app/`).
69
- - Language-specific build/test configuration files (e.g. `package.json`, `pyproject.toml`, `go.mod`).
70
- - Relevant test suites and sample data.
1538
+ ## Cross-Platform Development Patterns
1539
+
1540
+ ### KMP Shared Business Logic
71
1541
 
72
- ## Outputs
73
- - Test/lint execution plan tailored to the selected language.
74
- - List of key language idioms and review checkpoints.
1542
+ ```kotlin
1543
+ // commonMain/kotlin/com/example/data/models/User.kt
1544
+ @Serializable
1545
+ data class User(
1546
+ val id: String,
1547
+ val username: String,
1548
+ val email: String,
1549
+ val avatar: String? = null,
1550
+ val createdAt: Instant = Clock.System.now()
1551
+ )
75
1552
 
76
- ## Failure Modes
77
- - When the language runtime or package manager is not installed.
78
- - When the main language cannot be determined in a multilingual project.
1553
+ // commonMain/kotlin/com/example/data/repository/UserRepository.kt
1554
+ interface UserRepository {
1555
+ suspend fun getUsers(): Result<List<User>>
1556
+ suspend fun getUserById(id: String): Result<User>
1557
+ suspend fun createUser(user: User): Result<User>
1558
+ }
79
1559
 
80
- ## Dependencies
81
- - Access to the project file is required using the Read/Grep tool.
82
- - When used with `Skill("moai-foundation-langs")`, it is easy to share cross-language conventions.
1560
+ // commonMain/kotlin/com/example/data/service/UserService.kt
1561
+ class UserService(
1562
+ private val repository: UserRepository,
1563
+ private val logger: Logger
1564
+ ) {
1565
+ suspend fun getAllUsers(): Result<List<User>> {
1566
+ return try {
1567
+ val users = repository.getUsers().getOrElse { error ->
1568
+ logger.error("Failed to fetch users", error)
1569
+ return Result.failure(error)
1570
+ }
1571
+ Result.success(users)
1572
+ } catch (e: Exception) {
1573
+ logger.error("Unexpected error fetching users", e)
1574
+ Result.failure(e)
1575
+ }
1576
+ }
1577
+
1578
+ fun getUsersFlow(): Flow<List<User>> = flow {
1579
+ while (currentCoroutineContext()[Job]?.isActive == true) {
1580
+ val result = getAllUsers()
1581
+ if (result.isSuccess) {
1582
+ emit(result.getOrNull() ?: emptyList())
1583
+ }
1584
+ delay(30.seconds) // Refresh every 30 seconds
1585
+ }
1586
+ }
1587
+ }
83
1588
 
84
- ## References
85
- - JetBrains. "Kotlin Language Documentation." https://kotlinlang.org/docs/home.html (accessed 2025-03-29).
86
- - Pinterest. "ktlint." https://pinterest.github.io/ktlint/ (accessed 2025-03-29).
1589
+ // Platform-specific implementations
1590
+ // androidMain/kotlin/com/example/data/repository/AndroidUserRepository.kt
1591
+ class AndroidUserRepository(
1592
+ private val context: Context
1593
+ ) : UserRepository {
1594
+
1595
+ private val httpClient = HttpClient(OkHttp) {
1596
+ install(ContentNegotiation) {
1597
+ json(Json {
1598
+ ignoreUnknownKeys = true
1599
+ })
1600
+ }
1601
+ }
1602
+
1603
+ override suspend fun getUsers(): Result<List<User>> {
1604
+ return try {
1605
+ val response = httpClient.get("https://api.example.com/users")
1606
+ val users = response.body<List<User>>()
1607
+ Result.success(users)
1608
+ } catch (e: Exception) {
1609
+ Result.failure(e)
1610
+ }
1611
+ }
1612
+
1613
+ override suspend fun getUserById(id: String): Result<User> {
1614
+ // Implementation
1615
+ }
1616
+
1617
+ override suspend fun createUser(user: User): Result<User> {
1618
+ // Implementation
1619
+ }
1620
+ }
87
1621
 
88
- ## Changelog
89
- - 2025-03-29: Input/output/failure response/reference information for each language has been specified.
1622
+ // iosMain/kotlin/com/example/data/repository/IosUserRepository.kt
1623
+ class IosUserRepository : UserRepository {
1624
+
1625
+ private val httpClient = HttpClient(Darwin) {
1626
+ install(ContentNegotiation) {
1627
+ json(Json {
1628
+ ignoreUnknownKeys = true
1629
+ })
1630
+ }
1631
+ }
1632
+
1633
+ override suspend fun getUsers(): Result<List<User>> {
1634
+ return try {
1635
+ val response = httpClient.get("https://api.example.com/users")
1636
+ val users = response.body<List<User>>()
1637
+ Result.success(users)
1638
+ } catch (e: Exception) {
1639
+ Result.failure(e)
1640
+ }
1641
+ }
1642
+
1643
+ override suspend fun getUserById(id: String): Result<User> {
1644
+ // Implementation
1645
+ }
1646
+
1647
+ override suspend fun createUser(user: User): Result<User> {
1648
+ // Implementation
1649
+ }
1650
+ }
1651
+ ```
90
1652
 
91
- ## Works well with
1653
+ ---
92
1654
 
93
- - alfred-trust-validation (coverage verification)
94
- - alfred-code-reviewer (Kotlin-specific review)
95
- - mobile-app-expert (Android app development)
1655
+ **Created by**: MoAI Language Skill Factory
1656
+ **Last Updated**: 2025-11-06
1657
+ **Version**: 2.0.0
1658
+ **Kotlin Target**: 2.0.20 with modern coroutines, KMP, and Jetpack Compose
96
1659
 
97
- ## Best Practices
98
- - Enable automatic validation by matching your linter with the language's official style guide.
99
- - Fix test/build pipelines with reproducible commands in CI.
1660
+ This skill provides comprehensive Kotlin development guidance with 2025 best practices, covering everything from Android development with Compose to backend services with Spring Boot and cross-platform KMP development.