claude-mpm 4.25.10__py3-none-any.whl → 5.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of 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/PM_INSTRUCTIONS.md +1055 -2230
- claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
- claude_mpm/agents/WORKFLOW.md +4 -4
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +1 -4
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +576 -66
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- 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 +28 -3
- 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 +959 -36
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/auto_configure.py +537 -239
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +924 -45
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +1 -39
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +322 -19
- claude_mpm/cli/executor.py +22 -3
- claude_mpm/cli/interactive/agent_wizard.py +1028 -43
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +256 -4
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
- claude_mpm/cli/parsers/base_parser.py +25 -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 +7 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +456 -103
- claude_mpm/cli/startup_display.py +4 -4
- 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 +9 -0
- 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 +1 -0
- claude_mpm/core/claude_runner.py +5 -34
- claude_mpm/core/config.py +16 -0
- 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/interactive_session.py +83 -7
- claude_mpm/core/oneshot_session.py +71 -8
- 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_config.py +22 -0
- claude_mpm/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -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/models/git_repository.py +198 -0
- 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_lifecycle_manager.py +1 -5
- 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/multi_source_deployment_service.py +115 -15
- 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 +1 -4
- claude_mpm/services/agents/local_template_manager.py +47 -9
- 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/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_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- 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 +34 -6
- 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/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/mcp_config_manager.py +75 -145
- 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_service_verifier.py +6 -3
- claude_mpm/services/monitor/daemon.py +28 -8
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/runner_configuration_service.py +16 -3
- 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/socketio/server/core.py +1 -4
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/templates/questions/__init__.py +2 -7
- claude_mpm/templates/questions/pr_strategy.py +1 -4
- claude_mpm/templates/questions/project_init.py +1 -4
- claude_mpm/templates/questions/ticket_mgmt.py +1 -4
- claude_mpm/utils/agent_dependency_loader.py +77 -10
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/gitignore.py +3 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +356 -112
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +188 -439
- 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 -183
- 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 -238
- 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/javascript_engineer_agent.json +0 -380
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- 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 -144
- 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 -243
- claude_mpm/agents/templates/react_engineer.json +0 -239
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -258
- 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/tauri_engineer.json +0 -274
- claude_mpm/agents/templates/ticketing.json +0 -181
- 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 -159
- claude_mpm/agents/templates/web_qa.json +0 -400
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/cli/README.md +0 -253
- claude_mpm/cli/commands/mcp_install_commands.py.backup +0 -284
- claude_mpm/cli/commands/mpm_init/README.md +0 -365
- claude_mpm/cli_module/refactoring_guide.md +0 -253
- claude_mpm/commands/mpm-tickets.md +0 -151
- claude_mpm/config/agent_capabilities.yaml +0 -658
- claude_mpm/config/async_logging_config.yaml +0 -145
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
- claude_mpm/d2/.gitignore +0 -22
- claude_mpm/d2/ARCHITECTURE_COMPARISON.md +0 -273
- claude_mpm/d2/FLASK_INTEGRATION.md +0 -156
- claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +0 -452
- claude_mpm/d2/QUICKSTART.md +0 -186
- claude_mpm/d2/README.md +0 -232
- claude_mpm/d2/STORE_FIX_SUMMARY.md +0 -167
- claude_mpm/d2/SVELTE5_STORES_GUIDE.md +0 -180
- claude_mpm/d2/TESTING.md +0 -288
- claude_mpm/d2/index.html +0 -118
- claude_mpm/d2/package.json +0 -19
- claude_mpm/d2/src/App.svelte +0 -110
- claude_mpm/d2/src/components/Header.svelte +0 -153
- claude_mpm/d2/src/components/MainContent.svelte +0 -74
- claude_mpm/d2/src/components/Sidebar.svelte +0 -85
- claude_mpm/d2/src/components/tabs/EventsTab.svelte +0 -326
- claude_mpm/d2/src/lib/socketio.js +0 -144
- claude_mpm/d2/src/main.js +0 -7
- claude_mpm/d2/src/stores/events.js +0 -114
- claude_mpm/d2/src/stores/socket.js +0 -108
- claude_mpm/d2/src/stores/theme.js +0 -65
- claude_mpm/d2/svelte.config.js +0 -12
- claude_mpm/d2/vite.config.js +0 -15
- claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/BUILD_NUMBER +0 -1
- claude_mpm/dashboard/README.md +0 -121
- claude_mpm/dashboard/VERSION +0 -1
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +0 -273
- claude_mpm/dashboard/react/components/ErrorBoundary.tsx +0 -75
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +0 -141
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +0 -36
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/react/components/shared/FilterBar.tsx +0 -89
- claude_mpm/dashboard/react/contexts/DashboardContext.tsx +0 -215
- claude_mpm/dashboard/react/entries/events.tsx +0 -165
- claude_mpm/dashboard/react/hooks/useEvents.ts +0 -191
- claude_mpm/dashboard/react/hooks/useSocket.ts +0 -225
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +0 -170
- 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/activity-tree.js.map +0 -1
- 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/agent-inference.js.map +0 -1
- 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-tree.js.map +0 -1
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js.map +0 -1
- 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-processor.js.map +0 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js.map +0 -1
- 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-tool-tracker.js.map +0 -1
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +0 -1
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js.map +0 -1
- 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/session-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js.map +0 -1
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/dashboard.js.map +0 -1
- 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/react/events.js.map +0 -1
- 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/socket-client.js.map +0 -1
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +0 -170
- 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/navigation-test-results.md +0 -118
- 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/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
- claude_mpm/hooks/README.md +0 -143
- claude_mpm/hooks/templates/README.md +0 -180
- claude_mpm/hooks/templates/settings.json.example +0 -147
- claude_mpm/schemas/agent_schema.json +0 -596
- claude_mpm/schemas/frontmatter_schema.json +0 -165
- claude_mpm/services/event_bus/README.md +0 -244
- claude_mpm/services/events/README.md +0 -303
- claude_mpm/services/framework_claude_md_generator/README.md +0 -119
- claude_mpm/services/mcp_gateway/README.md +0 -185
- claude_mpm/services/socketio/handlers/connection.py.backup +0 -217
- claude_mpm/services/socketio/handlers/hook.py.backup +0 -154
- claude_mpm/services/static/.gitkeep +0 -2
- claude_mpm/services/version_control/VERSION +0 -1
- claude_mpm/skills/bundled/.gitkeep +0 -2
- 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/git-worktrees.md +0 -317
- 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/stacked-prs.md +0 -251
- 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/find-polluter.sh +0 -63
- 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/infrastructure/env-manager/INTEGRATION.md +0 -611
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +0 -596
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +0 -260
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +0 -315
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +0 -436
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +0 -433
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +0 -452
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +0 -404
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +0 -420
- claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +0 -202
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +0 -54
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +0 -322
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +0 -202
- 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/LICENSE.txt +0 -202
- 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/mcp-builder/scripts/example_evaluation.xml +0 -22
- claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +0 -2
- claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +0 -202
- 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/react/flexlayout-react.md +0 -742
- 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/tauri/tauri-async-patterns.md +0 -495
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +0 -599
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +0 -535
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +0 -613
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +0 -648
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +0 -673
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +0 -767
- claude_mpm/skills/bundled/tauri/tauri-performance.md +0 -669
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +0 -573
- claude_mpm/skills/bundled/tauri/tauri-testing.md +0 -384
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +0 -628
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +0 -158
- 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/test-quality-inspector/SKILL.md +0 -458
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +0 -411
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +0 -317
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +0 -270
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +0 -436
- 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/LICENSE.txt +0 -202
- 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/templates/questions/EXAMPLES.md +0 -501
- claude_mpm/tools/README_SOCKETIO_DEBUG.md +0 -224
- claude_mpm/tools/code_tree_analyzer/README.md +0 -64
- /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/{pm_red_flags.md → pm-red-flags.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.25.10.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
|
@@ -66,6 +66,53 @@ class FileLoader:
|
|
|
66
66
|
if "INSTRUCTIONS.md" in str(file_path):
|
|
67
67
|
self.framework_last_modified = timestamp
|
|
68
68
|
|
|
69
|
+
def _load_tier_file(
|
|
70
|
+
self,
|
|
71
|
+
filename: str,
|
|
72
|
+
current_dir: Path,
|
|
73
|
+
framework_path: Optional[Path] = None,
|
|
74
|
+
include_system: bool = False,
|
|
75
|
+
) -> tuple[Optional[str], Optional[str]]:
|
|
76
|
+
"""Load file with tier precedence: project → user → system.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
filename: Name of file to load (e.g., "INSTRUCTIONS.md")
|
|
80
|
+
current_dir: Current working directory for project-level
|
|
81
|
+
framework_path: Path to framework installation for system-level
|
|
82
|
+
include_system: Whether to check system-level path
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Tuple of (content, level) where level is 'project', 'user', 'system', or None
|
|
86
|
+
"""
|
|
87
|
+
# Check project-level (highest priority)
|
|
88
|
+
project_path = current_dir / ".claude-mpm" / filename
|
|
89
|
+
if project_path.exists():
|
|
90
|
+
loaded_content = self.try_load_file(
|
|
91
|
+
project_path, f"project-specific {filename}"
|
|
92
|
+
)
|
|
93
|
+
if loaded_content:
|
|
94
|
+
self.logger.info(f"Using project-specific {filename} from .claude-mpm/")
|
|
95
|
+
return loaded_content, "project"
|
|
96
|
+
|
|
97
|
+
# Check user-level (medium priority)
|
|
98
|
+
user_path = Path.home() / ".claude-mpm" / filename
|
|
99
|
+
if user_path.exists():
|
|
100
|
+
loaded_content = self.try_load_file(user_path, f"user-specific {filename}")
|
|
101
|
+
if loaded_content:
|
|
102
|
+
self.logger.info(f"Using user-specific {filename} from ~/.claude-mpm/")
|
|
103
|
+
return loaded_content, "user"
|
|
104
|
+
|
|
105
|
+
# Check system-level (lowest priority)
|
|
106
|
+
if include_system and framework_path and framework_path != Path("__PACKAGED__"):
|
|
107
|
+
system_path = framework_path / "src" / "claude_mpm" / "agents" / filename
|
|
108
|
+
if system_path.exists():
|
|
109
|
+
loaded_content = self.try_load_file(system_path, f"system {filename}")
|
|
110
|
+
if loaded_content:
|
|
111
|
+
self.logger.info(f"Using system {filename}")
|
|
112
|
+
return loaded_content, "system"
|
|
113
|
+
|
|
114
|
+
return None, None
|
|
115
|
+
|
|
69
116
|
def load_instructions_file(
|
|
70
117
|
self, current_dir: Path
|
|
71
118
|
) -> tuple[Optional[str], Optional[str]]:
|
|
@@ -82,31 +129,7 @@ class FileLoader:
|
|
|
82
129
|
Returns:
|
|
83
130
|
Tuple of (content, level) where level is 'project', 'user', or None
|
|
84
131
|
"""
|
|
85
|
-
|
|
86
|
-
project_instructions_path = current_dir / ".claude-mpm" / "INSTRUCTIONS.md"
|
|
87
|
-
if project_instructions_path.exists():
|
|
88
|
-
loaded_content = self.try_load_file(
|
|
89
|
-
project_instructions_path, "project-specific INSTRUCTIONS.md"
|
|
90
|
-
)
|
|
91
|
-
if loaded_content:
|
|
92
|
-
self.logger.info(
|
|
93
|
-
"Using project-specific PM instructions from .claude-mpm/INSTRUCTIONS.md"
|
|
94
|
-
)
|
|
95
|
-
return loaded_content, "project"
|
|
96
|
-
|
|
97
|
-
# Check for user-specific INSTRUCTIONS.md
|
|
98
|
-
user_instructions_path = Path.home() / ".claude-mpm" / "INSTRUCTIONS.md"
|
|
99
|
-
if user_instructions_path.exists():
|
|
100
|
-
loaded_content = self.try_load_file(
|
|
101
|
-
user_instructions_path, "user-specific INSTRUCTIONS.md"
|
|
102
|
-
)
|
|
103
|
-
if loaded_content:
|
|
104
|
-
self.logger.info(
|
|
105
|
-
"Using user-specific PM instructions from ~/.claude-mpm/INSTRUCTIONS.md"
|
|
106
|
-
)
|
|
107
|
-
return loaded_content, "user"
|
|
108
|
-
|
|
109
|
-
return None, None
|
|
132
|
+
return self._load_tier_file("INSTRUCTIONS.md", current_dir)
|
|
110
133
|
|
|
111
134
|
def load_workflow_file(
|
|
112
135
|
self, current_dir: Path, framework_path: Path
|
|
@@ -126,44 +149,9 @@ class FileLoader:
|
|
|
126
149
|
Returns:
|
|
127
150
|
Tuple of (content, level) where level is 'project', 'user', 'system', or None
|
|
128
151
|
"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
loaded_content = self.try_load_file(
|
|
133
|
-
project_workflow_path, "project-specific WORKFLOW.md"
|
|
134
|
-
)
|
|
135
|
-
if loaded_content:
|
|
136
|
-
self.logger.info(
|
|
137
|
-
"Using project-specific workflow instructions from .claude-mpm/WORKFLOW.md"
|
|
138
|
-
)
|
|
139
|
-
return loaded_content, "project"
|
|
140
|
-
|
|
141
|
-
# Check for user-specific WORKFLOW.md (medium priority)
|
|
142
|
-
user_workflow_path = Path.home() / ".claude-mpm" / "WORKFLOW.md"
|
|
143
|
-
if user_workflow_path.exists():
|
|
144
|
-
loaded_content = self.try_load_file(
|
|
145
|
-
user_workflow_path, "user-specific WORKFLOW.md"
|
|
146
|
-
)
|
|
147
|
-
if loaded_content:
|
|
148
|
-
self.logger.info(
|
|
149
|
-
"Using user-specific workflow instructions from ~/.claude-mpm/WORKFLOW.md"
|
|
150
|
-
)
|
|
151
|
-
return loaded_content, "user"
|
|
152
|
-
|
|
153
|
-
# Fall back to system workflow (lowest priority)
|
|
154
|
-
if framework_path and framework_path != Path("__PACKAGED__"):
|
|
155
|
-
system_workflow_path = (
|
|
156
|
-
framework_path / "src" / "claude_mpm" / "agents" / "WORKFLOW.md"
|
|
157
|
-
)
|
|
158
|
-
if system_workflow_path.exists():
|
|
159
|
-
loaded_content = self.try_load_file(
|
|
160
|
-
system_workflow_path, "system WORKFLOW.md"
|
|
161
|
-
)
|
|
162
|
-
if loaded_content:
|
|
163
|
-
self.logger.info("Using system workflow instructions")
|
|
164
|
-
return loaded_content, "system"
|
|
165
|
-
|
|
166
|
-
return None, None
|
|
152
|
+
return self._load_tier_file(
|
|
153
|
+
"WORKFLOW.md", current_dir, framework_path, include_system=True
|
|
154
|
+
)
|
|
167
155
|
|
|
168
156
|
def load_memory_file(
|
|
169
157
|
self, current_dir: Path, framework_path: Path
|
|
@@ -183,41 +171,6 @@ class FileLoader:
|
|
|
183
171
|
Returns:
|
|
184
172
|
Tuple of (content, level) where level is 'project', 'user', 'system', or None
|
|
185
173
|
"""
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
loaded_content = self.try_load_file(
|
|
190
|
-
project_memory_path, "project-specific MEMORY.md"
|
|
191
|
-
)
|
|
192
|
-
if loaded_content:
|
|
193
|
-
self.logger.info(
|
|
194
|
-
"Using project-specific memory instructions from .claude-mpm/MEMORY.md"
|
|
195
|
-
)
|
|
196
|
-
return loaded_content, "project"
|
|
197
|
-
|
|
198
|
-
# Check for user-specific MEMORY.md (medium priority)
|
|
199
|
-
user_memory_path = Path.home() / ".claude-mpm" / "MEMORY.md"
|
|
200
|
-
if user_memory_path.exists():
|
|
201
|
-
loaded_content = self.try_load_file(
|
|
202
|
-
user_memory_path, "user-specific MEMORY.md"
|
|
203
|
-
)
|
|
204
|
-
if loaded_content:
|
|
205
|
-
self.logger.info(
|
|
206
|
-
"Using user-specific memory instructions from ~/.claude-mpm/MEMORY.md"
|
|
207
|
-
)
|
|
208
|
-
return loaded_content, "user"
|
|
209
|
-
|
|
210
|
-
# Fall back to system memory instructions (lowest priority)
|
|
211
|
-
if framework_path and framework_path != Path("__PACKAGED__"):
|
|
212
|
-
system_memory_path = (
|
|
213
|
-
framework_path / "src" / "claude_mpm" / "agents" / "MEMORY.md"
|
|
214
|
-
)
|
|
215
|
-
if system_memory_path.exists():
|
|
216
|
-
loaded_content = self.try_load_file(
|
|
217
|
-
system_memory_path, "system MEMORY.md"
|
|
218
|
-
)
|
|
219
|
-
if loaded_content:
|
|
220
|
-
self.logger.info("Using system memory instructions")
|
|
221
|
-
return loaded_content, "system"
|
|
222
|
-
|
|
223
|
-
return None, None
|
|
174
|
+
return self._load_tier_file(
|
|
175
|
+
"MEMORY.md", current_dir, framework_path, include_system=True
|
|
176
|
+
)
|
|
@@ -91,10 +91,28 @@ class InstructionLoader:
|
|
|
91
91
|
def _load_filesystem_framework_instructions(self, content: Dict[str, Any]) -> None:
|
|
92
92
|
"""Load framework instructions from filesystem.
|
|
93
93
|
|
|
94
|
+
Priority order:
|
|
95
|
+
1. Deployed compiled file: .claude-mpm/PM_INSTRUCTIONS_DEPLOYED.md (HIGHEST PRIORITY)
|
|
96
|
+
2. Source file (development): src/claude_mpm/agents/PM_INSTRUCTIONS.md
|
|
97
|
+
3. Legacy file (backward compat): src/claude_mpm/agents/INSTRUCTIONS.md
|
|
98
|
+
|
|
94
99
|
Args:
|
|
95
100
|
content: Dictionary to update with framework instructions
|
|
96
101
|
"""
|
|
97
|
-
#
|
|
102
|
+
# PRIORITY 1: Check for compiled/deployed version in .claude-mpm/
|
|
103
|
+
# This is the merged PM_INSTRUCTIONS.md + WORKFLOW.md + MEMORY.md
|
|
104
|
+
deployed_path = self.current_dir / ".claude-mpm" / "PM_INSTRUCTIONS_DEPLOYED.md"
|
|
105
|
+
if deployed_path.exists():
|
|
106
|
+
loaded_content = self.file_loader.try_load_file(
|
|
107
|
+
deployed_path, "deployed PM_INSTRUCTIONS_DEPLOYED.md"
|
|
108
|
+
)
|
|
109
|
+
if loaded_content:
|
|
110
|
+
content["framework_instructions"] = loaded_content
|
|
111
|
+
content["loaded"] = True
|
|
112
|
+
self.logger.info("Loaded PM_INSTRUCTIONS_DEPLOYED.md from .claude-mpm/")
|
|
113
|
+
return # Stop here - deployed version takes precedence
|
|
114
|
+
|
|
115
|
+
# PRIORITY 2: Development mode - load from source PM_INSTRUCTIONS.md
|
|
98
116
|
pm_instructions_path = (
|
|
99
117
|
self.framework_path / "src" / "claude_mpm" / "agents" / "PM_INSTRUCTIONS.md"
|
|
100
118
|
)
|
|
@@ -102,16 +120,18 @@ class InstructionLoader:
|
|
|
102
120
|
self.framework_path / "src" / "claude_mpm" / "agents" / "INSTRUCTIONS.md"
|
|
103
121
|
)
|
|
104
122
|
|
|
105
|
-
# Try loading new consolidated file
|
|
123
|
+
# Try loading new consolidated file
|
|
106
124
|
if pm_instructions_path.exists():
|
|
107
125
|
loaded_content = self.file_loader.try_load_file(
|
|
108
|
-
pm_instructions_path, "
|
|
126
|
+
pm_instructions_path, "source PM_INSTRUCTIONS.md (development mode)"
|
|
109
127
|
)
|
|
110
128
|
if loaded_content:
|
|
111
129
|
content["framework_instructions"] = loaded_content
|
|
112
130
|
content["loaded"] = True
|
|
113
|
-
self.logger.
|
|
114
|
-
|
|
131
|
+
self.logger.warning(
|
|
132
|
+
"Using source PM_INSTRUCTIONS.md - deployed version not found"
|
|
133
|
+
)
|
|
134
|
+
# PRIORITY 3: Fall back to legacy file for backward compatibility
|
|
115
135
|
elif framework_instructions_path.exists():
|
|
116
136
|
loaded_content = self.file_loader.try_load_file(
|
|
117
137
|
framework_instructions_path, "framework INSTRUCTIONS.md (legacy)"
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
This module provides the InteractiveSession class that manages Claude's interactive mode
|
|
4
4
|
with proper separation of concerns and reduced complexity.
|
|
5
|
+
|
|
6
|
+
DEPENDENCY INJECTION:
|
|
7
|
+
This module uses protocol-based dependency injection to break circular imports.
|
|
8
|
+
Instead of importing ClaudeRunner directly, it uses ClaudeRunnerProtocol which
|
|
9
|
+
defines the interface it needs. This allows ClaudeRunner to create instances
|
|
10
|
+
of InteractiveSession without circular dependency issues.
|
|
5
11
|
"""
|
|
6
12
|
|
|
7
13
|
import contextlib
|
|
@@ -9,11 +15,18 @@ import os
|
|
|
9
15
|
import subprocess
|
|
10
16
|
import uuid
|
|
11
17
|
from pathlib import Path
|
|
12
|
-
from typing import Any, Dict, Optional, Tuple
|
|
18
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
|
|
13
19
|
|
|
14
20
|
from claude_mpm.core.enums import ServiceState
|
|
15
21
|
from claude_mpm.core.logger import get_logger
|
|
16
22
|
|
|
23
|
+
# Protocol imports for type checking without circular dependencies
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from claude_mpm.core.protocols import ClaudeRunnerProtocol
|
|
26
|
+
else:
|
|
27
|
+
# At runtime, accept any object with matching interface
|
|
28
|
+
ClaudeRunnerProtocol = Any
|
|
29
|
+
|
|
17
30
|
|
|
18
31
|
class InteractiveSession:
|
|
19
32
|
"""
|
|
@@ -28,13 +41,14 @@ class InteractiveSession:
|
|
|
28
41
|
and makes testing easier while preserving all original functionality.
|
|
29
42
|
"""
|
|
30
43
|
|
|
31
|
-
def __init__(self, runner):
|
|
44
|
+
def __init__(self, runner: "ClaudeRunnerProtocol"):
|
|
32
45
|
"""Initialize interactive session handler.
|
|
33
46
|
|
|
34
47
|
Args:
|
|
35
|
-
runner: ClaudeRunner instance
|
|
48
|
+
runner: ClaudeRunner instance (or any object matching ClaudeRunnerProtocol)
|
|
49
|
+
with all necessary services
|
|
36
50
|
"""
|
|
37
|
-
self.runner = runner
|
|
51
|
+
self.runner: ClaudeRunnerProtocol = runner
|
|
38
52
|
self.logger = get_logger("interactive_session")
|
|
39
53
|
self.session_id = None
|
|
40
54
|
self.original_cwd = Path.cwd()
|
|
@@ -396,12 +410,74 @@ class InteractiveSession:
|
|
|
396
410
|
cmd.extend(agents_flag)
|
|
397
411
|
self.logger.info("✓ Native agents mode: Using --agents CLI flag")
|
|
398
412
|
|
|
399
|
-
# Add system instructions
|
|
400
|
-
from claude_mpm.core.
|
|
413
|
+
# Add system instructions with file-based caching
|
|
414
|
+
from claude_mpm.core.system_context import create_simple_context
|
|
415
|
+
from claude_mpm.services.instructions.instruction_cache_service import (
|
|
416
|
+
InstructionCacheService,
|
|
417
|
+
)
|
|
401
418
|
|
|
402
419
|
system_prompt = self.runner._create_system_prompt()
|
|
403
420
|
if system_prompt and system_prompt != create_simple_context():
|
|
404
|
-
|
|
421
|
+
# Try to use cached instruction file for better performance
|
|
422
|
+
try:
|
|
423
|
+
# Initialize cache service with project root
|
|
424
|
+
if "CLAUDE_MPM_USER_PWD" in os.environ:
|
|
425
|
+
project_root = Path(os.environ["CLAUDE_MPM_USER_PWD"])
|
|
426
|
+
else:
|
|
427
|
+
project_root = Path.cwd()
|
|
428
|
+
|
|
429
|
+
# Instruction Caching (1M-446)
|
|
430
|
+
# Cache assembled instructions to file to avoid ARG_MAX limits on Linux/Windows.
|
|
431
|
+
# - Linux: 128 KB limit, instructions are ~152 KB (exceeds by 19.1%)
|
|
432
|
+
# - Windows: 32 KB limit (exceeds by 476%)
|
|
433
|
+
# Cache updates only when content hash changes (hash-based invalidation).
|
|
434
|
+
# Fallback to inline instruction if cache fails (graceful degradation).
|
|
435
|
+
cache_service = InstructionCacheService(project_root=project_root)
|
|
436
|
+
|
|
437
|
+
# Update cache with assembled instruction content
|
|
438
|
+
cache_result = cache_service.update_cache(
|
|
439
|
+
instruction_content=system_prompt
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# Use cache file if available
|
|
443
|
+
if (
|
|
444
|
+
cache_result.get("updated")
|
|
445
|
+
or cache_service.get_cache_path().exists()
|
|
446
|
+
):
|
|
447
|
+
cache_file = cache_service.get_cache_path()
|
|
448
|
+
|
|
449
|
+
# Log cache operation
|
|
450
|
+
if cache_result.get("updated"):
|
|
451
|
+
self.logger.info(
|
|
452
|
+
f"Instruction cache updated: {cache_result.get('reason', 'unknown')}"
|
|
453
|
+
)
|
|
454
|
+
self.logger.debug(
|
|
455
|
+
f"Cache hash: {cache_result.get('content_hash', 'N/A')[:8]}..."
|
|
456
|
+
)
|
|
457
|
+
self.logger.debug(
|
|
458
|
+
f"Cache size: {cache_result.get('content_size_kb', 'N/A')} KB"
|
|
459
|
+
)
|
|
460
|
+
else:
|
|
461
|
+
self.logger.debug(
|
|
462
|
+
f"Using cached instructions: {cache_result.get('reason', 'unknown')}"
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
# Use file-based loading for better performance
|
|
466
|
+
cmd.extend(["--system-prompt-file", str(cache_file)])
|
|
467
|
+
self.logger.info(
|
|
468
|
+
f"✓ Using file-based instruction loading: {cache_file}"
|
|
469
|
+
)
|
|
470
|
+
else:
|
|
471
|
+
# Fallback to inline if cache file doesn't exist
|
|
472
|
+
self.logger.warning(
|
|
473
|
+
"Cache file not available, falling back to inline instruction"
|
|
474
|
+
)
|
|
475
|
+
cmd.extend(["--append-system-prompt", system_prompt])
|
|
476
|
+
|
|
477
|
+
except Exception as e:
|
|
478
|
+
# Graceful fallback - cache failures don't break deployment
|
|
479
|
+
self.logger.warning(f"Failed to cache instructions, using inline: {e}")
|
|
480
|
+
cmd.extend(["--append-system-prompt", system_prompt])
|
|
405
481
|
|
|
406
482
|
# Final command verification
|
|
407
483
|
# self.logger.info(f"Final Claude command built: {' '.join(cmd)}")
|
|
@@ -2,19 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
This module encapsulates the logic for running one-time Claude commands,
|
|
4
4
|
breaking down the monolithic run_oneshot method into focused, testable components.
|
|
5
|
+
|
|
6
|
+
DEPENDENCY INJECTION:
|
|
7
|
+
This module uses protocol-based dependency injection to break circular imports.
|
|
8
|
+
Instead of importing ClaudeRunner directly, it uses ClaudeRunnerProtocol which
|
|
9
|
+
defines the interface it needs.
|
|
5
10
|
"""
|
|
6
11
|
|
|
7
12
|
import contextlib
|
|
8
13
|
import os
|
|
9
14
|
import subprocess
|
|
15
|
+
import tempfile
|
|
10
16
|
import time
|
|
11
17
|
import uuid
|
|
12
18
|
from pathlib import Path
|
|
13
|
-
from typing import Any, Dict, Optional, Tuple
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
|
|
14
20
|
|
|
15
21
|
from claude_mpm.core.enums import OperationResult, ServiceState
|
|
16
22
|
from claude_mpm.core.logger import get_logger
|
|
17
23
|
|
|
24
|
+
# Protocol imports for type checking without circular dependencies
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from claude_mpm.core.protocols import ClaudeRunnerProtocol
|
|
27
|
+
else:
|
|
28
|
+
# At runtime, accept any object with matching interface
|
|
29
|
+
ClaudeRunnerProtocol = Any
|
|
30
|
+
|
|
18
31
|
|
|
19
32
|
class OneshotSession:
|
|
20
33
|
"""Manages a single oneshot Claude execution session.
|
|
@@ -26,17 +39,18 @@ class OneshotSession:
|
|
|
26
39
|
complexity < 10 and lines < 80, making the code easier to test and modify.
|
|
27
40
|
"""
|
|
28
41
|
|
|
29
|
-
def __init__(self, runner):
|
|
42
|
+
def __init__(self, runner: "ClaudeRunnerProtocol"):
|
|
30
43
|
"""Initialize the oneshot session with a reference to the runner.
|
|
31
44
|
|
|
32
45
|
Args:
|
|
33
|
-
runner: The ClaudeRunner instance
|
|
46
|
+
runner: The ClaudeRunner instance (or any object matching ClaudeRunnerProtocol)
|
|
34
47
|
"""
|
|
35
|
-
self.runner = runner
|
|
48
|
+
self.runner: ClaudeRunnerProtocol = runner
|
|
36
49
|
self.logger = get_logger("oneshot_session")
|
|
37
50
|
self.start_time = None
|
|
38
51
|
self.session_id = None
|
|
39
52
|
self.original_cwd = None
|
|
53
|
+
self.temp_system_prompt_file = None
|
|
40
54
|
|
|
41
55
|
def initialize_session(self, prompt: str) -> Tuple[bool, Optional[str]]:
|
|
42
56
|
"""Initialize the oneshot session.
|
|
@@ -134,7 +148,13 @@ class OneshotSession:
|
|
|
134
148
|
def _build_final_command(
|
|
135
149
|
self, prompt: str, context: Optional[str], infrastructure: Dict[str, Any]
|
|
136
150
|
) -> list:
|
|
137
|
-
"""Build the final command with prompt and system instructions.
|
|
151
|
+
"""Build the final command with prompt and system instructions.
|
|
152
|
+
|
|
153
|
+
Uses file-based caching to avoid Linux ARG_MAX limits:
|
|
154
|
+
- Linux MAX_ARG_STRLEN: 128 KB per argument
|
|
155
|
+
- System prompt size: ~138.7 KB (exceeds limit by 7.7 KB)
|
|
156
|
+
- Solution: Write to temp file, pass file path (~60 bytes)
|
|
157
|
+
"""
|
|
138
158
|
full_prompt = f"{context}\n\n{prompt}" if context else prompt
|
|
139
159
|
cmd = infrastructure["cmd"] + ["--print", full_prompt]
|
|
140
160
|
|
|
@@ -148,9 +168,38 @@ class OneshotSession:
|
|
|
148
168
|
self.logger.warning("System prompt contains Python code references!")
|
|
149
169
|
|
|
150
170
|
if system_prompt and system_prompt != self._get_simple_context():
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
|
|
171
|
+
# Use file-based loading to avoid ARG_MAX limits (1M-485)
|
|
172
|
+
# Create temp file for system prompt
|
|
173
|
+
try:
|
|
174
|
+
# Create temp file in system temp directory
|
|
175
|
+
temp_fd, temp_path = tempfile.mkstemp(
|
|
176
|
+
suffix=".md", prefix="claude_mpm_system_prompt_"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Write system prompt to temp file
|
|
180
|
+
with os.fdopen(temp_fd, "w", encoding="utf-8") as f:
|
|
181
|
+
f.write(system_prompt)
|
|
182
|
+
|
|
183
|
+
# Store temp file path for cleanup
|
|
184
|
+
self.temp_system_prompt_file = temp_path
|
|
185
|
+
|
|
186
|
+
# Use --system-prompt-file flag (matches interactive mode pattern)
|
|
187
|
+
cmd.extend(["--system-prompt-file", temp_path])
|
|
188
|
+
|
|
189
|
+
# User-visible notification
|
|
190
|
+
print(f"📄 Reading system prompt from: {temp_path}")
|
|
191
|
+
|
|
192
|
+
self.logger.info(
|
|
193
|
+
f"Using file-based system prompt loading: {temp_path} "
|
|
194
|
+
f"({len(system_prompt) / 1024:.1f} KB)"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
# Fallback to inline if file creation fails
|
|
199
|
+
self.logger.warning(
|
|
200
|
+
f"Failed to create temp file for system prompt, using inline: {e}"
|
|
201
|
+
)
|
|
202
|
+
cmd.extend(["--append-system-prompt", system_prompt])
|
|
154
203
|
|
|
155
204
|
return cmd
|
|
156
205
|
|
|
@@ -203,6 +252,20 @@ class OneshotSession:
|
|
|
203
252
|
|
|
204
253
|
def cleanup_session(self) -> None:
|
|
205
254
|
"""Clean up the session and restore state."""
|
|
255
|
+
# Clean up temp system prompt file
|
|
256
|
+
if self.temp_system_prompt_file:
|
|
257
|
+
try:
|
|
258
|
+
temp_file_path = Path(self.temp_system_prompt_file)
|
|
259
|
+
if temp_file_path.exists():
|
|
260
|
+
temp_file_path.unlink()
|
|
261
|
+
self.logger.debug(
|
|
262
|
+
f"Cleaned up temp system prompt file: {self.temp_system_prompt_file}"
|
|
263
|
+
)
|
|
264
|
+
except Exception as e:
|
|
265
|
+
self.logger.warning(f"Failed to clean up temp system prompt file: {e}")
|
|
266
|
+
finally:
|
|
267
|
+
self.temp_system_prompt_file = None
|
|
268
|
+
|
|
206
269
|
# Restore original working directory
|
|
207
270
|
if self.original_cwd:
|
|
208
271
|
with contextlib.suppress(Exception):
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Protocol interfaces for dependency injection.
|
|
2
|
+
|
|
3
|
+
This module defines Protocol interfaces to break circular dependencies
|
|
4
|
+
using Python's typing.Protocol feature for structural subtyping.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from claude_mpm.core.protocols.runner_protocol import (
|
|
8
|
+
ClaudeRunnerProtocol,
|
|
9
|
+
SystemPromptProvider,
|
|
10
|
+
)
|
|
11
|
+
from claude_mpm.core.protocols.session_protocol import (
|
|
12
|
+
InteractiveSessionProtocol,
|
|
13
|
+
OneshotSessionProtocol,
|
|
14
|
+
SessionManagementProtocol,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"ClaudeRunnerProtocol",
|
|
19
|
+
"InteractiveSessionProtocol",
|
|
20
|
+
"OneshotSessionProtocol",
|
|
21
|
+
"SessionManagementProtocol",
|
|
22
|
+
"SystemPromptProvider",
|
|
23
|
+
]
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Protocol definitions for ClaudeRunner dependencies.
|
|
2
|
+
|
|
3
|
+
These protocols use Python's typing.Protocol for structural subtyping,
|
|
4
|
+
allowing dependency injection without circular imports.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Optional, Protocol
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SystemPromptProvider(Protocol):
|
|
12
|
+
"""Protocol for providing system prompts without circular dependency.
|
|
13
|
+
|
|
14
|
+
This protocol allows InteractiveSession to get system prompts without
|
|
15
|
+
directly importing ClaudeRunner, breaking the circular dependency.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def _create_system_prompt(self) -> str:
|
|
19
|
+
"""Create the complete system prompt including instructions.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Complete system prompt as string
|
|
23
|
+
"""
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ClaudeRunnerProtocol(Protocol):
|
|
28
|
+
"""Protocol defining the interface InteractiveSession needs from ClaudeRunner.
|
|
29
|
+
|
|
30
|
+
This protocol breaks the circular dependency between InteractiveSession
|
|
31
|
+
and ClaudeRunner by defining only the methods that InteractiveSession
|
|
32
|
+
actually uses, without requiring the full ClaudeRunner import.
|
|
33
|
+
|
|
34
|
+
Design Decision: Uses Protocol instead of ABC to allow structural subtyping.
|
|
35
|
+
This means ClaudeRunner doesn't need to explicitly inherit from this protocol,
|
|
36
|
+
it just needs to implement these methods with matching signatures.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# Configuration attributes
|
|
40
|
+
enable_websocket: bool
|
|
41
|
+
enable_tickets: bool
|
|
42
|
+
log_level: str
|
|
43
|
+
claude_args: Optional[list]
|
|
44
|
+
launch_method: str
|
|
45
|
+
websocket_port: int
|
|
46
|
+
use_native_agents: bool
|
|
47
|
+
config: Any
|
|
48
|
+
session_log_file: Optional[Path]
|
|
49
|
+
|
|
50
|
+
# Service references
|
|
51
|
+
project_logger: Any
|
|
52
|
+
websocket_server: Any
|
|
53
|
+
command_handler_service: Any
|
|
54
|
+
subprocess_launcher_service: Any
|
|
55
|
+
|
|
56
|
+
def setup_agents(self) -> bool:
|
|
57
|
+
"""Deploy native agents to .claude/agents/.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
True if successful, False otherwise
|
|
61
|
+
"""
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
def deploy_project_agents_to_claude(self) -> bool:
|
|
65
|
+
"""Deploy project agents from .claude-mpm/agents/ to .claude/agents/.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
True if successful, False otherwise
|
|
69
|
+
"""
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
def _create_system_prompt(self) -> str:
|
|
73
|
+
"""Create the complete system prompt including instructions.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Complete system prompt as string
|
|
77
|
+
"""
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
def _get_version(self) -> str:
|
|
81
|
+
"""Get version string.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Version string
|
|
85
|
+
"""
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
def _log_session_event(self, event_data: dict) -> None:
|
|
89
|
+
"""Log an event to the session log file.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
event_data: Event data to log
|
|
93
|
+
"""
|
|
94
|
+
...
|
|
95
|
+
|
|
96
|
+
def _launch_subprocess_interactive(self, cmd: list, env: dict) -> None:
|
|
97
|
+
"""Launch Claude as a subprocess with PTY for interactive mode.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
cmd: Command to execute
|
|
101
|
+
env: Environment variables
|
|
102
|
+
"""
|
|
103
|
+
...
|