claude-mpm 3.7.8__py3-none-any.whl → 3.9.0__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 (100) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +0 -106
  3. claude_mpm/agents/INSTRUCTIONS.md +0 -96
  4. claude_mpm/agents/MEMORY.md +94 -0
  5. claude_mpm/agents/WORKFLOW.md +86 -0
  6. claude_mpm/agents/templates/code_analyzer.json +2 -2
  7. claude_mpm/agents/templates/data_engineer.json +1 -1
  8. claude_mpm/agents/templates/documentation.json +1 -1
  9. claude_mpm/agents/templates/engineer.json +1 -1
  10. claude_mpm/agents/templates/ops.json +1 -1
  11. claude_mpm/agents/templates/qa.json +1 -1
  12. claude_mpm/agents/templates/research.json +1 -1
  13. claude_mpm/agents/templates/security.json +1 -1
  14. claude_mpm/agents/templates/ticketing.json +3 -8
  15. claude_mpm/agents/templates/version_control.json +1 -1
  16. claude_mpm/agents/templates/web_qa.json +2 -2
  17. claude_mpm/agents/templates/web_ui.json +2 -2
  18. claude_mpm/cli/__init__.py +2 -2
  19. claude_mpm/cli/commands/__init__.py +2 -1
  20. claude_mpm/cli/commands/agents.py +8 -3
  21. claude_mpm/cli/commands/tickets.py +596 -19
  22. claude_mpm/cli/parser.py +217 -5
  23. claude_mpm/config/__init__.py +30 -39
  24. claude_mpm/config/socketio_config.py +8 -5
  25. claude_mpm/constants.py +13 -0
  26. claude_mpm/core/__init__.py +8 -18
  27. claude_mpm/core/cache.py +596 -0
  28. claude_mpm/core/claude_runner.py +166 -622
  29. claude_mpm/core/config.py +7 -3
  30. claude_mpm/core/constants.py +339 -0
  31. claude_mpm/core/container.py +548 -38
  32. claude_mpm/core/exceptions.py +392 -0
  33. claude_mpm/core/framework_loader.py +249 -93
  34. claude_mpm/core/interactive_session.py +479 -0
  35. claude_mpm/core/interfaces.py +424 -0
  36. claude_mpm/core/lazy.py +467 -0
  37. claude_mpm/core/logging_config.py +444 -0
  38. claude_mpm/core/oneshot_session.py +465 -0
  39. claude_mpm/core/optimized_agent_loader.py +485 -0
  40. claude_mpm/core/optimized_startup.py +490 -0
  41. claude_mpm/core/service_registry.py +52 -26
  42. claude_mpm/core/socketio_pool.py +162 -5
  43. claude_mpm/core/types.py +292 -0
  44. claude_mpm/core/typing_utils.py +477 -0
  45. claude_mpm/hooks/claude_hooks/hook_handler.py +213 -99
  46. claude_mpm/init.py +2 -1
  47. claude_mpm/services/__init__.py +78 -14
  48. claude_mpm/services/agent/__init__.py +24 -0
  49. claude_mpm/services/agent/deployment.py +2548 -0
  50. claude_mpm/services/agent/management.py +598 -0
  51. claude_mpm/services/agent/registry.py +813 -0
  52. claude_mpm/services/agents/deployment/agent_deployment.py +728 -308
  53. claude_mpm/services/agents/memory/agent_memory_manager.py +160 -4
  54. claude_mpm/services/async_session_logger.py +8 -3
  55. claude_mpm/services/communication/__init__.py +21 -0
  56. claude_mpm/services/communication/socketio.py +1933 -0
  57. claude_mpm/services/communication/websocket.py +479 -0
  58. claude_mpm/services/core/__init__.py +123 -0
  59. claude_mpm/services/core/base.py +247 -0
  60. claude_mpm/services/core/interfaces.py +951 -0
  61. claude_mpm/services/framework_claude_md_generator/__init__.py +10 -3
  62. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +14 -11
  63. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +23 -23
  64. claude_mpm/services/framework_claude_md_generator.py +3 -2
  65. claude_mpm/services/health_monitor.py +4 -3
  66. claude_mpm/services/hook_service.py +64 -4
  67. claude_mpm/services/infrastructure/__init__.py +21 -0
  68. claude_mpm/services/infrastructure/logging.py +202 -0
  69. claude_mpm/services/infrastructure/monitoring.py +893 -0
  70. claude_mpm/services/memory/indexed_memory.py +648 -0
  71. claude_mpm/services/project/__init__.py +21 -0
  72. claude_mpm/services/project/analyzer.py +864 -0
  73. claude_mpm/services/project/registry.py +608 -0
  74. claude_mpm/services/project_analyzer.py +95 -2
  75. claude_mpm/services/recovery_manager.py +15 -9
  76. claude_mpm/services/response_tracker.py +3 -5
  77. claude_mpm/services/socketio/__init__.py +25 -0
  78. claude_mpm/services/socketio/handlers/__init__.py +25 -0
  79. claude_mpm/services/socketio/handlers/base.py +121 -0
  80. claude_mpm/services/socketio/handlers/connection.py +198 -0
  81. claude_mpm/services/socketio/handlers/file.py +213 -0
  82. claude_mpm/services/socketio/handlers/git.py +723 -0
  83. claude_mpm/services/socketio/handlers/memory.py +27 -0
  84. claude_mpm/services/socketio/handlers/project.py +25 -0
  85. claude_mpm/services/socketio/handlers/registry.py +145 -0
  86. claude_mpm/services/socketio_client_manager.py +12 -7
  87. claude_mpm/services/socketio_server.py +156 -30
  88. claude_mpm/services/ticket_manager.py +172 -9
  89. claude_mpm/services/ticket_manager_di.py +1 -1
  90. claude_mpm/services/version_control/semantic_versioning.py +80 -7
  91. claude_mpm/services/version_control/version_parser.py +528 -0
  92. claude_mpm/utils/error_handler.py +1 -1
  93. claude_mpm/validation/agent_validator.py +27 -14
  94. claude_mpm/validation/frontmatter_validator.py +231 -0
  95. {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/METADATA +38 -128
  96. {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/RECORD +100 -59
  97. {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/WHEEL +0 -0
  98. {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/entry_points.txt +0 -0
  99. {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/licenses/LICENSE +0 -0
  100. {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/top_level.txt +0 -0
@@ -4,13 +4,12 @@ from pathlib import Path
4
4
  from typing import Optional, Dict, Any, List
5
5
  from datetime import datetime
6
6
 
7
- try:
8
- from ..core.logger import get_logger
9
- except ImportError:
10
- from core.logger import get_logger
7
+ from claude_mpm.core.logging_config import get_logger
11
8
 
9
+ from ..core.interfaces import TicketManagerInterface
12
10
 
13
- class TicketManager:
11
+
12
+ class TicketManager(TicketManagerInterface):
14
13
  """
15
14
  Manage ticket creation using ai-trackdown-pytools.
16
15
 
@@ -25,7 +24,7 @@ class TicketManager:
25
24
  Args:
26
25
  project_path: Project root (defaults to current directory)
27
26
  """
28
- self.logger = get_logger("ticket_manager")
27
+ self.logger = get_logger(__name__)
29
28
  self.project_path = project_path or Path.cwd()
30
29
  self.task_manager = self._init_task_manager()
31
30
 
@@ -50,7 +49,7 @@ class TicketManager:
50
49
  # Check if config exists, create if needed
51
50
  if not config_file.exists():
52
51
  try:
53
- config = Config.create_default(str(config_file))
52
+ config = Config.create_default(config_file) # Pass Path object directly
54
53
  config.set("paths.tickets_dir", "tickets")
55
54
  config.set("paths.epics_dir", "tickets/epics")
56
55
  config.set("paths.issues_dir", "tickets/issues")
@@ -65,7 +64,7 @@ class TicketManager:
65
64
 
66
65
  # Initialize TaskManager directly with the project path
67
66
  # TaskManager will handle project initialization internally
68
- task_manager = TaskManager(str(self.project_path))
67
+ task_manager = TaskManager(self.project_path) # Pass Path object directly
69
68
 
70
69
  # Verify it's using the right directory
71
70
  if hasattr(task_manager, 'tasks_dir'):
@@ -373,4 +372,168 @@ class TicketManager:
373
372
  self.logger.error(f"Failed to get ticket {ticket_id}: {e.__class__.__name__}: {e}")
374
373
  self.logger.info(f"Try using the CLI: aitrackdown show {ticket_id}")
375
374
  self.logger.debug("Full error details:", exc_info=True)
376
- return None
375
+ return None
376
+
377
+ # ================================================================================
378
+ # Interface Adapter Methods
379
+ # ================================================================================
380
+ # These methods adapt the existing implementation to comply with TicketManagerInterface
381
+
382
+ def create_task(self, title: str, description: str, **kwargs) -> Optional[str]:
383
+ """Create a new task ticket.
384
+
385
+ WHY: This adapter method provides interface compliance by wrapping
386
+ the underlying task manager's create functionality.
387
+
388
+ Args:
389
+ title: Task title
390
+ description: Task description
391
+ **kwargs: Additional task properties
392
+
393
+ Returns:
394
+ Task ID if created successfully, None otherwise
395
+ """
396
+ if not self.task_manager:
397
+ self.logger.error("Task manager not initialized")
398
+ return None
399
+
400
+ try:
401
+ # Create task using ai-trackdown-pytools
402
+ from ai_trackdown_pytools.core.task import Task
403
+
404
+ task = Task(
405
+ title=title,
406
+ description=description,
407
+ status=kwargs.get('status', 'open'),
408
+ priority=kwargs.get('priority', 'medium'),
409
+ tags=kwargs.get('tags', []),
410
+ assignees=kwargs.get('assignees', [])
411
+ )
412
+
413
+ # Save the task
414
+ task_id = self.task_manager.create_task(task)
415
+ self.logger.info(f"Created task {task_id}: {title}")
416
+ return task_id
417
+
418
+ except ImportError:
419
+ self.logger.error("ai-trackdown-pytools not available")
420
+ return None
421
+ except Exception as e:
422
+ self.logger.error(f"Failed to create task: {e}")
423
+ return None
424
+
425
+ def update_task(self, task_id: str, **updates) -> bool:
426
+ """Update an existing task.
427
+
428
+ WHY: This adapter method provides interface compliance by wrapping
429
+ task update operations.
430
+
431
+ Args:
432
+ task_id: ID of task to update
433
+ **updates: Fields to update
434
+
435
+ Returns:
436
+ True if update successful
437
+ """
438
+ if not self.task_manager:
439
+ self.logger.error("Task manager not initialized")
440
+ return False
441
+
442
+ try:
443
+ # Get the existing task
444
+ task = self.task_manager.get_task(task_id)
445
+ if not task:
446
+ self.logger.error(f"Task {task_id} not found")
447
+ return False
448
+
449
+ # Apply updates
450
+ for key, value in updates.items():
451
+ if hasattr(task, key):
452
+ setattr(task, key, value)
453
+
454
+ # Save the updated task
455
+ self.task_manager.update_task(task)
456
+ self.logger.info(f"Updated task {task_id}")
457
+ return True
458
+
459
+ except Exception as e:
460
+ self.logger.error(f"Failed to update task {task_id}: {e}")
461
+ return False
462
+
463
+ def get_task(self, task_id: str) -> Optional[Dict[str, Any]]:
464
+ """Get task details.
465
+
466
+ WHY: This adapter method provides interface compliance by wrapping
467
+ the existing get_ticket method.
468
+
469
+ Args:
470
+ task_id: ID of task to retrieve
471
+
472
+ Returns:
473
+ Task data dictionary or None if not found
474
+ """
475
+ # Use existing get_ticket method which already returns dict format
476
+ return self.get_ticket(task_id)
477
+
478
+ def list_tasks(self, status: Optional[str] = None, **filters) -> List[Dict[str, Any]]:
479
+ """List tasks with optional filtering.
480
+
481
+ WHY: This adapter method provides interface compliance by wrapping
482
+ task listing operations.
483
+
484
+ Args:
485
+ status: Optional status filter
486
+ **filters: Additional filter criteria
487
+
488
+ Returns:
489
+ List of task dictionaries
490
+ """
491
+ if not self.task_manager:
492
+ self.logger.error("Task manager not initialized")
493
+ return []
494
+
495
+ try:
496
+ # Get all tasks
497
+ tasks = self.task_manager.list_tasks()
498
+
499
+ # Apply filters
500
+ filtered_tasks = []
501
+ for task in tasks:
502
+ # Check status filter
503
+ if status and task.get('status') != status:
504
+ continue
505
+
506
+ # Check additional filters
507
+ match = True
508
+ for key, value in filters.items():
509
+ if task.get(key) != value:
510
+ match = False
511
+ break
512
+
513
+ if match:
514
+ filtered_tasks.append(task)
515
+
516
+ return filtered_tasks
517
+
518
+ except Exception as e:
519
+ self.logger.error(f"Failed to list tasks: {e}")
520
+ return []
521
+
522
+ def close_task(self, task_id: str, resolution: Optional[str] = None) -> bool:
523
+ """Close a task.
524
+
525
+ WHY: This adapter method provides interface compliance by updating
526
+ task status to closed.
527
+
528
+ Args:
529
+ task_id: ID of task to close
530
+ resolution: Optional resolution description
531
+
532
+ Returns:
533
+ True if close successful
534
+ """
535
+ updates = {'status': 'closed'}
536
+ if resolution:
537
+ updates['resolution'] = resolution
538
+
539
+ return self.update_task(task_id, **updates)
@@ -56,7 +56,7 @@ class AITrackdownAdapter(ITaskManagerAdapter):
56
56
  # Configure ai-trackdown if needed
57
57
  config_file = self.project_path / ".trackdown.yaml"
58
58
  if not config_file.exists():
59
- config = TrackdownConfig.create_default(config_file)
59
+ config = TrackdownConfig.create_default(config_file) # Already correct - using Path object
60
60
  config.set("paths.tickets_dir", "tickets")
61
61
  config.set("paths.epics_dir", "tickets/epics")
62
62
  config.set("paths.issues_dir", "tickets/issues")
@@ -334,11 +334,42 @@ class SemanticVersionManager:
334
334
 
335
335
  def get_current_version(self) -> Optional[SemanticVersion]:
336
336
  """
337
- Get the current version from project files.
337
+ Get the current version from multiple sources with intelligent fallback.
338
+
339
+ Uses the enhanced version parser to check:
340
+ 1. Git tags (most recent)
341
+ 2. VERSION file
342
+ 3. package.json
343
+ 4. pyproject.toml
344
+ 5. Other configured version files
338
345
 
339
346
  Returns:
340
347
  Current SemanticVersion or None if not found
341
348
  """
349
+ try:
350
+ # Import here to avoid circular dependency
351
+ from claude_mpm.services.version_control.version_parser import get_version_parser
352
+
353
+ # Use enhanced parser for current version
354
+ parser = get_version_parser(self.project_root)
355
+ version_meta = parser.get_current_version()
356
+
357
+ if version_meta:
358
+ version = self.parse_version(version_meta.version)
359
+ if version:
360
+ self.logger.info(f"Found version {version} from {version_meta.source}")
361
+ # Optionally attach metadata
362
+ if hasattr(version, '__dict__'):
363
+ version.source = version_meta.source
364
+ return version
365
+
366
+ except ImportError:
367
+ # Fallback to original implementation
368
+ self.logger.debug("Enhanced version parser not available, using fallback")
369
+ except Exception as e:
370
+ self.logger.error(f"Error getting current version with enhanced parser: {e}")
371
+
372
+ # Fallback to original implementation
342
373
  for filename, parser in self.version_files.items():
343
374
  file_path = self.project_root / filename
344
375
 
@@ -811,19 +842,61 @@ class SemanticVersionManager:
811
842
 
812
843
  def get_version_history(self) -> List[SemanticVersion]:
813
844
  """
814
- Get version history from changelog or Git tags.
845
+ Get version history from multiple sources with intelligent fallback.
846
+
847
+ Uses the enhanced version parser to retrieve version history from:
848
+ 1. Git tags (primary source)
849
+ 2. CHANGELOG.md (fallback)
850
+ 3. VERSION files (current version only)
815
851
 
816
852
  Returns:
817
853
  List of versions in descending order
818
854
  """
855
+ try:
856
+ # Import here to avoid circular dependency
857
+ from claude_mpm.services.version_control.version_parser import get_version_parser
858
+
859
+ # Use enhanced parser for comprehensive version history
860
+ parser = get_version_parser(self.project_root)
861
+ version_metadata = parser.get_version_history(include_prereleases=False)
862
+
863
+ # Convert to SemanticVersion objects
864
+ versions = []
865
+ for meta in version_metadata:
866
+ version = self.parse_version(meta.version)
867
+ if version:
868
+ # Optionally attach metadata to version
869
+ if hasattr(version, '__dict__'):
870
+ version.source = meta.source
871
+ version.release_date = meta.release_date
872
+ version.commit_hash = meta.commit_hash
873
+ versions.append(version)
874
+
875
+ return versions
876
+
877
+ except ImportError:
878
+ # Fallback to original implementation if enhanced parser not available
879
+ self.logger.warning("Enhanced version parser not available, falling back to changelog parsing")
880
+ return self._parse_changelog_versions_fallback()
881
+ except Exception as e:
882
+ self.logger.error(f"Error getting version history: {e}")
883
+ # Fallback to original implementation
884
+ return self._parse_changelog_versions_fallback()
885
+
886
+ def _parse_changelog_versions_fallback(self) -> List[SemanticVersion]:
887
+ """Fallback method: Parse versions from changelog file only."""
819
888
  versions = []
820
889
 
821
890
  # Try to get versions from changelog
822
- changelog_path = self.project_root / "docs" / "CHANGELOG.md"
823
- if changelog_path.exists():
824
- versions.extend(self._parse_changelog_versions(changelog_path))
825
-
826
- # TODO: Add Git tag parsing if needed
891
+ changelog_paths = [
892
+ self.project_root / "CHANGELOG.md",
893
+ self.project_root / "docs" / "CHANGELOG.md"
894
+ ]
895
+
896
+ for changelog_path in changelog_paths:
897
+ if changelog_path.exists():
898
+ versions.extend(self._parse_changelog_versions(changelog_path))
899
+ break
827
900
 
828
901
  # Sort versions in descending order
829
902
  versions.sort(reverse=True)