moai-adk 0.15.1__py3-none-any.whl → 0.25.4__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 (417) hide show
  1. moai_adk/__init__.py +1 -2
  2. moai_adk/__main__.py +85 -2
  3. moai_adk/cli/__init__.py +0 -1
  4. moai_adk/cli/commands/__init__.py +0 -1
  5. moai_adk/cli/commands/analyze.py +127 -0
  6. moai_adk/cli/commands/backup.py +5 -3
  7. moai_adk/cli/commands/doctor.py +35 -11
  8. moai_adk/cli/commands/improve_user_experience.py +348 -0
  9. moai_adk/cli/commands/init.py +150 -23
  10. moai_adk/cli/commands/language.py +269 -0
  11. moai_adk/cli/commands/migrate.py +158 -0
  12. moai_adk/cli/commands/status.py +13 -12
  13. moai_adk/cli/commands/update.py +364 -60
  14. moai_adk/cli/commands/validate_links.py +118 -0
  15. moai_adk/cli/main.py +3 -2
  16. moai_adk/cli/prompts/init_prompts.py +79 -82
  17. moai_adk/core/__init__.py +0 -1
  18. moai_adk/core/analysis/__init__.py +9 -0
  19. moai_adk/core/analysis/session_analyzer.py +439 -0
  20. moai_adk/core/claude_integration.py +421 -0
  21. moai_adk/core/command_helpers.py +270 -0
  22. moai_adk/core/config/__init__.py +6 -0
  23. moai_adk/core/config/auto_spec_config.py +346 -0
  24. moai_adk/core/config/migration.py +133 -12
  25. moai_adk/core/context_manager.py +279 -0
  26. moai_adk/core/diagnostics/slash_commands.py +0 -1
  27. moai_adk/core/error_recovery_system.py +1289 -0
  28. moai_adk/core/git/__init__.py +0 -1
  29. moai_adk/core/git/branch.py +0 -1
  30. moai_adk/core/git/branch_manager.py +4 -4
  31. moai_adk/core/git/checkpoint.py +1 -5
  32. moai_adk/core/git/commit.py +0 -1
  33. moai_adk/core/git/event_detector.py +3 -5
  34. moai_adk/core/git/manager.py +0 -1
  35. moai_adk/core/hooks/post_tool_auto_spec_completion.py +925 -0
  36. moai_adk/core/integration/__init__.py +22 -0
  37. moai_adk/core/integration/engine.py +169 -0
  38. moai_adk/core/integration/integration_tester.py +225 -0
  39. moai_adk/core/integration/models.py +88 -0
  40. moai_adk/core/integration/utils.py +211 -0
  41. moai_adk/core/issue_creator.py +28 -18
  42. moai_adk/core/language_config.py +202 -0
  43. moai_adk/core/language_validator.py +556 -0
  44. moai_adk/core/mcp/setup.py +113 -0
  45. moai_adk/core/migration/__init__.py +18 -0
  46. moai_adk/core/migration/backup_manager.py +208 -0
  47. moai_adk/core/migration/file_migrator.py +218 -0
  48. moai_adk/core/migration/version_detector.py +143 -0
  49. moai_adk/core/migration/version_migrator.py +228 -0
  50. moai_adk/core/performance/__init__.py +6 -0
  51. moai_adk/core/performance/cache_system.py +318 -0
  52. moai_adk/core/performance/parallel_processor.py +116 -0
  53. moai_adk/core/project/__init__.py +0 -1
  54. moai_adk/core/project/backup_utils.py +2 -7
  55. moai_adk/core/project/checker.py +3 -3
  56. moai_adk/core/project/detector.py +20 -40
  57. moai_adk/core/project/initializer.py +42 -17
  58. moai_adk/core/project/phase_executor.py +415 -58
  59. moai_adk/core/project/validator.py +6 -25
  60. moai_adk/core/quality/__init__.py +1 -1
  61. moai_adk/core/quality/trust_checker.py +64 -110
  62. moai_adk/core/quality/validators/__init__.py +1 -1
  63. moai_adk/core/quality/validators/base_validator.py +1 -1
  64. moai_adk/core/rollback_manager.py +993 -0
  65. moai_adk/core/session_manager.py +667 -0
  66. moai_adk/core/spec/confidence_scoring.py +749 -0
  67. moai_adk/core/spec/ears_template_engine.py +1182 -0
  68. moai_adk/core/spec/quality_validator.py +721 -0
  69. moai_adk/core/spec_status_manager.py +488 -0
  70. moai_adk/core/template/__init__.py +0 -1
  71. moai_adk/core/template/backup.py +41 -1
  72. moai_adk/core/template/config.py +11 -12
  73. moai_adk/core/template/languages.py +0 -1
  74. moai_adk/core/template/merger.py +79 -22
  75. moai_adk/core/template/processor.py +614 -40
  76. moai_adk/core/template_engine.py +36 -27
  77. moai_adk/foundation/git/commit_templates.py +565 -0
  78. moai_adk/foundation/trust/trust_principles.py +725 -0
  79. moai_adk/foundation/trust/validation_checklist.py +1678 -0
  80. moai_adk/statusline/__init__.py +38 -0
  81. moai_adk/statusline/alfred_detector.py +107 -0
  82. moai_adk/statusline/config.py +364 -0
  83. moai_adk/statusline/enhanced_output_style_detector.py +364 -0
  84. moai_adk/statusline/git_collector.py +190 -0
  85. moai_adk/statusline/main.py +228 -0
  86. moai_adk/statusline/metrics_tracker.py +78 -0
  87. moai_adk/statusline/renderer.py +327 -0
  88. moai_adk/statusline/update_checker.py +135 -0
  89. moai_adk/statusline/version_reader.py +647 -0
  90. moai_adk/templates/.git-hooks/pre-commit +66 -0
  91. moai_adk/templates/.git-hooks/pre-push +116 -4
  92. moai_adk/templates/.github/workflows/moai-gitflow.yml +1 -7
  93. moai_adk/templates/.github/workflows/spec-issue-sync.yml +0 -1
  94. moai_adk/templates/.gitignore +44 -0
  95. moai_adk/templates/.mcp.json +22 -0
  96. moai_adk/templates/CLAUDE.md +450 -1071
  97. moai_adk/utils/__init__.py +0 -1
  98. moai_adk/utils/banner.py +0 -1
  99. moai_adk/utils/common.py +308 -0
  100. moai_adk/utils/link_validator.py +249 -0
  101. moai_adk/utils/logger.py +4 -9
  102. moai_adk/utils/safe_file_reader.py +210 -0
  103. moai_adk/utils/user_experience.py +531 -0
  104. moai_adk-0.25.4.dist-info/METADATA +2279 -0
  105. moai_adk-0.25.4.dist-info/RECORD +112 -0
  106. moai_adk/core/tags/__init__.py +0 -86
  107. moai_adk/core/tags/ci_validator.py +0 -463
  108. moai_adk/core/tags/cli.py +0 -283
  109. moai_adk/core/tags/generator.py +0 -109
  110. moai_adk/core/tags/inserter.py +0 -99
  111. moai_adk/core/tags/mapper.py +0 -126
  112. moai_adk/core/tags/parser.py +0 -76
  113. moai_adk/core/tags/pre_commit_validator.py +0 -393
  114. moai_adk/core/tags/reporter.py +0 -956
  115. moai_adk/core/tags/tags.py +0 -149
  116. moai_adk/core/tags/validator.py +0 -897
  117. moai_adk/templates/.claude/agents/alfred/backend-expert.md +0 -319
  118. moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -316
  119. moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -208
  120. moai_adk/templates/.claude/agents/alfred/devops-expert.md +0 -464
  121. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -214
  122. moai_adk/templates/.claude/agents/alfred/frontend-expert.md +0 -357
  123. moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -406
  124. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -423
  125. moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -312
  126. moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -343
  127. moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -865
  128. moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -426
  129. moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -361
  130. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -428
  131. moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -375
  132. moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +0 -571
  133. moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1854
  134. moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -880
  135. moai_adk/templates/.claude/commands/alfred/2-run.md +0 -793
  136. moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -1084
  137. moai_adk/templates/.claude/commands/alfred/9-feedback.md +0 -149
  138. moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -748
  139. moai_adk/templates/.claude/hooks/alfred/core/timeout.py +0 -136
  140. moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +0 -108
  141. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +0 -198
  142. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -29
  143. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +0 -94
  144. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +0 -100
  145. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +0 -94
  146. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +0 -94
  147. moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +0 -170
  148. moai_adk/templates/.claude/hooks/alfred/shared/core/checkpoint.py +0 -271
  149. moai_adk/templates/.claude/hooks/alfred/shared/core/context.py +0 -67
  150. moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +0 -749
  151. moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +0 -230
  152. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +0 -198
  153. moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +0 -21
  154. moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +0 -154
  155. moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +0 -174
  156. moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +0 -87
  157. moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +0 -61
  158. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +0 -112
  159. moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +0 -1
  160. moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +0 -161
  161. moai_adk/templates/.claude/settings.json +0 -144
  162. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +0 -70
  163. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +0 -62
  164. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/reference.md +0 -242
  165. moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +0 -56
  166. moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +0 -28
  167. moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +0 -444
  168. moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +0 -62
  169. moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +0 -28
  170. moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +0 -405
  171. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +0 -51
  172. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +0 -355
  173. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +0 -239
  174. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
  175. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
  176. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
  177. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +0 -323
  178. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +0 -286
  179. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +0 -126
  180. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
  181. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
  182. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
  183. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +0 -74
  184. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +0 -4
  185. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +0 -269
  186. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
  187. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
  188. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
  189. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +0 -19
  190. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +0 -4
  191. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +0 -150
  192. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
  193. moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
  194. moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
  195. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +0 -198
  196. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +0 -431
  197. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +0 -141
  198. moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +0 -89
  199. moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +0 -122
  200. moai_adk/templates/.claude/skills/moai-alfred-practices/reference.md +0 -369
  201. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +0 -508
  202. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +0 -481
  203. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +0 -100
  204. moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +0 -273
  205. moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +0 -77
  206. moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +0 -265
  207. moai_adk/templates/.claude/skills/moai-alfred-rules/reference.md +0 -539
  208. moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +0 -19
  209. moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +0 -4
  210. moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +0 -84
  211. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +0 -137
  212. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +0 -219
  213. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples/validate-spec.sh +0 -161
  214. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +0 -541
  215. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +0 -622
  216. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +0 -115
  217. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +0 -4
  218. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +0 -348
  219. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
  220. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
  221. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
  222. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
  223. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
  224. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
  225. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +0 -19
  226. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +0 -4
  227. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +0 -211
  228. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
  229. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
  230. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
  231. moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +0 -288
  232. moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
  233. moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
  234. moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
  235. moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
  236. moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
  237. moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
  238. moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
  239. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
  240. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
  241. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
  242. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
  243. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
  244. moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
  245. moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
  246. moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
  247. moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
  248. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +0 -19
  249. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +0 -4
  250. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/reference.md +0 -218
  251. moai_adk/templates/.claude/skills/moai-cc-skill-factory/CHECKLIST.md +0 -482
  252. moai_adk/templates/.claude/skills/moai-cc-skill-factory/EXAMPLES.md +0 -278
  253. moai_adk/templates/.claude/skills/moai-cc-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
  254. moai_adk/templates/.claude/skills/moai-cc-skill-factory/METADATA.md +0 -477
  255. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
  256. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
  257. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
  258. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
  259. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL.md +0 -271
  260. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
  261. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STRUCTURE.md +0 -583
  262. moai_adk/templates/.claude/skills/moai-cc-skill-factory/WEB-RESEARCH.md +0 -526
  263. moai_adk/templates/.claude/skills/moai-cc-skill-factory/reference.md +0 -465
  264. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/generate-structure.sh +0 -328
  265. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/validate-skill.sh +0 -312
  266. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
  267. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/examples-template.md +0 -285
  268. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/reference-template.md +0 -278
  269. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/scripts-template.sh +0 -303
  270. moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
  271. moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
  272. moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +0 -802
  273. moai_adk/templates/.claude/skills/moai-design-systems/examples.md +0 -1238
  274. moai_adk/templates/.claude/skills/moai-design-systems/reference.md +0 -673
  275. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +0 -290
  276. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +0 -1633
  277. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +0 -660
  278. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
  279. moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
  280. moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
  281. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
  282. moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
  283. moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
  284. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +0 -123
  285. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +0 -29
  286. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +0 -30
  287. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
  288. moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
  289. moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
  290. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +0 -128
  291. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +0 -29
  292. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +0 -31
  293. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
  294. moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
  295. moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
  296. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
  297. moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
  298. moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
  299. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
  300. moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
  301. moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
  302. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
  303. moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
  304. moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
  305. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
  306. moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
  307. moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
  308. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
  309. moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
  310. moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
  311. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
  312. moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
  313. moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
  314. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
  315. moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
  316. moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
  317. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -116
  318. moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
  319. moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
  320. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
  321. moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
  322. moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
  323. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
  324. moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
  325. moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
  326. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
  327. moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
  328. moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
  329. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
  330. moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
  331. moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
  332. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
  333. moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
  334. moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
  335. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
  336. moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
  337. moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
  338. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +0 -124
  339. moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
  340. moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
  341. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +0 -123
  342. moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
  343. moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
  344. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
  345. moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
  346. moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
  347. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +0 -127
  348. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +0 -29
  349. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +0 -31
  350. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +0 -126
  351. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +0 -29
  352. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +0 -31
  353. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
  354. moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
  355. moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
  356. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +0 -124
  357. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +0 -29
  358. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +0 -31
  359. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +0 -126
  360. moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
  361. moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
  362. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +0 -433
  363. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +0 -624
  364. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +0 -316
  365. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +0 -123
  366. moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
  367. moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
  368. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +0 -124
  369. moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
  370. moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
  371. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +0 -127
  372. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +0 -29
  373. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +0 -31
  374. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +0 -125
  375. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +0 -29
  376. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +0 -30
  377. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
  378. moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
  379. moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
  380. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
  381. moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
  382. moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
  383. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +0 -123
  384. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +0 -29
  385. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +0 -30
  386. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +0 -133
  387. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +0 -29
  388. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +0 -34
  389. moai_adk/templates/.claude/skills/moai-project-documentation.md +0 -622
  390. moai_adk/templates/.github/workflows/c-tag-validation.yml +0 -11
  391. moai_adk/templates/.github/workflows/cpp-tag-validation.yml +0 -11
  392. moai_adk/templates/.github/workflows/csharp-tag-validation.yml +0 -11
  393. moai_adk/templates/.github/workflows/dart-tag-validation.yml +0 -11
  394. moai_adk/templates/.github/workflows/go-tag-validation.yml +0 -130
  395. moai_adk/templates/.github/workflows/java-tag-validation.yml +0 -11
  396. moai_adk/templates/.github/workflows/javascript-tag-validation.yml +0 -135
  397. moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +0 -11
  398. moai_adk/templates/.github/workflows/php-tag-validation.yml +0 -11
  399. moai_adk/templates/.github/workflows/python-tag-validation.yml +0 -118
  400. moai_adk/templates/.github/workflows/release.yml +0 -118
  401. moai_adk/templates/.github/workflows/ruby-tag-validation.yml +0 -11
  402. moai_adk/templates/.github/workflows/rust-tag-validation.yml +0 -11
  403. moai_adk/templates/.github/workflows/shell-tag-validation.yml +0 -11
  404. moai_adk/templates/.github/workflows/swift-tag-validation.yml +0 -11
  405. moai_adk/templates/.github/workflows/tag-report.yml +0 -269
  406. moai_adk/templates/.github/workflows/tag-validation.yml +0 -186
  407. moai_adk/templates/.github/workflows/typescript-tag-validation.yml +0 -154
  408. moai_adk/templates/.moai/config.json +0 -115
  409. moai_adk/templates/workflows/go-tag-validation.yml +0 -30
  410. moai_adk/templates/workflows/javascript-tag-validation.yml +0 -41
  411. moai_adk/templates/workflows/python-tag-validation.yml +0 -42
  412. moai_adk/templates/workflows/typescript-tag-validation.yml +0 -31
  413. moai_adk-0.15.1.dist-info/METADATA +0 -3094
  414. moai_adk-0.15.1.dist-info/RECORD +0 -365
  415. {moai_adk-0.15.1.dist-info → moai_adk-0.25.4.dist-info}/WHEEL +0 -0
  416. {moai_adk-0.15.1.dist-info → moai_adk-0.25.4.dist-info}/entry_points.txt +0 -0
  417. {moai_adk-0.15.1.dist-info → moai_adk-0.25.4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,993 @@
1
+ """
2
+ Rollback Manager for Research Integration Changes
3
+
4
+ Provides comprehensive rollback system for:
5
+ - Configuration backup and restore
6
+ - Version management
7
+ - Safe rollback procedures
8
+ - Integration with existing MoAI-ADK backup systems
9
+ - Research-specific rollback operations
10
+
11
+ Supports:
12
+ - Full system rollback
13
+ - Component-specific rollback
14
+ - Incremental rollback
15
+ - Emergency rollback
16
+ - Rollback validation and verification
17
+ """
18
+
19
+ import hashlib
20
+ import json
21
+ import logging
22
+ import os
23
+ import shutil
24
+ import sys
25
+ from dataclasses import asdict, dataclass
26
+ from datetime import datetime, timezone
27
+ from pathlib import Path
28
+ from typing import Any, Dict, List, Tuple
29
+
30
+ # Configure logging
31
+ logging.basicConfig(level=logging.INFO)
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ @dataclass
36
+ class RollbackPoint:
37
+ """Represents a rollback point with metadata"""
38
+
39
+ id: str
40
+ timestamp: datetime
41
+ description: str
42
+ changes: List[str]
43
+ backup_path: str
44
+ checksum: str
45
+ metadata: Dict[str, Any]
46
+
47
+
48
+ @dataclass
49
+ class RollbackResult:
50
+ """Result of a rollback operation"""
51
+
52
+ success: bool
53
+ rollback_point_id: str
54
+ message: str
55
+ restored_files: List[str]
56
+ failed_files: List[str] = None
57
+ validation_results: Dict[str, Any] = None
58
+
59
+
60
+ class RollbackManager:
61
+ """Comprehensive rollback management system"""
62
+
63
+ def __init__(self, project_root: Path = None):
64
+ self.project_root = project_root or Path.cwd()
65
+ self.backup_root = self.project_root / ".moai" / "rollbacks"
66
+ self.config_backup_dir = self.backup_root / "config"
67
+ self.code_backup_dir = self.backup_root / "code"
68
+ self.docs_backup_dir = self.backup_root / "docs"
69
+ self.registry_file = self.backup_root / "rollback_registry.json"
70
+
71
+ # Create backup directories
72
+ self.backup_root.mkdir(parents=True, exist_ok=True)
73
+ self.config_backup_dir.mkdir(parents=True, exist_ok=True)
74
+ self.code_backup_dir.mkdir(parents=True, exist_ok=True)
75
+ self.docs_backup_dir.mkdir(parents=True, exist_ok=True)
76
+
77
+ # Load existing registry
78
+ self.registry = self._load_registry()
79
+
80
+ # Research-specific paths
81
+ self.research_dirs = [
82
+ self.project_root / ".claude" / "skills",
83
+ self.project_root / ".claude" / "agents",
84
+ self.project_root / ".claude" / "commands",
85
+ self.project_root / ".claude" / "hooks",
86
+ ]
87
+
88
+ def create_rollback_point(self, description: str, changes: List[str] = None) -> str:
89
+ """
90
+ Create a rollback point before making changes
91
+
92
+ Args:
93
+ description: Description of the changes being made
94
+ changes: List of specific changes (files modified, components updated)
95
+
96
+ Returns:
97
+ Rollback point ID
98
+ """
99
+ rollback_id = self._generate_rollback_id()
100
+ timestamp = datetime.now(timezone.utc)
101
+
102
+ logger.info(f"Creating rollback point {rollback_id}: {description}")
103
+
104
+ try:
105
+ # Create backup directory for this rollback point
106
+ rollback_dir = self.backup_root / rollback_id
107
+ rollback_dir.mkdir(parents=True, exist_ok=True)
108
+
109
+ # Backup configuration files
110
+ config_backup_path = self._backup_configuration(rollback_dir)
111
+
112
+ # Backup research components
113
+ research_backup_path = self._backup_research_components(rollback_dir)
114
+
115
+ # Backup project files
116
+ code_backup_path = self._backup_code_files(rollback_dir)
117
+
118
+ # Create checksum for integrity verification
119
+ checksum = self._calculate_backup_checksum(rollback_dir)
120
+
121
+ # Create rollback point record
122
+ rollback_point = RollbackPoint(
123
+ id=rollback_id,
124
+ timestamp=timestamp,
125
+ description=description,
126
+ changes=changes or [],
127
+ backup_path=str(rollback_dir),
128
+ checksum=checksum,
129
+ metadata={
130
+ "config_backup": config_backup_path,
131
+ "research_backup": research_backup_path,
132
+ "code_backup": code_backup_path,
133
+ "project_root": str(self.project_root),
134
+ "created_by": "rollback_manager",
135
+ "version": "1.0.0",
136
+ },
137
+ )
138
+
139
+ # Register rollback point
140
+ self.registry[rollback_id] = asdict(rollback_point)
141
+ self._save_registry()
142
+
143
+ logger.info(f"Rollback point {rollback_id} created successfully")
144
+ return rollback_id
145
+
146
+ except Exception as e:
147
+ logger.error(f"Failed to create rollback point: {str(e)}")
148
+ # Cleanup partial backup
149
+ self._cleanup_partial_backup(rollback_id)
150
+ raise
151
+
152
+ def rollback_to_point(
153
+ self,
154
+ rollback_id: str,
155
+ validate_before: bool = True,
156
+ validate_after: bool = True,
157
+ ) -> RollbackResult:
158
+ """
159
+ Rollback to a specific rollback point
160
+
161
+ Args:
162
+ rollback_id: ID of rollback point to restore
163
+ validate_before: Validate rollback point before restoration
164
+ validate_after: Validate system after restoration
165
+
166
+ Returns:
167
+ RollbackResult with operation details
168
+ """
169
+ if rollback_id not in self.registry:
170
+ return RollbackResult(
171
+ success=False,
172
+ rollback_point_id=rollback_id,
173
+ message=f"Rollback point {rollback_id} not found",
174
+ restored_files=[],
175
+ )
176
+
177
+ logger.info(f"Rolling back to point {rollback_id}")
178
+
179
+ try:
180
+ rollback_point = RollbackPoint(**self.registry[rollback_id])
181
+
182
+ # Pre-rollback validation
183
+ if validate_before:
184
+ validation_result = self._validate_rollback_point(rollback_point)
185
+ if not validation_result["valid"]:
186
+ return RollbackResult(
187
+ success=False,
188
+ rollback_point_id=rollback_id,
189
+ message=f"Rollback point validation failed: {validation_result['message']}",
190
+ restored_files=[],
191
+ )
192
+
193
+ # Perform rollback
194
+ restored_files, failed_files = self._perform_rollback(rollback_point)
195
+
196
+ # Post-rollback validation
197
+ validation_results = {}
198
+ if validate_after:
199
+ validation_results = self._validate_system_after_rollback()
200
+
201
+ # Update registry with rollback info
202
+ self._mark_rollback_as_used(rollback_id)
203
+
204
+ success = len(failed_files) == 0
205
+
206
+ result = RollbackResult(
207
+ success=success,
208
+ rollback_point_id=rollback_id,
209
+ message=f"Rollback {'completed successfully' if success else 'completed with errors'}",
210
+ restored_files=restored_files,
211
+ failed_files=failed_files or [],
212
+ validation_results=validation_results,
213
+ )
214
+
215
+ logger.info(f"Rollback {rollback_id} completed. Success: {success}")
216
+ return result
217
+
218
+ except Exception as e:
219
+ logger.error(f"Rollback failed: {str(e)}")
220
+ return RollbackResult(
221
+ success=False,
222
+ rollback_point_id=rollback_id,
223
+ message=f"Rollback failed with error: {str(e)}",
224
+ restored_files=[],
225
+ )
226
+
227
+ def rollback_research_integration(
228
+ self, component_type: str = None, component_name: str = None
229
+ ) -> RollbackResult:
230
+ """
231
+ Specialized rollback for research integration changes
232
+
233
+ Args:
234
+ component_type: Type of component (skills, agents, commands, hooks)
235
+ component_name: Specific component name to rollback
236
+
237
+ Returns:
238
+ RollbackResult with operation details
239
+ """
240
+ logger.info(
241
+ f"Rolling back research integration: {component_type}:{component_name}"
242
+ )
243
+
244
+ try:
245
+ # Find relevant rollback points for research integration
246
+ research_rollback_points = self._find_research_rollback_points(
247
+ component_type, component_name
248
+ )
249
+
250
+ if not research_rollback_points:
251
+ return RollbackResult(
252
+ success=False,
253
+ rollback_point_id="",
254
+ message="No suitable rollback points found for research integration",
255
+ restored_files=[],
256
+ )
257
+
258
+ # Use the most recent suitable rollback point
259
+ latest_rollback = max(
260
+ research_rollback_points, key=lambda x: x["timestamp"]
261
+ )
262
+
263
+ # Perform targeted rollback
264
+ restored_files, failed_files = self._perform_research_rollback(
265
+ latest_rollback, component_type, component_name
266
+ )
267
+
268
+ # Validate research components
269
+ validation_results = self._validate_research_components()
270
+
271
+ success = len(failed_files) == 0
272
+
273
+ return RollbackResult(
274
+ success=success,
275
+ rollback_point_id=latest_rollback["id"],
276
+ message=f"Research integration rollback {'completed successfully' if success else 'completed with errors'}",
277
+ restored_files=restored_files,
278
+ failed_files=failed_files or [],
279
+ validation_results=validation_results,
280
+ )
281
+
282
+ except Exception as e:
283
+ logger.error(f"Research integration rollback failed: {str(e)}")
284
+ return RollbackResult(
285
+ success=False,
286
+ rollback_point_id="",
287
+ message=f"Research integration rollback failed: {str(e)}",
288
+ restored_files=[],
289
+ )
290
+
291
+ def list_rollback_points(self, limit: int = 10) -> List[Dict[str, Any]]:
292
+ """
293
+ List available rollback points
294
+
295
+ Args:
296
+ limit: Maximum number of rollback points to return
297
+
298
+ Returns:
299
+ List of rollback point information
300
+ """
301
+ rollback_points = []
302
+
303
+ for rollback_id, rollback_data in self.registry.items():
304
+ rollback_points.append(
305
+ {
306
+ "id": rollback_id,
307
+ "timestamp": rollback_data["timestamp"],
308
+ "description": rollback_data["description"],
309
+ "changes_count": len(rollback_data.get("changes", [])),
310
+ "used": rollback_data.get("used", False),
311
+ }
312
+ )
313
+
314
+ # Sort by timestamp (newest first) and limit
315
+ rollback_points.sort(key=lambda x: x["timestamp"], reverse=True)
316
+ return rollback_points[:limit]
317
+
318
+ def validate_rollback_system(self) -> Dict[str, Any]:
319
+ """
320
+ Validate the rollback system integrity
321
+
322
+ Returns:
323
+ Validation results with system health information
324
+ """
325
+ validation_results = {
326
+ "system_healthy": True,
327
+ "issues": [],
328
+ "recommendations": [],
329
+ "rollback_points_count": len(self.registry),
330
+ "backup_size": self._calculate_backup_size(),
331
+ "last_rollback": None,
332
+ }
333
+
334
+ try:
335
+ # Check backup directories exist
336
+ required_dirs = [
337
+ self.backup_root,
338
+ self.config_backup_dir,
339
+ self.code_backup_dir,
340
+ self.docs_backup_dir,
341
+ ]
342
+
343
+ for dir_path in required_dirs:
344
+ if not dir_path.exists():
345
+ validation_results["issues"].append(
346
+ f"Missing backup directory: {dir_path}"
347
+ )
348
+ validation_results["system_healthy"] = False
349
+
350
+ # Validate rollback points
351
+ invalid_rollback_points = []
352
+ for rollback_id, rollback_data in self.registry.items():
353
+ backup_path = Path(rollback_data["backup_path"])
354
+ if not backup_path.exists():
355
+ invalid_rollback_points.append(rollback_id)
356
+
357
+ if invalid_rollback_points:
358
+ validation_results["issues"].append(
359
+ f"Invalid rollback points: {invalid_rollback_points}"
360
+ )
361
+ validation_results["system_healthy"] = False
362
+
363
+ # Check available disk space
364
+ backup_size = validation_results["backup_size"]
365
+ free_space = shutil.disk_usage(self.backup_root).free
366
+ if backup_size > free_space * 0.8: # Using more than 80% of free space
367
+ validation_results["recommendations"].append(
368
+ "Consider cleaning up old rollback points"
369
+ )
370
+
371
+ # Check last rollback
372
+ if self.registry:
373
+ last_rollback = max(
374
+ self.registry.values(), key=lambda x: x["timestamp"]
375
+ )
376
+ validation_results["last_rollback"] = last_rollback["timestamp"]
377
+
378
+ except Exception as e:
379
+ validation_results["system_healthy"] = False
380
+ validation_results["issues"].append(f"Validation error: {str(e)}")
381
+
382
+ return validation_results
383
+
384
+ def cleanup_old_rollbacks(
385
+ self, keep_count: int = 10, dry_run: bool = True
386
+ ) -> Dict[str, Any]:
387
+ """
388
+ Clean up old rollback points
389
+
390
+ Args:
391
+ keep_count: Number of recent rollback points to keep
392
+ dry_run: If True, only show what would be deleted
393
+
394
+ Returns:
395
+ Cleanup operation results
396
+ """
397
+ rollback_points = list(self.registry.values())
398
+ rollback_points.sort(key=lambda x: x["timestamp"], reverse=True)
399
+
400
+ # Keep the most recent rollback points
401
+ to_keep = rollback_points[:keep_count]
402
+ to_delete = rollback_points[keep_count:]
403
+
404
+ if dry_run:
405
+ return {
406
+ "dry_run": True,
407
+ "would_delete_count": len(to_delete),
408
+ "would_keep_count": len(to_keep),
409
+ "would_free_space": sum(
410
+ self._get_directory_size(Path(rp["backup_path"]))
411
+ for rp in to_delete
412
+ ),
413
+ }
414
+
415
+ # Perform actual cleanup
416
+ deleted_count = 0
417
+ freed_space = 0
418
+
419
+ for rollback_point in to_delete:
420
+ try:
421
+ backup_path = Path(rollback_point["backup_path"])
422
+ if backup_path.exists():
423
+ size = self._get_directory_size(backup_path)
424
+ shutil.rmtree(backup_path)
425
+ freed_space += size
426
+
427
+ # Remove from registry
428
+ del self.registry[rollback_point["id"]]
429
+ deleted_count += 1
430
+
431
+ except Exception as e:
432
+ logger.warning(
433
+ f"Failed to delete rollback point {rollback_point['id']}: {str(e)}"
434
+ )
435
+
436
+ # Save updated registry
437
+ self._save_registry()
438
+
439
+ return {
440
+ "dry_run": False,
441
+ "deleted_count": deleted_count,
442
+ "kept_count": len(to_keep),
443
+ "freed_space": freed_space,
444
+ }
445
+
446
+ def _generate_rollback_id(self) -> str:
447
+ """Generate unique rollback point ID"""
448
+ timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
449
+ random_suffix = hashlib.md5(os.urandom(4)).hexdigest()[:8]
450
+ return f"rollback_{timestamp}_{random_suffix}"
451
+
452
+ def _load_registry(self) -> Dict[str, Any]:
453
+ """Load rollback registry from file"""
454
+ if self.registry_file.exists():
455
+ try:
456
+ with open(self.registry_file, "r") as f:
457
+ return json.load(f)
458
+ except Exception as e:
459
+ logger.warning(f"Failed to load rollback registry: {str(e)}")
460
+
461
+ return {}
462
+
463
+ def _save_registry(self):
464
+ """Save rollback registry to file"""
465
+ try:
466
+ with open(self.registry_file, "w") as f:
467
+ json.dump(self.registry, f, indent=2, default=str)
468
+ except Exception as e:
469
+ logger.error(f"Failed to save rollback registry: {str(e)}")
470
+ raise
471
+
472
+ def _backup_configuration(self, rollback_dir: Path) -> str:
473
+ """Backup configuration files"""
474
+ config_backup_path = rollback_dir / "config"
475
+ config_backup_path.mkdir(parents=True, exist_ok=True)
476
+
477
+ # Backup .moai/config/config.json
478
+ config_file = self.project_root / ".moai" / "config" / "config.json"
479
+ if config_file.exists():
480
+ shutil.copy2(config_file, config_backup_path / "config.json")
481
+
482
+ # Backup .claude/settings.json
483
+ settings_file = self.project_root / ".claude" / "settings.json"
484
+ if settings_file.exists():
485
+ shutil.copy2(settings_file, config_backup_path / "settings.json")
486
+
487
+ # Backup .claude/settings.local.json
488
+ local_settings_file = self.project_root / ".claude" / "settings.local.json"
489
+ if local_settings_file.exists():
490
+ shutil.copy2(
491
+ local_settings_file, config_backup_path / "settings.local.json"
492
+ )
493
+
494
+ return str(config_backup_path)
495
+
496
+ def _backup_research_components(self, rollback_dir: Path) -> str:
497
+ """Backup research-specific components"""
498
+ research_backup_path = rollback_dir / "research"
499
+ research_backup_path.mkdir(parents=True, exist_ok=True)
500
+
501
+ for research_dir in self.research_dirs:
502
+ if research_dir.exists():
503
+ dir_name = research_dir.name
504
+ target_dir = research_backup_path / dir_name
505
+ shutil.copytree(research_dir, target_dir, dirs_exist_ok=True)
506
+
507
+ return str(research_backup_path)
508
+
509
+ def _backup_code_files(self, rollback_dir: Path) -> str:
510
+ """Backup important code files"""
511
+ code_backup_path = rollback_dir / "code"
512
+ code_backup_path.mkdir(parents=True, exist_ok=True)
513
+
514
+ # Backup source code
515
+ src_dir = self.project_root / "src"
516
+ if src_dir.exists():
517
+ shutil.copytree(src_dir, code_backup_path / "src", dirs_exist_ok=True)
518
+
519
+ # Backup tests
520
+ tests_dir = self.project_root / "tests"
521
+ if tests_dir.exists():
522
+ shutil.copytree(tests_dir, code_backup_path / "tests", dirs_exist_ok=True)
523
+
524
+ # Backup documentation
525
+ docs_dir = self.project_root / "docs"
526
+ if docs_dir.exists():
527
+ shutil.copytree(docs_dir, code_backup_path / "docs", dirs_exist_ok=True)
528
+
529
+ return str(code_backup_path)
530
+
531
+ def _calculate_backup_checksum(self, backup_dir: Path) -> str:
532
+ """Calculate checksum for backup integrity verification"""
533
+ checksum_hash = hashlib.sha256()
534
+
535
+ for file_path in backup_dir.rglob("*"):
536
+ if file_path.is_file():
537
+ with open(file_path, "rb") as f:
538
+ # Update hash with file content and path
539
+ checksum_hash.update(f.read())
540
+ checksum_hash.update(
541
+ str(file_path.relative_to(backup_dir)).encode()
542
+ )
543
+
544
+ return checksum_hash.hexdigest()
545
+
546
+ def _validate_rollback_point(self, rollback_point: RollbackPoint) -> Dict[str, Any]:
547
+ """Validate rollback point before restoration"""
548
+ validation_result = {
549
+ "valid": True,
550
+ "message": "Rollback point is valid",
551
+ "warnings": [],
552
+ }
553
+
554
+ try:
555
+ # Check backup directory exists
556
+ backup_path = Path(rollback_point.backup_path)
557
+ if not backup_path.exists():
558
+ validation_result["valid"] = False
559
+ validation_result["message"] = "Backup directory not found"
560
+ return validation_result
561
+
562
+ # Verify checksum
563
+ current_checksum = self._calculate_backup_checksum(backup_path)
564
+ if current_checksum != rollback_point.checksum:
565
+ validation_result["warnings"].append(
566
+ "Backup checksum mismatch - possible corruption"
567
+ )
568
+
569
+ # Check essential files exist
570
+ required_files = [
571
+ backup_path / "config" / "config.json",
572
+ backup_path / "research",
573
+ ]
574
+
575
+ missing_files = [f for f in required_files if not f.exists()]
576
+ if missing_files:
577
+ validation_result["warnings"].append(
578
+ f"Missing backup files: {missing_files}"
579
+ )
580
+
581
+ except Exception as e:
582
+ validation_result["valid"] = False
583
+ validation_result["message"] = f"Validation error: {str(e)}"
584
+
585
+ return validation_result
586
+
587
+ def _perform_rollback(
588
+ self, rollback_point: RollbackPoint
589
+ ) -> Tuple[List[str], List[str]]:
590
+ """Perform the actual rollback operation"""
591
+ backup_path = Path(rollback_point.backup_path)
592
+ restored_files = []
593
+ failed_files = []
594
+
595
+ try:
596
+ # Restore configuration
597
+ config_backup = backup_path / "config"
598
+ if config_backup.exists():
599
+ for config_file in config_backup.rglob("*"):
600
+ if config_file.is_file():
601
+ target_path = (
602
+ self.project_root
603
+ / ".moai"
604
+ / config_file.relative_to(config_backup)
605
+ )
606
+ target_path.parent.mkdir(parents=True, exist_ok=True)
607
+ try:
608
+ shutil.copy2(config_file, target_path)
609
+ restored_files.append(str(target_path))
610
+ except Exception as e:
611
+ failed_files.append((str(target_path), str(e)))
612
+
613
+ # Restore research components
614
+ research_backup = backup_path / "research"
615
+ if research_backup.exists():
616
+ for research_file in research_backup.rglob("*"):
617
+ if research_file.is_file():
618
+ target_path = self.project_root / research_file.relative_to(
619
+ research_backup
620
+ )
621
+ target_path.parent.mkdir(parents=True, exist_ok=True)
622
+ try:
623
+ shutil.copy2(research_file, target_path)
624
+ restored_files.append(str(target_path))
625
+ except Exception as e:
626
+ failed_files.append((str(target_path), str(e)))
627
+
628
+ # Restore code files
629
+ code_backup = backup_path / "code"
630
+ if code_backup.exists():
631
+ for code_file in code_backup.rglob("*"):
632
+ if code_file.is_file():
633
+ target_path = self.project_root / code_file.relative_to(
634
+ code_backup
635
+ )
636
+ target_path.parent.mkdir(parents=True, exist_ok=True)
637
+ try:
638
+ shutil.copy2(code_file, target_path)
639
+ restored_files.append(str(target_path))
640
+ except Exception as e:
641
+ failed_files.append((str(target_path), str(e)))
642
+
643
+ except Exception as e:
644
+ logger.error(f"Rollback operation failed: {str(e)}")
645
+ failed_files.append(("rollback_operation", str(e)))
646
+
647
+ return restored_files, failed_files
648
+
649
+ def _perform_research_rollback(
650
+ self,
651
+ rollback_point: Dict[str, Any],
652
+ component_type: str = None,
653
+ component_name: str = None,
654
+ ) -> Tuple[List[str], List[str]]:
655
+ """Perform targeted research component rollback"""
656
+ backup_path = Path(rollback_point["backup_path"])
657
+ research_backup = backup_path / "research"
658
+
659
+ restored_files = []
660
+ failed_files = []
661
+
662
+ if not research_backup.exists():
663
+ failed_files.append(("research_backup", "Research backup not found"))
664
+ return restored_files, failed_files
665
+
666
+ try:
667
+ # Restore specific component or all research components
668
+ if component_type:
669
+ component_backup_dir = research_backup / component_type
670
+ if component_backup_dir.exists():
671
+ target_dir = self.project_root / ".claude" / component_type
672
+
673
+ if component_name:
674
+ # Restore specific component
675
+ component_file = component_backup_dir / f"{component_name}.md"
676
+ if component_file.exists():
677
+ target_file = target_dir / f"{component_name}.md"
678
+ target_file.parent.mkdir(parents=True, exist_ok=True)
679
+ shutil.copy2(component_file, target_file)
680
+ restored_files.append(str(target_file))
681
+ else:
682
+ failed_files.append(
683
+ (component_name, "Component file not found in backup")
684
+ )
685
+ else:
686
+ # Restore entire component type
687
+ if target_dir.exists():
688
+ shutil.rmtree(target_dir)
689
+ shutil.copytree(component_backup_dir, target_dir)
690
+ restored_files.append(str(target_dir))
691
+ else:
692
+ failed_files.append(
693
+ (component_type, "Component type not found in backup")
694
+ )
695
+ else:
696
+ # Restore all research components
697
+ for research_dir in research_backup.iterdir():
698
+ if research_dir.is_dir():
699
+ target_dir = self.project_root / ".claude" / research_dir.name
700
+ if target_dir.exists():
701
+ shutil.rmtree(target_dir)
702
+ shutil.copytree(research_dir, target_dir)
703
+ restored_files.append(str(target_dir))
704
+
705
+ except Exception as e:
706
+ logger.error(f"Research rollback failed: {str(e)}")
707
+ failed_files.append(("research_rollback", str(e)))
708
+
709
+ return restored_files, failed_files
710
+
711
+ def _validate_system_after_rollback(self) -> Dict[str, Any]:
712
+ """Validate system state after rollback"""
713
+ validation_results = {
714
+ "config_valid": True,
715
+ "research_valid": True,
716
+ "issues": [],
717
+ }
718
+
719
+ try:
720
+ # Validate configuration
721
+ config_file = self.project_root / ".moai" / "config" / "config.json"
722
+ if config_file.exists():
723
+ try:
724
+ with open(config_file, "r") as f:
725
+ json.load(f) # Validate JSON syntax
726
+ except json.JSONDecodeError:
727
+ validation_results["config_valid"] = False
728
+ validation_results["issues"].append("Invalid JSON in config.json")
729
+ else:
730
+ validation_results["config_valid"] = False
731
+ validation_results["issues"].append("config.json not found")
732
+
733
+ # Validate research components
734
+ for research_dir in self.research_dirs:
735
+ if research_dir.exists():
736
+ # Check for readable files
737
+ for file_path in research_dir.rglob("*.md"):
738
+ try:
739
+ with open(file_path, "r", encoding="utf-8") as f:
740
+ f.read() # Validate file can be read
741
+ except Exception as e:
742
+ validation_results["research_valid"] = False
743
+ validation_results["issues"].append(
744
+ f"Cannot read {file_path}: {str(e)}"
745
+ )
746
+
747
+ except Exception as e:
748
+ validation_results["issues"].append(f"Validation error: {str(e)}")
749
+
750
+ return validation_results
751
+
752
+ def _validate_research_components(self) -> Dict[str, Any]:
753
+ """Validate research components after rollback"""
754
+ validation_results = {
755
+ "skills_valid": True,
756
+ "agents_valid": True,
757
+ "commands_valid": True,
758
+ "hooks_valid": True,
759
+ "issues": [],
760
+ }
761
+
762
+ component_checks = [
763
+ ("skills", "Skills", self.project_root / ".claude" / "skills"),
764
+ ("agents", "Agents", self.project_root / ".claude" / "agents"),
765
+ ("commands", "Commands", self.project_root / ".claude" / "commands"),
766
+ ("hooks", "Hooks", self.project_root / ".claude" / "hooks"),
767
+ ]
768
+
769
+ for component_key, component_name, component_path in component_checks:
770
+ if component_path.exists():
771
+ # Check component structure
772
+ files = list(component_path.rglob("*.md"))
773
+ if not files:
774
+ validation_results[f"{component_key}_valid"] = False
775
+ validation_results["issues"].append(
776
+ f"{component_name} directory is empty"
777
+ )
778
+
779
+ # Validate file content
780
+ for file_path in files[:5]: # Check first 5 files
781
+ try:
782
+ with open(file_path, "r", encoding="utf-8") as f:
783
+ content = f.read()
784
+ if not content.strip():
785
+ validation_results[f"{component_key}_valid"] = False
786
+ validation_results["issues"].append(
787
+ f"Empty file: {file_path}"
788
+ )
789
+ except Exception as e:
790
+ validation_results[f"{component_key}_valid"] = False
791
+ validation_results["issues"].append(
792
+ f"Cannot read {file_path}: {str(e)}"
793
+ )
794
+ else:
795
+ validation_results[f"{component_key}_valid"] = False
796
+ validation_results["issues"].append(
797
+ f"{component_name} directory not found"
798
+ )
799
+
800
+ return validation_results
801
+
802
+ def _find_research_rollback_points(
803
+ self, component_type: str = None, component_name: str = None
804
+ ) -> List[Dict[str, Any]]:
805
+ """Find rollback points related to research integration"""
806
+ research_rollback_points = []
807
+
808
+ for rollback_id, rollback_data in self.registry.items():
809
+ # Check if rollback point has research backup
810
+ backup_path = Path(rollback_data["backup_path"])
811
+ research_backup = backup_path / "research"
812
+
813
+ if not research_backup.exists():
814
+ continue
815
+
816
+ # Check for specific component match
817
+ if component_type:
818
+ component_backup = research_backup / component_type
819
+ if component_backup.exists():
820
+ if component_name:
821
+ component_file = component_backup / f"{component_name}.md"
822
+ if component_file.exists():
823
+ research_rollback_points.append(rollback_data)
824
+ else:
825
+ research_rollback_points.append(rollback_data)
826
+ else:
827
+ # Include any rollback with research components
828
+ research_rollback_points.append(rollback_data)
829
+
830
+ return research_rollback_points
831
+
832
+ def _mark_rollback_as_used(self, rollback_id: str):
833
+ """Mark rollback point as used in registry"""
834
+ if rollback_id in self.registry:
835
+ self.registry[rollback_id]["used"] = True
836
+ self.registry[rollback_id]["used_timestamp"] = datetime.now(
837
+ timezone.utc
838
+ ).isoformat()
839
+ self._save_registry()
840
+
841
+ def _cleanup_partial_backup(self, rollback_id: str):
842
+ """Clean up partial backup if creation failed"""
843
+ try:
844
+ backup_dir = self.backup_root / rollback_id
845
+ if backup_dir.exists():
846
+ shutil.rmtree(backup_dir)
847
+ except Exception as e:
848
+ logger.warning(f"Failed to cleanup partial backup {rollback_id}: {str(e)}")
849
+
850
+ def _calculate_backup_size(self) -> int:
851
+ """Calculate total size of all backups"""
852
+ total_size = 0
853
+ for rollback_id, rollback_data in self.registry.items():
854
+ backup_path = Path(rollback_data["backup_path"])
855
+ if backup_path.exists():
856
+ total_size += self._get_directory_size(backup_path)
857
+ return total_size
858
+
859
+ def _get_directory_size(self, directory: Path) -> int:
860
+ """Get total size of directory in bytes"""
861
+ total_size = 0
862
+ try:
863
+ for file_path in directory.rglob("*"):
864
+ if file_path.is_file():
865
+ total_size += file_path.stat().st_size
866
+ except Exception:
867
+ pass # Ignore errors in size calculation
868
+ return total_size
869
+
870
+
871
+ # Command-line interface for rollback manager
872
+ def main():
873
+ """Command-line interface for rollback operations"""
874
+ import argparse
875
+
876
+ parser = argparse.ArgumentParser(description="MoAI-ADK Rollback Manager")
877
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
878
+
879
+ # Create rollback point
880
+ create_parser = subparsers.add_parser("create", help="Create rollback point")
881
+ create_parser.add_argument("description", help="Description of changes")
882
+ create_parser.add_argument("--changes", nargs="*", help="List of changes")
883
+
884
+ # List rollback points
885
+ list_parser = subparsers.add_parser("list", help="List rollback points")
886
+ list_parser.add_argument(
887
+ "--limit", type=int, default=10, help="Maximum number to show"
888
+ )
889
+
890
+ # Perform rollback
891
+ rollback_parser = subparsers.add_parser("rollback", help="Rollback to point")
892
+ rollback_parser.add_argument("rollback_id", help="Rollback point ID")
893
+ rollback_parser.add_argument(
894
+ "--no-validate", action="store_true", help="Skip validation"
895
+ )
896
+
897
+ # Research rollback
898
+ research_parser = subparsers.add_parser(
899
+ "research-rollback", help="Rollback research components"
900
+ )
901
+ research_parser.add_argument(
902
+ "--type", help="Component type (skills, agents, commands, hooks)"
903
+ )
904
+ research_parser.add_argument("--name", help="Component name")
905
+
906
+ # Validate system
907
+ validate_parser = subparsers.add_parser("validate", help="Validate rollback system")
908
+
909
+ # Cleanup
910
+ cleanup_parser = subparsers.add_parser(
911
+ "cleanup", help="Cleanup old rollback points"
912
+ )
913
+ cleanup_parser.add_argument("--keep", type=int, default=10, help="Number to keep")
914
+ cleanup_parser.add_argument(
915
+ "--execute", action="store_true", help="Execute cleanup (default: dry run)"
916
+ )
917
+
918
+ args = parser.parse_args()
919
+
920
+ if not args.command:
921
+ parser.print_help()
922
+ return
923
+
924
+ # Initialize rollback manager
925
+ rollback_manager = RollbackManager()
926
+
927
+ try:
928
+ if args.command == "create":
929
+ rollback_id = rollback_manager.create_rollback_point(
930
+ args.description, args.changes
931
+ )
932
+ print(f"Rollback point created: {rollback_id}")
933
+
934
+ elif args.command == "list":
935
+ rollback_points = rollback_manager.list_rollback_points(args.limit)
936
+ print(f"Available rollback points (showing {len(rollback_points)}):")
937
+ for rp in rollback_points:
938
+ status = "USED" if rp["used"] else "AVAILABLE"
939
+ print(f" {rp['id']} - {rp['description']} ({status})")
940
+
941
+ elif args.command == "rollback":
942
+ result = rollback_manager.rollback_to_point(
943
+ args.rollback_id, validate_before=not args.no_validate
944
+ )
945
+ if result.success:
946
+ print("Rollback completed successfully")
947
+ print(f"Restored {len(result.restored_files)} files")
948
+ else:
949
+ print(f"Rollback failed: {result.message}")
950
+
951
+ elif args.command == "research-rollback":
952
+ result = rollback_manager.rollback_research_integration(
953
+ args.type, args.name
954
+ )
955
+ if result.success:
956
+ print("Research rollback completed successfully")
957
+ else:
958
+ print(f"Research rollback failed: {result.message}")
959
+
960
+ elif args.command == "validate":
961
+ validation = rollback_manager.validate_rollback_system()
962
+ print(
963
+ f"Rollback system health: {'HEALTHY' if validation['system_healthy'] else 'UNHEALTHY'}"
964
+ )
965
+ if validation["issues"]:
966
+ print("Issues found:")
967
+ for issue in validation["issues"]:
968
+ print(f" - {issue}")
969
+ if validation["recommendations"]:
970
+ print("Recommendations:")
971
+ for rec in validation["recommendations"]:
972
+ print(f" - {rec}")
973
+
974
+ elif args.command == "cleanup":
975
+ result = rollback_manager.cleanup_old_rollback_points(
976
+ args.keep, dry_run=not args.execute
977
+ )
978
+ if result["dry_run"]:
979
+ print(
980
+ f"Dry run: Would delete {result['would_delete_count']} rollback points"
981
+ )
982
+ print(f"Would free {result['would_free_space'] / 1024 / 1024:.1f} MB")
983
+ else:
984
+ print(f"Deleted {result['deleted_count']} rollback points")
985
+ print(f"Freed {result['freed_space'] / 1024 / 1024:.1f} MB")
986
+
987
+ except Exception as e:
988
+ print(f"Error: {str(e)}")
989
+ sys.exit(1)
990
+
991
+
992
+ if __name__ == "__main__":
993
+ main()