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.
- moai_adk/__init__.py +1 -2
- moai_adk/__main__.py +85 -2
- moai_adk/cli/__init__.py +0 -1
- moai_adk/cli/commands/__init__.py +0 -1
- moai_adk/cli/commands/analyze.py +127 -0
- moai_adk/cli/commands/backup.py +5 -3
- moai_adk/cli/commands/doctor.py +35 -11
- moai_adk/cli/commands/improve_user_experience.py +348 -0
- moai_adk/cli/commands/init.py +150 -23
- moai_adk/cli/commands/language.py +269 -0
- moai_adk/cli/commands/migrate.py +158 -0
- moai_adk/cli/commands/status.py +13 -12
- moai_adk/cli/commands/update.py +364 -60
- moai_adk/cli/commands/validate_links.py +118 -0
- moai_adk/cli/main.py +3 -2
- moai_adk/cli/prompts/init_prompts.py +79 -82
- moai_adk/core/__init__.py +0 -1
- moai_adk/core/analysis/__init__.py +9 -0
- moai_adk/core/analysis/session_analyzer.py +439 -0
- moai_adk/core/claude_integration.py +421 -0
- moai_adk/core/command_helpers.py +270 -0
- moai_adk/core/config/__init__.py +6 -0
- moai_adk/core/config/auto_spec_config.py +346 -0
- moai_adk/core/config/migration.py +133 -12
- moai_adk/core/context_manager.py +279 -0
- moai_adk/core/diagnostics/slash_commands.py +0 -1
- moai_adk/core/error_recovery_system.py +1289 -0
- moai_adk/core/git/__init__.py +0 -1
- moai_adk/core/git/branch.py +0 -1
- moai_adk/core/git/branch_manager.py +4 -4
- moai_adk/core/git/checkpoint.py +1 -5
- moai_adk/core/git/commit.py +0 -1
- moai_adk/core/git/event_detector.py +3 -5
- moai_adk/core/git/manager.py +0 -1
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +925 -0
- moai_adk/core/integration/__init__.py +22 -0
- moai_adk/core/integration/engine.py +169 -0
- moai_adk/core/integration/integration_tester.py +225 -0
- moai_adk/core/integration/models.py +88 -0
- moai_adk/core/integration/utils.py +211 -0
- moai_adk/core/issue_creator.py +28 -18
- moai_adk/core/language_config.py +202 -0
- moai_adk/core/language_validator.py +556 -0
- moai_adk/core/mcp/setup.py +113 -0
- moai_adk/core/migration/__init__.py +18 -0
- moai_adk/core/migration/backup_manager.py +208 -0
- moai_adk/core/migration/file_migrator.py +218 -0
- moai_adk/core/migration/version_detector.py +143 -0
- moai_adk/core/migration/version_migrator.py +228 -0
- moai_adk/core/performance/__init__.py +6 -0
- moai_adk/core/performance/cache_system.py +318 -0
- moai_adk/core/performance/parallel_processor.py +116 -0
- moai_adk/core/project/__init__.py +0 -1
- moai_adk/core/project/backup_utils.py +2 -7
- moai_adk/core/project/checker.py +3 -3
- moai_adk/core/project/detector.py +20 -40
- moai_adk/core/project/initializer.py +42 -17
- moai_adk/core/project/phase_executor.py +415 -58
- moai_adk/core/project/validator.py +6 -25
- moai_adk/core/quality/__init__.py +1 -1
- moai_adk/core/quality/trust_checker.py +64 -110
- moai_adk/core/quality/validators/__init__.py +1 -1
- moai_adk/core/quality/validators/base_validator.py +1 -1
- moai_adk/core/rollback_manager.py +993 -0
- moai_adk/core/session_manager.py +667 -0
- moai_adk/core/spec/confidence_scoring.py +749 -0
- moai_adk/core/spec/ears_template_engine.py +1182 -0
- moai_adk/core/spec/quality_validator.py +721 -0
- moai_adk/core/spec_status_manager.py +488 -0
- moai_adk/core/template/__init__.py +0 -1
- moai_adk/core/template/backup.py +41 -1
- moai_adk/core/template/config.py +11 -12
- moai_adk/core/template/languages.py +0 -1
- moai_adk/core/template/merger.py +79 -22
- moai_adk/core/template/processor.py +614 -40
- moai_adk/core/template_engine.py +36 -27
- moai_adk/foundation/git/commit_templates.py +565 -0
- moai_adk/foundation/trust/trust_principles.py +725 -0
- moai_adk/foundation/trust/validation_checklist.py +1678 -0
- moai_adk/statusline/__init__.py +38 -0
- moai_adk/statusline/alfred_detector.py +107 -0
- moai_adk/statusline/config.py +364 -0
- moai_adk/statusline/enhanced_output_style_detector.py +364 -0
- moai_adk/statusline/git_collector.py +190 -0
- moai_adk/statusline/main.py +228 -0
- moai_adk/statusline/metrics_tracker.py +78 -0
- moai_adk/statusline/renderer.py +327 -0
- moai_adk/statusline/update_checker.py +135 -0
- moai_adk/statusline/version_reader.py +647 -0
- moai_adk/templates/.git-hooks/pre-commit +66 -0
- moai_adk/templates/.git-hooks/pre-push +116 -4
- moai_adk/templates/.github/workflows/moai-gitflow.yml +1 -7
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +0 -1
- moai_adk/templates/.gitignore +44 -0
- moai_adk/templates/.mcp.json +22 -0
- moai_adk/templates/CLAUDE.md +450 -1071
- moai_adk/utils/__init__.py +0 -1
- moai_adk/utils/banner.py +0 -1
- moai_adk/utils/common.py +308 -0
- moai_adk/utils/link_validator.py +249 -0
- moai_adk/utils/logger.py +4 -9
- moai_adk/utils/safe_file_reader.py +210 -0
- moai_adk/utils/user_experience.py +531 -0
- moai_adk-0.25.4.dist-info/METADATA +2279 -0
- moai_adk-0.25.4.dist-info/RECORD +112 -0
- moai_adk/core/tags/__init__.py +0 -86
- moai_adk/core/tags/ci_validator.py +0 -463
- moai_adk/core/tags/cli.py +0 -283
- moai_adk/core/tags/generator.py +0 -109
- moai_adk/core/tags/inserter.py +0 -99
- moai_adk/core/tags/mapper.py +0 -126
- moai_adk/core/tags/parser.py +0 -76
- moai_adk/core/tags/pre_commit_validator.py +0 -393
- moai_adk/core/tags/reporter.py +0 -956
- moai_adk/core/tags/tags.py +0 -149
- moai_adk/core/tags/validator.py +0 -897
- moai_adk/templates/.claude/agents/alfred/backend-expert.md +0 -319
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -316
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -208
- moai_adk/templates/.claude/agents/alfred/devops-expert.md +0 -464
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -214
- moai_adk/templates/.claude/agents/alfred/frontend-expert.md +0 -357
- moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -406
- moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -423
- moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -312
- moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -343
- moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -865
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -426
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -361
- moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -428
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -375
- moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +0 -571
- moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1854
- moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -880
- moai_adk/templates/.claude/commands/alfred/2-run.md +0 -793
- moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -1084
- moai_adk/templates/.claude/commands/alfred/9-feedback.md +0 -149
- moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -748
- moai_adk/templates/.claude/hooks/alfred/core/timeout.py +0 -136
- moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +0 -108
- moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +0 -198
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -29
- moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +0 -94
- moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +0 -100
- moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +0 -94
- moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +0 -94
- moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +0 -170
- moai_adk/templates/.claude/hooks/alfred/shared/core/checkpoint.py +0 -271
- moai_adk/templates/.claude/hooks/alfred/shared/core/context.py +0 -67
- moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +0 -749
- moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +0 -230
- moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +0 -198
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +0 -21
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +0 -154
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +0 -174
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +0 -87
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +0 -61
- moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +0 -112
- moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +0 -1
- moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +0 -161
- moai_adk/templates/.claude/settings.json +0 -144
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +0 -70
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +0 -62
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/reference.md +0 -242
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +0 -56
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +0 -444
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +0 -62
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +0 -405
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +0 -51
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +0 -355
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +0 -239
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +0 -323
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +0 -286
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +0 -126
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +0 -74
- moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +0 -4
- moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +0 -269
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +0 -19
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +0 -4
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +0 -150
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +0 -198
- moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +0 -431
- moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +0 -141
- moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +0 -89
- moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +0 -122
- moai_adk/templates/.claude/skills/moai-alfred-practices/reference.md +0 -369
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +0 -508
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +0 -481
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +0 -100
- moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +0 -273
- moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +0 -77
- moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +0 -265
- moai_adk/templates/.claude/skills/moai-alfred-rules/reference.md +0 -539
- moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +0 -19
- moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +0 -4
- moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +0 -84
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +0 -137
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +0 -219
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples/validate-spec.sh +0 -161
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +0 -541
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +0 -622
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +0 -115
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +0 -4
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +0 -348
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +0 -19
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +0 -4
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +0 -211
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +0 -288
- moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
- moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
- moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
- moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
- moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
- moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
- moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
- moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
- moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
- moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
- moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
- moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +0 -19
- moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +0 -4
- moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/reference.md +0 -218
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/CHECKLIST.md +0 -482
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/EXAMPLES.md +0 -278
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/METADATA.md +0 -477
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL.md +0 -271
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/STRUCTURE.md +0 -583
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/WEB-RESEARCH.md +0 -526
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/reference.md +0 -465
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/generate-structure.sh +0 -328
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/validate-skill.sh +0 -312
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/examples-template.md +0 -285
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/reference-template.md +0 -278
- moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/scripts-template.sh +0 -303
- moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
- moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
- moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +0 -802
- moai_adk/templates/.claude/skills/moai-design-systems/examples.md +0 -1238
- moai_adk/templates/.claude/skills/moai-design-systems/reference.md +0 -673
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +0 -290
- moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +0 -1633
- moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +0 -660
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-database/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-database/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +0 -128
- moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
- moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
- moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
- moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -116
- moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
- moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
- moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
- moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +0 -127
- moai_adk/templates/.claude/skills/moai-lang-go/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-go/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +0 -126
- moai_adk/templates/.claude/skills/moai-lang-java/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-java/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
- moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +0 -126
- moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +0 -433
- moai_adk/templates/.claude/skills/moai-lang-python/examples.md +0 -624
- moai_adk/templates/.claude/skills/moai-lang-python/reference.md +0 -316
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +0 -127
- moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +0 -125
- moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +0 -133
- moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +0 -34
- moai_adk/templates/.claude/skills/moai-project-documentation.md +0 -622
- moai_adk/templates/.github/workflows/c-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/cpp-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/csharp-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/dart-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/go-tag-validation.yml +0 -130
- moai_adk/templates/.github/workflows/java-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/javascript-tag-validation.yml +0 -135
- moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/php-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/python-tag-validation.yml +0 -118
- moai_adk/templates/.github/workflows/release.yml +0 -118
- moai_adk/templates/.github/workflows/ruby-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/rust-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/shell-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/swift-tag-validation.yml +0 -11
- moai_adk/templates/.github/workflows/tag-report.yml +0 -269
- moai_adk/templates/.github/workflows/tag-validation.yml +0 -186
- moai_adk/templates/.github/workflows/typescript-tag-validation.yml +0 -154
- moai_adk/templates/.moai/config.json +0 -115
- moai_adk/templates/workflows/go-tag-validation.yml +0 -30
- moai_adk/templates/workflows/javascript-tag-validation.yml +0 -41
- moai_adk/templates/workflows/python-tag-validation.yml +0 -42
- moai_adk/templates/workflows/typescript-tag-validation.yml +0 -31
- moai_adk-0.15.1.dist-info/METADATA +0 -3094
- moai_adk-0.15.1.dist-info/RECORD +0 -365
- {moai_adk-0.15.1.dist-info → moai_adk-0.25.4.dist-info}/WHEEL +0 -0
- {moai_adk-0.15.1.dist-info → moai_adk-0.25.4.dist-info}/entry_points.txt +0 -0
- {moai_adk-0.15.1.dist-info → moai_adk-0.25.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
"""SPEC Status Manager
|
|
2
|
+
|
|
3
|
+
Automated management of SPEC status transitions from 'draft' to 'completed'
|
|
4
|
+
based on implementation completion detection and validation criteria.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import re
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, Set
|
|
12
|
+
|
|
13
|
+
import yaml
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SpecStatusManager:
|
|
19
|
+
"""Manages SPEC status detection and updates based on implementation completion"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, project_root: Path):
|
|
22
|
+
"""Initialize the SPEC status manager
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
project_root: Root directory of the MoAI project
|
|
26
|
+
"""
|
|
27
|
+
self.project_root = Path(project_root)
|
|
28
|
+
self.specs_dir = self.project_root / ".moai" / "specs"
|
|
29
|
+
self.src_dir = self.project_root / "src"
|
|
30
|
+
self.tests_dir = self.project_root / "tests"
|
|
31
|
+
self.docs_dir = self.project_root / "docs"
|
|
32
|
+
|
|
33
|
+
# Validation criteria (configurable)
|
|
34
|
+
self.validation_criteria = {
|
|
35
|
+
"min_code_coverage": 0.85, # 85% minimum coverage
|
|
36
|
+
"require_acceptance_criteria": True,
|
|
37
|
+
"min_implementation_age_days": 0, # Days since last implementation
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def detect_draft_specs(self) -> Set[str]:
|
|
41
|
+
"""Detect all SPEC files with 'draft' status
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Set of SPEC IDs that have draft status
|
|
45
|
+
"""
|
|
46
|
+
draft_specs = set()
|
|
47
|
+
|
|
48
|
+
if not self.specs_dir.exists():
|
|
49
|
+
logger.warning(f"SPEC directory not found: {self.specs_dir}")
|
|
50
|
+
return draft_specs
|
|
51
|
+
|
|
52
|
+
for spec_dir in self.specs_dir.iterdir():
|
|
53
|
+
if spec_dir.is_dir():
|
|
54
|
+
spec_file = spec_dir / "spec.md"
|
|
55
|
+
if spec_file.exists():
|
|
56
|
+
try:
|
|
57
|
+
# Read frontmatter to check status
|
|
58
|
+
with open(spec_file, "r", encoding="utf-8") as f:
|
|
59
|
+
content = f.read()
|
|
60
|
+
|
|
61
|
+
frontmatter = None
|
|
62
|
+
|
|
63
|
+
# Handle JSON-like meta (common in older specs)
|
|
64
|
+
meta_match = re.search(
|
|
65
|
+
r"<%?\s*---\s*\n(.*?)\n---\s*%?>", content, re.DOTALL
|
|
66
|
+
)
|
|
67
|
+
if meta_match:
|
|
68
|
+
try:
|
|
69
|
+
meta_text = meta_match.group(1)
|
|
70
|
+
# Replace JSON-style quotes and parse as YAML
|
|
71
|
+
meta_text = meta_text.replace('"', "").replace("'", "")
|
|
72
|
+
frontmatter = yaml.safe_load("{" + meta_text + "}")
|
|
73
|
+
except Exception as e:
|
|
74
|
+
logger.debug(
|
|
75
|
+
f"JSON meta parsing failed for {spec_dir.name}: {e}"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Handle regular YAML frontmatter
|
|
79
|
+
elif content.startswith("---"):
|
|
80
|
+
end_marker = content.find("---", 3)
|
|
81
|
+
if end_marker != -1:
|
|
82
|
+
frontmatter_text = content[3:end_marker].strip()
|
|
83
|
+
try:
|
|
84
|
+
frontmatter = yaml.safe_load(frontmatter_text)
|
|
85
|
+
except yaml.YAMLError as e:
|
|
86
|
+
logger.warning(
|
|
87
|
+
f"YAML parsing error for {spec_dir.name}: {e}"
|
|
88
|
+
)
|
|
89
|
+
# Try to fix common issues (like @ in author field)
|
|
90
|
+
try:
|
|
91
|
+
# Replace problematic @author entries
|
|
92
|
+
fixed_text = frontmatter_text
|
|
93
|
+
if "author: @" in fixed_text:
|
|
94
|
+
fixed_text = re.sub(
|
|
95
|
+
r"author:\s*@(\w+)",
|
|
96
|
+
r'author: "\1"',
|
|
97
|
+
fixed_text,
|
|
98
|
+
)
|
|
99
|
+
frontmatter = yaml.safe_load(fixed_text)
|
|
100
|
+
except:
|
|
101
|
+
logger.error(
|
|
102
|
+
f"Could not parse YAML for {spec_dir.name} even after fixes"
|
|
103
|
+
)
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
if frontmatter and frontmatter.get("status") == "draft":
|
|
107
|
+
spec_id = spec_dir.name
|
|
108
|
+
draft_specs.add(spec_id)
|
|
109
|
+
logger.debug(f"Found draft SPEC: {spec_id}")
|
|
110
|
+
|
|
111
|
+
except Exception as e:
|
|
112
|
+
logger.error(f"Error reading SPEC {spec_dir.name}: {e}")
|
|
113
|
+
|
|
114
|
+
logger.info(f"Found {len(draft_specs)} draft SPECs")
|
|
115
|
+
return draft_specs
|
|
116
|
+
|
|
117
|
+
def is_spec_implementation_completed(self, spec_id: str) -> bool:
|
|
118
|
+
"""Check if a SPEC's implementation is complete
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
spec_id: The SPEC identifier (e.g., "SPEC-001")
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
True if implementation is complete, False otherwise
|
|
125
|
+
"""
|
|
126
|
+
spec_dir = self.specs_dir / spec_id
|
|
127
|
+
spec_file = spec_dir / "spec.md"
|
|
128
|
+
|
|
129
|
+
if not spec_file.exists():
|
|
130
|
+
logger.warning(f"SPEC file not found: {spec_file}")
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
# Check basic implementation status
|
|
135
|
+
spec_dir = spec_file.parent
|
|
136
|
+
|
|
137
|
+
# Check for implementation files
|
|
138
|
+
src_files = (
|
|
139
|
+
list(spec_dir.rglob("*.py"))
|
|
140
|
+
if (spec_dir.parent.parent / "src").exists()
|
|
141
|
+
else []
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Check for test files
|
|
145
|
+
test_dir = spec_dir.parent.parent / "tests"
|
|
146
|
+
test_files = (
|
|
147
|
+
list(test_dir.rglob(f"test_*{spec_id.lower()}*.py"))
|
|
148
|
+
if test_dir.exists()
|
|
149
|
+
else []
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Simple completion criteria
|
|
153
|
+
has_code = len(src_files) > 0
|
|
154
|
+
has_tests = len(test_files) > 0
|
|
155
|
+
|
|
156
|
+
# Check if SPEC has acceptance criteria
|
|
157
|
+
with open(spec_file, "r", encoding="utf-8") as f:
|
|
158
|
+
spec_content = f.read()
|
|
159
|
+
has_acceptance_criteria = "Acceptance Criteria" in spec_content
|
|
160
|
+
|
|
161
|
+
# Overall completion check
|
|
162
|
+
is_complete = has_code and has_tests and has_acceptance_criteria
|
|
163
|
+
|
|
164
|
+
logger.info(
|
|
165
|
+
f"SPEC {spec_id} implementation status: {'COMPLETE' if is_complete else 'INCOMPLETE'}"
|
|
166
|
+
)
|
|
167
|
+
return is_complete
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(f"Error checking SPEC {spec_id} completion: {e}")
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
def update_spec_status(self, spec_id: str, new_status: str) -> bool:
|
|
174
|
+
"""Update SPEC status in frontmatter
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
spec_id: The SPEC identifier
|
|
178
|
+
new_status: New status value ('completed', 'draft', etc.)
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
True if update successful, False otherwise
|
|
182
|
+
"""
|
|
183
|
+
spec_dir = self.specs_dir / spec_id
|
|
184
|
+
spec_file = spec_dir / "spec.md"
|
|
185
|
+
|
|
186
|
+
if not spec_file.exists():
|
|
187
|
+
logger.error(f"SPEC file not found: {spec_file}")
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
with open(spec_file, "r", encoding="utf-8") as f:
|
|
192
|
+
content = f.read()
|
|
193
|
+
|
|
194
|
+
# Extract and update frontmatter
|
|
195
|
+
if content.startswith("---"):
|
|
196
|
+
end_marker = content.find("---", 3)
|
|
197
|
+
if end_marker != -1:
|
|
198
|
+
frontmatter_text = content[3:end_marker].strip()
|
|
199
|
+
try:
|
|
200
|
+
frontmatter = yaml.safe_load(frontmatter_text) or {}
|
|
201
|
+
except yaml.YAMLError as e:
|
|
202
|
+
logger.warning(f"YAML parsing error for {spec_id}: {e}")
|
|
203
|
+
# Try to fix common issues
|
|
204
|
+
try:
|
|
205
|
+
fixed_text = frontmatter_text
|
|
206
|
+
if "author: @" in fixed_text:
|
|
207
|
+
fixed_text = re.sub(
|
|
208
|
+
r"author:\s*@(\w+)", r'author: "\1"', fixed_text
|
|
209
|
+
)
|
|
210
|
+
frontmatter = yaml.safe_load(fixed_text) or {}
|
|
211
|
+
except:
|
|
212
|
+
logger.error(
|
|
213
|
+
f"Could not parse YAML for {spec_id} even after fixes"
|
|
214
|
+
)
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
# Update status
|
|
218
|
+
frontmatter["status"] = new_status
|
|
219
|
+
|
|
220
|
+
# Bump version if completing
|
|
221
|
+
if new_status == "completed":
|
|
222
|
+
frontmatter["version"] = self._bump_version(
|
|
223
|
+
frontmatter.get("version", "0.1.0")
|
|
224
|
+
)
|
|
225
|
+
frontmatter["updated"] = datetime.now().strftime("%Y-%m-%d")
|
|
226
|
+
|
|
227
|
+
# Reconstruct the file
|
|
228
|
+
new_frontmatter = yaml.dump(frontmatter, default_flow_style=False)
|
|
229
|
+
new_content = f"---\n{new_frontmatter}---{content[end_marker+3:]}"
|
|
230
|
+
|
|
231
|
+
# Write back to file
|
|
232
|
+
with open(spec_file, "w", encoding="utf-8") as f:
|
|
233
|
+
f.write(new_content)
|
|
234
|
+
|
|
235
|
+
logger.info(f"Updated SPEC {spec_id} status to {new_status}")
|
|
236
|
+
return True
|
|
237
|
+
|
|
238
|
+
except Exception as e:
|
|
239
|
+
logger.error(f"Error updating SPEC {spec_id} status: {e}")
|
|
240
|
+
return False
|
|
241
|
+
|
|
242
|
+
def get_completion_validation_criteria(self) -> Dict:
|
|
243
|
+
"""Get the current validation criteria for SPEC completion
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
Dictionary of validation criteria
|
|
247
|
+
"""
|
|
248
|
+
return self.validation_criteria.copy()
|
|
249
|
+
|
|
250
|
+
def validate_spec_for_completion(self, spec_id: str) -> Dict:
|
|
251
|
+
"""Validate if a SPEC is ready for completion
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
spec_id: The SPEC identifier
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
Dictionary with validation results:
|
|
258
|
+
{
|
|
259
|
+
'is_ready': bool,
|
|
260
|
+
'criteria_met': Dict[str, bool],
|
|
261
|
+
'issues': List[str],
|
|
262
|
+
'recommendations': List[str]
|
|
263
|
+
}
|
|
264
|
+
"""
|
|
265
|
+
result = {
|
|
266
|
+
"is_ready": False,
|
|
267
|
+
"criteria_met": {},
|
|
268
|
+
"issues": [],
|
|
269
|
+
"recommendations": [],
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
spec_dir = self.specs_dir / spec_id
|
|
274
|
+
spec_file = spec_dir / "spec.md"
|
|
275
|
+
|
|
276
|
+
if not spec_file.exists():
|
|
277
|
+
result["issues"].append(f"SPEC file not found: {spec_file}")
|
|
278
|
+
return result
|
|
279
|
+
|
|
280
|
+
# Check implementation status
|
|
281
|
+
criteria_checks = {}
|
|
282
|
+
|
|
283
|
+
# Check for code implementation
|
|
284
|
+
spec_dir = spec_file.parent
|
|
285
|
+
src_dir = spec_dir.parent.parent / "src"
|
|
286
|
+
criteria_checks["code_implemented"] = (
|
|
287
|
+
src_dir.exists() and len(list(src_dir.rglob("*.py"))) > 0
|
|
288
|
+
)
|
|
289
|
+
if not criteria_checks["code_implemented"]:
|
|
290
|
+
result["issues"].append("No source code files found")
|
|
291
|
+
|
|
292
|
+
# Check for test implementation
|
|
293
|
+
test_dir = spec_dir.parent.parent / "tests"
|
|
294
|
+
test_files = list(test_dir.rglob("test_*.py")) if test_dir.exists() else []
|
|
295
|
+
criteria_checks["test_implemented"] = len(test_files) > 0
|
|
296
|
+
if not criteria_checks["test_implemented"]:
|
|
297
|
+
result["issues"].append("No test files found")
|
|
298
|
+
|
|
299
|
+
# Check for acceptance criteria
|
|
300
|
+
criteria_checks["tasks_completed"] = self._check_acceptance_criteria(
|
|
301
|
+
spec_file
|
|
302
|
+
)
|
|
303
|
+
if not criteria_checks["tasks_completed"]:
|
|
304
|
+
result["issues"].append("Missing acceptance criteria section")
|
|
305
|
+
|
|
306
|
+
# 4. Acceptance criteria present
|
|
307
|
+
criteria_checks["has_acceptance_criteria"] = (
|
|
308
|
+
self._check_acceptance_criteria(spec_file)
|
|
309
|
+
)
|
|
310
|
+
if (
|
|
311
|
+
not criteria_checks["has_acceptance_criteria"]
|
|
312
|
+
and self.validation_criteria["require_acceptance_criteria"]
|
|
313
|
+
):
|
|
314
|
+
result["issues"].append("Missing acceptance criteria section")
|
|
315
|
+
|
|
316
|
+
# 5. Documentation sync
|
|
317
|
+
criteria_checks["docs_synced"] = self._check_documentation_sync(spec_id)
|
|
318
|
+
if not criteria_checks["docs_synced"]:
|
|
319
|
+
result["recommendations"].append(
|
|
320
|
+
"Consider running /alfred:3-sync to update documentation"
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
result["criteria_met"] = criteria_checks
|
|
324
|
+
result["is_ready"] = all(criteria_checks.values())
|
|
325
|
+
|
|
326
|
+
# Add recommendations
|
|
327
|
+
if result["is_ready"]:
|
|
328
|
+
result["recommendations"].append(
|
|
329
|
+
"SPEC is ready for completion. Consider updating status to 'completed'"
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
except Exception as e:
|
|
333
|
+
logger.error(f"Error validating SPEC {spec_id}: {e}")
|
|
334
|
+
result["issues"].append(f"Validation error: {e}")
|
|
335
|
+
|
|
336
|
+
return result
|
|
337
|
+
|
|
338
|
+
def batch_update_completed_specs(self) -> Dict:
|
|
339
|
+
"""Batch update all draft SPECs that have completed implementations
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
Dictionary with update results:
|
|
343
|
+
{
|
|
344
|
+
'updated': List[str], # Successfully updated SPEC IDs
|
|
345
|
+
'failed': List[str], # Failed SPEC IDs with errors
|
|
346
|
+
'skipped': List[str] # Incomplete SPEC IDs
|
|
347
|
+
}
|
|
348
|
+
"""
|
|
349
|
+
results = {"updated": [], "failed": [], "skipped": []}
|
|
350
|
+
|
|
351
|
+
draft_specs = self.detect_draft_specs()
|
|
352
|
+
logger.info(f"Checking {len(draft_specs)} draft SPECs for completion")
|
|
353
|
+
|
|
354
|
+
for spec_id in draft_specs:
|
|
355
|
+
try:
|
|
356
|
+
# Validate first
|
|
357
|
+
validation = self.validate_spec_for_completion(spec_id)
|
|
358
|
+
|
|
359
|
+
if validation["is_ready"]:
|
|
360
|
+
# Update status
|
|
361
|
+
if self.update_spec_status(spec_id, "completed"):
|
|
362
|
+
results["updated"].append(spec_id)
|
|
363
|
+
logger.info(f"Updated SPEC {spec_id} to completed")
|
|
364
|
+
else:
|
|
365
|
+
results["failed"].append(spec_id)
|
|
366
|
+
logger.error(f"Failed to update SPEC {spec_id}")
|
|
367
|
+
else:
|
|
368
|
+
results["skipped"].append(spec_id)
|
|
369
|
+
logger.debug(
|
|
370
|
+
f"SPEC {spec_id} not ready for completion: {validation['issues']}"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
except Exception as e:
|
|
374
|
+
results["failed"].append(spec_id)
|
|
375
|
+
logger.error(f"Error processing SPEC {spec_id}: {e}")
|
|
376
|
+
|
|
377
|
+
logger.info(
|
|
378
|
+
f"Batch update complete: {len(results['updated'])} updated, {len(results['failed'])} failed, {len(results['skipped'])} skipped"
|
|
379
|
+
)
|
|
380
|
+
return results
|
|
381
|
+
|
|
382
|
+
# Private helper methods
|
|
383
|
+
|
|
384
|
+
def _check_acceptance_criteria(self, spec_file: Path) -> bool:
|
|
385
|
+
"""
|
|
386
|
+
Check if SPEC file contains acceptance criteria
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
spec_file: Path to SPEC file
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
True if acceptance criteria present
|
|
393
|
+
"""
|
|
394
|
+
try:
|
|
395
|
+
with open(spec_file, "r", encoding="utf-8") as f:
|
|
396
|
+
content = f.read()
|
|
397
|
+
|
|
398
|
+
# Look for acceptance criteria section
|
|
399
|
+
acceptance_patterns = [
|
|
400
|
+
r"##\s*Acceptance\s+Criteria",
|
|
401
|
+
r"###\s*Acceptance\s+Criteria",
|
|
402
|
+
r"##\s*验收\s+标准",
|
|
403
|
+
r"###\s*验收\s+标准",
|
|
404
|
+
]
|
|
405
|
+
|
|
406
|
+
for pattern in acceptance_patterns:
|
|
407
|
+
if re.search(pattern, content, re.IGNORECASE):
|
|
408
|
+
return True
|
|
409
|
+
|
|
410
|
+
return False
|
|
411
|
+
|
|
412
|
+
except Exception as e:
|
|
413
|
+
logger.error(f"Error checking acceptance criteria in {spec_file}: {e}")
|
|
414
|
+
return False
|
|
415
|
+
|
|
416
|
+
def _check_documentation_sync(self, spec_id: str) -> bool:
|
|
417
|
+
"""
|
|
418
|
+
Check if documentation is synchronized with implementation
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
spec_id: The SPEC identifier
|
|
422
|
+
|
|
423
|
+
Returns:
|
|
424
|
+
True if documentation appears synchronized
|
|
425
|
+
"""
|
|
426
|
+
try:
|
|
427
|
+
# Simple heuristic: check if docs exist and are recent
|
|
428
|
+
docs_dir = self.project_root / "docs"
|
|
429
|
+
if not docs_dir.exists():
|
|
430
|
+
return True # No docs to sync
|
|
431
|
+
|
|
432
|
+
# Check if there are any doc files related to this SPEC
|
|
433
|
+
spec_docs = list(docs_dir.rglob(f"*{spec_id.lower()}*"))
|
|
434
|
+
if not spec_docs:
|
|
435
|
+
return True # No specific docs for this SPEC
|
|
436
|
+
|
|
437
|
+
# Basic check - assume docs are in sync if they exist
|
|
438
|
+
return True
|
|
439
|
+
|
|
440
|
+
except Exception as e:
|
|
441
|
+
logger.error(f"Error checking documentation sync for {spec_id}: {e}")
|
|
442
|
+
return False
|
|
443
|
+
|
|
444
|
+
def _run_additional_validations(self, spec_id: str) -> bool:
|
|
445
|
+
"""Run additional validation checks for SPEC completion
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
spec_id: The SPEC identifier
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
True if all additional validations pass
|
|
452
|
+
"""
|
|
453
|
+
# Add any additional validation logic here
|
|
454
|
+
# For now, return True as default
|
|
455
|
+
return True
|
|
456
|
+
|
|
457
|
+
def _bump_version(self, current_version: str) -> str:
|
|
458
|
+
"""Bump version to indicate completion
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
current_version: Current version string
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
New version string
|
|
465
|
+
"""
|
|
466
|
+
try:
|
|
467
|
+
# Parse current version - strip quotes if present
|
|
468
|
+
version = str(current_version).strip("\"'")
|
|
469
|
+
|
|
470
|
+
if version.startswith("0."):
|
|
471
|
+
# Major version bump for completion
|
|
472
|
+
return "1.0.0"
|
|
473
|
+
else:
|
|
474
|
+
# Minor version bump for updates
|
|
475
|
+
parts = version.split(".")
|
|
476
|
+
if len(parts) >= 2:
|
|
477
|
+
try:
|
|
478
|
+
minor = int(parts[1]) + 1
|
|
479
|
+
return f"{parts[0]}.{minor}.0"
|
|
480
|
+
except ValueError:
|
|
481
|
+
# If parsing fails, default to 1.0.0
|
|
482
|
+
return "1.0.0"
|
|
483
|
+
else:
|
|
484
|
+
return f"{version}.1"
|
|
485
|
+
|
|
486
|
+
except Exception:
|
|
487
|
+
# Fallback to 1.0.0
|
|
488
|
+
return "1.0.0"
|
moai_adk/core/template/backup.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# @CODE:TEMPLATE-001 | SPEC: SPEC-INIT-003/spec.md | Chain: TEMPLATE-001
|
|
2
1
|
"""Template backup manager (SPEC-INIT-003 v0.3.0).
|
|
3
2
|
|
|
4
3
|
Creates and manages backups to protect user data during template updates.
|
|
@@ -107,3 +106,44 @@ class TemplateBackup:
|
|
|
107
106
|
shutil.copy2(item, dst_item)
|
|
108
107
|
elif item.is_dir():
|
|
109
108
|
dst_item.mkdir(parents=True, exist_ok=True)
|
|
109
|
+
|
|
110
|
+
def restore_backup(self, backup_path: Path | None = None) -> None:
|
|
111
|
+
"""Restore project files from backup.
|
|
112
|
+
|
|
113
|
+
Restores .moai, .claude, .github directories and CLAUDE.md file
|
|
114
|
+
from a backup created by create_backup().
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
backup_path: Backup path to restore from.
|
|
118
|
+
Defaults to .moai-backups/backup/
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
FileNotFoundError: When backup_path doesn't exist.
|
|
122
|
+
"""
|
|
123
|
+
if backup_path is None:
|
|
124
|
+
backup_path = self.backup_dir / "backup"
|
|
125
|
+
|
|
126
|
+
if not backup_path.exists():
|
|
127
|
+
raise FileNotFoundError(f"Backup not found: {backup_path}")
|
|
128
|
+
|
|
129
|
+
# Restore each item from backup
|
|
130
|
+
for item in [".moai", ".claude", ".github", "CLAUDE.md"]:
|
|
131
|
+
src = backup_path / item
|
|
132
|
+
dst = self.target_path / item
|
|
133
|
+
|
|
134
|
+
# Skip if not in backup
|
|
135
|
+
if not src.exists():
|
|
136
|
+
continue
|
|
137
|
+
|
|
138
|
+
# Remove current version
|
|
139
|
+
if dst.exists():
|
|
140
|
+
if dst.is_dir():
|
|
141
|
+
shutil.rmtree(dst)
|
|
142
|
+
else:
|
|
143
|
+
dst.unlink()
|
|
144
|
+
|
|
145
|
+
# Restore from backup
|
|
146
|
+
if src.is_dir():
|
|
147
|
+
shutil.copytree(src, dst, dirs_exist_ok=True)
|
|
148
|
+
else:
|
|
149
|
+
shutil.copy2(src, dst)
|
moai_adk/core/template/config.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
# @CODE:PY314-001 | SPEC: SPEC-PY314-001.md | TEST: tests/unit/test_config_manager.py
|
|
2
1
|
"""Configuration Manager
|
|
3
2
|
|
|
4
|
-
Manage .moai/config.json:
|
|
3
|
+
Manage .moai/config/config.json:
|
|
5
4
|
- Read and write configuration files
|
|
6
5
|
- Support deep merges
|
|
7
6
|
- Preserve UTF-8 content
|
|
@@ -14,15 +13,9 @@ from typing import Any
|
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class ConfigManager:
|
|
17
|
-
"""Read and write .moai/config.json."""
|
|
16
|
+
"""Read and write .moai/config/config.json."""
|
|
18
17
|
|
|
19
|
-
DEFAULT_CONFIG = {
|
|
20
|
-
"mode": "personal",
|
|
21
|
-
"locale": "ko",
|
|
22
|
-
"moai": {
|
|
23
|
-
"version": "0.3.0"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
18
|
+
DEFAULT_CONFIG = {"mode": "personal", "locale": "ko", "moai": {"version": "0.3.0"}}
|
|
26
19
|
|
|
27
20
|
def __init__(self, config_path: Path) -> None:
|
|
28
21
|
"""Initialize the ConfigManager.
|
|
@@ -72,7 +65,9 @@ class ConfigManager:
|
|
|
72
65
|
merged = self._deep_merge(current, updates)
|
|
73
66
|
self.save(merged)
|
|
74
67
|
|
|
75
|
-
def _deep_merge(
|
|
68
|
+
def _deep_merge(
|
|
69
|
+
self, base: dict[str, Any], updates: dict[str, Any]
|
|
70
|
+
) -> dict[str, Any]:
|
|
76
71
|
"""Recursively deep-merge dictionaries.
|
|
77
72
|
|
|
78
73
|
Args:
|
|
@@ -85,7 +80,11 @@ class ConfigManager:
|
|
|
85
80
|
result = base.copy()
|
|
86
81
|
|
|
87
82
|
for key, value in updates.items():
|
|
88
|
-
if
|
|
83
|
+
if (
|
|
84
|
+
key in result
|
|
85
|
+
and isinstance(result[key], dict)
|
|
86
|
+
and isinstance(value, dict)
|
|
87
|
+
):
|
|
89
88
|
# When both sides are dicts, merge recursively
|
|
90
89
|
result[key] = self._deep_merge(result[key], value)
|
|
91
90
|
else:
|