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,672 @@
1
+ """CLI commands for Git worktree management."""
2
+
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+
6
+ import click
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+
10
+ from moai_adk.cli.worktree.exceptions import (
11
+ GitOperationError,
12
+ MergeConflictError,
13
+ UncommittedChangesError,
14
+ WorktreeExistsError,
15
+ WorktreeNotFoundError,
16
+ )
17
+ from moai_adk.cli.worktree.manager import WorktreeManager
18
+
19
+ try:
20
+ from git import Repo
21
+ except ImportError:
22
+ Repo = None # type: ignore[misc,assignment]
23
+
24
+ # Initialize Rich console for formatted output
25
+ console = Console()
26
+
27
+
28
+ def get_manager(repo_path: Path | None = None, worktree_root: Path | None = None) -> WorktreeManager:
29
+ """Get or create a WorktreeManager instance.
30
+
31
+ Args:
32
+ repo_path: Path to Git repository. Defaults to current directory.
33
+ worktree_root: Root directory for worktrees. Auto-detects optimal location.
34
+
35
+ Returns:
36
+ WorktreeManager instance.
37
+ """
38
+ # 1. Find Git repository if not specified
39
+ if repo_path is None:
40
+ current_path = Path.cwd()
41
+ # Walk up to find .git directory
42
+ while current_path != current_path.parent:
43
+ if (current_path / ".git").exists():
44
+ repo_path = current_path
45
+ break
46
+ current_path = current_path.parent
47
+
48
+ # Fallback to current directory if no .git found
49
+ if repo_path is None:
50
+ repo_path = Path.cwd()
51
+
52
+ # 2. Auto-detect worktree root if not specified
53
+ if worktree_root is None:
54
+ worktree_root = _detect_worktree_root(repo_path)
55
+
56
+ return WorktreeManager(repo_path=repo_path, worktree_root=worktree_root)
57
+
58
+
59
+ def _detect_worktree_root(repo_path: Path) -> Path:
60
+ """Auto-detect the most appropriate worktree root directory.
61
+
62
+ Args:
63
+ repo_path: Path to the Git repository.
64
+
65
+ Returns:
66
+ Detected worktree root path.
67
+ """
68
+ # Special handling: if we're in a worktree, find the main repo
69
+ main_repo_path = _find_main_repository(repo_path)
70
+
71
+ # Strategy 1: Look for existing registry files in common locations
72
+ potential_roots = [
73
+ Path.home() / "moai" / "worktrees", # MoAI worktrees directory (highest priority)
74
+ Path.home() / "worktrees", # User's worktrees directory
75
+ Path.home() / "moai" / "worktrees" / main_repo_path.name, # MoAI project-specific
76
+ main_repo_path.parent / "worktrees", # Project-level worktrees
77
+ Path("/Users") / Path.home().name / "worktrees", # macOS user worktrees
78
+ Path.home() / "worktrees" / main_repo_path.name, # Alternative organization
79
+ ]
80
+
81
+ for root in potential_roots:
82
+ registry_path = root / ".moai-worktree-registry.json"
83
+ if registry_path.exists():
84
+ try:
85
+ with open(registry_path, "r") as f:
86
+ content = f.read().strip()
87
+ if content and content != "{}":
88
+ return root
89
+ except Exception:
90
+ pass
91
+
92
+ # Strategy 2: Check if there are actual worktrees in standard locations
93
+ for root in potential_roots:
94
+ if root.exists() and any(root.iterdir()):
95
+ # Look for directories that might be worktrees
96
+ for item in root.iterdir():
97
+ if item.is_dir() and (item / ".git").exists():
98
+ return root
99
+
100
+ # Strategy 3: Create a sensible default based on user's system
101
+ # Prefer ~/moai/worktrees for MoAI projects
102
+ default_root = Path.home() / "moai" / "worktrees"
103
+ if default_root.exists() or default_root.parent.exists():
104
+ return default_root
105
+
106
+ # Fallback to user worktrees
107
+ return Path.home() / "worktrees"
108
+
109
+
110
+ def _find_main_repository(start_path: Path) -> Path:
111
+ """Find the main Git repository (not a worktree).
112
+
113
+ Args:
114
+ start_path: Starting path to search from.
115
+
116
+ Returns:
117
+ Path to the main repository.
118
+ """
119
+ current_path = start_path
120
+
121
+ # Walk up to find the main repository (non-worktree)
122
+ while current_path != current_path.parent:
123
+ git_path = current_path / ".git"
124
+ if git_path.exists():
125
+ # Check if this is a worktree or main repo
126
+ if git_path.is_file():
127
+ # This is a worktree - read the main repo path
128
+ try:
129
+ with open(git_path, "r") as f:
130
+ for line in f:
131
+ if line.startswith("gitdir:"):
132
+ gitdir_path = line[8:].strip()
133
+ main_git_path = Path(current_path / gitdir_path).parent.parent
134
+ return main_git_path.resolve()
135
+ except Exception:
136
+ pass
137
+ elif (git_path / "objects").exists():
138
+ # This is the main repository
139
+ return current_path.resolve()
140
+
141
+ current_path = current_path.parent
142
+
143
+ # Fallback to the original path
144
+ return start_path.resolve()
145
+
146
+
147
+ @click.group()
148
+ def worktree() -> None:
149
+ """Manage Git worktrees for parallel SPEC development."""
150
+ pass
151
+
152
+
153
+ @worktree.command(name="new")
154
+ @click.argument("spec_id")
155
+ @click.option("--branch", "-b", default=None, help="Custom branch name")
156
+ @click.option("--base", default="main", help="Base branch to create from")
157
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
158
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
159
+ @click.option("--force", "-f", is_flag=True, help="Force creation even if worktree exists")
160
+ def new_worktree(
161
+ spec_id: str,
162
+ branch: str | None,
163
+ base: str,
164
+ repo: str | None,
165
+ worktree_root: str | None,
166
+ force: bool,
167
+ ) -> None:
168
+ """Create a new worktree for a SPEC.
169
+
170
+ Args:
171
+ spec_id: SPEC ID (e.g., SPEC-AUTH-001)
172
+ branch: Custom branch name (optional)
173
+ base: Base branch to create from (default: main)
174
+ repo: Repository path (optional)
175
+ worktree_root: Worktree root directory (optional)
176
+ """
177
+ try:
178
+ repo_path = Path(repo) if repo else Path.cwd()
179
+ wt_root = Path(worktree_root) if worktree_root else None
180
+
181
+ manager = get_manager(repo_path, wt_root)
182
+ info = manager.create(
183
+ spec_id=spec_id,
184
+ branch_name=branch,
185
+ base_branch=base,
186
+ force=force,
187
+ )
188
+
189
+ console.print("[green]✓[/green] Worktree created successfully")
190
+ console.print(f" SPEC ID: {info.spec_id}")
191
+ console.print(f" Path: {info.path}")
192
+ console.print(f" Branch: {info.branch}")
193
+ console.print(f" Status: {info.status}")
194
+ console.print()
195
+ console.print("[yellow]Next steps:[/yellow]")
196
+ console.print(f" moai-worktree switch {spec_id} # Switch to this worktree")
197
+ console.print(f" moai-worktree go {spec_id} # Get cd command")
198
+
199
+ except WorktreeExistsError as e:
200
+ console.print(f"[red]✗[/red] {e}")
201
+ raise click.Abort()
202
+ except GitOperationError as e:
203
+ console.print(f"[red]✗[/red] {e}")
204
+ raise click.Abort()
205
+
206
+
207
+ @worktree.command(name="list")
208
+ @click.option(
209
+ "--format",
210
+ type=click.Choice(["table", "json"]),
211
+ default="table",
212
+ help="Output format",
213
+ )
214
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
215
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
216
+ def list_worktrees(format: str, repo: str | None, worktree_root: str | None) -> None:
217
+ """List all active worktrees.
218
+
219
+ Args:
220
+ format: Output format (table or json)
221
+ repo: Repository path (optional)
222
+ worktree_root: Worktree root directory (optional)
223
+ """
224
+ try:
225
+ repo_path = Path(repo) if repo else Path.cwd()
226
+ wt_root = Path(worktree_root) if worktree_root else None
227
+
228
+ manager = get_manager(repo_path, wt_root)
229
+ worktrees = manager.list()
230
+
231
+ if not worktrees:
232
+ console.print("[yellow]No worktrees found[/yellow]")
233
+ return
234
+
235
+ if format == "json":
236
+ data = [w.to_dict() for w in worktrees]
237
+ console.print_json(data=data)
238
+ else: # table
239
+ table = Table(title="Git Worktrees")
240
+ table.add_column("SPEC ID", style="cyan")
241
+ table.add_column("Branch", style="magenta")
242
+ table.add_column("Path", style="green")
243
+ table.add_column("Status", style="yellow")
244
+ table.add_column("Created", style="blue")
245
+
246
+ for info in worktrees:
247
+ created = datetime.fromisoformat(info.created_at.replace("Z", "+00:00"))
248
+ table.add_row(
249
+ info.spec_id,
250
+ info.branch,
251
+ str(info.path),
252
+ info.status,
253
+ created.strftime("%Y-%m-%d %H:%M:%S"),
254
+ )
255
+
256
+ console.print(table)
257
+
258
+ except Exception as e:
259
+ console.print(f"[red]✗[/red] Error listing worktrees: {e}")
260
+ raise click.Abort()
261
+
262
+
263
+ @worktree.command(name="switch")
264
+ @click.argument("spec_id")
265
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
266
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
267
+ def switch_worktree(spec_id: str, repo: str | None, worktree_root: str | None) -> None:
268
+ """Switch to a worktree (opens new shell).
269
+
270
+ Args:
271
+ spec_id: SPEC ID to switch to
272
+ repo: Repository path (optional)
273
+ worktree_root: Worktree root directory (optional)
274
+ """
275
+ try:
276
+ repo_path = Path(repo) if repo else Path.cwd()
277
+ wt_root = Path(worktree_root) if worktree_root else None
278
+
279
+ manager = get_manager(repo_path, wt_root)
280
+ info = manager.registry.get(spec_id)
281
+
282
+ if not info:
283
+ console.print(f"[red]✗[/red] Worktree not found: {spec_id}")
284
+ raise click.Abort()
285
+
286
+ import os
287
+ import subprocess
288
+
289
+ shell = os.environ.get("SHELL", "/bin/bash")
290
+ console.print(f"[green]→[/green] Opening new shell in {info.path}")
291
+ subprocess.call([shell], cwd=str(info.path))
292
+
293
+ except Exception as e:
294
+ console.print(f"[red]✗[/red] Error switching worktree: {e}")
295
+ raise click.Abort()
296
+
297
+
298
+ @worktree.command(name="remove")
299
+ @click.argument("spec_id")
300
+ @click.option("--force", "-f", is_flag=True, help="Force remove with uncommitted changes")
301
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
302
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
303
+ def remove_worktree(spec_id: str, force: bool, repo: str | None, worktree_root: str | None) -> None:
304
+ """Remove a worktree.
305
+
306
+ Args:
307
+ spec_id: SPEC ID to remove
308
+ force: Force removal even with uncommitted changes
309
+ repo: Repository path (optional)
310
+ worktree_root: Worktree root directory (optional)
311
+ """
312
+ try:
313
+ repo_path = Path(repo) if repo else Path.cwd()
314
+ wt_root = Path(worktree_root) if worktree_root else None
315
+
316
+ manager = get_manager(repo_path, wt_root)
317
+ manager.remove(spec_id=spec_id, force=force)
318
+
319
+ console.print(f"[green]✓[/green] Worktree removed: {spec_id}")
320
+
321
+ except WorktreeNotFoundError as e:
322
+ console.print(f"[red]✗[/red] {e}")
323
+ raise click.Abort()
324
+ except UncommittedChangesError as e:
325
+ console.print(f"[red]✗[/red] {e}")
326
+ raise click.Abort()
327
+ except GitOperationError as e:
328
+ console.print(f"[red]✗[/red] {e}")
329
+ raise click.Abort()
330
+
331
+
332
+ @worktree.command(name="status")
333
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
334
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
335
+ def status_worktrees(repo: str | None, worktree_root: str | None) -> None:
336
+ """Show worktree status and sync registry.
337
+
338
+ Args:
339
+ repo: Repository path (optional)
340
+ worktree_root: Worktree root directory (optional)
341
+ """
342
+ try:
343
+ repo_path = Path(repo) if repo else Path.cwd()
344
+ wt_root = Path(worktree_root) if worktree_root else None
345
+
346
+ manager = get_manager(repo_path, wt_root)
347
+
348
+ # Sync registry with Git
349
+ manager.registry.sync_with_git(manager.repo)
350
+
351
+ worktrees = manager.list()
352
+
353
+ if not worktrees:
354
+ console.print("[yellow]No worktrees found[/yellow]")
355
+ return
356
+
357
+ console.print(f"[cyan]Total worktrees: {len(worktrees)}[/cyan]")
358
+ console.print()
359
+
360
+ for info in worktrees:
361
+ status_color = "green" if info.status == "active" else "yellow"
362
+ console.print(f"[{status_color}]{info.spec_id}[/{status_color}]")
363
+ console.print(f" Branch: {info.branch}")
364
+ console.print(f" Path: {info.path}")
365
+ console.print(f" Status: {info.status}")
366
+ console.print()
367
+
368
+ except Exception as e:
369
+ console.print(f"[red]✗[/red] Error getting status: {e}")
370
+ raise click.Abort()
371
+
372
+
373
+ @worktree.command(name="go")
374
+ @click.argument("spec_id")
375
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
376
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
377
+ def go_worktree(spec_id: str, repo: str | None, worktree_root: str | None) -> None:
378
+ """Print cd command for shell eval.
379
+
380
+ Usage: eval $(moai-worktree go SPEC-001)
381
+
382
+ Args:
383
+ spec_id: SPEC ID to navigate to
384
+ repo: Repository path (optional)
385
+ worktree_root: Worktree root directory (optional)
386
+ """
387
+ try:
388
+ repo_path = Path(repo) if repo else Path.cwd()
389
+ wt_root = Path(worktree_root) if worktree_root else None
390
+
391
+ manager = get_manager(repo_path, wt_root)
392
+ info = manager.registry.get(spec_id)
393
+
394
+ if not info:
395
+ console.print(f"[red]✗[/red] Worktree not found: {spec_id}")
396
+ raise click.Abort()
397
+
398
+ # Print cd command that can be eval'd
399
+ click.echo(f"cd {info.path}")
400
+
401
+ except Exception as e:
402
+ console.print(f"[red]✗[/red] Error: {e}")
403
+ raise click.Abort()
404
+
405
+
406
+ @worktree.command(name="sync")
407
+ @click.argument("spec_id", required=False)
408
+ @click.option("--base", default="main", help="Base branch to sync from")
409
+ @click.option("--rebase", is_flag=True, help="Use rebase instead of merge")
410
+ @click.option("--ff-only", is_flag=True, help="Only sync if fast-forward is possible")
411
+ @click.option("--all", "sync_all", is_flag=True, help="Sync all worktrees")
412
+ @click.option("--auto-resolve", is_flag=True, help="Automatically resolve conflicts")
413
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
414
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
415
+ def sync_worktree(
416
+ spec_id: str | None,
417
+ base: str,
418
+ rebase: bool,
419
+ ff_only: bool,
420
+ sync_all: bool,
421
+ auto_resolve: bool,
422
+ repo: str | None,
423
+ worktree_root: str | None,
424
+ ) -> None:
425
+ """Sync worktree with base branch.
426
+
427
+ Args:
428
+ spec_id: SPEC ID to sync (optional with --all)
429
+ base: Base branch to sync from (default: main)
430
+ rebase: Use rebase instead of merge
431
+ ff_only: Only sync if fast-forward is possible
432
+ sync_all: Sync all worktrees
433
+ auto_resolve: Automatically resolve conflicts
434
+ repo: Repository path (optional)
435
+ worktree_root: Worktree root directory (optional)
436
+ """
437
+ if not spec_id and not sync_all:
438
+ console.print("[red]✗[/red] Either SPEC_ID or --all option is required")
439
+ raise click.Abort()
440
+
441
+ if spec_id and sync_all:
442
+ console.print("[red]✗[/red] Cannot use both SPEC_ID and --all option")
443
+ raise click.Abort()
444
+
445
+ try:
446
+ repo_path = Path(repo) if repo else Path.cwd()
447
+ wt_root = Path(worktree_root) if worktree_root else None
448
+
449
+ manager = get_manager(repo_path, wt_root)
450
+
451
+ if sync_all:
452
+ # Sync all worktrees
453
+ worktrees = manager.list()
454
+ if not worktrees:
455
+ console.print("[yellow]No worktrees found to sync[/yellow]")
456
+ return
457
+
458
+ console.print(f"[cyan]Syncing {len(worktrees)} worktrees...[/cyan]")
459
+ success_count = 0
460
+ conflict_count = 0
461
+
462
+ for info in worktrees:
463
+ try:
464
+ manager.sync(
465
+ spec_id=info.spec_id,
466
+ base_branch=base,
467
+ rebase=rebase,
468
+ ff_only=ff_only,
469
+ auto_resolve=auto_resolve,
470
+ )
471
+ sync_method = "rebase" if rebase else ("fast-forward" if ff_only else "merge")
472
+ console.print(f"[green]✓[/green] {info.spec_id} ({sync_method})")
473
+ success_count += 1
474
+ except MergeConflictError:
475
+ if auto_resolve:
476
+ # Try to auto-resolve conflicts
477
+ try:
478
+ worktree_repo = Repo(info.path)
479
+ conflicted_files = [info.spec_id] # This will be handled by the method
480
+ manager.auto_resolve_conflicts(worktree_repo, info.spec_id, conflicted_files)
481
+ console.print(f"[yellow]![/yellow] {info.spec_id} (auto-resolved)")
482
+ success_count += 1
483
+ except Exception as e:
484
+ console.print(f"[red]✗[/red] {info.spec_id} (auto-resolve failed: {e})")
485
+ conflict_count += 1
486
+ else:
487
+ console.print(f"[red]✗[/red] {info.spec_id} (conflicts)")
488
+ conflict_count += 1
489
+ except Exception as e:
490
+ console.print(f"[red]✗[/red] {info.spec_id} (failed: {e})")
491
+ conflict_count += 1
492
+
493
+ console.print()
494
+ console.print(f"[green]Summary:[/green] {success_count} synced, {conflict_count} failed")
495
+ else:
496
+ # Sync single worktree
497
+ manager.sync(
498
+ spec_id=spec_id,
499
+ base_branch=base,
500
+ rebase=rebase,
501
+ ff_only=ff_only,
502
+ auto_resolve=auto_resolve,
503
+ )
504
+ sync_method = "rebase" if rebase else ("fast-forward" if ff_only else "merge")
505
+ console.print(f"[green]✓[/green] Worktree synced: {spec_id} ({sync_method})")
506
+
507
+ except WorktreeNotFoundError as e:
508
+ console.print(f"[red]✗[/red] {e}")
509
+ raise click.Abort()
510
+ except GitOperationError as e:
511
+ console.print(f"[red]✗[/red] {e}")
512
+ raise click.Abort()
513
+
514
+
515
+ @worktree.command(name="clean")
516
+ @click.option("--merged-only", is_flag=True, help="Only remove merged branch worktrees")
517
+ @click.option("--interactive", is_flag=True, help="Interactive cleanup with confirmation prompts")
518
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
519
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
520
+ def clean_worktrees(merged_only: bool, interactive: bool, repo: str | None, worktree_root: str | None) -> None:
521
+ """Remove worktrees for merged branches.
522
+
523
+ Args:
524
+ merged_only: Only remove worktrees for merged branches
525
+ interactive: Interactive cleanup with confirmation prompts
526
+ repo: Repository path (optional)
527
+ worktree_root: Worktree root directory (optional)
528
+ """
529
+ try:
530
+ repo_path = Path(repo) if repo else Path.cwd()
531
+ wt_root = Path(worktree_root) if worktree_root else None
532
+
533
+ manager = get_manager(repo_path, wt_root)
534
+
535
+ if merged_only:
536
+ # Only clean merged branches (default behavior)
537
+ cleaned = manager.clean_merged()
538
+ elif interactive:
539
+ # Interactive cleanup
540
+ worktrees = manager.list()
541
+ if not worktrees:
542
+ console.print("[yellow]No worktrees found to clean[/yellow]")
543
+ return
544
+
545
+ console.print(f"[cyan]Found {len(worktrees)} worktrees:[/cyan]")
546
+ for i, info in enumerate(worktrees, 1):
547
+ console.print(f" {i}. [cyan]{info.spec_id}[/cyan] ({info.branch}) - {info.status}")
548
+
549
+ console.print()
550
+ console.print("[yellow]Select worktrees to remove (comma-separated numbers, or 'all'):[/yellow]")
551
+
552
+ try:
553
+ selection = input("> ").strip()
554
+ if selection.lower() == "all":
555
+ cleaned = [info.spec_id for info in worktrees]
556
+ else:
557
+ indices = [int(x.strip()) for x in selection.split(",") if x.strip().isdigit()]
558
+ for idx in indices:
559
+ if 1 <= idx <= len(worktrees):
560
+ cleaned.append(worktrees[idx - 1].spec_id)
561
+ else:
562
+ console.print(f"[red]✗[/red] Invalid index: {idx}")
563
+ raise click.Abort()
564
+
565
+ if not cleaned:
566
+ console.print("[yellow]No worktrees selected for cleanup[/yellow]")
567
+ return
568
+
569
+ # Final confirmation
570
+ console.print(f"[yellow]About to remove {len(cleaned)} worktrees: {', '.join(cleaned)}[/yellow]")
571
+ if input("Continue? [y/N]: ").strip().lower() in ["y", "yes"]:
572
+ for spec_id in cleaned:
573
+ try:
574
+ manager.remove(spec_id, force=True)
575
+ except Exception as e:
576
+ console.print(f"[red]✗[/red] Failed to remove {spec_id}: {e}")
577
+
578
+ console.print("[green]✓[/green] Interactive cleanup completed")
579
+
580
+ except (ValueError, KeyboardInterrupt):
581
+ console.print("[yellow]Interactive cleanup cancelled[/yellow]")
582
+ raise click.Abort()
583
+ else:
584
+ # Default: clean all (legacy behavior)
585
+ worktrees = manager.list()
586
+ if not worktrees:
587
+ console.print("[yellow]No worktrees found to clean[/yellow]")
588
+ return
589
+
590
+ cleaned = [info.spec_id for info in worktrees]
591
+ console.print(
592
+ "[yellow]Removing all worktrees. "
593
+ "Use --merged-only for merged branches only "
594
+ "or --interactive for selective cleanup.[/yellow]"
595
+ )
596
+
597
+ for spec_id in cleaned:
598
+ try:
599
+ manager.remove(spec_id, force=True)
600
+ except Exception as e:
601
+ console.print(f"[red]✗[/red] Failed to remove {spec_id}: {e}")
602
+ cleaned.remove(spec_id)
603
+
604
+ if cleaned:
605
+ console.print(f"[green]✓[/green] Cleaned {len(cleaned)} worktree(s)")
606
+ for spec_id in cleaned:
607
+ console.print(f" - {spec_id}")
608
+ else:
609
+ console.print("[yellow]No worktrees were cleaned[/yellow]")
610
+
611
+ except Exception as e:
612
+ console.print(f"[red]✗[/red] Error cleaning worktrees: {e}")
613
+ raise click.Abort()
614
+
615
+
616
+ @worktree.command(name="config")
617
+ @click.argument("key", required=False)
618
+ @click.argument("value", required=False)
619
+ @click.option("--repo", type=click.Path(), default=None, help="Repository path")
620
+ @click.option("--worktree-root", type=click.Path(), default=None, help="Worktree root directory")
621
+ def config_worktree(key: str | None, value: str | None, repo: str | None, worktree_root: str | None) -> None:
622
+ """Get or set worktree configuration.
623
+
624
+ Supported configuration keys:
625
+ - root: Worktree root directory
626
+ - auto-sync: Enable automatic sync on worktree creation
627
+
628
+ Args:
629
+ key: Configuration key
630
+ value: Configuration value (optional for get)
631
+ repo: Repository path (optional)
632
+ worktree_root: Worktree root directory (optional)
633
+ """
634
+ try:
635
+ repo_path = Path(repo) if repo else Path.cwd()
636
+ wt_root = Path(worktree_root) if worktree_root else None
637
+
638
+ manager = get_manager(repo_path, wt_root)
639
+
640
+ if key is None:
641
+ # No arguments - show all configuration
642
+ console.print("[cyan]Configuration:[/cyan]")
643
+ console.print(f" root: {manager.worktree_root}")
644
+ console.print(f" registry: {manager.registry.registry_path}")
645
+ console.print()
646
+ console.print("[yellow]Available commands:[/yellow]")
647
+ console.print(" moai-worktree config all # Show all config")
648
+ console.print(" moai-worktree config root # Show worktree root")
649
+ console.print(" moai-worktree config registry # Show registry path")
650
+ elif value is None:
651
+ # Get configuration
652
+ if key == "root":
653
+ console.print(f"[cyan]Worktree root:[/cyan] {manager.worktree_root}")
654
+ elif key == "registry":
655
+ console.print(f"[cyan]Registry path:[/cyan] {manager.registry.registry_path}")
656
+ elif key == "all":
657
+ console.print("[cyan]Configuration:[/cyan]")
658
+ console.print(f" root: {manager.worktree_root}")
659
+ console.print(f" registry: {manager.registry.registry_path}")
660
+ else:
661
+ console.print(f"[yellow]Unknown config key: {key}[/yellow]")
662
+ console.print("[yellow]Available keys: root, registry, all[/yellow]")
663
+ else:
664
+ # Set configuration (limited support)
665
+ if key == "root":
666
+ console.print("[yellow]Use --worktree-root option to change root directory[/yellow]")
667
+ else:
668
+ console.print(f"[yellow]Cannot set configuration key: {key}[/yellow]")
669
+
670
+ except Exception as e:
671
+ console.print(f"[red]✗[/red] Error: {e}")
672
+ raise click.Abort()