tapps-agents 3.5.40__py3-none-any.whl → 3.6.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.
- tapps_agents/__init__.py +2 -2
- tapps_agents/agents/__init__.py +22 -22
- tapps_agents/agents/analyst/__init__.py +5 -5
- tapps_agents/agents/architect/__init__.py +5 -5
- tapps_agents/agents/architect/agent.py +1033 -1033
- tapps_agents/agents/architect/pattern_detector.py +75 -75
- tapps_agents/agents/cleanup/__init__.py +7 -7
- tapps_agents/agents/cleanup/agent.py +445 -445
- tapps_agents/agents/debugger/__init__.py +7 -7
- tapps_agents/agents/debugger/agent.py +310 -310
- tapps_agents/agents/debugger/error_analyzer.py +437 -437
- tapps_agents/agents/designer/__init__.py +5 -5
- tapps_agents/agents/designer/agent.py +786 -786
- tapps_agents/agents/designer/visual_designer.py +638 -638
- tapps_agents/agents/documenter/__init__.py +7 -7
- tapps_agents/agents/documenter/agent.py +531 -531
- tapps_agents/agents/documenter/doc_generator.py +472 -472
- tapps_agents/agents/documenter/doc_validator.py +393 -393
- tapps_agents/agents/documenter/framework_doc_updater.py +493 -493
- tapps_agents/agents/enhancer/__init__.py +7 -7
- tapps_agents/agents/evaluator/__init__.py +7 -7
- tapps_agents/agents/evaluator/agent.py +443 -443
- tapps_agents/agents/evaluator/priority_evaluator.py +641 -641
- tapps_agents/agents/evaluator/quality_analyzer.py +147 -147
- tapps_agents/agents/evaluator/report_generator.py +344 -344
- tapps_agents/agents/evaluator/usage_analyzer.py +192 -192
- tapps_agents/agents/evaluator/workflow_analyzer.py +189 -189
- tapps_agents/agents/implementer/__init__.py +7 -7
- tapps_agents/agents/implementer/agent.py +798 -798
- tapps_agents/agents/implementer/auto_fix.py +1119 -1119
- tapps_agents/agents/implementer/code_generator.py +73 -73
- tapps_agents/agents/improver/__init__.py +1 -1
- tapps_agents/agents/improver/agent.py +753 -753
- tapps_agents/agents/ops/__init__.py +1 -1
- tapps_agents/agents/ops/agent.py +619 -619
- tapps_agents/agents/ops/dependency_analyzer.py +600 -600
- tapps_agents/agents/orchestrator/__init__.py +5 -5
- tapps_agents/agents/orchestrator/agent.py +522 -522
- tapps_agents/agents/planner/__init__.py +7 -7
- tapps_agents/agents/planner/agent.py +1127 -1127
- tapps_agents/agents/reviewer/__init__.py +24 -24
- tapps_agents/agents/reviewer/agent.py +3513 -3513
- tapps_agents/agents/reviewer/aggregator.py +213 -213
- tapps_agents/agents/reviewer/batch_review.py +448 -448
- tapps_agents/agents/reviewer/cache.py +443 -443
- tapps_agents/agents/reviewer/context7_enhancer.py +630 -630
- tapps_agents/agents/reviewer/context_detector.py +203 -203
- tapps_agents/agents/reviewer/docker_compose_validator.py +158 -158
- tapps_agents/agents/reviewer/dockerfile_validator.py +176 -176
- tapps_agents/agents/reviewer/error_handling.py +126 -126
- tapps_agents/agents/reviewer/feedback_generator.py +490 -490
- tapps_agents/agents/reviewer/influxdb_validator.py +316 -316
- tapps_agents/agents/reviewer/issue_tracking.py +169 -169
- tapps_agents/agents/reviewer/library_detector.py +295 -295
- tapps_agents/agents/reviewer/library_patterns.py +268 -268
- tapps_agents/agents/reviewer/maintainability_scorer.py +593 -593
- tapps_agents/agents/reviewer/metric_strategies.py +276 -276
- tapps_agents/agents/reviewer/mqtt_validator.py +160 -160
- tapps_agents/agents/reviewer/output_enhancer.py +105 -105
- tapps_agents/agents/reviewer/pattern_detector.py +241 -241
- tapps_agents/agents/reviewer/performance_scorer.py +357 -357
- tapps_agents/agents/reviewer/phased_review.py +516 -516
- tapps_agents/agents/reviewer/progressive_review.py +435 -435
- tapps_agents/agents/reviewer/react_scorer.py +331 -331
- tapps_agents/agents/reviewer/score_constants.py +228 -228
- tapps_agents/agents/reviewer/score_validator.py +507 -507
- tapps_agents/agents/reviewer/scorer_registry.py +373 -373
- tapps_agents/agents/reviewer/scoring.py +1566 -1566
- tapps_agents/agents/reviewer/service_discovery.py +534 -534
- tapps_agents/agents/reviewer/tools/__init__.py +41 -41
- tapps_agents/agents/reviewer/tools/parallel_executor.py +581 -581
- tapps_agents/agents/reviewer/tools/ruff_grouping.py +250 -250
- tapps_agents/agents/reviewer/tools/scoped_mypy.py +284 -284
- tapps_agents/agents/reviewer/typescript_scorer.py +1142 -1142
- tapps_agents/agents/reviewer/validation.py +208 -208
- tapps_agents/agents/reviewer/websocket_validator.py +132 -132
- tapps_agents/agents/tester/__init__.py +7 -7
- tapps_agents/agents/tester/accessibility_auditor.py +309 -309
- tapps_agents/agents/tester/agent.py +1080 -1080
- tapps_agents/agents/tester/batch_generator.py +54 -54
- tapps_agents/agents/tester/context_learner.py +51 -51
- tapps_agents/agents/tester/coverage_analyzer.py +386 -386
- tapps_agents/agents/tester/coverage_test_generator.py +290 -290
- tapps_agents/agents/tester/debug_enhancer.py +238 -238
- tapps_agents/agents/tester/device_emulator.py +241 -241
- tapps_agents/agents/tester/integration_generator.py +62 -62
- tapps_agents/agents/tester/network_recorder.py +300 -300
- tapps_agents/agents/tester/performance_monitor.py +320 -320
- tapps_agents/agents/tester/test_fixer.py +316 -316
- tapps_agents/agents/tester/test_generator.py +632 -632
- tapps_agents/agents/tester/trace_manager.py +234 -234
- tapps_agents/agents/tester/visual_regression.py +291 -291
- tapps_agents/analysis/pattern_detector.py +36 -36
- tapps_agents/beads/hydration.py +213 -213
- tapps_agents/beads/parse.py +32 -32
- tapps_agents/beads/specs.py +206 -206
- tapps_agents/cli/__init__.py +9 -9
- tapps_agents/cli/__main__.py +8 -8
- tapps_agents/cli/base.py +478 -478
- tapps_agents/cli/command_classifier.py +72 -72
- tapps_agents/cli/commands/__init__.py +2 -2
- tapps_agents/cli/commands/analyst.py +173 -173
- tapps_agents/cli/commands/architect.py +109 -109
- tapps_agents/cli/commands/cleanup_agent.py +92 -92
- tapps_agents/cli/commands/common.py +126 -126
- tapps_agents/cli/commands/debugger.py +90 -90
- tapps_agents/cli/commands/designer.py +112 -112
- tapps_agents/cli/commands/documenter.py +136 -136
- tapps_agents/cli/commands/enhancer.py +110 -110
- tapps_agents/cli/commands/evaluator.py +255 -255
- tapps_agents/cli/commands/health.py +665 -665
- tapps_agents/cli/commands/implementer.py +301 -301
- tapps_agents/cli/commands/improver.py +91 -91
- tapps_agents/cli/commands/knowledge.py +111 -111
- tapps_agents/cli/commands/learning.py +172 -172
- tapps_agents/cli/commands/observability.py +283 -283
- tapps_agents/cli/commands/ops.py +135 -135
- tapps_agents/cli/commands/orchestrator.py +116 -116
- tapps_agents/cli/commands/planner.py +237 -237
- tapps_agents/cli/commands/reviewer.py +1872 -1872
- tapps_agents/cli/commands/status.py +285 -285
- tapps_agents/cli/commands/task.py +227 -219
- tapps_agents/cli/commands/tester.py +191 -191
- tapps_agents/cli/commands/top_level.py +3586 -3586
- tapps_agents/cli/feedback.py +936 -936
- tapps_agents/cli/formatters.py +608 -608
- tapps_agents/cli/help/__init__.py +7 -7
- tapps_agents/cli/help/static_help.py +425 -425
- tapps_agents/cli/network_detection.py +110 -110
- tapps_agents/cli/output_compactor.py +274 -274
- tapps_agents/cli/parsers/__init__.py +2 -2
- tapps_agents/cli/parsers/analyst.py +186 -186
- tapps_agents/cli/parsers/architect.py +167 -167
- tapps_agents/cli/parsers/cleanup_agent.py +228 -228
- tapps_agents/cli/parsers/debugger.py +116 -116
- tapps_agents/cli/parsers/designer.py +182 -182
- tapps_agents/cli/parsers/documenter.py +134 -134
- tapps_agents/cli/parsers/enhancer.py +113 -113
- tapps_agents/cli/parsers/evaluator.py +213 -213
- tapps_agents/cli/parsers/implementer.py +168 -168
- tapps_agents/cli/parsers/improver.py +132 -132
- tapps_agents/cli/parsers/ops.py +159 -159
- tapps_agents/cli/parsers/orchestrator.py +98 -98
- tapps_agents/cli/parsers/planner.py +145 -145
- tapps_agents/cli/parsers/reviewer.py +462 -462
- tapps_agents/cli/parsers/tester.py +124 -124
- tapps_agents/cli/progress_heartbeat.py +254 -254
- tapps_agents/cli/streaming_progress.py +336 -336
- tapps_agents/cli/utils/__init__.py +6 -6
- tapps_agents/cli/utils/agent_lifecycle.py +48 -48
- tapps_agents/cli/utils/error_formatter.py +82 -82
- tapps_agents/cli/utils/error_recovery.py +188 -188
- tapps_agents/cli/utils/output_handler.py +59 -59
- tapps_agents/cli/utils/prompt_enhancer.py +319 -319
- tapps_agents/cli/validators/__init__.py +9 -9
- tapps_agents/cli/validators/command_validator.py +81 -81
- tapps_agents/context7/__init__.py +112 -112
- tapps_agents/context7/agent_integration.py +869 -869
- tapps_agents/context7/analytics.py +382 -382
- tapps_agents/context7/analytics_dashboard.py +299 -299
- tapps_agents/context7/async_cache.py +681 -681
- tapps_agents/context7/backup_client.py +958 -958
- tapps_agents/context7/cache_locking.py +194 -194
- tapps_agents/context7/cache_metadata.py +214 -214
- tapps_agents/context7/cache_prewarm.py +488 -488
- tapps_agents/context7/cache_structure.py +168 -168
- tapps_agents/context7/cache_warming.py +604 -604
- tapps_agents/context7/circuit_breaker.py +376 -376
- tapps_agents/context7/cleanup.py +461 -461
- tapps_agents/context7/commands.py +858 -858
- tapps_agents/context7/credential_validation.py +276 -276
- tapps_agents/context7/cross_reference_resolver.py +168 -168
- tapps_agents/context7/cross_references.py +424 -424
- tapps_agents/context7/doc_manager.py +225 -225
- tapps_agents/context7/fuzzy_matcher.py +369 -369
- tapps_agents/context7/kb_cache.py +404 -404
- tapps_agents/context7/language_detector.py +219 -219
- tapps_agents/context7/library_detector.py +725 -725
- tapps_agents/context7/lookup.py +738 -738
- tapps_agents/context7/metadata.py +258 -258
- tapps_agents/context7/refresh_queue.py +300 -300
- tapps_agents/context7/security.py +373 -373
- tapps_agents/context7/staleness_policies.py +278 -278
- tapps_agents/context7/tiles_integration.py +47 -47
- tapps_agents/continuous_bug_fix/__init__.py +20 -20
- tapps_agents/continuous_bug_fix/bug_finder.py +306 -306
- tapps_agents/continuous_bug_fix/bug_fix_coordinator.py +177 -177
- tapps_agents/continuous_bug_fix/commit_manager.py +178 -178
- tapps_agents/continuous_bug_fix/continuous_bug_fixer.py +322 -322
- tapps_agents/continuous_bug_fix/proactive_bug_finder.py +285 -285
- tapps_agents/core/__init__.py +298 -298
- tapps_agents/core/adaptive_cache_config.py +432 -432
- tapps_agents/core/agent_base.py +647 -647
- tapps_agents/core/agent_cache.py +466 -466
- tapps_agents/core/agent_learning.py +1865 -1865
- tapps_agents/core/analytics_dashboard.py +563 -563
- tapps_agents/core/analytics_enhancements.py +597 -597
- tapps_agents/core/anonymization.py +274 -274
- tapps_agents/core/artifact_context_builder.py +293 -0
- tapps_agents/core/ast_parser.py +228 -228
- tapps_agents/core/async_file_ops.py +402 -402
- tapps_agents/core/best_practice_consultant.py +299 -299
- tapps_agents/core/brownfield_analyzer.py +299 -299
- tapps_agents/core/brownfield_review.py +541 -541
- tapps_agents/core/browser_controller.py +513 -513
- tapps_agents/core/capability_registry.py +418 -418
- tapps_agents/core/change_impact_analyzer.py +190 -190
- tapps_agents/core/checkpoint_manager.py +377 -377
- tapps_agents/core/code_generator.py +329 -329
- tapps_agents/core/code_validator.py +276 -276
- tapps_agents/core/command_registry.py +327 -327
- tapps_agents/core/config.py +33 -0
- tapps_agents/core/context_gathering/__init__.py +2 -2
- tapps_agents/core/context_gathering/repository_explorer.py +28 -28
- tapps_agents/core/context_intelligence/__init__.py +2 -2
- tapps_agents/core/context_intelligence/relevance_scorer.py +24 -24
- tapps_agents/core/context_intelligence/token_budget_manager.py +27 -27
- tapps_agents/core/context_manager.py +240 -240
- tapps_agents/core/cursor_feedback_monitor.py +146 -146
- tapps_agents/core/cursor_verification.py +290 -290
- tapps_agents/core/customization_loader.py +280 -280
- tapps_agents/core/customization_schema.py +260 -260
- tapps_agents/core/customization_template.py +238 -238
- tapps_agents/core/debug_logger.py +124 -124
- tapps_agents/core/design_validator.py +298 -298
- tapps_agents/core/diagram_generator.py +226 -226
- tapps_agents/core/docker_utils.py +232 -232
- tapps_agents/core/document_generator.py +617 -617
- tapps_agents/core/domain_detector.py +30 -30
- tapps_agents/core/error_envelope.py +454 -454
- tapps_agents/core/error_handler.py +270 -270
- tapps_agents/core/estimation_tracker.py +189 -189
- tapps_agents/core/eval_prompt_engine.py +116 -116
- tapps_agents/core/evaluation_base.py +119 -119
- tapps_agents/core/evaluation_models.py +320 -320
- tapps_agents/core/evaluation_orchestrator.py +225 -225
- tapps_agents/core/evaluators/__init__.py +7 -7
- tapps_agents/core/evaluators/architectural_evaluator.py +205 -205
- tapps_agents/core/evaluators/behavioral_evaluator.py +160 -160
- tapps_agents/core/evaluators/performance_profile_evaluator.py +160 -160
- tapps_agents/core/evaluators/security_posture_evaluator.py +148 -148
- tapps_agents/core/evaluators/spec_compliance_evaluator.py +181 -181
- tapps_agents/core/exceptions.py +107 -107
- tapps_agents/core/expert_config_generator.py +293 -293
- tapps_agents/core/export_schema.py +202 -202
- tapps_agents/core/external_feedback_models.py +102 -102
- tapps_agents/core/external_feedback_storage.py +213 -213
- tapps_agents/core/fallback_strategy.py +314 -314
- tapps_agents/core/feedback_analyzer.py +162 -162
- tapps_agents/core/feedback_collector.py +178 -178
- tapps_agents/core/git_operations.py +445 -445
- tapps_agents/core/hardware_profiler.py +151 -151
- tapps_agents/core/instructions.py +324 -324
- tapps_agents/core/io_guardrails.py +69 -69
- tapps_agents/core/issue_manifest.py +249 -249
- tapps_agents/core/issue_schema.py +139 -139
- tapps_agents/core/json_utils.py +128 -128
- tapps_agents/core/knowledge_graph.py +446 -446
- tapps_agents/core/language_detector.py +296 -296
- tapps_agents/core/learning_confidence.py +242 -242
- tapps_agents/core/learning_dashboard.py +246 -246
- tapps_agents/core/learning_decision.py +384 -384
- tapps_agents/core/learning_explainability.py +578 -578
- tapps_agents/core/learning_export.py +287 -287
- tapps_agents/core/learning_integration.py +228 -228
- tapps_agents/core/llm_behavior.py +232 -232
- tapps_agents/core/long_duration_support.py +786 -786
- tapps_agents/core/mcp_setup.py +106 -106
- tapps_agents/core/memory_integration.py +396 -396
- tapps_agents/core/meta_learning.py +666 -666
- tapps_agents/core/module_path_sanitizer.py +199 -199
- tapps_agents/core/multi_agent_orchestrator.py +382 -382
- tapps_agents/core/network_errors.py +125 -125
- tapps_agents/core/nfr_validator.py +336 -336
- tapps_agents/core/offline_mode.py +158 -158
- tapps_agents/core/output_contracts.py +300 -300
- tapps_agents/core/output_formatter.py +300 -300
- tapps_agents/core/path_normalizer.py +174 -174
- tapps_agents/core/path_validator.py +322 -322
- tapps_agents/core/pattern_library.py +250 -250
- tapps_agents/core/performance_benchmark.py +301 -301
- tapps_agents/core/performance_monitor.py +184 -184
- tapps_agents/core/playwright_mcp_controller.py +771 -771
- tapps_agents/core/policy_loader.py +135 -135
- tapps_agents/core/progress.py +166 -166
- tapps_agents/core/project_profile.py +354 -354
- tapps_agents/core/project_type_detector.py +454 -454
- tapps_agents/core/prompt_base.py +223 -223
- tapps_agents/core/prompt_learning/__init__.py +2 -2
- tapps_agents/core/prompt_learning/learning_loop.py +24 -24
- tapps_agents/core/prompt_learning/project_prompt_store.py +25 -25
- tapps_agents/core/prompt_learning/skills_prompt_analyzer.py +35 -35
- tapps_agents/core/prompt_optimization/__init__.py +6 -6
- tapps_agents/core/prompt_optimization/ab_tester.py +114 -114
- tapps_agents/core/prompt_optimization/correlation_analyzer.py +160 -160
- tapps_agents/core/prompt_optimization/progressive_refiner.py +129 -129
- tapps_agents/core/prompt_optimization/prompt_library.py +37 -37
- tapps_agents/core/requirements_evaluator.py +431 -431
- tapps_agents/core/resource_aware_executor.py +449 -449
- tapps_agents/core/resource_monitor.py +343 -343
- tapps_agents/core/resume_handler.py +298 -298
- tapps_agents/core/retry_handler.py +197 -197
- tapps_agents/core/review_checklists.py +479 -479
- tapps_agents/core/role_loader.py +201 -201
- tapps_agents/core/role_template_loader.py +201 -201
- tapps_agents/core/runtime_mode.py +60 -60
- tapps_agents/core/security_scanner.py +342 -342
- tapps_agents/core/skill_agent_registry.py +194 -194
- tapps_agents/core/skill_integration.py +208 -208
- tapps_agents/core/skill_loader.py +492 -492
- tapps_agents/core/skill_template.py +341 -341
- tapps_agents/core/skill_validator.py +478 -478
- tapps_agents/core/stack_analyzer.py +35 -35
- tapps_agents/core/startup.py +174 -174
- tapps_agents/core/storage_manager.py +397 -397
- tapps_agents/core/storage_models.py +166 -166
- tapps_agents/core/story_evaluator.py +410 -410
- tapps_agents/core/subprocess_utils.py +170 -170
- tapps_agents/core/task_duration.py +296 -296
- tapps_agents/core/task_memory.py +582 -582
- tapps_agents/core/task_state.py +226 -226
- tapps_agents/core/tech_stack_priorities.py +208 -208
- tapps_agents/core/temp_directory.py +194 -194
- tapps_agents/core/template_merger.py +600 -600
- tapps_agents/core/template_selector.py +280 -280
- tapps_agents/core/test_generator.py +286 -286
- tapps_agents/core/tiered_context.py +253 -253
- tapps_agents/core/token_monitor.py +345 -345
- tapps_agents/core/traceability.py +254 -254
- tapps_agents/core/trajectory_tracker.py +50 -50
- tapps_agents/core/unicode_safe.py +143 -143
- tapps_agents/core/unified_cache_config.py +170 -170
- tapps_agents/core/unified_state.py +324 -324
- tapps_agents/core/validate_cursor_setup.py +237 -237
- tapps_agents/core/validation_registry.py +136 -136
- tapps_agents/core/validators/__init__.py +4 -4
- tapps_agents/core/validators/python_validator.py +87 -87
- tapps_agents/core/verification_agent.py +90 -90
- tapps_agents/core/visual_feedback.py +644 -644
- tapps_agents/core/workflow_validator.py +197 -197
- tapps_agents/core/worktree.py +367 -367
- tapps_agents/docker/__init__.py +10 -10
- tapps_agents/docker/analyzer.py +186 -186
- tapps_agents/docker/debugger.py +229 -229
- tapps_agents/docker/error_patterns.py +216 -216
- tapps_agents/epic/__init__.py +22 -22
- tapps_agents/epic/beads_sync.py +115 -115
- tapps_agents/epic/markdown_sync.py +105 -105
- tapps_agents/epic/models.py +96 -96
- tapps_agents/experts/__init__.py +163 -163
- tapps_agents/experts/agent_integration.py +243 -243
- tapps_agents/experts/auto_generator.py +331 -331
- tapps_agents/experts/base_expert.py +536 -536
- tapps_agents/experts/builtin_registry.py +261 -261
- tapps_agents/experts/business_metrics.py +565 -565
- tapps_agents/experts/cache.py +266 -266
- tapps_agents/experts/confidence_breakdown.py +306 -306
- tapps_agents/experts/confidence_calculator.py +336 -336
- tapps_agents/experts/confidence_metrics.py +236 -236
- tapps_agents/experts/domain_config.py +311 -311
- tapps_agents/experts/domain_detector.py +550 -550
- tapps_agents/experts/domain_utils.py +84 -84
- tapps_agents/experts/expert_config.py +113 -113
- tapps_agents/experts/expert_engine.py +465 -465
- tapps_agents/experts/expert_registry.py +744 -744
- tapps_agents/experts/expert_synthesizer.py +70 -70
- tapps_agents/experts/governance.py +197 -197
- tapps_agents/experts/history_logger.py +312 -312
- tapps_agents/experts/knowledge/README.md +180 -180
- tapps_agents/experts/knowledge/accessibility/accessible-forms.md +331 -331
- tapps_agents/experts/knowledge/accessibility/aria-patterns.md +344 -344
- tapps_agents/experts/knowledge/accessibility/color-contrast.md +285 -285
- tapps_agents/experts/knowledge/accessibility/keyboard-navigation.md +332 -332
- tapps_agents/experts/knowledge/accessibility/screen-readers.md +282 -282
- tapps_agents/experts/knowledge/accessibility/semantic-html.md +355 -355
- tapps_agents/experts/knowledge/accessibility/testing-accessibility.md +369 -369
- tapps_agents/experts/knowledge/accessibility/wcag-2.1.md +296 -296
- tapps_agents/experts/knowledge/accessibility/wcag-2.2.md +211 -211
- tapps_agents/experts/knowledge/agent-learning/best-practices.md +715 -715
- tapps_agents/experts/knowledge/agent-learning/pattern-extraction.md +282 -282
- tapps_agents/experts/knowledge/agent-learning/prompt-optimization.md +320 -320
- tapps_agents/experts/knowledge/ai-frameworks/model-optimization.md +90 -90
- tapps_agents/experts/knowledge/ai-frameworks/openvino-patterns.md +260 -260
- tapps_agents/experts/knowledge/api-design-integration/api-gateway-patterns.md +309 -309
- tapps_agents/experts/knowledge/api-design-integration/api-security-patterns.md +521 -521
- tapps_agents/experts/knowledge/api-design-integration/api-versioning.md +421 -421
- tapps_agents/experts/knowledge/api-design-integration/async-protocol-patterns.md +61 -61
- tapps_agents/experts/knowledge/api-design-integration/contract-testing.md +221 -221
- tapps_agents/experts/knowledge/api-design-integration/external-api-integration.md +489 -489
- tapps_agents/experts/knowledge/api-design-integration/fastapi-patterns.md +360 -360
- tapps_agents/experts/knowledge/api-design-integration/fastapi-testing.md +262 -262
- tapps_agents/experts/knowledge/api-design-integration/graphql-patterns.md +582 -582
- tapps_agents/experts/knowledge/api-design-integration/grpc-best-practices.md +499 -499
- tapps_agents/experts/knowledge/api-design-integration/mqtt-patterns.md +455 -455
- tapps_agents/experts/knowledge/api-design-integration/rate-limiting.md +507 -507
- tapps_agents/experts/knowledge/api-design-integration/restful-api-design.md +618 -618
- tapps_agents/experts/knowledge/api-design-integration/websocket-patterns.md +480 -480
- tapps_agents/experts/knowledge/cloud-infrastructure/cloud-native-patterns.md +175 -175
- tapps_agents/experts/knowledge/cloud-infrastructure/container-health-checks.md +261 -261
- tapps_agents/experts/knowledge/cloud-infrastructure/containerization.md +222 -222
- tapps_agents/experts/knowledge/cloud-infrastructure/cost-optimization.md +122 -122
- tapps_agents/experts/knowledge/cloud-infrastructure/disaster-recovery.md +153 -153
- tapps_agents/experts/knowledge/cloud-infrastructure/dockerfile-patterns.md +285 -285
- tapps_agents/experts/knowledge/cloud-infrastructure/infrastructure-as-code.md +187 -187
- tapps_agents/experts/knowledge/cloud-infrastructure/kubernetes-patterns.md +253 -253
- tapps_agents/experts/knowledge/cloud-infrastructure/multi-cloud-strategies.md +155 -155
- tapps_agents/experts/knowledge/cloud-infrastructure/serverless-architecture.md +200 -200
- tapps_agents/experts/knowledge/code-quality-analysis/README.md +16 -16
- tapps_agents/experts/knowledge/code-quality-analysis/code-metrics.md +137 -137
- tapps_agents/experts/knowledge/code-quality-analysis/complexity-analysis.md +181 -181
- tapps_agents/experts/knowledge/code-quality-analysis/technical-debt-patterns.md +191 -191
- tapps_agents/experts/knowledge/data-privacy-compliance/anonymization.md +313 -313
- tapps_agents/experts/knowledge/data-privacy-compliance/ccpa.md +255 -255
- tapps_agents/experts/knowledge/data-privacy-compliance/consent-management.md +282 -282
- tapps_agents/experts/knowledge/data-privacy-compliance/data-minimization.md +275 -275
- tapps_agents/experts/knowledge/data-privacy-compliance/data-retention.md +297 -297
- tapps_agents/experts/knowledge/data-privacy-compliance/data-subject-rights.md +383 -383
- tapps_agents/experts/knowledge/data-privacy-compliance/encryption-privacy.md +285 -285
- tapps_agents/experts/knowledge/data-privacy-compliance/gdpr.md +344 -344
- tapps_agents/experts/knowledge/data-privacy-compliance/hipaa.md +385 -385
- tapps_agents/experts/knowledge/data-privacy-compliance/privacy-by-design.md +280 -280
- tapps_agents/experts/knowledge/database-data-management/acid-vs-cap.md +164 -164
- tapps_agents/experts/knowledge/database-data-management/backup-and-recovery.md +182 -182
- tapps_agents/experts/knowledge/database-data-management/data-modeling.md +172 -172
- tapps_agents/experts/knowledge/database-data-management/database-design.md +187 -187
- tapps_agents/experts/knowledge/database-data-management/flux-query-optimization.md +342 -342
- tapps_agents/experts/knowledge/database-data-management/influxdb-connection-patterns.md +432 -432
- tapps_agents/experts/knowledge/database-data-management/influxdb-patterns.md +442 -442
- tapps_agents/experts/knowledge/database-data-management/migration-strategies.md +216 -216
- tapps_agents/experts/knowledge/database-data-management/nosql-patterns.md +259 -259
- tapps_agents/experts/knowledge/database-data-management/scalability-patterns.md +184 -184
- tapps_agents/experts/knowledge/database-data-management/sql-optimization.md +175 -175
- tapps_agents/experts/knowledge/database-data-management/time-series-modeling.md +444 -444
- tapps_agents/experts/knowledge/development-workflow/README.md +16 -16
- tapps_agents/experts/knowledge/development-workflow/automation-best-practices.md +216 -216
- tapps_agents/experts/knowledge/development-workflow/build-strategies.md +198 -198
- tapps_agents/experts/knowledge/development-workflow/deployment-patterns.md +205 -205
- tapps_agents/experts/knowledge/development-workflow/git-workflows.md +205 -205
- tapps_agents/experts/knowledge/documentation-knowledge-management/README.md +16 -16
- tapps_agents/experts/knowledge/documentation-knowledge-management/api-documentation-patterns.md +231 -231
- tapps_agents/experts/knowledge/documentation-knowledge-management/documentation-standards.md +191 -191
- tapps_agents/experts/knowledge/documentation-knowledge-management/knowledge-management.md +171 -171
- tapps_agents/experts/knowledge/documentation-knowledge-management/technical-writing-guide.md +192 -192
- tapps_agents/experts/knowledge/observability-monitoring/alerting-patterns.md +461 -461
- tapps_agents/experts/knowledge/observability-monitoring/apm-tools.md +459 -459
- tapps_agents/experts/knowledge/observability-monitoring/distributed-tracing.md +367 -367
- tapps_agents/experts/knowledge/observability-monitoring/logging-strategies.md +478 -478
- tapps_agents/experts/knowledge/observability-monitoring/metrics-and-monitoring.md +510 -510
- tapps_agents/experts/knowledge/observability-monitoring/observability-best-practices.md +492 -492
- tapps_agents/experts/knowledge/observability-monitoring/open-telemetry.md +573 -573
- tapps_agents/experts/knowledge/observability-monitoring/slo-sli-sla.md +419 -419
- tapps_agents/experts/knowledge/performance/anti-patterns.md +284 -284
- tapps_agents/experts/knowledge/performance/api-performance.md +256 -256
- tapps_agents/experts/knowledge/performance/caching.md +327 -327
- tapps_agents/experts/knowledge/performance/database-performance.md +252 -252
- tapps_agents/experts/knowledge/performance/optimization-patterns.md +327 -327
- tapps_agents/experts/knowledge/performance/profiling.md +297 -297
- tapps_agents/experts/knowledge/performance/resource-management.md +293 -293
- tapps_agents/experts/knowledge/performance/scalability.md +306 -306
- tapps_agents/experts/knowledge/security/owasp-top10.md +209 -209
- tapps_agents/experts/knowledge/security/secure-coding-practices.md +207 -207
- tapps_agents/experts/knowledge/security/threat-modeling.md +220 -220
- tapps_agents/experts/knowledge/security/vulnerability-patterns.md +342 -342
- tapps_agents/experts/knowledge/software-architecture/docker-compose-patterns.md +314 -314
- tapps_agents/experts/knowledge/software-architecture/microservices-patterns.md +379 -379
- tapps_agents/experts/knowledge/software-architecture/service-communication.md +316 -316
- tapps_agents/experts/knowledge/testing/best-practices.md +310 -310
- tapps_agents/experts/knowledge/testing/coverage-analysis.md +293 -293
- tapps_agents/experts/knowledge/testing/mocking.md +256 -256
- tapps_agents/experts/knowledge/testing/test-automation.md +276 -276
- tapps_agents/experts/knowledge/testing/test-data.md +271 -271
- tapps_agents/experts/knowledge/testing/test-design-patterns.md +280 -280
- tapps_agents/experts/knowledge/testing/test-maintenance.md +236 -236
- tapps_agents/experts/knowledge/testing/test-strategies.md +311 -311
- tapps_agents/experts/knowledge/user-experience/information-architecture.md +325 -325
- tapps_agents/experts/knowledge/user-experience/interaction-design.md +363 -363
- tapps_agents/experts/knowledge/user-experience/prototyping.md +293 -293
- tapps_agents/experts/knowledge/user-experience/usability-heuristics.md +337 -337
- tapps_agents/experts/knowledge/user-experience/usability-testing.md +311 -311
- tapps_agents/experts/knowledge/user-experience/user-journeys.md +296 -296
- tapps_agents/experts/knowledge/user-experience/user-research.md +373 -373
- tapps_agents/experts/knowledge/user-experience/ux-principles.md +340 -340
- tapps_agents/experts/knowledge_freshness.py +321 -321
- tapps_agents/experts/knowledge_ingestion.py +438 -438
- tapps_agents/experts/knowledge_need_detector.py +93 -93
- tapps_agents/experts/knowledge_validator.py +382 -382
- tapps_agents/experts/observability.py +440 -440
- tapps_agents/experts/passive_notifier.py +238 -238
- tapps_agents/experts/proactive_orchestrator.py +32 -32
- tapps_agents/experts/rag_chunker.py +205 -205
- tapps_agents/experts/rag_embedder.py +152 -152
- tapps_agents/experts/rag_evaluation.py +299 -299
- tapps_agents/experts/rag_index.py +303 -303
- tapps_agents/experts/rag_metrics.py +293 -293
- tapps_agents/experts/rag_safety.py +263 -263
- tapps_agents/experts/report_generator.py +296 -296
- tapps_agents/experts/setup_wizard.py +441 -441
- tapps_agents/experts/simple_rag.py +431 -431
- tapps_agents/experts/vector_rag.py +354 -354
- tapps_agents/experts/weight_distributor.py +304 -304
- tapps_agents/health/__init__.py +24 -24
- tapps_agents/health/base.py +75 -75
- tapps_agents/health/checks/__init__.py +22 -22
- tapps_agents/health/checks/automation.py +127 -127
- tapps_agents/health/checks/context7_cache.py +210 -210
- tapps_agents/health/checks/environment.py +116 -116
- tapps_agents/health/checks/execution.py +170 -170
- tapps_agents/health/checks/knowledge_base.py +187 -187
- tapps_agents/health/checks/outcomes.py +324 -324
- tapps_agents/health/collector.py +280 -280
- tapps_agents/health/dashboard.py +137 -137
- tapps_agents/health/metrics.py +151 -151
- tapps_agents/health/orchestrator.py +271 -271
- tapps_agents/health/registry.py +166 -166
- tapps_agents/hooks/__init__.py +33 -33
- tapps_agents/hooks/config.py +140 -140
- tapps_agents/hooks/events.py +135 -135
- tapps_agents/hooks/executor.py +128 -128
- tapps_agents/hooks/manager.py +143 -143
- tapps_agents/integration/__init__.py +8 -8
- tapps_agents/integration/service_integrator.py +121 -121
- tapps_agents/integrations/__init__.py +10 -10
- tapps_agents/integrations/clawdbot.py +525 -525
- tapps_agents/integrations/memory_bridge.py +356 -356
- tapps_agents/mcp/__init__.py +18 -18
- tapps_agents/mcp/gateway.py +112 -112
- tapps_agents/mcp/servers/__init__.py +13 -13
- tapps_agents/mcp/servers/analysis.py +204 -204
- tapps_agents/mcp/servers/context7.py +198 -198
- tapps_agents/mcp/servers/filesystem.py +218 -218
- tapps_agents/mcp/servers/git.py +201 -201
- tapps_agents/mcp/tool_registry.py +115 -115
- tapps_agents/quality/__init__.py +54 -54
- tapps_agents/quality/coverage_analyzer.py +379 -379
- tapps_agents/quality/enforcement.py +82 -82
- tapps_agents/quality/gates/__init__.py +37 -37
- tapps_agents/quality/gates/approval_gate.py +255 -255
- tapps_agents/quality/gates/base.py +84 -84
- tapps_agents/quality/gates/exceptions.py +43 -43
- tapps_agents/quality/gates/policy_gate.py +195 -195
- tapps_agents/quality/gates/registry.py +239 -239
- tapps_agents/quality/gates/security_gate.py +156 -156
- tapps_agents/quality/quality_gates.py +369 -369
- tapps_agents/quality/secret_scanner.py +335 -335
- tapps_agents/session/__init__.py +19 -19
- tapps_agents/session/manager.py +256 -256
- tapps_agents/simple_mode/__init__.py +66 -66
- tapps_agents/simple_mode/agent_contracts.py +357 -357
- tapps_agents/simple_mode/beads_hooks.py +151 -151
- tapps_agents/simple_mode/code_snippet_handler.py +382 -382
- tapps_agents/simple_mode/documentation_manager.py +395 -395
- tapps_agents/simple_mode/documentation_reader.py +187 -187
- tapps_agents/simple_mode/file_inference.py +292 -292
- tapps_agents/simple_mode/framework_change_detector.py +268 -268
- tapps_agents/simple_mode/intent_parser.py +510 -510
- tapps_agents/simple_mode/learning_progression.py +358 -358
- tapps_agents/simple_mode/nl_handler.py +700 -700
- tapps_agents/simple_mode/onboarding.py +253 -253
- tapps_agents/simple_mode/orchestrators/__init__.py +38 -38
- tapps_agents/simple_mode/orchestrators/base.py +185 -185
- tapps_agents/simple_mode/orchestrators/breakdown_orchestrator.py +49 -49
- tapps_agents/simple_mode/orchestrators/brownfield_orchestrator.py +135 -135
- tapps_agents/simple_mode/orchestrators/build_orchestrator.py +2700 -2667
- tapps_agents/simple_mode/orchestrators/deliverable_checklist.py +349 -349
- tapps_agents/simple_mode/orchestrators/enhance_orchestrator.py +53 -53
- tapps_agents/simple_mode/orchestrators/epic_orchestrator.py +122 -122
- tapps_agents/simple_mode/orchestrators/explore_orchestrator.py +184 -184
- tapps_agents/simple_mode/orchestrators/fix_orchestrator.py +723 -723
- tapps_agents/simple_mode/orchestrators/plan_analysis_orchestrator.py +206 -206
- tapps_agents/simple_mode/orchestrators/pr_orchestrator.py +237 -237
- tapps_agents/simple_mode/orchestrators/refactor_orchestrator.py +222 -222
- tapps_agents/simple_mode/orchestrators/requirements_tracer.py +262 -262
- tapps_agents/simple_mode/orchestrators/resume_orchestrator.py +210 -210
- tapps_agents/simple_mode/orchestrators/review_orchestrator.py +161 -161
- tapps_agents/simple_mode/orchestrators/test_orchestrator.py +82 -82
- tapps_agents/simple_mode/output_aggregator.py +340 -340
- tapps_agents/simple_mode/result_formatters.py +598 -598
- tapps_agents/simple_mode/step_dependencies.py +382 -382
- tapps_agents/simple_mode/step_results.py +276 -276
- tapps_agents/simple_mode/streaming.py +388 -388
- tapps_agents/simple_mode/variations.py +129 -129
- tapps_agents/simple_mode/visual_feedback.py +238 -238
- tapps_agents/simple_mode/zero_config.py +274 -274
- tapps_agents/suggestions/__init__.py +8 -8
- tapps_agents/suggestions/inline_suggester.py +52 -52
- tapps_agents/templates/__init__.py +8 -8
- tapps_agents/templates/microservice_generator.py +274 -274
- tapps_agents/utils/env_validator.py +291 -291
- tapps_agents/workflow/__init__.py +171 -171
- tapps_agents/workflow/acceptance_verifier.py +132 -132
- tapps_agents/workflow/agent_handlers/__init__.py +41 -41
- tapps_agents/workflow/agent_handlers/analyst_handler.py +75 -75
- tapps_agents/workflow/agent_handlers/architect_handler.py +107 -107
- tapps_agents/workflow/agent_handlers/base.py +84 -84
- tapps_agents/workflow/agent_handlers/debugger_handler.py +100 -100
- tapps_agents/workflow/agent_handlers/designer_handler.py +110 -110
- tapps_agents/workflow/agent_handlers/documenter_handler.py +94 -94
- tapps_agents/workflow/agent_handlers/implementer_handler.py +235 -235
- tapps_agents/workflow/agent_handlers/ops_handler.py +62 -62
- tapps_agents/workflow/agent_handlers/orchestrator_handler.py +43 -43
- tapps_agents/workflow/agent_handlers/planner_handler.py +98 -98
- tapps_agents/workflow/agent_handlers/registry.py +119 -119
- tapps_agents/workflow/agent_handlers/reviewer_handler.py +119 -119
- tapps_agents/workflow/agent_handlers/tester_handler.py +69 -69
- tapps_agents/workflow/analytics_accessor.py +337 -337
- tapps_agents/workflow/analytics_alerts.py +416 -416
- tapps_agents/workflow/analytics_dashboard_cursor.py +281 -281
- tapps_agents/workflow/analytics_dual_write.py +103 -103
- tapps_agents/workflow/analytics_integration.py +119 -119
- tapps_agents/workflow/analytics_query_parser.py +278 -278
- tapps_agents/workflow/analytics_visualizer.py +259 -259
- tapps_agents/workflow/artifact_helper.py +204 -204
- tapps_agents/workflow/audit_logger.py +263 -263
- tapps_agents/workflow/auto_execution_config.py +340 -340
- tapps_agents/workflow/auto_progression.py +586 -586
- tapps_agents/workflow/branch_cleanup.py +349 -349
- tapps_agents/workflow/checkpoint.py +256 -256
- tapps_agents/workflow/checkpoint_manager.py +178 -178
- tapps_agents/workflow/code_artifact.py +179 -179
- tapps_agents/workflow/common_enums.py +96 -96
- tapps_agents/workflow/confirmation_handler.py +130 -130
- tapps_agents/workflow/context_analyzer.py +222 -222
- tapps_agents/workflow/context_artifact.py +230 -230
- tapps_agents/workflow/cursor_chat.py +94 -94
- tapps_agents/workflow/cursor_executor.py +2337 -2196
- tapps_agents/workflow/cursor_skill_helper.py +516 -516
- tapps_agents/workflow/dependency_resolver.py +244 -244
- tapps_agents/workflow/design_artifact.py +156 -156
- tapps_agents/workflow/detector.py +751 -751
- tapps_agents/workflow/direct_execution_fallback.py +301 -301
- tapps_agents/workflow/docs_artifact.py +168 -168
- tapps_agents/workflow/enforcer.py +389 -389
- tapps_agents/workflow/enhancement_artifact.py +142 -142
- tapps_agents/workflow/error_recovery.py +806 -806
- tapps_agents/workflow/event_bus.py +183 -183
- tapps_agents/workflow/event_log.py +612 -612
- tapps_agents/workflow/events.py +63 -63
- tapps_agents/workflow/exceptions.py +43 -43
- tapps_agents/workflow/execution_graph.py +498 -498
- tapps_agents/workflow/execution_plan.py +126 -126
- tapps_agents/workflow/file_utils.py +186 -186
- tapps_agents/workflow/gate_evaluator.py +182 -182
- tapps_agents/workflow/gate_integration.py +200 -200
- tapps_agents/workflow/graph_visualizer.py +130 -130
- tapps_agents/workflow/health_checker.py +206 -206
- tapps_agents/workflow/logging_helper.py +243 -243
- tapps_agents/workflow/manifest.py +582 -582
- tapps_agents/workflow/marker_writer.py +250 -250
- tapps_agents/workflow/message_formatter.py +188 -188
- tapps_agents/workflow/messaging.py +325 -325
- tapps_agents/workflow/metadata_models.py +91 -91
- tapps_agents/workflow/metrics_integration.py +226 -226
- tapps_agents/workflow/migration_utils.py +116 -116
- tapps_agents/workflow/models.py +148 -111
- tapps_agents/workflow/nlp_config.py +198 -198
- tapps_agents/workflow/nlp_error_handler.py +207 -207
- tapps_agents/workflow/nlp_executor.py +163 -163
- tapps_agents/workflow/nlp_parser.py +528 -528
- tapps_agents/workflow/observability_dashboard.py +451 -451
- tapps_agents/workflow/observer.py +170 -170
- tapps_agents/workflow/ops_artifact.py +257 -257
- tapps_agents/workflow/output_passing.py +214 -214
- tapps_agents/workflow/parallel_executor.py +463 -463
- tapps_agents/workflow/planning_artifact.py +179 -179
- tapps_agents/workflow/preset_loader.py +285 -285
- tapps_agents/workflow/preset_recommender.py +270 -270
- tapps_agents/workflow/progress_logger.py +145 -145
- tapps_agents/workflow/progress_manager.py +303 -303
- tapps_agents/workflow/progress_monitor.py +186 -186
- tapps_agents/workflow/progress_updates.py +423 -423
- tapps_agents/workflow/quality_artifact.py +158 -158
- tapps_agents/workflow/quality_loopback.py +101 -101
- tapps_agents/workflow/recommender.py +387 -387
- tapps_agents/workflow/remediation_loop.py +166 -166
- tapps_agents/workflow/result_aggregator.py +300 -300
- tapps_agents/workflow/review_artifact.py +185 -185
- tapps_agents/workflow/schema_validator.py +522 -522
- tapps_agents/workflow/session_handoff.py +178 -178
- tapps_agents/workflow/skill_invoker.py +648 -648
- tapps_agents/workflow/state_manager.py +756 -756
- tapps_agents/workflow/state_persistence_config.py +331 -331
- tapps_agents/workflow/status_monitor.py +449 -449
- tapps_agents/workflow/step_checkpoint.py +314 -314
- tapps_agents/workflow/step_details.py +201 -201
- tapps_agents/workflow/story_models.py +147 -147
- tapps_agents/workflow/streaming.py +416 -416
- tapps_agents/workflow/suggestion_engine.py +552 -552
- tapps_agents/workflow/testing_artifact.py +186 -186
- tapps_agents/workflow/timeline.py +158 -158
- tapps_agents/workflow/token_integration.py +209 -209
- tapps_agents/workflow/validation.py +217 -217
- tapps_agents/workflow/visual_feedback.py +391 -391
- tapps_agents/workflow/workflow_chain.py +95 -95
- tapps_agents/workflow/workflow_summary.py +219 -219
- tapps_agents/workflow/worktree_manager.py +724 -724
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/METADATA +672 -672
- tapps_agents-3.6.0.dist-info/RECORD +758 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/licenses/LICENSE +22 -22
- tapps_agents/health/checks/outcomes.backup_20260204_064058.py +0 -324
- tapps_agents/health/checks/outcomes.backup_20260204_064256.py +0 -324
- tapps_agents/health/checks/outcomes.backup_20260204_064600.py +0 -324
- tapps_agents-3.5.40.dist-info/RECORD +0 -760
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/WHEEL +0 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/entry_points.txt +0 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/top_level.txt +0 -0
|
@@ -1,541 +1,541 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Brownfield System Review Orchestrator
|
|
3
|
-
|
|
4
|
-
Orchestrates complete brownfield review workflow: analysis, expert creation, and RAG population.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import json
|
|
10
|
-
import logging
|
|
11
|
-
import time
|
|
12
|
-
from dataclasses import dataclass, field
|
|
13
|
-
from datetime import datetime
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Any
|
|
16
|
-
|
|
17
|
-
from ..context7.agent_integration import Context7AgentHelper
|
|
18
|
-
from ..experts.domain_detector import DomainMapping
|
|
19
|
-
from ..experts.knowledge_ingestion import IngestionResult, KnowledgeIngestionPipeline
|
|
20
|
-
from .brownfield_analyzer import BrownfieldAnalysisResult, BrownfieldAnalyzer
|
|
21
|
-
from .expert_config_generator import ExpertConfig, ExpertConfigGenerator
|
|
22
|
-
|
|
23
|
-
logger = logging.getLogger(__name__)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@dataclass
|
|
27
|
-
class BrownfieldReviewResult:
|
|
28
|
-
"""Result of complete brownfield review."""
|
|
29
|
-
|
|
30
|
-
analysis: BrownfieldAnalysisResult
|
|
31
|
-
experts_created: list[ExpertConfig] = field(default_factory=list)
|
|
32
|
-
rag_results: dict[str, IngestionResult] = field(
|
|
33
|
-
default_factory=dict
|
|
34
|
-
) # expert_id -> ingestion result
|
|
35
|
-
errors: list[str] = field(default_factory=list)
|
|
36
|
-
warnings: list[str] = field(default_factory=list)
|
|
37
|
-
execution_time: float = 0.0
|
|
38
|
-
dry_run: bool = False
|
|
39
|
-
report: str = ""
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class BrownfieldReviewOrchestrator:
|
|
43
|
-
"""
|
|
44
|
-
Orchestrates complete brownfield review workflow.
|
|
45
|
-
|
|
46
|
-
Usage:
|
|
47
|
-
orchestrator = BrownfieldReviewOrchestrator(
|
|
48
|
-
project_root=Path.cwd(),
|
|
49
|
-
context7_helper=context7_helper,
|
|
50
|
-
dry_run=False
|
|
51
|
-
)
|
|
52
|
-
result = await orchestrator.review(auto=True, include_context7=True)
|
|
53
|
-
print(result.report)
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
def __init__(
|
|
57
|
-
self,
|
|
58
|
-
project_root: Path,
|
|
59
|
-
context7_helper: Context7AgentHelper | None = None,
|
|
60
|
-
dry_run: bool = False,
|
|
61
|
-
) -> None:
|
|
62
|
-
"""
|
|
63
|
-
Initialize orchestrator.
|
|
64
|
-
|
|
65
|
-
Args:
|
|
66
|
-
project_root: Root directory of project to review
|
|
67
|
-
context7_helper: Optional Context7 helper for library docs
|
|
68
|
-
dry_run: If True, preview changes without applying
|
|
69
|
-
"""
|
|
70
|
-
self.project_root = Path(project_root).resolve()
|
|
71
|
-
self.context7_helper = context7_helper
|
|
72
|
-
self.dry_run = dry_run
|
|
73
|
-
self.config_dir = self.project_root / ".tapps-agents"
|
|
74
|
-
self.state_file = self.config_dir / "brownfield-review-state.json"
|
|
75
|
-
|
|
76
|
-
# Initialize components
|
|
77
|
-
self.analyzer = BrownfieldAnalyzer(project_root=self.project_root)
|
|
78
|
-
self.config_generator = ExpertConfigGenerator(project_root=self.project_root)
|
|
79
|
-
self.ingestion_pipeline = KnowledgeIngestionPipeline(
|
|
80
|
-
project_root=self.project_root, context7_helper=context7_helper
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
async def review(
|
|
84
|
-
self,
|
|
85
|
-
auto: bool = False,
|
|
86
|
-
include_context7: bool = True,
|
|
87
|
-
resume: bool = False,
|
|
88
|
-
resume_from: str | None = None,
|
|
89
|
-
) -> BrownfieldReviewResult:
|
|
90
|
-
"""
|
|
91
|
-
Perform complete brownfield review.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
auto: If True, skip all prompts and use defaults
|
|
95
|
-
include_context7: If True, fetch library docs from Context7
|
|
96
|
-
resume: If True, resume from saved state
|
|
97
|
-
resume_from: Step to resume from ("analyze", "create_experts", "populate_rag")
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
BrownfieldReviewResult with complete analysis and results
|
|
101
|
-
"""
|
|
102
|
-
start_time = time.time()
|
|
103
|
-
errors: list[str] = []
|
|
104
|
-
warnings: list[str] = []
|
|
105
|
-
|
|
106
|
-
logger.info("Starting brownfield review")
|
|
107
|
-
if self.dry_run:
|
|
108
|
-
logger.info("DRY RUN MODE: No changes will be applied")
|
|
109
|
-
|
|
110
|
-
# Load state if resuming
|
|
111
|
-
state = None
|
|
112
|
-
if resume:
|
|
113
|
-
state = self._load_state()
|
|
114
|
-
if state and resume_from:
|
|
115
|
-
logger.info(f"Resuming from step: {resume_from}")
|
|
116
|
-
|
|
117
|
-
try:
|
|
118
|
-
# Step 1: Analyze codebase
|
|
119
|
-
if not resume or not state or resume_from == "analyze" or resume_from is None:
|
|
120
|
-
logger.info("Step 1: Analyzing codebase...")
|
|
121
|
-
analysis = await self._analyze_codebase()
|
|
122
|
-
self._save_state({"step": "analyze", "analysis": self._serialize_analysis(analysis)})
|
|
123
|
-
logger.info(
|
|
124
|
-
f"Analysis complete: {len(analysis.domains)} domains detected"
|
|
125
|
-
)
|
|
126
|
-
else:
|
|
127
|
-
# Load from state
|
|
128
|
-
analysis = self._deserialize_analysis(state.get("analysis", {}))
|
|
129
|
-
logger.info("Loaded analysis from saved state")
|
|
130
|
-
|
|
131
|
-
# Step 2: Create expert configurations
|
|
132
|
-
if not resume or not state or resume_from == "create_experts" or resume_from is None:
|
|
133
|
-
logger.info("Step 2: Creating expert configurations...")
|
|
134
|
-
experts_created = await self._create_experts(analysis.domains)
|
|
135
|
-
self._save_state({
|
|
136
|
-
"step": "create_experts",
|
|
137
|
-
"analysis": self._serialize_analysis(analysis),
|
|
138
|
-
"experts_created": [self._serialize_expert(e) for e in experts_created],
|
|
139
|
-
})
|
|
140
|
-
logger.info(f"Created {len(experts_created)} expert configurations")
|
|
141
|
-
else:
|
|
142
|
-
# Load from state
|
|
143
|
-
experts_created = [
|
|
144
|
-
self._deserialize_expert(e) for e in state.get("experts_created", [])
|
|
145
|
-
]
|
|
146
|
-
logger.info(f"Loaded {len(experts_created)} experts from saved state")
|
|
147
|
-
|
|
148
|
-
# Step 3: Populate RAG knowledge bases
|
|
149
|
-
if not resume or not state or resume_from == "populate_rag" or resume_from is None:
|
|
150
|
-
logger.info("Step 3: Populating RAG knowledge bases...")
|
|
151
|
-
rag_results = await self._populate_rag(
|
|
152
|
-
experts_created, include_context7=include_context7
|
|
153
|
-
)
|
|
154
|
-
self._save_state({
|
|
155
|
-
"step": "complete",
|
|
156
|
-
"analysis": self._serialize_analysis(analysis),
|
|
157
|
-
"experts_created": [self._serialize_expert(e) for e in experts_created],
|
|
158
|
-
"rag_results": {k: {
|
|
159
|
-
"entries_ingested": v.entries_ingested,
|
|
160
|
-
"entries_failed": v.entries_failed,
|
|
161
|
-
"source_type": v.source_type,
|
|
162
|
-
} for k, v in rag_results.items()},
|
|
163
|
-
})
|
|
164
|
-
logger.info(
|
|
165
|
-
f"Populated RAG for {len(rag_results)} experts"
|
|
166
|
-
)
|
|
167
|
-
else:
|
|
168
|
-
# Load from state
|
|
169
|
-
rag_results = {
|
|
170
|
-
k: IngestionResult(
|
|
171
|
-
source_type=v.get("source_type", "unknown"),
|
|
172
|
-
entries_ingested=v.get("entries_ingested", 0),
|
|
173
|
-
entries_failed=v.get("entries_failed", 0),
|
|
174
|
-
)
|
|
175
|
-
for k, v in state.get("rag_results", {}).items()
|
|
176
|
-
}
|
|
177
|
-
logger.info(f"Loaded RAG results from saved state")
|
|
178
|
-
|
|
179
|
-
except Exception as e:
|
|
180
|
-
error_msg = f"Brownfield review failed: {e}"
|
|
181
|
-
logger.error(error_msg, exc_info=True)
|
|
182
|
-
errors.append(error_msg)
|
|
183
|
-
# Save error state
|
|
184
|
-
self._save_state({
|
|
185
|
-
"step": "error",
|
|
186
|
-
"error": str(e),
|
|
187
|
-
"errors": errors,
|
|
188
|
-
})
|
|
189
|
-
# Create minimal result for error case
|
|
190
|
-
if 'analysis' not in locals():
|
|
191
|
-
analysis = BrownfieldAnalysisResult(project_root=self.project_root)
|
|
192
|
-
if 'experts_created' not in locals():
|
|
193
|
-
experts_created = []
|
|
194
|
-
if 'rag_results' not in locals():
|
|
195
|
-
rag_results = {}
|
|
196
|
-
|
|
197
|
-
execution_time = time.time() - start_time
|
|
198
|
-
|
|
199
|
-
# Generate report
|
|
200
|
-
result = BrownfieldReviewResult(
|
|
201
|
-
analysis=analysis,
|
|
202
|
-
experts_created=experts_created,
|
|
203
|
-
rag_results=rag_results,
|
|
204
|
-
errors=errors,
|
|
205
|
-
warnings=warnings,
|
|
206
|
-
execution_time=execution_time,
|
|
207
|
-
dry_run=self.dry_run,
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
result.report = self._generate_report(result)
|
|
211
|
-
|
|
212
|
-
logger.info(f"Brownfield review complete in {execution_time:.2f}s")
|
|
213
|
-
return result
|
|
214
|
-
|
|
215
|
-
async def _analyze_codebase(self) -> BrownfieldAnalysisResult:
|
|
216
|
-
"""Step 1: Analyze codebase structure and detect domains."""
|
|
217
|
-
try:
|
|
218
|
-
result = await self.analyzer.analyze()
|
|
219
|
-
return result
|
|
220
|
-
except Exception as e:
|
|
221
|
-
logger.error(f"Codebase analysis failed: {e}", exc_info=True)
|
|
222
|
-
raise
|
|
223
|
-
|
|
224
|
-
async def _create_experts(
|
|
225
|
-
self, domains: list[DomainMapping]
|
|
226
|
-
) -> list[ExpertConfig]:
|
|
227
|
-
"""Step 2: Create expert configurations."""
|
|
228
|
-
if self.dry_run:
|
|
229
|
-
logger.info("DRY RUN: Would create expert configs")
|
|
230
|
-
# Still generate configs for preview
|
|
231
|
-
configs = self.config_generator.generate_expert_configs(domains)
|
|
232
|
-
return configs
|
|
233
|
-
|
|
234
|
-
try:
|
|
235
|
-
# Generate expert configurations
|
|
236
|
-
configs = self.config_generator.generate_expert_configs(domains)
|
|
237
|
-
|
|
238
|
-
# Validate each config
|
|
239
|
-
valid_configs = []
|
|
240
|
-
for config in configs:
|
|
241
|
-
if self.config_generator.validate_config(config):
|
|
242
|
-
valid_configs.append(config)
|
|
243
|
-
else:
|
|
244
|
-
logger.warning(f"Invalid config for {config.expert_id}, skipping")
|
|
245
|
-
|
|
246
|
-
# Write to YAML file
|
|
247
|
-
if valid_configs:
|
|
248
|
-
self.config_generator.write_expert_configs(valid_configs, merge=True)
|
|
249
|
-
|
|
250
|
-
# Create knowledge base directories
|
|
251
|
-
for config in valid_configs:
|
|
252
|
-
if config.knowledge_base_dir:
|
|
253
|
-
config.knowledge_base_dir.mkdir(parents=True, exist_ok=True)
|
|
254
|
-
logger.info(
|
|
255
|
-
f"Created knowledge base directory: {config.knowledge_base_dir}"
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
return valid_configs
|
|
259
|
-
except Exception as e:
|
|
260
|
-
logger.error(f"Expert creation failed: {e}", exc_info=True)
|
|
261
|
-
raise
|
|
262
|
-
|
|
263
|
-
async def _populate_rag(
|
|
264
|
-
self, experts: list[ExpertConfig], include_context7: bool = True
|
|
265
|
-
) -> dict[str, IngestionResult]:
|
|
266
|
-
"""Step 3: Populate RAG knowledge bases for each expert."""
|
|
267
|
-
results: dict[str, IngestionResult] = {}
|
|
268
|
-
|
|
269
|
-
if self.dry_run:
|
|
270
|
-
logger.info("DRY RUN: Would populate RAG knowledge bases")
|
|
271
|
-
return results
|
|
272
|
-
|
|
273
|
-
# Use parallel processing for better performance
|
|
274
|
-
import asyncio
|
|
275
|
-
|
|
276
|
-
async def populate_expert_rag(expert: ExpertConfig) -> tuple[str, IngestionResult]:
|
|
277
|
-
"""Populate RAG for a single expert."""
|
|
278
|
-
try:
|
|
279
|
-
logger.info(f"Populating RAG for expert {expert.expert_id}...")
|
|
280
|
-
|
|
281
|
-
# Create expert-specific knowledge base directory if needed
|
|
282
|
-
if expert.knowledge_base_dir:
|
|
283
|
-
expert.knowledge_base_dir.mkdir(parents=True, exist_ok=True)
|
|
284
|
-
|
|
285
|
-
# Create expert-specific ingestion pipeline
|
|
286
|
-
expert_pipeline = KnowledgeIngestionPipeline(
|
|
287
|
-
project_root=self.project_root,
|
|
288
|
-
context7_helper=self.context7_helper,
|
|
289
|
-
)
|
|
290
|
-
|
|
291
|
-
# Ingest project sources for this expert's domain
|
|
292
|
-
project_result = expert_pipeline.ingest_project_sources()
|
|
293
|
-
|
|
294
|
-
# Store ingested content in expert-specific KB directory
|
|
295
|
-
if expert.knowledge_base_dir and project_result.entries_ingested > 0:
|
|
296
|
-
# Copy/move ingested files to expert KB directory
|
|
297
|
-
# This is a simplified version - full implementation would
|
|
298
|
-
# use the knowledge base's add_chunk methods
|
|
299
|
-
logger.debug(
|
|
300
|
-
f"Stored {project_result.entries_ingested} entries in {expert.knowledge_base_dir}"
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
# Ingest Context7 sources if enabled
|
|
304
|
-
context7_result = None
|
|
305
|
-
if include_context7 and self.context7_helper:
|
|
306
|
-
try:
|
|
307
|
-
context7_result = (
|
|
308
|
-
await expert_pipeline.ingest_context7_sources()
|
|
309
|
-
)
|
|
310
|
-
# Combine project and context7 results
|
|
311
|
-
if context7_result:
|
|
312
|
-
project_result.entries_ingested += context7_result.entries_ingested
|
|
313
|
-
project_result.entries_failed += context7_result.entries_failed
|
|
314
|
-
project_result.errors.extend(context7_result.errors)
|
|
315
|
-
except Exception as e:
|
|
316
|
-
logger.warning(
|
|
317
|
-
f"Context7 ingestion failed for {expert.expert_id}: {e}"
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
logger.info(
|
|
321
|
-
f"RAG population complete for {expert.expert_id}: "
|
|
322
|
-
f"{project_result.entries_ingested} entries ingested"
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
return (expert.expert_id, project_result)
|
|
326
|
-
|
|
327
|
-
except Exception as e:
|
|
328
|
-
logger.error(
|
|
329
|
-
f"RAG population failed for {expert.expert_id}: {e}",
|
|
330
|
-
exc_info=True,
|
|
331
|
-
)
|
|
332
|
-
return (
|
|
333
|
-
expert.expert_id,
|
|
334
|
-
IngestionResult(
|
|
335
|
-
source_type="error",
|
|
336
|
-
entries_ingested=0,
|
|
337
|
-
entries_failed=1,
|
|
338
|
-
errors=[str(e)],
|
|
339
|
-
),
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
# Process experts in parallel (with limit to avoid overwhelming system)
|
|
343
|
-
tasks = [populate_expert_rag(expert) for expert in experts]
|
|
344
|
-
expert_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
345
|
-
|
|
346
|
-
# Collect results
|
|
347
|
-
for result in expert_results:
|
|
348
|
-
if isinstance(result, Exception):
|
|
349
|
-
logger.error(f"Expert RAG population task failed: {result}")
|
|
350
|
-
continue
|
|
351
|
-
expert_id, ingestion_result = result
|
|
352
|
-
results[expert_id] = ingestion_result
|
|
353
|
-
|
|
354
|
-
return results
|
|
355
|
-
|
|
356
|
-
def _generate_report(self, result: BrownfieldReviewResult) -> str:
|
|
357
|
-
"""Generate human-readable summary report."""
|
|
358
|
-
lines = []
|
|
359
|
-
lines.append("# Brownfield System Review Report")
|
|
360
|
-
lines.append("")
|
|
361
|
-
lines.append(f"**Generated:** {datetime.now().isoformat()}")
|
|
362
|
-
lines.append(f"**Execution Time:** {result.execution_time:.2f}s")
|
|
363
|
-
if result.dry_run:
|
|
364
|
-
lines.append("**Mode:** DRY RUN (no changes applied)")
|
|
365
|
-
lines.append("")
|
|
366
|
-
|
|
367
|
-
# Analysis Summary
|
|
368
|
-
lines.append("## Analysis Summary")
|
|
369
|
-
lines.append("")
|
|
370
|
-
lines.append(f"- **Languages Detected:** {', '.join(result.analysis.languages) or 'None'}")
|
|
371
|
-
lines.append(f"- **Frameworks Detected:** {', '.join(result.analysis.frameworks) or 'None'}")
|
|
372
|
-
lines.append(f"- **Dependencies Found:** {len(result.analysis.dependencies)}")
|
|
373
|
-
lines.append(f"- **Domains Detected:** {len(result.analysis.domains)}")
|
|
374
|
-
lines.append("")
|
|
375
|
-
|
|
376
|
-
# Domains
|
|
377
|
-
if result.analysis.domains:
|
|
378
|
-
lines.append("### Detected Domains")
|
|
379
|
-
lines.append("")
|
|
380
|
-
for domain in result.analysis.domains[:10]: # Top 10
|
|
381
|
-
lines.append(
|
|
382
|
-
f"- **{domain.domain}** (confidence: {domain.confidence:.2f})"
|
|
383
|
-
)
|
|
384
|
-
if len(result.analysis.domains) > 10:
|
|
385
|
-
lines.append(f"- ... and {len(result.analysis.domains) - 10} more")
|
|
386
|
-
lines.append("")
|
|
387
|
-
|
|
388
|
-
# Experts Created
|
|
389
|
-
lines.append("## Experts Created")
|
|
390
|
-
lines.append("")
|
|
391
|
-
if result.experts_created:
|
|
392
|
-
for expert in result.experts_created:
|
|
393
|
-
lines.append(f"- **{expert.expert_name}** (`{expert.expert_id}`)")
|
|
394
|
-
lines.append(f" - Domain: {expert.primary_domain}")
|
|
395
|
-
lines.append(f" - RAG Enabled: {expert.rag_enabled}")
|
|
396
|
-
if expert.knowledge_base_dir:
|
|
397
|
-
lines.append(f" - KB Directory: `{expert.knowledge_base_dir}`")
|
|
398
|
-
lines.append("")
|
|
399
|
-
else:
|
|
400
|
-
lines.append("No new experts created (may already exist or no domains detected)")
|
|
401
|
-
lines.append("")
|
|
402
|
-
|
|
403
|
-
# RAG Population Results
|
|
404
|
-
lines.append("## RAG Population Results")
|
|
405
|
-
lines.append("")
|
|
406
|
-
if result.rag_results:
|
|
407
|
-
total_ingested = sum(
|
|
408
|
-
r.entries_ingested for r in result.rag_results.values()
|
|
409
|
-
)
|
|
410
|
-
total_failed = sum(r.entries_failed for r in result.rag_results.values())
|
|
411
|
-
lines.append(f"- **Total Entries Ingested:** {total_ingested}")
|
|
412
|
-
lines.append(f"- **Total Entries Failed:** {total_failed}")
|
|
413
|
-
lines.append("")
|
|
414
|
-
for expert_id, rag_result in result.rag_results.items():
|
|
415
|
-
lines.append(f"### {expert_id}")
|
|
416
|
-
lines.append(f"- Ingested: {rag_result.entries_ingested}")
|
|
417
|
-
lines.append(f"- Failed: {rag_result.entries_failed}")
|
|
418
|
-
if rag_result.errors:
|
|
419
|
-
lines.append(f"- Errors: {len(rag_result.errors)}")
|
|
420
|
-
lines.append("")
|
|
421
|
-
else:
|
|
422
|
-
lines.append("No RAG population performed (dry run or no experts)")
|
|
423
|
-
lines.append("")
|
|
424
|
-
|
|
425
|
-
# Errors and Warnings
|
|
426
|
-
if result.errors:
|
|
427
|
-
lines.append("## Errors")
|
|
428
|
-
lines.append("")
|
|
429
|
-
for error in result.errors:
|
|
430
|
-
lines.append(f"- ❌ {error}")
|
|
431
|
-
lines.append("")
|
|
432
|
-
|
|
433
|
-
if result.warnings:
|
|
434
|
-
lines.append("## Warnings")
|
|
435
|
-
lines.append("")
|
|
436
|
-
for warning in result.warnings:
|
|
437
|
-
lines.append(f"- ⚠️ {warning}")
|
|
438
|
-
lines.append("")
|
|
439
|
-
|
|
440
|
-
# Summary
|
|
441
|
-
lines.append("## Summary")
|
|
442
|
-
lines.append("")
|
|
443
|
-
if result.dry_run:
|
|
444
|
-
lines.append("This was a dry run. No changes were applied.")
|
|
445
|
-
else:
|
|
446
|
-
lines.append(
|
|
447
|
-
f"✅ Created {len(result.experts_created)} expert configurations"
|
|
448
|
-
)
|
|
449
|
-
lines.append(
|
|
450
|
-
f"✅ Populated RAG for {len(result.rag_results)} experts"
|
|
451
|
-
)
|
|
452
|
-
lines.append("")
|
|
453
|
-
|
|
454
|
-
return "\n".join(lines)
|
|
455
|
-
|
|
456
|
-
def _save_state(self, state: dict[str, Any]) -> None:
|
|
457
|
-
"""Save workflow state to file."""
|
|
458
|
-
if self.dry_run:
|
|
459
|
-
return # Don't save state in dry-run mode
|
|
460
|
-
|
|
461
|
-
try:
|
|
462
|
-
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
463
|
-
with open(self.state_file, "w", encoding="utf-8") as f:
|
|
464
|
-
json.dump(state, f, indent=2, default=str)
|
|
465
|
-
logger.debug(f"Saved state to {self.state_file}")
|
|
466
|
-
except Exception as e:
|
|
467
|
-
logger.warning(f"Failed to save state: {e}")
|
|
468
|
-
|
|
469
|
-
def _load_state(self) -> dict[str, Any] | None:
|
|
470
|
-
"""Load workflow state from file."""
|
|
471
|
-
if not self.state_file.exists():
|
|
472
|
-
return None
|
|
473
|
-
|
|
474
|
-
try:
|
|
475
|
-
with open(self.state_file, "r", encoding="utf-8") as f:
|
|
476
|
-
return json.load(f)
|
|
477
|
-
except Exception as e:
|
|
478
|
-
logger.warning(f"Failed to load state: {e}")
|
|
479
|
-
return None
|
|
480
|
-
|
|
481
|
-
def _serialize_analysis(self, analysis: BrownfieldAnalysisResult) -> dict[str, Any]:
|
|
482
|
-
"""Serialize analysis result for state storage."""
|
|
483
|
-
return {
|
|
484
|
-
"languages": analysis.languages,
|
|
485
|
-
"frameworks": analysis.frameworks,
|
|
486
|
-
"dependencies": analysis.dependencies,
|
|
487
|
-
"domains": [
|
|
488
|
-
{
|
|
489
|
-
"domain": d.domain,
|
|
490
|
-
"confidence": d.confidence,
|
|
491
|
-
"reasoning": d.reasoning,
|
|
492
|
-
}
|
|
493
|
-
for d in analysis.domains
|
|
494
|
-
],
|
|
495
|
-
"analysis_metadata": analysis.analysis_metadata,
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
def _deserialize_analysis(self, data: dict[str, Any]) -> BrownfieldAnalysisResult:
|
|
499
|
-
"""Deserialize analysis result from state."""
|
|
500
|
-
from ..experts.domain_detector import DomainMapping
|
|
501
|
-
|
|
502
|
-
domains = [
|
|
503
|
-
DomainMapping(
|
|
504
|
-
domain=d["domain"],
|
|
505
|
-
confidence=d["confidence"],
|
|
506
|
-
signals=[],
|
|
507
|
-
reasoning=d.get("reasoning", ""),
|
|
508
|
-
)
|
|
509
|
-
for d in data.get("domains", [])
|
|
510
|
-
]
|
|
511
|
-
|
|
512
|
-
return BrownfieldAnalysisResult(
|
|
513
|
-
project_root=self.project_root,
|
|
514
|
-
languages=data.get("languages", []),
|
|
515
|
-
frameworks=data.get("frameworks", []),
|
|
516
|
-
dependencies=data.get("dependencies", []),
|
|
517
|
-
domains=domains,
|
|
518
|
-
analysis_metadata=data.get("analysis_metadata", {}),
|
|
519
|
-
)
|
|
520
|
-
|
|
521
|
-
def _serialize_expert(self, expert: ExpertConfig) -> dict[str, Any]:
|
|
522
|
-
"""Serialize expert config for state storage."""
|
|
523
|
-
return {
|
|
524
|
-
"expert_id": expert.expert_id,
|
|
525
|
-
"expert_name": expert.expert_name,
|
|
526
|
-
"primary_domain": expert.primary_domain,
|
|
527
|
-
"rag_enabled": expert.rag_enabled,
|
|
528
|
-
"knowledge_base_dir": str(expert.knowledge_base_dir) if expert.knowledge_base_dir else None,
|
|
529
|
-
"confidence_matrix": expert.confidence_matrix,
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
def _deserialize_expert(self, data: dict[str, Any]) -> ExpertConfig:
|
|
533
|
-
"""Deserialize expert config from state."""
|
|
534
|
-
return ExpertConfig(
|
|
535
|
-
expert_id=data["expert_id"],
|
|
536
|
-
expert_name=data["expert_name"],
|
|
537
|
-
primary_domain=data["primary_domain"],
|
|
538
|
-
rag_enabled=data.get("rag_enabled", True),
|
|
539
|
-
knowledge_base_dir=Path(data["knowledge_base_dir"]) if data.get("knowledge_base_dir") else None,
|
|
540
|
-
confidence_matrix=data.get("confidence_matrix"),
|
|
541
|
-
)
|
|
1
|
+
"""
|
|
2
|
+
Brownfield System Review Orchestrator
|
|
3
|
+
|
|
4
|
+
Orchestrates complete brownfield review workflow: analysis, expert creation, and RAG population.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
import time
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from ..context7.agent_integration import Context7AgentHelper
|
|
18
|
+
from ..experts.domain_detector import DomainMapping
|
|
19
|
+
from ..experts.knowledge_ingestion import IngestionResult, KnowledgeIngestionPipeline
|
|
20
|
+
from .brownfield_analyzer import BrownfieldAnalysisResult, BrownfieldAnalyzer
|
|
21
|
+
from .expert_config_generator import ExpertConfig, ExpertConfigGenerator
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class BrownfieldReviewResult:
|
|
28
|
+
"""Result of complete brownfield review."""
|
|
29
|
+
|
|
30
|
+
analysis: BrownfieldAnalysisResult
|
|
31
|
+
experts_created: list[ExpertConfig] = field(default_factory=list)
|
|
32
|
+
rag_results: dict[str, IngestionResult] = field(
|
|
33
|
+
default_factory=dict
|
|
34
|
+
) # expert_id -> ingestion result
|
|
35
|
+
errors: list[str] = field(default_factory=list)
|
|
36
|
+
warnings: list[str] = field(default_factory=list)
|
|
37
|
+
execution_time: float = 0.0
|
|
38
|
+
dry_run: bool = False
|
|
39
|
+
report: str = ""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class BrownfieldReviewOrchestrator:
|
|
43
|
+
"""
|
|
44
|
+
Orchestrates complete brownfield review workflow.
|
|
45
|
+
|
|
46
|
+
Usage:
|
|
47
|
+
orchestrator = BrownfieldReviewOrchestrator(
|
|
48
|
+
project_root=Path.cwd(),
|
|
49
|
+
context7_helper=context7_helper,
|
|
50
|
+
dry_run=False
|
|
51
|
+
)
|
|
52
|
+
result = await orchestrator.review(auto=True, include_context7=True)
|
|
53
|
+
print(result.report)
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def __init__(
|
|
57
|
+
self,
|
|
58
|
+
project_root: Path,
|
|
59
|
+
context7_helper: Context7AgentHelper | None = None,
|
|
60
|
+
dry_run: bool = False,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Initialize orchestrator.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
project_root: Root directory of project to review
|
|
67
|
+
context7_helper: Optional Context7 helper for library docs
|
|
68
|
+
dry_run: If True, preview changes without applying
|
|
69
|
+
"""
|
|
70
|
+
self.project_root = Path(project_root).resolve()
|
|
71
|
+
self.context7_helper = context7_helper
|
|
72
|
+
self.dry_run = dry_run
|
|
73
|
+
self.config_dir = self.project_root / ".tapps-agents"
|
|
74
|
+
self.state_file = self.config_dir / "brownfield-review-state.json"
|
|
75
|
+
|
|
76
|
+
# Initialize components
|
|
77
|
+
self.analyzer = BrownfieldAnalyzer(project_root=self.project_root)
|
|
78
|
+
self.config_generator = ExpertConfigGenerator(project_root=self.project_root)
|
|
79
|
+
self.ingestion_pipeline = KnowledgeIngestionPipeline(
|
|
80
|
+
project_root=self.project_root, context7_helper=context7_helper
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
async def review(
|
|
84
|
+
self,
|
|
85
|
+
auto: bool = False,
|
|
86
|
+
include_context7: bool = True,
|
|
87
|
+
resume: bool = False,
|
|
88
|
+
resume_from: str | None = None,
|
|
89
|
+
) -> BrownfieldReviewResult:
|
|
90
|
+
"""
|
|
91
|
+
Perform complete brownfield review.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
auto: If True, skip all prompts and use defaults
|
|
95
|
+
include_context7: If True, fetch library docs from Context7
|
|
96
|
+
resume: If True, resume from saved state
|
|
97
|
+
resume_from: Step to resume from ("analyze", "create_experts", "populate_rag")
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
BrownfieldReviewResult with complete analysis and results
|
|
101
|
+
"""
|
|
102
|
+
start_time = time.time()
|
|
103
|
+
errors: list[str] = []
|
|
104
|
+
warnings: list[str] = []
|
|
105
|
+
|
|
106
|
+
logger.info("Starting brownfield review")
|
|
107
|
+
if self.dry_run:
|
|
108
|
+
logger.info("DRY RUN MODE: No changes will be applied")
|
|
109
|
+
|
|
110
|
+
# Load state if resuming
|
|
111
|
+
state = None
|
|
112
|
+
if resume:
|
|
113
|
+
state = self._load_state()
|
|
114
|
+
if state and resume_from:
|
|
115
|
+
logger.info(f"Resuming from step: {resume_from}")
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
# Step 1: Analyze codebase
|
|
119
|
+
if not resume or not state or resume_from == "analyze" or resume_from is None:
|
|
120
|
+
logger.info("Step 1: Analyzing codebase...")
|
|
121
|
+
analysis = await self._analyze_codebase()
|
|
122
|
+
self._save_state({"step": "analyze", "analysis": self._serialize_analysis(analysis)})
|
|
123
|
+
logger.info(
|
|
124
|
+
f"Analysis complete: {len(analysis.domains)} domains detected"
|
|
125
|
+
)
|
|
126
|
+
else:
|
|
127
|
+
# Load from state
|
|
128
|
+
analysis = self._deserialize_analysis(state.get("analysis", {}))
|
|
129
|
+
logger.info("Loaded analysis from saved state")
|
|
130
|
+
|
|
131
|
+
# Step 2: Create expert configurations
|
|
132
|
+
if not resume or not state or resume_from == "create_experts" or resume_from is None:
|
|
133
|
+
logger.info("Step 2: Creating expert configurations...")
|
|
134
|
+
experts_created = await self._create_experts(analysis.domains)
|
|
135
|
+
self._save_state({
|
|
136
|
+
"step": "create_experts",
|
|
137
|
+
"analysis": self._serialize_analysis(analysis),
|
|
138
|
+
"experts_created": [self._serialize_expert(e) for e in experts_created],
|
|
139
|
+
})
|
|
140
|
+
logger.info(f"Created {len(experts_created)} expert configurations")
|
|
141
|
+
else:
|
|
142
|
+
# Load from state
|
|
143
|
+
experts_created = [
|
|
144
|
+
self._deserialize_expert(e) for e in state.get("experts_created", [])
|
|
145
|
+
]
|
|
146
|
+
logger.info(f"Loaded {len(experts_created)} experts from saved state")
|
|
147
|
+
|
|
148
|
+
# Step 3: Populate RAG knowledge bases
|
|
149
|
+
if not resume or not state or resume_from == "populate_rag" or resume_from is None:
|
|
150
|
+
logger.info("Step 3: Populating RAG knowledge bases...")
|
|
151
|
+
rag_results = await self._populate_rag(
|
|
152
|
+
experts_created, include_context7=include_context7
|
|
153
|
+
)
|
|
154
|
+
self._save_state({
|
|
155
|
+
"step": "complete",
|
|
156
|
+
"analysis": self._serialize_analysis(analysis),
|
|
157
|
+
"experts_created": [self._serialize_expert(e) for e in experts_created],
|
|
158
|
+
"rag_results": {k: {
|
|
159
|
+
"entries_ingested": v.entries_ingested,
|
|
160
|
+
"entries_failed": v.entries_failed,
|
|
161
|
+
"source_type": v.source_type,
|
|
162
|
+
} for k, v in rag_results.items()},
|
|
163
|
+
})
|
|
164
|
+
logger.info(
|
|
165
|
+
f"Populated RAG for {len(rag_results)} experts"
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
# Load from state
|
|
169
|
+
rag_results = {
|
|
170
|
+
k: IngestionResult(
|
|
171
|
+
source_type=v.get("source_type", "unknown"),
|
|
172
|
+
entries_ingested=v.get("entries_ingested", 0),
|
|
173
|
+
entries_failed=v.get("entries_failed", 0),
|
|
174
|
+
)
|
|
175
|
+
for k, v in state.get("rag_results", {}).items()
|
|
176
|
+
}
|
|
177
|
+
logger.info(f"Loaded RAG results from saved state")
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
error_msg = f"Brownfield review failed: {e}"
|
|
181
|
+
logger.error(error_msg, exc_info=True)
|
|
182
|
+
errors.append(error_msg)
|
|
183
|
+
# Save error state
|
|
184
|
+
self._save_state({
|
|
185
|
+
"step": "error",
|
|
186
|
+
"error": str(e),
|
|
187
|
+
"errors": errors,
|
|
188
|
+
})
|
|
189
|
+
# Create minimal result for error case
|
|
190
|
+
if 'analysis' not in locals():
|
|
191
|
+
analysis = BrownfieldAnalysisResult(project_root=self.project_root)
|
|
192
|
+
if 'experts_created' not in locals():
|
|
193
|
+
experts_created = []
|
|
194
|
+
if 'rag_results' not in locals():
|
|
195
|
+
rag_results = {}
|
|
196
|
+
|
|
197
|
+
execution_time = time.time() - start_time
|
|
198
|
+
|
|
199
|
+
# Generate report
|
|
200
|
+
result = BrownfieldReviewResult(
|
|
201
|
+
analysis=analysis,
|
|
202
|
+
experts_created=experts_created,
|
|
203
|
+
rag_results=rag_results,
|
|
204
|
+
errors=errors,
|
|
205
|
+
warnings=warnings,
|
|
206
|
+
execution_time=execution_time,
|
|
207
|
+
dry_run=self.dry_run,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
result.report = self._generate_report(result)
|
|
211
|
+
|
|
212
|
+
logger.info(f"Brownfield review complete in {execution_time:.2f}s")
|
|
213
|
+
return result
|
|
214
|
+
|
|
215
|
+
async def _analyze_codebase(self) -> BrownfieldAnalysisResult:
|
|
216
|
+
"""Step 1: Analyze codebase structure and detect domains."""
|
|
217
|
+
try:
|
|
218
|
+
result = await self.analyzer.analyze()
|
|
219
|
+
return result
|
|
220
|
+
except Exception as e:
|
|
221
|
+
logger.error(f"Codebase analysis failed: {e}", exc_info=True)
|
|
222
|
+
raise
|
|
223
|
+
|
|
224
|
+
async def _create_experts(
|
|
225
|
+
self, domains: list[DomainMapping]
|
|
226
|
+
) -> list[ExpertConfig]:
|
|
227
|
+
"""Step 2: Create expert configurations."""
|
|
228
|
+
if self.dry_run:
|
|
229
|
+
logger.info("DRY RUN: Would create expert configs")
|
|
230
|
+
# Still generate configs for preview
|
|
231
|
+
configs = self.config_generator.generate_expert_configs(domains)
|
|
232
|
+
return configs
|
|
233
|
+
|
|
234
|
+
try:
|
|
235
|
+
# Generate expert configurations
|
|
236
|
+
configs = self.config_generator.generate_expert_configs(domains)
|
|
237
|
+
|
|
238
|
+
# Validate each config
|
|
239
|
+
valid_configs = []
|
|
240
|
+
for config in configs:
|
|
241
|
+
if self.config_generator.validate_config(config):
|
|
242
|
+
valid_configs.append(config)
|
|
243
|
+
else:
|
|
244
|
+
logger.warning(f"Invalid config for {config.expert_id}, skipping")
|
|
245
|
+
|
|
246
|
+
# Write to YAML file
|
|
247
|
+
if valid_configs:
|
|
248
|
+
self.config_generator.write_expert_configs(valid_configs, merge=True)
|
|
249
|
+
|
|
250
|
+
# Create knowledge base directories
|
|
251
|
+
for config in valid_configs:
|
|
252
|
+
if config.knowledge_base_dir:
|
|
253
|
+
config.knowledge_base_dir.mkdir(parents=True, exist_ok=True)
|
|
254
|
+
logger.info(
|
|
255
|
+
f"Created knowledge base directory: {config.knowledge_base_dir}"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
return valid_configs
|
|
259
|
+
except Exception as e:
|
|
260
|
+
logger.error(f"Expert creation failed: {e}", exc_info=True)
|
|
261
|
+
raise
|
|
262
|
+
|
|
263
|
+
async def _populate_rag(
|
|
264
|
+
self, experts: list[ExpertConfig], include_context7: bool = True
|
|
265
|
+
) -> dict[str, IngestionResult]:
|
|
266
|
+
"""Step 3: Populate RAG knowledge bases for each expert."""
|
|
267
|
+
results: dict[str, IngestionResult] = {}
|
|
268
|
+
|
|
269
|
+
if self.dry_run:
|
|
270
|
+
logger.info("DRY RUN: Would populate RAG knowledge bases")
|
|
271
|
+
return results
|
|
272
|
+
|
|
273
|
+
# Use parallel processing for better performance
|
|
274
|
+
import asyncio
|
|
275
|
+
|
|
276
|
+
async def populate_expert_rag(expert: ExpertConfig) -> tuple[str, IngestionResult]:
|
|
277
|
+
"""Populate RAG for a single expert."""
|
|
278
|
+
try:
|
|
279
|
+
logger.info(f"Populating RAG for expert {expert.expert_id}...")
|
|
280
|
+
|
|
281
|
+
# Create expert-specific knowledge base directory if needed
|
|
282
|
+
if expert.knowledge_base_dir:
|
|
283
|
+
expert.knowledge_base_dir.mkdir(parents=True, exist_ok=True)
|
|
284
|
+
|
|
285
|
+
# Create expert-specific ingestion pipeline
|
|
286
|
+
expert_pipeline = KnowledgeIngestionPipeline(
|
|
287
|
+
project_root=self.project_root,
|
|
288
|
+
context7_helper=self.context7_helper,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# Ingest project sources for this expert's domain
|
|
292
|
+
project_result = expert_pipeline.ingest_project_sources()
|
|
293
|
+
|
|
294
|
+
# Store ingested content in expert-specific KB directory
|
|
295
|
+
if expert.knowledge_base_dir and project_result.entries_ingested > 0:
|
|
296
|
+
# Copy/move ingested files to expert KB directory
|
|
297
|
+
# This is a simplified version - full implementation would
|
|
298
|
+
# use the knowledge base's add_chunk methods
|
|
299
|
+
logger.debug(
|
|
300
|
+
f"Stored {project_result.entries_ingested} entries in {expert.knowledge_base_dir}"
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
# Ingest Context7 sources if enabled
|
|
304
|
+
context7_result = None
|
|
305
|
+
if include_context7 and self.context7_helper:
|
|
306
|
+
try:
|
|
307
|
+
context7_result = (
|
|
308
|
+
await expert_pipeline.ingest_context7_sources()
|
|
309
|
+
)
|
|
310
|
+
# Combine project and context7 results
|
|
311
|
+
if context7_result:
|
|
312
|
+
project_result.entries_ingested += context7_result.entries_ingested
|
|
313
|
+
project_result.entries_failed += context7_result.entries_failed
|
|
314
|
+
project_result.errors.extend(context7_result.errors)
|
|
315
|
+
except Exception as e:
|
|
316
|
+
logger.warning(
|
|
317
|
+
f"Context7 ingestion failed for {expert.expert_id}: {e}"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
logger.info(
|
|
321
|
+
f"RAG population complete for {expert.expert_id}: "
|
|
322
|
+
f"{project_result.entries_ingested} entries ingested"
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
return (expert.expert_id, project_result)
|
|
326
|
+
|
|
327
|
+
except Exception as e:
|
|
328
|
+
logger.error(
|
|
329
|
+
f"RAG population failed for {expert.expert_id}: {e}",
|
|
330
|
+
exc_info=True,
|
|
331
|
+
)
|
|
332
|
+
return (
|
|
333
|
+
expert.expert_id,
|
|
334
|
+
IngestionResult(
|
|
335
|
+
source_type="error",
|
|
336
|
+
entries_ingested=0,
|
|
337
|
+
entries_failed=1,
|
|
338
|
+
errors=[str(e)],
|
|
339
|
+
),
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Process experts in parallel (with limit to avoid overwhelming system)
|
|
343
|
+
tasks = [populate_expert_rag(expert) for expert in experts]
|
|
344
|
+
expert_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
345
|
+
|
|
346
|
+
# Collect results
|
|
347
|
+
for result in expert_results:
|
|
348
|
+
if isinstance(result, Exception):
|
|
349
|
+
logger.error(f"Expert RAG population task failed: {result}")
|
|
350
|
+
continue
|
|
351
|
+
expert_id, ingestion_result = result
|
|
352
|
+
results[expert_id] = ingestion_result
|
|
353
|
+
|
|
354
|
+
return results
|
|
355
|
+
|
|
356
|
+
def _generate_report(self, result: BrownfieldReviewResult) -> str:
|
|
357
|
+
"""Generate human-readable summary report."""
|
|
358
|
+
lines = []
|
|
359
|
+
lines.append("# Brownfield System Review Report")
|
|
360
|
+
lines.append("")
|
|
361
|
+
lines.append(f"**Generated:** {datetime.now().isoformat()}")
|
|
362
|
+
lines.append(f"**Execution Time:** {result.execution_time:.2f}s")
|
|
363
|
+
if result.dry_run:
|
|
364
|
+
lines.append("**Mode:** DRY RUN (no changes applied)")
|
|
365
|
+
lines.append("")
|
|
366
|
+
|
|
367
|
+
# Analysis Summary
|
|
368
|
+
lines.append("## Analysis Summary")
|
|
369
|
+
lines.append("")
|
|
370
|
+
lines.append(f"- **Languages Detected:** {', '.join(result.analysis.languages) or 'None'}")
|
|
371
|
+
lines.append(f"- **Frameworks Detected:** {', '.join(result.analysis.frameworks) or 'None'}")
|
|
372
|
+
lines.append(f"- **Dependencies Found:** {len(result.analysis.dependencies)}")
|
|
373
|
+
lines.append(f"- **Domains Detected:** {len(result.analysis.domains)}")
|
|
374
|
+
lines.append("")
|
|
375
|
+
|
|
376
|
+
# Domains
|
|
377
|
+
if result.analysis.domains:
|
|
378
|
+
lines.append("### Detected Domains")
|
|
379
|
+
lines.append("")
|
|
380
|
+
for domain in result.analysis.domains[:10]: # Top 10
|
|
381
|
+
lines.append(
|
|
382
|
+
f"- **{domain.domain}** (confidence: {domain.confidence:.2f})"
|
|
383
|
+
)
|
|
384
|
+
if len(result.analysis.domains) > 10:
|
|
385
|
+
lines.append(f"- ... and {len(result.analysis.domains) - 10} more")
|
|
386
|
+
lines.append("")
|
|
387
|
+
|
|
388
|
+
# Experts Created
|
|
389
|
+
lines.append("## Experts Created")
|
|
390
|
+
lines.append("")
|
|
391
|
+
if result.experts_created:
|
|
392
|
+
for expert in result.experts_created:
|
|
393
|
+
lines.append(f"- **{expert.expert_name}** (`{expert.expert_id}`)")
|
|
394
|
+
lines.append(f" - Domain: {expert.primary_domain}")
|
|
395
|
+
lines.append(f" - RAG Enabled: {expert.rag_enabled}")
|
|
396
|
+
if expert.knowledge_base_dir:
|
|
397
|
+
lines.append(f" - KB Directory: `{expert.knowledge_base_dir}`")
|
|
398
|
+
lines.append("")
|
|
399
|
+
else:
|
|
400
|
+
lines.append("No new experts created (may already exist or no domains detected)")
|
|
401
|
+
lines.append("")
|
|
402
|
+
|
|
403
|
+
# RAG Population Results
|
|
404
|
+
lines.append("## RAG Population Results")
|
|
405
|
+
lines.append("")
|
|
406
|
+
if result.rag_results:
|
|
407
|
+
total_ingested = sum(
|
|
408
|
+
r.entries_ingested for r in result.rag_results.values()
|
|
409
|
+
)
|
|
410
|
+
total_failed = sum(r.entries_failed for r in result.rag_results.values())
|
|
411
|
+
lines.append(f"- **Total Entries Ingested:** {total_ingested}")
|
|
412
|
+
lines.append(f"- **Total Entries Failed:** {total_failed}")
|
|
413
|
+
lines.append("")
|
|
414
|
+
for expert_id, rag_result in result.rag_results.items():
|
|
415
|
+
lines.append(f"### {expert_id}")
|
|
416
|
+
lines.append(f"- Ingested: {rag_result.entries_ingested}")
|
|
417
|
+
lines.append(f"- Failed: {rag_result.entries_failed}")
|
|
418
|
+
if rag_result.errors:
|
|
419
|
+
lines.append(f"- Errors: {len(rag_result.errors)}")
|
|
420
|
+
lines.append("")
|
|
421
|
+
else:
|
|
422
|
+
lines.append("No RAG population performed (dry run or no experts)")
|
|
423
|
+
lines.append("")
|
|
424
|
+
|
|
425
|
+
# Errors and Warnings
|
|
426
|
+
if result.errors:
|
|
427
|
+
lines.append("## Errors")
|
|
428
|
+
lines.append("")
|
|
429
|
+
for error in result.errors:
|
|
430
|
+
lines.append(f"- ❌ {error}")
|
|
431
|
+
lines.append("")
|
|
432
|
+
|
|
433
|
+
if result.warnings:
|
|
434
|
+
lines.append("## Warnings")
|
|
435
|
+
lines.append("")
|
|
436
|
+
for warning in result.warnings:
|
|
437
|
+
lines.append(f"- ⚠️ {warning}")
|
|
438
|
+
lines.append("")
|
|
439
|
+
|
|
440
|
+
# Summary
|
|
441
|
+
lines.append("## Summary")
|
|
442
|
+
lines.append("")
|
|
443
|
+
if result.dry_run:
|
|
444
|
+
lines.append("This was a dry run. No changes were applied.")
|
|
445
|
+
else:
|
|
446
|
+
lines.append(
|
|
447
|
+
f"✅ Created {len(result.experts_created)} expert configurations"
|
|
448
|
+
)
|
|
449
|
+
lines.append(
|
|
450
|
+
f"✅ Populated RAG for {len(result.rag_results)} experts"
|
|
451
|
+
)
|
|
452
|
+
lines.append("")
|
|
453
|
+
|
|
454
|
+
return "\n".join(lines)
|
|
455
|
+
|
|
456
|
+
def _save_state(self, state: dict[str, Any]) -> None:
|
|
457
|
+
"""Save workflow state to file."""
|
|
458
|
+
if self.dry_run:
|
|
459
|
+
return # Don't save state in dry-run mode
|
|
460
|
+
|
|
461
|
+
try:
|
|
462
|
+
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
463
|
+
with open(self.state_file, "w", encoding="utf-8") as f:
|
|
464
|
+
json.dump(state, f, indent=2, default=str)
|
|
465
|
+
logger.debug(f"Saved state to {self.state_file}")
|
|
466
|
+
except Exception as e:
|
|
467
|
+
logger.warning(f"Failed to save state: {e}")
|
|
468
|
+
|
|
469
|
+
def _load_state(self) -> dict[str, Any] | None:
|
|
470
|
+
"""Load workflow state from file."""
|
|
471
|
+
if not self.state_file.exists():
|
|
472
|
+
return None
|
|
473
|
+
|
|
474
|
+
try:
|
|
475
|
+
with open(self.state_file, "r", encoding="utf-8") as f:
|
|
476
|
+
return json.load(f)
|
|
477
|
+
except Exception as e:
|
|
478
|
+
logger.warning(f"Failed to load state: {e}")
|
|
479
|
+
return None
|
|
480
|
+
|
|
481
|
+
def _serialize_analysis(self, analysis: BrownfieldAnalysisResult) -> dict[str, Any]:
|
|
482
|
+
"""Serialize analysis result for state storage."""
|
|
483
|
+
return {
|
|
484
|
+
"languages": analysis.languages,
|
|
485
|
+
"frameworks": analysis.frameworks,
|
|
486
|
+
"dependencies": analysis.dependencies,
|
|
487
|
+
"domains": [
|
|
488
|
+
{
|
|
489
|
+
"domain": d.domain,
|
|
490
|
+
"confidence": d.confidence,
|
|
491
|
+
"reasoning": d.reasoning,
|
|
492
|
+
}
|
|
493
|
+
for d in analysis.domains
|
|
494
|
+
],
|
|
495
|
+
"analysis_metadata": analysis.analysis_metadata,
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
def _deserialize_analysis(self, data: dict[str, Any]) -> BrownfieldAnalysisResult:
|
|
499
|
+
"""Deserialize analysis result from state."""
|
|
500
|
+
from ..experts.domain_detector import DomainMapping
|
|
501
|
+
|
|
502
|
+
domains = [
|
|
503
|
+
DomainMapping(
|
|
504
|
+
domain=d["domain"],
|
|
505
|
+
confidence=d["confidence"],
|
|
506
|
+
signals=[],
|
|
507
|
+
reasoning=d.get("reasoning", ""),
|
|
508
|
+
)
|
|
509
|
+
for d in data.get("domains", [])
|
|
510
|
+
]
|
|
511
|
+
|
|
512
|
+
return BrownfieldAnalysisResult(
|
|
513
|
+
project_root=self.project_root,
|
|
514
|
+
languages=data.get("languages", []),
|
|
515
|
+
frameworks=data.get("frameworks", []),
|
|
516
|
+
dependencies=data.get("dependencies", []),
|
|
517
|
+
domains=domains,
|
|
518
|
+
analysis_metadata=data.get("analysis_metadata", {}),
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
def _serialize_expert(self, expert: ExpertConfig) -> dict[str, Any]:
|
|
522
|
+
"""Serialize expert config for state storage."""
|
|
523
|
+
return {
|
|
524
|
+
"expert_id": expert.expert_id,
|
|
525
|
+
"expert_name": expert.expert_name,
|
|
526
|
+
"primary_domain": expert.primary_domain,
|
|
527
|
+
"rag_enabled": expert.rag_enabled,
|
|
528
|
+
"knowledge_base_dir": str(expert.knowledge_base_dir) if expert.knowledge_base_dir else None,
|
|
529
|
+
"confidence_matrix": expert.confidence_matrix,
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
def _deserialize_expert(self, data: dict[str, Any]) -> ExpertConfig:
|
|
533
|
+
"""Deserialize expert config from state."""
|
|
534
|
+
return ExpertConfig(
|
|
535
|
+
expert_id=data["expert_id"],
|
|
536
|
+
expert_name=data["expert_name"],
|
|
537
|
+
primary_domain=data["primary_domain"],
|
|
538
|
+
rag_enabled=data.get("rag_enabled", True),
|
|
539
|
+
knowledge_base_dir=Path(data["knowledge_base_dir"]) if data.get("knowledge_base_dir") else None,
|
|
540
|
+
confidence_matrix=data.get("confidence_matrix"),
|
|
541
|
+
)
|