claude-mpm 5.4.54__py3-none-any.whl → 5.4.56__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
claude_mpm/VERSION CHANGED
@@ -1 +1 @@
1
- 5.4.54
1
+ 5.4.56
claude_mpm/cli/startup.py CHANGED
@@ -990,160 +990,188 @@ def sync_remote_skills_on_startup():
990
990
 
991
991
  # Phase 2: Scan agents and save to configuration.yaml
992
992
  # This step populates configuration.yaml with agent-referenced skills
993
- if results["synced_count"] > 0:
994
- agents_dir = Path.cwd() / ".claude" / "agents"
995
-
996
- # Scan agents for skill requirements
997
- agent_skills = get_required_skills_from_agents(agents_dir)
998
-
999
- # Save to project-level configuration.yaml
1000
- project_config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
1001
- save_agent_skills_to_config(list(agent_skills), project_config_path)
1002
-
1003
- # Phase 3: Resolve which skills to deploy (user_defined or agent_referenced)
1004
- skills_to_deploy, skill_source = get_skills_to_deploy(project_config_path)
1005
-
1006
- # Phase 4: Apply profile filtering if active
1007
- if active_profile and profile_manager.active_profile:
1008
- # Filter skills based on profile
1009
- if skills_to_deploy:
1010
- # Filter the resolved skill list
1011
- original_count = len(skills_to_deploy)
1012
- filtered_skills = [
1013
- skill
1014
- for skill in skills_to_deploy
1015
- if profile_manager.is_skill_enabled(skill)
1016
- ]
1017
- filtered_count = original_count - len(filtered_skills)
1018
-
1019
- # SAFEGUARD: Warn if all skills were filtered out (misconfiguration)
1020
- if not filtered_skills and original_count > 0:
1021
- logger.warning(
1022
- f"Profile '{active_profile}' filtered ALL {original_count} skills. "
1023
- f"This may indicate a naming mismatch in the profile."
1024
- )
1025
- elif filtered_count > 0:
1026
- logger.info(
1027
- f"Profile '{active_profile}' filtered {filtered_count} skills "
1028
- f"({len(filtered_skills)} remaining)"
1029
- )
993
+ # CRITICAL: Always scan agents to populate agent_referenced, even when using cached skills.
994
+ # Without this, skill_filter=None causes ALL skills to deploy and NO cleanup to run.
995
+ agents_dir = Path.cwd() / ".claude" / "agents"
996
+
997
+ # Scan agents for skill requirements (ALWAYS run to ensure cleanup works)
998
+ agent_skills = get_required_skills_from_agents(agents_dir)
999
+ logger.info(
1000
+ f"Agent scan found {len(agent_skills)} unique skills across deployed agents"
1001
+ )
1030
1002
 
1031
- skills_to_deploy = filtered_skills
1032
- skill_source = f"{skill_source} + profile filtered"
1033
- else:
1034
- # No explicit skill list - filter from all available
1035
- all_skills = manager.get_all_skills()
1036
- filtered_skills = [
1037
- skill["name"]
1038
- for skill in all_skills
1039
- if profile_manager.is_skill_enabled(skill["name"])
1040
- ]
1041
- skills_to_deploy = filtered_skills
1042
- skill_source = "profile filtered"
1043
- logger.info(
1044
- f"Profile '{active_profile}': "
1045
- f"{len(filtered_skills)} skills enabled from {len(all_skills)} available"
1046
- )
1003
+ # Save to project-level configuration.yaml
1004
+ project_config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
1005
+ save_agent_skills_to_config(list(agent_skills), project_config_path)
1006
+ logger.debug(
1007
+ f"Saved {len(agent_skills)} agent-referenced skills to {project_config_path}"
1008
+ )
1047
1009
 
1048
- # Get all skills to determine counts
1049
- all_skills = manager.get_all_skills()
1050
- total_skill_count = len(all_skills)
1010
+ # Phase 3: Resolve which skills to deploy (user_defined or agent_referenced)
1011
+ skills_to_deploy, skill_source = get_skills_to_deploy(project_config_path)
1051
1012
 
1052
- # Determine skill count based on resolution
1053
- skill_count = (
1054
- len(skills_to_deploy) if skills_to_deploy else total_skill_count
1013
+ # CRITICAL DEBUG: Log deployment resolution to diagnose cleanup issues
1014
+ if skills_to_deploy:
1015
+ logger.info(
1016
+ f"Resolved {len(skills_to_deploy)} skills from {skill_source} (cleanup will run)"
1017
+ )
1018
+ else:
1019
+ logger.warning(
1020
+ f"No skills resolved from {skill_source} - will deploy ALL skills WITHOUT cleanup! "
1021
+ f"This may indicate agent_referenced is empty in configuration.yaml."
1055
1022
  )
1056
1023
 
1057
- if skill_count > 0:
1058
- # Deploy skills with resolved filter
1059
- # Deploy to BOTH project directory (for local dev) AND global directory (for Claude Code)
1024
+ # Phase 4: Apply profile filtering if active
1025
+ if active_profile and profile_manager.active_profile:
1026
+ # Filter skills based on profile
1027
+ if skills_to_deploy:
1028
+ # Filter the resolved skill list
1029
+ original_count = len(skills_to_deploy)
1030
+ filtered_skills = [
1031
+ skill
1032
+ for skill in skills_to_deploy
1033
+ if profile_manager.is_skill_enabled(skill)
1034
+ ]
1035
+ filtered_count = original_count - len(filtered_skills)
1036
+
1037
+ # SAFEGUARD: Warn if all skills were filtered out (misconfiguration)
1038
+ if not filtered_skills and original_count > 0:
1039
+ logger.warning(
1040
+ f"Profile '{active_profile}' filtered ALL {original_count} skills. "
1041
+ f"This may indicate a naming mismatch in the profile."
1042
+ )
1043
+ elif filtered_count > 0:
1044
+ logger.info(
1045
+ f"Profile '{active_profile}' filtered {filtered_count} skills "
1046
+ f"({len(filtered_skills)} remaining)"
1047
+ )
1060
1048
 
1061
- # 1. Deploy to project-local directory
1062
- deployment_result = manager.deploy_skills(
1063
- target_dir=Path.cwd() / ".claude" / "skills",
1064
- force=False,
1065
- skill_filter=set(skills_to_deploy) if skills_to_deploy else None,
1049
+ skills_to_deploy = filtered_skills
1050
+ skill_source = f"{skill_source} + profile filtered"
1051
+ else:
1052
+ # No explicit skill list - filter from all available
1053
+ all_skills = manager.get_all_skills()
1054
+ filtered_skills = [
1055
+ skill["name"]
1056
+ for skill in all_skills
1057
+ if profile_manager.is_skill_enabled(skill["name"])
1058
+ ]
1059
+ skills_to_deploy = filtered_skills
1060
+ skill_source = "profile filtered"
1061
+ logger.info(
1062
+ f"Profile '{active_profile}': "
1063
+ f"{len(filtered_skills)} skills enabled from {len(all_skills)} available"
1066
1064
  )
1067
1065
 
1068
- # 2. Deploy to global directory (this is where Claude Code reads from)
1069
- # Also cleans up orphaned skills via _cleanup_unfiltered_skills()
1070
- manager.deploy_skills(
1071
- target_dir=Path.home() / ".claude" / "skills",
1072
- force=False,
1073
- skill_filter=set(skills_to_deploy) if skills_to_deploy else None,
1074
- )
1066
+ # Get all skills to determine counts
1067
+ all_skills = manager.get_all_skills()
1068
+ total_skill_count = len(all_skills)
1075
1069
 
1076
- # Get actual counts from deployment result (use project-local for display)
1077
- deployed = deployment_result.get("deployed_count", 0)
1078
- skipped = deployment_result.get("skipped_count", 0)
1079
- filtered = deployment_result.get("filtered_count", 0)
1080
- total_available = deployed + skipped
1070
+ # Determine skill count based on resolution
1071
+ skill_count = (
1072
+ len(skills_to_deploy) if skills_to_deploy else total_skill_count
1073
+ )
1081
1074
 
1082
- # Only show progress bar if there are skills to deploy
1083
- if total_available > 0:
1084
- deploy_progress = ProgressBar(
1085
- total=total_available,
1086
- prefix="Deploying skill directories",
1087
- show_percentage=True,
1088
- show_counter=True,
1089
- )
1090
- # Update progress bar to completion
1091
- deploy_progress.update(total_available)
1092
- else:
1093
- # No skills to deploy - create dummy progress for message only
1094
- deploy_progress = ProgressBar(
1095
- total=1,
1096
- prefix="Deploying skill directories",
1097
- show_percentage=False,
1098
- show_counter=False,
1099
- )
1100
- deploy_progress.update(1)
1075
+ if skill_count > 0:
1076
+ # Deploy skills with resolved filter
1077
+ # Deploy ONLY to project directory (not user-level)
1078
+ # DESIGN DECISION: Project-level deployment keeps skills isolated per project,
1079
+ # avoiding pollution of user's global ~/.claude/skills/ directory.
1080
+
1081
+ # Deploy to project-local directory with cleanup
1082
+ deployment_result = manager.deploy_skills(
1083
+ target_dir=Path.cwd() / ".claude" / "skills",
1084
+ force=False,
1085
+ skill_filter=set(skills_to_deploy) if skills_to_deploy else None,
1086
+ )
1101
1087
 
1102
- # Show total available skills (deployed + already existing)
1103
- # Include source indication (user_defined vs agent_referenced)
1104
- # Note: total_skill_count is from cache, total_available is what's deployed/needed
1105
- source_label = (
1106
- "user override" if skill_source == "user_defined" else "from agents"
1088
+ # REMOVED: User-level deployment (lines 1068-1074)
1089
+ # Reason: Skills should be project-specific, not user-global.
1090
+ # Claude Code can read from project-level .claude/skills/ directory.
1091
+
1092
+ # Get actual counts from deployment result (use project-local for display)
1093
+ deployed = deployment_result.get("deployed_count", 0)
1094
+ skipped = deployment_result.get("skipped_count", 0)
1095
+ filtered = deployment_result.get("filtered_count", 0)
1096
+ removed = deployment_result.get("removed_count", 0)
1097
+ total_available = deployed + skipped
1098
+
1099
+ # Only show progress bar if there are skills to deploy
1100
+ if total_available > 0:
1101
+ deploy_progress = ProgressBar(
1102
+ total=total_available,
1103
+ prefix="Deploying skill directories",
1104
+ show_percentage=True,
1105
+ show_counter=True,
1107
1106
  )
1107
+ # Update progress bar to completion
1108
+ deploy_progress.update(total_available)
1109
+ else:
1110
+ # No skills to deploy - create dummy progress for message only
1111
+ deploy_progress = ProgressBar(
1112
+ total=1,
1113
+ prefix="Deploying skill directories",
1114
+ show_percentage=False,
1115
+ show_counter=False,
1116
+ )
1117
+ deploy_progress.update(1)
1118
+
1119
+ # Show total available skills (deployed + already existing)
1120
+ # Include source indication (user_defined vs agent_referenced)
1121
+ # Note: total_skill_count is from cache, total_available is what's deployed/needed
1122
+ source_label = (
1123
+ "user override" if skill_source == "user_defined" else "from agents"
1124
+ )
1108
1125
 
1126
+ # Build finish message with cleanup info
1127
+ if deployed > 0 or removed > 0:
1128
+ parts = []
1109
1129
  if deployed > 0:
1110
- if filtered > 0:
1111
- deploy_progress.finish(
1112
- f"Complete: {deployed} new, {skipped} unchanged "
1113
- f"({total_available} {source_label}, {filtered} files in cache)"
1114
- )
1115
- else:
1116
- deploy_progress.finish(
1117
- f"Complete: {deployed} new, {skipped} unchanged "
1118
- f"({total_available} skills {source_label} from {total_skill_count} files in cache)"
1119
- )
1120
- elif filtered > 0:
1121
- # Skills filtered means agents require fewer skills than available
1130
+ parts.append(f"{deployed} new")
1131
+ if skipped > 0:
1132
+ parts.append(f"{skipped} unchanged")
1133
+ if removed > 0:
1134
+ parts.append(f"{removed} removed")
1135
+
1136
+ status = ", ".join(parts)
1137
+
1138
+ if filtered > 0:
1122
1139
  deploy_progress.finish(
1123
- f"No skills needed ({source_label}, {total_skill_count} files in cache)"
1140
+ f"Complete: {status} ({total_available} {source_label}, {filtered} files in cache)"
1124
1141
  )
1125
1142
  else:
1126
1143
  deploy_progress.finish(
1127
- f"Complete: {total_available} skills {source_label} "
1128
- f"({total_skill_count} files in cache)"
1144
+ f"Complete: {status} ({total_available} skills {source_label} from {total_skill_count} files in cache)"
1129
1145
  )
1146
+ elif filtered > 0:
1147
+ # Skills filtered means agents require fewer skills than available
1148
+ deploy_progress.finish(
1149
+ f"No skills needed ({source_label}, {total_skill_count} files in cache)"
1150
+ )
1151
+ else:
1152
+ # No changes - all skills already deployed
1153
+ msg = f"Complete: {total_available} skills {source_label}"
1154
+ if removed > 0:
1155
+ msg += f", {removed} removed"
1156
+ msg += f" ({total_skill_count} files in cache)"
1157
+ deploy_progress.finish(msg)
1158
+
1159
+ # Log deployment errors if any
1160
+ from ..core.logger import get_logger
1130
1161
 
1131
- # Log deployment errors if any
1132
- from ..core.logger import get_logger
1133
-
1134
- logger = get_logger("cli")
1162
+ logger = get_logger("cli")
1135
1163
 
1136
- errors = deployment_result.get("errors", [])
1137
- if errors:
1138
- logger.warning(
1139
- f"Skill deployment completed with {len(errors)} errors: {errors}"
1140
- )
1164
+ errors = deployment_result.get("errors", [])
1165
+ if errors:
1166
+ logger.warning(
1167
+ f"Skill deployment completed with {len(errors)} errors: {errors}"
1168
+ )
1141
1169
 
1142
- # Log sync errors if any
1143
- if results["failed_count"] > 0:
1144
- logger.warning(
1145
- f"Skill sync completed with {results['failed_count']} failures"
1146
- )
1170
+ # Log sync errors if any
1171
+ if results["failed_count"] > 0:
1172
+ logger.warning(
1173
+ f"Skill sync completed with {results['failed_count']} failures"
1174
+ )
1147
1175
 
1148
1176
  except Exception as e:
1149
1177
  # Non-critical - log but don't fail startup
@@ -1243,61 +1271,64 @@ def show_skill_summary():
1243
1271
  Display skill availability summary on startup.
1244
1272
 
1245
1273
  WHY: Users should see at a glance how many skills are deployed and available
1246
- from collections, similar to the agent summary.
1274
+ from cache, similar to the agent summary showing "X deployed / Y cached".
1275
+
1276
+ DESIGN DECISION: Fast, non-blocking check that counts skills from:
1277
+ - Deployed skills: PROJECT-level .claude/skills/ directory
1278
+ - Cached skills: ~/.claude-mpm/cache/skills/ directory (from remote sources)
1247
1279
 
1248
- DESIGN DECISION: Fast, non-blocking check that counts skills from deployment
1249
- directory and collection repos. Shows "X installed (Y available)" format.
1280
+ Shows format: "✓ Skills: X deployed / Y cached"
1250
1281
  Failures are silent to avoid blocking startup.
1251
1282
  """
1252
1283
  try:
1253
1284
  from pathlib import Path
1254
1285
 
1255
- # Count deployed skills (installed)
1256
- skills_dir = Path.home() / ".claude" / "skills"
1257
- installed_count = 0
1258
- if skills_dir.exists():
1286
+ # Count deployed skills (PROJECT-level, not user-level)
1287
+ project_skills_dir = Path.cwd() / ".claude" / "skills"
1288
+ deployed_count = 0
1289
+ if project_skills_dir.exists():
1259
1290
  # Count directories with SKILL.md (excludes collection repos)
1260
1291
  # Exclude collection directories (obra-superpowers, etc.)
1261
1292
  skill_dirs = [
1262
1293
  d
1263
- for d in skills_dir.iterdir()
1294
+ for d in project_skills_dir.iterdir()
1264
1295
  if d.is_dir()
1265
1296
  and (d / "SKILL.md").exists()
1266
1297
  and not (d / ".git").exists() # Exclude collection repos
1267
1298
  ]
1268
- installed_count = len(skill_dirs)
1299
+ deployed_count = len(skill_dirs)
1269
1300
 
1270
- # Count available skills in collections
1271
- available_count = 0
1272
- if skills_dir.exists():
1273
- # Scan all collection directories (those with .git)
1274
- for collection_dir in skills_dir.iterdir():
1275
- if (
1276
- not collection_dir.is_dir()
1277
- or not (collection_dir / ".git").exists()
1278
- ):
1301
+ # Count cached skills (from remote sources, not deployed yet)
1302
+ # This matches the agent summary pattern: deployed vs cached
1303
+ cache_dir = Path.home() / ".claude-mpm" / "cache" / "skills"
1304
+ cached_count = 0
1305
+ if cache_dir.exists():
1306
+ # Scan all repository directories in cache
1307
+ # Cache structure: ~/.claude-mpm/cache/skills/{owner}/{repo}/...
1308
+ for repo_dir in cache_dir.rglob("*"):
1309
+ if not repo_dir.is_dir():
1279
1310
  continue
1280
1311
 
1281
- # Count skill directories in this collection
1312
+ # Count skill directories (those with SKILL.md)
1282
1313
  # Skills can be nested in: skills/category/skill-name/SKILL.md
1283
1314
  # or in flat structure: skill-name/SKILL.md
1284
- for root, dirs, files in os.walk(collection_dir):
1315
+ for root, dirs, files in os.walk(repo_dir):
1285
1316
  if "SKILL.md" in files:
1286
- # Exclude build artifacts and hidden directories (within the collection)
1287
- # Get relative path from collection_dir to avoid excluding based on .claude parent
1317
+ # Exclude build artifacts and hidden directories
1288
1318
  root_path = Path(root)
1289
- relative_parts = root_path.relative_to(collection_dir).parts
1290
1319
  if not any(
1291
1320
  part.startswith(".")
1292
1321
  or part in ["dist", "build", "__pycache__"]
1293
- for part in relative_parts
1322
+ for part in root_path.parts
1294
1323
  ):
1295
- available_count += 1
1324
+ cached_count += 1
1296
1325
 
1297
- # Display summary if we have skills
1298
- if installed_count > 0 or available_count > 0:
1326
+ # Display summary using agent summary format: "X deployed / Y cached"
1327
+ # Only show non-deployed cached skills (subtract deployed from cached)
1328
+ non_deployed_cached = max(0, cached_count - deployed_count)
1329
+ if deployed_count > 0 or non_deployed_cached > 0:
1299
1330
  print(
1300
- f"✓ Skills: {installed_count} installed ({available_count} available)",
1331
+ f"✓ Skills: {deployed_count} deployed / {non_deployed_cached} cached",
1301
1332
  flush=True,
1302
1333
  )
1303
1334
 
@@ -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,12 @@ 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
+ + (f" (and {len(removed_skills) - 10} more)" if len(removed_skills) > 10 else "")
1090
1099
  )
1091
1100
 
1092
1101
  self.logger.info(
@@ -1130,6 +1139,7 @@ class GitSkillSourceManager:
1130
1139
  self.logger.info(
1131
1140
  f"Deployment complete: {len(deployed)} deployed, "
1132
1141
  f"{len(skipped)} skipped, {len(errors)} errors"
1142
+ + (f", {len(removed_skills)} removed" if removed_skills else "")
1133
1143
  )
1134
1144
 
1135
1145
  return {
@@ -1140,6 +1150,8 @@ class GitSkillSourceManager:
1140
1150
  "skipped_skills": skipped,
1141
1151
  "errors": errors,
1142
1152
  "filtered_count": filtered_count,
1153
+ "removed_count": len(removed_skills),
1154
+ "removed_skills": removed_skills,
1143
1155
  }
1144
1156
 
1145
1157
  def _cleanup_unfiltered_skills(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 5.4.54
3
+ Version: 5.4.56
4
4
  Summary: Claude Multi-Agent Project Manager - Orchestrate Claude with agent delegation and ticket tracking
5
5
  Author-email: Bob Matsuoka <bob@matsuoka.com>
6
6
  Maintainer: Claude MPM Team
@@ -1,5 +1,5 @@
1
1
  claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
2
- claude_mpm/VERSION,sha256=R5eO2fFErMMpKeWmFcXMMGMeukdVhYJo3blU2lvfrr8,7
2
+ claude_mpm/VERSION,sha256=nwC2X1qTiadu5lECbdz8Av1yO5Df8yo2mz7YehUJ0yI,7
3
3
  claude_mpm/__init__.py,sha256=AGfh00BHKvLYD-UVFw7qbKtl7NMRIzRXOWw7vEuZ-h4,2214
4
4
  claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
5
5
  claude_mpm/constants.py,sha256=CU7v8LZT-cFCNNLZU4dpaMD-4c3ib16v8fVE620wUjk,6761
@@ -41,7 +41,7 @@ claude_mpm/cli/chrome_devtools_installer.py,sha256=efA_ZX1iR3oaJi3222079BQw6DEG8
41
41
  claude_mpm/cli/executor.py,sha256=cetKiY2YS4XETUBXmfySdHYloI_M_lBJUFViRQ9TcS4,10544
42
42
  claude_mpm/cli/helpers.py,sha256=CypEhw0tbNH6_GzVTaQdi4w7ThCWO43Ep92YbJzPR4I,3638
43
43
  claude_mpm/cli/parser.py,sha256=Vqx9n-6Xo1uNhXR4rThmgWpZXTr0nOtkgDf3oMS9b0g,5855
44
- claude_mpm/cli/startup.py,sha256=wFJDw4uKiweP2zwOmpvtrSDcJ-5MTUc4RoY246ryZAc,71868
44
+ claude_mpm/cli/startup.py,sha256=3NuNrGG7keeTbC5YNcmgEVgtFQlIz9ui6XNy-1YEF7c,72965
45
45
  claude_mpm/cli/startup_display.py,sha256=R_QIamjfdaY5o_VxpIeymyYj1Qde2B9hPXy1P-KmUKI,14972
46
46
  claude_mpm/cli/startup_logging.py,sha256=RTuyd6CbhiFQz7Z07LDDhK_ZAnZfuJ9B0NghVSntHFI,29390
47
47
  claude_mpm/cli/utils.py,sha256=FSMPftBZM8MeUyTtiB63Lz7oFOgkzwTetQs58RbRb_Q,8785
@@ -339,6 +339,7 @@ claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc,sha256=EGpgXq
339
339
  claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc,sha256=SQX5iiP9bQZkLL-cj_2tlGH7lpAzarO0mYal7btj3tc,3521
340
340
  claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc,sha256=T9FMRyRjvHTRJm0LXosba7MezdUVw6I-nt_KP--LTwA,35923
341
341
  claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc,sha256=AsvVXkge1Pio3jgnS-zNbPt9brySB8ZeVPSn7VvuKjs,29654
342
+ claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc,sha256=9mpAKY4gNcbU5VvZ5tGbf2UM0uIEWdreKSUvVr_BKcM,33917
342
343
  claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc,sha256=YbwauQDKSGvXkT1972faalJLuxwyvq328DYQhkCnel0,10513
343
344
  claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc,sha256=0xWsBZ63F-akLopSiRi36-hmhh1v9R5aKFBM0z93Jd0,16730
344
345
  claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc,sha256=ZjcNfNY5Ht6FhalPeh7M7OzMffcey5iF4AVjDDg9kak,10694
@@ -700,7 +701,7 @@ claude_mpm/services/shared/lifecycle_service_base.py,sha256=YJZHs2sUrnIsbHHjrd8l
700
701
  claude_mpm/services/shared/manager_base.py,sha256=kmjhpVqgfYC1N4YQnPAilCfdrSpAh9Qz7wcQ602L4x4,9296
701
702
  claude_mpm/services/shared/service_factory.py,sha256=9yvnD62urrNQCGmtk_3OcR5tVUCnoS6wHkaI5PK34mg,9891
702
703
  claude_mpm/services/skills/__init__.py,sha256=X1fPRCGZjteLd35HlhWv2M6tAJ_WbYrEv84kbaqBAiU,742
703
- claude_mpm/services/skills/git_skill_source_manager.py,sha256=YztvRMqayar2MLQElfyMX3XNCi9VwMrzlYwIir7LXQ0,50713
704
+ claude_mpm/services/skills/git_skill_source_manager.py,sha256=H0MEug2lCix6RHqF4nVt3-Olfe9DM9bKlm_Bw9OJC4g,51529
704
705
  claude_mpm/services/skills/selective_skill_deployer.py,sha256=7iTtPYSSO33rLCeZEZ_ZNNa369rhKsYCiqL0QcpMVbg,26478
705
706
  claude_mpm/services/skills/skill_discovery_service.py,sha256=riy0PTnJS8e5R2ai8y1KPhBIR7SxlYIa9bnI9YccRMQ,20247
706
707
  claude_mpm/services/skills/skill_to_agent_mapper.py,sha256=4PRwcSDSNGS55lg4t-VmBK2ottE_cGFq1zsvjiumAlI,14847
@@ -858,10 +859,10 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
858
859
  claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
859
860
  claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
860
861
  claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
861
- claude_mpm-5.4.54.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
862
- claude_mpm-5.4.54.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
863
- claude_mpm-5.4.54.dist-info/METADATA,sha256=uw_bVb7Ez0wVR0_RyFgwhLXoPlMQxTgmeFPnvAKANJc,37997
864
- claude_mpm-5.4.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
865
- claude_mpm-5.4.54.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
866
- claude_mpm-5.4.54.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
867
- claude_mpm-5.4.54.dist-info/RECORD,,
862
+ claude_mpm-5.4.56.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
863
+ claude_mpm-5.4.56.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
864
+ claude_mpm-5.4.56.dist-info/METADATA,sha256=TNxOdaTaMPQctoM85R8jZl7eixue-OGtgCrzj13lpCk,37997
865
+ claude_mpm-5.4.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
866
+ claude_mpm-5.4.56.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
867
+ claude_mpm-5.4.56.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
868
+ claude_mpm-5.4.56.dist-info/RECORD,,