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,862 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """SessionEnd Hook: Cleanup and state saving on session end
4
+
5
+ Performs the following tasks on session end:
6
+ - Clean up temporary files and cache
7
+ - Save session metrics (for productivity analysis)
8
+ - Save work state snapshot (ensure work continuity)
9
+ - Warn uncommitted changes
10
+ - Generate session summary
11
+
12
+ Features:
13
+ - Clean up old temporary files
14
+ - Clean up cache files
15
+ - Collect and save session metrics
16
+ - Work state snapshot (current SPEC, TodoWrite items, etc.)
17
+ - Detect uncommitted Git changes
18
+ - Generate session summary message
19
+ """
20
+
21
+ import json
22
+ import logging
23
+ import shutil
24
+ import subprocess
25
+ import sys
26
+ import time
27
+ from datetime import datetime, timedelta
28
+ from pathlib import Path
29
+ from typing import Any, Dict, List, Optional
30
+
31
+ # Add module path
32
+ sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))
33
+
34
+ from lib.path_utils import find_project_root # noqa: E402
35
+
36
+ # Import unified timeout manager and Git operations manager
37
+ try:
38
+ from lib.common import ( # noqa: E402
39
+ format_duration,
40
+ get_summary_stats,
41
+ is_root_whitelisted,
42
+ suggest_moai_location,
43
+ )
44
+ from lib.config_manager import ConfigManager # noqa: E402
45
+ from lib.config_validator import ValidationIssue, get_config_validator
46
+ from lib.git_operations_manager import GitOperationType, get_git_manager
47
+ from lib.unified_timeout_manager import (
48
+ HookTimeoutConfig,
49
+ HookTimeoutError,
50
+ TimeoutPolicy,
51
+ get_timeout_manager,
52
+ hook_timeout_context,
53
+ )
54
+ except ImportError:
55
+ # Fallback implementations if new modules not available
56
+ def get_timeout_manager():
57
+ return None
58
+
59
+ def hook_timeout_context(hook_name, config=None):
60
+ import contextlib
61
+
62
+ @contextlib.contextmanager
63
+ def dummy_context():
64
+ yield
65
+
66
+ return dummy_context()
67
+
68
+ class HookTimeoutConfig: # type: ignore[no-redef]
69
+ def __init__(self, **kwargs):
70
+ pass
71
+
72
+ class TimeoutPolicy: # type: ignore[no-redef]
73
+ FAST = "fast"
74
+ NORMAL = "normal"
75
+ SLOW = "slow"
76
+
77
+ class HookTimeoutError(Exception): # type: ignore[no-redef]
78
+ pass
79
+
80
+ def get_git_manager():
81
+ return None
82
+
83
+ class GitOperationType: # type: ignore[no-redef]
84
+ STATUS = "status"
85
+ LOG = "log"
86
+
87
+ def get_config_validator():
88
+ return None
89
+
90
+ class ValidationIssue: # type: ignore[no-redef]
91
+ pass
92
+
93
+ ConfigManager = None # type: ignore
94
+ # Fallback implementations if module not found
95
+ import statistics
96
+
97
+ def format_duration(seconds):
98
+ """Format duration in seconds to readable string"""
99
+ if seconds < 60:
100
+ return f"{seconds:.1f}s"
101
+ minutes = seconds / 60
102
+ if minutes < 60:
103
+ return f"{minutes:.1f}m"
104
+ hours = minutes / 60
105
+ return f"{hours:.1f}h"
106
+
107
+ def get_summary_stats(values):
108
+ """Get summary statistics for a list of values"""
109
+ if not values:
110
+ return {"mean": 0, "min": 0, "max": 0, "std": 0}
111
+ return {
112
+ "mean": statistics.mean(values),
113
+ "min": min(values),
114
+ "max": max(values),
115
+ "std": statistics.stdev(values) if len(values) > 1 else 0,
116
+ }
117
+
118
+
119
+ logger = logging.getLogger(__name__)
120
+
121
+
122
+ def load_hook_timeout() -> int:
123
+ """Load hook timeout from config.json (default: 5000ms)
124
+
125
+ Returns:
126
+ Timeout in milliseconds
127
+ """
128
+ try:
129
+ config_file = Path(".moai/config/config.json")
130
+ if config_file.exists():
131
+ with open(config_file, "r", encoding="utf-8") as f:
132
+ config: Dict[str, Any] = json.load(f)
133
+ return config.get("hooks", {}).get("timeout_ms", 5000)
134
+ except Exception:
135
+ pass
136
+ return 5000
137
+
138
+
139
+ def get_graceful_degradation() -> bool:
140
+ """Load graceful_degradation setting from config.json (default: true)
141
+
142
+ Returns:
143
+ Whether graceful degradation is enabled
144
+ """
145
+ try:
146
+ config_file = Path(".moai/config/config.json")
147
+ if config_file.exists():
148
+ with open(config_file, "r", encoding="utf-8") as f:
149
+ config: Dict[str, Any] = json.load(f)
150
+ return config.get("hooks", {}).get("graceful_degradation", True)
151
+ except Exception:
152
+ pass
153
+ return True
154
+
155
+
156
+ def cleanup_old_files(config: Dict[str, Any]) -> Dict[str, int]:
157
+ """Clean up old files
158
+
159
+ Args:
160
+ config: Configuration dictionary
161
+
162
+ Returns:
163
+ Statistics of cleaned files
164
+ """
165
+ stats = {"temp_cleaned": 0, "cache_cleaned": 0, "total_cleaned": 0}
166
+
167
+ try:
168
+ cleanup_config = config.get("auto_cleanup", {})
169
+ if not cleanup_config.get("enabled", True):
170
+ return stats
171
+
172
+ cleanup_days = cleanup_config.get("cleanup_days", 7)
173
+ cutoff_date = datetime.now() - timedelta(days=cleanup_days)
174
+
175
+ # Clean up temporary files
176
+ temp_dir = Path(".moai/temp")
177
+ if temp_dir.exists():
178
+ stats["temp_cleaned"] = cleanup_directory(temp_dir, cutoff_date, None, patterns=["*"])
179
+
180
+ # Clean up cache files
181
+ cache_dir = Path(".moai/cache")
182
+ if cache_dir.exists():
183
+ stats["cache_cleaned"] = cleanup_directory(cache_dir, cutoff_date, None, patterns=["*"])
184
+
185
+ stats["total_cleaned"] = stats["temp_cleaned"] + stats["cache_cleaned"]
186
+
187
+ except Exception as e:
188
+ logger.error(f"File cleanup failed: {e}")
189
+
190
+ return stats
191
+
192
+
193
+ def cleanup_directory(
194
+ directory: Path,
195
+ cutoff_date: datetime,
196
+ max_files: Optional[int],
197
+ patterns: List[str],
198
+ ) -> int:
199
+ """Clean up directory files
200
+
201
+ Args:
202
+ directory: Target directory
203
+ cutoff_date: Cutoff date threshold
204
+ max_files: Maximum number of files to keep
205
+ patterns: List of file patterns to delete
206
+
207
+ Returns:
208
+ Number of deleted files
209
+ """
210
+ if not directory.exists():
211
+ return 0
212
+
213
+ cleaned_count = 0
214
+
215
+ try:
216
+ # Collect files matching patterns
217
+ files_to_check: list[Path] = []
218
+ for pattern in patterns:
219
+ files_to_check.extend(directory.glob(pattern))
220
+
221
+ # Sort by date (oldest first)
222
+ files_to_check.sort(key=lambda f: f.stat().st_mtime)
223
+
224
+ # Delete files
225
+ for file_path in files_to_check:
226
+ try:
227
+ # Check file modification time
228
+ file_mtime = datetime.fromtimestamp(file_path.stat().st_mtime)
229
+
230
+ # Delete if before cutoff date
231
+ if file_mtime < cutoff_date:
232
+ if file_path.is_file():
233
+ file_path.unlink()
234
+ cleaned_count += 1
235
+ elif file_path.is_dir():
236
+ shutil.rmtree(file_path)
237
+ cleaned_count += 1
238
+
239
+ except Exception as e:
240
+ logger.warning(f"Failed to delete {file_path}: {e}")
241
+ continue
242
+
243
+ except Exception as e:
244
+ logger.error(f"Directory cleanup failed for {directory}: {e}")
245
+
246
+ return cleaned_count
247
+
248
+
249
+ def save_session_metrics(payload: Dict[str, Any]) -> bool:
250
+ """Save session metrics (P0-1)
251
+
252
+ Args:
253
+ payload: Hook payload
254
+
255
+ Returns:
256
+ Success status
257
+ """
258
+ try:
259
+ # Create logs directory
260
+ logs_dir = Path(".moai/logs/sessions")
261
+ logs_dir.mkdir(parents=True, exist_ok=True)
262
+
263
+ # Collect session information
264
+ session_metrics = {
265
+ "session_id": datetime.now().strftime("%Y-%m-%d-%H%M%S"),
266
+ "end_time": datetime.now().isoformat(),
267
+ "cwd": str(find_project_root()),
268
+ "files_modified": count_modified_files(),
269
+ "git_commits": count_recent_commits(),
270
+ "specs_worked_on": extract_specs_from_memory(),
271
+ }
272
+
273
+ # Save session metrics
274
+ session_file = logs_dir / f"session-{session_metrics['session_id']}.json"
275
+ with open(session_file, "w", encoding="utf-8") as f:
276
+ json.dump(session_metrics, f, indent=2, ensure_ascii=False)
277
+
278
+ logger.info(f"Session metrics saved: {session_file}")
279
+ return True
280
+
281
+ except Exception as e:
282
+ logger.error(f"Failed to save session metrics: {e}")
283
+ return False
284
+
285
+
286
+ def save_work_state(payload: Dict[str, Any]) -> bool:
287
+ """Save work state snapshot (P0-2)
288
+
289
+ Args:
290
+ payload: Hook payload
291
+
292
+ Returns:
293
+ Success status
294
+ """
295
+ try:
296
+ # Create memory directory
297
+ memory_dir = Path(".moai/memory")
298
+ memory_dir.mkdir(parents=True, exist_ok=True)
299
+
300
+ # Collect work state
301
+ work_state = {
302
+ "last_updated": datetime.now().isoformat(),
303
+ "current_branch": get_current_branch(),
304
+ "uncommitted_changes": check_uncommitted_changes(),
305
+ "uncommitted_files": count_uncommitted_files(),
306
+ "specs_in_progress": extract_specs_from_memory(),
307
+ }
308
+
309
+ # Save state
310
+ state_file = memory_dir / "last-session-state.json"
311
+ with open(state_file, "w", encoding="utf-8") as f:
312
+ json.dump(work_state, f, indent=2, ensure_ascii=False)
313
+
314
+ logger.info(f"Work state saved: {state_file}")
315
+ return True
316
+
317
+ except Exception as e:
318
+ logger.error(f"Failed to save work state: {e}")
319
+ return False
320
+
321
+
322
+ def check_uncommitted_changes() -> Optional[str]:
323
+ """Warn uncommitted changes (P0-3) using optimized Git operations
324
+
325
+ Returns:
326
+ Warning message or None
327
+ """
328
+ git_manager = get_git_manager()
329
+ if git_manager:
330
+ try:
331
+ # Use optimized Git manager
332
+ from lib.git_operations_manager import GitCommand
333
+
334
+ status_result = git_manager.execute_git_command(
335
+ GitCommand(
336
+ operation_type=GitOperationType.STATUS,
337
+ args=["status", "--porcelain"],
338
+ cache_ttl_seconds=5, # Short TTL for status
339
+ timeout_seconds=3,
340
+ )
341
+ )
342
+
343
+ if status_result.success:
344
+ uncommitted = status_result.stdout.strip()
345
+ if uncommitted:
346
+ line_count = len(uncommitted.split("\n"))
347
+ return f"⚠️ {line_count} uncommitted files detected - Consider committing or stashing changes"
348
+
349
+ except Exception as e:
350
+ logger.warning(f"Git manager failed for uncommitted changes check: {e}")
351
+
352
+ # Fallback to direct Git command
353
+ try:
354
+ result = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, timeout=1)
355
+
356
+ if result.returncode == 0:
357
+ uncommitted = result.stdout.strip()
358
+ if uncommitted:
359
+ line_count = len(uncommitted.split("\n"))
360
+ return f"⚠️ {line_count} uncommitted files detected - Consider committing or stashing changes"
361
+
362
+ except (subprocess.TimeoutExpired, FileNotFoundError):
363
+ pass
364
+ except Exception as e:
365
+ logger.warning(f"Failed to check uncommitted changes: {e}")
366
+
367
+ return None
368
+
369
+
370
+ def get_current_branch() -> Optional[str]:
371
+ """Get current Git branch name using optimized Git operations
372
+
373
+ Returns:
374
+ Branch name or None if query fails
375
+ """
376
+ git_manager = get_git_manager()
377
+ if git_manager:
378
+ try:
379
+ from lib.git_operations_manager import GitCommand
380
+
381
+ branch_result = git_manager.execute_git_command(
382
+ GitCommand(
383
+ operation_type=GitOperationType.BRANCH,
384
+ args=["rev-parse", "--abbrev-ref", "HEAD"],
385
+ cache_ttl_seconds=30,
386
+ timeout_seconds=3,
387
+ )
388
+ )
389
+
390
+ if branch_result.success:
391
+ return branch_result.stdout.strip()
392
+
393
+ except Exception as e:
394
+ logger.warning(f"Git manager failed for branch query: {e}")
395
+
396
+ # Fallback to direct Git command
397
+ try:
398
+ result = subprocess.run(
399
+ ["git", "rev-parse", "--abbrev-ref", "HEAD"],
400
+ capture_output=True,
401
+ text=True,
402
+ timeout=1,
403
+ )
404
+ if result.returncode == 0:
405
+ return result.stdout.strip()
406
+ except Exception:
407
+ pass
408
+
409
+ return None
410
+
411
+
412
+ def count_modified_files() -> int:
413
+ """Count number of modified files using optimized Git operations"""
414
+ git_manager = get_git_manager()
415
+ if git_manager:
416
+ try:
417
+ from lib.git_operations_manager import GitCommand
418
+
419
+ status_result = git_manager.execute_git_command(
420
+ GitCommand(
421
+ operation_type=GitOperationType.STATUS,
422
+ args=["status", "--porcelain"],
423
+ cache_ttl_seconds=5,
424
+ timeout_seconds=3,
425
+ )
426
+ )
427
+
428
+ if status_result.success:
429
+ return len([line for line in status_result.stdout.strip().split("\n") if line])
430
+
431
+ except Exception as e:
432
+ logger.warning(f"Git manager failed for file count: {e}")
433
+
434
+ # Fallback to direct Git command
435
+ try:
436
+ result = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, timeout=1)
437
+ if result.returncode == 0:
438
+ return len([line for line in result.stdout.strip().split("\n") if line])
439
+ except Exception:
440
+ pass
441
+
442
+ return 0
443
+
444
+
445
+ def count_uncommitted_files() -> int:
446
+ """Count number of uncommitted files"""
447
+ return count_modified_files()
448
+
449
+
450
+ def count_recent_commits() -> int:
451
+ """Count recent commits (during this session) using optimized Git operations"""
452
+ git_manager = get_git_manager()
453
+ if git_manager:
454
+ try:
455
+ from lib.git_operations_manager import GitCommand
456
+
457
+ log_result = git_manager.execute_git_command(
458
+ GitCommand(
459
+ operation_type=GitOperationType.LOG,
460
+ args=["rev-list", "--since=1 hour", "HEAD"],
461
+ cache_ttl_seconds=60, # Cache for 1 minute
462
+ timeout_seconds=5,
463
+ )
464
+ )
465
+
466
+ if log_result.success:
467
+ commits = [line for line in log_result.stdout.strip().split("\n") if line]
468
+ return len(commits)
469
+
470
+ except Exception as e:
471
+ logger.warning(f"Git manager failed for recent commits: {e}")
472
+
473
+ # Fallback to direct Git command
474
+ try:
475
+ result = subprocess.run(
476
+ ["git", "rev-list", "--since=1 hour", "HEAD"],
477
+ capture_output=True,
478
+ text=True,
479
+ timeout=1,
480
+ )
481
+ if result.returncode == 0:
482
+ commits = [line for line in result.stdout.strip().split("\n") if line]
483
+ return len(commits)
484
+ except Exception:
485
+ pass
486
+
487
+ return 0
488
+
489
+
490
+ def extract_specs_from_memory() -> List[str]:
491
+ """Extract SPEC information from memory"""
492
+ specs = []
493
+
494
+ try:
495
+ # Query recent SPECs from command_execution_state.json
496
+ state_file = Path(".moai/memory/command-execution-state.json")
497
+ if state_file.exists():
498
+ with open(state_file, "r", encoding="utf-8") as f:
499
+ state_data = json.load(f)
500
+
501
+ # Extract recent SPEC IDs
502
+ if "last_specs" in state_data:
503
+ specs = state_data["last_specs"][:3] # Latest 3
504
+
505
+ except Exception as e:
506
+ logger.warning(f"Failed to extract specs from memory: {e}")
507
+
508
+ return specs
509
+
510
+
511
+ # Note: is_root_whitelisted, get_file_pattern_category, and suggest_moai_location
512
+ # are now imported from lib.common (consolidated from duplicate implementations)
513
+
514
+
515
+ def scan_root_violations(config: Dict[str, Any]) -> List[Dict[str, str]]:
516
+ """Scan project root for document management violations
517
+
518
+ Args:
519
+ config: Configuration dictionary
520
+
521
+ Returns:
522
+ List of violation dictionaries with file info and suggested location
523
+ """
524
+ violations = []
525
+
526
+ try:
527
+ # Get project root
528
+ project_root = Path(".moai/config/config.json").parent.parent
529
+ if not project_root.exists():
530
+ project_root = find_project_root()
531
+
532
+ # Scan root directory
533
+ for item in project_root.iterdir():
534
+ # Skip directories (except backup directories)
535
+ if item.is_dir():
536
+ # Check for backup directories
537
+ if item.name.endswith("-backup") or item.name.endswith("_backup") or "_backup_" in item.name:
538
+ suggested = suggest_moai_location(item.name, config)
539
+ violations.append(
540
+ {
541
+ "file": item.name + "/",
542
+ "type": "directory",
543
+ "suggested": suggested,
544
+ }
545
+ )
546
+ continue
547
+
548
+ # Skip hidden files and directories
549
+ if item.name.startswith("."):
550
+ continue
551
+
552
+ # Check if whitelisted
553
+ if is_root_whitelisted(item.name, config):
554
+ continue
555
+
556
+ # Not whitelisted - add to violations
557
+ suggested = suggest_moai_location(item.name, config)
558
+ violations.append({"file": item.name, "type": "file", "suggested": suggested})
559
+
560
+ except Exception as e:
561
+ logger.warning(f"Failed to scan root violations: {e}")
562
+
563
+ return violations
564
+
565
+
566
+ def generate_migration_report(violations: List[Dict[str, str]]) -> str:
567
+ """Generate migration suggestions report
568
+
569
+ Args:
570
+ violations: List of violations
571
+
572
+ Returns:
573
+ Formatted report string
574
+ """
575
+ if not violations:
576
+ return ""
577
+
578
+ report_lines = [
579
+ "\n⚠️ Document Management Violations Detected",
580
+ f" Found {len(violations)} misplaced file(s) in project root:\n",
581
+ ]
582
+
583
+ for idx, violation in enumerate(violations, 1):
584
+ file_display = violation["file"]
585
+ suggested = violation["suggested"]
586
+ report_lines.append(f" {idx}. {file_display} → {suggested}")
587
+
588
+ report_lines.append("\n Action: Move files to suggested locations or update root_whitelist")
589
+ report_lines.append(' Guide: Skill("moai-core-document-management")')
590
+
591
+ return "\n".join(report_lines)
592
+
593
+
594
+ def generate_session_summary(
595
+ cleanup_stats: Dict[str, int], work_state: Dict[str, Any], violations_count: int = 0
596
+ ) -> str:
597
+ """Generate session summary (P1-3)
598
+
599
+ Args:
600
+ cleanup_stats: Cleanup statistics
601
+ work_state: Work state
602
+ violations_count: Number of document management violations
603
+
604
+ Returns:
605
+ Summary message
606
+ """
607
+ summary_lines = ["✅ Session Ended"]
608
+
609
+ try:
610
+ # Work information
611
+ specs = work_state.get("specs_in_progress", [])
612
+ if specs:
613
+ summary_lines.append(f" • Worked on: {', '.join(specs)}")
614
+
615
+ # File modification information
616
+ files_modified = work_state.get("uncommitted_files", 0)
617
+ if files_modified > 0:
618
+ summary_lines.append(f" • Files modified: {files_modified}")
619
+
620
+ # Cleanup information
621
+ total_cleaned = cleanup_stats.get("total_cleaned", 0)
622
+ if total_cleaned > 0:
623
+ summary_lines.append(f" • Cleaned: {total_cleaned} temp files")
624
+
625
+ # Document management violations
626
+ if violations_count > 0:
627
+ summary_lines.append(f" ⚠️ {violations_count} root violations detected (see below)")
628
+
629
+ except Exception as e:
630
+ logger.warning(f"Failed to generate session summary: {e}")
631
+
632
+ return "\n".join(summary_lines)
633
+
634
+
635
+ def execute_session_end_workflow() -> tuple[Dict[str, Any], str]:
636
+ """Execute the session end workflow with proper error handling"""
637
+ start_time = time.time()
638
+
639
+ # Load configuration
640
+ if ConfigManager:
641
+ config = ConfigManager().load_config()
642
+ else:
643
+ config = {}
644
+
645
+ # Generate hook payload (simple version)
646
+ payload = {"cwd": str(find_project_root())}
647
+
648
+ results = {
649
+ "hook": "session_end__auto_cleanup",
650
+ "success": True,
651
+ "execution_time_seconds": 0,
652
+ "cleanup_stats": {"total_cleaned": 0},
653
+ "work_state_saved": False,
654
+ "session_metrics_saved": False,
655
+ "uncommitted_warning": None,
656
+ "session_summary": "",
657
+ "timestamp": datetime.now().isoformat(),
658
+ "performance": {
659
+ "git_manager_used": get_git_manager() is not None,
660
+ "timeout_manager_used": get_timeout_manager() is not None,
661
+ "config_validator_used": get_config_validator() is not None,
662
+ },
663
+ }
664
+
665
+ try:
666
+ # P0-1: Save session metrics
667
+ if save_session_metrics(payload):
668
+ results["session_metrics_saved"] = True
669
+
670
+ # P0-2: Save work state snapshot
671
+ work_state = {}
672
+ if save_work_state(payload):
673
+ results["work_state_saved"] = True
674
+ work_state = {
675
+ "uncommitted_files": count_uncommitted_files(),
676
+ "specs_in_progress": extract_specs_from_memory(),
677
+ }
678
+
679
+ # P0-3: Warn uncommitted changes
680
+ uncommitted_warning = check_uncommitted_changes()
681
+ if uncommitted_warning:
682
+ results["uncommitted_warning"] = uncommitted_warning
683
+
684
+ # P1-1: Clean up temporary files
685
+ cleanup_stats = cleanup_old_files(config)
686
+ results["cleanup_stats"] = cleanup_stats
687
+
688
+ # P1-2: Document Management - Scan root violations
689
+ violations = []
690
+ migration_report = ""
691
+ doc_mgmt = config.get("document_management", {})
692
+ if doc_mgmt.get("enabled", True):
693
+ violations = scan_root_violations(config)
694
+ if violations:
695
+ migration_report = generate_migration_report(violations)
696
+ results["document_violations"] = {
697
+ "count": len(violations),
698
+ "violations": violations,
699
+ }
700
+
701
+ # P1-3: Generate session summary
702
+ session_summary = generate_session_summary(cleanup_stats, work_state, len(violations))
703
+ results["session_summary"] = session_summary
704
+
705
+ # Add migration report to summary if violations exist
706
+ if migration_report:
707
+ results["migration_report"] = migration_report
708
+
709
+ # Record execution time
710
+ execution_time = time.time() - start_time
711
+ results["execution_time_seconds"] = round(execution_time, 2)
712
+
713
+ return results, migration_report
714
+
715
+ except Exception as e:
716
+ results["success"] = False
717
+ results["error"] = str(e)
718
+ results["execution_time_seconds"] = round(time.time() - start_time, 2)
719
+ return results, ""
720
+
721
+
722
+ def main() -> None:
723
+ """Main function
724
+
725
+ SessionEnd Hook entry point for cleanup and work state tracking.
726
+ Cleans up temporary files, saves session metrics, and warns uncommitted changes.
727
+
728
+ Features:
729
+ - Optimized timeout handling with unified manager
730
+ - Enhanced error handling with graceful degradation
731
+ - Resource monitoring and cleanup
732
+ - Performance optimization with Git operations manager
733
+
734
+ Returns:
735
+ None
736
+ """
737
+ # Configure timeout for session end hook
738
+ timeout_config = HookTimeoutConfig(
739
+ policy=TimeoutPolicy.NORMAL,
740
+ custom_timeout_ms=5000, # 5 seconds
741
+ retry_count=1,
742
+ retry_delay_ms=500,
743
+ graceful_degradation=True,
744
+ memory_limit_mb=150, # Higher memory limit for cleanup operations
745
+ )
746
+
747
+ # Use unified timeout manager if available
748
+ timeout_manager = get_timeout_manager()
749
+ if timeout_manager:
750
+ try:
751
+ results, migration_report = timeout_manager.execute_with_timeout(
752
+ "session_end__auto_cleanup",
753
+ execute_session_end_workflow,
754
+ config=timeout_config,
755
+ )
756
+
757
+ # Print results
758
+ output_lines = [json.dumps(results, ensure_ascii=False, indent=2)]
759
+
760
+ # Print migration report separately for visibility
761
+ if migration_report:
762
+ output_lines.append(migration_report)
763
+
764
+ print("\n".join(output_lines))
765
+
766
+ except HookTimeoutError as e:
767
+ # Enhanced timeout error handling
768
+ timeout_response = {
769
+ "hook": "session_end__auto_cleanup",
770
+ "success": False,
771
+ "error": f"Hook execution timeout: {str(e)}",
772
+ "error_details": {
773
+ "hook_id": e.hook_id,
774
+ "timeout_seconds": e.timeout_seconds,
775
+ "execution_time": e.execution_time,
776
+ "will_retry": e.will_retry,
777
+ },
778
+ "graceful_degradation": True,
779
+ "timestamp": datetime.now().isoformat(),
780
+ }
781
+ timeout_response["message"] = "Hook timeout but continuing due to graceful degradation"
782
+ print(json.dumps(timeout_response, ensure_ascii=False, indent=2))
783
+
784
+ except Exception as e:
785
+ # Enhanced error handling with context
786
+ error_response = {
787
+ "hook": "session_end__auto_cleanup",
788
+ "success": False,
789
+ "error": f"Hook execution failed: {str(e)}",
790
+ "error_details": {
791
+ "error_type": type(e).__name__,
792
+ "message": str(e),
793
+ "graceful_degradation": True,
794
+ },
795
+ "timestamp": datetime.now().isoformat(),
796
+ }
797
+ error_response["message"] = "Hook failed but continuing due to graceful degradation"
798
+ print(json.dumps(error_response, ensure_ascii=False, indent=2))
799
+
800
+ else:
801
+ # Fallback to legacy timeout handling
802
+ try:
803
+ timeout_seconds = load_hook_timeout() / 1000
804
+ graceful_degradation = get_graceful_degradation()
805
+
806
+ # Legacy timeout implementation
807
+ import signal
808
+
809
+ def timeout_handler(signum, frame):
810
+ raise TimeoutError("Hook execution timeout")
811
+
812
+ signal.signal(signal.SIGALRM, timeout_handler)
813
+ signal.alarm(int(timeout_seconds))
814
+
815
+ try:
816
+ results, migration_report = execute_session_end_workflow()
817
+
818
+ # Print results
819
+ output_lines = [json.dumps(results, ensure_ascii=False, indent=2)]
820
+
821
+ # Print migration report separately for visibility
822
+ if migration_report:
823
+ output_lines.append(migration_report)
824
+
825
+ print("\n".join(output_lines))
826
+
827
+ finally:
828
+ signal.alarm(0) # Clear timeout
829
+
830
+ except TimeoutError as e:
831
+ # Handle timeout with graceful degradation
832
+ result = {
833
+ "hook": "session_end__auto_cleanup",
834
+ "success": False,
835
+ "error": f"Hook execution timeout: {str(e)}",
836
+ "graceful_degradation": graceful_degradation,
837
+ "timestamp": datetime.now().isoformat(),
838
+ }
839
+
840
+ if graceful_degradation:
841
+ result["message"] = "Hook timeout but continuing due to graceful degradation"
842
+
843
+ print(json.dumps(result, ensure_ascii=False, indent=2))
844
+
845
+ except Exception as e:
846
+ # Handle exceptions with graceful degradation
847
+ result = {
848
+ "hook": "session_end__auto_cleanup",
849
+ "success": False,
850
+ "error": f"Hook execution failed: {str(e)}",
851
+ "graceful_degradation": graceful_degradation,
852
+ "timestamp": datetime.now().isoformat(),
853
+ }
854
+
855
+ if graceful_degradation:
856
+ result["message"] = "Hook failed but continuing due to graceful degradation"
857
+
858
+ print(json.dumps(result, ensure_ascii=False, indent=2))
859
+
860
+
861
+ if __name__ == "__main__":
862
+ main()