moai-adk 0.25.4__py3-none-any.whl → 0.32.8__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (378) hide show
  1. moai_adk/__init__.py +2 -5
  2. moai_adk/__main__.py +114 -82
  3. moai_adk/cli/__init__.py +6 -1
  4. moai_adk/cli/commands/__init__.py +1 -3
  5. moai_adk/cli/commands/analyze.py +5 -16
  6. moai_adk/cli/commands/doctor.py +6 -18
  7. moai_adk/cli/commands/init.py +56 -125
  8. moai_adk/cli/commands/language.py +14 -35
  9. moai_adk/cli/commands/status.py +9 -15
  10. moai_adk/cli/commands/update.py +1555 -190
  11. moai_adk/cli/prompts/init_prompts.py +112 -56
  12. moai_adk/cli/spec_status.py +263 -0
  13. moai_adk/cli/ui/__init__.py +44 -0
  14. moai_adk/cli/ui/progress.py +422 -0
  15. moai_adk/cli/ui/prompts.py +389 -0
  16. moai_adk/cli/ui/theme.py +129 -0
  17. moai_adk/cli/worktree/__init__.py +27 -0
  18. moai_adk/cli/worktree/__main__.py +31 -0
  19. moai_adk/cli/worktree/cli.py +672 -0
  20. moai_adk/cli/worktree/exceptions.py +89 -0
  21. moai_adk/cli/worktree/manager.py +490 -0
  22. moai_adk/cli/worktree/models.py +65 -0
  23. moai_adk/cli/worktree/registry.py +128 -0
  24. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  25. moai_adk/core/analysis/session_analyzer.py +17 -56
  26. moai_adk/core/claude_integration.py +26 -54
  27. moai_adk/core/command_helpers.py +10 -10
  28. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  29. moai_adk/core/config/auto_spec_config.py +5 -11
  30. moai_adk/core/config/migration.py +19 -9
  31. moai_adk/core/config/unified.py +436 -0
  32. moai_adk/core/context_manager.py +6 -12
  33. moai_adk/core/enterprise_features.py +1404 -0
  34. moai_adk/core/error_recovery_system.py +725 -112
  35. moai_adk/core/event_driven_hook_system.py +1371 -0
  36. moai_adk/core/git/__init__.py +8 -0
  37. moai_adk/core/git/branch_manager.py +3 -11
  38. moai_adk/core/git/checkpoint.py +1 -3
  39. moai_adk/core/git/conflict_detector.py +413 -0
  40. moai_adk/core/git/manager.py +91 -1
  41. moai_adk/core/hooks/post_tool_auto_spec_completion.py +56 -80
  42. moai_adk/core/input_validation_middleware.py +1006 -0
  43. moai_adk/core/integration/engine.py +6 -18
  44. moai_adk/core/integration/integration_tester.py +10 -9
  45. moai_adk/core/integration/utils.py +1 -1
  46. moai_adk/core/issue_creator.py +10 -28
  47. moai_adk/core/jit_context_loader.py +956 -0
  48. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  49. moai_adk/core/language_config_resolver.py +485 -0
  50. moai_adk/core/language_validator.py +28 -41
  51. moai_adk/core/mcp/setup.py +15 -12
  52. moai_adk/core/merge/__init__.py +9 -0
  53. moai_adk/core/merge/analyzer.py +481 -0
  54. moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
  55. moai_adk/core/migration/backup_manager.py +78 -9
  56. moai_adk/core/migration/custom_element_scanner.py +358 -0
  57. moai_adk/core/migration/file_migrator.py +8 -17
  58. moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
  59. moai_adk/core/migration/selective_restorer.py +470 -0
  60. moai_adk/core/migration/template_utils.py +74 -0
  61. moai_adk/core/migration/user_selection_ui.py +338 -0
  62. moai_adk/core/migration/version_detector.py +6 -10
  63. moai_adk/core/migration/version_migrator.py +3 -3
  64. moai_adk/core/performance/cache_system.py +8 -10
  65. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  66. moai_adk/core/project/checker.py +2 -4
  67. moai_adk/core/project/detector.py +1 -3
  68. moai_adk/core/project/initializer.py +135 -23
  69. moai_adk/core/project/phase_executor.py +54 -81
  70. moai_adk/core/project/validator.py +6 -12
  71. moai_adk/core/quality/trust_checker.py +9 -27
  72. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  73. moai_adk/core/robust_json_parser.py +611 -0
  74. moai_adk/core/rollback_manager.py +73 -148
  75. moai_adk/core/session_manager.py +10 -26
  76. moai_adk/core/skill_loading_system.py +579 -0
  77. moai_adk/core/spec/confidence_scoring.py +31 -100
  78. moai_adk/core/spec/ears_template_engine.py +351 -286
  79. moai_adk/core/spec/quality_validator.py +35 -69
  80. moai_adk/core/spec_status_manager.py +64 -74
  81. moai_adk/core/template/backup.py +45 -20
  82. moai_adk/core/template/config.py +112 -39
  83. moai_adk/core/template/merger.py +11 -19
  84. moai_adk/core/template/processor.py +253 -149
  85. moai_adk/core/template_engine.py +73 -40
  86. moai_adk/core/template_variable_synchronizer.py +417 -0
  87. moai_adk/core/unified_permission_manager.py +745 -0
  88. moai_adk/core/user_behavior_analytics.py +851 -0
  89. moai_adk/core/version_sync.py +429 -0
  90. moai_adk/foundation/__init__.py +56 -0
  91. moai_adk/foundation/backend.py +1027 -0
  92. moai_adk/foundation/database.py +1115 -0
  93. moai_adk/foundation/devops.py +1585 -0
  94. moai_adk/foundation/ears.py +431 -0
  95. moai_adk/foundation/frontend.py +870 -0
  96. moai_adk/foundation/git/commit_templates.py +4 -12
  97. moai_adk/foundation/git.py +376 -0
  98. moai_adk/foundation/langs.py +484 -0
  99. moai_adk/foundation/ml_ops.py +1162 -0
  100. moai_adk/foundation/testing.py +1524 -0
  101. moai_adk/foundation/trust/trust_principles.py +23 -72
  102. moai_adk/foundation/trust/validation_checklist.py +57 -162
  103. moai_adk/project/__init__.py +0 -0
  104. moai_adk/project/configuration.py +1084 -0
  105. moai_adk/project/documentation.py +566 -0
  106. moai_adk/project/schema.py +447 -0
  107. moai_adk/statusline/alfred_detector.py +1 -3
  108. moai_adk/statusline/config.py +13 -4
  109. moai_adk/statusline/enhanced_output_style_detector.py +23 -15
  110. moai_adk/statusline/main.py +51 -15
  111. moai_adk/statusline/renderer.py +104 -48
  112. moai_adk/statusline/update_checker.py +3 -9
  113. moai_adk/statusline/version_reader.py +140 -46
  114. moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
  115. moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
  116. moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
  117. moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
  118. moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
  119. moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
  120. moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
  121. moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
  122. moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
  123. moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
  124. moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
  125. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
  126. moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
  127. moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
  128. moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
  129. moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
  130. moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
  131. moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
  132. moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
  133. moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
  134. moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
  135. moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
  136. moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
  137. moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
  138. moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
  139. moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
  140. moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
  141. moai_adk/templates/.claude/commands/moai/3-sync.md +993 -0
  142. moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
  143. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  144. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  145. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
  146. moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
  147. moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
  148. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
  149. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  150. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  151. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
  152. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
  153. moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
  154. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
  155. moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
  156. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  157. moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
  158. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
  159. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
  160. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +921 -0
  161. moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
  162. moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
  163. moai_adk/templates/.claude/settings.json +172 -0
  164. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -0
  165. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
  166. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
  167. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  168. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
  169. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
  170. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +319 -0
  171. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +320 -0
  172. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  173. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  174. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  175. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  176. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +496 -0
  177. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -0
  178. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  179. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  180. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  181. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
  182. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  183. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  184. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  185. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +491 -0
  186. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
  187. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  188. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  189. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  190. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  191. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  192. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +201 -0
  193. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  194. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
  195. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
  196. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  197. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  198. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  199. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
  200. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
  201. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  202. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  203. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  204. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  205. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  206. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  207. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +438 -0
  208. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -0
  209. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  210. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +346 -0
  211. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  212. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
  213. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  214. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  215. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  216. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
  217. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  218. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
  219. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +362 -0
  220. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  221. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  222. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  223. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  224. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  225. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  226. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  227. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  228. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  229. moai_adk/templates/.claude/skills/moai-integration-mcp/SKILL.md +352 -0
  230. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
  231. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
  232. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
  233. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
  234. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
  235. moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
  236. moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
  237. moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
  238. moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
  239. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -0
  240. moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
  241. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  242. moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
  243. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  244. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +316 -0
  245. moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
  246. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  247. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
  248. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
  249. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  250. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  251. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  252. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  253. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  254. moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
  255. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +370 -0
  256. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  257. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  258. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  259. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  260. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  261. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  262. moai_adk/templates/.claude/skills/moai-platform-baas/README.md +186 -0
  263. moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
  264. moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
  265. moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
  266. moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
  267. moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
  268. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
  269. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
  270. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
  271. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  272. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -0
  273. moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
  274. moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
  275. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
  276. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
  277. moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
  278. moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +135 -0
  279. moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
  280. moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
  281. moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
  282. moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
  283. moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
  284. moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
  285. moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
  286. moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
  287. moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
  288. moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
  289. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  290. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -0
  291. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  292. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  293. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  294. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +71 -0
  295. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  296. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  297. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  298. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  299. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  300. moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
  301. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +374 -0
  302. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  303. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  304. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  305. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  306. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -0
  307. moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
  308. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  309. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  310. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  311. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  312. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
  313. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
  314. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
  315. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
  316. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
  317. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
  318. moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
  319. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  320. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  321. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  322. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  323. moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +410 -0
  324. moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
  325. moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
  326. moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
  327. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
  328. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
  329. moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
  330. moai_adk/templates/.git-hooks/pre-commit +103 -41
  331. moai_adk/templates/.git-hooks/pre-push +116 -21
  332. moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
  333. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  334. moai_adk/templates/.gitignore +184 -44
  335. moai_adk/templates/.mcp.json +7 -9
  336. moai_adk/templates/.moai/cache/personalization.json +10 -0
  337. moai_adk/templates/.moai/config/config.yaml +344 -0
  338. moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
  339. moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
  340. moai_adk/templates/.moai/config/presets/team.yaml +33 -0
  341. moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
  342. moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
  343. moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
  344. moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
  345. moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
  346. moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
  347. moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -0
  348. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  349. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  350. moai_adk/templates/.moai/config/sections/quality.yaml +15 -0
  351. moai_adk/templates/.moai/config/sections/system.yaml +14 -0
  352. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  353. moai_adk/templates/.moai/config/statusline-config.yaml +86 -0
  354. moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
  355. moai_adk/templates/CLAUDE.md +382 -501
  356. moai_adk/utils/__init__.py +24 -1
  357. moai_adk/utils/banner.py +7 -10
  358. moai_adk/utils/common.py +16 -30
  359. moai_adk/utils/link_validator.py +4 -12
  360. moai_adk/utils/safe_file_reader.py +2 -6
  361. moai_adk/utils/timeout.py +160 -0
  362. moai_adk/utils/toon_utils.py +256 -0
  363. moai_adk/version.py +22 -0
  364. moai_adk-0.32.8.dist-info/METADATA +2478 -0
  365. moai_adk-0.32.8.dist-info/RECORD +396 -0
  366. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
  367. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
  368. moai_adk/cli/commands/backup.py +0 -82
  369. moai_adk/cli/commands/improve_user_experience.py +0 -348
  370. moai_adk/cli/commands/migrate.py +0 -158
  371. moai_adk/cli/commands/validate_links.py +0 -118
  372. moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -413
  373. moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
  374. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
  375. moai_adk/utils/user_experience.py +0 -531
  376. moai_adk-0.25.4.dist-info/METADATA +0 -2279
  377. moai_adk-0.25.4.dist-info/RECORD +0 -112
  378. {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
@@ -4,8 +4,11 @@ Template engine for parameterizing GitHub templates and other configuration file
4
4
  Supports Jinja2-style templating with variable substitution and conditional sections.
5
5
  Enables users to customize MoAI-ADK templates for their own projects.
6
6
 
7
+ Performance: Jinja2 Environment instances are cached to avoid recreation overhead
8
+ (40-60ms per render → ~1ms after caching).
7
9
  """
8
10
 
11
+ from functools import lru_cache
9
12
  from pathlib import Path
10
13
  from typing import Any, Dict, Optional
11
14
 
@@ -20,6 +23,49 @@ from jinja2 import (
20
23
  )
21
24
 
22
25
 
26
+ # Module-level cached Environment factory functions
27
+ @lru_cache(maxsize=2)
28
+ def _get_string_environment(strict: bool) -> Environment:
29
+ """
30
+ Get cached Jinja2 Environment for string rendering.
31
+
32
+ Args:
33
+ strict: If True, raise error on undefined variables
34
+
35
+ Returns:
36
+ Cached Environment instance
37
+
38
+ Performance: Cached to avoid Environment recreation overhead
39
+ """
40
+ return Environment(
41
+ undefined=StrictUndefined if strict else Undefined,
42
+ trim_blocks=False,
43
+ lstrip_blocks=False,
44
+ )
45
+
46
+
47
+ @lru_cache(maxsize=8)
48
+ def _get_file_environment(template_dir: str, strict: bool) -> Environment:
49
+ """
50
+ Get cached Jinja2 Environment for file rendering.
51
+
52
+ Args:
53
+ template_dir: Template directory path (string for hashability)
54
+ strict: If True, raise error on undefined variables
55
+
56
+ Returns:
57
+ Cached Environment instance with FileSystemLoader
58
+
59
+ Performance: Cached to avoid Environment recreation overhead
60
+ """
61
+ return Environment(
62
+ loader=FileSystemLoader(template_dir),
63
+ undefined=StrictUndefined if strict else Undefined,
64
+ trim_blocks=False,
65
+ lstrip_blocks=False,
66
+ )
67
+
68
+
23
69
  class TemplateEngine:
24
70
  """
25
71
  Jinja2-based template engine for MoAI-ADK configuration and GitHub templates.
@@ -59,13 +105,12 @@ class TemplateEngine:
59
105
  Raises:
60
106
  TemplateSyntaxError: If template syntax is invalid
61
107
  TemplateRuntimeError: If variable substitution fails in strict mode
108
+
109
+ Performance: Uses cached Environment instance (40-60ms → ~1ms)
62
110
  """
63
111
  try:
64
- env = Environment(
65
- undefined=self.undefined_behavior,
66
- trim_blocks=False,
67
- lstrip_blocks=False,
68
- )
112
+ # Use cached Environment instead of creating new one
113
+ env = _get_string_environment(strict=self.strict_undefined)
69
114
  template = env.from_string(template_string)
70
115
  return template.render(**variables)
71
116
  except (TemplateSyntaxError, TemplateRuntimeError) as e:
@@ -92,6 +137,8 @@ class TemplateEngine:
92
137
  FileNotFoundError: If template file doesn't exist
93
138
  TemplateSyntaxError: If template syntax is invalid
94
139
  TemplateRuntimeError: If variable substitution fails in strict mode
140
+
141
+ Performance: Uses cached Environment instance (40-60ms → ~1ms)
95
142
  """
96
143
  if not template_path.exists():
97
144
  raise FileNotFoundError(f"Template file not found: {template_path}")
@@ -100,12 +147,8 @@ class TemplateEngine:
100
147
  template_name = template_path.name
101
148
 
102
149
  try:
103
- env = Environment(
104
- loader=FileSystemLoader(str(template_dir)),
105
- undefined=self.undefined_behavior,
106
- trim_blocks=False,
107
- lstrip_blocks=False,
108
- )
150
+ # Use cached Environment instead of creating new one
151
+ env = _get_file_environment(template_dir=str(template_dir), strict=self.strict_undefined)
109
152
  template = env.get_template(template_name)
110
153
  rendered = template.render(**variables)
111
154
 
@@ -115,9 +158,7 @@ class TemplateEngine:
115
158
 
116
159
  return rendered
117
160
  except TemplateNotFound:
118
- raise FileNotFoundError(
119
- f"Template not found in {template_dir}: {template_name}"
120
- )
161
+ raise FileNotFoundError(f"Template not found in {template_dir}: {template_name}")
121
162
  except (TemplateSyntaxError, TemplateRuntimeError) as e:
122
163
  raise RuntimeError(f"Template rendering error in {template_path}: {e}")
123
164
 
@@ -173,7 +214,8 @@ class TemplateEngine:
173
214
  Returns:
174
215
  Dictionary of template variables
175
216
  """
176
- github_config = config.get("github", {}).get("templates", {})
217
+ github_templates_config = config.get("github", {}).get("templates", {})
218
+ github_config = config.get("github", {})
177
219
  project_config = config.get("project", {})
178
220
  user_config = config.get("user", {})
179
221
 
@@ -181,28 +223,23 @@ class TemplateEngine:
181
223
  # Project information
182
224
  "PROJECT_NAME": project_config.get("name", "MyProject"),
183
225
  "PROJECT_DESCRIPTION": project_config.get("description", ""),
184
- "PROJECT_OWNER": project_config.get("owner", ""),
226
+ "PROJECT_OWNER": project_config.get("owner", ""), # GitHub username (project owner)
227
+ "GITHUB_PROFILE_NAME": github_config.get("profile_name", ""),
185
228
  "PROJECT_MODE": project_config.get("mode", "team"), # team or personal
186
229
  "CODEBASE_LANGUAGE": project_config.get("codebase_language", "python"),
187
230
  # User information
188
231
  "USER_NAME": user_config.get("name", ""),
189
232
  # Directory structure
190
- "SPEC_DIR": github_config.get("spec_directory", ".moai/specs"),
191
- "DOCS_DIR": github_config.get("docs_directory", ".moai/docs"),
192
- "TEST_DIR": github_config.get("test_directory", "tests"),
233
+ "SPEC_DIR": github_templates_config.get("spec_directory", ".moai/specs"),
234
+ "DOCS_DIR": github_templates_config.get("docs_directory", ".moai/docs"),
235
+ "TEST_DIR": github_templates_config.get("test_directory", "tests"),
193
236
  # Feature flags
194
237
  "ENABLE_TRUST_5": github_config.get("enable_trust_5", True),
195
- "ENABLE_ALFRED_COMMANDS": github_config.get("enable_alfred_commands", True),
238
+ "ENABLE_ALFRED_COMMANDS": github_templates_config.get("enable_alfred_commands", True),
196
239
  # Language configuration
197
- "CONVERSATION_LANGUAGE": config.get("language", {}).get(
198
- "conversation_language", "en"
199
- ),
200
- "CONVERSATION_LANGUAGE_NAME": config.get("language", {}).get(
201
- "conversation_language_name", "English"
202
- ),
203
- "AGENT_PROMPT_LANGUAGE": config.get("language", {}).get(
204
- "agent_prompt_language", "english"
205
- ),
240
+ "CONVERSATION_LANGUAGE": config.get("language", {}).get("conversation_language", "en"),
241
+ "CONVERSATION_LANGUAGE_NAME": config.get("language", {}).get("conversation_language_name", "English"),
242
+ "AGENT_PROMPT_LANGUAGE": config.get("language", {}).get("agent_prompt_language", "english"),
206
243
  # Additional metadata
207
244
  "MOAI_VERSION": config.get("moai", {}).get("version", "0.7.0"),
208
245
  }
@@ -253,25 +290,21 @@ class TemplateVariableValidator:
253
290
  errors.append(f"Missing required variable: {var_name}")
254
291
  elif not isinstance(variables[var_name], var_type):
255
292
  actual_type = type(variables[var_name]).__name__
256
- errors.append(
257
- f"Invalid type for {var_name}: "
258
- f"expected {var_type.__name__}, got {actual_type}"
259
- )
293
+ errors.append(f"Invalid type for {var_name}: expected {var_type.__name__}, got {actual_type}")
260
294
 
261
295
  # Check optional variables (if present)
262
296
  for var_name, var_type in cls.OPTIONAL_VARIABLES.items():
263
297
  if var_name in variables:
264
298
  if not isinstance(variables[var_name], var_type):
265
299
  if isinstance(var_type, tuple):
266
- type_names = " or ".join(
267
- getattr(t, "__name__", str(t)) for t in var_type
268
- )
300
+ type_names = (
301
+ " or ".join(getattr(t, "__name__", str(t)) for t in var_type)
302
+ if var_type is not None
303
+ else "unknown"
304
+ ) # type: ignore[union-attr]
269
305
  else:
270
306
  type_names = getattr(var_type, "__name__", str(var_type))
271
307
  actual_type = type(variables[var_name]).__name__
272
- errors.append(
273
- f"Invalid type for {var_name}: "
274
- f"expected {type_names}, got {actual_type}"
275
- )
308
+ errors.append(f"Invalid type for {var_name}: expected {type_names}, got {actual_type}")
276
309
 
277
310
  return len(errors) == 0, errors
@@ -0,0 +1,417 @@
1
+ """
2
+ Template Variable Synchronizer for MoAI-ADK
3
+
4
+ Handles synchronization of template variables when configuration is updated
5
+ through /moai:0-project command or other configuration management operations.
6
+
7
+ This module ensures that when language or user settings change, all template
8
+ variables in the system are properly updated to reflect the new configuration.
9
+ """
10
+
11
+ import json
12
+ import re
13
+ from pathlib import Path
14
+ from typing import Any, Dict, List, Optional
15
+
16
+ from .language_config_resolver import get_resolver
17
+
18
+
19
+ class TemplateVariableSynchronizer:
20
+ """
21
+ Synchronizes template variables across the MoAI-ADK system when configuration changes.
22
+
23
+ Responsible for:
24
+ - Detecting template variables that need updating
25
+ - Re-substituting variables in affected files
26
+ - Maintaining consistency between config and template files
27
+ - Tracking template variable usage across the project
28
+ """
29
+
30
+ # Template variable patterns to track and synchronize
31
+ TEMPLATE_PATTERNS = {
32
+ r"\{\{CONVERSATION_LANGUAGE\}\}",
33
+ r"\{\{CONVERSATION_LANGUAGE_NAME\}\}",
34
+ r"\{\{AGENT_PROMPT_LANGUAGE\}\}",
35
+ r"\{\{USER_NAME\}\}",
36
+ r"\{\{PERSONALIZED_GREETING\}\}",
37
+ r"\{\{LANGUAGE_CONFIG_SOURCE\}\}",
38
+ }
39
+
40
+ # Files that typically contain template variables
41
+ TEMPLATE_TRACKING_PATTERNS = [
42
+ ".claude/settings.json",
43
+ ".claude/settings.local.json",
44
+ ".moai/config/config.json",
45
+ ".claude/output-styles/**/*.md",
46
+ ".claude/hooks/**/*.py",
47
+ ".claude/commands/**/*.md",
48
+ ".claude/skills/**/*.md",
49
+ "CLAUDE.md",
50
+ "README.md",
51
+ ]
52
+
53
+ def __init__(self, project_root: str):
54
+ """
55
+ Initialize the synchronizer.
56
+
57
+ Args:
58
+ project_root: Root directory of the MoAI-ADK project
59
+ """
60
+ self.project_root = Path(project_root)
61
+ self.language_resolver = get_resolver(project_root)
62
+
63
+ def synchronize_after_config_change(self, changed_config_path: Optional[Path] = None) -> Dict[str, Any]:
64
+ """
65
+ Synchronize template variables after configuration changes.
66
+
67
+ Args:
68
+ changed_config_path: Path to the configuration file that was changed
69
+ (None if unknown or multiple files changed)
70
+
71
+ Returns:
72
+ Dictionary containing synchronization results
73
+ """
74
+ results: Dict[str, Any] = {
75
+ "files_updated": 0,
76
+ "variables_updated": [],
77
+ "errors": [],
78
+ "sync_status": "completed",
79
+ }
80
+
81
+ try:
82
+ # Get current resolved configuration
83
+ current_config = self.language_resolver.resolve_config(force_refresh=True)
84
+ template_vars = self.language_resolver.export_template_variables(current_config)
85
+
86
+ # Find files that need updating
87
+ files_to_update = self._find_files_with_template_variables(changed_config_path)
88
+
89
+ # Update each file
90
+ for file_path in files_to_update:
91
+ try:
92
+ updated_vars = self._update_file_template_variables(file_path, template_vars)
93
+ if updated_vars:
94
+ files_updated: int = results["files_updated"] # type: ignore[assignment]
95
+ results["files_updated"] = files_updated + 1
96
+ variables_updated: List[str] = results["variables_updated"] # type: ignore[assignment]
97
+ variables_updated.extend(updated_vars)
98
+
99
+ except Exception as e:
100
+ error_msg = f"Failed to update {file_path}: {str(e)}"
101
+ errors: List[str] = results["errors"] # type: ignore[assignment]
102
+ errors.append(error_msg)
103
+
104
+ # Special handling for certain file types
105
+ self._handle_special_file_updates(template_vars, results)
106
+
107
+ except Exception as e:
108
+ results["sync_status"] = "failed"
109
+ errors_list: List[str] = results["errors"] # type: ignore[assignment]
110
+ errors_list.append(f"Synchronization failed: {str(e)}")
111
+
112
+ return results
113
+
114
+ def _find_files_with_template_variables(self, changed_config_path: Optional[Path]) -> List[Path]:
115
+ """
116
+ Find files that contain template variables and might need updating.
117
+
118
+ Args:
119
+ changed_config_path: Specific config file that changed, if known
120
+
121
+ Returns:
122
+ List of file paths that contain template variables
123
+ """
124
+ files_with_variables = []
125
+
126
+ # If a specific config file changed, prioritize files that depend on it
127
+ if changed_config_path:
128
+ dependency_map = {
129
+ ".moai/config/config.json": [
130
+ ".claude/settings.json",
131
+ ".claude/settings.local.json",
132
+ ".claude/output-styles",
133
+ ".claude/hooks",
134
+ ]
135
+ }
136
+
137
+ config_key = str(changed_config_path.relative_to(self.project_root))
138
+ if config_key in dependency_map:
139
+ for pattern in dependency_map[config_key]:
140
+ files_with_variables.extend(self._glob_files(pattern))
141
+
142
+ # Always check common template files
143
+ common_patterns = [
144
+ ".claude/settings.json",
145
+ ".claude/settings.local.json",
146
+ ".claude/output-styles/**/*.md",
147
+ "CLAUDE.md",
148
+ ]
149
+
150
+ for pattern in common_patterns:
151
+ files_with_variables.extend(self._glob_files(pattern))
152
+
153
+ # Remove duplicates and sort
154
+ files_with_variables = list(set(files_with_variables))
155
+ files_with_variables.sort()
156
+
157
+ return [f for f in files_with_variables if f.exists() and f.is_file()]
158
+
159
+ def _glob_files(self, pattern: str) -> List[Path]:
160
+ """
161
+ Glob files matching a pattern.
162
+
163
+ Args:
164
+ pattern: Glob pattern (supports ** for recursive matching)
165
+
166
+ Returns:
167
+ List of matching file paths
168
+ """
169
+ try:
170
+ return list(self.project_root.glob(pattern))
171
+ except (OSError, ValueError):
172
+ return []
173
+
174
+ def _update_file_template_variables(self, file_path: Path, template_vars: Dict[str, str]) -> List[str]:
175
+ """
176
+ Update template variables in a specific file.
177
+
178
+ Args:
179
+ file_path: Path to the file to update
180
+ template_vars: Dictionary of template variables to substitute
181
+
182
+ Returns:
183
+ List of variable names that were updated in this file
184
+ """
185
+ if not file_path.exists():
186
+ return []
187
+
188
+ try:
189
+ content = file_path.read_text(encoding="utf-8")
190
+ original_content = content
191
+
192
+ # Track which variables were updated
193
+ updated_vars = []
194
+
195
+ # Apply each template variable substitution
196
+ for var_name, var_value in template_vars.items():
197
+ # Look for {{VARIABLE_NAME}} pattern
198
+ pattern = re.compile(r"\{\{" + re.escape(var_name) + r"\}\}")
199
+
200
+ if pattern.search(content):
201
+ content = pattern.sub(var_value, content)
202
+ updated_vars.append(var_name)
203
+
204
+ # Only write if content changed
205
+ if content != original_content:
206
+ file_path.write_text(content, encoding="utf-8")
207
+
208
+ return updated_vars
209
+
210
+ except (OSError, UnicodeDecodeError, UnicodeEncodeError):
211
+ # File read/write errors - skip this file
212
+ return []
213
+
214
+ def _handle_special_file_updates(self, template_vars: Dict[str, str], results: Dict[str, Any]) -> None:
215
+ """
216
+ Handle special cases for certain file types.
217
+
218
+ Args:
219
+ template_vars: Dictionary of template variables
220
+ results: Results dictionary to update
221
+ """
222
+ # Handle settings.json environment variables section
223
+ settings_file = self.project_root / ".claude" / "settings.json"
224
+ if settings_file.exists():
225
+ try:
226
+ self._update_settings_env_vars(settings_file, template_vars, results)
227
+ except Exception as e:
228
+ results["errors"].append(f"Failed to update settings.json env vars: {str(e)}")
229
+
230
+ def _update_settings_env_vars(
231
+ self,
232
+ settings_file: Path,
233
+ template_vars: Dict[str, str],
234
+ results: Dict[str, Any],
235
+ ) -> None:
236
+ """
237
+ Update the environment variables section in settings.json.
238
+
239
+ Args:
240
+ settings_file: Path to settings.json
241
+ template_vars: Template variables to use for env values
242
+ results: Results dictionary to update
243
+ """
244
+ try:
245
+ settings_data = json.loads(settings_file.read_text(encoding="utf-8"))
246
+
247
+ # Define environment variable mappings
248
+ env_mappings = {
249
+ "CONVERSATION_LANGUAGE": "MOAI_CONVERSATION_LANG",
250
+ "AGENT_PROMPT_LANGUAGE": "MOAI_AGENT_PROMPT_LANG",
251
+ "CONVERSATION_LANGUAGE_NAME": "MOAI_CONVERSATION_LANG_NAME",
252
+ "USER_NAME": "MOAI_USER_NAME",
253
+ "LANGUAGE_CONFIG_SOURCE": "MOAI_CONFIG_SOURCE",
254
+ }
255
+
256
+ # Update or create env section
257
+ if "env" not in settings_data:
258
+ settings_data["env"] = {}
259
+
260
+ updated_vars = []
261
+ for template_var, env_var in env_mappings.items():
262
+ if template_var in template_vars:
263
+ old_value = settings_data["env"].get(env_var)
264
+ new_value = template_vars[template_var]
265
+
266
+ if old_value != new_value:
267
+ settings_data["env"][env_var] = new_value
268
+ updated_vars.append(f"{env_var}: {old_value} → {new_value}")
269
+
270
+ # Write back if changed
271
+ if updated_vars:
272
+ settings_file.write_text(
273
+ json.dumps(settings_data, indent=2, ensure_ascii=False) + "\n",
274
+ encoding="utf-8",
275
+ )
276
+ results["files_updated"] += 1
277
+ results["variables_updated"].extend(updated_vars)
278
+
279
+ except (json.JSONDecodeError, OSError, UnicodeDecodeError, UnicodeEncodeError):
280
+ # Skip if settings.json is malformed or can't be accessed
281
+ pass
282
+
283
+ def validate_template_variable_consistency(self) -> Dict[str, Any]:
284
+ """
285
+ Validate that template variables are consistent across the project.
286
+
287
+ Returns:
288
+ Dictionary containing validation results
289
+ """
290
+ validation_results = {
291
+ "status": "passed",
292
+ "inconsistencies": [],
293
+ "total_files_checked": 0,
294
+ "files_with_variables": 0,
295
+ }
296
+
297
+ try:
298
+ # Get current template variables
299
+ current_config = self.language_resolver.resolve_config()
300
+ current_vars = self.language_resolver.export_template_variables(current_config)
301
+
302
+ # Check files for template variable consistency
303
+ files_with_variables = self._find_files_with_template_variables(None)
304
+ validation_results["total_files_checked"] = len(files_with_variables)
305
+
306
+ for file_path in files_with_variables:
307
+ try:
308
+ content = file_path.read_text(encoding="utf-8")
309
+ file_inconsistencies: List[str] = []
310
+
311
+ # Check each template variable
312
+ for var_name, expected_value in current_vars.items():
313
+ pattern = re.compile(r"\{\{" + re.escape(var_name) + r"\}\}")
314
+
315
+ if pattern.search(content):
316
+ files_with_vars: int = validation_results["files_with_variables"] # type: ignore[assignment]
317
+ validation_results["files_with_variables"] = files_with_vars + 1
318
+ # Variable found but not substituted - this might be expected
319
+ # Only report as inconsistency if we expect it to be substituted
320
+ pass
321
+
322
+ if file_inconsistencies:
323
+ inconsistencies: List[Dict[str, Any]] = validation_results["inconsistencies"] # type: ignore[assignment]
324
+ inconsistencies.append(
325
+ {
326
+ "file": str(file_path.relative_to(self.project_root)),
327
+ "issues": file_inconsistencies,
328
+ }
329
+ )
330
+
331
+ except (OSError, UnicodeDecodeError):
332
+ # Skip files that can't be read
333
+ continue
334
+
335
+ if validation_results["inconsistencies"]:
336
+ validation_results["status"] = "warning"
337
+
338
+ except Exception as e:
339
+ validation_results["status"] = "failed"
340
+ validation_results["error"] = str(e)
341
+
342
+ return validation_results
343
+
344
+ def get_template_variable_usage_report(self) -> Dict[str, Any]:
345
+ """
346
+ Generate a report of template variable usage across the project.
347
+
348
+ Returns:
349
+ Dictionary containing template variable usage statistics
350
+ """
351
+ usage_report = {
352
+ "total_files_with_variables": 0,
353
+ "variable_usage": {},
354
+ "files_by_variable": {},
355
+ "unsubstituted_variables": [],
356
+ }
357
+
358
+ try:
359
+ files_with_variables = self._find_files_with_template_variables(None)
360
+ usage_report["total_files_with_variables"] = len(files_with_variables)
361
+
362
+ for file_path in files_with_variables:
363
+ try:
364
+ content = file_path.read_text(encoding="utf-8")
365
+ relative_path = str(file_path.relative_to(self.project_root))
366
+
367
+ # Check for each template variable pattern
368
+ for pattern_str in self.TEMPLATE_PATTERNS:
369
+ pattern = re.compile(pattern_str)
370
+ matches = pattern.findall(content)
371
+
372
+ if matches:
373
+ var_name = pattern_str.strip(r"{}")
374
+ variable_usage: Dict[str, int] = usage_report["variable_usage"] # type: ignore[assignment]
375
+ files_by_variable: Dict[str, List[str]] = usage_report["files_by_variable"] # type: ignore[assignment]
376
+ unsubstituted_variables: List[Dict[str, Any]] = usage_report["unsubstituted_variables"] # type: ignore[assignment]
377
+
378
+ if var_name not in variable_usage:
379
+ variable_usage[var_name] = 0
380
+ files_by_variable[var_name] = []
381
+
382
+ variable_usage[var_name] += len(matches)
383
+ files_by_variable[var_name].append(relative_path)
384
+
385
+ # Track unsubstituted variables
386
+ unsubstituted_variables.append(
387
+ {
388
+ "file": relative_path,
389
+ "variable": var_name,
390
+ "count": len(matches),
391
+ }
392
+ )
393
+
394
+ except (OSError, UnicodeDecodeError):
395
+ continue
396
+
397
+ except Exception as e:
398
+ usage_report["error"] = str(e)
399
+
400
+ return usage_report
401
+
402
+
403
+ def synchronize_template_variables(project_root: str, changed_config_path: Optional[str] = None) -> Dict[str, Any]:
404
+ """
405
+ Convenience function to synchronize template variables.
406
+
407
+ Args:
408
+ project_root: Root directory of the project
409
+ changed_config_path: Path to configuration file that changed
410
+
411
+ Returns:
412
+ Synchronization results
413
+ """
414
+ synchronizer = TemplateVariableSynchronizer(project_root)
415
+
416
+ config_path = Path(changed_config_path) if changed_config_path else None
417
+ return synchronizer.synchronize_after_config_change(config_path)