moai-adk 0.35.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +10 -0
- moai_adk/__main__.py +199 -0
- moai_adk/cli/__init__.py +6 -0
- moai_adk/cli/commands/__init__.py +17 -0
- moai_adk/cli/commands/analyze.py +116 -0
- moai_adk/cli/commands/doctor.py +272 -0
- moai_adk/cli/commands/init.py +372 -0
- moai_adk/cli/commands/language.py +248 -0
- moai_adk/cli/commands/status.py +104 -0
- moai_adk/cli/commands/update.py +2686 -0
- moai_adk/cli/main.py +13 -0
- moai_adk/cli/prompts/__init__.py +5 -0
- moai_adk/cli/prompts/init_prompts.py +219 -0
- 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 +683 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +493 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +422 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/__init__.py +1 -0
- moai_adk/core/analysis/__init__.py +9 -0
- moai_adk/core/analysis/session_analyzer.py +400 -0
- moai_adk/core/claude_integration.py +393 -0
- moai_adk/core/command_helpers.py +270 -0
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/__init__.py +19 -0
- moai_adk/core/config/auto_spec_config.py +340 -0
- moai_adk/core/config/migration.py +244 -0
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +273 -0
- moai_adk/core/diagnostics/__init__.py +19 -0
- moai_adk/core/diagnostics/slash_commands.py +159 -0
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +1902 -0
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +31 -0
- moai_adk/core/git/branch.py +25 -0
- moai_adk/core/git/branch_manager.py +129 -0
- moai_adk/core/git/checkpoint.py +134 -0
- moai_adk/core/git/commit.py +67 -0
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/event_detector.py +79 -0
- moai_adk/core/git/manager.py +216 -0
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/__init__.py +22 -0
- moai_adk/core/integration/engine.py +157 -0
- moai_adk/core/integration/integration_tester.py +226 -0
- moai_adk/core/integration/models.py +88 -0
- moai_adk/core/integration/utils.py +211 -0
- moai_adk/core/issue_creator.py +305 -0
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config.py +202 -0
- moai_adk/core/language_config_resolver.py +572 -0
- moai_adk/core/language_validator.py +543 -0
- moai_adk/core/mcp/setup.py +116 -0
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +605 -0
- moai_adk/core/migration/__init__.py +18 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +277 -0
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +209 -0
- 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 +139 -0
- moai_adk/core/migration/version_migrator.py +228 -0
- moai_adk/core/performance/__init__.py +6 -0
- moai_adk/core/performance/cache_system.py +316 -0
- moai_adk/core/performance/parallel_processor.py +116 -0
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/__init__.py +1 -0
- moai_adk/core/project/backup_utils.py +70 -0
- moai_adk/core/project/checker.py +300 -0
- moai_adk/core/project/detector.py +293 -0
- moai_adk/core/project/initializer.py +387 -0
- moai_adk/core/project/phase_executor.py +716 -0
- moai_adk/core/project/validator.py +139 -0
- moai_adk/core/quality/__init__.py +6 -0
- moai_adk/core/quality/trust_checker.py +377 -0
- moai_adk/core/quality/validators/__init__.py +6 -0
- moai_adk/core/quality/validators/base_validator.py +19 -0
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +918 -0
- moai_adk/core/session_manager.py +651 -0
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +680 -0
- moai_adk/core/spec/ears_template_engine.py +1247 -0
- moai_adk/core/spec/quality_validator.py +687 -0
- moai_adk/core/spec_status_manager.py +478 -0
- moai_adk/core/template/__init__.py +7 -0
- moai_adk/core/template/backup.py +174 -0
- moai_adk/core/template/config.py +191 -0
- moai_adk/core/template/languages.py +43 -0
- moai_adk/core/template/merger.py +233 -0
- moai_adk/core/template/processor.py +1200 -0
- moai_adk/core/template_engine.py +310 -0
- 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 +557 -0
- 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 +676 -0
- moai_adk/foundation/trust/validation_checklist.py +1573 -0
- 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/__init__.py +38 -0
- moai_adk/statusline/alfred_detector.py +105 -0
- moai_adk/statusline/config.py +376 -0
- moai_adk/statusline/enhanced_output_style_detector.py +372 -0
- moai_adk/statusline/git_collector.py +190 -0
- moai_adk/statusline/main.py +322 -0
- moai_adk/statusline/metrics_tracker.py +78 -0
- moai_adk/statusline/renderer.py +343 -0
- moai_adk/statusline/update_checker.py +129 -0
- moai_adk/statusline/version_reader.py +741 -0
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +714 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +474 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1172 -0
- moai_adk/templates/.claude/agents/moai/builder-plugin.md +637 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +899 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +777 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +401 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +720 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +734 -0
- moai_adk/templates/.claude/agents/moai/expert-performance.md +657 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +513 -0
- moai_adk/templates/.claude/agents/moai/expert-testing.md +733 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1041 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +432 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +573 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +1060 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +624 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +809 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +780 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +784 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +458 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1607 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +789 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +469 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +1032 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1386 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1427 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +943 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +1324 -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 +1083 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +560 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
- moai_adk/templates/.claude/settings.json +172 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/SKILL.md +307 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/examples.md +431 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/scripts/batch_generate.py +560 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/scripts/generate_image.py +362 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +249 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +406 -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-docs-generation/reference.md +328 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +320 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +718 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +464 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +323 -0
- moai_adk/templates/.claude/skills/moai-domain-database/examples.md +830 -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-database/reference.md +545 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +497 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +968 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +664 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +455 -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/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 +492 -0
- moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -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-formats-data/reference.md +585 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +202 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -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-claude/reference.md +209 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +441 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +420 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -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 +359 -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-core/reference.md +478 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +315 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +364 -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-lang-cpp/SKILL.md +649 -0
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +478 -0
- moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +612 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +477 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +376 -0
- moai_adk/templates/.claude/skills/moai-lang-go/examples.md +919 -0
- moai_adk/templates/.claude/skills/moai-lang-go/reference.md +737 -0
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +385 -0
- moai_adk/templates/.claude/skills/moai-lang-java/examples.md +864 -0
- moai_adk/templates/.claude/skills/moai-lang-java/reference.md +291 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +382 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +1006 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +562 -0
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +644 -0
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +481 -0
- moai_adk/templates/.claude/skills/moai-lang-python/examples.md +977 -0
- moai_adk/templates/.claude/skills/moai-lang-python/reference.md +804 -0
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +579 -0
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +687 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +372 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +659 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +504 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +497 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +633 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +423 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +497 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +918 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +672 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +368 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1089 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +731 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +300 -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 +319 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -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-nextra/reference.md +379 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +372 -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-mcp-figma/SKILL.md +402 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/advanced-patterns.md +607 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/advanced-patterns.md +537 -0
- moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +291 -0
- moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +398 -0
- moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +379 -0
- moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +358 -0
- moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +467 -0
- moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +466 -0
- moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +482 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/SKILL.md +474 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/examples.md +621 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/migration.md +341 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/reference.md +463 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/validation.md +373 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/SKILL.md +275 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/adaptive-mfa.md +233 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/akamai-integration.md +215 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/application-credentials.md +280 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/attack-protection-log-events.md +225 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/attack-protection-overview.md +140 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/bot-detection.md +144 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/breached-password-detection.md +187 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/brute-force-protection.md +189 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/certifications.md +282 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/compliance-overview.md +263 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/continuous-session-protection.md +307 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/customize-mfa.md +178 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/dpop-implementation.md +283 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/fapi-implementation.md +259 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/gdpr-compliance.md +313 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/guardian-configuration.md +269 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/highly-regulated-identity.md +272 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/jwt-fundamentals.md +248 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mdl-verification.md +211 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-api-management.md +278 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-factors.md +226 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-overview.md +174 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mtls-sender-constraining.md +316 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/ropg-flow-mfa.md +217 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/security-center.md +325 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/security-guidance.md +277 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/state-parameters.md +178 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/step-up-authentication.md +251 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/suspicious-ip-throttling.md +240 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/tenant-access-control.md +180 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/webauthn-fido.md +235 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +449 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +390 -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 +175 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -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/reference.md +275 -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 +1434 -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 +92 -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-spec/SKILL.md +534 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -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-templates/reference.md +346 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +456 -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/examples.md +672 -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/reference.md +440 -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 +411 -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 +128 -0
- moai_adk/templates/.git-hooks/pre-push +365 -0
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +337 -0
- moai_adk/templates/.gitignore +222 -0
- moai_adk/templates/.mcp.json +13 -0
- moai_adk/templates/.moai/config/config.yaml +58 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +174 -0
- moai_adk/templates/.moai/config/questions/tab0-init.yaml +251 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +107 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +79 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +632 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +182 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +96 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -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 +17 -0
- moai_adk/templates/.moai/config/sections/system.yaml +24 -0
- moai_adk/templates/.moai/config/sections/user.yaml +5 -0
- moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +642 -0
- moai_adk/utils/__init__.py +30 -0
- moai_adk/utils/banner.py +38 -0
- moai_adk/utils/common.py +294 -0
- moai_adk/utils/link_validator.py +241 -0
- moai_adk/utils/logger.py +147 -0
- moai_adk/utils/safe_file_reader.py +206 -0
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.35.1.dist-info/METADATA +3018 -0
- moai_adk-0.35.1.dist-info/RECORD +502 -0
- moai_adk-0.35.1.dist-info/WHEEL +4 -0
- moai_adk-0.35.1.dist-info/entry_points.txt +3 -0
- moai_adk-0.35.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Custom exceptions for Git Worktree CLI."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WorktreeError(Exception):
|
|
7
|
+
"""Base exception for worktree operations."""
|
|
8
|
+
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WorktreeExistsError(WorktreeError):
|
|
13
|
+
"""Raised when trying to create a worktree that already exists."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, spec_id: str, path: Path) -> None:
|
|
16
|
+
"""Initialize exception with spec ID and path.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
spec_id: The SPEC ID that already has a worktree.
|
|
20
|
+
path: The path of the existing worktree.
|
|
21
|
+
"""
|
|
22
|
+
self.spec_id = spec_id
|
|
23
|
+
self.path = path
|
|
24
|
+
super().__init__(f"Worktree for '{spec_id}' already exists at {path}")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class WorktreeNotFoundError(WorktreeError):
|
|
28
|
+
"""Raised when trying to access a nonexistent worktree."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, spec_id: str) -> None:
|
|
31
|
+
"""Initialize exception with spec ID.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
spec_id: The SPEC ID that was not found.
|
|
35
|
+
"""
|
|
36
|
+
self.spec_id = spec_id
|
|
37
|
+
super().__init__(f"Worktree for '{spec_id}' not found")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class UncommittedChangesError(WorktreeError):
|
|
41
|
+
"""Raised when trying to remove a worktree with uncommitted changes."""
|
|
42
|
+
|
|
43
|
+
def __init__(self, spec_id: str) -> None:
|
|
44
|
+
"""Initialize exception with spec ID.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
spec_id: The SPEC ID with uncommitted changes.
|
|
48
|
+
"""
|
|
49
|
+
self.spec_id = spec_id
|
|
50
|
+
super().__init__(f"Worktree for '{spec_id}' has uncommitted changes. Use --force to remove anyway.")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class GitOperationError(WorktreeError):
|
|
54
|
+
"""Raised when a Git operation fails."""
|
|
55
|
+
|
|
56
|
+
def __init__(self, message: str) -> None:
|
|
57
|
+
"""Initialize exception with error message.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
message: Description of the Git operation error.
|
|
61
|
+
"""
|
|
62
|
+
super().__init__(f"Git operation failed: {message}")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class MergeConflictError(WorktreeError):
|
|
66
|
+
"""Raised when a merge conflict occurs during sync."""
|
|
67
|
+
|
|
68
|
+
def __init__(self, spec_id: str, conflicted_files: list[str]) -> None:
|
|
69
|
+
"""Initialize exception with conflict details.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
spec_id: The SPEC ID with merge conflicts.
|
|
73
|
+
conflicted_files: List of files with conflicts.
|
|
74
|
+
"""
|
|
75
|
+
self.spec_id = spec_id
|
|
76
|
+
self.conflicted_files = conflicted_files
|
|
77
|
+
super().__init__(f"Merge conflict in worktree '{spec_id}'. Conflicted files: {', '.join(conflicted_files)}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class RegistryInconsistencyError(WorktreeError):
|
|
81
|
+
"""Raised when registry state is inconsistent with actual Git worktrees."""
|
|
82
|
+
|
|
83
|
+
def __init__(self, message: str) -> None:
|
|
84
|
+
"""Initialize exception with error message.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
message: Description of the inconsistency.
|
|
88
|
+
"""
|
|
89
|
+
super().__init__(f"Registry inconsistency: {message}")
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
"""Core manager for Git worktree operations."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
from git import Repo
|
|
8
|
+
|
|
9
|
+
from moai_adk.cli.worktree.exceptions import (
|
|
10
|
+
GitOperationError,
|
|
11
|
+
MergeConflictError,
|
|
12
|
+
UncommittedChangesError,
|
|
13
|
+
WorktreeExistsError,
|
|
14
|
+
WorktreeNotFoundError,
|
|
15
|
+
)
|
|
16
|
+
from moai_adk.cli.worktree.models import WorktreeInfo
|
|
17
|
+
from moai_adk.cli.worktree.registry import WorktreeRegistry
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WorktreeManager:
|
|
21
|
+
"""Manages Git worktrees for parallel SPEC development with project namespace support.
|
|
22
|
+
|
|
23
|
+
This class provides high-level operations for creating, removing,
|
|
24
|
+
switching, and maintaining Git worktrees. It integrates with
|
|
25
|
+
GitPython for Git operations and WorktreeRegistry for metadata
|
|
26
|
+
persistence. Worktrees are organized by project name namespace to
|
|
27
|
+
support multiple projects: /worktrees/{project-name}/{SPEC-ID}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, repo_path: Path, worktree_root: Path, project_name: str | None = None) -> None:
|
|
31
|
+
"""Initialize the worktree manager.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
repo_path: Path to the main Git repository.
|
|
35
|
+
worktree_root: Root directory for all worktrees.
|
|
36
|
+
project_name: Project name for namespace organization. Defaults to repo directory name.
|
|
37
|
+
"""
|
|
38
|
+
self.repo = Repo(repo_path)
|
|
39
|
+
self.worktree_root = Path(worktree_root)
|
|
40
|
+
self.project_name = project_name or repo_path.name
|
|
41
|
+
self.registry = WorktreeRegistry(self.worktree_root)
|
|
42
|
+
|
|
43
|
+
def create(
|
|
44
|
+
self,
|
|
45
|
+
spec_id: str,
|
|
46
|
+
branch_name: str | None = None,
|
|
47
|
+
base_branch: str = "main",
|
|
48
|
+
force: bool = False,
|
|
49
|
+
) -> WorktreeInfo:
|
|
50
|
+
"""Create a new worktree for a SPEC.
|
|
51
|
+
|
|
52
|
+
Creates a new Git worktree and registers it in the registry.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
spec_id: SPEC ID (e.g., 'SPEC-AUTH-001').
|
|
56
|
+
branch_name: Custom branch name (defaults to spec_id).
|
|
57
|
+
base_branch: Base branch to create from (defaults to 'main').
|
|
58
|
+
force: Force creation even if worktree exists.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
WorktreeInfo for the created worktree.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
WorktreeExistsError: If worktree already exists (unless force=True).
|
|
65
|
+
GitOperationError: If Git operation fails.
|
|
66
|
+
"""
|
|
67
|
+
# Check if worktree already exists
|
|
68
|
+
existing = self.registry.get(spec_id, project_name=self.project_name)
|
|
69
|
+
if existing and not force:
|
|
70
|
+
raise WorktreeExistsError(spec_id, existing.path)
|
|
71
|
+
|
|
72
|
+
# If force and exists, remove first
|
|
73
|
+
if existing and force:
|
|
74
|
+
try:
|
|
75
|
+
self.remove(spec_id, force=True)
|
|
76
|
+
except WorktreeNotFoundError:
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
# Determine branch name
|
|
80
|
+
if branch_name is None:
|
|
81
|
+
branch_name = f"feature/{spec_id}"
|
|
82
|
+
|
|
83
|
+
# Create worktree path with project_name namespace
|
|
84
|
+
worktree_path = self.worktree_root / self.project_name / spec_id
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
# Create parent directory if needed (including project_name namespace)
|
|
88
|
+
worktree_path.parent.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
|
|
90
|
+
# Fetch latest
|
|
91
|
+
try:
|
|
92
|
+
self.repo.remotes.origin.fetch()
|
|
93
|
+
except Exception:
|
|
94
|
+
# No origin or fetch fails, continue with local
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
# Check if branch exists, if not create it
|
|
98
|
+
try:
|
|
99
|
+
self.repo.heads[base_branch]
|
|
100
|
+
except IndexError:
|
|
101
|
+
# Branch doesn't exist locally, try to fetch
|
|
102
|
+
try:
|
|
103
|
+
self.repo.remotes.origin.fetch(base_branch)
|
|
104
|
+
except Exception:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
# Create branch if it doesn't exist
|
|
108
|
+
if branch_name not in [h.name for h in self.repo.heads]:
|
|
109
|
+
try:
|
|
110
|
+
self.repo.create_head(branch_name, base_branch)
|
|
111
|
+
except Exception as e:
|
|
112
|
+
# If create fails, check if it already exists
|
|
113
|
+
if branch_name not in [h.name for h in self.repo.heads]:
|
|
114
|
+
raise GitOperationError(f"Failed to create branch: {e}")
|
|
115
|
+
|
|
116
|
+
# Create worktree using git command
|
|
117
|
+
try:
|
|
118
|
+
self.repo.git.worktree("add", str(worktree_path), branch_name)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
raise GitOperationError(f"Failed to create worktree: {e}")
|
|
121
|
+
|
|
122
|
+
# Create WorktreeInfo
|
|
123
|
+
now = datetime.now().isoformat() + "Z"
|
|
124
|
+
info = WorktreeInfo(
|
|
125
|
+
spec_id=spec_id,
|
|
126
|
+
path=worktree_path,
|
|
127
|
+
branch=branch_name,
|
|
128
|
+
created_at=now,
|
|
129
|
+
last_accessed=now,
|
|
130
|
+
status="active",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Register in registry
|
|
134
|
+
self.registry.register(info, project_name=self.project_name)
|
|
135
|
+
|
|
136
|
+
return info
|
|
137
|
+
|
|
138
|
+
except WorktreeExistsError:
|
|
139
|
+
raise
|
|
140
|
+
except GitOperationError:
|
|
141
|
+
raise
|
|
142
|
+
except Exception as e:
|
|
143
|
+
raise GitOperationError(f"Failed to create worktree: {e}")
|
|
144
|
+
|
|
145
|
+
def remove(self, spec_id: str, force: bool = False) -> None:
|
|
146
|
+
"""Remove a worktree.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
spec_id: SPEC ID of worktree to remove.
|
|
150
|
+
force: Force removal even with uncommitted changes.
|
|
151
|
+
|
|
152
|
+
Raises:
|
|
153
|
+
WorktreeNotFoundError: If worktree doesn't exist.
|
|
154
|
+
UncommittedChangesError: If worktree has uncommitted changes (unless force=True).
|
|
155
|
+
GitOperationError: If Git operation fails.
|
|
156
|
+
"""
|
|
157
|
+
info = self.registry.get(spec_id, project_name=self.project_name)
|
|
158
|
+
if not info:
|
|
159
|
+
raise WorktreeNotFoundError(spec_id)
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
# Check for uncommitted changes
|
|
163
|
+
if not force:
|
|
164
|
+
try:
|
|
165
|
+
status = self.repo.git.status("--porcelain", spec_id)
|
|
166
|
+
if status.strip():
|
|
167
|
+
raise UncommittedChangesError(spec_id)
|
|
168
|
+
except Exception:
|
|
169
|
+
# Ignore status check errors
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
# Remove worktree
|
|
173
|
+
try:
|
|
174
|
+
self.repo.git.worktree("remove", str(info.path), "--force")
|
|
175
|
+
except Exception:
|
|
176
|
+
# Try to remove directory manually if git command fails
|
|
177
|
+
import shutil
|
|
178
|
+
|
|
179
|
+
if info.path.exists():
|
|
180
|
+
shutil.rmtree(info.path)
|
|
181
|
+
|
|
182
|
+
# Unregister from registry
|
|
183
|
+
self.registry.unregister(spec_id, project_name=self.project_name)
|
|
184
|
+
|
|
185
|
+
except (WorktreeNotFoundError, UncommittedChangesError):
|
|
186
|
+
raise
|
|
187
|
+
except GitOperationError:
|
|
188
|
+
raise
|
|
189
|
+
except Exception as e:
|
|
190
|
+
raise GitOperationError(f"Failed to remove worktree: {e}")
|
|
191
|
+
|
|
192
|
+
def list(self) -> list["WorktreeInfo"]:
|
|
193
|
+
"""List all worktrees.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
List of WorktreeInfo instances.
|
|
197
|
+
"""
|
|
198
|
+
return self.registry.list_all(project_name=self.project_name)
|
|
199
|
+
|
|
200
|
+
def sync(
|
|
201
|
+
self,
|
|
202
|
+
spec_id: str,
|
|
203
|
+
base_branch: str = "main",
|
|
204
|
+
rebase: bool = False,
|
|
205
|
+
ff_only: bool = False,
|
|
206
|
+
auto_resolve: bool = False,
|
|
207
|
+
) -> None:
|
|
208
|
+
"""Sync worktree with base branch.
|
|
209
|
+
|
|
210
|
+
Fetches latest changes from base branch and merges them.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
spec_id: SPEC ID of worktree to sync.
|
|
214
|
+
base_branch: Branch to sync from (defaults to 'main').
|
|
215
|
+
rebase: Use rebase instead of merge.
|
|
216
|
+
ff_only: Only sync if fast-forward is possible.
|
|
217
|
+
auto_resolve: Automatically attempt to resolve conflicts.
|
|
218
|
+
|
|
219
|
+
Raises:
|
|
220
|
+
WorktreeNotFoundError: If worktree doesn't exist.
|
|
221
|
+
MergeConflictError: If merge conflict occurs and auto_resolve is False.
|
|
222
|
+
GitOperationError: If Git operation fails.
|
|
223
|
+
"""
|
|
224
|
+
info = self.registry.get(spec_id, project_name=self.project_name)
|
|
225
|
+
if not info:
|
|
226
|
+
raise WorktreeNotFoundError(spec_id)
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
# Change to worktree directory
|
|
230
|
+
worktree_repo = Repo(info.path)
|
|
231
|
+
|
|
232
|
+
# Fetch latest
|
|
233
|
+
try:
|
|
234
|
+
worktree_repo.remotes.origin.fetch()
|
|
235
|
+
except Exception:
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
# Sync with preferred strategy
|
|
239
|
+
try:
|
|
240
|
+
# Determine target branch (try remote first, then local)
|
|
241
|
+
target_branch = None
|
|
242
|
+
for candidate in [f"origin/{base_branch}", base_branch]:
|
|
243
|
+
try:
|
|
244
|
+
worktree_repo.git.rev_parse(candidate)
|
|
245
|
+
target_branch = candidate
|
|
246
|
+
break
|
|
247
|
+
except Exception:
|
|
248
|
+
continue
|
|
249
|
+
|
|
250
|
+
if not target_branch:
|
|
251
|
+
raise GitOperationError(
|
|
252
|
+
f"Base branch '{base_branch}' not found (tried origin/{base_branch}, {base_branch})"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
if ff_only:
|
|
256
|
+
# Fast-forward only
|
|
257
|
+
worktree_repo.git.merge(target_branch, "--ff-only")
|
|
258
|
+
elif rebase:
|
|
259
|
+
# Rebase strategy
|
|
260
|
+
worktree_repo.git.rebase(target_branch)
|
|
261
|
+
else:
|
|
262
|
+
# Default merge strategy with conflict handling
|
|
263
|
+
worktree_repo.git.merge(target_branch)
|
|
264
|
+
except Exception as e:
|
|
265
|
+
# Handle merge conflicts and provide auto-abort/auto-resolve
|
|
266
|
+
try:
|
|
267
|
+
status = worktree_repo.git.status("--porcelain")
|
|
268
|
+
conflicted = [
|
|
269
|
+
line.split()[-1]
|
|
270
|
+
for line in status.split("\n")
|
|
271
|
+
if line.startswith("UU")
|
|
272
|
+
or line.startswith("DD")
|
|
273
|
+
or line.startswith("AA")
|
|
274
|
+
or line.startswith("DU")
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
if conflicted:
|
|
278
|
+
if auto_resolve:
|
|
279
|
+
# Attempt auto-resolution of conflicts
|
|
280
|
+
try:
|
|
281
|
+
# Try common conflict resolution strategies
|
|
282
|
+
for file_path in conflicted:
|
|
283
|
+
try:
|
|
284
|
+
# Strategy 1: Accept current changes (ours)
|
|
285
|
+
worktree_repo.git.checkout("--ours", file_path)
|
|
286
|
+
worktree_repo.git.add(file_path)
|
|
287
|
+
except Exception:
|
|
288
|
+
# Strategy 2: Accept incoming changes (theirs) if ours fails
|
|
289
|
+
try:
|
|
290
|
+
worktree_repo.git.checkout("--theirs", file_path)
|
|
291
|
+
worktree_repo.git.add(file_path)
|
|
292
|
+
except Exception:
|
|
293
|
+
# Strategy 3: Remove conflict markers and keep both
|
|
294
|
+
try:
|
|
295
|
+
# Simple conflict marker removal - keep both versions
|
|
296
|
+
file_full_path = info.path / file_path
|
|
297
|
+
if file_full_path.exists():
|
|
298
|
+
with open(file_full_path, "r") as f:
|
|
299
|
+
content = f.read()
|
|
300
|
+
|
|
301
|
+
# Remove conflict markers and keep both versions
|
|
302
|
+
lines = content.split("\n")
|
|
303
|
+
cleaned_lines = []
|
|
304
|
+
skip_next = False
|
|
305
|
+
in_conflict = False
|
|
306
|
+
|
|
307
|
+
for line in lines:
|
|
308
|
+
if "<<<<<<<" in line or ">>>>>>>" in line:
|
|
309
|
+
in_conflict = True
|
|
310
|
+
continue
|
|
311
|
+
elif "======" in line:
|
|
312
|
+
skip_next = True
|
|
313
|
+
in_conflict = False
|
|
314
|
+
continue
|
|
315
|
+
elif skip_next:
|
|
316
|
+
skip_next = False
|
|
317
|
+
continue
|
|
318
|
+
elif not in_conflict:
|
|
319
|
+
cleaned_lines.append(line)
|
|
320
|
+
|
|
321
|
+
with open(file_full_path, "w") as f:
|
|
322
|
+
f.write("\n".join(cleaned_lines))
|
|
323
|
+
|
|
324
|
+
worktree_repo.git.add(file_path)
|
|
325
|
+
except Exception:
|
|
326
|
+
pass
|
|
327
|
+
|
|
328
|
+
# Stage resolved files
|
|
329
|
+
worktree_repo.git.add(".")
|
|
330
|
+
|
|
331
|
+
# Commit the merge resolution
|
|
332
|
+
worktree_repo.git.commit(
|
|
333
|
+
"-m",
|
|
334
|
+
f"Auto-resolved conflicts during sync of {spec_id}",
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
except Exception as resolve_error:
|
|
338
|
+
# Auto-resolution failed, fall back to manual conflict
|
|
339
|
+
try:
|
|
340
|
+
worktree_repo.git.merge("--abort")
|
|
341
|
+
except Exception:
|
|
342
|
+
pass
|
|
343
|
+
try:
|
|
344
|
+
worktree_repo.git.rebase("--abort")
|
|
345
|
+
except Exception:
|
|
346
|
+
pass
|
|
347
|
+
conflict_list = conflicted if isinstance(conflicted, list) else [str(conflicted)]
|
|
348
|
+
error_msg = f"auto-resolve failed: {resolve_error}"
|
|
349
|
+
raise MergeConflictError(spec_id, conflict_list + [error_msg])
|
|
350
|
+
else:
|
|
351
|
+
# Auto-abort merge/rebase on conflicts
|
|
352
|
+
try:
|
|
353
|
+
worktree_repo.git.merge("--abort")
|
|
354
|
+
except Exception:
|
|
355
|
+
pass
|
|
356
|
+
try:
|
|
357
|
+
worktree_repo.git.rebase("--abort")
|
|
358
|
+
except Exception:
|
|
359
|
+
pass
|
|
360
|
+
|
|
361
|
+
raise MergeConflictError(spec_id, conflicted)
|
|
362
|
+
|
|
363
|
+
# If no conflicts but sync failed, raise general error
|
|
364
|
+
raise GitOperationError(f"Failed to sync worktree: {e}")
|
|
365
|
+
|
|
366
|
+
except MergeConflictError:
|
|
367
|
+
raise
|
|
368
|
+
except Exception:
|
|
369
|
+
# If conflict detection fails, still try to clean up
|
|
370
|
+
try:
|
|
371
|
+
worktree_repo.git.merge("--abort")
|
|
372
|
+
except Exception:
|
|
373
|
+
pass
|
|
374
|
+
try:
|
|
375
|
+
worktree_repo.git.rebase("--abort")
|
|
376
|
+
except Exception:
|
|
377
|
+
pass
|
|
378
|
+
raise GitOperationError(f"Failed to sync worktree: {e}")
|
|
379
|
+
|
|
380
|
+
# Update last accessed time
|
|
381
|
+
info.last_accessed = datetime.now().isoformat() + "Z"
|
|
382
|
+
self.registry.register(info, project_name=self.project_name)
|
|
383
|
+
|
|
384
|
+
except (WorktreeNotFoundError, MergeConflictError):
|
|
385
|
+
raise
|
|
386
|
+
except GitOperationError:
|
|
387
|
+
raise
|
|
388
|
+
except Exception as e:
|
|
389
|
+
raise GitOperationError(f"Failed to sync worktree: {e}")
|
|
390
|
+
|
|
391
|
+
def clean_merged(self) -> List[str]:
|
|
392
|
+
"""Clean up worktrees for merged branches.
|
|
393
|
+
|
|
394
|
+
Removes worktrees whose branches have been merged to main.
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
List of spec_ids that were cleaned up.
|
|
398
|
+
"""
|
|
399
|
+
cleaned = []
|
|
400
|
+
|
|
401
|
+
try:
|
|
402
|
+
# Get list of merged branches
|
|
403
|
+
try:
|
|
404
|
+
merged_branches = self.repo.git.branch("--merged", "main").split("\n")
|
|
405
|
+
merged_branches = [b.strip().lstrip("*").strip() for b in merged_branches]
|
|
406
|
+
except Exception:
|
|
407
|
+
merged_branches = []
|
|
408
|
+
|
|
409
|
+
# Check each worktree
|
|
410
|
+
for info in self.list():
|
|
411
|
+
if info.branch in merged_branches:
|
|
412
|
+
try:
|
|
413
|
+
self.remove(info.spec_id, force=True)
|
|
414
|
+
cleaned.append(info.spec_id)
|
|
415
|
+
except Exception:
|
|
416
|
+
pass
|
|
417
|
+
|
|
418
|
+
except Exception:
|
|
419
|
+
pass
|
|
420
|
+
|
|
421
|
+
return cleaned
|
|
422
|
+
|
|
423
|
+
def auto_resolve_conflicts(self, worktree_repo: Repo, spec_id: str, conflicted_files: List[str]) -> None:
|
|
424
|
+
"""Automatically resolve conflicts in worktree.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
worktree_repo: Git repository object for the worktree.
|
|
428
|
+
spec_id: SPEC ID for error reporting.
|
|
429
|
+
conflicted_files: List of conflicted files.
|
|
430
|
+
|
|
431
|
+
Raises:
|
|
432
|
+
GitOperationError: If auto-resolution fails.
|
|
433
|
+
"""
|
|
434
|
+
try:
|
|
435
|
+
# Try common conflict resolution strategies
|
|
436
|
+
for file_path in conflicted_files:
|
|
437
|
+
try:
|
|
438
|
+
# Strategy 1: Accept current changes (ours)
|
|
439
|
+
worktree_repo.git.checkout("--ours", file_path)
|
|
440
|
+
worktree_repo.git.add(file_path)
|
|
441
|
+
except Exception:
|
|
442
|
+
# Strategy 2: Accept incoming changes (theirs) if ours fails
|
|
443
|
+
try:
|
|
444
|
+
worktree_repo.git.checkout("--theirs", file_path)
|
|
445
|
+
worktree_repo.git.add(file_path)
|
|
446
|
+
except Exception:
|
|
447
|
+
# Strategy 3: Remove conflict markers and keep both
|
|
448
|
+
try:
|
|
449
|
+
# Simple conflict marker removal - keep both versions
|
|
450
|
+
|
|
451
|
+
worktree_path = Path(worktree_repo.working_dir)
|
|
452
|
+
file_full_path = worktree_path / file_path
|
|
453
|
+
|
|
454
|
+
if file_full_path.exists():
|
|
455
|
+
with open(file_full_path, "r") as f:
|
|
456
|
+
content = f.read()
|
|
457
|
+
|
|
458
|
+
# Remove conflict markers and keep both versions
|
|
459
|
+
lines = content.split("\n")
|
|
460
|
+
cleaned_lines = []
|
|
461
|
+
skip_next = False
|
|
462
|
+
in_conflict = False
|
|
463
|
+
|
|
464
|
+
for line in lines:
|
|
465
|
+
if "<<<<<<<" in line or ">>>>>>>" in line:
|
|
466
|
+
in_conflict = True
|
|
467
|
+
continue
|
|
468
|
+
elif "======" in line:
|
|
469
|
+
skip_next = True
|
|
470
|
+
in_conflict = False
|
|
471
|
+
continue
|
|
472
|
+
elif skip_next:
|
|
473
|
+
skip_next = False
|
|
474
|
+
continue
|
|
475
|
+
elif not in_conflict:
|
|
476
|
+
cleaned_lines.append(line)
|
|
477
|
+
|
|
478
|
+
with open(file_full_path, "w") as f:
|
|
479
|
+
f.write("\n".join(cleaned_lines))
|
|
480
|
+
|
|
481
|
+
worktree_repo.git.add(file_path)
|
|
482
|
+
except Exception:
|
|
483
|
+
pass
|
|
484
|
+
|
|
485
|
+
# Stage resolved files
|
|
486
|
+
worktree_repo.git.add(".")
|
|
487
|
+
|
|
488
|
+
# Commit the merge resolution
|
|
489
|
+
worktree_repo.git.commit("-m", f"Auto-resolved conflicts during sync of {spec_id}")
|
|
490
|
+
|
|
491
|
+
except Exception as e:
|
|
492
|
+
# Auto-resolution failed, raise error for manual intervention
|
|
493
|
+
raise GitOperationError(f"Auto-resolution failed for {spec_id}: {e}")
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Data models for Git Worktree CLI."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class WorktreeInfo:
|
|
9
|
+
"""Metadata information for a Git worktree.
|
|
10
|
+
|
|
11
|
+
This dataclass stores all essential information about a managed worktree,
|
|
12
|
+
including its location, associated branch, creation time, and status.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
spec_id: str
|
|
16
|
+
"""The SPEC ID associated with this worktree (e.g., 'SPEC-AUTH-001')."""
|
|
17
|
+
|
|
18
|
+
path: Path
|
|
19
|
+
"""Absolute path to the worktree directory."""
|
|
20
|
+
|
|
21
|
+
branch: str
|
|
22
|
+
"""The Git branch associated with this worktree."""
|
|
23
|
+
|
|
24
|
+
created_at: str
|
|
25
|
+
"""ISO 8601 timestamp of worktree creation."""
|
|
26
|
+
|
|
27
|
+
last_accessed: str
|
|
28
|
+
"""ISO 8601 timestamp of last access."""
|
|
29
|
+
|
|
30
|
+
status: str
|
|
31
|
+
"""Current status of the worktree ('active', 'merged', 'stale')."""
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> dict:
|
|
34
|
+
"""Convert WorktreeInfo to dictionary for JSON serialization.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Dictionary with all worktree metadata.
|
|
38
|
+
"""
|
|
39
|
+
return {
|
|
40
|
+
"spec_id": self.spec_id,
|
|
41
|
+
"path": str(self.path),
|
|
42
|
+
"branch": self.branch,
|
|
43
|
+
"created_at": self.created_at,
|
|
44
|
+
"last_accessed": self.last_accessed,
|
|
45
|
+
"status": self.status,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def from_dict(cls, data: dict) -> "WorktreeInfo":
|
|
50
|
+
"""Create WorktreeInfo from dictionary (JSON deserialization).
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
data: Dictionary containing worktree metadata.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
New WorktreeInfo instance.
|
|
57
|
+
"""
|
|
58
|
+
return cls(
|
|
59
|
+
spec_id=data["spec_id"],
|
|
60
|
+
path=Path(data["path"]),
|
|
61
|
+
branch=data["branch"],
|
|
62
|
+
created_at=data["created_at"],
|
|
63
|
+
last_accessed=data["last_accessed"],
|
|
64
|
+
status=data["status"],
|
|
65
|
+
)
|