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,723 +1,723 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Fix Orchestrator - Coordinates bug fixing workflow with review loopback and auto-commit.
|
|
3
|
-
|
|
4
|
-
Coordinates: Debugger → Implementer → Tester → Reviewer (with loopback) → Security Scan → Git Commit
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import logging
|
|
8
|
-
import time
|
|
9
|
-
from datetime import UTC, datetime
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from typing import Any
|
|
12
|
-
|
|
13
|
-
from tapps_agents.core.config import ProjectConfig, load_config
|
|
14
|
-
from tapps_agents.core.git_operations import (
|
|
15
|
-
commit_changes,
|
|
16
|
-
create_and_checkout_branch,
|
|
17
|
-
create_pull_request,
|
|
18
|
-
get_current_branch,
|
|
19
|
-
push_changes,
|
|
20
|
-
)
|
|
21
|
-
from tapps_agents.core.multi_agent_orchestrator import MultiAgentOrchestrator
|
|
22
|
-
from tapps_agents.quality.quality_gates import QualityGate, QualityThresholds
|
|
23
|
-
from ..intent_parser import Intent
|
|
24
|
-
from .base import SimpleModeOrchestrator
|
|
25
|
-
|
|
26
|
-
logger = logging.getLogger(__name__)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _write_fix_handoff(
|
|
30
|
-
project_root: Path,
|
|
31
|
-
workflow_id: str,
|
|
32
|
-
success: bool,
|
|
33
|
-
iterations: int = 0,
|
|
34
|
-
error: str | None = None,
|
|
35
|
-
target_file: str | None = None,
|
|
36
|
-
) -> None:
|
|
37
|
-
"""Write session handoff for fix workflow (plan 2.1)."""
|
|
38
|
-
try:
|
|
39
|
-
from tapps_agents.workflow.session_handoff import SessionHandoff, write_handoff
|
|
40
|
-
|
|
41
|
-
status = "completed" if success else "failed"
|
|
42
|
-
summary = f"Fix workflow {status}. Iterations: {iterations}."
|
|
43
|
-
if error:
|
|
44
|
-
summary += f" Error: {error[:100]}."
|
|
45
|
-
if target_file:
|
|
46
|
-
summary += f" Target: {target_file}."
|
|
47
|
-
handoff = SessionHandoff(
|
|
48
|
-
workflow_id=workflow_id,
|
|
49
|
-
session_ended_at=datetime.now(UTC).isoformat(),
|
|
50
|
-
summary=summary,
|
|
51
|
-
done=[f"iteration {i + 1}" for i in range(iterations)] if iterations else ["debugger"],
|
|
52
|
-
decisions=[],
|
|
53
|
-
next_steps=["Resume with tapps-agents workflow resume", "Run `bd ready`"],
|
|
54
|
-
artifact_paths=[],
|
|
55
|
-
bd_ready_hint="Run `bd ready`",
|
|
56
|
-
)
|
|
57
|
-
write_handoff(project_root, handoff)
|
|
58
|
-
except Exception as e: # pylint: disable=broad-except
|
|
59
|
-
logger.debug("Could not write session handoff: %s", e)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class FixOrchestrator(SimpleModeOrchestrator):
|
|
63
|
-
"""Orchestrator for fixing bugs and errors with review loopback and auto-commit."""
|
|
64
|
-
|
|
65
|
-
def get_agent_sequence(self) -> list[str]:
|
|
66
|
-
"""Get the sequence of agents for fix workflow."""
|
|
67
|
-
return ["debugger", "implementer", "tester", "reviewer"]
|
|
68
|
-
|
|
69
|
-
async def execute(
|
|
70
|
-
self, intent: Intent, parameters: dict[str, Any] | None = None
|
|
71
|
-
) -> dict[str, Any]:
|
|
72
|
-
"""
|
|
73
|
-
Execute fix workflow with review loopback and auto-commit.
|
|
74
|
-
|
|
75
|
-
Args:
|
|
76
|
-
intent: Parsed user intent
|
|
77
|
-
parameters: Additional parameters from user input:
|
|
78
|
-
- files: List of file paths
|
|
79
|
-
- error_message: Error description
|
|
80
|
-
- max_iterations: Maximum iterations for loopback (default: 3)
|
|
81
|
-
- auto_commit: Whether to commit on success (default: True)
|
|
82
|
-
- commit_message: Optional commit message (auto-generated if not provided)
|
|
83
|
-
- quality_thresholds: Optional quality thresholds dict
|
|
84
|
-
|
|
85
|
-
Returns:
|
|
86
|
-
Dictionary with execution results including commit info
|
|
87
|
-
"""
|
|
88
|
-
parameters = parameters or {}
|
|
89
|
-
files = parameters.get("files", [])
|
|
90
|
-
error_message = parameters.get("error_message", "")
|
|
91
|
-
workflow_id = f"fix-{int(time.time() * 1000)}"
|
|
92
|
-
|
|
93
|
-
# Load configuration
|
|
94
|
-
config = self.config or load_config()
|
|
95
|
-
bug_fix_config = config.bug_fix_agent
|
|
96
|
-
|
|
97
|
-
# Beads required: fail early if beads.required and bd unavailable
|
|
98
|
-
try:
|
|
99
|
-
from tapps_agents.beads import require_beads
|
|
100
|
-
|
|
101
|
-
require_beads(config, self.project_root)
|
|
102
|
-
except Exception as e:
|
|
103
|
-
from tapps_agents.cli.feedback import get_feedback
|
|
104
|
-
|
|
105
|
-
get_feedback().error(str(e), context={"beads_required": True})
|
|
106
|
-
return {
|
|
107
|
-
"type": "fix",
|
|
108
|
-
"success": False,
|
|
109
|
-
"error": str(e),
|
|
110
|
-
"workflow_id": workflow_id,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
max_iterations = parameters.get("max_iterations", bug_fix_config.max_iterations)
|
|
114
|
-
auto_commit = parameters.get("auto_commit", bug_fix_config.auto_commit)
|
|
115
|
-
commit_message = parameters.get("commit_message")
|
|
116
|
-
escalation_threshold = bug_fix_config.escalation_threshold
|
|
117
|
-
escalation_enabled = bug_fix_config.escalation_enabled
|
|
118
|
-
pre_commit_security_scan = bug_fix_config.pre_commit_security_scan
|
|
119
|
-
metrics_enabled = bug_fix_config.metrics_enabled
|
|
120
|
-
commit_strategy = bug_fix_config.commit_strategy
|
|
121
|
-
auto_merge_pr = bug_fix_config.auto_merge_pr
|
|
122
|
-
require_pr_review = bug_fix_config.require_pr_review
|
|
123
|
-
|
|
124
|
-
# Get quality thresholds from config or parameters
|
|
125
|
-
thresholds_dict = parameters.get("quality_thresholds", {})
|
|
126
|
-
if thresholds_dict:
|
|
127
|
-
thresholds = QualityThresholds.from_dict(thresholds_dict)
|
|
128
|
-
else:
|
|
129
|
-
# Use thresholds from config
|
|
130
|
-
quality_thresholds = bug_fix_config.quality_thresholds
|
|
131
|
-
thresholds = QualityThresholds(
|
|
132
|
-
overall_min=quality_thresholds.get("overall_min", 7.0),
|
|
133
|
-
security_min=quality_thresholds.get("security_min", 6.5),
|
|
134
|
-
maintainability_min=quality_thresholds.get("maintainability_min", 7.0),
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
# Initialize metrics collection
|
|
138
|
-
start_time = time.time()
|
|
139
|
-
metrics = {
|
|
140
|
-
"bug_description": error_message or intent.original_input,
|
|
141
|
-
"target_file": files[0] if files else None,
|
|
142
|
-
"start_time": start_time,
|
|
143
|
-
"iterations": 0,
|
|
144
|
-
"success": False,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
# Create multi-agent orchestrator
|
|
148
|
-
orchestrator = MultiAgentOrchestrator(
|
|
149
|
-
project_root=self.project_root,
|
|
150
|
-
config=self.config,
|
|
151
|
-
max_parallel=1, # Sequential for fix workflow
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
# Prepare agent tasks
|
|
155
|
-
target_file = files[0] if files else None
|
|
156
|
-
bug_description = error_message or intent.original_input
|
|
157
|
-
|
|
158
|
-
from ..beads_hooks import create_fix_issue, close_issue
|
|
159
|
-
|
|
160
|
-
beads_issue_id: str | None = None
|
|
161
|
-
if self.config:
|
|
162
|
-
beads_issue_id = create_fix_issue(
|
|
163
|
-
self.project_root,
|
|
164
|
-
self.config,
|
|
165
|
-
str(target_file) if target_file else "",
|
|
166
|
-
bug_description,
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
# Step 1: Execute debugger
|
|
170
|
-
debug_tasks = [
|
|
171
|
-
{
|
|
172
|
-
"agent_id": "debugger-1",
|
|
173
|
-
"agent": "debugger",
|
|
174
|
-
"command": "debug",
|
|
175
|
-
"args": {
|
|
176
|
-
"error_message": bug_description,
|
|
177
|
-
"file": target_file,
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
]
|
|
181
|
-
|
|
182
|
-
logger.info(f"Step 1/4+: Analyzing bug: {bug_description}")
|
|
183
|
-
# #region agent log
|
|
184
|
-
import json
|
|
185
|
-
from datetime import datetime
|
|
186
|
-
log_path = self.project_root / ".cursor" / "debug.log"
|
|
187
|
-
try:
|
|
188
|
-
with open(log_path, "a", encoding="utf-8") as f:
|
|
189
|
-
f.write(json.dumps({
|
|
190
|
-
"sessionId": "debug-session",
|
|
191
|
-
"runId": "run1",
|
|
192
|
-
"hypothesisId": "E",
|
|
193
|
-
"location": "fix_orchestrator.py:execute:before_debugger",
|
|
194
|
-
"message": "About to execute debugger",
|
|
195
|
-
"data": {"bug_description": bug_description[:200], "target_file": target_file},
|
|
196
|
-
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
197
|
-
}) + "\n")
|
|
198
|
-
except Exception:
|
|
199
|
-
pass
|
|
200
|
-
# #endregion
|
|
201
|
-
debug_result = await orchestrator.execute_parallel(debug_tasks)
|
|
202
|
-
# #region agent log
|
|
203
|
-
try:
|
|
204
|
-
with open(log_path, "a", encoding="utf-8") as f:
|
|
205
|
-
f.write(json.dumps({
|
|
206
|
-
"sessionId": "debug-session",
|
|
207
|
-
"runId": "run1",
|
|
208
|
-
"hypothesisId": "E",
|
|
209
|
-
"location": "fix_orchestrator.py:execute:after_debugger",
|
|
210
|
-
"message": "debugger execute_parallel returned",
|
|
211
|
-
"data": {"has_results": "results" in debug_result, "result_keys": list(debug_result.keys())},
|
|
212
|
-
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
213
|
-
}) + "\n")
|
|
214
|
-
except Exception:
|
|
215
|
-
pass
|
|
216
|
-
# #endregion
|
|
217
|
-
|
|
218
|
-
# Check if debugger succeeded
|
|
219
|
-
debugger_result = debug_result.get("results", {}).get("debugger-1", {})
|
|
220
|
-
# #region agent log
|
|
221
|
-
try:
|
|
222
|
-
with open(log_path, "a", encoding="utf-8") as f:
|
|
223
|
-
f.write(json.dumps({
|
|
224
|
-
"sessionId": "debug-session",
|
|
225
|
-
"runId": "run1",
|
|
226
|
-
"hypothesisId": "F",
|
|
227
|
-
"location": "fix_orchestrator.py:execute:debugger_result_check",
|
|
228
|
-
"message": "debugger_result structure",
|
|
229
|
-
"data": {"success": debugger_result.get("success"), "result_keys": list(debugger_result.keys()), "has_result_key": "result" in debugger_result},
|
|
230
|
-
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
231
|
-
}) + "\n")
|
|
232
|
-
except Exception:
|
|
233
|
-
pass
|
|
234
|
-
# #endregion
|
|
235
|
-
if not debugger_result.get("success"):
|
|
236
|
-
# #region agent log
|
|
237
|
-
try:
|
|
238
|
-
with open(log_path, "a", encoding="utf-8") as f:
|
|
239
|
-
f.write(json.dumps({
|
|
240
|
-
"sessionId": "debug-session",
|
|
241
|
-
"runId": "run1",
|
|
242
|
-
"hypothesisId": "F",
|
|
243
|
-
"location": "fix_orchestrator.py:execute:debugger_failed",
|
|
244
|
-
"message": "Debugger failed",
|
|
245
|
-
"data": {"debugger_result": str(debugger_result)[:500]},
|
|
246
|
-
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
247
|
-
}) + "\n")
|
|
248
|
-
except Exception:
|
|
249
|
-
pass
|
|
250
|
-
# #endregion
|
|
251
|
-
close_issue(self.project_root, beads_issue_id)
|
|
252
|
-
_write_fix_handoff(
|
|
253
|
-
self.project_root, workflow_id,
|
|
254
|
-
success=False, iterations=0,
|
|
255
|
-
error="Debugger failed to analyze the bug",
|
|
256
|
-
target_file=files[0] if files else None,
|
|
257
|
-
)
|
|
258
|
-
return {
|
|
259
|
-
"type": "fix",
|
|
260
|
-
"success": False,
|
|
261
|
-
"error": "Debugger failed to analyze the bug",
|
|
262
|
-
"debugger_result": debugger_result,
|
|
263
|
-
"iterations": 0,
|
|
264
|
-
"committed": False,
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
# Extract fix suggestion from debugger analysis
|
|
268
|
-
# debug_command returns: {"type": "debug", "analysis": {...}, "suggestions": [...], "fix_examples": [...]}
|
|
269
|
-
debugger_analysis = debugger_result.get("result", {}).get("analysis", {})
|
|
270
|
-
suggestions = debugger_result.get("result", {}).get("suggestions", [])
|
|
271
|
-
fix_examples = debugger_result.get("result", {}).get("fix_examples", [])
|
|
272
|
-
|
|
273
|
-
# Build fix suggestion from suggestions and examples
|
|
274
|
-
fix_suggestion_parts = []
|
|
275
|
-
if suggestions:
|
|
276
|
-
fix_suggestion_parts.extend(suggestions[:3]) # Take first 3 suggestions
|
|
277
|
-
if fix_examples:
|
|
278
|
-
fix_suggestion_parts.append("\n".join(fix_examples[:2])) # Take first 2 examples
|
|
279
|
-
fix_suggestion = "\n\n".join(fix_suggestion_parts) if fix_suggestion_parts else ""
|
|
280
|
-
|
|
281
|
-
# #region agent log
|
|
282
|
-
try:
|
|
283
|
-
result_inner = debugger_result.get("result", {})
|
|
284
|
-
with open(log_path, "a", encoding="utf-8") as f:
|
|
285
|
-
f.write(json.dumps({
|
|
286
|
-
"sessionId": "debug-session",
|
|
287
|
-
"runId": "run1",
|
|
288
|
-
"hypothesisId": "G",
|
|
289
|
-
"location": "fix_orchestrator.py:execute:fix_suggestion_check",
|
|
290
|
-
"message": "Checking fix_suggestion",
|
|
291
|
-
"data": {"has_result_key": "result" in debugger_result, "result_keys": list(result_inner.keys()) if isinstance(result_inner, dict) else "not_dict", "has_analysis": "analysis" in result_inner, "has_suggestions": "suggestions" in result_inner, "suggestions_count": len(suggestions), "fix_examples_count": len(fix_examples), "fix_suggestion_length": len(fix_suggestion)},
|
|
292
|
-
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
293
|
-
}) + "\n")
|
|
294
|
-
except Exception:
|
|
295
|
-
pass
|
|
296
|
-
# #endregion
|
|
297
|
-
if not fix_suggestion:
|
|
298
|
-
close_issue(self.project_root, beads_issue_id)
|
|
299
|
-
_write_fix_handoff(
|
|
300
|
-
self.project_root, workflow_id,
|
|
301
|
-
success=False, iterations=0,
|
|
302
|
-
error="Debugger did not provide a fix suggestion",
|
|
303
|
-
target_file=files[0] if files else None,
|
|
304
|
-
)
|
|
305
|
-
return {
|
|
306
|
-
"type": "fix",
|
|
307
|
-
"success": False,
|
|
308
|
-
"error": "Debugger did not provide a fix suggestion",
|
|
309
|
-
"debugger_result": debugger_result,
|
|
310
|
-
"iterations": 0,
|
|
311
|
-
"committed": False,
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
# Step 2-4: Loop: Fix → Test → Review (until quality passes or max iterations)
|
|
315
|
-
quality_passed = False
|
|
316
|
-
iteration = 0
|
|
317
|
-
review_results = []
|
|
318
|
-
|
|
319
|
-
while iteration < max_iterations and not quality_passed:
|
|
320
|
-
iteration += 1
|
|
321
|
-
logger.info(f"Iteration {iteration}/{max_iterations}: Fix → Test → Review")
|
|
322
|
-
|
|
323
|
-
# Step 2: Implement fix
|
|
324
|
-
implement_tasks = [
|
|
325
|
-
{
|
|
326
|
-
"agent_id": f"implementer-{iteration}",
|
|
327
|
-
"agent": "implementer",
|
|
328
|
-
"command": "refactor",
|
|
329
|
-
"args": {
|
|
330
|
-
"file": target_file,
|
|
331
|
-
"instructions": fix_suggestion,
|
|
332
|
-
},
|
|
333
|
-
},
|
|
334
|
-
]
|
|
335
|
-
|
|
336
|
-
implement_result = await orchestrator.execute_parallel(implement_tasks)
|
|
337
|
-
implementer_result = implement_result.get("results", {}).get(
|
|
338
|
-
f"implementer-{iteration}", {}
|
|
339
|
-
)
|
|
340
|
-
|
|
341
|
-
if not implementer_result.get("success"):
|
|
342
|
-
close_issue(self.project_root, beads_issue_id)
|
|
343
|
-
_write_fix_handoff(
|
|
344
|
-
self.project_root, workflow_id,
|
|
345
|
-
success=False, iterations=iteration,
|
|
346
|
-
error=f"Implementer failed on iteration {iteration}",
|
|
347
|
-
target_file=target_file,
|
|
348
|
-
)
|
|
349
|
-
return {
|
|
350
|
-
"type": "fix",
|
|
351
|
-
"success": False,
|
|
352
|
-
"error": f"Implementer failed on iteration {iteration}",
|
|
353
|
-
"implementer_result": implementer_result,
|
|
354
|
-
"iterations": iteration,
|
|
355
|
-
"committed": False,
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
# Step 3: Test the fix
|
|
359
|
-
test_tasks = [
|
|
360
|
-
{
|
|
361
|
-
"agent_id": f"tester-{iteration}",
|
|
362
|
-
"agent": "tester",
|
|
363
|
-
"command": "test",
|
|
364
|
-
"args": {"file": target_file},
|
|
365
|
-
},
|
|
366
|
-
]
|
|
367
|
-
|
|
368
|
-
test_result = await orchestrator.execute_parallel(test_tasks)
|
|
369
|
-
tester_result = test_result.get("results", {}).get(
|
|
370
|
-
f"tester-{iteration}", {}
|
|
371
|
-
)
|
|
372
|
-
|
|
373
|
-
if not tester_result.get("success"):
|
|
374
|
-
logger.warning(
|
|
375
|
-
f"Tester reported issues on iteration {iteration}, continuing to review"
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
# Step 4: Review quality
|
|
379
|
-
review_tasks = [
|
|
380
|
-
{
|
|
381
|
-
"agent_id": f"reviewer-{iteration}",
|
|
382
|
-
"agent": "reviewer",
|
|
383
|
-
"command": "review",
|
|
384
|
-
"args": {"file": target_file},
|
|
385
|
-
},
|
|
386
|
-
]
|
|
387
|
-
|
|
388
|
-
review_result_exec = await orchestrator.execute_parallel(review_tasks)
|
|
389
|
-
reviewer_result = review_result_exec.get("results", {}).get(
|
|
390
|
-
f"reviewer-{iteration}", {}
|
|
391
|
-
)
|
|
392
|
-
|
|
393
|
-
if not reviewer_result.get("success"):
|
|
394
|
-
logger.warning(
|
|
395
|
-
f"Reviewer failed on iteration {iteration}, assuming quality passed"
|
|
396
|
-
)
|
|
397
|
-
quality_passed = True
|
|
398
|
-
review_results.append({
|
|
399
|
-
"iteration": iteration,
|
|
400
|
-
"result": reviewer_result,
|
|
401
|
-
"quality_passed": True,
|
|
402
|
-
})
|
|
403
|
-
break
|
|
404
|
-
|
|
405
|
-
# Extract review result
|
|
406
|
-
review_result_data = reviewer_result.get("result", {})
|
|
407
|
-
review_results.append({
|
|
408
|
-
"iteration": iteration,
|
|
409
|
-
"result": review_result_data,
|
|
410
|
-
})
|
|
411
|
-
|
|
412
|
-
# Evaluate quality gate
|
|
413
|
-
quality_gate = QualityGate(thresholds=thresholds)
|
|
414
|
-
gate_result = quality_gate.evaluate_from_review_result(
|
|
415
|
-
review_result_data, thresholds
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
quality_passed = gate_result.passed
|
|
419
|
-
|
|
420
|
-
logger.info(
|
|
421
|
-
f"Iteration {iteration}: Quality gate {'PASSED' if quality_passed else 'FAILED'}"
|
|
422
|
-
)
|
|
423
|
-
logger.info(
|
|
424
|
-
f" Overall: {gate_result.scores.get('overall_score', 0):.2f}/10 "
|
|
425
|
-
f"(threshold: {thresholds.overall_min})"
|
|
426
|
-
)
|
|
427
|
-
logger.info(
|
|
428
|
-
f" Security: {gate_result.scores.get('security_score', 0):.2f}/10 "
|
|
429
|
-
f"(threshold: {thresholds.security_min})"
|
|
430
|
-
)
|
|
431
|
-
|
|
432
|
-
if not quality_passed:
|
|
433
|
-
failed_iterations = iteration
|
|
434
|
-
# Human-in-the-Loop Escalation (2025 Enhancement)
|
|
435
|
-
if escalation_enabled and failed_iterations >= escalation_threshold:
|
|
436
|
-
logger.warning(
|
|
437
|
-
f"🔔 ESCALATION: {failed_iterations} failed iterations reached escalation threshold ({escalation_threshold})"
|
|
438
|
-
)
|
|
439
|
-
logger.warning(
|
|
440
|
-
f"Human intervention recommended. Bug fix agent has attempted {failed_iterations} fixes without meeting quality thresholds."
|
|
441
|
-
)
|
|
442
|
-
logger.warning(
|
|
443
|
-
f"Current scores: Overall={gate_result.scores.get('overall_score', 0):.2f}/10, "
|
|
444
|
-
f"Security={gate_result.scores.get('security_score', 0):.2f}/10, "
|
|
445
|
-
f"Maintainability={gate_result.scores.get('maintainability_score', 0):.2f}/10"
|
|
446
|
-
)
|
|
447
|
-
# Continue to max_iterations but log escalation
|
|
448
|
-
|
|
449
|
-
if iteration < max_iterations:
|
|
450
|
-
# Get improvement suggestions from review
|
|
451
|
-
improvements = review_result_data.get("improvements", [])
|
|
452
|
-
if improvements:
|
|
453
|
-
# Combine with previous fix suggestion
|
|
454
|
-
fix_suggestion = (
|
|
455
|
-
f"{fix_suggestion}\n\nAdditional improvements needed:\n"
|
|
456
|
-
+ "\n".join(f"- {imp}" for imp in improvements[:5])
|
|
457
|
-
)
|
|
458
|
-
logger.info(
|
|
459
|
-
f"Quality threshold not met, attempting improvement (iteration {iteration + 1})"
|
|
460
|
-
)
|
|
461
|
-
else:
|
|
462
|
-
logger.error(
|
|
463
|
-
f"Maximum iterations ({max_iterations}) reached, quality threshold not met"
|
|
464
|
-
)
|
|
465
|
-
# Record escalation in metrics
|
|
466
|
-
if metrics_enabled and failed_iterations >= escalation_threshold:
|
|
467
|
-
metrics["escalated"] = True
|
|
468
|
-
metrics["escalation_iteration"] = escalation_threshold
|
|
469
|
-
|
|
470
|
-
# Check if quality passed
|
|
471
|
-
if not quality_passed:
|
|
472
|
-
execution_time = time.time() - start_time
|
|
473
|
-
if metrics_enabled:
|
|
474
|
-
metrics.update({
|
|
475
|
-
"iterations": iteration,
|
|
476
|
-
"success": False,
|
|
477
|
-
"execution_time": execution_time,
|
|
478
|
-
"final_quality_scores": review_results[-1]["result"].get("scores", {}) if review_results else {},
|
|
479
|
-
})
|
|
480
|
-
logger.info(f"Metrics: {metrics}")
|
|
481
|
-
|
|
482
|
-
close_issue(self.project_root, beads_issue_id)
|
|
483
|
-
return {
|
|
484
|
-
"type": "fix",
|
|
485
|
-
"success": False,
|
|
486
|
-
"error": f"Quality threshold not met after {max_iterations} iterations",
|
|
487
|
-
"review_results": review_results,
|
|
488
|
-
"iterations": iteration,
|
|
489
|
-
"committed": False,
|
|
490
|
-
"escalated": escalation_enabled and iteration >= escalation_threshold,
|
|
491
|
-
"metrics": metrics if metrics_enabled else None,
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
# Step 5: Pre-Commit Security Scan (2025 Enhancement)
|
|
495
|
-
security_scan_passed = True
|
|
496
|
-
security_scan_result = None
|
|
497
|
-
if pre_commit_security_scan and auto_commit:
|
|
498
|
-
logger.info("Running pre-commit security scan...")
|
|
499
|
-
try:
|
|
500
|
-
security_scan_tasks = [
|
|
501
|
-
{
|
|
502
|
-
"agent_id": "ops-security-1",
|
|
503
|
-
"agent": "ops",
|
|
504
|
-
"command": "security-scan",
|
|
505
|
-
"args": {
|
|
506
|
-
"target": target_file,
|
|
507
|
-
"scan_type": "code",
|
|
508
|
-
},
|
|
509
|
-
},
|
|
510
|
-
]
|
|
511
|
-
security_result = await orchestrator.execute_parallel(security_scan_tasks)
|
|
512
|
-
security_scan_result = security_result.get("results", {}).get("ops-security-1", {})
|
|
513
|
-
|
|
514
|
-
if security_scan_result.get("success"):
|
|
515
|
-
security_score = security_scan_result.get("result", {}).get("security_score", 10.0)
|
|
516
|
-
vulnerabilities = security_scan_result.get("result", {}).get("vulnerabilities", [])
|
|
517
|
-
critical_vulns = [v for v in vulnerabilities if v.get("severity") in ["CRITICAL", "HIGH"]]
|
|
518
|
-
|
|
519
|
-
if critical_vulns:
|
|
520
|
-
logger.error(f"Pre-commit security scan FAILED: {len(critical_vulns)} CRITICAL/HIGH vulnerabilities found")
|
|
521
|
-
security_scan_passed = False
|
|
522
|
-
logger.error("Blocking commit due to security vulnerabilities")
|
|
523
|
-
elif security_score < thresholds.security_min:
|
|
524
|
-
logger.warning(f"Pre-commit security scan: score {security_score:.2f} below threshold {thresholds.security_min}")
|
|
525
|
-
# Warn but don't block for non-critical issues
|
|
526
|
-
else:
|
|
527
|
-
logger.info(f"Pre-commit security scan PASSED: score {security_score:.2f}/10")
|
|
528
|
-
else:
|
|
529
|
-
logger.warning("Security scan failed, but continuing with commit")
|
|
530
|
-
except Exception as e:
|
|
531
|
-
logger.warning(f"Error during security scan: {e}, continuing with commit")
|
|
532
|
-
|
|
533
|
-
if not security_scan_passed:
|
|
534
|
-
execution_time = time.time() - start_time
|
|
535
|
-
if metrics_enabled:
|
|
536
|
-
metrics.update({
|
|
537
|
-
"iterations": iteration,
|
|
538
|
-
"success": False,
|
|
539
|
-
"execution_time": execution_time,
|
|
540
|
-
"security_scan_blocked": True,
|
|
541
|
-
})
|
|
542
|
-
close_issue(self.project_root, beads_issue_id)
|
|
543
|
-
_write_fix_handoff(
|
|
544
|
-
self.project_root, workflow_id,
|
|
545
|
-
success=False, iterations=iteration,
|
|
546
|
-
error="Pre-commit security scan failed: CRITICAL/HIGH vulnerabilities detected",
|
|
547
|
-
target_file=target_file,
|
|
548
|
-
)
|
|
549
|
-
return {
|
|
550
|
-
"type": "fix",
|
|
551
|
-
"success": False,
|
|
552
|
-
"error": "Pre-commit security scan failed: CRITICAL/HIGH vulnerabilities detected",
|
|
553
|
-
"review_results": review_results,
|
|
554
|
-
"iterations": iteration,
|
|
555
|
-
"committed": False,
|
|
556
|
-
"security_scan_result": security_scan_result,
|
|
557
|
-
"metrics": metrics if metrics_enabled else None,
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
# Step 6: Commit changes (direct or PR workflow)
|
|
561
|
-
commit_info = None
|
|
562
|
-
pr_info = None
|
|
563
|
-
if auto_commit:
|
|
564
|
-
try:
|
|
565
|
-
# Generate commit message if not provided
|
|
566
|
-
if not commit_message:
|
|
567
|
-
final_scores = review_results[-1]["result"].get("scores", {}) if review_results else {}
|
|
568
|
-
overall_score = final_scores.get("overall_score", 0)
|
|
569
|
-
commit_message = (
|
|
570
|
-
f"Fix: {bug_description}\n\n"
|
|
571
|
-
f"Quality scores: Overall {overall_score:.1f}/10\n"
|
|
572
|
-
f"Iterations: {iteration}\n"
|
|
573
|
-
f"Auto-fixed by TappsCodingAgents Bug Fix Agent"
|
|
574
|
-
)
|
|
575
|
-
|
|
576
|
-
# Branch Protection & PR Workflow (2025 Enhancement)
|
|
577
|
-
if commit_strategy == "pull_request":
|
|
578
|
-
# Create feature branch for PR
|
|
579
|
-
timestamp = datetime.now(UTC).strftime("%Y%m%d%H%M%S")
|
|
580
|
-
file_stem = Path(target_file).stem if target_file else "fix"
|
|
581
|
-
feature_branch = f"bugfix/{file_stem}-{timestamp}"
|
|
582
|
-
|
|
583
|
-
logger.info(f"Creating feature branch: {feature_branch}")
|
|
584
|
-
branch_result = create_and_checkout_branch(feature_branch, self.project_root)
|
|
585
|
-
|
|
586
|
-
if not branch_result["success"]:
|
|
587
|
-
raise RuntimeError(f"Failed to create branch: {branch_result.get('error')}")
|
|
588
|
-
|
|
589
|
-
# Commit to feature branch
|
|
590
|
-
commit_result = commit_changes(
|
|
591
|
-
message=commit_message,
|
|
592
|
-
files=[target_file] if target_file else None,
|
|
593
|
-
branch=feature_branch,
|
|
594
|
-
path=self.project_root,
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
if commit_result["success"]:
|
|
598
|
-
# Push feature branch
|
|
599
|
-
push_result = push_changes(feature_branch, self.project_root)
|
|
600
|
-
|
|
601
|
-
if push_result["success"]:
|
|
602
|
-
# Create PR
|
|
603
|
-
pr_title = f"Fix: {bug_description[:100]}"
|
|
604
|
-
pr_body = (
|
|
605
|
-
f"## Automated Bug Fix\n\n"
|
|
606
|
-
f"**Bug Description:** {bug_description}\n\n"
|
|
607
|
-
f"**Target File:** {target_file}\n\n"
|
|
608
|
-
f"**Quality Scores:**\n"
|
|
609
|
-
f"- Overall: {final_scores.get('overall_score', 0):.1f}/10\n"
|
|
610
|
-
f"- Security: {final_scores.get('security_score', 0):.1f}/10\n"
|
|
611
|
-
f"- Maintainability: {final_scores.get('maintainability_score', 0):.1f}/10\n\n"
|
|
612
|
-
f"**Iterations:** {iteration}\n\n"
|
|
613
|
-
f"**Auto-fixed by:** TappsCodingAgents Bug Fix Agent\n\n"
|
|
614
|
-
f"---\n\n"
|
|
615
|
-
f"*This PR was created automatically after passing quality gates.*"
|
|
616
|
-
)
|
|
617
|
-
|
|
618
|
-
pr_result = create_pull_request(
|
|
619
|
-
title=pr_title,
|
|
620
|
-
body=pr_body,
|
|
621
|
-
head_branch=feature_branch,
|
|
622
|
-
base_branch="main",
|
|
623
|
-
path=self.project_root,
|
|
624
|
-
)
|
|
625
|
-
|
|
626
|
-
if pr_result["success"]:
|
|
627
|
-
pr_info = {
|
|
628
|
-
"pr_url": pr_result.get("pr_url"),
|
|
629
|
-
"pr_number": pr_result.get("pr_number"),
|
|
630
|
-
"branch": feature_branch,
|
|
631
|
-
}
|
|
632
|
-
logger.info(f"Created pull request: {pr_result.get('pr_url', 'N/A')}")
|
|
633
|
-
|
|
634
|
-
if auto_merge_pr and not require_pr_review:
|
|
635
|
-
logger.info("Auto-merge enabled, but manual merge required (GitHub CLI limitation)")
|
|
636
|
-
else:
|
|
637
|
-
logger.warning(f"Failed to create PR: {pr_result.get('error')}")
|
|
638
|
-
# Fall back to commit info even if PR creation failed
|
|
639
|
-
commit_info = {
|
|
640
|
-
"commit_hash": commit_result["commit_hash"],
|
|
641
|
-
"branch": feature_branch,
|
|
642
|
-
"message": commit_message,
|
|
643
|
-
"pr_error": pr_result.get("error"),
|
|
644
|
-
}
|
|
645
|
-
else:
|
|
646
|
-
logger.warning(f"Failed to push branch: {push_result.get('error')}")
|
|
647
|
-
commit_info = {"error": f"Push failed: {push_result.get('error')}"}
|
|
648
|
-
else:
|
|
649
|
-
logger.warning(f"Failed to commit to branch: {commit_result.get('error')}")
|
|
650
|
-
commit_info = {"error": commit_result.get("error")}
|
|
651
|
-
|
|
652
|
-
else:
|
|
653
|
-
# Direct commit to main (original behavior)
|
|
654
|
-
commit_result = commit_changes(
|
|
655
|
-
message=commit_message,
|
|
656
|
-
files=[target_file] if target_file else None,
|
|
657
|
-
branch="main",
|
|
658
|
-
path=self.project_root,
|
|
659
|
-
)
|
|
660
|
-
|
|
661
|
-
if commit_result["success"]:
|
|
662
|
-
commit_info = {
|
|
663
|
-
"commit_hash": commit_result["commit_hash"],
|
|
664
|
-
"branch": commit_result["branch"],
|
|
665
|
-
"message": commit_message,
|
|
666
|
-
}
|
|
667
|
-
logger.info(
|
|
668
|
-
f"Committed changes to {commit_result['branch']}: "
|
|
669
|
-
f"{commit_result['commit_hash'][:8]}"
|
|
670
|
-
)
|
|
671
|
-
else:
|
|
672
|
-
logger.warning(
|
|
673
|
-
f"Failed to commit changes: {commit_result.get('error')}"
|
|
674
|
-
)
|
|
675
|
-
commit_info = {
|
|
676
|
-
"error": commit_result.get("error"),
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
except Exception as e:
|
|
680
|
-
logger.error(f"Error during commit: {e}", exc_info=True)
|
|
681
|
-
commit_info = {"error": str(e)}
|
|
682
|
-
|
|
683
|
-
# Update metrics for successful execution
|
|
684
|
-
execution_time = time.time() - start_time
|
|
685
|
-
if metrics_enabled:
|
|
686
|
-
final_scores = review_results[-1]["result"].get("scores", {}) if review_results else {}
|
|
687
|
-
metrics.update({
|
|
688
|
-
"iterations": iteration,
|
|
689
|
-
"success": True,
|
|
690
|
-
"execution_time": execution_time,
|
|
691
|
-
"final_quality_scores": final_scores,
|
|
692
|
-
"committed": commit_info is not None and "error" not in commit_info,
|
|
693
|
-
"security_scan_performed": pre_commit_security_scan and auto_commit,
|
|
694
|
-
})
|
|
695
|
-
logger.info(f"Execution metrics: {metrics}")
|
|
696
|
-
|
|
697
|
-
close_issue(self.project_root, beads_issue_id)
|
|
698
|
-
_write_fix_handoff(
|
|
699
|
-
self.project_root, workflow_id,
|
|
700
|
-
success=True, iterations=iteration,
|
|
701
|
-
target_file=target_file,
|
|
702
|
-
)
|
|
703
|
-
return {
|
|
704
|
-
"type": "fix",
|
|
705
|
-
"success": True,
|
|
706
|
-
"agents_executed": ["debugger", "implementer", "tester", "reviewer"] + (["ops"] if pre_commit_security_scan and auto_commit else []),
|
|
707
|
-
"iterations": iteration,
|
|
708
|
-
"review_results": review_results,
|
|
709
|
-
"quality_passed": True,
|
|
710
|
-
"committed": commit_info is not None and "error" not in commit_info,
|
|
711
|
-
"commit_info": commit_info,
|
|
712
|
-
"pr_info": pr_info,
|
|
713
|
-
"commit_strategy": commit_strategy,
|
|
714
|
-
"security_scan_result": security_scan_result if pre_commit_security_scan and auto_commit else None,
|
|
715
|
-
"metrics": metrics if metrics_enabled else None,
|
|
716
|
-
"summary": {
|
|
717
|
-
"bug_description": bug_description,
|
|
718
|
-
"target_file": target_file,
|
|
719
|
-
"iterations": iteration,
|
|
720
|
-
"final_quality": review_results[-1]["result"].get("scores", {}) if review_results else {},
|
|
721
|
-
"execution_time": execution_time,
|
|
722
|
-
},
|
|
723
|
-
}
|
|
1
|
+
"""
|
|
2
|
+
Fix Orchestrator - Coordinates bug fixing workflow with review loopback and auto-commit.
|
|
3
|
+
|
|
4
|
+
Coordinates: Debugger → Implementer → Tester → Reviewer (with loopback) → Security Scan → Git Commit
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import time
|
|
9
|
+
from datetime import UTC, datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from tapps_agents.core.config import ProjectConfig, load_config
|
|
14
|
+
from tapps_agents.core.git_operations import (
|
|
15
|
+
commit_changes,
|
|
16
|
+
create_and_checkout_branch,
|
|
17
|
+
create_pull_request,
|
|
18
|
+
get_current_branch,
|
|
19
|
+
push_changes,
|
|
20
|
+
)
|
|
21
|
+
from tapps_agents.core.multi_agent_orchestrator import MultiAgentOrchestrator
|
|
22
|
+
from tapps_agents.quality.quality_gates import QualityGate, QualityThresholds
|
|
23
|
+
from ..intent_parser import Intent
|
|
24
|
+
from .base import SimpleModeOrchestrator
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _write_fix_handoff(
|
|
30
|
+
project_root: Path,
|
|
31
|
+
workflow_id: str,
|
|
32
|
+
success: bool,
|
|
33
|
+
iterations: int = 0,
|
|
34
|
+
error: str | None = None,
|
|
35
|
+
target_file: str | None = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Write session handoff for fix workflow (plan 2.1)."""
|
|
38
|
+
try:
|
|
39
|
+
from tapps_agents.workflow.session_handoff import SessionHandoff, write_handoff
|
|
40
|
+
|
|
41
|
+
status = "completed" if success else "failed"
|
|
42
|
+
summary = f"Fix workflow {status}. Iterations: {iterations}."
|
|
43
|
+
if error:
|
|
44
|
+
summary += f" Error: {error[:100]}."
|
|
45
|
+
if target_file:
|
|
46
|
+
summary += f" Target: {target_file}."
|
|
47
|
+
handoff = SessionHandoff(
|
|
48
|
+
workflow_id=workflow_id,
|
|
49
|
+
session_ended_at=datetime.now(UTC).isoformat(),
|
|
50
|
+
summary=summary,
|
|
51
|
+
done=[f"iteration {i + 1}" for i in range(iterations)] if iterations else ["debugger"],
|
|
52
|
+
decisions=[],
|
|
53
|
+
next_steps=["Resume with tapps-agents workflow resume", "Run `bd ready`"],
|
|
54
|
+
artifact_paths=[],
|
|
55
|
+
bd_ready_hint="Run `bd ready`",
|
|
56
|
+
)
|
|
57
|
+
write_handoff(project_root, handoff)
|
|
58
|
+
except Exception as e: # pylint: disable=broad-except
|
|
59
|
+
logger.debug("Could not write session handoff: %s", e)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class FixOrchestrator(SimpleModeOrchestrator):
|
|
63
|
+
"""Orchestrator for fixing bugs and errors with review loopback and auto-commit."""
|
|
64
|
+
|
|
65
|
+
def get_agent_sequence(self) -> list[str]:
|
|
66
|
+
"""Get the sequence of agents for fix workflow."""
|
|
67
|
+
return ["debugger", "implementer", "tester", "reviewer"]
|
|
68
|
+
|
|
69
|
+
async def execute(
|
|
70
|
+
self, intent: Intent, parameters: dict[str, Any] | None = None
|
|
71
|
+
) -> dict[str, Any]:
|
|
72
|
+
"""
|
|
73
|
+
Execute fix workflow with review loopback and auto-commit.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
intent: Parsed user intent
|
|
77
|
+
parameters: Additional parameters from user input:
|
|
78
|
+
- files: List of file paths
|
|
79
|
+
- error_message: Error description
|
|
80
|
+
- max_iterations: Maximum iterations for loopback (default: 3)
|
|
81
|
+
- auto_commit: Whether to commit on success (default: True)
|
|
82
|
+
- commit_message: Optional commit message (auto-generated if not provided)
|
|
83
|
+
- quality_thresholds: Optional quality thresholds dict
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Dictionary with execution results including commit info
|
|
87
|
+
"""
|
|
88
|
+
parameters = parameters or {}
|
|
89
|
+
files = parameters.get("files", [])
|
|
90
|
+
error_message = parameters.get("error_message", "")
|
|
91
|
+
workflow_id = f"fix-{int(time.time() * 1000)}"
|
|
92
|
+
|
|
93
|
+
# Load configuration
|
|
94
|
+
config = self.config or load_config()
|
|
95
|
+
bug_fix_config = config.bug_fix_agent
|
|
96
|
+
|
|
97
|
+
# Beads required: fail early if beads.required and bd unavailable
|
|
98
|
+
try:
|
|
99
|
+
from tapps_agents.beads import require_beads
|
|
100
|
+
|
|
101
|
+
require_beads(config, self.project_root)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
from tapps_agents.cli.feedback import get_feedback
|
|
104
|
+
|
|
105
|
+
get_feedback().error(str(e), context={"beads_required": True})
|
|
106
|
+
return {
|
|
107
|
+
"type": "fix",
|
|
108
|
+
"success": False,
|
|
109
|
+
"error": str(e),
|
|
110
|
+
"workflow_id": workflow_id,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
max_iterations = parameters.get("max_iterations", bug_fix_config.max_iterations)
|
|
114
|
+
auto_commit = parameters.get("auto_commit", bug_fix_config.auto_commit)
|
|
115
|
+
commit_message = parameters.get("commit_message")
|
|
116
|
+
escalation_threshold = bug_fix_config.escalation_threshold
|
|
117
|
+
escalation_enabled = bug_fix_config.escalation_enabled
|
|
118
|
+
pre_commit_security_scan = bug_fix_config.pre_commit_security_scan
|
|
119
|
+
metrics_enabled = bug_fix_config.metrics_enabled
|
|
120
|
+
commit_strategy = bug_fix_config.commit_strategy
|
|
121
|
+
auto_merge_pr = bug_fix_config.auto_merge_pr
|
|
122
|
+
require_pr_review = bug_fix_config.require_pr_review
|
|
123
|
+
|
|
124
|
+
# Get quality thresholds from config or parameters
|
|
125
|
+
thresholds_dict = parameters.get("quality_thresholds", {})
|
|
126
|
+
if thresholds_dict:
|
|
127
|
+
thresholds = QualityThresholds.from_dict(thresholds_dict)
|
|
128
|
+
else:
|
|
129
|
+
# Use thresholds from config
|
|
130
|
+
quality_thresholds = bug_fix_config.quality_thresholds
|
|
131
|
+
thresholds = QualityThresholds(
|
|
132
|
+
overall_min=quality_thresholds.get("overall_min", 7.0),
|
|
133
|
+
security_min=quality_thresholds.get("security_min", 6.5),
|
|
134
|
+
maintainability_min=quality_thresholds.get("maintainability_min", 7.0),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Initialize metrics collection
|
|
138
|
+
start_time = time.time()
|
|
139
|
+
metrics = {
|
|
140
|
+
"bug_description": error_message or intent.original_input,
|
|
141
|
+
"target_file": files[0] if files else None,
|
|
142
|
+
"start_time": start_time,
|
|
143
|
+
"iterations": 0,
|
|
144
|
+
"success": False,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Create multi-agent orchestrator
|
|
148
|
+
orchestrator = MultiAgentOrchestrator(
|
|
149
|
+
project_root=self.project_root,
|
|
150
|
+
config=self.config,
|
|
151
|
+
max_parallel=1, # Sequential for fix workflow
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Prepare agent tasks
|
|
155
|
+
target_file = files[0] if files else None
|
|
156
|
+
bug_description = error_message or intent.original_input
|
|
157
|
+
|
|
158
|
+
from ..beads_hooks import create_fix_issue, close_issue
|
|
159
|
+
|
|
160
|
+
beads_issue_id: str | None = None
|
|
161
|
+
if self.config:
|
|
162
|
+
beads_issue_id = create_fix_issue(
|
|
163
|
+
self.project_root,
|
|
164
|
+
self.config,
|
|
165
|
+
str(target_file) if target_file else "",
|
|
166
|
+
bug_description,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Step 1: Execute debugger
|
|
170
|
+
debug_tasks = [
|
|
171
|
+
{
|
|
172
|
+
"agent_id": "debugger-1",
|
|
173
|
+
"agent": "debugger",
|
|
174
|
+
"command": "debug",
|
|
175
|
+
"args": {
|
|
176
|
+
"error_message": bug_description,
|
|
177
|
+
"file": target_file,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
logger.info(f"Step 1/4+: Analyzing bug: {bug_description}")
|
|
183
|
+
# #region agent log
|
|
184
|
+
import json
|
|
185
|
+
from datetime import datetime
|
|
186
|
+
log_path = self.project_root / ".cursor" / "debug.log"
|
|
187
|
+
try:
|
|
188
|
+
with open(log_path, "a", encoding="utf-8") as f:
|
|
189
|
+
f.write(json.dumps({
|
|
190
|
+
"sessionId": "debug-session",
|
|
191
|
+
"runId": "run1",
|
|
192
|
+
"hypothesisId": "E",
|
|
193
|
+
"location": "fix_orchestrator.py:execute:before_debugger",
|
|
194
|
+
"message": "About to execute debugger",
|
|
195
|
+
"data": {"bug_description": bug_description[:200], "target_file": target_file},
|
|
196
|
+
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
197
|
+
}) + "\n")
|
|
198
|
+
except Exception:
|
|
199
|
+
pass
|
|
200
|
+
# #endregion
|
|
201
|
+
debug_result = await orchestrator.execute_parallel(debug_tasks)
|
|
202
|
+
# #region agent log
|
|
203
|
+
try:
|
|
204
|
+
with open(log_path, "a", encoding="utf-8") as f:
|
|
205
|
+
f.write(json.dumps({
|
|
206
|
+
"sessionId": "debug-session",
|
|
207
|
+
"runId": "run1",
|
|
208
|
+
"hypothesisId": "E",
|
|
209
|
+
"location": "fix_orchestrator.py:execute:after_debugger",
|
|
210
|
+
"message": "debugger execute_parallel returned",
|
|
211
|
+
"data": {"has_results": "results" in debug_result, "result_keys": list(debug_result.keys())},
|
|
212
|
+
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
213
|
+
}) + "\n")
|
|
214
|
+
except Exception:
|
|
215
|
+
pass
|
|
216
|
+
# #endregion
|
|
217
|
+
|
|
218
|
+
# Check if debugger succeeded
|
|
219
|
+
debugger_result = debug_result.get("results", {}).get("debugger-1", {})
|
|
220
|
+
# #region agent log
|
|
221
|
+
try:
|
|
222
|
+
with open(log_path, "a", encoding="utf-8") as f:
|
|
223
|
+
f.write(json.dumps({
|
|
224
|
+
"sessionId": "debug-session",
|
|
225
|
+
"runId": "run1",
|
|
226
|
+
"hypothesisId": "F",
|
|
227
|
+
"location": "fix_orchestrator.py:execute:debugger_result_check",
|
|
228
|
+
"message": "debugger_result structure",
|
|
229
|
+
"data": {"success": debugger_result.get("success"), "result_keys": list(debugger_result.keys()), "has_result_key": "result" in debugger_result},
|
|
230
|
+
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
231
|
+
}) + "\n")
|
|
232
|
+
except Exception:
|
|
233
|
+
pass
|
|
234
|
+
# #endregion
|
|
235
|
+
if not debugger_result.get("success"):
|
|
236
|
+
# #region agent log
|
|
237
|
+
try:
|
|
238
|
+
with open(log_path, "a", encoding="utf-8") as f:
|
|
239
|
+
f.write(json.dumps({
|
|
240
|
+
"sessionId": "debug-session",
|
|
241
|
+
"runId": "run1",
|
|
242
|
+
"hypothesisId": "F",
|
|
243
|
+
"location": "fix_orchestrator.py:execute:debugger_failed",
|
|
244
|
+
"message": "Debugger failed",
|
|
245
|
+
"data": {"debugger_result": str(debugger_result)[:500]},
|
|
246
|
+
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
247
|
+
}) + "\n")
|
|
248
|
+
except Exception:
|
|
249
|
+
pass
|
|
250
|
+
# #endregion
|
|
251
|
+
close_issue(self.project_root, beads_issue_id)
|
|
252
|
+
_write_fix_handoff(
|
|
253
|
+
self.project_root, workflow_id,
|
|
254
|
+
success=False, iterations=0,
|
|
255
|
+
error="Debugger failed to analyze the bug",
|
|
256
|
+
target_file=files[0] if files else None,
|
|
257
|
+
)
|
|
258
|
+
return {
|
|
259
|
+
"type": "fix",
|
|
260
|
+
"success": False,
|
|
261
|
+
"error": "Debugger failed to analyze the bug",
|
|
262
|
+
"debugger_result": debugger_result,
|
|
263
|
+
"iterations": 0,
|
|
264
|
+
"committed": False,
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
# Extract fix suggestion from debugger analysis
|
|
268
|
+
# debug_command returns: {"type": "debug", "analysis": {...}, "suggestions": [...], "fix_examples": [...]}
|
|
269
|
+
debugger_analysis = debugger_result.get("result", {}).get("analysis", {})
|
|
270
|
+
suggestions = debugger_result.get("result", {}).get("suggestions", [])
|
|
271
|
+
fix_examples = debugger_result.get("result", {}).get("fix_examples", [])
|
|
272
|
+
|
|
273
|
+
# Build fix suggestion from suggestions and examples
|
|
274
|
+
fix_suggestion_parts = []
|
|
275
|
+
if suggestions:
|
|
276
|
+
fix_suggestion_parts.extend(suggestions[:3]) # Take first 3 suggestions
|
|
277
|
+
if fix_examples:
|
|
278
|
+
fix_suggestion_parts.append("\n".join(fix_examples[:2])) # Take first 2 examples
|
|
279
|
+
fix_suggestion = "\n\n".join(fix_suggestion_parts) if fix_suggestion_parts else ""
|
|
280
|
+
|
|
281
|
+
# #region agent log
|
|
282
|
+
try:
|
|
283
|
+
result_inner = debugger_result.get("result", {})
|
|
284
|
+
with open(log_path, "a", encoding="utf-8") as f:
|
|
285
|
+
f.write(json.dumps({
|
|
286
|
+
"sessionId": "debug-session",
|
|
287
|
+
"runId": "run1",
|
|
288
|
+
"hypothesisId": "G",
|
|
289
|
+
"location": "fix_orchestrator.py:execute:fix_suggestion_check",
|
|
290
|
+
"message": "Checking fix_suggestion",
|
|
291
|
+
"data": {"has_result_key": "result" in debugger_result, "result_keys": list(result_inner.keys()) if isinstance(result_inner, dict) else "not_dict", "has_analysis": "analysis" in result_inner, "has_suggestions": "suggestions" in result_inner, "suggestions_count": len(suggestions), "fix_examples_count": len(fix_examples), "fix_suggestion_length": len(fix_suggestion)},
|
|
292
|
+
"timestamp": int(datetime.now().timestamp() * 1000)
|
|
293
|
+
}) + "\n")
|
|
294
|
+
except Exception:
|
|
295
|
+
pass
|
|
296
|
+
# #endregion
|
|
297
|
+
if not fix_suggestion:
|
|
298
|
+
close_issue(self.project_root, beads_issue_id)
|
|
299
|
+
_write_fix_handoff(
|
|
300
|
+
self.project_root, workflow_id,
|
|
301
|
+
success=False, iterations=0,
|
|
302
|
+
error="Debugger did not provide a fix suggestion",
|
|
303
|
+
target_file=files[0] if files else None,
|
|
304
|
+
)
|
|
305
|
+
return {
|
|
306
|
+
"type": "fix",
|
|
307
|
+
"success": False,
|
|
308
|
+
"error": "Debugger did not provide a fix suggestion",
|
|
309
|
+
"debugger_result": debugger_result,
|
|
310
|
+
"iterations": 0,
|
|
311
|
+
"committed": False,
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
# Step 2-4: Loop: Fix → Test → Review (until quality passes or max iterations)
|
|
315
|
+
quality_passed = False
|
|
316
|
+
iteration = 0
|
|
317
|
+
review_results = []
|
|
318
|
+
|
|
319
|
+
while iteration < max_iterations and not quality_passed:
|
|
320
|
+
iteration += 1
|
|
321
|
+
logger.info(f"Iteration {iteration}/{max_iterations}: Fix → Test → Review")
|
|
322
|
+
|
|
323
|
+
# Step 2: Implement fix
|
|
324
|
+
implement_tasks = [
|
|
325
|
+
{
|
|
326
|
+
"agent_id": f"implementer-{iteration}",
|
|
327
|
+
"agent": "implementer",
|
|
328
|
+
"command": "refactor",
|
|
329
|
+
"args": {
|
|
330
|
+
"file": target_file,
|
|
331
|
+
"instructions": fix_suggestion,
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
]
|
|
335
|
+
|
|
336
|
+
implement_result = await orchestrator.execute_parallel(implement_tasks)
|
|
337
|
+
implementer_result = implement_result.get("results", {}).get(
|
|
338
|
+
f"implementer-{iteration}", {}
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
if not implementer_result.get("success"):
|
|
342
|
+
close_issue(self.project_root, beads_issue_id)
|
|
343
|
+
_write_fix_handoff(
|
|
344
|
+
self.project_root, workflow_id,
|
|
345
|
+
success=False, iterations=iteration,
|
|
346
|
+
error=f"Implementer failed on iteration {iteration}",
|
|
347
|
+
target_file=target_file,
|
|
348
|
+
)
|
|
349
|
+
return {
|
|
350
|
+
"type": "fix",
|
|
351
|
+
"success": False,
|
|
352
|
+
"error": f"Implementer failed on iteration {iteration}",
|
|
353
|
+
"implementer_result": implementer_result,
|
|
354
|
+
"iterations": iteration,
|
|
355
|
+
"committed": False,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# Step 3: Test the fix
|
|
359
|
+
test_tasks = [
|
|
360
|
+
{
|
|
361
|
+
"agent_id": f"tester-{iteration}",
|
|
362
|
+
"agent": "tester",
|
|
363
|
+
"command": "test",
|
|
364
|
+
"args": {"file": target_file},
|
|
365
|
+
},
|
|
366
|
+
]
|
|
367
|
+
|
|
368
|
+
test_result = await orchestrator.execute_parallel(test_tasks)
|
|
369
|
+
tester_result = test_result.get("results", {}).get(
|
|
370
|
+
f"tester-{iteration}", {}
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
if not tester_result.get("success"):
|
|
374
|
+
logger.warning(
|
|
375
|
+
f"Tester reported issues on iteration {iteration}, continuing to review"
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Step 4: Review quality
|
|
379
|
+
review_tasks = [
|
|
380
|
+
{
|
|
381
|
+
"agent_id": f"reviewer-{iteration}",
|
|
382
|
+
"agent": "reviewer",
|
|
383
|
+
"command": "review",
|
|
384
|
+
"args": {"file": target_file},
|
|
385
|
+
},
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
review_result_exec = await orchestrator.execute_parallel(review_tasks)
|
|
389
|
+
reviewer_result = review_result_exec.get("results", {}).get(
|
|
390
|
+
f"reviewer-{iteration}", {}
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
if not reviewer_result.get("success"):
|
|
394
|
+
logger.warning(
|
|
395
|
+
f"Reviewer failed on iteration {iteration}, assuming quality passed"
|
|
396
|
+
)
|
|
397
|
+
quality_passed = True
|
|
398
|
+
review_results.append({
|
|
399
|
+
"iteration": iteration,
|
|
400
|
+
"result": reviewer_result,
|
|
401
|
+
"quality_passed": True,
|
|
402
|
+
})
|
|
403
|
+
break
|
|
404
|
+
|
|
405
|
+
# Extract review result
|
|
406
|
+
review_result_data = reviewer_result.get("result", {})
|
|
407
|
+
review_results.append({
|
|
408
|
+
"iteration": iteration,
|
|
409
|
+
"result": review_result_data,
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
# Evaluate quality gate
|
|
413
|
+
quality_gate = QualityGate(thresholds=thresholds)
|
|
414
|
+
gate_result = quality_gate.evaluate_from_review_result(
|
|
415
|
+
review_result_data, thresholds
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
quality_passed = gate_result.passed
|
|
419
|
+
|
|
420
|
+
logger.info(
|
|
421
|
+
f"Iteration {iteration}: Quality gate {'PASSED' if quality_passed else 'FAILED'}"
|
|
422
|
+
)
|
|
423
|
+
logger.info(
|
|
424
|
+
f" Overall: {gate_result.scores.get('overall_score', 0):.2f}/10 "
|
|
425
|
+
f"(threshold: {thresholds.overall_min})"
|
|
426
|
+
)
|
|
427
|
+
logger.info(
|
|
428
|
+
f" Security: {gate_result.scores.get('security_score', 0):.2f}/10 "
|
|
429
|
+
f"(threshold: {thresholds.security_min})"
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
if not quality_passed:
|
|
433
|
+
failed_iterations = iteration
|
|
434
|
+
# Human-in-the-Loop Escalation (2025 Enhancement)
|
|
435
|
+
if escalation_enabled and failed_iterations >= escalation_threshold:
|
|
436
|
+
logger.warning(
|
|
437
|
+
f"🔔 ESCALATION: {failed_iterations} failed iterations reached escalation threshold ({escalation_threshold})"
|
|
438
|
+
)
|
|
439
|
+
logger.warning(
|
|
440
|
+
f"Human intervention recommended. Bug fix agent has attempted {failed_iterations} fixes without meeting quality thresholds."
|
|
441
|
+
)
|
|
442
|
+
logger.warning(
|
|
443
|
+
f"Current scores: Overall={gate_result.scores.get('overall_score', 0):.2f}/10, "
|
|
444
|
+
f"Security={gate_result.scores.get('security_score', 0):.2f}/10, "
|
|
445
|
+
f"Maintainability={gate_result.scores.get('maintainability_score', 0):.2f}/10"
|
|
446
|
+
)
|
|
447
|
+
# Continue to max_iterations but log escalation
|
|
448
|
+
|
|
449
|
+
if iteration < max_iterations:
|
|
450
|
+
# Get improvement suggestions from review
|
|
451
|
+
improvements = review_result_data.get("improvements", [])
|
|
452
|
+
if improvements:
|
|
453
|
+
# Combine with previous fix suggestion
|
|
454
|
+
fix_suggestion = (
|
|
455
|
+
f"{fix_suggestion}\n\nAdditional improvements needed:\n"
|
|
456
|
+
+ "\n".join(f"- {imp}" for imp in improvements[:5])
|
|
457
|
+
)
|
|
458
|
+
logger.info(
|
|
459
|
+
f"Quality threshold not met, attempting improvement (iteration {iteration + 1})"
|
|
460
|
+
)
|
|
461
|
+
else:
|
|
462
|
+
logger.error(
|
|
463
|
+
f"Maximum iterations ({max_iterations}) reached, quality threshold not met"
|
|
464
|
+
)
|
|
465
|
+
# Record escalation in metrics
|
|
466
|
+
if metrics_enabled and failed_iterations >= escalation_threshold:
|
|
467
|
+
metrics["escalated"] = True
|
|
468
|
+
metrics["escalation_iteration"] = escalation_threshold
|
|
469
|
+
|
|
470
|
+
# Check if quality passed
|
|
471
|
+
if not quality_passed:
|
|
472
|
+
execution_time = time.time() - start_time
|
|
473
|
+
if metrics_enabled:
|
|
474
|
+
metrics.update({
|
|
475
|
+
"iterations": iteration,
|
|
476
|
+
"success": False,
|
|
477
|
+
"execution_time": execution_time,
|
|
478
|
+
"final_quality_scores": review_results[-1]["result"].get("scores", {}) if review_results else {},
|
|
479
|
+
})
|
|
480
|
+
logger.info(f"Metrics: {metrics}")
|
|
481
|
+
|
|
482
|
+
close_issue(self.project_root, beads_issue_id)
|
|
483
|
+
return {
|
|
484
|
+
"type": "fix",
|
|
485
|
+
"success": False,
|
|
486
|
+
"error": f"Quality threshold not met after {max_iterations} iterations",
|
|
487
|
+
"review_results": review_results,
|
|
488
|
+
"iterations": iteration,
|
|
489
|
+
"committed": False,
|
|
490
|
+
"escalated": escalation_enabled and iteration >= escalation_threshold,
|
|
491
|
+
"metrics": metrics if metrics_enabled else None,
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
# Step 5: Pre-Commit Security Scan (2025 Enhancement)
|
|
495
|
+
security_scan_passed = True
|
|
496
|
+
security_scan_result = None
|
|
497
|
+
if pre_commit_security_scan and auto_commit:
|
|
498
|
+
logger.info("Running pre-commit security scan...")
|
|
499
|
+
try:
|
|
500
|
+
security_scan_tasks = [
|
|
501
|
+
{
|
|
502
|
+
"agent_id": "ops-security-1",
|
|
503
|
+
"agent": "ops",
|
|
504
|
+
"command": "security-scan",
|
|
505
|
+
"args": {
|
|
506
|
+
"target": target_file,
|
|
507
|
+
"scan_type": "code",
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
]
|
|
511
|
+
security_result = await orchestrator.execute_parallel(security_scan_tasks)
|
|
512
|
+
security_scan_result = security_result.get("results", {}).get("ops-security-1", {})
|
|
513
|
+
|
|
514
|
+
if security_scan_result.get("success"):
|
|
515
|
+
security_score = security_scan_result.get("result", {}).get("security_score", 10.0)
|
|
516
|
+
vulnerabilities = security_scan_result.get("result", {}).get("vulnerabilities", [])
|
|
517
|
+
critical_vulns = [v for v in vulnerabilities if v.get("severity") in ["CRITICAL", "HIGH"]]
|
|
518
|
+
|
|
519
|
+
if critical_vulns:
|
|
520
|
+
logger.error(f"Pre-commit security scan FAILED: {len(critical_vulns)} CRITICAL/HIGH vulnerabilities found")
|
|
521
|
+
security_scan_passed = False
|
|
522
|
+
logger.error("Blocking commit due to security vulnerabilities")
|
|
523
|
+
elif security_score < thresholds.security_min:
|
|
524
|
+
logger.warning(f"Pre-commit security scan: score {security_score:.2f} below threshold {thresholds.security_min}")
|
|
525
|
+
# Warn but don't block for non-critical issues
|
|
526
|
+
else:
|
|
527
|
+
logger.info(f"Pre-commit security scan PASSED: score {security_score:.2f}/10")
|
|
528
|
+
else:
|
|
529
|
+
logger.warning("Security scan failed, but continuing with commit")
|
|
530
|
+
except Exception as e:
|
|
531
|
+
logger.warning(f"Error during security scan: {e}, continuing with commit")
|
|
532
|
+
|
|
533
|
+
if not security_scan_passed:
|
|
534
|
+
execution_time = time.time() - start_time
|
|
535
|
+
if metrics_enabled:
|
|
536
|
+
metrics.update({
|
|
537
|
+
"iterations": iteration,
|
|
538
|
+
"success": False,
|
|
539
|
+
"execution_time": execution_time,
|
|
540
|
+
"security_scan_blocked": True,
|
|
541
|
+
})
|
|
542
|
+
close_issue(self.project_root, beads_issue_id)
|
|
543
|
+
_write_fix_handoff(
|
|
544
|
+
self.project_root, workflow_id,
|
|
545
|
+
success=False, iterations=iteration,
|
|
546
|
+
error="Pre-commit security scan failed: CRITICAL/HIGH vulnerabilities detected",
|
|
547
|
+
target_file=target_file,
|
|
548
|
+
)
|
|
549
|
+
return {
|
|
550
|
+
"type": "fix",
|
|
551
|
+
"success": False,
|
|
552
|
+
"error": "Pre-commit security scan failed: CRITICAL/HIGH vulnerabilities detected",
|
|
553
|
+
"review_results": review_results,
|
|
554
|
+
"iterations": iteration,
|
|
555
|
+
"committed": False,
|
|
556
|
+
"security_scan_result": security_scan_result,
|
|
557
|
+
"metrics": metrics if metrics_enabled else None,
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
# Step 6: Commit changes (direct or PR workflow)
|
|
561
|
+
commit_info = None
|
|
562
|
+
pr_info = None
|
|
563
|
+
if auto_commit:
|
|
564
|
+
try:
|
|
565
|
+
# Generate commit message if not provided
|
|
566
|
+
if not commit_message:
|
|
567
|
+
final_scores = review_results[-1]["result"].get("scores", {}) if review_results else {}
|
|
568
|
+
overall_score = final_scores.get("overall_score", 0)
|
|
569
|
+
commit_message = (
|
|
570
|
+
f"Fix: {bug_description}\n\n"
|
|
571
|
+
f"Quality scores: Overall {overall_score:.1f}/10\n"
|
|
572
|
+
f"Iterations: {iteration}\n"
|
|
573
|
+
f"Auto-fixed by TappsCodingAgents Bug Fix Agent"
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
# Branch Protection & PR Workflow (2025 Enhancement)
|
|
577
|
+
if commit_strategy == "pull_request":
|
|
578
|
+
# Create feature branch for PR
|
|
579
|
+
timestamp = datetime.now(UTC).strftime("%Y%m%d%H%M%S")
|
|
580
|
+
file_stem = Path(target_file).stem if target_file else "fix"
|
|
581
|
+
feature_branch = f"bugfix/{file_stem}-{timestamp}"
|
|
582
|
+
|
|
583
|
+
logger.info(f"Creating feature branch: {feature_branch}")
|
|
584
|
+
branch_result = create_and_checkout_branch(feature_branch, self.project_root)
|
|
585
|
+
|
|
586
|
+
if not branch_result["success"]:
|
|
587
|
+
raise RuntimeError(f"Failed to create branch: {branch_result.get('error')}")
|
|
588
|
+
|
|
589
|
+
# Commit to feature branch
|
|
590
|
+
commit_result = commit_changes(
|
|
591
|
+
message=commit_message,
|
|
592
|
+
files=[target_file] if target_file else None,
|
|
593
|
+
branch=feature_branch,
|
|
594
|
+
path=self.project_root,
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
if commit_result["success"]:
|
|
598
|
+
# Push feature branch
|
|
599
|
+
push_result = push_changes(feature_branch, self.project_root)
|
|
600
|
+
|
|
601
|
+
if push_result["success"]:
|
|
602
|
+
# Create PR
|
|
603
|
+
pr_title = f"Fix: {bug_description[:100]}"
|
|
604
|
+
pr_body = (
|
|
605
|
+
f"## Automated Bug Fix\n\n"
|
|
606
|
+
f"**Bug Description:** {bug_description}\n\n"
|
|
607
|
+
f"**Target File:** {target_file}\n\n"
|
|
608
|
+
f"**Quality Scores:**\n"
|
|
609
|
+
f"- Overall: {final_scores.get('overall_score', 0):.1f}/10\n"
|
|
610
|
+
f"- Security: {final_scores.get('security_score', 0):.1f}/10\n"
|
|
611
|
+
f"- Maintainability: {final_scores.get('maintainability_score', 0):.1f}/10\n\n"
|
|
612
|
+
f"**Iterations:** {iteration}\n\n"
|
|
613
|
+
f"**Auto-fixed by:** TappsCodingAgents Bug Fix Agent\n\n"
|
|
614
|
+
f"---\n\n"
|
|
615
|
+
f"*This PR was created automatically after passing quality gates.*"
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
pr_result = create_pull_request(
|
|
619
|
+
title=pr_title,
|
|
620
|
+
body=pr_body,
|
|
621
|
+
head_branch=feature_branch,
|
|
622
|
+
base_branch="main",
|
|
623
|
+
path=self.project_root,
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
if pr_result["success"]:
|
|
627
|
+
pr_info = {
|
|
628
|
+
"pr_url": pr_result.get("pr_url"),
|
|
629
|
+
"pr_number": pr_result.get("pr_number"),
|
|
630
|
+
"branch": feature_branch,
|
|
631
|
+
}
|
|
632
|
+
logger.info(f"Created pull request: {pr_result.get('pr_url', 'N/A')}")
|
|
633
|
+
|
|
634
|
+
if auto_merge_pr and not require_pr_review:
|
|
635
|
+
logger.info("Auto-merge enabled, but manual merge required (GitHub CLI limitation)")
|
|
636
|
+
else:
|
|
637
|
+
logger.warning(f"Failed to create PR: {pr_result.get('error')}")
|
|
638
|
+
# Fall back to commit info even if PR creation failed
|
|
639
|
+
commit_info = {
|
|
640
|
+
"commit_hash": commit_result["commit_hash"],
|
|
641
|
+
"branch": feature_branch,
|
|
642
|
+
"message": commit_message,
|
|
643
|
+
"pr_error": pr_result.get("error"),
|
|
644
|
+
}
|
|
645
|
+
else:
|
|
646
|
+
logger.warning(f"Failed to push branch: {push_result.get('error')}")
|
|
647
|
+
commit_info = {"error": f"Push failed: {push_result.get('error')}"}
|
|
648
|
+
else:
|
|
649
|
+
logger.warning(f"Failed to commit to branch: {commit_result.get('error')}")
|
|
650
|
+
commit_info = {"error": commit_result.get("error")}
|
|
651
|
+
|
|
652
|
+
else:
|
|
653
|
+
# Direct commit to main (original behavior)
|
|
654
|
+
commit_result = commit_changes(
|
|
655
|
+
message=commit_message,
|
|
656
|
+
files=[target_file] if target_file else None,
|
|
657
|
+
branch="main",
|
|
658
|
+
path=self.project_root,
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
if commit_result["success"]:
|
|
662
|
+
commit_info = {
|
|
663
|
+
"commit_hash": commit_result["commit_hash"],
|
|
664
|
+
"branch": commit_result["branch"],
|
|
665
|
+
"message": commit_message,
|
|
666
|
+
}
|
|
667
|
+
logger.info(
|
|
668
|
+
f"Committed changes to {commit_result['branch']}: "
|
|
669
|
+
f"{commit_result['commit_hash'][:8]}"
|
|
670
|
+
)
|
|
671
|
+
else:
|
|
672
|
+
logger.warning(
|
|
673
|
+
f"Failed to commit changes: {commit_result.get('error')}"
|
|
674
|
+
)
|
|
675
|
+
commit_info = {
|
|
676
|
+
"error": commit_result.get("error"),
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
except Exception as e:
|
|
680
|
+
logger.error(f"Error during commit: {e}", exc_info=True)
|
|
681
|
+
commit_info = {"error": str(e)}
|
|
682
|
+
|
|
683
|
+
# Update metrics for successful execution
|
|
684
|
+
execution_time = time.time() - start_time
|
|
685
|
+
if metrics_enabled:
|
|
686
|
+
final_scores = review_results[-1]["result"].get("scores", {}) if review_results else {}
|
|
687
|
+
metrics.update({
|
|
688
|
+
"iterations": iteration,
|
|
689
|
+
"success": True,
|
|
690
|
+
"execution_time": execution_time,
|
|
691
|
+
"final_quality_scores": final_scores,
|
|
692
|
+
"committed": commit_info is not None and "error" not in commit_info,
|
|
693
|
+
"security_scan_performed": pre_commit_security_scan and auto_commit,
|
|
694
|
+
})
|
|
695
|
+
logger.info(f"Execution metrics: {metrics}")
|
|
696
|
+
|
|
697
|
+
close_issue(self.project_root, beads_issue_id)
|
|
698
|
+
_write_fix_handoff(
|
|
699
|
+
self.project_root, workflow_id,
|
|
700
|
+
success=True, iterations=iteration,
|
|
701
|
+
target_file=target_file,
|
|
702
|
+
)
|
|
703
|
+
return {
|
|
704
|
+
"type": "fix",
|
|
705
|
+
"success": True,
|
|
706
|
+
"agents_executed": ["debugger", "implementer", "tester", "reviewer"] + (["ops"] if pre_commit_security_scan and auto_commit else []),
|
|
707
|
+
"iterations": iteration,
|
|
708
|
+
"review_results": review_results,
|
|
709
|
+
"quality_passed": True,
|
|
710
|
+
"committed": commit_info is not None and "error" not in commit_info,
|
|
711
|
+
"commit_info": commit_info,
|
|
712
|
+
"pr_info": pr_info,
|
|
713
|
+
"commit_strategy": commit_strategy,
|
|
714
|
+
"security_scan_result": security_scan_result if pre_commit_security_scan and auto_commit else None,
|
|
715
|
+
"metrics": metrics if metrics_enabled else None,
|
|
716
|
+
"summary": {
|
|
717
|
+
"bug_description": bug_description,
|
|
718
|
+
"target_file": target_file,
|
|
719
|
+
"iterations": iteration,
|
|
720
|
+
"final_quality": review_results[-1]["result"].get("scores", {}) if review_results else {},
|
|
721
|
+
"execution_time": execution_time,
|
|
722
|
+
},
|
|
723
|
+
}
|