claude-mpm 4.21.3__py3-none-any.whl → 5.1.9__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 claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +12 -0
- claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +3 -48
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1239 -674
- claude_mpm/agents/WORKFLOW.md +75 -2
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +1 -4
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/frontmatter_validator.py +69 -1
- claude_mpm/agents/templates/circuit-breakers.md +1254 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +37 -2
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +188 -30
- claude_mpm/cli/commands/agents.py +1128 -36
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/auto_configure.py +537 -239
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +935 -45
- claude_mpm/cli/commands/configure_agent_display.py +4 -4
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mpm_init/core.py +50 -2
- claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
- claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +125 -167
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +757 -20
- claude_mpm/cli/executor.py +78 -3
- claude_mpm/cli/interactive/agent_wizard.py +1032 -47
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +310 -4
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
- claude_mpm/cli/parsers/base_parser.py +53 -0
- claude_mpm/cli/parsers/config_parser.py +96 -43
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +145 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +564 -108
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
- claude_mpm/commands/mpm-agents-detect.md +9 -0
- claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
- claude_mpm/commands/mpm-agents-recommend.md +9 -0
- claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
- claude_mpm/commands/mpm-doctor.md +9 -0
- claude_mpm/commands/mpm-help.md +14 -2
- claude_mpm/commands/mpm-init.md +27 -2
- claude_mpm/commands/mpm-monitor.md +9 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
- claude_mpm/commands/mpm-status.md +9 -0
- claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
- claude_mpm/commands/mpm-ticket-view.md +552 -0
- claude_mpm/commands/mpm-version.md +9 -0
- claude_mpm/commands/mpm.md +10 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +13 -0
- claude_mpm/core/api_validator.py +1 -1
- claude_mpm/core/claude_runner.py +19 -35
- claude_mpm/core/config.py +24 -0
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/framework/__init__.py +3 -16
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
- claude_mpm/core/framework/processors/metadata_processor.py +1 -1
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +131 -10
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +110 -8
- claude_mpm/core/output_style_manager.py +173 -43
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_agent_registry.py +129 -1
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +15 -15
- claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
- claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
- claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
- claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
- claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
- claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
- claude_mpm/dashboard/static/js/connection-manager.js +76 -76
- claude_mpm/dashboard/static/js/dashboard.js +76 -58
- claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/js/socket-client.js +138 -121
- claude_mpm/dashboard/templates/code_simple.html +23 -23
- claude_mpm/dashboard/templates/index.html +18 -18
- claude_mpm/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
- claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
- claude_mpm/hooks/claude_hooks/installer.py +45 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/scripts/claude-hook-handler.sh +3 -3
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/agent_builder.py +45 -9
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +225 -18
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +557 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +629 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
- claude_mpm/services/agents/local_template_manager.py +50 -10
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -0
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/cli/session_pause_manager.py +1 -1
- claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/command_deployment_service.py +200 -6
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/event_bus/event_bus.py +36 -3
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +494 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +3 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/local_ops/process_manager.py +1 -1
- claude_mpm/services/local_ops/resource_monitor.py +2 -2
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/memory/optimizer.py +1 -1
- claude_mpm/services/model/model_router.py +8 -9
- claude_mpm/services/monitor/daemon.py +29 -9
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/monitor/server.py +2 -2
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +17 -3
- claude_mpm/services/self_upgrade_service.py +165 -7
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/services/skills/__init__.py +18 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +955 -0
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +2 -2
- claude_mpm/services/socketio/server/core.py +1 -4
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/performance-profiling.md +6 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
- claude_mpm/skills/skills_registry.py +0 -1
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/tools/code_tree_analyzer/analysis.py +1 -1
- claude_mpm/utils/agent_dependency_loader.py +80 -13
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/log_cleanup.py +3 -3
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +3 -5
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +496 -65
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +284 -443
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -180
- claude_mpm/agents/templates/circuit_breakers.md +0 -638
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -211
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -287
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -140
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -242
- claude_mpm/agents/templates/react_engineer.json +0 -238
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -188
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/ticketing.json +0 -177
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -157
- claude_mpm/agents/templates/web_qa.json +0 -399
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/commands/mpm-tickets.md +0 -102
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cache Git Manager - Git workflow integration for agent cache management.
|
|
3
|
+
|
|
4
|
+
Design Decision: Wrap existing GitOperationsService instead of duplicating code
|
|
5
|
+
|
|
6
|
+
Rationale: GitOperationsService already provides all necessary git operations
|
|
7
|
+
(status, pull, commit, push) with proper error handling. This wrapper adapts
|
|
8
|
+
it specifically for cache directory operations without code duplication.
|
|
9
|
+
|
|
10
|
+
Trade-offs:
|
|
11
|
+
- Code Reuse: Leverages 90% of existing GitOperationsService (~400 lines)
|
|
12
|
+
- Maintainability: Changes to git operations benefit all users
|
|
13
|
+
- Specificity: Adds cache-specific behavior (status reporting, sync workflow)
|
|
14
|
+
- Simplicity: Net new code ~150 lines vs ~400 for complete reimplementation
|
|
15
|
+
|
|
16
|
+
Performance:
|
|
17
|
+
- Time Complexity: O(1) for status checks, O(n) for file operations where n = number of changed files
|
|
18
|
+
- Expected Performance:
|
|
19
|
+
* Status check: ~100-200ms (git status + rev-list)
|
|
20
|
+
* Pull latest: ~1-2s (git pull from GitHub)
|
|
21
|
+
* Commit + push: ~2-3s (git commit + push)
|
|
22
|
+
|
|
23
|
+
Error Handling:
|
|
24
|
+
- Network unavailable: Warns user, continues with cached version
|
|
25
|
+
- Merge conflicts: Detects, displays files, guides user to manual resolution
|
|
26
|
+
- Detached HEAD: Warns user, provides recovery instructions
|
|
27
|
+
- Push rejected: Informs about remote changes, suggests pull first
|
|
28
|
+
- Uncommitted changes: Warns before pull, offers to continue or abort
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
>>> from pathlib import Path
|
|
32
|
+
>>> manager = CacheGitManager(Path.home() / ".claude-mpm/cache/remote-agents")
|
|
33
|
+
>>> if manager.is_git_repo():
|
|
34
|
+
... status = manager.get_status()
|
|
35
|
+
... print(f"Branch: {status['branch']}, Uncommitted: {len(status['uncommitted'])}")
|
|
36
|
+
... success, msg = manager.pull_latest()
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
import logging
|
|
40
|
+
from pathlib import Path
|
|
41
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
42
|
+
|
|
43
|
+
from claude_mpm.services.git.git_operations_service import (
|
|
44
|
+
GitAuthenticationError,
|
|
45
|
+
GitConflictError,
|
|
46
|
+
GitOperationError,
|
|
47
|
+
GitOperationsService,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
logger = logging.getLogger(__name__)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class CacheGitManager:
|
|
54
|
+
"""
|
|
55
|
+
Git operations wrapper for agent cache directory.
|
|
56
|
+
|
|
57
|
+
Design Decision: Composition over inheritance
|
|
58
|
+
|
|
59
|
+
Rationale: Wraps GitOperationsService instead of inheriting to maintain
|
|
60
|
+
separation of concerns. Cache-specific logic (sync workflow, status
|
|
61
|
+
reporting) is independent from core git operations.
|
|
62
|
+
|
|
63
|
+
Provides high-level git workflows specifically for cache management:
|
|
64
|
+
- Pre-deploy git pull (sync latest agents)
|
|
65
|
+
- Status reporting with uncommitted/unpushed detection
|
|
66
|
+
- Full sync workflow (pull, handle conflicts, push)
|
|
67
|
+
- User-friendly error messages for cache context
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def __init__(self, cache_path: Path, timeout: int = 30):
|
|
71
|
+
"""
|
|
72
|
+
Initialize cache git manager.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
cache_path: Path to cache directory (should contain .git)
|
|
76
|
+
timeout: Git command timeout in seconds (default: 30)
|
|
77
|
+
|
|
78
|
+
Example:
|
|
79
|
+
>>> cache_dir = Path.home() / ".claude-mpm/cache/remote-agents"
|
|
80
|
+
>>> manager = CacheGitManager(cache_dir)
|
|
81
|
+
"""
|
|
82
|
+
self.cache_path = Path(cache_path)
|
|
83
|
+
self.git_ops = GitOperationsService(timeout=timeout)
|
|
84
|
+
|
|
85
|
+
# Find git repository root (cache_path or parent)
|
|
86
|
+
self.repo_path = self._find_git_root()
|
|
87
|
+
|
|
88
|
+
if self.repo_path:
|
|
89
|
+
logger.debug(f"Initialized CacheGitManager for repo: {self.repo_path}")
|
|
90
|
+
else:
|
|
91
|
+
logger.warning(f"Cache path is not a git repository: {cache_path}")
|
|
92
|
+
|
|
93
|
+
def _find_git_root(self) -> Optional[Path]:
|
|
94
|
+
"""
|
|
95
|
+
Find git repository root starting from cache_path.
|
|
96
|
+
|
|
97
|
+
Searches cache_path and up to 3 parent directories for .git directory.
|
|
98
|
+
If not found upward, searches one level down into subdirectories.
|
|
99
|
+
This handles both cases:
|
|
100
|
+
- cache_path is inside repo (search upward)
|
|
101
|
+
- repo is nested in cache_path (search downward)
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Path to repository root, or None if not a git repo
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
>>> # Case 1: cache_path inside repo (searches upward)
|
|
108
|
+
>>> # cache_path: ~/.claude-mpm/cache/remote-agents/bobmatnyc/claude-mpm-agents/agents
|
|
109
|
+
>>> # Found at: ~/.claude-mpm/cache/remote-agents/bobmatnyc/claude-mpm-agents
|
|
110
|
+
|
|
111
|
+
>>> # Case 2: repo nested in cache_path (searches downward)
|
|
112
|
+
>>> # cache_path: ~/.claude-mpm/cache/remote-agents
|
|
113
|
+
>>> # Found at: ~/.claude-mpm/cache/remote-agents/bobmatnyc/claude-mpm-agents
|
|
114
|
+
"""
|
|
115
|
+
# Strategy 1: Search upward (cache_path is inside repo)
|
|
116
|
+
current = self.cache_path
|
|
117
|
+
max_depth = 3
|
|
118
|
+
|
|
119
|
+
for _ in range(max_depth):
|
|
120
|
+
if self.git_ops.is_git_repo(current):
|
|
121
|
+
return current
|
|
122
|
+
parent = current.parent
|
|
123
|
+
if parent == current: # Reached filesystem root
|
|
124
|
+
break
|
|
125
|
+
current = parent
|
|
126
|
+
|
|
127
|
+
# Strategy 2: Search downward one level (repo nested in cache_path)
|
|
128
|
+
# Check immediate subdirectories for git repos
|
|
129
|
+
if self.cache_path.is_dir():
|
|
130
|
+
try:
|
|
131
|
+
for subdir in self.cache_path.iterdir():
|
|
132
|
+
if subdir.is_dir():
|
|
133
|
+
# Check if subdir itself is a git repo
|
|
134
|
+
if self.git_ops.is_git_repo(subdir):
|
|
135
|
+
return subdir
|
|
136
|
+
|
|
137
|
+
# Check one level deeper (handle org/repo structure)
|
|
138
|
+
try:
|
|
139
|
+
for nested_dir in subdir.iterdir():
|
|
140
|
+
if nested_dir.is_dir() and self.git_ops.is_git_repo(
|
|
141
|
+
nested_dir
|
|
142
|
+
):
|
|
143
|
+
return nested_dir
|
|
144
|
+
except (OSError, PermissionError):
|
|
145
|
+
# Skip subdirectories we can't read
|
|
146
|
+
continue
|
|
147
|
+
except (OSError, PermissionError) as e:
|
|
148
|
+
logger.debug(f"Could not scan cache directory for git repos: {e}")
|
|
149
|
+
|
|
150
|
+
return None
|
|
151
|
+
|
|
152
|
+
def is_git_repo(self) -> bool:
|
|
153
|
+
"""
|
|
154
|
+
Check if cache is a git repository.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
True if cache contains a valid git repository, False otherwise
|
|
158
|
+
|
|
159
|
+
Example:
|
|
160
|
+
>>> if not manager.is_git_repo():
|
|
161
|
+
... print("Cache is not a git repo. Falling back to HTTP sync.")
|
|
162
|
+
"""
|
|
163
|
+
return self.repo_path is not None
|
|
164
|
+
|
|
165
|
+
def get_status(self) -> Dict[str, Any]:
|
|
166
|
+
"""
|
|
167
|
+
Get comprehensive git status for cache.
|
|
168
|
+
|
|
169
|
+
Returns dictionary with current branch, uncommitted changes, and
|
|
170
|
+
unpushed commits. Useful for warning users before destructive operations.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Dictionary with status information:
|
|
174
|
+
{
|
|
175
|
+
"branch": "main",
|
|
176
|
+
"uncommitted": ["agents/engineer.md", "agents/research.md"],
|
|
177
|
+
"uncommitted_count": 2,
|
|
178
|
+
"unpushed": 3,
|
|
179
|
+
"is_clean": False,
|
|
180
|
+
"remote_url": "https://github.com/owner/repo",
|
|
181
|
+
"ahead": 3,
|
|
182
|
+
"behind": 0
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
Error Handling:
|
|
186
|
+
- Not a git repo: Returns error dict with "error" key
|
|
187
|
+
- Git command failure: Logs error, returns partial status
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
>>> status = manager.get_status()
|
|
191
|
+
>>> if status.get("uncommitted_count", 0) > 0:
|
|
192
|
+
... print(f"Warning: {status['uncommitted_count']} uncommitted changes")
|
|
193
|
+
... for file in status["uncommitted"]:
|
|
194
|
+
... print(f" - {file}")
|
|
195
|
+
"""
|
|
196
|
+
if not self.is_git_repo():
|
|
197
|
+
return {"error": "Not a git repository", "is_clean": True}
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
# Get current branch
|
|
201
|
+
branch = self.git_ops.get_current_branch(self.repo_path)
|
|
202
|
+
|
|
203
|
+
# Get uncommitted changes
|
|
204
|
+
has_changes = self.git_ops.has_uncommitted_changes(self.repo_path)
|
|
205
|
+
uncommitted_files: List[str] = []
|
|
206
|
+
|
|
207
|
+
if has_changes:
|
|
208
|
+
# Parse git status --porcelain for file list
|
|
209
|
+
returncode, stdout, _stderr = self.git_ops._run_git_command(
|
|
210
|
+
["git", "status", "--porcelain"], cwd=self.repo_path
|
|
211
|
+
)
|
|
212
|
+
if returncode == 0:
|
|
213
|
+
# Split without stripping first to preserve format
|
|
214
|
+
for line in stdout.split("\n"):
|
|
215
|
+
if line.strip():
|
|
216
|
+
# Extract filename from git status output (format: "XY filename")
|
|
217
|
+
# Skip first 3 characters (2 status + 1 space)
|
|
218
|
+
filename = (
|
|
219
|
+
line[3:].strip() if len(line) > 3 else line.strip()
|
|
220
|
+
)
|
|
221
|
+
if filename:
|
|
222
|
+
uncommitted_files.append(filename)
|
|
223
|
+
|
|
224
|
+
# Get unpushed commits (commits ahead of remote)
|
|
225
|
+
ahead = 0
|
|
226
|
+
behind = 0
|
|
227
|
+
try:
|
|
228
|
+
returncode, stdout, _stderr = self.git_ops._run_git_command(
|
|
229
|
+
[
|
|
230
|
+
"git",
|
|
231
|
+
"rev-list",
|
|
232
|
+
"--left-right",
|
|
233
|
+
"--count",
|
|
234
|
+
f"origin/{branch}...HEAD",
|
|
235
|
+
],
|
|
236
|
+
cwd=self.repo_path,
|
|
237
|
+
)
|
|
238
|
+
if returncode == 0 and stdout.strip():
|
|
239
|
+
parts = stdout.strip().split()
|
|
240
|
+
if len(parts) == 2:
|
|
241
|
+
try:
|
|
242
|
+
behind, ahead = map(int, parts)
|
|
243
|
+
except ValueError:
|
|
244
|
+
# Parsing error, skip ahead/behind count
|
|
245
|
+
logger.debug(
|
|
246
|
+
f"Could not parse rev-list output: {stdout.strip()}"
|
|
247
|
+
)
|
|
248
|
+
except (GitOperationError, Exception) as e:
|
|
249
|
+
# No remote tracking branch configured or other error
|
|
250
|
+
logger.debug(f"Could not get ahead/behind count: {e}")
|
|
251
|
+
|
|
252
|
+
# Get remote URL
|
|
253
|
+
remote_url = self.git_ops.get_remote_url(self.repo_path)
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
"branch": branch,
|
|
257
|
+
"uncommitted": uncommitted_files,
|
|
258
|
+
"uncommitted_count": len(uncommitted_files),
|
|
259
|
+
"unpushed": ahead,
|
|
260
|
+
"is_clean": not has_changes and ahead == 0,
|
|
261
|
+
"remote_url": remote_url,
|
|
262
|
+
"ahead": ahead,
|
|
263
|
+
"behind": behind,
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
except GitOperationError as e:
|
|
267
|
+
logger.error(f"Error getting git status: {e}")
|
|
268
|
+
return {
|
|
269
|
+
"error": str(e),
|
|
270
|
+
"is_clean": False,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
def pull_latest(self, branch: str = "main") -> Tuple[bool, str]:
|
|
274
|
+
"""
|
|
275
|
+
Pull latest changes from remote.
|
|
276
|
+
|
|
277
|
+
Design Decision: Non-blocking pull with informative messages
|
|
278
|
+
|
|
279
|
+
Rationale: Pull failures shouldn't stop deployment. Cache may be
|
|
280
|
+
outdated but still usable. HTTP sync provides fallback mechanism.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
branch: Branch to pull (default: "main")
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
Tuple of (success, message) where:
|
|
287
|
+
- success: True if pull succeeded, False if failed
|
|
288
|
+
- message: Human-readable status message
|
|
289
|
+
|
|
290
|
+
Error Handling:
|
|
291
|
+
- Merge conflicts: Returns (False, detailed conflict message)
|
|
292
|
+
- Network errors: Returns (False, network error message)
|
|
293
|
+
- Detached HEAD: Returns (False, recovery instructions)
|
|
294
|
+
- Success: Returns (True, summary of changes)
|
|
295
|
+
|
|
296
|
+
Example:
|
|
297
|
+
>>> success, msg = manager.pull_latest()
|
|
298
|
+
>>> if not success:
|
|
299
|
+
... logger.warning(f"Pull failed: {msg}")
|
|
300
|
+
... logger.info("Continuing with cached version")
|
|
301
|
+
"""
|
|
302
|
+
if not self.is_git_repo():
|
|
303
|
+
return False, "Not a git repository"
|
|
304
|
+
|
|
305
|
+
try:
|
|
306
|
+
# Check for uncommitted changes first
|
|
307
|
+
if self.git_ops.has_uncommitted_changes(self.repo_path):
|
|
308
|
+
uncommitted_count = len(self.get_status().get("uncommitted", []))
|
|
309
|
+
logger.warning(
|
|
310
|
+
f"Cache has {uncommitted_count} uncommitted change(s). "
|
|
311
|
+
"Pull may fail or create merge conflicts."
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Perform pull
|
|
315
|
+
self.git_ops.pull(self.repo_path, branch)
|
|
316
|
+
|
|
317
|
+
logger.info(f"Successfully pulled latest changes from {branch}")
|
|
318
|
+
return True, f"Successfully pulled latest changes from {branch}"
|
|
319
|
+
|
|
320
|
+
except GitConflictError:
|
|
321
|
+
# Parse conflict details from error message
|
|
322
|
+
conflict_msg = (
|
|
323
|
+
f"Merge conflicts detected when pulling {branch}. "
|
|
324
|
+
"Manual resolution required.\n\n"
|
|
325
|
+
"To resolve:\n"
|
|
326
|
+
f" 1. cd {self.repo_path}\n"
|
|
327
|
+
" 2. Resolve conflicts in affected files\n"
|
|
328
|
+
" 3. git add <resolved-files>\n"
|
|
329
|
+
" 4. git commit\n"
|
|
330
|
+
" 5. Run sync again"
|
|
331
|
+
)
|
|
332
|
+
logger.error(conflict_msg)
|
|
333
|
+
return False, conflict_msg
|
|
334
|
+
|
|
335
|
+
except GitOperationError as e:
|
|
336
|
+
error_msg = f"Failed to pull {branch}: {e!s}"
|
|
337
|
+
logger.error(error_msg)
|
|
338
|
+
return False, error_msg
|
|
339
|
+
|
|
340
|
+
def commit_changes(
|
|
341
|
+
self, message: str, files: Optional[List[Path]] = None
|
|
342
|
+
) -> Tuple[bool, str]:
|
|
343
|
+
"""
|
|
344
|
+
Commit changes to cache.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
message: Commit message (should follow conventional commits format)
|
|
348
|
+
files: Specific files to commit (None = all modified files)
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
Tuple of (success, message)
|
|
352
|
+
|
|
353
|
+
Error Handling:
|
|
354
|
+
- No changes to commit: Returns (False, informative message)
|
|
355
|
+
- Git commit failure: Returns (False, error details)
|
|
356
|
+
- File staging error: Returns (False, staging error message)
|
|
357
|
+
|
|
358
|
+
Example:
|
|
359
|
+
>>> success, msg = manager.commit_changes(
|
|
360
|
+
... "feat: update agents from local development",
|
|
361
|
+
... files=[Path("agents/engineer.md")]
|
|
362
|
+
... )
|
|
363
|
+
>>> if success:
|
|
364
|
+
... print(f"Committed: {msg}")
|
|
365
|
+
"""
|
|
366
|
+
if not self.is_git_repo():
|
|
367
|
+
return False, "Not a git repository"
|
|
368
|
+
|
|
369
|
+
try:
|
|
370
|
+
# Stage files
|
|
371
|
+
if files:
|
|
372
|
+
# Convert Path objects to strings relative to repo root
|
|
373
|
+
file_strs = [str(f.relative_to(self.repo_path)) for f in files]
|
|
374
|
+
self.git_ops.stage_files(self.repo_path, file_strs)
|
|
375
|
+
else:
|
|
376
|
+
# Stage all changes
|
|
377
|
+
self.git_ops.stage_files(self.repo_path, ["."])
|
|
378
|
+
|
|
379
|
+
# Commit
|
|
380
|
+
self.git_ops.commit(self.repo_path, message)
|
|
381
|
+
|
|
382
|
+
logger.info(f"Committed changes: {message[:50]}")
|
|
383
|
+
return True, "Successfully committed changes"
|
|
384
|
+
|
|
385
|
+
except GitOperationError as e:
|
|
386
|
+
error_msg = f"Failed to commit: {e!s}"
|
|
387
|
+
logger.error(error_msg)
|
|
388
|
+
return False, error_msg
|
|
389
|
+
|
|
390
|
+
def push_changes(self, branch: str = "main") -> Tuple[bool, str]:
|
|
391
|
+
"""
|
|
392
|
+
Push committed changes to remote.
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
branch: Branch to push (default: "main")
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
Tuple of (success, message)
|
|
399
|
+
|
|
400
|
+
Error Handling:
|
|
401
|
+
- Authentication failure: Returns (False, auth error with instructions)
|
|
402
|
+
- Push rejected: Returns (False, suggests pull first)
|
|
403
|
+
- Network error: Returns (False, network error message)
|
|
404
|
+
|
|
405
|
+
Example:
|
|
406
|
+
>>> success, msg = manager.push_changes()
|
|
407
|
+
>>> if not success:
|
|
408
|
+
... if "authentication" in msg.lower():
|
|
409
|
+
... print("Configure SSH keys or GitHub token")
|
|
410
|
+
"""
|
|
411
|
+
if not self.is_git_repo():
|
|
412
|
+
return False, "Not a git repository"
|
|
413
|
+
|
|
414
|
+
try:
|
|
415
|
+
self.git_ops.push(self.repo_path, branch, set_upstream=True)
|
|
416
|
+
|
|
417
|
+
logger.info(f"Successfully pushed changes to {branch}")
|
|
418
|
+
return True, f"Successfully pushed changes to {branch}"
|
|
419
|
+
|
|
420
|
+
except GitAuthenticationError as e:
|
|
421
|
+
error_msg = (
|
|
422
|
+
f"Authentication failed: {e!s}\n\n"
|
|
423
|
+
"To fix:\n"
|
|
424
|
+
" 1. Configure SSH keys: ssh-keygen -t ed25519\n"
|
|
425
|
+
" 2. Add to GitHub: https://github.com/settings/keys\n"
|
|
426
|
+
" OR\n"
|
|
427
|
+
" 3. Use HTTPS with token: git remote set-url origin https://TOKEN@github.com/owner/repo"
|
|
428
|
+
)
|
|
429
|
+
logger.error(error_msg)
|
|
430
|
+
return False, error_msg
|
|
431
|
+
|
|
432
|
+
except GitOperationError as e:
|
|
433
|
+
# Check if push was rejected due to remote changes
|
|
434
|
+
if "rejected" in str(e).lower() or "non-fast-forward" in str(e).lower():
|
|
435
|
+
error_msg = (
|
|
436
|
+
"Push rejected: Remote has changes you don't have locally.\n\n"
|
|
437
|
+
"To fix:\n"
|
|
438
|
+
" 1. Pull latest changes: git pull origin main\n"
|
|
439
|
+
" 2. Resolve any conflicts\n"
|
|
440
|
+
" 3. Push again"
|
|
441
|
+
)
|
|
442
|
+
else:
|
|
443
|
+
error_msg = f"Failed to push: {e!s}"
|
|
444
|
+
|
|
445
|
+
logger.error(error_msg)
|
|
446
|
+
return False, error_msg
|
|
447
|
+
|
|
448
|
+
def has_uncommitted_changes(self) -> bool:
|
|
449
|
+
"""
|
|
450
|
+
Check for uncommitted changes in cache.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
True if there are uncommitted changes, False otherwise
|
|
454
|
+
|
|
455
|
+
Example:
|
|
456
|
+
>>> if manager.has_uncommitted_changes():
|
|
457
|
+
... print("⚠️ Uncommitted changes detected")
|
|
458
|
+
... print("Commit changes before pushing")
|
|
459
|
+
"""
|
|
460
|
+
if not self.is_git_repo():
|
|
461
|
+
return False
|
|
462
|
+
|
|
463
|
+
try:
|
|
464
|
+
return self.git_ops.has_uncommitted_changes(self.repo_path)
|
|
465
|
+
except GitOperationError:
|
|
466
|
+
return False
|
|
467
|
+
|
|
468
|
+
def has_unpushed_commits(self) -> bool:
|
|
469
|
+
"""
|
|
470
|
+
Check for commits not pushed to remote.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
True if there are unpushed commits, False otherwise
|
|
474
|
+
|
|
475
|
+
Example:
|
|
476
|
+
>>> if manager.has_unpushed_commits():
|
|
477
|
+
... print("📤 You have local commits not pushed to remote")
|
|
478
|
+
... print("Run: claude-mpm agents cache-push")
|
|
479
|
+
"""
|
|
480
|
+
status = self.get_status()
|
|
481
|
+
return status.get("unpushed", 0) > 0
|
|
482
|
+
|
|
483
|
+
def check_conflicts(self) -> List[Path]:
|
|
484
|
+
"""
|
|
485
|
+
Check for merge conflicts after pull.
|
|
486
|
+
|
|
487
|
+
Scans working directory for Git conflict markers (<<<<<<, ======, >>>>>>).
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
List of file paths with unresolved conflicts
|
|
491
|
+
|
|
492
|
+
Algorithm:
|
|
493
|
+
1. Run git status --porcelain to find files with merge conflicts
|
|
494
|
+
2. Look for "UU" status (both modified - conflict)
|
|
495
|
+
3. Return relative paths for user-friendly display
|
|
496
|
+
|
|
497
|
+
Example:
|
|
498
|
+
>>> conflicts = manager.check_conflicts()
|
|
499
|
+
>>> if conflicts:
|
|
500
|
+
... print("⚠️ Merge conflicts detected:")
|
|
501
|
+
... for file in conflicts:
|
|
502
|
+
... print(f" - {file}")
|
|
503
|
+
"""
|
|
504
|
+
if not self.is_git_repo():
|
|
505
|
+
return []
|
|
506
|
+
|
|
507
|
+
try:
|
|
508
|
+
returncode, stdout, _stderr = self.git_ops._run_git_command(
|
|
509
|
+
["git", "status", "--porcelain"], cwd=self.repo_path
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
if returncode != 0:
|
|
513
|
+
return []
|
|
514
|
+
|
|
515
|
+
# Parse git status output for conflict markers
|
|
516
|
+
conflicted_files: List[Path] = []
|
|
517
|
+
for line in stdout.strip().split("\n"):
|
|
518
|
+
if line.strip():
|
|
519
|
+
status = line[:2]
|
|
520
|
+
# "UU" means both modified (merge conflict)
|
|
521
|
+
# "AA" means both added
|
|
522
|
+
# "DD" means both deleted
|
|
523
|
+
if status in ["UU", "AA", "DD", "AU", "UA", "DU", "UD"]:
|
|
524
|
+
filename = line[3:].strip()
|
|
525
|
+
conflicted_files.append(Path(filename))
|
|
526
|
+
|
|
527
|
+
return conflicted_files
|
|
528
|
+
|
|
529
|
+
except GitOperationError as e:
|
|
530
|
+
logger.error(f"Error checking conflicts: {e}")
|
|
531
|
+
return []
|
|
532
|
+
|
|
533
|
+
def sync_with_remote(self) -> Tuple[bool, str]:
|
|
534
|
+
"""
|
|
535
|
+
Full sync workflow: pull, handle conflicts, push if needed.
|
|
536
|
+
|
|
537
|
+
Design Decision: Three-phase sync with conflict detection
|
|
538
|
+
|
|
539
|
+
Rationale: Provides complete sync automation while protecting against
|
|
540
|
+
data loss. Detects issues (uncommitted changes, conflicts) and guides
|
|
541
|
+
user through resolution rather than silently failing.
|
|
542
|
+
|
|
543
|
+
Workflow:
|
|
544
|
+
1. Check for uncommitted changes (warn user but continue)
|
|
545
|
+
2. Pull latest from remote
|
|
546
|
+
3. Detect and report conflicts (stops if found)
|
|
547
|
+
4. Push local commits if any exist and no conflicts
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
Tuple of (success, detailed_message)
|
|
551
|
+
|
|
552
|
+
Error Handling:
|
|
553
|
+
- Uncommitted changes: Warns user, continues with pull
|
|
554
|
+
- Conflicts: Stops sync, provides resolution instructions
|
|
555
|
+
- Network errors: Reports error, doesn't attempt push
|
|
556
|
+
- Push failures: Reports error with recovery instructions
|
|
557
|
+
|
|
558
|
+
Example:
|
|
559
|
+
>>> success, msg = manager.sync_with_remote()
|
|
560
|
+
>>> print(msg) # Detailed breakdown of sync process
|
|
561
|
+
>>> if not success:
|
|
562
|
+
... logger.error("Sync failed, investigate manually")
|
|
563
|
+
"""
|
|
564
|
+
if not self.is_git_repo():
|
|
565
|
+
return False, "Not a git repository"
|
|
566
|
+
|
|
567
|
+
status_log = []
|
|
568
|
+
|
|
569
|
+
# Phase 1: Check for uncommitted changes
|
|
570
|
+
status_log.append("Phase 1: Checking local changes...")
|
|
571
|
+
if self.has_uncommitted_changes():
|
|
572
|
+
uncommitted_count = self.get_status().get("uncommitted_count", 0)
|
|
573
|
+
warning = (
|
|
574
|
+
f"⚠️ Warning: {uncommitted_count} uncommitted change(s) detected.\n"
|
|
575
|
+
" Sync will continue, but you should commit these changes."
|
|
576
|
+
)
|
|
577
|
+
status_log.append(warning)
|
|
578
|
+
logger.warning(warning)
|
|
579
|
+
|
|
580
|
+
# Phase 2: Pull latest
|
|
581
|
+
status_log.append("\nPhase 2: Pulling latest changes...")
|
|
582
|
+
pull_success, pull_msg = self.pull_latest()
|
|
583
|
+
|
|
584
|
+
if not pull_success:
|
|
585
|
+
status_log.append(f"❌ Pull failed: {pull_msg}")
|
|
586
|
+
return False, "\n".join(status_log)
|
|
587
|
+
|
|
588
|
+
status_log.append(f"✅ {pull_msg}")
|
|
589
|
+
|
|
590
|
+
# Phase 3: Check for conflicts
|
|
591
|
+
status_log.append("\nPhase 3: Checking for conflicts...")
|
|
592
|
+
conflicts = self.check_conflicts()
|
|
593
|
+
|
|
594
|
+
if conflicts:
|
|
595
|
+
conflict_msg = (
|
|
596
|
+
f"❌ {len(conflicts)} merge conflict(s) detected:\n"
|
|
597
|
+
+ "\n".join(f" - {file}" for file in conflicts)
|
|
598
|
+
+ "\n\nResolve conflicts manually before continuing."
|
|
599
|
+
)
|
|
600
|
+
status_log.append(conflict_msg)
|
|
601
|
+
return False, "\n".join(status_log)
|
|
602
|
+
|
|
603
|
+
status_log.append("✅ No conflicts detected")
|
|
604
|
+
|
|
605
|
+
# Phase 4: Push if we have local commits
|
|
606
|
+
status_log.append("\nPhase 4: Checking for local commits...")
|
|
607
|
+
if self.has_unpushed_commits():
|
|
608
|
+
unpushed = self.get_status().get("unpushed", 0)
|
|
609
|
+
status_log.append(f"📤 Pushing {unpushed} local commit(s)...")
|
|
610
|
+
|
|
611
|
+
push_success, push_msg = self.push_changes()
|
|
612
|
+
if not push_success:
|
|
613
|
+
status_log.append(f"❌ Push failed: {push_msg}")
|
|
614
|
+
return False, "\n".join(status_log)
|
|
615
|
+
|
|
616
|
+
status_log.append(f"✅ {push_msg}")
|
|
617
|
+
else:
|
|
618
|
+
status_log.append("✅ No local commits to push")
|
|
619
|
+
|
|
620
|
+
status_log.append("\n✅ Sync complete!")
|
|
621
|
+
return True, "\n".join(status_log)
|