claude-mpm 4.21.3__py3-none-any.whl → 5.0.2__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +12 -0
- claude_mpm/agents/OUTPUT_STYLE.md +3 -48
- claude_mpm/agents/PM_INSTRUCTIONS.md +632 -334
- 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/frontmatter_validator.py +1 -1
- claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +370 -3
- 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 +38 -2
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +125 -20
- claude_mpm/cli/commands/agents.py +684 -13
- 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 +2 -6
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +478 -44
- 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/run.py +124 -128
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +435 -1
- claude_mpm/cli/executor.py +78 -3
- claude_mpm/cli/interactive/agent_wizard.py +919 -41
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +173 -4
- claude_mpm/cli/parsers/base_parser.py +49 -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 +138 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +499 -84
- 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 +11 -2
- claude_mpm/commands/mpm-init.md +27 -2
- claude_mpm/commands/mpm-monitor.md +9 -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 +258 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +12 -0
- claude_mpm/core/api_validator.py +1 -1
- claude_mpm/core/claude_runner.py +17 -10
- 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/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 +112 -5
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +94 -4
- 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/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/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/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 +115 -15
- 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 +363 -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 +1055 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -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 +92 -1
- 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/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_gateway/config/configuration.py +1 -1
- 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/memory/optimizer.py +1 -1
- claude_mpm/services/model/model_router.py +8 -9
- claude_mpm/services/monitor/daemon.py +1 -1
- 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/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +1 -0
- claude_mpm/services/self_upgrade_service.py +165 -7
- 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/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +241 -0
- claude_mpm/utils/log_cleanup.py +3 -3
- claude_mpm/utils/progress.py +383 -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.0.2.dist-info}/METADATA +429 -59
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/RECORD +252 -425
- 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/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.0.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.21.3.dist-info → claude_mpm-5.0.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""GitIgnore management utilities.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to safely manage .gitignore entries,
|
|
4
|
+
ensuring claude-mpm configuration directories are excluded from version control.
|
|
5
|
+
|
|
6
|
+
Design Decisions:
|
|
7
|
+
- In-memory set for duplicate detection (O(1) lookups)
|
|
8
|
+
- Preserves existing file formatting and comments
|
|
9
|
+
- Adds section headers for clarity
|
|
10
|
+
- Handles edge cases (missing newlines, empty files, etc.)
|
|
11
|
+
|
|
12
|
+
Trade-offs:
|
|
13
|
+
- Simplicity: File append vs. full parse/rewrite (chosen append for safety)
|
|
14
|
+
- Performance: Read entire file vs. streaming (file is small, simplicity wins)
|
|
15
|
+
- Safety: Non-destructive append only, never modifies existing entries
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import List, Set, Tuple
|
|
20
|
+
|
|
21
|
+
from claude_mpm.core.logging_utils import get_logger
|
|
22
|
+
|
|
23
|
+
logger = get_logger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class GitIgnoreManager:
|
|
27
|
+
"""Manages .gitignore file updates safely and non-destructively.
|
|
28
|
+
|
|
29
|
+
Design Pattern: Builder pattern for fluent API
|
|
30
|
+
- Initialize with project directory
|
|
31
|
+
- Call ensure_entries() to add patterns
|
|
32
|
+
- Returns summary of changes made
|
|
33
|
+
|
|
34
|
+
Performance:
|
|
35
|
+
- Time Complexity: O(n) where n = existing .gitignore lines
|
|
36
|
+
- Space Complexity: O(n) for storing unique entries in set
|
|
37
|
+
- Expected Performance: <1ms for typical .gitignore files (<1000 lines)
|
|
38
|
+
|
|
39
|
+
Error Handling:
|
|
40
|
+
- FileNotFoundError: Creates new .gitignore if missing
|
|
41
|
+
- PermissionError: Propagated to caller for appropriate handling
|
|
42
|
+
- UnicodeDecodeError: Logged and treated as binary file (skip)
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, project_dir: Path):
|
|
46
|
+
"""Initialize with project directory.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
project_dir: Path to project root (where .gitignore lives)
|
|
50
|
+
"""
|
|
51
|
+
self.project_dir = Path(project_dir)
|
|
52
|
+
self.gitignore_path = self.project_dir / ".gitignore"
|
|
53
|
+
|
|
54
|
+
def ensure_entries(self, entries: List[str]) -> Tuple[List[str], List[str]]:
|
|
55
|
+
"""Ensure specified entries exist in .gitignore.
|
|
56
|
+
|
|
57
|
+
Non-destructive operation that:
|
|
58
|
+
1. Reads existing entries (if file exists)
|
|
59
|
+
2. Identifies which entries are missing
|
|
60
|
+
3. Appends only missing entries with section header
|
|
61
|
+
4. Preserves all existing content and formatting
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
entries: List of gitignore patterns to add (e.g., [".claude-mpm/"])
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Tuple of (added_entries, existing_entries)
|
|
68
|
+
- added_entries: Patterns that were added to .gitignore
|
|
69
|
+
- existing_entries: Patterns that were already present
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
>>> manager = GitIgnoreManager(Path("."))
|
|
73
|
+
>>> added, existing = manager.ensure_entries([".claude-mpm/"])
|
|
74
|
+
>>> print(f"Added: {added}, Already present: {existing}")
|
|
75
|
+
Added: ['.claude-mpm/'], Already present: []
|
|
76
|
+
"""
|
|
77
|
+
# Read existing entries
|
|
78
|
+
existing = self._read_existing_entries()
|
|
79
|
+
|
|
80
|
+
# Determine what needs to be added
|
|
81
|
+
to_add = [e for e in entries if e not in existing]
|
|
82
|
+
already_present = [e for e in entries if e in existing]
|
|
83
|
+
|
|
84
|
+
if to_add:
|
|
85
|
+
self._append_entries(to_add)
|
|
86
|
+
logger.info(f"Added {len(to_add)} entries to .gitignore: {to_add}")
|
|
87
|
+
|
|
88
|
+
if already_present:
|
|
89
|
+
logger.debug(f"Entries already in .gitignore: {already_present}")
|
|
90
|
+
|
|
91
|
+
return to_add, already_present
|
|
92
|
+
|
|
93
|
+
def _read_existing_entries(self) -> Set[str]:
|
|
94
|
+
"""Read existing .gitignore entries.
|
|
95
|
+
|
|
96
|
+
Parses .gitignore file and extracts all non-comment, non-blank patterns.
|
|
97
|
+
Handles edge cases:
|
|
98
|
+
- File doesn't exist -> returns empty set
|
|
99
|
+
- File is binary -> logs warning, returns empty set
|
|
100
|
+
- File has no newline at end -> handled correctly
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Set of existing gitignore patterns (stripped, normalized)
|
|
104
|
+
"""
|
|
105
|
+
if not self.gitignore_path.exists():
|
|
106
|
+
logger.debug(".gitignore does not exist, will create new file")
|
|
107
|
+
return set()
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
with open(self.gitignore_path, encoding="utf-8") as f:
|
|
111
|
+
# Strip whitespace and comments, filter blanks
|
|
112
|
+
entries = {
|
|
113
|
+
line.strip()
|
|
114
|
+
for line in f
|
|
115
|
+
if line.strip() and not line.strip().startswith("#")
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
logger.debug(f"Found {len(entries)} existing entries in .gitignore")
|
|
119
|
+
return entries
|
|
120
|
+
|
|
121
|
+
except UnicodeDecodeError:
|
|
122
|
+
logger.warning(
|
|
123
|
+
f".gitignore appears to be binary, cannot parse: {self.gitignore_path}"
|
|
124
|
+
)
|
|
125
|
+
return set()
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.error(f"Error reading .gitignore: {e}")
|
|
128
|
+
raise
|
|
129
|
+
|
|
130
|
+
def _append_entries(self, entries: List[str]) -> None:
|
|
131
|
+
"""Append entries to .gitignore with proper formatting.
|
|
132
|
+
|
|
133
|
+
Handles formatting edge cases:
|
|
134
|
+
- Ensures blank line before new section (if file exists and isn't empty)
|
|
135
|
+
- Adds section header comment for clarity
|
|
136
|
+
- Ensures each entry on its own line
|
|
137
|
+
- Handles missing trailing newline in existing file
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
entries: List of patterns to append
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
PermissionError: If cannot write to .gitignore
|
|
144
|
+
OSError: If disk is full or other I/O error
|
|
145
|
+
"""
|
|
146
|
+
mode = "a" if self.gitignore_path.exists() else "w"
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
with open(self.gitignore_path, mode, encoding="utf-8") as f:
|
|
150
|
+
# Add blank line before entries if file exists and isn't empty
|
|
151
|
+
if mode == "a" and self.gitignore_path.stat().st_size > 0:
|
|
152
|
+
# Check if last line has newline
|
|
153
|
+
with open(self.gitignore_path, "rb") as check:
|
|
154
|
+
check.seek(-1, 2) # Seek to last byte
|
|
155
|
+
last_byte = check.read(1)
|
|
156
|
+
if last_byte != b"\n":
|
|
157
|
+
f.write("\n")
|
|
158
|
+
|
|
159
|
+
f.write("\n# Claude MPM configuration\n")
|
|
160
|
+
else:
|
|
161
|
+
# New file or empty file - add header without extra blank line
|
|
162
|
+
f.write("# Claude MPM configuration\n")
|
|
163
|
+
|
|
164
|
+
for entry in entries:
|
|
165
|
+
f.write(f"{entry}\n")
|
|
166
|
+
|
|
167
|
+
logger.info(f"Updated .gitignore at {self.gitignore_path}")
|
|
168
|
+
|
|
169
|
+
except PermissionError:
|
|
170
|
+
logger.error(
|
|
171
|
+
f"Permission denied writing to .gitignore: {self.gitignore_path}"
|
|
172
|
+
)
|
|
173
|
+
raise
|
|
174
|
+
except OSError as e:
|
|
175
|
+
logger.error(f"I/O error writing to .gitignore: {e}")
|
|
176
|
+
raise
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def ensure_claude_mpm_gitignore(project_dir: str = ".") -> dict:
|
|
180
|
+
"""Ensure claude-mpm directories are in .gitignore.
|
|
181
|
+
|
|
182
|
+
Convenience function that wraps GitIgnoreManager to add standard
|
|
183
|
+
claude-mpm configuration directories to .gitignore.
|
|
184
|
+
|
|
185
|
+
Standard Entries Added:
|
|
186
|
+
- .claude-mpm/: Main configuration directory
|
|
187
|
+
- .claude/agents/: Agent runtime files
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
project_dir: Project directory path (default: current directory)
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Dictionary with operation results:
|
|
194
|
+
- added: List of patterns that were added
|
|
195
|
+
- existing: List of patterns that were already present
|
|
196
|
+
- gitignore_path: Path to the .gitignore file
|
|
197
|
+
|
|
198
|
+
Example:
|
|
199
|
+
>>> result = ensure_claude_mpm_gitignore()
|
|
200
|
+
>>> if result["added"]:
|
|
201
|
+
... print(f"Added {len(result['added'])} entries to .gitignore")
|
|
202
|
+
|
|
203
|
+
Error Handling:
|
|
204
|
+
- PermissionError: Returns error dict with status="error"
|
|
205
|
+
- FileNotFoundError on parent dir: Returns error dict
|
|
206
|
+
- All other exceptions: Propagated to caller
|
|
207
|
+
"""
|
|
208
|
+
try:
|
|
209
|
+
manager = GitIgnoreManager(Path(project_dir))
|
|
210
|
+
|
|
211
|
+
# Standard claude-mpm entries
|
|
212
|
+
entries_to_add = [
|
|
213
|
+
".claude-mpm/",
|
|
214
|
+
".claude/agents/",
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
added, existing = manager.ensure_entries(entries_to_add)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
"status": "success",
|
|
221
|
+
"added": added,
|
|
222
|
+
"existing": existing,
|
|
223
|
+
"gitignore_path": str(manager.gitignore_path),
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
except PermissionError as e:
|
|
227
|
+
logger.error(f"Permission denied updating .gitignore: {e}")
|
|
228
|
+
return {
|
|
229
|
+
"status": "error",
|
|
230
|
+
"error": f"Permission denied: {e}",
|
|
231
|
+
"added": [],
|
|
232
|
+
"existing": [],
|
|
233
|
+
}
|
|
234
|
+
except FileNotFoundError as e:
|
|
235
|
+
logger.error(f"Project directory not found: {e}")
|
|
236
|
+
return {
|
|
237
|
+
"status": "error",
|
|
238
|
+
"error": f"Directory not found: {e}",
|
|
239
|
+
"added": [],
|
|
240
|
+
"existing": [],
|
|
241
|
+
}
|
claude_mpm/utils/log_cleanup.py
CHANGED
|
@@ -496,15 +496,15 @@ class LogCleanupUtility:
|
|
|
496
496
|
}
|
|
497
497
|
|
|
498
498
|
# Cleanup operations
|
|
499
|
-
|
|
499
|
+
_sessions_removed, _sessions_space = self.cleanup_old_sessions(
|
|
500
500
|
session_max_age_days, dry_run
|
|
501
501
|
)
|
|
502
502
|
|
|
503
|
-
|
|
503
|
+
_archives_removed, _archives_space = self.cleanup_archived_logs(
|
|
504
504
|
archive_max_age_days, dry_run
|
|
505
505
|
)
|
|
506
506
|
|
|
507
|
-
|
|
507
|
+
_logs_removed, _logs_space = self.cleanup_old_logs(log_max_age_days, dry_run)
|
|
508
508
|
|
|
509
509
|
# Optional compression
|
|
510
510
|
if compress_age_days is not None:
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"""ASCII Progress Bar Utility for Git Operations.
|
|
2
|
+
|
|
3
|
+
WHY: Provides visual feedback during long-running operations like agent/skill downloads
|
|
4
|
+
from Git sources. Enhances user experience with real-time progress indicators.
|
|
5
|
+
|
|
6
|
+
DESIGN DECISION: Terminal-aware progress bar with graceful degradation
|
|
7
|
+
|
|
8
|
+
Rationale: Use sys.stdout for line overwriting with \r to create animated progress bars.
|
|
9
|
+
Detect TTY environments to avoid breaking non-interactive terminals (CI/CD, pipes).
|
|
10
|
+
ASCII-based to ensure compatibility across all terminal types.
|
|
11
|
+
|
|
12
|
+
Trade-offs:
|
|
13
|
+
- Performance: Progress updates are throttled to avoid output flooding
|
|
14
|
+
- Compatibility: Works in both TTY and non-TTY modes (graceful degradation)
|
|
15
|
+
- Simplicity: Pure Python, no external dependencies (tqdm would be overkill)
|
|
16
|
+
|
|
17
|
+
Extension Points: Can be extended to support multi-line progress (parallel downloads),
|
|
18
|
+
nested progress bars, or integration with logging frameworks.
|
|
19
|
+
|
|
20
|
+
Performance:
|
|
21
|
+
- Time Complexity: O(1) for each update operation
|
|
22
|
+
- Space Complexity: O(1) - no state accumulation
|
|
23
|
+
- Expected Performance: <1ms per update, negligible overhead
|
|
24
|
+
|
|
25
|
+
Example Usage:
|
|
26
|
+
>>> with ProgressBar(total=100, prefix="Downloading") as pb:
|
|
27
|
+
... for i in range(100):
|
|
28
|
+
... time.sleep(0.01)
|
|
29
|
+
... pb.update(i + 1)
|
|
30
|
+
... # Progress bar updates automatically
|
|
31
|
+
>>> # Automatically prints completion message and newline
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
import os
|
|
35
|
+
import sys
|
|
36
|
+
import time
|
|
37
|
+
from typing import Any, Optional
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ProgressBar:
|
|
41
|
+
"""ASCII progress bar for terminal output.
|
|
42
|
+
|
|
43
|
+
Features:
|
|
44
|
+
- Animated progress bar with percentage
|
|
45
|
+
- Current/total item counter
|
|
46
|
+
- Customizable prefix message
|
|
47
|
+
- TTY detection for safe degradation
|
|
48
|
+
- Automatic terminal width detection
|
|
49
|
+
- Context manager support for cleanup
|
|
50
|
+
|
|
51
|
+
Design Decision: Use █ (U+2588) for filled sections and ░ (U+2591) for empty
|
|
52
|
+
|
|
53
|
+
Rationale: These Unicode block characters provide clear visual progress while
|
|
54
|
+
maintaining compatibility with most modern terminals. Alternative ASCII chars
|
|
55
|
+
like '#' and '-' were rejected for being less visually appealing.
|
|
56
|
+
|
|
57
|
+
Compatibility: Gracefully degrades to simple logging in non-TTY environments
|
|
58
|
+
(CI/CD, redirected output, etc.)
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
total: int,
|
|
64
|
+
prefix: str = "Progress",
|
|
65
|
+
bar_width: int = 20,
|
|
66
|
+
show_percentage: bool = True,
|
|
67
|
+
show_counter: bool = True,
|
|
68
|
+
enabled: Optional[bool] = None,
|
|
69
|
+
):
|
|
70
|
+
"""Initialize progress bar.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
total: Total number of items to process
|
|
74
|
+
prefix: Message to display before progress bar (e.g., "Downloading")
|
|
75
|
+
bar_width: Width of the progress bar in characters (default: 20)
|
|
76
|
+
show_percentage: Show percentage complete (default: True)
|
|
77
|
+
show_counter: Show current/total counter (default: True)
|
|
78
|
+
enabled: Override TTY detection (None = auto-detect, True = always show, False = disable)
|
|
79
|
+
|
|
80
|
+
Example:
|
|
81
|
+
>>> pb = ProgressBar(100, prefix="Syncing agents", bar_width=30)
|
|
82
|
+
>>> pb.update(50, message="agent.md")
|
|
83
|
+
>>> # Displays: Syncing agents [███████████████░░░░░░░░░░░░░░░] 50% (50/100) agent.md
|
|
84
|
+
"""
|
|
85
|
+
self.total = total
|
|
86
|
+
self.prefix = prefix
|
|
87
|
+
self.bar_width = bar_width
|
|
88
|
+
self.show_percentage = show_percentage
|
|
89
|
+
self.show_counter = show_counter
|
|
90
|
+
self.current = 0
|
|
91
|
+
self.start_time = time.time()
|
|
92
|
+
self.last_update_time = 0.0
|
|
93
|
+
self.update_throttle = (
|
|
94
|
+
0.1 # Minimum seconds between updates (throttle to 10 Hz)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Auto-detect TTY unless explicitly overridden
|
|
98
|
+
if enabled is None:
|
|
99
|
+
self.enabled = self._is_tty()
|
|
100
|
+
else:
|
|
101
|
+
self.enabled = enabled
|
|
102
|
+
|
|
103
|
+
# Terminal width detection for preventing overflow
|
|
104
|
+
self.terminal_width = self._get_terminal_width()
|
|
105
|
+
|
|
106
|
+
def _is_tty(self) -> bool:
|
|
107
|
+
"""Check if stdout is a TTY (interactive terminal).
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
True if stdout is a TTY, False otherwise (e.g., piped, redirected)
|
|
111
|
+
|
|
112
|
+
Design Decision: Disable progress bars in non-TTY environments
|
|
113
|
+
|
|
114
|
+
Rationale: Progress bars use \r (carriage return) for line overwriting,
|
|
115
|
+
which appears as garbage in log files, CI/CD output, and piped commands.
|
|
116
|
+
Detecting TTY ensures clean output in all contexts.
|
|
117
|
+
|
|
118
|
+
Example:
|
|
119
|
+
$ python script.py # TTY - progress bars enabled
|
|
120
|
+
$ python script.py > log.txt # Non-TTY - simple logging
|
|
121
|
+
$ python script.py | grep foo # Non-TTY - simple logging
|
|
122
|
+
"""
|
|
123
|
+
try:
|
|
124
|
+
return sys.stdout.isatty()
|
|
125
|
+
except AttributeError:
|
|
126
|
+
# sys.stdout might not have isatty() in some environments
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
def _get_terminal_width(self) -> int:
|
|
130
|
+
"""Get terminal width for preventing line overflow.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Terminal width in characters (default: 80 if detection fails)
|
|
134
|
+
|
|
135
|
+
Error Handling:
|
|
136
|
+
- OSError: Returns 80 (standard terminal width)
|
|
137
|
+
- AttributeError: Returns 80 (fallback)
|
|
138
|
+
- ValueError: Returns 80 (invalid terminal size)
|
|
139
|
+
"""
|
|
140
|
+
try:
|
|
141
|
+
# Try to get terminal size from os module (Python 3.3+)
|
|
142
|
+
size = os.get_terminal_size()
|
|
143
|
+
return size.columns
|
|
144
|
+
except (OSError, AttributeError, ValueError):
|
|
145
|
+
# Fallback to standard terminal width
|
|
146
|
+
return 80
|
|
147
|
+
|
|
148
|
+
def update(self, current: int, message: str = "") -> None:
|
|
149
|
+
"""Update progress bar to current position.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
current: Current progress value (0 to total)
|
|
153
|
+
message: Optional message to display after progress bar (e.g., filename)
|
|
154
|
+
|
|
155
|
+
Performance: Updates are throttled to 10 Hz to avoid output flooding.
|
|
156
|
+
Non-TTY mode: Logs milestone updates (0%, 25%, 50%, 75%, 100%) instead of every update.
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
>>> pb = ProgressBar(10, prefix="Downloading")
|
|
160
|
+
>>> for i in range(10):
|
|
161
|
+
... pb.update(i + 1, message=f"file_{i}.md")
|
|
162
|
+
>>> # Progress bar updates in-place, then prints completion
|
|
163
|
+
"""
|
|
164
|
+
self.current = min(current, self.total) # Clamp to total
|
|
165
|
+
|
|
166
|
+
# Throttle updates to avoid flooding terminal
|
|
167
|
+
current_time = time.time()
|
|
168
|
+
if (
|
|
169
|
+
current_time - self.last_update_time < self.update_throttle
|
|
170
|
+
and current < self.total
|
|
171
|
+
):
|
|
172
|
+
return # Skip update, too soon since last one
|
|
173
|
+
|
|
174
|
+
self.last_update_time = current_time
|
|
175
|
+
|
|
176
|
+
if not self.enabled:
|
|
177
|
+
# Non-TTY mode: Log milestone updates only
|
|
178
|
+
self._log_milestone(message)
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
# TTY mode: Render and display progress bar
|
|
182
|
+
self._render_progress_bar(message)
|
|
183
|
+
|
|
184
|
+
def _log_milestone(self, message: str) -> None:
|
|
185
|
+
"""Log progress at milestone percentages in non-TTY mode.
|
|
186
|
+
|
|
187
|
+
Milestones: 0%, 25%, 50%, 75%, 100%
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
message: Optional message to include in log
|
|
191
|
+
|
|
192
|
+
Design Decision: Log milestones instead of every update in non-TTY
|
|
193
|
+
|
|
194
|
+
Rationale: Avoids flooding logs with hundreds of progress lines while
|
|
195
|
+
still providing useful feedback. Rejected logging every update because
|
|
196
|
+
it creates noise in CI/CD logs and log files.
|
|
197
|
+
|
|
198
|
+
Respects show_percentage and show_counter settings for consistent output
|
|
199
|
+
across TTY and non-TTY modes.
|
|
200
|
+
"""
|
|
201
|
+
percentage = int((self.current / self.total) * 100) if self.total > 0 else 0
|
|
202
|
+
|
|
203
|
+
# Log at milestones: 0%, 25%, 50%, 75%, 100%
|
|
204
|
+
milestones = [0, 25, 50, 75, 100]
|
|
205
|
+
if percentage in milestones or self.current == self.total:
|
|
206
|
+
# Build output respecting show_percentage and show_counter settings
|
|
207
|
+
if message and not (self.show_counter or self.show_percentage):
|
|
208
|
+
# Simple format: "Prefix: message"
|
|
209
|
+
output = f"{self.prefix}: {message}"
|
|
210
|
+
else:
|
|
211
|
+
# Complex format with counter/percentage
|
|
212
|
+
parts = [self.prefix]
|
|
213
|
+
|
|
214
|
+
if self.show_counter:
|
|
215
|
+
parts.append(f"{self.current}/{self.total}")
|
|
216
|
+
|
|
217
|
+
if self.show_percentage:
|
|
218
|
+
parts.append(f"({percentage}%)")
|
|
219
|
+
|
|
220
|
+
if message:
|
|
221
|
+
parts.append(f"- {message}")
|
|
222
|
+
|
|
223
|
+
output = " ".join(parts)
|
|
224
|
+
|
|
225
|
+
print(output, flush=True)
|
|
226
|
+
|
|
227
|
+
def _render_progress_bar(self, message: str) -> None:
|
|
228
|
+
"""Render and display progress bar in TTY mode.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
message: Optional message to display after progress bar
|
|
232
|
+
|
|
233
|
+
Output Format:
|
|
234
|
+
[Prefix] [████████░░░░░░░░░░░░] XX% (current/total) message
|
|
235
|
+
|
|
236
|
+
Design Decision: Use \r to overwrite same line for animation effect
|
|
237
|
+
|
|
238
|
+
Rationale: Creates smooth animation by updating the same line instead
|
|
239
|
+
of printing new lines. Requires TTY for proper display (hence TTY check).
|
|
240
|
+
|
|
241
|
+
Terminal Width Handling:
|
|
242
|
+
- Calculates available space based on terminal width
|
|
243
|
+
- Truncates message if output would overflow
|
|
244
|
+
- Ensures progress bar always fits on one line
|
|
245
|
+
"""
|
|
246
|
+
percentage = int((self.current / self.total) * 100) if self.total > 0 else 0
|
|
247
|
+
filled = (
|
|
248
|
+
int(self.bar_width * self.current / self.total) if self.total > 0 else 0
|
|
249
|
+
)
|
|
250
|
+
bar = "█" * filled + "░" * (self.bar_width - filled)
|
|
251
|
+
|
|
252
|
+
# Build output components
|
|
253
|
+
parts = [f"{self.prefix} [{bar}]"]
|
|
254
|
+
|
|
255
|
+
if self.show_percentage:
|
|
256
|
+
parts.append(f"{percentage}%")
|
|
257
|
+
|
|
258
|
+
if self.show_counter:
|
|
259
|
+
parts.append(f"({self.current}/{self.total})")
|
|
260
|
+
|
|
261
|
+
if message:
|
|
262
|
+
parts.append(message)
|
|
263
|
+
|
|
264
|
+
output = " ".join(parts)
|
|
265
|
+
|
|
266
|
+
# Truncate if exceeds terminal width (leave 2 chars margin)
|
|
267
|
+
max_width = self.terminal_width - 2
|
|
268
|
+
if len(output) > max_width:
|
|
269
|
+
# Truncate message part, preserve progress bar
|
|
270
|
+
truncate_at = max_width - 3 # Leave room for "..."
|
|
271
|
+
output = output[:truncate_at] + "..."
|
|
272
|
+
|
|
273
|
+
# Write to stdout with carriage return (overwrite current line)
|
|
274
|
+
sys.stdout.write(f"\r{output}")
|
|
275
|
+
sys.stdout.flush()
|
|
276
|
+
|
|
277
|
+
def finish(self, message: str = "Complete") -> None:
|
|
278
|
+
"""Complete progress bar and print final message.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
message: Final message to display (default: "Complete")
|
|
282
|
+
|
|
283
|
+
Design Decision: Print newline after completion to prevent terminal corruption
|
|
284
|
+
|
|
285
|
+
Rationale: Without newline, next shell prompt or log message would
|
|
286
|
+
overwrite the final progress bar state. Explicit finish() ensures
|
|
287
|
+
clean terminal output.
|
|
288
|
+
|
|
289
|
+
Bug Fix: Avoid duplicate completion messages in non-TTY mode by not
|
|
290
|
+
calling update() again if already at 100%. The final milestone was
|
|
291
|
+
already logged during the last update() call.
|
|
292
|
+
|
|
293
|
+
Example:
|
|
294
|
+
>>> pb = ProgressBar(100)
|
|
295
|
+
>>> pb.update(100)
|
|
296
|
+
>>> pb.finish(message="Download complete")
|
|
297
|
+
>>> # Output: [████████████████████] 100% (100/100) Download complete
|
|
298
|
+
"""
|
|
299
|
+
if self.enabled:
|
|
300
|
+
# TTY mode: Update to show final message, then add newline
|
|
301
|
+
self.update(self.total, message=message)
|
|
302
|
+
sys.stdout.write("\n")
|
|
303
|
+
sys.stdout.flush()
|
|
304
|
+
# Non-TTY mode: Only log if not already at 100%
|
|
305
|
+
# If already at 100%, _log_milestone() already printed during last update()
|
|
306
|
+
elif self.current < self.total:
|
|
307
|
+
self.update(self.total, message=message)
|
|
308
|
+
|
|
309
|
+
def __enter__(self) -> "ProgressBar":
|
|
310
|
+
"""Context manager entry.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
Self for use in with statements
|
|
314
|
+
|
|
315
|
+
Example:
|
|
316
|
+
>>> with ProgressBar(100, prefix="Processing") as pb:
|
|
317
|
+
... for i in range(100):
|
|
318
|
+
... pb.update(i + 1)
|
|
319
|
+
>>> # Automatically calls finish() on exit
|
|
320
|
+
"""
|
|
321
|
+
return self
|
|
322
|
+
|
|
323
|
+
def __exit__(
|
|
324
|
+
self,
|
|
325
|
+
exc_type: Optional[type],
|
|
326
|
+
exc_val: Optional[BaseException],
|
|
327
|
+
exc_tb: Optional[Any],
|
|
328
|
+
) -> None:
|
|
329
|
+
"""Context manager exit - ensures finish() is called.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
exc_type: Exception type (if raised)
|
|
333
|
+
exc_val: Exception value (if raised)
|
|
334
|
+
exc_tb: Exception traceback (if raised)
|
|
335
|
+
|
|
336
|
+
Error Handling:
|
|
337
|
+
- Calls finish() even if exception occurred
|
|
338
|
+
- Displays "Failed" message if exception raised
|
|
339
|
+
- Re-raises exception after cleanup
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
None (does not suppress exceptions)
|
|
343
|
+
"""
|
|
344
|
+
if exc_type is not None:
|
|
345
|
+
# Exception occurred - finish with error message
|
|
346
|
+
self.finish(message="Failed")
|
|
347
|
+
else:
|
|
348
|
+
# Normal completion
|
|
349
|
+
self.finish()
|
|
350
|
+
|
|
351
|
+
# Don't suppress exceptions (returning None is equivalent to returning False)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
# Convenience function for simple use cases
|
|
355
|
+
def create_progress_bar(
|
|
356
|
+
total: int,
|
|
357
|
+
prefix: str = "Progress",
|
|
358
|
+
enabled: Optional[bool] = None,
|
|
359
|
+
) -> ProgressBar:
|
|
360
|
+
"""Create a progress bar with sensible defaults.
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
total: Total number of items
|
|
364
|
+
prefix: Progress message
|
|
365
|
+
enabled: Override TTY detection (None = auto)
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Configured ProgressBar instance
|
|
369
|
+
|
|
370
|
+
Example:
|
|
371
|
+
>>> pb = create_progress_bar(100, "Downloading agents")
|
|
372
|
+
>>> for i in range(100):
|
|
373
|
+
... pb.update(i + 1, message=f"agent_{i}.md")
|
|
374
|
+
>>> pb.finish()
|
|
375
|
+
"""
|
|
376
|
+
return ProgressBar(
|
|
377
|
+
total=total,
|
|
378
|
+
prefix=prefix,
|
|
379
|
+
bar_width=20,
|
|
380
|
+
show_percentage=True,
|
|
381
|
+
show_counter=True,
|
|
382
|
+
enabled=enabled,
|
|
383
|
+
)
|
|
@@ -218,8 +218,7 @@ class RobustPackageInstaller:
|
|
|
218
218
|
return (
|
|
219
219
|
(
|
|
220
220
|
# venv creates sys.base_prefix
|
|
221
|
-
hasattr(sys, "base_prefix")
|
|
222
|
-
and sys.base_prefix != sys.prefix
|
|
221
|
+
hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix
|
|
223
222
|
)
|
|
224
223
|
or (
|
|
225
224
|
# virtualenv creates sys.real_prefix
|
|
@@ -227,8 +226,7 @@ class RobustPackageInstaller:
|
|
|
227
226
|
)
|
|
228
227
|
or (
|
|
229
228
|
# VIRTUAL_ENV environment variable
|
|
230
|
-
os.environ.get("VIRTUAL_ENV")
|
|
231
|
-
is not None
|
|
229
|
+
os.environ.get("VIRTUAL_ENV") is not None
|
|
232
230
|
)
|
|
233
231
|
)
|
|
234
232
|
|
|
@@ -768,7 +766,7 @@ def install_with_retry(
|
|
|
768
766
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
769
767
|
|
|
770
768
|
installer = RobustPackageInstaller(max_retries=max_retries)
|
|
771
|
-
|
|
769
|
+
_successful, failed, errors = installer.install_packages(packages)
|
|
772
770
|
|
|
773
771
|
if verbose:
|
|
774
772
|
print(installer.get_report())
|