claude-mpm 5.4.55__py3-none-any.whl → 5.4.85__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.
Files changed (173) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
  3. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +63 -241
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +36 -9
  6. claude_mpm/cli/__init__.py +5 -1
  7. claude_mpm/cli/commands/agents.py +2 -4
  8. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  9. claude_mpm/cli/commands/configure.py +620 -21
  10. claude_mpm/cli/commands/skills.py +166 -14
  11. claude_mpm/cli/executor.py +1 -0
  12. claude_mpm/cli/interactive/__init__.py +10 -0
  13. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  14. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  15. claude_mpm/cli/interactive/skill_selector.py +481 -0
  16. claude_mpm/cli/parsers/base_parser.py +5 -0
  17. claude_mpm/cli/startup.py +223 -388
  18. claude_mpm/constants.py +1 -0
  19. claude_mpm/core/claude_runner.py +2 -2
  20. claude_mpm/core/interactive_session.py +7 -7
  21. claude_mpm/core/output_style_manager.py +21 -13
  22. claude_mpm/core/unified_config.py +50 -8
  23. claude_mpm/core/unified_paths.py +30 -13
  24. claude_mpm/scripts/start_activity_logging.py +0 -0
  25. claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
  26. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  27. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  28. claude_mpm/services/agents/sources/git_source_sync_service.py +7 -4
  29. claude_mpm/services/agents/startup_sync.py +5 -2
  30. claude_mpm/services/pm_skills_deployer.py +4 -0
  31. claude_mpm/services/skills/git_skill_source_manager.py +24 -8
  32. claude_mpm/services/skills/selective_skill_deployer.py +82 -83
  33. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  34. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  35. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  36. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  37. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  38. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  39. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  40. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  41. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  42. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  43. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  44. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  45. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  46. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  47. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  48. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  49. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  50. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  51. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  52. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  53. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  54. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  55. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  56. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  57. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  58. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  59. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  60. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  61. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  62. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  63. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  64. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  65. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  66. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  67. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  68. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  69. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  70. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  71. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  72. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  73. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  74. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  75. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  76. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  77. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  78. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  79. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  80. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  81. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  82. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  83. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  84. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  85. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  86. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  87. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  88. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  89. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  90. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  91. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  92. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  93. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  94. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  95. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  96. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  97. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  98. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  99. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  100. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  101. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  102. claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
  103. claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
  104. claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
  105. claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
  106. claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
  107. claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
  108. claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
  109. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  110. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  111. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  112. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  113. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  114. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  115. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  116. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  117. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  118. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  119. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  120. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  121. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  122. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  123. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  124. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  125. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  126. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  127. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  128. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  129. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  130. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  131. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  132. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  133. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  134. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  135. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  136. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  137. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  138. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  139. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  140. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  141. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  142. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  143. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  144. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  145. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  146. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  147. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  148. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  149. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  150. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  151. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  152. claude_mpm/utils/agent_dependency_loader.py +103 -4
  153. claude_mpm/utils/robust_installer.py +45 -24
  154. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/METADATA +47 -23
  155. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/RECORD +159 -47
  156. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  157. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  158. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  159. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  160. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  161. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  162. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  163. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  164. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  165. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  166. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  167. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  168. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  169. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/WHEEL +0 -0
  170. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +0 -0
  171. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/licenses/LICENSE +0 -0
  172. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  173. {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,138 @@
1
+ """
2
+ Startup Reconciliation Hook
3
+
4
+ This module provides a hook for performing agent/skill reconciliation
5
+ during application startup, ensuring deployed state matches configuration.
6
+
7
+ Usage:
8
+ from claude_mpm.services.agents.deployment.startup_reconciliation import (
9
+ perform_startup_reconciliation
10
+ )
11
+
12
+ # In your startup code
13
+ perform_startup_reconciliation()
14
+ """
15
+
16
+ from pathlib import Path
17
+ from typing import Optional
18
+
19
+ from claude_mpm.core.logging_utils import get_logger
20
+ from claude_mpm.core.unified_config import UnifiedConfig
21
+
22
+ from .deployment_reconciler import DeploymentReconciler, DeploymentResult
23
+
24
+ logger = get_logger(__name__)
25
+
26
+
27
+ def perform_startup_reconciliation(
28
+ project_path: Optional[Path] = None,
29
+ config: Optional[UnifiedConfig] = None,
30
+ silent: bool = False,
31
+ ) -> tuple[DeploymentResult, DeploymentResult]:
32
+ """
33
+ Perform agent and skill reconciliation during startup.
34
+
35
+ This ensures the deployed state (.claude/agents, .claude/skills) matches
36
+ the configuration (agents.enabled, skills.enabled lists).
37
+
38
+ Args:
39
+ project_path: Project directory (default: current directory)
40
+ config: Configuration instance (auto-loads if None)
41
+ silent: Suppress info logging (only errors)
42
+
43
+ Returns:
44
+ Tuple of (agent_result, skill_result)
45
+ """
46
+ project_path = project_path or Path.cwd()
47
+
48
+ # Load config if not provided
49
+ if config is None:
50
+ config = UnifiedConfig()
51
+
52
+ # Initialize reconciler
53
+ reconciler = DeploymentReconciler(config)
54
+
55
+ if not silent:
56
+ logger.info("Performing startup reconciliation...")
57
+
58
+ # Reconcile agents
59
+ agent_result = reconciler.reconcile_agents(project_path)
60
+
61
+ if agent_result.deployed and not silent:
62
+ logger.info(f"Deployed agents: {', '.join(agent_result.deployed)}")
63
+ if agent_result.removed and not silent:
64
+ logger.info(f"Removed agents: {', '.join(agent_result.removed)}")
65
+ if agent_result.errors:
66
+ for error in agent_result.errors:
67
+ logger.error(f"Agent reconciliation error: {error}")
68
+
69
+ # Reconcile skills
70
+ skill_result = reconciler.reconcile_skills(project_path)
71
+
72
+ if skill_result.deployed and not silent:
73
+ logger.info(f"Deployed skills: {', '.join(skill_result.deployed)}")
74
+ if skill_result.removed and not silent:
75
+ logger.info(f"Removed skills: {', '.join(skill_result.removed)}")
76
+ if skill_result.errors:
77
+ for error in skill_result.errors:
78
+ logger.error(f"Skill reconciliation error: {error}")
79
+
80
+ if not silent:
81
+ total_errors = len(agent_result.errors) + len(skill_result.errors)
82
+ if total_errors == 0:
83
+ logger.info("Startup reconciliation complete")
84
+ else:
85
+ logger.warning(
86
+ f"Startup reconciliation complete with {total_errors} errors"
87
+ )
88
+
89
+ return agent_result, skill_result
90
+
91
+
92
+ def check_reconciliation_needed(
93
+ project_path: Optional[Path] = None, config: Optional[UnifiedConfig] = None
94
+ ) -> bool:
95
+ """
96
+ Check if reconciliation is needed (without performing it).
97
+
98
+ Args:
99
+ project_path: Project directory
100
+ config: Configuration instance
101
+
102
+ Returns:
103
+ True if reconciliation would make changes
104
+ """
105
+ project_path = project_path or Path.cwd()
106
+
107
+ if config is None:
108
+ config = UnifiedConfig()
109
+
110
+ reconciler = DeploymentReconciler(config)
111
+ view = reconciler.get_reconciliation_view(project_path)
112
+
113
+ agent_state = view["agents"]
114
+ skill_state = view["skills"]
115
+
116
+ # Check if any changes needed
117
+ return (
118
+ len(agent_state.to_deploy) > 0
119
+ or len(agent_state.to_remove) > 0
120
+ or len(skill_state.to_deploy) > 0
121
+ or len(skill_state.to_remove) > 0
122
+ )
123
+
124
+
125
+ # Example integration in startup code:
126
+ #
127
+ # from claude_mpm.services.agents.deployment.startup_reconciliation import (
128
+ # perform_startup_reconciliation,
129
+ # check_reconciliation_needed
130
+ # )
131
+ #
132
+ # def startup():
133
+ # # Check if reconciliation needed
134
+ # if check_reconciliation_needed():
135
+ # logger.info("Reconciliation needed, performing...")
136
+ # perform_startup_reconciliation()
137
+ # else:
138
+ # logger.debug("No reconciliation needed")
@@ -1118,14 +1118,17 @@ class GitSourceSyncService:
1118
1118
  deploy_filename = Path(agent_path).name
1119
1119
  deploy_file = deployment_dir / deploy_filename
1120
1120
 
1121
- # Check if update needed (compare modification times)
1121
+ # Check if update needed (compare content, not just mtime)
1122
+ # DESIGN: Use content hash comparison for reliable change detection
1123
+ # Mtime comparison can fail when cache downloads have older timestamps
1122
1124
  should_deploy = force
1123
1125
  was_existing = deploy_file.exists()
1124
1126
 
1125
1127
  if not force and was_existing:
1126
- cache_mtime = cache_file.stat().st_mtime
1127
- deploy_mtime = deploy_file.stat().st_mtime
1128
- should_deploy = cache_mtime > deploy_mtime
1128
+ # Compare file contents using hash
1129
+ cache_content = cache_file.read_bytes()
1130
+ deploy_content = deploy_file.read_bytes()
1131
+ should_deploy = cache_content != deploy_content
1129
1132
 
1130
1133
  if not should_deploy and was_existing:
1131
1134
  results["skipped"].append(deploy_filename)
@@ -32,7 +32,9 @@ from claude_mpm.services.agents.sources.git_source_sync_service import (
32
32
  logger = logging.getLogger(__name__)
33
33
 
34
34
 
35
- def sync_agents_on_startup(config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
35
+ def sync_agents_on_startup(
36
+ config: Optional[Dict[str, Any]] = None, force_refresh: bool = False
37
+ ) -> Dict[str, Any]:
36
38
  """Synchronize agents from remote sources on Claude MPM startup.
37
39
 
38
40
  Design Decision: Single-source support for Stage 1
@@ -44,6 +46,7 @@ def sync_agents_on_startup(config: Optional[Dict[str, Any]] = None) -> Dict[str,
44
46
 
45
47
  Args:
46
48
  config: Optional configuration dictionary. If None, loads from Config singleton.
49
+ force_refresh: Force download even if cache is fresh (bypasses ETag).
47
50
 
48
51
  Returns:
49
52
  Dictionary with sync results:
@@ -156,7 +159,7 @@ def sync_agents_on_startup(config: Optional[Dict[str, Any]] = None) -> Dict[str,
156
159
  )
157
160
 
158
161
  # Perform sync
159
- sync_result = sync_service.sync_agents(force_refresh=False)
162
+ sync_result = sync_service.sync_agents(force_refresh=force_refresh)
160
163
 
161
164
  # Aggregate results
162
165
  result["sources_synced"] += 1
@@ -98,6 +98,7 @@ class VerificationResult:
98
98
  missing_skills: List of missing skill names
99
99
  outdated_skills: List of outdated skill names
100
100
  message: Summary message
101
+ skill_count: Total number of deployed skills
101
102
  """
102
103
 
103
104
  verified: bool
@@ -105,6 +106,7 @@ class VerificationResult:
105
106
  missing_skills: List[str]
106
107
  outdated_skills: List[str]
107
108
  message: str
109
+ skill_count: int = 0
108
110
 
109
111
 
110
112
  @dataclass
@@ -551,6 +553,7 @@ class PMSkillsDeployerService(LoggerMixin):
551
553
  missing_skills=missing_skills,
552
554
  outdated_skills=outdated_skills,
553
555
  message="PM skills not deployed. Run 'claude-mpm init' to deploy.",
556
+ skill_count=0,
554
557
  )
555
558
 
556
559
  # Check each registered skill exists
@@ -610,6 +613,7 @@ class PMSkillsDeployerService(LoggerMixin):
610
613
  missing_skills=missing_skills,
611
614
  outdated_skills=outdated_skills,
612
615
  message=message,
616
+ skill_count=len(deployed_skills),
613
617
  )
614
618
 
615
619
  def get_deployed_skills(self, project_dir: Path) -> List[PMSkillInfo]:
@@ -991,12 +991,17 @@ class GitSkillSourceManager:
991
991
  progress_callback=None,
992
992
  skill_filter: Optional[Set[str]] = None,
993
993
  ) -> Dict[str, Any]:
994
- """Deploy skills from cache to target directory with flat structure.
994
+ """Deploy skills from cache to target directory with flat structure and automatic cleanup.
995
995
 
996
996
  Flattens nested Git repository structure into Claude Code compatible
997
997
  flat directory structure. Each skill directory is copied with a
998
998
  hyphen-separated name derived from its path.
999
999
 
1000
+ CRITICAL: When skill_filter is provided (agent-referenced skills), this function:
1001
+ 1. Deploys ONLY the filtered skills
1002
+ 2. REMOVES orphaned skills (deployed but not in filter)
1003
+ 3. Returns removed_count and removed_skills in result
1004
+
1000
1005
  Transformation Example:
1001
1006
  Cache: collaboration/dispatching-parallel-agents/SKILL.md
1002
1007
  Deploy: collaboration-dispatching-parallel-agents/SKILL.md
@@ -1006,8 +1011,8 @@ class GitSkillSourceManager:
1006
1011
  force: Overwrite existing skills
1007
1012
  progress_callback: Optional callback(increment: int) called for each skill deployed
1008
1013
  skill_filter: Optional set of skill names to deploy (selective deployment).
1009
- If None, deploys all skills. If provided, only deploys skills
1010
- whose name matches an entry in the filter set.
1014
+ If None, deploys ALL skills WITHOUT cleanup.
1015
+ If provided, deploys ONLY filtered skills AND removes orphans.
1011
1016
 
1012
1017
  Returns:
1013
1018
  Dict with deployment results:
@@ -1018,7 +1023,9 @@ class GitSkillSourceManager:
1018
1023
  "deployed_skills": List[str],
1019
1024
  "skipped_skills": List[str],
1020
1025
  "errors": List[str],
1021
- "filtered_count": int # Number of skills filtered out
1026
+ "filtered_count": int, # Number of skills filtered out
1027
+ "removed_count": int, # Number of orphaned skills removed
1028
+ "removed_skills": List[str] # Names of removed orphaned skills
1022
1029
  }
1023
1030
 
1024
1031
  Example:
@@ -1026,10 +1033,10 @@ class GitSkillSourceManager:
1026
1033
  >>> result = manager.deploy_skills()
1027
1034
  >>> print(f"Deployed {result['deployed_count']} skills")
1028
1035
 
1029
- # Selective deployment based on agent requirements:
1036
+ # Selective deployment based on agent requirements (with cleanup):
1030
1037
  >>> required = {"typescript-core", "react-patterns"}
1031
1038
  >>> result = manager.deploy_skills(skill_filter=required)
1032
- >>> print(f"Deployed {result['deployed_count']} of {len(required)} required skills")
1039
+ >>> print(f"Deployed {result['deployed_count']}, removed {result['removed_count']} orphans")
1033
1040
  """
1034
1041
  if target_dir is None:
1035
1042
  target_dir = Path.home() / ".claude" / "skills"
@@ -1040,6 +1047,7 @@ class GitSkillSourceManager:
1040
1047
  skipped = []
1041
1048
  errors = []
1042
1049
  filtered_count = 0
1050
+ removed_skills = [] # Track removed orphaned skills
1043
1051
 
1044
1052
  # Get all skills from all sources
1045
1053
  all_skills = self.get_all_skills()
@@ -1082,11 +1090,16 @@ class GitSkillSourceManager:
1082
1090
  )
1083
1091
 
1084
1092
  # Cleanup: Remove skills from target directory that aren't in the filtered set
1085
- # This ensures only the skills in the profile are deployed
1093
+ # This ensures only agent-referenced skills remain deployed
1086
1094
  removed_skills = self._cleanup_unfiltered_skills(target_dir, all_skills)
1087
1095
  if removed_skills:
1088
1096
  self.logger.info(
1089
- f"Removed {len(removed_skills)} skills not in profile filter: {removed_skills}"
1097
+ f"Removed {len(removed_skills)} orphaned skills not referenced by agents: {removed_skills[:10]}"
1098
+ + (
1099
+ f" (and {len(removed_skills) - 10} more)"
1100
+ if len(removed_skills) > 10
1101
+ else ""
1102
+ )
1090
1103
  )
1091
1104
 
1092
1105
  self.logger.info(
@@ -1130,6 +1143,7 @@ class GitSkillSourceManager:
1130
1143
  self.logger.info(
1131
1144
  f"Deployment complete: {len(deployed)} deployed, "
1132
1145
  f"{len(skipped)} skipped, {len(errors)} errors"
1146
+ + (f", {len(removed_skills)} removed" if removed_skills else "")
1133
1147
  )
1134
1148
 
1135
1149
  return {
@@ -1140,6 +1154,8 @@ class GitSkillSourceManager:
1140
1154
  "skipped_skills": skipped,
1141
1155
  "errors": errors,
1142
1156
  "filtered_count": filtered_count,
1157
+ "removed_count": len(removed_skills),
1158
+ "removed_skills": removed_skills,
1143
1159
  }
1144
1160
 
1145
1161
  def _cleanup_unfiltered_skills(
@@ -44,13 +44,56 @@ from typing import Any, Dict, List, Set, Tuple
44
44
  import yaml
45
45
 
46
46
  from claude_mpm.core.logging_config import get_logger
47
- from claude_mpm.services.skills.skill_to_agent_mapper import SkillToAgentMapper
48
47
 
49
48
  logger = get_logger(__name__)
50
49
 
51
50
  # Deployment tracking index file
52
51
  DEPLOYED_INDEX_FILE = ".mpm-deployed-skills.json"
53
52
 
53
+ # Core skills that are universally useful across all projects
54
+ # These are deployed when skill mapping returns too many skills (>60)
55
+ # Target: ~25-30 core skills for balanced functionality
56
+ CORE_SKILLS = {
57
+ # Universal debugging and verification (4 skills)
58
+ "universal-debugging-systematic-debugging",
59
+ "universal-debugging-verification-before-completion",
60
+ "universal-verification-pre-merge",
61
+ "universal-verification-screenshot",
62
+ # Universal testing patterns (2 skills)
63
+ "universal-testing-test-driven-development",
64
+ "universal-testing-testing-anti-patterns",
65
+ # Universal architecture and design (1 skill)
66
+ "universal-architecture-software-patterns",
67
+ # Universal infrastructure (3 skills)
68
+ "universal-infrastructure-env-manager",
69
+ "universal-infrastructure-docker",
70
+ "universal-infrastructure-github-actions",
71
+ # Universal collaboration (1 skill)
72
+ "universal-collaboration-stacked-prs",
73
+ # Universal emergency/operations (1 skill)
74
+ "toolchains-universal-emergency-release",
75
+ "toolchains-universal-dependency-audit",
76
+ # Common language toolchains (6 skills)
77
+ "toolchains-typescript-core",
78
+ "toolchains-python-core",
79
+ "toolchains-javascript-tooling-biome",
80
+ "toolchains-python-tooling-mypy",
81
+ "toolchains-typescript-testing-vitest",
82
+ "toolchains-python-frameworks-flask",
83
+ # Common web frameworks (4 skills)
84
+ "toolchains-javascript-frameworks-nextjs",
85
+ "toolchains-nextjs-core",
86
+ "toolchains-typescript-frameworks-nodejs-backend",
87
+ "toolchains-javascript-frameworks-react-state-machine",
88
+ # Common testing tools (2 skills)
89
+ "toolchains-javascript-testing-playwright",
90
+ "toolchains-typescript-testing-jest",
91
+ # Common data/UI tools (3 skills)
92
+ "universal-data-xlsx",
93
+ "toolchains-ui-styling-tailwind",
94
+ "toolchains-ui-components-headlessui",
95
+ }
96
+
54
97
 
55
98
  def parse_agent_frontmatter(agent_file: Path) -> Dict[str, Any]:
56
99
  """Parse YAML frontmatter from agent markdown file.
@@ -140,22 +183,14 @@ def get_skills_from_agent(frontmatter: Dict[str, Any]) -> Set[str]:
140
183
  def get_skills_from_mapping(agent_ids: List[str]) -> Set[str]:
141
184
  """Get skills for agents using SkillToAgentMapper inference.
142
185
 
143
- Uses SkillToAgentMapper to find all skills associated with given agent IDs.
144
- This provides pattern-based skill discovery beyond explicit frontmatter declarations.
145
-
146
- CRITICAL DESIGN DECISION: This function ONLY returns skills for the DEPLOYED agents
147
- provided in agent_ids. It does NOT return skills for all agents in the mapping
148
- configuration (skill_to_agent_mapping.yaml lists 41 agents, but only 33 may be deployed).
186
+ DEPRECATED: This function is deprecated as of Phase 3 refactor.
187
+ Skills are now declared exclusively in agent frontmatter.
149
188
 
150
- GENERIC AGENT HANDLING: The generic "engineer" agent is mapped to 100+ skills in the
151
- configuration because it's designed as a fallback. To prevent over-deployment when
152
- specialized agents exist, we skip "engineer" if specialized agents are present.
189
+ The static skill_to_agent_mapping.yaml is no longer used for skill deployment.
190
+ Each agent must declare its skills in frontmatter or it gets zero skills.
153
191
 
154
- WHY THIS MATTERS:
155
- - skill_to_agent_mapping.yaml lists ALL possible agents (41 total)
156
- - User may only have 33 agents deployed in ~/.claude/agents/
157
- - Without filtering, we'd deploy skills for all 41 agents (over-deployment)
158
- - Solution: Only query skills for DEPLOYED agents (passed in agent_ids)
192
+ This function remains for backward compatibility but is NO LONGER CALLED
193
+ by get_required_skills_from_agents().
159
194
 
160
195
  Args:
161
196
  agent_ids: List of DEPLOYED agent identifiers (e.g., ["python-engineer", "typescript-engineer"])
@@ -163,67 +198,34 @@ def get_skills_from_mapping(agent_ids: List[str]) -> Set[str]:
163
198
 
164
199
  Returns:
165
200
  Set of unique skill names inferred from mapping configuration for DEPLOYED agents only
201
+ NOTE: This is now an empty set as the function is deprecated.
166
202
 
167
203
  Example:
168
- >>> # DEPLOYED agents only (from ~/.claude/agents/)
204
+ >>> # DEPRECATED - use frontmatter instead
169
205
  >>> deployed_agent_ids = ["python-engineer", "typescript-engineer", "qa"]
170
- >>> skills = get_skills_from_mapping(deployed_agent_ids)
171
- >>> print(f"Found {len(skills)} skills for {len(deployed_agent_ids)} deployed agents")
206
+ >>> skills = get_skills_from_mapping(deployed_agent_ids) # Returns empty set
172
207
  """
173
- try:
174
- mapper = SkillToAgentMapper()
175
- all_skills = set()
176
-
177
- # CRITICAL FIX: Skip generic "engineer" agent if specialized agents exist
178
- # The "engineer" agent is mapped to ~107 skills (almost all skills) because
179
- # it's a fallback agent. This causes over-deployment when you have specialized
180
- # agents like "python-engineer", "typescript-engineer", etc.
181
- #
182
- # Solution: Filter out "engineer" from agent_ids if specialized agents exist
183
- specialized_engineers = [
184
- aid for aid in agent_ids if aid.endswith("-engineer") and aid != "engineer"
185
- ]
186
-
187
- # If specialized engineers exist, exclude generic "engineer" from skill mapping
188
- # This prevents deploying 100+ skills when only a subset is needed
189
- agents_to_query = agent_ids
190
- if specialized_engineers and "engineer" in agent_ids:
191
- agents_to_query = [aid for aid in agent_ids if aid != "engineer"]
192
- logger.info(
193
- f"Excluding generic 'engineer' agent from skill mapping "
194
- f"(found {len(specialized_engineers)} specialized engineers: "
195
- f"{', '.join(specialized_engineers[:5])}{'...' if len(specialized_engineers) > 5 else ''})"
196
- )
197
-
198
- # IMPORTANT: Only query skills for DEPLOYED agents (those in agent_ids)
199
- # Do NOT query all agents from skill_to_agent_mapping.yaml (that's 41 agents)
200
- for agent_id in agents_to_query:
201
- agent_skills = mapper.get_skills_for_agent(agent_id)
202
- if agent_skills:
203
- all_skills.update(agent_skills)
204
- logger.debug(f"Mapped {len(agent_skills)} skills to {agent_id}")
205
-
206
- logger.info(
207
- f"Mapped {len(all_skills)} unique skills for {len(agents_to_query)} deployed agents "
208
- f"(out of {len(agent_ids)} total deployed, excluding generic 'engineer' if specialized exist)"
209
- )
210
- return all_skills
211
-
212
- except Exception as e:
213
- logger.warning(f"Failed to load SkillToAgentMapper: {e}")
214
- logger.info("Falling back to frontmatter-only skill discovery")
215
- return set()
208
+ # DEPRECATED: Return empty set
209
+ logger.warning(
210
+ "get_skills_from_mapping() is DEPRECATED and returns empty set. "
211
+ "Skills are now declared in agent frontmatter only. "
212
+ "Update your agents with 'skills:' field in frontmatter."
213
+ )
214
+ return set()
216
215
 
217
216
 
218
217
  def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
219
218
  """Extract all skills referenced by deployed agents.
220
219
 
221
- Combines skills from two sources:
222
- 1. Explicit frontmatter declarations (skills: field in agent .md files)
223
- 2. SkillToAgentMapper inference (pattern-based skill discovery)
220
+ MAJOR CHANGE (Phase 3): Now ONLY uses frontmatter-declared skills.
221
+ The static skill_to_agent_mapping.yaml is DEPRECATED. Each agent must
222
+ declare its skills in frontmatter or it gets zero skills deployed.
224
223
 
225
- This dual-source approach ensures agents get both explicitly declared skills
226
- and skills inferred from their domain/toolchain patterns.
224
+ This change:
225
+ - Eliminates dual-source complexity (frontmatter + mapping)
226
+ - Makes skill requirements explicit per agent
227
+ - Enables per-agent customization via frontmatter
228
+ - Removes dependency on static YAML mapping
227
229
 
228
230
  Args:
229
231
  agents_dir: Path to deployed agents directory (e.g., .claude/agents/)
@@ -244,13 +246,11 @@ def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
244
246
  agent_files = list(agents_dir.glob("*.md"))
245
247
  logger.debug(f"Scanning {len(agent_files)} agent files in {agents_dir}")
246
248
 
247
- # Source 1: Extract skills from frontmatter
249
+ # ONLY use frontmatter skills - no more mapping inference
248
250
  frontmatter_skills = set()
249
- agent_ids = []
250
251
 
251
252
  for agent_file in agent_files:
252
253
  agent_id = agent_file.stem
253
- agent_ids.append(agent_id)
254
254
 
255
255
  frontmatter = parse_agent_frontmatter(agent_file)
256
256
  agent_skills = get_skills_from_agent(frontmatter)
@@ -260,24 +260,23 @@ def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
260
260
  logger.debug(
261
261
  f"Agent {agent_id}: {len(agent_skills)} skills from frontmatter"
262
262
  )
263
+ else:
264
+ logger.debug(f"Agent {agent_id}: No skills declared in frontmatter")
263
265
 
264
- logger.info(f"Found {len(frontmatter_skills)} unique skills from frontmatter")
265
-
266
- # Source 2: Get skills from SkillToAgentMapper
267
- mapped_skills = get_skills_from_mapping(agent_ids)
268
-
269
- # Combine both sources
270
- required_skills = frontmatter_skills | mapped_skills
266
+ logger.info(
267
+ f"Found {len(frontmatter_skills)} unique skills from agent frontmatter "
268
+ f"(static mapping no longer used)"
269
+ )
271
270
 
272
271
  # Normalize skill paths: convert slashes to dashes for compatibility with deployment
273
- # SkillToAgentMapper returns paths like "toolchains/python/frameworks/django"
274
- # but deployment expects "toolchains-python-frameworks-django"
275
- normalized_skills = {skill.replace("/", "-") for skill in required_skills}
272
+ # Some skills may use slash format, normalize to dashes
273
+ normalized_skills = {skill.replace("/", "-") for skill in frontmatter_skills}
276
274
 
277
- logger.info(
278
- f"Combined {len(frontmatter_skills)} frontmatter + {len(mapped_skills)} mapped "
279
- f"= {len(required_skills)} total unique skills (normalized to {len(normalized_skills)})"
280
- )
275
+ if normalized_skills != frontmatter_skills:
276
+ logger.debug(
277
+ f"Normalized {len(frontmatter_skills)} skills to {len(normalized_skills)} "
278
+ "(converted slashes to dashes)"
279
+ )
281
280
 
282
281
  return normalized_skills
283
282
 
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: Brainstorming Ideas Into Designs
3
+ description: Interactive idea refinement using Socratic method to develop fully-formed designs
4
+ when_to_use: when partner describes any feature or project idea, before writing code or implementation plans
5
+ version: 2.2.0
6
+ progressive_disclosure:
7
+ level: 1
8
+ references: []
9
+ note: Already optimal at 75 lines - intentionally compact, no references needed
10
+ ---
11
+
12
+ # Brainstorming Ideas Into Designs
13
+
14
+ ## Overview
15
+
16
+ Transform rough ideas into fully-formed designs through structured questioning and alternative exploration.
17
+
18
+ **Core principle:** Ask questions to understand, explore alternatives, present design incrementally for validation.
19
+
20
+ **Announce at start:** "I'm using the Brainstorming skill to refine your idea into a design."
21
+
22
+ ## The Process
23
+
24
+ ### Phase 1: Understanding
25
+ - Check current project state in working directory
26
+ - Ask ONE question at a time to refine the idea
27
+ - Prefer multiple choice when possible
28
+ - Gather: Purpose, constraints, success criteria
29
+
30
+ ### Phase 2: Exploration
31
+ - Propose 2-3 different approaches
32
+ - For each: Core architecture, trade-offs, complexity assessment
33
+ - Ask your human partner which approach resonates
34
+
35
+ ### Phase 3: Design Presentation
36
+ - Present in 200-300 word sections
37
+ - Cover: Architecture, components, data flow, error handling, testing
38
+ - Ask after each section: "Does this look right so far?"
39
+
40
+ ### Phase 4: Worktree Setup (for implementation)
41
+ When design is approved and implementation will follow:
42
+ - Announce: "I'm using the Using Git Worktrees skill to set up an isolated workspace."
43
+ - Switch to skills/collaboration/using-git-worktrees
44
+ - Follow that skill's process for directory selection, safety verification, and setup
45
+ - Return here when worktree ready
46
+
47
+ ### Phase 5: Planning Handoff
48
+ Ask: "Ready to create the implementation plan?"
49
+
50
+ When your human partner confirms (any affirmative response):
51
+ - Announce: "I'm using the Writing Plans skill to create the implementation plan."
52
+ - Switch to skills/collaboration/writing-plans skill
53
+ - Create detailed plan in the worktree
54
+
55
+ ## When to Revisit Earlier Phases
56
+
57
+ **You can and should go backward when:**
58
+ - Partner reveals new constraint during Phase 2 or 3 → Return to Phase 1 to understand it
59
+ - Validation shows fundamental gap in requirements → Return to Phase 1
60
+ - Partner questions approach during Phase 3 → Return to Phase 2 to explore alternatives
61
+ - Something doesn't make sense → Go back and clarify
62
+
63
+ **Don't force forward linearly** when going backward would give better results.
64
+
65
+ ## Related Skills
66
+
67
+ **During exploration:**
68
+ - When approaches have genuine trade-offs: skills/architecture/preserving-productive-tensions
69
+
70
+ **Before proposing changes to existing code:**
71
+ - Understand why it exists: skills/research/tracing-knowledge-lineages
72
+
73
+ ## Remember
74
+ - One question per message during Phase 1
75
+ - Apply YAGNI ruthlessly
76
+ - Explore 2-3 alternatives before settling
77
+ - Present incrementally, validate as you go
78
+ - Go backward when needed - flexibility > rigid progression
79
+ - Announce skill usage at start