moai-adk 0.25.4__py3-none-any.whl → 0.32.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +2 -5
- moai_adk/__main__.py +114 -82
- moai_adk/cli/__init__.py +6 -1
- moai_adk/cli/commands/__init__.py +1 -3
- moai_adk/cli/commands/analyze.py +5 -16
- moai_adk/cli/commands/doctor.py +6 -18
- moai_adk/cli/commands/init.py +56 -125
- moai_adk/cli/commands/language.py +14 -35
- moai_adk/cli/commands/status.py +9 -15
- moai_adk/cli/commands/update.py +1555 -190
- moai_adk/cli/prompts/init_prompts.py +112 -56
- moai_adk/cli/spec_status.py +263 -0
- moai_adk/cli/ui/__init__.py +44 -0
- moai_adk/cli/ui/progress.py +422 -0
- moai_adk/cli/ui/prompts.py +389 -0
- moai_adk/cli/ui/theme.py +129 -0
- moai_adk/cli/worktree/__init__.py +27 -0
- moai_adk/cli/worktree/__main__.py +31 -0
- moai_adk/cli/worktree/cli.py +672 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +490 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +128 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/analysis/session_analyzer.py +17 -56
- moai_adk/core/claude_integration.py +26 -54
- moai_adk/core/command_helpers.py +10 -10
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/auto_spec_config.py +5 -11
- moai_adk/core/config/migration.py +19 -9
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +6 -12
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +725 -112
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +8 -0
- moai_adk/core/git/branch_manager.py +3 -11
- moai_adk/core/git/checkpoint.py +1 -3
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/manager.py +91 -1
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +56 -80
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/engine.py +6 -18
- moai_adk/core/integration/integration_tester.py +10 -9
- moai_adk/core/integration/utils.py +1 -1
- moai_adk/core/issue_creator.py +10 -28
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config_resolver.py +485 -0
- moai_adk/core/language_validator.py +28 -41
- moai_adk/core/mcp/setup.py +15 -12
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +481 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +78 -9
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +8 -17
- moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
- moai_adk/core/migration/selective_restorer.py +470 -0
- moai_adk/core/migration/template_utils.py +74 -0
- moai_adk/core/migration/user_selection_ui.py +338 -0
- moai_adk/core/migration/version_detector.py +6 -10
- moai_adk/core/migration/version_migrator.py +3 -3
- moai_adk/core/performance/cache_system.py +8 -10
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/checker.py +2 -4
- moai_adk/core/project/detector.py +1 -3
- moai_adk/core/project/initializer.py +135 -23
- moai_adk/core/project/phase_executor.py +54 -81
- moai_adk/core/project/validator.py +6 -12
- moai_adk/core/quality/trust_checker.py +9 -27
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +73 -148
- moai_adk/core/session_manager.py +10 -26
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +31 -100
- moai_adk/core/spec/ears_template_engine.py +351 -286
- moai_adk/core/spec/quality_validator.py +35 -69
- moai_adk/core/spec_status_manager.py +64 -74
- moai_adk/core/template/backup.py +45 -20
- moai_adk/core/template/config.py +112 -39
- moai_adk/core/template/merger.py +11 -19
- moai_adk/core/template/processor.py +253 -149
- moai_adk/core/template_engine.py +73 -40
- moai_adk/core/template_variable_synchronizer.py +417 -0
- moai_adk/core/unified_permission_manager.py +745 -0
- moai_adk/core/user_behavior_analytics.py +851 -0
- moai_adk/core/version_sync.py +429 -0
- moai_adk/foundation/__init__.py +56 -0
- moai_adk/foundation/backend.py +1027 -0
- moai_adk/foundation/database.py +1115 -0
- moai_adk/foundation/devops.py +1585 -0
- moai_adk/foundation/ears.py +431 -0
- moai_adk/foundation/frontend.py +870 -0
- moai_adk/foundation/git/commit_templates.py +4 -12
- moai_adk/foundation/git.py +376 -0
- moai_adk/foundation/langs.py +484 -0
- moai_adk/foundation/ml_ops.py +1162 -0
- moai_adk/foundation/testing.py +1524 -0
- moai_adk/foundation/trust/trust_principles.py +23 -72
- moai_adk/foundation/trust/validation_checklist.py +57 -162
- moai_adk/project/__init__.py +0 -0
- moai_adk/project/configuration.py +1084 -0
- moai_adk/project/documentation.py +566 -0
- moai_adk/project/schema.py +447 -0
- moai_adk/statusline/alfred_detector.py +1 -3
- moai_adk/statusline/config.py +13 -4
- moai_adk/statusline/enhanced_output_style_detector.py +23 -15
- moai_adk/statusline/main.py +51 -15
- moai_adk/statusline/renderer.py +104 -48
- moai_adk/statusline/update_checker.py +3 -9
- moai_adk/statusline/version_reader.py +140 -46
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +993 -0
- moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
- moai_adk/templates/.claude/hooks/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
- moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
- moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
- moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
- moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
- moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
- moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
- moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
- moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
- moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
- moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
- moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
- moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
- moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +921 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
- moai_adk/templates/.claude/settings.json +172 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +320 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +496 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
- moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +491 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +201 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +438 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +346 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +362 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/SKILL.md +352 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +316 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +370 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/README.md +186 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +135 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +374 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
- moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +410 -0
- moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
- moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
- moai_adk/templates/.git-hooks/pre-commit +103 -41
- moai_adk/templates/.git-hooks/pre-push +116 -21
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.gitignore +184 -44
- moai_adk/templates/.mcp.json +7 -9
- moai_adk/templates/.moai/cache/personalization.json +10 -0
- moai_adk/templates/.moai/config/config.yaml +344 -0
- moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
- moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
- moai_adk/templates/.moai/config/presets/team.yaml +33 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -0
- moai_adk/templates/.moai/config/sections/language.yaml +11 -0
- moai_adk/templates/.moai/config/sections/project.yaml +13 -0
- moai_adk/templates/.moai/config/sections/quality.yaml +15 -0
- moai_adk/templates/.moai/config/sections/system.yaml +14 -0
- moai_adk/templates/.moai/config/sections/user.yaml +5 -0
- moai_adk/templates/.moai/config/statusline-config.yaml +86 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +382 -501
- moai_adk/utils/__init__.py +24 -1
- moai_adk/utils/banner.py +7 -10
- moai_adk/utils/common.py +16 -30
- moai_adk/utils/link_validator.py +4 -12
- moai_adk/utils/safe_file_reader.py +2 -6
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.32.8.dist-info/METADATA +2478 -0
- moai_adk-0.32.8.dist-info/RECORD +396 -0
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
- moai_adk/cli/commands/backup.py +0 -82
- moai_adk/cli/commands/improve_user_experience.py +0 -348
- moai_adk/cli/commands/migrate.py +0 -158
- moai_adk/cli/commands/validate_links.py +0 -118
- moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -413
- moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
- moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
- moai_adk/utils/user_experience.py +0 -531
- moai_adk-0.25.4.dist-info/METADATA +0 -2279
- moai_adk-0.25.4.dist-info/RECORD +0 -112
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,6 +10,9 @@ from moai_adk.core.spec.confidence_scoring import ConfidenceScoringSystem
|
|
|
10
10
|
# Configure logging
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
|
+
# Traceability tag patterns
|
|
14
|
+
TRACEABILITY_TAGS = ["@SPEC:", "@REQ:", "@TEST:", "@IMPL:", "@DOC:"]
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
class QualityValidator:
|
|
15
18
|
"""
|
|
@@ -92,7 +95,7 @@ class QualityValidator:
|
|
|
92
95
|
logger.info("Starting SPEC quality validation")
|
|
93
96
|
|
|
94
97
|
# Initialize validation results
|
|
95
|
-
validation_result = {
|
|
98
|
+
validation_result: Dict[str, Any] = {
|
|
96
99
|
"validation_time": 0.0,
|
|
97
100
|
"overall_score": 0.0,
|
|
98
101
|
"quality_grade": "F",
|
|
@@ -113,9 +116,7 @@ class QualityValidator:
|
|
|
113
116
|
validation_result["details"]["content_completeness"] = completeness_result
|
|
114
117
|
|
|
115
118
|
# Validate technical accuracy
|
|
116
|
-
technical_result = self._validate_technical_accuracy(
|
|
117
|
-
spec_content, code_analysis
|
|
118
|
-
)
|
|
119
|
+
technical_result = self._validate_technical_accuracy(spec_content, code_analysis)
|
|
119
120
|
validation_result["details"]["technical_accuracy"] = technical_result
|
|
120
121
|
|
|
121
122
|
# Validate clarity and readability
|
|
@@ -131,9 +132,7 @@ class QualityValidator:
|
|
|
131
132
|
validation_result["overall_score"] = overall_score
|
|
132
133
|
|
|
133
134
|
# Determine quality grade
|
|
134
|
-
validation_result["quality_grade"] = self._determine_quality_grade(
|
|
135
|
-
overall_score
|
|
136
|
-
)
|
|
135
|
+
validation_result["quality_grade"] = self._determine_quality_grade(overall_score)
|
|
137
136
|
|
|
138
137
|
# Check if SPEC meets minimum quality standards
|
|
139
138
|
meets_standards = self._check_quality_standards(validation_result)
|
|
@@ -144,12 +143,8 @@ class QualityValidator:
|
|
|
144
143
|
validation_result["recommendations"] = recommendations
|
|
145
144
|
|
|
146
145
|
# Compile check results
|
|
147
|
-
validation_result["passed_checks"] = self._compile_passed_checks(
|
|
148
|
-
|
|
149
|
-
)
|
|
150
|
-
validation_result["failed_checks"] = self._compile_failed_checks(
|
|
151
|
-
validation_result["details"]
|
|
152
|
-
)
|
|
146
|
+
validation_result["passed_checks"] = self._compile_passed_checks(validation_result["details"])
|
|
147
|
+
validation_result["failed_checks"] = self._compile_failed_checks(validation_result["details"])
|
|
153
148
|
|
|
154
149
|
except Exception as e:
|
|
155
150
|
logger.error(f"Error during SPEC validation: {str(e)}")
|
|
@@ -158,9 +153,7 @@ class QualityValidator:
|
|
|
158
153
|
# Set validation time
|
|
159
154
|
validation_result["validation_time"] = time.time() - start_time
|
|
160
155
|
|
|
161
|
-
logger.info(
|
|
162
|
-
f"SPEC quality validation completed in {validation_result['validation_time']:.2f}s"
|
|
163
|
-
)
|
|
156
|
+
logger.info(f"SPEC quality validation completed in {validation_result['validation_time']:.2f}s")
|
|
164
157
|
|
|
165
158
|
return validation_result
|
|
166
159
|
|
|
@@ -184,6 +177,10 @@ class QualityValidator:
|
|
|
184
177
|
overall_compliance = sum(section_scores.values()) / len(required_sections)
|
|
185
178
|
|
|
186
179
|
# Check for META information
|
|
180
|
+
has_meta = "---" in spec_md and "title:" in spec_md
|
|
181
|
+
|
|
182
|
+
# Check for tags
|
|
183
|
+
has_tags = self._check_traceability_tags(spec_md)
|
|
187
184
|
|
|
188
185
|
# Check for proper structure
|
|
189
186
|
has_proper_headings = self._check_heading_structure(spec_md)
|
|
@@ -196,14 +193,10 @@ class QualityValidator:
|
|
|
196
193
|
"has_tags": has_tags,
|
|
197
194
|
"has_proper_structure": has_proper_headings,
|
|
198
195
|
"total_sections": len(required_sections),
|
|
199
|
-
"present_sections": sum(
|
|
200
|
-
1 for score in section_scores.values() if score > 0
|
|
201
|
-
),
|
|
196
|
+
"present_sections": sum(1 for score in section_scores.values() if score > 0),
|
|
202
197
|
}
|
|
203
198
|
|
|
204
|
-
def _validate_content_completeness(
|
|
205
|
-
self, spec_content: Dict[str, str]
|
|
206
|
-
) -> Dict[str, Any]:
|
|
199
|
+
def _validate_content_completeness(self, spec_content: Dict[str, str]) -> Dict[str, Any]:
|
|
207
200
|
"""Validate content completeness across all SPEC files."""
|
|
208
201
|
logger.info("Validating content completeness")
|
|
209
202
|
|
|
@@ -230,9 +223,7 @@ class QualityValidator:
|
|
|
230
223
|
results["acceptance_completeness"] = acceptance_completeness
|
|
231
224
|
|
|
232
225
|
# Calculate overall completeness
|
|
233
|
-
overall_completeness = (
|
|
234
|
-
spec_completeness + plan_completeness + acceptance_completeness
|
|
235
|
-
) / 3
|
|
226
|
+
overall_completeness = (spec_completeness + plan_completeness + acceptance_completeness) / 3
|
|
236
227
|
results["overall_completeness"] = round(overall_completeness, 2)
|
|
237
228
|
|
|
238
229
|
return results
|
|
@@ -301,13 +292,7 @@ class QualityValidator:
|
|
|
301
292
|
"ambiguity_score": ambiguity_score,
|
|
302
293
|
"consistency_score": consistency_score,
|
|
303
294
|
"overall_clarity": round(
|
|
304
|
-
(
|
|
305
|
-
language_quality
|
|
306
|
-
+ clarity_requirements
|
|
307
|
-
+ (1.0 - ambiguity_score)
|
|
308
|
-
+ consistency_score
|
|
309
|
-
)
|
|
310
|
-
/ 4,
|
|
295
|
+
(language_quality + clarity_requirements + (1.0 - ambiguity_score) + consistency_score) / 4,
|
|
311
296
|
2,
|
|
312
297
|
),
|
|
313
298
|
}
|
|
@@ -331,12 +316,9 @@ class QualityValidator:
|
|
|
331
316
|
weights = self.quality_weights
|
|
332
317
|
|
|
333
318
|
overall_score = (
|
|
334
|
-
details["ears_compliance"]["overall_compliance"]
|
|
335
|
-
* weights["
|
|
336
|
-
+ details["
|
|
337
|
-
* weights["content_completeness"]
|
|
338
|
-
+ details["technical_accuracy"]["overall_accuracy"]
|
|
339
|
-
* weights["technical_accuracy"]
|
|
319
|
+
details["ears_compliance"]["overall_compliance"] * weights["ears_compliance"]
|
|
320
|
+
+ details["content_completeness"]["overall_completeness"] * weights["content_completeness"]
|
|
321
|
+
+ details["technical_accuracy"]["overall_accuracy"] * weights["technical_accuracy"]
|
|
340
322
|
+ details["clarity_score"]["overall_clarity"] * weights["clarity_score"]
|
|
341
323
|
+ details["traceability"]["overall_traceability"] * weights["traceability"]
|
|
342
324
|
)
|
|
@@ -359,9 +341,7 @@ class QualityValidator:
|
|
|
359
341
|
def _check_quality_standards(self, validation_result: Dict[str, Any]) -> bool:
|
|
360
342
|
"""Check if SPEC meets minimum quality standards."""
|
|
361
343
|
overall_score = validation_result["overall_score"]
|
|
362
|
-
ears_compliance = validation_result["details"]["ears_compliance"][
|
|
363
|
-
"overall_compliance"
|
|
364
|
-
]
|
|
344
|
+
ears_compliance = validation_result["details"]["ears_compliance"]["overall_compliance"]
|
|
365
345
|
|
|
366
346
|
meets_overall = overall_score >= self.min_confidence_score
|
|
367
347
|
meets_ears = ears_compliance >= self.min_ears_compliance
|
|
@@ -376,15 +356,11 @@ class QualityValidator:
|
|
|
376
356
|
# EARS compliance recommendations
|
|
377
357
|
if details["ears_compliance"]["overall_compliance"] < 1.0:
|
|
378
358
|
missing = details["ears_compliance"]["missing_sections"]
|
|
379
|
-
recommendations.append(
|
|
380
|
-
f"Add missing EARS sections: {', '.join(missing[:3])}"
|
|
381
|
-
)
|
|
359
|
+
recommendations.append(f"Add missing EARS sections: {', '.join(missing[:3])}")
|
|
382
360
|
|
|
383
361
|
# Content completeness recommendations
|
|
384
362
|
if details["content_completeness"]["overall_completeness"] < 0.8:
|
|
385
|
-
recommendations.append(
|
|
386
|
-
"Expand content sections with more detailed requirements"
|
|
387
|
-
)
|
|
363
|
+
recommendations.append("Expand content sections with more detailed requirements")
|
|
388
364
|
|
|
389
365
|
# Technical accuracy recommendations
|
|
390
366
|
if details["technical_accuracy"]["overall_accuracy"] < 0.8:
|
|
@@ -494,9 +470,7 @@ class QualityValidator:
|
|
|
494
470
|
|
|
495
471
|
return min(score, 1.0)
|
|
496
472
|
|
|
497
|
-
def _assess_acceptance_criteria_completeness(
|
|
498
|
-
self, acceptance_content: str
|
|
499
|
-
) -> float:
|
|
473
|
+
def _assess_acceptance_criteria_completeness(self, acceptance_content: str) -> float:
|
|
500
474
|
"""Assess completeness of acceptance criteria."""
|
|
501
475
|
if not acceptance_content:
|
|
502
476
|
return 0.0
|
|
@@ -526,9 +500,7 @@ class QualityValidator:
|
|
|
526
500
|
|
|
527
501
|
return len(found_keywords) / len(keywords)
|
|
528
502
|
|
|
529
|
-
def _check_code_consistency(
|
|
530
|
-
self, spec_md: str, code_analysis: Dict[str, Any]
|
|
531
|
-
) -> float:
|
|
503
|
+
def _check_code_consistency(self, spec_md: str, code_analysis: Dict[str, Any]) -> float:
|
|
532
504
|
"""Check consistency between SPEC and code analysis."""
|
|
533
505
|
# Extract key elements from code analysis
|
|
534
506
|
classes = code_analysis.get("structure_info", {}).get("classes", [])
|
|
@@ -590,9 +562,7 @@ class QualityValidator:
|
|
|
590
562
|
r"Relevant",
|
|
591
563
|
]
|
|
592
564
|
|
|
593
|
-
found_indicators = sum(
|
|
594
|
-
1 for indicator in clarity_indicators if re.search(indicator, spec_md)
|
|
595
|
-
)
|
|
565
|
+
found_indicators = sum(1 for indicator in clarity_indicators if re.search(indicator, spec_md))
|
|
596
566
|
|
|
597
567
|
return min(found_indicators / len(clarity_indicators), 1.0)
|
|
598
568
|
|
|
@@ -606,9 +576,7 @@ class QualityValidator:
|
|
|
606
576
|
r"around",
|
|
607
577
|
]
|
|
608
578
|
|
|
609
|
-
ambiguous_count = sum(
|
|
610
|
-
1 for indicator in ambiguity_indicators if re.search(indicator, spec_md)
|
|
611
|
-
)
|
|
579
|
+
ambiguous_count = sum(1 for indicator in ambiguity_indicators if re.search(indicator, spec_md))
|
|
612
580
|
|
|
613
581
|
# Normalize by content length
|
|
614
582
|
content_length = len(spec_md.split())
|
|
@@ -633,7 +601,7 @@ class QualityValidator:
|
|
|
633
601
|
|
|
634
602
|
def _check_traceability_tags(self, spec_md: str) -> bool:
|
|
635
603
|
"""Check for traceability tags."""
|
|
636
|
-
return any(tag in spec_md for tag in
|
|
604
|
+
return any(tag in spec_md for tag in TRACEABILITY_TAGS)
|
|
637
605
|
|
|
638
606
|
def _check_tag_formatting(self, spec_md: str) -> float:
|
|
639
607
|
"""Check proper tag formatting."""
|
|
@@ -659,9 +627,7 @@ class QualityValidator:
|
|
|
659
627
|
r"Trace",
|
|
660
628
|
]
|
|
661
629
|
|
|
662
|
-
found_indicators = sum(
|
|
663
|
-
1 for indicator in traceability_indicators if re.search(indicator, spec_md)
|
|
664
|
-
)
|
|
630
|
+
found_indicators = sum(1 for indicator in traceability_indicators if re.search(indicator, spec_md))
|
|
665
631
|
|
|
666
632
|
return min(found_indicators / len(traceability_indicators), 1.0)
|
|
667
633
|
|
|
@@ -691,14 +657,14 @@ class QualityValidator:
|
|
|
691
657
|
report = f"""
|
|
692
658
|
# Quality Validation Report
|
|
693
659
|
|
|
694
|
-
## Overall Quality Score: {validation_result[
|
|
695
|
-
## Quality Grade: {validation_result[
|
|
696
|
-
## Validation Time: {validation_result[
|
|
660
|
+
## Overall Quality Score: {validation_result["overall_score"]:.2f}/1.0
|
|
661
|
+
## Quality Grade: {validation_result["quality_grade"]}
|
|
662
|
+
## Validation Time: {validation_result["validation_time"]:.2f}s
|
|
697
663
|
|
|
698
664
|
## Summary
|
|
699
|
-
- Passed Checks: {len(validation_result[
|
|
700
|
-
- Failed Checks: {len(validation_result[
|
|
701
|
-
- Recommendations: {len(validation_result[
|
|
665
|
+
- Passed Checks: {len(validation_result["passed_checks"])}
|
|
666
|
+
- Failed Checks: {len(validation_result["failed_checks"])}
|
|
667
|
+
- Recommendations: {len(validation_result["recommendations"])}
|
|
702
668
|
|
|
703
669
|
## Detailed Metrics
|
|
704
670
|
"""
|
|
@@ -8,9 +8,9 @@ import logging
|
|
|
8
8
|
import re
|
|
9
9
|
from datetime import datetime
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Dict, Set
|
|
11
|
+
from typing import Any, Dict, List, Set
|
|
12
12
|
|
|
13
|
-
import yaml
|
|
13
|
+
import yaml # type: ignore
|
|
14
14
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
@@ -43,7 +43,7 @@ class SpecStatusManager:
|
|
|
43
43
|
Returns:
|
|
44
44
|
Set of SPEC IDs that have draft status
|
|
45
45
|
"""
|
|
46
|
-
draft_specs = set()
|
|
46
|
+
draft_specs: Set[str] = set()
|
|
47
47
|
|
|
48
48
|
if not self.specs_dir.exists():
|
|
49
49
|
logger.warning(f"SPEC directory not found: {self.specs_dir}")
|
|
@@ -61,9 +61,7 @@ class SpecStatusManager:
|
|
|
61
61
|
frontmatter = None
|
|
62
62
|
|
|
63
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
|
-
)
|
|
64
|
+
meta_match = re.search(r"<%?\s*---\s*\n(.*?)\n---\s*%?>", content, re.DOTALL)
|
|
67
65
|
if meta_match:
|
|
68
66
|
try:
|
|
69
67
|
meta_text = meta_match.group(1)
|
|
@@ -71,9 +69,7 @@ class SpecStatusManager:
|
|
|
71
69
|
meta_text = meta_text.replace('"', "").replace("'", "")
|
|
72
70
|
frontmatter = yaml.safe_load("{" + meta_text + "}")
|
|
73
71
|
except Exception as e:
|
|
74
|
-
logger.debug(
|
|
75
|
-
f"JSON meta parsing failed for {spec_dir.name}: {e}"
|
|
76
|
-
)
|
|
72
|
+
logger.debug(f"JSON meta parsing failed for {spec_dir.name}: {e}")
|
|
77
73
|
|
|
78
74
|
# Handle regular YAML frontmatter
|
|
79
75
|
elif content.startswith("---"):
|
|
@@ -83,9 +79,7 @@ class SpecStatusManager:
|
|
|
83
79
|
try:
|
|
84
80
|
frontmatter = yaml.safe_load(frontmatter_text)
|
|
85
81
|
except yaml.YAMLError as e:
|
|
86
|
-
logger.warning(
|
|
87
|
-
f"YAML parsing error for {spec_dir.name}: {e}"
|
|
88
|
-
)
|
|
82
|
+
logger.warning(f"YAML parsing error for {spec_dir.name}: {e}")
|
|
89
83
|
# Try to fix common issues (like @ in author field)
|
|
90
84
|
try:
|
|
91
85
|
# Replace problematic @author entries
|
|
@@ -97,10 +91,8 @@ class SpecStatusManager:
|
|
|
97
91
|
fixed_text,
|
|
98
92
|
)
|
|
99
93
|
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
|
-
)
|
|
94
|
+
except yaml.YAMLError:
|
|
95
|
+
logger.error(f"Could not parse YAML for {spec_dir.name} even after fixes")
|
|
104
96
|
continue
|
|
105
97
|
|
|
106
98
|
if frontmatter and frontmatter.get("status") == "draft":
|
|
@@ -135,19 +127,11 @@ class SpecStatusManager:
|
|
|
135
127
|
spec_dir = spec_file.parent
|
|
136
128
|
|
|
137
129
|
# Check for implementation files
|
|
138
|
-
src_files = (
|
|
139
|
-
list(spec_dir.rglob("*.py"))
|
|
140
|
-
if (spec_dir.parent.parent / "src").exists()
|
|
141
|
-
else []
|
|
142
|
-
)
|
|
130
|
+
src_files = list(spec_dir.rglob("*.py")) if (spec_dir.parent.parent / "src").exists() else []
|
|
143
131
|
|
|
144
132
|
# Check for test files
|
|
145
133
|
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
|
-
)
|
|
134
|
+
test_files = list(test_dir.rglob(f"test_*{spec_id.lower()}*.py")) if test_dir.exists() else []
|
|
151
135
|
|
|
152
136
|
# Simple completion criteria
|
|
153
137
|
has_code = len(src_files) > 0
|
|
@@ -161,9 +145,7 @@ class SpecStatusManager:
|
|
|
161
145
|
# Overall completion check
|
|
162
146
|
is_complete = has_code and has_tests and has_acceptance_criteria
|
|
163
147
|
|
|
164
|
-
logger.info(
|
|
165
|
-
f"SPEC {spec_id} implementation status: {'COMPLETE' if is_complete else 'INCOMPLETE'}"
|
|
166
|
-
)
|
|
148
|
+
logger.info(f"SPEC {spec_id} implementation status: {'COMPLETE' if is_complete else 'INCOMPLETE'}")
|
|
167
149
|
return is_complete
|
|
168
150
|
|
|
169
151
|
except Exception as e:
|
|
@@ -204,14 +186,10 @@ class SpecStatusManager:
|
|
|
204
186
|
try:
|
|
205
187
|
fixed_text = frontmatter_text
|
|
206
188
|
if "author: @" in fixed_text:
|
|
207
|
-
fixed_text = re.sub(
|
|
208
|
-
r"author:\s*@(\w+)", r'author: "\1"', fixed_text
|
|
209
|
-
)
|
|
189
|
+
fixed_text = re.sub(r"author:\s*@(\w+)", r'author: "\1"', fixed_text)
|
|
210
190
|
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
|
-
)
|
|
191
|
+
except yaml.YAMLError:
|
|
192
|
+
logger.error(f"Could not parse YAML for {spec_id} even after fixes")
|
|
215
193
|
return False
|
|
216
194
|
|
|
217
195
|
# Update status
|
|
@@ -219,14 +197,12 @@ class SpecStatusManager:
|
|
|
219
197
|
|
|
220
198
|
# Bump version if completing
|
|
221
199
|
if new_status == "completed":
|
|
222
|
-
frontmatter["version"] = self._bump_version(
|
|
223
|
-
frontmatter.get("version", "0.1.0")
|
|
224
|
-
)
|
|
200
|
+
frontmatter["version"] = self._bump_version(frontmatter.get("version", "0.1.0"))
|
|
225
201
|
frontmatter["updated"] = datetime.now().strftime("%Y-%m-%d")
|
|
226
202
|
|
|
227
203
|
# Reconstruct the file
|
|
228
204
|
new_frontmatter = yaml.dump(frontmatter, default_flow_style=False)
|
|
229
|
-
new_content = f"---\n{new_frontmatter}---{content[end_marker+3:]}"
|
|
205
|
+
new_content = f"---\n{new_frontmatter}---{content[end_marker + 3 :]}"
|
|
230
206
|
|
|
231
207
|
# Write back to file
|
|
232
208
|
with open(spec_file, "w", encoding="utf-8") as f:
|
|
@@ -247,7 +223,7 @@ class SpecStatusManager:
|
|
|
247
223
|
"""
|
|
248
224
|
return self.validation_criteria.copy()
|
|
249
225
|
|
|
250
|
-
def validate_spec_for_completion(self, spec_id: str) -> Dict:
|
|
226
|
+
def validate_spec_for_completion(self, spec_id: str) -> Dict[str, Any]:
|
|
251
227
|
"""Validate if a SPEC is ready for completion
|
|
252
228
|
|
|
253
229
|
Args:
|
|
@@ -262,7 +238,7 @@ class SpecStatusManager:
|
|
|
262
238
|
'recommendations': List[str]
|
|
263
239
|
}
|
|
264
240
|
"""
|
|
265
|
-
result = {
|
|
241
|
+
result: Dict[str, Any] = {
|
|
266
242
|
"is_ready": False,
|
|
267
243
|
"criteria_met": {},
|
|
268
244
|
"issues": [],
|
|
@@ -274,68 +250,74 @@ class SpecStatusManager:
|
|
|
274
250
|
spec_file = spec_dir / "spec.md"
|
|
275
251
|
|
|
276
252
|
if not spec_file.exists():
|
|
277
|
-
result["issues"]
|
|
253
|
+
issues_list = result["issues"]
|
|
254
|
+
if isinstance(issues_list, list):
|
|
255
|
+
issues_list.append(f"SPEC file not found: {spec_file}")
|
|
278
256
|
return result
|
|
279
257
|
|
|
280
258
|
# Check implementation status
|
|
281
|
-
criteria_checks = {}
|
|
259
|
+
criteria_checks: Dict[str, bool] = {}
|
|
282
260
|
|
|
283
261
|
# Check for code implementation
|
|
284
262
|
spec_dir = spec_file.parent
|
|
285
263
|
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
|
-
)
|
|
264
|
+
criteria_checks["code_implemented"] = src_dir.exists() and len(list(src_dir.rglob("*.py"))) > 0
|
|
289
265
|
if not criteria_checks["code_implemented"]:
|
|
290
|
-
result["issues"]
|
|
266
|
+
issues_list = result["issues"]
|
|
267
|
+
if isinstance(issues_list, list):
|
|
268
|
+
issues_list.append("No source code files found")
|
|
291
269
|
|
|
292
270
|
# Check for test implementation
|
|
293
271
|
test_dir = spec_dir.parent.parent / "tests"
|
|
294
272
|
test_files = list(test_dir.rglob("test_*.py")) if test_dir.exists() else []
|
|
295
273
|
criteria_checks["test_implemented"] = len(test_files) > 0
|
|
296
274
|
if not criteria_checks["test_implemented"]:
|
|
297
|
-
result["issues"]
|
|
275
|
+
issues_list = result["issues"]
|
|
276
|
+
if isinstance(issues_list, list):
|
|
277
|
+
issues_list.append("No test files found")
|
|
298
278
|
|
|
299
279
|
# Check for acceptance criteria
|
|
300
|
-
criteria_checks["tasks_completed"] = self._check_acceptance_criteria(
|
|
301
|
-
spec_file
|
|
302
|
-
)
|
|
280
|
+
criteria_checks["tasks_completed"] = self._check_acceptance_criteria(spec_file)
|
|
303
281
|
if not criteria_checks["tasks_completed"]:
|
|
304
|
-
result["issues"]
|
|
282
|
+
issues_list = result["issues"]
|
|
283
|
+
if isinstance(issues_list, list):
|
|
284
|
+
issues_list.append("Missing acceptance criteria section")
|
|
305
285
|
|
|
306
286
|
# 4. Acceptance criteria present
|
|
307
|
-
criteria_checks["has_acceptance_criteria"] = (
|
|
308
|
-
self._check_acceptance_criteria(spec_file)
|
|
309
|
-
)
|
|
287
|
+
criteria_checks["has_acceptance_criteria"] = self._check_acceptance_criteria(spec_file)
|
|
310
288
|
if (
|
|
311
289
|
not criteria_checks["has_acceptance_criteria"]
|
|
312
290
|
and self.validation_criteria["require_acceptance_criteria"]
|
|
313
291
|
):
|
|
314
|
-
result["issues"]
|
|
292
|
+
issues_list = result["issues"]
|
|
293
|
+
if isinstance(issues_list, list):
|
|
294
|
+
issues_list.append("Missing acceptance criteria section")
|
|
315
295
|
|
|
316
296
|
# 5. Documentation sync
|
|
317
297
|
criteria_checks["docs_synced"] = self._check_documentation_sync(spec_id)
|
|
318
298
|
if not criteria_checks["docs_synced"]:
|
|
319
|
-
result["recommendations"]
|
|
320
|
-
|
|
321
|
-
|
|
299
|
+
recs_list = result["recommendations"]
|
|
300
|
+
if isinstance(recs_list, list):
|
|
301
|
+
recs_list.append("Consider running /moai:3-sync to update documentation")
|
|
322
302
|
|
|
323
303
|
result["criteria_met"] = criteria_checks
|
|
324
304
|
result["is_ready"] = all(criteria_checks.values())
|
|
325
305
|
|
|
326
306
|
# Add recommendations
|
|
327
307
|
if result["is_ready"]:
|
|
328
|
-
result["recommendations"]
|
|
329
|
-
|
|
330
|
-
|
|
308
|
+
recs_list = result["recommendations"]
|
|
309
|
+
if isinstance(recs_list, list):
|
|
310
|
+
recs_list.append("SPEC is ready for completion. Consider updating status to 'completed'")
|
|
331
311
|
|
|
332
312
|
except Exception as e:
|
|
333
313
|
logger.error(f"Error validating SPEC {spec_id}: {e}")
|
|
334
|
-
result["issues"]
|
|
314
|
+
issues_list = result["issues"]
|
|
315
|
+
if isinstance(issues_list, list):
|
|
316
|
+
issues_list.append(f"Validation error: {e}")
|
|
335
317
|
|
|
336
318
|
return result
|
|
337
319
|
|
|
338
|
-
def batch_update_completed_specs(self) -> Dict:
|
|
320
|
+
def batch_update_completed_specs(self) -> Dict[str, List[str]]:
|
|
339
321
|
"""Batch update all draft SPECs that have completed implementations
|
|
340
322
|
|
|
341
323
|
Returns:
|
|
@@ -346,7 +328,7 @@ class SpecStatusManager:
|
|
|
346
328
|
'skipped': List[str] # Incomplete SPEC IDs
|
|
347
329
|
}
|
|
348
330
|
"""
|
|
349
|
-
results = {"updated": [], "failed": [], "skipped": []}
|
|
331
|
+
results: Dict[str, List[str]] = {"updated": [], "failed": [], "skipped": []}
|
|
350
332
|
|
|
351
333
|
draft_specs = self.detect_draft_specs()
|
|
352
334
|
logger.info(f"Checking {len(draft_specs)} draft SPECs for completion")
|
|
@@ -359,23 +341,31 @@ class SpecStatusManager:
|
|
|
359
341
|
if validation["is_ready"]:
|
|
360
342
|
# Update status
|
|
361
343
|
if self.update_spec_status(spec_id, "completed"):
|
|
362
|
-
results["updated"]
|
|
344
|
+
updated_list = results["updated"]
|
|
345
|
+
if isinstance(updated_list, list):
|
|
346
|
+
updated_list.append(spec_id)
|
|
363
347
|
logger.info(f"Updated SPEC {spec_id} to completed")
|
|
364
348
|
else:
|
|
365
|
-
results["failed"]
|
|
349
|
+
failed_list = results["failed"]
|
|
350
|
+
if isinstance(failed_list, list):
|
|
351
|
+
failed_list.append(spec_id)
|
|
366
352
|
logger.error(f"Failed to update SPEC {spec_id}")
|
|
367
353
|
else:
|
|
368
|
-
results["skipped"]
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
)
|
|
354
|
+
skipped_list = results["skipped"]
|
|
355
|
+
if isinstance(skipped_list, list):
|
|
356
|
+
skipped_list.append(spec_id)
|
|
357
|
+
logger.debug(f"SPEC {spec_id} not ready for completion: {validation['issues']}")
|
|
372
358
|
|
|
373
359
|
except Exception as e:
|
|
374
|
-
results["failed"]
|
|
360
|
+
failed_list = results["failed"]
|
|
361
|
+
if isinstance(failed_list, list):
|
|
362
|
+
failed_list.append(spec_id)
|
|
375
363
|
logger.error(f"Error processing SPEC {spec_id}: {e}")
|
|
376
364
|
|
|
377
365
|
logger.info(
|
|
378
|
-
f"Batch update complete: {len(results['updated'])} updated,
|
|
366
|
+
f"Batch update complete: {len(results['updated'])} updated, "
|
|
367
|
+
f"{len(results['failed'])} failed, "
|
|
368
|
+
f"{len(results['skipped'])} skipped"
|
|
379
369
|
)
|
|
380
370
|
return results
|
|
381
371
|
|
moai_adk/core/template/backup.py
CHANGED
|
@@ -5,7 +5,9 @@ Creates and manages backups to protect user data during template updates.
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import re
|
|
8
9
|
import shutil
|
|
10
|
+
from datetime import datetime
|
|
9
11
|
from pathlib import Path
|
|
10
12
|
|
|
11
13
|
|
|
@@ -41,24 +43,20 @@ class TemplateBackup:
|
|
|
41
43
|
Returns:
|
|
42
44
|
True when any tracked file exists.
|
|
43
45
|
"""
|
|
44
|
-
return any(
|
|
45
|
-
(self.target_path / item).exists()
|
|
46
|
-
for item in [".moai", ".claude", ".github", "CLAUDE.md"]
|
|
47
|
-
)
|
|
46
|
+
return any((self.target_path / item).exists() for item in [".moai", ".claude", ".github", "CLAUDE.md"])
|
|
48
47
|
|
|
49
48
|
def create_backup(self) -> Path:
|
|
50
|
-
"""Create a
|
|
49
|
+
"""Create a timestamped backup under .moai-backups/.
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
Creates a new timestamped backup directory for each update.
|
|
52
|
+
Maintains backward compatibility by supporting both new and legacy structures.
|
|
53
53
|
|
|
54
54
|
Returns:
|
|
55
|
-
|
|
55
|
+
Path to timestamped backup directory (e.g., .moai-backups/20241201_143022/).
|
|
56
56
|
"""
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if backup_path.exists():
|
|
61
|
-
shutil.rmtree(backup_path)
|
|
57
|
+
# Generate timestamp for backup directory name
|
|
58
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
59
|
+
backup_path = self.target_path / ".moai-backups" / timestamp
|
|
62
60
|
|
|
63
61
|
backup_path.mkdir(parents=True, exist_ok=True)
|
|
64
62
|
|
|
@@ -80,6 +78,35 @@ class TemplateBackup:
|
|
|
80
78
|
|
|
81
79
|
return backup_path
|
|
82
80
|
|
|
81
|
+
def get_latest_backup(self) -> Path | None:
|
|
82
|
+
"""Get the most recent backup, supporting both new and legacy structures.
|
|
83
|
+
|
|
84
|
+
Searches for backups in order of preference:
|
|
85
|
+
1. Latest timestamped backup (new structure)
|
|
86
|
+
2. Legacy backup/ directory (old structure)
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Path to the most recent backup directory, or None if no backups exist.
|
|
90
|
+
"""
|
|
91
|
+
# Check for new timestamped backups first
|
|
92
|
+
backup_dir = self.target_path / ".moai-backups"
|
|
93
|
+
if backup_dir.exists():
|
|
94
|
+
# Match pattern: YYYYMMDD_HHMMSS (8 digits + underscore + 6 digits)
|
|
95
|
+
timestamp_pattern = re.compile(r"^\d{8}_\d{6}$")
|
|
96
|
+
timestamped_backups = [d for d in backup_dir.iterdir() if d.is_dir() and timestamp_pattern.match(d.name)]
|
|
97
|
+
|
|
98
|
+
if timestamped_backups:
|
|
99
|
+
# Sort by name (timestamp) and return the latest
|
|
100
|
+
latest_backup = max(timestamped_backups, key=lambda x: x.name)
|
|
101
|
+
return latest_backup
|
|
102
|
+
|
|
103
|
+
# Fall back to legacy backup/ directory
|
|
104
|
+
legacy_backup = backup_dir / "backup"
|
|
105
|
+
if legacy_backup.exists():
|
|
106
|
+
return legacy_backup
|
|
107
|
+
|
|
108
|
+
return None
|
|
109
|
+
|
|
83
110
|
def _copy_exclude_protected(self, src: Path, dst: Path) -> None:
|
|
84
111
|
"""Copy backup content while excluding protected paths.
|
|
85
112
|
|
|
@@ -94,10 +121,7 @@ class TemplateBackup:
|
|
|
94
121
|
rel_path_str = str(rel_path)
|
|
95
122
|
|
|
96
123
|
# Skip excluded paths
|
|
97
|
-
if any(
|
|
98
|
-
rel_path_str.startswith(exclude_dir)
|
|
99
|
-
for exclude_dir in self.BACKUP_EXCLUDE_DIRS
|
|
100
|
-
):
|
|
124
|
+
if any(rel_path_str.startswith(exclude_dir) for exclude_dir in self.BACKUP_EXCLUDE_DIRS):
|
|
101
125
|
continue
|
|
102
126
|
|
|
103
127
|
dst_item = dst / rel_path
|
|
@@ -112,18 +136,19 @@ class TemplateBackup:
|
|
|
112
136
|
|
|
113
137
|
Restores .moai, .claude, .github directories and CLAUDE.md file
|
|
114
138
|
from a backup created by create_backup().
|
|
139
|
+
Supports both new timestamped and legacy backup structures.
|
|
115
140
|
|
|
116
141
|
Args:
|
|
117
142
|
backup_path: Backup path to restore from.
|
|
118
|
-
|
|
143
|
+
If None, automatically finds the latest backup.
|
|
119
144
|
|
|
120
145
|
Raises:
|
|
121
|
-
FileNotFoundError: When
|
|
146
|
+
FileNotFoundError: When no backup is found.
|
|
122
147
|
"""
|
|
123
148
|
if backup_path is None:
|
|
124
|
-
backup_path = self.
|
|
149
|
+
backup_path = self.get_latest_backup()
|
|
125
150
|
|
|
126
|
-
if not backup_path.exists():
|
|
151
|
+
if backup_path is None or not backup_path.exists():
|
|
127
152
|
raise FileNotFoundError(f"Backup not found: {backup_path}")
|
|
128
153
|
|
|
129
154
|
# Restore each item from backup
|