moai-adk 0.4.5__py3-none-any.whl â 0.20.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +1 -1
- moai_adk/__main__.py +74 -1
- moai_adk/cli/commands/__init__.py +1 -1
- moai_adk/cli/commands/analyze.py +119 -0
- moai_adk/cli/commands/backup.py +25 -1
- moai_adk/cli/commands/doctor.py +31 -5
- moai_adk/cli/commands/improve_user_experience.py +307 -0
- moai_adk/cli/commands/init.py +111 -10
- moai_adk/cli/commands/status.py +33 -3
- moai_adk/cli/commands/update.py +921 -130
- moai_adk/cli/commands/validate_links.py +120 -0
- moai_adk/cli/prompts/init_prompts.py +22 -87
- moai_adk/core/analysis/__init__.py +9 -0
- moai_adk/core/analysis/session_analyzer.py +388 -0
- moai_adk/core/analysis/tag_chain_analyzer.py +344 -0
- moai_adk/core/analysis/tag_chain_repair.py +879 -0
- moai_adk/core/config/__init__.py +19 -0
- moai_adk/core/config/migration.py +235 -0
- moai_adk/core/git/__init__.py +1 -1
- moai_adk/core/git/branch.py +1 -1
- moai_adk/core/git/commit.py +1 -1
- moai_adk/core/git/manager.py +1 -1
- moai_adk/core/issue_creator.py +313 -0
- moai_adk/core/mcp/setup.py +56 -0
- moai_adk/core/mcp/setup_old.py +296 -0
- moai_adk/core/project/backup_utils.py +1 -1
- moai_adk/core/project/checker.py +2 -2
- moai_adk/core/project/detector.py +211 -12
- moai_adk/core/project/initializer.py +85 -15
- moai_adk/core/project/phase_executor.py +76 -13
- moai_adk/core/project/validator.py +13 -13
- moai_adk/core/quality/__init__.py +1 -1
- moai_adk/core/quality/trust_checker.py +1 -1
- moai_adk/core/quality/validators/__init__.py +1 -1
- moai_adk/core/quality/validators/base_validator.py +1 -1
- moai_adk/core/tags/__init__.py +86 -0
- moai_adk/core/tags/auto_corrector.py +693 -0
- moai_adk/core/tags/ci_validator.py +463 -0
- moai_adk/core/tags/cli.py +283 -0
- moai_adk/core/tags/generator.py +109 -0
- moai_adk/core/tags/inserter.py +99 -0
- moai_adk/core/tags/mapper.py +126 -0
- moai_adk/core/tags/parser.py +76 -0
- moai_adk/core/tags/policy_validator.py +580 -0
- moai_adk/core/tags/pre_commit_validator.py +421 -0
- moai_adk/core/tags/reporter.py +956 -0
- moai_adk/core/tags/rollback_manager.py +525 -0
- moai_adk/core/tags/tags.py +149 -0
- moai_adk/core/tags/validator.py +897 -0
- moai_adk/core/template/__init__.py +1 -1
- moai_adk/core/template/backup.py +1 -1
- moai_adk/core/template/merger.py +50 -1
- moai_adk/core/template/processor.py +119 -13
- moai_adk/core/template_engine.py +268 -0
- moai_adk/templates/.claude/agents/alfred/backend-expert.md +348 -0
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +209 -944
- moai_adk/templates/.claude/agents/alfred/database-expert.md +352 -0
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +34 -5
- moai_adk/templates/.claude/agents/alfred/devops-expert.md +464 -0
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +38 -8
- moai_adk/templates/.claude/agents/alfred/format-expert.md +469 -0
- moai_adk/templates/.claude/agents/alfred/frontend-expert.md +357 -0
- moai_adk/templates/.claude/agents/alfred/git-manager.md +128 -9
- moai_adk/templates/.claude/agents/alfred/implementation-planner.md +104 -6
- moai_adk/templates/.claude/agents/alfred/project-manager.md +88 -16
- moai_adk/templates/.claude/agents/alfred/quality-gate.md +36 -9
- moai_adk/templates/.claude/agents/alfred/security-expert.md +270 -0
- moai_adk/templates/.claude/agents/alfred/skill-factory.md +865 -0
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +214 -43
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +111 -9
- moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +309 -160
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +36 -7
- moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +605 -0
- moai_adk/templates/.claude/commands/alfred/0-project.md +393 -966
- moai_adk/templates/.claude/commands/alfred/1-plan.md +651 -367
- moai_adk/templates/.claude/commands/alfred/2-run.md +388 -241
- moai_adk/templates/.claude/commands/alfred/3-sync.md +1921 -410
- moai_adk/templates/.claude/commands/alfred/9-feedback.md +153 -0
- moai_adk/templates/.claude/commands/alfred/release-new.md +3604 -0
- moai_adk/templates/.claude/hooks/alfred/core/project.py +484 -20
- moai_adk/templates/.claude/hooks/alfred/core/timeout.py +136 -0
- moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +108 -0
- moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +198 -0
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +14 -6
- moai_adk/templates/.claude/hooks/alfred/post_tool__enable_streaming_ui.py +50 -0
- moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +93 -0
- moai_adk/templates/.claude/hooks/alfred/post_tool__tag_auto_corrector.py +407 -0
- moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +99 -0
- moai_adk/templates/.claude/hooks/alfred/pre_tool__realtime_tag_monitor.py +335 -0
- moai_adk/templates/.claude/hooks/alfred/pre_tool__tag_policy_validator.py +325 -0
- moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +93 -0
- moai_adk/templates/.claude/hooks/alfred/session_start__auto_cleanup.py +580 -0
- moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +298 -0
- moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +170 -0
- moai_adk/templates/.claude/hooks/alfred/{core â shared/core}/checkpoint.py +3 -3
- moai_adk/templates/.claude/hooks/alfred/{core â shared/core}/context.py +5 -5
- moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +749 -0
- moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +230 -0
- moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +198 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +21 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/daily_analysis.py +351 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +154 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +174 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +87 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +61 -0
- moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +111 -0
- moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +1 -0
- moai_adk/templates/.claude/hooks/alfred/utils/hook_config.py +94 -0
- moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +161 -0
- moai_adk/templates/.claude/output-styles/alfred/alfred-moai-adk-beginner.md +267 -0
- moai_adk/templates/.claude/output-styles/alfred/keating-personal-tutor.md +440 -0
- moai_adk/templates/.claude/output-styles/alfred/r2d2-agentic-coding.md +583 -0
- moai_adk/templates/.claude/settings.json +96 -14
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +70 -0
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +62 -0
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/reference.md +242 -0
- moai_adk/templates/.claude/skills/moai-alfred-ask-user-questions/SKILL.md +237 -0
- moai_adk/templates/.claude/skills/moai-alfred-ask-user-questions/examples.md +871 -0
- moai_adk/templates/.claude/skills/moai-alfred-ask-user-questions/reference.md +653 -0
- moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/README.md +162 -0
- moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/SKILL.md +227 -0
- moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/examples.md +354 -0
- moai_adk/templates/.claude/skills/moai-alfred-clone-pattern/reference.md +158 -0
- moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/SKILL.md +179 -79
- moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/examples.md +117 -0
- moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/scripts/pre-review-check.sh +62 -0
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +132 -0
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +28 -0
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +444 -0
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +62 -0
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +28 -0
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +405 -0
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +51 -0
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +355 -0
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +239 -0
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +323 -0
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +286 -0
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +126 -0
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +229 -0
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +150 -0
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +87 -73
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-alfred-personas/README.md +42 -0
- moai_adk/templates/.claude/skills/moai-alfred-personas/SKILL.md +429 -0
- moai_adk/templates/.claude/skills/moai-alfred-personas/examples.md +520 -0
- moai_adk/templates/.claude/skills/moai-alfred-personas/reference.md +405 -0
- moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +89 -0
- moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +122 -0
- moai_adk/templates/.claude/skills/moai-alfred-practices/reference.md +369 -0
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +508 -0
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +481 -0
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +100 -0
- moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +77 -0
- moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +265 -0
- moai_adk/templates/.claude/skills/moai-alfred-rules/reference.md +539 -0
- moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +320 -0
- moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +84 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +137 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +219 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples/validate-spec.sh +161 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +541 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +622 -0
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +19 -0
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +211 -0
- moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +288 -0
- moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +269 -0
- moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +32 -0
- moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +298 -0
- moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +26 -0
- moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +307 -0
- moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +21 -0
- moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +252 -0
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +19 -0
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +19 -0
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +24 -0
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +199 -0
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +39 -0
- moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +316 -0
- moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +18 -0
- moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +263 -0
- moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +30 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/CHECKLIST.md +482 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/EXAMPLES.md +303 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/INTERACTIVE-DISCOVERY.md +524 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/METADATA.md +477 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/PARALLEL-ANALYSIS-REPORT.md +429 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/PYTHON-VERSION-MATRIX.md +391 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-FACTORY-WORKFLOW.md +431 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-UPDATE-ADVISOR.md +577 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL.md +273 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/STEP-BY-STEP-GUIDE.md +466 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/STRUCTURE.md +583 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/WEB-RESEARCH.md +526 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/reference.md +608 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/generate-structure.sh +328 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/validate-skill.sh +312 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/SKILL_TEMPLATE.md +245 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/examples-template.md +285 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/reference-template.md +278 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/scripts-template.sh +303 -0
- moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +291 -0
- moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +15 -0
- moai_adk/templates/.claude/skills/moai-change-logger/SKILL.md +563 -0
- moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +802 -0
- moai_adk/templates/.claude/skills/moai-design-systems/examples.md +1238 -0
- moai_adk/templates/.claude/skills/moai-design-systems/reference.md +673 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +234 -43
- moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +1633 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +660 -0
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +97 -69
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +97 -72
- moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +97 -74
- moai_adk/templates/.claude/skills/moai-domain-database/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-database/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +98 -74
- moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +102 -73
- moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +97 -73
- moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +97 -67
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +97 -79
- moai_adk/templates/.claude/skills/moai-domain-security/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-security/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +97 -71
- moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +265 -64
- moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +1064 -0
- moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +1047 -0
- moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +87 -78
- moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +87 -70
- moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +87 -86
- moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +80 -62
- moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +207 -50
- moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +29 -0
- moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +90 -71
- moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +78 -58
- moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +78 -51
- moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +28 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/.!11330!examples.md +0 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +253 -32
- moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +1099 -0
- moai_adk/templates/.claude/skills/moai-jit-docs-enhanced/SKILL.md +460 -0
- moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +98 -74
- moai_adk/templates/.claude/skills/moai-lang-c/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-c/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +98 -76
- moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +2358 -70
- moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +2962 -68
- moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +1898 -70
- moai_adk/templates/.claude/skills/moai-lang-go/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-go/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +1465 -68
- moai_adk/templates/.claude/skills/moai-lang-java/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-java/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +2364 -66
- moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +32 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +1630 -69
- moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +89 -61
- moai_adk/templates/.claude/skills/moai-lang-php/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-php/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +735 -66
- moai_adk/templates/.claude/skills/moai-lang-python/examples.md +624 -0
- moai_adk/templates/.claude/skills/moai-lang-python/reference.md +316 -0
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +97 -73
- moai_adk/templates/.claude/skills/moai-lang-r/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-r/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +98 -73
- moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +1834 -70
- moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +99 -74
- moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +97 -74
- moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +98 -74
- moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +31 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +1959 -69
- moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +30 -0
- moai_adk/templates/.claude/skills/moai-lang-template/SKILL.md +348 -0
- moai_adk/templates/.claude/skills/moai-lang-template/VARIABLES.md +98 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +1230 -66
- moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +29 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +34 -0
- moai_adk/templates/.claude/skills/moai-learning-optimizer/SKILL.md +575 -0
- moai_adk/templates/.claude/skills/moai-project-batch-questions/README.md +50 -0
- moai_adk/templates/.claude/skills/moai-project-batch-questions/SKILL.md +304 -0
- moai_adk/templates/.claude/skills/moai-project-batch-questions/examples.md +417 -0
- moai_adk/templates/.claude/skills/moai-project-batch-questions/reference.md +704 -0
- moai_adk/templates/.claude/skills/moai-project-config-manager/README.md +87 -0
- moai_adk/templates/.claude/skills/moai-project-config-manager/SKILL.md +552 -0
- moai_adk/templates/.claude/skills/moai-project-config-manager/examples.md +1109 -0
- moai_adk/templates/.claude/skills/moai-project-config-manager/reference.md +514 -0
- moai_adk/templates/.claude/skills/moai-project-config-manager/validate.py +106 -0
- moai_adk/templates/.claude/skills/moai-project-documentation/README.md +11 -0
- moai_adk/templates/.claude/skills/moai-project-documentation/SKILL.md +622 -0
- moai_adk/templates/.claude/skills/moai-project-documentation/examples.md +20 -0
- moai_adk/templates/.claude/skills/moai-project-documentation/reference.md +12 -0
- moai_adk/templates/.claude/skills/moai-project-language-initializer/README.md +152 -0
- moai_adk/templates/.claude/skills/moai-project-language-initializer/SKILL.md +285 -0
- moai_adk/templates/.claude/skills/moai-project-language-initializer/examples.md +333 -0
- moai_adk/templates/.claude/skills/moai-project-language-initializer/reference.md +386 -0
- moai_adk/templates/.claude/skills/moai-project-template-optimizer/README.md +49 -0
- moai_adk/templates/.claude/skills/moai-project-template-optimizer/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-project-template-optimizer/examples.md +58 -0
- moai_adk/templates/.claude/skills/moai-project-template-optimizer/reference.md +123 -0
- moai_adk/templates/.claude/skills/moai-session-info/SKILL.md +314 -0
- moai_adk/templates/.claude/skills/moai-streaming-ui/SKILL.md +552 -0
- moai_adk/templates/.claude/skills/moai-tag-policy-validator/SKILL.md +570 -0
- moai_adk/templates/.git-hooks/pre-commit +66 -0
- moai_adk/templates/.git-hooks/pre-push +255 -0
- moai_adk/templates/.github/workflows/c-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/cpp-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/csharp-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/dart-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/go-tag-validation.yml +130 -0
- moai_adk/templates/.github/workflows/java-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/javascript-tag-validation.yml +135 -0
- moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/moai-gitflow.yml +166 -3
- moai_adk/templates/.github/workflows/moai-release-create.yml +100 -0
- moai_adk/templates/.github/workflows/moai-release-pipeline.yml +188 -0
- moai_adk/templates/.github/workflows/php-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/python-tag-validation.yml +118 -0
- moai_adk/templates/.github/workflows/release.yml +118 -0
- moai_adk/templates/.github/workflows/ruby-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/rust-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/shell-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +338 -0
- moai_adk/templates/.github/workflows/swift-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/tag-report.yml +269 -0
- moai_adk/templates/.github/workflows/tag-validation.yml +186 -0
- moai_adk/templates/.github/workflows/typescript-tag-validation.yml +154 -0
- moai_adk/templates/.mcp.json +31 -0
- moai_adk/templates/.moai/config.json +80 -7
- moai_adk/templates/CLAUDE.md +562 -546
- moai_adk/utils/banner.py +5 -5
- moai_adk/utils/common.py +294 -0
- moai_adk/utils/link_validator.py +235 -0
- moai_adk/utils/logger.py +8 -8
- moai_adk/utils/user_experience.py +451 -0
- moai_adk-0.20.1.dist-info/METADATA +233 -0
- moai_adk-0.20.1.dist-info/RECORD +404 -0
- moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -156
- moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -85
- moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
- moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -92
- moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -70
- moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -41
- moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -636
- moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -692
- moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -470
- moai_adk/templates/.claude/skills/moai-alfred-debugger-pro/SKILL.md +0 -103
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -103
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -95
- moai_adk/templates/.claude/skills/moai-alfred-performance-optimizer/SKILL.md +0 -105
- moai_adk/templates/.claude/skills/moai-alfred-refactoring-coach/SKILL.md +0 -97
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -97
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -90
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -99
- moai_adk/templates/.claude/skills/moai-alfred-tui-survey/SKILL.md +0 -87
- moai_adk/templates/.claude/skills/moai-alfred-tui-survey/examples.md +0 -62
- moai_adk/templates/.claude/skills/moai-claude-code/SKILL.md +0 -94
- moai_adk/templates/.claude/skills/moai-claude-code/examples.md +0 -513
- moai_adk/templates/.claude/skills/moai-claude-code/reference.md +0 -433
- moai_adk/templates/.claude/skills/moai-claude-code/templates/agent-full.md +0 -332
- moai_adk/templates/.claude/skills/moai-claude-code/templates/command-full.md +0 -384
- moai_adk/templates/.claude/skills/moai-claude-code/templates/plugin-full.json +0 -363
- moai_adk/templates/.claude/skills/moai-claude-code/templates/settings-full.json +0 -595
- moai_adk/templates/.claude/skills/moai-claude-code/templates/skill-full.md +0 -496
- moai_adk/templates/.claude/skills/moai-lang-clojure/SKILL.md +0 -100
- moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +0 -99
- moai_adk/templates/.claude/skills/moai-lang-haskell/SKILL.md +0 -100
- moai_adk/templates/.claude/skills/moai-lang-julia/SKILL.md +0 -98
- moai_adk/templates/.claude/skills/moai-lang-lua/SKILL.md +0 -98
- moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
- moai_adk/templates/.moai/memory/development-guide.md +0 -344
- moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
- moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
- moai_adk/templates/.moai/project/product.md +0 -161
- moai_adk/templates/.moai/project/structure.md +0 -156
- moai_adk/templates/.moai/project/tech.md +0 -227
- moai_adk/templates/__init__.py +0 -2
- moai_adk-0.4.5.dist-info/METADATA +0 -369
- moai_adk-0.4.5.dist-info/RECORD +0 -152
- {moai_adk-0.4.5.dist-info â moai_adk-0.20.1.dist-info}/WHEEL +0 -0
- {moai_adk-0.4.5.dist-info â moai_adk-0.20.1.dist-info}/entry_points.txt +0 -0
- {moai_adk-0.4.5.dist-info â moai_adk-0.20.1.dist-info}/licenses/LICENSE +0 -0
moai_adk/cli/commands/update.py
CHANGED
|
@@ -1,7 +1,48 @@
|
|
|
1
|
-
"""Update command
|
|
1
|
+
"""Update command
|
|
2
|
+
|
|
3
|
+
Update MoAI-ADK to the latest version available on PyPI with 3-stage workflow:
|
|
4
|
+
- Stage 1: Package version check (PyPI vs current)
|
|
5
|
+
- Stage 2: Config version comparison (template_version in config.json)
|
|
6
|
+
- Stage 3: Template sync (only if versions differ)
|
|
7
|
+
|
|
8
|
+
Includes:
|
|
9
|
+
- Automatic installer detection (uv tool, pipx, pip)
|
|
10
|
+
- Package upgrade with intelligent re-run prompts
|
|
11
|
+
- Template and configuration updates with performance optimization
|
|
12
|
+
- Backward compatibility validation
|
|
13
|
+
- 70-80% performance improvement for up-to-date projects
|
|
14
|
+
|
|
15
|
+
## Skill Invocation Guide (English-Only)
|
|
16
|
+
|
|
17
|
+
### Related Skills
|
|
18
|
+
- **moai-foundation-trust**: For post-update validation
|
|
19
|
+
- Trigger: After updating MoAI-ADK version
|
|
20
|
+
- Invocation: `Skill("moai-foundation-trust")` to verify all toolchains still work
|
|
21
|
+
|
|
22
|
+
- **moai-foundation-langs**: For language detection after update
|
|
23
|
+
- Trigger: After updating, confirm language stack is intact
|
|
24
|
+
- Invocation: `Skill("moai-foundation-langs")` to re-detect and validate language configuration
|
|
25
|
+
|
|
26
|
+
### When to Invoke Skills in Related Workflows
|
|
27
|
+
1. **After successful update**:
|
|
28
|
+
- Run `Skill("moai-foundation-trust")` to validate all TRUST 5 gates
|
|
29
|
+
- Run `Skill("moai-foundation-langs")` to confirm language toolchain still works
|
|
30
|
+
- Run project doctor command for full system validation
|
|
31
|
+
|
|
32
|
+
2. **Before updating**:
|
|
33
|
+
- Create backup with `python -m moai_adk backup`
|
|
34
|
+
- Run `Skill("moai-foundation-tags")` to document current TAG state
|
|
35
|
+
|
|
36
|
+
3. **If update fails**:
|
|
37
|
+
- Use backup to restore previous state
|
|
38
|
+
- Debug with `python -m moai_adk doctor --verbose`
|
|
39
|
+
"""
|
|
40
|
+
|
|
2
41
|
from __future__ import annotations
|
|
3
42
|
|
|
4
43
|
import json
|
|
44
|
+
import logging
|
|
45
|
+
import subprocess
|
|
5
46
|
from datetime import datetime
|
|
6
47
|
from pathlib import Path
|
|
7
48
|
from typing import Any, cast
|
|
@@ -14,13 +55,153 @@ from moai_adk import __version__
|
|
|
14
55
|
from moai_adk.core.template.processor import TemplateProcessor
|
|
15
56
|
|
|
16
57
|
console = Console()
|
|
58
|
+
logger = logging.getLogger(__name__)
|
|
17
59
|
|
|
60
|
+
# Constants for tool detection
|
|
61
|
+
TOOL_DETECTION_TIMEOUT = 5 # seconds
|
|
62
|
+
UV_TOOL_COMMAND = ["uv", "tool", "upgrade", "moai-adk"]
|
|
63
|
+
PIPX_COMMAND = ["pipx", "upgrade", "moai-adk"]
|
|
64
|
+
PIP_COMMAND = ["pip", "install", "--upgrade", "moai-adk"]
|
|
18
65
|
|
|
19
|
-
|
|
20
|
-
|
|
66
|
+
|
|
67
|
+
# @CODE:UPDATE-TEMPLATE-004
|
|
68
|
+
# Custom exceptions for better error handling
|
|
69
|
+
class UpdateError(Exception):
|
|
70
|
+
"""Base exception for update operations."""
|
|
71
|
+
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class InstallerNotFoundError(UpdateError):
|
|
76
|
+
"""Raised when no package installer detected."""
|
|
77
|
+
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class NetworkError(UpdateError):
|
|
82
|
+
"""Raised when network operation fails."""
|
|
83
|
+
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class UpgradeError(UpdateError):
|
|
88
|
+
"""Raised when package upgrade fails."""
|
|
89
|
+
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TemplateSyncError(UpdateError):
|
|
94
|
+
"""Raised when template sync fails."""
|
|
95
|
+
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _is_installed_via_uv_tool() -> bool:
|
|
100
|
+
"""Check if moai-adk installed via uv tool.
|
|
21
101
|
|
|
22
102
|
Returns:
|
|
23
|
-
|
|
103
|
+
True if uv tool list shows moai-adk, False otherwise
|
|
104
|
+
"""
|
|
105
|
+
try:
|
|
106
|
+
result = subprocess.run(
|
|
107
|
+
["uv", "tool", "list"], capture_output=True, text=True, timeout=TOOL_DETECTION_TIMEOUT, check=False
|
|
108
|
+
)
|
|
109
|
+
return result.returncode == 0 and "moai-adk" in result.stdout
|
|
110
|
+
except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _is_installed_via_pipx() -> bool:
|
|
115
|
+
"""Check if moai-adk installed via pipx.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
True if pipx list shows moai-adk, False otherwise
|
|
119
|
+
"""
|
|
120
|
+
try:
|
|
121
|
+
result = subprocess.run(
|
|
122
|
+
["pipx", "list"], capture_output=True, text=True, timeout=TOOL_DETECTION_TIMEOUT, check=False
|
|
123
|
+
)
|
|
124
|
+
return result.returncode == 0 and "moai-adk" in result.stdout
|
|
125
|
+
except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _is_installed_via_pip() -> bool:
|
|
130
|
+
"""Check if moai-adk installed via pip.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
True if pip show finds moai-adk, False otherwise
|
|
134
|
+
"""
|
|
135
|
+
try:
|
|
136
|
+
result = subprocess.run(
|
|
137
|
+
["pip", "show", "moai-adk"], capture_output=True, text=True, timeout=TOOL_DETECTION_TIMEOUT, check=False
|
|
138
|
+
)
|
|
139
|
+
return result.returncode == 0
|
|
140
|
+
except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
|
|
141
|
+
return False
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# @CODE:UPDATE-CONTEXT-001
|
|
145
|
+
def _detect_tool_installer() -> list[str] | None:
|
|
146
|
+
"""Detect which tool installed moai-adk.
|
|
147
|
+
|
|
148
|
+
Checks in priority order:
|
|
149
|
+
1. uv tool (most likely for MoAI-ADK users)
|
|
150
|
+
2. pipx
|
|
151
|
+
3. pip (fallback)
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Command list [tool, ...args] ready for subprocess.run()
|
|
155
|
+
or None if detection fails
|
|
156
|
+
|
|
157
|
+
Examples:
|
|
158
|
+
>>> # If uv tool is detected:
|
|
159
|
+
>>> _detect_tool_installer()
|
|
160
|
+
['uv', 'tool', 'upgrade', 'moai-adk']
|
|
161
|
+
|
|
162
|
+
>>> # If pipx is detected:
|
|
163
|
+
>>> _detect_tool_installer()
|
|
164
|
+
['pipx', 'upgrade', 'moai-adk']
|
|
165
|
+
|
|
166
|
+
>>> # If only pip is available:
|
|
167
|
+
>>> _detect_tool_installer()
|
|
168
|
+
['pip', 'install', '--upgrade', 'moai-adk']
|
|
169
|
+
|
|
170
|
+
>>> # If none are detected:
|
|
171
|
+
>>> _detect_tool_installer()
|
|
172
|
+
None
|
|
173
|
+
"""
|
|
174
|
+
if _is_installed_via_uv_tool():
|
|
175
|
+
return UV_TOOL_COMMAND
|
|
176
|
+
elif _is_installed_via_pipx():
|
|
177
|
+
return PIPX_COMMAND
|
|
178
|
+
elif _is_installed_via_pip():
|
|
179
|
+
return PIP_COMMAND
|
|
180
|
+
else:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# @CODE:UPDATE-VERSION-002
|
|
185
|
+
def _get_current_version() -> str:
|
|
186
|
+
"""Get currently installed moai-adk version.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
Version string (e.g., "0.6.1")
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
RuntimeError: If version cannot be determined
|
|
193
|
+
"""
|
|
194
|
+
return __version__
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _get_latest_version() -> str:
|
|
198
|
+
"""Fetch latest moai-adk version from PyPI.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Version string (e.g., "0.6.2")
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
RuntimeError: If PyPI API unavailable or parsing fails
|
|
24
205
|
"""
|
|
25
206
|
try:
|
|
26
207
|
import urllib.error
|
|
@@ -29,10 +210,387 @@ def get_latest_version() -> str | None:
|
|
|
29
210
|
url = "https://pypi.org/pypi/moai-adk/json"
|
|
30
211
|
with urllib.request.urlopen(url, timeout=5) as response: # nosec B310 - URL is hardcoded HTTPS to PyPI API, no user input
|
|
31
212
|
data = json.loads(response.read().decode("utf-8"))
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
213
|
+
return cast(str, data["info"]["version"])
|
|
214
|
+
except (urllib.error.URLError, json.JSONDecodeError, KeyError, TimeoutError) as e:
|
|
215
|
+
raise RuntimeError(f"Failed to fetch latest version from PyPI: {e}") from e
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _compare_versions(current: str, latest: str) -> int:
|
|
219
|
+
"""Compare semantic versions.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
current: Current version string
|
|
223
|
+
latest: Latest version string
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
-1 if current < latest (upgrade needed)
|
|
227
|
+
0 if current == latest (up to date)
|
|
228
|
+
1 if current > latest (unusual, already newer)
|
|
229
|
+
"""
|
|
230
|
+
current_v = version.parse(current)
|
|
231
|
+
latest_v = version.parse(latest)
|
|
232
|
+
|
|
233
|
+
if current_v < latest_v:
|
|
234
|
+
return -1
|
|
235
|
+
elif current_v == latest_v:
|
|
236
|
+
return 0
|
|
237
|
+
else:
|
|
238
|
+
return 1
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# @CODE:UPDATE-SYNC-006
|
|
242
|
+
def _get_package_config_version() -> str:
|
|
243
|
+
"""Get the current package template version.
|
|
244
|
+
|
|
245
|
+
This returns the version of the currently installed moai-adk package,
|
|
246
|
+
which is the version of templates that this package provides.
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Version string of the installed package (e.g., "0.6.1")
|
|
250
|
+
"""
|
|
251
|
+
# Package template version = current installed package version
|
|
252
|
+
# This is simple and reliable since templates are versioned with the package
|
|
253
|
+
return __version__
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
# @CODE:UPDATE-PACKAGE-007
|
|
257
|
+
def _get_project_config_version(project_path: Path) -> str:
|
|
258
|
+
"""Get current project config.json template version.
|
|
259
|
+
|
|
260
|
+
This reads the project's .moai/config.json to determine the current
|
|
261
|
+
template version that the project is configured with.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
project_path: Project directory path (absolute)
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Version string from project's config.json (e.g., "0.6.1")
|
|
268
|
+
Returns "0.0.0" if template_version field not found (indicates no prior sync)
|
|
269
|
+
|
|
270
|
+
Raises:
|
|
271
|
+
ValueError: If config.json exists but cannot be parsed
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
def _is_placeholder(value: str) -> bool:
|
|
275
|
+
"""Check if value contains unsubstituted template placeholders."""
|
|
276
|
+
return isinstance(value, str) and value.startswith("{{") and value.endswith("}}")
|
|
277
|
+
|
|
278
|
+
config_path = project_path / ".moai" / "config.json"
|
|
279
|
+
|
|
280
|
+
if not config_path.exists():
|
|
281
|
+
# No config yet, treat as version 0.0.0 (needs initial sync)
|
|
282
|
+
return "0.0.0"
|
|
283
|
+
|
|
284
|
+
try:
|
|
285
|
+
config_data = json.loads(config_path.read_text(encoding="utf-8"))
|
|
286
|
+
# Check for template_version in project section
|
|
287
|
+
template_version = config_data.get("project", {}).get("template_version")
|
|
288
|
+
if template_version and not _is_placeholder(template_version):
|
|
289
|
+
return template_version
|
|
290
|
+
|
|
291
|
+
# Fallback to moai version if no template_version exists
|
|
292
|
+
moai_version = config_data.get("moai", {}).get("version")
|
|
293
|
+
if moai_version and not _is_placeholder(moai_version):
|
|
294
|
+
return moai_version
|
|
295
|
+
|
|
296
|
+
# If values are placeholders or don't exist, treat as uninitialized (0.0.0 triggers sync)
|
|
297
|
+
return "0.0.0"
|
|
298
|
+
except json.JSONDecodeError as e:
|
|
299
|
+
raise ValueError(f"Failed to parse project config.json: {e}") from e
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
# @CODE:UPDATE-CACHE-001
|
|
303
|
+
def _detect_stale_cache(upgrade_output: str, current_version: str, latest_version: str) -> bool:
|
|
304
|
+
"""
|
|
305
|
+
Detect if uv cache is stale by comparing versions.
|
|
306
|
+
|
|
307
|
+
A stale cache occurs when PyPI metadata is outdated, causing uv to incorrectly
|
|
308
|
+
report "Nothing to upgrade" even though a newer version exists. This function
|
|
309
|
+
detects this condition by:
|
|
310
|
+
1. Checking if upgrade output contains "Nothing to upgrade"
|
|
311
|
+
2. Verifying that latest version is actually newer than current version
|
|
312
|
+
|
|
313
|
+
Uses packaging.version.parse() for robust semantic version comparison that
|
|
314
|
+
handles pre-releases, dev versions, and other PEP 440 version formats correctly.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
upgrade_output: Output from uv tool upgrade command
|
|
318
|
+
current_version: Currently installed version (string, e.g., "0.8.3")
|
|
319
|
+
latest_version: Latest version available on PyPI (string, e.g., "0.9.0")
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
True if cache is stale (output shows "Nothing to upgrade" but current < latest),
|
|
323
|
+
False otherwise
|
|
324
|
+
|
|
325
|
+
Examples:
|
|
326
|
+
>>> _detect_stale_cache("Nothing to upgrade", "0.8.3", "0.9.0")
|
|
327
|
+
True
|
|
328
|
+
>>> _detect_stale_cache("Updated moai-adk", "0.8.3", "0.9.0")
|
|
329
|
+
False
|
|
330
|
+
>>> _detect_stale_cache("Nothing to upgrade", "0.9.0", "0.9.0")
|
|
331
|
+
False
|
|
332
|
+
"""
|
|
333
|
+
# Check if output indicates no upgrade needed
|
|
334
|
+
if not upgrade_output or "Nothing to upgrade" not in upgrade_output:
|
|
335
|
+
return False
|
|
336
|
+
|
|
337
|
+
# Compare versions using packaging.version
|
|
338
|
+
try:
|
|
339
|
+
current_v = version.parse(current_version)
|
|
340
|
+
latest_v = version.parse(latest_version)
|
|
341
|
+
return current_v < latest_v
|
|
342
|
+
except (version.InvalidVersion, TypeError) as e:
|
|
343
|
+
# Graceful degradation: if version parsing fails, assume cache is not stale
|
|
344
|
+
logger.debug(f"Version parsing failed: {e}")
|
|
345
|
+
return False
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
# @CODE:UPDATE-CACHE-002
|
|
349
|
+
def _clear_uv_package_cache(package_name: str = "moai-adk") -> bool:
|
|
350
|
+
"""
|
|
351
|
+
Clear uv cache for specific package.
|
|
352
|
+
|
|
353
|
+
Executes `uv cache clean <package>` with 10-second timeout to prevent
|
|
354
|
+
hanging on network issues. Provides user-friendly error handling for
|
|
355
|
+
various failure scenarios (timeout, missing uv, etc.).
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
package_name: Package name to clear cache for (default: "moai-adk")
|
|
359
|
+
|
|
360
|
+
Returns:
|
|
361
|
+
True if cache cleared successfully, False otherwise
|
|
362
|
+
|
|
363
|
+
Exceptions:
|
|
364
|
+
- subprocess.TimeoutExpired: Logged as warning, returns False
|
|
365
|
+
- FileNotFoundError: Logged as warning, returns False
|
|
366
|
+
- Exception: Logged as warning, returns False
|
|
367
|
+
|
|
368
|
+
Examples:
|
|
369
|
+
>>> _clear_uv_package_cache("moai-adk")
|
|
370
|
+
True # If uv cache clean succeeds
|
|
371
|
+
"""
|
|
372
|
+
try:
|
|
373
|
+
result = subprocess.run(
|
|
374
|
+
["uv", "cache", "clean", package_name],
|
|
375
|
+
capture_output=True,
|
|
376
|
+
text=True,
|
|
377
|
+
timeout=10, # 10 second timeout
|
|
378
|
+
check=False,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
if result.returncode == 0:
|
|
382
|
+
logger.debug(f"UV cache cleared for {package_name}")
|
|
383
|
+
return True
|
|
384
|
+
else:
|
|
385
|
+
logger.warning(f"Failed to clear UV cache: {result.stderr}")
|
|
386
|
+
return False
|
|
387
|
+
|
|
388
|
+
except subprocess.TimeoutExpired:
|
|
389
|
+
logger.warning(f"UV cache clean timed out for {package_name}")
|
|
390
|
+
return False
|
|
391
|
+
except FileNotFoundError:
|
|
392
|
+
logger.warning("UV command not found. Is uv installed?")
|
|
393
|
+
return False
|
|
394
|
+
except Exception as e:
|
|
395
|
+
logger.warning(f"Unexpected error clearing cache: {e}")
|
|
396
|
+
return False
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# @CODE:UPDATE-CACHE-003
|
|
400
|
+
def _execute_upgrade_with_retry(installer_cmd: list[str], package_name: str = "moai-adk") -> bool:
|
|
401
|
+
"""
|
|
402
|
+
Execute upgrade with automatic cache retry on stale detection.
|
|
403
|
+
|
|
404
|
+
Implements a robust 7-stage upgrade flow that handles PyPI cache staleness:
|
|
405
|
+
|
|
406
|
+
Stage 1: First upgrade attempt (up to 60 seconds)
|
|
407
|
+
Stage 2: Check success condition (returncode=0 AND no "Nothing to upgrade")
|
|
408
|
+
Stage 3: Detect stale cache using _detect_stale_cache()
|
|
409
|
+
Stage 4: Show user feedback if stale cache detected
|
|
410
|
+
Stage 5: Clear cache using _clear_uv_package_cache()
|
|
411
|
+
Stage 6: Retry upgrade with same command
|
|
412
|
+
Stage 7: Return final result (success or failure)
|
|
413
|
+
|
|
414
|
+
Retry Logic:
|
|
415
|
+
- Only ONE retry is performed to prevent infinite loops
|
|
416
|
+
- Retry only happens if stale cache is detected AND cache clear succeeds
|
|
417
|
+
- Cache clear failures are reported to user with manual workaround
|
|
418
|
+
|
|
419
|
+
User Feedback:
|
|
420
|
+
- Shows emoji-based status messages for each stage
|
|
421
|
+
- Clear guidance on manual workaround if automatic retry fails
|
|
422
|
+
- All errors logged at WARNING level for debugging
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
installer_cmd: Command list from _detect_tool_installer()
|
|
426
|
+
e.g., ["uv", "tool", "upgrade", "moai-adk"]
|
|
427
|
+
package_name: Package name for cache clearing (default: "moai-adk")
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
True if upgrade succeeded (either first attempt or after retry),
|
|
431
|
+
False otherwise
|
|
432
|
+
|
|
433
|
+
Examples:
|
|
434
|
+
>>> # First attempt succeeds
|
|
435
|
+
>>> _execute_upgrade_with_retry(["uv", "tool", "upgrade", "moai-adk"])
|
|
436
|
+
True
|
|
437
|
+
|
|
438
|
+
>>> # First attempt stale, retry succeeds
|
|
439
|
+
>>> _execute_upgrade_with_retry(["uv", "tool", "upgrade", "moai-adk"])
|
|
440
|
+
True # After cache clear and retry
|
|
441
|
+
|
|
442
|
+
Raises:
|
|
443
|
+
subprocess.TimeoutExpired: Re-raised if upgrade command times out
|
|
444
|
+
"""
|
|
445
|
+
# Stage 1: First upgrade attempt
|
|
446
|
+
try:
|
|
447
|
+
result = subprocess.run(installer_cmd, capture_output=True, text=True, timeout=60, check=False)
|
|
448
|
+
except subprocess.TimeoutExpired:
|
|
449
|
+
raise # Re-raise timeout for caller to handle
|
|
450
|
+
except Exception:
|
|
451
|
+
return False
|
|
452
|
+
|
|
453
|
+
# Stage 2: Check if upgrade succeeded without stale cache
|
|
454
|
+
if result.returncode == 0 and "Nothing to upgrade" not in result.stdout:
|
|
455
|
+
return True
|
|
456
|
+
|
|
457
|
+
# Stage 3: Detect stale cache
|
|
458
|
+
try:
|
|
459
|
+
current_version = _get_current_version()
|
|
460
|
+
latest_version = _get_latest_version()
|
|
461
|
+
except RuntimeError:
|
|
462
|
+
# If version check fails, return original result
|
|
463
|
+
return result.returncode == 0
|
|
464
|
+
|
|
465
|
+
if _detect_stale_cache(result.stdout, current_version, latest_version):
|
|
466
|
+
# Stage 4: User feedback
|
|
467
|
+
console.print("[yellow]â ī¸ Cache outdated, refreshing...[/yellow]")
|
|
468
|
+
|
|
469
|
+
# Stage 5: Clear cache
|
|
470
|
+
if _clear_uv_package_cache(package_name):
|
|
471
|
+
console.print("[cyan]âģī¸ Cache cleared, retrying upgrade...[/cyan]")
|
|
472
|
+
|
|
473
|
+
# Stage 6: Retry upgrade
|
|
474
|
+
try:
|
|
475
|
+
result = subprocess.run(installer_cmd, capture_output=True, text=True, timeout=60, check=False)
|
|
476
|
+
|
|
477
|
+
if result.returncode == 0:
|
|
478
|
+
return True
|
|
479
|
+
else:
|
|
480
|
+
console.print("[red]â Upgrade failed after retry[/red]")
|
|
481
|
+
return False
|
|
482
|
+
except subprocess.TimeoutExpired:
|
|
483
|
+
raise # Re-raise timeout
|
|
484
|
+
except Exception:
|
|
485
|
+
return False
|
|
486
|
+
else:
|
|
487
|
+
# Cache clear failed
|
|
488
|
+
console.print("[red]â Cache clear failed. Manual workaround:[/red]")
|
|
489
|
+
console.print(" [cyan]uv cache clean moai-adk && moai-adk update[/cyan]")
|
|
490
|
+
return False
|
|
491
|
+
|
|
492
|
+
# Stage 7: Cache is not stale, return original result
|
|
493
|
+
return result.returncode == 0
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
def _execute_upgrade(installer_cmd: list[str]) -> bool:
|
|
497
|
+
"""Execute package upgrade using detected installer.
|
|
498
|
+
|
|
499
|
+
Args:
|
|
500
|
+
installer_cmd: Command list from _detect_tool_installer()
|
|
501
|
+
e.g., ["uv", "tool", "upgrade", "moai-adk"]
|
|
502
|
+
|
|
503
|
+
Returns:
|
|
504
|
+
True if upgrade succeeded, False otherwise
|
|
505
|
+
|
|
506
|
+
Raises:
|
|
507
|
+
subprocess.TimeoutExpired: If upgrade times out
|
|
508
|
+
"""
|
|
509
|
+
try:
|
|
510
|
+
result = subprocess.run(installer_cmd, capture_output=True, text=True, timeout=60, check=False)
|
|
511
|
+
return result.returncode == 0
|
|
512
|
+
except subprocess.TimeoutExpired:
|
|
513
|
+
raise # Re-raise timeout for caller to handle
|
|
514
|
+
except Exception:
|
|
515
|
+
return False
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def _sync_templates(project_path: Path, force: bool = False) -> bool:
|
|
519
|
+
"""Sync templates to project with rollback mechanism.
|
|
520
|
+
|
|
521
|
+
Args:
|
|
522
|
+
project_path: Project path (absolute)
|
|
523
|
+
force: Force update without backup
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
True if sync succeeded, False otherwise
|
|
527
|
+
"""
|
|
528
|
+
from moai_adk.core.template.backup import TemplateBackup
|
|
529
|
+
|
|
530
|
+
backup_path = None
|
|
531
|
+
try:
|
|
532
|
+
processor = TemplateProcessor(project_path)
|
|
533
|
+
|
|
534
|
+
# Create pre-sync backup for rollback
|
|
535
|
+
if not force:
|
|
536
|
+
backup = TemplateBackup(project_path)
|
|
537
|
+
if backup.has_existing_files():
|
|
538
|
+
backup_path = backup.create_backup()
|
|
539
|
+
console.print(f"đž Created backup: {backup_path.name}")
|
|
540
|
+
|
|
541
|
+
# Load existing config
|
|
542
|
+
existing_config = _load_existing_config(project_path)
|
|
543
|
+
|
|
544
|
+
# Build context
|
|
545
|
+
context = _build_template_context(project_path, existing_config, __version__)
|
|
546
|
+
if context:
|
|
547
|
+
processor.set_context(context)
|
|
548
|
+
|
|
549
|
+
# Copy templates
|
|
550
|
+
processor.copy_templates(backup=False, silent=True)
|
|
551
|
+
|
|
552
|
+
# Validate template substitution
|
|
553
|
+
validation_passed = _validate_template_substitution_with_rollback(project_path, backup_path)
|
|
554
|
+
if not validation_passed:
|
|
555
|
+
if backup_path:
|
|
556
|
+
console.print(f"[yellow]đ Rolling back to backup: {backup_path.name}[/yellow]")
|
|
557
|
+
backup.restore_backup(backup_path)
|
|
558
|
+
return False
|
|
559
|
+
|
|
560
|
+
# Preserve metadata
|
|
561
|
+
_preserve_project_metadata(project_path, context, existing_config, __version__)
|
|
562
|
+
_apply_context_to_file(processor, project_path / "CLAUDE.md")
|
|
563
|
+
|
|
564
|
+
# Set optimized=false
|
|
565
|
+
set_optimized_false(project_path)
|
|
566
|
+
|
|
567
|
+
return True
|
|
568
|
+
except Exception as e:
|
|
569
|
+
console.print(f"[red]â Template sync failed: {e}[/red]")
|
|
570
|
+
if backup_path:
|
|
571
|
+
console.print(f"[yellow]đ Rolling back to backup: {backup_path.name}[/yellow]")
|
|
572
|
+
try:
|
|
573
|
+
backup = TemplateBackup(project_path)
|
|
574
|
+
backup.restore_backup(backup_path)
|
|
575
|
+
console.print("[green]â
Rollback completed[/green]")
|
|
576
|
+
except Exception as rollback_error:
|
|
577
|
+
console.print(f"[red]â Rollback failed: {rollback_error}[/red]")
|
|
578
|
+
return False
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
def get_latest_version() -> str | None:
|
|
582
|
+
"""Get the latest version from PyPI.
|
|
583
|
+
|
|
584
|
+
DEPRECATED: Use _get_latest_version() for new code.
|
|
585
|
+
This function is kept for backward compatibility.
|
|
586
|
+
|
|
587
|
+
Returns:
|
|
588
|
+
Latest version string, or None if fetch fails.
|
|
589
|
+
"""
|
|
590
|
+
try:
|
|
591
|
+
return _get_latest_version()
|
|
592
|
+
except RuntimeError:
|
|
593
|
+
# Return None if PyPI check fails (backward compatibility)
|
|
36
594
|
return None
|
|
37
595
|
|
|
38
596
|
|
|
@@ -49,10 +607,7 @@ def set_optimized_false(project_path: Path) -> None:
|
|
|
49
607
|
try:
|
|
50
608
|
config_data = json.loads(config_path.read_text(encoding="utf-8"))
|
|
51
609
|
config_data.setdefault("project", {})["optimized"] = False
|
|
52
|
-
config_path.write_text(
|
|
53
|
-
json.dumps(config_data, indent=2, ensure_ascii=False) + "\n",
|
|
54
|
-
encoding="utf-8"
|
|
55
|
-
)
|
|
610
|
+
config_path.write_text(json.dumps(config_data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
56
611
|
except (json.JSONDecodeError, KeyError):
|
|
57
612
|
# Ignore errors if config.json is invalid
|
|
58
613
|
pass
|
|
@@ -103,22 +658,24 @@ def _build_template_context(
|
|
|
103
658
|
version_for_config: str,
|
|
104
659
|
) -> dict[str, str]:
|
|
105
660
|
"""Build substitution context for template files."""
|
|
661
|
+
import platform
|
|
662
|
+
|
|
106
663
|
project_section = _extract_project_section(existing_config)
|
|
107
664
|
|
|
108
665
|
project_name = _coalesce(
|
|
109
666
|
project_section.get("name"),
|
|
110
|
-
existing_config.get("projectName"),
|
|
667
|
+
existing_config.get("projectName"), # Legacy fallback
|
|
111
668
|
project_path.name,
|
|
112
669
|
)
|
|
113
670
|
project_mode = _coalesce(
|
|
114
671
|
project_section.get("mode"),
|
|
115
|
-
existing_config.get("mode"),
|
|
672
|
+
existing_config.get("mode"), # Legacy fallback
|
|
116
673
|
default="personal",
|
|
117
674
|
)
|
|
118
675
|
project_description = _coalesce(
|
|
119
676
|
project_section.get("description"),
|
|
120
|
-
existing_config.get("projectDescription"),
|
|
121
|
-
existing_config.get("description"),
|
|
677
|
+
existing_config.get("projectDescription"), # Legacy fallback
|
|
678
|
+
existing_config.get("description"), # Legacy fallback
|
|
122
679
|
)
|
|
123
680
|
project_version = _coalesce(
|
|
124
681
|
project_section.get("version"),
|
|
@@ -132,6 +689,17 @@ def _build_template_context(
|
|
|
132
689
|
default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
133
690
|
)
|
|
134
691
|
|
|
692
|
+
# Detect OS for cross-platform Hook path configuration
|
|
693
|
+
hook_project_dir = (
|
|
694
|
+
"%CLAUDE_PROJECT_DIR%" if platform.system() == "Windows"
|
|
695
|
+
else "$CLAUDE_PROJECT_DIR"
|
|
696
|
+
)
|
|
697
|
+
|
|
698
|
+
# Extract language configuration
|
|
699
|
+
language_config = existing_config.get("language", {})
|
|
700
|
+
if not isinstance(language_config, dict):
|
|
701
|
+
language_config = {}
|
|
702
|
+
|
|
135
703
|
return {
|
|
136
704
|
"MOAI_VERSION": version_for_config,
|
|
137
705
|
"PROJECT_NAME": project_name,
|
|
@@ -139,6 +707,12 @@ def _build_template_context(
|
|
|
139
707
|
"PROJECT_DESCRIPTION": project_description,
|
|
140
708
|
"PROJECT_VERSION": project_version,
|
|
141
709
|
"CREATION_TIMESTAMP": created_at,
|
|
710
|
+
"HOOK_PROJECT_DIR": hook_project_dir,
|
|
711
|
+
"CONVERSATION_LANGUAGE": language_config.get("conversation_language", "en"),
|
|
712
|
+
"CONVERSATION_LANGUAGE_NAME": language_config.get("conversation_language_name", "English"),
|
|
713
|
+
"CODEBASE_LANGUAGE": project_section.get("language", "generic"),
|
|
714
|
+
"PROJECT_OWNER": project_section.get("author", "@user"),
|
|
715
|
+
"AUTHOR": project_section.get("author", "@user"),
|
|
142
716
|
}
|
|
143
717
|
|
|
144
718
|
|
|
@@ -148,7 +722,10 @@ def _preserve_project_metadata(
|
|
|
148
722
|
existing_config: dict[str, Any],
|
|
149
723
|
version_for_config: str,
|
|
150
724
|
) -> None:
|
|
151
|
-
"""Restore project-specific metadata in the new config.json.
|
|
725
|
+
"""Restore project-specific metadata in the new config.json.
|
|
726
|
+
|
|
727
|
+
Also updates template_version to track which template version is synchronized.
|
|
728
|
+
"""
|
|
152
729
|
config_path = project_path / ".moai" / "config.json"
|
|
153
730
|
if not config_path.exists():
|
|
154
731
|
return
|
|
@@ -164,7 +741,6 @@ def _preserve_project_metadata(
|
|
|
164
741
|
project_data["mode"] = context["PROJECT_MODE"]
|
|
165
742
|
project_data["description"] = context["PROJECT_DESCRIPTION"]
|
|
166
743
|
project_data["created_at"] = context["CREATION_TIMESTAMP"]
|
|
167
|
-
project_data["moai_adk_version"] = version_for_config
|
|
168
744
|
|
|
169
745
|
if "optimized" not in project_data and isinstance(existing_config, dict):
|
|
170
746
|
existing_project = _extract_project_section(existing_config)
|
|
@@ -184,10 +760,11 @@ def _preserve_project_metadata(
|
|
|
184
760
|
config_data.setdefault("moai", {})
|
|
185
761
|
config_data["moai"]["version"] = version_for_config
|
|
186
762
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
763
|
+
# @CODE:UPDATE-VERSION-008: Update template_version to track sync status
|
|
764
|
+
# This allows Stage 2 to compare package vs project template versions
|
|
765
|
+
project_data["template_version"] = version_for_config
|
|
766
|
+
|
|
767
|
+
config_path.write_text(json.dumps(config_data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
191
768
|
|
|
192
769
|
|
|
193
770
|
def _apply_context_to_file(processor: TemplateProcessor, target_path: Path) -> None:
|
|
@@ -209,36 +786,186 @@ def _apply_context_to_file(processor: TemplateProcessor, target_path: Path) -> N
|
|
|
209
786
|
target_path.write_text(substituted, encoding="utf-8")
|
|
210
787
|
|
|
211
788
|
|
|
789
|
+
def _validate_template_substitution(project_path: Path) -> None:
|
|
790
|
+
"""Validate that all template variables have been properly substituted."""
|
|
791
|
+
import re
|
|
792
|
+
|
|
793
|
+
# Files to check for unsubstituted variables
|
|
794
|
+
files_to_check = [
|
|
795
|
+
project_path / ".claude" / "settings.json",
|
|
796
|
+
project_path / "CLAUDE.md",
|
|
797
|
+
]
|
|
798
|
+
|
|
799
|
+
issues_found = []
|
|
800
|
+
|
|
801
|
+
for file_path in files_to_check:
|
|
802
|
+
if not file_path.exists():
|
|
803
|
+
continue
|
|
804
|
+
|
|
805
|
+
try:
|
|
806
|
+
content = file_path.read_text(encoding='utf-8')
|
|
807
|
+
# Look for unsubstituted template variables
|
|
808
|
+
unsubstituted = re.findall(r'\{\{([A-Z_]+)\}\}', content)
|
|
809
|
+
if unsubstituted:
|
|
810
|
+
unique_vars = sorted(set(unsubstituted))
|
|
811
|
+
issues_found.append(f"{file_path.relative_to(project_path)}: {', '.join(unique_vars)}")
|
|
812
|
+
except Exception as e:
|
|
813
|
+
console.print(f"[yellow]â ī¸ Could not validate {file_path.relative_to(project_path)}: {e}[/yellow]")
|
|
814
|
+
|
|
815
|
+
if issues_found:
|
|
816
|
+
console.print("[red]â Template substitution validation failed:[/red]")
|
|
817
|
+
for issue in issues_found:
|
|
818
|
+
console.print(f" {issue}")
|
|
819
|
+
console.print("[yellow]đĄ Run '/alfred:0-project' to fix template variables[/yellow]")
|
|
820
|
+
else:
|
|
821
|
+
console.print("[green]â
Template substitution validation passed[/green]")
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
def _validate_template_substitution_with_rollback(project_path: Path, backup_path: Path | None) -> bool:
|
|
825
|
+
"""Validate template substitution with rollback capability.
|
|
826
|
+
|
|
827
|
+
Returns:
|
|
828
|
+
True if validation passed, False if failed (rollback handled by caller)
|
|
829
|
+
"""
|
|
830
|
+
import re
|
|
831
|
+
|
|
832
|
+
# Files to check for unsubstituted variables
|
|
833
|
+
files_to_check = [
|
|
834
|
+
project_path / ".claude" / "settings.json",
|
|
835
|
+
project_path / "CLAUDE.md",
|
|
836
|
+
]
|
|
837
|
+
|
|
838
|
+
issues_found = []
|
|
839
|
+
|
|
840
|
+
for file_path in files_to_check:
|
|
841
|
+
if not file_path.exists():
|
|
842
|
+
continue
|
|
843
|
+
|
|
844
|
+
try:
|
|
845
|
+
content = file_path.read_text(encoding='utf-8')
|
|
846
|
+
# Look for unsubstituted template variables
|
|
847
|
+
unsubstituted = re.findall(r'\{\{([A-Z_]+)\}\}', content)
|
|
848
|
+
if unsubstituted:
|
|
849
|
+
unique_vars = sorted(set(unsubstituted))
|
|
850
|
+
issues_found.append(f"{file_path.relative_to(project_path)}: {', '.join(unique_vars)}")
|
|
851
|
+
except Exception as e:
|
|
852
|
+
console.print(f"[yellow]â ī¸ Could not validate {file_path.relative_to(project_path)}: {e}[/yellow]")
|
|
853
|
+
|
|
854
|
+
if issues_found:
|
|
855
|
+
console.print("[red]â Template substitution validation failed:[/red]")
|
|
856
|
+
for issue in issues_found:
|
|
857
|
+
console.print(f" {issue}")
|
|
858
|
+
|
|
859
|
+
if backup_path:
|
|
860
|
+
console.print("[yellow]đ Rolling back due to validation failure...[/yellow]")
|
|
861
|
+
else:
|
|
862
|
+
console.print("[yellow]đĄ Run '/alfred:0-project' to fix template variables[/yellow]")
|
|
863
|
+
console.print("[red]â ī¸ No backup available - manual fix required[/red]")
|
|
864
|
+
|
|
865
|
+
return False
|
|
866
|
+
else:
|
|
867
|
+
console.print("[green]â
Template substitution validation passed[/green]")
|
|
868
|
+
return True
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
# @CODE:UPDATE-METADATA-003
|
|
872
|
+
def _show_version_info(current: str, latest: str) -> None:
|
|
873
|
+
"""Display version information.
|
|
874
|
+
|
|
875
|
+
Args:
|
|
876
|
+
current: Current installed version
|
|
877
|
+
latest: Latest available version
|
|
878
|
+
"""
|
|
879
|
+
console.print("[cyan]đ Checking versions...[/cyan]")
|
|
880
|
+
console.print(f" Current version: {current}")
|
|
881
|
+
console.print(f" Latest version: {latest}")
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
# @CODE:UPDATE-CONFIG-005
|
|
885
|
+
def _show_installer_not_found_help() -> None:
|
|
886
|
+
"""Show help when installer not found."""
|
|
887
|
+
console.print("[red]â Cannot detect package installer[/red]\n")
|
|
888
|
+
console.print("Installation method not detected. To update manually:\n")
|
|
889
|
+
console.print(" âĸ If installed via uv tool:")
|
|
890
|
+
console.print(" [cyan]uv tool upgrade moai-adk[/cyan]\n")
|
|
891
|
+
console.print(" âĸ If installed via pipx:")
|
|
892
|
+
console.print(" [cyan]pipx upgrade moai-adk[/cyan]\n")
|
|
893
|
+
console.print(" âĸ If installed via pip:")
|
|
894
|
+
console.print(" [cyan]pip install --upgrade moai-adk[/cyan]\n")
|
|
895
|
+
console.print("Then run:")
|
|
896
|
+
console.print(" [cyan]moai-adk update --templates-only[/cyan]")
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
def _show_upgrade_failure_help(installer_cmd: list[str]) -> None:
|
|
900
|
+
"""Show help when upgrade fails.
|
|
901
|
+
|
|
902
|
+
Args:
|
|
903
|
+
installer_cmd: The installer command that failed
|
|
904
|
+
"""
|
|
905
|
+
console.print("[red]â Upgrade failed[/red]\n")
|
|
906
|
+
console.print("Troubleshooting:")
|
|
907
|
+
console.print(" 1. Check network connection")
|
|
908
|
+
console.print(f" 2. Clear cache: {installer_cmd[0]} cache clean")
|
|
909
|
+
console.print(f" 3. Try manually: {' '.join(installer_cmd)}")
|
|
910
|
+
console.print(" 4. Report issue: https://github.com/modu-ai/moai-adk/issues")
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
def _show_network_error_help() -> None:
|
|
914
|
+
"""Show help for network errors."""
|
|
915
|
+
console.print("[yellow]â ī¸ Cannot reach PyPI to check latest version[/yellow]\n")
|
|
916
|
+
console.print("Options:")
|
|
917
|
+
console.print(" 1. Check network connection")
|
|
918
|
+
console.print(" 2. Try again with: [cyan]moai-adk update --force[/cyan]")
|
|
919
|
+
console.print(" 3. Skip version check: [cyan]moai-adk update --templates-only[/cyan]")
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
def _show_template_sync_failure_help() -> None:
|
|
923
|
+
"""Show help when template sync fails."""
|
|
924
|
+
console.print("[yellow]â ī¸ Template sync failed[/yellow]\n")
|
|
925
|
+
console.print("Rollback options:")
|
|
926
|
+
console.print(" 1. Restore from backup: [cyan]cp -r .moai-backups/TIMESTAMP .moai/[/cyan]")
|
|
927
|
+
console.print(" 2. Skip backup and retry: [cyan]moai-adk update --force[/cyan]")
|
|
928
|
+
console.print(" 3. Report issue: https://github.com/modu-ai/moai-adk/issues")
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
def _show_timeout_error_help() -> None:
|
|
932
|
+
"""Show help for timeout errors."""
|
|
933
|
+
console.print("[red]â Error: Operation timed out[/red]\n")
|
|
934
|
+
console.print("Try again with:")
|
|
935
|
+
console.print(" [cyan]moai-adk update --yes --force[/cyan]")
|
|
936
|
+
|
|
937
|
+
|
|
212
938
|
@click.command()
|
|
213
|
-
@click.option(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
- .claude
|
|
234
|
-
-
|
|
235
|
-
-
|
|
236
|
-
- config.json (smart merge)
|
|
939
|
+
@click.option("--path", type=click.Path(exists=True), default=".", help="Project path (default: current directory)")
|
|
940
|
+
@click.option("--force", is_flag=True, help="Skip backup and force the update")
|
|
941
|
+
@click.option("--check", is_flag=True, help="Only check version (do not update)")
|
|
942
|
+
@click.option("--templates-only", is_flag=True, help="Skip package upgrade, sync templates only")
|
|
943
|
+
@click.option("--yes", is_flag=True, help="Auto-confirm all prompts (CI/CD mode)")
|
|
944
|
+
def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool) -> None:
|
|
945
|
+
"""Update command with 3-stage workflow (v0.6.3+).
|
|
946
|
+
|
|
947
|
+
Stage 1 (Package Version Check):
|
|
948
|
+
- Fetches current and latest versions from PyPI
|
|
949
|
+
- If current < latest: detects installer (uv tool, pipx, pip) and upgrades package
|
|
950
|
+
- Prompts user to re-run after upgrade completes
|
|
951
|
+
|
|
952
|
+
Stage 2 (Config Version Comparison - NEW in v0.6.3):
|
|
953
|
+
- Compares package template_version with project config.json template_version
|
|
954
|
+
- If versions match: skips Stage 3 (already up-to-date)
|
|
955
|
+
- Performance improvement: 70-80% faster for unchanged projects (3-4s vs 12-18s)
|
|
956
|
+
|
|
957
|
+
Stage 3 (Template Sync):
|
|
958
|
+
- Syncs templates only if versions differ
|
|
959
|
+
- Updates .claude/, .moai/, CLAUDE.md, config.json
|
|
960
|
+
- Preserves specs and reports
|
|
961
|
+
- Saves new template_version to config.json
|
|
237
962
|
|
|
238
963
|
Examples:
|
|
239
|
-
python -m moai_adk update
|
|
240
|
-
python -m moai_adk update --force
|
|
241
|
-
python -m moai_adk update --check
|
|
964
|
+
python -m moai_adk update # auto 3-stage workflow
|
|
965
|
+
python -m moai_adk update --force # force template sync
|
|
966
|
+
python -m moai_adk update --check # check version only
|
|
967
|
+
python -m moai_adk update --templates-only # skip package upgrade
|
|
968
|
+
python -m moai_adk update --yes # CI/CD mode (auto-confirm)
|
|
242
969
|
"""
|
|
243
970
|
try:
|
|
244
971
|
project_path = Path(path).resolve()
|
|
@@ -248,106 +975,170 @@ def update(path: str, force: bool, check: bool) -> None:
|
|
|
248
975
|
console.print("[yellow]â Project not initialized[/yellow]")
|
|
249
976
|
raise click.Abort()
|
|
250
977
|
|
|
251
|
-
|
|
978
|
+
# Get versions (needed for --check and normal workflow, but not for --templates-only alone)
|
|
979
|
+
# Note: If --check is used, always fetch versions even if --templates-only is also present
|
|
980
|
+
if check or not templates_only:
|
|
981
|
+
try:
|
|
982
|
+
current = _get_current_version()
|
|
983
|
+
latest = _get_latest_version()
|
|
984
|
+
except RuntimeError as e:
|
|
985
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
986
|
+
if not force:
|
|
987
|
+
console.print("[yellow]â Cannot check for updates. Use --force to update anyway.[/yellow]")
|
|
988
|
+
raise click.Abort()
|
|
989
|
+
# With --force, proceed to Stage 2 even if version check fails
|
|
990
|
+
current = __version__
|
|
991
|
+
latest = __version__
|
|
252
992
|
|
|
253
|
-
|
|
254
|
-
console.print("[cyan]đ Checking versions...[/cyan]")
|
|
255
|
-
current_version = __version__
|
|
256
|
-
latest_version = get_latest_version()
|
|
257
|
-
version_for_config = current_version
|
|
258
|
-
|
|
259
|
-
# Handle PyPI fetch failure
|
|
260
|
-
if latest_version is None:
|
|
261
|
-
console.print(f" Current version: {current_version}")
|
|
262
|
-
console.print(" Latest version: [yellow]Unable to fetch from PyPI[/yellow]")
|
|
263
|
-
if not force:
|
|
264
|
-
console.print("[yellow]â Cannot check for updates. Use --force to update anyway.[/yellow]")
|
|
265
|
-
return
|
|
266
|
-
else:
|
|
267
|
-
console.print(f" Current version: {current_version}")
|
|
268
|
-
console.print(f" Latest version: {latest_version}")
|
|
993
|
+
_show_version_info(current, latest)
|
|
269
994
|
|
|
995
|
+
# Step 1: Handle --check (preview mode, no changes) - takes priority
|
|
270
996
|
if check:
|
|
271
|
-
|
|
272
|
-
if
|
|
273
|
-
console.print("[yellow]
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
console.print("[green]â Development version (newer than PyPI)[/green]")
|
|
997
|
+
comparison = _compare_versions(current, latest)
|
|
998
|
+
if comparison < 0:
|
|
999
|
+
console.print(f"\n[yellow]đĻ Update available: {current} â {latest}[/yellow]")
|
|
1000
|
+
console.print(" Run 'moai-adk update' to upgrade")
|
|
1001
|
+
elif comparison == 0:
|
|
1002
|
+
console.print(f"[green]â Already up to date ({current})[/green]")
|
|
278
1003
|
else:
|
|
279
|
-
console.print("[
|
|
1004
|
+
console.print(f"[cyan]âšī¸ Dev version: {current} (latest: {latest})[/cyan]")
|
|
280
1005
|
return
|
|
281
1006
|
|
|
282
|
-
#
|
|
283
|
-
if
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
console.print("[
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
1007
|
+
# Step 2: Handle --templates-only (skip upgrade, go straight to sync)
|
|
1008
|
+
if templates_only:
|
|
1009
|
+
console.print("[cyan]đ Syncing templates only...[/cyan]")
|
|
1010
|
+
try:
|
|
1011
|
+
if not _sync_templates(project_path, force):
|
|
1012
|
+
raise TemplateSyncError("Template sync returned False")
|
|
1013
|
+
except TemplateSyncError:
|
|
1014
|
+
console.print("[red]Error: Template sync failed[/red]")
|
|
1015
|
+
_show_template_sync_failure_help()
|
|
1016
|
+
raise click.Abort()
|
|
1017
|
+
except Exception as e:
|
|
1018
|
+
console.print(f"[red]Error: Template sync failed - {e}[/red]")
|
|
1019
|
+
_show_template_sync_failure_help()
|
|
1020
|
+
raise click.Abort()
|
|
1021
|
+
|
|
1022
|
+
console.print(" [green]â
.claude/ update complete[/green]")
|
|
1023
|
+
console.print(" [green]â
.moai/ update complete (specs/reports preserved)[/green]")
|
|
1024
|
+
console.print(" [green]đ CLAUDE.md merge complete[/green]")
|
|
1025
|
+
console.print(" [green]đ config.json merge complete[/green]")
|
|
1026
|
+
console.print("\n[green]â Template sync complete![/green]")
|
|
1027
|
+
return
|
|
1028
|
+
|
|
1029
|
+
# Compare versions
|
|
1030
|
+
comparison = _compare_versions(current, latest)
|
|
1031
|
+
|
|
1032
|
+
# Stage 1: Package Upgrade (if current < latest)
|
|
1033
|
+
# @CODE:UPDATE-STAGE1-009
|
|
1034
|
+
if comparison < 0:
|
|
1035
|
+
console.print(f"\n[cyan]đĻ Upgrading: {current} â {latest}[/cyan]")
|
|
1036
|
+
|
|
1037
|
+
# Confirm upgrade (unless --yes)
|
|
1038
|
+
if not yes:
|
|
1039
|
+
if not click.confirm(f"Upgrade {current} â {latest}?", default=True):
|
|
1040
|
+
console.print("Cancelled")
|
|
311
1041
|
return
|
|
312
1042
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
1043
|
+
# Detect installer
|
|
1044
|
+
try:
|
|
1045
|
+
installer_cmd = _detect_tool_installer()
|
|
1046
|
+
if not installer_cmd:
|
|
1047
|
+
raise InstallerNotFoundError("No package installer detected")
|
|
1048
|
+
except InstallerNotFoundError:
|
|
1049
|
+
_show_installer_not_found_help()
|
|
1050
|
+
raise click.Abort()
|
|
321
1051
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
processor = TemplateProcessor(project_path)
|
|
1052
|
+
# Display upgrade command
|
|
1053
|
+
console.print(f"Running: {' '.join(installer_cmd)}")
|
|
325
1054
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
1055
|
+
# Execute upgrade with timeout handling
|
|
1056
|
+
try:
|
|
1057
|
+
upgrade_result = _execute_upgrade(installer_cmd)
|
|
1058
|
+
if not upgrade_result:
|
|
1059
|
+
raise UpgradeError(f"Upgrade command failed: {' '.join(installer_cmd)}")
|
|
1060
|
+
except subprocess.TimeoutExpired:
|
|
1061
|
+
_show_timeout_error_help()
|
|
1062
|
+
raise click.Abort()
|
|
1063
|
+
except UpgradeError:
|
|
1064
|
+
_show_upgrade_failure_help(installer_cmd)
|
|
1065
|
+
raise click.Abort()
|
|
1066
|
+
|
|
1067
|
+
# Prompt re-run
|
|
1068
|
+
console.print("\n[green]â Upgrade complete![/green]")
|
|
1069
|
+
console.print("[cyan]đĸ Run 'moai-adk update' again to sync templates[/cyan]")
|
|
1070
|
+
return
|
|
1071
|
+
|
|
1072
|
+
# Stage 2: Config Version Comparison
|
|
1073
|
+
# @CODE:UPDATE-STAGE2-010: Stage 2 - Compare template versions to determine if sync needed
|
|
1074
|
+
console.print(f"â Package already up to date ({current})")
|
|
329
1075
|
|
|
330
|
-
|
|
1076
|
+
try:
|
|
1077
|
+
package_config_version = _get_package_config_version()
|
|
1078
|
+
project_config_version = _get_project_config_version(project_path)
|
|
1079
|
+
except ValueError as e:
|
|
1080
|
+
console.print(f"[yellow]â Warning: {e}[/yellow]")
|
|
1081
|
+
# On version detection error, proceed with template sync (safer choice)
|
|
1082
|
+
package_config_version = __version__
|
|
1083
|
+
project_config_version = "0.0.0"
|
|
1084
|
+
|
|
1085
|
+
console.print("\n[cyan]đ Comparing config versions...[/cyan]")
|
|
1086
|
+
console.print(f" Package template: {package_config_version}")
|
|
1087
|
+
console.print(f" Project config: {project_config_version}")
|
|
1088
|
+
|
|
1089
|
+
try:
|
|
1090
|
+
config_comparison = _compare_versions(package_config_version, project_config_version)
|
|
1091
|
+
except version.InvalidVersion as e:
|
|
1092
|
+
# Handle invalid version strings (e.g., unsubstituted template placeholders, corrupted configs)
|
|
1093
|
+
console.print(f"[yellow]â Invalid version format in config: {e}[/yellow]")
|
|
1094
|
+
console.print("[cyan]âšī¸ Forcing template sync to repair configuration...[/cyan]")
|
|
1095
|
+
# Force template sync by treating project version as outdated
|
|
1096
|
+
config_comparison = 1 # package_config_version > project_config_version
|
|
1097
|
+
|
|
1098
|
+
# If versions are equal, no sync needed
|
|
1099
|
+
if config_comparison <= 0:
|
|
1100
|
+
console.print(f"\n[green]â Project already has latest template version ({project_config_version})[/green]")
|
|
1101
|
+
console.print("[cyan]âšī¸ Templates are up to date! No changes needed.[/cyan]")
|
|
1102
|
+
return
|
|
1103
|
+
|
|
1104
|
+
# Stage 3: Template Sync (Only if package_config_version > project_config_version)
|
|
1105
|
+
# @CODE:UPDATE-STAGE3-011: Stage 3 - Template sync only if versions differ
|
|
1106
|
+
console.print(f"\n[cyan]đ Syncing templates ({project_config_version} â {package_config_version})...[/cyan]")
|
|
1107
|
+
|
|
1108
|
+
# Create backup unless --force
|
|
1109
|
+
if not force:
|
|
1110
|
+
console.print(" [cyan]đž Creating backup...[/cyan]")
|
|
1111
|
+
try:
|
|
1112
|
+
processor = TemplateProcessor(project_path)
|
|
1113
|
+
backup_path = processor.create_backup()
|
|
1114
|
+
console.print(f" [green]â Backup: {backup_path.relative_to(project_path)}/[/green]")
|
|
1115
|
+
except Exception as e:
|
|
1116
|
+
console.print(f" [yellow]â Backup failed: {e}[/yellow]")
|
|
1117
|
+
console.print(" [yellow]â Continuing without backup...[/yellow]")
|
|
1118
|
+
else:
|
|
1119
|
+
console.print(" [yellow]â Skipping backup (--force)[/yellow]")
|
|
1120
|
+
|
|
1121
|
+
# Sync templates
|
|
1122
|
+
try:
|
|
1123
|
+
if not _sync_templates(project_path, force):
|
|
1124
|
+
raise TemplateSyncError("Template sync returned False")
|
|
1125
|
+
except TemplateSyncError:
|
|
1126
|
+
console.print("[red]Error: Template sync failed[/red]")
|
|
1127
|
+
_show_template_sync_failure_help()
|
|
1128
|
+
raise click.Abort()
|
|
1129
|
+
except Exception as e:
|
|
1130
|
+
console.print(f"[red]Error: Template sync failed - {e}[/red]")
|
|
1131
|
+
_show_template_sync_failure_help()
|
|
1132
|
+
raise click.Abort()
|
|
331
1133
|
|
|
332
1134
|
console.print(" [green]â
.claude/ update complete[/green]")
|
|
333
1135
|
console.print(" [green]â
.moai/ update complete (specs/reports preserved)[/green]")
|
|
334
1136
|
console.print(" [green]đ CLAUDE.md merge complete[/green]")
|
|
335
1137
|
console.print(" [green]đ config.json merge complete[/green]")
|
|
336
|
-
|
|
337
|
-
_preserve_project_metadata(project_path, context, existing_config, version_for_config)
|
|
338
|
-
_apply_context_to_file(processor, project_path / "CLAUDE.md")
|
|
339
|
-
|
|
340
|
-
# Phase 4: set optimized=false
|
|
341
|
-
set_optimized_false(project_path)
|
|
342
1138
|
console.print(" [yellow]âī¸ Set optimized=false (optimization needed)[/yellow]")
|
|
343
1139
|
|
|
344
1140
|
console.print("\n[green]â Update complete![/green]")
|
|
345
|
-
|
|
346
|
-
console.print(
|
|
347
|
-
"[yellow]â Python package still on older version. "
|
|
348
|
-
"Run 'pip install --upgrade moai-adk' to upgrade the CLI package.[/yellow]"
|
|
349
|
-
)
|
|
350
|
-
console.print("\n[cyan]âšī¸ Next step: Run /alfred:0-project update to optimize template changes[/cyan]")
|
|
1141
|
+
console.print("[cyan]âšī¸ Next step: Run /alfred:0-project update to optimize template changes[/cyan]")
|
|
351
1142
|
|
|
352
1143
|
except Exception as e:
|
|
353
1144
|
console.print(f"[red]â Update failed: {e}[/red]")
|