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
|
@@ -20,7 +20,7 @@ class AutoSpecConfig:
|
|
|
20
20
|
def __init__(self, config_path: str = None):
|
|
21
21
|
"""Initialize the configuration reader."""
|
|
22
22
|
self.config_path = config_path or self._get_default_config_path()
|
|
23
|
-
self.config = {}
|
|
23
|
+
self.config: dict[str, Any] = {}
|
|
24
24
|
self.load_config()
|
|
25
25
|
|
|
26
26
|
def _get_default_config_path(self) -> str:
|
|
@@ -48,9 +48,7 @@ class AutoSpecConfig:
|
|
|
48
48
|
# Extract auto-spec completion config
|
|
49
49
|
self.config = self.config.get("auto_spec_completion", {})
|
|
50
50
|
|
|
51
|
-
logger.info(
|
|
52
|
-
f"Loaded auto-spec completion configuration from {self.config_path}"
|
|
53
|
-
)
|
|
51
|
+
logger.info(f"Loaded auto-spec completion configuration from {self.config_path}")
|
|
54
52
|
|
|
55
53
|
except FileNotFoundError:
|
|
56
54
|
logger.warning(f"Configuration file not found: {self.config_path}")
|
|
@@ -174,7 +172,7 @@ class AutoSpecConfig:
|
|
|
174
172
|
|
|
175
173
|
for pattern in excluded_patterns:
|
|
176
174
|
# Convert pattern to lowercase for case-insensitive matching
|
|
177
|
-
|
|
175
|
+
pattern.lower()
|
|
178
176
|
|
|
179
177
|
# Handle directory patterns
|
|
180
178
|
if pattern.startswith("*/") and pattern.endswith("/*"):
|
|
@@ -300,9 +298,7 @@ class AutoSpecConfig:
|
|
|
300
298
|
if not isinstance(quality_threshold["ears_compliance"], (int, float)):
|
|
301
299
|
errors.append("quality_threshold.ears_compliance must be a number")
|
|
302
300
|
elif not 0 <= quality_threshold["ears_compliance"] <= 1:
|
|
303
|
-
errors.append(
|
|
304
|
-
"quality_threshold.ears_compliance must be between 0 and 1"
|
|
305
|
-
)
|
|
301
|
+
errors.append("quality_threshold.ears_compliance must be between 0 and 1")
|
|
306
302
|
|
|
307
303
|
return errors
|
|
308
304
|
|
|
@@ -329,9 +325,7 @@ class AutoSpecConfig:
|
|
|
329
325
|
with open(self.config_path, "w", encoding="utf-8") as f:
|
|
330
326
|
json.dump(full_config, f, indent=2, ensure_ascii=False)
|
|
331
327
|
|
|
332
|
-
logger.info(
|
|
333
|
-
f"Saved auto-spec completion configuration to {self.config_path}"
|
|
334
|
-
)
|
|
328
|
+
logger.info(f"Saved auto-spec completion configuration to {self.config_path}")
|
|
335
329
|
|
|
336
330
|
except Exception as e:
|
|
337
331
|
logger.error(f"Error saving configuration: {e}")
|
|
@@ -39,9 +39,7 @@ def migrate_config_to_nested_structure(config: dict[str, Any]) -> dict[str, Any]
|
|
|
39
39
|
from ..language_config import LANGUAGE_CONFIG
|
|
40
40
|
|
|
41
41
|
# Extract language names from enhanced config
|
|
42
|
-
language_names = {
|
|
43
|
-
code: info["native_name"] for code, info in LANGUAGE_CONFIG.items()
|
|
44
|
-
}
|
|
42
|
+
language_names = {code: info["native_name"] for code, info in LANGUAGE_CONFIG.items()}
|
|
45
43
|
|
|
46
44
|
language_name = language_names.get(conversation_language, "English")
|
|
47
45
|
|
|
@@ -51,6 +49,22 @@ def migrate_config_to_nested_structure(config: dict[str, Any]) -> dict[str, Any]
|
|
|
51
49
|
"conversation_language_name": language_name,
|
|
52
50
|
}
|
|
53
51
|
|
|
52
|
+
# 2. Language settings migration
|
|
53
|
+
# Old: "language": "ko"
|
|
54
|
+
# New: "language": {"conversation_language": "ko", "conversation_language_name": "Korean"}
|
|
55
|
+
if "language" in config and isinstance(config["language"], str):
|
|
56
|
+
old_lang = config["language"]
|
|
57
|
+
lang_names = {
|
|
58
|
+
"ko": "Korean",
|
|
59
|
+
"en": "English",
|
|
60
|
+
"ja": "Japanese",
|
|
61
|
+
"zh": "Chinese",
|
|
62
|
+
}
|
|
63
|
+
config["language"] = {
|
|
64
|
+
"conversation_language": old_lang,
|
|
65
|
+
"conversation_language_name": lang_names.get(old_lang, "English"),
|
|
66
|
+
}
|
|
67
|
+
|
|
54
68
|
return config
|
|
55
69
|
|
|
56
70
|
|
|
@@ -106,9 +120,7 @@ def get_conversation_language_name(config: dict[str, Any]) -> str:
|
|
|
106
120
|
from ..language_config import LANGUAGE_CONFIG
|
|
107
121
|
|
|
108
122
|
# Extract language names from enhanced config
|
|
109
|
-
language_names = {
|
|
110
|
-
code: info["native_name"] for code, info in LANGUAGE_CONFIG.items()
|
|
111
|
-
}
|
|
123
|
+
language_names = {code: info["native_name"] for code, info in LANGUAGE_CONFIG.items()}
|
|
112
124
|
return language_names.get(language_code, "English")
|
|
113
125
|
|
|
114
126
|
|
|
@@ -164,9 +176,7 @@ def migrate_config_schema_v0_17_0(config: dict[str, Any]) -> dict[str, Any]:
|
|
|
164
176
|
if "spec_git_workflow" not in github_config:
|
|
165
177
|
github_config["spec_git_workflow"] = "per_spec"
|
|
166
178
|
github_config["spec_git_workflow_configured"] = False
|
|
167
|
-
github_config["spec_git_workflow_rationale"] = (
|
|
168
|
-
"Ask per SPEC (flexible, user controls each workflow)"
|
|
169
|
-
)
|
|
179
|
+
github_config["spec_git_workflow_rationale"] = "Ask per SPEC (flexible, user controls each workflow)"
|
|
170
180
|
|
|
171
181
|
# Add notes for new fields if missing
|
|
172
182
|
if "notes_new_fields" not in github_config:
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified Configuration Manager for MoAI-ADK
|
|
3
|
+
|
|
4
|
+
Thread-safe singleton configuration manager that consolidates all config management
|
|
5
|
+
patterns from across the codebase into a single, robust implementation.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Thread-safe singleton with double-checked locking
|
|
9
|
+
- Lazy loading with in-memory caching
|
|
10
|
+
- Atomic writes with backup creation
|
|
11
|
+
- Schema validation support
|
|
12
|
+
- Smart defaults with auto-detection
|
|
13
|
+
- Deep merge for nested configs
|
|
14
|
+
- Configuration migration between versions
|
|
15
|
+
- Domain-specific facades for different subsystems
|
|
16
|
+
|
|
17
|
+
Design Philosophy:
|
|
18
|
+
- Single source of truth for `.moai/config/config.yaml` (with JSON fallback)
|
|
19
|
+
- Best patterns from StatuslineConfig, UnifiedConfigManager, ConfigurationManager
|
|
20
|
+
- Backward compatible with existing ConfigManager interfaces
|
|
21
|
+
- Performance optimized with caching and minimal I/O
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
>>> from moai_adk.core.config.unified import get_unified_config
|
|
25
|
+
>>> config = get_unified_config()
|
|
26
|
+
>>> timeout = config.get("hooks.timeout_ms", 2000)
|
|
27
|
+
>>> config.update({"hooks.timeout_ms": 3000})
|
|
28
|
+
>>> config.save()
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
import json
|
|
32
|
+
import logging
|
|
33
|
+
import shutil
|
|
34
|
+
import threading
|
|
35
|
+
from datetime import datetime
|
|
36
|
+
from functools import lru_cache
|
|
37
|
+
from pathlib import Path
|
|
38
|
+
from typing import Any, Dict, Optional, Union
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
import yaml
|
|
42
|
+
|
|
43
|
+
YAML_AVAILABLE = True
|
|
44
|
+
except ImportError:
|
|
45
|
+
YAML_AVAILABLE = False
|
|
46
|
+
|
|
47
|
+
logger = logging.getLogger(__name__)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class UnifiedConfigManager:
|
|
51
|
+
"""
|
|
52
|
+
Thread-safe singleton configuration manager for MoAI-ADK.
|
|
53
|
+
|
|
54
|
+
This class consolidates all configuration management patterns from:
|
|
55
|
+
- StatuslineConfig: Thread-safe singleton pattern
|
|
56
|
+
- UnifiedConfigManager (skills): Backup, migration, validation
|
|
57
|
+
- ConfigurationManager (project): Smart defaults, auto-detection
|
|
58
|
+
- ConfigManager (hooks): Convenience functions
|
|
59
|
+
|
|
60
|
+
Attributes:
|
|
61
|
+
_instance: Singleton instance
|
|
62
|
+
_config: Cached configuration dictionary
|
|
63
|
+
_lock: Thread lock for singleton pattern
|
|
64
|
+
_config_path: Path to configuration file
|
|
65
|
+
_last_modified: Last modification timestamp for cache invalidation
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
_instance: Optional["UnifiedConfigManager"] = None
|
|
69
|
+
_config: Dict[str, Any] = {}
|
|
70
|
+
_lock = threading.Lock()
|
|
71
|
+
_config_path: Optional[Path] = None
|
|
72
|
+
_last_modified: Optional[float] = None
|
|
73
|
+
|
|
74
|
+
def __new__(cls, config_path: Optional[Union[str, Path]] = None):
|
|
75
|
+
"""
|
|
76
|
+
Create or return singleton instance with double-checked locking.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
config_path: Optional path to config file (default: .moai/config/config.json)
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
UnifiedConfigManager: Singleton instance
|
|
83
|
+
"""
|
|
84
|
+
# Double-checked locking pattern for thread-safe singleton
|
|
85
|
+
if cls._instance is None:
|
|
86
|
+
with cls._lock:
|
|
87
|
+
# Double-check after acquiring lock
|
|
88
|
+
if cls._instance is None:
|
|
89
|
+
cls._instance = super().__new__(cls)
|
|
90
|
+
cls._instance._initialize(config_path)
|
|
91
|
+
return cls._instance
|
|
92
|
+
|
|
93
|
+
def _initialize(self, config_path: Optional[Union[str, Path]] = None) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Initialize configuration manager (called once by singleton).
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
config_path: Optional path to config file
|
|
99
|
+
"""
|
|
100
|
+
# Set config path with auto-detection
|
|
101
|
+
if config_path:
|
|
102
|
+
self._config_path = Path(config_path)
|
|
103
|
+
else:
|
|
104
|
+
# Auto-detect YAML (preferred) or JSON (fallback)
|
|
105
|
+
base_path = Path.cwd() / ".moai" / "config"
|
|
106
|
+
yaml_path = base_path / "config.yaml"
|
|
107
|
+
json_path = base_path / "config.json"
|
|
108
|
+
|
|
109
|
+
if YAML_AVAILABLE and yaml_path.exists():
|
|
110
|
+
self._config_path = yaml_path
|
|
111
|
+
elif json_path.exists():
|
|
112
|
+
self._config_path = json_path
|
|
113
|
+
else:
|
|
114
|
+
# Default to YAML for new projects
|
|
115
|
+
self._config_path = yaml_path if YAML_AVAILABLE else json_path
|
|
116
|
+
|
|
117
|
+
# Load configuration
|
|
118
|
+
self._load_config()
|
|
119
|
+
|
|
120
|
+
def _load_config(self) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Load configuration from file with caching.
|
|
123
|
+
|
|
124
|
+
Implements cache invalidation based on file modification time.
|
|
125
|
+
Falls back to default configuration if file doesn't exist.
|
|
126
|
+
Supports both YAML (preferred) and JSON (legacy) formats.
|
|
127
|
+
"""
|
|
128
|
+
try:
|
|
129
|
+
# Check if file exists
|
|
130
|
+
if not self._config_path.exists():
|
|
131
|
+
logger.warning(f"Config file not found: {self._config_path}")
|
|
132
|
+
self._config = self._get_default_config()
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
# Check cache validity
|
|
136
|
+
current_mtime = self._config_path.stat().st_mtime
|
|
137
|
+
if self._last_modified and current_mtime == self._last_modified:
|
|
138
|
+
# Cache is still valid
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
# Load from file (auto-detect format)
|
|
142
|
+
with open(self._config_path, "r", encoding="utf-8") as f:
|
|
143
|
+
if self._config_path.suffix == ".yaml" or self._config_path.suffix == ".yml":
|
|
144
|
+
if not YAML_AVAILABLE:
|
|
145
|
+
raise ImportError("PyYAML is required for YAML config files. Install with: pip install pyyaml")
|
|
146
|
+
self._config = yaml.safe_load(f) or {}
|
|
147
|
+
else:
|
|
148
|
+
self._config = json.load(f)
|
|
149
|
+
|
|
150
|
+
# Update cache timestamp
|
|
151
|
+
self._last_modified = current_mtime
|
|
152
|
+
|
|
153
|
+
logger.debug(f"Loaded config from {self._config_path}")
|
|
154
|
+
|
|
155
|
+
except (
|
|
156
|
+
json.JSONDecodeError,
|
|
157
|
+
yaml.YAMLError if YAML_AVAILABLE else Exception,
|
|
158
|
+
OSError,
|
|
159
|
+
UnicodeDecodeError,
|
|
160
|
+
) as e:
|
|
161
|
+
logger.error(f"Failed to load config: {e}")
|
|
162
|
+
self._config = self._get_default_config()
|
|
163
|
+
|
|
164
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
165
|
+
"""
|
|
166
|
+
Get configuration value with dot-notation support.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
key: Configuration key (supports dot notation, e.g., "hooks.timeout_ms")
|
|
170
|
+
default: Default value if key not found
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Configuration value or default
|
|
174
|
+
|
|
175
|
+
Examples:
|
|
176
|
+
>>> config.get("hooks.timeout_ms", 2000)
|
|
177
|
+
2000
|
|
178
|
+
>>> config.get("project.name")
|
|
179
|
+
"MoAI-ADK"
|
|
180
|
+
"""
|
|
181
|
+
# Reload if file changed
|
|
182
|
+
self._reload_if_modified()
|
|
183
|
+
|
|
184
|
+
# Navigate nested dict with dot notation
|
|
185
|
+
keys = key.split(".")
|
|
186
|
+
value = self._config
|
|
187
|
+
|
|
188
|
+
for k in keys:
|
|
189
|
+
if isinstance(value, dict):
|
|
190
|
+
value = value.get(k)
|
|
191
|
+
if value is None:
|
|
192
|
+
return default
|
|
193
|
+
else:
|
|
194
|
+
return default
|
|
195
|
+
|
|
196
|
+
return value if value is not None else default
|
|
197
|
+
|
|
198
|
+
def set(self, key: str, value: Any) -> None:
|
|
199
|
+
"""
|
|
200
|
+
Set configuration value with dot-notation support.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
key: Configuration key (supports dot notation)
|
|
204
|
+
value: Value to set
|
|
205
|
+
|
|
206
|
+
Examples:
|
|
207
|
+
>>> config.set("hooks.timeout_ms", 3000)
|
|
208
|
+
>>> config.set("project.name", "MyProject")
|
|
209
|
+
"""
|
|
210
|
+
# Navigate to parent dict
|
|
211
|
+
keys = key.split(".")
|
|
212
|
+
target = self._config
|
|
213
|
+
|
|
214
|
+
for k in keys[:-1]:
|
|
215
|
+
if k not in target:
|
|
216
|
+
target[k] = {}
|
|
217
|
+
target = target[k]
|
|
218
|
+
|
|
219
|
+
# Set value
|
|
220
|
+
target[keys[-1]] = value
|
|
221
|
+
|
|
222
|
+
def update(self, updates: Dict[str, Any], deep_merge: bool = True) -> None:
|
|
223
|
+
"""
|
|
224
|
+
Update configuration with dictionary.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
updates: Dictionary of updates
|
|
228
|
+
deep_merge: If True, recursively merge nested dicts (default: True)
|
|
229
|
+
|
|
230
|
+
Examples:
|
|
231
|
+
>>> config.update({"hooks": {"timeout_ms": 3000}})
|
|
232
|
+
>>> config.update({"project.name": "MyProject"}, deep_merge=False)
|
|
233
|
+
"""
|
|
234
|
+
if deep_merge:
|
|
235
|
+
self._config = self._deep_merge(self._config, updates)
|
|
236
|
+
else:
|
|
237
|
+
self._config.update(updates)
|
|
238
|
+
|
|
239
|
+
def save(self, backup: bool = True) -> bool:
|
|
240
|
+
"""
|
|
241
|
+
Save configuration to file with atomic write.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
backup: If True, create backup before saving (default: True)
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
bool: True if save successful, False otherwise
|
|
248
|
+
|
|
249
|
+
Pattern: Temp file → Atomic rename (prevents corruption)
|
|
250
|
+
"""
|
|
251
|
+
try:
|
|
252
|
+
# Create backup if requested
|
|
253
|
+
if backup and self._config_path.exists():
|
|
254
|
+
self._create_backup()
|
|
255
|
+
|
|
256
|
+
# Atomic write pattern: temp file → rename
|
|
257
|
+
temp_path = self._config_path.with_suffix(".tmp")
|
|
258
|
+
|
|
259
|
+
# Write to temp file (auto-detect format)
|
|
260
|
+
with open(temp_path, "w", encoding="utf-8") as f:
|
|
261
|
+
if self._config_path.suffix == ".yaml" or self._config_path.suffix == ".yml":
|
|
262
|
+
if not YAML_AVAILABLE:
|
|
263
|
+
raise ImportError("PyYAML is required for YAML config files. Install with: pip install pyyaml")
|
|
264
|
+
yaml.safe_dump(
|
|
265
|
+
self._config,
|
|
266
|
+
f,
|
|
267
|
+
default_flow_style=False,
|
|
268
|
+
allow_unicode=True,
|
|
269
|
+
sort_keys=False,
|
|
270
|
+
)
|
|
271
|
+
else:
|
|
272
|
+
json.dump(self._config, f, indent=2, ensure_ascii=False)
|
|
273
|
+
|
|
274
|
+
# Atomic rename
|
|
275
|
+
temp_path.replace(self._config_path)
|
|
276
|
+
|
|
277
|
+
# Update cache timestamp
|
|
278
|
+
self._last_modified = self._config_path.stat().st_mtime
|
|
279
|
+
|
|
280
|
+
logger.info(f"Saved config to {self._config_path}")
|
|
281
|
+
return True
|
|
282
|
+
|
|
283
|
+
except (OSError, PermissionError) as e:
|
|
284
|
+
logger.error(f"Failed to save config: {e}")
|
|
285
|
+
return False
|
|
286
|
+
|
|
287
|
+
def _create_backup(self) -> None:
|
|
288
|
+
"""Create timestamped backup of config file."""
|
|
289
|
+
try:
|
|
290
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
291
|
+
backup_dir = self._config_path.parent / "backups"
|
|
292
|
+
backup_dir.mkdir(parents=True, exist_ok=True)
|
|
293
|
+
|
|
294
|
+
backup_path = backup_dir / f"config_backup_{timestamp}.json"
|
|
295
|
+
shutil.copy2(self._config_path, backup_path)
|
|
296
|
+
|
|
297
|
+
logger.debug(f"Created backup: {backup_path}")
|
|
298
|
+
|
|
299
|
+
except (OSError, PermissionError) as e:
|
|
300
|
+
logger.warning(f"Failed to create backup: {e}")
|
|
301
|
+
|
|
302
|
+
def _reload_if_modified(self) -> None:
|
|
303
|
+
"""Reload config if file has been modified."""
|
|
304
|
+
try:
|
|
305
|
+
if self._config_path.exists():
|
|
306
|
+
current_mtime = self._config_path.stat().st_mtime
|
|
307
|
+
if self._last_modified is None or current_mtime != self._last_modified:
|
|
308
|
+
self._load_config()
|
|
309
|
+
except OSError:
|
|
310
|
+
pass
|
|
311
|
+
|
|
312
|
+
@staticmethod
|
|
313
|
+
def _deep_merge(base: Dict[str, Any], updates: Dict[str, Any]) -> Dict[str, Any]:
|
|
314
|
+
"""
|
|
315
|
+
Recursively merge two dictionaries.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
base: Base dictionary
|
|
319
|
+
updates: Updates to merge
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
Merged dictionary
|
|
323
|
+
"""
|
|
324
|
+
result = base.copy()
|
|
325
|
+
|
|
326
|
+
for key, value in updates.items():
|
|
327
|
+
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
|
328
|
+
result[key] = UnifiedConfigManager._deep_merge(result[key], value)
|
|
329
|
+
else:
|
|
330
|
+
result[key] = value
|
|
331
|
+
|
|
332
|
+
return result
|
|
333
|
+
|
|
334
|
+
@staticmethod
|
|
335
|
+
def _get_default_config() -> Dict[str, Any]:
|
|
336
|
+
"""
|
|
337
|
+
Get default configuration when file doesn't exist.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
Default configuration dictionary
|
|
341
|
+
"""
|
|
342
|
+
return {
|
|
343
|
+
"moai": {"version": "0.28.0", "update_check_frequency": "daily"},
|
|
344
|
+
"project": {"name": "MyProject", "initialized": False},
|
|
345
|
+
"hooks": {"timeout_ms": 2000, "graceful_degradation": True},
|
|
346
|
+
"session": {"suppress_setup_messages": False},
|
|
347
|
+
"language": {"conversation_language": "en", "agent_prompt_language": "en"},
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
def get_all(self) -> Dict[str, Any]:
|
|
351
|
+
"""
|
|
352
|
+
Get entire configuration dictionary.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
Complete configuration dictionary
|
|
356
|
+
"""
|
|
357
|
+
self._reload_if_modified()
|
|
358
|
+
return self._config.copy()
|
|
359
|
+
|
|
360
|
+
def reset_to_defaults(self) -> None:
|
|
361
|
+
"""Reset configuration to defaults without saving."""
|
|
362
|
+
self._config = self._get_default_config()
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
# Module-level singleton instance
|
|
366
|
+
_unified_config_instance: Optional[UnifiedConfigManager] = None
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def get_unified_config(
|
|
370
|
+
config_path: Optional[Union[str, Path]] = None,
|
|
371
|
+
) -> UnifiedConfigManager:
|
|
372
|
+
"""
|
|
373
|
+
Get or create unified configuration manager instance.
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
config_path: Optional path to config file
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
UnifiedConfigManager: Singleton instance
|
|
380
|
+
|
|
381
|
+
Examples:
|
|
382
|
+
>>> config = get_unified_config()
|
|
383
|
+
>>> timeout = config.get("hooks.timeout_ms", 2000)
|
|
384
|
+
"""
|
|
385
|
+
global _unified_config_instance
|
|
386
|
+
|
|
387
|
+
if _unified_config_instance is None:
|
|
388
|
+
_unified_config_instance = UnifiedConfigManager(config_path)
|
|
389
|
+
|
|
390
|
+
return _unified_config_instance
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
# Convenience functions for common operations
|
|
394
|
+
@lru_cache(maxsize=1)
|
|
395
|
+
def get_config_path() -> Path:
|
|
396
|
+
"""Get path to configuration file."""
|
|
397
|
+
return Path.cwd() / ".moai" / "config" / "config.json"
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def get_config_value(key: str, default: Any = None) -> Any:
|
|
401
|
+
"""
|
|
402
|
+
Get configuration value (convenience function).
|
|
403
|
+
|
|
404
|
+
Args:
|
|
405
|
+
key: Configuration key with dot notation
|
|
406
|
+
default: Default value if key not found
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
Configuration value or default
|
|
410
|
+
"""
|
|
411
|
+
return get_unified_config().get(key, default)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def set_config_value(key: str, value: Any) -> None:
|
|
415
|
+
"""
|
|
416
|
+
Set configuration value (convenience function).
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
key: Configuration key with dot notation
|
|
420
|
+
value: Value to set
|
|
421
|
+
"""
|
|
422
|
+
config = get_unified_config()
|
|
423
|
+
config.set(key, value)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def save_config(backup: bool = True) -> bool:
|
|
427
|
+
"""
|
|
428
|
+
Save configuration (convenience function).
|
|
429
|
+
|
|
430
|
+
Args:
|
|
431
|
+
backup: Create backup before saving
|
|
432
|
+
|
|
433
|
+
Returns:
|
|
434
|
+
bool: True if successful
|
|
435
|
+
"""
|
|
436
|
+
return get_unified_config().save(backup)
|
moai_adk/core/context_manager.py
CHANGED
|
@@ -37,9 +37,7 @@ def _is_path_within_root(abs_path: str, project_root: str) -> bool:
|
|
|
37
37
|
real_abs_path = os.path.realpath(abs_path)
|
|
38
38
|
real_project_root = os.path.realpath(project_root)
|
|
39
39
|
|
|
40
|
-
return real_abs_path == real_project_root or real_abs_path.startswith(
|
|
41
|
-
real_project_root + os.sep
|
|
42
|
-
)
|
|
40
|
+
return real_abs_path == real_project_root or real_abs_path.startswith(real_project_root + os.sep)
|
|
43
41
|
except OSError:
|
|
44
42
|
return False
|
|
45
43
|
|
|
@@ -129,13 +127,11 @@ def save_phase_result(data: Dict[str, Any], target_path: str) -> None:
|
|
|
129
127
|
|
|
130
128
|
try:
|
|
131
129
|
# Create temp file in target directory for atomic rename
|
|
132
|
-
temp_fd, temp_path = tempfile.mkstemp(
|
|
133
|
-
dir=target_dir, prefix=".tmp_phase_", suffix=".json"
|
|
134
|
-
)
|
|
130
|
+
temp_fd, temp_path = tempfile.mkstemp(dir=target_dir, prefix=".tmp_phase_", suffix=".json")
|
|
135
131
|
|
|
136
132
|
# Write JSON to temp file
|
|
137
|
-
with os.fdopen(temp_fd, "w") as f:
|
|
138
|
-
json.dump(data, f, indent=2)
|
|
133
|
+
with os.fdopen(temp_fd, "w", encoding="utf-8") as f:
|
|
134
|
+
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
139
135
|
|
|
140
136
|
temp_fd = None # File handle is now closed
|
|
141
137
|
|
|
@@ -164,7 +160,7 @@ def load_phase_result(source_path: str) -> Dict[str, Any]:
|
|
|
164
160
|
if not os.path.exists(source_path):
|
|
165
161
|
raise FileNotFoundError(f"Phase result file not found: {source_path}")
|
|
166
162
|
|
|
167
|
-
with open(source_path, "r") as f:
|
|
163
|
+
with open(source_path, "r", encoding="utf-8") as f:
|
|
168
164
|
data = json.load(f)
|
|
169
165
|
|
|
170
166
|
return data
|
|
@@ -261,9 +257,7 @@ class ContextManager:
|
|
|
261
257
|
Phase result dictionary or None if no phase files exist
|
|
262
258
|
"""
|
|
263
259
|
# List all phase files
|
|
264
|
-
phase_files = sorted(
|
|
265
|
-
[f for f in os.listdir(self.state_dir) if f.endswith(".json")]
|
|
266
|
-
)
|
|
260
|
+
phase_files = sorted([f for f in os.listdir(self.state_dir) if f.endswith(".json")])
|
|
267
261
|
|
|
268
262
|
if not phase_files:
|
|
269
263
|
return None
|