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
moai_adk/utils/banner.py CHANGED
@@ -9,8 +9,8 @@ from rich.console import Console
9
9
  console = Console()
10
10
 
11
11
  MOAI_BANNER = """
12
- ███╗ ███╗ ██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗ ██╗
13
- ████╗ ████║██╔═══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║ ██╔╝
12
+ ███╗ ███╗ █████╗ ██╗ █████╗ ██████╗ ██╗ ██╗
13
+ ████╗ ████║ ██████╗ ██╔══██╗██║ ██╔══██╗██╔══██╗██║ ██╔╝
14
14
  ██╔████╔██║██║ ██║███████║██║█████╗███████║██║ ██║█████╔╝
15
15
  ██║╚██╔╝██║██║ ██║██╔══██║██║╚════╝██╔══██║██║ ██║██╔═██╗
16
16
  ██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ██║ ██║██████╔╝██║ ██╗
@@ -33,10 +33,10 @@ def print_banner(version: str = "0.3.0") -> None:
33
33
 
34
34
  def print_welcome_message() -> None:
35
35
  """Print the welcome message"""
36
- console.print("[cyan bold]🚀 Welcome to MoAI-ADK Project Initialization![/cyan bold]\n")
37
36
  console.print(
38
- "[dim]This wizard will guide you through setting up your MoAI-ADK project.[/dim]"
37
+ "[cyan bold]🚀 Welcome to MoAI-ADK Project Initialization![/cyan bold]\n"
39
38
  )
40
39
  console.print(
41
- "[dim]You can press Ctrl+C at any time to cancel.\n[/dim]"
40
+ "[dim]This wizard will guide you through setting up your MoAI-ADK project.[/dim]"
42
41
  )
42
+ console.print("[dim]You can press Ctrl+C at any time to cancel.\n[/dim]")
@@ -0,0 +1,294 @@
1
+ # @CODE:COMMON-UTILITIES-001
2
+
3
+ """
4
+ Common Utilities
5
+ 공통 유틸리티 함수들
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import logging
11
+ import re
12
+ from dataclasses import dataclass
13
+ from datetime import datetime
14
+ from pathlib import Path
15
+ from typing import Dict, List, Optional
16
+ from urllib.parse import urlparse
17
+
18
+ import aiohttp
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ @dataclass
24
+ class HTTPResponse:
25
+ """HTTP 응답 데이터"""
26
+ status_code: int
27
+ url: str
28
+ load_time: float
29
+ success: bool
30
+ error_message: Optional[str] = None
31
+ timestamp: datetime = None
32
+
33
+ def __post_init__(self):
34
+ if self.timestamp is None:
35
+ self.timestamp = datetime.now()
36
+
37
+
38
+ class HTTPClient:
39
+ """HTTP 클라이언트 유틸리티"""
40
+
41
+ def __init__(self, max_concurrent: int = 5, timeout: int = 10):
42
+ self.max_concurrent = max_concurrent
43
+ self.timeout = timeout
44
+ self.session: Optional[aiohttp.ClientSession] = None
45
+
46
+ async def __aenter__(self):
47
+ """비동기 컨텍스트 매니저 진입"""
48
+ connector = aiohttp.TCPConnector(limit=self.max_concurrent)
49
+ timeout = aiohttp.ClientTimeout(total=self.timeout)
50
+ self.session = aiohttp.ClientSession(
51
+ connector=connector,
52
+ timeout=timeout,
53
+ headers={
54
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
55
+ }
56
+ )
57
+ return self
58
+
59
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
60
+ """비동기 컨텍스트 매니저 종료"""
61
+ if self.session:
62
+ await self.session.close()
63
+
64
+ async def fetch_url(self, url: str) -> HTTPResponse:
65
+ """단일 URL 가져오기"""
66
+ try:
67
+ start_time = asyncio.get_event_loop().time()
68
+ async with self.session.get(url, allow_redirects=True) as response:
69
+ load_time = asyncio.get_event_loop().time() - start_time
70
+ success = 200 <= response.status < 300
71
+ return HTTPResponse(
72
+ status_code=response.status,
73
+ url=str(response.url),
74
+ load_time=load_time,
75
+ success=success
76
+ )
77
+ except asyncio.TimeoutError:
78
+ return HTTPResponse(
79
+ status_code=0,
80
+ url=url,
81
+ load_time=self.timeout,
82
+ success=False,
83
+ error_message="Request timeout"
84
+ )
85
+ except aiohttp.ClientError as e:
86
+ return HTTPResponse(
87
+ status_code=0,
88
+ url=url,
89
+ load_time=0.0,
90
+ success=False,
91
+ error_message=f"HTTP client error: {str(e)}"
92
+ )
93
+ except Exception as e:
94
+ return HTTPResponse(
95
+ status_code=0,
96
+ url=url,
97
+ load_time=0.0,
98
+ success=False,
99
+ error_message=f"Unexpected error: {str(e)}"
100
+ )
101
+
102
+ async def fetch_urls(self, urls: List[str]) -> List[HTTPResponse]:
103
+ """여러 URL 동시 가져오기"""
104
+ async with self:
105
+ tasks = [self.fetch_url(url) for url in urls]
106
+ return await asyncio.gather(*tasks)
107
+
108
+
109
+ def extract_links_from_text(text: str, base_url: str = None) -> List[str]:
110
+ """텍스트에서 링크 추출"""
111
+ links = []
112
+
113
+ # Markdown 링크 패턴: [text](url)
114
+ markdown_pattern = r'\[([^\]]+)\]\(([^)]+)\)'
115
+ markdown_matches = re.findall(markdown_pattern, text)
116
+
117
+ for match in markdown_matches:
118
+ url = match[1]
119
+ # 상대 URL을 절대 URL로 변환
120
+ if url.startswith(('http://', 'https://')):
121
+ links.append(url)
122
+ elif base_url and url.startswith('/'):
123
+ links.append(f"{base_url}{url}")
124
+ elif base_url and not url.startswith(('http://', 'https://', '#')):
125
+ links.append(f"{base_url}/{url.rstrip('/')}")
126
+
127
+ # 일반 URL 패턴
128
+ url_pattern = r'https?://[^\s<>"\'()]+'
129
+ url_matches = re.findall(url_pattern, text)
130
+ links.extend(url_matches)
131
+
132
+ logger.info(f"텍스트에서 {len(links)}개의 링크를 발견했습니다")
133
+ return list(set(links)) # 중복 제거
134
+
135
+
136
+ def is_valid_url(url: str) -> bool:
137
+ """URL 유효성 검사"""
138
+ try:
139
+ result = urlparse(url)
140
+ return all([result.scheme, result.netloc])
141
+ except Exception:
142
+ return False
143
+
144
+
145
+ def create_report_path(base_path: Path, suffix: str = "report") -> Path:
146
+ """보고서 파일 경로 생성"""
147
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
148
+ filename = f"{suffix}_{timestamp}.md"
149
+ return base_path / filename
150
+
151
+
152
+ def format_duration(seconds: float) -> str:
153
+ """시간(초)을 읽기 쉬운 형식으로 변환"""
154
+ if seconds < 1:
155
+ return f"{seconds*1000:.0f}ms"
156
+ elif seconds < 60:
157
+ return f"{seconds:.1f}s"
158
+ elif seconds < 3600:
159
+ minutes = int(seconds // 60)
160
+ remaining_seconds = seconds % 60
161
+ return f"{minutes}m {remaining_seconds:.0f}s"
162
+ else:
163
+ hours = int(seconds // 3600)
164
+ remaining_minutes = int((seconds % 3600) // 60)
165
+ return f"{hours}h {remaining_minutes}m"
166
+
167
+
168
+ def calculate_score(values: List[float], weights: Optional[List[float]] = None) -> float:
169
+ """가중 평균 점수 계산"""
170
+ if not values:
171
+ return 0.0
172
+
173
+ if weights is None:
174
+ weights = [1.0] * len(values)
175
+
176
+ if len(values) != len(weights):
177
+ raise ValueError("값과 가중치의 길이가 일치해야 합니다")
178
+
179
+ weighted_sum = sum(v * w for v, w in zip(values, weights))
180
+ total_weight = sum(weights)
181
+
182
+ return weighted_sum / total_weight if total_weight > 0 else 0.0
183
+
184
+
185
+ def get_summary_stats(numbers: List[float]) -> Dict[str, float]:
186
+ """기통계량 계산"""
187
+ if not numbers:
188
+ return {"mean": 0.0, "min": 0.0, "max": 0.0, "std": 0.0}
189
+
190
+ mean = sum(numbers) / len(numbers)
191
+ min_val = min(numbers)
192
+ max_val = max(numbers)
193
+
194
+ # 표준편차 계산
195
+ if len(numbers) > 1:
196
+ variance = sum((x - mean) ** 2 for x in numbers) / (len(numbers) - 1)
197
+ std_dev = variance ** 0.5
198
+ else:
199
+ std_dev = 0.0
200
+
201
+ return {
202
+ "mean": mean,
203
+ "min": min_val,
204
+ "max": max_val,
205
+ "std": std_dev
206
+ }
207
+
208
+
209
+ class RateLimiter:
210
+ """요청 속도 제한기"""
211
+
212
+ def __init__(self, max_requests: int = 10, time_window: int = 60):
213
+ self.max_requests = max_requests
214
+ self.time_window = time_window
215
+ self.requests = []
216
+
217
+ def can_make_request(self) -> bool:
218
+ """요청 가능 여부 확인"""
219
+ now = datetime.now()
220
+
221
+ # 오래된 요청 제거
222
+ self.requests = [req_time for req_time in self.requests
223
+ if (now - req_time).total_seconds() < self.time_window]
224
+
225
+ return len(self.requests) < self.max_requests
226
+
227
+ def add_request(self):
228
+ """요청 기록 추가"""
229
+ if self.can_make_request():
230
+ self.requests.append(datetime.now())
231
+ else:
232
+ raise RateLimitError(f"Rate limit exceeded: {self.max_requests} requests per {self.time_window}s")
233
+
234
+ async def wait_if_needed(self):
235
+ """요청이 가능할 때까지 대기"""
236
+ if not self.can_make_request():
237
+ oldest_request = min(self.requests)
238
+ wait_time = self.time_window - (datetime.now() - oldest_request).total_seconds()
239
+ if wait_time > 0:
240
+ logger.info(f"Rate limiting: waiting {wait_time:.1f}s")
241
+ await asyncio.sleep(wait_time)
242
+
243
+
244
+ class RateLimitError(Exception):
245
+ """속도 제한 오류"""
246
+ pass
247
+
248
+
249
+ def load_hook_timeout() -> int:
250
+ """
251
+ .moai/config.json에서 Hook timeout 설정 로드
252
+
253
+ Returns:
254
+ int: timeout 값 (밀리초), 설정이 없으면 기본값 5000 반환
255
+ """
256
+ try:
257
+ config_path = Path(".moai/config.json")
258
+ if not config_path.exists():
259
+ return 5000 # 기본값
260
+
261
+ with open(config_path, 'r', encoding='utf-8') as f:
262
+ config = json.load(f)
263
+
264
+ # hooks 섹션에서 timeout_ms 값 가져오기
265
+ hooks_config = config.get("hooks", {})
266
+ timeout_ms = hooks_config.get("timeout_ms", 5000)
267
+
268
+ return int(timeout_ms)
269
+ except (json.JSONDecodeError, FileNotFoundError, KeyError, ValueError):
270
+ logger.warning("Failed to load hook timeout from config, using default 5000ms")
271
+ return 5000
272
+
273
+
274
+ def get_graceful_degradation() -> bool:
275
+ """
276
+ .moai/config.json에서 graceful_degradation 설정 로드
277
+
278
+ Returns:
279
+ bool: graceful_degradation 설정값, 설정이 없으면 기본값 True 반환
280
+ """
281
+ try:
282
+ config_path = Path(".moai/config.json")
283
+ if not config_path.exists():
284
+ return True # 기본값
285
+
286
+ with open(config_path, 'r', encoding='utf-8') as f:
287
+ config = json.load(f)
288
+
289
+ # hooks 섹션에서 graceful_degradation 값 가져오기
290
+ hooks_config = config.get("hooks", {})
291
+ return hooks_config.get("graceful_degradation", True)
292
+ except (json.JSONDecodeError, FileNotFoundError, KeyError):
293
+ logger.warning("Failed to load graceful_degradation from config, using default True")
294
+ return True
@@ -0,0 +1,235 @@
1
+ # @CODE:PORTAL-LINK-001: 온라인 문서 링크 검증 유틸리티 | @TEST:PORTAL-LINK-001: 링크 검증 테스트
2
+
3
+ """
4
+ Link Validation Utilities
5
+ 온라인 문서 링크 검증 유틸리티
6
+ """
7
+
8
+ import asyncio
9
+ import logging
10
+ from dataclasses import dataclass
11
+ from datetime import datetime
12
+ from pathlib import Path
13
+ from typing import List, Optional
14
+
15
+ from moai_adk.utils.common import HTTPClient, create_report_path, extract_links_from_text, is_valid_url
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ @dataclass
21
+ class LinkResult:
22
+ """링크 검증 결과"""
23
+ url: str
24
+ status_code: int
25
+ is_valid: bool
26
+ response_time: float
27
+ error_message: Optional[str] = None
28
+ checked_at: datetime = None
29
+
30
+ def __post_init__(self):
31
+ if self.checked_at is None:
32
+ self.checked_at = datetime.now()
33
+
34
+
35
+ @dataclass
36
+ class ValidationResult:
37
+ """전체 검증 결과"""
38
+ total_links: int
39
+ valid_links: int
40
+ invalid_links: int
41
+ results: List[LinkResult]
42
+ completed_at: datetime = None
43
+
44
+ def __post_init__(self):
45
+ if self.completed_at is None:
46
+ self.completed_at = datetime.now()
47
+
48
+ @property
49
+ def success_rate(self) -> float:
50
+ """성공률 계산"""
51
+ if self.total_links == 0:
52
+ return 0.0
53
+ return (self.valid_links / self.total_links) * 100
54
+
55
+
56
+ class LinkValidator(HTTPClient):
57
+ """온라인 문서 링크 검증기"""
58
+
59
+ def __init__(self, max_concurrent: int = 5, timeout: int = 10):
60
+ super().__init__(max_concurrent, timeout)
61
+
62
+ def extract_links_from_file(self, file_path: Path) -> List[str]:
63
+ """파일에서 모든 링크 추출"""
64
+ if not file_path.exists():
65
+ logger.warning(f"파일이 존재하지 않습니다: {file_path}")
66
+ return []
67
+
68
+ try:
69
+ content = file_path.read_text(encoding='utf-8')
70
+ base_url = "https://adk.mo.ai.kr"
71
+ links = extract_links_from_text(content, base_url)
72
+ logger.info(f"파일에서 {len(links)}개의 링크를 발견했습니다: {file_path}")
73
+ return links
74
+ except Exception as e:
75
+ logger.error(f"링크 추출 중 오류 발생: {e}")
76
+ return []
77
+
78
+ async def validate_link(self, url: str) -> LinkResult:
79
+ """단일 링크 검증"""
80
+ try:
81
+ # URL 유효성 검사
82
+ if not is_valid_url(url):
83
+ return LinkResult(
84
+ url=url,
85
+ status_code=0,
86
+ is_valid=False,
87
+ response_time=0.0,
88
+ error_message="Invalid URL format"
89
+ )
90
+
91
+ # HTTP 요청
92
+ response = await self.fetch_url(url)
93
+
94
+ return LinkResult(
95
+ url=url,
96
+ status_code=response.status_code,
97
+ is_valid=response.success,
98
+ response_time=response.load_time,
99
+ error_message=response.error_message
100
+ )
101
+
102
+ except Exception as e:
103
+ return LinkResult(
104
+ url=url,
105
+ status_code=0,
106
+ is_valid=False,
107
+ response_time=0.0,
108
+ error_message=f"Unexpected error: {str(e)}"
109
+ )
110
+
111
+ async def validate_all_links(self, links: List[str]) -> ValidationResult:
112
+ """모든 링크 검증"""
113
+ results = []
114
+
115
+ # 링크 그룹으로 분할 (동시성 제어)
116
+ semaphore = asyncio.Semaphore(self.max_concurrent)
117
+
118
+ async def validate_with_semaphore(link: str):
119
+ async with semaphore:
120
+ result = await self.validate_link(link)
121
+ results.append(result)
122
+ # 진행 상황 로깅
123
+ logger.info(f"검증 완료: {link} -> {result.status_code} ({result.is_valid})")
124
+ return result
125
+
126
+ # 모든 링크를 비동기로 검증
127
+ tasks = [validate_with_semaphore(link) for link in links]
128
+ await asyncio.gather(*tasks)
129
+
130
+ # 결과 분석
131
+ valid_links = sum(1 for r in results if r.is_valid)
132
+ invalid_links = len(results) - valid_links
133
+
134
+ return ValidationResult(
135
+ total_links=len(results),
136
+ valid_links=valid_links,
137
+ invalid_links=invalid_links,
138
+ results=results,
139
+ completed_at=datetime.now()
140
+ )
141
+
142
+ def generate_report(self, validation_result: ValidationResult) -> str:
143
+ """검증 보고서 생성"""
144
+ from moai_adk.utils.common import get_summary_stats
145
+
146
+ report = []
147
+ report.append("# 온라인 문서 링크 검증 보고서")
148
+ report.append(f"**검증 시간**: {validation_result.completed_at.strftime('%Y-%m-%d %H:%M:%S')}")
149
+ report.append(f"**총 링크 수**: {validation_result.total_links}")
150
+ report.append(f"**유효한 링크**: {validation_result.valid_links}")
151
+ report.append(f"**유효하지 않은 링크**: {validation_result.invalid_links}")
152
+ report.append(f"**성공률**: {validation_result.success_rate:.1f}%")
153
+ report.append("")
154
+
155
+ # 통계 정보
156
+ if validation_result.results:
157
+ response_times = [r.response_time for r in validation_result.results]
158
+ stats = get_summary_stats(response_times)
159
+ report.append("## 📊 통계 정보")
160
+ report.append("")
161
+ report.append(f"- 평균 응답 시간: {stats['mean']:.2f}초")
162
+ report.append(f"- 최소 응답 시간: {stats['min']:.2f}초")
163
+ report.append(f"- 최대 응답 시간: {stats['max']:.2f}초")
164
+ report.append(f"- 표준편차: {stats['std']:.2f}초")
165
+ report.append("")
166
+
167
+ # 실패한 링크 상세 보고
168
+ if validation_result.invalid_links > 0:
169
+ report.append("## ❌ 실패한 링크")
170
+ report.append("")
171
+
172
+ for result in validation_result.results:
173
+ if not result.is_valid:
174
+ report.append(f"- **{result.url}**")
175
+ report.append(f" - 상태 코드: {result.status_code}")
176
+ report.append(f" - 응답 시간: {result.response_time:.2f}초")
177
+ if result.error_message:
178
+ report.append(f" - 오류: {result.error_message}")
179
+ report.append("")
180
+
181
+ # 성공한 링크 요약
182
+ if validation_result.valid_links > 0:
183
+ report.append("## ✅ 성공한 링크")
184
+ report.append("")
185
+ report.append(f"총 {validation_result.valid_links}개의 링크가 정상적으로 검증되었습니다.")
186
+
187
+ return "\n".join(report)
188
+
189
+
190
+ def validate_readme_links(readme_path: Path = None) -> ValidationResult:
191
+ """README 파일의 모든 링크 검증"""
192
+ if readme_path is None:
193
+ readme_path = Path("README.ko.md")
194
+
195
+ validator = LinkValidator(max_concurrent=3, timeout=8)
196
+
197
+ # README 파일에서 링크 추출
198
+ links = validator.extract_links_from_file(readme_path)
199
+
200
+ if not links:
201
+ logger.warning("검증할 링크가 없습니다")
202
+ return ValidationResult(
203
+ total_links=0,
204
+ valid_links=0,
205
+ invalid_links=0,
206
+ results=[]
207
+ )
208
+
209
+ logger.info(f"총 {len(links)}개의 링크를 검증합니다...")
210
+
211
+ # 비동기 검증 수행
212
+ result = asyncio.run(validator.validate_all_links(links))
213
+
214
+ # 보고서 생성 및 저장
215
+ report = validator.generate_report(result)
216
+ report_path = create_report_path(Path("."), "link_validation")
217
+ report_path.write_text(report, encoding='utf-8')
218
+ logger.info(f"보고서가 저장되었습니다: {report_path}")
219
+
220
+ return result
221
+
222
+
223
+ if __name__ == "__main__":
224
+ # README 파일 기준 링크 검증 실행
225
+ result = validate_readme_links()
226
+
227
+ # 결과 출력
228
+ validator = LinkValidator()
229
+ report = validator.generate_report(result)
230
+ print(report)
231
+
232
+ # 파일로 저장
233
+ report_path = Path("link_validation_report.md")
234
+ report_path.write_text(report, encoding='utf-8')
235
+ print(f"\n보고서가 저장되었습니다: {report_path}")
moai_adk/utils/logger.py CHANGED
@@ -1,4 +1,4 @@
1
- # @CODE:LOGGING-001 | SPEC: SPEC-LOGGING-001/spec.md | TEST: tests/unit/test_logger.py
1
+ # @CODE:LOGGER-MAIN-001 | SPEC: SPEC-LOGGING-001/spec.md | TEST: tests/unit/test_logger.py
2
2
  """
3
3
  Logging system built on Python's logging module
4
4
 
@@ -36,7 +36,7 @@ class SensitiveDataFilter(logging.Filter):
36
36
  API Key: ***REDACTED***
37
37
  """
38
38
 
39
- # @CODE:LOGGING-001:DOMAIN - Define sensitive data patterns
39
+ # @CODE:LOGGER-MAIN-001:DOMAIN - Define sensitive data patterns
40
40
  PATTERNS = [
41
41
  (r"sk-[a-zA-Z0-9]+", "***REDACTED***"), # API Key
42
42
  (r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", "***REDACTED***"), # Email
@@ -107,7 +107,7 @@ def setup_logger(
107
107
  - Sensitive data (API Key, Email, Password) is automatically masked.
108
108
  - Existing handlers are removed to prevent duplicates.
109
109
  """
110
- # @CODE:LOGGING-001:DOMAIN - Determine logging level
110
+ # @CODE:LOGGER-MAIN-001:DOMAIN - Determine logging level
111
111
  if level is None:
112
112
  env = os.getenv("MOAI_ENV", "").lower()
113
113
  level_map = {
@@ -117,31 +117,31 @@ def setup_logger(
117
117
  }
118
118
  level = level_map.get(env, logging.INFO)
119
119
 
120
- # @CODE:LOGGING-001:INFRA - Create and configure logger
120
+ # @CODE:LOGGER-MAIN-001:INFRA - Create and configure logger
121
121
  logger = logging.getLogger(name)
122
122
  logger.setLevel(level)
123
123
  logger.handlers.clear() # Remove existing handlers to avoid duplicates
124
124
 
125
- # @CODE:LOGGING-001:INFRA - Ensure log directory exists
125
+ # @CODE:LOGGER-MAIN-001:INFRA - Ensure log directory exists
126
126
  if log_dir is None:
127
127
  log_dir = ".moai/logs"
128
128
  log_path = Path(log_dir)
129
129
  log_path.mkdir(parents=True, exist_ok=True)
130
130
 
131
- # @CODE:LOGGING-001:INFRA - Define log format
131
+ # @CODE:LOGGER-MAIN-001:INFRA - Define log format
132
132
  formatter = logging.Formatter(
133
133
  fmt="[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s",
134
134
  datefmt="%Y-%m-%d %H:%M:%S",
135
135
  )
136
136
 
137
- # @CODE:LOGGING-001:INFRA - Console handler
137
+ # @CODE:LOGGER-MAIN-001:INFRA - Console handler
138
138
  console_handler = logging.StreamHandler()
139
139
  console_handler.setLevel(level)
140
140
  console_handler.setFormatter(formatter)
141
141
  console_handler.addFilter(SensitiveDataFilter())
142
142
  logger.addHandler(console_handler)
143
143
 
144
- # @CODE:LOGGING-001:INFRA - File handler
144
+ # @CODE:LOGGER-MAIN-001:INFRA - File handler
145
145
  log_file = log_path / "moai.log"
146
146
  file_handler = logging.FileHandler(log_file, encoding="utf-8")
147
147
  file_handler.setLevel(level)