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
@@ -10,6 +10,9 @@ from moai_adk.core.spec.confidence_scoring import ConfidenceScoringSystem
10
10
  # Configure logging
11
11
  logger = logging.getLogger(__name__)
12
12
 
13
+ # Traceability tag patterns
14
+ TRACEABILITY_TAGS = ["@SPEC:", "@REQ:", "@TEST:", "@IMPL:", "@DOC:"]
15
+
13
16
 
14
17
  class QualityValidator:
15
18
  """
@@ -92,7 +95,7 @@ class QualityValidator:
92
95
  logger.info("Starting SPEC quality validation")
93
96
 
94
97
  # Initialize validation results
95
- validation_result = {
98
+ validation_result: Dict[str, Any] = {
96
99
  "validation_time": 0.0,
97
100
  "overall_score": 0.0,
98
101
  "quality_grade": "F",
@@ -113,9 +116,7 @@ class QualityValidator:
113
116
  validation_result["details"]["content_completeness"] = completeness_result
114
117
 
115
118
  # Validate technical accuracy
116
- technical_result = self._validate_technical_accuracy(
117
- spec_content, code_analysis
118
- )
119
+ technical_result = self._validate_technical_accuracy(spec_content, code_analysis)
119
120
  validation_result["details"]["technical_accuracy"] = technical_result
120
121
 
121
122
  # Validate clarity and readability
@@ -131,9 +132,7 @@ class QualityValidator:
131
132
  validation_result["overall_score"] = overall_score
132
133
 
133
134
  # Determine quality grade
134
- validation_result["quality_grade"] = self._determine_quality_grade(
135
- overall_score
136
- )
135
+ validation_result["quality_grade"] = self._determine_quality_grade(overall_score)
137
136
 
138
137
  # Check if SPEC meets minimum quality standards
139
138
  meets_standards = self._check_quality_standards(validation_result)
@@ -144,12 +143,8 @@ class QualityValidator:
144
143
  validation_result["recommendations"] = recommendations
145
144
 
146
145
  # Compile check results
147
- validation_result["passed_checks"] = self._compile_passed_checks(
148
- validation_result["details"]
149
- )
150
- validation_result["failed_checks"] = self._compile_failed_checks(
151
- validation_result["details"]
152
- )
146
+ validation_result["passed_checks"] = self._compile_passed_checks(validation_result["details"])
147
+ validation_result["failed_checks"] = self._compile_failed_checks(validation_result["details"])
153
148
 
154
149
  except Exception as e:
155
150
  logger.error(f"Error during SPEC validation: {str(e)}")
@@ -158,9 +153,7 @@ class QualityValidator:
158
153
  # Set validation time
159
154
  validation_result["validation_time"] = time.time() - start_time
160
155
 
161
- logger.info(
162
- f"SPEC quality validation completed in {validation_result['validation_time']:.2f}s"
163
- )
156
+ logger.info(f"SPEC quality validation completed in {validation_result['validation_time']:.2f}s")
164
157
 
165
158
  return validation_result
166
159
 
@@ -184,6 +177,10 @@ class QualityValidator:
184
177
  overall_compliance = sum(section_scores.values()) / len(required_sections)
185
178
 
186
179
  # Check for META information
180
+ has_meta = "---" in spec_md and "title:" in spec_md
181
+
182
+ # Check for tags
183
+ has_tags = self._check_traceability_tags(spec_md)
187
184
 
188
185
  # Check for proper structure
189
186
  has_proper_headings = self._check_heading_structure(spec_md)
@@ -196,14 +193,10 @@ class QualityValidator:
196
193
  "has_tags": has_tags,
197
194
  "has_proper_structure": has_proper_headings,
198
195
  "total_sections": len(required_sections),
199
- "present_sections": sum(
200
- 1 for score in section_scores.values() if score > 0
201
- ),
196
+ "present_sections": sum(1 for score in section_scores.values() if score > 0),
202
197
  }
203
198
 
204
- def _validate_content_completeness(
205
- self, spec_content: Dict[str, str]
206
- ) -> Dict[str, Any]:
199
+ def _validate_content_completeness(self, spec_content: Dict[str, str]) -> Dict[str, Any]:
207
200
  """Validate content completeness across all SPEC files."""
208
201
  logger.info("Validating content completeness")
209
202
 
@@ -230,9 +223,7 @@ class QualityValidator:
230
223
  results["acceptance_completeness"] = acceptance_completeness
231
224
 
232
225
  # Calculate overall completeness
233
- overall_completeness = (
234
- spec_completeness + plan_completeness + acceptance_completeness
235
- ) / 3
226
+ overall_completeness = (spec_completeness + plan_completeness + acceptance_completeness) / 3
236
227
  results["overall_completeness"] = round(overall_completeness, 2)
237
228
 
238
229
  return results
@@ -301,13 +292,7 @@ class QualityValidator:
301
292
  "ambiguity_score": ambiguity_score,
302
293
  "consistency_score": consistency_score,
303
294
  "overall_clarity": round(
304
- (
305
- language_quality
306
- + clarity_requirements
307
- + (1.0 - ambiguity_score)
308
- + consistency_score
309
- )
310
- / 4,
295
+ (language_quality + clarity_requirements + (1.0 - ambiguity_score) + consistency_score) / 4,
311
296
  2,
312
297
  ),
313
298
  }
@@ -331,12 +316,9 @@ class QualityValidator:
331
316
  weights = self.quality_weights
332
317
 
333
318
  overall_score = (
334
- details["ears_compliance"]["overall_compliance"]
335
- * weights["ears_compliance"]
336
- + details["content_completeness"]["overall_completeness"]
337
- * weights["content_completeness"]
338
- + details["technical_accuracy"]["overall_accuracy"]
339
- * weights["technical_accuracy"]
319
+ details["ears_compliance"]["overall_compliance"] * weights["ears_compliance"]
320
+ + details["content_completeness"]["overall_completeness"] * weights["content_completeness"]
321
+ + details["technical_accuracy"]["overall_accuracy"] * weights["technical_accuracy"]
340
322
  + details["clarity_score"]["overall_clarity"] * weights["clarity_score"]
341
323
  + details["traceability"]["overall_traceability"] * weights["traceability"]
342
324
  )
@@ -359,9 +341,7 @@ class QualityValidator:
359
341
  def _check_quality_standards(self, validation_result: Dict[str, Any]) -> bool:
360
342
  """Check if SPEC meets minimum quality standards."""
361
343
  overall_score = validation_result["overall_score"]
362
- ears_compliance = validation_result["details"]["ears_compliance"][
363
- "overall_compliance"
364
- ]
344
+ ears_compliance = validation_result["details"]["ears_compliance"]["overall_compliance"]
365
345
 
366
346
  meets_overall = overall_score >= self.min_confidence_score
367
347
  meets_ears = ears_compliance >= self.min_ears_compliance
@@ -376,15 +356,11 @@ class QualityValidator:
376
356
  # EARS compliance recommendations
377
357
  if details["ears_compliance"]["overall_compliance"] < 1.0:
378
358
  missing = details["ears_compliance"]["missing_sections"]
379
- recommendations.append(
380
- f"Add missing EARS sections: {', '.join(missing[:3])}"
381
- )
359
+ recommendations.append(f"Add missing EARS sections: {', '.join(missing[:3])}")
382
360
 
383
361
  # Content completeness recommendations
384
362
  if details["content_completeness"]["overall_completeness"] < 0.8:
385
- recommendations.append(
386
- "Expand content sections with more detailed requirements"
387
- )
363
+ recommendations.append("Expand content sections with more detailed requirements")
388
364
 
389
365
  # Technical accuracy recommendations
390
366
  if details["technical_accuracy"]["overall_accuracy"] < 0.8:
@@ -494,9 +470,7 @@ class QualityValidator:
494
470
 
495
471
  return min(score, 1.0)
496
472
 
497
- def _assess_acceptance_criteria_completeness(
498
- self, acceptance_content: str
499
- ) -> float:
473
+ def _assess_acceptance_criteria_completeness(self, acceptance_content: str) -> float:
500
474
  """Assess completeness of acceptance criteria."""
501
475
  if not acceptance_content:
502
476
  return 0.0
@@ -526,9 +500,7 @@ class QualityValidator:
526
500
 
527
501
  return len(found_keywords) / len(keywords)
528
502
 
529
- def _check_code_consistency(
530
- self, spec_md: str, code_analysis: Dict[str, Any]
531
- ) -> float:
503
+ def _check_code_consistency(self, spec_md: str, code_analysis: Dict[str, Any]) -> float:
532
504
  """Check consistency between SPEC and code analysis."""
533
505
  # Extract key elements from code analysis
534
506
  classes = code_analysis.get("structure_info", {}).get("classes", [])
@@ -590,9 +562,7 @@ class QualityValidator:
590
562
  r"Relevant",
591
563
  ]
592
564
 
593
- found_indicators = sum(
594
- 1 for indicator in clarity_indicators if re.search(indicator, spec_md)
595
- )
565
+ found_indicators = sum(1 for indicator in clarity_indicators if re.search(indicator, spec_md))
596
566
 
597
567
  return min(found_indicators / len(clarity_indicators), 1.0)
598
568
 
@@ -606,9 +576,7 @@ class QualityValidator:
606
576
  r"around",
607
577
  ]
608
578
 
609
- ambiguous_count = sum(
610
- 1 for indicator in ambiguity_indicators if re.search(indicator, spec_md)
611
- )
579
+ ambiguous_count = sum(1 for indicator in ambiguity_indicators if re.search(indicator, spec_md))
612
580
 
613
581
  # Normalize by content length
614
582
  content_length = len(spec_md.split())
@@ -633,7 +601,7 @@ class QualityValidator:
633
601
 
634
602
  def _check_traceability_tags(self, spec_md: str) -> bool:
635
603
  """Check for traceability tags."""
636
- return any(tag in spec_md for tag in traceability_tags)
604
+ return any(tag in spec_md for tag in TRACEABILITY_TAGS)
637
605
 
638
606
  def _check_tag_formatting(self, spec_md: str) -> float:
639
607
  """Check proper tag formatting."""
@@ -659,9 +627,7 @@ class QualityValidator:
659
627
  r"Trace",
660
628
  ]
661
629
 
662
- found_indicators = sum(
663
- 1 for indicator in traceability_indicators if re.search(indicator, spec_md)
664
- )
630
+ found_indicators = sum(1 for indicator in traceability_indicators if re.search(indicator, spec_md))
665
631
 
666
632
  return min(found_indicators / len(traceability_indicators), 1.0)
667
633
 
@@ -691,14 +657,14 @@ class QualityValidator:
691
657
  report = f"""
692
658
  # Quality Validation Report
693
659
 
694
- ## Overall Quality Score: {validation_result['overall_score']:.2f}/1.0
695
- ## Quality Grade: {validation_result['quality_grade']}
696
- ## Validation Time: {validation_result['validation_time']:.2f}s
660
+ ## Overall Quality Score: {validation_result["overall_score"]:.2f}/1.0
661
+ ## Quality Grade: {validation_result["quality_grade"]}
662
+ ## Validation Time: {validation_result["validation_time"]:.2f}s
697
663
 
698
664
  ## Summary
699
- - Passed Checks: {len(validation_result['passed_checks'])}
700
- - Failed Checks: {len(validation_result['failed_checks'])}
701
- - Recommendations: {len(validation_result['recommendations'])}
665
+ - Passed Checks: {len(validation_result["passed_checks"])}
666
+ - Failed Checks: {len(validation_result["failed_checks"])}
667
+ - Recommendations: {len(validation_result["recommendations"])}
702
668
 
703
669
  ## Detailed Metrics
704
670
  """
@@ -8,9 +8,9 @@ import logging
8
8
  import re
9
9
  from datetime import datetime
10
10
  from pathlib import Path
11
- from typing import Dict, Set
11
+ from typing import Any, Dict, List, Set
12
12
 
13
- import yaml
13
+ import yaml # type: ignore
14
14
 
15
15
  logger = logging.getLogger(__name__)
16
16
 
@@ -43,7 +43,7 @@ class SpecStatusManager:
43
43
  Returns:
44
44
  Set of SPEC IDs that have draft status
45
45
  """
46
- draft_specs = set()
46
+ draft_specs: Set[str] = set()
47
47
 
48
48
  if not self.specs_dir.exists():
49
49
  logger.warning(f"SPEC directory not found: {self.specs_dir}")
@@ -61,9 +61,7 @@ class SpecStatusManager:
61
61
  frontmatter = None
62
62
 
63
63
  # Handle JSON-like meta (common in older specs)
64
- meta_match = re.search(
65
- r"<%?\s*---\s*\n(.*?)\n---\s*%?>", content, re.DOTALL
66
- )
64
+ meta_match = re.search(r"<%?\s*---\s*\n(.*?)\n---\s*%?>", content, re.DOTALL)
67
65
  if meta_match:
68
66
  try:
69
67
  meta_text = meta_match.group(1)
@@ -71,9 +69,7 @@ class SpecStatusManager:
71
69
  meta_text = meta_text.replace('"', "").replace("'", "")
72
70
  frontmatter = yaml.safe_load("{" + meta_text + "}")
73
71
  except Exception as e:
74
- logger.debug(
75
- f"JSON meta parsing failed for {spec_dir.name}: {e}"
76
- )
72
+ logger.debug(f"JSON meta parsing failed for {spec_dir.name}: {e}")
77
73
 
78
74
  # Handle regular YAML frontmatter
79
75
  elif content.startswith("---"):
@@ -83,9 +79,7 @@ class SpecStatusManager:
83
79
  try:
84
80
  frontmatter = yaml.safe_load(frontmatter_text)
85
81
  except yaml.YAMLError as e:
86
- logger.warning(
87
- f"YAML parsing error for {spec_dir.name}: {e}"
88
- )
82
+ logger.warning(f"YAML parsing error for {spec_dir.name}: {e}")
89
83
  # Try to fix common issues (like @ in author field)
90
84
  try:
91
85
  # Replace problematic @author entries
@@ -97,10 +91,8 @@ class SpecStatusManager:
97
91
  fixed_text,
98
92
  )
99
93
  frontmatter = yaml.safe_load(fixed_text)
100
- except:
101
- logger.error(
102
- f"Could not parse YAML for {spec_dir.name} even after fixes"
103
- )
94
+ except yaml.YAMLError:
95
+ logger.error(f"Could not parse YAML for {spec_dir.name} even after fixes")
104
96
  continue
105
97
 
106
98
  if frontmatter and frontmatter.get("status") == "draft":
@@ -135,19 +127,11 @@ class SpecStatusManager:
135
127
  spec_dir = spec_file.parent
136
128
 
137
129
  # Check for implementation files
138
- src_files = (
139
- list(spec_dir.rglob("*.py"))
140
- if (spec_dir.parent.parent / "src").exists()
141
- else []
142
- )
130
+ src_files = list(spec_dir.rglob("*.py")) if (spec_dir.parent.parent / "src").exists() else []
143
131
 
144
132
  # Check for test files
145
133
  test_dir = spec_dir.parent.parent / "tests"
146
- test_files = (
147
- list(test_dir.rglob(f"test_*{spec_id.lower()}*.py"))
148
- if test_dir.exists()
149
- else []
150
- )
134
+ test_files = list(test_dir.rglob(f"test_*{spec_id.lower()}*.py")) if test_dir.exists() else []
151
135
 
152
136
  # Simple completion criteria
153
137
  has_code = len(src_files) > 0
@@ -161,9 +145,7 @@ class SpecStatusManager:
161
145
  # Overall completion check
162
146
  is_complete = has_code and has_tests and has_acceptance_criteria
163
147
 
164
- logger.info(
165
- f"SPEC {spec_id} implementation status: {'COMPLETE' if is_complete else 'INCOMPLETE'}"
166
- )
148
+ logger.info(f"SPEC {spec_id} implementation status: {'COMPLETE' if is_complete else 'INCOMPLETE'}")
167
149
  return is_complete
168
150
 
169
151
  except Exception as e:
@@ -204,14 +186,10 @@ class SpecStatusManager:
204
186
  try:
205
187
  fixed_text = frontmatter_text
206
188
  if "author: @" in fixed_text:
207
- fixed_text = re.sub(
208
- r"author:\s*@(\w+)", r'author: "\1"', fixed_text
209
- )
189
+ fixed_text = re.sub(r"author:\s*@(\w+)", r'author: "\1"', fixed_text)
210
190
  frontmatter = yaml.safe_load(fixed_text) or {}
211
- except:
212
- logger.error(
213
- f"Could not parse YAML for {spec_id} even after fixes"
214
- )
191
+ except yaml.YAMLError:
192
+ logger.error(f"Could not parse YAML for {spec_id} even after fixes")
215
193
  return False
216
194
 
217
195
  # Update status
@@ -219,14 +197,12 @@ class SpecStatusManager:
219
197
 
220
198
  # Bump version if completing
221
199
  if new_status == "completed":
222
- frontmatter["version"] = self._bump_version(
223
- frontmatter.get("version", "0.1.0")
224
- )
200
+ frontmatter["version"] = self._bump_version(frontmatter.get("version", "0.1.0"))
225
201
  frontmatter["updated"] = datetime.now().strftime("%Y-%m-%d")
226
202
 
227
203
  # Reconstruct the file
228
204
  new_frontmatter = yaml.dump(frontmatter, default_flow_style=False)
229
- new_content = f"---\n{new_frontmatter}---{content[end_marker+3:]}"
205
+ new_content = f"---\n{new_frontmatter}---{content[end_marker + 3 :]}"
230
206
 
231
207
  # Write back to file
232
208
  with open(spec_file, "w", encoding="utf-8") as f:
@@ -247,7 +223,7 @@ class SpecStatusManager:
247
223
  """
248
224
  return self.validation_criteria.copy()
249
225
 
250
- def validate_spec_for_completion(self, spec_id: str) -> Dict:
226
+ def validate_spec_for_completion(self, spec_id: str) -> Dict[str, Any]:
251
227
  """Validate if a SPEC is ready for completion
252
228
 
253
229
  Args:
@@ -262,7 +238,7 @@ class SpecStatusManager:
262
238
  'recommendations': List[str]
263
239
  }
264
240
  """
265
- result = {
241
+ result: Dict[str, Any] = {
266
242
  "is_ready": False,
267
243
  "criteria_met": {},
268
244
  "issues": [],
@@ -274,68 +250,74 @@ class SpecStatusManager:
274
250
  spec_file = spec_dir / "spec.md"
275
251
 
276
252
  if not spec_file.exists():
277
- result["issues"].append(f"SPEC file not found: {spec_file}")
253
+ issues_list = result["issues"]
254
+ if isinstance(issues_list, list):
255
+ issues_list.append(f"SPEC file not found: {spec_file}")
278
256
  return result
279
257
 
280
258
  # Check implementation status
281
- criteria_checks = {}
259
+ criteria_checks: Dict[str, bool] = {}
282
260
 
283
261
  # Check for code implementation
284
262
  spec_dir = spec_file.parent
285
263
  src_dir = spec_dir.parent.parent / "src"
286
- criteria_checks["code_implemented"] = (
287
- src_dir.exists() and len(list(src_dir.rglob("*.py"))) > 0
288
- )
264
+ criteria_checks["code_implemented"] = src_dir.exists() and len(list(src_dir.rglob("*.py"))) > 0
289
265
  if not criteria_checks["code_implemented"]:
290
- result["issues"].append("No source code files found")
266
+ issues_list = result["issues"]
267
+ if isinstance(issues_list, list):
268
+ issues_list.append("No source code files found")
291
269
 
292
270
  # Check for test implementation
293
271
  test_dir = spec_dir.parent.parent / "tests"
294
272
  test_files = list(test_dir.rglob("test_*.py")) if test_dir.exists() else []
295
273
  criteria_checks["test_implemented"] = len(test_files) > 0
296
274
  if not criteria_checks["test_implemented"]:
297
- result["issues"].append("No test files found")
275
+ issues_list = result["issues"]
276
+ if isinstance(issues_list, list):
277
+ issues_list.append("No test files found")
298
278
 
299
279
  # Check for acceptance criteria
300
- criteria_checks["tasks_completed"] = self._check_acceptance_criteria(
301
- spec_file
302
- )
280
+ criteria_checks["tasks_completed"] = self._check_acceptance_criteria(spec_file)
303
281
  if not criteria_checks["tasks_completed"]:
304
- result["issues"].append("Missing acceptance criteria section")
282
+ issues_list = result["issues"]
283
+ if isinstance(issues_list, list):
284
+ issues_list.append("Missing acceptance criteria section")
305
285
 
306
286
  # 4. Acceptance criteria present
307
- criteria_checks["has_acceptance_criteria"] = (
308
- self._check_acceptance_criteria(spec_file)
309
- )
287
+ criteria_checks["has_acceptance_criteria"] = self._check_acceptance_criteria(spec_file)
310
288
  if (
311
289
  not criteria_checks["has_acceptance_criteria"]
312
290
  and self.validation_criteria["require_acceptance_criteria"]
313
291
  ):
314
- result["issues"].append("Missing acceptance criteria section")
292
+ issues_list = result["issues"]
293
+ if isinstance(issues_list, list):
294
+ issues_list.append("Missing acceptance criteria section")
315
295
 
316
296
  # 5. Documentation sync
317
297
  criteria_checks["docs_synced"] = self._check_documentation_sync(spec_id)
318
298
  if not criteria_checks["docs_synced"]:
319
- result["recommendations"].append(
320
- "Consider running /alfred:3-sync to update documentation"
321
- )
299
+ recs_list = result["recommendations"]
300
+ if isinstance(recs_list, list):
301
+ recs_list.append("Consider running /moai:3-sync to update documentation")
322
302
 
323
303
  result["criteria_met"] = criteria_checks
324
304
  result["is_ready"] = all(criteria_checks.values())
325
305
 
326
306
  # Add recommendations
327
307
  if result["is_ready"]:
328
- result["recommendations"].append(
329
- "SPEC is ready for completion. Consider updating status to 'completed'"
330
- )
308
+ recs_list = result["recommendations"]
309
+ if isinstance(recs_list, list):
310
+ recs_list.append("SPEC is ready for completion. Consider updating status to 'completed'")
331
311
 
332
312
  except Exception as e:
333
313
  logger.error(f"Error validating SPEC {spec_id}: {e}")
334
- result["issues"].append(f"Validation error: {e}")
314
+ issues_list = result["issues"]
315
+ if isinstance(issues_list, list):
316
+ issues_list.append(f"Validation error: {e}")
335
317
 
336
318
  return result
337
319
 
338
- def batch_update_completed_specs(self) -> Dict:
320
+ def batch_update_completed_specs(self) -> Dict[str, List[str]]:
339
321
  """Batch update all draft SPECs that have completed implementations
340
322
 
341
323
  Returns:
@@ -346,7 +328,7 @@ class SpecStatusManager:
346
328
  'skipped': List[str] # Incomplete SPEC IDs
347
329
  }
348
330
  """
349
- results = {"updated": [], "failed": [], "skipped": []}
331
+ results: Dict[str, List[str]] = {"updated": [], "failed": [], "skipped": []}
350
332
 
351
333
  draft_specs = self.detect_draft_specs()
352
334
  logger.info(f"Checking {len(draft_specs)} draft SPECs for completion")
@@ -359,23 +341,31 @@ class SpecStatusManager:
359
341
  if validation["is_ready"]:
360
342
  # Update status
361
343
  if self.update_spec_status(spec_id, "completed"):
362
- results["updated"].append(spec_id)
344
+ updated_list = results["updated"]
345
+ if isinstance(updated_list, list):
346
+ updated_list.append(spec_id)
363
347
  logger.info(f"Updated SPEC {spec_id} to completed")
364
348
  else:
365
- results["failed"].append(spec_id)
349
+ failed_list = results["failed"]
350
+ if isinstance(failed_list, list):
351
+ failed_list.append(spec_id)
366
352
  logger.error(f"Failed to update SPEC {spec_id}")
367
353
  else:
368
- results["skipped"].append(spec_id)
369
- logger.debug(
370
- f"SPEC {spec_id} not ready for completion: {validation['issues']}"
371
- )
354
+ skipped_list = results["skipped"]
355
+ if isinstance(skipped_list, list):
356
+ skipped_list.append(spec_id)
357
+ logger.debug(f"SPEC {spec_id} not ready for completion: {validation['issues']}")
372
358
 
373
359
  except Exception as e:
374
- results["failed"].append(spec_id)
360
+ failed_list = results["failed"]
361
+ if isinstance(failed_list, list):
362
+ failed_list.append(spec_id)
375
363
  logger.error(f"Error processing SPEC {spec_id}: {e}")
376
364
 
377
365
  logger.info(
378
- f"Batch update complete: {len(results['updated'])} updated, {len(results['failed'])} failed, {len(results['skipped'])} skipped"
366
+ f"Batch update complete: {len(results['updated'])} updated, "
367
+ f"{len(results['failed'])} failed, "
368
+ f"{len(results['skipped'])} skipped"
379
369
  )
380
370
  return results
381
371
 
@@ -5,7 +5,9 @@ Creates and manages backups to protect user data during template updates.
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
+ import re
8
9
  import shutil
10
+ from datetime import datetime
9
11
  from pathlib import Path
10
12
 
11
13
 
@@ -41,24 +43,20 @@ class TemplateBackup:
41
43
  Returns:
42
44
  True when any tracked file exists.
43
45
  """
44
- return any(
45
- (self.target_path / item).exists()
46
- for item in [".moai", ".claude", ".github", "CLAUDE.md"]
47
- )
46
+ return any((self.target_path / item).exists() for item in [".moai", ".claude", ".github", "CLAUDE.md"])
48
47
 
49
48
  def create_backup(self) -> Path:
50
- """Create a single backup (always at .moai-backups/backup/).
49
+ """Create a timestamped backup under .moai-backups/.
51
50
 
52
- Existing backups are overwritten to maintain only one backup copy.
51
+ Creates a new timestamped backup directory for each update.
52
+ Maintains backward compatibility by supporting both new and legacy structures.
53
53
 
54
54
  Returns:
55
- Backup path (always .moai-backups/backup/).
55
+ Path to timestamped backup directory (e.g., .moai-backups/20241201_143022/).
56
56
  """
57
- backup_path = self.target_path / ".moai-backups" / "backup"
58
-
59
- # Remove existing backup if present
60
- if backup_path.exists():
61
- shutil.rmtree(backup_path)
57
+ # Generate timestamp for backup directory name
58
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
59
+ backup_path = self.target_path / ".moai-backups" / timestamp
62
60
 
63
61
  backup_path.mkdir(parents=True, exist_ok=True)
64
62
 
@@ -80,6 +78,35 @@ class TemplateBackup:
80
78
 
81
79
  return backup_path
82
80
 
81
+ def get_latest_backup(self) -> Path | None:
82
+ """Get the most recent backup, supporting both new and legacy structures.
83
+
84
+ Searches for backups in order of preference:
85
+ 1. Latest timestamped backup (new structure)
86
+ 2. Legacy backup/ directory (old structure)
87
+
88
+ Returns:
89
+ Path to the most recent backup directory, or None if no backups exist.
90
+ """
91
+ # Check for new timestamped backups first
92
+ backup_dir = self.target_path / ".moai-backups"
93
+ if backup_dir.exists():
94
+ # Match pattern: YYYYMMDD_HHMMSS (8 digits + underscore + 6 digits)
95
+ timestamp_pattern = re.compile(r"^\d{8}_\d{6}$")
96
+ timestamped_backups = [d for d in backup_dir.iterdir() if d.is_dir() and timestamp_pattern.match(d.name)]
97
+
98
+ if timestamped_backups:
99
+ # Sort by name (timestamp) and return the latest
100
+ latest_backup = max(timestamped_backups, key=lambda x: x.name)
101
+ return latest_backup
102
+
103
+ # Fall back to legacy backup/ directory
104
+ legacy_backup = backup_dir / "backup"
105
+ if legacy_backup.exists():
106
+ return legacy_backup
107
+
108
+ return None
109
+
83
110
  def _copy_exclude_protected(self, src: Path, dst: Path) -> None:
84
111
  """Copy backup content while excluding protected paths.
85
112
 
@@ -94,10 +121,7 @@ class TemplateBackup:
94
121
  rel_path_str = str(rel_path)
95
122
 
96
123
  # Skip excluded paths
97
- if any(
98
- rel_path_str.startswith(exclude_dir)
99
- for exclude_dir in self.BACKUP_EXCLUDE_DIRS
100
- ):
124
+ if any(rel_path_str.startswith(exclude_dir) for exclude_dir in self.BACKUP_EXCLUDE_DIRS):
101
125
  continue
102
126
 
103
127
  dst_item = dst / rel_path
@@ -112,18 +136,19 @@ class TemplateBackup:
112
136
 
113
137
  Restores .moai, .claude, .github directories and CLAUDE.md file
114
138
  from a backup created by create_backup().
139
+ Supports both new timestamped and legacy backup structures.
115
140
 
116
141
  Args:
117
142
  backup_path: Backup path to restore from.
118
- Defaults to .moai-backups/backup/
143
+ If None, automatically finds the latest backup.
119
144
 
120
145
  Raises:
121
- FileNotFoundError: When backup_path doesn't exist.
146
+ FileNotFoundError: When no backup is found.
122
147
  """
123
148
  if backup_path is None:
124
- backup_path = self.backup_dir / "backup"
149
+ backup_path = self.get_latest_backup()
125
150
 
126
- if not backup_path.exists():
151
+ if backup_path is None or not backup_path.exists():
127
152
  raise FileNotFoundError(f"Backup not found: {backup_path}")
128
153
 
129
154
  # Restore each item from backup