claude-mpm 5.0.2__py3-none-any.whl → 5.1.9__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.

Files changed (76) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  3. claude_mpm/agents/PM_INSTRUCTIONS.md +1176 -909
  4. claude_mpm/agents/base_agent_loader.py +10 -35
  5. claude_mpm/agents/frontmatter_validator.py +68 -0
  6. claude_mpm/agents/templates/circuit-breakers.md +293 -44
  7. claude_mpm/cli/__init__.py +0 -1
  8. claude_mpm/cli/commands/__init__.py +2 -0
  9. claude_mpm/cli/commands/agent_state_manager.py +64 -11
  10. claude_mpm/cli/commands/agents.py +446 -25
  11. claude_mpm/cli/commands/auto_configure.py +535 -233
  12. claude_mpm/cli/commands/configure.py +545 -89
  13. claude_mpm/cli/commands/postmortem.py +401 -0
  14. claude_mpm/cli/commands/run.py +1 -39
  15. claude_mpm/cli/commands/skills.py +322 -19
  16. claude_mpm/cli/interactive/agent_wizard.py +302 -195
  17. claude_mpm/cli/parsers/agents_parser.py +137 -0
  18. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  19. claude_mpm/cli/parsers/base_parser.py +4 -0
  20. claude_mpm/cli/parsers/skills_parser.py +7 -0
  21. claude_mpm/cli/startup.py +73 -32
  22. claude_mpm/commands/mpm-agents-auto-configure.md +2 -2
  23. claude_mpm/commands/mpm-agents-list.md +2 -2
  24. claude_mpm/commands/mpm-config-view.md +2 -2
  25. claude_mpm/commands/mpm-help.md +3 -0
  26. claude_mpm/commands/mpm-postmortem.md +123 -0
  27. claude_mpm/commands/mpm-session-resume.md +2 -2
  28. claude_mpm/commands/mpm-ticket-organize.md +2 -2
  29. claude_mpm/commands/mpm-ticket-view.md +2 -2
  30. claude_mpm/config/agent_presets.py +312 -82
  31. claude_mpm/config/skill_presets.py +392 -0
  32. claude_mpm/constants.py +1 -0
  33. claude_mpm/core/claude_runner.py +2 -25
  34. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  35. claude_mpm/core/interactive_session.py +19 -5
  36. claude_mpm/core/oneshot_session.py +16 -4
  37. claude_mpm/core/output_style_manager.py +173 -43
  38. claude_mpm/core/protocols/__init__.py +23 -0
  39. claude_mpm/core/protocols/runner_protocol.py +103 -0
  40. claude_mpm/core/protocols/session_protocol.py +131 -0
  41. claude_mpm/core/shared/singleton_manager.py +11 -4
  42. claude_mpm/core/system_context.py +38 -0
  43. claude_mpm/core/unified_agent_registry.py +129 -1
  44. claude_mpm/core/unified_config.py +22 -0
  45. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  46. claude_mpm/models/agent_definition.py +7 -0
  47. claude_mpm/services/agents/cache_git_manager.py +621 -0
  48. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +110 -3
  49. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +195 -1
  50. claude_mpm/services/agents/sources/git_source_sync_service.py +37 -5
  51. claude_mpm/services/analysis/__init__.py +25 -0
  52. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  53. claude_mpm/services/analysis/postmortem_service.py +765 -0
  54. claude_mpm/services/command_deployment_service.py +108 -5
  55. claude_mpm/services/core/base.py +7 -2
  56. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  57. claude_mpm/services/git/git_operations_service.py +8 -8
  58. claude_mpm/services/mcp_config_manager.py +75 -145
  59. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  60. claude_mpm/services/mcp_service_verifier.py +6 -3
  61. claude_mpm/services/monitor/daemon.py +28 -8
  62. claude_mpm/services/monitor/daemon_manager.py +96 -19
  63. claude_mpm/services/project/project_organizer.py +4 -0
  64. claude_mpm/services/runner_configuration_service.py +16 -3
  65. claude_mpm/services/session_management_service.py +16 -4
  66. claude_mpm/utils/agent_filters.py +288 -0
  67. claude_mpm/utils/gitignore.py +3 -0
  68. claude_mpm/utils/migration.py +372 -0
  69. claude_mpm/utils/progress.py +5 -1
  70. {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +69 -8
  71. {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +76 -62
  72. /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
  73. {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
  74. {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
  75. {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
  76. {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,38 @@
1
+ """System context utilities for Claude runner.
2
+
3
+ This module provides shared context creation functions that can be used
4
+ across different modules without circular dependencies.
5
+ """
6
+
7
+
8
+ def create_simple_context() -> str:
9
+ """Create basic context for Claude.
10
+
11
+ This function is extracted to avoid circular imports between
12
+ claude_runner.py and interactive_session.py.
13
+
14
+ Returns:
15
+ Basic system context string for Claude
16
+ """
17
+ return """You are Claude Code running in Claude MPM (Multi-Agent Project Manager).
18
+
19
+ You have access to native subagents via the Task tool with subagent_type parameter:
20
+ - engineer: For coding, implementation, and technical tasks
21
+ - qa: For testing, validation, and quality assurance
22
+ - documentation: For docs, guides, and explanations
23
+ - research: For investigation and analysis
24
+ - security: For security-related tasks
25
+ - ops: For deployment and infrastructure
26
+ - version-control: For git and version management
27
+ - data-engineer: For data processing and APIs
28
+
29
+ Use these agents by calling: Task(description="task description", subagent_type="agent_name")
30
+
31
+ IMPORTANT: The Task tool accepts both naming formats:
32
+ - Capitalized format: "Research", "Engineer", "QA", "Version Control", "Data Engineer"
33
+ - Lowercase format: "research", "engineer", "qa", "version-control", "data-engineer"
34
+
35
+ Both formats work correctly. When you see capitalized names (matching TodoWrite prefixes),
36
+ automatically normalize them to lowercase-hyphenated format for the Task tool.
37
+
38
+ Work efficiently and delegate appropriately to subagents when needed."""
@@ -84,6 +84,12 @@ class AgentMetadata:
84
84
  version: str = "1.0.0"
85
85
  author: str = ""
86
86
  tags: List[str] = None
87
+ # NEW: Collection-based identification fields
88
+ collection_id: Optional[str] = None # Format: owner/repo-name
89
+ source_path: Optional[str] = None # Relative path in repo
90
+ canonical_id: Optional[str] = (
91
+ None # Format: collection_id:agent_id or legacy:filename
92
+ )
87
93
 
88
94
  def __post_init__(self):
89
95
  """Initialize default values for mutable fields."""
@@ -690,6 +696,111 @@ class UnifiedAgentRegistry:
690
696
  """Get all memory-aware agents."""
691
697
  return self.list_agents(agent_type=AgentType.MEMORY_AWARE)
692
698
 
699
+ def get_agents_by_collection(self, collection_id: str) -> List[AgentMetadata]:
700
+ """Get all agents from a specific collection.
701
+
702
+ NEW: Enables collection-based agent selection.
703
+
704
+ Args:
705
+ collection_id: Collection identifier (e.g., "bobmatnyc/claude-mpm-agents")
706
+
707
+ Returns:
708
+ List of agents from the specified collection
709
+
710
+ Example:
711
+ >>> registry = get_agent_registry()
712
+ >>> agents = registry.get_agents_by_collection("bobmatnyc/claude-mpm-agents")
713
+ >>> len(agents)
714
+ 45
715
+ """
716
+ if not self.registry:
717
+ self.discover_agents()
718
+
719
+ collection_agents = [
720
+ agent
721
+ for agent in self.registry.values()
722
+ if agent.collection_id == collection_id
723
+ ]
724
+
725
+ return sorted(collection_agents, key=lambda a: a.name)
726
+
727
+ def list_collections(self) -> List[Dict[str, Any]]:
728
+ """List all available collections with agent counts.
729
+
730
+ NEW: Provides overview of available collections.
731
+
732
+ Returns:
733
+ List of collection info dictionaries with:
734
+ - collection_id: Collection identifier
735
+ - agent_count: Number of agents in collection
736
+ - agents: List of agent names in collection
737
+
738
+ Example:
739
+ >>> registry = get_agent_registry()
740
+ >>> collections = registry.list_collections()
741
+ >>> collections
742
+ [
743
+ {
744
+ "collection_id": "bobmatnyc/claude-mpm-agents",
745
+ "agent_count": 45,
746
+ "agents": ["pm", "engineer", "qa", ...]
747
+ }
748
+ ]
749
+ """
750
+ if not self.registry:
751
+ self.discover_agents()
752
+
753
+ # Group agents by collection_id
754
+ collections_map: Dict[str, List[str]] = {}
755
+
756
+ for agent in self.registry.values():
757
+ if not agent.collection_id:
758
+ # Skip agents without collection (legacy or local)
759
+ continue
760
+
761
+ if agent.collection_id not in collections_map:
762
+ collections_map[agent.collection_id] = []
763
+
764
+ collections_map[agent.collection_id].append(agent.name)
765
+
766
+ # Convert to list format
767
+ collections = [
768
+ {
769
+ "collection_id": coll_id,
770
+ "agent_count": len(agent_names),
771
+ "agents": sorted(agent_names),
772
+ }
773
+ for coll_id, agent_names in collections_map.items()
774
+ ]
775
+
776
+ return sorted(collections, key=lambda c: c["collection_id"])
777
+
778
+ def get_agent_by_canonical_id(self, canonical_id: str) -> Optional[AgentMetadata]:
779
+ """Get agent by canonical ID (primary matching key).
780
+
781
+ NEW: Primary matching method using canonical_id.
782
+
783
+ Args:
784
+ canonical_id: Canonical identifier (e.g., "bobmatnyc/claude-mpm-agents:pm")
785
+
786
+ Returns:
787
+ AgentMetadata if found, None otherwise
788
+
789
+ Example:
790
+ >>> registry = get_agent_registry()
791
+ >>> agent = registry.get_agent_by_canonical_id("bobmatnyc/claude-mpm-agents:pm")
792
+ >>> agent.name
793
+ 'Project Manager Agent'
794
+ """
795
+ if not self.registry:
796
+ self.discover_agents()
797
+
798
+ for agent in self.registry.values():
799
+ if agent.canonical_id == canonical_id:
800
+ return agent
801
+
802
+ return None
803
+
693
804
  def add_discovery_path(self, path: Union[str, Path]) -> None:
694
805
  """Add a new path for agent discovery."""
695
806
  path = Path(path)
@@ -809,6 +920,21 @@ def get_registry_stats() -> Dict[str, Any]:
809
920
  return get_agent_registry().get_registry_stats()
810
921
 
811
922
 
923
+ def get_agents_by_collection(collection_id: str) -> List[AgentMetadata]:
924
+ """Get all agents from a specific collection."""
925
+ return get_agent_registry().get_agents_by_collection(collection_id)
926
+
927
+
928
+ def list_collections() -> List[Dict[str, Any]]:
929
+ """List all available collections."""
930
+ return get_agent_registry().list_collections()
931
+
932
+
933
+ def get_agent_by_canonical_id(canonical_id: str) -> Optional[AgentMetadata]:
934
+ """Get agent by canonical ID."""
935
+ return get_agent_registry().get_agent_by_canonical_id(canonical_id)
936
+
937
+
812
938
  # Legacy function names for backward compatibility
813
939
  def listAgents() -> List[str]:
814
940
  """Legacy function: Get list of agent names."""
@@ -838,14 +964,16 @@ __all__ = [
838
964
  "discover_agents",
839
965
  "discover_agents_sync",
840
966
  "get_agent",
967
+ "get_agent_by_canonical_id",
841
968
  "get_agent_names",
842
969
  "get_agent_registry",
970
+ "get_agents_by_collection",
843
971
  "get_core_agents",
844
972
  "get_project_agents",
845
973
  "get_registry_stats",
846
974
  "get_specialized_agents",
847
- # Legacy compatibility
848
975
  "listAgents",
849
976
  "list_agents",
850
977
  "list_agents_all",
978
+ "list_collections",
851
979
  ]
@@ -218,6 +218,27 @@ class DevelopmentConfig(BaseModel):
218
218
  )
219
219
 
220
220
 
221
+ class DocumentationConfig(BaseModel):
222
+ """Documentation routing and management configuration."""
223
+
224
+ docs_path: str = Field(
225
+ default="docs/research/",
226
+ description="Default path for session documentation (relative to project root)",
227
+ )
228
+ attach_to_tickets: bool = Field(
229
+ default=True,
230
+ description="Attach work products to tickets when ticket context exists",
231
+ )
232
+ backup_locally: bool = Field(
233
+ default=True,
234
+ description="Always create local backup copies of documentation",
235
+ )
236
+ enable_ticket_detection: bool = Field(
237
+ default=True,
238
+ description="Enable automatic ticket context detection from user messages",
239
+ )
240
+
241
+
221
242
  class UnifiedConfig(BaseSettings):
222
243
  """
223
244
  Unified configuration model for Claude MPM.
@@ -242,6 +263,7 @@ class UnifiedConfig(BaseSettings):
242
263
  performance: PerformanceConfig = Field(default_factory=PerformanceConfig)
243
264
  sessions: SessionConfig = Field(default_factory=SessionConfig)
244
265
  development: DevelopmentConfig = Field(default_factory=DevelopmentConfig)
266
+ documentation: DocumentationConfig = Field(default_factory=DocumentationConfig)
245
267
 
246
268
  # Path configuration
247
269
  base_path: Optional[Path] = Field(
@@ -5,8 +5,19 @@ This module provides utilities for integrating with the memory system,
5
5
  including pre and post delegation hooks.
6
6
  """
7
7
 
8
- import os
8
+ import logging
9
9
  import sys
10
+
11
+ # Reconfigure logging to INFO level BEFORE kuzu-memory imports
12
+ # This overrides kuzu-memory's WARNING-level basicConfig (fixes 1M-445)
13
+ logging.basicConfig(
14
+ level=logging.INFO,
15
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
16
+ force=True, # Python 3.8+ - reconfigures root logger
17
+ stream=sys.stderr,
18
+ )
19
+
20
+ import os
10
21
  from datetime import datetime, timezone
11
22
  from typing import Optional
12
23
 
@@ -103,6 +103,10 @@ class AgentMetadata:
103
103
  author: Optional[str] = None
104
104
  tags: List[str] = field(default_factory=list)
105
105
  specializations: List[str] = field(default_factory=list)
106
+ # NEW: Collection metadata for enhanced agent matching
107
+ collection_id: Optional[str] = None # Format: owner/repo-name
108
+ source_path: Optional[str] = None # Relative path in repository
109
+ canonical_id: Optional[str] = None # Format: collection_id:agent_id
106
110
 
107
111
  def increment_serial_version(self) -> None:
108
112
  """Increment the patch version number.
@@ -181,6 +185,9 @@ class AgentDefinition:
181
185
  "author": self.metadata.author,
182
186
  "tags": self.metadata.tags,
183
187
  "specializations": self.metadata.specializations,
188
+ "collection_id": self.metadata.collection_id,
189
+ "source_path": self.metadata.source_path,
190
+ "canonical_id": self.metadata.canonical_id,
184
191
  },
185
192
  "primary_role": self.primary_role,
186
193
  "when_to_use": self.when_to_use,