moai-adk 0.15.0__py3-none-any.whl → 0.25.4__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 (417) hide show
  1. moai_adk/__init__.py +1 -2
  2. moai_adk/__main__.py +85 -2
  3. moai_adk/cli/__init__.py +0 -1
  4. moai_adk/cli/commands/__init__.py +0 -1
  5. moai_adk/cli/commands/analyze.py +127 -0
  6. moai_adk/cli/commands/backup.py +5 -3
  7. moai_adk/cli/commands/doctor.py +35 -11
  8. moai_adk/cli/commands/improve_user_experience.py +348 -0
  9. moai_adk/cli/commands/init.py +150 -23
  10. moai_adk/cli/commands/language.py +269 -0
  11. moai_adk/cli/commands/migrate.py +158 -0
  12. moai_adk/cli/commands/status.py +13 -12
  13. moai_adk/cli/commands/update.py +364 -60
  14. moai_adk/cli/commands/validate_links.py +118 -0
  15. moai_adk/cli/main.py +3 -2
  16. moai_adk/cli/prompts/init_prompts.py +79 -82
  17. moai_adk/core/__init__.py +0 -1
  18. moai_adk/core/analysis/__init__.py +9 -0
  19. moai_adk/core/analysis/session_analyzer.py +439 -0
  20. moai_adk/core/claude_integration.py +421 -0
  21. moai_adk/core/command_helpers.py +270 -0
  22. moai_adk/core/config/__init__.py +6 -0
  23. moai_adk/core/config/auto_spec_config.py +346 -0
  24. moai_adk/core/config/migration.py +133 -12
  25. moai_adk/core/context_manager.py +279 -0
  26. moai_adk/core/diagnostics/slash_commands.py +0 -1
  27. moai_adk/core/error_recovery_system.py +1289 -0
  28. moai_adk/core/git/__init__.py +0 -1
  29. moai_adk/core/git/branch.py +0 -1
  30. moai_adk/core/git/branch_manager.py +4 -4
  31. moai_adk/core/git/checkpoint.py +1 -5
  32. moai_adk/core/git/commit.py +0 -1
  33. moai_adk/core/git/event_detector.py +3 -5
  34. moai_adk/core/git/manager.py +0 -1
  35. moai_adk/core/hooks/post_tool_auto_spec_completion.py +925 -0
  36. moai_adk/core/integration/__init__.py +22 -0
  37. moai_adk/core/integration/engine.py +169 -0
  38. moai_adk/core/integration/integration_tester.py +225 -0
  39. moai_adk/core/integration/models.py +88 -0
  40. moai_adk/core/integration/utils.py +211 -0
  41. moai_adk/core/issue_creator.py +28 -18
  42. moai_adk/core/language_config.py +202 -0
  43. moai_adk/core/language_validator.py +556 -0
  44. moai_adk/core/mcp/setup.py +113 -0
  45. moai_adk/core/migration/__init__.py +18 -0
  46. moai_adk/core/migration/backup_manager.py +208 -0
  47. moai_adk/core/migration/file_migrator.py +218 -0
  48. moai_adk/core/migration/version_detector.py +143 -0
  49. moai_adk/core/migration/version_migrator.py +228 -0
  50. moai_adk/core/performance/__init__.py +6 -0
  51. moai_adk/core/performance/cache_system.py +318 -0
  52. moai_adk/core/performance/parallel_processor.py +116 -0
  53. moai_adk/core/project/__init__.py +0 -1
  54. moai_adk/core/project/backup_utils.py +2 -7
  55. moai_adk/core/project/checker.py +3 -3
  56. moai_adk/core/project/detector.py +20 -40
  57. moai_adk/core/project/initializer.py +42 -17
  58. moai_adk/core/project/phase_executor.py +415 -58
  59. moai_adk/core/project/validator.py +6 -25
  60. moai_adk/core/quality/__init__.py +1 -1
  61. moai_adk/core/quality/trust_checker.py +64 -110
  62. moai_adk/core/quality/validators/__init__.py +1 -1
  63. moai_adk/core/quality/validators/base_validator.py +1 -1
  64. moai_adk/core/rollback_manager.py +993 -0
  65. moai_adk/core/session_manager.py +667 -0
  66. moai_adk/core/spec/confidence_scoring.py +749 -0
  67. moai_adk/core/spec/ears_template_engine.py +1182 -0
  68. moai_adk/core/spec/quality_validator.py +721 -0
  69. moai_adk/core/spec_status_manager.py +488 -0
  70. moai_adk/core/template/__init__.py +0 -1
  71. moai_adk/core/template/backup.py +41 -1
  72. moai_adk/core/template/config.py +11 -12
  73. moai_adk/core/template/languages.py +0 -1
  74. moai_adk/core/template/merger.py +79 -22
  75. moai_adk/core/template/processor.py +614 -40
  76. moai_adk/core/template_engine.py +36 -27
  77. moai_adk/foundation/git/commit_templates.py +565 -0
  78. moai_adk/foundation/trust/trust_principles.py +725 -0
  79. moai_adk/foundation/trust/validation_checklist.py +1678 -0
  80. moai_adk/statusline/__init__.py +38 -0
  81. moai_adk/statusline/alfred_detector.py +107 -0
  82. moai_adk/statusline/config.py +364 -0
  83. moai_adk/statusline/enhanced_output_style_detector.py +364 -0
  84. moai_adk/statusline/git_collector.py +190 -0
  85. moai_adk/statusline/main.py +228 -0
  86. moai_adk/statusline/metrics_tracker.py +78 -0
  87. moai_adk/statusline/renderer.py +327 -0
  88. moai_adk/statusline/update_checker.py +135 -0
  89. moai_adk/statusline/version_reader.py +647 -0
  90. moai_adk/templates/.git-hooks/pre-commit +66 -0
  91. moai_adk/templates/.git-hooks/pre-push +116 -4
  92. moai_adk/templates/.github/workflows/moai-gitflow.yml +1 -7
  93. moai_adk/templates/.github/workflows/spec-issue-sync.yml +0 -1
  94. moai_adk/templates/.gitignore +44 -0
  95. moai_adk/templates/.mcp.json +22 -0
  96. moai_adk/templates/CLAUDE.md +450 -1071
  97. moai_adk/utils/__init__.py +0 -1
  98. moai_adk/utils/banner.py +0 -1
  99. moai_adk/utils/common.py +308 -0
  100. moai_adk/utils/link_validator.py +249 -0
  101. moai_adk/utils/logger.py +4 -9
  102. moai_adk/utils/safe_file_reader.py +210 -0
  103. moai_adk/utils/user_experience.py +531 -0
  104. moai_adk-0.25.4.dist-info/METADATA +2279 -0
  105. moai_adk-0.25.4.dist-info/RECORD +112 -0
  106. moai_adk/core/tags/__init__.py +0 -86
  107. moai_adk/core/tags/ci_validator.py +0 -463
  108. moai_adk/core/tags/cli.py +0 -283
  109. moai_adk/core/tags/generator.py +0 -109
  110. moai_adk/core/tags/inserter.py +0 -99
  111. moai_adk/core/tags/mapper.py +0 -126
  112. moai_adk/core/tags/parser.py +0 -76
  113. moai_adk/core/tags/pre_commit_validator.py +0 -393
  114. moai_adk/core/tags/reporter.py +0 -956
  115. moai_adk/core/tags/tags.py +0 -149
  116. moai_adk/core/tags/validator.py +0 -897
  117. moai_adk/templates/.claude/agents/alfred/backend-expert.md +0 -319
  118. moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -316
  119. moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -208
  120. moai_adk/templates/.claude/agents/alfred/devops-expert.md +0 -464
  121. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -214
  122. moai_adk/templates/.claude/agents/alfred/frontend-expert.md +0 -357
  123. moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -406
  124. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -423
  125. moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -312
  126. moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -343
  127. moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -865
  128. moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -392
  129. moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -361
  130. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -428
  131. moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -375
  132. moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +0 -571
  133. moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1525
  134. moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -802
  135. moai_adk/templates/.claude/commands/alfred/2-run.md +0 -709
  136. moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -1009
  137. moai_adk/templates/.claude/commands/alfred/9-feedback.md +0 -149
  138. moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -748
  139. moai_adk/templates/.claude/hooks/alfred/core/timeout.py +0 -136
  140. moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +0 -108
  141. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +0 -198
  142. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -29
  143. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +0 -94
  144. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +0 -100
  145. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +0 -94
  146. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +0 -94
  147. moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +0 -170
  148. moai_adk/templates/.claude/hooks/alfred/shared/core/checkpoint.py +0 -271
  149. moai_adk/templates/.claude/hooks/alfred/shared/core/context.py +0 -67
  150. moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +0 -749
  151. moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +0 -230
  152. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +0 -198
  153. moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +0 -21
  154. moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +0 -154
  155. moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +0 -174
  156. moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +0 -87
  157. moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +0 -61
  158. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +0 -112
  159. moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +0 -1
  160. moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +0 -161
  161. moai_adk/templates/.claude/settings.json +0 -144
  162. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +0 -70
  163. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +0 -62
  164. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/reference.md +0 -242
  165. moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +0 -56
  166. moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +0 -28
  167. moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +0 -444
  168. moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +0 -62
  169. moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +0 -28
  170. moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +0 -405
  171. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +0 -51
  172. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +0 -355
  173. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +0 -239
  174. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
  175. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
  176. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
  177. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +0 -323
  178. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +0 -286
  179. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +0 -126
  180. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
  181. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
  182. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
  183. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +0 -74
  184. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +0 -4
  185. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +0 -269
  186. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
  187. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
  188. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
  189. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +0 -19
  190. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +0 -4
  191. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +0 -150
  192. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
  193. moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
  194. moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
  195. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +0 -198
  196. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +0 -431
  197. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +0 -141
  198. moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +0 -89
  199. moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +0 -122
  200. moai_adk/templates/.claude/skills/moai-alfred-practices/reference.md +0 -369
  201. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +0 -508
  202. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +0 -481
  203. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +0 -100
  204. moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +0 -273
  205. moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +0 -77
  206. moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +0 -265
  207. moai_adk/templates/.claude/skills/moai-alfred-rules/reference.md +0 -539
  208. moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +0 -19
  209. moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +0 -4
  210. moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +0 -84
  211. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +0 -137
  212. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +0 -219
  213. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples/validate-spec.sh +0 -161
  214. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +0 -541
  215. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +0 -622
  216. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +0 -115
  217. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +0 -4
  218. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +0 -348
  219. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
  220. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
  221. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
  222. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
  223. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
  224. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
  225. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +0 -19
  226. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +0 -4
  227. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +0 -211
  228. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
  229. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
  230. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
  231. moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +0 -288
  232. moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
  233. moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
  234. moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
  235. moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
  236. moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
  237. moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
  238. moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
  239. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
  240. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
  241. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
  242. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
  243. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
  244. moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
  245. moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
  246. moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
  247. moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
  248. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +0 -19
  249. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +0 -4
  250. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/reference.md +0 -218
  251. moai_adk/templates/.claude/skills/moai-cc-skill-factory/CHECKLIST.md +0 -482
  252. moai_adk/templates/.claude/skills/moai-cc-skill-factory/EXAMPLES.md +0 -278
  253. moai_adk/templates/.claude/skills/moai-cc-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
  254. moai_adk/templates/.claude/skills/moai-cc-skill-factory/METADATA.md +0 -477
  255. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
  256. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
  257. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
  258. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
  259. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL.md +0 -271
  260. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
  261. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STRUCTURE.md +0 -583
  262. moai_adk/templates/.claude/skills/moai-cc-skill-factory/WEB-RESEARCH.md +0 -526
  263. moai_adk/templates/.claude/skills/moai-cc-skill-factory/reference.md +0 -465
  264. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/generate-structure.sh +0 -328
  265. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/validate-skill.sh +0 -312
  266. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
  267. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/examples-template.md +0 -285
  268. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/reference-template.md +0 -278
  269. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/scripts-template.sh +0 -303
  270. moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
  271. moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
  272. moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +0 -802
  273. moai_adk/templates/.claude/skills/moai-design-systems/examples.md +0 -1238
  274. moai_adk/templates/.claude/skills/moai-design-systems/reference.md +0 -673
  275. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +0 -290
  276. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +0 -1633
  277. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +0 -660
  278. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
  279. moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
  280. moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
  281. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
  282. moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
  283. moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
  284. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +0 -123
  285. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +0 -29
  286. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +0 -30
  287. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
  288. moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
  289. moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
  290. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +0 -128
  291. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +0 -29
  292. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +0 -31
  293. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
  294. moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
  295. moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
  296. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
  297. moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
  298. moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
  299. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
  300. moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
  301. moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
  302. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
  303. moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
  304. moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
  305. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
  306. moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
  307. moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
  308. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
  309. moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
  310. moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
  311. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
  312. moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
  313. moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
  314. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
  315. moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
  316. moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
  317. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -116
  318. moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
  319. moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
  320. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
  321. moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
  322. moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
  323. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
  324. moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
  325. moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
  326. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
  327. moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
  328. moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
  329. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
  330. moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
  331. moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
  332. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
  333. moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
  334. moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
  335. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
  336. moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
  337. moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
  338. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +0 -124
  339. moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
  340. moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
  341. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +0 -123
  342. moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
  343. moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
  344. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
  345. moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
  346. moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
  347. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +0 -127
  348. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +0 -29
  349. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +0 -31
  350. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +0 -126
  351. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +0 -29
  352. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +0 -31
  353. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
  354. moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
  355. moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
  356. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +0 -124
  357. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +0 -29
  358. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +0 -31
  359. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +0 -126
  360. moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
  361. moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
  362. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +0 -433
  363. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +0 -624
  364. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +0 -316
  365. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +0 -123
  366. moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
  367. moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
  368. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +0 -124
  369. moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
  370. moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
  371. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +0 -127
  372. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +0 -29
  373. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +0 -31
  374. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +0 -125
  375. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +0 -29
  376. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +0 -30
  377. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
  378. moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
  379. moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
  380. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
  381. moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
  382. moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
  383. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +0 -123
  384. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +0 -29
  385. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +0 -30
  386. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +0 -133
  387. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +0 -29
  388. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +0 -34
  389. moai_adk/templates/.claude/skills/moai-project-documentation.md +0 -622
  390. moai_adk/templates/.github/workflows/c-tag-validation.yml +0 -11
  391. moai_adk/templates/.github/workflows/cpp-tag-validation.yml +0 -11
  392. moai_adk/templates/.github/workflows/csharp-tag-validation.yml +0 -11
  393. moai_adk/templates/.github/workflows/dart-tag-validation.yml +0 -11
  394. moai_adk/templates/.github/workflows/go-tag-validation.yml +0 -130
  395. moai_adk/templates/.github/workflows/java-tag-validation.yml +0 -11
  396. moai_adk/templates/.github/workflows/javascript-tag-validation.yml +0 -135
  397. moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +0 -11
  398. moai_adk/templates/.github/workflows/php-tag-validation.yml +0 -11
  399. moai_adk/templates/.github/workflows/python-tag-validation.yml +0 -118
  400. moai_adk/templates/.github/workflows/release.yml +0 -118
  401. moai_adk/templates/.github/workflows/ruby-tag-validation.yml +0 -11
  402. moai_adk/templates/.github/workflows/rust-tag-validation.yml +0 -11
  403. moai_adk/templates/.github/workflows/shell-tag-validation.yml +0 -11
  404. moai_adk/templates/.github/workflows/swift-tag-validation.yml +0 -11
  405. moai_adk/templates/.github/workflows/tag-report.yml +0 -269
  406. moai_adk/templates/.github/workflows/tag-validation.yml +0 -186
  407. moai_adk/templates/.github/workflows/typescript-tag-validation.yml +0 -154
  408. moai_adk/templates/.moai/config.json +0 -115
  409. moai_adk/templates/workflows/go-tag-validation.yml +0 -30
  410. moai_adk/templates/workflows/javascript-tag-validation.yml +0 -41
  411. moai_adk/templates/workflows/python-tag-validation.yml +0 -42
  412. moai_adk/templates/workflows/typescript-tag-validation.yml +0 -31
  413. moai_adk-0.15.0.dist-info/METADATA +0 -3079
  414. moai_adk-0.15.0.dist-info/RECORD +0 -365
  415. {moai_adk-0.15.0.dist-info → moai_adk-0.25.4.dist-info}/WHEEL +0 -0
  416. {moai_adk-0.15.0.dist-info → moai_adk-0.25.4.dist-info}/entry_points.txt +0 -0
  417. {moai_adk-0.15.0.dist-info → moai_adk-0.25.4.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,3 @@
1
- # @CODE:LOGGING-001 | SPEC: SPEC-LOGGING-001/spec.md | TEST: tests/unit/test_logger.py
2
1
  """
3
2
  MoAI-ADK utility module
4
3
  """
moai_adk/utils/banner.py CHANGED
@@ -1,4 +1,3 @@
1
- # @CODE:UTILS-001 | SPEC: SPEC-CLI-001/spec.md
2
1
  """ASCII banner module
3
2
 
4
3
  Render the MoAI-ADK ASCII art banner
@@ -0,0 +1,308 @@
1
+ """
2
+ Common Utilities
3
+ Common utility functions
4
+ """
5
+
6
+ import asyncio
7
+ import json
8
+ import logging
9
+ import re
10
+ from dataclasses import dataclass, field
11
+ from datetime import datetime
12
+ from pathlib import Path
13
+ from typing import Dict, List, Optional
14
+ from urllib.parse import urlparse
15
+
16
+ import aiohttp
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ @dataclass
22
+ class HTTPResponse:
23
+ """HTTP response data"""
24
+
25
+ status_code: int
26
+ url: str
27
+ load_time: float
28
+ success: bool
29
+ error_message: Optional[str] = None
30
+ timestamp: datetime = field(default_factory=datetime.now)
31
+
32
+ def __post_init__(self):
33
+ if self.timestamp is None:
34
+ self.timestamp = datetime.now()
35
+
36
+
37
+ class HTTPClient:
38
+ """HTTP client utility"""
39
+
40
+ def __init__(self, max_concurrent: int = 5, timeout: int = 10):
41
+ self.max_concurrent = max_concurrent
42
+ self.timeout = timeout
43
+ self.session: Optional[aiohttp.ClientSession] = None
44
+
45
+ async def __aenter__(self):
46
+ """Async context manager entry"""
47
+ connector = aiohttp.TCPConnector(limit=self.max_concurrent)
48
+ timeout = aiohttp.ClientTimeout(total=self.timeout)
49
+ self.session = aiohttp.ClientSession(
50
+ connector=connector,
51
+ timeout=timeout,
52
+ headers={
53
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
54
+ },
55
+ )
56
+ return self
57
+
58
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
59
+ """Async context manager exit"""
60
+ if self.session:
61
+ await self.session.close()
62
+
63
+ async def fetch_url(self, url: str) -> HTTPResponse:
64
+ """Fetch single URL"""
65
+ try:
66
+ if self.session is None:
67
+ return HTTPResponse(
68
+ status_code=0,
69
+ url=url,
70
+ load_time=0,
71
+ success=False,
72
+ error_message="Session not initialized",
73
+ )
74
+ start_time = asyncio.get_event_loop().time()
75
+ async with self.session.get(url, allow_redirects=True) as response:
76
+ load_time = asyncio.get_event_loop().time() - start_time
77
+ success = 200 <= response.status < 300
78
+ return HTTPResponse(
79
+ status_code=response.status,
80
+ url=str(response.url),
81
+ load_time=load_time,
82
+ success=success,
83
+ )
84
+ except asyncio.TimeoutError:
85
+ return HTTPResponse(
86
+ status_code=0,
87
+ url=url,
88
+ load_time=self.timeout,
89
+ success=False,
90
+ error_message="Request timeout",
91
+ )
92
+ except aiohttp.ClientError as e:
93
+ return HTTPResponse(
94
+ status_code=0,
95
+ url=url,
96
+ load_time=0.0,
97
+ success=False,
98
+ error_message=f"HTTP client error: {str(e)}",
99
+ )
100
+ except Exception as e:
101
+ return HTTPResponse(
102
+ status_code=0,
103
+ url=url,
104
+ load_time=0.0,
105
+ success=False,
106
+ error_message=f"Unexpected error: {str(e)}",
107
+ )
108
+
109
+ async def fetch_urls(self, urls: List[str]) -> List[HTTPResponse]:
110
+ """Fetch multiple URLs concurrently"""
111
+ async with self:
112
+ tasks = [self.fetch_url(url) for url in urls]
113
+ return await asyncio.gather(*tasks)
114
+
115
+
116
+ def extract_links_from_text(text: str, base_url: Optional[str] = None) -> List[str]:
117
+ """Extract links from text"""
118
+ links = []
119
+
120
+ # Markdown link pattern: [text](url)
121
+ markdown_pattern = r"\[([^\]]+)\]\(([^)]+)\)"
122
+ markdown_matches = re.findall(markdown_pattern, text)
123
+
124
+ for match in markdown_matches:
125
+ url = match[1]
126
+ # Convert relative URLs to absolute URLs
127
+ if url.startswith(("http://", "https://")):
128
+ links.append(url)
129
+ elif base_url and url.startswith("/"):
130
+ links.append(f"{base_url}{url}")
131
+ elif base_url and not url.startswith(("http://", "https://", "#")):
132
+ links.append(f"{base_url}/{url.rstrip('/')}")
133
+
134
+ # General URL pattern
135
+ url_pattern = r'https?://[^\s<>"\'()]+'
136
+ url_matches = re.findall(url_pattern, text)
137
+ links.extend(url_matches)
138
+
139
+ logger.info(f"Found {len(links)} links in text")
140
+ return list(set(links)) # Remove duplicates
141
+
142
+
143
+ def is_valid_url(url: str) -> bool:
144
+ """Validate URL"""
145
+ try:
146
+ result = urlparse(url)
147
+ return all([result.scheme, result.netloc])
148
+ except Exception:
149
+ return False
150
+
151
+
152
+ def create_report_path(base_path: Path, suffix: str = "report") -> Path:
153
+ """Create report file path"""
154
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
155
+ filename = f"{suffix}_{timestamp}.md"
156
+ return base_path / filename
157
+
158
+
159
+ def format_duration(seconds: float) -> str:
160
+ """Convert time (seconds) to readable format"""
161
+ if seconds < 1:
162
+ return f"{seconds*1000:.0f}ms"
163
+ elif seconds < 60:
164
+ return f"{seconds:.1f}s"
165
+ elif seconds < 3600:
166
+ minutes = int(seconds // 60)
167
+ remaining_seconds = seconds % 60
168
+ return f"{minutes}m {remaining_seconds:.0f}s"
169
+ else:
170
+ hours = int(seconds // 3600)
171
+ remaining_minutes = int((seconds % 3600) // 60)
172
+ return f"{hours}h {remaining_minutes}m"
173
+
174
+
175
+ def calculate_score(
176
+ values: List[float], weights: Optional[List[float]] = None
177
+ ) -> float:
178
+ """Calculate weighted average score"""
179
+ if not values:
180
+ return 0.0
181
+
182
+ if weights is None:
183
+ weights = [1.0] * len(values)
184
+
185
+ if len(values) != len(weights):
186
+ raise ValueError("Values and weights must have the same length")
187
+
188
+ weighted_sum = sum(v * w for v, w in zip(values, weights))
189
+ total_weight = sum(weights)
190
+
191
+ return weighted_sum / total_weight if total_weight > 0 else 0.0
192
+
193
+
194
+ def get_summary_stats(numbers: List[float]) -> Dict[str, float]:
195
+ """Calculate basic statistics"""
196
+ if not numbers:
197
+ return {"mean": 0.0, "min": 0.0, "max": 0.0, "std": 0.0}
198
+
199
+ mean = sum(numbers) / len(numbers)
200
+ min_val = min(numbers)
201
+ max_val = max(numbers)
202
+
203
+ # Calculate standard deviation
204
+ if len(numbers) > 1:
205
+ variance = sum((x - mean) ** 2 for x in numbers) / (len(numbers) - 1)
206
+ std_dev = variance**0.5
207
+ else:
208
+ std_dev = 0.0
209
+
210
+ return {"mean": mean, "min": min_val, "max": max_val, "std": std_dev}
211
+
212
+
213
+ class RateLimiter:
214
+ """Request rate limiter"""
215
+
216
+ def __init__(self, max_requests: int = 10, time_window: int = 60):
217
+ self.max_requests = max_requests
218
+ self.time_window = time_window
219
+ self.requests: List[datetime] = []
220
+
221
+ def can_make_request(self) -> bool:
222
+ """Check if request can be made"""
223
+ now = datetime.now()
224
+
225
+ # Remove old requests
226
+ self.requests = [
227
+ req_time
228
+ for req_time in self.requests
229
+ if (now - req_time).total_seconds() < self.time_window
230
+ ]
231
+
232
+ return len(self.requests) < self.max_requests
233
+
234
+ def add_request(self):
235
+ """Add request record"""
236
+ if self.can_make_request():
237
+ self.requests.append(datetime.now())
238
+ else:
239
+ raise RateLimitError(
240
+ f"Rate limit exceeded: {self.max_requests} requests per {self.time_window}s"
241
+ )
242
+
243
+ async def wait_if_needed(self):
244
+ """Wait until request can be made"""
245
+ if not self.can_make_request():
246
+ oldest_request = min(self.requests)
247
+ wait_time = (
248
+ self.time_window - (datetime.now() - oldest_request).total_seconds()
249
+ )
250
+ if wait_time > 0:
251
+ logger.info(f"Rate limiting: waiting {wait_time:.1f}s")
252
+ await asyncio.sleep(wait_time)
253
+
254
+
255
+ class RateLimitError(Exception):
256
+ """Rate limit error"""
257
+
258
+ pass
259
+
260
+
261
+ def load_hook_timeout() -> int:
262
+ """
263
+ Load Hook timeout setting from .moai/config/config.json
264
+
265
+ Returns:
266
+ int: timeout value (milliseconds), returns default 5000 if not configured
267
+ """
268
+ try:
269
+ config_path = Path(".moai/config/config.json")
270
+ if not config_path.exists():
271
+ return 5000 # Default value
272
+
273
+ with open(config_path, "r", encoding="utf-8") as f:
274
+ config = json.load(f)
275
+
276
+ # Get timeout_ms value from hooks section
277
+ hooks_config = config.get("hooks", {})
278
+ timeout_ms = hooks_config.get("timeout_ms", 5000)
279
+
280
+ return int(timeout_ms)
281
+ except (json.JSONDecodeError, FileNotFoundError, KeyError, ValueError):
282
+ logger.warning("Failed to load hook timeout from config, using default 5000ms")
283
+ return 5000
284
+
285
+
286
+ def get_graceful_degradation() -> bool:
287
+ """
288
+ Load graceful_degradation setting from .moai/config/config.json
289
+
290
+ Returns:
291
+ bool: graceful_degradation setting value, returns default True if not configured
292
+ """
293
+ try:
294
+ config_path = Path(".moai/config/config.json")
295
+ if not config_path.exists():
296
+ return True # Default value
297
+
298
+ with open(config_path, "r", encoding="utf-8") as f:
299
+ config = json.load(f)
300
+
301
+ # Get graceful_degradation value from hooks section
302
+ hooks_config = config.get("hooks", {})
303
+ return hooks_config.get("graceful_degradation", True)
304
+ except (json.JSONDecodeError, FileNotFoundError, KeyError):
305
+ logger.warning(
306
+ "Failed to load graceful_degradation from config, using default True"
307
+ )
308
+ return True
@@ -0,0 +1,249 @@
1
+ """
2
+ Link Validation Utilities
3
+ Online documentation link validation utilities
4
+ """
5
+
6
+ import asyncio
7
+ import logging
8
+ from dataclasses import dataclass, field
9
+ from datetime import datetime
10
+ from pathlib import Path
11
+ from typing import List, Optional
12
+
13
+ from moai_adk.utils.common import (
14
+ HTTPClient,
15
+ create_report_path,
16
+ extract_links_from_text,
17
+ is_valid_url,
18
+ )
19
+ from moai_adk.utils.safe_file_reader import SafeFileReader
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ @dataclass
25
+ class LinkResult:
26
+ """Link validation result"""
27
+
28
+ url: str
29
+ status_code: int
30
+ is_valid: bool
31
+ response_time: float
32
+ error_message: Optional[str] = None
33
+ checked_at: datetime = field(default_factory=datetime.now)
34
+
35
+ def __post_init__(self):
36
+ if self.checked_at is None:
37
+ self.checked_at = datetime.now()
38
+
39
+
40
+ @dataclass
41
+ class ValidationResult:
42
+ """Overall validation result"""
43
+
44
+ total_links: int
45
+ valid_links: int
46
+ invalid_links: int
47
+ results: List[LinkResult]
48
+ completed_at: datetime = field(default_factory=datetime.now)
49
+
50
+ def __post_init__(self):
51
+ if self.completed_at is None:
52
+ self.completed_at = datetime.now()
53
+
54
+ @property
55
+ def success_rate(self) -> float:
56
+ """Calculate success rate"""
57
+ if self.total_links == 0:
58
+ return 0.0
59
+ return (self.valid_links / self.total_links) * 100
60
+
61
+
62
+ class LinkValidator(HTTPClient):
63
+ """Online documentation link validator"""
64
+
65
+ def __init__(self, max_concurrent: int = 5, timeout: int = 10):
66
+ super().__init__(max_concurrent, timeout)
67
+
68
+ def extract_links_from_file(self, file_path: Path) -> List[str]:
69
+ """Extract all links from file (using safe file reading)"""
70
+ if not file_path.exists():
71
+ logger.warning(f"File does not exist: {file_path}")
72
+ return []
73
+
74
+ try:
75
+ reader = SafeFileReader()
76
+ content = reader.read_text(file_path)
77
+ if content is None:
78
+ logger.error(f"Unable to read file: {file_path}")
79
+ return []
80
+
81
+ base_url = "https://adk.mo.ai.kr"
82
+ links = extract_links_from_text(content, base_url)
83
+ logger.info(f"Found {len(links)} links in file: {file_path}")
84
+ return links
85
+ except Exception as e:
86
+ logger.error(f"Error during link extraction: {e}")
87
+ return []
88
+
89
+ async def validate_link(self, url: str) -> LinkResult:
90
+ """Validate single link"""
91
+ try:
92
+ # URL validity check
93
+ if not is_valid_url(url):
94
+ return LinkResult(
95
+ url=url,
96
+ status_code=0,
97
+ is_valid=False,
98
+ response_time=0.0,
99
+ error_message="Invalid URL format",
100
+ )
101
+
102
+ # HTTP request
103
+ response = await self.fetch_url(url)
104
+
105
+ return LinkResult(
106
+ url=url,
107
+ status_code=response.status_code,
108
+ is_valid=response.success,
109
+ response_time=response.load_time,
110
+ error_message=response.error_message,
111
+ )
112
+
113
+ except Exception as e:
114
+ return LinkResult(
115
+ url=url,
116
+ status_code=0,
117
+ is_valid=False,
118
+ response_time=0.0,
119
+ error_message=f"Unexpected error: {str(e)}",
120
+ )
121
+
122
+ async def validate_all_links(self, links: List[str]) -> ValidationResult:
123
+ """Validate all links"""
124
+ results = []
125
+
126
+ # Split into link groups (concurrency control)
127
+ semaphore = asyncio.Semaphore(self.max_concurrent)
128
+
129
+ async def validate_with_semaphore(link: str):
130
+ async with semaphore:
131
+ result = await self.validate_link(link)
132
+ results.append(result)
133
+ # Log progress
134
+ logger.info(
135
+ f"Validation complete: {link} -> {result.status_code} ({result.is_valid})"
136
+ )
137
+ return result
138
+
139
+ # Validate all links asynchronously
140
+ tasks = [validate_with_semaphore(link) for link in links]
141
+ await asyncio.gather(*tasks)
142
+
143
+ # Analyze results
144
+ valid_links = sum(1 for r in results if r.is_valid)
145
+ invalid_links = len(results) - valid_links
146
+
147
+ return ValidationResult(
148
+ total_links=len(results),
149
+ valid_links=valid_links,
150
+ invalid_links=invalid_links,
151
+ results=results,
152
+ completed_at=datetime.now(),
153
+ )
154
+
155
+ def generate_report(self, validation_result: ValidationResult) -> str:
156
+ """Generate validation report"""
157
+ from moai_adk.utils.common import get_summary_stats
158
+
159
+ report = []
160
+ report.append("# Online Documentation Link Validation Report")
161
+ report.append(
162
+ f"**Validation Time**: {validation_result.completed_at.strftime('%Y-%m-%d %H:%M:%S')}"
163
+ )
164
+ report.append(f"**Total Links**: {validation_result.total_links}")
165
+ report.append(f"**Valid Links**: {validation_result.valid_links}")
166
+ report.append(f"**Invalid Links**: {validation_result.invalid_links}")
167
+ report.append(f"**Success Rate**: {validation_result.success_rate:.1f}%")
168
+ report.append("")
169
+
170
+ # Statistics
171
+ if validation_result.results:
172
+ response_times = [r.response_time for r in validation_result.results]
173
+ stats = get_summary_stats(response_times)
174
+ report.append("## 📊 Statistics")
175
+ report.append("")
176
+ report.append(f"- Average Response Time: {stats['mean']:.2f}s")
177
+ report.append(f"- Minimum Response Time: {stats['min']:.2f}s")
178
+ report.append(f"- Maximum Response Time: {stats['max']:.2f}s")
179
+ report.append(f"- Standard Deviation: {stats['std']:.2f}s")
180
+ report.append("")
181
+
182
+ # Failed links detailed report
183
+ if validation_result.invalid_links > 0:
184
+ report.append("## ❌ Failed Links")
185
+ report.append("")
186
+
187
+ for result in validation_result.results:
188
+ if not result.is_valid:
189
+ report.append(f"- **{result.url}**")
190
+ report.append(f" - Status Code: {result.status_code}")
191
+ report.append(f" - Response Time: {result.response_time:.2f}s")
192
+ if result.error_message:
193
+ report.append(f" - Error: {result.error_message}")
194
+ report.append("")
195
+
196
+ # Successful links summary
197
+ if validation_result.valid_links > 0:
198
+ report.append("## ✅ Successful Links")
199
+ report.append("")
200
+ report.append(
201
+ f"Total of {validation_result.valid_links} links validated successfully."
202
+ )
203
+
204
+ return "\n".join(report)
205
+
206
+
207
+ def validate_readme_links(readme_path: Optional[Path] = None) -> ValidationResult:
208
+ """Validate all links in README file"""
209
+ if readme_path is None:
210
+ readme_path = Path("README.ko.md")
211
+
212
+ validator = LinkValidator(max_concurrent=3, timeout=8)
213
+
214
+ # Extract links from README file
215
+ links = validator.extract_links_from_file(readme_path)
216
+
217
+ if not links:
218
+ logger.warning("No links to validate")
219
+ return ValidationResult(
220
+ total_links=0, valid_links=0, invalid_links=0, results=[]
221
+ )
222
+
223
+ logger.info(f"Validating total of {len(links)} links...")
224
+
225
+ # Perform asynchronous validation
226
+ result = asyncio.run(validator.validate_all_links(links))
227
+
228
+ # Generate and save report
229
+ report = validator.generate_report(result)
230
+ report_path = create_report_path(Path("."), "link_validation")
231
+ report_path.write_text(report, encoding="utf-8")
232
+ logger.info(f"Report saved to: {report_path}")
233
+
234
+ return result
235
+
236
+
237
+ if __name__ == "__main__":
238
+ # Execute README file link validation
239
+ result = validate_readme_links()
240
+
241
+ # Print results
242
+ validator = LinkValidator()
243
+ report = validator.generate_report(result)
244
+ print(report)
245
+
246
+ # Save to file
247
+ report_path = Path("link_validation_report.md")
248
+ report_path.write_text(report, encoding="utf-8")
249
+ print(f"\nReport saved to: {report_path}")
moai_adk/utils/logger.py CHANGED
@@ -1,4 +1,3 @@
1
- # @CODE:LOGGING-001 | SPEC: SPEC-LOGGING-001/spec.md | TEST: tests/unit/test_logger.py
2
1
  """
3
2
  Logging system built on Python's logging module
4
3
 
@@ -36,10 +35,12 @@ class SensitiveDataFilter(logging.Filter):
36
35
  API Key: ***REDACTED***
37
36
  """
38
37
 
39
- # @CODE:LOGGING-001:DOMAIN - Define sensitive data patterns
40
38
  PATTERNS = [
41
39
  (r"sk-[a-zA-Z0-9]+", "***REDACTED***"), # API Key
42
- (r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", "***REDACTED***"), # Email
40
+ (
41
+ r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
42
+ "***REDACTED***",
43
+ ), # Email
43
44
  (r"(?i)(password|passwd|pwd)[\s:=]+\S+", r"\1: ***REDACTED***"), # Password
44
45
  ]
45
46
 
@@ -107,7 +108,6 @@ def setup_logger(
107
108
  - Sensitive data (API Key, Email, Password) is automatically masked.
108
109
  - Existing handlers are removed to prevent duplicates.
109
110
  """
110
- # @CODE:LOGGING-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,26 @@ 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
121
120
  logger = logging.getLogger(name)
122
121
  logger.setLevel(level)
123
122
  logger.handlers.clear() # Remove existing handlers to avoid duplicates
124
123
 
125
- # @CODE:LOGGING-001:INFRA - Ensure log directory exists
126
124
  if log_dir is None:
127
125
  log_dir = ".moai/logs"
128
126
  log_path = Path(log_dir)
129
127
  log_path.mkdir(parents=True, exist_ok=True)
130
128
 
131
- # @CODE:LOGGING-001:INFRA - Define log format
132
129
  formatter = logging.Formatter(
133
130
  fmt="[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s",
134
131
  datefmt="%Y-%m-%d %H:%M:%S",
135
132
  )
136
133
 
137
- # @CODE:LOGGING-001:INFRA - Console handler
138
134
  console_handler = logging.StreamHandler()
139
135
  console_handler.setLevel(level)
140
136
  console_handler.setFormatter(formatter)
141
137
  console_handler.addFilter(SensitiveDataFilter())
142
138
  logger.addHandler(console_handler)
143
139
 
144
- # @CODE:LOGGING-001:INFRA - File handler
145
140
  log_file = log_path / "moai.log"
146
141
  file_handler = logging.FileHandler(log_file, encoding="utf-8")
147
142
  file_handler.setLevel(level)