moai-adk 0.8.0__py3-none-any.whl → 1.1.0__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.
Files changed (881) hide show
  1. moai_adk/__init__.py +2 -6
  2. moai_adk/__main__.py +267 -21
  3. moai_adk/astgrep/__init__.py +37 -0
  4. moai_adk/astgrep/analyzer.py +522 -0
  5. moai_adk/astgrep/models.py +124 -0
  6. moai_adk/astgrep/rules.py +179 -0
  7. moai_adk/cli/__init__.py +6 -2
  8. moai_adk/cli/commands/__init__.py +1 -4
  9. moai_adk/cli/commands/analyze.py +125 -0
  10. moai_adk/cli/commands/doctor.py +24 -6
  11. moai_adk/cli/commands/init.py +437 -57
  12. moai_adk/cli/commands/language.py +254 -0
  13. moai_adk/cli/commands/rank.py +449 -0
  14. moai_adk/cli/commands/status.py +15 -14
  15. moai_adk/cli/commands/switch.py +325 -0
  16. moai_adk/cli/commands/update.py +2195 -93
  17. moai_adk/cli/main.py +3 -2
  18. moai_adk/cli/prompts/init_prompts.py +457 -108
  19. moai_adk/cli/prompts/translations/__init__.py +573 -0
  20. moai_adk/cli/spec_status.py +263 -0
  21. moai_adk/cli/ui/__init__.py +44 -0
  22. moai_adk/cli/ui/progress.py +422 -0
  23. moai_adk/cli/ui/prompts.py +448 -0
  24. moai_adk/cli/ui/theme.py +129 -0
  25. moai_adk/cli/worktree/__init__.py +27 -0
  26. moai_adk/cli/worktree/__main__.py +31 -0
  27. moai_adk/cli/worktree/cli.py +788 -0
  28. moai_adk/cli/worktree/exceptions.py +89 -0
  29. moai_adk/cli/worktree/manager.py +648 -0
  30. moai_adk/cli/worktree/models.py +65 -0
  31. moai_adk/cli/worktree/registry.py +422 -0
  32. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  33. moai_adk/core/__init__.py +0 -1
  34. moai_adk/core/analysis/__init__.py +9 -0
  35. moai_adk/core/analysis/session_analyzer.py +400 -0
  36. moai_adk/core/claude_integration.py +393 -0
  37. moai_adk/core/command_helpers.py +270 -0
  38. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  39. moai_adk/core/config/__init__.py +6 -0
  40. moai_adk/core/config/migration.py +148 -17
  41. moai_adk/core/config/unified.py +617 -0
  42. moai_adk/core/context_manager.py +273 -0
  43. moai_adk/core/credentials.py +264 -0
  44. moai_adk/core/diagnostics/slash_commands.py +0 -1
  45. moai_adk/core/enterprise_features.py +1404 -0
  46. moai_adk/core/error_recovery_system.py +1920 -0
  47. moai_adk/core/event_driven_hook_system.py +1371 -0
  48. moai_adk/core/git/__init__.py +8 -1
  49. moai_adk/core/git/branch.py +0 -1
  50. moai_adk/core/git/branch_manager.py +2 -10
  51. moai_adk/core/git/checkpoint.py +1 -7
  52. moai_adk/core/git/commit.py +0 -1
  53. moai_adk/core/git/conflict_detector.py +422 -0
  54. moai_adk/core/git/event_detector.py +16 -7
  55. moai_adk/core/git/manager.py +91 -2
  56. moai_adk/core/input_validation_middleware.py +1006 -0
  57. moai_adk/core/integration/__init__.py +22 -0
  58. moai_adk/core/integration/engine.py +157 -0
  59. moai_adk/core/integration/integration_tester.py +226 -0
  60. moai_adk/core/integration/models.py +88 -0
  61. moai_adk/core/integration/utils.py +211 -0
  62. moai_adk/core/issue_creator.py +305 -0
  63. moai_adk/core/jit_context_loader.py +956 -0
  64. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  65. moai_adk/core/language_config.py +202 -0
  66. moai_adk/core/language_config_resolver.py +578 -0
  67. moai_adk/core/language_validator.py +543 -0
  68. moai_adk/core/mcp/setup.py +116 -0
  69. moai_adk/core/merge/__init__.py +9 -0
  70. moai_adk/core/merge/analyzer.py +666 -0
  71. moai_adk/core/migration/__init__.py +18 -0
  72. moai_adk/core/migration/alfred_to_moai_migrator.py +389 -0
  73. moai_adk/core/migration/backup_manager.py +327 -0
  74. moai_adk/core/migration/custom_element_scanner.py +358 -0
  75. moai_adk/core/migration/file_migrator.py +381 -0
  76. moai_adk/core/migration/interactive_checkbox_ui.py +499 -0
  77. moai_adk/core/migration/selective_restorer.py +470 -0
  78. moai_adk/core/migration/template_utils.py +74 -0
  79. moai_adk/core/migration/user_selection_ui.py +338 -0
  80. moai_adk/core/migration/version_detector.py +243 -0
  81. moai_adk/core/migration/version_migrator.py +263 -0
  82. moai_adk/core/model_allocator.py +241 -0
  83. moai_adk/core/performance/__init__.py +6 -0
  84. moai_adk/core/performance/cache_system.py +316 -0
  85. moai_adk/core/performance/parallel_processor.py +116 -0
  86. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  87. moai_adk/core/project/__init__.py +0 -1
  88. moai_adk/core/project/backup_utils.py +13 -8
  89. moai_adk/core/project/checker.py +2 -4
  90. moai_adk/core/project/detector.py +189 -22
  91. moai_adk/core/project/initializer.py +177 -29
  92. moai_adk/core/project/phase_executor.py +482 -48
  93. moai_adk/core/project/validator.py +22 -32
  94. moai_adk/core/quality/__init__.py +1 -1
  95. moai_adk/core/quality/trust_checker.py +66 -110
  96. moai_adk/core/quality/validators/__init__.py +1 -1
  97. moai_adk/core/quality/validators/base_validator.py +1 -1
  98. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  99. moai_adk/core/robust_json_parser.py +611 -0
  100. moai_adk/core/rollback_manager.py +953 -0
  101. moai_adk/core/session_manager.py +651 -0
  102. moai_adk/core/skill_loading_system.py +579 -0
  103. moai_adk/core/spec_status_manager.py +478 -0
  104. moai_adk/core/template/__init__.py +0 -1
  105. moai_adk/core/template/backup.py +168 -21
  106. moai_adk/core/template/config.py +141 -45
  107. moai_adk/core/template/languages.py +0 -1
  108. moai_adk/core/template/merger.py +107 -32
  109. moai_adk/core/template/processor.py +1075 -74
  110. moai_adk/core/template_engine.py +319 -0
  111. moai_adk/core/template_variable_synchronizer.py +431 -0
  112. moai_adk/core/unified_permission_manager.py +745 -0
  113. moai_adk/core/user_behavior_analytics.py +851 -0
  114. moai_adk/core/version_sync.py +477 -0
  115. moai_adk/foundation/__init__.py +37 -0
  116. moai_adk/foundation/backend.py +1027 -0
  117. moai_adk/foundation/database.py +1115 -0
  118. moai_adk/foundation/devops.py +1585 -0
  119. moai_adk/foundation/ears.py +431 -0
  120. moai_adk/foundation/frontend.py +870 -0
  121. moai_adk/foundation/git/__init__.py +376 -0
  122. moai_adk/foundation/git/commit_templates.py +557 -0
  123. moai_adk/foundation/langs.py +484 -0
  124. moai_adk/foundation/ml_ops.py +1162 -0
  125. moai_adk/foundation/testing.py +1524 -0
  126. moai_adk/foundation/trust/trust_principles.py +676 -0
  127. moai_adk/foundation/trust/validation_checklist.py +1573 -0
  128. moai_adk/loop/__init__.py +54 -0
  129. moai_adk/loop/controller.py +305 -0
  130. moai_adk/loop/feedback.py +230 -0
  131. moai_adk/loop/state.py +209 -0
  132. moai_adk/loop/storage.py +220 -0
  133. moai_adk/lsp/__init__.py +70 -0
  134. moai_adk/lsp/client.py +320 -0
  135. moai_adk/lsp/models.py +261 -0
  136. moai_adk/lsp/protocol.py +404 -0
  137. moai_adk/lsp/server_manager.py +248 -0
  138. moai_adk/project/__init__.py +0 -0
  139. moai_adk/project/configuration.py +1091 -0
  140. moai_adk/project/documentation.py +566 -0
  141. moai_adk/project/schema.py +447 -0
  142. moai_adk/py.typed +0 -0
  143. moai_adk/ralph/__init__.py +37 -0
  144. moai_adk/ralph/engine.py +307 -0
  145. moai_adk/rank/__init__.py +21 -0
  146. moai_adk/rank/auth.py +425 -0
  147. moai_adk/rank/client.py +557 -0
  148. moai_adk/rank/config.py +147 -0
  149. moai_adk/rank/hook.py +1503 -0
  150. moai_adk/rank/py.typed +0 -0
  151. moai_adk/statusline/__init__.py +41 -0
  152. moai_adk/statusline/alfred_detector.py +105 -0
  153. moai_adk/statusline/config.py +376 -0
  154. moai_adk/statusline/enhanced_output_style_detector.py +372 -0
  155. moai_adk/statusline/git_collector.py +190 -0
  156. moai_adk/statusline/main.py +341 -0
  157. moai_adk/statusline/memory_collector.py +268 -0
  158. moai_adk/statusline/metrics_tracker.py +78 -0
  159. moai_adk/statusline/renderer.py +359 -0
  160. moai_adk/statusline/update_checker.py +129 -0
  161. moai_adk/statusline/version_reader.py +741 -0
  162. moai_adk/tag_system/__init__.py +48 -0
  163. moai_adk/tag_system/atomic_ops.py +117 -0
  164. moai_adk/tag_system/linkage.py +335 -0
  165. moai_adk/tag_system/parser.py +176 -0
  166. moai_adk/tag_system/validator.py +200 -0
  167. moai_adk/templates/.claude/agents/moai/builder-agent.md +490 -0
  168. moai_adk/templates/.claude/agents/moai/builder-command.md +1218 -0
  169. moai_adk/templates/.claude/agents/moai/builder-plugin.md +763 -0
  170. moai_adk/templates/.claude/agents/moai/builder-skill.md +682 -0
  171. moai_adk/templates/.claude/agents/moai/expert-backend.md +963 -0
  172. moai_adk/templates/.claude/agents/moai/expert-debug.md +407 -0
  173. moai_adk/templates/.claude/agents/moai/expert-devops.md +722 -0
  174. moai_adk/templates/.claude/agents/moai/expert-frontend.md +748 -0
  175. moai_adk/templates/.claude/agents/moai/expert-performance.md +661 -0
  176. moai_adk/templates/.claude/agents/moai/expert-refactoring.md +228 -0
  177. moai_adk/templates/.claude/agents/moai/expert-security.md +525 -0
  178. moai_adk/templates/.claude/agents/moai/expert-testing.md +737 -0
  179. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +438 -0
  180. moai_adk/templates/.claude/agents/moai/manager-docs.md +578 -0
  181. moai_adk/templates/.claude/agents/moai/manager-git.md +1092 -0
  182. moai_adk/templates/.claude/agents/moai/manager-project.md +971 -0
  183. moai_adk/templates/.claude/agents/moai/manager-quality.md +641 -0
  184. moai_adk/templates/.claude/agents/moai/manager-spec.md +815 -0
  185. moai_adk/templates/.claude/agents/moai/manager-strategy.md +811 -0
  186. moai_adk/templates/.claude/agents/moai/manager-tdd.md +797 -0
  187. moai_adk/templates/.claude/commands/moai/0-project.md +438 -0
  188. moai_adk/templates/.claude/commands/moai/1-plan.md +1447 -0
  189. moai_adk/templates/.claude/commands/moai/2-run.md +850 -0
  190. moai_adk/templates/.claude/commands/moai/3-sync.md +1398 -0
  191. moai_adk/templates/.claude/commands/moai/9-feedback.md +330 -0
  192. moai_adk/templates/.claude/commands/moai/alfred.md +339 -0
  193. moai_adk/templates/.claude/commands/moai/cancel-loop.md +163 -0
  194. moai_adk/templates/.claude/commands/moai/fix.md +264 -0
  195. moai_adk/templates/.claude/commands/moai/loop.md +363 -0
  196. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  197. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  198. moai_adk/templates/.claude/hooks/moai/lib/README.md +143 -0
  199. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +41 -0
  200. moai_adk/templates/.claude/hooks/moai/lib/alfred_detector.py +105 -0
  201. moai_adk/templates/.claude/hooks/moai/lib/atomic_write.py +122 -0
  202. moai_adk/templates/.claude/hooks/{alfred/core → moai/lib}/checkpoint.py +13 -37
  203. moai_adk/templates/.claude/hooks/moai/lib/common.py +161 -0
  204. moai_adk/templates/.claude/hooks/moai/lib/config.py +376 -0
  205. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +442 -0
  206. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  207. moai_adk/templates/.claude/hooks/moai/lib/enhanced_output_style_detector.py +372 -0
  208. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  209. moai_adk/templates/.claude/hooks/moai/lib/exceptions.py +171 -0
  210. moai_adk/templates/.claude/hooks/moai/lib/file_utils.py +95 -0
  211. moai_adk/templates/.claude/hooks/moai/lib/git_collector.py +190 -0
  212. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +592 -0
  213. moai_adk/templates/.claude/hooks/moai/lib/language_detector.py +298 -0
  214. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +417 -0
  215. moai_adk/templates/.claude/hooks/moai/lib/main.py +341 -0
  216. moai_adk/templates/.claude/hooks/moai/lib/memory_collector.py +268 -0
  217. moai_adk/templates/.claude/hooks/moai/lib/metrics_tracker.py +78 -0
  218. moai_adk/templates/.claude/hooks/moai/lib/models.py +104 -0
  219. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +219 -0
  220. moai_adk/templates/.claude/hooks/moai/lib/project.py +777 -0
  221. moai_adk/templates/.claude/hooks/moai/lib/renderer.py +359 -0
  222. moai_adk/templates/.claude/hooks/moai/lib/tag_linkage.py +333 -0
  223. moai_adk/templates/.claude/hooks/moai/lib/tag_parser.py +176 -0
  224. moai_adk/templates/.claude/hooks/moai/lib/tag_validator.py +200 -0
  225. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  226. moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
  227. moai_adk/templates/.claude/hooks/moai/lib/tool_registry.py +896 -0
  228. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +542 -0
  229. moai_adk/templates/.claude/hooks/moai/lib/update_checker.py +129 -0
  230. moai_adk/templates/.claude/hooks/moai/lib/version_reader.py +741 -0
  231. moai_adk/templates/.claude/hooks/moai/post_tool__ast_grep_scan.py +276 -0
  232. moai_adk/templates/.claude/hooks/moai/post_tool__code_formatter.py +255 -0
  233. moai_adk/templates/.claude/hooks/moai/post_tool__coverage_guard.py +325 -0
  234. moai_adk/templates/.claude/hooks/moai/post_tool__linter.py +315 -0
  235. moai_adk/templates/.claude/hooks/moai/post_tool__lsp_diagnostic.py +508 -0
  236. moai_adk/templates/.claude/hooks/moai/pre_commit__tag_validator.py +287 -0
  237. moai_adk/templates/.claude/hooks/moai/pre_tool__security_guard.py +268 -0
  238. moai_adk/templates/.claude/hooks/moai/pre_tool__tdd_enforcer.py +208 -0
  239. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +894 -0
  240. moai_adk/templates/.claude/hooks/moai/session_end__rank_submit.py +69 -0
  241. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +1170 -0
  242. moai_adk/templates/.claude/hooks/moai/shared/utils/announcement_translator.py +206 -0
  243. moai_adk/templates/.claude/hooks/moai/stop__loop_controller.py +621 -0
  244. moai_adk/templates/.claude/output-styles/moai/alfred.md +758 -0
  245. moai_adk/templates/.claude/output-styles/moai/r2d2.md +643 -0
  246. moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
  247. moai_adk/templates/.claude/settings.json +177 -72
  248. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +303 -0
  249. moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +252 -0
  250. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +56 -0
  251. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +120 -0
  252. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  253. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +185 -0
  254. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +207 -0
  255. moai_adk/templates/.claude/skills/moai-docs-generation/reference.md +234 -0
  256. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +132 -281
  257. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +610 -1525
  258. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +423 -619
  259. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +133 -77
  260. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +817 -16
  261. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  262. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  263. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  264. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  265. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +532 -17
  266. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +91 -78
  267. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +955 -16
  268. moai_adk/templates/.claude/skills/moai-domain-frontend/modules/component-architecture.md +723 -0
  269. moai_adk/templates/.claude/skills/moai-domain-frontend/modules/nextjs16-patterns.md +713 -0
  270. moai_adk/templates/.claude/skills/moai-domain-frontend/modules/performance-optimization.md +694 -0
  271. moai_adk/templates/.claude/skills/moai-domain-frontend/modules/react19-patterns.md +591 -0
  272. moai_adk/templates/.claude/skills/moai-domain-frontend/modules/state-management.md +680 -0
  273. moai_adk/templates/.claude/skills/moai-domain-frontend/modules/vue35-patterns.md +802 -0
  274. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +651 -18
  275. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +234 -0
  276. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  277. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  278. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  279. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  280. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  281. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  282. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +189 -0
  283. moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -0
  284. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +327 -0
  285. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  286. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  287. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  288. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  289. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  290. moai_adk/templates/.claude/skills/moai-formats-data/reference.md +585 -0
  291. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +225 -0
  292. moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -0
  293. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/advanced-agent-patterns.md +370 -0
  294. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  295. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-cli-reference-official.md +420 -0
  296. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +739 -0
  297. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-devcontainers-official.md +381 -0
  298. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-discover-plugins-official.md +379 -0
  299. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-headless-official.md +378 -0
  300. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +670 -0
  301. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  302. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  303. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-plugin-marketplaces-official.md +308 -0
  304. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-plugins-official.md +640 -0
  305. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sandboxing-official.md +282 -0
  306. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  307. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +467 -0
  308. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-statusline-official.md +293 -0
  309. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +420 -0
  310. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  311. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  312. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  313. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  314. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  315. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  316. moai_adk/templates/.claude/skills/moai-foundation-claude/reference.md +209 -0
  317. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +221 -0
  318. moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
  319. moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
  320. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +242 -0
  321. moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -0
  322. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  323. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +359 -0
  324. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  325. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-advanced.md +279 -0
  326. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-implementation.md +267 -0
  327. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +228 -0
  328. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  329. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  330. moai_adk/templates/.claude/skills/moai-foundation-core/modules/patterns.md +22 -0
  331. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  332. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-ears-format.md +200 -0
  333. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +171 -0
  334. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-tdd-implementation.md +275 -0
  335. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  336. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +239 -0
  337. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-implementation.md +244 -0
  338. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-validation.md +219 -0
  339. moai_adk/templates/.claude/skills/moai-foundation-core/reference.md +478 -0
  340. moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +311 -0
  341. moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
  342. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
  343. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
  344. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
  345. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
  346. moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
  347. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +180 -0
  348. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  349. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  350. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  351. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  352. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  353. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  354. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  355. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  356. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  357. moai_adk/templates/.claude/skills/moai-framework-electron/SKILL.md +288 -0
  358. moai_adk/templates/.claude/skills/moai-framework-electron/examples.md +2082 -0
  359. moai_adk/templates/.claude/skills/moai-framework-electron/reference.md +1649 -0
  360. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +96 -77
  361. moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +1226 -16
  362. moai_adk/templates/.claude/skills/moai-lang-cpp/modules/advanced-patterns.md +401 -0
  363. moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +1119 -14
  364. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +80 -79
  365. moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +572 -16
  366. moai_adk/templates/.claude/skills/moai-lang-csharp/modules/aspnet-core.md +627 -0
  367. moai_adk/templates/.claude/skills/moai-lang-csharp/modules/blazor-components.md +767 -0
  368. moai_adk/templates/.claude/skills/moai-lang-csharp/modules/cqrs-validation.md +626 -0
  369. moai_adk/templates/.claude/skills/moai-lang-csharp/modules/csharp12-features.md +580 -0
  370. moai_adk/templates/.claude/skills/moai-lang-csharp/modules/efcore-patterns.md +622 -0
  371. moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +388 -15
  372. moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +135 -0
  373. moai_adk/templates/.claude/skills/moai-lang-elixir/examples.md +1171 -0
  374. moai_adk/templates/.claude/skills/moai-lang-elixir/modules/advanced-patterns.md +531 -0
  375. moai_adk/templates/.claude/skills/moai-lang-elixir/reference.md +889 -0
  376. moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +104 -0
  377. moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
  378. moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
  379. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +153 -80
  380. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +906 -16
  381. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +721 -15
  382. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +117 -80
  383. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +851 -16
  384. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +278 -18
  385. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +133 -79
  386. moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +960 -16
  387. moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +1528 -17
  388. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +100 -79
  389. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +993 -16
  390. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +549 -18
  391. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +135 -76
  392. moai_adk/templates/.claude/skills/moai-lang-php/examples.md +1595 -16
  393. moai_adk/templates/.claude/skills/moai-lang-php/modules/advanced-patterns.md +538 -0
  394. moai_adk/templates/.claude/skills/moai-lang-php/reference.md +1309 -16
  395. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +141 -341
  396. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +849 -496
  397. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +731 -243
  398. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +134 -76
  399. moai_adk/templates/.claude/skills/moai-lang-r/examples.md +1141 -16
  400. moai_adk/templates/.claude/skills/moai-lang-r/modules/advanced-patterns.md +489 -0
  401. moai_adk/templates/.claude/skills/moai-lang-r/reference.md +1074 -17
  402. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +136 -77
  403. moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +1093 -16
  404. moai_adk/templates/.claude/skills/moai-lang-ruby/modules/advanced-patterns.md +309 -0
  405. moai_adk/templates/.claude/skills/moai-lang-ruby/modules/testing-patterns.md +306 -0
  406. moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +1010 -17
  407. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +112 -78
  408. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +646 -16
  409. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +491 -18
  410. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +113 -75
  411. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +620 -16
  412. moai_adk/templates/.claude/skills/moai-lang-scala/modules/akka-actors.md +479 -0
  413. moai_adk/templates/.claude/skills/moai-lang-scala/modules/cats-effect.md +489 -0
  414. moai_adk/templates/.claude/skills/moai-lang-scala/modules/functional-programming.md +460 -0
  415. moai_adk/templates/.claude/skills/moai-lang-scala/modules/spark-data.md +498 -0
  416. moai_adk/templates/.claude/skills/moai-lang-scala/modules/zio-patterns.md +541 -0
  417. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +410 -17
  418. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +88 -83
  419. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +905 -16
  420. moai_adk/templates/.claude/skills/moai-lang-swift/modules/combine-reactive.md +256 -0
  421. moai_adk/templates/.claude/skills/moai-lang-swift/modules/concurrency.md +270 -0
  422. moai_adk/templates/.claude/skills/moai-lang-swift/modules/swift6-features.md +265 -0
  423. moai_adk/templates/.claude/skills/moai-lang-swift/modules/swiftui-patterns.md +314 -0
  424. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +659 -17
  425. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +115 -82
  426. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1076 -16
  427. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +718 -21
  428. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +145 -0
  429. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  430. moai_adk/templates/.claude/skills/moai-library-mermaid/modules/advanced-patterns.md +465 -0
  431. moai_adk/templates/.claude/skills/moai-library-mermaid/modules/optimization.md +440 -0
  432. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  433. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +143 -0
  434. moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -0
  435. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  436. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +336 -0
  437. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +350 -0
  438. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  439. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  440. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  441. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  442. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  443. moai_adk/templates/.claude/skills/moai-library-nextra/modules/optimization.md +303 -0
  444. moai_adk/templates/.claude/skills/moai-library-nextra/reference.md +379 -0
  445. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +175 -0
  446. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  447. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  448. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  449. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  450. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  451. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  452. moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +284 -0
  453. moai_adk/templates/.claude/skills/moai-platform-auth0/examples.md +2446 -0
  454. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/adaptive-mfa.md +233 -0
  455. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/akamai-integration.md +214 -0
  456. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/application-credentials.md +280 -0
  457. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/attack-protection-log-events.md +224 -0
  458. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/attack-protection-overview.md +140 -0
  459. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/bot-detection.md +144 -0
  460. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/breached-password-detection.md +187 -0
  461. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/brute-force-protection.md +189 -0
  462. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/certifications.md +282 -0
  463. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/compliance-overview.md +263 -0
  464. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/continuous-session-protection.md +307 -0
  465. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/customize-mfa.md +177 -0
  466. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/dpop-implementation.md +283 -0
  467. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/fapi-implementation.md +259 -0
  468. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/gdpr-compliance.md +313 -0
  469. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/guardian-configuration.md +269 -0
  470. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/highly-regulated-identity.md +272 -0
  471. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/jwt-fundamentals.md +248 -0
  472. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/mdl-verification.md +210 -0
  473. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/mfa-api-management.md +278 -0
  474. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/mfa-factors.md +226 -0
  475. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/mfa-overview.md +174 -0
  476. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/mtls-sender-constraining.md +316 -0
  477. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/ropg-flow-mfa.md +216 -0
  478. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/security-center.md +325 -0
  479. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/security-guidance.md +277 -0
  480. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/state-parameters.md +177 -0
  481. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/step-up-authentication.md +251 -0
  482. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/suspicious-ip-throttling.md +240 -0
  483. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/tenant-access-control.md +179 -0
  484. moai_adk/templates/.claude/skills/moai-platform-auth0/modules/webauthn-fido.md +235 -0
  485. moai_adk/templates/.claude/skills/moai-platform-auth0/reference.md +224 -0
  486. moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +135 -0
  487. moai_adk/templates/.claude/skills/moai-platform-clerk/examples.md +1426 -0
  488. moai_adk/templates/.claude/skills/moai-platform-clerk/modules/advanced-patterns.md +417 -0
  489. moai_adk/templates/.claude/skills/moai-platform-clerk/reference.md +273 -0
  490. moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +158 -0
  491. moai_adk/templates/.claude/skills/moai-platform-convex/examples.md +506 -0
  492. moai_adk/templates/.claude/skills/moai-platform-convex/modules/auth-integration.md +421 -0
  493. moai_adk/templates/.claude/skills/moai-platform-convex/modules/file-storage.md +474 -0
  494. moai_adk/templates/.claude/skills/moai-platform-convex/modules/reactive-queries.md +302 -0
  495. moai_adk/templates/.claude/skills/moai-platform-convex/modules/server-functions.md +452 -0
  496. moai_adk/templates/.claude/skills/moai-platform-convex/reference.md +385 -0
  497. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +166 -0
  498. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/examples.md +514 -0
  499. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/modules/custom-claims.md +374 -0
  500. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/modules/phone-auth.md +372 -0
  501. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/modules/social-auth.md +339 -0
  502. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/reference.md +382 -0
  503. moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +127 -0
  504. moai_adk/templates/.claude/skills/moai-platform-firestore/examples.md +445 -0
  505. moai_adk/templates/.claude/skills/moai-platform-firestore/modules/offline-cache.md +392 -0
  506. moai_adk/templates/.claude/skills/moai-platform-firestore/modules/realtime-listeners.md +441 -0
  507. moai_adk/templates/.claude/skills/moai-platform-firestore/modules/security-rules.md +352 -0
  508. moai_adk/templates/.claude/skills/moai-platform-firestore/modules/transactions.md +452 -0
  509. moai_adk/templates/.claude/skills/moai-platform-firestore/reference.md +322 -0
  510. moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +156 -0
  511. moai_adk/templates/.claude/skills/moai-platform-neon/examples.md +470 -0
  512. moai_adk/templates/.claude/skills/moai-platform-neon/modules/auto-scaling.md +349 -0
  513. moai_adk/templates/.claude/skills/moai-platform-neon/modules/branching-workflows.md +354 -0
  514. moai_adk/templates/.claude/skills/moai-platform-neon/modules/connection-pooling.md +412 -0
  515. moai_adk/templates/.claude/skills/moai-platform-neon/modules/pitr-backups.md +458 -0
  516. moai_adk/templates/.claude/skills/moai-platform-neon/reference.md +272 -0
  517. moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +146 -0
  518. moai_adk/templates/.claude/skills/moai-platform-railway/examples.md +539 -0
  519. moai_adk/templates/.claude/skills/moai-platform-railway/modules/docker-deployment.md +261 -0
  520. moai_adk/templates/.claude/skills/moai-platform-railway/modules/multi-service.md +291 -0
  521. moai_adk/templates/.claude/skills/moai-platform-railway/modules/networking-domains.md +338 -0
  522. moai_adk/templates/.claude/skills/moai-platform-railway/modules/volumes-storage.md +353 -0
  523. moai_adk/templates/.claude/skills/moai-platform-railway/reference.md +374 -0
  524. moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +141 -0
  525. moai_adk/templates/.claude/skills/moai-platform-supabase/examples.md +502 -0
  526. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/auth-integration.md +384 -0
  527. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/edge-functions.md +371 -0
  528. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/postgresql-pgvector.md +231 -0
  529. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/realtime-presence.md +354 -0
  530. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/row-level-security.md +286 -0
  531. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/storage-cdn.md +319 -0
  532. moai_adk/templates/.claude/skills/moai-platform-supabase/modules/typescript-patterns.md +453 -0
  533. moai_adk/templates/.claude/skills/moai-platform-supabase/reference.md +284 -0
  534. moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +132 -0
  535. moai_adk/templates/.claude/skills/moai-platform-vercel/examples.md +502 -0
  536. moai_adk/templates/.claude/skills/moai-platform-vercel/modules/analytics-speed.md +348 -0
  537. moai_adk/templates/.claude/skills/moai-platform-vercel/modules/deployment-config.md +344 -0
  538. moai_adk/templates/.claude/skills/moai-platform-vercel/modules/edge-functions.md +222 -0
  539. moai_adk/templates/.claude/skills/moai-platform-vercel/modules/isr-caching.md +306 -0
  540. moai_adk/templates/.claude/skills/moai-platform-vercel/modules/kv-storage.md +399 -0
  541. moai_adk/templates/.claude/skills/moai-platform-vercel/reference.md +360 -0
  542. moai_adk/templates/.claude/skills/moai-tool-ast-grep/SKILL.md +193 -0
  543. moai_adk/templates/.claude/skills/moai-tool-ast-grep/examples.md +1099 -0
  544. moai_adk/templates/.claude/skills/moai-tool-ast-grep/modules/language-specific.md +307 -0
  545. moai_adk/templates/.claude/skills/moai-tool-ast-grep/modules/pattern-syntax.md +237 -0
  546. moai_adk/templates/.claude/skills/moai-tool-ast-grep/modules/refactoring-patterns.md +260 -0
  547. moai_adk/templates/.claude/skills/moai-tool-ast-grep/modules/security-rules.md +239 -0
  548. moai_adk/templates/.claude/skills/moai-tool-ast-grep/reference.md +288 -0
  549. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/languages/go.yml +90 -0
  550. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/languages/python.yml +101 -0
  551. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/languages/typescript.yml +83 -0
  552. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/quality/complexity-check.yml +94 -0
  553. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/quality/deprecated-apis.yml +84 -0
  554. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/security/secrets-detection.yml +89 -0
  555. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/security/sql-injection.yml +45 -0
  556. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/security/xss-prevention.yml +50 -0
  557. moai_adk/templates/.claude/skills/moai-tool-ast-grep/rules/sgconfig.yml +54 -0
  558. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +251 -0
  559. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
  560. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/modules/advanced-patterns.md +379 -0
  561. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/modules/optimization.md +286 -0
  562. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
  563. moai_adk/templates/.claude/skills/moai-workflow-loop/SKILL.md +197 -0
  564. moai_adk/templates/.claude/skills/moai-workflow-loop/examples.md +1063 -0
  565. moai_adk/templates/.claude/skills/moai-workflow-loop/reference.md +1414 -0
  566. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  567. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +287 -0
  568. moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -0
  569. moai_adk/templates/.claude/skills/moai-workflow-project/reference.md +275 -0
  570. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  571. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1434 -0
  572. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  573. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  574. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  575. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +92 -0
  576. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  577. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  578. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  579. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  580. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  581. moai_adk/templates/.claude/skills/moai-workflow-spec/SKILL.md +337 -0
  582. moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
  583. moai_adk/templates/.claude/skills/moai-workflow-spec/modules/advanced-patterns.md +237 -0
  584. moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
  585. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +270 -0
  586. moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -0
  587. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  588. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  589. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  590. moai_adk/templates/.claude/skills/moai-workflow-templates/reference.md +346 -0
  591. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  592. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +269 -0
  593. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  594. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  595. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  596. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  597. moai_adk/templates/.claude/skills/moai-workflow-testing/examples.md +672 -0
  598. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +269 -0
  599. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/advanced-patterns.md +576 -0
  600. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +302 -0
  601. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/context7-integration.md +286 -0
  602. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/review-workflows.md +500 -0
  603. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework/relevance-analysis.md +154 -0
  604. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework/safety-analysis.md +148 -0
  605. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework/scoring-algorithms.md +196 -0
  606. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework/timeliness-analysis.md +168 -0
  607. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework/truthfulness-analysis.md +136 -0
  608. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework/usability-analysis.md +153 -0
  609. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review/trust5-framework.md +257 -0
  610. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +263 -0
  611. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/code-review/analysis-patterns.md +340 -0
  612. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/code-review/core-classes.md +299 -0
  613. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/code-review/tool-integration.md +380 -0
  614. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/debugging/debugging-workflows.md +451 -0
  615. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/debugging/error-analysis.md +442 -0
  616. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/optimization.md +505 -0
  617. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance/optimization-patterns.md +473 -0
  618. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance/profiling-techniques.md +481 -0
  619. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization/ai-optimization.md +241 -0
  620. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization/bottleneck-detection.md +397 -0
  621. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization/optimization-plan.md +315 -0
  622. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization/profiler-core.md +277 -0
  623. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization/real-time-monitoring.md +187 -0
  624. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +327 -0
  625. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/quality-metrics.md +415 -0
  626. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/refactoring/ai-workflows.md +620 -0
  627. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/refactoring/patterns.md +692 -0
  628. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/security-analysis.md +429 -0
  629. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +313 -0
  630. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/static-analysis.md +438 -0
  631. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd/core-classes.md +397 -0
  632. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7/advanced-features.md +494 -0
  633. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7/red-green-refactor.md +316 -0
  634. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7/test-generation.md +471 -0
  635. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7/test-patterns.md +371 -0
  636. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +265 -0
  637. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/trust5-validation.md +428 -0
  638. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  639. moai_adk/templates/.claude/skills/moai-workflow-testing/reference.md +440 -0
  640. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  641. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  642. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  643. moai_adk/templates/.claude/skills/moai-workflow-worktree/SKILL.md +228 -0
  644. moai_adk/templates/.claude/skills/moai-workflow-worktree/examples.md +606 -0
  645. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/integration-patterns.md +149 -0
  646. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/moai-adk-integration.md +245 -0
  647. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/parallel-advanced.md +310 -0
  648. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/parallel-development.md +202 -0
  649. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/parallel-workflows.md +302 -0
  650. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/registry-architecture.md +271 -0
  651. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/resource-optimization.md +300 -0
  652. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/tools-integration.md +280 -0
  653. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/troubleshooting.md +397 -0
  654. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/worktree-commands.md +296 -0
  655. moai_adk/templates/.claude/skills/moai-workflow-worktree/modules/worktree-management.md +217 -0
  656. moai_adk/templates/.claude/skills/moai-workflow-worktree/reference.md +357 -0
  657. moai_adk/templates/.git-hooks/pre-commit +128 -0
  658. moai_adk/templates/.git-hooks/pre-push +468 -0
  659. moai_adk/templates/.github/workflows/ci-universal.yml +1314 -0
  660. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  661. moai_adk/templates/.github/workflows/spec-issue-sync.yml +206 -36
  662. moai_adk/templates/.gitignore +152 -13
  663. moai_adk/templates/.lsp.json +152 -0
  664. moai_adk/templates/.mcp.json +13 -0
  665. moai_adk/templates/.moai/announcements/en.json +18 -0
  666. moai_adk/templates/.moai/announcements/ja.json +18 -0
  667. moai_adk/templates/.moai/announcements/ko.json +18 -0
  668. moai_adk/templates/.moai/announcements/zh.json +18 -0
  669. moai_adk/templates/.moai/config/config.yaml +64 -0
  670. moai_adk/templates/.moai/config/multilingual-triggers.yaml +213 -0
  671. moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -0
  672. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  673. moai_adk/templates/.moai/config/sections/llm.yaml +41 -0
  674. moai_adk/templates/.moai/config/sections/pricing.yaml +30 -0
  675. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  676. moai_adk/templates/.moai/config/sections/quality.yaml +55 -0
  677. moai_adk/templates/.moai/config/sections/ralph.yaml +55 -0
  678. moai_adk/templates/.moai/config/sections/system.yaml +59 -0
  679. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  680. moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
  681. moai_adk/templates/.moai/llm-configs/glm.json +22 -0
  682. moai_adk/templates/CLAUDE.ja.md +343 -0
  683. moai_adk/templates/CLAUDE.ko.md +343 -0
  684. moai_adk/templates/CLAUDE.md +274 -246
  685. moai_adk/templates/CLAUDE.zh.md +343 -0
  686. moai_adk/utils/__init__.py +24 -2
  687. moai_adk/utils/banner.py +9 -13
  688. moai_adk/utils/common.py +331 -0
  689. moai_adk/utils/link_validator.py +241 -0
  690. moai_adk/utils/logger.py +4 -9
  691. moai_adk/utils/safe_file_reader.py +206 -0
  692. moai_adk/utils/timeout.py +160 -0
  693. moai_adk/utils/toon_utils.py +256 -0
  694. moai_adk/version.py +22 -0
  695. moai_adk-1.1.0.dist-info/METADATA +2443 -0
  696. moai_adk-1.1.0.dist-info/RECORD +701 -0
  697. {moai_adk-0.8.0.dist-info → moai_adk-1.1.0.dist-info}/WHEEL +1 -1
  698. moai_adk-1.1.0.dist-info/entry_points.txt +5 -0
  699. moai_adk-1.1.0.dist-info/licenses/LICENSE +99 -0
  700. moai_adk/cli/commands/backup.py +0 -80
  701. moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -293
  702. moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -196
  703. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -207
  704. moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -375
  705. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -343
  706. moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -246
  707. moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -320
  708. moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -837
  709. moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -272
  710. moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -265
  711. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -311
  712. moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -352
  713. moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1184
  714. moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -665
  715. moai_adk/templates/.claude/commands/alfred/2-run.md +0 -488
  716. moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -623
  717. moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
  718. moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
  719. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -174
  720. moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -170
  721. moai_adk/templates/.claude/hooks/alfred/core/context.py +0 -67
  722. moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -416
  723. moai_adk/templates/.claude/hooks/alfred/core/tags.py +0 -198
  724. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -21
  725. moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
  726. moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -161
  727. moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -90
  728. moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -42
  729. moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
  730. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
  731. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
  732. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
  733. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
  734. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
  735. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
  736. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
  737. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
  738. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
  739. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
  740. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
  741. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
  742. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
  743. moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
  744. moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
  745. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
  746. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
  747. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
  748. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
  749. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
  750. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
  751. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
  752. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
  753. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
  754. moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
  755. moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
  756. moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
  757. moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
  758. moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
  759. moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
  760. moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
  761. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
  762. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
  763. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
  764. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
  765. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
  766. moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
  767. moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
  768. moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
  769. moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
  770. moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
  771. moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
  772. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
  773. moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
  774. moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
  775. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
  776. moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
  777. moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
  778. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
  779. moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
  780. moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
  781. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
  782. moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
  783. moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
  784. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
  785. moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
  786. moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
  787. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
  788. moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
  789. moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
  790. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
  791. moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
  792. moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
  793. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
  794. moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
  795. moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
  796. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
  797. moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
  798. moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
  799. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
  800. moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
  801. moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
  802. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
  803. moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
  804. moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
  805. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -113
  806. moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
  807. moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
  808. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
  809. moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
  810. moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
  811. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
  812. moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
  813. moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
  814. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
  815. moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
  816. moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
  817. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
  818. moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
  819. moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
  820. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
  821. moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
  822. moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
  823. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
  824. moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
  825. moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
  826. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
  827. moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
  828. moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
  829. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
  830. moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
  831. moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
  832. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
  833. moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
  834. moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
  835. moai_adk/templates/.claude/skills/moai-skill-factory/CHECKLIST.md +0 -482
  836. moai_adk/templates/.claude/skills/moai-skill-factory/EXAMPLES.md +0 -278
  837. moai_adk/templates/.claude/skills/moai-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
  838. moai_adk/templates/.claude/skills/moai-skill-factory/METADATA.md +0 -477
  839. moai_adk/templates/.claude/skills/moai-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
  840. moai_adk/templates/.claude/skills/moai-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
  841. moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
  842. moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
  843. moai_adk/templates/.claude/skills/moai-skill-factory/SKILL.md +0 -271
  844. moai_adk/templates/.claude/skills/moai-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
  845. moai_adk/templates/.claude/skills/moai-skill-factory/STRUCTURE.md +0 -583
  846. moai_adk/templates/.claude/skills/moai-skill-factory/WEB-RESEARCH.md +0 -526
  847. moai_adk/templates/.claude/skills/moai-skill-factory/reference.md +0 -465
  848. moai_adk/templates/.claude/skills/moai-skill-factory/scripts/generate-structure.sh +0 -328
  849. moai_adk/templates/.claude/skills/moai-skill-factory/scripts/validate-skill.sh +0 -312
  850. moai_adk/templates/.claude/skills/moai-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
  851. moai_adk/templates/.claude/skills/moai-skill-factory/templates/examples-template.md +0 -285
  852. moai_adk/templates/.claude/skills/moai-skill-factory/templates/reference-template.md +0 -278
  853. moai_adk/templates/.claude/skills/moai-skill-factory/templates/scripts-template.sh +0 -303
  854. moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +0 -137
  855. moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +0 -218
  856. moai_adk/templates/.claude/skills/moai-spec-authoring/examples/validate-spec.sh +0 -161
  857. moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +0 -541
  858. moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +0 -622
  859. moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
  860. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
  861. moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -256
  862. moai_adk/templates/.moai/config.json +0 -96
  863. moai_adk/templates/.moai/memory/CLAUDE-AGENTS-GUIDE.md +0 -208
  864. moai_adk/templates/.moai/memory/CLAUDE-PRACTICES.md +0 -369
  865. moai_adk/templates/.moai/memory/CLAUDE-RULES.md +0 -539
  866. moai_adk/templates/.moai/memory/CONFIG-SCHEMA.md +0 -444
  867. moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
  868. moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +0 -220
  869. moai_adk/templates/.moai/memory/SKILLS-DESCRIPTION-POLICY.md +0 -218
  870. moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
  871. moai_adk/templates/.moai/memory/config-schema.md +0 -444
  872. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
  873. moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
  874. moai_adk/templates/.moai/project/product.md +0 -161
  875. moai_adk/templates/.moai/project/structure.md +0 -156
  876. moai_adk/templates/.moai/project/tech.md +0 -227
  877. moai_adk/templates/__init__.py +0 -2
  878. moai_adk-0.8.0.dist-info/METADATA +0 -1722
  879. moai_adk-0.8.0.dist-info/RECORD +0 -282
  880. moai_adk-0.8.0.dist-info/entry_points.txt +0 -2
  881. moai_adk-0.8.0.dist-info/licenses/LICENSE +0 -21
@@ -13,6 +13,7 @@ Includes:
13
13
  - 70-80% performance improvement for up-to-date projects
14
14
 
15
15
  ## Skill Invocation Guide (English-Only)
16
+ # mypy: disable-error-code=return-value
16
17
 
17
18
  ### Related Skills
18
19
  - **moai-foundation-trust**: For post-update validation
@@ -25,34 +26,56 @@ Includes:
25
26
 
26
27
  ### When to Invoke Skills in Related Workflows
27
28
  1. **After successful update**:
28
- - Run `Skill("moai-foundation-trust")` to validate all TRUST 5 gates
29
+ - Run `Skill("moai-foundation-trust")` to validate all TRUST 4 gates
29
30
  - Run `Skill("moai-foundation-langs")` to confirm language toolchain still works
30
31
  - Run project doctor command for full system validation
31
32
 
32
33
  2. **Before updating**:
33
34
  - Create backup with `python -m moai_adk backup`
34
- - Run `Skill("moai-foundation-tags")` to document current TAG state
35
35
 
36
36
  3. **If update fails**:
37
37
  - Use backup to restore previous state
38
38
  - Debug with `python -m moai_adk doctor --verbose`
39
39
  """
40
+
41
+ # type: ignore
42
+
40
43
  from __future__ import annotations
41
44
 
42
45
  import json
46
+ import logging
47
+ import os
48
+ import shutil
43
49
  import subprocess
50
+ import sys
44
51
  from datetime import datetime
45
52
  from pathlib import Path
46
- from typing import Any, cast
53
+ from typing import Any, Union, cast
47
54
 
48
55
  import click
56
+ import yaml
49
57
  from packaging import version
50
58
  from rich.console import Console
51
59
 
52
60
  from moai_adk import __version__
61
+ from moai_adk.core.merge import MergeAnalyzer
62
+ from moai_adk.core.migration import VersionMigrator
63
+ from moai_adk.core.migration.alfred_to_moai_migrator import AlfredToMoaiMigrator
64
+
65
+ # Import new custom element restoration modules
66
+ from moai_adk.core.migration.custom_element_scanner import create_custom_element_scanner
67
+ from moai_adk.core.migration.selective_restorer import create_selective_restorer
68
+ from moai_adk.core.migration.user_selection_ui import create_user_selection_ui
53
69
  from moai_adk.core.template.processor import TemplateProcessor
70
+ from moai_adk.utils.common import reset_stdin
54
71
 
55
- console = Console()
72
+ # Force UTF-8 encoding for Windows compatibility
73
+ # Windows PowerShell/Console uses 'charmap' by default, which can't encode emojis
74
+ if sys.platform == "win32":
75
+ console = Console(force_terminal=True, legacy_windows=False)
76
+ else:
77
+ console = Console()
78
+ logger = logging.getLogger(__name__)
56
79
 
57
80
  # Constants for tool detection
58
81
  TOOL_DETECTION_TIMEOUT = 5 # seconds
@@ -61,33 +84,76 @@ PIPX_COMMAND = ["pipx", "upgrade", "moai-adk"]
61
84
  PIP_COMMAND = ["pip", "install", "--upgrade", "moai-adk"]
62
85
 
63
86
 
64
- # @CODE:UPDATE-REFACTOR-002-004
65
87
  # Custom exceptions for better error handling
66
88
  class UpdateError(Exception):
67
89
  """Base exception for update operations."""
90
+
68
91
  pass
69
92
 
70
93
 
71
94
  class InstallerNotFoundError(UpdateError):
72
95
  """Raised when no package installer detected."""
96
+
73
97
  pass
74
98
 
75
99
 
76
100
  class NetworkError(UpdateError):
77
101
  """Raised when network operation fails."""
102
+
78
103
  pass
79
104
 
80
105
 
81
106
  class UpgradeError(UpdateError):
82
107
  """Raised when package upgrade fails."""
108
+
83
109
  pass
84
110
 
85
111
 
86
112
  class TemplateSyncError(UpdateError):
87
113
  """Raised when template sync fails."""
114
+
88
115
  pass
89
116
 
90
117
 
118
+ def _get_config_path(project_path: Path) -> tuple[Path, bool]:
119
+ """Get config file path, preferring YAML over JSON.
120
+
121
+ Returns:
122
+ Tuple of (config_path, is_yaml)
123
+ """
124
+ yaml_path = project_path / ".moai" / "config" / "config.yaml"
125
+ json_path = project_path / ".moai" / "config" / "config.json"
126
+
127
+ if yaml_path.exists():
128
+ return yaml_path, True
129
+ return json_path, False
130
+
131
+
132
+ def _load_config(config_path: Path) -> dict[str, Any]:
133
+ """Load config from YAML or JSON file."""
134
+ if not config_path.exists():
135
+ return {}
136
+
137
+ is_yaml = config_path.suffix in (".yaml", ".yml")
138
+ content = config_path.read_text(encoding="utf-8")
139
+
140
+ if is_yaml:
141
+ return yaml.safe_load(content) or {}
142
+ return json.loads(content)
143
+
144
+
145
+ def _save_config(config_path: Path, config_data: dict[str, Any]) -> None:
146
+ """Save config to YAML or JSON file."""
147
+ is_yaml = config_path.suffix in (".yaml", ".yml")
148
+
149
+ if is_yaml:
150
+ content = yaml.safe_dump(config_data, default_flow_style=False, allow_unicode=True, sort_keys=False)
151
+ else:
152
+ content = json.dumps(config_data, indent=2, ensure_ascii=False) + "\n"
153
+
154
+ config_path.write_text(content, encoding="utf-8")
155
+
156
+
91
157
  def _is_installed_via_uv_tool() -> bool:
92
158
  """Check if moai-adk installed via uv tool.
93
159
 
@@ -100,7 +166,7 @@ def _is_installed_via_uv_tool() -> bool:
100
166
  capture_output=True,
101
167
  text=True,
102
168
  timeout=TOOL_DETECTION_TIMEOUT,
103
- check=False
169
+ check=False,
104
170
  )
105
171
  return result.returncode == 0 and "moai-adk" in result.stdout
106
172
  except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
@@ -119,7 +185,7 @@ def _is_installed_via_pipx() -> bool:
119
185
  capture_output=True,
120
186
  text=True,
121
187
  timeout=TOOL_DETECTION_TIMEOUT,
122
- check=False
188
+ check=False,
123
189
  )
124
190
  return result.returncode == 0 and "moai-adk" in result.stdout
125
191
  except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
@@ -138,14 +204,13 @@ def _is_installed_via_pip() -> bool:
138
204
  capture_output=True,
139
205
  text=True,
140
206
  timeout=TOOL_DETECTION_TIMEOUT,
141
- check=False
207
+ check=False,
142
208
  )
143
209
  return result.returncode == 0
144
210
  except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
145
211
  return False
146
212
 
147
213
 
148
- # @CODE:UPDATE-REFACTOR-002-001
149
214
  def _detect_tool_installer() -> list[str] | None:
150
215
  """Detect which tool installed moai-adk.
151
216
 
@@ -185,7 +250,6 @@ def _detect_tool_installer() -> list[str] | None:
185
250
  return None
186
251
 
187
252
 
188
- # @CODE:UPDATE-REFACTOR-002-002
189
253
  def _get_current_version() -> str:
190
254
  """Get currently installed moai-adk version.
191
255
 
@@ -207,10 +271,10 @@ def _get_latest_version() -> str:
207
271
  Raises:
208
272
  RuntimeError: If PyPI API unavailable or parsing fails
209
273
  """
210
- try:
211
- import urllib.error
212
- import urllib.request
274
+ import urllib.error
275
+ import urllib.request
213
276
 
277
+ try:
214
278
  url = "https://pypi.org/pypi/moai-adk/json"
215
279
  with urllib.request.urlopen(url, timeout=5) as response: # nosec B310 - URL is hardcoded HTTPS to PyPI API, no user input
216
280
  data = json.loads(response.read().decode("utf-8"))
@@ -242,7 +306,6 @@ def _compare_versions(current: str, latest: str) -> int:
242
306
  return 1
243
307
 
244
308
 
245
- # @CODE:UPDATE-REFACTOR-002-006
246
309
  def _get_package_config_version() -> str:
247
310
  """Get the current package template version.
248
311
 
@@ -257,11 +320,10 @@ def _get_package_config_version() -> str:
257
320
  return __version__
258
321
 
259
322
 
260
- # @CODE:UPDATE-REFACTOR-002-007
261
323
  def _get_project_config_version(project_path: Path) -> str:
262
324
  """Get current project config.json template version.
263
325
 
264
- This reads the project's .moai/config.json to determine the current
326
+ This reads the project's .moai/config/config.json to determine the current
265
327
  template version that the project is configured with.
266
328
 
267
329
  Args:
@@ -272,30 +334,592 @@ def _get_project_config_version(project_path: Path) -> str:
272
334
  Returns "0.0.0" if template_version field not found (indicates no prior sync)
273
335
 
274
336
  Raises:
275
- ValueError: If config.json exists but cannot be parsed
337
+ ValueError: If config file exists but cannot be parsed
276
338
  """
277
- config_path = project_path / ".moai" / "config.json"
339
+
340
+ def _is_placeholder_val(value: str) -> bool:
341
+ """Check if value contains unsubstituted template placeholders."""
342
+ return isinstance(value, str) and value.startswith("{{") and value.endswith("}}")
343
+
344
+ config_path, _ = _get_config_path(project_path)
278
345
 
279
346
  if not config_path.exists():
280
347
  # No config yet, treat as version 0.0.0 (needs initial sync)
281
348
  return "0.0.0"
282
349
 
283
350
  try:
284
- config_data = json.loads(config_path.read_text(encoding="utf-8"))
351
+ config_data = _load_config(config_path)
285
352
  # Check for template_version in project section
286
353
  template_version = config_data.get("project", {}).get("template_version")
287
- if template_version:
354
+ if template_version and not _is_placeholder_val(template_version):
288
355
  return template_version
289
356
 
290
357
  # Fallback to moai version if no template_version exists
291
358
  moai_version = config_data.get("moai", {}).get("version")
292
- if moai_version:
359
+ if moai_version and not _is_placeholder_val(moai_version):
293
360
  return moai_version
294
361
 
295
- # If neither exists, this is a new/old project
362
+ # If values are placeholders or don't exist, treat as uninitialized (0.0.0 triggers sync)
296
363
  return "0.0.0"
297
- except json.JSONDecodeError as e:
298
- raise ValueError(f"Failed to parse project config.json: {e}") from e
364
+ except (json.JSONDecodeError, yaml.YAMLError) as e:
365
+ raise ValueError(f"Failed to parse project config: {e}") from e
366
+
367
+
368
+ def _ask_merge_strategy(yes: bool = False) -> str:
369
+ """
370
+ Ask user to choose merge strategy via CLI prompt.
371
+
372
+ Args:
373
+ yes: If True, auto-select "auto" (for --yes flag)
374
+
375
+ Returns:
376
+ "auto" or "manual"
377
+ """
378
+ if yes:
379
+ return "auto"
380
+
381
+ console.print("\n[cyan]🔀 Choose merge strategy:[/cyan]")
382
+ console.print("[cyan] [1] Auto-merge (default)[/cyan]")
383
+ console.print("[dim] → Template installs fresh + user changes preserved + minimal conflicts[/dim]")
384
+ console.print("[cyan] [2] Manual merge[/cyan]")
385
+ console.print("[dim] → Backup preserved + merge guide generated + you control merging[/dim]")
386
+
387
+ response = click.prompt("Select [1 or 2]", default="1")
388
+ if response == "2":
389
+ return "manual"
390
+ return "auto"
391
+
392
+
393
+ def _generate_manual_merge_guide(backup_path: Path, template_path: Path, project_path: Path) -> Path:
394
+ """
395
+ Generate comprehensive merge guide for manual merging.
396
+
397
+ Args:
398
+ backup_path: Path to backup directory
399
+ template_path: Path to template directory
400
+ project_path: Project root path
401
+
402
+ Returns:
403
+ Path to generated merge guide
404
+ """
405
+ guide_dir = project_path / ".moai" / "guides"
406
+ guide_dir.mkdir(parents=True, exist_ok=True)
407
+
408
+ guide_path = guide_dir / "merge-guide.md"
409
+
410
+ # Find changed files
411
+ changed_files = []
412
+ backup_claude = backup_path / ".claude"
413
+ backup_path / ".moai"
414
+
415
+ # Compare .claude/
416
+ if backup_claude.exists():
417
+ for file in backup_claude.rglob("*"):
418
+ if file.is_file():
419
+ rel_path = file.relative_to(backup_path)
420
+ current_file = project_path / rel_path
421
+ if current_file.exists():
422
+ if file.read_text(encoding="utf-8", errors="ignore") != current_file.read_text(
423
+ encoding="utf-8", errors="ignore"
424
+ ):
425
+ changed_files.append(f" - {rel_path}")
426
+ else:
427
+ changed_files.append(f" - {rel_path} (new)")
428
+
429
+ # Generate guide
430
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
431
+ guide_content = f"""# Merge Guide - Manual Merge Mode
432
+
433
+ **Generated**: {timestamp}
434
+ **Backup Location**: `{backup_path.relative_to(project_path)}/`
435
+
436
+ ## Summary
437
+
438
+ During this update, the following files were changed:
439
+
440
+ {chr(10).join(changed_files) if changed_files else " (No changes detected)"}
441
+
442
+ ## How to Merge
443
+
444
+ ### Option 1: Using diff (Terminal)
445
+
446
+ ```bash
447
+ # Compare specific files
448
+ diff {backup_path.name}/.claude/settings.json .claude/settings.json
449
+
450
+ # View all differences
451
+ diff -r {backup_path.name}/ .
452
+ ```
453
+
454
+ ### Option 2: Using Visual Merge Tool
455
+
456
+ ```bash
457
+ # macOS/Linux - Using meld
458
+ meld {backup_path.relative_to(project_path)}/ .
459
+
460
+ # Using VSCode
461
+ code --diff {backup_path.relative_to(project_path)}/.claude/settings.json .claude/settings.json
462
+ ```
463
+
464
+ ### Option 3: Manual Line-by-Line
465
+
466
+ 1. Open backup file in your editor
467
+ 2. Open current file side-by-side
468
+ 3. Manually copy your customizations
469
+
470
+ ## Key Files to Review
471
+
472
+ ### .claude/settings.json
473
+ - Contains MCP servers, hooks, environment variables
474
+ - **Action**: Restore any custom MCP servers and environment variables
475
+ - **Location**: {backup_path.relative_to(project_path)}/.claude/settings.json
476
+
477
+ ### .moai/config/config.json
478
+ - Contains project configuration and metadata
479
+ - **Action**: Verify user-specific settings are preserved
480
+ - **Location**: {backup_path.relative_to(project_path)}/.moai/config/config.json
481
+
482
+ ### .claude/commands/, .claude/agents/, .claude/hooks/
483
+ - Contains custom scripts and automation
484
+ - **Action**: Restore any custom scripts outside of /moai/ folders
485
+ - **Location**: {backup_path.relative_to(project_path)}/.claude/
486
+
487
+ ## Migration Checklist
488
+
489
+ - [ ] Compare `.claude/settings.json`
490
+ - [ ] Restore custom MCP servers
491
+ - [ ] Restore environment variables
492
+ - [ ] Verify hooks are properly configured
493
+
494
+ - [ ] Review `.moai/config/config.json`
495
+ - [ ] Check version was updated
496
+ - [ ] Verify user settings preserved
497
+
498
+ - [ ] Restore custom scripts
499
+ - [ ] Any custom commands outside /moai/
500
+ - [ ] Any custom agents outside /moai/
501
+ - [ ] Any custom hooks outside /moai/
502
+
503
+ - [ ] Run tests
504
+ ```bash
505
+ uv run pytest
506
+ moai-adk validate
507
+ ```
508
+
509
+ - [ ] Commit changes
510
+ ```bash
511
+ git add .
512
+ git commit -m "merge: Update templates with manual merge"
513
+ ```
514
+
515
+ ## Rollback if Needed
516
+
517
+ If you want to cancel and restore the backup:
518
+
519
+ ```bash
520
+ # Restore everything from backup
521
+ cp -r {backup_path.relative_to(project_path)}/.claude .
522
+ cp -r {backup_path.relative_to(project_path)}/.moai .
523
+ cp {backup_path.relative_to(project_path)}/CLAUDE.md .
524
+
525
+ # Or restore specific files
526
+ cp {backup_path.relative_to(project_path)}/.claude/settings.json .claude/
527
+ ```
528
+
529
+ ## Questions?
530
+
531
+ If you encounter merge conflicts or issues:
532
+
533
+ 1. Check the backup folder for original files
534
+ 2. Compare line-by-line using diff tools
535
+ 3. Consult documentation: https://adk.mo.ai.kr/update-merge
536
+
537
+ ---
538
+
539
+ **Backup**: `{backup_path}/`
540
+ **Generated**: {timestamp}
541
+ """
542
+
543
+ guide_path.write_text(guide_content, encoding="utf-8")
544
+ logger.info(f"✅ Merge guide created: {guide_path}")
545
+ return guide_path
546
+
547
+
548
+ def _migrate_legacy_logs(project_path: Path, dry_run: bool = False) -> bool:
549
+ """Migrate legacy log files to unified directory structure.
550
+
551
+ Creates new unified directory structure (.moai/docs/, .moai/logs/archive/) and
552
+ migrates files from legacy locations to new unified structure:
553
+ - .moai/memory/last-session-state.json → .moai/logs/sessions/
554
+ - .moai/error_logs/ → .moai/logs/errors/
555
+ - .moai/reports/ → .moai/docs/reports/
556
+
557
+ Args:
558
+ project_path: Project directory path (absolute)
559
+ dry_run: If True, only simulate migration without making changes
560
+
561
+ Returns:
562
+ True if migration succeeded or no migration needed, False otherwise
563
+
564
+ Raises:
565
+ Exception: If migration fails during actual execution
566
+ """
567
+ try:
568
+ # Define source and target directories
569
+ legacy_memory = project_path / ".moai" / "memory"
570
+ legacy_error_logs = project_path / ".moai" / "error_logs"
571
+ legacy_reports = project_path / ".moai" / "reports"
572
+
573
+ # Create new unified directory structure
574
+ new_logs_dir = project_path / ".moai" / "logs"
575
+ new_docs_dir = project_path / ".moai" / "docs"
576
+ new_sessions_dir = new_logs_dir / "sessions"
577
+ new_errors_dir = new_logs_dir / "errors"
578
+ new_archive_dir = new_logs_dir / "archive"
579
+ new_docs_reports_dir = new_docs_dir / "reports"
580
+
581
+ migration_log = []
582
+ files_migrated = 0
583
+ files_skipped = 0
584
+
585
+ # Check if any legacy directories exist
586
+ has_legacy_files = legacy_memory.exists() or legacy_error_logs.exists() or legacy_reports.exists()
587
+
588
+ if not has_legacy_files:
589
+ if not dry_run:
590
+ # Create new directory structure anyway for consistency
591
+ new_logs_dir.mkdir(parents=True, exist_ok=True)
592
+ new_docs_dir.mkdir(parents=True, exist_ok=True)
593
+ new_sessions_dir.mkdir(parents=True, exist_ok=True)
594
+ new_errors_dir.mkdir(parents=True, exist_ok=True)
595
+ new_archive_dir.mkdir(parents=True, exist_ok=True)
596
+ new_docs_reports_dir.mkdir(parents=True, exist_ok=True)
597
+ return True
598
+
599
+ if dry_run:
600
+ console.print("[cyan]🔍 Legacy log migration (dry run):[/cyan]")
601
+
602
+ # Create new directories if not dry run
603
+ if not dry_run:
604
+ new_logs_dir.mkdir(parents=True, exist_ok=True)
605
+ new_docs_dir.mkdir(parents=True, exist_ok=True)
606
+ new_sessions_dir.mkdir(parents=True, exist_ok=True)
607
+ new_errors_dir.mkdir(parents=True, exist_ok=True)
608
+ new_archive_dir.mkdir(parents=True, exist_ok=True)
609
+ new_docs_reports_dir.mkdir(parents=True, exist_ok=True)
610
+
611
+ # Migration 1: .moai/memory/last-session-state.json → .moai/logs/sessions/
612
+ if legacy_memory.exists():
613
+ session_file = legacy_memory / "last-session-state.json"
614
+ if session_file.exists():
615
+ target_file = new_sessions_dir / "last-session-state.json"
616
+
617
+ if target_file.exists():
618
+ files_skipped += 1
619
+ migration_log.append(f"Skipped: {session_file.relative_to(project_path)} (target already exists)")
620
+ else:
621
+ if not dry_run:
622
+ shutil.copy2(session_file, target_file)
623
+ # Preserve original timestamp
624
+ shutil.copystat(session_file, target_file)
625
+ src_path = session_file.relative_to(project_path)
626
+ dst_path = target_file.relative_to(project_path)
627
+ migration_log.append(f"Migrated: {src_path} → {dst_path}")
628
+ else:
629
+ src_path = session_file.relative_to(project_path)
630
+ dst_path = target_file.relative_to(project_path)
631
+ migration_log.append(f"Would migrate: {src_path} → {dst_path}")
632
+ files_migrated += 1
633
+
634
+ # Migration 2: .moai/error_logs/ → .moai/logs/errors/
635
+ if legacy_error_logs.exists() and legacy_error_logs.is_dir():
636
+ for error_file in legacy_error_logs.rglob("*"):
637
+ if error_file.is_file():
638
+ relative_path = error_file.relative_to(legacy_error_logs)
639
+ target_file = new_errors_dir / relative_path
640
+
641
+ # Ensure target directory exists
642
+ if not dry_run:
643
+ target_file.parent.mkdir(parents=True, exist_ok=True)
644
+
645
+ if target_file.exists():
646
+ files_skipped += 1
647
+ error_path = error_file.relative_to(project_path)
648
+ migration_log.append(f"Skipped: {error_path} (target already exists)")
649
+ else:
650
+ if not dry_run:
651
+ shutil.copy2(error_file, target_file)
652
+ shutil.copystat(error_file, target_file)
653
+ error_path = error_file.relative_to(project_path)
654
+ target_path = target_file.relative_to(project_path)
655
+ migration_log.append(f"Migrated: {error_path} → {target_path}")
656
+ else:
657
+ error_path = error_file.relative_to(project_path)
658
+ target_path = target_file.relative_to(project_path)
659
+ migration_log.append(f"Would migrate: {error_path} → {target_path}")
660
+ files_migrated += 1
661
+
662
+ # Migration 3: .moai/reports/ → .moai/docs/reports/
663
+ if legacy_reports.exists() and legacy_reports.is_dir():
664
+ for report_file in legacy_reports.rglob("*"):
665
+ if report_file.is_file():
666
+ relative_path = report_file.relative_to(legacy_reports)
667
+ target_file = new_docs_reports_dir / relative_path
668
+
669
+ # Ensure target directory exists
670
+ if not dry_run:
671
+ target_file.parent.mkdir(parents=True, exist_ok=True)
672
+
673
+ if target_file.exists():
674
+ files_skipped += 1
675
+ report_path = report_file.relative_to(project_path)
676
+ migration_log.append(f"Skipped: {report_path} (target already exists)")
677
+ else:
678
+ if not dry_run:
679
+ shutil.copy2(report_file, target_file)
680
+ shutil.copystat(report_file, target_file)
681
+ report_path = report_file.relative_to(project_path)
682
+ target_path = target_file.relative_to(project_path)
683
+ migration_log.append(f"Migrated: {report_path} → {target_path}")
684
+ else:
685
+ report_path = report_file.relative_to(project_path)
686
+ target_path = target_file.relative_to(project_path)
687
+ migration_log.append(f"Would migrate: {report_path} → {target_path}")
688
+ files_migrated += 1
689
+
690
+ # Create migration log
691
+ migration_log_path = new_logs_dir / "migration-log.json"
692
+ if not dry_run and files_migrated > 0:
693
+ migration_data = {
694
+ "migration_timestamp": datetime.now().isoformat(),
695
+ "moai_adk_version": __version__,
696
+ "files_migrated": files_migrated,
697
+ "files_skipped": files_skipped,
698
+ "migration_log": migration_log,
699
+ "legacy_directories_found": [
700
+ str(d.relative_to(project_path))
701
+ for d in [legacy_memory, legacy_error_logs, legacy_reports]
702
+ if d.exists()
703
+ ],
704
+ }
705
+ json_content = json.dumps(migration_data, indent=2, ensure_ascii=False)
706
+ migration_log_path.write_text(json_content + "\n", encoding="utf-8")
707
+
708
+ # Display results
709
+ if files_migrated > 0 or files_skipped > 0:
710
+ if dry_run:
711
+ console.print(f" [yellow]Would migrate {files_migrated} files, skip {files_skipped} files[/yellow]")
712
+ else:
713
+ console.print(f" [green]✓ Migrated {files_migrated} legacy log files[/green]")
714
+ if files_skipped > 0:
715
+ console.print(f" [yellow]⚠ Skipped {files_skipped} files (already exist)[/yellow]")
716
+ console.print(f" [dim] Migration log: {migration_log_path.relative_to(project_path)}[/dim]")
717
+ elif has_legacy_files:
718
+ console.print(" [dim] No files to migrate[/dim]")
719
+
720
+ return True
721
+
722
+ except Exception as e:
723
+ console.print(f" [red]✗ Log migration failed: {e}[/red]")
724
+ logger.error(f"Legacy log migration failed: {e}", exc_info=True)
725
+ return False
726
+
727
+
728
+ def _detect_stale_cache(upgrade_output: str, current_version: str, latest_version: str) -> bool:
729
+ """
730
+ Detect if uv cache is stale by comparing versions.
731
+
732
+ A stale cache occurs when PyPI metadata is outdated, causing uv to incorrectly
733
+ report "Nothing to upgrade" even though a newer version exists. This function
734
+ detects this condition by:
735
+ 1. Checking if upgrade output contains "Nothing to upgrade"
736
+ 2. Verifying that latest version is actually newer than current version
737
+
738
+ Uses packaging.version.parse() for robust semantic version comparison that
739
+ handles pre-releases, dev versions, and other PEP 440 version formats correctly.
740
+
741
+ Args:
742
+ upgrade_output: Output from uv tool upgrade command
743
+ current_version: Currently installed version (string, e.g., "0.8.3")
744
+ latest_version: Latest version available on PyPI (string, e.g., "0.9.0")
745
+
746
+ Returns:
747
+ True if cache is stale (output shows "Nothing to upgrade" but current < latest),
748
+ False otherwise
749
+
750
+ Examples:
751
+ >>> _detect_stale_cache("Nothing to upgrade", "0.8.3", "0.9.0")
752
+ True
753
+ >>> _detect_stale_cache("Updated moai-adk", "0.8.3", "0.9.0")
754
+ False
755
+ >>> _detect_stale_cache("Nothing to upgrade", "0.9.0", "0.9.0")
756
+ False
757
+ """
758
+ # Check if output indicates no upgrade needed
759
+ if not upgrade_output or "Nothing to upgrade" not in upgrade_output:
760
+ return False
761
+
762
+ # Compare versions using packaging.version
763
+ try:
764
+ current_v = version.parse(current_version)
765
+ latest_v = version.parse(latest_version)
766
+ return current_v < latest_v
767
+ except (version.InvalidVersion, TypeError) as e:
768
+ # Graceful degradation: if version parsing fails, assume cache is not stale
769
+ logger.debug(f"Version parsing failed: {e}")
770
+ return False
771
+
772
+
773
+ def _clear_uv_package_cache(package_name: str = "moai-adk") -> bool:
774
+ """
775
+ Clear uv cache for specific package.
776
+
777
+ Executes `uv cache clean <package>` with 10-second timeout to prevent
778
+ hanging on network issues. Provides user-friendly error handling for
779
+ various failure scenarios (timeout, missing uv, etc.).
780
+
781
+ Args:
782
+ package_name: Package name to clear cache for (default: "moai-adk")
783
+
784
+ Returns:
785
+ True if cache cleared successfully, False otherwise
786
+
787
+ Exceptions:
788
+ - subprocess.TimeoutExpired: Logged as warning, returns False
789
+ - FileNotFoundError: Logged as warning, returns False
790
+ - Exception: Logged as warning, returns False
791
+
792
+ Examples:
793
+ >>> _clear_uv_package_cache("moai-adk")
794
+ True # If uv cache clean succeeds
795
+ """
796
+ try:
797
+ result = subprocess.run(
798
+ ["uv", "cache", "clean", package_name],
799
+ capture_output=True,
800
+ text=True,
801
+ timeout=10, # 10 second timeout
802
+ check=False,
803
+ )
804
+
805
+ if result.returncode == 0:
806
+ logger.debug(f"UV cache cleared for {package_name}")
807
+ return True
808
+ else:
809
+ logger.warning(f"Failed to clear UV cache: {result.stderr}")
810
+ return False
811
+
812
+ except subprocess.TimeoutExpired:
813
+ logger.warning(f"UV cache clean timed out for {package_name}")
814
+ return False
815
+ except FileNotFoundError:
816
+ logger.warning("UV command not found. Is uv installed?")
817
+ return False
818
+ except Exception as e:
819
+ logger.warning(f"Unexpected error clearing cache: {e}")
820
+ return False
821
+
822
+
823
+ def _execute_upgrade_with_retry(installer_cmd: list[str], package_name: str = "moai-adk") -> bool:
824
+ """
825
+ Execute upgrade with automatic cache retry on stale detection.
826
+
827
+ Implements a robust 7-stage upgrade flow that handles PyPI cache staleness:
828
+
829
+ Stage 1: First upgrade attempt (up to 60 seconds)
830
+ Stage 2: Check success condition (returncode=0 AND no "Nothing to upgrade")
831
+ Stage 3: Detect stale cache using _detect_stale_cache()
832
+ Stage 4: Show user feedback if stale cache detected
833
+ Stage 5: Clear cache using _clear_uv_package_cache()
834
+ Stage 6: Retry upgrade with same command
835
+ Stage 7: Return final result (success or failure)
836
+
837
+ Retry Logic:
838
+ - Only ONE retry is performed to prevent infinite loops
839
+ - Retry only happens if stale cache is detected AND cache clear succeeds
840
+ - Cache clear failures are reported to user with manual workaround
841
+
842
+ User Feedback:
843
+ - Shows emoji-based status messages for each stage
844
+ - Clear guidance on manual workaround if automatic retry fails
845
+ - All errors logged at WARNING level for debugging
846
+
847
+ Args:
848
+ installer_cmd: Command list from _detect_tool_installer()
849
+ e.g., ["uv", "tool", "upgrade", "moai-adk"]
850
+ package_name: Package name for cache clearing (default: "moai-adk")
851
+
852
+ Returns:
853
+ True if upgrade succeeded (either first attempt or after retry),
854
+ False otherwise
855
+
856
+ Examples:
857
+ >>> # First attempt succeeds
858
+ >>> _execute_upgrade_with_retry(["uv", "tool", "upgrade", "moai-adk"])
859
+ True
860
+
861
+ >>> # First attempt stale, retry succeeds
862
+ >>> _execute_upgrade_with_retry(["uv", "tool", "upgrade", "moai-adk"])
863
+ True # After cache clear and retry
864
+
865
+ Raises:
866
+ subprocess.TimeoutExpired: Re-raised if upgrade command times out
867
+ """
868
+ # Stage 1: First upgrade attempt
869
+ try:
870
+ result = subprocess.run(installer_cmd, capture_output=True, text=True, timeout=60, check=False)
871
+ except subprocess.TimeoutExpired:
872
+ raise # Re-raise timeout for caller to handle
873
+ except Exception:
874
+ return False
875
+
876
+ # Stage 2: Check if upgrade succeeded without stale cache
877
+ if result.returncode == 0 and "Nothing to upgrade" not in result.stdout:
878
+ return True
879
+
880
+ # Stage 3: Detect stale cache
881
+ try:
882
+ current_version = _get_current_version()
883
+ latest_version = _get_latest_version()
884
+ except RuntimeError:
885
+ # If version check fails, return original result
886
+ return result.returncode == 0
887
+
888
+ if _detect_stale_cache(result.stdout, current_version, latest_version):
889
+ # Stage 4: User feedback
890
+ console.print("[yellow]⚠️ Cache outdated, refreshing...[/yellow]")
891
+
892
+ # Stage 5: Clear cache
893
+ if _clear_uv_package_cache(package_name):
894
+ console.print("[cyan]♻️ Cache cleared, retrying upgrade...[/cyan]")
895
+
896
+ # Stage 6: Retry upgrade
897
+ try:
898
+ result = subprocess.run(
899
+ installer_cmd,
900
+ capture_output=True,
901
+ text=True,
902
+ timeout=60,
903
+ check=False,
904
+ )
905
+
906
+ if result.returncode == 0:
907
+ return True
908
+ else:
909
+ console.print("[red]✗ Upgrade failed after retry[/red]")
910
+ return False
911
+ except subprocess.TimeoutExpired:
912
+ raise # Re-raise timeout
913
+ except Exception:
914
+ return False
915
+ else:
916
+ # Cache clear failed
917
+ console.print("[red]✗ Cache clear failed. Manual workaround:[/red]")
918
+ console.print(" [cyan]uv cache clean moai-adk && moai-adk update[/cyan]")
919
+ return False
920
+
921
+ # Stage 7: Cache is not stale, return original result
922
+ return result.returncode == 0
299
923
 
300
924
 
301
925
  def _execute_upgrade(installer_cmd: list[str]) -> bool:
@@ -312,13 +936,7 @@ def _execute_upgrade(installer_cmd: list[str]) -> bool:
312
936
  subprocess.TimeoutExpired: If upgrade times out
313
937
  """
314
938
  try:
315
- result = subprocess.run(
316
- installer_cmd,
317
- capture_output=True,
318
- text=True,
319
- timeout=60,
320
- check=False
321
- )
939
+ result = subprocess.run(installer_cmd, capture_output=True, text=True, timeout=60, check=False)
322
940
  return result.returncode == 0
323
941
  except subprocess.TimeoutExpired:
324
942
  raise # Re-raise timeout for caller to handle
@@ -326,19 +944,584 @@ def _execute_upgrade(installer_cmd: list[str]) -> bool:
326
944
  return False
327
945
 
328
946
 
329
- def _sync_templates(project_path: Path, force: bool = False) -> bool:
330
- """Sync templates to project.
947
+ def _preserve_user_settings(project_path: Path) -> dict[str, Path | None]:
948
+ """Back up user-specific settings files before template sync.
949
+
950
+ Args:
951
+ project_path: Project directory path
952
+
953
+ Returns:
954
+ Dictionary with backup paths of preserved files
955
+ """
956
+ preserved = {}
957
+ claude_dir = project_path / ".claude"
958
+
959
+ # Preserve settings.local.json (user MCP and GLM configuration)
960
+ settings_local = claude_dir / "settings.local.json"
961
+ if settings_local.exists():
962
+ try:
963
+ backup_dir = project_path / ".moai-backups" / "settings-backup"
964
+ backup_dir.mkdir(parents=True, exist_ok=True)
965
+ backup_path = backup_dir / "settings.local.json"
966
+ backup_path.write_text(settings_local.read_text(encoding="utf-8"))
967
+ preserved["settings.local.json"] = backup_path
968
+ console.print(" [cyan]💾 Backed up user settings[/cyan]")
969
+ except Exception as e:
970
+ logger.warning(f"Failed to backup settings.local.json: {e}")
971
+ preserved["settings.local.json"] = None
972
+ else:
973
+ preserved["settings.local.json"] = None
974
+
975
+ return preserved
976
+
977
+
978
+ def _restore_user_settings(project_path: Path, preserved: dict[str, Path | None]) -> bool:
979
+ """Restore user-specific settings files after template sync.
980
+
981
+ Args:
982
+ project_path: Project directory path
983
+ preserved: Dictionary of backup paths from _preserve_user_settings()
984
+
985
+ Returns:
986
+ True if restoration succeeded, False otherwise
987
+ """
988
+ claude_dir = project_path / ".claude"
989
+ claude_dir.mkdir(parents=True, exist_ok=True)
990
+
991
+ success = True
992
+
993
+ # Restore settings.local.json
994
+ backup_path = preserved.get("settings.local.json")
995
+ if backup_path is not None:
996
+ try:
997
+ settings_local = claude_dir / "settings.local.json"
998
+ settings_local.write_text(backup_path.read_text(encoding="utf-8"))
999
+ console.print(" [cyan]✓ Restored user settings[/cyan]")
1000
+ except Exception as e:
1001
+ console.print(f" [yellow]⚠️ Failed to restore settings.local.json: {e}[/yellow]")
1002
+ logger.warning(f"Failed to restore settings.local.json: {e}")
1003
+ success = False
1004
+
1005
+ return success
1006
+
1007
+
1008
+ def _get_template_skill_names() -> set[str]:
1009
+ """Get set of skill folder names from installed template.
1010
+
1011
+ Returns:
1012
+ Set of skill folder names that are part of the template package.
1013
+ """
1014
+ template_path = Path(__file__).parent.parent.parent / "templates"
1015
+ skills_path = template_path / ".claude" / "skills"
1016
+
1017
+ if not skills_path.exists():
1018
+ return set()
1019
+
1020
+ return {d.name for d in skills_path.iterdir() if d.is_dir()}
1021
+
1022
+
1023
+ def _get_template_command_names() -> set[str]:
1024
+ """Get set of command file names from installed template.
1025
+
1026
+ Returns:
1027
+ Set of .md command file names from .claude/commands/moai/ in template.
1028
+ """
1029
+ template_path = Path(__file__).parent.parent.parent / "templates"
1030
+ commands_path = template_path / ".claude" / "commands" / "moai"
1031
+
1032
+ if not commands_path.exists():
1033
+ return set()
1034
+
1035
+ return {f.name for f in commands_path.iterdir() if f.is_file() and f.suffix == ".md"}
1036
+
1037
+
1038
+ def _get_template_agent_names() -> set[str]:
1039
+ """Get set of agent file names from installed template.
1040
+
1041
+ Returns:
1042
+ Set of agent file names from .claude/agents/ in template.
1043
+ """
1044
+ template_path = Path(__file__).parent.parent.parent / "templates"
1045
+ agents_path = template_path / ".claude" / "agents"
1046
+
1047
+ if not agents_path.exists():
1048
+ return set()
1049
+
1050
+ return {f.name for f in agents_path.iterdir() if f.is_file()}
1051
+
1052
+
1053
+ def _get_template_hook_names() -> set[str]:
1054
+ """Get set of hook file names from installed template.
1055
+
1056
+ Returns:
1057
+ Set of .py hook file names from .claude/hooks/moai/ in template.
1058
+ """
1059
+ template_path = Path(__file__).parent.parent.parent / "templates"
1060
+ hooks_path = template_path / ".claude" / "hooks" / "moai"
1061
+
1062
+ if not hooks_path.exists():
1063
+ return set()
1064
+
1065
+ return {f.name for f in hooks_path.iterdir() if f.is_file() and f.suffix == ".py"}
1066
+
1067
+
1068
+ def _detect_custom_commands(project_path: Path, template_commands: set[str]) -> list[str]:
1069
+ """Detect custom commands NOT in template (user-created).
1070
+
1071
+ Args:
1072
+ project_path: Project path (absolute)
1073
+ template_commands: Set of template command file names
1074
+
1075
+ Returns:
1076
+ Sorted list of custom command file names.
1077
+ """
1078
+ commands_path = project_path / ".claude" / "commands" / "moai"
1079
+
1080
+ if not commands_path.exists():
1081
+ return []
1082
+
1083
+ project_commands = {f.name for f in commands_path.iterdir() if f.is_file() and f.suffix == ".md"}
1084
+ custom_commands = project_commands - template_commands
1085
+
1086
+ return sorted(custom_commands)
1087
+
1088
+
1089
+ def _detect_custom_agents(project_path: Path, template_agents: set[str]) -> list[str]:
1090
+ """Detect custom agents NOT in template (user-created).
1091
+
1092
+ Args:
1093
+ project_path: Project path (absolute)
1094
+ template_agents: Set of template agent file names
1095
+
1096
+ Returns:
1097
+ Sorted list of custom agent file names.
1098
+ """
1099
+ agents_path = project_path / ".claude" / "agents"
1100
+
1101
+ if not agents_path.exists():
1102
+ return []
1103
+
1104
+ project_agents = {f.name for f in agents_path.iterdir() if f.is_file()}
1105
+ custom_agents = project_agents - template_agents
1106
+
1107
+ return sorted(custom_agents)
1108
+
1109
+
1110
+ def _detect_custom_hooks(project_path: Path, template_hooks: set[str]) -> list[str]:
1111
+ """Detect custom hooks NOT in template (user-created).
1112
+
1113
+ Args:
1114
+ project_path: Project path (absolute)
1115
+ template_hooks: Set of template hook file names
1116
+
1117
+ Returns:
1118
+ Sorted list of custom hook file names.
1119
+ """
1120
+ hooks_path = project_path / ".claude" / "hooks" / "moai"
1121
+
1122
+ if not hooks_path.exists():
1123
+ return []
1124
+
1125
+ project_hooks = {f.name for f in hooks_path.iterdir() if f.is_file() and f.suffix == ".py"}
1126
+ custom_hooks = project_hooks - template_hooks
1127
+
1128
+ return sorted(custom_hooks)
1129
+
1130
+
1131
+ def _group_custom_files_by_type(
1132
+ custom_commands: list[str],
1133
+ custom_agents: list[str],
1134
+ custom_hooks: list[str],
1135
+ ) -> dict[str, list[str]]:
1136
+ """Group custom files by type for UI display.
1137
+
1138
+ Args:
1139
+ custom_commands: List of custom command file names
1140
+ custom_agents: List of custom agent file names
1141
+ custom_hooks: List of custom hook file names
1142
+
1143
+ Returns:
1144
+ Dictionary with keys: commands, agents, hooks
1145
+ """
1146
+ return {
1147
+ "commands": custom_commands,
1148
+ "agents": custom_agents,
1149
+ "hooks": custom_hooks,
1150
+ }
1151
+
1152
+
1153
+ def _prompt_custom_files_restore(
1154
+ custom_commands: list[str],
1155
+ custom_agents: list[str],
1156
+ custom_hooks: list[str],
1157
+ yes: bool = False,
1158
+ ) -> dict[str, list[str]]:
1159
+ """Interactive fuzzy checkbox for custom files restore with search support.
1160
+
1161
+ Args:
1162
+ custom_commands: List of custom command file names
1163
+ custom_agents: List of custom agent file names
1164
+ custom_hooks: List of custom hook file names
1165
+ yes: Auto-confirm flag (skips restoration in CI/CD mode)
1166
+
1167
+ Returns:
1168
+ Dictionary with selected files grouped by type.
1169
+ """
1170
+ # If no custom files, skip UI
1171
+ if not (custom_commands or custom_agents or custom_hooks):
1172
+ return {
1173
+ "commands": [],
1174
+ "agents": [],
1175
+ "hooks": [],
1176
+ }
1177
+
1178
+ # In --yes mode, skip restoration (safest default)
1179
+ if yes:
1180
+ console.print("\n[dim] Skipping custom files restoration (--yes mode)[/dim]\n")
1181
+ return {
1182
+ "commands": [],
1183
+ "agents": [],
1184
+ "hooks": [],
1185
+ }
1186
+
1187
+ # Try to use new UI, fallback to questionary if import fails
1188
+ try:
1189
+ from moai_adk.cli.ui.prompts import create_grouped_choices, fuzzy_checkbox
1190
+
1191
+ # Build grouped choices for fuzzy checkbox
1192
+ groups: dict[str, list[dict[str, str]]] = {}
1193
+
1194
+ if custom_commands:
1195
+ groups["Commands (.claude/commands/moai/)"] = [
1196
+ {"name": cmd, "value": f"cmd:{cmd}"} for cmd in custom_commands
1197
+ ]
1198
+
1199
+ if custom_agents:
1200
+ groups["Agents (.claude/agents/)"] = [{"name": agent, "value": f"agent:{agent}"} for agent in custom_agents]
1201
+
1202
+ if custom_hooks:
1203
+ groups["Hooks (.claude/hooks/moai/)"] = [{"name": hook, "value": f"hook:{hook}"} for hook in custom_hooks]
1204
+
1205
+ choices = create_grouped_choices(groups)
1206
+
1207
+ console.print("\n[#DA7756]📦 Custom files detected in backup:[/#DA7756]")
1208
+ console.print("[dim] Use fuzzy search to find files quickly[/dim]\n")
1209
+
1210
+ selected = fuzzy_checkbox(
1211
+ "Select custom files to restore:",
1212
+ choices=choices,
1213
+ instruction="[Space] Toggle [Tab] All [Enter] Confirm [Type to search]",
1214
+ )
1215
+
1216
+ except ImportError:
1217
+ # Fallback to questionary if new UI not available
1218
+ import questionary
1219
+ from questionary import Choice, Separator
1220
+
1221
+ choices_legacy: list[Union[Separator, Choice]] = []
1222
+
1223
+ if custom_commands:
1224
+ choices_legacy.append(Separator("Commands (.claude/commands/moai/)"))
1225
+ for cmd in custom_commands:
1226
+ choices_legacy.append(Choice(title=cmd, value=f"cmd:{cmd}"))
1227
+
1228
+ if custom_agents:
1229
+ choices_legacy.append(Separator("Agents (.claude/agents/)"))
1230
+ for agent in custom_agents:
1231
+ choices_legacy.append(Choice(title=agent, value=f"agent:{agent}"))
1232
+
1233
+ if custom_hooks:
1234
+ choices_legacy.append(Separator("Hooks (.claude/hooks/moai/)"))
1235
+ for hook in custom_hooks:
1236
+ choices_legacy.append(Choice(title=hook, value=f"hook:{hook}"))
1237
+
1238
+ console.print("\n[cyan]📦 Custom files detected in backup:[/cyan]")
1239
+ console.print("[dim] Select files to restore (none selected by default)[/dim]\n")
1240
+
1241
+ selected = questionary.checkbox(
1242
+ "Select custom files to restore:",
1243
+ choices=choices_legacy,
1244
+ ).ask()
1245
+
1246
+ # Parse results
1247
+ result_commands = []
1248
+ result_agents = []
1249
+ result_hooks = []
1250
+
1251
+ if selected:
1252
+ for item in selected:
1253
+ if item.startswith("cmd:"):
1254
+ result_commands.append(item[4:])
1255
+ elif item.startswith("agent:"):
1256
+ result_agents.append(item[6:])
1257
+ elif item.startswith("hook:"):
1258
+ result_hooks.append(item[5:])
1259
+
1260
+ return {
1261
+ "commands": result_commands,
1262
+ "agents": result_agents,
1263
+ "hooks": result_hooks,
1264
+ }
1265
+
1266
+
1267
+ def _restore_custom_files(
1268
+ project_path: Path,
1269
+ backup_path: Path,
1270
+ selected_commands: list[str],
1271
+ selected_agents: list[str],
1272
+ selected_hooks: list[str],
1273
+ ) -> bool:
1274
+ """Restore selected custom files from backup to project.
1275
+
1276
+ Args:
1277
+ project_path: Project directory path
1278
+ backup_path: Backup directory path
1279
+ selected_commands: List of command files to restore
1280
+ selected_agents: List of agent files to restore
1281
+ selected_hooks: List of hook files to restore
1282
+
1283
+ Returns:
1284
+ True if all restorations succeeded, False otherwise.
1285
+ """
1286
+ import shutil
1287
+
1288
+ success = True
1289
+
1290
+ # Restore commands
1291
+ if selected_commands:
1292
+ commands_dst = project_path / ".claude" / "commands" / "moai"
1293
+ commands_dst.mkdir(parents=True, exist_ok=True)
1294
+
1295
+ for cmd_file in selected_commands:
1296
+ src = backup_path / ".claude" / "commands" / "moai" / cmd_file
1297
+ dst = commands_dst / cmd_file
1298
+
1299
+ if src.exists():
1300
+ try:
1301
+ shutil.copy2(src, dst)
1302
+ except Exception as e:
1303
+ logger.warning(f"Failed to restore command {cmd_file}: {e}")
1304
+ success = False
1305
+ else:
1306
+ logger.warning(f"Command file not in backup: {cmd_file}")
1307
+ success = False
1308
+
1309
+ # Restore agents
1310
+ if selected_agents:
1311
+ agents_dst = project_path / ".claude" / "agents"
1312
+ agents_dst.mkdir(parents=True, exist_ok=True)
1313
+
1314
+ for agent_file in selected_agents:
1315
+ src = backup_path / ".claude" / "agents" / agent_file
1316
+ dst = agents_dst / agent_file
1317
+
1318
+ if src.exists():
1319
+ try:
1320
+ shutil.copy2(src, dst)
1321
+ except Exception as e:
1322
+ logger.warning(f"Failed to restore agent {agent_file}: {e}")
1323
+ success = False
1324
+ else:
1325
+ logger.warning(f"Agent file not in backup: {agent_file}")
1326
+ success = False
1327
+
1328
+ # Restore hooks
1329
+ if selected_hooks:
1330
+ hooks_dst = project_path / ".claude" / "hooks" / "moai"
1331
+ hooks_dst.mkdir(parents=True, exist_ok=True)
1332
+
1333
+ for hook_file in selected_hooks:
1334
+ src = backup_path / ".claude" / "hooks" / "moai" / hook_file
1335
+ dst = hooks_dst / hook_file
1336
+
1337
+ if src.exists():
1338
+ try:
1339
+ shutil.copy2(src, dst)
1340
+ except Exception as e:
1341
+ logger.warning(f"Failed to restore hook {hook_file}: {e}")
1342
+ success = False
1343
+ else:
1344
+ logger.warning(f"Hook file not in backup: {hook_file}")
1345
+ success = False
1346
+
1347
+ return success
1348
+
1349
+
1350
+ def _detect_custom_skills(project_path: Path, template_skills: set[str]) -> list[str]:
1351
+ """Detect skills NOT in template (user-created).
1352
+
1353
+ Args:
1354
+ project_path: Project path (absolute)
1355
+ template_skills: Set of template skill names
1356
+
1357
+ Returns:
1358
+ Sorted list of custom skill names.
1359
+ """
1360
+ skills_path = project_path / ".claude" / "skills"
1361
+
1362
+ if not skills_path.exists():
1363
+ return []
1364
+
1365
+ project_skills = {d.name for d in skills_path.iterdir() if d.is_dir()}
1366
+ custom_skills = project_skills - template_skills
1367
+
1368
+ return sorted(custom_skills)
1369
+
1370
+
1371
+ def _prompt_skill_restore(custom_skills: list[str], yes: bool = False) -> list[str]:
1372
+ """Interactive fuzzy checkbox for skill restore with search support.
1373
+
1374
+ Args:
1375
+ custom_skills: List of custom skill names
1376
+ yes: Auto-confirm flag (skips restoration in CI/CD mode)
1377
+
1378
+ Returns:
1379
+ List of skills user selected to restore.
1380
+ """
1381
+ if not custom_skills:
1382
+ return []
1383
+
1384
+ console.print("\n[#DA7756]📦 Custom skills detected in backup:[/#DA7756]")
1385
+ for skill in custom_skills:
1386
+ console.print(f" • {skill}")
1387
+ console.print()
1388
+
1389
+ if yes:
1390
+ console.print("[dim] Skipping restoration (--yes mode)[/dim]\n")
1391
+ return []
1392
+
1393
+ # Try new UI, fallback to questionary
1394
+ try:
1395
+ from moai_adk.cli.ui.prompts import fuzzy_checkbox
1396
+
1397
+ choices = [{"name": skill, "value": skill} for skill in custom_skills]
1398
+
1399
+ selected = fuzzy_checkbox(
1400
+ "Select skills to restore (type to search):",
1401
+ choices=choices,
1402
+ instruction="[Space] Toggle [Tab] All [Enter] Confirm [Type to search]",
1403
+ )
1404
+
1405
+ except ImportError:
1406
+ import questionary
1407
+
1408
+ selected = questionary.checkbox(
1409
+ "Select skills to restore (none selected by default):",
1410
+ choices=[questionary.Choice(title=skill, checked=False) for skill in custom_skills],
1411
+ ).ask()
1412
+
1413
+ return selected if selected else []
1414
+
1415
+
1416
+ def _restore_selected_skills(skills: list[str], backup_path: Path, project_path: Path) -> bool:
1417
+ """Restore selected skills from backup.
1418
+
1419
+ Args:
1420
+ skills: List of skill names to restore
1421
+ backup_path: Backup directory path
1422
+ project_path: Project path (absolute)
1423
+
1424
+ Returns:
1425
+ True if all restorations succeeded.
1426
+ """
1427
+ import shutil
1428
+
1429
+ if not skills:
1430
+ return True
1431
+
1432
+ console.print("\n[cyan]📥 Restoring selected skills...[/cyan]")
1433
+ skills_dst = project_path / ".claude" / "skills"
1434
+ skills_dst.mkdir(parents=True, exist_ok=True)
1435
+
1436
+ success = True
1437
+ for skill_name in skills:
1438
+ src = backup_path / ".claude" / "skills" / skill_name
1439
+ dst = skills_dst / skill_name
1440
+
1441
+ if src.exists():
1442
+ try:
1443
+ shutil.copytree(src, dst, dirs_exist_ok=True)
1444
+ console.print(f" [green]✓ Restored: {skill_name}[/green]")
1445
+ except Exception as e:
1446
+ console.print(f" [red]✗ Failed: {skill_name} - {e}[/red]")
1447
+ success = False
1448
+ else:
1449
+ console.print(f" [yellow]⚠ Not in backup: {skill_name}[/yellow]")
1450
+ success = False
1451
+
1452
+ return success
1453
+
1454
+
1455
+ def _show_post_update_guidance(backup_path: Path) -> None:
1456
+ """Show post-update completion message.
1457
+
1458
+ Args:
1459
+ backup_path: Backup directory path for reference
1460
+ """
1461
+ console.print("\n" + "[cyan]" + "=" * 60 + "[/cyan]")
1462
+ console.print("[green]✅ Update complete![/green]")
1463
+ console.print("\n[dim]💡 Personal instructions should go in CLAUDE.local.md[/dim]")
1464
+ console.print(f"[dim]📂 Backup location: {backup_path}[/dim]")
1465
+ console.print("[cyan]" + "=" * 60 + "[/cyan]\n")
1466
+
1467
+
1468
+ def _sync_templates(project_path: Path, force: bool = False, yes: bool = False) -> bool:
1469
+ """Sync templates to project with rollback mechanism.
331
1470
 
332
1471
  Args:
333
1472
  project_path: Project path (absolute)
334
1473
  force: Force update without backup
1474
+ yes: Auto-confirm flag (skips interactive prompts)
335
1475
 
336
1476
  Returns:
337
1477
  True if sync succeeded, False otherwise
338
1478
  """
1479
+ from moai_adk.core.template.backup import TemplateBackup
1480
+
1481
+ backup_path = None
339
1482
  try:
1483
+ # NEW: Detect custom files and skills BEFORE backup/sync
1484
+ template_skills = _get_template_skill_names()
1485
+ _detect_custom_skills(project_path, template_skills)
1486
+
1487
+ # Detect custom commands, agents, and hooks
1488
+ template_commands = _get_template_command_names()
1489
+ _detect_custom_commands(project_path, template_commands)
1490
+
1491
+ template_agents = _get_template_agent_names()
1492
+ _detect_custom_agents(project_path, template_agents)
1493
+
1494
+ template_hooks = _get_template_hook_names()
1495
+ _detect_custom_hooks(project_path, template_hooks)
1496
+
340
1497
  processor = TemplateProcessor(project_path)
341
1498
 
1499
+ # Create pre-sync backup for rollback
1500
+ if not force:
1501
+ backup = TemplateBackup(project_path)
1502
+ if backup.has_existing_files():
1503
+ backup_path = backup.create_backup()
1504
+ console.print(f"💾 Created backup: {backup_path.name}")
1505
+
1506
+ # Merge analysis using Pure Python semantic heuristics
1507
+ try:
1508
+ analyzer = MergeAnalyzer(project_path)
1509
+ # Template source path from installed package
1510
+ template_path = Path(__file__).parent.parent.parent / "templates"
1511
+
1512
+ console.print("\n[cyan]🔍 Starting merge analysis...[/cyan]")
1513
+ console.print("[dim] Analyzing templates with semantic heuristics.[/dim]\n")
1514
+ analysis = analyzer.analyze_merge(backup_path, template_path)
1515
+
1516
+ # Ask user confirmation
1517
+ if not analyzer.ask_user_confirmation(analysis):
1518
+ console.print("[yellow]⚠️ User cancelled the update.[/yellow]")
1519
+ backup.restore_backup(backup_path)
1520
+ return False
1521
+ except Exception as e:
1522
+ console.print(f"[yellow]⚠️ Merge analysis failed: {e}[/yellow]")
1523
+ console.print("[yellow]Proceeding with automatic merge.[/yellow]")
1524
+
342
1525
  # Load existing config
343
1526
  existing_config = _load_existing_config(project_path)
344
1527
 
@@ -347,9 +1530,38 @@ def _sync_templates(project_path: Path, force: bool = False) -> bool:
347
1530
  if context:
348
1531
  processor.set_context(context)
349
1532
 
350
- # Copy templates
1533
+ # Copy templates (including moai folder)
351
1534
  processor.copy_templates(backup=False, silent=True)
352
1535
 
1536
+ # Stage 1.5: Alfred → Moai migration (AFTER template sync)
1537
+ # Execute migration after template copy (moai folders must exist first)
1538
+ migrator = AlfredToMoaiMigrator(project_path)
1539
+ if migrator.needs_migration():
1540
+ console.print("\n[cyan]🔄 Migrating folder structure: Alfred → Moai[/cyan]")
1541
+ try:
1542
+ if not migrator.execute_migration(backup_path):
1543
+ console.print("[red]❌ Alfred → Moai migration failed[/red]")
1544
+ if backup_path:
1545
+ console.print("[yellow]🔄 Restoring from backup...[/yellow]")
1546
+ backup = TemplateBackup(project_path)
1547
+ backup.restore_backup(backup_path)
1548
+ return False
1549
+ except Exception as e:
1550
+ console.print(f"[red]❌ Error during migration: {e}[/red]")
1551
+ if backup_path:
1552
+ backup = TemplateBackup(project_path)
1553
+ backup.restore_backup(backup_path)
1554
+ return False
1555
+
1556
+ # Validate template substitution
1557
+ validation_passed = _validate_template_substitution_with_rollback(project_path, backup_path)
1558
+ if not validation_passed:
1559
+ if backup_path:
1560
+ console.print(f"[yellow]🔄 Rolling back to backup: {backup_path.name}[/yellow]")
1561
+ backup = TemplateBackup(project_path)
1562
+ backup.restore_backup(backup_path)
1563
+ return False
1564
+
353
1565
  # Preserve metadata
354
1566
  _preserve_project_metadata(project_path, context, existing_config, __version__)
355
1567
  _apply_context_to_file(processor, project_path / "CLAUDE.md")
@@ -357,8 +1569,59 @@ def _sync_templates(project_path: Path, force: bool = False) -> bool:
357
1569
  # Set optimized=false
358
1570
  set_optimized_false(project_path)
359
1571
 
1572
+ # Update companyAnnouncements in settings.local.json
1573
+ try:
1574
+ import sys
1575
+
1576
+ utils_dir = (
1577
+ Path(__file__).parent.parent.parent / "templates" / ".claude" / "hooks" / "moai" / "shared" / "utils"
1578
+ )
1579
+
1580
+ if utils_dir.exists():
1581
+ sys.path.insert(0, str(utils_dir))
1582
+ try:
1583
+ from announcement_translator import auto_translate_and_update # type: ignore[import-not-found]
1584
+
1585
+ console.print("[cyan]Updating announcements...[/cyan]")
1586
+ auto_translate_and_update(project_path)
1587
+ console.print("[green]✓ Announcements updated[/green]")
1588
+ except Exception as e:
1589
+ console.print(f"[yellow]⚠️ Announcement update failed: {e}[/yellow]")
1590
+ finally:
1591
+ sys.path.remove(str(utils_dir))
1592
+
1593
+ except Exception as e:
1594
+ console.print(f"[yellow]⚠️ Announcement module not available: {e}[/yellow]")
1595
+
1596
+ # NEW: Interactive custom element restore using new system
1597
+ _handle_custom_element_restoration(project_path, backup_path, yes)
1598
+
1599
+ # NEW: Migrate legacy logs to unified structure
1600
+ console.print("\n[cyan]📁 Migrating legacy log files...[/cyan]")
1601
+ if not _migrate_legacy_logs(project_path):
1602
+ console.print("[yellow]⚠️ Legacy log migration failed, but update continuing[/yellow]")
1603
+
1604
+ # Clean up legacy presets directory
1605
+ _cleanup_legacy_presets(project_path)
1606
+
1607
+ # Clean up CLI redesign obsolete files (v0.41+)
1608
+ _cleanup_cli_redesign_obsolete_files(project_path)
1609
+
1610
+ # NEW: Show post-update guidance
1611
+ if backup_path:
1612
+ _show_post_update_guidance(backup_path)
1613
+
360
1614
  return True
361
- except Exception:
1615
+ except Exception as e:
1616
+ console.print(f"[red]✗ Template sync failed: {e}[/red]")
1617
+ if backup_path:
1618
+ console.print(f"[yellow]🔄 Rolling back to backup: {backup_path.name}[/yellow]")
1619
+ try:
1620
+ backup = TemplateBackup(project_path)
1621
+ backup.restore_backup(backup_path)
1622
+ console.print("[green]✅ Rollback completed[/green]")
1623
+ except Exception as rollback_error:
1624
+ console.print(f"[red]✗ Rollback failed: {rollback_error}[/red]")
362
1625
  return False
363
1626
 
364
1627
 
@@ -379,35 +1642,32 @@ def get_latest_version() -> str | None:
379
1642
 
380
1643
 
381
1644
  def set_optimized_false(project_path: Path) -> None:
382
- """Set config.json's optimized field to false.
1645
+ """Set config's optimized field to false.
383
1646
 
384
1647
  Args:
385
1648
  project_path: Project path (absolute).
386
1649
  """
387
- config_path = project_path / ".moai" / "config.json"
1650
+ config_path, _ = _get_config_path(project_path)
388
1651
  if not config_path.exists():
389
1652
  return
390
1653
 
391
1654
  try:
392
- config_data = json.loads(config_path.read_text(encoding="utf-8"))
1655
+ config_data = _load_config(config_path)
393
1656
  config_data.setdefault("project", {})["optimized"] = False
394
- config_path.write_text(
395
- json.dumps(config_data, indent=2, ensure_ascii=False) + "\n",
396
- encoding="utf-8"
397
- )
398
- except (json.JSONDecodeError, KeyError):
399
- # Ignore errors if config.json is invalid
1657
+ _save_config(config_path, config_data)
1658
+ except (json.JSONDecodeError, yaml.YAMLError, KeyError):
1659
+ # Ignore errors if config is invalid
400
1660
  pass
401
1661
 
402
1662
 
403
1663
  def _load_existing_config(project_path: Path) -> dict[str, Any]:
404
- """Load existing config.json if available."""
405
- config_path = project_path / ".moai" / "config.json"
1664
+ """Load existing config (YAML or JSON) if available."""
1665
+ config_path, _ = _get_config_path(project_path)
406
1666
  if config_path.exists():
407
1667
  try:
408
- return json.loads(config_path.read_text(encoding="utf-8"))
409
- except json.JSONDecodeError:
410
- console.print("[yellow]⚠ Existing config.json could not be parsed. Proceeding with defaults.[/yellow]")
1668
+ return _load_config(config_path)
1669
+ except (json.JSONDecodeError, yaml.YAMLError):
1670
+ console.print("[yellow]⚠ Existing config could not be parsed. Proceeding with defaults.[/yellow]")
411
1671
  return {}
412
1672
 
413
1673
 
@@ -445,6 +1705,8 @@ def _build_template_context(
445
1705
  version_for_config: str,
446
1706
  ) -> dict[str, str]:
447
1707
  """Build substitution context for template files."""
1708
+ import platform
1709
+
448
1710
  project_section = _extract_project_section(existing_config)
449
1711
 
450
1712
  project_name = _coalesce(
@@ -474,13 +1736,115 @@ def _build_template_context(
474
1736
  default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
475
1737
  )
476
1738
 
1739
+ # Detect OS for cross-platform Hook path configuration
1740
+ hook_project_dir = "%CLAUDE_PROJECT_DIR%" if platform.system() == "Windows" else "$CLAUDE_PROJECT_DIR"
1741
+
1742
+ # Detect OS for cross-platform statusline command
1743
+ # Windows: Use python -m for better PATH compatibility
1744
+ # Unix: Use moai-adk directly (assumes installed via uv tool)
1745
+ if platform.system() == "Windows":
1746
+ statusline_command = "python -m moai_adk statusline"
1747
+ else:
1748
+ statusline_command = "moai-adk statusline"
1749
+
1750
+ # Extract and resolve language configuration using centralized resolver
1751
+ try:
1752
+ from moai_adk.core.language_config_resolver import get_resolver
1753
+
1754
+ # Use language resolver to get complete configuration
1755
+ resolver = get_resolver(str(project_path))
1756
+ resolved_config = resolver.resolve_config()
1757
+
1758
+ # Extract language configuration with environment variable priority
1759
+ language_config = {
1760
+ "conversation_language": resolved_config.get("conversation_language", "en"),
1761
+ "conversation_language_name": resolved_config.get("conversation_language_name", "English"),
1762
+ "agent_prompt_language": resolved_config.get("agent_prompt_language", "en"),
1763
+ }
1764
+
1765
+ # Extract user personalization
1766
+ user_name = resolved_config.get("user_name", "")
1767
+ personalized_greeting = resolver.get_personalized_greeting(resolved_config)
1768
+ config_source = resolved_config.get("config_source", "config_file")
1769
+
1770
+ except ImportError:
1771
+ # Fallback to basic language config extraction if resolver not available
1772
+ language_config = existing_config.get("language", {})
1773
+ if not isinstance(language_config, dict):
1774
+ language_config = {}
1775
+
1776
+ user_name = existing_config.get("user", {}).get("name", "")
1777
+ conv_lang = language_config.get("conversation_language")
1778
+ personalized_greeting = f"{user_name}님" if user_name and conv_lang == "ko" else user_name
1779
+ config_source = "config_file"
1780
+
1781
+ # Enhanced version formatting (matches TemplateProcessor.get_enhanced_version_context)
1782
+ def format_short_version(v: str) -> str:
1783
+ """Remove 'v' prefix if present."""
1784
+ return v[1:] if v.startswith("v") else v
1785
+
1786
+ def format_display_version(v: str) -> str:
1787
+ """Format display version with proper formatting."""
1788
+ if v == "unknown":
1789
+ return "MoAI-ADK unknown version"
1790
+ elif v.startswith("v"):
1791
+ return f"MoAI-ADK {v}"
1792
+ else:
1793
+ return f"MoAI-ADK v{v}"
1794
+
1795
+ def format_trimmed_version(v: str, max_length: int = 10) -> str:
1796
+ """Format version with maximum length for UI displays."""
1797
+ if v == "unknown":
1798
+ return "unknown"
1799
+ clean_version = v[1:] if v.startswith("v") else v
1800
+ if len(clean_version) > max_length:
1801
+ return clean_version[:max_length]
1802
+ return clean_version
1803
+
1804
+ def format_semver_version(v: str) -> str:
1805
+ """Format version as semantic version."""
1806
+ if v == "unknown":
1807
+ return "0.0.0"
1808
+ clean_version = v[1:] if v.startswith("v") else v
1809
+ import re
1810
+
1811
+ semver_match = re.match(r"^(\d+\.\d+\.\d+)", clean_version)
1812
+ if semver_match:
1813
+ return semver_match.group(1)
1814
+ return "0.0.0"
1815
+
477
1816
  return {
478
1817
  "MOAI_VERSION": version_for_config,
1818
+ "MOAI_VERSION_SHORT": format_short_version(version_for_config),
1819
+ "MOAI_VERSION_DISPLAY": format_display_version(version_for_config),
1820
+ "MOAI_VERSION_TRIMMED": format_trimmed_version(version_for_config),
1821
+ "MOAI_VERSION_SEMVER": format_semver_version(version_for_config),
1822
+ "MOAI_VERSION_VALID": "true" if version_for_config != "unknown" else "false",
1823
+ "MOAI_VERSION_SOURCE": "config_cached",
479
1824
  "PROJECT_NAME": project_name,
480
1825
  "PROJECT_MODE": project_mode,
481
1826
  "PROJECT_DESCRIPTION": project_description,
482
1827
  "PROJECT_VERSION": project_version,
483
1828
  "CREATION_TIMESTAMP": created_at,
1829
+ "PROJECT_DIR": hook_project_dir,
1830
+ "CONVERSATION_LANGUAGE": language_config.get("conversation_language", "en"),
1831
+ "CONVERSATION_LANGUAGE_NAME": language_config.get("conversation_language_name", "English"),
1832
+ "AGENT_PROMPT_LANGUAGE": language_config.get("agent_prompt_language", "en"),
1833
+ "GIT_COMMIT_MESSAGES_LANGUAGE": language_config.get("git_commit_messages", "en"),
1834
+ "CODE_COMMENTS_LANGUAGE": language_config.get("code_comments", "en"),
1835
+ "DOCUMENTATION_LANGUAGE": language_config.get(
1836
+ "documentation", language_config.get("conversation_language", "en")
1837
+ ),
1838
+ "ERROR_MESSAGES_LANGUAGE": language_config.get(
1839
+ "error_messages", language_config.get("conversation_language", "en")
1840
+ ),
1841
+ "USER_NAME": user_name,
1842
+ "PERSONALIZED_GREETING": personalized_greeting,
1843
+ "LANGUAGE_CONFIG_SOURCE": config_source,
1844
+ "CODEBASE_LANGUAGE": project_section.get("language", "generic"),
1845
+ "PROJECT_OWNER": project_section.get("author", "@user"),
1846
+ "AUTHOR": project_section.get("author", "@user"),
1847
+ "STATUSLINE_COMMAND": statusline_command,
484
1848
  }
485
1849
 
486
1850
 
@@ -490,18 +1854,18 @@ def _preserve_project_metadata(
490
1854
  existing_config: dict[str, Any],
491
1855
  version_for_config: str,
492
1856
  ) -> None:
493
- """Restore project-specific metadata in the new config.json.
1857
+ """Restore project-specific metadata in the new config (YAML or JSON).
494
1858
 
495
1859
  Also updates template_version to track which template version is synchronized.
496
1860
  """
497
- config_path = project_path / ".moai" / "config.json"
1861
+ config_path, _ = _get_config_path(project_path)
498
1862
  if not config_path.exists():
499
1863
  return
500
1864
 
501
1865
  try:
502
- config_data = json.loads(config_path.read_text(encoding="utf-8"))
503
- except json.JSONDecodeError:
504
- console.print("[red]✗ Failed to parse config.json after template copy[/red]")
1866
+ config_data = _load_config(config_path)
1867
+ except (json.JSONDecodeError, yaml.YAMLError):
1868
+ console.print("[red]✗ Failed to parse config after template copy[/red]")
505
1869
  return
506
1870
 
507
1871
  project_data = config_data.setdefault("project", {})
@@ -528,14 +1892,10 @@ def _preserve_project_metadata(
528
1892
  config_data.setdefault("moai", {})
529
1893
  config_data["moai"]["version"] = version_for_config
530
1894
 
531
- # @CODE:UPDATE-REFACTOR-002-008: Update template_version to track sync status
532
1895
  # This allows Stage 2 to compare package vs project template versions
533
1896
  project_data["template_version"] = version_for_config
534
1897
 
535
- config_path.write_text(
536
- json.dumps(config_data, indent=2, ensure_ascii=False) + "\n",
537
- encoding="utf-8"
538
- )
1898
+ _save_config(config_path, config_data)
539
1899
 
540
1900
 
541
1901
  def _apply_context_to_file(processor: TemplateProcessor, target_path: Path) -> None:
@@ -557,7 +1917,88 @@ def _apply_context_to_file(processor: TemplateProcessor, target_path: Path) -> N
557
1917
  target_path.write_text(substituted, encoding="utf-8")
558
1918
 
559
1919
 
560
- # @CODE:UPDATE-REFACTOR-002-003
1920
+ def _validate_template_substitution(project_path: Path) -> None:
1921
+ """Validate that all template variables have been properly substituted."""
1922
+ import re
1923
+
1924
+ # Files to check for unsubstituted variables
1925
+ files_to_check = [
1926
+ project_path / ".claude" / "settings.json",
1927
+ project_path / "CLAUDE.md",
1928
+ ]
1929
+
1930
+ issues_found = []
1931
+
1932
+ for file_path in files_to_check:
1933
+ if not file_path.exists():
1934
+ continue
1935
+
1936
+ try:
1937
+ content = file_path.read_text(encoding="utf-8")
1938
+ # Look for unsubstituted template variables
1939
+ unsubstituted = re.findall(r"\{\{([A-Z_]+)\}\}", content)
1940
+ if unsubstituted:
1941
+ unique_vars = sorted(set(unsubstituted))
1942
+ issues_found.append(f"{file_path.relative_to(project_path)}: {', '.join(unique_vars)}")
1943
+ except Exception as e:
1944
+ console.print(f"[yellow]⚠️ Could not validate {file_path.relative_to(project_path)}: {e}[/yellow]")
1945
+
1946
+ if issues_found:
1947
+ console.print("[red]✗ Template substitution validation failed:[/red]")
1948
+ for issue in issues_found:
1949
+ console.print(f" {issue}")
1950
+ console.print("[yellow]💡 Check .moai/config/ files for missing variable values[/yellow]")
1951
+ else:
1952
+ console.print("[green]✅ Template substitution validation passed[/green]")
1953
+
1954
+
1955
+ def _validate_template_substitution_with_rollback(project_path: Path, backup_path: Path | None) -> bool:
1956
+ """Validate template substitution with rollback capability.
1957
+
1958
+ Returns:
1959
+ True if validation passed, False if failed (rollback handled by caller)
1960
+ """
1961
+ import re
1962
+
1963
+ # Files to check for unsubstituted variables
1964
+ files_to_check = [
1965
+ project_path / ".claude" / "settings.json",
1966
+ project_path / "CLAUDE.md",
1967
+ ]
1968
+
1969
+ issues_found = []
1970
+
1971
+ for file_path in files_to_check:
1972
+ if not file_path.exists():
1973
+ continue
1974
+
1975
+ try:
1976
+ content = file_path.read_text(encoding="utf-8")
1977
+ # Look for unsubstituted template variables
1978
+ unsubstituted = re.findall(r"\{\{([A-Z_]+)\}\}", content)
1979
+ if unsubstituted:
1980
+ unique_vars = sorted(set(unsubstituted))
1981
+ issues_found.append(f"{file_path.relative_to(project_path)}: {', '.join(unique_vars)}")
1982
+ except Exception as e:
1983
+ console.print(f"[yellow]⚠️ Could not validate {file_path.relative_to(project_path)}: {e}[/yellow]")
1984
+
1985
+ if issues_found:
1986
+ console.print("[red]✗ Template substitution validation failed:[/red]")
1987
+ for issue in issues_found:
1988
+ console.print(f" {issue}")
1989
+
1990
+ if backup_path:
1991
+ console.print("[yellow]🔄 Rolling back due to validation failure...[/yellow]")
1992
+ else:
1993
+ console.print("[yellow]💡 Check .moai/config/ files for missing variable values[/yellow]")
1994
+ console.print("[red]⚠️ No backup available - manual fix required[/red]")
1995
+
1996
+ return False
1997
+ else:
1998
+ console.print("[green]✅ Template substitution validation passed[/green]")
1999
+ return True
2000
+
2001
+
561
2002
  def _show_version_info(current: str, latest: str) -> None:
562
2003
  """Display version information.
563
2004
 
@@ -570,7 +2011,6 @@ def _show_version_info(current: str, latest: str) -> None:
570
2011
  console.print(f" Latest version: {latest}")
571
2012
 
572
2013
 
573
- # @CODE:UPDATE-REFACTOR-002-005
574
2014
  def _show_installer_not_found_help() -> None:
575
2015
  """Show help when installer not found."""
576
2016
  console.print("[red]❌ Cannot detect package installer[/red]\n")
@@ -624,35 +2064,103 @@ def _show_timeout_error_help() -> None:
624
2064
  console.print(" [cyan]moai-adk update --yes --force[/cyan]")
625
2065
 
626
2066
 
2067
+ def _execute_migration_if_needed(project_path: Path, yes: bool = False) -> bool:
2068
+ """Check and execute migration if needed.
2069
+
2070
+ Args:
2071
+ project_path: Project directory path
2072
+ yes: Auto-confirm without prompting
2073
+
2074
+ Returns:
2075
+ True if no migration needed or migration succeeded, False if migration failed
2076
+ """
2077
+ try:
2078
+ migrator = VersionMigrator(project_path)
2079
+
2080
+ # Check if migration is needed
2081
+ if not migrator.needs_migration():
2082
+ return True
2083
+
2084
+ # Get migration info
2085
+ info = migrator.get_migration_info()
2086
+ console.print("\n[cyan]🔄 Migration Required[/cyan]")
2087
+ console.print(f" Current version: {info['current_version']}")
2088
+ console.print(f" Target version: {info['target_version']}")
2089
+ console.print(f" Files to migrate: {info['file_count']}")
2090
+ console.print()
2091
+ console.print(" This will migrate configuration files to new locations:")
2092
+ console.print(" • .moai/config.json → .moai/config/config.json")
2093
+ console.print(" • .claude/statusline-config.yaml → .moai/config/statusline-config.yaml")
2094
+ console.print()
2095
+ console.print(" A backup will be created automatically.")
2096
+ console.print()
2097
+
2098
+ # Confirm with user (unless --yes)
2099
+ if not yes:
2100
+ reset_stdin() # Reset stdin before interactive prompt
2101
+ if not click.confirm("Do you want to proceed with migration?", default=True):
2102
+ console.print("[yellow]⚠️ Migration skipped. Some features may not work correctly.[/yellow]")
2103
+ console.print("[cyan]💡 Run 'moai-adk migrate' manually when ready[/cyan]")
2104
+ return False
2105
+
2106
+ # Execute migration
2107
+ console.print("[cyan]🚀 Starting migration...[/cyan]")
2108
+ success = migrator.migrate_to_v024(dry_run=False, cleanup=True)
2109
+
2110
+ if success:
2111
+ console.print("[green]✅ Migration completed successfully![/green]")
2112
+ return True
2113
+ else:
2114
+ console.print("[red]❌ Migration failed[/red]")
2115
+ console.print("[cyan]💡 Use 'moai-adk migrate --rollback' to restore from backup[/cyan]")
2116
+ return False
2117
+
2118
+ except Exception as e:
2119
+ console.print(f"[red]❌ Migration error: {e}[/red]")
2120
+ logger.error(f"Migration failed: {e}", exc_info=True)
2121
+ return False
2122
+
2123
+
627
2124
  @click.command()
628
2125
  @click.option(
629
2126
  "--path",
630
2127
  type=click.Path(exists=True),
631
2128
  default=".",
632
- help="Project path (default: current directory)"
633
- )
634
- @click.option(
635
- "--force",
636
- is_flag=True,
637
- help="Skip backup and force the update"
2129
+ help="Project path (default: current directory)",
638
2130
  )
2131
+ @click.option("--force", is_flag=True, help="Skip backup and force the update")
2132
+ @click.option("--check", is_flag=True, help="Only check version (do not update)")
2133
+ @click.option("--templates-only", is_flag=True, help="Skip package upgrade, sync templates only")
2134
+ @click.option("--yes", is_flag=True, help="Auto-confirm all prompts (CI/CD mode)")
639
2135
  @click.option(
640
- "--check",
2136
+ "-c",
2137
+ "--config",
2138
+ "edit_config",
641
2139
  is_flag=True,
642
- help="Only check version (do not update)"
2140
+ help="Edit project configuration (same as init wizard)",
643
2141
  )
644
2142
  @click.option(
645
- "--templates-only",
646
- is_flag=True,
647
- help="Skip package upgrade, sync templates only"
2143
+ "--merge",
2144
+ "merge_strategy",
2145
+ flag_value="auto",
2146
+ help="Auto-merge: Apply template + preserve user changes",
648
2147
  )
649
2148
  @click.option(
650
- "--yes",
651
- is_flag=True,
652
- help="Auto-confirm all prompts (CI/CD mode)"
2149
+ "--manual",
2150
+ "merge_strategy",
2151
+ flag_value="manual",
2152
+ help="Manual merge: Preserve backup, generate merge guide",
653
2153
  )
654
- def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool) -> None:
655
- """Update command with 3-stage workflow (v0.6.3+).
2154
+ def update(
2155
+ path: str,
2156
+ force: bool,
2157
+ check: bool,
2158
+ templates_only: bool,
2159
+ yes: bool,
2160
+ edit_config: bool,
2161
+ merge_strategy: str | None,
2162
+ ) -> None:
2163
+ """Update command with 3-stage workflow + merge strategy selection (v0.26.0+).
656
2164
 
657
2165
  Stage 1 (Package Version Check):
658
2166
  - Fetches current and latest versions from PyPI
@@ -664,33 +2172,73 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
664
2172
  - If versions match: skips Stage 3 (already up-to-date)
665
2173
  - Performance improvement: 70-80% faster for unchanged projects (3-4s vs 12-18s)
666
2174
 
667
- Stage 3 (Template Sync):
2175
+ Stage 3 (Template Sync with Merge Strategy - NEW in v0.26.0):
668
2176
  - Syncs templates only if versions differ
2177
+ - User chooses merge strategy:
2178
+ * Auto-merge (default): Template + preserved user changes
2179
+ * Manual merge: Backup + comprehensive merge guide (full control)
669
2180
  - Updates .claude/, .moai/, CLAUDE.md, config.json
670
2181
  - Preserves specs and reports
671
2182
  - Saves new template_version to config.json
672
2183
 
673
2184
  Examples:
674
- python -m moai_adk update # auto 3-stage workflow
675
- python -m moai_adk update --force # force template sync
2185
+ python -m moai_adk update # interactive merge strategy selection
2186
+ python -m moai_adk update --merge # auto-merge (template + user changes)
2187
+ python -m moai_adk update --manual # manual merge (backup + guide)
2188
+ python -m moai_adk update --force # force template sync (no backup)
676
2189
  python -m moai_adk update --check # check version only
677
2190
  python -m moai_adk update --templates-only # skip package upgrade
678
- python -m moai_adk update --yes # CI/CD mode (auto-confirm)
2191
+ python -m moai_adk update --yes # CI/CD mode (auto-confirm + auto-merge)
2192
+
2193
+ Merge Strategies:
2194
+ --merge: Auto-merge applies template + preserves your changes (default)
2195
+ Generated files: backup, merge report
2196
+ --manual: Manual merge preserves backup + generates comprehensive guide
2197
+ Generated files: backup, merge guide
2198
+
2199
+ Generated Files:
2200
+ - Backup: .moai-backups/pre-update-backup_{timestamp}/
2201
+ - Report: .moai/reports/merge-report.md (auto-merge only)
2202
+ - Guide: .moai/guides/merge-guide.md (manual merge only)
679
2203
  """
680
2204
  try:
681
- project_path = Path(path).resolve()
2205
+ # Use os.getcwd() for consistent path resolution in test environments
2206
+ if path == ".":
2207
+ project_path = Path(os.getcwd()).resolve()
2208
+ else:
2209
+ project_path = Path(path).resolve()
682
2210
 
683
2211
  # Verify the project is initialized
684
2212
  if not (project_path / ".moai").exists():
685
2213
  console.print("[yellow]⚠ Project not initialized[/yellow]")
686
2214
  raise click.Abort()
687
2215
 
2216
+ # Handle --config / -c mode (edit configuration only, no template updates)
2217
+ if edit_config:
2218
+ _edit_configuration(project_path)
2219
+ return
2220
+
688
2221
  # Get versions (needed for --check and normal workflow, but not for --templates-only alone)
689
2222
  # Note: If --check is used, always fetch versions even if --templates-only is also present
2223
+ # Initialize with defaults to satisfy type checker (will be set in the block below if needed)
2224
+ current: str = __version__
2225
+ latest: str = __version__
690
2226
  if check or not templates_only:
691
2227
  try:
692
- current = _get_current_version()
693
- latest = _get_latest_version()
2228
+ # Try to use new spinner UI
2229
+ try:
2230
+ from moai_adk.cli.ui.progress import SpinnerContext
2231
+
2232
+ with SpinnerContext("Checking for updates...") as spinner:
2233
+ current = _get_current_version()
2234
+ spinner.update("Fetching latest version from PyPI...")
2235
+ latest = _get_latest_version()
2236
+ spinner.success("Version check complete")
2237
+ except ImportError:
2238
+ # Fallback to simple console output
2239
+ console.print("[dim]Checking for updates...[/dim]")
2240
+ current = _get_current_version()
2241
+ latest = _get_latest_version()
694
2242
  except RuntimeError as e:
695
2243
  console.print(f"[red]Error: {e}[/red]")
696
2244
  if not force:
@@ -717,8 +2265,13 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
717
2265
  # Step 2: Handle --templates-only (skip upgrade, go straight to sync)
718
2266
  if templates_only:
719
2267
  console.print("[cyan]📄 Syncing templates only...[/cyan]")
2268
+
2269
+ # Preserve user-specific settings before sync
2270
+ console.print(" [cyan]💾 Preserving user settings...[/cyan]")
2271
+ preserved_settings = _preserve_user_settings(project_path)
2272
+
720
2273
  try:
721
- if not _sync_templates(project_path, force):
2274
+ if not _sync_templates(project_path, force, yes):
722
2275
  raise TemplateSyncError("Template sync returned False")
723
2276
  except TemplateSyncError:
724
2277
  console.print("[red]Error: Template sync failed[/red]")
@@ -729,6 +2282,9 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
729
2282
  _show_template_sync_failure_help()
730
2283
  raise click.Abort()
731
2284
 
2285
+ # Restore user-specific settings after sync
2286
+ _restore_user_settings(project_path, preserved_settings)
2287
+
732
2288
  console.print(" [green]✅ .claude/ update complete[/green]")
733
2289
  console.print(" [green]✅ .moai/ update complete (specs/reports preserved)[/green]")
734
2290
  console.print(" [green]🔄 CLAUDE.md merge complete[/green]")
@@ -740,12 +2296,12 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
740
2296
  comparison = _compare_versions(current, latest)
741
2297
 
742
2298
  # Stage 1: Package Upgrade (if current < latest)
743
- # @CODE:UPDATE-REFACTOR-002-009: Stage 1 - Package version check and upgrade
744
2299
  if comparison < 0:
745
2300
  console.print(f"\n[cyan]📦 Upgrading: {current} → {latest}[/cyan]")
746
2301
 
747
2302
  # Confirm upgrade (unless --yes)
748
2303
  if not yes:
2304
+ reset_stdin() # Reset stdin before interactive prompt
749
2305
  if not click.confirm(f"Upgrade {current} → {latest}?", default=True):
750
2306
  console.print("Cancelled")
751
2307
  return
@@ -779,10 +2335,20 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
779
2335
  console.print("[cyan]📢 Run 'moai-adk update' again to sync templates[/cyan]")
780
2336
  return
781
2337
 
782
- # Stage 2: Config Version Comparison
783
- # @CODE:UPDATE-REFACTOR-002-010: Stage 2 - Compare template versions to determine if sync needed
2338
+ # Stage 1.5: Migration Check (NEW in v0.24.0)
784
2339
  console.print(f"✓ Package already up to date ({current})")
785
2340
 
2341
+ # Execute migration if needed
2342
+ if not _execute_migration_if_needed(project_path, yes):
2343
+ console.print("[yellow]⚠️ Update continuing without migration[/yellow]")
2344
+ console.print("[cyan]💡 Some features may require migration to work correctly[/cyan]")
2345
+
2346
+ # Migrate config.json → config.yaml (v0.32.0+)
2347
+ console.print("\n[cyan]🔍 Checking for config format migration...[/cyan]")
2348
+ if not _migrate_config_json_to_yaml(project_path):
2349
+ console.print("[yellow]⚠️ Config migration failed, continuing with existing format[/yellow]")
2350
+
2351
+ # Stage 2: Config Version Comparison
786
2352
  try:
787
2353
  package_config_version = _get_package_config_version()
788
2354
  project_config_version = _get_project_config_version(project_path)
@@ -796,7 +2362,14 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
796
2362
  console.print(f" Package template: {package_config_version}")
797
2363
  console.print(f" Project config: {project_config_version}")
798
2364
 
799
- config_comparison = _compare_versions(package_config_version, project_config_version)
2365
+ try:
2366
+ config_comparison = _compare_versions(package_config_version, project_config_version)
2367
+ except version.InvalidVersion as e:
2368
+ # Handle invalid version strings (e.g., unsubstituted template placeholders, corrupted configs)
2369
+ console.print(f"[yellow]⚠ Invalid version format in config: {e}[/yellow]")
2370
+ console.print("[cyan]ℹ️ Forcing template sync to repair configuration...[/cyan]")
2371
+ # Force template sync by treating project version as outdated
2372
+ config_comparison = 1 # package_config_version > project_config_version
800
2373
 
801
2374
  # If versions are equal, no sync needed
802
2375
  if config_comparison <= 0:
@@ -805,9 +2378,52 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
805
2378
  return
806
2379
 
807
2380
  # Stage 3: Template Sync (Only if package_config_version > project_config_version)
808
- # @CODE:UPDATE-REFACTOR-002-011: Stage 3 - Template sync only if versions differ
809
2381
  console.print(f"\n[cyan]📄 Syncing templates ({project_config_version} → {package_config_version})...[/cyan]")
810
2382
 
2383
+ # Determine merge strategy (default: auto-merge)
2384
+ final_merge_strategy = merge_strategy or "auto"
2385
+
2386
+ # Handle merge strategy
2387
+ if final_merge_strategy == "manual":
2388
+ # Manual merge mode: Create full backup + generate guide, no template sync
2389
+ console.print("\n[cyan]🔀 Manual merge mode selected[/cyan]")
2390
+
2391
+ # Create full project backup
2392
+ console.print(" [cyan]💾 Creating full project backup...[/cyan]")
2393
+ try:
2394
+ from moai_adk.core.migration.backup_manager import BackupManager
2395
+
2396
+ backup_manager = BackupManager(project_path)
2397
+ full_backup_path = backup_manager.create_full_project_backup(description="pre-update-backup")
2398
+ console.print(f" [green]✓ Backup: {full_backup_path.relative_to(project_path)}/[/green]")
2399
+
2400
+ # Generate merge guide
2401
+ console.print(" [cyan]📋 Generating merge guide...[/cyan]")
2402
+ template_path = Path(__file__).parent.parent.parent / "templates"
2403
+ guide_path = _generate_manual_merge_guide(full_backup_path, template_path, project_path)
2404
+ console.print(f" [green]✓ Guide: {guide_path.relative_to(project_path)}[/green]")
2405
+
2406
+ # Summary
2407
+ console.print("\n[green]✓ Manual merge setup complete![/green]")
2408
+ console.print(f"[cyan]📍 Backup location: {full_backup_path.relative_to(project_path)}/[/cyan]")
2409
+ console.print(f"[cyan]📋 Merge guide: {guide_path.relative_to(project_path)}[/cyan]")
2410
+ console.print("\n[yellow]⚠️ Next steps:[/yellow]")
2411
+ console.print("[yellow] 1. Review the merge guide[/yellow]")
2412
+ console.print("[yellow] 2. Compare files using diff or visual tools[/yellow]")
2413
+ console.print("[yellow] 3. Manually merge your customizations[/yellow]")
2414
+ console.print("[yellow] 4. Test and commit changes[/yellow]")
2415
+
2416
+ except Exception as e:
2417
+ console.print(f"[red]Error: Manual merge setup failed - {e}[/red]")
2418
+ raise click.Abort()
2419
+
2420
+ return
2421
+
2422
+ # Auto merge mode: Preserve user-specific settings before sync
2423
+ console.print("\n[cyan]🔀 Auto-merge mode selected[/cyan]")
2424
+ console.print(" [cyan]💾 Preserving user settings...[/cyan]")
2425
+ preserved_settings = _preserve_user_settings(project_path)
2426
+
811
2427
  # Create backup unless --force
812
2428
  if not force:
813
2429
  console.print(" [cyan]💾 Creating backup...[/cyan]")
@@ -815,16 +2431,28 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
815
2431
  processor = TemplateProcessor(project_path)
816
2432
  backup_path = processor.create_backup()
817
2433
  console.print(f" [green]✓ Backup: {backup_path.relative_to(project_path)}/[/green]")
2434
+
2435
+ # Clean up old backups (keep last 5)
2436
+ from moai_adk.core.template.backup import TemplateBackup
2437
+
2438
+ template_backup = TemplateBackup(project_path)
2439
+ deleted_count = template_backup.cleanup_old_backups(keep_count=5)
2440
+ if deleted_count > 0:
2441
+ console.print(f" [cyan]🧹 Cleaned up {deleted_count} old backup(s)[/cyan]")
818
2442
  except Exception as e:
819
2443
  console.print(f" [yellow]⚠ Backup failed: {e}[/yellow]")
820
2444
  console.print(" [yellow]⚠ Continuing without backup...[/yellow]")
821
2445
  else:
822
2446
  console.print(" [yellow]⚠ Skipping backup (--force)[/yellow]")
823
2447
 
824
- # Sync templates
2448
+ # Sync templates (NO spinner - user interaction may be required)
2449
+ # SpinnerContext blocks stdin, causing hang when click.confirm() is called
825
2450
  try:
826
- if not _sync_templates(project_path, force):
2451
+ console.print(" [cyan]Syncing templates...[/cyan]")
2452
+ if not _sync_templates(project_path, force, yes):
827
2453
  raise TemplateSyncError("Template sync returned False")
2454
+ _restore_user_settings(project_path, preserved_settings)
2455
+ console.print(" [green]✓ Template sync complete[/green]")
828
2456
  except TemplateSyncError:
829
2457
  console.print("[red]Error: Template sync failed[/red]")
830
2458
  _show_template_sync_failure_help()
@@ -841,8 +2469,482 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
841
2469
  console.print(" [yellow]⚙️ Set optimized=false (optimization needed)[/yellow]")
842
2470
 
843
2471
  console.print("\n[green]✓ Update complete![/green]")
844
- console.print("[cyan]ℹ️ Next step: Run /alfred:0-project update to optimize template changes[/cyan]")
2472
+
2473
+ # Prompt for MoAI Rank hook installation if eligible
2474
+ try:
2475
+ from moai_adk.rank.hook import prompt_hook_installation
2476
+
2477
+ prompt_hook_installation(console=console)
2478
+ except ImportError:
2479
+ pass # rank module not available
845
2480
 
846
2481
  except Exception as e:
847
2482
  console.print(f"[red]✗ Update failed: {e}[/red]")
848
2483
  raise click.ClickException(str(e)) from e
2484
+
2485
+
2486
+ def _handle_custom_element_restoration(project_path: Path, backup_path: Path | None, yes: bool = False) -> None:
2487
+ """Handle custom element restoration using the enhanced system.
2488
+
2489
+ This function provides an improved interface for restoring user-created custom elements
2490
+ (agents, commands, skills, hooks) from backup during MoAI-ADK updates.
2491
+
2492
+ Key improvements:
2493
+ - Preserves unselected elements (fixes disappearing issue)
2494
+ - Only overwrites/creates selected elements from backup
2495
+ - Interactive checkbox selection with arrow key navigation
2496
+ - Includes all categories (Agents, Commands, Skills, Hooks)
2497
+
2498
+ Args:
2499
+ project_path: Path to the MoAI-ADK project directory
2500
+ backup_path: Path to the backup directory (None if no backup)
2501
+ yes: Whether to automatically accept defaults (non-interactive mode)
2502
+ """
2503
+ if not backup_path:
2504
+ # No backup available, cannot restore
2505
+ return
2506
+
2507
+ try:
2508
+ # Create scanner to find custom elements in backup (not current project)
2509
+ backup_scanner = create_custom_element_scanner(backup_path)
2510
+
2511
+ # Get count of custom elements in backup
2512
+ backup_element_count = backup_scanner.get_element_count()
2513
+
2514
+ if backup_element_count == 0:
2515
+ # No custom elements found in backup
2516
+ console.print("[green]✓ No custom elements found in backup to restore[/green]")
2517
+ return
2518
+
2519
+ # Create enhanced user selection UI
2520
+ # IMPORTANT: Use backup_path, not project_path!
2521
+ # At this point, custom elements in project have been deleted by copy_templates().
2522
+ # The UI must scan the BACKUP to find elements available for restoration.
2523
+ ui = create_user_selection_ui(backup_path)
2524
+
2525
+ console.print(f"\n[cyan]🔍 Found {backup_element_count} custom elements in backup[/cyan]")
2526
+
2527
+ # If yes mode is enabled, restore all elements automatically
2528
+ if yes:
2529
+ console.print(f"[cyan]🔄 Auto-restoring {backup_element_count} custom elements...[/cyan]")
2530
+ backup_custom_elements = backup_scanner.scan_custom_elements()
2531
+ selected_elements = []
2532
+
2533
+ # Collect all element paths from backup
2534
+ for element_type, elements in backup_custom_elements.items():
2535
+ if element_type == "skills":
2536
+ for skill in elements:
2537
+ selected_elements.append(str(skill.path))
2538
+ else:
2539
+ for element_path in elements:
2540
+ selected_elements.append(str(element_path))
2541
+ else:
2542
+ # Interactive mode - prompt user for selection using enhanced UI
2543
+ selected_elements = ui.prompt_user_selection(backup_available=True)
2544
+
2545
+ if not selected_elements:
2546
+ console.print("[yellow]⚠ No elements selected for restoration[/yellow]")
2547
+ console.print("[green]✓ All existing custom elements will be preserved[/green]")
2548
+ return
2549
+
2550
+ # Confirm selection
2551
+ if not ui.confirm_selection(selected_elements):
2552
+ console.print("[yellow]⚠ Restoration cancelled by user[/yellow]")
2553
+ console.print("[green]✓ All existing custom elements will be preserved[/green]")
2554
+ return
2555
+
2556
+ # Perform selective restoration - ONLY restore selected elements
2557
+ if selected_elements:
2558
+ console.print(f"[cyan]🔄 Restoring {len(selected_elements)} selected elements from backup...[/cyan]")
2559
+ restorer = create_selective_restorer(project_path, backup_path)
2560
+ success, stats = restorer.restore_elements(selected_elements)
2561
+
2562
+ if success:
2563
+ console.print(f"[green]✅ Successfully restored {stats['success']} custom elements[/green]")
2564
+ console.print("[green]✓ All unselected elements remain preserved[/green]")
2565
+ else:
2566
+ console.print(f"[yellow]⚠️ Partial restoration: {stats['success']}/{stats['total']} elements[/yellow]")
2567
+ if stats["failed"] > 0:
2568
+ console.print(f"[red]❌ Failed to restore {stats['failed']} elements[/red]")
2569
+ console.print("[yellow]⚠️ All other elements remain preserved[/yellow]")
2570
+ else:
2571
+ console.print("[green]✓ No elements selected, all custom elements preserved[/green]")
2572
+
2573
+ except Exception as e:
2574
+ console.print(f"[yellow]⚠️ Custom element restoration failed: {e}[/yellow]")
2575
+ logger.warning(f"Custom element restoration error: {e}")
2576
+ console.print("[yellow]⚠️ All existing custom elements remain as-is[/yellow]")
2577
+ # Don't fail the entire update process, just log the error
2578
+ pass
2579
+
2580
+
2581
+ def _cleanup_legacy_presets(project_path: Path) -> None:
2582
+ """Remove legacy presets directory entirely.
2583
+
2584
+ This function removes the entire .moai/config/presets/ directory as it is
2585
+ no longer used. All preset settings are now consolidated in sections/git-strategy.yaml.
2586
+
2587
+ Args:
2588
+ project_path: Project directory path (absolute)
2589
+ """
2590
+ import shutil
2591
+
2592
+ presets_dir = project_path / ".moai" / "config" / "presets"
2593
+
2594
+ if not presets_dir.exists() or not presets_dir.is_dir():
2595
+ return
2596
+
2597
+ try:
2598
+ # Remove entire presets directory (no longer needed)
2599
+ shutil.rmtree(presets_dir)
2600
+ console.print(" [cyan]🧹 Removed legacy presets directory (now in sections/git-strategy.yaml)[/cyan]")
2601
+ logger.info(f"Removed legacy presets directory: {presets_dir}")
2602
+ except Exception as e:
2603
+ logger.warning(f"Failed to remove legacy presets directory {presets_dir}: {e}")
2604
+
2605
+
2606
+ def _cleanup_cli_redesign_obsolete_files(project_path: Path, dry_run: bool = False) -> int:
2607
+ """
2608
+ Remove obsolete files from CLI redesign migration (v0.41+).
2609
+
2610
+ Cleans up:
2611
+ - .moai/scripts/setup-glm.py (replaced by moai init CLI)
2612
+ - .moai/config/questions/ (replaced by moai init CLI prompts)
2613
+ - .moai/scripts/ (if empty after cleanup)
2614
+
2615
+ Args:
2616
+ project_path: Project directory path
2617
+ dry_run: If True, only simulate cleanup
2618
+
2619
+ Returns:
2620
+ Number of items cleaned up
2621
+ """
2622
+ obsolete_items = [
2623
+ ".moai/scripts/setup-glm.py",
2624
+ ".moai/config/questions",
2625
+ ]
2626
+
2627
+ cleaned_count = 0
2628
+
2629
+ for relative_path in obsolete_items:
2630
+ full_path = project_path / relative_path
2631
+
2632
+ if not full_path.exists():
2633
+ continue
2634
+
2635
+ try:
2636
+ if dry_run:
2637
+ console.print(f" [dim]Would remove: {relative_path}[/dim]")
2638
+ cleaned_count += 1
2639
+ else:
2640
+ if full_path.is_dir():
2641
+ shutil.rmtree(full_path)
2642
+ console.print(f" [cyan]Removed obsolete directory: {relative_path}[/cyan]")
2643
+ else:
2644
+ full_path.unlink()
2645
+ console.print(f" [cyan]Removed obsolete file: {relative_path}[/cyan]")
2646
+ logger.info(f"Cleaned up obsolete: {relative_path}")
2647
+ cleaned_count += 1
2648
+ except Exception as e:
2649
+ logger.warning(f"Failed to clean up {relative_path}: {e}")
2650
+
2651
+ # Remove .moai/scripts/ if empty
2652
+ scripts_dir = project_path / ".moai" / "scripts"
2653
+ if scripts_dir.exists() and scripts_dir.is_dir():
2654
+ try:
2655
+ if not any(scripts_dir.iterdir()):
2656
+ if dry_run:
2657
+ console.print(" [dim]Would remove: .moai/scripts (empty)[/dim]")
2658
+ else:
2659
+ shutil.rmtree(scripts_dir)
2660
+ console.print(" [cyan]Removed empty .moai/scripts directory[/cyan]")
2661
+ logger.info("Removed empty .moai/scripts directory")
2662
+ cleaned_count += 1
2663
+ except Exception as e:
2664
+ logger.warning(f"Failed to remove empty scripts directory: {e}")
2665
+
2666
+ return cleaned_count
2667
+
2668
+
2669
+ def _migrate_config_json_to_yaml(project_path: Path) -> bool:
2670
+ """Migrate legacy config.json to config.yaml format.
2671
+
2672
+ This function:
2673
+ 1. Checks if config.json exists
2674
+ 2. Converts it to config.yaml using YAML format
2675
+ 3. Removes the old config.json file
2676
+ 4. Also migrates preset files from JSON to YAML
2677
+
2678
+ Args:
2679
+ project_path: Project directory path (absolute)
2680
+
2681
+ Returns:
2682
+ bool: True if migration successful or not needed, False on error
2683
+ """
2684
+ try:
2685
+ import yaml
2686
+ except ImportError:
2687
+ console.print(" [yellow]⚠️ PyYAML not available, skipping config migration[/yellow]")
2688
+ return True # Not a critical error
2689
+
2690
+ config_dir = project_path / ".moai" / "config"
2691
+ json_path = config_dir / "config.json"
2692
+ yaml_path = config_dir / "config.yaml"
2693
+
2694
+ # Check if migration needed
2695
+ if not json_path.exists():
2696
+ # No JSON file, migration not needed
2697
+ return True
2698
+
2699
+ if yaml_path.exists():
2700
+ # YAML already exists, just remove JSON
2701
+ try:
2702
+ json_path.unlink()
2703
+ console.print(" [cyan]🔄 Removed legacy config.json (YAML version exists)[/cyan]")
2704
+ logger.info(f"Removed legacy config.json: {json_path}")
2705
+ return True
2706
+ except Exception as e:
2707
+ console.print(f" [yellow]⚠️ Failed to remove legacy config.json: {e}[/yellow]")
2708
+ logger.warning(f"Failed to remove {json_path}: {e}")
2709
+ return True # Not critical
2710
+
2711
+ # Perform migration
2712
+ try:
2713
+ # Read JSON config
2714
+ with open(json_path, "r", encoding="utf-8") as f:
2715
+ config_data = json.load(f)
2716
+
2717
+ # Write YAML config
2718
+ with open(yaml_path, "w", encoding="utf-8") as f:
2719
+ yaml.safe_dump(
2720
+ config_data,
2721
+ f,
2722
+ default_flow_style=False,
2723
+ allow_unicode=True,
2724
+ sort_keys=False,
2725
+ )
2726
+
2727
+ # Remove old JSON file
2728
+ json_path.unlink()
2729
+
2730
+ console.print(" [green]✓ Migrated config.json → config.yaml[/green]")
2731
+ logger.info(f"Migrated config from JSON to YAML: {json_path} → {yaml_path}")
2732
+
2733
+ # Migrate preset files if they exist
2734
+ _migrate_preset_files_to_yaml(config_dir)
2735
+
2736
+ return True
2737
+
2738
+ except Exception as e:
2739
+ console.print(f" [red]✗ Config migration failed: {e}[/red]")
2740
+ logger.error(f"Failed to migrate config.json to YAML: {e}")
2741
+ return False
2742
+
2743
+
2744
+ def _migrate_preset_files_to_yaml(config_dir: Path) -> None:
2745
+ """Migrate preset files from JSON to YAML format.
2746
+
2747
+ Args:
2748
+ config_dir: .moai/config directory path
2749
+ """
2750
+ try:
2751
+ import yaml
2752
+ except ImportError:
2753
+ return
2754
+
2755
+ presets_dir = config_dir / "presets"
2756
+ if not presets_dir.exists():
2757
+ return
2758
+
2759
+ migrated_count = 0
2760
+ for json_file in presets_dir.glob("*.json"):
2761
+ yaml_file = json_file.with_suffix(".yaml")
2762
+
2763
+ # Skip if YAML already exists
2764
+ if yaml_file.exists():
2765
+ # Just remove the JSON file
2766
+ try:
2767
+ json_file.unlink()
2768
+ migrated_count += 1
2769
+ except Exception as e:
2770
+ logger.warning(f"Failed to remove {json_file}: {e}")
2771
+ continue
2772
+
2773
+ # Migrate JSON → YAML
2774
+ try:
2775
+ with open(json_file, "r", encoding="utf-8") as f:
2776
+ preset_data = json.load(f)
2777
+
2778
+ with open(yaml_file, "w", encoding="utf-8") as f:
2779
+ yaml.safe_dump(
2780
+ preset_data,
2781
+ f,
2782
+ default_flow_style=False,
2783
+ allow_unicode=True,
2784
+ sort_keys=False,
2785
+ )
2786
+
2787
+ json_file.unlink()
2788
+ migrated_count += 1
2789
+
2790
+ except Exception as e:
2791
+ logger.warning(f"Failed to migrate preset {json_file}: {e}")
2792
+
2793
+ if migrated_count > 0:
2794
+ console.print(f" [cyan]🔄 Migrated {migrated_count} preset file(s) to YAML[/cyan]")
2795
+ logger.info(f"Migrated {migrated_count} preset files to YAML")
2796
+
2797
+
2798
+ def _load_current_settings(project_path: Path) -> dict[str, Any]:
2799
+ """Load current settings from section YAML files.
2800
+
2801
+ Args:
2802
+ project_path: Project directory path
2803
+
2804
+ Returns:
2805
+ Dictionary with current settings from all section files
2806
+ """
2807
+ sections_dir = project_path / ".moai" / "config" / "sections"
2808
+ settings: dict[str, Any] = {}
2809
+
2810
+ section_files = [
2811
+ ("language", "language.yaml"),
2812
+ ("project", "project.yaml"),
2813
+ ("pricing", "pricing.yaml"),
2814
+ ("git_strategy", "git-strategy.yaml"),
2815
+ ("user", "user.yaml"),
2816
+ ("llm", "llm.yaml"),
2817
+ ]
2818
+
2819
+ for key, filename in section_files:
2820
+ file_path = sections_dir / filename
2821
+ if file_path.exists():
2822
+ try:
2823
+ data = yaml.safe_load(file_path.read_text(encoding="utf-8"))
2824
+ if data:
2825
+ settings[key] = data
2826
+ except yaml.YAMLError:
2827
+ pass
2828
+
2829
+ return settings
2830
+
2831
+
2832
+ def _show_current_config(project_path: Path) -> None:
2833
+ """Display current configuration summary in a panel.
2834
+
2835
+ Args:
2836
+ project_path: Project directory path
2837
+ """
2838
+ from rich.panel import Panel
2839
+
2840
+ settings = _load_current_settings(project_path)
2841
+
2842
+ # Extract values with defaults
2843
+ project_name = settings.get("project", {}).get("project", {}).get("name", project_path.name)
2844
+ if isinstance(settings.get("project", {}).get("project"), dict):
2845
+ project_name = settings["project"]["project"].get("name", project_path.name)
2846
+ elif "project" in settings and "name" in settings.get("project", {}).get("project", {}):
2847
+ project_name = settings["project"]["project"]["name"]
2848
+ else:
2849
+ # Try alternative structure
2850
+ project_name = settings.get("project", {}).get("name", project_path.name)
2851
+
2852
+ user_name = settings.get("user", {}).get("user", {}).get("name", "")
2853
+ if not user_name and isinstance(settings.get("user"), dict):
2854
+ user_name = settings.get("user", {}).get("name", "")
2855
+
2856
+ conv_lang = settings.get("language", {}).get("language", {}).get("conversation_language", "en")
2857
+ conv_lang_name = settings.get("language", {}).get("language", {}).get("conversation_language_name", "English")
2858
+
2859
+ # GLM-only simplified flow - service is always GLM
2860
+ glm_pricing_plan = settings.get("pricing", {}).get("service", {}).get("glm_pricing_plan", "basic")
2861
+
2862
+ git_mode = settings.get("git_strategy", {}).get("git_strategy", {}).get("mode", "personal")
2863
+
2864
+ llm_mode = settings.get("llm", {}).get("llm", {}).get("mode", "claude-only")
2865
+
2866
+ # Build display content
2867
+ lines = [
2868
+ f"📁 Project: [cyan]{project_name}[/cyan]",
2869
+ ]
2870
+ if user_name:
2871
+ lines.append(f"👤 User: [cyan]{user_name}[/cyan]")
2872
+
2873
+ lines.append("")
2874
+ lines.append(f"🌐 Language: [green]{conv_lang}[/green] ({conv_lang_name})")
2875
+ lines.append("🔧 Service: [green]GLM CodePlan[/green]" + (f" ({glm_pricing_plan})" if glm_pricing_plan else ""))
2876
+ lines.append(f"🔀 Git: [green]{git_mode}[/green]")
2877
+ lines.append(f"🤖 LLM Mode: [green]{llm_mode}[/green]")
2878
+
2879
+ content = "\n".join(lines)
2880
+ console.print(Panel(content, title="[yellow]Current Configuration[/yellow]", border_style="cyan"))
2881
+
2882
+
2883
+ def _edit_configuration(project_path: Path) -> None:
2884
+ """Interactive configuration editing using init prompts.
2885
+
2886
+ Args:
2887
+ project_path: Project directory path
2888
+ """
2889
+ from moai_adk.cli.commands.init import _save_additional_config
2890
+ from moai_adk.cli.prompts.init_prompts import prompt_project_setup
2891
+
2892
+ console.print("\n[cyan]⚙️ Configuration Edit Mode[/cyan]")
2893
+ console.print("[dim]Edit your project settings (same as init wizard)[/dim]\n")
2894
+
2895
+ # Show current config
2896
+ _show_current_config(project_path)
2897
+ console.print()
2898
+
2899
+ # Load current settings to pre-fill
2900
+ settings = _load_current_settings(project_path)
2901
+
2902
+ # Extract current locale for pre-fill
2903
+ current_locale = settings.get("language", {}).get("language", {}).get("conversation_language", "en")
2904
+ project_name = project_path.name
2905
+
2906
+ # Try to get project name from settings
2907
+ project_data = settings.get("project", {})
2908
+ if isinstance(project_data.get("project"), dict):
2909
+ project_name = project_data["project"].get("name", project_path.name)
2910
+ elif "name" in project_data:
2911
+ project_name = project_data.get("name", project_path.name)
2912
+
2913
+ # Run interactive prompt
2914
+ try:
2915
+ answers = prompt_project_setup(
2916
+ project_name=project_name,
2917
+ is_current_dir=True,
2918
+ project_path=project_path,
2919
+ initial_locale=current_locale,
2920
+ )
2921
+ except KeyboardInterrupt:
2922
+ console.print("\n[yellow]Configuration edit cancelled.[/yellow]")
2923
+ return
2924
+
2925
+ if not answers:
2926
+ console.print("[yellow]No changes made.[/yellow]")
2927
+ return
2928
+
2929
+ # Save configuration to section files
2930
+ # Note: API keys are not modified in config edit mode (pass None to preserve existing)
2931
+ # GLM-only flow: service_type is always "glm", glm_pricing_plan defaults to "basic"
2932
+ _save_additional_config(
2933
+ project_path=project_path,
2934
+ project_name=answers.get("project_name", project_name),
2935
+ locale=answers.get("locale", current_locale),
2936
+ user_name=answers.get("user_name", ""),
2937
+ service_type="glm", # Always GLM in simplified flow
2938
+ pricing_plan=None, # Not used in GLM-only flow
2939
+ glm_pricing_plan="basic", # Default GLM pricing plan
2940
+ anthropic_api_key=None, # Not used in GLM-only flow
2941
+ glm_api_key=None, # Preserve existing key
2942
+ git_mode=answers.get("git_mode", "personal"),
2943
+ github_username=answers.get("github_username"),
2944
+ git_commit_lang=answers.get("git_commit_lang", "en"),
2945
+ code_comment_lang=answers.get("code_comment_lang", "en"),
2946
+ doc_lang=answers.get("doc_lang", "en"),
2947
+ )
2948
+
2949
+ console.print("\n[green]✓ Configuration updated successfully![/green]")
2950
+ console.print("[dim]Changes saved to .moai/config/sections/[/dim]")