attune-ai 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
"""Pattern Library for Multi-Agent Collaboration
|
|
2
|
+
|
|
3
|
+
Enables AI agents to share discovered patterns with each other, accelerating
|
|
4
|
+
learning across the agent collective (Level 5: Systems Empathy).
|
|
5
|
+
|
|
6
|
+
One agent's discovery benefits all agents through pattern sharing.
|
|
7
|
+
|
|
8
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
9
|
+
Licensed under Fair Source 0.9
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Pattern:
|
|
19
|
+
"""A discovered pattern that can be shared across AI agents
|
|
20
|
+
|
|
21
|
+
Patterns represent reusable solutions, common behaviors, or
|
|
22
|
+
learned heuristics that one agent discovered and others can benefit from.
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
- Sequential patterns: "After action X, users typically need Y"
|
|
26
|
+
- Temporal patterns: "On Mondays, prioritize Z"
|
|
27
|
+
- Conditional patterns: "If context A, then approach B works best"
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
id: str
|
|
32
|
+
agent_id: str
|
|
33
|
+
pattern_type: str # "sequential", "temporal", "conditional", "behavioral"
|
|
34
|
+
name: str
|
|
35
|
+
description: str
|
|
36
|
+
context: dict[str, Any] = field(default_factory=dict)
|
|
37
|
+
code: str | None = None # Optional code implementation
|
|
38
|
+
confidence: float = 0.5 # 0.0-1.0, how confident in pattern
|
|
39
|
+
usage_count: int = 0
|
|
40
|
+
success_count: int = 0
|
|
41
|
+
failure_count: int = 0
|
|
42
|
+
discovered_at: datetime = field(default_factory=datetime.now)
|
|
43
|
+
last_used: datetime | None = None
|
|
44
|
+
tags: list[str] = field(default_factory=list)
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def success_rate(self) -> float:
|
|
48
|
+
"""Calculate success rate of pattern usage"""
|
|
49
|
+
total_uses = self.success_count + self.failure_count
|
|
50
|
+
if total_uses == 0:
|
|
51
|
+
return 0.0
|
|
52
|
+
return self.success_count / total_uses
|
|
53
|
+
|
|
54
|
+
def record_usage(self, success: bool):
|
|
55
|
+
"""Record pattern usage outcome"""
|
|
56
|
+
self.usage_count += 1
|
|
57
|
+
if success:
|
|
58
|
+
self.success_count += 1
|
|
59
|
+
else:
|
|
60
|
+
self.failure_count += 1
|
|
61
|
+
self.last_used = datetime.now()
|
|
62
|
+
|
|
63
|
+
# Update confidence based on success rate
|
|
64
|
+
if self.usage_count >= 5:
|
|
65
|
+
self.confidence = self.success_rate
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass
|
|
69
|
+
class PatternMatch:
|
|
70
|
+
"""Result of pattern matching against current context"""
|
|
71
|
+
|
|
72
|
+
pattern: Pattern
|
|
73
|
+
relevance_score: float # 0.0-1.0, how relevant to current context
|
|
74
|
+
matching_factors: list[str] # What made this pattern match
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class PatternLibrary:
|
|
78
|
+
"""Shared library for multi-agent pattern discovery and sharing
|
|
79
|
+
|
|
80
|
+
Enables Level 5 Systems Empathy: AI-AI cooperation where one agent's
|
|
81
|
+
discovery benefits all agents in the collective.
|
|
82
|
+
|
|
83
|
+
**Key Concepts:**
|
|
84
|
+
- **Pattern Discovery**: Agents detect patterns in their interactions
|
|
85
|
+
- **Pattern Contribution**: Agents share patterns with the library
|
|
86
|
+
- **Pattern Querying**: Agents query for relevant patterns before acting
|
|
87
|
+
- **Collective Learning**: All agents benefit from each discovery
|
|
88
|
+
|
|
89
|
+
**Pattern Types:**
|
|
90
|
+
1. **Sequential**: "After X, users typically need Y"
|
|
91
|
+
2. **Temporal**: "On Mondays at 9am, prioritize Z"
|
|
92
|
+
3. **Conditional**: "If context A, approach B works best"
|
|
93
|
+
4. **Behavioral**: "Users with trait X prefer style Y"
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
>>> library = PatternLibrary()
|
|
97
|
+
>>>
|
|
98
|
+
>>> # Agent 1 contributes a pattern
|
|
99
|
+
>>> pattern = Pattern(
|
|
100
|
+
... id="pat_001",
|
|
101
|
+
... agent_id="compliance_agent",
|
|
102
|
+
... pattern_type="sequential",
|
|
103
|
+
... name="Post-update documentation pattern",
|
|
104
|
+
... description="After system updates, users need help finding changed features",
|
|
105
|
+
... confidence=0.85
|
|
106
|
+
... )
|
|
107
|
+
>>> library.contribute_pattern("compliance_agent", pattern)
|
|
108
|
+
>>>
|
|
109
|
+
>>> # Agent 2 queries for relevant patterns
|
|
110
|
+
>>> context = {"recent_event": "system_update", "user_confusion": True}
|
|
111
|
+
>>> matches = library.query_patterns("documentation_agent", context)
|
|
112
|
+
>>> print(f"Found {len(matches)} relevant patterns")
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self):
|
|
117
|
+
"""Initialize PatternLibrary with optimized index structures.
|
|
118
|
+
|
|
119
|
+
Performance optimizations:
|
|
120
|
+
- patterns_by_type: O(1) lookup by pattern type
|
|
121
|
+
- patterns_by_tag: O(1) lookup by tag
|
|
122
|
+
- Reduces query_patterns from O(n) to O(k) where k = matching patterns
|
|
123
|
+
"""
|
|
124
|
+
self.patterns: dict[str, Pattern] = {} # pattern_id -> Pattern
|
|
125
|
+
self.agent_contributions: dict[str, list[str]] = {} # agent_id -> pattern_ids
|
|
126
|
+
self.pattern_graph: dict[str, list[str]] = {} # pattern_id -> related_pattern_ids
|
|
127
|
+
|
|
128
|
+
# Performance optimization: Index structures for fast lookups
|
|
129
|
+
self._patterns_by_type: dict[str, list[str]] = {} # pattern_type -> pattern_ids
|
|
130
|
+
self._patterns_by_tag: dict[str, list[str]] = {} # tag -> pattern_ids
|
|
131
|
+
|
|
132
|
+
def contribute_pattern(self, agent_id: str, pattern: Pattern) -> None:
|
|
133
|
+
"""Agent contributes a discovered pattern to the library
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
agent_id: ID of contributing agent
|
|
137
|
+
pattern: Pattern to contribute
|
|
138
|
+
|
|
139
|
+
Raises:
|
|
140
|
+
ValueError: If agent_id is empty or pattern.id already exists
|
|
141
|
+
|
|
142
|
+
Example:
|
|
143
|
+
>>> pattern = Pattern(
|
|
144
|
+
... id="pat_002",
|
|
145
|
+
... agent_id="agent_1",
|
|
146
|
+
... pattern_type="conditional",
|
|
147
|
+
... name="High-stakes decision pattern",
|
|
148
|
+
... description="For high-stakes decisions, provide options with tradeoffs",
|
|
149
|
+
... confidence=0.9
|
|
150
|
+
... )
|
|
151
|
+
>>> library.contribute_pattern("agent_1", pattern)
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
# Validate inputs
|
|
155
|
+
if not agent_id or not agent_id.strip():
|
|
156
|
+
raise ValueError("agent_id cannot be empty")
|
|
157
|
+
|
|
158
|
+
if pattern.id in self.patterns:
|
|
159
|
+
raise ValueError(
|
|
160
|
+
f"Pattern '{pattern.id}' already exists. "
|
|
161
|
+
f"Use a different ID or remove the existing pattern first."
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Store pattern
|
|
165
|
+
self.patterns[pattern.id] = pattern
|
|
166
|
+
|
|
167
|
+
# Track agent contribution
|
|
168
|
+
if agent_id not in self.agent_contributions:
|
|
169
|
+
self.agent_contributions[agent_id] = []
|
|
170
|
+
self.agent_contributions[agent_id].append(pattern.id)
|
|
171
|
+
|
|
172
|
+
# Initialize pattern graph entry
|
|
173
|
+
if pattern.id not in self.pattern_graph:
|
|
174
|
+
self.pattern_graph[pattern.id] = []
|
|
175
|
+
|
|
176
|
+
# Update index structures for O(1) lookups
|
|
177
|
+
if pattern.pattern_type not in self._patterns_by_type:
|
|
178
|
+
self._patterns_by_type[pattern.pattern_type] = []
|
|
179
|
+
self._patterns_by_type[pattern.pattern_type].append(pattern.id)
|
|
180
|
+
|
|
181
|
+
for tag in pattern.tags:
|
|
182
|
+
if tag not in self._patterns_by_tag:
|
|
183
|
+
self._patterns_by_tag[tag] = []
|
|
184
|
+
self._patterns_by_tag[tag].append(pattern.id)
|
|
185
|
+
|
|
186
|
+
def query_patterns(
|
|
187
|
+
self,
|
|
188
|
+
agent_id: str,
|
|
189
|
+
context: dict[str, Any],
|
|
190
|
+
pattern_type: str | None = None,
|
|
191
|
+
min_confidence: float = 0.5,
|
|
192
|
+
limit: int = 10,
|
|
193
|
+
) -> list[PatternMatch]:
|
|
194
|
+
"""Query relevant patterns for current context
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
agent_id: ID of querying agent
|
|
198
|
+
context: Current context dictionary
|
|
199
|
+
pattern_type: Optional filter by pattern type
|
|
200
|
+
min_confidence: Minimum confidence threshold (0-1)
|
|
201
|
+
limit: Maximum patterns to return
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
List of PatternMatch objects, sorted by relevance
|
|
205
|
+
|
|
206
|
+
Raises:
|
|
207
|
+
ValueError: If agent_id is empty, min_confidence out of range, or limit < 1
|
|
208
|
+
TypeError: If context is not a dictionary
|
|
209
|
+
|
|
210
|
+
Example:
|
|
211
|
+
>>> context = {
|
|
212
|
+
... "user_role": "developer",
|
|
213
|
+
... "task_type": "debugging",
|
|
214
|
+
... "time_of_day": "morning"
|
|
215
|
+
... }
|
|
216
|
+
>>> matches = library.query_patterns("debug_agent", context, min_confidence=0.7)
|
|
217
|
+
|
|
218
|
+
"""
|
|
219
|
+
# Validate inputs
|
|
220
|
+
if not agent_id or not agent_id.strip():
|
|
221
|
+
raise ValueError("agent_id cannot be empty")
|
|
222
|
+
|
|
223
|
+
if not isinstance(context, dict):
|
|
224
|
+
raise TypeError(f"context must be dict, got {type(context).__name__}")
|
|
225
|
+
|
|
226
|
+
if not 0.0 <= min_confidence <= 1.0:
|
|
227
|
+
raise ValueError(f"min_confidence must be 0-1, got {min_confidence}")
|
|
228
|
+
|
|
229
|
+
if limit < 1:
|
|
230
|
+
raise ValueError(f"limit must be positive, got {limit}")
|
|
231
|
+
|
|
232
|
+
matches: list[PatternMatch] = []
|
|
233
|
+
|
|
234
|
+
# Performance optimization: Use index for pattern_type filter (O(1) vs O(n))
|
|
235
|
+
if pattern_type:
|
|
236
|
+
# Only check patterns of the requested type
|
|
237
|
+
# Use generator to avoid creating intermediate list
|
|
238
|
+
pattern_ids = self._patterns_by_type.get(pattern_type, [])
|
|
239
|
+
patterns_to_check = (self.patterns[pid] for pid in pattern_ids)
|
|
240
|
+
else:
|
|
241
|
+
# Check all patterns - use generator to avoid materializing all patterns
|
|
242
|
+
patterns_to_check = (p for p in self.patterns.values())
|
|
243
|
+
|
|
244
|
+
for pattern in patterns_to_check:
|
|
245
|
+
# Apply confidence filter
|
|
246
|
+
if pattern.confidence < min_confidence:
|
|
247
|
+
continue
|
|
248
|
+
|
|
249
|
+
# Calculate relevance
|
|
250
|
+
relevance_score, matching_factors = self._calculate_relevance(pattern, context)
|
|
251
|
+
|
|
252
|
+
if relevance_score > 0.3: # Minimum relevance threshold
|
|
253
|
+
matches.append(
|
|
254
|
+
PatternMatch(
|
|
255
|
+
pattern=pattern,
|
|
256
|
+
relevance_score=relevance_score,
|
|
257
|
+
matching_factors=matching_factors,
|
|
258
|
+
),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Sort by relevance and limit
|
|
262
|
+
matches.sort(key=lambda m: m.relevance_score, reverse=True)
|
|
263
|
+
return matches[:limit]
|
|
264
|
+
|
|
265
|
+
def get_pattern(self, pattern_id: str) -> Pattern | None:
|
|
266
|
+
"""Get a specific pattern by ID
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
pattern_id: Pattern identifier
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
Pattern if found, None otherwise
|
|
273
|
+
|
|
274
|
+
"""
|
|
275
|
+
return self.patterns.get(pattern_id)
|
|
276
|
+
|
|
277
|
+
def get_patterns_by_tag(self, tag: str) -> list[Pattern]:
|
|
278
|
+
"""Get all patterns with a specific tag (O(1) lookup).
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
tag: Tag to search for
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
List of patterns with the given tag
|
|
285
|
+
|
|
286
|
+
Performance:
|
|
287
|
+
O(1) index lookup instead of O(n) linear scan.
|
|
288
|
+
|
|
289
|
+
Example:
|
|
290
|
+
>>> patterns = library.get_patterns_by_tag("debugging")
|
|
291
|
+
"""
|
|
292
|
+
pattern_ids = self._patterns_by_tag.get(tag, [])
|
|
293
|
+
# Generator expression for memory efficiency, converted to list for return type
|
|
294
|
+
return [
|
|
295
|
+
self.patterns[pid] for pid in pattern_ids if pid in self.patterns
|
|
296
|
+
] # Keep list comp: API returns list, typically small result set
|
|
297
|
+
|
|
298
|
+
def get_patterns_by_type(self, pattern_type: str) -> list[Pattern]:
|
|
299
|
+
"""Get all patterns of a specific type (O(1) lookup).
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
pattern_type: Type of patterns to retrieve
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
List of patterns of the given type
|
|
306
|
+
|
|
307
|
+
Performance:
|
|
308
|
+
O(1) index lookup instead of O(n) linear scan.
|
|
309
|
+
|
|
310
|
+
Example:
|
|
311
|
+
>>> patterns = library.get_patterns_by_type("conditional")
|
|
312
|
+
"""
|
|
313
|
+
pattern_ids = self._patterns_by_type.get(pattern_type, [])
|
|
314
|
+
return [self.patterns[pid] for pid in pattern_ids if pid in self.patterns]
|
|
315
|
+
|
|
316
|
+
def record_pattern_outcome(self, pattern_id: str, success: bool):
|
|
317
|
+
"""Record outcome of using a pattern
|
|
318
|
+
|
|
319
|
+
Updates pattern statistics to improve future recommendations.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
pattern_id: ID of pattern that was used
|
|
323
|
+
success: Whether using the pattern was successful
|
|
324
|
+
|
|
325
|
+
Raises:
|
|
326
|
+
ValueError: If pattern_id does not exist
|
|
327
|
+
|
|
328
|
+
"""
|
|
329
|
+
pattern = self.patterns.get(pattern_id)
|
|
330
|
+
if not pattern:
|
|
331
|
+
raise ValueError(f"Pattern '{pattern_id}' not found. Cannot record outcome.")
|
|
332
|
+
pattern.record_usage(success)
|
|
333
|
+
|
|
334
|
+
def link_patterns(self, pattern_id_1: str, pattern_id_2: str):
|
|
335
|
+
"""Create a link between related patterns
|
|
336
|
+
|
|
337
|
+
Helps agents discover complementary patterns.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
pattern_id_1: First pattern ID
|
|
341
|
+
pattern_id_2: Second pattern ID
|
|
342
|
+
|
|
343
|
+
Raises:
|
|
344
|
+
ValueError: If either pattern ID doesn't exist or IDs are the same
|
|
345
|
+
|
|
346
|
+
"""
|
|
347
|
+
# Validate patterns exist
|
|
348
|
+
if pattern_id_1 not in self.patterns:
|
|
349
|
+
raise ValueError(f"Pattern '{pattern_id_1}' does not exist")
|
|
350
|
+
|
|
351
|
+
if pattern_id_2 not in self.patterns:
|
|
352
|
+
raise ValueError(f"Pattern '{pattern_id_2}' does not exist")
|
|
353
|
+
|
|
354
|
+
if pattern_id_1 == pattern_id_2:
|
|
355
|
+
raise ValueError("Cannot link a pattern to itself")
|
|
356
|
+
|
|
357
|
+
# Create bidirectional link
|
|
358
|
+
if pattern_id_1 in self.pattern_graph:
|
|
359
|
+
if pattern_id_2 not in self.pattern_graph[pattern_id_1]:
|
|
360
|
+
self.pattern_graph[pattern_id_1].append(pattern_id_2)
|
|
361
|
+
|
|
362
|
+
if pattern_id_2 in self.pattern_graph:
|
|
363
|
+
if pattern_id_1 not in self.pattern_graph[pattern_id_2]:
|
|
364
|
+
self.pattern_graph[pattern_id_2].append(pattern_id_1)
|
|
365
|
+
|
|
366
|
+
def get_related_patterns(
|
|
367
|
+
self, pattern_id: str, depth: int = 1, _visited: set[str] | None = None
|
|
368
|
+
) -> list[Pattern]:
|
|
369
|
+
"""Get patterns related to a given pattern
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
pattern_id: Source pattern ID
|
|
373
|
+
depth: How many hops to traverse (1 = immediate neighbors)
|
|
374
|
+
_visited: Internal tracking to prevent cycles (do not use directly)
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
List of related patterns (no duplicates, cycle-safe)
|
|
378
|
+
|
|
379
|
+
"""
|
|
380
|
+
# Initialize visited set on first call
|
|
381
|
+
if _visited is None:
|
|
382
|
+
_visited = {pattern_id}
|
|
383
|
+
|
|
384
|
+
if depth <= 0 or pattern_id not in self.pattern_graph:
|
|
385
|
+
return []
|
|
386
|
+
|
|
387
|
+
related_ids = set(self.pattern_graph[pattern_id])
|
|
388
|
+
|
|
389
|
+
if depth > 1:
|
|
390
|
+
# Traverse deeper (avoiding cycles)
|
|
391
|
+
for related_id in list(related_ids):
|
|
392
|
+
if related_id not in _visited:
|
|
393
|
+
_visited.add(related_id)
|
|
394
|
+
deeper = self.get_related_patterns(related_id, depth - 1, _visited)
|
|
395
|
+
related_ids.update(p.id for p in deeper)
|
|
396
|
+
|
|
397
|
+
# Remove source pattern
|
|
398
|
+
related_ids.discard(pattern_id)
|
|
399
|
+
|
|
400
|
+
return [self.patterns[pid] for pid in related_ids if pid in self.patterns]
|
|
401
|
+
|
|
402
|
+
def get_agent_patterns(self, agent_id: str) -> list[Pattern]:
|
|
403
|
+
"""Get all patterns contributed by a specific agent
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
agent_id: Agent identifier
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
List of patterns from this agent
|
|
410
|
+
|
|
411
|
+
"""
|
|
412
|
+
pattern_ids = self.agent_contributions.get(agent_id, [])
|
|
413
|
+
return [self.patterns[pid] for pid in pattern_ids if pid in self.patterns]
|
|
414
|
+
|
|
415
|
+
def get_top_patterns(self, n: int = 10, sort_by: str = "success_rate") -> list[Pattern]:
|
|
416
|
+
"""Get top N patterns by specified metric
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
n: Number of patterns to return
|
|
420
|
+
sort_by: Metric to sort by ("success_rate", "usage_count", "confidence")
|
|
421
|
+
|
|
422
|
+
Returns:
|
|
423
|
+
Top N patterns
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
patterns = list(self.patterns.values())
|
|
427
|
+
|
|
428
|
+
if sort_by == "success_rate":
|
|
429
|
+
patterns.sort(key=lambda p: p.success_rate, reverse=True)
|
|
430
|
+
elif sort_by == "usage_count":
|
|
431
|
+
patterns.sort(key=lambda p: p.usage_count, reverse=True)
|
|
432
|
+
elif sort_by == "confidence":
|
|
433
|
+
patterns.sort(key=lambda p: p.confidence, reverse=True)
|
|
434
|
+
|
|
435
|
+
return patterns[:n]
|
|
436
|
+
|
|
437
|
+
def get_library_stats(self) -> dict[str, Any]:
|
|
438
|
+
"""Get statistics about the pattern library
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
Dict with library statistics
|
|
442
|
+
|
|
443
|
+
"""
|
|
444
|
+
if not self.patterns:
|
|
445
|
+
return {
|
|
446
|
+
"total_patterns": 0,
|
|
447
|
+
"total_agents": 0,
|
|
448
|
+
"total_usage": 0,
|
|
449
|
+
"average_confidence": 0.0,
|
|
450
|
+
"average_success_rate": 0.0,
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
patterns = list(self.patterns.values())
|
|
454
|
+
total_usage = sum(p.usage_count for p in patterns)
|
|
455
|
+
avg_confidence = sum(p.confidence for p in patterns) / len(patterns)
|
|
456
|
+
|
|
457
|
+
# Calculate average success rate (only for used patterns)
|
|
458
|
+
used_patterns = [p for p in patterns if p.usage_count > 0]
|
|
459
|
+
avg_success_rate = (
|
|
460
|
+
sum(p.success_rate for p in used_patterns) / len(used_patterns)
|
|
461
|
+
if used_patterns
|
|
462
|
+
else 0.0
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
return {
|
|
466
|
+
"total_patterns": len(self.patterns),
|
|
467
|
+
"total_agents": len(self.agent_contributions),
|
|
468
|
+
"total_usage": total_usage,
|
|
469
|
+
"average_confidence": avg_confidence,
|
|
470
|
+
"average_success_rate": avg_success_rate,
|
|
471
|
+
"patterns_by_type": self._count_by_type(),
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
def _calculate_relevance(
|
|
475
|
+
self,
|
|
476
|
+
pattern: Pattern,
|
|
477
|
+
context: dict[str, Any],
|
|
478
|
+
) -> tuple[float, list[str]]:
|
|
479
|
+
"""Calculate how relevant a pattern is to current context
|
|
480
|
+
|
|
481
|
+
Args:
|
|
482
|
+
pattern: Pattern to evaluate
|
|
483
|
+
context: Current context to match against
|
|
484
|
+
|
|
485
|
+
Returns:
|
|
486
|
+
tuple: (relevance_score, matching_factors)
|
|
487
|
+
- relevance_score (float): 0.0-1.0 relevance score
|
|
488
|
+
- matching_factors (list[str]): Human-readable reasons for match
|
|
489
|
+
|
|
490
|
+
Algorithm:
|
|
491
|
+
- 50% weight: Context key/value matches
|
|
492
|
+
- 30% weight: Tag matches
|
|
493
|
+
- 20% weight: Pattern success rate boost
|
|
494
|
+
|
|
495
|
+
"""
|
|
496
|
+
relevance = 0.0
|
|
497
|
+
matching_factors = []
|
|
498
|
+
|
|
499
|
+
# Check for direct key matches
|
|
500
|
+
pattern_context_keys = set(pattern.context.keys())
|
|
501
|
+
current_context_keys = set(context.keys())
|
|
502
|
+
common_keys = pattern_context_keys & current_context_keys
|
|
503
|
+
|
|
504
|
+
if common_keys:
|
|
505
|
+
# Calculate how many context values match
|
|
506
|
+
matches = sum(1 for key in common_keys if pattern.context.get(key) == context.get(key))
|
|
507
|
+
if common_keys:
|
|
508
|
+
key_match_ratio = matches / len(common_keys)
|
|
509
|
+
relevance += key_match_ratio * 0.5
|
|
510
|
+
if matches > 0:
|
|
511
|
+
matching_factors.append(f"{matches} context matches")
|
|
512
|
+
|
|
513
|
+
# Check for tag matches
|
|
514
|
+
context_tags = context.get("tags", [])
|
|
515
|
+
if context_tags and pattern.tags:
|
|
516
|
+
tag_matches = len(set(context_tags) & set(pattern.tags))
|
|
517
|
+
if tag_matches > 0:
|
|
518
|
+
relevance += min(tag_matches / len(pattern.tags), 1.0) * 0.3
|
|
519
|
+
matching_factors.append(f"{tag_matches} tag matches")
|
|
520
|
+
|
|
521
|
+
# Boost by pattern success rate
|
|
522
|
+
if pattern.usage_count > 0:
|
|
523
|
+
relevance += pattern.success_rate * 0.2
|
|
524
|
+
if pattern.success_rate > 0.7:
|
|
525
|
+
matching_factors.append(f"high success rate ({pattern.success_rate:.2f})")
|
|
526
|
+
|
|
527
|
+
return min(relevance, 1.0), matching_factors
|
|
528
|
+
|
|
529
|
+
def _count_by_type(self) -> dict[str, int]:
|
|
530
|
+
"""Count patterns by type"""
|
|
531
|
+
counts: dict[str, int] = {}
|
|
532
|
+
for pattern in self.patterns.values():
|
|
533
|
+
counts[pattern.pattern_type] = counts.get(pattern.pattern_type, 0) + 1
|
|
534
|
+
return counts
|
|
535
|
+
|
|
536
|
+
def reset(self):
|
|
537
|
+
"""Reset library to empty state"""
|
|
538
|
+
self.patterns = {}
|
|
539
|
+
self.agent_contributions = {}
|
|
540
|
+
self.pattern_graph = {}
|
|
541
|
+
self._patterns_by_type = {}
|
|
542
|
+
self._patterns_by_tag = {}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"patterns": [
|
|
3
|
+
{
|
|
4
|
+
"pattern_id": "workflow_20260107_1770825e",
|
|
5
|
+
"bug_type": "refactoring",
|
|
6
|
+
"status": "resolved",
|
|
7
|
+
"root_cause": "Workflow: refactor-plan - Prioritize tech debt based on trajectory and impact",
|
|
8
|
+
"fix": "Completed via refactor-plan workflow",
|
|
9
|
+
"resolved_by": "@empathy_framework",
|
|
10
|
+
"resolved_at": "2026-01-07",
|
|
11
|
+
"files_affected": [],
|
|
12
|
+
"source": "workflow_tracking",
|
|
13
|
+
"tier_progression": {
|
|
14
|
+
"methodology": "AI-ADDIE",
|
|
15
|
+
"recommended_tier": "CHEAP",
|
|
16
|
+
"starting_tier": "PREMIUM",
|
|
17
|
+
"successful_tier": "PREMIUM",
|
|
18
|
+
"total_attempts": 3,
|
|
19
|
+
"tier_history": [
|
|
20
|
+
{
|
|
21
|
+
"tier": "CHEAP",
|
|
22
|
+
"attempts": 1,
|
|
23
|
+
"success": {
|
|
24
|
+
"attempt": 1,
|
|
25
|
+
"quality_gates_passed": [
|
|
26
|
+
"execution",
|
|
27
|
+
"output"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"tier": "CAPABLE",
|
|
33
|
+
"attempts": 2,
|
|
34
|
+
"success": {
|
|
35
|
+
"attempt": 2,
|
|
36
|
+
"quality_gates_passed": [
|
|
37
|
+
"execution",
|
|
38
|
+
"output"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"tier": "PREMIUM",
|
|
44
|
+
"attempts": 1,
|
|
45
|
+
"success": {
|
|
46
|
+
"attempt": 1,
|
|
47
|
+
"quality_gates_passed": [
|
|
48
|
+
"execution",
|
|
49
|
+
"output"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"cost_breakdown": {
|
|
55
|
+
"total_cost": 0.021,
|
|
56
|
+
"cost_if_always_premium": 0.104,
|
|
57
|
+
"savings_percent": 80.0
|
|
58
|
+
},
|
|
59
|
+
"quality_metrics": {
|
|
60
|
+
"tests_passed": true,
|
|
61
|
+
"health_score_before": 73,
|
|
62
|
+
"health_score_after": 73
|
|
63
|
+
},
|
|
64
|
+
"xml_protocol_compliance": {
|
|
65
|
+
"prompt_used_xml": true,
|
|
66
|
+
"response_used_xml": true,
|
|
67
|
+
"all_sections_present": true,
|
|
68
|
+
"test_evidence_provided": true,
|
|
69
|
+
"false_complete_avoided": true
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"workflow_metadata": {
|
|
73
|
+
"workflow_name": "refactor-plan",
|
|
74
|
+
"workflow_id": "1770825e-b645-4c66-b4e1-87b9463b0082",
|
|
75
|
+
"duration_seconds": 3.24,
|
|
76
|
+
"started_at": "2026-01-07T06:30:40.696987",
|
|
77
|
+
"completed_at": "2026-01-07T06:30:43.935316"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pattern_id": "workflow_20260107_1770825e",
|
|
3
|
+
"bug_type": "refactoring",
|
|
4
|
+
"status": "resolved",
|
|
5
|
+
"root_cause": "Workflow: refactor-plan - Prioritize tech debt based on trajectory and impact",
|
|
6
|
+
"fix": "Completed via refactor-plan workflow",
|
|
7
|
+
"resolved_by": "@empathy_framework",
|
|
8
|
+
"resolved_at": "2026-01-07",
|
|
9
|
+
"files_affected": [],
|
|
10
|
+
"source": "workflow_tracking",
|
|
11
|
+
"tier_progression": {
|
|
12
|
+
"methodology": "AI-ADDIE",
|
|
13
|
+
"recommended_tier": "CHEAP",
|
|
14
|
+
"starting_tier": "PREMIUM",
|
|
15
|
+
"successful_tier": "PREMIUM",
|
|
16
|
+
"total_attempts": 3,
|
|
17
|
+
"tier_history": [
|
|
18
|
+
{
|
|
19
|
+
"tier": "CHEAP",
|
|
20
|
+
"attempts": 1,
|
|
21
|
+
"success": {
|
|
22
|
+
"attempt": 1,
|
|
23
|
+
"quality_gates_passed": [
|
|
24
|
+
"execution",
|
|
25
|
+
"output"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"tier": "CAPABLE",
|
|
31
|
+
"attempts": 2,
|
|
32
|
+
"success": {
|
|
33
|
+
"attempt": 2,
|
|
34
|
+
"quality_gates_passed": [
|
|
35
|
+
"execution",
|
|
36
|
+
"output"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"tier": "PREMIUM",
|
|
42
|
+
"attempts": 1,
|
|
43
|
+
"success": {
|
|
44
|
+
"attempt": 1,
|
|
45
|
+
"quality_gates_passed": [
|
|
46
|
+
"execution",
|
|
47
|
+
"output"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"cost_breakdown": {
|
|
53
|
+
"total_cost": 0.021,
|
|
54
|
+
"cost_if_always_premium": 0.104,
|
|
55
|
+
"savings_percent": 80.0
|
|
56
|
+
},
|
|
57
|
+
"quality_metrics": {
|
|
58
|
+
"tests_passed": true,
|
|
59
|
+
"health_score_before": 73,
|
|
60
|
+
"health_score_after": 73
|
|
61
|
+
},
|
|
62
|
+
"xml_protocol_compliance": {
|
|
63
|
+
"prompt_used_xml": true,
|
|
64
|
+
"response_used_xml": true,
|
|
65
|
+
"all_sections_present": true,
|
|
66
|
+
"test_evidence_provided": true,
|
|
67
|
+
"false_complete_avoided": true
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"workflow_metadata": {
|
|
71
|
+
"workflow_name": "refactor-plan",
|
|
72
|
+
"workflow_id": "1770825e-b645-4c66-b4e1-87b9463b0082",
|
|
73
|
+
"duration_seconds": 3.24,
|
|
74
|
+
"started_at": "2026-01-07T06:30:40.696987",
|
|
75
|
+
"completed_at": "2026-01-07T06:30:43.935316"
|
|
76
|
+
}
|
|
77
|
+
}
|