moai-adk 0.25.4__py3-none-any.whl → 0.32.8__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 (378) hide show
  1. moai_adk/__init__.py +2 -5
  2. moai_adk/__main__.py +114 -82
  3. moai_adk/cli/__init__.py +6 -1
  4. moai_adk/cli/commands/__init__.py +1 -3
  5. moai_adk/cli/commands/analyze.py +5 -16
  6. moai_adk/cli/commands/doctor.py +6 -18
  7. moai_adk/cli/commands/init.py +56 -125
  8. moai_adk/cli/commands/language.py +14 -35
  9. moai_adk/cli/commands/status.py +9 -15
  10. moai_adk/cli/commands/update.py +1555 -190
  11. moai_adk/cli/prompts/init_prompts.py +112 -56
  12. moai_adk/cli/spec_status.py +263 -0
  13. moai_adk/cli/ui/__init__.py +44 -0
  14. moai_adk/cli/ui/progress.py +422 -0
  15. moai_adk/cli/ui/prompts.py +389 -0
  16. moai_adk/cli/ui/theme.py +129 -0
  17. moai_adk/cli/worktree/__init__.py +27 -0
  18. moai_adk/cli/worktree/__main__.py +31 -0
  19. moai_adk/cli/worktree/cli.py +672 -0
  20. moai_adk/cli/worktree/exceptions.py +89 -0
  21. moai_adk/cli/worktree/manager.py +490 -0
  22. moai_adk/cli/worktree/models.py +65 -0
  23. moai_adk/cli/worktree/registry.py +128 -0
  24. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  25. moai_adk/core/analysis/session_analyzer.py +17 -56
  26. moai_adk/core/claude_integration.py +26 -54
  27. moai_adk/core/command_helpers.py +10 -10
  28. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  29. moai_adk/core/config/auto_spec_config.py +5 -11
  30. moai_adk/core/config/migration.py +19 -9
  31. moai_adk/core/config/unified.py +436 -0
  32. moai_adk/core/context_manager.py +6 -12
  33. moai_adk/core/enterprise_features.py +1404 -0
  34. moai_adk/core/error_recovery_system.py +725 -112
  35. moai_adk/core/event_driven_hook_system.py +1371 -0
  36. moai_adk/core/git/__init__.py +8 -0
  37. moai_adk/core/git/branch_manager.py +3 -11
  38. moai_adk/core/git/checkpoint.py +1 -3
  39. moai_adk/core/git/conflict_detector.py +413 -0
  40. moai_adk/core/git/manager.py +91 -1
  41. moai_adk/core/hooks/post_tool_auto_spec_completion.py +56 -80
  42. moai_adk/core/input_validation_middleware.py +1006 -0
  43. moai_adk/core/integration/engine.py +6 -18
  44. moai_adk/core/integration/integration_tester.py +10 -9
  45. moai_adk/core/integration/utils.py +1 -1
  46. moai_adk/core/issue_creator.py +10 -28
  47. moai_adk/core/jit_context_loader.py +956 -0
  48. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  49. moai_adk/core/language_config_resolver.py +485 -0
  50. moai_adk/core/language_validator.py +28 -41
  51. moai_adk/core/mcp/setup.py +15 -12
  52. moai_adk/core/merge/__init__.py +9 -0
  53. moai_adk/core/merge/analyzer.py +481 -0
  54. moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
  55. moai_adk/core/migration/backup_manager.py +78 -9
  56. moai_adk/core/migration/custom_element_scanner.py +358 -0
  57. moai_adk/core/migration/file_migrator.py +8 -17
  58. moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
  59. moai_adk/core/migration/selective_restorer.py +470 -0
  60. moai_adk/core/migration/template_utils.py +74 -0
  61. moai_adk/core/migration/user_selection_ui.py +338 -0
  62. moai_adk/core/migration/version_detector.py +6 -10
  63. moai_adk/core/migration/version_migrator.py +3 -3
  64. moai_adk/core/performance/cache_system.py +8 -10
  65. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  66. moai_adk/core/project/checker.py +2 -4
  67. moai_adk/core/project/detector.py +1 -3
  68. moai_adk/core/project/initializer.py +135 -23
  69. moai_adk/core/project/phase_executor.py +54 -81
  70. moai_adk/core/project/validator.py +6 -12
  71. moai_adk/core/quality/trust_checker.py +9 -27
  72. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  73. moai_adk/core/robust_json_parser.py +611 -0
  74. moai_adk/core/rollback_manager.py +73 -148
  75. moai_adk/core/session_manager.py +10 -26
  76. moai_adk/core/skill_loading_system.py +579 -0
  77. moai_adk/core/spec/confidence_scoring.py +31 -100
  78. moai_adk/core/spec/ears_template_engine.py +351 -286
  79. moai_adk/core/spec/quality_validator.py +35 -69
  80. moai_adk/core/spec_status_manager.py +64 -74
  81. moai_adk/core/template/backup.py +45 -20
  82. moai_adk/core/template/config.py +112 -39
  83. moai_adk/core/template/merger.py +11 -19
  84. moai_adk/core/template/processor.py +253 -149
  85. moai_adk/core/template_engine.py +73 -40
  86. moai_adk/core/template_variable_synchronizer.py +417 -0
  87. moai_adk/core/unified_permission_manager.py +745 -0
  88. moai_adk/core/user_behavior_analytics.py +851 -0
  89. moai_adk/core/version_sync.py +429 -0
  90. moai_adk/foundation/__init__.py +56 -0
  91. moai_adk/foundation/backend.py +1027 -0
  92. moai_adk/foundation/database.py +1115 -0
  93. moai_adk/foundation/devops.py +1585 -0
  94. moai_adk/foundation/ears.py +431 -0
  95. moai_adk/foundation/frontend.py +870 -0
  96. moai_adk/foundation/git/commit_templates.py +4 -12
  97. moai_adk/foundation/git.py +376 -0
  98. moai_adk/foundation/langs.py +484 -0
  99. moai_adk/foundation/ml_ops.py +1162 -0
  100. moai_adk/foundation/testing.py +1524 -0
  101. moai_adk/foundation/trust/trust_principles.py +23 -72
  102. moai_adk/foundation/trust/validation_checklist.py +57 -162
  103. moai_adk/project/__init__.py +0 -0
  104. moai_adk/project/configuration.py +1084 -0
  105. moai_adk/project/documentation.py +566 -0
  106. moai_adk/project/schema.py +447 -0
  107. moai_adk/statusline/alfred_detector.py +1 -3
  108. moai_adk/statusline/config.py +13 -4
  109. moai_adk/statusline/enhanced_output_style_detector.py +23 -15
  110. moai_adk/statusline/main.py +51 -15
  111. moai_adk/statusline/renderer.py +104 -48
  112. moai_adk/statusline/update_checker.py +3 -9
  113. moai_adk/statusline/version_reader.py +140 -46
  114. moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
  115. moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
  116. moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
  117. moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
  118. moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
  119. moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
  120. moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
  121. moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
  122. moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
  123. moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
  124. moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
  125. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
  126. moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
  127. moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
  128. moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
  129. moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
  130. moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
  131. moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
  132. moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
  133. moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
  134. moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
  135. moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
  136. moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
  137. moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
  138. moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
  139. moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
  140. moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
  141. moai_adk/templates/.claude/commands/moai/3-sync.md +993 -0
  142. moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
  143. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  144. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  145. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
  146. moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
  147. moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
  148. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
  149. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  150. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  151. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
  152. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
  153. moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
  154. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
  155. moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
  156. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  157. moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
  158. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
  159. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
  160. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +921 -0
  161. moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
  162. moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
  163. moai_adk/templates/.claude/settings.json +172 -0
  164. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -0
  165. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
  166. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
  167. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  168. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
  169. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
  170. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +319 -0
  171. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +320 -0
  172. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  173. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  174. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  175. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  176. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +496 -0
  177. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -0
  178. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  179. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  180. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  181. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
  182. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  183. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  184. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  185. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +491 -0
  186. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
  187. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  188. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  189. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  190. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  191. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  192. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +201 -0
  193. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  194. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
  195. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
  196. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  197. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  198. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  199. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
  200. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
  201. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  202. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  203. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  204. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  205. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  206. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  207. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +438 -0
  208. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -0
  209. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  210. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +346 -0
  211. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  212. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
  213. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  214. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  215. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  216. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
  217. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  218. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
  219. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +362 -0
  220. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  221. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  222. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  223. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  224. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  225. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  226. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  227. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  228. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  229. moai_adk/templates/.claude/skills/moai-integration-mcp/SKILL.md +352 -0
  230. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
  231. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
  232. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
  233. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
  234. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
  235. moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
  236. moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
  237. moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
  238. moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
  239. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -0
  240. moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
  241. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  242. moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
  243. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  244. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +316 -0
  245. moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
  246. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  247. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
  248. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
  249. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  250. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  251. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  252. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  253. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  254. moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
  255. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +370 -0
  256. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  257. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  258. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  259. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  260. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  261. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  262. moai_adk/templates/.claude/skills/moai-platform-baas/README.md +186 -0
  263. moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
  264. moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
  265. moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
  266. moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
  267. moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
  268. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
  269. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
  270. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
  271. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  272. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -0
  273. moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
  274. moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
  275. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
  276. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
  277. moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
  278. moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +135 -0
  279. moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
  280. moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
  281. moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
  282. moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
  283. moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
  284. moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
  285. moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
  286. moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
  287. moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
  288. moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
  289. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  290. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -0
  291. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  292. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  293. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  294. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +71 -0
  295. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  296. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  297. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  298. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  299. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  300. moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
  301. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +374 -0
  302. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  303. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  304. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  305. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  306. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -0
  307. moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
  308. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  309. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  310. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  311. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  312. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
  313. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
  314. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
  315. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
  316. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
  317. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
  318. moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
  319. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  320. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  321. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  322. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  323. moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +410 -0
  324. moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
  325. moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
  326. moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
  327. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
  328. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
  329. moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
  330. moai_adk/templates/.git-hooks/pre-commit +103 -41
  331. moai_adk/templates/.git-hooks/pre-push +116 -21
  332. moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
  333. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  334. moai_adk/templates/.gitignore +184 -44
  335. moai_adk/templates/.mcp.json +7 -9
  336. moai_adk/templates/.moai/cache/personalization.json +10 -0
  337. moai_adk/templates/.moai/config/config.yaml +344 -0
  338. moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
  339. moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
  340. moai_adk/templates/.moai/config/presets/team.yaml +33 -0
  341. moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
  342. moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
  343. moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
  344. moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
  345. moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
  346. moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
  347. moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -0
  348. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  349. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  350. moai_adk/templates/.moai/config/sections/quality.yaml +15 -0
  351. moai_adk/templates/.moai/config/sections/system.yaml +14 -0
  352. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  353. moai_adk/templates/.moai/config/statusline-config.yaml +86 -0
  354. moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
  355. moai_adk/templates/CLAUDE.md +382 -501
  356. moai_adk/utils/__init__.py +24 -1
  357. moai_adk/utils/banner.py +7 -10
  358. moai_adk/utils/common.py +16 -30
  359. moai_adk/utils/link_validator.py +4 -12
  360. moai_adk/utils/safe_file_reader.py +2 -6
  361. moai_adk/utils/timeout.py +160 -0
  362. moai_adk/utils/toon_utils.py +256 -0
  363. moai_adk/version.py +22 -0
  364. moai_adk-0.32.8.dist-info/METADATA +2478 -0
  365. moai_adk-0.32.8.dist-info/RECORD +396 -0
  366. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
  367. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
  368. moai_adk/cli/commands/backup.py +0 -82
  369. moai_adk/cli/commands/improve_user_experience.py +0 -348
  370. moai_adk/cli/commands/migrate.py +0 -158
  371. moai_adk/cli/commands/validate_links.py +0 -118
  372. moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -413
  373. moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
  374. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
  375. moai_adk/utils/user_experience.py +0 -531
  376. moai_adk-0.25.4.dist-info/METADATA +0 -2279
  377. moai_adk-0.25.4.dist-info/RECORD +0 -112
  378. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,921 @@
1
+ #!/usr/bin/env python3
2
+ # SessionStart Hook: Enhanced Project Information
3
+ """SessionStart Hook: Enhanced Project Information
4
+
5
+ Claude Code Event: SessionStart
6
+ Purpose: Display enhanced project status with Git info, test status, and SPEC progress
7
+ Execution: Triggered automatically when Claude Code session begins
8
+
9
+ Enhanced Features:
10
+ - Optimized timeout handling with unified manager
11
+ - Efficient Git operations with connection pooling and caching
12
+ - Enhanced error handling with graceful degradation
13
+ - Resource monitoring and cleanup
14
+ - Risk assessment with performance metrics
15
+ """
16
+
17
+ import json
18
+ import logging
19
+ import sys
20
+ from datetime import datetime
21
+ from pathlib import Path
22
+ from typing import Any, Dict
23
+
24
+ # Setup import path for shared modules
25
+ HOOKS_DIR = Path(__file__).parent
26
+ LIB_DIR = HOOKS_DIR / "lib"
27
+ if str(LIB_DIR) not in sys.path:
28
+ sys.path.insert(0, str(LIB_DIR))
29
+
30
+ # Import path utils for project root resolution
31
+ from lib.path_utils import find_project_root # noqa: E402
32
+
33
+ # Import unified timeout manager and Git operations manager
34
+ try:
35
+ from lib.git_operations_manager import GitOperationType, get_git_manager
36
+ from lib.timeout import TimeoutError as PlatformTimeoutError
37
+ from lib.unified_timeout_manager import (
38
+ HookTimeoutConfig,
39
+ HookTimeoutError,
40
+ TimeoutPolicy,
41
+ get_timeout_manager,
42
+ hook_timeout_context,
43
+ )
44
+ except ImportError:
45
+ # Fallback implementations if new modules not available
46
+
47
+ def get_timeout_manager():
48
+ return None
49
+
50
+ def hook_timeout_context(hook_name, config=None):
51
+ import contextlib
52
+
53
+ @contextlib.contextmanager
54
+ def dummy_context():
55
+ yield
56
+
57
+ return dummy_context()
58
+
59
+ class HookTimeoutConfig: # type: ignore[no-redef]
60
+ def __init__(self, **kwargs):
61
+ pass
62
+
63
+ class TimeoutPolicy: # type: ignore[no-redef]
64
+ FAST = "fast"
65
+ NORMAL = "normal"
66
+ SLOW = "slow"
67
+
68
+ class HookTimeoutError(Exception): # type: ignore[no-redef]
69
+ pass
70
+
71
+ def get_git_manager():
72
+ return None
73
+
74
+ class GitOperationType: # type: ignore[no-redef]
75
+ BRANCH = "branch"
76
+ LOG = "log"
77
+ STATUS = "status"
78
+
79
+ class PlatformTimeoutError(Exception): # type: ignore[no-redef]
80
+ pass
81
+
82
+
83
+ # Import config cache
84
+ try:
85
+ from core.config_cache import get_cached_config, get_cached_spec_progress
86
+ except ImportError:
87
+ # Fallback to direct functions if cache not available
88
+ import yaml as yaml_fallback
89
+
90
+ def get_cached_config():
91
+ # FIX: Use absolute path from find_project_root() to ensure correct directory
92
+ project_root = find_project_root()
93
+ config_path = project_root / ".moai" / "config" / "config.yaml"
94
+ if config_path.exists():
95
+ try:
96
+ return yaml_fallback.safe_load(config_path.read_text()) or {}
97
+ except (yaml_fallback.YAMLError, OSError, UnicodeDecodeError):
98
+ # YAML parsing, file read, or encoding errors
99
+ return None
100
+ return None
101
+
102
+ def get_cached_spec_progress():
103
+ """Get SPEC progress information - FIXED to use YAML frontmatter parsing"""
104
+ # FIX #3: Use absolute path from find_project_root() to ensure current project only
105
+ project_root = find_project_root()
106
+ specs_dir = project_root / ".moai" / "specs"
107
+
108
+ if not specs_dir.exists():
109
+ return {"completed": 0, "total": 0, "percentage": 0}
110
+ try:
111
+ # Only scan SPEC folders in THIS project's .moai/specs/ directory
112
+ spec_folders = [d for d in specs_dir.iterdir() if d.is_dir() and d.name.startswith("SPEC-")]
113
+ total = len(spec_folders)
114
+
115
+ # FIX: Parse YAML frontmatter to check for status: completed
116
+ completed = 0
117
+ for folder in spec_folders:
118
+ spec_file = folder / "spec.md"
119
+ if not spec_file.exists():
120
+ continue
121
+
122
+ try:
123
+ # Read spec.md content
124
+ content = spec_file.read_text(encoding="utf-8")
125
+
126
+ # Parse YAML frontmatter (between --- delimiters)
127
+ if content.startswith("---"):
128
+ yaml_end = content.find("---", 3)
129
+ if yaml_end > 0:
130
+ yaml_content = content[3:yaml_end]
131
+ # Check for status: completed (with or without quotes)
132
+ if "status: completed" in yaml_content or 'status: "completed"' in yaml_content:
133
+ completed += 1
134
+ except (OSError, UnicodeDecodeError):
135
+ # File read failure or encoding error - considered incomplete
136
+ pass
137
+
138
+ percentage = (completed / total * 100) if total > 0 else 0
139
+ return {
140
+ "completed": completed,
141
+ "total": total,
142
+ "percentage": round(percentage, 0),
143
+ }
144
+ except (OSError, PermissionError):
145
+ # Directory access or permission errors
146
+ return {"completed": 0, "total": 0, "percentage": 0}
147
+
148
+
149
+ def should_show_setup_messages() -> bool:
150
+ """Determine whether to show setup completion messages (cached version).
151
+
152
+ Logic:
153
+ 1. Read .moai/config/config.json (using cache)
154
+ 2. Check session.suppress_setup_messages flag
155
+ 3. If suppress_setup_messages is False, always show messages
156
+ 4. If suppress_setup_messages is True:
157
+ - Check if more than 7 days have passed since suppression
158
+ - Show messages if time threshold exceeded
159
+
160
+ Uses ConfigCache to avoid repeated config file reads.
161
+
162
+ Returns:
163
+ bool: True if messages should be shown, False otherwise
164
+ """
165
+ config = get_cached_config()
166
+
167
+ # If config doesn't exist, show messages
168
+ if not config:
169
+ return True
170
+
171
+ # Check project initialization status
172
+ if not config.get("project", {}).get("initialized", False):
173
+ return True
174
+
175
+ # Check suppress_setup_messages flag
176
+ session_config = config.get("session", {})
177
+ suppress = session_config.get("suppress_setup_messages", False)
178
+
179
+ if not suppress:
180
+ # Flag is False, show messages
181
+ return True
182
+
183
+ # Flag is True, check time threshold (7 days)
184
+ suppressed_at_str = session_config.get("setup_messages_suppressed_at")
185
+ if not suppressed_at_str:
186
+ # No timestamp recorded, show messages
187
+ return True
188
+
189
+ try:
190
+ suppressed_at = datetime.fromisoformat(suppressed_at_str)
191
+ now = datetime.now(suppressed_at.tzinfo) if suppressed_at.tzinfo else datetime.now()
192
+ days_passed = (now - suppressed_at).days
193
+
194
+ # Show messages if more than 7 days have passed
195
+ return days_passed >= 7
196
+ except (ValueError, TypeError):
197
+ # If timestamp is invalid, show messages
198
+ return True
199
+
200
+
201
+ def check_git_initialized() -> bool:
202
+ """Check if git repository is initialized
203
+
204
+ Returns:
205
+ bool: True if .git directory exists, False otherwise
206
+ """
207
+ try:
208
+ project_root = find_project_root()
209
+ git_dir = project_root / ".git"
210
+ return git_dir.exists() and git_dir.is_dir()
211
+ except Exception:
212
+ return False
213
+
214
+
215
+ def get_git_info() -> Dict[str, Any]:
216
+ """Get comprehensive git information using optimized Git operations manager
217
+
218
+ FIXED: Handles git not initialized state properly
219
+ - Branch: Shows helpful message if git not initialized
220
+ - Last Commit: Shows helpful message if git not initialized or no commits
221
+
222
+ Uses connection pooling, caching, and parallel execution for optimal performance.
223
+ Falls back to basic implementation if Git manager unavailable.
224
+ """
225
+ # FIX #1 and #4: Check if git is initialized first
226
+ if not check_git_initialized():
227
+ return {
228
+ "branch": "Git not initialized → Run 'moai-adk init' to set up Git repository",
229
+ "last_commit": "Git not initialized → Run 'moai-adk init' to set up Git repository",
230
+ "commit_time": "",
231
+ "changes": 0,
232
+ "git_initialized": False,
233
+ }
234
+
235
+ git_manager = get_git_manager()
236
+ if git_manager:
237
+ try:
238
+ # Use optimized Git manager
239
+ project_info = git_manager.get_project_info(use_cache=True)
240
+ branch = project_info.get("branch", "unknown")
241
+ last_commit = project_info.get("last_commit", "unknown")
242
+
243
+ # FIX #1: Handle empty branch (no commits yet)
244
+ if not branch or branch == "unknown":
245
+ branch = "No commits yet → Make your first commit"
246
+
247
+ # FIX #4: Handle no commits case
248
+ if not last_commit or last_commit == "unknown":
249
+ last_commit = "No commits yet"
250
+
251
+ return {
252
+ "branch": branch,
253
+ "last_commit": last_commit,
254
+ "commit_time": project_info.get("commit_time", "unknown"),
255
+ "changes": project_info.get("changes", 0),
256
+ "fetch_time": project_info.get("fetch_time", ""),
257
+ "git_initialized": True,
258
+ }
259
+ except Exception as e:
260
+ logging.warning(f"Git manager failed, falling back: {e}")
261
+
262
+ # Fallback to basic Git operations
263
+ try:
264
+ from concurrent.futures import ThreadPoolExecutor, as_completed
265
+
266
+ # Define git commands to run in parallel
267
+ git_commands = [
268
+ (["git", "branch", "--show-current"], "branch"),
269
+ (["git", "log", "--pretty=format:%h %s", "-1"], "last_commit"),
270
+ (["git", "log", "--pretty=format:%ar", "-1"], "commit_time"),
271
+ (["git", "status", "--porcelain"], "changes_raw"),
272
+ ]
273
+
274
+ # Execute git commands in parallel
275
+ results = {}
276
+ with ThreadPoolExecutor(max_workers=4) as executor:
277
+ # Submit all tasks
278
+ futures = {executor.submit(_run_git_command_fallback, cmd): key for cmd, key in git_commands}
279
+
280
+ # Collect results as they complete
281
+ for future in as_completed(futures):
282
+ key = futures[future]
283
+ try:
284
+ results[key] = future.result()
285
+ except (TimeoutError, RuntimeError):
286
+ # Future execution timeout or runtime errors
287
+ results[key] = ""
288
+
289
+ # Process results with proper handling for empty values
290
+ branch = results.get("branch", "")
291
+ last_commit = results.get("last_commit", "")
292
+
293
+ # FIX #1: Handle empty branch (no commits yet)
294
+ if not branch:
295
+ branch = "No commits yet → Make your first commit"
296
+
297
+ # FIX #4: Handle no commits case
298
+ if not last_commit:
299
+ last_commit = "No commits yet"
300
+
301
+ return {
302
+ "branch": branch,
303
+ "last_commit": last_commit,
304
+ "commit_time": results.get("commit_time", ""),
305
+ "changes": (len(results.get("changes_raw", "").splitlines()) if results.get("changes_raw") else 0),
306
+ "git_initialized": True,
307
+ }
308
+
309
+ except (RuntimeError, OSError, TimeoutError):
310
+ # ThreadPoolExecutor, git command, or timeout errors
311
+ return {
312
+ "branch": "Error reading git info",
313
+ "last_commit": "Error reading git info",
314
+ "commit_time": "",
315
+ "changes": 0,
316
+ "git_initialized": True,
317
+ }
318
+
319
+
320
+ def _run_git_command_fallback(cmd: list[str]) -> str:
321
+ """Fallback git command execution"""
322
+ try:
323
+ import subprocess
324
+
325
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=3)
326
+ return result.stdout.strip() if result.returncode == 0 else ""
327
+ except (
328
+ subprocess.TimeoutExpired,
329
+ subprocess.SubprocessError,
330
+ FileNotFoundError,
331
+ OSError,
332
+ ):
333
+ # Git command timeout, subprocess error, or git not found
334
+ return ""
335
+
336
+
337
+ def get_git_strategy_info(config: dict) -> dict:
338
+ """Get git strategy information from config
339
+
340
+ FIX #2: NEW FEATURE - Display git strategy information
341
+
342
+ Args:
343
+ config: Configuration dictionary
344
+
345
+ Returns:
346
+ Dictionary with git_flow and auto_branch information
347
+ """
348
+ if not config:
349
+ return {"git_flow": "unknown", "auto_branch": "unknown"}
350
+
351
+ git_strategy = config.get("git_strategy", {})
352
+ mode = git_strategy.get("mode", "manual")
353
+
354
+ # Get auto_branch setting from branch_creation config
355
+ branch_creation = git_strategy.get("branch_creation", {})
356
+ auto_enabled = branch_creation.get("auto_enabled", False)
357
+
358
+ # Determine auto_branch display
359
+ auto_branch_display = "Yes" if auto_enabled else "No"
360
+
361
+ return {"git_flow": mode, "auto_branch": auto_branch_display}
362
+
363
+
364
+ def _parse_version(version_str: str) -> tuple[int, ...]:
365
+ """Parse version string to comparable tuple
366
+
367
+ Args:
368
+ version_str: Version string (e.g., "0.25.4")
369
+
370
+ Returns:
371
+ Tuple of integers for comparison (e.g., (0, 25, 4))
372
+ """
373
+ try:
374
+ import re
375
+
376
+ clean = version_str.lstrip("v")
377
+ parts = [int(x) for x in re.split(r"[^\d]+", clean) if x.isdigit()]
378
+ return tuple(parts) if parts else (0,)
379
+ except (ValueError, AttributeError, TypeError):
380
+ # Version parsing errors (invalid format, None input, type mismatch)
381
+ return (0,)
382
+
383
+
384
+ def _is_newer_version(newer: str, older: str) -> bool:
385
+ """Compare two versions (semantic versioning)
386
+
387
+ Args:
388
+ newer: Version that might be newer
389
+ older: Version that might be older
390
+
391
+ Returns:
392
+ True if newer > older
393
+ """
394
+ newer_parts = _parse_version(newer)
395
+ older_parts = _parse_version(older)
396
+ return newer_parts > older_parts
397
+
398
+
399
+ def check_version_update() -> tuple[str, bool]:
400
+ """Check if version update is available (fast version using cached data)
401
+
402
+ Reuses PyPI cache from Phase 1 (config_health_check.py).
403
+ Falls back to importlib.metadata for installed version.
404
+
405
+ Returns:
406
+ (status_indicator, has_update)
407
+ - status_indicator: "(latest)", "(dev)" or "⬆️ X.X.X available"
408
+ - has_update: True if update available
409
+ """
410
+ try:
411
+ import importlib.metadata
412
+
413
+ # Get installed version (fast, ~6ms)
414
+ try:
415
+ installed_version = importlib.metadata.version("moai-adk")
416
+ except importlib.metadata.PackageNotFoundError:
417
+ return "(latest)", False
418
+
419
+ # Try to load cached PyPI version from Phase 1
420
+ version_cache_file = find_project_root() / ".moai" / "cache" / "version-check.json"
421
+ latest_version = None
422
+
423
+ if version_cache_file.exists():
424
+ try:
425
+ cache_data = json.loads(version_cache_file.read_text())
426
+ latest_version = cache_data.get("latest")
427
+ except (json.JSONDecodeError, OSError, UnicodeDecodeError):
428
+ # Cache file read or JSON parsing errors
429
+ pass
430
+
431
+ # If no cache or cache is stale, skip check (avoid slow subprocess)
432
+ if not latest_version:
433
+ return "(latest)", False
434
+
435
+ # Compare versions with semantic versioning
436
+ if _is_newer_version(latest_version, installed_version):
437
+ # PyPI has newer version (use update icon instead of warning)
438
+ return f"⬆️ {latest_version} available", True
439
+ elif _is_newer_version(installed_version, latest_version):
440
+ # Local version is newer (development version)
441
+ return "(dev)", False
442
+ else:
443
+ # Same version
444
+ return "(latest)", False
445
+
446
+ except (ImportError, AttributeError, TypeError):
447
+ # Import errors or unexpected type/attribute errors
448
+ return "(latest)", False
449
+
450
+
451
+ def get_test_info() -> dict[str, Any]:
452
+ """Get test coverage and status information
453
+
454
+ NOTE: SessionStart hook must complete quickly (<0.5s).
455
+ Running pytest is too slow (5+ seconds), so we skip it and return unknown status.
456
+ Users can run tests manually with: pytest --cov
457
+
458
+ To check test status, use: /moai:test-status (future feature)
459
+ """
460
+ # Skip pytest execution - it's too slow for SessionStart
461
+ return {"coverage": "unknown", "status": "❓"}
462
+
463
+
464
+ def get_spec_progress() -> dict[str, Any]:
465
+ """Get SPEC progress information (cached version)
466
+
467
+ Uses ConfigCache to avoid repeated filesystem scans.
468
+ Cache is valid for 5 minutes or until .moai/specs/ is modified.
469
+
470
+ Returns:
471
+ Dict with keys: completed, total, percentage
472
+ """
473
+ return get_cached_spec_progress()
474
+
475
+
476
+ def calculate_risk(git_info: dict, spec_progress: dict, test_info: dict) -> str:
477
+ """Calculate overall project risk level"""
478
+ risk_score = 0
479
+
480
+ # Git changes contribute to risk
481
+ if git_info["changes"] > 20:
482
+ risk_score += 10
483
+ elif git_info["changes"] > 10:
484
+ risk_score += 5
485
+
486
+ # SPEC progress contributes to risk
487
+ if spec_progress["percentage"] < 50:
488
+ risk_score += 15
489
+ elif spec_progress["percentage"] < 80:
490
+ risk_score += 8
491
+
492
+ # Test status contributes to risk
493
+ if test_info["status"] != "✅":
494
+ risk_score += 12
495
+ elif test_info["coverage"] == "unknown":
496
+ risk_score += 5
497
+
498
+ # Determine risk level
499
+ if risk_score >= 20:
500
+ return "HIGH"
501
+ elif risk_score >= 10:
502
+ return "MEDIUM"
503
+ else:
504
+ return "LOW"
505
+
506
+
507
+ def format_project_metadata() -> str:
508
+ """Format project metadata information as a string.
509
+
510
+ Returns:
511
+ Formatted project metadata string with version and Git info
512
+ """
513
+ moai_version = "unknown"
514
+ config = get_cached_config()
515
+ if config:
516
+ moai_version = config.get("moai", {}).get("version", "unknown")
517
+
518
+ version_status, _has_update = check_version_update()
519
+ return f"📦 Version: {moai_version} {version_status}"
520
+
521
+
522
+ def get_language_info(config: dict) -> dict:
523
+ """Get language configuration information
524
+
525
+ Args:
526
+ config: Configuration dictionary
527
+
528
+ Returns:
529
+ Dictionary with language info including display name and status
530
+ """
531
+ if not config:
532
+ return {
533
+ "conversation_language": "en",
534
+ "language_name": "English",
535
+ "status": "⚠️ No config",
536
+ }
537
+
538
+ lang_config = config.get("language", {})
539
+ conversation_lang = lang_config.get("conversation_language", "en")
540
+ lang_name = lang_config.get("conversation_language_name", "Unknown")
541
+
542
+ # Language status indicator (removed Active indicator for cleaner output)
543
+ return {"conversation_language": conversation_lang, "language_name": lang_name}
544
+
545
+
546
+ def load_user_personalization() -> dict:
547
+ """Load user personalization settings using centralized language configuration resolver
548
+
549
+ FIX #5: Check for template variables and provide setup guidance
550
+
551
+ Uses the new LanguageConfigResolver which provides:
552
+ - Environment variable priority handling
553
+ - Configuration file integration
554
+ - Consistency validation and auto-correction
555
+ - Template variable export capabilities
556
+
557
+ Returns:
558
+ Dictionary with user personalization information
559
+ """
560
+ try:
561
+ # Import the centralized language configuration resolver
562
+ from src.moai_adk.core.language_config_resolver import get_resolver
563
+
564
+ # Get resolver instance and resolve configuration
565
+ resolver = get_resolver(str(find_project_root()))
566
+ config = resolver.resolve_config()
567
+
568
+ # FIX #5: Check if USER_NAME is a template variable or empty
569
+ user_name = config.get("user_name", "")
570
+ has_valid_name = user_name and not user_name.startswith("{{") and not user_name.endswith("}}")
571
+
572
+ # Build personalization info using resolved configuration
573
+ personalization = {
574
+ "user_name": user_name if has_valid_name else "",
575
+ "conversation_language": config.get("conversation_language", "en"),
576
+ "conversation_language_name": config.get("conversation_language_name", "English"),
577
+ "agent_prompt_language": config.get("agent_prompt_language", "en"),
578
+ "is_korean": config.get("conversation_language") == "ko",
579
+ "has_personalization": has_valid_name,
580
+ "config_source": config.get("config_source", "default"),
581
+ "personalized_greeting": (resolver.get_personalized_greeting(config) if has_valid_name else ""),
582
+ "needs_setup": not has_valid_name, # FIX #5: Flag for setup guidance
583
+ }
584
+
585
+ # Export template variables for other system components
586
+ template_vars = resolver.export_template_variables(config)
587
+
588
+ # Store resolved configuration for session-wide access
589
+ personalization_cache_file = find_project_root() / ".moai" / "cache" / "personalization.json"
590
+ try:
591
+ personalization_cache_file.parent.mkdir(parents=True, exist_ok=True)
592
+
593
+ # Store both personalization info and template variables
594
+ cache_data = {
595
+ "personalization": personalization,
596
+ "template_variables": template_vars,
597
+ "resolved_at": datetime.now().isoformat(),
598
+ "config_source": config.get("config_source", "default"),
599
+ }
600
+ personalization_cache_file.write_text(json.dumps(cache_data, ensure_ascii=False, indent=2))
601
+
602
+ except (OSError, PermissionError):
603
+ # Cache write errors are non-critical
604
+ pass
605
+
606
+ return personalization
607
+
608
+ except ImportError:
609
+ # Fallback to basic implementation if resolver not available
610
+ import os
611
+
612
+ # Load config from cache or direct file
613
+ config = get_cached_config()
614
+
615
+ # Environment variables take priority
616
+ user_name = os.getenv("MOAI_USER_NAME")
617
+ conversation_lang = os.getenv("MOAI_CONVERSATION_LANG")
618
+
619
+ # Fallback to config file if environment variables not set
620
+ if user_name is None and config:
621
+ user_name = config.get("user", {}).get("name", "")
622
+
623
+ if conversation_lang is None and config:
624
+ conversation_lang = config.get("language", {}).get("conversation_language", "en")
625
+
626
+ # FIX #5: Check if USER_NAME is a template variable or empty
627
+ has_valid_name = user_name and not user_name.startswith("{{") and not user_name.endswith("}}")
628
+
629
+ # Get language name
630
+ lang_name_map = {
631
+ "ko": "Korean",
632
+ "en": "English",
633
+ "ja": "Japanese",
634
+ "zh": "Chinese",
635
+ "es": "Spanish",
636
+ "fr": "French",
637
+ "de": "German",
638
+ "ru": "Russian",
639
+ }
640
+ lang_name = lang_name_map.get(conversation_lang, "Unknown")
641
+
642
+ # Build personalization info
643
+ personalization = {
644
+ "user_name": user_name if has_valid_name else "",
645
+ "conversation_language": conversation_lang or "en",
646
+ "conversation_language_name": lang_name,
647
+ "is_korean": conversation_lang == "ko",
648
+ "has_personalization": has_valid_name,
649
+ "config_source": "fallback",
650
+ "personalized_greeting": (
651
+ f"{user_name}님"
652
+ if has_valid_name and conversation_lang == "ko"
653
+ else user_name
654
+ if has_valid_name
655
+ else ""
656
+ ),
657
+ "needs_setup": not has_valid_name, # FIX #5: Flag for setup guidance
658
+ }
659
+
660
+ # Store for session-wide access
661
+ personalization_cache_file = find_project_root() / ".moai" / "cache" / "personalization.json"
662
+ try:
663
+ personalization_cache_file.parent.mkdir(parents=True, exist_ok=True)
664
+ personalization_cache_file.write_text(json.dumps(personalization, ensure_ascii=False, indent=2))
665
+ except (OSError, PermissionError):
666
+ # Cache write errors are non-critical
667
+ pass
668
+
669
+ return personalization
670
+
671
+
672
+ def format_session_output() -> str:
673
+ """Format the complete session start output with proper line alignment (optimized).
674
+
675
+ Uses caches for config and SPEC progress to minimize file I/O.
676
+ Parallel git command execution for fast data gathering.
677
+ """
678
+ # Gather information (in parallel for git, cached for config/SPEC)
679
+ git_info = get_git_info()
680
+
681
+ # Get config for language and version info
682
+ config = get_cached_config()
683
+
684
+ # Load user personalization settings
685
+ personalization = load_user_personalization()
686
+
687
+ # Get MoAI version from installed package (not config.json)
688
+ try:
689
+ from moai_adk import __version__ as installed_version
690
+
691
+ moai_version = installed_version
692
+ except ImportError:
693
+ # Fallback to config version if package import fails
694
+ moai_version = "unknown"
695
+ if config:
696
+ moai_version = config.get("moai", {}).get("version", "unknown")
697
+
698
+ # Get language info
699
+ lang_info = get_language_info(config)
700
+
701
+ # FIX #2: Get git strategy info
702
+ git_strategy = get_git_strategy_info(config)
703
+
704
+ # Check for version updates (uses Phase 1 cache)
705
+ version_status, _has_update = check_version_update()
706
+
707
+ # Format output with each item on separate line (reordered per user request)
708
+ output = [
709
+ "🚀 MoAI-ADK Session Started",
710
+ f" 📦 Version: {moai_version} {version_status}",
711
+ f" 🔄 Changes: {git_info['changes']}",
712
+ f" 🌿 Branch: {git_info['branch']}",
713
+ # FIX #2: Add Git Strategy information
714
+ f" 🔧 Github-Flow: {git_strategy['git_flow']} | Auto Branch: {git_strategy['auto_branch']}",
715
+ f" 🔨 Last Commit: {git_info['last_commit']}",
716
+ f" 🌐 Language: {lang_info['language_name']} ({lang_info['conversation_language']})",
717
+ ]
718
+
719
+ # FIX #5: Add personalization or setup guidance (never show template variables)
720
+ if personalization.get("needs_setup", False):
721
+ # Show setup guidance (based on conversation_language)
722
+ if personalization["is_korean"]:
723
+ output.append(
724
+ " 👋 환영합니다! 프로젝트를 시작하기 전에 "
725
+ "'moai:0-project setting' 명령어로 사용자 이름과 설정을 구성해주세요"
726
+ )
727
+ else:
728
+ output.append(
729
+ " 👋 Welcome! Before starting, please run 'moai:0-project setting' "
730
+ "to configure your name and project settings"
731
+ )
732
+ elif personalization["has_personalization"]:
733
+ user_greeting = personalization.get("personalized_greeting", "")
734
+ if user_greeting:
735
+ if personalization["is_korean"]:
736
+ greeting = f" 👋 다시 오신 것을 환영합니다, {user_greeting}!"
737
+ else:
738
+ greeting = f" 👋 Welcome back, {user_greeting}!"
739
+ else:
740
+ if personalization["is_korean"]:
741
+ greeting = f" 👋 다시 오신 것을 환영합니다, {personalization['user_name']}님!"
742
+ else:
743
+ greeting = f" 👋 Welcome back, {personalization['user_name']}!"
744
+ output.append(greeting)
745
+
746
+ # Configuration source is now handled silently for cleaner output
747
+ # Users can check configuration using dedicated tools if needed
748
+
749
+ return "\n".join(output)
750
+
751
+
752
+ def main() -> None:
753
+ """Main entry point for enhanced SessionStart hook
754
+
755
+ Displays enhanced project information including:
756
+ - Programming language and version
757
+ - Git branch, changes, and last commit with time
758
+ - Git strategy (mode and auto_branch setting)
759
+ - SPEC progress (completed/total)
760
+ - Test coverage and status
761
+ - Risk assessment
762
+
763
+ Features:
764
+ - Optimized timeout handling with unified manager
765
+ - Enhanced error handling with graceful degradation
766
+ - Resource monitoring and cleanup
767
+ - Retry mechanisms for transient failures
768
+
769
+ Exit Codes:
770
+ 0: Success
771
+ 1: Error (timeout, JSON parse failure, handler exception)
772
+ """
773
+ # Configure timeout for session start hook
774
+ timeout_config = HookTimeoutConfig(
775
+ policy=TimeoutPolicy.NORMAL,
776
+ custom_timeout_ms=5000, # 5 seconds
777
+ retry_count=1,
778
+ retry_delay_ms=200,
779
+ graceful_degradation=True,
780
+ memory_limit_mb=100, # Optional memory limit
781
+ )
782
+
783
+ def execute_session_start():
784
+ """Execute session start logic with proper error handling"""
785
+ # Read JSON payload from stdin (for compatibility)
786
+ # Handle Docker/non-interactive environments by checking TTY
787
+ input_data = sys.stdin.read() if not sys.stdin.isatty() else "{}"
788
+ json.loads(input_data) if input_data.strip() else {}
789
+
790
+ # Check if setup messages should be shown
791
+ show_messages = should_show_setup_messages()
792
+
793
+ # Generate enhanced session output (conditionally)
794
+ session_output = format_session_output() if show_messages else ""
795
+
796
+ # Return as system message
797
+ result: Dict[str, Any] = {
798
+ "continue": True,
799
+ "systemMessage": session_output,
800
+ "performance": {
801
+ "git_manager_used": get_git_manager() is not None,
802
+ "timeout_manager_used": get_timeout_manager() is not None,
803
+ },
804
+ }
805
+
806
+ return result
807
+
808
+ # Use unified timeout manager if available
809
+ timeout_manager = get_timeout_manager()
810
+ if timeout_manager:
811
+ try:
812
+ result = timeout_manager.execute_with_timeout(
813
+ "session_start__show_project_info",
814
+ execute_session_start,
815
+ config=timeout_config,
816
+ )
817
+
818
+ print(json.dumps(result, ensure_ascii=False))
819
+ sys.exit(0)
820
+
821
+ except HookTimeoutError as e:
822
+ # Enhanced timeout error handling
823
+ timeout_response: Dict[str, Any] = {
824
+ "continue": True,
825
+ "systemMessage": "⚠️ Session start timeout - continuing without project info",
826
+ "error_details": {
827
+ "hook_id": e.hook_id,
828
+ "timeout_seconds": e.timeout_seconds,
829
+ "execution_time": e.execution_time,
830
+ "will_retry": e.will_retry,
831
+ },
832
+ }
833
+ print(json.dumps(timeout_response, ensure_ascii=False))
834
+ print(f"SessionStart hook timeout: {e}", file=sys.stderr)
835
+ sys.exit(1)
836
+
837
+ except Exception as e:
838
+ # Enhanced error handling with context
839
+ error_response: Dict[str, Any] = {
840
+ "continue": True,
841
+ "systemMessage": "⚠️ Session start encountered an error - continuing",
842
+ "error_details": {
843
+ "error_type": type(e).__name__,
844
+ "message": str(e),
845
+ "graceful_degradation": True,
846
+ },
847
+ }
848
+ print(json.dumps(error_response, ensure_ascii=False))
849
+ print(f"SessionStart error: {e}", file=sys.stderr)
850
+ sys.exit(1)
851
+
852
+ else:
853
+ # Fallback to legacy timeout handling
854
+ try:
855
+ from lib.timeout import CrossPlatformTimeout
856
+ from lib.timeout import TimeoutError as PlatformTimeoutError
857
+
858
+ # Set 5-second timeout
859
+ timeout = CrossPlatformTimeout(5)
860
+ timeout.start()
861
+
862
+ try:
863
+ result = execute_session_start()
864
+ print(json.dumps(result))
865
+ sys.exit(0)
866
+
867
+ except PlatformTimeoutError:
868
+ # Timeout - return minimal valid response
869
+ timeout_response_legacy: Dict[str, Any] = {
870
+ "continue": True,
871
+ "systemMessage": "⚠️ Session start timeout - continuing without project info",
872
+ }
873
+ print(json.dumps(timeout_response_legacy))
874
+ print("SessionStart hook timeout after 5 seconds", file=sys.stderr)
875
+ sys.exit(1)
876
+
877
+ finally:
878
+ # Always cancel timeout
879
+ timeout.cancel()
880
+
881
+ except ImportError:
882
+ # No timeout handling available
883
+ try:
884
+ result = execute_session_start()
885
+ print(json.dumps(result))
886
+ sys.exit(0)
887
+ except Exception as e:
888
+ print(
889
+ json.dumps(
890
+ {
891
+ "continue": True,
892
+ "systemMessage": "⚠️ Session start completed with errors",
893
+ "error": str(e),
894
+ }
895
+ )
896
+ )
897
+ sys.exit(0)
898
+
899
+ except json.JSONDecodeError as e:
900
+ # JSON parse error
901
+ json_error_response: Dict[str, Any] = {
902
+ "continue": True,
903
+ "hookSpecificOutput": {"error": f"JSON parse error: {e}"},
904
+ }
905
+ print(json.dumps(json_error_response))
906
+ print(f"SessionStart JSON parse error: {e}", file=sys.stderr)
907
+ sys.exit(1)
908
+
909
+ except Exception as e:
910
+ # Unexpected error
911
+ general_error_response: Dict[str, Any] = {
912
+ "continue": True,
913
+ "hookSpecificOutput": {"error": f"SessionStart error: {e}"},
914
+ }
915
+ print(json.dumps(general_error_response))
916
+ print(f"SessionStart unexpected error: {e}", file=sys.stderr)
917
+ sys.exit(1)
918
+
919
+
920
+ if __name__ == "__main__":
921
+ main()