claude-mpm 4.20.3__py3-none-any.whl → 4.25.10__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 +23 -6
- claude_mpm/agents/OUTPUT_STYLE.md +3 -48
- claude_mpm/agents/PM_INSTRUCTIONS.md +1783 -34
- claude_mpm/agents/WORKFLOW.md +75 -2
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/frontmatter_validator.py +1 -1
- claude_mpm/agents/templates/api_qa.json +5 -2
- claude_mpm/agents/templates/circuit_breakers.md +108 -2
- claude_mpm/agents/templates/documentation.json +33 -6
- claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
- claude_mpm/agents/templates/php-engineer.json +10 -4
- claude_mpm/agents/templates/pm_red_flags.md +89 -19
- claude_mpm/agents/templates/project_organizer.json +7 -3
- claude_mpm/agents/templates/qa.json +2 -1
- claude_mpm/agents/templates/react_engineer.json +1 -0
- claude_mpm/agents/templates/research.json +82 -12
- claude_mpm/agents/templates/security.json +4 -4
- claude_mpm/agents/templates/tauri_engineer.json +274 -0
- claude_mpm/agents/templates/ticketing.json +10 -6
- claude_mpm/agents/templates/version_control.json +4 -2
- claude_mpm/agents/templates/web_qa.json +2 -1
- claude_mpm/cli/README.md +253 -0
- claude_mpm/cli/__init__.py +11 -1
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/configure_agent_display.py +4 -4
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mcp_install_commands.py.backup +284 -0
- claude_mpm/cli/commands/mpm_init/README.md +365 -0
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +573 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +67 -1
- claude_mpm/cli/commands/run.py +124 -128
- claude_mpm/cli/commands/skills.py +522 -34
- claude_mpm/cli/executor.py +56 -0
- claude_mpm/cli/interactive/agent_wizard.py +5 -5
- claude_mpm/cli/parsers/base_parser.py +28 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
- claude_mpm/cli/parsers/skills_parser.py +138 -0
- claude_mpm/cli/startup.py +111 -8
- 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/cli_module/refactoring_guide.md +253 -0
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-init.md +19 -3
- claude_mpm/commands/mpm-resume.md +372 -0
- claude_mpm/commands/mpm-tickets.md +56 -7
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_capabilities.yaml +658 -0
- claude_mpm/config/async_logging_config.yaml +145 -0
- claude_mpm/constants.py +12 -0
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +34 -0
- claude_mpm/core/api_validator.py +1 -1
- claude_mpm/core/claude_runner.py +14 -1
- claude_mpm/core/config.py +8 -0
- claude_mpm/core/constants.py +1 -1
- 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 +48 -3
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +39 -0
- claude_mpm/d2/.gitignore +22 -0
- claude_mpm/d2/ARCHITECTURE_COMPARISON.md +273 -0
- claude_mpm/d2/FLASK_INTEGRATION.md +156 -0
- claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +452 -0
- claude_mpm/d2/QUICKSTART.md +186 -0
- claude_mpm/d2/README.md +232 -0
- claude_mpm/d2/STORE_FIX_SUMMARY.md +167 -0
- claude_mpm/d2/SVELTE5_STORES_GUIDE.md +180 -0
- claude_mpm/d2/TESTING.md +288 -0
- claude_mpm/d2/index.html +118 -0
- claude_mpm/d2/package.json +19 -0
- claude_mpm/d2/src/App.svelte +110 -0
- claude_mpm/d2/src/components/Header.svelte +153 -0
- claude_mpm/d2/src/components/MainContent.svelte +74 -0
- claude_mpm/d2/src/components/Sidebar.svelte +85 -0
- claude_mpm/d2/src/components/tabs/EventsTab.svelte +326 -0
- claude_mpm/d2/src/lib/socketio.js +144 -0
- claude_mpm/d2/src/main.js +7 -0
- claude_mpm/d2/src/stores/events.js +114 -0
- claude_mpm/d2/src/stores/socket.js +108 -0
- claude_mpm/d2/src/stores/theme.js +65 -0
- claude_mpm/d2/svelte.config.js +12 -0
- claude_mpm/d2/vite.config.js +15 -0
- claude_mpm/dashboard/.claude-mpm/memories/README.md +36 -0
- claude_mpm/dashboard/BUILD_NUMBER +1 -0
- claude_mpm/dashboard/README.md +121 -0
- claude_mpm/dashboard/VERSION +1 -0
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +273 -0
- claude_mpm/dashboard/react/components/ErrorBoundary.tsx +75 -0
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +141 -0
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +36 -0
- claude_mpm/dashboard/react/components/shared/FilterBar.tsx +89 -0
- claude_mpm/dashboard/react/contexts/DashboardContext.tsx +215 -0
- claude_mpm/dashboard/react/entries/events.tsx +165 -0
- claude_mpm/dashboard/react/hooks/useEvents.ts +191 -0
- claude_mpm/dashboard/react/hooks/useSocket.ts +225 -0
- claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +170 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js.map +1 -0
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/built/components/agent-inference.js.map +1 -0
- claude_mpm/dashboard/static/built/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/built/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +29 -29
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +24 -24
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +27 -27
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +25 -25
- claude_mpm/dashboard/static/built/components/code-tree.js.map +1 -0
- claude_mpm/dashboard/static/built/components/code-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/built/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/built/components/event-processor.js.map +1 -0
- claude_mpm/dashboard/static/built/components/event-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/export-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +1 -0
- claude_mpm/dashboard/static/built/components/file-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +1 -0
- claude_mpm/dashboard/static/built/components/hud-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/session-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/socket-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/working-directory.js.map +1 -0
- claude_mpm/dashboard/static/built/connection-manager.js +76 -76
- claude_mpm/dashboard/static/built/dashboard.js.map +1 -0
- claude_mpm/dashboard/static/built/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/built/react/events.js.map +1 -0
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +9 -9
- claude_mpm/dashboard/static/built/shared/event-bus.js +5 -5
- claude_mpm/dashboard/static/built/shared/logger.js +16 -16
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +6 -6
- claude_mpm/dashboard/static/built/socket-client.js.map +1 -0
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +15 -15
- claude_mpm/dashboard/static/index.html +22 -22
- claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +170 -0
- 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/shared/dom-helpers.js +9 -9
- claude_mpm/dashboard/static/js/shared/event-bus.js +5 -5
- claude_mpm/dashboard/static/js/shared/logger.js +16 -16
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +6 -6
- claude_mpm/dashboard/static/js/socket-client.js +138 -121
- claude_mpm/dashboard/static/navigation-test-results.md +118 -0
- claude_mpm/dashboard/static/production/main.html +21 -21
- claude_mpm/dashboard/static/test-archive/dashboard.html +22 -22
- claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +36 -0
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +39 -0
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +38 -0
- claude_mpm/dashboard/templates/code_simple.html +23 -23
- claude_mpm/dashboard/templates/index.html +18 -18
- claude_mpm/hooks/README.md +143 -0
- 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/templates/README.md +180 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/templates/settings.json.example +147 -0
- claude_mpm/schemas/agent_schema.json +596 -0
- claude_mpm/schemas/frontmatter_schema.json +165 -0
- claude_mpm/scripts/claude-hook-handler.sh +3 -3
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +8 -8
- claude_mpm/services/agents/local_template_manager.py +3 -1
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +36 -16
- claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/core/base.py +26 -11
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/models/agent_config.py +3 -0
- claude_mpm/services/core/models/process.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
- 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/doctor_reporter.py +6 -4
- claude_mpm/services/diagnostics/models.py +21 -0
- claude_mpm/services/event_bus/README.md +244 -0
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/event_bus/event_bus.py +36 -3
- claude_mpm/services/event_bus/relay.py +23 -7
- claude_mpm/services/events/README.md +303 -0
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/framework_claude_md_generator/README.md +119 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
- claude_mpm/services/local_ops/__init__.py +2 -0
- 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/README.md +185 -0
- claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
- 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/external_mcp_services.py +26 -21
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
- claude_mpm/services/memory/failure_tracker.py +19 -4
- 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/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_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/connection.py.backup +217 -0
- claude_mpm/services/socketio/handlers/git.py +2 -2
- claude_mpm/services/socketio/handlers/hook.py.backup +154 -0
- claude_mpm/services/static/.gitkeep +2 -0
- 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/version_control/VERSION +1 -0
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/__init__.py +3 -3
- claude_mpm/skills/agent_skills_injector.py +42 -49
- claude_mpm/skills/bundled/.gitkeep +2 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +4 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +108 -114
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +46 -41
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +36 -73
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +100 -125
- claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +63 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +28 -72
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +11 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +272 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +13 -1
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +54 -0
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +322 -0
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +11 -0
- claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +109 -277
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +17 -10
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +92 -39
- claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +22 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +2 -0
- claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +135 -155
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +13 -12
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +5 -3
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +19 -12
- claude_mpm/skills/bundled/performance-profiling.md +6 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +21 -25
- claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +158 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +86 -250
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +145 -57
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +6 -6
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +13 -9
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +8 -8
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +37 -15
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/skills_registry.py +44 -48
- claude_mpm/skills/skills_service.py +117 -108
- claude_mpm/templates/questions/EXAMPLES.md +501 -0
- claude_mpm/templates/questions/__init__.py +43 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +314 -0
- claude_mpm/templates/questions/project_init.py +388 -0
- claude_mpm/templates/questions/ticket_mgmt.py +397 -0
- claude_mpm/tools/README_SOCKETIO_DEBUG.md +224 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/tools/code_tree_analyzer/README.md +64 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/utils/agent_dependency_loader.py +3 -3
- 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/robust_installer.py +3 -5
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/METADATA +218 -31
- {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/RECORD +409 -246
- 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/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/cli/commands/mpm_init.py +0 -2093
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- 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/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/test-archive/test_debug.html +0 -25
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +0 -213
- claude_mpm/tools/code_tree_analyzer.py +0 -1825
- /claude_mpm/skills/bundled/collaboration/requesting-code-review/{code-reviewer.md → references/code-reviewer-template.md} +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/WHEEL +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-4.25.10.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
"""Session Pause Manager Service.
|
|
2
|
+
|
|
3
|
+
WHY: This service creates session pause documents that capture complete conversation
|
|
4
|
+
context, git state, todos, and working directory for seamless resume.
|
|
5
|
+
|
|
6
|
+
DESIGN DECISIONS:
|
|
7
|
+
- Three format output (JSON, YAML, Markdown) for different use cases
|
|
8
|
+
- Atomic file operations using StateStorage
|
|
9
|
+
- Git integration for automatic commits
|
|
10
|
+
- Compatible with SessionResumeHelper for resume workflow
|
|
11
|
+
- LATEST-SESSION.txt pointer for quick access
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import subprocess
|
|
15
|
+
from datetime import datetime, timezone
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Any, Dict, Optional
|
|
18
|
+
|
|
19
|
+
import yaml
|
|
20
|
+
|
|
21
|
+
from claude_mpm.core.logger import get_logger
|
|
22
|
+
from claude_mpm.storage.state_storage import StateStorage
|
|
23
|
+
|
|
24
|
+
logger = get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SessionPauseManager:
|
|
28
|
+
"""Manages creating pause sessions and capturing state."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, project_path: Optional[Path] = None):
|
|
31
|
+
"""Initialize session pause manager.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
project_path: Project root path (default: current directory)
|
|
35
|
+
"""
|
|
36
|
+
self.project_path = (project_path or Path.cwd()).resolve()
|
|
37
|
+
# Use flattened structure: .claude-mpm/sessions/ instead of sessions/pause/
|
|
38
|
+
self.pause_dir = self.project_path / ".claude-mpm" / "sessions"
|
|
39
|
+
self.pause_dir.mkdir(parents=True, exist_ok=True)
|
|
40
|
+
self.storage = StateStorage(self.pause_dir)
|
|
41
|
+
|
|
42
|
+
def create_pause_session(
|
|
43
|
+
self,
|
|
44
|
+
message: Optional[str] = None,
|
|
45
|
+
skip_commit: bool = False,
|
|
46
|
+
export_path: Optional[str] = None,
|
|
47
|
+
) -> str:
|
|
48
|
+
"""Create a pause session with captured state.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
message: Optional pause reason/context message
|
|
52
|
+
skip_commit: Skip git commit of session state
|
|
53
|
+
export_path: Optional export location for session file
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Session ID
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
Exception: If session creation fails
|
|
60
|
+
"""
|
|
61
|
+
logger.info("Creating pause session")
|
|
62
|
+
|
|
63
|
+
# Generate session ID
|
|
64
|
+
session_id = f"session-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}"
|
|
65
|
+
|
|
66
|
+
# Capture state
|
|
67
|
+
state = self._capture_state(session_id, message)
|
|
68
|
+
|
|
69
|
+
# Save JSON format
|
|
70
|
+
json_path = self.pause_dir / f"{session_id}.json"
|
|
71
|
+
if not self.storage.write_json(state, json_path, atomic=True):
|
|
72
|
+
raise RuntimeError(f"Failed to write JSON to {json_path}")
|
|
73
|
+
logger.debug(f"Saved JSON: {json_path}")
|
|
74
|
+
|
|
75
|
+
# Save YAML format
|
|
76
|
+
yaml_path = self.pause_dir / f"{session_id}.yaml"
|
|
77
|
+
self._save_yaml(state, yaml_path)
|
|
78
|
+
logger.debug(f"Saved YAML: {yaml_path}")
|
|
79
|
+
|
|
80
|
+
# Save Markdown format
|
|
81
|
+
md_path = self.pause_dir / f"{session_id}.md"
|
|
82
|
+
md_content = self._generate_markdown(state)
|
|
83
|
+
md_path.write_text(md_content)
|
|
84
|
+
logger.debug(f"Saved Markdown: {md_path}")
|
|
85
|
+
|
|
86
|
+
# Update LATEST-SESSION.txt pointer
|
|
87
|
+
self._update_latest_pointer(session_id)
|
|
88
|
+
|
|
89
|
+
# Optional export
|
|
90
|
+
if export_path:
|
|
91
|
+
export_file = Path(export_path).resolve()
|
|
92
|
+
if not self.storage.write_json(state, export_file, atomic=True):
|
|
93
|
+
logger.warning(f"Failed to export to {export_file}")
|
|
94
|
+
else:
|
|
95
|
+
logger.info(f"Exported session to {export_file}")
|
|
96
|
+
|
|
97
|
+
# Optional git commit
|
|
98
|
+
if not skip_commit and self._is_git_repo():
|
|
99
|
+
self._commit_pause_session(session_id, message)
|
|
100
|
+
|
|
101
|
+
logger.info(f"Pause session created: {session_id}")
|
|
102
|
+
return session_id
|
|
103
|
+
|
|
104
|
+
def _capture_state(self, session_id: str, message: Optional[str]) -> Dict[str, Any]:
|
|
105
|
+
"""Capture current session state.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
session_id: Session identifier
|
|
109
|
+
message: Optional context message
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Complete state dictionary
|
|
113
|
+
"""
|
|
114
|
+
# Get git context
|
|
115
|
+
git_context = self._get_git_context()
|
|
116
|
+
|
|
117
|
+
# Build state dictionary
|
|
118
|
+
return {
|
|
119
|
+
"session_id": session_id,
|
|
120
|
+
"paused_at": datetime.now(timezone.utc).isoformat(),
|
|
121
|
+
"duration_hours": 0, # Can be calculated if session start time known
|
|
122
|
+
"context_usage": {
|
|
123
|
+
"tokens_used": 0, # Would need Claude API integration
|
|
124
|
+
"tokens_total": 200000,
|
|
125
|
+
"percentage": 0,
|
|
126
|
+
},
|
|
127
|
+
"conversation": {
|
|
128
|
+
"primary_task": "Manual pause - see message below",
|
|
129
|
+
"current_phase": "In progress",
|
|
130
|
+
"summary": message or "No summary provided",
|
|
131
|
+
"accomplishments": [],
|
|
132
|
+
"next_steps": [],
|
|
133
|
+
},
|
|
134
|
+
"git_context": git_context,
|
|
135
|
+
"active_context": {
|
|
136
|
+
"working_directory": str(self.project_path),
|
|
137
|
+
},
|
|
138
|
+
"important_reminders": [],
|
|
139
|
+
"resume_instructions": {
|
|
140
|
+
"quick_start": [
|
|
141
|
+
f"Read {session_id}.md for full context",
|
|
142
|
+
"Run: git status to check current state",
|
|
143
|
+
"Run: cat .claude-mpm/sessions/LATEST-SESSION.txt",
|
|
144
|
+
],
|
|
145
|
+
"files_to_review": [],
|
|
146
|
+
"validation_commands": {
|
|
147
|
+
"check_git": "git status && git log -1 --stat",
|
|
148
|
+
"check_session": f"cat .claude-mpm/sessions/{session_id}.md",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
"open_questions": [],
|
|
152
|
+
"performance_metrics": {},
|
|
153
|
+
"todos": {"active": [], "completed": []},
|
|
154
|
+
"version": self._get_project_version(),
|
|
155
|
+
"build": "current",
|
|
156
|
+
"project_path": str(self.project_path),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
def _get_git_context(self) -> Dict[str, Any]:
|
|
160
|
+
"""Get git repository context.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Git context dictionary
|
|
164
|
+
"""
|
|
165
|
+
if not self._is_git_repo():
|
|
166
|
+
return {
|
|
167
|
+
"is_git_repo": False,
|
|
168
|
+
"branch": None,
|
|
169
|
+
"recent_commits": [],
|
|
170
|
+
"status": {
|
|
171
|
+
"clean": True,
|
|
172
|
+
"modified_files": [],
|
|
173
|
+
"untracked_files": [],
|
|
174
|
+
},
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
# Get current branch
|
|
179
|
+
branch = subprocess.check_output(
|
|
180
|
+
["git", "branch", "--show-current"],
|
|
181
|
+
cwd=self.project_path,
|
|
182
|
+
text=True,
|
|
183
|
+
stderr=subprocess.DEVNULL,
|
|
184
|
+
).strip()
|
|
185
|
+
|
|
186
|
+
# Get recent commits (last 5)
|
|
187
|
+
commit_log = subprocess.check_output(
|
|
188
|
+
["git", "log", "-5", "--pretty=format:%h|%an|%ai|%s"],
|
|
189
|
+
cwd=self.project_path,
|
|
190
|
+
text=True,
|
|
191
|
+
stderr=subprocess.DEVNULL,
|
|
192
|
+
).strip()
|
|
193
|
+
|
|
194
|
+
recent_commits = []
|
|
195
|
+
for line in commit_log.split("\n"):
|
|
196
|
+
if line:
|
|
197
|
+
parts = line.split("|", 3)
|
|
198
|
+
if len(parts) == 4:
|
|
199
|
+
recent_commits.append(
|
|
200
|
+
{
|
|
201
|
+
"sha": parts[0],
|
|
202
|
+
"author": parts[1],
|
|
203
|
+
"timestamp": parts[2],
|
|
204
|
+
"message": parts[3],
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Get status
|
|
209
|
+
status_output = subprocess.check_output(
|
|
210
|
+
["git", "status", "--porcelain"],
|
|
211
|
+
cwd=self.project_path,
|
|
212
|
+
text=True,
|
|
213
|
+
stderr=subprocess.DEVNULL,
|
|
214
|
+
).strip()
|
|
215
|
+
|
|
216
|
+
modified_files = []
|
|
217
|
+
untracked_files = []
|
|
218
|
+
if status_output:
|
|
219
|
+
for line in status_output.split("\n"):
|
|
220
|
+
if line.startswith("??"):
|
|
221
|
+
untracked_files.append(line[3:])
|
|
222
|
+
elif line:
|
|
223
|
+
modified_files.append(line[3:])
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
"is_git_repo": True,
|
|
227
|
+
"branch": branch,
|
|
228
|
+
"recent_commits": recent_commits,
|
|
229
|
+
"status": {
|
|
230
|
+
"clean": len(modified_files) == 0 and len(untracked_files) == 0,
|
|
231
|
+
"modified_files": modified_files,
|
|
232
|
+
"untracked_files": untracked_files,
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
except subprocess.CalledProcessError as e:
|
|
237
|
+
logger.warning(f"Git command failed: {e}")
|
|
238
|
+
return {
|
|
239
|
+
"is_git_repo": True,
|
|
240
|
+
"branch": "unknown",
|
|
241
|
+
"recent_commits": [],
|
|
242
|
+
"status": {"clean": True, "modified_files": [], "untracked_files": []},
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
def _is_git_repo(self) -> bool:
|
|
246
|
+
"""Check if directory is a git repository.
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
True if git repository exists
|
|
250
|
+
"""
|
|
251
|
+
return (self.project_path / ".git").exists()
|
|
252
|
+
|
|
253
|
+
def _save_yaml(self, state: Dict[str, Any], yaml_path: Path) -> None:
|
|
254
|
+
"""Save state as YAML format.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
state: State dictionary
|
|
258
|
+
yaml_path: Target YAML file path
|
|
259
|
+
"""
|
|
260
|
+
try:
|
|
261
|
+
with yaml_path.open("w") as f:
|
|
262
|
+
yaml.dump(
|
|
263
|
+
state,
|
|
264
|
+
f,
|
|
265
|
+
default_flow_style=False,
|
|
266
|
+
allow_unicode=True,
|
|
267
|
+
sort_keys=False,
|
|
268
|
+
)
|
|
269
|
+
except Exception as e:
|
|
270
|
+
logger.error(f"Failed to write YAML to {yaml_path}: {e}")
|
|
271
|
+
raise
|
|
272
|
+
|
|
273
|
+
def _generate_markdown(self, state: Dict[str, Any]) -> str:
|
|
274
|
+
"""Generate human-readable markdown format.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
state: State dictionary
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Markdown formatted string
|
|
281
|
+
"""
|
|
282
|
+
session_id = state["session_id"]
|
|
283
|
+
paused_at = state["paused_at"]
|
|
284
|
+
conversation = state["conversation"]
|
|
285
|
+
git_context = state["git_context"]
|
|
286
|
+
active_context = state["active_context"]
|
|
287
|
+
|
|
288
|
+
lines = [
|
|
289
|
+
"# Claude MPM Session Pause Document",
|
|
290
|
+
"",
|
|
291
|
+
"## Session Metadata",
|
|
292
|
+
"",
|
|
293
|
+
f"**Session ID**: `{session_id}`",
|
|
294
|
+
f"**Paused At**: {paused_at}",
|
|
295
|
+
f"**Project**: `{state['project_path']}`",
|
|
296
|
+
f"**Version**: {state.get('version', 'unknown')}",
|
|
297
|
+
"",
|
|
298
|
+
"## What You Were Working On",
|
|
299
|
+
"",
|
|
300
|
+
f"**Primary Task**: {conversation['primary_task']}",
|
|
301
|
+
f"**Current Phase**: {conversation['current_phase']}",
|
|
302
|
+
"",
|
|
303
|
+
"**Summary**:",
|
|
304
|
+
f"{conversation['summary']}",
|
|
305
|
+
"",
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
# Accomplishments
|
|
309
|
+
if conversation.get("accomplishments"):
|
|
310
|
+
lines.append("## Accomplishments This Session")
|
|
311
|
+
lines.append("")
|
|
312
|
+
for item in conversation["accomplishments"]:
|
|
313
|
+
lines.append(f"- {item}")
|
|
314
|
+
lines.append("")
|
|
315
|
+
|
|
316
|
+
# Next steps
|
|
317
|
+
if conversation.get("next_steps"):
|
|
318
|
+
lines.append("## Next Steps (Priority Order)")
|
|
319
|
+
lines.append("")
|
|
320
|
+
for i, step in enumerate(conversation["next_steps"], 1):
|
|
321
|
+
if isinstance(step, dict):
|
|
322
|
+
lines.append(
|
|
323
|
+
f"{i}. **{step.get('task', 'Unknown task')}** (Priority: {step.get('priority', '?')})"
|
|
324
|
+
)
|
|
325
|
+
if step.get("estimated_hours"):
|
|
326
|
+
lines.append(f" - Est. time: {step['estimated_hours']}")
|
|
327
|
+
if step.get("status"):
|
|
328
|
+
lines.append(f" - Status: {step['status']}")
|
|
329
|
+
if step.get("notes"):
|
|
330
|
+
lines.append(f" - Notes: {step['notes']}")
|
|
331
|
+
else:
|
|
332
|
+
lines.append(f"{i}. {step}")
|
|
333
|
+
lines.append("")
|
|
334
|
+
|
|
335
|
+
# Active context
|
|
336
|
+
lines.extend(
|
|
337
|
+
[
|
|
338
|
+
"## Active Context",
|
|
339
|
+
"",
|
|
340
|
+
f"**Working Directory**: `{active_context['working_directory']}`",
|
|
341
|
+
"",
|
|
342
|
+
]
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# Git context
|
|
346
|
+
lines.append("## Git Context")
|
|
347
|
+
lines.append("")
|
|
348
|
+
if git_context["is_git_repo"]:
|
|
349
|
+
lines.append(f"**Branch**: `{git_context['branch']}`")
|
|
350
|
+
lines.append(
|
|
351
|
+
f"**Status**: {'Clean' if git_context['status']['clean'] else 'Modified'}"
|
|
352
|
+
)
|
|
353
|
+
lines.append("")
|
|
354
|
+
|
|
355
|
+
if git_context["status"]["modified_files"]:
|
|
356
|
+
lines.append("**Modified files**:")
|
|
357
|
+
for f in git_context["status"]["modified_files"][:10]:
|
|
358
|
+
lines.append(f"- `{f}`")
|
|
359
|
+
lines.append("")
|
|
360
|
+
|
|
361
|
+
if git_context["recent_commits"]:
|
|
362
|
+
lines.append("**Recent commits**:")
|
|
363
|
+
for commit in git_context["recent_commits"]:
|
|
364
|
+
lines.append(
|
|
365
|
+
f"- `{commit['sha']}` - {commit['message']} ({commit['author']})"
|
|
366
|
+
)
|
|
367
|
+
lines.append("")
|
|
368
|
+
else:
|
|
369
|
+
lines.append("*Not a git repository*")
|
|
370
|
+
lines.append("")
|
|
371
|
+
|
|
372
|
+
# Important reminders
|
|
373
|
+
if state.get("important_reminders"):
|
|
374
|
+
lines.append("## Important Reminders")
|
|
375
|
+
lines.append("")
|
|
376
|
+
for reminder in state["important_reminders"]:
|
|
377
|
+
lines.append(f"- {reminder}")
|
|
378
|
+
lines.append("")
|
|
379
|
+
|
|
380
|
+
# Resume instructions
|
|
381
|
+
lines.extend(
|
|
382
|
+
[
|
|
383
|
+
"## Resume Instructions",
|
|
384
|
+
"",
|
|
385
|
+
"### Quick Resume (5 minutes)",
|
|
386
|
+
"",
|
|
387
|
+
]
|
|
388
|
+
)
|
|
389
|
+
for instruction in state["resume_instructions"]["quick_start"]:
|
|
390
|
+
lines.append(f"1. {instruction}")
|
|
391
|
+
lines.append("")
|
|
392
|
+
|
|
393
|
+
if state["resume_instructions"]["validation_commands"]:
|
|
394
|
+
lines.append("### Validation Commands")
|
|
395
|
+
lines.append("")
|
|
396
|
+
lines.append("```bash")
|
|
397
|
+
for cmd in state["resume_instructions"]["validation_commands"].values():
|
|
398
|
+
lines.append(cmd)
|
|
399
|
+
lines.append("```")
|
|
400
|
+
lines.append("")
|
|
401
|
+
|
|
402
|
+
# Footer
|
|
403
|
+
lines.extend(
|
|
404
|
+
[
|
|
405
|
+
"---",
|
|
406
|
+
"",
|
|
407
|
+
"Resume with: `/mpm-init resume` or `cat .claude-mpm/sessions/LATEST-SESSION.txt`",
|
|
408
|
+
"",
|
|
409
|
+
]
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
return "\n".join(lines)
|
|
413
|
+
|
|
414
|
+
def _update_latest_pointer(self, session_id: str) -> None:
|
|
415
|
+
"""Update LATEST-SESSION.txt pointer.
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
session_id: Session identifier
|
|
419
|
+
"""
|
|
420
|
+
try:
|
|
421
|
+
latest_file = self.pause_dir / "LATEST-SESSION.txt"
|
|
422
|
+
content = f"""Latest Session: {session_id}
|
|
423
|
+
Paused At: {datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S %Z")}
|
|
424
|
+
Project: {self.project_path}
|
|
425
|
+
|
|
426
|
+
Files:
|
|
427
|
+
- {session_id}.json (machine-readable)
|
|
428
|
+
- {session_id}.yaml (human-readable config)
|
|
429
|
+
- {session_id}.md (documentation)
|
|
430
|
+
|
|
431
|
+
Quick Resume:
|
|
432
|
+
/mpm-init resume
|
|
433
|
+
|
|
434
|
+
Full Context:
|
|
435
|
+
cat .claude-mpm/sessions/{session_id}.md
|
|
436
|
+
|
|
437
|
+
Validation:
|
|
438
|
+
git status && git log -1 --stat
|
|
439
|
+
"""
|
|
440
|
+
latest_file.write_text(content)
|
|
441
|
+
logger.debug(f"Updated LATEST-SESSION.txt: {session_id}")
|
|
442
|
+
except Exception as e:
|
|
443
|
+
logger.warning(f"Failed to update LATEST-SESSION.txt: {e}")
|
|
444
|
+
|
|
445
|
+
def _commit_pause_session(self, session_id: str, message: Optional[str]) -> None:
|
|
446
|
+
"""Create git commit for pause session.
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
session_id: Session identifier
|
|
450
|
+
message: Optional context message
|
|
451
|
+
"""
|
|
452
|
+
try:
|
|
453
|
+
# Add session files
|
|
454
|
+
subprocess.run(
|
|
455
|
+
["git", "add", ".claude-mpm/sessions/"],
|
|
456
|
+
cwd=self.project_path,
|
|
457
|
+
check=True,
|
|
458
|
+
capture_output=True,
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
# Build commit message
|
|
462
|
+
commit_msg = f"session: pause at {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')}\n\nSession ID: {session_id}"
|
|
463
|
+
if message:
|
|
464
|
+
commit_msg += f"\nContext: {message}"
|
|
465
|
+
|
|
466
|
+
# Create commit
|
|
467
|
+
subprocess.run(
|
|
468
|
+
["git", "commit", "-m", commit_msg],
|
|
469
|
+
cwd=self.project_path,
|
|
470
|
+
check=True,
|
|
471
|
+
capture_output=True,
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
logger.info(f"Created git commit for pause session: {session_id}")
|
|
475
|
+
|
|
476
|
+
except subprocess.CalledProcessError as e:
|
|
477
|
+
# Non-fatal - pause still succeeded
|
|
478
|
+
logger.warning(f"Failed to create git commit: {e.stderr.decode()}")
|
|
479
|
+
|
|
480
|
+
def _get_project_version(self) -> str:
|
|
481
|
+
"""Get project version from pyproject.toml or package.
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
Version string or 'unknown'
|
|
485
|
+
"""
|
|
486
|
+
try:
|
|
487
|
+
# Try pyproject.toml
|
|
488
|
+
pyproject = self.project_path / "pyproject.toml"
|
|
489
|
+
if pyproject.exists():
|
|
490
|
+
content = pyproject.read_text()
|
|
491
|
+
for line in content.split("\n"):
|
|
492
|
+
if line.startswith("version"):
|
|
493
|
+
return line.split("=")[1].strip().strip('"')
|
|
494
|
+
|
|
495
|
+
# Try package __version__
|
|
496
|
+
import claude_mpm
|
|
497
|
+
|
|
498
|
+
if hasattr(claude_mpm, "__version__"):
|
|
499
|
+
return claude_mpm.__version__
|
|
500
|
+
|
|
501
|
+
except Exception:
|
|
502
|
+
pass
|
|
503
|
+
|
|
504
|
+
return "unknown"
|
|
@@ -5,7 +5,8 @@ It detects paused sessions, calculates git changes since pause, and presents res
|
|
|
5
5
|
context to users.
|
|
6
6
|
|
|
7
7
|
DESIGN DECISIONS:
|
|
8
|
-
- Project-specific session storage (.claude-mpm/sessions/
|
|
8
|
+
- Project-specific session storage (.claude-mpm/sessions/)
|
|
9
|
+
- Backward compatibility with legacy .claude-mpm/sessions/pause/ location
|
|
9
10
|
- Non-blocking detection with graceful degradation
|
|
10
11
|
- Git change detection for context updates
|
|
11
12
|
- User-friendly prompts with time elapsed information
|
|
@@ -33,7 +34,10 @@ class SessionResumeHelper:
|
|
|
33
34
|
project_path: Project root path (default: current directory)
|
|
34
35
|
"""
|
|
35
36
|
self.project_path = project_path or Path.cwd()
|
|
36
|
-
|
|
37
|
+
# Primary location: flattened structure
|
|
38
|
+
self.pause_dir = self.project_path / ".claude-mpm" / "sessions"
|
|
39
|
+
# Legacy location for backward compatibility
|
|
40
|
+
self.legacy_pause_dir = self.project_path / ".claude-mpm" / "sessions" / "pause"
|
|
37
41
|
|
|
38
42
|
def has_paused_sessions(self) -> bool:
|
|
39
43
|
"""Check if there are any paused sessions.
|
|
@@ -41,11 +45,15 @@ class SessionResumeHelper:
|
|
|
41
45
|
Returns:
|
|
42
46
|
True if paused sessions exist, False otherwise
|
|
43
47
|
"""
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
# Check both primary and legacy locations
|
|
49
|
+
session_files = []
|
|
50
|
+
|
|
51
|
+
if self.pause_dir.exists():
|
|
52
|
+
session_files.extend(list(self.pause_dir.glob("session-*.json")))
|
|
53
|
+
|
|
54
|
+
if self.legacy_pause_dir.exists():
|
|
55
|
+
session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
|
|
46
56
|
|
|
47
|
-
# Look for session JSON files
|
|
48
|
-
session_files = list(self.pause_dir.glob("session-*.json"))
|
|
49
57
|
return len(session_files) > 0
|
|
50
58
|
|
|
51
59
|
def get_most_recent_session(self) -> Optional[Dict[str, Any]]:
|
|
@@ -54,11 +62,15 @@ class SessionResumeHelper:
|
|
|
54
62
|
Returns:
|
|
55
63
|
Session data dictionary or None if no sessions found
|
|
56
64
|
"""
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
# Find all session files from both locations
|
|
66
|
+
session_files = []
|
|
67
|
+
|
|
68
|
+
if self.pause_dir.exists():
|
|
69
|
+
session_files.extend(list(self.pause_dir.glob("session-*.json")))
|
|
70
|
+
|
|
71
|
+
if self.legacy_pause_dir.exists():
|
|
72
|
+
session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
|
|
59
73
|
|
|
60
|
-
# Find all session files
|
|
61
|
-
session_files = list(self.pause_dir.glob("session-*.json"))
|
|
62
74
|
if not session_files:
|
|
63
75
|
return None
|
|
64
76
|
|
|
@@ -316,10 +328,14 @@ class SessionResumeHelper:
|
|
|
316
328
|
Returns:
|
|
317
329
|
Number of paused sessions
|
|
318
330
|
"""
|
|
319
|
-
|
|
320
|
-
|
|
331
|
+
session_files = []
|
|
332
|
+
|
|
333
|
+
if self.pause_dir.exists():
|
|
334
|
+
session_files.extend(list(self.pause_dir.glob("session-*.json")))
|
|
335
|
+
|
|
336
|
+
if self.legacy_pause_dir.exists():
|
|
337
|
+
session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
|
|
321
338
|
|
|
322
|
-
session_files = list(self.pause_dir.glob("session-*.json"))
|
|
323
339
|
return len(session_files)
|
|
324
340
|
|
|
325
341
|
def list_all_sessions(self) -> List[Dict[str, Any]]:
|
|
@@ -328,10 +344,14 @@ class SessionResumeHelper:
|
|
|
328
344
|
Returns:
|
|
329
345
|
List of session data dictionaries
|
|
330
346
|
"""
|
|
331
|
-
|
|
332
|
-
|
|
347
|
+
session_files = []
|
|
348
|
+
|
|
349
|
+
if self.pause_dir.exists():
|
|
350
|
+
session_files.extend(list(self.pause_dir.glob("session-*.json")))
|
|
351
|
+
|
|
352
|
+
if self.legacy_pause_dir.exists():
|
|
353
|
+
session_files.extend(list(self.legacy_pause_dir.glob("session-*.json")))
|
|
333
354
|
|
|
334
|
-
session_files = list(self.pause_dir.glob("session-*.json"))
|
|
335
355
|
if not session_files:
|
|
336
356
|
return []
|
|
337
357
|
|
|
@@ -392,7 +392,7 @@ class UnifiedDashboardManager(IUnifiedDashboardManager):
|
|
|
392
392
|
port = self.find_available_port()
|
|
393
393
|
|
|
394
394
|
# Use force_restart to ensure we're using the latest code
|
|
395
|
-
success,
|
|
395
|
+
success, _browser_opened = self.start_dashboard(
|
|
396
396
|
port=port, background=True, open_browser=False, force_restart=force_restart
|
|
397
397
|
)
|
|
398
398
|
|
claude_mpm/services/core/base.py
CHANGED
|
@@ -9,6 +9,7 @@ and lifecycle management.
|
|
|
9
9
|
Part of TSK-0046: Service Layer Architecture Reorganization
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
import threading
|
|
12
13
|
from abc import ABC, abstractmethod
|
|
13
14
|
from typing import Any, Dict, Optional
|
|
14
15
|
|
|
@@ -221,29 +222,43 @@ class SingletonService(SyncBaseService):
|
|
|
221
222
|
"""
|
|
222
223
|
Base class for singleton services.
|
|
223
224
|
|
|
224
|
-
Ensures only one instance of the service exists.
|
|
225
|
+
Ensures only one instance of the service exists with thread-safe initialization.
|
|
226
|
+
Uses double-checked locking pattern to prevent race conditions.
|
|
225
227
|
"""
|
|
226
228
|
|
|
227
229
|
_instances: Dict[type, "SingletonService"] = {}
|
|
230
|
+
_lock = threading.Lock()
|
|
228
231
|
|
|
229
232
|
def __new__(cls, *args, **kwargs):
|
|
230
|
-
"""Ensure only one instance exists."""
|
|
233
|
+
"""Ensure only one instance exists with thread-safe initialization."""
|
|
234
|
+
# Fast path - check without lock
|
|
231
235
|
if cls not in cls._instances:
|
|
232
|
-
|
|
236
|
+
# Slow path - acquire lock and double-check
|
|
237
|
+
with cls._lock:
|
|
238
|
+
if cls not in cls._instances:
|
|
239
|
+
cls._instances[cls] = super().__new__(cls)
|
|
233
240
|
return cls._instances[cls]
|
|
234
241
|
|
|
235
242
|
@classmethod
|
|
236
243
|
def get_instance(cls) -> "SingletonService":
|
|
237
|
-
"""Get the singleton instance."""
|
|
244
|
+
"""Get the singleton instance with thread-safe initialization."""
|
|
245
|
+
# Fast path - check without lock
|
|
238
246
|
if cls not in cls._instances:
|
|
239
|
-
|
|
247
|
+
# Slow path - acquire lock and double-check
|
|
248
|
+
with cls._lock:
|
|
249
|
+
if cls not in cls._instances:
|
|
250
|
+
cls._instances[cls] = cls()
|
|
240
251
|
return cls._instances[cls]
|
|
241
252
|
|
|
242
253
|
@classmethod
|
|
243
254
|
def clear_instance(cls) -> None:
|
|
244
|
-
"""Clear the singleton instance (useful for testing).
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
255
|
+
"""Clear the singleton instance (useful for testing).
|
|
256
|
+
|
|
257
|
+
Thread-safe implementation ensures proper cleanup.
|
|
258
|
+
"""
|
|
259
|
+
with cls._lock:
|
|
260
|
+
if cls in cls._instances:
|
|
261
|
+
instance = cls._instances[cls]
|
|
262
|
+
if hasattr(instance, "shutdown") and not instance.is_shutdown:
|
|
263
|
+
instance.shutdown()
|
|
264
|
+
del cls._instances[cls]
|