claude-mpm 5.6.31__py3-none-any.whl → 5.6.32__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.6.31
1
+ 5.6.32
File without changes
File without changes
File without changes
@@ -605,40 +605,98 @@ main "$@"
605
605
  # Hook configuration for each event type
606
606
  hook_command = {"type": "command", "command": str(hook_script_path.absolute())}
607
607
 
608
+ def is_our_hook(cmd: dict) -> bool:
609
+ """Check if a hook command belongs to claude-mpm."""
610
+ if cmd.get("type") != "command":
611
+ return False
612
+ command = cmd.get("command", "")
613
+ return "claude-hook-handler.sh" in command or command.endswith(
614
+ "claude-mpm-hook.sh"
615
+ )
616
+
617
+ def merge_hooks_for_event(
618
+ existing_hooks: list, new_hook_command: dict, use_matcher: bool = True
619
+ ) -> list:
620
+ """Merge new hook command into existing hooks without duplication.
621
+
622
+ Args:
623
+ existing_hooks: Current hooks configuration for an event type
624
+ new_hook_command: The claude-mpm hook command to add
625
+ use_matcher: Whether to include matcher: "*" in the config
626
+
627
+ Returns:
628
+ Updated hooks list with our hook merged in
629
+ """
630
+ # Check if our hook already exists in any existing hook config
631
+ our_hook_exists = False
632
+
633
+ for hook_config in existing_hooks:
634
+ if "hooks" in hook_config and isinstance(hook_config["hooks"], list):
635
+ for hook in hook_config["hooks"]:
636
+ if is_our_hook(hook):
637
+ # Update existing hook command path (in case it changed)
638
+ hook["command"] = new_hook_command["command"]
639
+ our_hook_exists = True
640
+ break
641
+ if our_hook_exists:
642
+ break
643
+
644
+ if our_hook_exists:
645
+ # Our hook already exists, just return the updated list
646
+ return existing_hooks
647
+
648
+ # Our hook doesn't exist - need to add it
649
+ # Strategy: Add our hook to the first "*" matcher config, or create new config
650
+ added = False
651
+
652
+ for hook_config in existing_hooks:
653
+ # Check if this config has matcher: "*" (or no matcher for simple events)
654
+ matcher = hook_config.get("matcher")
655
+ if matcher == "*" or (not use_matcher and matcher is None):
656
+ # Add our hook to this config's hooks array
657
+ if "hooks" not in hook_config:
658
+ hook_config["hooks"] = []
659
+ hook_config["hooks"].append(new_hook_command)
660
+ added = True
661
+ break
662
+
663
+ if not added:
664
+ # No suitable config found, create a new one
665
+ if use_matcher:
666
+ new_config = {"matcher": "*", "hooks": [new_hook_command]}
667
+ else:
668
+ new_config = {"hooks": [new_hook_command]}
669
+ existing_hooks.append(new_config)
670
+
671
+ return existing_hooks
672
+
608
673
  # Tool-related events need a matcher string
609
674
  tool_events = ["PreToolUse", "PostToolUse"]
610
675
  for event_type in tool_events:
611
- settings["hooks"][event_type] = [
612
- {
613
- "matcher": "*", # String value to match all tools
614
- "hooks": [hook_command],
615
- }
616
- ]
676
+ existing = settings["hooks"].get(event_type, [])
677
+ settings["hooks"][event_type] = merge_hooks_for_event(
678
+ existing, hook_command, use_matcher=True
679
+ )
617
680
 
618
681
  # Simple events (no subtypes, no matcher needed)
619
682
  simple_events = ["Stop", "SubagentStop", "SubagentStart"]
620
683
  for event_type in simple_events:
621
- settings["hooks"][event_type] = [
622
- {
623
- "hooks": [hook_command],
624
- }
625
- ]
684
+ existing = settings["hooks"].get(event_type, [])
685
+ settings["hooks"][event_type] = merge_hooks_for_event(
686
+ existing, hook_command, use_matcher=False
687
+ )
626
688
 
627
689
  # SessionStart needs matcher for subtypes (startup, resume)
628
- settings["hooks"]["SessionStart"] = [
629
- {
630
- "matcher": "*", # Match all SessionStart subtypes
631
- "hooks": [hook_command],
632
- }
633
- ]
690
+ existing = settings["hooks"].get("SessionStart", [])
691
+ settings["hooks"]["SessionStart"] = merge_hooks_for_event(
692
+ existing, hook_command, use_matcher=True
693
+ )
634
694
 
635
695
  # UserPromptSubmit needs matcher for potential subtypes
636
- settings["hooks"]["UserPromptSubmit"] = [
637
- {
638
- "matcher": "*",
639
- "hooks": [hook_command],
640
- }
641
- ]
696
+ existing = settings["hooks"].get("UserPromptSubmit", [])
697
+ settings["hooks"]["UserPromptSubmit"] = merge_hooks_for_event(
698
+ existing, hook_command, use_matcher=True
699
+ )
642
700
 
643
701
  # Fix statusLine command to handle both output style schemas
644
702
  self._fix_status_line(settings)
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -304,16 +304,77 @@ class HookInstallerService:
304
304
  self.logger.debug("Creating new Claude settings")
305
305
 
306
306
  # Configure hooks
307
- hook_config = {
308
- "matcher": "*",
309
- "hooks": [{"type": "command", "command": hook_script_path}],
310
- }
307
+ new_hook_command = {"type": "command", "command": hook_script_path}
311
308
 
312
309
  # Update settings
313
310
  if "hooks" not in settings:
314
311
  settings["hooks"] = {}
315
312
 
316
- # Add hooks for all event types
313
+ def is_our_hook(cmd: Dict[str, Any]) -> bool:
314
+ """Check if a hook command belongs to claude-mpm."""
315
+ if cmd.get("type") != "command":
316
+ return False
317
+ command = cmd.get("command", "")
318
+ return (
319
+ "hook_wrapper.sh" in command
320
+ or "claude-hook-handler.sh" in command
321
+ or "claude-mpm" in command
322
+ )
323
+
324
+ def merge_hooks_for_event(
325
+ existing_hooks: list, hook_command: Dict[str, Any]
326
+ ) -> list:
327
+ """Merge new hook command into existing hooks without duplication.
328
+
329
+ Args:
330
+ existing_hooks: Current hooks configuration for an event type
331
+ hook_command: The claude-mpm hook command to add
332
+
333
+ Returns:
334
+ Updated hooks list with our hook merged in
335
+ """
336
+ # Check if our hook already exists in any existing hook config
337
+ our_hook_exists = False
338
+
339
+ for hook_config in existing_hooks:
340
+ if "hooks" in hook_config and isinstance(
341
+ hook_config["hooks"], list
342
+ ):
343
+ for hook in hook_config["hooks"]:
344
+ if is_our_hook(hook):
345
+ # Update existing hook command path (in case it changed)
346
+ hook["command"] = hook_command["command"]
347
+ our_hook_exists = True
348
+ break
349
+ if our_hook_exists:
350
+ break
351
+
352
+ if our_hook_exists:
353
+ # Our hook already exists, just return the updated list
354
+ return existing_hooks
355
+
356
+ # Our hook doesn't exist - need to add it
357
+ # Strategy: Add our hook to the first "*" matcher config, or create new
358
+ added = False
359
+
360
+ for hook_config in existing_hooks:
361
+ # Check if this config has matcher: "*"
362
+ if hook_config.get("matcher") == "*":
363
+ # Add our hook to this config's hooks array
364
+ if "hooks" not in hook_config:
365
+ hook_config["hooks"] = []
366
+ hook_config["hooks"].append(hook_command)
367
+ added = True
368
+ break
369
+
370
+ if not added:
371
+ # No suitable config found, create a new one
372
+ new_config = {"matcher": "*", "hooks": [hook_command]}
373
+ existing_hooks.append(new_config)
374
+
375
+ return existing_hooks
376
+
377
+ # Add hooks for all event types - MERGE instead of overwrite
317
378
  for event_type in [
318
379
  "UserPromptSubmit",
319
380
  "PreToolUse",
@@ -321,7 +382,10 @@ class HookInstallerService:
321
382
  "Stop",
322
383
  "SubagentStop",
323
384
  ]:
324
- settings["hooks"][event_type] = [hook_config]
385
+ existing = settings["hooks"].get(event_type, [])
386
+ settings["hooks"][event_type] = merge_hooks_for_event(
387
+ existing, new_hook_command
388
+ )
325
389
 
326
390
  # Write settings
327
391
  with self.settings_file.open("w") as f:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 5.6.31
3
+ Version: 5.6.32
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=qA_UH0QMgAvTCzfuWWxESBiXsP0lh8bSznuGUwuOEl8,7
2
+ claude_mpm/VERSION,sha256=dAg_-LZ5hKzApBj_BHyWt6jpEC7yRMezwMk3MwtJm40,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=pz3lTrZZR5HhV3eZzYtIbtBwWo7iM6pkBHP_ixxmI6Y,6827
@@ -432,7 +432,7 @@ claude_mpm/hooks/claude_hooks/correlation_manager.py,sha256=3n-RxzqE8egG4max_Ncp
432
432
  claude_mpm/hooks/claude_hooks/event_handlers.py,sha256=ztkKTr5xFAY-K5gxhsXFtR_4tir3Cjx2l4auSYbJErU,46745
433
433
  claude_mpm/hooks/claude_hooks/hook_handler.py,sha256=UbBypLK1xhm6NdBBLLjqlsjLGWg1GgW-XSfeR7gLAOc,28242
434
434
  claude_mpm/hooks/claude_hooks/hook_wrapper.sh,sha256=XYkdYtcM0nfnwYvMdyIFCasr80ry3uI5-fLYsLtDGw4,2214
435
- claude_mpm/hooks/claude_hooks/installer.py,sha256=Od_xgLaqL3ZEerRrCiRuM5LiTKVZLwjYHI-fMozPBI8,35179
435
+ claude_mpm/hooks/claude_hooks/installer.py,sha256=SvIgxRMocQxnqNF3ZQfKH8zA-1b4lpiCA4vCI0vWOZI,38065
436
436
  claude_mpm/hooks/claude_hooks/memory_integration.py,sha256=YOMD4Ah003uMh7A454w8ngLmKw8RUAEIHpEj-FRk3TI,10759
437
437
  claude_mpm/hooks/claude_hooks/response_tracking.py,sha256=1KOGC19rYRNYbc1Tfe7FAP6AtvgOMSM5uEPxMi2N6-c,16323
438
438
  claude_mpm/hooks/claude_hooks/tool_analysis.py,sha256=3_o2PP9D7wEMwLriCtIBOw0cj2fSZfepN7lI4P1meSQ,7862
@@ -483,7 +483,7 @@ claude_mpm/services/delegation_detector.py,sha256=ZpElqjhTbuEeeTjTMUsl-G1lHMJ9m1
483
483
  claude_mpm/services/event_aggregator.py,sha256=V_5Wln1RzozLMDZawIPl5gSjIN5KHniNPaaSP11Lihc,20251
484
484
  claude_mpm/services/event_log.py,sha256=pMKc8p2lXRoRi_cvVxaU1uNuUCNrGc0EXqBv8TeueyI,10043
485
485
  claude_mpm/services/exceptions.py,sha256=5lVZETr_6-xk0ItH7BTfYUiX5RlckS1e8ah_UalYG9c,26475
486
- claude_mpm/services/hook_installer_service.py,sha256=2Oioyp3LOY4Tra2hNMd_9erW2RxWA7j33ybIwKXsTmk,20049
486
+ claude_mpm/services/hook_installer_service.py,sha256=AFN5hXfj0oz-pzPNaPRUOAqWFNF9lIZE3i2vNTduYCE,22916
487
487
  claude_mpm/services/hook_service.py,sha256=I6JILbackBsdvrDNQ9TeGSB7XNqozNRP26T4E9_ROtU,15693
488
488
  claude_mpm/services/mcp_config_manager.py,sha256=pQcu5g3lHo082TMX0RDgnfspnvW8huiKysCnFGOD54A,57792
489
489
  claude_mpm/services/mcp_service_verifier.py,sha256=C2DhHY9R4j91WQbe1XSpfYeHjxHg2UyiJ1VQsBgjnlc,25808
@@ -1102,10 +1102,10 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
1102
1102
  claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
1103
1103
  claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
1104
1104
  claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
1105
- claude_mpm-5.6.31.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
1106
- claude_mpm-5.6.31.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
1107
- claude_mpm-5.6.31.dist-info/METADATA,sha256=9AEOst6iPDmwxY5OD3hWc1wxmn8Az6V8sO3De5zK7M8,15245
1108
- claude_mpm-5.6.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1109
- claude_mpm-5.6.31.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
1110
- claude_mpm-5.6.31.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
1111
- claude_mpm-5.6.31.dist-info/RECORD,,
1105
+ claude_mpm-5.6.32.dist-info/licenses/LICENSE,sha256=ca3y_Rk4aPrbF6f62z8Ht5MJM9OAvbGlHvEDcj9vUQ4,3867
1106
+ claude_mpm-5.6.32.dist-info/licenses/LICENSE-FAQ.md,sha256=TxfEkXVCK98RzDOer09puc7JVCP_q_bN4dHtZKHCMcM,5104
1107
+ claude_mpm-5.6.32.dist-info/METADATA,sha256=hRiW5VmkSFqGVVORVStb3BZ5YCGSa2LFW50eFGy3jSY,15245
1108
+ claude_mpm-5.6.32.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1109
+ claude_mpm-5.6.32.dist-info/entry_points.txt,sha256=n-Uk4vwHPpuvu-g_I7-GHORzTnN_m6iyOsoLveKKD0E,228
1110
+ claude_mpm-5.6.32.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
1111
+ claude_mpm-5.6.32.dist-info/RECORD,,