moai-adk 0.35.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of moai-adk might be problematic. Click here for more details.

Files changed (502) hide show
  1. moai_adk/__init__.py +10 -0
  2. moai_adk/__main__.py +199 -0
  3. moai_adk/cli/__init__.py +6 -0
  4. moai_adk/cli/commands/__init__.py +17 -0
  5. moai_adk/cli/commands/analyze.py +116 -0
  6. moai_adk/cli/commands/doctor.py +272 -0
  7. moai_adk/cli/commands/init.py +372 -0
  8. moai_adk/cli/commands/language.py +248 -0
  9. moai_adk/cli/commands/status.py +104 -0
  10. moai_adk/cli/commands/update.py +2686 -0
  11. moai_adk/cli/main.py +13 -0
  12. moai_adk/cli/prompts/__init__.py +5 -0
  13. moai_adk/cli/prompts/init_prompts.py +219 -0
  14. moai_adk/cli/spec_status.py +263 -0
  15. moai_adk/cli/ui/__init__.py +44 -0
  16. moai_adk/cli/ui/progress.py +422 -0
  17. moai_adk/cli/ui/prompts.py +389 -0
  18. moai_adk/cli/ui/theme.py +129 -0
  19. moai_adk/cli/worktree/__init__.py +27 -0
  20. moai_adk/cli/worktree/__main__.py +31 -0
  21. moai_adk/cli/worktree/cli.py +683 -0
  22. moai_adk/cli/worktree/exceptions.py +89 -0
  23. moai_adk/cli/worktree/manager.py +493 -0
  24. moai_adk/cli/worktree/models.py +65 -0
  25. moai_adk/cli/worktree/registry.py +422 -0
  26. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  27. moai_adk/core/__init__.py +1 -0
  28. moai_adk/core/analysis/__init__.py +9 -0
  29. moai_adk/core/analysis/session_analyzer.py +400 -0
  30. moai_adk/core/claude_integration.py +393 -0
  31. moai_adk/core/command_helpers.py +270 -0
  32. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  33. moai_adk/core/config/__init__.py +19 -0
  34. moai_adk/core/config/auto_spec_config.py +340 -0
  35. moai_adk/core/config/migration.py +244 -0
  36. moai_adk/core/config/unified.py +436 -0
  37. moai_adk/core/context_manager.py +273 -0
  38. moai_adk/core/diagnostics/__init__.py +19 -0
  39. moai_adk/core/diagnostics/slash_commands.py +159 -0
  40. moai_adk/core/enterprise_features.py +1404 -0
  41. moai_adk/core/error_recovery_system.py +1902 -0
  42. moai_adk/core/event_driven_hook_system.py +1371 -0
  43. moai_adk/core/git/__init__.py +31 -0
  44. moai_adk/core/git/branch.py +25 -0
  45. moai_adk/core/git/branch_manager.py +129 -0
  46. moai_adk/core/git/checkpoint.py +134 -0
  47. moai_adk/core/git/commit.py +67 -0
  48. moai_adk/core/git/conflict_detector.py +413 -0
  49. moai_adk/core/git/event_detector.py +79 -0
  50. moai_adk/core/git/manager.py +216 -0
  51. moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
  52. moai_adk/core/input_validation_middleware.py +1006 -0
  53. moai_adk/core/integration/__init__.py +22 -0
  54. moai_adk/core/integration/engine.py +157 -0
  55. moai_adk/core/integration/integration_tester.py +226 -0
  56. moai_adk/core/integration/models.py +88 -0
  57. moai_adk/core/integration/utils.py +211 -0
  58. moai_adk/core/issue_creator.py +305 -0
  59. moai_adk/core/jit_context_loader.py +956 -0
  60. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  61. moai_adk/core/language_config.py +202 -0
  62. moai_adk/core/language_config_resolver.py +572 -0
  63. moai_adk/core/language_validator.py +543 -0
  64. moai_adk/core/mcp/setup.py +116 -0
  65. moai_adk/core/merge/__init__.py +9 -0
  66. moai_adk/core/merge/analyzer.py +605 -0
  67. moai_adk/core/migration/__init__.py +18 -0
  68. moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
  69. moai_adk/core/migration/backup_manager.py +277 -0
  70. moai_adk/core/migration/custom_element_scanner.py +358 -0
  71. moai_adk/core/migration/file_migrator.py +209 -0
  72. moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
  73. moai_adk/core/migration/selective_restorer.py +470 -0
  74. moai_adk/core/migration/template_utils.py +74 -0
  75. moai_adk/core/migration/user_selection_ui.py +338 -0
  76. moai_adk/core/migration/version_detector.py +139 -0
  77. moai_adk/core/migration/version_migrator.py +228 -0
  78. moai_adk/core/performance/__init__.py +6 -0
  79. moai_adk/core/performance/cache_system.py +316 -0
  80. moai_adk/core/performance/parallel_processor.py +116 -0
  81. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  82. moai_adk/core/project/__init__.py +1 -0
  83. moai_adk/core/project/backup_utils.py +70 -0
  84. moai_adk/core/project/checker.py +300 -0
  85. moai_adk/core/project/detector.py +293 -0
  86. moai_adk/core/project/initializer.py +387 -0
  87. moai_adk/core/project/phase_executor.py +716 -0
  88. moai_adk/core/project/validator.py +139 -0
  89. moai_adk/core/quality/__init__.py +6 -0
  90. moai_adk/core/quality/trust_checker.py +377 -0
  91. moai_adk/core/quality/validators/__init__.py +6 -0
  92. moai_adk/core/quality/validators/base_validator.py +19 -0
  93. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  94. moai_adk/core/robust_json_parser.py +611 -0
  95. moai_adk/core/rollback_manager.py +918 -0
  96. moai_adk/core/session_manager.py +651 -0
  97. moai_adk/core/skill_loading_system.py +579 -0
  98. moai_adk/core/spec/confidence_scoring.py +680 -0
  99. moai_adk/core/spec/ears_template_engine.py +1247 -0
  100. moai_adk/core/spec/quality_validator.py +687 -0
  101. moai_adk/core/spec_status_manager.py +478 -0
  102. moai_adk/core/template/__init__.py +7 -0
  103. moai_adk/core/template/backup.py +174 -0
  104. moai_adk/core/template/config.py +191 -0
  105. moai_adk/core/template/languages.py +43 -0
  106. moai_adk/core/template/merger.py +233 -0
  107. moai_adk/core/template/processor.py +1200 -0
  108. moai_adk/core/template_engine.py +310 -0
  109. moai_adk/core/template_variable_synchronizer.py +417 -0
  110. moai_adk/core/unified_permission_manager.py +745 -0
  111. moai_adk/core/user_behavior_analytics.py +851 -0
  112. moai_adk/core/version_sync.py +429 -0
  113. moai_adk/foundation/__init__.py +56 -0
  114. moai_adk/foundation/backend.py +1027 -0
  115. moai_adk/foundation/database.py +1115 -0
  116. moai_adk/foundation/devops.py +1585 -0
  117. moai_adk/foundation/ears.py +431 -0
  118. moai_adk/foundation/frontend.py +870 -0
  119. moai_adk/foundation/git/commit_templates.py +557 -0
  120. moai_adk/foundation/git.py +376 -0
  121. moai_adk/foundation/langs.py +484 -0
  122. moai_adk/foundation/ml_ops.py +1162 -0
  123. moai_adk/foundation/testing.py +1524 -0
  124. moai_adk/foundation/trust/trust_principles.py +676 -0
  125. moai_adk/foundation/trust/validation_checklist.py +1573 -0
  126. moai_adk/project/__init__.py +0 -0
  127. moai_adk/project/configuration.py +1084 -0
  128. moai_adk/project/documentation.py +566 -0
  129. moai_adk/project/schema.py +447 -0
  130. moai_adk/statusline/__init__.py +38 -0
  131. moai_adk/statusline/alfred_detector.py +105 -0
  132. moai_adk/statusline/config.py +376 -0
  133. moai_adk/statusline/enhanced_output_style_detector.py +372 -0
  134. moai_adk/statusline/git_collector.py +190 -0
  135. moai_adk/statusline/main.py +322 -0
  136. moai_adk/statusline/metrics_tracker.py +78 -0
  137. moai_adk/statusline/renderer.py +343 -0
  138. moai_adk/statusline/update_checker.py +129 -0
  139. moai_adk/statusline/version_reader.py +741 -0
  140. moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +714 -0
  141. moai_adk/templates/.claude/agents/moai/builder-agent.md +474 -0
  142. moai_adk/templates/.claude/agents/moai/builder-command.md +1172 -0
  143. moai_adk/templates/.claude/agents/moai/builder-plugin.md +637 -0
  144. moai_adk/templates/.claude/agents/moai/builder-skill.md +666 -0
  145. moai_adk/templates/.claude/agents/moai/expert-backend.md +899 -0
  146. moai_adk/templates/.claude/agents/moai/expert-database.md +777 -0
  147. moai_adk/templates/.claude/agents/moai/expert-debug.md +401 -0
  148. moai_adk/templates/.claude/agents/moai/expert-devops.md +720 -0
  149. moai_adk/templates/.claude/agents/moai/expert-frontend.md +734 -0
  150. moai_adk/templates/.claude/agents/moai/expert-performance.md +657 -0
  151. moai_adk/templates/.claude/agents/moai/expert-security.md +513 -0
  152. moai_adk/templates/.claude/agents/moai/expert-testing.md +733 -0
  153. moai_adk/templates/.claude/agents/moai/expert-uiux.md +1041 -0
  154. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +432 -0
  155. moai_adk/templates/.claude/agents/moai/manager-docs.md +573 -0
  156. moai_adk/templates/.claude/agents/moai/manager-git.md +1060 -0
  157. moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
  158. moai_adk/templates/.claude/agents/moai/manager-quality.md +624 -0
  159. moai_adk/templates/.claude/agents/moai/manager-spec.md +809 -0
  160. moai_adk/templates/.claude/agents/moai/manager-strategy.md +780 -0
  161. moai_adk/templates/.claude/agents/moai/manager-tdd.md +784 -0
  162. moai_adk/templates/.claude/agents/moai/mcp-context7.md +458 -0
  163. moai_adk/templates/.claude/agents/moai/mcp-figma.md +1607 -0
  164. moai_adk/templates/.claude/agents/moai/mcp-notion.md +789 -0
  165. moai_adk/templates/.claude/agents/moai/mcp-playwright.md +469 -0
  166. moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +1032 -0
  167. moai_adk/templates/.claude/commands/moai/0-project.md +1386 -0
  168. moai_adk/templates/.claude/commands/moai/1-plan.md +1427 -0
  169. moai_adk/templates/.claude/commands/moai/2-run.md +943 -0
  170. moai_adk/templates/.claude/commands/moai/3-sync.md +1324 -0
  171. moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
  172. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  173. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  174. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
  175. moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
  176. moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
  177. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
  178. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  179. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  180. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
  181. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
  182. moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
  183. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
  184. moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
  185. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  186. moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
  187. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
  188. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
  189. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +1083 -0
  190. moai_adk/templates/.claude/output-styles/moai/r2d2.md +560 -0
  191. moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
  192. moai_adk/templates/.claude/settings.json +172 -0
  193. moai_adk/templates/.claude/skills/moai-ai-nano-banana/SKILL.md +307 -0
  194. moai_adk/templates/.claude/skills/moai-ai-nano-banana/examples.md +431 -0
  195. moai_adk/templates/.claude/skills/moai-ai-nano-banana/scripts/batch_generate.py +560 -0
  196. moai_adk/templates/.claude/skills/moai-ai-nano-banana/scripts/generate_image.py +362 -0
  197. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +249 -0
  198. moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +406 -0
  199. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
  200. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
  201. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  202. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
  203. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
  204. moai_adk/templates/.claude/skills/moai-docs-generation/reference.md +328 -0
  205. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +320 -0
  206. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +718 -0
  207. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +464 -0
  208. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +323 -0
  209. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +830 -0
  210. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  211. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  212. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  213. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  214. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +545 -0
  215. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +497 -0
  216. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +968 -0
  217. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +664 -0
  218. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +455 -0
  219. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  220. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  221. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  222. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  223. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  224. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  225. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +492 -0
  226. moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -0
  227. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
  228. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  229. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  230. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  231. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  232. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  233. moai_adk/templates/.claude/skills/moai-formats-data/reference.md +585 -0
  234. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +202 -0
  235. moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -0
  236. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  237. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
  238. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
  239. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  240. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  241. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  242. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
  243. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
  244. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  245. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  246. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  247. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  248. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  249. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  250. moai_adk/templates/.claude/skills/moai-foundation-claude/reference.md +209 -0
  251. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +441 -0
  252. moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
  253. moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
  254. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +420 -0
  255. moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -0
  256. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  257. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +359 -0
  258. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  259. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
  260. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  261. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  262. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  263. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
  264. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  265. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
  266. moai_adk/templates/.claude/skills/moai-foundation-core/reference.md +478 -0
  267. moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +315 -0
  268. moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
  269. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
  270. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
  271. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
  272. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
  273. moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
  274. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +364 -0
  275. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  276. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  277. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  278. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  279. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  280. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  281. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  282. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  283. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  284. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +649 -0
  285. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +478 -0
  286. moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +612 -0
  287. moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +477 -0
  288. moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
  289. moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
  290. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +376 -0
  291. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +919 -0
  292. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +737 -0
  293. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +385 -0
  294. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +864 -0
  295. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +291 -0
  296. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +382 -0
  297. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +1006 -0
  298. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +562 -0
  299. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +644 -0
  300. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +481 -0
  301. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +977 -0
  302. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +804 -0
  303. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +579 -0
  304. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +687 -0
  305. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +372 -0
  306. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +659 -0
  307. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +504 -0
  308. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +497 -0
  309. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +633 -0
  310. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +423 -0
  311. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +497 -0
  312. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +918 -0
  313. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +672 -0
  314. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +368 -0
  315. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1089 -0
  316. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +731 -0
  317. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +300 -0
  318. moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
  319. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  320. moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
  321. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  322. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +319 -0
  323. moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
  324. moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -0
  325. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  326. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
  327. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
  328. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  329. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  330. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  331. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  332. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  333. moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
  334. moai_adk/templates/.claude/skills/moai-library-nextra/reference.md +379 -0
  335. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +372 -0
  336. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  337. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  338. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  339. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  340. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  341. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  342. moai_adk/templates/.claude/skills/moai-mcp-figma/SKILL.md +402 -0
  343. moai_adk/templates/.claude/skills/moai-mcp-figma/advanced-patterns.md +607 -0
  344. moai_adk/templates/.claude/skills/moai-mcp-notion/SKILL.md +300 -0
  345. moai_adk/templates/.claude/skills/moai-mcp-notion/advanced-patterns.md +537 -0
  346. moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +291 -0
  347. moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +390 -0
  348. moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +398 -0
  349. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +379 -0
  350. moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +358 -0
  351. moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +467 -0
  352. moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +377 -0
  353. moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +466 -0
  354. moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +482 -0
  355. moai_adk/templates/.claude/skills/moai-plugin-builder/SKILL.md +474 -0
  356. moai_adk/templates/.claude/skills/moai-plugin-builder/examples.md +621 -0
  357. moai_adk/templates/.claude/skills/moai-plugin-builder/migration.md +341 -0
  358. moai_adk/templates/.claude/skills/moai-plugin-builder/reference.md +463 -0
  359. moai_adk/templates/.claude/skills/moai-plugin-builder/validation.md +373 -0
  360. moai_adk/templates/.claude/skills/moai-security-auth0/SKILL.md +275 -0
  361. moai_adk/templates/.claude/skills/moai-security-auth0/modules/adaptive-mfa.md +233 -0
  362. moai_adk/templates/.claude/skills/moai-security-auth0/modules/akamai-integration.md +215 -0
  363. moai_adk/templates/.claude/skills/moai-security-auth0/modules/application-credentials.md +280 -0
  364. moai_adk/templates/.claude/skills/moai-security-auth0/modules/attack-protection-log-events.md +225 -0
  365. moai_adk/templates/.claude/skills/moai-security-auth0/modules/attack-protection-overview.md +140 -0
  366. moai_adk/templates/.claude/skills/moai-security-auth0/modules/bot-detection.md +144 -0
  367. moai_adk/templates/.claude/skills/moai-security-auth0/modules/breached-password-detection.md +187 -0
  368. moai_adk/templates/.claude/skills/moai-security-auth0/modules/brute-force-protection.md +189 -0
  369. moai_adk/templates/.claude/skills/moai-security-auth0/modules/certifications.md +282 -0
  370. moai_adk/templates/.claude/skills/moai-security-auth0/modules/compliance-overview.md +263 -0
  371. moai_adk/templates/.claude/skills/moai-security-auth0/modules/continuous-session-protection.md +307 -0
  372. moai_adk/templates/.claude/skills/moai-security-auth0/modules/customize-mfa.md +178 -0
  373. moai_adk/templates/.claude/skills/moai-security-auth0/modules/dpop-implementation.md +283 -0
  374. moai_adk/templates/.claude/skills/moai-security-auth0/modules/fapi-implementation.md +259 -0
  375. moai_adk/templates/.claude/skills/moai-security-auth0/modules/gdpr-compliance.md +313 -0
  376. moai_adk/templates/.claude/skills/moai-security-auth0/modules/guardian-configuration.md +269 -0
  377. moai_adk/templates/.claude/skills/moai-security-auth0/modules/highly-regulated-identity.md +272 -0
  378. moai_adk/templates/.claude/skills/moai-security-auth0/modules/jwt-fundamentals.md +248 -0
  379. moai_adk/templates/.claude/skills/moai-security-auth0/modules/mdl-verification.md +211 -0
  380. moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-api-management.md +278 -0
  381. moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-factors.md +226 -0
  382. moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-overview.md +174 -0
  383. moai_adk/templates/.claude/skills/moai-security-auth0/modules/mtls-sender-constraining.md +316 -0
  384. moai_adk/templates/.claude/skills/moai-security-auth0/modules/ropg-flow-mfa.md +217 -0
  385. moai_adk/templates/.claude/skills/moai-security-auth0/modules/security-center.md +325 -0
  386. moai_adk/templates/.claude/skills/moai-security-auth0/modules/security-guidance.md +277 -0
  387. moai_adk/templates/.claude/skills/moai-security-auth0/modules/state-parameters.md +178 -0
  388. moai_adk/templates/.claude/skills/moai-security-auth0/modules/step-up-authentication.md +251 -0
  389. moai_adk/templates/.claude/skills/moai-security-auth0/modules/suspicious-ip-throttling.md +240 -0
  390. moai_adk/templates/.claude/skills/moai-security-auth0/modules/tenant-access-control.md +180 -0
  391. moai_adk/templates/.claude/skills/moai-security-auth0/modules/webauthn-fido.md +235 -0
  392. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +449 -0
  393. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
  394. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
  395. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
  396. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
  397. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  398. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +390 -0
  399. moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
  400. moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
  401. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
  402. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
  403. moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
  404. moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +175 -0
  405. moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
  406. moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -0
  407. moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
  408. moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
  409. moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
  410. moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
  411. moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
  412. moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
  413. moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
  414. moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
  415. moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
  416. moai_adk/templates/.claude/skills/moai-workflow-project/reference.md +275 -0
  417. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  418. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1434 -0
  419. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  420. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  421. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  422. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +92 -0
  423. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  424. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  425. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  426. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  427. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  428. moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
  429. moai_adk/templates/.claude/skills/moai-workflow-spec/SKILL.md +534 -0
  430. moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
  431. moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
  432. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +377 -0
  433. moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -0
  434. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  435. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  436. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  437. moai_adk/templates/.claude/skills/moai-workflow-templates/reference.md +346 -0
  438. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  439. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +456 -0
  440. moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
  441. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  442. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  443. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  444. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  445. moai_adk/templates/.claude/skills/moai-workflow-testing/examples.md +672 -0
  446. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
  447. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
  448. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
  449. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
  450. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
  451. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
  452. moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
  453. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  454. moai_adk/templates/.claude/skills/moai-workflow-testing/reference.md +440 -0
  455. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  456. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  457. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  458. moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +411 -0
  459. moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
  460. moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
  461. moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
  462. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
  463. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
  464. moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
  465. moai_adk/templates/.git-hooks/pre-commit +128 -0
  466. moai_adk/templates/.git-hooks/pre-push +365 -0
  467. moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
  468. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  469. moai_adk/templates/.github/workflows/spec-issue-sync.yml +337 -0
  470. moai_adk/templates/.gitignore +222 -0
  471. moai_adk/templates/.mcp.json +13 -0
  472. moai_adk/templates/.moai/config/config.yaml +58 -0
  473. moai_adk/templates/.moai/config/questions/_schema.yaml +174 -0
  474. moai_adk/templates/.moai/config/questions/tab0-init.yaml +251 -0
  475. moai_adk/templates/.moai/config/questions/tab1-user.yaml +107 -0
  476. moai_adk/templates/.moai/config/questions/tab2-project.yaml +79 -0
  477. moai_adk/templates/.moai/config/questions/tab3-git.yaml +632 -0
  478. moai_adk/templates/.moai/config/questions/tab4-quality.yaml +182 -0
  479. moai_adk/templates/.moai/config/questions/tab5-system.yaml +96 -0
  480. moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -0
  481. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  482. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  483. moai_adk/templates/.moai/config/sections/quality.yaml +17 -0
  484. moai_adk/templates/.moai/config/sections/system.yaml +24 -0
  485. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  486. moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
  487. moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
  488. moai_adk/templates/CLAUDE.md +642 -0
  489. moai_adk/utils/__init__.py +30 -0
  490. moai_adk/utils/banner.py +38 -0
  491. moai_adk/utils/common.py +294 -0
  492. moai_adk/utils/link_validator.py +241 -0
  493. moai_adk/utils/logger.py +147 -0
  494. moai_adk/utils/safe_file_reader.py +206 -0
  495. moai_adk/utils/timeout.py +160 -0
  496. moai_adk/utils/toon_utils.py +256 -0
  497. moai_adk/version.py +22 -0
  498. moai_adk-0.35.1.dist-info/METADATA +3018 -0
  499. moai_adk-0.35.1.dist-info/RECORD +502 -0
  500. moai_adk-0.35.1.dist-info/WHEEL +4 -0
  501. moai_adk-0.35.1.dist-info/entry_points.txt +3 -0
  502. moai_adk-0.35.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,1200 @@
1
+ # # REMOVED_ORPHAN_CODE:TEMPLATE-001 | SPEC: SPEC-INIT-003/spec.md | Chain: TEMPLATE-001
2
+ """Enhanced Template copy and backup processor with improved version handling and validation.
3
+
4
+ SPEC-INIT-003 v0.3.0: preserve user content
5
+ Enhanced with:
6
+ - Comprehensive version field management
7
+ - Template substitution validation
8
+ - Performance optimization
9
+ - Error handling improvements
10
+ - Configuration-driven behavior
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ import logging
17
+ import re
18
+ import shutil
19
+ from dataclasses import dataclass
20
+ from pathlib import Path
21
+ from typing import Any, Dict, List, Optional
22
+
23
+ from rich.console import Console
24
+
25
+ from moai_adk.core.template.backup import TemplateBackup
26
+ from moai_adk.core.template.merger import TemplateMerger
27
+ from moai_adk.statusline.version_reader import VersionConfig, VersionReader
28
+
29
+ console = Console()
30
+
31
+
32
+ @dataclass
33
+ class TemplateProcessorConfig:
34
+ """Configuration for TemplateProcessor behavior."""
35
+
36
+ # Version handling configuration
37
+ version_cache_ttl_seconds: int = 120
38
+ version_fallback: str = "unknown"
39
+ version_format_regex: str = r"^v?(\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?)$"
40
+ enable_version_validation: bool = True
41
+ preserve_user_version: bool = True
42
+
43
+ # Template substitution configuration
44
+ validate_template_variables: bool = True
45
+ max_variable_length: int = 50
46
+ allowed_variable_pattern: str = r"^[A-Z_]+$"
47
+ enable_substitution_warnings: bool = True
48
+
49
+ # Performance configuration
50
+ enable_caching: bool = True
51
+ cache_size: int = 100
52
+ async_operations: bool = False
53
+
54
+ # Error handling configuration
55
+ graceful_degradation: bool = True
56
+ verbose_logging: bool = False
57
+
58
+ @classmethod
59
+ def from_dict(cls, config_dict: Dict[str, Any]) -> "TemplateProcessorConfig":
60
+ """Create config from dictionary."""
61
+ config_dict = config_dict or {}
62
+ return cls(
63
+ version_cache_ttl_seconds=config_dict.get("version_cache_ttl_seconds", 120),
64
+ version_fallback=config_dict.get("version_fallback", "unknown"),
65
+ version_format_regex=config_dict.get("version_format_regex", r"^v?(\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?)$"),
66
+ enable_version_validation=config_dict.get("enable_version_validation", True),
67
+ preserve_user_version=config_dict.get("preserve_user_version", True),
68
+ validate_template_variables=config_dict.get("validate_template_variables", True),
69
+ max_variable_length=config_dict.get("max_variable_length", 50),
70
+ allowed_variable_pattern=config_dict.get("allowed_variable_pattern", r"^[A-Z_]+$"),
71
+ enable_substitution_warnings=config_dict.get("enable_substitution_warnings", True),
72
+ enable_caching=config_dict.get("enable_caching", True),
73
+ cache_size=config_dict.get("cache_size", 100),
74
+ async_operations=config_dict.get("async_operations", False),
75
+ graceful_degradation=config_dict.get("graceful_degradation", True),
76
+ verbose_logging=config_dict.get("verbose_logging", False),
77
+ )
78
+
79
+
80
+ class TemplateProcessor:
81
+ """Orchestrate template copying and backups with enhanced version handling and validation."""
82
+
83
+ # User data protection paths (never touch) - SPEC-INIT-003 v0.3.0
84
+ PROTECTED_PATHS = [
85
+ ".moai/specs/", # User SPEC documents
86
+ ".moai/reports/", # User reports
87
+ ".moai/project/", # User project documents (product/structure/tech.md)
88
+ # config.json is now FORCE OVERWRITTEN (backup in .moai-backups/)
89
+ # Merge via /moai:0-project when optimized=false
90
+ ]
91
+
92
+ # Paths excluded from backups
93
+ BACKUP_EXCLUDE = PROTECTED_PATHS
94
+
95
+ # Common template variables with validation hints
96
+ COMMON_TEMPLATE_VARIABLES = {
97
+ "PROJECT_DIR": "Cross-platform project path (run /moai:0-project to set)",
98
+ "PROJECT_NAME": "Project name (run /moai:0-project to set)",
99
+ "AUTHOR": "Project author (run /moai:0-project to set)",
100
+ "CONVERSATION_LANGUAGE": "Interface language (run /moai:0-project to set)",
101
+ "MOAI_VERSION": "MoAI-ADK version (should be set automatically)",
102
+ "MOAI_VERSION_SHORT": "Short MoAI-ADK version (without 'v' prefix)",
103
+ "MOAI_VERSION_DISPLAY": "Display version with proper formatting",
104
+ "MOAI_VERSION_TRIMMED": "Trimmed version for UI displays",
105
+ "MOAI_VERSION_SEMVER": "Semantic version format (major.minor.patch)",
106
+ "MOAI_VERSION_VALID": "Version validation status",
107
+ "MOAI_VERSION_SOURCE": "Version source information",
108
+ "MOAI_VERSION_CACHE_AGE": "Cache age for debugging",
109
+ "CREATION_TIMESTAMP": "Project creation timestamp",
110
+ "STATUSLINE_COMMAND": "Cross-platform statusline command (OS-specific)",
111
+ }
112
+
113
+ def __init__(self, target_path: Path, config: Optional[TemplateProcessorConfig] = None) -> None:
114
+ """Initialize the processor with enhanced configuration.
115
+
116
+ Args:
117
+ target_path: Project path.
118
+ config: Optional configuration for processor behavior.
119
+ """
120
+ self.target_path = target_path.resolve()
121
+ self.template_root = self._get_template_root()
122
+ self.backup = TemplateBackup(self.target_path)
123
+ self.merger = TemplateMerger(self.target_path)
124
+ self.context: dict[str, str] = {} # Template variable substitution context
125
+ self._version_reader: VersionReader | None = None
126
+ self.config = config or TemplateProcessorConfig()
127
+ self._substitution_cache: Dict[
128
+ int, tuple[str, list[str]]
129
+ ] = {} # Cache for substitution results (key: hash, value: (content, warnings))
130
+ self._variable_validation_cache: Dict[str, bool] = {} # Cache for variable validation
131
+ self.logger = logging.getLogger(__name__)
132
+
133
+ if self.config.verbose_logging:
134
+ self.logger.info(f"TemplateProcessor initialized with config: {self.config}")
135
+
136
+ def set_context(self, context: dict[str, str]) -> None:
137
+ """Set variable substitution context with enhanced validation.
138
+
139
+ Args:
140
+ context: Dictionary of template variables.
141
+ """
142
+ self.context = context
143
+ self._substitution_cache.clear() # Clear cache when context changes
144
+ self._variable_validation_cache.clear()
145
+
146
+ if self.config.verbose_logging:
147
+ self.logger.debug(f"Context set with {len(context)} variables")
148
+
149
+ # Validate template variables if enabled
150
+ if self.config.validate_template_variables:
151
+ self._validate_template_variables(context)
152
+
153
+ # Add deprecation mapping for HOOK_PROJECT_DIR
154
+ if "PROJECT_DIR" in self.context and "HOOK_PROJECT_DIR" not in self.context:
155
+ self.context["HOOK_PROJECT_DIR"] = self.context["PROJECT_DIR"]
156
+
157
+ def _get_version_reader(self) -> VersionReader:
158
+ """
159
+ Get or create version reader instance with enhanced configuration.
160
+
161
+ Returns:
162
+ VersionReader instance
163
+ """
164
+ if self._version_reader is None:
165
+ version_config = VersionConfig(
166
+ cache_ttl_seconds=self.config.version_cache_ttl_seconds,
167
+ fallback_version=self.config.version_fallback,
168
+ version_format_regex=self.config.version_format_regex,
169
+ debug_mode=self.config.verbose_logging,
170
+ )
171
+ self._version_reader = VersionReader(version_config)
172
+
173
+ if self.config.verbose_logging:
174
+ self.logger.info("VersionReader created with enhanced configuration")
175
+ return self._version_reader
176
+
177
+ def _validate_template_variables(self, context: Dict[str, str]) -> None:
178
+ """
179
+ Validate template variables with comprehensive checking.
180
+
181
+ Args:
182
+ context: Dictionary of template variables to validate
183
+ """
184
+ import re
185
+
186
+ if not self.config.validate_template_variables:
187
+ return
188
+
189
+ validation_errors: List[str] = []
190
+ warning_messages: List[str] = []
191
+
192
+ # Check variable names against pattern
193
+ variable_pattern = re.compile(self.config.allowed_variable_pattern)
194
+
195
+ for var_name, var_value in context.items():
196
+ # Check variable name format
197
+ if not variable_pattern.match(var_name):
198
+ validation_errors.append(f"Invalid variable name format: '{var_name}'")
199
+ continue
200
+
201
+ # Check variable length
202
+ if len(var_name) > self.config.max_variable_length:
203
+ warning_messages.append(f"Variable name '{var_name}' exceeds maximum length")
204
+
205
+ # Check variable value length
206
+ if len(var_value) > self.config.max_variable_length * 2:
207
+ warning_messages.append(f"Variable value '{var_value[:20]}...' is very long")
208
+
209
+ # Check for potentially dangerous values
210
+ if "{{" in var_value or "}}" in var_value:
211
+ warning_messages.append(f"Variable '{var_name}' contains placeholder patterns")
212
+
213
+ # Check for common variables that should be present
214
+ missing_common_vars = []
215
+ for common_var in self.COMMON_TEMPLATE_VARIABLES:
216
+ if common_var not in context:
217
+ missing_common_vars.append(common_var)
218
+
219
+ if missing_common_vars and self.config.enable_substitution_warnings:
220
+ warning_messages.append(f"Common variables missing: {', '.join(missing_common_vars[:3])}")
221
+
222
+ # Report validation results
223
+ if validation_errors and not self.config.graceful_degradation:
224
+ raise ValueError(f"Template variable validation failed: {validation_errors}")
225
+
226
+ if validation_errors and self.config.graceful_degradation:
227
+ self.logger.warning(f"Template variable validation warnings: {validation_errors}")
228
+
229
+ if warning_messages and self.config.enable_substitution_warnings:
230
+ self.logger.warning(f"Template variable warnings: {warning_messages}")
231
+
232
+ if self.config.verbose_logging:
233
+ self.logger.debug(f"Template variables validated: {len(context)} variables checked")
234
+
235
+ def get_enhanced_version_context(self) -> dict[str, str]:
236
+ """
237
+ Get enhanced version context with proper error handling and caching.
238
+
239
+ Returns comprehensive version information including multiple format options
240
+ and debugging information.
241
+
242
+ Returns:
243
+ Dictionary containing enhanced version-related template variables
244
+ """
245
+ version_context = {}
246
+ logger = logging.getLogger(__name__)
247
+
248
+ try:
249
+ version_reader = self._get_version_reader()
250
+ moai_version = version_reader.get_version()
251
+
252
+ # Basic version information
253
+ version_context["MOAI_VERSION"] = moai_version
254
+ version_context["MOAI_VERSION_SHORT"] = self._format_short_version(moai_version)
255
+ version_context["MOAI_VERSION_DISPLAY"] = self._format_display_version(moai_version)
256
+
257
+ # Enhanced formatting options
258
+ version_context["MOAI_VERSION_TRIMMED"] = self._format_trimmed_version(moai_version, max_length=10)
259
+ version_context["MOAI_VERSION_SEMVER"] = self._format_semver_version(moai_version)
260
+
261
+ # Validation and source information
262
+ version_context["MOAI_VERSION_VALID"] = "true" if moai_version != "unknown" else "false"
263
+ version_context["MOAI_VERSION_SOURCE"] = self._get_version_source(version_reader)
264
+
265
+ # Performance metrics
266
+ cache_age = version_reader.get_cache_age_seconds()
267
+ if cache_age is not None:
268
+ version_context["MOAI_VERSION_CACHE_AGE"] = f"{cache_age:.2f}s"
269
+ else:
270
+ version_context["MOAI_VERSION_CACHE_AGE"] = "uncached"
271
+
272
+ # Additional metadata
273
+ if self.config.enable_version_validation:
274
+ is_valid = self._is_valid_version_format(moai_version)
275
+ version_context["MOAI_VERSION_FORMAT_VALID"] = "true" if is_valid else "false"
276
+
277
+ if self.config.verbose_logging:
278
+ logger.debug(f"Enhanced version context generated: {version_context}")
279
+
280
+ except Exception as e:
281
+ logger.warning(f"Failed to read version for template context: {e}")
282
+ # Use fallback version with comprehensive formatting
283
+ fallback_version = self.config.version_fallback
284
+ version_context["MOAI_VERSION"] = fallback_version
285
+ version_context["MOAI_VERSION_SHORT"] = self._format_short_version(fallback_version)
286
+ version_context["MOAI_VERSION_DISPLAY"] = self._format_display_version(fallback_version)
287
+ version_context["MOAI_VERSION_TRIMMED"] = self._format_trimmed_version(fallback_version, max_length=10)
288
+ version_context["MOAI_VERSION_SEMVER"] = self._format_semver_version(fallback_version)
289
+ version_context["MOAI_VERSION_VALID"] = "false" if fallback_version == "unknown" else "true"
290
+ version_context["MOAI_VERSION_SOURCE"] = "fallback_config"
291
+ version_context["MOAI_VERSION_CACHE_AGE"] = "unavailable"
292
+ version_context["MOAI_VERSION_FORMAT_VALID"] = "false"
293
+
294
+ return version_context
295
+
296
+ def _is_valid_version_format(self, version: str) -> bool:
297
+ """
298
+ Validate version format using configured regex pattern.
299
+
300
+ Args:
301
+ version: Version string to validate
302
+
303
+ Returns:
304
+ True if version format is valid
305
+ """
306
+ import re
307
+
308
+ try:
309
+ pattern = re.compile(self.config.version_format_regex)
310
+ return bool(pattern.match(version))
311
+ except re.error:
312
+ # Fallback to default pattern if custom one is invalid
313
+ default_pattern = re.compile(r"^v?(\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?)$")
314
+ return bool(default_pattern.match(version))
315
+
316
+ def _format_short_version(self, version: str) -> str:
317
+ """
318
+ Format short version by removing 'v' prefix if present.
319
+
320
+ Args:
321
+ version: Version string
322
+
323
+ Returns:
324
+ Short version string
325
+ """
326
+ return version[1:] if version.startswith("v") else version
327
+
328
+ def _format_display_version(self, version: str) -> str:
329
+ """
330
+ Format display version with proper formatting.
331
+
332
+ Args:
333
+ version: Version string
334
+
335
+ Returns:
336
+ Display version string
337
+ """
338
+ if version == "unknown":
339
+ return "MoAI-ADK unknown version"
340
+ elif version.startswith("v"):
341
+ return f"MoAI-ADK {version}"
342
+ else:
343
+ return f"MoAI-ADK v{version}"
344
+
345
+ def _format_trimmed_version(self, version: str, max_length: int = 10) -> str:
346
+ """
347
+ Format version with maximum length, suitable for UI displays.
348
+
349
+ Args:
350
+ version: Version string
351
+ max_length: Maximum allowed length for the version string
352
+
353
+ Returns:
354
+ Trimmed version string
355
+ """
356
+ if version == "unknown":
357
+ return "unknown"
358
+
359
+ # Remove 'v' prefix for trimming
360
+ clean_version = version[1:] if version.startswith("v") else version
361
+
362
+ # Trim if necessary
363
+ if len(clean_version) > max_length:
364
+ return clean_version[:max_length]
365
+ return clean_version
366
+
367
+ def _format_semver_version(self, version: str) -> str:
368
+ """
369
+ Format version as semantic version with major.minor.patch structure.
370
+
371
+ Args:
372
+ version: Version string
373
+
374
+ Returns:
375
+ Semantic version string
376
+ """
377
+ if version == "unknown":
378
+ return "0.0.0"
379
+
380
+ # Remove 'v' prefix and extract semantic version
381
+ clean_version = version[1:] if version.startswith("v") else version
382
+
383
+ # Extract core semantic version (remove pre-release and build metadata)
384
+ import re
385
+
386
+ semver_match = re.match(r"^(\d+\.\d+\.\d+)", clean_version)
387
+ if semver_match:
388
+ return semver_match.group(1)
389
+ return "0.0.0"
390
+
391
+ def _get_version_source(self, version_reader: VersionReader) -> str:
392
+ """
393
+ Determine the source of the version information.
394
+
395
+ Args:
396
+ version_reader: VersionReader instance
397
+
398
+ Returns:
399
+ String indicating version source
400
+ """
401
+ config = version_reader.get_config()
402
+ cache_age = version_reader.get_cache_age_seconds()
403
+
404
+ if cache_age is not None and cache_age < config.cache_ttl_seconds:
405
+ return "config_cached"
406
+ elif cache_age is not None:
407
+ return "config_stale"
408
+ else:
409
+ return config.fallback_source.value
410
+
411
+ def _get_template_root(self) -> Path:
412
+ """Return the template root path."""
413
+ # src/moai_adk/core/template/processor.py → src/moai_adk/templates/
414
+ current_file = Path(__file__).resolve()
415
+ package_root = current_file.parent.parent.parent
416
+ return package_root / "templates"
417
+
418
+ def _substitute_variables(self, content: str) -> tuple[str, list[str]]:
419
+ """
420
+ Substitute template variables in content with enhanced validation and caching.
421
+
422
+ Args:
423
+ content: Content to substitute variables in
424
+
425
+ Returns:
426
+ Tuple of (substituted_content, warnings_list)
427
+ """
428
+ warnings = []
429
+ logger = logging.getLogger(__name__)
430
+
431
+ # Check cache first if enabled
432
+ cache_key = hash((frozenset(self.context.items()), content[:1000]))
433
+ if self.config.enable_caching and cache_key in self._substitution_cache:
434
+ cached_result = self._substitution_cache[cache_key]
435
+ if self.config.verbose_logging:
436
+ logger.debug("Using cached substitution result")
437
+ return cached_result
438
+
439
+ # Enhanced variable substitution with validation
440
+ substitution_count = 0
441
+ for key, value in self.context.items():
442
+ placeholder = f"{{{{{key}}}}}" # {{KEY}}
443
+ if placeholder in content:
444
+ if self.config.validate_template_variables:
445
+ # Validate variable before substitution
446
+ if not self._is_valid_template_variable(key, value):
447
+ warnings.append(f"Invalid variable {key} - skipped substitution")
448
+ continue
449
+
450
+ safe_value = self._sanitize_value(value)
451
+ content = content.replace(placeholder, safe_value)
452
+ substitution_count += 1
453
+
454
+ if self.config.verbose_logging:
455
+ logger.debug(f"Substituted {key}: {safe_value[:50]}...")
456
+
457
+ # Detect unsubstituted variables with enhanced error messages
458
+ remaining = re.findall(r"\{\{([A-Z_]+)\}\}", content)
459
+ if remaining:
460
+ unique_remaining = sorted(set(remaining))
461
+
462
+ # Build detailed warning message with enhanced suggestions
463
+ warning_parts = []
464
+ for var in unique_remaining:
465
+ if var in self.COMMON_TEMPLATE_VARIABLES:
466
+ suggestion = self.COMMON_TEMPLATE_VARIABLES[var]
467
+ warning_parts.append(f"{{{{{var}}}}} → {suggestion}")
468
+ else:
469
+ warning_parts.append(f"{{{{{var}}}}} → Unknown variable (check template)")
470
+
471
+ warnings.append("Template variables not substituted:")
472
+ warnings.extend(f" • {part}" for part in warning_parts)
473
+
474
+ if self.config.enable_substitution_warnings:
475
+ warnings.append("💡 Run 'uv run moai-adk update' to fix template variables")
476
+
477
+ # Add performance information if verbose logging is enabled
478
+ if self.config.verbose_logging:
479
+ warnings.append(f" 📊 Substituted {substitution_count} variables")
480
+
481
+ # Cache the result if enabled
482
+ if self.config.enable_caching:
483
+ result = (content, warnings)
484
+ self._substitution_cache[cache_key] = result
485
+
486
+ # Manage cache size
487
+ if len(self._substitution_cache) > self.config.cache_size:
488
+ # Remove oldest entry (simple FIFO)
489
+ oldest_key = next(iter(self._substitution_cache))
490
+ del self._substitution_cache[oldest_key]
491
+ if self.config.verbose_logging:
492
+ logger.debug("Cache size limit reached, removed oldest entry")
493
+
494
+ return content, warnings
495
+
496
+ def _is_valid_template_variable(self, key: str, value: str) -> bool:
497
+ """
498
+ Validate a template variable before substitution.
499
+
500
+ Args:
501
+ key: Variable name
502
+ value: Variable value
503
+
504
+ Returns:
505
+ True if variable is valid
506
+ """
507
+ import re
508
+
509
+ # Check variable name format
510
+ if not re.match(self.config.allowed_variable_pattern, key):
511
+ return False
512
+
513
+ # Check variable length
514
+ if len(key) > self.config.max_variable_length:
515
+ return False
516
+
517
+ # Check value length
518
+ if len(value) > self.config.max_variable_length * 2:
519
+ return False
520
+
521
+ # Note: {{ }} patterns are handled by sanitization, not validation
522
+
523
+ # Check for empty values
524
+ if not value.strip():
525
+ return False
526
+
527
+ return True
528
+
529
+ def clear_substitution_cache(self) -> None:
530
+ """Clear the substitution cache."""
531
+ self._substitution_cache.clear()
532
+ if self.config.verbose_logging:
533
+ self.logger.debug("Substitution cache cleared")
534
+
535
+ def get_cache_stats(self) -> Dict[str, Any]:
536
+ """
537
+ Get cache statistics.
538
+
539
+ Returns:
540
+ Dictionary containing cache statistics
541
+ """
542
+ return {
543
+ "cache_size": len(self._substitution_cache),
544
+ "max_cache_size": self.config.cache_size,
545
+ "cache_enabled": self.config.enable_caching,
546
+ "cache_hit_ratio": 0.0, # Would need to track hits to implement this
547
+ }
548
+
549
+ def _sanitize_value(self, value: str) -> str:
550
+ """Sanitize value to prevent recursive substitution and control characters.
551
+
552
+ Args:
553
+ value: Value to sanitize.
554
+
555
+ Returns:
556
+ Sanitized value.
557
+ """
558
+ # Remove control characters (keep printable and whitespace)
559
+ value = "".join(c for c in value if c.isprintable() or c in "\n\r\t")
560
+ # Prevent recursive substitution by removing placeholder patterns
561
+ value = value.replace("{{", "").replace("}}", "")
562
+ return value
563
+
564
+ def _is_text_file(self, file_path: Path) -> bool:
565
+ """Check if file is text-based (not binary).
566
+
567
+ Args:
568
+ file_path: File path to check.
569
+
570
+ Returns:
571
+ True if file is text-based.
572
+ """
573
+ text_extensions = {
574
+ ".md",
575
+ ".json",
576
+ ".txt",
577
+ ".py",
578
+ ".ts",
579
+ ".js",
580
+ ".yaml",
581
+ ".yml",
582
+ ".toml",
583
+ ".xml",
584
+ ".sh",
585
+ ".bash",
586
+ }
587
+ return file_path.suffix.lower() in text_extensions
588
+
589
+ def _localize_yaml_description(self, content: str, language: str = "en") -> str:
590
+ """Localize multilingual YAML description field.
591
+
592
+ Converts multilingual description maps to single-language strings:
593
+ description:
594
+ en: "English text"
595
+ ko: "Korean text"
596
+
597
+ description: "Korean text" (if language="ko")
598
+
599
+ Args:
600
+ content: File content.
601
+ language: Target language code (en, ko, ja, zh).
602
+
603
+ Returns:
604
+ Content with localized descriptions.
605
+ """
606
+ import yaml # type: ignore[import-untyped]
607
+
608
+ # Pattern to match YAML frontmatter
609
+ frontmatter_pattern = r"^---\n(.*?)\n---"
610
+ match = re.match(frontmatter_pattern, content, re.DOTALL)
611
+
612
+ if not match:
613
+ return content
614
+
615
+ try:
616
+ yaml_content = match.group(1)
617
+ yaml_data = yaml.safe_load(yaml_content)
618
+
619
+ # Check if description is a dict (multilingual)
620
+ if isinstance(yaml_data.get("description"), dict):
621
+ # Select language (fallback to English)
622
+ descriptions = yaml_data["description"]
623
+ selected_desc = descriptions.get(language, descriptions.get("en", ""))
624
+
625
+ # Replace description with selected language
626
+ yaml_data["description"] = selected_desc
627
+
628
+ # Reconstruct frontmatter
629
+ new_yaml = yaml.dump(yaml_data, allow_unicode=True, sort_keys=False)
630
+ # Preserve the rest of the content
631
+ rest_content = content[match.end() :]
632
+ return f"---\n{new_yaml}---{rest_content}"
633
+
634
+ except Exception:
635
+ # If YAML parsing fails, return original content
636
+ pass
637
+
638
+ return content
639
+
640
+ def _copy_file_with_substitution(self, src: Path, dst: Path) -> list[str]:
641
+ """Copy file with variable substitution and description localization for text files.
642
+
643
+ Args:
644
+ src: Source file path.
645
+ dst: Destination file path.
646
+
647
+ Returns:
648
+ List of warnings.
649
+ """
650
+ import stat
651
+
652
+ warnings = []
653
+
654
+ # Text files: read, substitute, write
655
+ if self._is_text_file(src) and self.context:
656
+ try:
657
+ content = src.read_text(encoding="utf-8")
658
+ content, file_warnings = self._substitute_variables(content)
659
+
660
+ # Apply description localization for command/output-style files
661
+ if src.suffix == ".md" and ("commands/alfred" in str(src) or "output-styles/alfred" in str(src)):
662
+ lang = self.context.get("CONVERSATION_LANGUAGE", "en")
663
+ content = self._localize_yaml_description(content, lang)
664
+
665
+ dst.write_text(content, encoding="utf-8")
666
+ warnings.extend(file_warnings)
667
+ except UnicodeDecodeError:
668
+ # Binary file fallback
669
+ shutil.copy2(src, dst)
670
+ else:
671
+ # Binary file or no context: simple copy
672
+ shutil.copy2(src, dst)
673
+
674
+ # Ensure executable permission for shell scripts
675
+ if src.suffix == ".sh":
676
+ # Always make shell scripts executable regardless of source permissions
677
+ dst_mode = dst.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
678
+ dst.chmod(dst_mode)
679
+
680
+ return warnings
681
+
682
+ def _copy_dir_with_substitution(self, src: Path, dst: Path) -> None:
683
+ """Recursively copy directory with variable substitution for text files.
684
+
685
+ Args:
686
+ src: Source directory path.
687
+ dst: Destination directory path.
688
+ """
689
+ dst.mkdir(parents=True, exist_ok=True)
690
+
691
+ for item in src.rglob("*"):
692
+ rel_path = item.relative_to(src)
693
+ dst_item = dst / rel_path
694
+
695
+ if item.is_file():
696
+ # Create parent directory if needed
697
+ dst_item.parent.mkdir(parents=True, exist_ok=True)
698
+ # Copy with variable substitution
699
+ self._copy_file_with_substitution(item, dst_item)
700
+ elif item.is_dir():
701
+ dst_item.mkdir(parents=True, exist_ok=True)
702
+
703
+ def copy_templates(self, backup: bool = True, silent: bool = False) -> None:
704
+ """Copy template files into the project.
705
+
706
+ Args:
707
+ backup: Whether to create a backup.
708
+ silent: Reduce log output when True.
709
+ """
710
+ # 1. Create a backup when existing files are present
711
+ if backup and self._has_existing_files():
712
+ backup_path = self.create_backup()
713
+ if not silent:
714
+ console.print(f"💾 Backup created: {backup_path.name}")
715
+
716
+ # 2. Copy templates
717
+ if not silent:
718
+ console.print("📄 Copying templates...")
719
+
720
+ self._copy_claude(silent)
721
+ self._copy_moai(silent)
722
+ self._copy_github(silent)
723
+ self._copy_claude_md(silent)
724
+ self._copy_gitignore(silent)
725
+ self._copy_mcp_json(silent)
726
+
727
+ if not silent:
728
+ console.print("✅ Templates copied successfully")
729
+
730
+ def _has_existing_files(self) -> bool:
731
+ """Determine whether project files exist (backup decision helper)."""
732
+ return self.backup.has_existing_files()
733
+
734
+ def create_backup(self) -> Path:
735
+ """Create a timestamped backup (delegated)."""
736
+ return self.backup.create_backup()
737
+
738
+ def _copy_exclude_protected(self, src: Path, dst: Path) -> None:
739
+ """Copy content while excluding protected paths.
740
+
741
+ Args:
742
+ src: Source directory.
743
+ dst: Destination directory.
744
+ """
745
+ dst.mkdir(parents=True, exist_ok=True)
746
+
747
+ # PROTECTED_PATHS: only specs/ and reports/ are excluded during copying
748
+ # project/ and config.json are preserved only when they already exist
749
+ template_protected_paths = [
750
+ "specs",
751
+ "reports",
752
+ ]
753
+
754
+ for item in src.rglob("*"):
755
+ rel_path = item.relative_to(src)
756
+ rel_path_str = str(rel_path)
757
+
758
+ # Skip template copy for specs/ and reports/
759
+ if any(rel_path_str.startswith(p) for p in template_protected_paths):
760
+ continue
761
+
762
+ dst_item = dst / rel_path
763
+ if item.is_file():
764
+ # Preserve user content by skipping existing files (v0.3.0)
765
+ # This automatically protects project/ and config.json
766
+ if dst_item.exists():
767
+ continue
768
+ dst_item.parent.mkdir(parents=True, exist_ok=True)
769
+ shutil.copy2(item, dst_item)
770
+ elif item.is_dir():
771
+ dst_item.mkdir(parents=True, exist_ok=True)
772
+
773
+ def _copy_claude(self, silent: bool = False) -> None:
774
+ """.claude/ directory copy with variable substitution (selective with alfred folder overwrite).
775
+
776
+
777
+ Strategy:
778
+ - Alfred folders (commands/agents/hooks/output-styles/alfred) → copy wholesale (delete & overwrite)
779
+ * Creates individual backup before deletion for safety
780
+ * Commands: 0-project.md, 1-plan.md, 2-run.md, 3-sync.md
781
+ - Other files/folders → copy individually (preserve existing)
782
+ """
783
+ src = self.template_root / ".claude"
784
+ dst = self.target_path / ".claude"
785
+
786
+ if not src.exists():
787
+ if not silent:
788
+ console.print("⚠️ .claude/ template not found")
789
+ return
790
+
791
+ # Create .claude directory if not exists
792
+ dst.mkdir(parents=True, exist_ok=True)
793
+
794
+ # Alfred and Moai folders to copy wholesale (overwrite)
795
+ # Including both legacy alfred/ and new moai/ structure
796
+ alfred_moai_folders = [
797
+ "hooks/alfred",
798
+ "hooks/moai",
799
+ "commands/alfred", # Contains 0-project.md, 1-plan.md, 2-run.md, 3-sync.md
800
+ "commands/moai",
801
+ "output-styles/moai",
802
+ "agents/alfred",
803
+ "agents/moai",
804
+ "skills", # NEW: Complete replacement for skills folder
805
+ ]
806
+
807
+ # 1. Copy Alfred and Moai folders wholesale (backup before delete & overwrite)
808
+ for folder in alfred_moai_folders:
809
+ src_folder = src / folder
810
+ dst_folder = dst / folder
811
+
812
+ if src_folder.exists():
813
+ # Remove existing folder (backup is already handled by create_backup() in update.py)
814
+ if dst_folder.exists():
815
+ shutil.rmtree(dst_folder)
816
+
817
+ # Create parent directory if needed
818
+ dst_folder.parent.mkdir(parents=True, exist_ok=True)
819
+ shutil.copytree(src_folder, dst_folder)
820
+ if not silent:
821
+ console.print(f" ✅ .claude/{folder}/ overwritten")
822
+
823
+ # 1.5 Copy other subdirectories in parent folders (e.g., output-styles/moai, hooks/shared)
824
+ # This ensures non-alfred subdirectories are also copied
825
+ parent_folders_with_subdirs = ["output-styles", "hooks", "commands", "agents"]
826
+ for parent_name in parent_folders_with_subdirs:
827
+ src_parent = src / parent_name
828
+ if not src_parent.exists():
829
+ continue
830
+
831
+ for subdir in src_parent.iterdir():
832
+ if not subdir.is_dir():
833
+ continue
834
+
835
+ # Skip alfred subdirectories (already handled above)
836
+ if subdir.name == "alfred":
837
+ continue
838
+
839
+ rel_subdir = f"{parent_name}/{subdir.name}"
840
+ dst_subdir = dst / parent_name / subdir.name
841
+
842
+ if dst_subdir.exists():
843
+ # For non-alfred directories, overwrite with merge if necessary
844
+ shutil.rmtree(dst_subdir)
845
+
846
+ # Copy the subdirectory
847
+ shutil.copytree(subdir, dst_subdir)
848
+ if not silent:
849
+ console.print(f" ✅ .claude/{rel_subdir}/ copied")
850
+
851
+ # 2. Copy other files/folders individually (smart merge for settings.json and config.json)
852
+ all_warnings = []
853
+ for item in src.iterdir():
854
+ rel_path = item.relative_to(src)
855
+ dst_item = dst / rel_path
856
+
857
+ # Skip Alfred parent folders (already handled above)
858
+ if item.is_dir() and item.name in [
859
+ "hooks",
860
+ "commands",
861
+ "output-styles",
862
+ "agents",
863
+ ]:
864
+ continue
865
+
866
+ if item.is_file():
867
+ # Smart merge for settings.json
868
+ if item.name == "settings.json":
869
+ self._merge_settings_json(item, dst_item)
870
+ # Apply variable substitution to merged settings.json (for cross-platform Hook paths)
871
+ if self.context:
872
+ content = dst_item.read_text(encoding="utf-8")
873
+ content, file_warnings = self._substitute_variables(content)
874
+ dst_item.write_text(content, encoding="utf-8")
875
+ all_warnings.extend(file_warnings)
876
+ if not silent:
877
+ console.print(" 🔄 settings.json merged (Hook paths configured for your OS)")
878
+ # Smart merge for config.json
879
+ elif item.name == "config.json":
880
+ self._merge_config_json(item, dst_item)
881
+ if not silent:
882
+ console.print(" 🔄 config.json merged (user preferences preserved)")
883
+ else:
884
+ # FORCE OVERWRITE: Always copy other files (no skip)
885
+ warnings = self._copy_file_with_substitution(item, dst_item)
886
+ all_warnings.extend(warnings)
887
+ elif item.is_dir():
888
+ # FORCE OVERWRITE: Always copy directories (no skip)
889
+ self._copy_dir_with_substitution(item, dst_item)
890
+
891
+ # Print warnings if any
892
+ if all_warnings and not silent:
893
+ console.print("[yellow]⚠️ Template warnings:[/yellow]")
894
+ for warning in set(all_warnings): # Deduplicate
895
+ console.print(f" {warning}")
896
+
897
+ if not silent:
898
+ console.print(" ✅ .claude/ copy complete (variables substituted)")
899
+
900
+ def _copy_moai(self, silent: bool = False) -> None:
901
+ """.moai/ directory copy with variable substitution (excludes protected paths)."""
902
+ src = self.template_root / ".moai"
903
+ dst = self.target_path / ".moai"
904
+
905
+ if not src.exists():
906
+ if not silent:
907
+ console.print("⚠️ .moai/ template not found")
908
+ return
909
+
910
+ # Paths excluded from template copying (specs/, reports/, .moai/config/config.json)
911
+ template_protected_paths = [
912
+ "specs",
913
+ "reports",
914
+ ".moai/config/config.json",
915
+ ]
916
+
917
+ all_warnings = []
918
+
919
+ # Copy while skipping protected paths
920
+ for item in src.rglob("*"):
921
+ rel_path = item.relative_to(src)
922
+ rel_path_str = str(rel_path)
923
+
924
+ # Skip specs/ and reports/
925
+ if any(rel_path_str.startswith(p) for p in template_protected_paths):
926
+ continue
927
+
928
+ dst_item = dst / rel_path
929
+ if item.is_file():
930
+ # FORCE OVERWRITE: Always copy files (no skip)
931
+ dst_item.parent.mkdir(parents=True, exist_ok=True)
932
+ # Copy with variable substitution
933
+ warnings = self._copy_file_with_substitution(item, dst_item)
934
+ all_warnings.extend(warnings)
935
+ elif item.is_dir():
936
+ dst_item.mkdir(parents=True, exist_ok=True)
937
+
938
+ # Print warnings if any
939
+ if all_warnings and not silent:
940
+ console.print("[yellow]⚠️ Template warnings:[/yellow]")
941
+ for warning in set(all_warnings): # Deduplicate
942
+ console.print(f" {warning}")
943
+
944
+ if not silent:
945
+ console.print(" ✅ .moai/ copy complete (variables substituted)")
946
+
947
+ def _copy_github(self, silent: bool = False) -> None:
948
+ """.github/ directory copy with smart merge (preserves user workflows)."""
949
+ src = self.template_root / ".github"
950
+ dst = self.target_path / ".github"
951
+
952
+ if not src.exists():
953
+ if not silent:
954
+ console.print("⚠️ .github/ template not found")
955
+ return
956
+
957
+ # Smart merge: preserve existing user workflows
958
+ if dst.exists():
959
+ self._merge_github_workflows(src, dst)
960
+ else:
961
+ # First time: just copy
962
+ self._copy_dir_with_substitution(src, dst)
963
+
964
+ if not silent:
965
+ console.print(" 🔄 .github/ merged (user workflows preserved, variables substituted)")
966
+
967
+ def _copy_claude_md(self, silent: bool = False) -> None:
968
+ """Copy CLAUDE.md with complete replacement (no merge)."""
969
+ src = self.template_root / "CLAUDE.md"
970
+ dst = self.target_path / "CLAUDE.md"
971
+
972
+ if not src.exists():
973
+ if not silent:
974
+ console.print("⚠️ CLAUDE.md template not found")
975
+ return
976
+
977
+ # Simple copy with substitution (no merge)
978
+ self._copy_file_with_substitution(src, dst)
979
+
980
+ if not silent:
981
+ console.print(" ✅ CLAUDE.md replaced (use CLAUDE.local.md for personal instructions)")
982
+
983
+ def _merge_claude_md(self, src: Path, dst: Path) -> None:
984
+ """Delegate the smart merge for CLAUDE.md.
985
+
986
+ Args:
987
+ src: Template CLAUDE.md.
988
+ dst: Project CLAUDE.md.
989
+ """
990
+ self.merger.merge_claude_md(src, dst)
991
+
992
+ def _merge_github_workflows(self, src: Path, dst: Path) -> None:
993
+ """Delegate the smart merge for .github/workflows/.
994
+
995
+ Args:
996
+ src: Template .github directory.
997
+ dst: Project .github directory.
998
+ """
999
+ self.merger.merge_github_workflows(src, dst)
1000
+
1001
+ def _merge_settings_json(self, src: Path, dst: Path) -> None:
1002
+ """Delegate the smart merge for settings.json.
1003
+
1004
+ Args:
1005
+ src: Template settings.json.
1006
+ dst: Project settings.json.
1007
+ """
1008
+ # Find the latest backup for user settings extraction
1009
+ backup_path = None
1010
+ latest_backup = self.backup.get_latest_backup()
1011
+ if latest_backup:
1012
+ backup_settings = latest_backup / ".claude" / "settings.json"
1013
+ if backup_settings.exists():
1014
+ backup_path = backup_settings
1015
+
1016
+ self.merger.merge_settings_json(src, dst, backup_path)
1017
+
1018
+ def _merge_config_json(self, src: Path, dst: Path) -> None:
1019
+ """Smart merge for config.json using LanguageConfigResolver priority system.
1020
+
1021
+ Args:
1022
+ src: Template config.json.
1023
+ dst: Project config.json.
1024
+ """
1025
+ import json
1026
+
1027
+ # Load template config
1028
+ try:
1029
+ template_config = json.loads(src.read_text(encoding="utf-8"))
1030
+ except (json.JSONDecodeError, FileNotFoundError) as e:
1031
+ console.print(f"⚠️ Warning: Could not read template config.json: {e}")
1032
+ return
1033
+
1034
+ # Find latest backup config.json
1035
+ latest_backup = self.backup.get_latest_backup()
1036
+ if latest_backup:
1037
+ backup_config_path = latest_backup / ".moai" / "config" / "config.json"
1038
+ if backup_config_path.exists():
1039
+ try:
1040
+ json.loads(backup_config_path.read_text(encoding="utf-8"))
1041
+ except json.JSONDecodeError as e:
1042
+ console.print(f"⚠️ Warning: Could not read backup config.json: {e}")
1043
+
1044
+ # Load existing project config.json
1045
+ existing_config = {}
1046
+ if dst.exists():
1047
+ try:
1048
+ existing_config = json.loads(dst.read_text(encoding="utf-8"))
1049
+ except json.JSONDecodeError as e:
1050
+ console.print(f"⚠️ Warning: Could not read existing config.json: {e}")
1051
+
1052
+ # Merge with priority system: Environment > Existing User > Template
1053
+ # We'll use LanguageConfigResolver to handle this properly
1054
+ try:
1055
+ # Import LanguageConfigResolver for priority-based merging
1056
+ from moai_adk.core.language_config_resolver import LanguageConfigResolver
1057
+
1058
+ # Create temporary resolver to handle merging
1059
+ temp_project_path = self.target_path / ".moai" / "config"
1060
+ temp_project_path.mkdir(parents=True, exist_ok=True)
1061
+
1062
+ # Start with template config as base
1063
+ merged_config = template_config.copy()
1064
+
1065
+ # Apply existing user config (higher priority than template)
1066
+ for key, value in existing_config.items():
1067
+ if key not in ["config_source"]: # Skip metadata
1068
+ if key in merged_config and isinstance(merged_config[key], dict) and isinstance(value, dict):
1069
+ # Deep merge for nested objects
1070
+ merged_config[key].update(value)
1071
+ else:
1072
+ merged_config[key] = value
1073
+
1074
+ # Apply environment variables (highest priority)
1075
+ import os
1076
+
1077
+ env_mappings = {
1078
+ "MOAI_USER_NAME": ("user", "name"),
1079
+ "MOAI_CONVERSATION_LANG": ("language", "conversation_language"),
1080
+ "MOAI_AGENT_PROMPT_LANG": ("language", "agent_prompt_language"),
1081
+ "MOAI_CONVERSATION_LANG_NAME": (
1082
+ "language",
1083
+ "conversation_language_name",
1084
+ ),
1085
+ "MOAI_GIT_COMMIT_MESSAGES_LANG": ("language", "git_commit_messages"),
1086
+ "MOAI_CODE_COMMENTS_LANG": ("language", "code_comments"),
1087
+ "MOAI_DOCUMENTATION_LANG": ("language", "documentation"),
1088
+ "MOAI_ERROR_MESSAGES_LANG": ("language", "error_messages"),
1089
+ }
1090
+
1091
+ for env_var, (section, key) in env_mappings.items():
1092
+ env_value = os.getenv(env_var)
1093
+ if env_value:
1094
+ if section not in merged_config:
1095
+ merged_config[section] = {}
1096
+ merged_config[section][key] = env_value
1097
+
1098
+ # Ensure consistency
1099
+ resolver = LanguageConfigResolver(str(self.target_path))
1100
+ merged_config = resolver._ensure_consistency(merged_config)
1101
+
1102
+ # Write merged config
1103
+ dst.write_text(
1104
+ json.dumps(merged_config, indent=2, ensure_ascii=False) + "\n",
1105
+ encoding="utf-8",
1106
+ )
1107
+
1108
+ except ImportError:
1109
+ # Fallback: simple merge without LanguageConfigResolver
1110
+ merged_config = template_config.copy()
1111
+
1112
+ # Apply existing config
1113
+ for key, value in existing_config.items():
1114
+ if key not in ["config_source"]:
1115
+ merged_config[key] = value
1116
+
1117
+ dst.write_text(
1118
+ json.dumps(merged_config, indent=2, ensure_ascii=False) + "\n",
1119
+ encoding="utf-8",
1120
+ )
1121
+ console.print(" ⚠️ Warning: Using simple merge (LanguageConfigResolver not available)")
1122
+
1123
+ def _copy_gitignore(self, silent: bool = False) -> None:
1124
+ """.gitignore copy (optional)."""
1125
+ src = self.template_root / ".gitignore"
1126
+ dst = self.target_path / ".gitignore"
1127
+
1128
+ if not src.exists():
1129
+ return
1130
+
1131
+ # Merge with the existing .gitignore when present
1132
+ if dst.exists():
1133
+ self._merge_gitignore(src, dst)
1134
+ if not silent:
1135
+ console.print(" 🔄 .gitignore merged")
1136
+ else:
1137
+ shutil.copy2(src, dst)
1138
+ if not silent:
1139
+ console.print(" ✅ .gitignore copy complete")
1140
+
1141
+ def _merge_gitignore(self, src: Path, dst: Path) -> None:
1142
+ """Delegate the .gitignore merge.
1143
+
1144
+ Args:
1145
+ src: Template .gitignore.
1146
+ dst: Project .gitignore.
1147
+ """
1148
+ self.merger.merge_gitignore(src, dst)
1149
+
1150
+ def _copy_mcp_json(self, silent: bool = False) -> None:
1151
+ """.mcp.json copy (smart merge with existing MCP server configuration)."""
1152
+ src = self.template_root / ".mcp.json"
1153
+ dst = self.target_path / ".mcp.json"
1154
+
1155
+ if not src.exists():
1156
+ return
1157
+
1158
+ # Merge with existing .mcp.json when present (preserve user-added MCP servers)
1159
+ if dst.exists():
1160
+ self._merge_mcp_json(src, dst)
1161
+ if not silent:
1162
+ console.print(" 🔄 .mcp.json merged (user MCP servers preserved)")
1163
+ else:
1164
+ shutil.copy2(src, dst)
1165
+ if not silent:
1166
+ console.print(" ✅ .mcp.json copy complete")
1167
+
1168
+ def _merge_mcp_json(self, src: Path, dst: Path) -> None:
1169
+ """Smart merge for .mcp.json (preserve user-added MCP servers).
1170
+
1171
+ Args:
1172
+ src: Template .mcp.json.
1173
+ dst: Project .mcp.json.
1174
+ """
1175
+ try:
1176
+ src_data = json.loads(src.read_text(encoding="utf-8"))
1177
+ dst_data = json.loads(dst.read_text(encoding="utf-8"))
1178
+
1179
+ # Merge mcpServers: preserve user servers, update template servers
1180
+ if "mcpServers" in src_data:
1181
+ if "mcpServers" not in dst_data:
1182
+ dst_data["mcpServers"] = {}
1183
+ # Update with template servers (preserves existing user servers)
1184
+ dst_data["mcpServers"].update(src_data["mcpServers"])
1185
+
1186
+ # Write merged result back
1187
+ dst.write_text(json.dumps(dst_data, indent=2, ensure_ascii=False), encoding="utf-8")
1188
+ except json.JSONDecodeError as e:
1189
+ console.print(f"[yellow]⚠️ Failed to merge .mcp.json: {e}[/yellow]")
1190
+
1191
+ def merge_config(self, detected_language: str | None = None) -> dict[str, str]:
1192
+ """Delegate the smart merge for config.json.
1193
+
1194
+ Args:
1195
+ detected_language: Detected language.
1196
+
1197
+ Returns:
1198
+ Merged configuration dictionary.
1199
+ """
1200
+ return self.merger.merge_config(detected_language)