claude-mpm 3.9.11__py3-none-any.whl → 4.0.3__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 +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +1 -1
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +79 -51
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +20 -20
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +140 -905
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +203 -81
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +305 -197
- claude_mpm/cli/parser.py +24 -1156
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +104 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +71 -73
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +35 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +120 -54
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +233 -199
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +30 -13
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
- claude_mpm/services/mcp_gateway/main.py +287 -137
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +223 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +145 -65
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +170 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +19 -533
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +2 -2
- claude_mpm/storage/state_storage.py +177 -181
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
- claude_mpm-4.0.3.dist-info/RECORD +402 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/cli/commands/run_guarded.py +0 -511
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/config/memory_guardian_yaml.py +0 -335
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/core/memory_aware_runner.py +0 -353
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
- claude_mpm/services/infrastructure/health_monitor.py +0 -775
- claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
- claude_mpm/services/infrastructure/memory_guardian.py +0 -944
- claude_mpm/services/infrastructure/restart_protection.py +0 -642
- claude_mpm/services/infrastructure/state_manager.py +0 -774
- claude_mpm/services/mcp_gateway/manager.py +0 -334
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.11.dist-info/RECORD +0 -306
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
| @@ -1,864 +0,0 @@ | |
| 1 | 
            -
            #!/usr/bin/env python3
         | 
| 2 | 
            -
            """
         | 
| 3 | 
            -
            Project Analyzer Service
         | 
| 4 | 
            -
            =======================
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            Analyzes project characteristics to enable project-specific memory creation.
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            WHY: Instead of creating generic memories, agents need to understand the specific
         | 
| 9 | 
            -
            project they're working on - its tech stack, architecture patterns, coding conventions,
         | 
| 10 | 
            -
            and key components. This service extracts these characteristics automatically.
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            DESIGN DECISION: Separates project analysis from memory creation to allow reuse
         | 
| 13 | 
            -
            across different memory-related services and enable caching of analysis results.
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            This service analyzes:
         | 
| 16 | 
            -
            - Technology stack from config files (package.json, requirements.txt, etc.)
         | 
| 17 | 
            -
            - Code patterns from source files
         | 
| 18 | 
            -
            - Architecture patterns from directory structure
         | 
| 19 | 
            -
            - Testing frameworks and approaches
         | 
| 20 | 
            -
            - API patterns and endpoints
         | 
| 21 | 
            -
            - Database integrations
         | 
| 22 | 
            -
            - Project-specific terminology and conventions
         | 
| 23 | 
            -
            """
         | 
| 24 | 
            -
             | 
| 25 | 
            -
            import json
         | 
| 26 | 
            -
            import re
         | 
| 27 | 
            -
            from pathlib import Path
         | 
| 28 | 
            -
            from typing import Dict, List, Optional, Any, Set, Tuple
         | 
| 29 | 
            -
            import logging
         | 
| 30 | 
            -
            from dataclasses import dataclass, asdict
         | 
| 31 | 
            -
            from collections import defaultdict, Counter
         | 
| 32 | 
            -
             | 
| 33 | 
            -
            from claude_mpm.core.config import Config
         | 
| 34 | 
            -
            from claude_mpm.utils.paths import PathResolver
         | 
| 35 | 
            -
            from claude_mpm.core.interfaces import ProjectAnalyzerInterface
         | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
            @dataclass
         | 
| 39 | 
            -
            class ProjectCharacteristics:
         | 
| 40 | 
            -
                """Structured representation of project characteristics."""
         | 
| 41 | 
            -
                
         | 
| 42 | 
            -
                # Core project info
         | 
| 43 | 
            -
                project_name: str
         | 
| 44 | 
            -
                primary_language: Optional[str]
         | 
| 45 | 
            -
                languages: List[str]
         | 
| 46 | 
            -
                frameworks: List[str]
         | 
| 47 | 
            -
                
         | 
| 48 | 
            -
                # Architecture and structure
         | 
| 49 | 
            -
                architecture_type: str
         | 
| 50 | 
            -
                main_modules: List[str]
         | 
| 51 | 
            -
                key_directories: List[str]
         | 
| 52 | 
            -
                entry_points: List[str]
         | 
| 53 | 
            -
                
         | 
| 54 | 
            -
                # Development practices
         | 
| 55 | 
            -
                testing_framework: Optional[str]
         | 
| 56 | 
            -
                test_patterns: List[str]
         | 
| 57 | 
            -
                package_manager: Optional[str]
         | 
| 58 | 
            -
                build_tools: List[str]
         | 
| 59 | 
            -
                
         | 
| 60 | 
            -
                # Integrations and dependencies
         | 
| 61 | 
            -
                databases: List[str]
         | 
| 62 | 
            -
                web_frameworks: List[str]
         | 
| 63 | 
            -
                api_patterns: List[str]
         | 
| 64 | 
            -
                key_dependencies: List[str]
         | 
| 65 | 
            -
                
         | 
| 66 | 
            -
                # Project-specific patterns
         | 
| 67 | 
            -
                code_conventions: List[str]
         | 
| 68 | 
            -
                configuration_patterns: List[str]
         | 
| 69 | 
            -
                project_terminology: List[str]
         | 
| 70 | 
            -
                
         | 
| 71 | 
            -
                # Documentation and structure
         | 
| 72 | 
            -
                documentation_files: List[str]
         | 
| 73 | 
            -
                important_configs: List[str]
         | 
| 74 | 
            -
                
         | 
| 75 | 
            -
                def to_dict(self) -> Dict[str, Any]:
         | 
| 76 | 
            -
                    """Convert to dictionary for JSON serialization."""
         | 
| 77 | 
            -
                    return asdict(self)
         | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
            class ProjectAnalyzer(ProjectAnalyzerInterface):
         | 
| 81 | 
            -
                """Analyzes project characteristics for context-aware memory creation.
         | 
| 82 | 
            -
                
         | 
| 83 | 
            -
                WHY: Generic agent memories aren't helpful for specific projects. This analyzer
         | 
| 84 | 
            -
                extracts project-specific characteristics that enable agents to create relevant,
         | 
| 85 | 
            -
                actionable memories with proper context.
         | 
| 86 | 
            -
                
         | 
| 87 | 
            -
                DESIGN DECISION: Uses a combination of file pattern analysis, content parsing,
         | 
| 88 | 
            -
                and directory structure analysis to build comprehensive project understanding
         | 
| 89 | 
            -
                without requiring external tools or API calls.
         | 
| 90 | 
            -
                """
         | 
| 91 | 
            -
                
         | 
| 92 | 
            -
                # Common configuration files and their indicators
         | 
| 93 | 
            -
                CONFIG_FILE_PATTERNS = {
         | 
| 94 | 
            -
                    'package.json': 'node_js',
         | 
| 95 | 
            -
                    'requirements.txt': 'python',
         | 
| 96 | 
            -
                    'pyproject.toml': 'python',
         | 
| 97 | 
            -
                    'setup.py': 'python',
         | 
| 98 | 
            -
                    'Cargo.toml': 'rust',
         | 
| 99 | 
            -
                    'pom.xml': 'java',
         | 
| 100 | 
            -
                    'build.gradle': 'java',
         | 
| 101 | 
            -
                    'composer.json': 'php',
         | 
| 102 | 
            -
                    'Gemfile': 'ruby',
         | 
| 103 | 
            -
                    'go.mod': 'go',
         | 
| 104 | 
            -
                    'CMakeLists.txt': 'cpp',
         | 
| 105 | 
            -
                    'Makefile': 'c_cpp',
         | 
| 106 | 
            -
                }
         | 
| 107 | 
            -
                
         | 
| 108 | 
            -
                # Framework detection patterns
         | 
| 109 | 
            -
                FRAMEWORK_PATTERNS = {
         | 
| 110 | 
            -
                    'flask': ['from flask', 'Flask(', 'app.route'],
         | 
| 111 | 
            -
                    'django': ['from django', 'DJANGO_SETTINGS', 'django.contrib'],
         | 
| 112 | 
            -
                    'fastapi': ['from fastapi', 'FastAPI(', '@app.'],
         | 
| 113 | 
            -
                    'express': ['express()', 'app.get(', 'app.post('],
         | 
| 114 | 
            -
                    'react': ['import React', 'from react', 'ReactDOM'],
         | 
| 115 | 
            -
                    'vue': ['Vue.createApp', 'new Vue(', 'vue-'],
         | 
| 116 | 
            -
                    'angular': ['@Component', '@Injectable', 'Angular'],
         | 
| 117 | 
            -
                    'spring': ['@SpringBootApplication', '@RestController', 'Spring'],
         | 
| 118 | 
            -
                    'rails': ['Rails.application', 'ApplicationController'],
         | 
| 119 | 
            -
                }
         | 
| 120 | 
            -
                
         | 
| 121 | 
            -
                # Database detection patterns
         | 
| 122 | 
            -
                DATABASE_PATTERNS = {
         | 
| 123 | 
            -
                    'postgresql': ['psycopg2', 'postgresql:', 'postgres:', 'pg_'],
         | 
| 124 | 
            -
                    'mysql': ['mysql-connector', 'mysql:', 'MySQLdb'],
         | 
| 125 | 
            -
                    'sqlite': ['sqlite3', 'sqlite:', '.db', '.sqlite'],
         | 
| 126 | 
            -
                    'mongodb': ['pymongo', 'mongodb:', 'mongoose'],
         | 
| 127 | 
            -
                    'redis': ['redis:', 'redis-py', 'RedisClient'],
         | 
| 128 | 
            -
                    'elasticsearch': ['elasticsearch:', 'elastic'],
         | 
| 129 | 
            -
                }
         | 
| 130 | 
            -
                
         | 
| 131 | 
            -
                def __init__(self, config: Optional[Config] = None, working_directory: Optional[Path] = None):
         | 
| 132 | 
            -
                    """Initialize the project analyzer.
         | 
| 133 | 
            -
                    
         | 
| 134 | 
            -
                    Args:
         | 
| 135 | 
            -
                        config: Optional Config object
         | 
| 136 | 
            -
                        working_directory: Optional working directory path. If not provided, uses current.
         | 
| 137 | 
            -
                    """
         | 
| 138 | 
            -
                    self.config = config or Config()
         | 
| 139 | 
            -
                    self.working_directory = working_directory or PathResolver.get_project_root()
         | 
| 140 | 
            -
                    self.logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
         | 
| 141 | 
            -
                    
         | 
| 142 | 
            -
                    # Cache for analysis results
         | 
| 143 | 
            -
                    self._analysis_cache: Optional[ProjectCharacteristics] = None
         | 
| 144 | 
            -
                    self._cache_timestamp: Optional[float] = None
         | 
| 145 | 
            -
                
         | 
| 146 | 
            -
                def analyze_project(self, force_refresh: bool = False) -> ProjectCharacteristics:
         | 
| 147 | 
            -
                    """Analyze the current project and return characteristics.
         | 
| 148 | 
            -
                    
         | 
| 149 | 
            -
                    WHY: Comprehensive project analysis enables agents to create memories
         | 
| 150 | 
            -
                    that are specific to the actual project context, tech stack, and patterns.
         | 
| 151 | 
            -
                    
         | 
| 152 | 
            -
                    Args:
         | 
| 153 | 
            -
                        force_refresh: If True, ignores cache and performs fresh analysis
         | 
| 154 | 
            -
                        
         | 
| 155 | 
            -
                    Returns:
         | 
| 156 | 
            -
                        ProjectCharacteristics: Structured project analysis results
         | 
| 157 | 
            -
                    """
         | 
| 158 | 
            -
                    try:
         | 
| 159 | 
            -
                        # Check cache first (unless force refresh)
         | 
| 160 | 
            -
                        if not force_refresh and self._analysis_cache and self._cache_timestamp:
         | 
| 161 | 
            -
                            # Cache is valid for 5 minutes
         | 
| 162 | 
            -
                            import time
         | 
| 163 | 
            -
                            if time.time() - self._cache_timestamp < 300:
         | 
| 164 | 
            -
                                self.logger.debug("Using cached project analysis")
         | 
| 165 | 
            -
                                return self._analysis_cache
         | 
| 166 | 
            -
                        
         | 
| 167 | 
            -
                        self.logger.info(f"Analyzing project at: {self.working_directory}")
         | 
| 168 | 
            -
                        
         | 
| 169 | 
            -
                        # Initialize characteristics with basic info
         | 
| 170 | 
            -
                        characteristics = ProjectCharacteristics(
         | 
| 171 | 
            -
                            project_name=self.working_directory.name,
         | 
| 172 | 
            -
                            primary_language=None,
         | 
| 173 | 
            -
                            languages=[],
         | 
| 174 | 
            -
                            frameworks=[],
         | 
| 175 | 
            -
                            architecture_type="unknown",
         | 
| 176 | 
            -
                            main_modules=[],
         | 
| 177 | 
            -
                            key_directories=[],
         | 
| 178 | 
            -
                            entry_points=[],
         | 
| 179 | 
            -
                            testing_framework=None,
         | 
| 180 | 
            -
                            test_patterns=[],
         | 
| 181 | 
            -
                            package_manager=None,
         | 
| 182 | 
            -
                            build_tools=[],
         | 
| 183 | 
            -
                            databases=[],
         | 
| 184 | 
            -
                            web_frameworks=[],
         | 
| 185 | 
            -
                            api_patterns=[],
         | 
| 186 | 
            -
                            key_dependencies=[],
         | 
| 187 | 
            -
                            code_conventions=[],
         | 
| 188 | 
            -
                            configuration_patterns=[],
         | 
| 189 | 
            -
                            project_terminology=[],
         | 
| 190 | 
            -
                            documentation_files=[],
         | 
| 191 | 
            -
                            important_configs=[]
         | 
| 192 | 
            -
                        )
         | 
| 193 | 
            -
                        
         | 
| 194 | 
            -
                        # Perform various analyses
         | 
| 195 | 
            -
                        self._analyze_config_files(characteristics)
         | 
| 196 | 
            -
                        self._analyze_directory_structure(characteristics)
         | 
| 197 | 
            -
                        self._analyze_source_code(characteristics)
         | 
| 198 | 
            -
                        self._analyze_dependencies(characteristics)
         | 
| 199 | 
            -
                        self._analyze_testing_patterns(characteristics)
         | 
| 200 | 
            -
                        self._analyze_documentation(characteristics)
         | 
| 201 | 
            -
                        self._infer_architecture_type(characteristics)
         | 
| 202 | 
            -
                        self._extract_project_terminology(characteristics)
         | 
| 203 | 
            -
                        
         | 
| 204 | 
            -
                        # Cache the results
         | 
| 205 | 
            -
                        self._analysis_cache = characteristics
         | 
| 206 | 
            -
                        import time
         | 
| 207 | 
            -
                        self._cache_timestamp = time.time()
         | 
| 208 | 
            -
                        
         | 
| 209 | 
            -
                        self.logger.info(f"Project analysis complete: {characteristics.primary_language} project with {len(characteristics.frameworks)} frameworks")
         | 
| 210 | 
            -
                        return characteristics
         | 
| 211 | 
            -
                        
         | 
| 212 | 
            -
                    except Exception as e:
         | 
| 213 | 
            -
                        self.logger.error(f"Error analyzing project: {e}")
         | 
| 214 | 
            -
                        # Return minimal characteristics on error
         | 
| 215 | 
            -
                        return ProjectCharacteristics(
         | 
| 216 | 
            -
                            project_name=self.working_directory.name,
         | 
| 217 | 
            -
                            primary_language="unknown",
         | 
| 218 | 
            -
                            languages=[],
         | 
| 219 | 
            -
                            frameworks=[],
         | 
| 220 | 
            -
                            architecture_type="unknown",
         | 
| 221 | 
            -
                            main_modules=[],
         | 
| 222 | 
            -
                            key_directories=[],
         | 
| 223 | 
            -
                            entry_points=[],
         | 
| 224 | 
            -
                            testing_framework=None,
         | 
| 225 | 
            -
                            test_patterns=[],
         | 
| 226 | 
            -
                            package_manager=None,
         | 
| 227 | 
            -
                            build_tools=[],
         | 
| 228 | 
            -
                            databases=[],
         | 
| 229 | 
            -
                            web_frameworks=[],
         | 
| 230 | 
            -
                            api_patterns=[],
         | 
| 231 | 
            -
                            key_dependencies=[],
         | 
| 232 | 
            -
                            code_conventions=[],
         | 
| 233 | 
            -
                            configuration_patterns=[],
         | 
| 234 | 
            -
                            project_terminology=[],
         | 
| 235 | 
            -
                            documentation_files=[],
         | 
| 236 | 
            -
                            important_configs=[]
         | 
| 237 | 
            -
                        )
         | 
| 238 | 
            -
                
         | 
| 239 | 
            -
                def _analyze_config_files(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 240 | 
            -
                    """Analyze configuration files to determine tech stack.
         | 
| 241 | 
            -
                    
         | 
| 242 | 
            -
                    WHY: Configuration files are the most reliable indicators of project
         | 
| 243 | 
            -
                    technology stack and dependencies. They provide definitive information
         | 
| 244 | 
            -
                    about what technologies are actually used.
         | 
| 245 | 
            -
                    
         | 
| 246 | 
            -
                    Args:
         | 
| 247 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 248 | 
            -
                    """
         | 
| 249 | 
            -
                    config_files = []
         | 
| 250 | 
            -
                    languages_found = set()
         | 
| 251 | 
            -
                    
         | 
| 252 | 
            -
                    for config_file, language in self.CONFIG_FILE_PATTERNS.items():
         | 
| 253 | 
            -
                        config_path = self.working_directory / config_file
         | 
| 254 | 
            -
                        if config_path.exists():
         | 
| 255 | 
            -
                            config_files.append(config_file)
         | 
| 256 | 
            -
                            languages_found.add(language)
         | 
| 257 | 
            -
                            characteristics.important_configs.append(str(config_path.relative_to(self.working_directory)))
         | 
| 258 | 
            -
                            
         | 
| 259 | 
            -
                            # Parse specific config files for more details
         | 
| 260 | 
            -
                            try:
         | 
| 261 | 
            -
                                if config_file == 'package.json':
         | 
| 262 | 
            -
                                    self._parse_package_json(config_path, characteristics)
         | 
| 263 | 
            -
                                elif config_file in ['requirements.txt', 'pyproject.toml']:
         | 
| 264 | 
            -
                                    self._parse_python_dependencies(config_path, characteristics)
         | 
| 265 | 
            -
                                elif config_file == 'Cargo.toml':
         | 
| 266 | 
            -
                                    self._parse_cargo_toml(config_path, characteristics)
         | 
| 267 | 
            -
                            except Exception as e:
         | 
| 268 | 
            -
                                self.logger.warning(f"Error parsing {config_file}: {e}")
         | 
| 269 | 
            -
                    
         | 
| 270 | 
            -
                    # Set primary language (prefer more specific indicators)
         | 
| 271 | 
            -
                    language_priority = ['python', 'node_js', 'rust', 'java', 'go', 'php', 'ruby']
         | 
| 272 | 
            -
                    for lang in language_priority:
         | 
| 273 | 
            -
                        if lang in languages_found:
         | 
| 274 | 
            -
                            characteristics.primary_language = lang
         | 
| 275 | 
            -
                            break
         | 
| 276 | 
            -
                    
         | 
| 277 | 
            -
                    characteristics.languages = list(languages_found)
         | 
| 278 | 
            -
                    
         | 
| 279 | 
            -
                    # Determine package manager
         | 
| 280 | 
            -
                    if 'package.json' in config_files:
         | 
| 281 | 
            -
                        if (self.working_directory / 'yarn.lock').exists():
         | 
| 282 | 
            -
                            characteristics.package_manager = 'yarn'
         | 
| 283 | 
            -
                        elif (self.working_directory / 'pnpm-lock.yaml').exists():
         | 
| 284 | 
            -
                            characteristics.package_manager = 'pnpm'
         | 
| 285 | 
            -
                        else:
         | 
| 286 | 
            -
                            characteristics.package_manager = 'npm'
         | 
| 287 | 
            -
                    elif 'requirements.txt' in config_files or 'pyproject.toml' in config_files:
         | 
| 288 | 
            -
                        characteristics.package_manager = 'pip'
         | 
| 289 | 
            -
                    elif 'Cargo.toml' in config_files:
         | 
| 290 | 
            -
                        characteristics.package_manager = 'cargo'
         | 
| 291 | 
            -
                
         | 
| 292 | 
            -
                def _parse_package_json(self, package_path: Path, characteristics: ProjectCharacteristics) -> None:
         | 
| 293 | 
            -
                    """Parse package.json for Node.js project details."""
         | 
| 294 | 
            -
                    try:
         | 
| 295 | 
            -
                        with open(package_path, 'r') as f:
         | 
| 296 | 
            -
                            package_data = json.load(f)
         | 
| 297 | 
            -
                        
         | 
| 298 | 
            -
                        # Extract dependencies
         | 
| 299 | 
            -
                        all_deps = {}
         | 
| 300 | 
            -
                        all_deps.update(package_data.get('dependencies', {}))
         | 
| 301 | 
            -
                        all_deps.update(package_data.get('devDependencies', {}))
         | 
| 302 | 
            -
                        
         | 
| 303 | 
            -
                        # Identify frameworks and tools
         | 
| 304 | 
            -
                        for dep_name in all_deps.keys():
         | 
| 305 | 
            -
                            dep_lower = dep_name.lower()
         | 
| 306 | 
            -
                            
         | 
| 307 | 
            -
                            # Web frameworks
         | 
| 308 | 
            -
                            if any(fw in dep_lower for fw in ['express', 'koa', 'hapi']):
         | 
| 309 | 
            -
                                characteristics.web_frameworks.append(dep_name)
         | 
| 310 | 
            -
                            elif any(fw in dep_lower for fw in ['react', 'vue', 'angular', 'svelte']):
         | 
| 311 | 
            -
                                characteristics.frameworks.append(dep_name)
         | 
| 312 | 
            -
                            elif any(db in dep_lower for db in ['mysql', 'postgres', 'mongodb', 'redis']):
         | 
| 313 | 
            -
                                characteristics.databases.append(dep_name)
         | 
| 314 | 
            -
                            elif any(test in dep_lower for test in ['jest', 'mocha', 'cypress', 'playwright']):
         | 
| 315 | 
            -
                                if not characteristics.testing_framework:
         | 
| 316 | 
            -
                                    characteristics.testing_framework = dep_name
         | 
| 317 | 
            -
                            
         | 
| 318 | 
            -
                            characteristics.key_dependencies.append(dep_name)
         | 
| 319 | 
            -
                        
         | 
| 320 | 
            -
                        # Check scripts for build tools
         | 
| 321 | 
            -
                        scripts = package_data.get('scripts', {})
         | 
| 322 | 
            -
                        for script_name, script_cmd in scripts.items():
         | 
| 323 | 
            -
                            if any(tool in script_cmd for tool in ['webpack', 'rollup', 'vite', 'parcel']):
         | 
| 324 | 
            -
                                characteristics.build_tools.append(script_name)
         | 
| 325 | 
            -
                                
         | 
| 326 | 
            -
                    except Exception as e:
         | 
| 327 | 
            -
                        self.logger.warning(f"Error parsing package.json: {e}")
         | 
| 328 | 
            -
                
         | 
| 329 | 
            -
                def _parse_python_dependencies(self, deps_path: Path, characteristics: ProjectCharacteristics) -> None:
         | 
| 330 | 
            -
                    """Parse Python dependency files."""
         | 
| 331 | 
            -
                    try:
         | 
| 332 | 
            -
                        if deps_path.name == 'requirements.txt':
         | 
| 333 | 
            -
                            content = deps_path.read_text()
         | 
| 334 | 
            -
                            deps = [line.strip().split('=')[0].split('>')[0].split('<')[0] 
         | 
| 335 | 
            -
                                   for line in content.splitlines() 
         | 
| 336 | 
            -
                                   if line.strip() and not line.startswith('#')]
         | 
| 337 | 
            -
                        elif deps_path.name == 'pyproject.toml':
         | 
| 338 | 
            -
                            try:
         | 
| 339 | 
            -
                                import tomllib
         | 
| 340 | 
            -
                            except ImportError:
         | 
| 341 | 
            -
                                try:
         | 
| 342 | 
            -
                                    import tomli as tomllib
         | 
| 343 | 
            -
                                except ImportError:
         | 
| 344 | 
            -
                                    self.logger.warning(f"TOML parsing not available for {deps_path}")
         | 
| 345 | 
            -
                                    return
         | 
| 346 | 
            -
                            with open(deps_path, 'rb') as f:
         | 
| 347 | 
            -
                                data = tomllib.load(f)
         | 
| 348 | 
            -
                            deps = list(data.get('project', {}).get('dependencies', []))
         | 
| 349 | 
            -
                            deps.extend(list(data.get('tool', {}).get('poetry', {}).get('dependencies', {}).keys()))
         | 
| 350 | 
            -
                        else:
         | 
| 351 | 
            -
                            return
         | 
| 352 | 
            -
                        
         | 
| 353 | 
            -
                        # Identify frameworks and tools
         | 
| 354 | 
            -
                        for dep in deps:
         | 
| 355 | 
            -
                            dep_lower = dep.lower()
         | 
| 356 | 
            -
                            
         | 
| 357 | 
            -
                            # Web frameworks
         | 
| 358 | 
            -
                            if dep_lower in ['flask', 'django', 'fastapi', 'tornado']:
         | 
| 359 | 
            -
                                characteristics.web_frameworks.append(dep)
         | 
| 360 | 
            -
                            elif dep_lower in ['pytest', 'unittest2', 'nose']:
         | 
| 361 | 
            -
                                if not characteristics.testing_framework:
         | 
| 362 | 
            -
                                    characteristics.testing_framework = dep
         | 
| 363 | 
            -
                            elif any(db in dep_lower for db in ['psycopg2', 'mysql', 'sqlite', 'redis', 'mongo']):
         | 
| 364 | 
            -
                                characteristics.databases.append(dep)
         | 
| 365 | 
            -
                            
         | 
| 366 | 
            -
                            characteristics.key_dependencies.append(dep)
         | 
| 367 | 
            -
                            
         | 
| 368 | 
            -
                    except Exception as e:
         | 
| 369 | 
            -
                        self.logger.warning(f"Error parsing Python dependencies: {e}")
         | 
| 370 | 
            -
                
         | 
| 371 | 
            -
                def _parse_cargo_toml(self, cargo_path: Path, characteristics: ProjectCharacteristics) -> None:
         | 
| 372 | 
            -
                    """Parse Cargo.toml for Rust project details."""
         | 
| 373 | 
            -
                    try:
         | 
| 374 | 
            -
                        try:
         | 
| 375 | 
            -
                            import tomllib
         | 
| 376 | 
            -
                        except ImportError:
         | 
| 377 | 
            -
                            try:
         | 
| 378 | 
            -
                                import tomli as tomllib
         | 
| 379 | 
            -
                            except ImportError:
         | 
| 380 | 
            -
                                self.logger.warning(f"TOML parsing not available for {cargo_path}")
         | 
| 381 | 
            -
                                return
         | 
| 382 | 
            -
                        with open(cargo_path, 'rb') as f:
         | 
| 383 | 
            -
                            cargo_data = tomllib.load(f)
         | 
| 384 | 
            -
                        
         | 
| 385 | 
            -
                        deps = cargo_data.get('dependencies', {})
         | 
| 386 | 
            -
                        for dep_name in deps.keys():
         | 
| 387 | 
            -
                            characteristics.key_dependencies.append(dep_name)
         | 
| 388 | 
            -
                            
         | 
| 389 | 
            -
                            # Identify common Rust frameworks
         | 
| 390 | 
            -
                            if dep_name in ['actix-web', 'warp', 'rocket']:
         | 
| 391 | 
            -
                                characteristics.web_frameworks.append(dep_name)
         | 
| 392 | 
            -
                            elif dep_name in ['tokio', 'async-std']:
         | 
| 393 | 
            -
                                characteristics.frameworks.append(dep_name)
         | 
| 394 | 
            -
                                
         | 
| 395 | 
            -
                    except Exception as e:
         | 
| 396 | 
            -
                        self.logger.warning(f"Error parsing Cargo.toml: {e}")
         | 
| 397 | 
            -
                
         | 
| 398 | 
            -
                def _analyze_directory_structure(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 399 | 
            -
                    """Analyze directory structure for architecture patterns.
         | 
| 400 | 
            -
                    
         | 
| 401 | 
            -
                    WHY: Directory structure reveals architectural decisions and project
         | 
| 402 | 
            -
                    organization patterns that agents should understand and follow.
         | 
| 403 | 
            -
                    
         | 
| 404 | 
            -
                    Args:
         | 
| 405 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 406 | 
            -
                    """
         | 
| 407 | 
            -
                    # Common important directories to look for
         | 
| 408 | 
            -
                    important_dirs = [
         | 
| 409 | 
            -
                        'src', 'lib', 'app', 'components', 'services', 'models', 'views',
         | 
| 410 | 
            -
                        'controllers', 'routes', 'api', 'web', 'static', 'templates',
         | 
| 411 | 
            -
                        'tests', 'test', '__tests__', 'spec', 'docs', 'documentation',
         | 
| 412 | 
            -
                        'config', 'configs', 'settings', 'utils', 'helpers', 'core',
         | 
| 413 | 
            -
                        'modules', 'packages', 'plugins', 'extensions'
         | 
| 414 | 
            -
                    ]
         | 
| 415 | 
            -
                    
         | 
| 416 | 
            -
                    # Check which directories exist
         | 
| 417 | 
            -
                    existing_dirs = []
         | 
| 418 | 
            -
                    for dir_name in important_dirs:
         | 
| 419 | 
            -
                        dir_path = self.working_directory / dir_name
         | 
| 420 | 
            -
                        if dir_path.exists() and dir_path.is_dir():
         | 
| 421 | 
            -
                            existing_dirs.append(dir_name)
         | 
| 422 | 
            -
                            
         | 
| 423 | 
            -
                            # Special handling for certain directories
         | 
| 424 | 
            -
                            if dir_name in ['src', 'lib', 'app']:
         | 
| 425 | 
            -
                                # These are likely main module directories
         | 
| 426 | 
            -
                                characteristics.main_modules.extend(self._get_subdirectories(dir_path))
         | 
| 427 | 
            -
                    
         | 
| 428 | 
            -
                    characteristics.key_directories = existing_dirs
         | 
| 429 | 
            -
                    
         | 
| 430 | 
            -
                    # Look for entry points
         | 
| 431 | 
            -
                    entry_point_patterns = [
         | 
| 432 | 
            -
                        'main.py', 'app.py', 'server.py', 'index.js', 'main.js',
         | 
| 433 | 
            -
                        'app.js', 'server.js', 'main.rs', 'lib.rs', 'Main.java',
         | 
| 434 | 
            -
                        'main.go', 'index.php', 'application.rb'
         | 
| 435 | 
            -
                    ]
         | 
| 436 | 
            -
                    
         | 
| 437 | 
            -
                    for pattern in entry_point_patterns:
         | 
| 438 | 
            -
                        entry_path = self.working_directory / pattern
         | 
| 439 | 
            -
                        if entry_path.exists():
         | 
| 440 | 
            -
                            characteristics.entry_points.append(pattern)
         | 
| 441 | 
            -
                        
         | 
| 442 | 
            -
                        # Also check in src/ directory
         | 
| 443 | 
            -
                        src_entry_path = self.working_directory / 'src' / pattern
         | 
| 444 | 
            -
                        if src_entry_path.exists():
         | 
| 445 | 
            -
                            characteristics.entry_points.append(f'src/{pattern}')
         | 
| 446 | 
            -
                
         | 
| 447 | 
            -
                def _get_subdirectories(self, path: Path, max_depth: int = 2) -> List[str]:
         | 
| 448 | 
            -
                    """Get subdirectory names up to a certain depth."""
         | 
| 449 | 
            -
                    subdirs = []
         | 
| 450 | 
            -
                    try:
         | 
| 451 | 
            -
                        for item in path.iterdir():
         | 
| 452 | 
            -
                            if item.is_dir() and not item.name.startswith('.'):
         | 
| 453 | 
            -
                                subdirs.append(item.name)
         | 
| 454 | 
            -
                                if max_depth > 1:
         | 
| 455 | 
            -
                                    for subitem in item.iterdir():
         | 
| 456 | 
            -
                                        if subitem.is_dir() and not subitem.name.startswith('.'):
         | 
| 457 | 
            -
                                            subdirs.append(f"{item.name}/{subitem.name}")
         | 
| 458 | 
            -
                    except PermissionError:
         | 
| 459 | 
            -
                        pass
         | 
| 460 | 
            -
                    return subdirs[:10]  # Limit to prevent overwhelming output
         | 
| 461 | 
            -
                
         | 
| 462 | 
            -
                def _analyze_source_code(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 463 | 
            -
                    """Analyze source code files for patterns and conventions.
         | 
| 464 | 
            -
                    
         | 
| 465 | 
            -
                    WHY: Source code contains the actual implementation patterns that agents
         | 
| 466 | 
            -
                    should understand and follow. This analysis extracts coding conventions
         | 
| 467 | 
            -
                    and architectural patterns from the codebase.
         | 
| 468 | 
            -
                    
         | 
| 469 | 
            -
                    Args:
         | 
| 470 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 471 | 
            -
                    """
         | 
| 472 | 
            -
                    source_extensions = {
         | 
| 473 | 
            -
                        '.py': 'python',
         | 
| 474 | 
            -
                        '.js': 'javascript', 
         | 
| 475 | 
            -
                        '.ts': 'typescript',
         | 
| 476 | 
            -
                        '.jsx': 'react',
         | 
| 477 | 
            -
                        '.tsx': 'react',
         | 
| 478 | 
            -
                        '.rs': 'rust',
         | 
| 479 | 
            -
                        '.java': 'java',
         | 
| 480 | 
            -
                        '.go': 'go',
         | 
| 481 | 
            -
                        '.php': 'php',
         | 
| 482 | 
            -
                        '.rb': 'ruby',
         | 
| 483 | 
            -
                        '.cpp': 'cpp',
         | 
| 484 | 
            -
                        '.cc': 'cpp',
         | 
| 485 | 
            -
                        '.c': 'c'
         | 
| 486 | 
            -
                    }
         | 
| 487 | 
            -
                    
         | 
| 488 | 
            -
                    # Find source files
         | 
| 489 | 
            -
                    source_files = []
         | 
| 490 | 
            -
                    languages_found = set()
         | 
| 491 | 
            -
                    
         | 
| 492 | 
            -
                    for ext, lang in source_extensions.items():
         | 
| 493 | 
            -
                        files = list(self.working_directory.rglob(f'*{ext}'))
         | 
| 494 | 
            -
                        # Filter out node_modules, .git, etc.
         | 
| 495 | 
            -
                        files = [f for f in files if not any(part.startswith('.') or part == 'node_modules' 
         | 
| 496 | 
            -
                                                            for part in f.parts)]
         | 
| 497 | 
            -
                        source_files.extend(files)
         | 
| 498 | 
            -
                        if files:
         | 
| 499 | 
            -
                            languages_found.add(lang)
         | 
| 500 | 
            -
                    
         | 
| 501 | 
            -
                    # Update languages found
         | 
| 502 | 
            -
                    characteristics.languages.extend([lang for lang in languages_found 
         | 
| 503 | 
            -
                                                    if lang not in characteristics.languages])
         | 
| 504 | 
            -
                    
         | 
| 505 | 
            -
                    # Analyze a sample of source files for patterns
         | 
| 506 | 
            -
                    sample_files = source_files[:20]  # Don't analyze too many files
         | 
| 507 | 
            -
                    
         | 
| 508 | 
            -
                    framework_mentions = Counter()
         | 
| 509 | 
            -
                    pattern_mentions = Counter()
         | 
| 510 | 
            -
                    
         | 
| 511 | 
            -
                    for file_path in sample_files:
         | 
| 512 | 
            -
                        try:
         | 
| 513 | 
            -
                            content = file_path.read_text(encoding='utf-8', errors='ignore')
         | 
| 514 | 
            -
                            
         | 
| 515 | 
            -
                            # Look for framework patterns
         | 
| 516 | 
            -
                            for framework, patterns in self.FRAMEWORK_PATTERNS.items():
         | 
| 517 | 
            -
                                if any(pattern in content for pattern in patterns):
         | 
| 518 | 
            -
                                    framework_mentions[framework] += 1
         | 
| 519 | 
            -
                            
         | 
| 520 | 
            -
                            # Look for database patterns
         | 
| 521 | 
            -
                            for db, patterns in self.DATABASE_PATTERNS.items():
         | 
| 522 | 
            -
                                if any(pattern in content for pattern in patterns):
         | 
| 523 | 
            -
                                    if db not in characteristics.databases:
         | 
| 524 | 
            -
                                        characteristics.databases.append(db)
         | 
| 525 | 
            -
                            
         | 
| 526 | 
            -
                            # Look for common patterns
         | 
| 527 | 
            -
                            if 'class ' in content and 'def __init__' in content:
         | 
| 528 | 
            -
                                pattern_mentions['object_oriented'] += 1
         | 
| 529 | 
            -
                            if '@app.route' in content or 'app.get(' in content:
         | 
| 530 | 
            -
                                pattern_mentions['web_routes'] += 1
         | 
| 531 | 
            -
                            if 'async def' in content or 'async function' in content:
         | 
| 532 | 
            -
                                pattern_mentions['async_programming'] += 1
         | 
| 533 | 
            -
                            if 'import pytest' in content or 'describe(' in content:
         | 
| 534 | 
            -
                                pattern_mentions['unit_testing'] += 1
         | 
| 535 | 
            -
                                
         | 
| 536 | 
            -
                        except Exception as e:
         | 
| 537 | 
            -
                            self.logger.debug(f"Error analyzing {file_path}: {e}")
         | 
| 538 | 
            -
                            continue
         | 
| 539 | 
            -
                    
         | 
| 540 | 
            -
                    # Add discovered frameworks
         | 
| 541 | 
            -
                    for framework, count in framework_mentions.most_common(5):
         | 
| 542 | 
            -
                        if framework not in characteristics.frameworks:
         | 
| 543 | 
            -
                            characteristics.frameworks.append(framework)
         | 
| 544 | 
            -
                    
         | 
| 545 | 
            -
                    # Add coding conventions based on patterns found
         | 
| 546 | 
            -
                    for pattern, count in pattern_mentions.most_common():
         | 
| 547 | 
            -
                        if count >= 2:  # Pattern appears in multiple files
         | 
| 548 | 
            -
                            characteristics.code_conventions.append(pattern.replace('_', ' ').title())
         | 
| 549 | 
            -
                
         | 
| 550 | 
            -
                def _analyze_dependencies(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 551 | 
            -
                    """Analyze dependencies for integration patterns.
         | 
| 552 | 
            -
                    
         | 
| 553 | 
            -
                    Args:
         | 
| 554 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 555 | 
            -
                    """
         | 
| 556 | 
            -
                    # This is partially covered by config file analysis
         | 
| 557 | 
            -
                    # Here we can add more sophisticated dependency analysis
         | 
| 558 | 
            -
                    
         | 
| 559 | 
            -
                    # Look for common integration patterns in dependencies
         | 
| 560 | 
            -
                    api_indicators = [
         | 
| 561 | 
            -
                        'requests', 'axios', 'fetch', 'http', 'urllib',
         | 
| 562 | 
            -
                        'rest', 'graphql', 'grpc', 'soap'
         | 
| 563 | 
            -
                    ]
         | 
| 564 | 
            -
                    
         | 
| 565 | 
            -
                    for dep in characteristics.key_dependencies:
         | 
| 566 | 
            -
                        dep_lower = dep.lower()
         | 
| 567 | 
            -
                        for indicator in api_indicators:
         | 
| 568 | 
            -
                            if indicator in dep_lower:
         | 
| 569 | 
            -
                                if 'REST API' not in characteristics.api_patterns:
         | 
| 570 | 
            -
                                    characteristics.api_patterns.append('REST API')
         | 
| 571 | 
            -
                                break
         | 
| 572 | 
            -
                
         | 
| 573 | 
            -
                def _analyze_testing_patterns(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 574 | 
            -
                    """Analyze testing patterns and frameworks.
         | 
| 575 | 
            -
                    
         | 
| 576 | 
            -
                    Args:
         | 
| 577 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 578 | 
            -
                    """
         | 
| 579 | 
            -
                    test_dirs = ['tests', 'test', '__tests__', 'spec']
         | 
| 580 | 
            -
                    test_patterns = []
         | 
| 581 | 
            -
                    
         | 
| 582 | 
            -
                    for test_dir in test_dirs:
         | 
| 583 | 
            -
                        test_path = self.working_directory / test_dir
         | 
| 584 | 
            -
                        if test_path.exists() and test_path.is_dir():
         | 
| 585 | 
            -
                            test_patterns.append(f"Tests in /{test_dir}/ directory")
         | 
| 586 | 
            -
                            
         | 
| 587 | 
            -
                            # Look for test files to understand patterns
         | 
| 588 | 
            -
                            test_files = list(test_path.rglob('*.py')) + list(test_path.rglob('*.js')) + list(test_path.rglob('*.ts'))
         | 
| 589 | 
            -
                            
         | 
| 590 | 
            -
                            for test_file in test_files[:5]:  # Sample a few test files
         | 
| 591 | 
            -
                                try:
         | 
| 592 | 
            -
                                    content = test_file.read_text(encoding='utf-8', errors='ignore')
         | 
| 593 | 
            -
                                    
         | 
| 594 | 
            -
                                    if 'def test_' in content:
         | 
| 595 | 
            -
                                        test_patterns.append("Python unittest pattern")
         | 
| 596 | 
            -
                                    if 'describe(' in content and 'it(' in content:
         | 
| 597 | 
            -
                                        test_patterns.append("BDD test pattern")
         | 
| 598 | 
            -
                                    if '@pytest.fixture' in content:
         | 
| 599 | 
            -
                                        test_patterns.append("pytest fixtures")
         | 
| 600 | 
            -
                                    if 'beforeEach(' in content or 'beforeAll(' in content:
         | 
| 601 | 
            -
                                        test_patterns.append("Setup/teardown patterns")
         | 
| 602 | 
            -
                                        
         | 
| 603 | 
            -
                                except Exception:
         | 
| 604 | 
            -
                                    continue
         | 
| 605 | 
            -
                    
         | 
| 606 | 
            -
                    characteristics.test_patterns = list(set(test_patterns))
         | 
| 607 | 
            -
                
         | 
| 608 | 
            -
                def _analyze_documentation(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 609 | 
            -
                    """Analyze documentation files.
         | 
| 610 | 
            -
                    
         | 
| 611 | 
            -
                    Args:
         | 
| 612 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 613 | 
            -
                    """
         | 
| 614 | 
            -
                    doc_patterns = [
         | 
| 615 | 
            -
                        'README.md', 'README.rst', 'README.txt',
         | 
| 616 | 
            -
                        'CONTRIBUTING.md', 'CHANGELOG.md', 'HISTORY.md',
         | 
| 617 | 
            -
                        'docs/', 'documentation/', 'wiki/'
         | 
| 618 | 
            -
                    ]
         | 
| 619 | 
            -
                    
         | 
| 620 | 
            -
                    doc_files = []
         | 
| 621 | 
            -
                    for pattern in doc_patterns:
         | 
| 622 | 
            -
                        doc_path = self.working_directory / pattern
         | 
| 623 | 
            -
                        if doc_path.exists():
         | 
| 624 | 
            -
                            if doc_path.is_file():
         | 
| 625 | 
            -
                                doc_files.append(pattern)
         | 
| 626 | 
            -
                            elif doc_path.is_dir():
         | 
| 627 | 
            -
                                # Find markdown files in doc directories
         | 
| 628 | 
            -
                                md_files = list(doc_path.rglob('*.md'))[:10]
         | 
| 629 | 
            -
                                doc_files.extend([str(f.relative_to(self.working_directory)) for f in md_files])
         | 
| 630 | 
            -
                    
         | 
| 631 | 
            -
                    characteristics.documentation_files = doc_files
         | 
| 632 | 
            -
                
         | 
| 633 | 
            -
                def _infer_architecture_type(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 634 | 
            -
                    """Infer architecture type based on discovered patterns.
         | 
| 635 | 
            -
                    
         | 
| 636 | 
            -
                    Args:
         | 
| 637 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 638 | 
            -
                    """
         | 
| 639 | 
            -
                    # Simple architecture inference based on patterns
         | 
| 640 | 
            -
                    if any(fw in characteristics.web_frameworks for fw in ['flask', 'django', 'express', 'fastapi']):
         | 
| 641 | 
            -
                        if 'api' in characteristics.key_directories:
         | 
| 642 | 
            -
                            characteristics.architecture_type = "REST API Service"
         | 
| 643 | 
            -
                        else:
         | 
| 644 | 
            -
                            characteristics.architecture_type = "Web Application"
         | 
| 645 | 
            -
                    elif 'services' in characteristics.key_directories:
         | 
| 646 | 
            -
                        characteristics.architecture_type = "Service-Oriented Architecture"
         | 
| 647 | 
            -
                    elif 'modules' in characteristics.key_directories or 'packages' in characteristics.key_directories:
         | 
| 648 | 
            -
                        characteristics.architecture_type = "Modular Architecture"
         | 
| 649 | 
            -
                    elif characteristics.primary_language == 'python' and 'cli' in characteristics.main_modules:
         | 
| 650 | 
            -
                        characteristics.architecture_type = "CLI Application"
         | 
| 651 | 
            -
                    elif any('react' in fw.lower() for fw in characteristics.frameworks):
         | 
| 652 | 
            -
                        characteristics.architecture_type = "Single Page Application"
         | 
| 653 | 
            -
                    else:
         | 
| 654 | 
            -
                        characteristics.architecture_type = "Standard Application"
         | 
| 655 | 
            -
                
         | 
| 656 | 
            -
                def _extract_project_terminology(self, characteristics: ProjectCharacteristics) -> None:
         | 
| 657 | 
            -
                    """Extract project-specific terminology from various sources.
         | 
| 658 | 
            -
                    
         | 
| 659 | 
            -
                    WHY: Projects often have domain-specific terminology that agents should
         | 
| 660 | 
            -
                    understand and use consistently.
         | 
| 661 | 
            -
                    
         | 
| 662 | 
            -
                    Args:
         | 
| 663 | 
            -
                        characteristics: ProjectCharacteristics object to update
         | 
| 664 | 
            -
                    """
         | 
| 665 | 
            -
                    terminology = set()
         | 
| 666 | 
            -
                    
         | 
| 667 | 
            -
                    # Extract from project name
         | 
| 668 | 
            -
                    project_words = re.findall(r'[A-Z][a-z]+|[a-z]+', characteristics.project_name)
         | 
| 669 | 
            -
                    terminology.update(project_words)
         | 
| 670 | 
            -
                    
         | 
| 671 | 
            -
                    # Extract from directory names
         | 
| 672 | 
            -
                    for dir_name in characteristics.key_directories:
         | 
| 673 | 
            -
                        words = re.findall(r'[A-Z][a-z]+|[a-z]+', dir_name)
         | 
| 674 | 
            -
                        terminology.update(words)
         | 
| 675 | 
            -
                    
         | 
| 676 | 
            -
                    # Extract from main modules
         | 
| 677 | 
            -
                    for module in characteristics.main_modules:
         | 
| 678 | 
            -
                        words = re.findall(r'[A-Z][a-z]+|[a-z]+', module)
         | 
| 679 | 
            -
                        terminology.update(words)
         | 
| 680 | 
            -
                    
         | 
| 681 | 
            -
                    # Filter out common words and keep domain-specific terms
         | 
| 682 | 
            -
                    common_words = {
         | 
| 683 | 
            -
                        'src', 'lib', 'app', 'main', 'test', 'tests', 'docs', 'config',
         | 
| 684 | 
            -
                        'utils', 'helpers', 'core', 'base', 'common', 'shared', 'public',
         | 
| 685 | 
            -
                        'private', 'static', 'assets', 'build', 'dist', 'node', 'modules'
         | 
| 686 | 
            -
                    }
         | 
| 687 | 
            -
                    
         | 
| 688 | 
            -
                    domain_terms = [term for term in terminology 
         | 
| 689 | 
            -
                                   if len(term) > 3 and term.lower() not in common_words]
         | 
| 690 | 
            -
                    
         | 
| 691 | 
            -
                    characteristics.project_terminology = list(set(domain_terms))[:10]  # Limit to most relevant
         | 
| 692 | 
            -
                
         | 
| 693 | 
            -
                def get_project_context_summary(self) -> str:
         | 
| 694 | 
            -
                    """Get a concise summary of project context for memory templates.
         | 
| 695 | 
            -
                    
         | 
| 696 | 
            -
                    WHY: Provides a formatted summary specifically designed for inclusion
         | 
| 697 | 
            -
                    in agent memory templates, focusing on the most relevant characteristics.
         | 
| 698 | 
            -
                    
         | 
| 699 | 
            -
                    Returns:
         | 
| 700 | 
            -
                        str: Formatted project context summary
         | 
| 701 | 
            -
                    """
         | 
| 702 | 
            -
                    characteristics = self.analyze_project()
         | 
| 703 | 
            -
                    
         | 
| 704 | 
            -
                    summary_parts = []
         | 
| 705 | 
            -
                    
         | 
| 706 | 
            -
                    # Basic project info
         | 
| 707 | 
            -
                    lang_info = characteristics.primary_language or "mixed"
         | 
| 708 | 
            -
                    if characteristics.languages and len(characteristics.languages) > 1:
         | 
| 709 | 
            -
                        lang_info = f"{lang_info} (with {', '.join(characteristics.languages[1:3])})"
         | 
| 710 | 
            -
                    
         | 
| 711 | 
            -
                    summary_parts.append(f"{characteristics.project_name}: {lang_info} {characteristics.architecture_type.lower()}")
         | 
| 712 | 
            -
                    
         | 
| 713 | 
            -
                    # Key directories and modules
         | 
| 714 | 
            -
                    if characteristics.main_modules:
         | 
| 715 | 
            -
                        modules_str = ", ".join(characteristics.main_modules[:4])
         | 
| 716 | 
            -
                        summary_parts.append(f"- Main modules: {modules_str}")
         | 
| 717 | 
            -
                    
         | 
| 718 | 
            -
                    # Frameworks and tools
         | 
| 719 | 
            -
                    if characteristics.frameworks or characteristics.web_frameworks:
         | 
| 720 | 
            -
                        all_frameworks = characteristics.frameworks + characteristics.web_frameworks
         | 
| 721 | 
            -
                        frameworks_str = ", ".join(all_frameworks[:3])
         | 
| 722 | 
            -
                        summary_parts.append(f"- Uses: {frameworks_str}")
         | 
| 723 | 
            -
                    
         | 
| 724 | 
            -
                    # Testing
         | 
| 725 | 
            -
                    if characteristics.testing_framework:
         | 
| 726 | 
            -
                        summary_parts.append(f"- Testing: {characteristics.testing_framework}")
         | 
| 727 | 
            -
                    elif characteristics.test_patterns:
         | 
| 728 | 
            -
                        summary_parts.append(f"- Testing: {characteristics.test_patterns[0]}")
         | 
| 729 | 
            -
                    
         | 
| 730 | 
            -
                    # Key patterns
         | 
| 731 | 
            -
                    if characteristics.code_conventions:
         | 
| 732 | 
            -
                        patterns_str = ", ".join(characteristics.code_conventions[:2])
         | 
| 733 | 
            -
                        summary_parts.append(f"- Key patterns: {patterns_str}")
         | 
| 734 | 
            -
                    
         | 
| 735 | 
            -
                    return "\n".join(summary_parts)
         | 
| 736 | 
            -
                
         | 
| 737 | 
            -
                def get_important_files_for_context(self) -> List[str]:
         | 
| 738 | 
            -
                    """Get list of important files that should be considered for memory context.
         | 
| 739 | 
            -
                    
         | 
| 740 | 
            -
                    WHY: Instead of hardcoding which files to analyze for memory creation,
         | 
| 741 | 
            -
                    this method dynamically determines the most relevant files based on
         | 
| 742 | 
            -
                    the actual project structure.
         | 
| 743 | 
            -
                    
         | 
| 744 | 
            -
                    Returns:
         | 
| 745 | 
            -
                        List[str]: List of file paths relative to project root
         | 
| 746 | 
            -
                    """
         | 
| 747 | 
            -
                    characteristics = self.analyze_project()
         | 
| 748 | 
            -
                    important_files = []
         | 
| 749 | 
            -
                    
         | 
| 750 | 
            -
                    # Always include standard documentation
         | 
| 751 | 
            -
                    standard_docs = ['README.md', 'CONTRIBUTING.md', 'CHANGELOG.md']
         | 
| 752 | 
            -
                    for doc in standard_docs:
         | 
| 753 | 
            -
                        if (self.working_directory / doc).exists():
         | 
| 754 | 
            -
                            important_files.append(doc)
         | 
| 755 | 
            -
                    
         | 
| 756 | 
            -
                    # Include configuration files
         | 
| 757 | 
            -
                    important_files.extend(characteristics.important_configs)
         | 
| 758 | 
            -
                    
         | 
| 759 | 
            -
                    # Include project-specific documentation
         | 
| 760 | 
            -
                    important_files.extend(characteristics.documentation_files[:5])
         | 
| 761 | 
            -
                    
         | 
| 762 | 
            -
                    # Include entry points
         | 
| 763 | 
            -
                    important_files.extend(characteristics.entry_points)
         | 
| 764 | 
            -
                    
         | 
| 765 | 
            -
                    # Look for architecture documentation
         | 
| 766 | 
            -
                    arch_patterns = ['ARCHITECTURE.md', 'docs/architecture.md', 'docs/STRUCTURE.md']
         | 
| 767 | 
            -
                    for pattern in arch_patterns:
         | 
| 768 | 
            -
                        if (self.working_directory / pattern).exists():
         | 
| 769 | 
            -
                            important_files.append(pattern)
         | 
| 770 | 
            -
                    
         | 
| 771 | 
            -
                    # Remove duplicates and return
         | 
| 772 | 
            -
                    return list(set(important_files))
         | 
| 773 | 
            -
                
         | 
| 774 | 
            -
                # ================================================================================
         | 
| 775 | 
            -
                # Interface Adapter Methods
         | 
| 776 | 
            -
                # ================================================================================
         | 
| 777 | 
            -
                # These methods adapt the existing implementation to comply with ProjectAnalyzerInterface
         | 
| 778 | 
            -
                
         | 
| 779 | 
            -
                def detect_technology_stack(self) -> List[str]:
         | 
| 780 | 
            -
                    """Detect technologies used in the project.
         | 
| 781 | 
            -
                    
         | 
| 782 | 
            -
                    WHY: This adapter method provides interface compliance by extracting
         | 
| 783 | 
            -
                    technology information from the analyzed project characteristics.
         | 
| 784 | 
            -
                    
         | 
| 785 | 
            -
                    Returns:
         | 
| 786 | 
            -
                        List of detected technologies
         | 
| 787 | 
            -
                    """
         | 
| 788 | 
            -
                    characteristics = self.analyze_project()
         | 
| 789 | 
            -
                    
         | 
| 790 | 
            -
                    technologies = []
         | 
| 791 | 
            -
                    technologies.extend(characteristics.languages)
         | 
| 792 | 
            -
                    technologies.extend(characteristics.frameworks)
         | 
| 793 | 
            -
                    technologies.extend(characteristics.web_frameworks)
         | 
| 794 | 
            -
                    technologies.extend(characteristics.databases)
         | 
| 795 | 
            -
                    
         | 
| 796 | 
            -
                    # Add package manager as technology
         | 
| 797 | 
            -
                    if characteristics.package_manager:
         | 
| 798 | 
            -
                        technologies.append(characteristics.package_manager)
         | 
| 799 | 
            -
                    
         | 
| 800 | 
            -
                    # Add build tools
         | 
| 801 | 
            -
                    technologies.extend(characteristics.build_tools)
         | 
| 802 | 
            -
                    
         | 
| 803 | 
            -
                    # Remove duplicates
         | 
| 804 | 
            -
                    return list(set(technologies))
         | 
| 805 | 
            -
                
         | 
| 806 | 
            -
                def analyze_code_patterns(self) -> Dict[str, Any]:
         | 
| 807 | 
            -
                    """Analyze code patterns and conventions.
         | 
| 808 | 
            -
                    
         | 
| 809 | 
            -
                    WHY: This adapter method provides interface compliance by extracting
         | 
| 810 | 
            -
                    pattern information from the project characteristics.
         | 
| 811 | 
            -
                    
         | 
| 812 | 
            -
                    Returns:
         | 
| 813 | 
            -
                        Dictionary of pattern analysis results
         | 
| 814 | 
            -
                    """
         | 
| 815 | 
            -
                    characteristics = self.analyze_project()
         | 
| 816 | 
            -
                    
         | 
| 817 | 
            -
                    return {
         | 
| 818 | 
            -
                        "code_conventions": characteristics.code_conventions,
         | 
| 819 | 
            -
                        "test_patterns": characteristics.test_patterns,
         | 
| 820 | 
            -
                        "api_patterns": characteristics.api_patterns,
         | 
| 821 | 
            -
                        "configuration_patterns": characteristics.configuration_patterns,
         | 
| 822 | 
            -
                        "architecture_type": characteristics.architecture_type
         | 
| 823 | 
            -
                    }
         | 
| 824 | 
            -
                
         | 
| 825 | 
            -
                def get_project_structure(self) -> Dict[str, Any]:
         | 
| 826 | 
            -
                    """Get project directory structure analysis.
         | 
| 827 | 
            -
                    
         | 
| 828 | 
            -
                    WHY: This adapter method provides interface compliance by organizing
         | 
| 829 | 
            -
                    structural information from the project characteristics.
         | 
| 830 | 
            -
                    
         | 
| 831 | 
            -
                    Returns:
         | 
| 832 | 
            -
                        Dictionary representing project structure
         | 
| 833 | 
            -
                    """
         | 
| 834 | 
            -
                    characteristics = self.analyze_project()
         | 
| 835 | 
            -
                    
         | 
| 836 | 
            -
                    return {
         | 
| 837 | 
            -
                        "project_name": characteristics.project_name,
         | 
| 838 | 
            -
                        "main_modules": characteristics.main_modules,
         | 
| 839 | 
            -
                        "key_directories": characteristics.key_directories,
         | 
| 840 | 
            -
                        "entry_points": characteristics.entry_points,
         | 
| 841 | 
            -
                        "documentation_files": characteristics.documentation_files,
         | 
| 842 | 
            -
                        "important_configs": characteristics.important_configs,
         | 
| 843 | 
            -
                        "architecture_type": characteristics.architecture_type
         | 
| 844 | 
            -
                    }
         | 
| 845 | 
            -
                
         | 
| 846 | 
            -
                def identify_entry_points(self) -> List[Path]:
         | 
| 847 | 
            -
                    """Identify project entry points.
         | 
| 848 | 
            -
                    
         | 
| 849 | 
            -
                    WHY: This adapter method provides interface compliance by converting
         | 
| 850 | 
            -
                    string entry points to Path objects as expected by the interface.
         | 
| 851 | 
            -
                    
         | 
| 852 | 
            -
                    Returns:
         | 
| 853 | 
            -
                        List of entry point paths
         | 
| 854 | 
            -
                    """
         | 
| 855 | 
            -
                    characteristics = self.analyze_project()
         | 
| 856 | 
            -
                    
         | 
| 857 | 
            -
                    # Convert string paths to Path objects
         | 
| 858 | 
            -
                    entry_paths = []
         | 
| 859 | 
            -
                    for entry_point in characteristics.entry_points:
         | 
| 860 | 
            -
                        entry_path = self.working_directory / entry_point
         | 
| 861 | 
            -
                        if entry_path.exists():
         | 
| 862 | 
            -
                            entry_paths.append(entry_path)
         | 
| 863 | 
            -
                    
         | 
| 864 | 
            -
                    return entry_paths
         |