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,1034 +1,1034 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Architect Agent - System and security architecture design.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import json
|
|
6
|
-
import logging
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from typing import Any
|
|
9
|
-
|
|
10
|
-
from ...context7.agent_integration import Context7AgentHelper, get_context7_helper
|
|
11
|
-
from ...core.agent_base import BaseAgent
|
|
12
|
-
from ...core.config import ProjectConfig, load_config
|
|
13
|
-
from ...core.instructions import GenericInstruction
|
|
14
|
-
from ...experts.agent_integration import ExpertSupportMixin
|
|
15
|
-
|
|
16
|
-
logger = logging.getLogger(__name__)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class ArchitectAgent(BaseAgent, ExpertSupportMixin):
|
|
20
|
-
"""
|
|
21
|
-
Architect Agent - System and security architecture design.
|
|
22
|
-
|
|
23
|
-
Permissions: Read, Write, Grep, Glob (no Edit, no Bash)
|
|
24
|
-
|
|
25
|
-
⚠️ CRITICAL ACCURACY REQUIREMENT:
|
|
26
|
-
- NEVER make up, invent, or fabricate information - Only report verified facts
|
|
27
|
-
- ALWAYS verify claims by checking actual results, not just test pass/fail
|
|
28
|
-
- Verify API calls succeed - inspect response data, status codes, error messages
|
|
29
|
-
- Distinguish between code paths executing and actual functionality working
|
|
30
|
-
- Admit uncertainty explicitly when you cannot verify
|
|
31
|
-
|
|
32
|
-
Responsibilities:
|
|
33
|
-
- Design system architecture
|
|
34
|
-
- Create architecture diagrams (text-based)
|
|
35
|
-
- Select technologies
|
|
36
|
-
- Design security architecture
|
|
37
|
-
- Define system boundaries
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
def __init__(
|
|
41
|
-
self,
|
|
42
|
-
config: ProjectConfig | None = None,
|
|
43
|
-
expert_registry: Any | None = None,
|
|
44
|
-
):
|
|
45
|
-
super().__init__(
|
|
46
|
-
agent_id="architect", agent_name="Architect Agent", config=config
|
|
47
|
-
)
|
|
48
|
-
if config is None:
|
|
49
|
-
config = load_config()
|
|
50
|
-
self.config = config
|
|
51
|
-
|
|
52
|
-
# Initialize Context7 helper
|
|
53
|
-
self.context7: Context7AgentHelper | None = None
|
|
54
|
-
if config:
|
|
55
|
-
self.context7 = get_context7_helper(self, config)
|
|
56
|
-
|
|
57
|
-
# Expert registry initialization (required due to multiple inheritance MRO issue)
|
|
58
|
-
# BaseAgent.__init__() doesn't call super().__init__(), so ExpertSupportMixin.__init__()
|
|
59
|
-
# is never called via MRO. We must manually initialize to avoid AttributeError.
|
|
60
|
-
# The registry will be properly initialized in activate() via _initialize_expert_support()
|
|
61
|
-
self.expert_registry: Any | None = None
|
|
62
|
-
# Allow manual override if provided (for testing or special cases)
|
|
63
|
-
if expert_registry:
|
|
64
|
-
self.expert_registry = expert_registry
|
|
65
|
-
|
|
66
|
-
async def activate(self, project_root: Path | None = None, offline_mode: bool = False):
|
|
67
|
-
"""Activate the architect agent with expert support."""
|
|
68
|
-
# Validate that expert_registry attribute exists (safety check)
|
|
69
|
-
if not hasattr(self, 'expert_registry'):
|
|
70
|
-
raise AttributeError(
|
|
71
|
-
f"{self.__class__.__name__}.expert_registry not initialized. "
|
|
72
|
-
"This should not happen if __init__() properly initializes the attribute."
|
|
73
|
-
)
|
|
74
|
-
await super().activate(project_root, offline_mode=offline_mode)
|
|
75
|
-
# Initialize expert support via mixin
|
|
76
|
-
await self._initialize_expert_support(project_root, offline_mode=offline_mode)
|
|
77
|
-
|
|
78
|
-
def get_commands(self) -> list[dict[str, str]]:
|
|
79
|
-
"""Return available commands for architect agent"""
|
|
80
|
-
base_commands = super().get_commands()
|
|
81
|
-
return base_commands + [
|
|
82
|
-
{
|
|
83
|
-
"command": "*design-system",
|
|
84
|
-
"description": "Design system architecture for a feature or project",
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"command": "*create-diagram",
|
|
88
|
-
"description": "Create architecture diagram (text-based)",
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
"command": "*select-technology",
|
|
92
|
-
"description": "Select technology stack for a component",
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"command": "*design-security",
|
|
96
|
-
"description": "Design security architecture",
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"command": "*define-boundaries",
|
|
100
|
-
"description": "Define system boundaries and interfaces",
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
"command": "*evaluate-architecture",
|
|
104
|
-
"description": "Evaluate architecture quality and completeness",
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
"command": "*validate-requirements-alignment",
|
|
108
|
-
"description": "Validate architecture covers all requirements",
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
"command": "*review-architecture",
|
|
112
|
-
"description": "Structured review of architecture with checklist",
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
"command": "*validate-nfr",
|
|
116
|
-
"description": "Validate architecture against non-functional requirements",
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
"command": "*generate-diagram",
|
|
120
|
-
"description": "Generate Mermaid or PlantUML diagram from architecture",
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
"command": "*export-diagram",
|
|
124
|
-
"description": "Export architecture diagram to file (Mermaid/PlantUML)",
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"command": "*suggest-patterns",
|
|
128
|
-
"description": "Suggest design patterns based on requirements",
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"command": "*detect-patterns",
|
|
132
|
-
"description": "Detect architecture patterns from project layout (§3.7)",
|
|
133
|
-
},
|
|
134
|
-
]
|
|
135
|
-
|
|
136
|
-
async def run(self, command: str, **kwargs: Any) -> dict[str, Any]:
|
|
137
|
-
"""
|
|
138
|
-
Execute architect agent command.
|
|
139
|
-
|
|
140
|
-
Commands:
|
|
141
|
-
- *design-system: Design system architecture
|
|
142
|
-
- *create-diagram: Create architecture diagram
|
|
143
|
-
- *select-technology: Select technology stack
|
|
144
|
-
- *design-security: Design security architecture
|
|
145
|
-
- *define-boundaries: Define system boundaries
|
|
146
|
-
- *help: Show help
|
|
147
|
-
"""
|
|
148
|
-
command = command.lstrip("*")
|
|
149
|
-
|
|
150
|
-
if command == "help":
|
|
151
|
-
return {"type": "help", "content": self.format_help()}
|
|
152
|
-
|
|
153
|
-
elif command == "design-system":
|
|
154
|
-
requirements = kwargs.get("requirements", "")
|
|
155
|
-
context = kwargs.get("context", "")
|
|
156
|
-
output_file = kwargs.get("output_file", None)
|
|
157
|
-
generate_doc = kwargs.get("generate_doc", False) or kwargs.get("generate-doc", False)
|
|
158
|
-
generate_code = kwargs.get("generate_code", False) or kwargs.get("generate-code", False)
|
|
159
|
-
code_language = kwargs.get("code_language", "python") or kwargs.get("code-language", "python")
|
|
160
|
-
output_format = kwargs.get("output_format", "markdown") or kwargs.get("output-format", "markdown")
|
|
161
|
-
|
|
162
|
-
result = await self._design_system(requirements, context, output_file)
|
|
163
|
-
|
|
164
|
-
# Generate document if requested
|
|
165
|
-
if generate_doc:
|
|
166
|
-
from ...core.document_generator import DocumentGenerator
|
|
167
|
-
doc_generator = DocumentGenerator(project_root=self._project_root)
|
|
168
|
-
|
|
169
|
-
# Determine output file if not provided
|
|
170
|
-
if not output_file:
|
|
171
|
-
docs_dir = self._project_root / "docs" / "architecture"
|
|
172
|
-
docs_dir.mkdir(parents=True, exist_ok=True)
|
|
173
|
-
safe_name = "architecture_design"
|
|
174
|
-
output_file = docs_dir / f"{safe_name}.{output_format if output_format != 'html' else 'html'}"
|
|
175
|
-
|
|
176
|
-
# Generate document
|
|
177
|
-
doc_path = doc_generator.generate_architecture_doc(
|
|
178
|
-
architecture_data=result,
|
|
179
|
-
output_file=output_file,
|
|
180
|
-
format=output_format,
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
result["document"] = {
|
|
184
|
-
"path": str(doc_path),
|
|
185
|
-
"format": output_format,
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
# Generate code skeletons if requested
|
|
189
|
-
if generate_code and "components" in str(result):
|
|
190
|
-
from ...core.code_generator import CodeGenerator
|
|
191
|
-
code_generator = CodeGenerator(project_root=self._project_root)
|
|
192
|
-
|
|
193
|
-
# Try to extract components from result
|
|
194
|
-
components = result.get("components", [])
|
|
195
|
-
if not components and "instruction" in result:
|
|
196
|
-
# If we have instruction, we can't generate code yet
|
|
197
|
-
# But we can prepare for it
|
|
198
|
-
result["code_generation_ready"] = False
|
|
199
|
-
result["code_generation_note"] = "Code generation requires executed architecture design"
|
|
200
|
-
elif components:
|
|
201
|
-
# Generate service skeletons for each component
|
|
202
|
-
generated_files = []
|
|
203
|
-
code_dir = self._project_root / "src" / "services"
|
|
204
|
-
code_dir.mkdir(parents=True, exist_ok=True)
|
|
205
|
-
|
|
206
|
-
for component in components:
|
|
207
|
-
component_name = component.get("name", "Service") or "Service"
|
|
208
|
-
safe_name = "".join(c if c.isalnum() or c == '_' else '_' for c in component_name)
|
|
209
|
-
code_file = code_dir / f"{safe_name.lower()}.py"
|
|
210
|
-
|
|
211
|
-
try:
|
|
212
|
-
code_path = code_generator.generate_python_class(
|
|
213
|
-
class_data={
|
|
214
|
-
"name": component_name,
|
|
215
|
-
"description": component.get("description", ""),
|
|
216
|
-
"properties": component.get("properties", []),
|
|
217
|
-
},
|
|
218
|
-
output_file=code_file,
|
|
219
|
-
)
|
|
220
|
-
generated_files.append(str(code_path))
|
|
221
|
-
except Exception as e:
|
|
222
|
-
logger.warning(f"Failed to generate code for component {component_name}: {e}")
|
|
223
|
-
|
|
224
|
-
if generated_files:
|
|
225
|
-
result["code"] = {
|
|
226
|
-
"files": generated_files,
|
|
227
|
-
"language": code_language,
|
|
228
|
-
"type": "service_skeletons",
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return result
|
|
232
|
-
|
|
233
|
-
elif command == "create-diagram":
|
|
234
|
-
architecture_description = kwargs.get("architecture_description", "")
|
|
235
|
-
diagram_type = kwargs.get("diagram_type", "component")
|
|
236
|
-
output_file = kwargs.get("output_file", None)
|
|
237
|
-
|
|
238
|
-
return await self._create_diagram(
|
|
239
|
-
architecture_description, diagram_type, output_file
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
elif command == "select-technology":
|
|
243
|
-
component_description = kwargs.get("component_description", "")
|
|
244
|
-
requirements = kwargs.get("requirements", "")
|
|
245
|
-
constraints = kwargs.get("constraints", [])
|
|
246
|
-
|
|
247
|
-
return await self._select_technology(
|
|
248
|
-
component_description, requirements, constraints
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
elif command == "design-security":
|
|
252
|
-
system_description = kwargs.get("system_description", "")
|
|
253
|
-
threat_model = kwargs.get("threat_model", "")
|
|
254
|
-
|
|
255
|
-
return await self._design_security(system_description, threat_model)
|
|
256
|
-
|
|
257
|
-
elif command == "define-boundaries":
|
|
258
|
-
system_description = kwargs.get("system_description", "")
|
|
259
|
-
context = kwargs.get("context", "")
|
|
260
|
-
|
|
261
|
-
return await self._define_boundaries(system_description, context)
|
|
262
|
-
|
|
263
|
-
elif command == "evaluate-architecture":
|
|
264
|
-
architecture = kwargs.get("architecture", {})
|
|
265
|
-
if isinstance(architecture, str):
|
|
266
|
-
arch_path = Path(architecture)
|
|
267
|
-
if arch_path.exists():
|
|
268
|
-
import json
|
|
269
|
-
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
270
|
-
else:
|
|
271
|
-
return {"error": f"Architecture file not found: {architecture}"}
|
|
272
|
-
|
|
273
|
-
return await self._evaluate_architecture(architecture)
|
|
274
|
-
|
|
275
|
-
elif command == "validate-requirements-alignment":
|
|
276
|
-
architecture = kwargs.get("architecture", {})
|
|
277
|
-
requirements = kwargs.get("requirements", {})
|
|
278
|
-
|
|
279
|
-
if isinstance(architecture, str):
|
|
280
|
-
arch_path = Path(architecture)
|
|
281
|
-
if arch_path.exists():
|
|
282
|
-
import json
|
|
283
|
-
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
284
|
-
else:
|
|
285
|
-
return {"error": f"Architecture file not found: {architecture}"}
|
|
286
|
-
|
|
287
|
-
if isinstance(requirements, str):
|
|
288
|
-
req_path = Path(requirements)
|
|
289
|
-
if req_path.exists():
|
|
290
|
-
import json
|
|
291
|
-
requirements = json.loads(req_path.read_text(encoding="utf-8"))
|
|
292
|
-
else:
|
|
293
|
-
return {"error": f"Requirements file not found: {requirements}"}
|
|
294
|
-
|
|
295
|
-
return await self._validate_requirements_alignment(architecture, requirements)
|
|
296
|
-
|
|
297
|
-
elif command == "review-architecture":
|
|
298
|
-
architecture = kwargs.get("architecture", {})
|
|
299
|
-
if isinstance(architecture, str):
|
|
300
|
-
arch_path = Path(architecture)
|
|
301
|
-
if arch_path.exists():
|
|
302
|
-
import json
|
|
303
|
-
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
304
|
-
else:
|
|
305
|
-
return {"error": f"Architecture file not found: {architecture}"}
|
|
306
|
-
|
|
307
|
-
return await self._review_architecture(architecture)
|
|
308
|
-
|
|
309
|
-
elif command == "validate-nfr":
|
|
310
|
-
architecture = kwargs.get("architecture", {})
|
|
311
|
-
nfr_requirements = kwargs.get("nfr_requirements", {})
|
|
312
|
-
|
|
313
|
-
if isinstance(architecture, str):
|
|
314
|
-
arch_path = Path(architecture)
|
|
315
|
-
if arch_path.exists():
|
|
316
|
-
import json
|
|
317
|
-
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
318
|
-
else:
|
|
319
|
-
return {"error": f"Architecture file not found: {architecture}"}
|
|
320
|
-
|
|
321
|
-
if isinstance(nfr_requirements, str):
|
|
322
|
-
nfr_path = Path(nfr_requirements)
|
|
323
|
-
if nfr_path.exists():
|
|
324
|
-
import json
|
|
325
|
-
nfr_requirements = json.loads(nfr_path.read_text(encoding="utf-8"))
|
|
326
|
-
else:
|
|
327
|
-
return {"error": f"NFR requirements file not found: {nfr_requirements}"}
|
|
328
|
-
|
|
329
|
-
return await self._validate_nfr(architecture, nfr_requirements)
|
|
330
|
-
|
|
331
|
-
elif command == "generate-diagram":
|
|
332
|
-
architecture = kwargs.get("architecture", {})
|
|
333
|
-
diagram_type = kwargs.get("diagram_type", "component") # component, sequence, class
|
|
334
|
-
format_type = kwargs.get("format", "mermaid") # mermaid, plantuml
|
|
335
|
-
|
|
336
|
-
if isinstance(architecture, str):
|
|
337
|
-
arch_path = Path(architecture)
|
|
338
|
-
if arch_path.exists():
|
|
339
|
-
import json
|
|
340
|
-
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
341
|
-
else:
|
|
342
|
-
return {"error": f"Architecture file not found: {architecture}"}
|
|
343
|
-
|
|
344
|
-
return await self._generate_diagram(architecture, diagram_type, format_type)
|
|
345
|
-
|
|
346
|
-
elif command == "export-diagram":
|
|
347
|
-
architecture = kwargs.get("architecture", {})
|
|
348
|
-
diagram_type = kwargs.get("diagram_type", "component")
|
|
349
|
-
format_type = kwargs.get("format", "mermaid")
|
|
350
|
-
output_file = kwargs.get("output_file", None)
|
|
351
|
-
|
|
352
|
-
if isinstance(architecture, str):
|
|
353
|
-
arch_path = Path(architecture)
|
|
354
|
-
if arch_path.exists():
|
|
355
|
-
import json
|
|
356
|
-
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
357
|
-
else:
|
|
358
|
-
return {"error": f"Architecture file not found: {architecture}"}
|
|
359
|
-
|
|
360
|
-
if not output_file:
|
|
361
|
-
return {"error": "output_file is required for export-diagram"}
|
|
362
|
-
|
|
363
|
-
return await self._export_diagram(architecture, diagram_type, format_type, output_file)
|
|
364
|
-
|
|
365
|
-
elif command == "suggest-patterns":
|
|
366
|
-
requirements = kwargs.get("requirements", {})
|
|
367
|
-
context = kwargs.get("context", {})
|
|
368
|
-
|
|
369
|
-
if isinstance(requirements, str):
|
|
370
|
-
req_path = Path(requirements)
|
|
371
|
-
if req_path.exists():
|
|
372
|
-
import json
|
|
373
|
-
requirements = json.loads(req_path.read_text(encoding="utf-8"))
|
|
374
|
-
else:
|
|
375
|
-
return {"error": f"Requirements file not found: {requirements}"}
|
|
376
|
-
|
|
377
|
-
return await self._suggest_patterns(requirements, context)
|
|
378
|
-
|
|
379
|
-
elif command == "detect-patterns":
|
|
380
|
-
from .pattern_detector import detect_architecture_patterns
|
|
381
|
-
|
|
382
|
-
root = kwargs.get("path") or getattr(self, "_project_root", None) or Path.cwd()
|
|
383
|
-
root = Path(root).resolve()
|
|
384
|
-
patterns = detect_architecture_patterns(root)
|
|
385
|
-
return {"patterns": patterns, "project_root": str(root)}
|
|
386
|
-
|
|
387
|
-
else:
|
|
388
|
-
return {"error": f"Unknown command: {command}"}
|
|
389
|
-
|
|
390
|
-
async def _consult_experts_for_design(
|
|
391
|
-
self, requirements: str, context: str
|
|
392
|
-
) -> dict[str, Any]:
|
|
393
|
-
"""Consult experts for architecture guidance."""
|
|
394
|
-
expert_guidance: dict[str, Any] = {}
|
|
395
|
-
if not self.expert_registry:
|
|
396
|
-
return expert_guidance
|
|
397
|
-
|
|
398
|
-
# Consult Software Architecture expert
|
|
399
|
-
try:
|
|
400
|
-
arch_consultation = await self.expert_registry.consult(
|
|
401
|
-
query=f"Design system architecture for: {requirements}. Context: {context}",
|
|
402
|
-
domain="software-architecture",
|
|
403
|
-
include_all=True,
|
|
404
|
-
prioritize_builtin=True,
|
|
405
|
-
agent_id="architect",
|
|
406
|
-
)
|
|
407
|
-
expert_guidance["architecture"] = arch_consultation.weighted_answer
|
|
408
|
-
expert_guidance["architecture_confidence"] = arch_consultation.confidence
|
|
409
|
-
except Exception:
|
|
410
|
-
logger.debug("Architecture expert consultation failed", exc_info=True)
|
|
411
|
-
|
|
412
|
-
# Consult Performance expert
|
|
413
|
-
try:
|
|
414
|
-
perf_consultation = await self.expert_registry.consult(
|
|
415
|
-
query=f"Performance considerations for architecture: {requirements}",
|
|
416
|
-
domain="performance-optimization",
|
|
417
|
-
include_all=True,
|
|
418
|
-
prioritize_builtin=True,
|
|
419
|
-
agent_id="architect",
|
|
420
|
-
)
|
|
421
|
-
expert_guidance["performance"] = perf_consultation.weighted_answer
|
|
422
|
-
except Exception:
|
|
423
|
-
logger.debug("Performance expert consultation failed", exc_info=True)
|
|
424
|
-
|
|
425
|
-
# Consult Security expert
|
|
426
|
-
try:
|
|
427
|
-
sec_consultation = await self.expert_registry.consult(
|
|
428
|
-
query=f"Security architecture considerations: {requirements}",
|
|
429
|
-
domain="security",
|
|
430
|
-
include_all=True,
|
|
431
|
-
prioritize_builtin=True,
|
|
432
|
-
agent_id="architect",
|
|
433
|
-
)
|
|
434
|
-
expert_guidance["security"] = sec_consultation.weighted_answer
|
|
435
|
-
except Exception:
|
|
436
|
-
logger.debug("Security expert consultation failed", exc_info=True)
|
|
437
|
-
|
|
438
|
-
return expert_guidance
|
|
439
|
-
|
|
440
|
-
def _format_expert_guidance(self, expert_guidance: dict[str, Any]) -> str:
|
|
441
|
-
"""Format expert guidance into a prompt section."""
|
|
442
|
-
if not expert_guidance:
|
|
443
|
-
return ""
|
|
444
|
-
|
|
445
|
-
expert_section = "\n\nExpert Guidance:\n"
|
|
446
|
-
if "architecture" in expert_guidance:
|
|
447
|
-
expert_section += (
|
|
448
|
-
f"\nArchitecture Expert:\n{expert_guidance['architecture'][:500]}...\n"
|
|
449
|
-
)
|
|
450
|
-
if "performance" in expert_guidance:
|
|
451
|
-
expert_section += (
|
|
452
|
-
f"\nPerformance Expert:\n{expert_guidance['performance'][:300]}...\n"
|
|
453
|
-
)
|
|
454
|
-
if "security" in expert_guidance:
|
|
455
|
-
expert_section += (
|
|
456
|
-
f"\nSecurity Expert:\n{expert_guidance['security'][:300]}...\n"
|
|
457
|
-
)
|
|
458
|
-
return expert_section
|
|
459
|
-
|
|
460
|
-
async def _get_context7_docs_for_design(
|
|
461
|
-
self, requirements: str, context: str
|
|
462
|
-
) -> dict[str, str]:
|
|
463
|
-
"""Get Context7 documentation for mentioned technologies."""
|
|
464
|
-
context7_docs: dict[str, str] = {}
|
|
465
|
-
if not self.context7:
|
|
466
|
-
return context7_docs
|
|
467
|
-
|
|
468
|
-
full_text = f"{requirements} {context}"
|
|
469
|
-
if not self.context7.should_use_context7(full_text):
|
|
470
|
-
return context7_docs
|
|
471
|
-
|
|
472
|
-
# Extract potential library names and get docs
|
|
473
|
-
libraries = await self.context7.search_libraries(requirements, limit=5)
|
|
474
|
-
for lib_info in libraries:
|
|
475
|
-
lib_name = (
|
|
476
|
-
lib_info.get("id", "").split("/")[-1]
|
|
477
|
-
if isinstance(lib_info, dict)
|
|
478
|
-
else str(lib_info)
|
|
479
|
-
)
|
|
480
|
-
if lib_name:
|
|
481
|
-
doc = await self.context7.get_documentation(
|
|
482
|
-
lib_name, topic="architecture"
|
|
483
|
-
)
|
|
484
|
-
if doc:
|
|
485
|
-
context7_docs[lib_name] = doc.get("content", "")[:500]
|
|
486
|
-
|
|
487
|
-
return context7_docs
|
|
488
|
-
|
|
489
|
-
def _format_context7_docs(self, context7_docs: dict[str, str]) -> str:
|
|
490
|
-
"""Format Context7 documentation into a prompt section."""
|
|
491
|
-
if not context7_docs:
|
|
492
|
-
return ""
|
|
493
|
-
|
|
494
|
-
context7_section = "\n\nRelevant Architecture Documentation:\n"
|
|
495
|
-
for lib_name, doc_content in context7_docs.items():
|
|
496
|
-
context7_section += f"\n{lib_name} Architecture:\n{doc_content[:300]}...\n"
|
|
497
|
-
return context7_section
|
|
498
|
-
|
|
499
|
-
def _build_design_prompt(
|
|
500
|
-
self,
|
|
501
|
-
requirements: str,
|
|
502
|
-
context: str,
|
|
503
|
-
expert_section: str,
|
|
504
|
-
context7_section: str,
|
|
505
|
-
) -> str:
|
|
506
|
-
"""Build the architecture design prompt."""
|
|
507
|
-
return f"""Design a system architecture based on the following requirements.
|
|
508
|
-
{expert_section}
|
|
509
|
-
|
|
510
|
-
Requirements:
|
|
511
|
-
{requirements}
|
|
512
|
-
|
|
513
|
-
{f"Context: {context}" if context else ""}
|
|
514
|
-
{context7_section}
|
|
515
|
-
|
|
516
|
-
Provide a comprehensive architecture design including:
|
|
517
|
-
1. System Overview
|
|
518
|
-
2. Architecture Pattern (microservices, monolith, serverless, etc.)
|
|
519
|
-
3. Component Diagram (text-based)
|
|
520
|
-
4. Technology Stack
|
|
521
|
-
5. Data Flow
|
|
522
|
-
6. Integration Points
|
|
523
|
-
7. Scalability Considerations
|
|
524
|
-
8. Security Considerations
|
|
525
|
-
9. Deployment Architecture
|
|
526
|
-
|
|
527
|
-
Format as structured JSON with detailed architecture specification."""
|
|
528
|
-
|
|
529
|
-
def _save_architecture_result(
|
|
530
|
-
self, architecture: dict[str, Any], output_file: str | None
|
|
531
|
-
) -> None:
|
|
532
|
-
"""Save architecture result to file if specified."""
|
|
533
|
-
if not output_file:
|
|
534
|
-
return
|
|
535
|
-
|
|
536
|
-
output_path = Path(output_file)
|
|
537
|
-
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
538
|
-
output_path.write_text(json.dumps(architecture, indent=2))
|
|
539
|
-
architecture["output_file"] = str(output_path)
|
|
540
|
-
|
|
541
|
-
async def _design_system(
|
|
542
|
-
self, requirements: str, context: str = "", output_file: str | None = None
|
|
543
|
-
) -> dict[str, Any]:
|
|
544
|
-
"""Design system architecture."""
|
|
545
|
-
if not requirements:
|
|
546
|
-
return {"error": "requirements is required"}
|
|
547
|
-
|
|
548
|
-
# Consult experts for architecture guidance
|
|
549
|
-
expert_guidance = await self._consult_experts_for_design(requirements, context)
|
|
550
|
-
expert_section = self._format_expert_guidance(expert_guidance)
|
|
551
|
-
|
|
552
|
-
# Get Context7 documentation
|
|
553
|
-
context7_docs = await self._get_context7_docs_for_design(requirements, context)
|
|
554
|
-
context7_section = self._format_context7_docs(context7_docs)
|
|
555
|
-
|
|
556
|
-
# Build prompt
|
|
557
|
-
prompt = self._build_design_prompt(
|
|
558
|
-
requirements, context, expert_section, context7_section
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
# Prepare instruction for Cursor Skills
|
|
562
|
-
instruction = GenericInstruction(
|
|
563
|
-
agent_name="architect",
|
|
564
|
-
command="design-system",
|
|
565
|
-
prompt=prompt,
|
|
566
|
-
parameters={
|
|
567
|
-
"requirements": requirements,
|
|
568
|
-
"output_file": str(output_file) if output_file else None,
|
|
569
|
-
},
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
result = {
|
|
573
|
-
"success": True,
|
|
574
|
-
"instruction": instruction.to_dict(),
|
|
575
|
-
"skill_command": instruction.to_skill_command(),
|
|
576
|
-
}
|
|
577
|
-
if expert_guidance:
|
|
578
|
-
result["expert_guidance"] = expert_guidance
|
|
579
|
-
return result
|
|
580
|
-
|
|
581
|
-
async def _create_diagram(
|
|
582
|
-
self,
|
|
583
|
-
architecture_description: str,
|
|
584
|
-
diagram_type: str = "component",
|
|
585
|
-
output_file: str | None = None,
|
|
586
|
-
) -> dict[str, Any]:
|
|
587
|
-
"""Create architecture diagram (text-based)."""
|
|
588
|
-
if not architecture_description:
|
|
589
|
-
return {"error": "architecture_description is required"}
|
|
590
|
-
|
|
591
|
-
diagram_types = {
|
|
592
|
-
"component": "component diagram showing system components and relationships",
|
|
593
|
-
"sequence": "sequence diagram showing interactions over time",
|
|
594
|
-
"deployment": "deployment diagram showing deployment architecture",
|
|
595
|
-
"class": "class diagram showing object relationships",
|
|
596
|
-
"data-flow": "data flow diagram showing data movement",
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
diagram_description = diagram_types.get(diagram_type, "architecture diagram")
|
|
600
|
-
|
|
601
|
-
prompt = f"""Create a text-based {diagram_description} for the following architecture.
|
|
602
|
-
|
|
603
|
-
Architecture Description:
|
|
604
|
-
{architecture_description}
|
|
605
|
-
|
|
606
|
-
Provide a clear, ASCII/text-based diagram that can be rendered in markdown or plain text.
|
|
607
|
-
Use standard diagram notation (boxes, arrows, labels) for clarity.
|
|
608
|
-
|
|
609
|
-
Format:
|
|
610
|
-
1. Diagram (ASCII/text format)
|
|
611
|
-
2. Legend/Explanation
|
|
612
|
-
3. Key Relationships
|
|
613
|
-
"""
|
|
614
|
-
|
|
615
|
-
# Prepare instruction for Cursor Skills
|
|
616
|
-
instruction = GenericInstruction(
|
|
617
|
-
agent_name="architect",
|
|
618
|
-
command="create-diagram",
|
|
619
|
-
prompt=prompt,
|
|
620
|
-
parameters={
|
|
621
|
-
"diagram_type": diagram_type,
|
|
622
|
-
"architecture": architecture_description,
|
|
623
|
-
"output_file": str(output_file) if output_file else None,
|
|
624
|
-
},
|
|
625
|
-
)
|
|
626
|
-
|
|
627
|
-
return {
|
|
628
|
-
"success": True,
|
|
629
|
-
"instruction": instruction.to_dict(),
|
|
630
|
-
"skill_command": instruction.to_skill_command(),
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
async def _select_technology(
|
|
634
|
-
self,
|
|
635
|
-
component_description: str,
|
|
636
|
-
requirements: str = "",
|
|
637
|
-
constraints: list[str] | None = None,
|
|
638
|
-
) -> dict[str, Any]:
|
|
639
|
-
"""Select technology stack for a component."""
|
|
640
|
-
if constraints is None:
|
|
641
|
-
constraints = []
|
|
642
|
-
|
|
643
|
-
# Consult Software Architecture expert for technology selection
|
|
644
|
-
tech_guidance = ""
|
|
645
|
-
# Use defensive check to ensure attribute exists (safety for MRO issue)
|
|
646
|
-
if hasattr(self, 'expert_registry') and self.expert_registry:
|
|
647
|
-
try:
|
|
648
|
-
tech_consultation = await self.expert_registry.consult(
|
|
649
|
-
query=f"Select technology stack for: {component_description}. Requirements: {requirements}. Constraints: {', '.join(constraints) if constraints else 'None'}",
|
|
650
|
-
domain="software-architecture",
|
|
651
|
-
include_all=True,
|
|
652
|
-
prioritize_builtin=True,
|
|
653
|
-
agent_id="architect",
|
|
654
|
-
)
|
|
655
|
-
tech_guidance = tech_consultation.weighted_answer
|
|
656
|
-
except Exception:
|
|
657
|
-
logger.debug("Technology selection consultation failed", exc_info=True)
|
|
658
|
-
|
|
659
|
-
# Use Context7 to get documentation for mentioned technologies
|
|
660
|
-
context7_docs = {}
|
|
661
|
-
if self.context7:
|
|
662
|
-
full_text = (
|
|
663
|
-
f"{component_description} {requirements} {' '.join(constraints)}"
|
|
664
|
-
)
|
|
665
|
-
if self.context7.should_use_context7(full_text):
|
|
666
|
-
# Search for library mentions and get docs
|
|
667
|
-
libraries = await self.context7.search_libraries(
|
|
668
|
-
component_description, limit=3
|
|
669
|
-
)
|
|
670
|
-
for lib_info in libraries:
|
|
671
|
-
lib_name = (
|
|
672
|
-
lib_info.get("id", "").split("/")[-1]
|
|
673
|
-
if isinstance(lib_info, dict)
|
|
674
|
-
else str(lib_info)
|
|
675
|
-
)
|
|
676
|
-
if lib_name:
|
|
677
|
-
doc = await self.context7.get_documentation(
|
|
678
|
-
lib_name, topic="overview"
|
|
679
|
-
)
|
|
680
|
-
if doc:
|
|
681
|
-
context7_docs[lib_name] = doc.get("content", "")[
|
|
682
|
-
:500
|
|
683
|
-
] # First 500 chars
|
|
684
|
-
|
|
685
|
-
context7_section = ""
|
|
686
|
-
if context7_docs:
|
|
687
|
-
context7_section = "\n\nRelevant Technology Documentation from Context7:\n"
|
|
688
|
-
for lib_name, doc_content in context7_docs.items():
|
|
689
|
-
context7_section += f"\n{lib_name}:\n{doc_content[:300]}...\n"
|
|
690
|
-
|
|
691
|
-
tech_guidance_section = (
|
|
692
|
-
f"Architecture Expert Guidance:\n{tech_guidance}" if tech_guidance else ""
|
|
693
|
-
)
|
|
694
|
-
|
|
695
|
-
prompt = f"""Select an appropriate technology stack for the following component.
|
|
696
|
-
|
|
697
|
-
Component Description:
|
|
698
|
-
{component_description}
|
|
699
|
-
|
|
700
|
-
{f"Requirements: {requirements}" if requirements else ""}
|
|
701
|
-
|
|
702
|
-
{f"Constraints: {', '.join(constraints)}" if constraints else ""}
|
|
703
|
-
|
|
704
|
-
{tech_guidance_section}
|
|
705
|
-
{context7_section}
|
|
706
|
-
|
|
707
|
-
For each technology recommendation, provide:
|
|
708
|
-
1. Technology Name
|
|
709
|
-
2. Rationale
|
|
710
|
-
3. Pros and Cons
|
|
711
|
-
4. Fit for Requirements
|
|
712
|
-
5. Learning Curve
|
|
713
|
-
6. Community Support
|
|
714
|
-
7. Alternative Options
|
|
715
|
-
|
|
716
|
-
Format as structured JSON with technology recommendations."""
|
|
717
|
-
|
|
718
|
-
try:
|
|
719
|
-
# Prepare instruction for Cursor Skills
|
|
720
|
-
instruction = GenericInstruction(
|
|
721
|
-
agent_name="architect",
|
|
722
|
-
command="select-technology",
|
|
723
|
-
prompt=prompt,
|
|
724
|
-
parameters={
|
|
725
|
-
"component": component_description,
|
|
726
|
-
"requirements": requirements,
|
|
727
|
-
"constraints": constraints,
|
|
728
|
-
},
|
|
729
|
-
)
|
|
730
|
-
|
|
731
|
-
return {
|
|
732
|
-
"success": True,
|
|
733
|
-
"instruction": instruction.to_dict(),
|
|
734
|
-
"skill_command": instruction.to_skill_command(),
|
|
735
|
-
}
|
|
736
|
-
except Exception as e:
|
|
737
|
-
return {"error": f"Failed to select technology: {str(e)}"}
|
|
738
|
-
|
|
739
|
-
async def _design_security(
|
|
740
|
-
self, system_description: str, threat_model: str = ""
|
|
741
|
-
) -> dict[str, Any]:
|
|
742
|
-
"""Design security architecture."""
|
|
743
|
-
if not system_description:
|
|
744
|
-
return {"error": "system_description is required"}
|
|
745
|
-
|
|
746
|
-
# Consult Security expert
|
|
747
|
-
security_guidance = ""
|
|
748
|
-
security_confidence = 0.0
|
|
749
|
-
# Use defensive check to ensure attribute exists (safety for MRO issue)
|
|
750
|
-
if hasattr(self, 'expert_registry') and self.expert_registry:
|
|
751
|
-
try:
|
|
752
|
-
security_consultation = await self.expert_registry.consult(
|
|
753
|
-
query=f"Design security architecture for: {system_description}. Threat model: {threat_model}",
|
|
754
|
-
domain="security",
|
|
755
|
-
include_all=True,
|
|
756
|
-
prioritize_builtin=True,
|
|
757
|
-
agent_id="architect",
|
|
758
|
-
)
|
|
759
|
-
security_guidance = security_consultation.weighted_answer
|
|
760
|
-
security_confidence = security_consultation.confidence
|
|
761
|
-
except Exception:
|
|
762
|
-
logger.debug("Security architecture consultation failed", exc_info=True)
|
|
763
|
-
|
|
764
|
-
security_guidance_section = (
|
|
765
|
-
f"Security Expert Guidance:\n{security_guidance}"
|
|
766
|
-
if security_guidance
|
|
767
|
-
else ""
|
|
768
|
-
)
|
|
769
|
-
|
|
770
|
-
prompt = f"""Design a security architecture for the following system.
|
|
771
|
-
|
|
772
|
-
System Description:
|
|
773
|
-
{system_description}
|
|
774
|
-
|
|
775
|
-
{f"Threat Model: {threat_model}" if threat_model else ""}
|
|
776
|
-
|
|
777
|
-
{security_guidance_section}
|
|
778
|
-
|
|
779
|
-
Provide a comprehensive security design including:
|
|
780
|
-
1. Security Principles
|
|
781
|
-
2. Authentication & Authorization Strategy
|
|
782
|
-
3. Data Protection (encryption, at-rest, in-transit)
|
|
783
|
-
4. Network Security
|
|
784
|
-
5. API Security
|
|
785
|
-
6. Threat Mitigation Strategies
|
|
786
|
-
7. Security Monitoring & Logging
|
|
787
|
-
8. Compliance Considerations
|
|
788
|
-
9. Security Best Practices
|
|
789
|
-
|
|
790
|
-
Format as structured JSON with detailed security architecture."""
|
|
791
|
-
|
|
792
|
-
try:
|
|
793
|
-
# Prepare instruction for Cursor Skills
|
|
794
|
-
instruction = GenericInstruction(
|
|
795
|
-
agent_name="architect",
|
|
796
|
-
command="design-security",
|
|
797
|
-
prompt=prompt,
|
|
798
|
-
parameters={
|
|
799
|
-
"system": system_description,
|
|
800
|
-
"threat_model": threat_model,
|
|
801
|
-
},
|
|
802
|
-
)
|
|
803
|
-
|
|
804
|
-
result = {
|
|
805
|
-
"success": True,
|
|
806
|
-
"instruction": instruction.to_dict(),
|
|
807
|
-
"skill_command": instruction.to_skill_command(),
|
|
808
|
-
}
|
|
809
|
-
if security_guidance:
|
|
810
|
-
result["expert_guidance"] = {
|
|
811
|
-
"security": security_guidance,
|
|
812
|
-
"confidence": security_confidence,
|
|
813
|
-
}
|
|
814
|
-
return result
|
|
815
|
-
except Exception as e:
|
|
816
|
-
return {"error": f"Failed to design security: {str(e)}"}
|
|
817
|
-
|
|
818
|
-
async def _define_boundaries(
|
|
819
|
-
self, system_description: str, context: str = ""
|
|
820
|
-
) -> dict[str, Any]:
|
|
821
|
-
"""Define system boundaries and interfaces."""
|
|
822
|
-
if not system_description:
|
|
823
|
-
return {"error": "system_description is required"}
|
|
824
|
-
|
|
825
|
-
prompt = f"""Define system boundaries and interfaces for the following system.
|
|
826
|
-
|
|
827
|
-
System Description:
|
|
828
|
-
{system_description}
|
|
829
|
-
|
|
830
|
-
{f"Context: {context}" if context else ""}
|
|
831
|
-
|
|
832
|
-
Provide:
|
|
833
|
-
1. System Boundaries (what's inside vs outside)
|
|
834
|
-
2. External Dependencies
|
|
835
|
-
3. API Interfaces (REST, GraphQL, gRPC, etc.)
|
|
836
|
-
4. Data Interfaces (data formats, schemas)
|
|
837
|
-
5. Integration Points
|
|
838
|
-
6. Interface Contracts
|
|
839
|
-
7. Service Contracts
|
|
840
|
-
8. Communication Protocols
|
|
841
|
-
|
|
842
|
-
Format as structured JSON with boundary and interface definitions."""
|
|
843
|
-
|
|
844
|
-
try:
|
|
845
|
-
# Prepare instruction for Cursor Skills
|
|
846
|
-
instruction = GenericInstruction(
|
|
847
|
-
agent_name="architect",
|
|
848
|
-
command="define-boundaries",
|
|
849
|
-
prompt=prompt,
|
|
850
|
-
parameters={
|
|
851
|
-
"system": system_description,
|
|
852
|
-
"context": context,
|
|
853
|
-
},
|
|
854
|
-
)
|
|
855
|
-
|
|
856
|
-
return {
|
|
857
|
-
"success": True,
|
|
858
|
-
"instruction": instruction.to_dict(),
|
|
859
|
-
"skill_command": instruction.to_skill_command(),
|
|
860
|
-
}
|
|
861
|
-
except Exception as e:
|
|
862
|
-
return {"error": f"Failed to define boundaries: {str(e)}"}
|
|
863
|
-
|
|
864
|
-
async def _evaluate_architecture(self, architecture: dict[str, Any]) -> dict[str, Any]:
|
|
865
|
-
"""Evaluate architecture quality and completeness."""
|
|
866
|
-
# Basic evaluation - can be enhanced with more sophisticated analysis
|
|
867
|
-
score = {
|
|
868
|
-
"overall": 75.0, # Placeholder - would use actual evaluation logic
|
|
869
|
-
"components_defined": len(architecture.get("components", [])) > 0,
|
|
870
|
-
"patterns_identified": len(architecture.get("patterns", [])) > 0,
|
|
871
|
-
"security_addressed": "security" in str(architecture).lower(),
|
|
872
|
-
"scalability_addressed": "scal" in str(architecture).lower() or "scale" in str(architecture).lower(),
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
return {
|
|
876
|
-
"success": True,
|
|
877
|
-
"score": score,
|
|
878
|
-
"architecture": architecture,
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
async def _validate_requirements_alignment(
|
|
882
|
-
self, architecture: dict[str, Any], requirements: dict[str, Any]
|
|
883
|
-
) -> dict[str, Any]:
|
|
884
|
-
"""Validate architecture covers all requirements."""
|
|
885
|
-
from ...core.design_validator import DesignValidator
|
|
886
|
-
|
|
887
|
-
validator = DesignValidator()
|
|
888
|
-
result = validator.validate_requirements_alignment(architecture, requirements)
|
|
889
|
-
|
|
890
|
-
return {
|
|
891
|
-
"success": True,
|
|
892
|
-
"is_valid": result.is_valid,
|
|
893
|
-
"requirements_coverage": result.requirements_coverage,
|
|
894
|
-
"missing_requirements": result.missing_requirements,
|
|
895
|
-
"pattern_violations": result.pattern_violations,
|
|
896
|
-
"security_issues": result.security_issues,
|
|
897
|
-
"scalability_concerns": result.scalability_concerns,
|
|
898
|
-
"recommendations": result.recommendations,
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
async def _review_architecture(self, architecture: dict[str, Any]) -> dict[str, Any]:
|
|
902
|
-
"""Structured review of architecture with checklist."""
|
|
903
|
-
from ...core.review_checklists import ArchitectureReviewChecklist
|
|
904
|
-
|
|
905
|
-
checklist = ArchitectureReviewChecklist()
|
|
906
|
-
result = checklist.review(architecture)
|
|
907
|
-
|
|
908
|
-
return {
|
|
909
|
-
"success": True,
|
|
910
|
-
"overall_score": result.overall_score,
|
|
911
|
-
"items_checked": result.items_checked,
|
|
912
|
-
"items_total": result.items_total,
|
|
913
|
-
"critical_issues": result.critical_issues,
|
|
914
|
-
"high_issues": result.high_issues,
|
|
915
|
-
"medium_issues": result.medium_issues,
|
|
916
|
-
"low_issues": result.low_issues,
|
|
917
|
-
"recommendations": result.recommendations,
|
|
918
|
-
"checklist_items": [
|
|
919
|
-
{
|
|
920
|
-
"category": item.category,
|
|
921
|
-
"item": item.item,
|
|
922
|
-
"checked": item.checked,
|
|
923
|
-
"severity": item.severity,
|
|
924
|
-
"notes": item.notes,
|
|
925
|
-
}
|
|
926
|
-
for item in result.checklist_items
|
|
927
|
-
],
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
async def _validate_nfr(
|
|
931
|
-
self, architecture: dict[str, Any], nfr_requirements: dict[str, Any]
|
|
932
|
-
) -> dict[str, Any]:
|
|
933
|
-
"""Validate architecture against non-functional requirements."""
|
|
934
|
-
from ...core.nfr_validator import NFRValidator
|
|
935
|
-
|
|
936
|
-
validator = NFRValidator()
|
|
937
|
-
result = validator.validate_architecture_nfr(architecture, nfr_requirements)
|
|
938
|
-
|
|
939
|
-
return {
|
|
940
|
-
"success": True,
|
|
941
|
-
"is_valid": result.is_valid,
|
|
942
|
-
"overall_score": result.overall_score,
|
|
943
|
-
"security_score": result.security_score,
|
|
944
|
-
"performance_score": result.performance_score,
|
|
945
|
-
"reliability_score": result.reliability_score,
|
|
946
|
-
"maintainability_score": result.maintainability_score,
|
|
947
|
-
"security_issues": result.security_issues,
|
|
948
|
-
"performance_issues": result.performance_issues,
|
|
949
|
-
"reliability_issues": result.reliability_issues,
|
|
950
|
-
"maintainability_issues": result.maintainability_issues,
|
|
951
|
-
"recommendations": result.recommendations,
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
async def _generate_diagram(
|
|
955
|
-
self, architecture: dict[str, Any], diagram_type: str, format_type: str
|
|
956
|
-
) -> dict[str, Any]:
|
|
957
|
-
"""Generate Mermaid or PlantUML diagram from architecture."""
|
|
958
|
-
from ...core.diagram_generator import DiagramGenerator
|
|
959
|
-
|
|
960
|
-
generator = DiagramGenerator()
|
|
961
|
-
|
|
962
|
-
if format_type == "mermaid":
|
|
963
|
-
if diagram_type == "component":
|
|
964
|
-
diagram_code = generator.generate_mermaid_component_diagram(architecture)
|
|
965
|
-
elif diagram_type == "sequence":
|
|
966
|
-
interactions = architecture.get("interactions", [])
|
|
967
|
-
diagram_code = generator.generate_mermaid_sequence_diagram(interactions)
|
|
968
|
-
elif diagram_type == "class":
|
|
969
|
-
classes = architecture.get("classes", [])
|
|
970
|
-
diagram_code = generator.generate_mermaid_class_diagram(classes)
|
|
971
|
-
else:
|
|
972
|
-
return {"error": f"Unsupported diagram type: {diagram_type}. Use: component, sequence, class"}
|
|
973
|
-
|
|
974
|
-
elif format_type == "plantuml":
|
|
975
|
-
if diagram_type == "component":
|
|
976
|
-
diagram_code = generator.generate_plantuml_component_diagram(architecture)
|
|
977
|
-
else:
|
|
978
|
-
return {"error": f"PlantUML only supports component diagrams currently"}
|
|
979
|
-
|
|
980
|
-
else:
|
|
981
|
-
return {"error": f"Unsupported format: {format_type}. Use: mermaid, plantuml"}
|
|
982
|
-
|
|
983
|
-
return {
|
|
984
|
-
"success": True,
|
|
985
|
-
"diagram_code": diagram_code,
|
|
986
|
-
"format": format_type,
|
|
987
|
-
"diagram_type": diagram_type,
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
async def _export_diagram(
|
|
991
|
-
self, architecture: dict[str, Any], diagram_type: str, format_type: str, output_file: str
|
|
992
|
-
) -> dict[str, Any]:
|
|
993
|
-
"""Export architecture diagram to file."""
|
|
994
|
-
from ...core.diagram_generator import DiagramGenerator
|
|
995
|
-
|
|
996
|
-
generator = DiagramGenerator()
|
|
997
|
-
|
|
998
|
-
# Generate diagram
|
|
999
|
-
result = await self._generate_diagram(architecture, diagram_type, format_type)
|
|
1000
|
-
if "error" in result:
|
|
1001
|
-
return result
|
|
1002
|
-
|
|
1003
|
-
diagram_code = result["diagram_code"]
|
|
1004
|
-
|
|
1005
|
-
# Export to file
|
|
1006
|
-
output_path = Path(output_file)
|
|
1007
|
-
generator.export_to_file(diagram_code, output_path, format_type)
|
|
1008
|
-
|
|
1009
|
-
return {
|
|
1010
|
-
"success": True,
|
|
1011
|
-
"output_file": str(output_path),
|
|
1012
|
-
"format": format_type,
|
|
1013
|
-
"diagram_type": diagram_type,
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
async def _suggest_patterns(self, requirements: dict[str, Any], context: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
1017
|
-
"""Suggest design patterns based on requirements."""
|
|
1018
|
-
from ...core.pattern_library import DesignPatternLibrary
|
|
1019
|
-
|
|
1020
|
-
library = DesignPatternLibrary()
|
|
1021
|
-
suggestions = library.suggest_patterns(requirements, context)
|
|
1022
|
-
|
|
1023
|
-
return {
|
|
1024
|
-
"success": True,
|
|
1025
|
-
"suggestions": suggestions,
|
|
1026
|
-
"total_patterns_available": len(library.patterns),
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
async def close(self) -> None:
|
|
1030
|
-
"""Cleanup resources."""
|
|
1031
|
-
await super().close()
|
|
1032
|
-
# Context7 helper cleanup if needed
|
|
1033
|
-
# (Context7AgentHelper doesn't currently require explicit cleanup)
|
|
1
|
+
"""
|
|
2
|
+
Architect Agent - System and security architecture design.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from ...context7.agent_integration import Context7AgentHelper, get_context7_helper
|
|
11
|
+
from ...core.agent_base import BaseAgent
|
|
12
|
+
from ...core.config import ProjectConfig, load_config
|
|
13
|
+
from ...core.instructions import GenericInstruction
|
|
14
|
+
from ...experts.agent_integration import ExpertSupportMixin
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ArchitectAgent(BaseAgent, ExpertSupportMixin):
|
|
20
|
+
"""
|
|
21
|
+
Architect Agent - System and security architecture design.
|
|
22
|
+
|
|
23
|
+
Permissions: Read, Write, Grep, Glob (no Edit, no Bash)
|
|
24
|
+
|
|
25
|
+
⚠️ CRITICAL ACCURACY REQUIREMENT:
|
|
26
|
+
- NEVER make up, invent, or fabricate information - Only report verified facts
|
|
27
|
+
- ALWAYS verify claims by checking actual results, not just test pass/fail
|
|
28
|
+
- Verify API calls succeed - inspect response data, status codes, error messages
|
|
29
|
+
- Distinguish between code paths executing and actual functionality working
|
|
30
|
+
- Admit uncertainty explicitly when you cannot verify
|
|
31
|
+
|
|
32
|
+
Responsibilities:
|
|
33
|
+
- Design system architecture
|
|
34
|
+
- Create architecture diagrams (text-based)
|
|
35
|
+
- Select technologies
|
|
36
|
+
- Design security architecture
|
|
37
|
+
- Define system boundaries
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
config: ProjectConfig | None = None,
|
|
43
|
+
expert_registry: Any | None = None,
|
|
44
|
+
):
|
|
45
|
+
super().__init__(
|
|
46
|
+
agent_id="architect", agent_name="Architect Agent", config=config
|
|
47
|
+
)
|
|
48
|
+
if config is None:
|
|
49
|
+
config = load_config()
|
|
50
|
+
self.config = config
|
|
51
|
+
|
|
52
|
+
# Initialize Context7 helper
|
|
53
|
+
self.context7: Context7AgentHelper | None = None
|
|
54
|
+
if config:
|
|
55
|
+
self.context7 = get_context7_helper(self, config)
|
|
56
|
+
|
|
57
|
+
# Expert registry initialization (required due to multiple inheritance MRO issue)
|
|
58
|
+
# BaseAgent.__init__() doesn't call super().__init__(), so ExpertSupportMixin.__init__()
|
|
59
|
+
# is never called via MRO. We must manually initialize to avoid AttributeError.
|
|
60
|
+
# The registry will be properly initialized in activate() via _initialize_expert_support()
|
|
61
|
+
self.expert_registry: Any | None = None
|
|
62
|
+
# Allow manual override if provided (for testing or special cases)
|
|
63
|
+
if expert_registry:
|
|
64
|
+
self.expert_registry = expert_registry
|
|
65
|
+
|
|
66
|
+
async def activate(self, project_root: Path | None = None, offline_mode: bool = False):
|
|
67
|
+
"""Activate the architect agent with expert support."""
|
|
68
|
+
# Validate that expert_registry attribute exists (safety check)
|
|
69
|
+
if not hasattr(self, 'expert_registry'):
|
|
70
|
+
raise AttributeError(
|
|
71
|
+
f"{self.__class__.__name__}.expert_registry not initialized. "
|
|
72
|
+
"This should not happen if __init__() properly initializes the attribute."
|
|
73
|
+
)
|
|
74
|
+
await super().activate(project_root, offline_mode=offline_mode)
|
|
75
|
+
# Initialize expert support via mixin
|
|
76
|
+
await self._initialize_expert_support(project_root, offline_mode=offline_mode)
|
|
77
|
+
|
|
78
|
+
def get_commands(self) -> list[dict[str, str]]:
|
|
79
|
+
"""Return available commands for architect agent"""
|
|
80
|
+
base_commands = super().get_commands()
|
|
81
|
+
return base_commands + [
|
|
82
|
+
{
|
|
83
|
+
"command": "*design-system",
|
|
84
|
+
"description": "Design system architecture for a feature or project",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"command": "*create-diagram",
|
|
88
|
+
"description": "Create architecture diagram (text-based)",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"command": "*select-technology",
|
|
92
|
+
"description": "Select technology stack for a component",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"command": "*design-security",
|
|
96
|
+
"description": "Design security architecture",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"command": "*define-boundaries",
|
|
100
|
+
"description": "Define system boundaries and interfaces",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"command": "*evaluate-architecture",
|
|
104
|
+
"description": "Evaluate architecture quality and completeness",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"command": "*validate-requirements-alignment",
|
|
108
|
+
"description": "Validate architecture covers all requirements",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"command": "*review-architecture",
|
|
112
|
+
"description": "Structured review of architecture with checklist",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"command": "*validate-nfr",
|
|
116
|
+
"description": "Validate architecture against non-functional requirements",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"command": "*generate-diagram",
|
|
120
|
+
"description": "Generate Mermaid or PlantUML diagram from architecture",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"command": "*export-diagram",
|
|
124
|
+
"description": "Export architecture diagram to file (Mermaid/PlantUML)",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"command": "*suggest-patterns",
|
|
128
|
+
"description": "Suggest design patterns based on requirements",
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"command": "*detect-patterns",
|
|
132
|
+
"description": "Detect architecture patterns from project layout (§3.7)",
|
|
133
|
+
},
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
async def run(self, command: str, **kwargs: Any) -> dict[str, Any]:
|
|
137
|
+
"""
|
|
138
|
+
Execute architect agent command.
|
|
139
|
+
|
|
140
|
+
Commands:
|
|
141
|
+
- *design-system: Design system architecture
|
|
142
|
+
- *create-diagram: Create architecture diagram
|
|
143
|
+
- *select-technology: Select technology stack
|
|
144
|
+
- *design-security: Design security architecture
|
|
145
|
+
- *define-boundaries: Define system boundaries
|
|
146
|
+
- *help: Show help
|
|
147
|
+
"""
|
|
148
|
+
command = command.lstrip("*")
|
|
149
|
+
|
|
150
|
+
if command == "help":
|
|
151
|
+
return {"type": "help", "content": self.format_help()}
|
|
152
|
+
|
|
153
|
+
elif command == "design-system":
|
|
154
|
+
requirements = kwargs.get("requirements", "")
|
|
155
|
+
context = kwargs.get("context", "")
|
|
156
|
+
output_file = kwargs.get("output_file", None)
|
|
157
|
+
generate_doc = kwargs.get("generate_doc", False) or kwargs.get("generate-doc", False)
|
|
158
|
+
generate_code = kwargs.get("generate_code", False) or kwargs.get("generate-code", False)
|
|
159
|
+
code_language = kwargs.get("code_language", "python") or kwargs.get("code-language", "python")
|
|
160
|
+
output_format = kwargs.get("output_format", "markdown") or kwargs.get("output-format", "markdown")
|
|
161
|
+
|
|
162
|
+
result = await self._design_system(requirements, context, output_file)
|
|
163
|
+
|
|
164
|
+
# Generate document if requested
|
|
165
|
+
if generate_doc:
|
|
166
|
+
from ...core.document_generator import DocumentGenerator
|
|
167
|
+
doc_generator = DocumentGenerator(project_root=self._project_root)
|
|
168
|
+
|
|
169
|
+
# Determine output file if not provided
|
|
170
|
+
if not output_file:
|
|
171
|
+
docs_dir = self._project_root / "docs" / "architecture"
|
|
172
|
+
docs_dir.mkdir(parents=True, exist_ok=True)
|
|
173
|
+
safe_name = "architecture_design"
|
|
174
|
+
output_file = docs_dir / f"{safe_name}.{output_format if output_format != 'html' else 'html'}"
|
|
175
|
+
|
|
176
|
+
# Generate document
|
|
177
|
+
doc_path = doc_generator.generate_architecture_doc(
|
|
178
|
+
architecture_data=result,
|
|
179
|
+
output_file=output_file,
|
|
180
|
+
format=output_format,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
result["document"] = {
|
|
184
|
+
"path": str(doc_path),
|
|
185
|
+
"format": output_format,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
# Generate code skeletons if requested
|
|
189
|
+
if generate_code and "components" in str(result):
|
|
190
|
+
from ...core.code_generator import CodeGenerator
|
|
191
|
+
code_generator = CodeGenerator(project_root=self._project_root)
|
|
192
|
+
|
|
193
|
+
# Try to extract components from result
|
|
194
|
+
components = result.get("components", [])
|
|
195
|
+
if not components and "instruction" in result:
|
|
196
|
+
# If we have instruction, we can't generate code yet
|
|
197
|
+
# But we can prepare for it
|
|
198
|
+
result["code_generation_ready"] = False
|
|
199
|
+
result["code_generation_note"] = "Code generation requires executed architecture design"
|
|
200
|
+
elif components:
|
|
201
|
+
# Generate service skeletons for each component
|
|
202
|
+
generated_files = []
|
|
203
|
+
code_dir = self._project_root / "src" / "services"
|
|
204
|
+
code_dir.mkdir(parents=True, exist_ok=True)
|
|
205
|
+
|
|
206
|
+
for component in components:
|
|
207
|
+
component_name = component.get("name", "Service") or "Service"
|
|
208
|
+
safe_name = "".join(c if c.isalnum() or c == '_' else '_' for c in component_name)
|
|
209
|
+
code_file = code_dir / f"{safe_name.lower()}.py"
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
code_path = code_generator.generate_python_class(
|
|
213
|
+
class_data={
|
|
214
|
+
"name": component_name,
|
|
215
|
+
"description": component.get("description", ""),
|
|
216
|
+
"properties": component.get("properties", []),
|
|
217
|
+
},
|
|
218
|
+
output_file=code_file,
|
|
219
|
+
)
|
|
220
|
+
generated_files.append(str(code_path))
|
|
221
|
+
except Exception as e:
|
|
222
|
+
logger.warning(f"Failed to generate code for component {component_name}: {e}")
|
|
223
|
+
|
|
224
|
+
if generated_files:
|
|
225
|
+
result["code"] = {
|
|
226
|
+
"files": generated_files,
|
|
227
|
+
"language": code_language,
|
|
228
|
+
"type": "service_skeletons",
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return result
|
|
232
|
+
|
|
233
|
+
elif command == "create-diagram":
|
|
234
|
+
architecture_description = kwargs.get("architecture_description", "")
|
|
235
|
+
diagram_type = kwargs.get("diagram_type", "component")
|
|
236
|
+
output_file = kwargs.get("output_file", None)
|
|
237
|
+
|
|
238
|
+
return await self._create_diagram(
|
|
239
|
+
architecture_description, diagram_type, output_file
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
elif command == "select-technology":
|
|
243
|
+
component_description = kwargs.get("component_description", "")
|
|
244
|
+
requirements = kwargs.get("requirements", "")
|
|
245
|
+
constraints = kwargs.get("constraints", [])
|
|
246
|
+
|
|
247
|
+
return await self._select_technology(
|
|
248
|
+
component_description, requirements, constraints
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
elif command == "design-security":
|
|
252
|
+
system_description = kwargs.get("system_description", "")
|
|
253
|
+
threat_model = kwargs.get("threat_model", "")
|
|
254
|
+
|
|
255
|
+
return await self._design_security(system_description, threat_model)
|
|
256
|
+
|
|
257
|
+
elif command == "define-boundaries":
|
|
258
|
+
system_description = kwargs.get("system_description", "")
|
|
259
|
+
context = kwargs.get("context", "")
|
|
260
|
+
|
|
261
|
+
return await self._define_boundaries(system_description, context)
|
|
262
|
+
|
|
263
|
+
elif command == "evaluate-architecture":
|
|
264
|
+
architecture = kwargs.get("architecture", {})
|
|
265
|
+
if isinstance(architecture, str):
|
|
266
|
+
arch_path = Path(architecture)
|
|
267
|
+
if arch_path.exists():
|
|
268
|
+
import json
|
|
269
|
+
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
270
|
+
else:
|
|
271
|
+
return {"error": f"Architecture file not found: {architecture}"}
|
|
272
|
+
|
|
273
|
+
return await self._evaluate_architecture(architecture)
|
|
274
|
+
|
|
275
|
+
elif command == "validate-requirements-alignment":
|
|
276
|
+
architecture = kwargs.get("architecture", {})
|
|
277
|
+
requirements = kwargs.get("requirements", {})
|
|
278
|
+
|
|
279
|
+
if isinstance(architecture, str):
|
|
280
|
+
arch_path = Path(architecture)
|
|
281
|
+
if arch_path.exists():
|
|
282
|
+
import json
|
|
283
|
+
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
284
|
+
else:
|
|
285
|
+
return {"error": f"Architecture file not found: {architecture}"}
|
|
286
|
+
|
|
287
|
+
if isinstance(requirements, str):
|
|
288
|
+
req_path = Path(requirements)
|
|
289
|
+
if req_path.exists():
|
|
290
|
+
import json
|
|
291
|
+
requirements = json.loads(req_path.read_text(encoding="utf-8"))
|
|
292
|
+
else:
|
|
293
|
+
return {"error": f"Requirements file not found: {requirements}"}
|
|
294
|
+
|
|
295
|
+
return await self._validate_requirements_alignment(architecture, requirements)
|
|
296
|
+
|
|
297
|
+
elif command == "review-architecture":
|
|
298
|
+
architecture = kwargs.get("architecture", {})
|
|
299
|
+
if isinstance(architecture, str):
|
|
300
|
+
arch_path = Path(architecture)
|
|
301
|
+
if arch_path.exists():
|
|
302
|
+
import json
|
|
303
|
+
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
304
|
+
else:
|
|
305
|
+
return {"error": f"Architecture file not found: {architecture}"}
|
|
306
|
+
|
|
307
|
+
return await self._review_architecture(architecture)
|
|
308
|
+
|
|
309
|
+
elif command == "validate-nfr":
|
|
310
|
+
architecture = kwargs.get("architecture", {})
|
|
311
|
+
nfr_requirements = kwargs.get("nfr_requirements", {})
|
|
312
|
+
|
|
313
|
+
if isinstance(architecture, str):
|
|
314
|
+
arch_path = Path(architecture)
|
|
315
|
+
if arch_path.exists():
|
|
316
|
+
import json
|
|
317
|
+
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
318
|
+
else:
|
|
319
|
+
return {"error": f"Architecture file not found: {architecture}"}
|
|
320
|
+
|
|
321
|
+
if isinstance(nfr_requirements, str):
|
|
322
|
+
nfr_path = Path(nfr_requirements)
|
|
323
|
+
if nfr_path.exists():
|
|
324
|
+
import json
|
|
325
|
+
nfr_requirements = json.loads(nfr_path.read_text(encoding="utf-8"))
|
|
326
|
+
else:
|
|
327
|
+
return {"error": f"NFR requirements file not found: {nfr_requirements}"}
|
|
328
|
+
|
|
329
|
+
return await self._validate_nfr(architecture, nfr_requirements)
|
|
330
|
+
|
|
331
|
+
elif command == "generate-diagram":
|
|
332
|
+
architecture = kwargs.get("architecture", {})
|
|
333
|
+
diagram_type = kwargs.get("diagram_type", "component") # component, sequence, class
|
|
334
|
+
format_type = kwargs.get("format", "mermaid") # mermaid, plantuml
|
|
335
|
+
|
|
336
|
+
if isinstance(architecture, str):
|
|
337
|
+
arch_path = Path(architecture)
|
|
338
|
+
if arch_path.exists():
|
|
339
|
+
import json
|
|
340
|
+
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
341
|
+
else:
|
|
342
|
+
return {"error": f"Architecture file not found: {architecture}"}
|
|
343
|
+
|
|
344
|
+
return await self._generate_diagram(architecture, diagram_type, format_type)
|
|
345
|
+
|
|
346
|
+
elif command == "export-diagram":
|
|
347
|
+
architecture = kwargs.get("architecture", {})
|
|
348
|
+
diagram_type = kwargs.get("diagram_type", "component")
|
|
349
|
+
format_type = kwargs.get("format", "mermaid")
|
|
350
|
+
output_file = kwargs.get("output_file", None)
|
|
351
|
+
|
|
352
|
+
if isinstance(architecture, str):
|
|
353
|
+
arch_path = Path(architecture)
|
|
354
|
+
if arch_path.exists():
|
|
355
|
+
import json
|
|
356
|
+
architecture = json.loads(arch_path.read_text(encoding="utf-8"))
|
|
357
|
+
else:
|
|
358
|
+
return {"error": f"Architecture file not found: {architecture}"}
|
|
359
|
+
|
|
360
|
+
if not output_file:
|
|
361
|
+
return {"error": "output_file is required for export-diagram"}
|
|
362
|
+
|
|
363
|
+
return await self._export_diagram(architecture, diagram_type, format_type, output_file)
|
|
364
|
+
|
|
365
|
+
elif command == "suggest-patterns":
|
|
366
|
+
requirements = kwargs.get("requirements", {})
|
|
367
|
+
context = kwargs.get("context", {})
|
|
368
|
+
|
|
369
|
+
if isinstance(requirements, str):
|
|
370
|
+
req_path = Path(requirements)
|
|
371
|
+
if req_path.exists():
|
|
372
|
+
import json
|
|
373
|
+
requirements = json.loads(req_path.read_text(encoding="utf-8"))
|
|
374
|
+
else:
|
|
375
|
+
return {"error": f"Requirements file not found: {requirements}"}
|
|
376
|
+
|
|
377
|
+
return await self._suggest_patterns(requirements, context)
|
|
378
|
+
|
|
379
|
+
elif command == "detect-patterns":
|
|
380
|
+
from .pattern_detector import detect_architecture_patterns
|
|
381
|
+
|
|
382
|
+
root = kwargs.get("path") or getattr(self, "_project_root", None) or Path.cwd()
|
|
383
|
+
root = Path(root).resolve()
|
|
384
|
+
patterns = detect_architecture_patterns(root)
|
|
385
|
+
return {"patterns": patterns, "project_root": str(root)}
|
|
386
|
+
|
|
387
|
+
else:
|
|
388
|
+
return {"error": f"Unknown command: {command}"}
|
|
389
|
+
|
|
390
|
+
async def _consult_experts_for_design(
|
|
391
|
+
self, requirements: str, context: str
|
|
392
|
+
) -> dict[str, Any]:
|
|
393
|
+
"""Consult experts for architecture guidance."""
|
|
394
|
+
expert_guidance: dict[str, Any] = {}
|
|
395
|
+
if not self.expert_registry:
|
|
396
|
+
return expert_guidance
|
|
397
|
+
|
|
398
|
+
# Consult Software Architecture expert
|
|
399
|
+
try:
|
|
400
|
+
arch_consultation = await self.expert_registry.consult(
|
|
401
|
+
query=f"Design system architecture for: {requirements}. Context: {context}",
|
|
402
|
+
domain="software-architecture",
|
|
403
|
+
include_all=True,
|
|
404
|
+
prioritize_builtin=True,
|
|
405
|
+
agent_id="architect",
|
|
406
|
+
)
|
|
407
|
+
expert_guidance["architecture"] = arch_consultation.weighted_answer
|
|
408
|
+
expert_guidance["architecture_confidence"] = arch_consultation.confidence
|
|
409
|
+
except Exception:
|
|
410
|
+
logger.debug("Architecture expert consultation failed", exc_info=True)
|
|
411
|
+
|
|
412
|
+
# Consult Performance expert
|
|
413
|
+
try:
|
|
414
|
+
perf_consultation = await self.expert_registry.consult(
|
|
415
|
+
query=f"Performance considerations for architecture: {requirements}",
|
|
416
|
+
domain="performance-optimization",
|
|
417
|
+
include_all=True,
|
|
418
|
+
prioritize_builtin=True,
|
|
419
|
+
agent_id="architect",
|
|
420
|
+
)
|
|
421
|
+
expert_guidance["performance"] = perf_consultation.weighted_answer
|
|
422
|
+
except Exception:
|
|
423
|
+
logger.debug("Performance expert consultation failed", exc_info=True)
|
|
424
|
+
|
|
425
|
+
# Consult Security expert
|
|
426
|
+
try:
|
|
427
|
+
sec_consultation = await self.expert_registry.consult(
|
|
428
|
+
query=f"Security architecture considerations: {requirements}",
|
|
429
|
+
domain="security",
|
|
430
|
+
include_all=True,
|
|
431
|
+
prioritize_builtin=True,
|
|
432
|
+
agent_id="architect",
|
|
433
|
+
)
|
|
434
|
+
expert_guidance["security"] = sec_consultation.weighted_answer
|
|
435
|
+
except Exception:
|
|
436
|
+
logger.debug("Security expert consultation failed", exc_info=True)
|
|
437
|
+
|
|
438
|
+
return expert_guidance
|
|
439
|
+
|
|
440
|
+
def _format_expert_guidance(self, expert_guidance: dict[str, Any]) -> str:
|
|
441
|
+
"""Format expert guidance into a prompt section."""
|
|
442
|
+
if not expert_guidance:
|
|
443
|
+
return ""
|
|
444
|
+
|
|
445
|
+
expert_section = "\n\nExpert Guidance:\n"
|
|
446
|
+
if "architecture" in expert_guidance:
|
|
447
|
+
expert_section += (
|
|
448
|
+
f"\nArchitecture Expert:\n{expert_guidance['architecture'][:500]}...\n"
|
|
449
|
+
)
|
|
450
|
+
if "performance" in expert_guidance:
|
|
451
|
+
expert_section += (
|
|
452
|
+
f"\nPerformance Expert:\n{expert_guidance['performance'][:300]}...\n"
|
|
453
|
+
)
|
|
454
|
+
if "security" in expert_guidance:
|
|
455
|
+
expert_section += (
|
|
456
|
+
f"\nSecurity Expert:\n{expert_guidance['security'][:300]}...\n"
|
|
457
|
+
)
|
|
458
|
+
return expert_section
|
|
459
|
+
|
|
460
|
+
async def _get_context7_docs_for_design(
|
|
461
|
+
self, requirements: str, context: str
|
|
462
|
+
) -> dict[str, str]:
|
|
463
|
+
"""Get Context7 documentation for mentioned technologies."""
|
|
464
|
+
context7_docs: dict[str, str] = {}
|
|
465
|
+
if not self.context7:
|
|
466
|
+
return context7_docs
|
|
467
|
+
|
|
468
|
+
full_text = f"{requirements} {context}"
|
|
469
|
+
if not self.context7.should_use_context7(full_text):
|
|
470
|
+
return context7_docs
|
|
471
|
+
|
|
472
|
+
# Extract potential library names and get docs
|
|
473
|
+
libraries = await self.context7.search_libraries(requirements, limit=5)
|
|
474
|
+
for lib_info in libraries:
|
|
475
|
+
lib_name = (
|
|
476
|
+
lib_info.get("id", "").split("/")[-1]
|
|
477
|
+
if isinstance(lib_info, dict)
|
|
478
|
+
else str(lib_info)
|
|
479
|
+
)
|
|
480
|
+
if lib_name:
|
|
481
|
+
doc = await self.context7.get_documentation(
|
|
482
|
+
lib_name, topic="architecture"
|
|
483
|
+
)
|
|
484
|
+
if doc:
|
|
485
|
+
context7_docs[lib_name] = doc.get("content", "")[:500]
|
|
486
|
+
|
|
487
|
+
return context7_docs
|
|
488
|
+
|
|
489
|
+
def _format_context7_docs(self, context7_docs: dict[str, str]) -> str:
|
|
490
|
+
"""Format Context7 documentation into a prompt section."""
|
|
491
|
+
if not context7_docs:
|
|
492
|
+
return ""
|
|
493
|
+
|
|
494
|
+
context7_section = "\n\nRelevant Architecture Documentation:\n"
|
|
495
|
+
for lib_name, doc_content in context7_docs.items():
|
|
496
|
+
context7_section += f"\n{lib_name} Architecture:\n{doc_content[:300]}...\n"
|
|
497
|
+
return context7_section
|
|
498
|
+
|
|
499
|
+
def _build_design_prompt(
|
|
500
|
+
self,
|
|
501
|
+
requirements: str,
|
|
502
|
+
context: str,
|
|
503
|
+
expert_section: str,
|
|
504
|
+
context7_section: str,
|
|
505
|
+
) -> str:
|
|
506
|
+
"""Build the architecture design prompt."""
|
|
507
|
+
return f"""Design a system architecture based on the following requirements.
|
|
508
|
+
{expert_section}
|
|
509
|
+
|
|
510
|
+
Requirements:
|
|
511
|
+
{requirements}
|
|
512
|
+
|
|
513
|
+
{f"Context: {context}" if context else ""}
|
|
514
|
+
{context7_section}
|
|
515
|
+
|
|
516
|
+
Provide a comprehensive architecture design including:
|
|
517
|
+
1. System Overview
|
|
518
|
+
2. Architecture Pattern (microservices, monolith, serverless, etc.)
|
|
519
|
+
3. Component Diagram (text-based)
|
|
520
|
+
4. Technology Stack
|
|
521
|
+
5. Data Flow
|
|
522
|
+
6. Integration Points
|
|
523
|
+
7. Scalability Considerations
|
|
524
|
+
8. Security Considerations
|
|
525
|
+
9. Deployment Architecture
|
|
526
|
+
|
|
527
|
+
Format as structured JSON with detailed architecture specification."""
|
|
528
|
+
|
|
529
|
+
def _save_architecture_result(
|
|
530
|
+
self, architecture: dict[str, Any], output_file: str | None
|
|
531
|
+
) -> None:
|
|
532
|
+
"""Save architecture result to file if specified."""
|
|
533
|
+
if not output_file:
|
|
534
|
+
return
|
|
535
|
+
|
|
536
|
+
output_path = Path(output_file)
|
|
537
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
538
|
+
output_path.write_text(json.dumps(architecture, indent=2))
|
|
539
|
+
architecture["output_file"] = str(output_path)
|
|
540
|
+
|
|
541
|
+
async def _design_system(
|
|
542
|
+
self, requirements: str, context: str = "", output_file: str | None = None
|
|
543
|
+
) -> dict[str, Any]:
|
|
544
|
+
"""Design system architecture."""
|
|
545
|
+
if not requirements:
|
|
546
|
+
return {"error": "requirements is required"}
|
|
547
|
+
|
|
548
|
+
# Consult experts for architecture guidance
|
|
549
|
+
expert_guidance = await self._consult_experts_for_design(requirements, context)
|
|
550
|
+
expert_section = self._format_expert_guidance(expert_guidance)
|
|
551
|
+
|
|
552
|
+
# Get Context7 documentation
|
|
553
|
+
context7_docs = await self._get_context7_docs_for_design(requirements, context)
|
|
554
|
+
context7_section = self._format_context7_docs(context7_docs)
|
|
555
|
+
|
|
556
|
+
# Build prompt
|
|
557
|
+
prompt = self._build_design_prompt(
|
|
558
|
+
requirements, context, expert_section, context7_section
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
# Prepare instruction for Cursor Skills
|
|
562
|
+
instruction = GenericInstruction(
|
|
563
|
+
agent_name="architect",
|
|
564
|
+
command="design-system",
|
|
565
|
+
prompt=prompt,
|
|
566
|
+
parameters={
|
|
567
|
+
"requirements": requirements,
|
|
568
|
+
"output_file": str(output_file) if output_file else None,
|
|
569
|
+
},
|
|
570
|
+
)
|
|
571
|
+
|
|
572
|
+
result = {
|
|
573
|
+
"success": True,
|
|
574
|
+
"instruction": instruction.to_dict(),
|
|
575
|
+
"skill_command": instruction.to_skill_command(),
|
|
576
|
+
}
|
|
577
|
+
if expert_guidance:
|
|
578
|
+
result["expert_guidance"] = expert_guidance
|
|
579
|
+
return result
|
|
580
|
+
|
|
581
|
+
async def _create_diagram(
|
|
582
|
+
self,
|
|
583
|
+
architecture_description: str,
|
|
584
|
+
diagram_type: str = "component",
|
|
585
|
+
output_file: str | None = None,
|
|
586
|
+
) -> dict[str, Any]:
|
|
587
|
+
"""Create architecture diagram (text-based)."""
|
|
588
|
+
if not architecture_description:
|
|
589
|
+
return {"error": "architecture_description is required"}
|
|
590
|
+
|
|
591
|
+
diagram_types = {
|
|
592
|
+
"component": "component diagram showing system components and relationships",
|
|
593
|
+
"sequence": "sequence diagram showing interactions over time",
|
|
594
|
+
"deployment": "deployment diagram showing deployment architecture",
|
|
595
|
+
"class": "class diagram showing object relationships",
|
|
596
|
+
"data-flow": "data flow diagram showing data movement",
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
diagram_description = diagram_types.get(diagram_type, "architecture diagram")
|
|
600
|
+
|
|
601
|
+
prompt = f"""Create a text-based {diagram_description} for the following architecture.
|
|
602
|
+
|
|
603
|
+
Architecture Description:
|
|
604
|
+
{architecture_description}
|
|
605
|
+
|
|
606
|
+
Provide a clear, ASCII/text-based diagram that can be rendered in markdown or plain text.
|
|
607
|
+
Use standard diagram notation (boxes, arrows, labels) for clarity.
|
|
608
|
+
|
|
609
|
+
Format:
|
|
610
|
+
1. Diagram (ASCII/text format)
|
|
611
|
+
2. Legend/Explanation
|
|
612
|
+
3. Key Relationships
|
|
613
|
+
"""
|
|
614
|
+
|
|
615
|
+
# Prepare instruction for Cursor Skills
|
|
616
|
+
instruction = GenericInstruction(
|
|
617
|
+
agent_name="architect",
|
|
618
|
+
command="create-diagram",
|
|
619
|
+
prompt=prompt,
|
|
620
|
+
parameters={
|
|
621
|
+
"diagram_type": diagram_type,
|
|
622
|
+
"architecture": architecture_description,
|
|
623
|
+
"output_file": str(output_file) if output_file else None,
|
|
624
|
+
},
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
return {
|
|
628
|
+
"success": True,
|
|
629
|
+
"instruction": instruction.to_dict(),
|
|
630
|
+
"skill_command": instruction.to_skill_command(),
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
async def _select_technology(
|
|
634
|
+
self,
|
|
635
|
+
component_description: str,
|
|
636
|
+
requirements: str = "",
|
|
637
|
+
constraints: list[str] | None = None,
|
|
638
|
+
) -> dict[str, Any]:
|
|
639
|
+
"""Select technology stack for a component."""
|
|
640
|
+
if constraints is None:
|
|
641
|
+
constraints = []
|
|
642
|
+
|
|
643
|
+
# Consult Software Architecture expert for technology selection
|
|
644
|
+
tech_guidance = ""
|
|
645
|
+
# Use defensive check to ensure attribute exists (safety for MRO issue)
|
|
646
|
+
if hasattr(self, 'expert_registry') and self.expert_registry:
|
|
647
|
+
try:
|
|
648
|
+
tech_consultation = await self.expert_registry.consult(
|
|
649
|
+
query=f"Select technology stack for: {component_description}. Requirements: {requirements}. Constraints: {', '.join(constraints) if constraints else 'None'}",
|
|
650
|
+
domain="software-architecture",
|
|
651
|
+
include_all=True,
|
|
652
|
+
prioritize_builtin=True,
|
|
653
|
+
agent_id="architect",
|
|
654
|
+
)
|
|
655
|
+
tech_guidance = tech_consultation.weighted_answer
|
|
656
|
+
except Exception:
|
|
657
|
+
logger.debug("Technology selection consultation failed", exc_info=True)
|
|
658
|
+
|
|
659
|
+
# Use Context7 to get documentation for mentioned technologies
|
|
660
|
+
context7_docs = {}
|
|
661
|
+
if self.context7:
|
|
662
|
+
full_text = (
|
|
663
|
+
f"{component_description} {requirements} {' '.join(constraints)}"
|
|
664
|
+
)
|
|
665
|
+
if self.context7.should_use_context7(full_text):
|
|
666
|
+
# Search for library mentions and get docs
|
|
667
|
+
libraries = await self.context7.search_libraries(
|
|
668
|
+
component_description, limit=3
|
|
669
|
+
)
|
|
670
|
+
for lib_info in libraries:
|
|
671
|
+
lib_name = (
|
|
672
|
+
lib_info.get("id", "").split("/")[-1]
|
|
673
|
+
if isinstance(lib_info, dict)
|
|
674
|
+
else str(lib_info)
|
|
675
|
+
)
|
|
676
|
+
if lib_name:
|
|
677
|
+
doc = await self.context7.get_documentation(
|
|
678
|
+
lib_name, topic="overview"
|
|
679
|
+
)
|
|
680
|
+
if doc:
|
|
681
|
+
context7_docs[lib_name] = doc.get("content", "")[
|
|
682
|
+
:500
|
|
683
|
+
] # First 500 chars
|
|
684
|
+
|
|
685
|
+
context7_section = ""
|
|
686
|
+
if context7_docs:
|
|
687
|
+
context7_section = "\n\nRelevant Technology Documentation from Context7:\n"
|
|
688
|
+
for lib_name, doc_content in context7_docs.items():
|
|
689
|
+
context7_section += f"\n{lib_name}:\n{doc_content[:300]}...\n"
|
|
690
|
+
|
|
691
|
+
tech_guidance_section = (
|
|
692
|
+
f"Architecture Expert Guidance:\n{tech_guidance}" if tech_guidance else ""
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
prompt = f"""Select an appropriate technology stack for the following component.
|
|
696
|
+
|
|
697
|
+
Component Description:
|
|
698
|
+
{component_description}
|
|
699
|
+
|
|
700
|
+
{f"Requirements: {requirements}" if requirements else ""}
|
|
701
|
+
|
|
702
|
+
{f"Constraints: {', '.join(constraints)}" if constraints else ""}
|
|
703
|
+
|
|
704
|
+
{tech_guidance_section}
|
|
705
|
+
{context7_section}
|
|
706
|
+
|
|
707
|
+
For each technology recommendation, provide:
|
|
708
|
+
1. Technology Name
|
|
709
|
+
2. Rationale
|
|
710
|
+
3. Pros and Cons
|
|
711
|
+
4. Fit for Requirements
|
|
712
|
+
5. Learning Curve
|
|
713
|
+
6. Community Support
|
|
714
|
+
7. Alternative Options
|
|
715
|
+
|
|
716
|
+
Format as structured JSON with technology recommendations."""
|
|
717
|
+
|
|
718
|
+
try:
|
|
719
|
+
# Prepare instruction for Cursor Skills
|
|
720
|
+
instruction = GenericInstruction(
|
|
721
|
+
agent_name="architect",
|
|
722
|
+
command="select-technology",
|
|
723
|
+
prompt=prompt,
|
|
724
|
+
parameters={
|
|
725
|
+
"component": component_description,
|
|
726
|
+
"requirements": requirements,
|
|
727
|
+
"constraints": constraints,
|
|
728
|
+
},
|
|
729
|
+
)
|
|
730
|
+
|
|
731
|
+
return {
|
|
732
|
+
"success": True,
|
|
733
|
+
"instruction": instruction.to_dict(),
|
|
734
|
+
"skill_command": instruction.to_skill_command(),
|
|
735
|
+
}
|
|
736
|
+
except Exception as e:
|
|
737
|
+
return {"error": f"Failed to select technology: {str(e)}"}
|
|
738
|
+
|
|
739
|
+
async def _design_security(
|
|
740
|
+
self, system_description: str, threat_model: str = ""
|
|
741
|
+
) -> dict[str, Any]:
|
|
742
|
+
"""Design security architecture."""
|
|
743
|
+
if not system_description:
|
|
744
|
+
return {"error": "system_description is required"}
|
|
745
|
+
|
|
746
|
+
# Consult Security expert
|
|
747
|
+
security_guidance = ""
|
|
748
|
+
security_confidence = 0.0
|
|
749
|
+
# Use defensive check to ensure attribute exists (safety for MRO issue)
|
|
750
|
+
if hasattr(self, 'expert_registry') and self.expert_registry:
|
|
751
|
+
try:
|
|
752
|
+
security_consultation = await self.expert_registry.consult(
|
|
753
|
+
query=f"Design security architecture for: {system_description}. Threat model: {threat_model}",
|
|
754
|
+
domain="security",
|
|
755
|
+
include_all=True,
|
|
756
|
+
prioritize_builtin=True,
|
|
757
|
+
agent_id="architect",
|
|
758
|
+
)
|
|
759
|
+
security_guidance = security_consultation.weighted_answer
|
|
760
|
+
security_confidence = security_consultation.confidence
|
|
761
|
+
except Exception:
|
|
762
|
+
logger.debug("Security architecture consultation failed", exc_info=True)
|
|
763
|
+
|
|
764
|
+
security_guidance_section = (
|
|
765
|
+
f"Security Expert Guidance:\n{security_guidance}"
|
|
766
|
+
if security_guidance
|
|
767
|
+
else ""
|
|
768
|
+
)
|
|
769
|
+
|
|
770
|
+
prompt = f"""Design a security architecture for the following system.
|
|
771
|
+
|
|
772
|
+
System Description:
|
|
773
|
+
{system_description}
|
|
774
|
+
|
|
775
|
+
{f"Threat Model: {threat_model}" if threat_model else ""}
|
|
776
|
+
|
|
777
|
+
{security_guidance_section}
|
|
778
|
+
|
|
779
|
+
Provide a comprehensive security design including:
|
|
780
|
+
1. Security Principles
|
|
781
|
+
2. Authentication & Authorization Strategy
|
|
782
|
+
3. Data Protection (encryption, at-rest, in-transit)
|
|
783
|
+
4. Network Security
|
|
784
|
+
5. API Security
|
|
785
|
+
6. Threat Mitigation Strategies
|
|
786
|
+
7. Security Monitoring & Logging
|
|
787
|
+
8. Compliance Considerations
|
|
788
|
+
9. Security Best Practices
|
|
789
|
+
|
|
790
|
+
Format as structured JSON with detailed security architecture."""
|
|
791
|
+
|
|
792
|
+
try:
|
|
793
|
+
# Prepare instruction for Cursor Skills
|
|
794
|
+
instruction = GenericInstruction(
|
|
795
|
+
agent_name="architect",
|
|
796
|
+
command="design-security",
|
|
797
|
+
prompt=prompt,
|
|
798
|
+
parameters={
|
|
799
|
+
"system": system_description,
|
|
800
|
+
"threat_model": threat_model,
|
|
801
|
+
},
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
result = {
|
|
805
|
+
"success": True,
|
|
806
|
+
"instruction": instruction.to_dict(),
|
|
807
|
+
"skill_command": instruction.to_skill_command(),
|
|
808
|
+
}
|
|
809
|
+
if security_guidance:
|
|
810
|
+
result["expert_guidance"] = {
|
|
811
|
+
"security": security_guidance,
|
|
812
|
+
"confidence": security_confidence,
|
|
813
|
+
}
|
|
814
|
+
return result
|
|
815
|
+
except Exception as e:
|
|
816
|
+
return {"error": f"Failed to design security: {str(e)}"}
|
|
817
|
+
|
|
818
|
+
async def _define_boundaries(
|
|
819
|
+
self, system_description: str, context: str = ""
|
|
820
|
+
) -> dict[str, Any]:
|
|
821
|
+
"""Define system boundaries and interfaces."""
|
|
822
|
+
if not system_description:
|
|
823
|
+
return {"error": "system_description is required"}
|
|
824
|
+
|
|
825
|
+
prompt = f"""Define system boundaries and interfaces for the following system.
|
|
826
|
+
|
|
827
|
+
System Description:
|
|
828
|
+
{system_description}
|
|
829
|
+
|
|
830
|
+
{f"Context: {context}" if context else ""}
|
|
831
|
+
|
|
832
|
+
Provide:
|
|
833
|
+
1. System Boundaries (what's inside vs outside)
|
|
834
|
+
2. External Dependencies
|
|
835
|
+
3. API Interfaces (REST, GraphQL, gRPC, etc.)
|
|
836
|
+
4. Data Interfaces (data formats, schemas)
|
|
837
|
+
5. Integration Points
|
|
838
|
+
6. Interface Contracts
|
|
839
|
+
7. Service Contracts
|
|
840
|
+
8. Communication Protocols
|
|
841
|
+
|
|
842
|
+
Format as structured JSON with boundary and interface definitions."""
|
|
843
|
+
|
|
844
|
+
try:
|
|
845
|
+
# Prepare instruction for Cursor Skills
|
|
846
|
+
instruction = GenericInstruction(
|
|
847
|
+
agent_name="architect",
|
|
848
|
+
command="define-boundaries",
|
|
849
|
+
prompt=prompt,
|
|
850
|
+
parameters={
|
|
851
|
+
"system": system_description,
|
|
852
|
+
"context": context,
|
|
853
|
+
},
|
|
854
|
+
)
|
|
855
|
+
|
|
856
|
+
return {
|
|
857
|
+
"success": True,
|
|
858
|
+
"instruction": instruction.to_dict(),
|
|
859
|
+
"skill_command": instruction.to_skill_command(),
|
|
860
|
+
}
|
|
861
|
+
except Exception as e:
|
|
862
|
+
return {"error": f"Failed to define boundaries: {str(e)}"}
|
|
863
|
+
|
|
864
|
+
async def _evaluate_architecture(self, architecture: dict[str, Any]) -> dict[str, Any]:
|
|
865
|
+
"""Evaluate architecture quality and completeness."""
|
|
866
|
+
# Basic evaluation - can be enhanced with more sophisticated analysis
|
|
867
|
+
score = {
|
|
868
|
+
"overall": 75.0, # Placeholder - would use actual evaluation logic
|
|
869
|
+
"components_defined": len(architecture.get("components", [])) > 0,
|
|
870
|
+
"patterns_identified": len(architecture.get("patterns", [])) > 0,
|
|
871
|
+
"security_addressed": "security" in str(architecture).lower(),
|
|
872
|
+
"scalability_addressed": "scal" in str(architecture).lower() or "scale" in str(architecture).lower(),
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
return {
|
|
876
|
+
"success": True,
|
|
877
|
+
"score": score,
|
|
878
|
+
"architecture": architecture,
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
async def _validate_requirements_alignment(
|
|
882
|
+
self, architecture: dict[str, Any], requirements: dict[str, Any]
|
|
883
|
+
) -> dict[str, Any]:
|
|
884
|
+
"""Validate architecture covers all requirements."""
|
|
885
|
+
from ...core.design_validator import DesignValidator
|
|
886
|
+
|
|
887
|
+
validator = DesignValidator()
|
|
888
|
+
result = validator.validate_requirements_alignment(architecture, requirements)
|
|
889
|
+
|
|
890
|
+
return {
|
|
891
|
+
"success": True,
|
|
892
|
+
"is_valid": result.is_valid,
|
|
893
|
+
"requirements_coverage": result.requirements_coverage,
|
|
894
|
+
"missing_requirements": result.missing_requirements,
|
|
895
|
+
"pattern_violations": result.pattern_violations,
|
|
896
|
+
"security_issues": result.security_issues,
|
|
897
|
+
"scalability_concerns": result.scalability_concerns,
|
|
898
|
+
"recommendations": result.recommendations,
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
async def _review_architecture(self, architecture: dict[str, Any]) -> dict[str, Any]:
|
|
902
|
+
"""Structured review of architecture with checklist."""
|
|
903
|
+
from ...core.review_checklists import ArchitectureReviewChecklist
|
|
904
|
+
|
|
905
|
+
checklist = ArchitectureReviewChecklist()
|
|
906
|
+
result = checklist.review(architecture)
|
|
907
|
+
|
|
908
|
+
return {
|
|
909
|
+
"success": True,
|
|
910
|
+
"overall_score": result.overall_score,
|
|
911
|
+
"items_checked": result.items_checked,
|
|
912
|
+
"items_total": result.items_total,
|
|
913
|
+
"critical_issues": result.critical_issues,
|
|
914
|
+
"high_issues": result.high_issues,
|
|
915
|
+
"medium_issues": result.medium_issues,
|
|
916
|
+
"low_issues": result.low_issues,
|
|
917
|
+
"recommendations": result.recommendations,
|
|
918
|
+
"checklist_items": [
|
|
919
|
+
{
|
|
920
|
+
"category": item.category,
|
|
921
|
+
"item": item.item,
|
|
922
|
+
"checked": item.checked,
|
|
923
|
+
"severity": item.severity,
|
|
924
|
+
"notes": item.notes,
|
|
925
|
+
}
|
|
926
|
+
for item in result.checklist_items
|
|
927
|
+
],
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
async def _validate_nfr(
|
|
931
|
+
self, architecture: dict[str, Any], nfr_requirements: dict[str, Any]
|
|
932
|
+
) -> dict[str, Any]:
|
|
933
|
+
"""Validate architecture against non-functional requirements."""
|
|
934
|
+
from ...core.nfr_validator import NFRValidator
|
|
935
|
+
|
|
936
|
+
validator = NFRValidator()
|
|
937
|
+
result = validator.validate_architecture_nfr(architecture, nfr_requirements)
|
|
938
|
+
|
|
939
|
+
return {
|
|
940
|
+
"success": True,
|
|
941
|
+
"is_valid": result.is_valid,
|
|
942
|
+
"overall_score": result.overall_score,
|
|
943
|
+
"security_score": result.security_score,
|
|
944
|
+
"performance_score": result.performance_score,
|
|
945
|
+
"reliability_score": result.reliability_score,
|
|
946
|
+
"maintainability_score": result.maintainability_score,
|
|
947
|
+
"security_issues": result.security_issues,
|
|
948
|
+
"performance_issues": result.performance_issues,
|
|
949
|
+
"reliability_issues": result.reliability_issues,
|
|
950
|
+
"maintainability_issues": result.maintainability_issues,
|
|
951
|
+
"recommendations": result.recommendations,
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
async def _generate_diagram(
|
|
955
|
+
self, architecture: dict[str, Any], diagram_type: str, format_type: str
|
|
956
|
+
) -> dict[str, Any]:
|
|
957
|
+
"""Generate Mermaid or PlantUML diagram from architecture."""
|
|
958
|
+
from ...core.diagram_generator import DiagramGenerator
|
|
959
|
+
|
|
960
|
+
generator = DiagramGenerator()
|
|
961
|
+
|
|
962
|
+
if format_type == "mermaid":
|
|
963
|
+
if diagram_type == "component":
|
|
964
|
+
diagram_code = generator.generate_mermaid_component_diagram(architecture)
|
|
965
|
+
elif diagram_type == "sequence":
|
|
966
|
+
interactions = architecture.get("interactions", [])
|
|
967
|
+
diagram_code = generator.generate_mermaid_sequence_diagram(interactions)
|
|
968
|
+
elif diagram_type == "class":
|
|
969
|
+
classes = architecture.get("classes", [])
|
|
970
|
+
diagram_code = generator.generate_mermaid_class_diagram(classes)
|
|
971
|
+
else:
|
|
972
|
+
return {"error": f"Unsupported diagram type: {diagram_type}. Use: component, sequence, class"}
|
|
973
|
+
|
|
974
|
+
elif format_type == "plantuml":
|
|
975
|
+
if diagram_type == "component":
|
|
976
|
+
diagram_code = generator.generate_plantuml_component_diagram(architecture)
|
|
977
|
+
else:
|
|
978
|
+
return {"error": f"PlantUML only supports component diagrams currently"}
|
|
979
|
+
|
|
980
|
+
else:
|
|
981
|
+
return {"error": f"Unsupported format: {format_type}. Use: mermaid, plantuml"}
|
|
982
|
+
|
|
983
|
+
return {
|
|
984
|
+
"success": True,
|
|
985
|
+
"diagram_code": diagram_code,
|
|
986
|
+
"format": format_type,
|
|
987
|
+
"diagram_type": diagram_type,
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
async def _export_diagram(
|
|
991
|
+
self, architecture: dict[str, Any], diagram_type: str, format_type: str, output_file: str
|
|
992
|
+
) -> dict[str, Any]:
|
|
993
|
+
"""Export architecture diagram to file."""
|
|
994
|
+
from ...core.diagram_generator import DiagramGenerator
|
|
995
|
+
|
|
996
|
+
generator = DiagramGenerator()
|
|
997
|
+
|
|
998
|
+
# Generate diagram
|
|
999
|
+
result = await self._generate_diagram(architecture, diagram_type, format_type)
|
|
1000
|
+
if "error" in result:
|
|
1001
|
+
return result
|
|
1002
|
+
|
|
1003
|
+
diagram_code = result["diagram_code"]
|
|
1004
|
+
|
|
1005
|
+
# Export to file
|
|
1006
|
+
output_path = Path(output_file)
|
|
1007
|
+
generator.export_to_file(diagram_code, output_path, format_type)
|
|
1008
|
+
|
|
1009
|
+
return {
|
|
1010
|
+
"success": True,
|
|
1011
|
+
"output_file": str(output_path),
|
|
1012
|
+
"format": format_type,
|
|
1013
|
+
"diagram_type": diagram_type,
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
async def _suggest_patterns(self, requirements: dict[str, Any], context: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
1017
|
+
"""Suggest design patterns based on requirements."""
|
|
1018
|
+
from ...core.pattern_library import DesignPatternLibrary
|
|
1019
|
+
|
|
1020
|
+
library = DesignPatternLibrary()
|
|
1021
|
+
suggestions = library.suggest_patterns(requirements, context)
|
|
1022
|
+
|
|
1023
|
+
return {
|
|
1024
|
+
"success": True,
|
|
1025
|
+
"suggestions": suggestions,
|
|
1026
|
+
"total_patterns_available": len(library.patterns),
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
async def close(self) -> None:
|
|
1030
|
+
"""Cleanup resources."""
|
|
1031
|
+
await super().close()
|
|
1032
|
+
# Context7 helper cleanup if needed
|
|
1033
|
+
# (Context7AgentHelper doesn't currently require explicit cleanup)
|
|
1034
1034
|
# Design cache cleanup would go here if we add caching in the future
|