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,644 +1,644 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Visual Feedback System for UI/UX Iterative Refinement
|
|
3
|
-
|
|
4
|
-
Provides visual analysis, comparison, and pattern learning for UI generation.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import logging
|
|
8
|
-
from dataclasses import asdict, dataclass, field
|
|
9
|
-
from datetime import UTC, datetime
|
|
10
|
-
from enum import Enum
|
|
11
|
-
from typing import Any
|
|
12
|
-
|
|
13
|
-
from .hardware_profiler import HardwareProfile, HardwareProfiler
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class RenderingMode(Enum):
|
|
19
|
-
"""Rendering mode based on hardware capabilities."""
|
|
20
|
-
|
|
21
|
-
LIGHTWEIGHT = "lightweight" # Minimal analysis for NUC
|
|
22
|
-
STANDARD = "standard" # Balanced analysis for development machines
|
|
23
|
-
FULL = "full" # Full analysis for workstations
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class VisualElementType(Enum):
|
|
27
|
-
"""Types of visual elements."""
|
|
28
|
-
|
|
29
|
-
BUTTON = "button"
|
|
30
|
-
TEXT = "text"
|
|
31
|
-
IMAGE = "image"
|
|
32
|
-
INPUT = "input"
|
|
33
|
-
CONTAINER = "container"
|
|
34
|
-
NAVIGATION = "navigation"
|
|
35
|
-
HEADER = "header"
|
|
36
|
-
FOOTER = "footer"
|
|
37
|
-
SIDEBAR = "sidebar"
|
|
38
|
-
MODAL = "modal"
|
|
39
|
-
CARD = "card"
|
|
40
|
-
LIST = "list"
|
|
41
|
-
GRID = "grid"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@dataclass
|
|
45
|
-
class VisualElement:
|
|
46
|
-
"""Represents a visual element in the UI."""
|
|
47
|
-
|
|
48
|
-
element_type: VisualElementType
|
|
49
|
-
position: tuple[float, float] # (x, y)
|
|
50
|
-
size: tuple[float, float] # (width, height)
|
|
51
|
-
text: str | None = None
|
|
52
|
-
color: str | None = None
|
|
53
|
-
background_color: str | None = None
|
|
54
|
-
font_size: float | None = None
|
|
55
|
-
z_index: int | None = None
|
|
56
|
-
metadata: dict[str, Any] = field(default_factory=dict)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@dataclass
|
|
60
|
-
class LayoutMetrics:
|
|
61
|
-
"""Layout analysis metrics."""
|
|
62
|
-
|
|
63
|
-
spacing_consistency: float # 0.0 to 1.0
|
|
64
|
-
alignment_score: float # 0.0 to 1.0
|
|
65
|
-
visual_hierarchy: float # 0.0 to 1.0
|
|
66
|
-
whitespace_balance: float # 0.0 to 1.0
|
|
67
|
-
grid_consistency: float # 0.0 to 1.0
|
|
68
|
-
issues: list[str] = field(default_factory=list)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@dataclass
|
|
72
|
-
class AccessibilityMetrics:
|
|
73
|
-
"""Accessibility analysis metrics."""
|
|
74
|
-
|
|
75
|
-
color_contrast_score: float # 0.0 to 1.0
|
|
76
|
-
keyboard_navigable: bool
|
|
77
|
-
screen_reader_compatible: bool
|
|
78
|
-
aria_labels_present: bool
|
|
79
|
-
focus_indicators_present: bool
|
|
80
|
-
issues: list[str] = field(default_factory=list)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
@dataclass
|
|
84
|
-
class VisualFeedback:
|
|
85
|
-
"""Visual feedback data structure."""
|
|
86
|
-
|
|
87
|
-
timestamp: datetime
|
|
88
|
-
iteration: int
|
|
89
|
-
screenshot_path: str | None = None
|
|
90
|
-
layout_metrics: LayoutMetrics | None = None
|
|
91
|
-
accessibility_metrics: AccessibilityMetrics | None = None
|
|
92
|
-
visual_elements: list[VisualElement] = field(default_factory=list)
|
|
93
|
-
user_interactions: list[dict[str, Any]] = field(default_factory=list)
|
|
94
|
-
quality_score: float = 0.0 # 0.0 to 1.0
|
|
95
|
-
issues: list[str] = field(default_factory=list)
|
|
96
|
-
suggestions: list[str] = field(default_factory=list)
|
|
97
|
-
metadata: dict[str, Any] = field(default_factory=dict)
|
|
98
|
-
|
|
99
|
-
def to_dict(self) -> dict[str, Any]:
|
|
100
|
-
"""Convert to dictionary for serialization."""
|
|
101
|
-
data = asdict(self)
|
|
102
|
-
data["timestamp"] = self.timestamp.isoformat()
|
|
103
|
-
data["visual_elements"] = [
|
|
104
|
-
{**asdict(elem), "element_type": elem.element_type.value}
|
|
105
|
-
for elem in self.visual_elements
|
|
106
|
-
]
|
|
107
|
-
return data
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
class VisualFeedbackCollector:
|
|
111
|
-
"""Collects visual feedback from generated UIs."""
|
|
112
|
-
|
|
113
|
-
def __init__(self, hardware_profile: HardwareProfile | None = None):
|
|
114
|
-
"""
|
|
115
|
-
Initialize visual feedback collector.
|
|
116
|
-
|
|
117
|
-
Args:
|
|
118
|
-
hardware_profile: Hardware profile for optimization
|
|
119
|
-
"""
|
|
120
|
-
self.hardware_profile = hardware_profile or HardwareProfiler().detect_profile()
|
|
121
|
-
self.rendering_mode = self._get_rendering_mode()
|
|
122
|
-
self.feedback_history: list[VisualFeedback] = []
|
|
123
|
-
|
|
124
|
-
def _get_rendering_mode(self) -> RenderingMode:
|
|
125
|
-
"""Rendering mode. Workstation-like default (hardware taxonomy removed)."""
|
|
126
|
-
return RenderingMode.FULL
|
|
127
|
-
|
|
128
|
-
def collect_feedback(
|
|
129
|
-
self,
|
|
130
|
-
iteration: int,
|
|
131
|
-
screenshot_path: str | None = None,
|
|
132
|
-
visual_elements: list[VisualElement] | None = None,
|
|
133
|
-
user_interactions: list[dict[str, Any]] | None = None,
|
|
134
|
-
metadata: dict[str, Any] | None = None,
|
|
135
|
-
) -> VisualFeedback:
|
|
136
|
-
"""
|
|
137
|
-
Collect visual feedback for an iteration.
|
|
138
|
-
|
|
139
|
-
Args:
|
|
140
|
-
iteration: Iteration number
|
|
141
|
-
screenshot_path: Path to screenshot
|
|
142
|
-
visual_elements: List of visual elements
|
|
143
|
-
user_interactions: List of user interactions
|
|
144
|
-
metadata: Additional metadata
|
|
145
|
-
|
|
146
|
-
Returns:
|
|
147
|
-
VisualFeedback object
|
|
148
|
-
"""
|
|
149
|
-
feedback = VisualFeedback(
|
|
150
|
-
timestamp=datetime.now(UTC),
|
|
151
|
-
iteration=iteration,
|
|
152
|
-
screenshot_path=screenshot_path,
|
|
153
|
-
visual_elements=visual_elements or [],
|
|
154
|
-
user_interactions=user_interactions or [],
|
|
155
|
-
metadata=metadata or {},
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
self.feedback_history.append(feedback)
|
|
159
|
-
return feedback
|
|
160
|
-
|
|
161
|
-
def get_feedback_history(self, limit: int | None = None) -> list[VisualFeedback]:
|
|
162
|
-
"""
|
|
163
|
-
Get feedback history.
|
|
164
|
-
|
|
165
|
-
Args:
|
|
166
|
-
limit: Maximum number of feedback items to return
|
|
167
|
-
|
|
168
|
-
Returns:
|
|
169
|
-
List of VisualFeedback objects
|
|
170
|
-
"""
|
|
171
|
-
if limit:
|
|
172
|
-
return self.feedback_history[-limit:]
|
|
173
|
-
return self.feedback_history.copy()
|
|
174
|
-
|
|
175
|
-
def clear_history(self):
|
|
176
|
-
"""Clear feedback history."""
|
|
177
|
-
self.feedback_history.clear()
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
class VisualAnalyzer:
|
|
181
|
-
"""Analyzes visual elements and layout."""
|
|
182
|
-
|
|
183
|
-
def __init__(self, hardware_profile: HardwareProfile | None = None):
|
|
184
|
-
"""
|
|
185
|
-
Initialize visual analyzer.
|
|
186
|
-
|
|
187
|
-
Args:
|
|
188
|
-
hardware_profile: Hardware profile for optimization
|
|
189
|
-
"""
|
|
190
|
-
self.hardware_profile = hardware_profile or HardwareProfiler().detect_profile()
|
|
191
|
-
self.rendering_mode = self._get_rendering_mode()
|
|
192
|
-
|
|
193
|
-
def _get_rendering_mode(self) -> RenderingMode:
|
|
194
|
-
"""Rendering mode. Workstation-like default (hardware taxonomy removed)."""
|
|
195
|
-
return RenderingMode.FULL
|
|
196
|
-
|
|
197
|
-
def analyze_layout(
|
|
198
|
-
self,
|
|
199
|
-
visual_elements: list[VisualElement],
|
|
200
|
-
design_spec: dict[str, Any] | None = None,
|
|
201
|
-
) -> LayoutMetrics:
|
|
202
|
-
"""
|
|
203
|
-
Analyze layout quality.
|
|
204
|
-
|
|
205
|
-
Args:
|
|
206
|
-
visual_elements: List of visual elements
|
|
207
|
-
design_spec: Optional design specification
|
|
208
|
-
|
|
209
|
-
Returns:
|
|
210
|
-
LayoutMetrics object
|
|
211
|
-
"""
|
|
212
|
-
if not visual_elements:
|
|
213
|
-
return LayoutMetrics(
|
|
214
|
-
spacing_consistency=0.0,
|
|
215
|
-
alignment_score=0.0,
|
|
216
|
-
visual_hierarchy=0.0,
|
|
217
|
-
whitespace_balance=0.0,
|
|
218
|
-
grid_consistency=0.0,
|
|
219
|
-
issues=["No visual elements found"],
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
# Lightweight mode: Basic analysis only
|
|
223
|
-
if self.rendering_mode == RenderingMode.LIGHTWEIGHT:
|
|
224
|
-
return self._analyze_layout_lightweight(visual_elements)
|
|
225
|
-
|
|
226
|
-
# Standard/Full mode: Detailed analysis
|
|
227
|
-
return self._analyze_layout_detailed(visual_elements, design_spec)
|
|
228
|
-
|
|
229
|
-
def _analyze_layout_lightweight(
|
|
230
|
-
self, elements: list[VisualElement]
|
|
231
|
-
) -> LayoutMetrics:
|
|
232
|
-
"""Lightweight layout analysis for NUC devices."""
|
|
233
|
-
if len(elements) < 2:
|
|
234
|
-
return LayoutMetrics(
|
|
235
|
-
spacing_consistency=0.5,
|
|
236
|
-
alignment_score=0.5,
|
|
237
|
-
visual_hierarchy=0.5,
|
|
238
|
-
whitespace_balance=0.5,
|
|
239
|
-
grid_consistency=0.5,
|
|
240
|
-
issues=["Insufficient elements for analysis"],
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
# Basic spacing check
|
|
244
|
-
spacing_scores = []
|
|
245
|
-
for i in range(len(elements) - 1):
|
|
246
|
-
elem1 = elements[i]
|
|
247
|
-
elem2 = elements[i + 1]
|
|
248
|
-
distance = abs(elem1.position[1] - elem2.position[1])
|
|
249
|
-
spacing_scores.append(1.0 if distance > 0 else 0.0)
|
|
250
|
-
|
|
251
|
-
spacing_consistency = (
|
|
252
|
-
sum(spacing_scores) / len(spacing_scores) if spacing_scores else 0.5
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
return LayoutMetrics(
|
|
256
|
-
spacing_consistency=spacing_consistency,
|
|
257
|
-
alignment_score=0.7, # Simplified
|
|
258
|
-
visual_hierarchy=0.6, # Simplified
|
|
259
|
-
whitespace_balance=0.6, # Simplified
|
|
260
|
-
grid_consistency=0.7, # Simplified
|
|
261
|
-
issues=[],
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
def _analyze_layout_detailed(
|
|
265
|
-
self, elements: list[VisualElement], design_spec: dict[str, Any] | None
|
|
266
|
-
) -> LayoutMetrics:
|
|
267
|
-
"""Detailed layout analysis for workstations."""
|
|
268
|
-
issues = []
|
|
269
|
-
|
|
270
|
-
# Spacing consistency
|
|
271
|
-
spacing_scores = []
|
|
272
|
-
for i in range(len(elements) - 1):
|
|
273
|
-
elem1 = elements[i]
|
|
274
|
-
elem2 = elements[i + 1]
|
|
275
|
-
if abs(elem1.position[0] - elem2.position[0]) < 10: # Same column
|
|
276
|
-
distance = abs(elem1.position[1] + elem1.size[1] - elem2.position[1])
|
|
277
|
-
if distance < 5:
|
|
278
|
-
spacing_scores.append(0.0)
|
|
279
|
-
issues.append(f"Elements {i} and {i+1} are too close")
|
|
280
|
-
elif distance > 100:
|
|
281
|
-
spacing_scores.append(0.5)
|
|
282
|
-
issues.append(f"Elements {i} and {i+1} have excessive spacing")
|
|
283
|
-
else:
|
|
284
|
-
spacing_scores.append(1.0)
|
|
285
|
-
|
|
286
|
-
spacing_consistency = (
|
|
287
|
-
sum(spacing_scores) / len(spacing_scores) if spacing_scores else 0.7
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
# Alignment score
|
|
291
|
-
x_positions = [elem.position[0] for elem in elements]
|
|
292
|
-
y_positions = [elem.position[1] for elem in elements]
|
|
293
|
-
|
|
294
|
-
x_alignment = (
|
|
295
|
-
1.0 - (max(x_positions) - min(x_positions)) / 1000.0 if x_positions else 0.5
|
|
296
|
-
)
|
|
297
|
-
y_alignment = (
|
|
298
|
-
1.0 - (max(y_positions) - min(y_positions)) / 1000.0 if y_positions else 0.5
|
|
299
|
-
)
|
|
300
|
-
alignment_score = (x_alignment + y_alignment) / 2.0
|
|
301
|
-
|
|
302
|
-
# Visual hierarchy (based on size and z-index)
|
|
303
|
-
sizes = [elem.size[0] * elem.size[1] for elem in elements]
|
|
304
|
-
if sizes:
|
|
305
|
-
max_size = max(sizes)
|
|
306
|
-
hierarchy_scores = [size / max_size for size in sizes]
|
|
307
|
-
visual_hierarchy = sum(hierarchy_scores) / len(hierarchy_scores)
|
|
308
|
-
else:
|
|
309
|
-
visual_hierarchy = 0.5
|
|
310
|
-
|
|
311
|
-
# Whitespace balance (simplified)
|
|
312
|
-
total_area = sum(elem.size[0] * elem.size[1] for elem in elements)
|
|
313
|
-
whitespace_balance = min(1.0, total_area / 100000.0) # Simplified calculation
|
|
314
|
-
|
|
315
|
-
# Grid consistency
|
|
316
|
-
grid_scores = []
|
|
317
|
-
for i in range(len(elements) - 1):
|
|
318
|
-
for j in range(i + 1, len(elements)):
|
|
319
|
-
elem1 = elements[i]
|
|
320
|
-
elem2 = elements[j]
|
|
321
|
-
# Check if aligned on grid
|
|
322
|
-
x_diff = abs(elem1.position[0] - elem2.position[0])
|
|
323
|
-
y_diff = abs(elem1.position[1] - elem2.position[1])
|
|
324
|
-
if x_diff < 10 or y_diff < 10:
|
|
325
|
-
grid_scores.append(1.0)
|
|
326
|
-
else:
|
|
327
|
-
grid_scores.append(0.5)
|
|
328
|
-
|
|
329
|
-
grid_consistency = sum(grid_scores) / len(grid_scores) if grid_scores else 0.7
|
|
330
|
-
|
|
331
|
-
return LayoutMetrics(
|
|
332
|
-
spacing_consistency=max(0.0, min(1.0, spacing_consistency)),
|
|
333
|
-
alignment_score=max(0.0, min(1.0, alignment_score)),
|
|
334
|
-
visual_hierarchy=max(0.0, min(1.0, visual_hierarchy)),
|
|
335
|
-
whitespace_balance=max(0.0, min(1.0, whitespace_balance)),
|
|
336
|
-
grid_consistency=max(0.0, min(1.0, grid_consistency)),
|
|
337
|
-
issues=issues[:10], # Limit issues
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
def analyze_accessibility(
|
|
341
|
-
self, visual_elements: list[VisualElement], html_content: str | None = None
|
|
342
|
-
) -> AccessibilityMetrics:
|
|
343
|
-
"""
|
|
344
|
-
Analyze accessibility features.
|
|
345
|
-
|
|
346
|
-
Args:
|
|
347
|
-
visual_elements: List of visual elements
|
|
348
|
-
html_content: Optional HTML content for deeper analysis
|
|
349
|
-
|
|
350
|
-
Returns:
|
|
351
|
-
AccessibilityMetrics object
|
|
352
|
-
"""
|
|
353
|
-
issues = []
|
|
354
|
-
|
|
355
|
-
# Lightweight mode: Basic checks only
|
|
356
|
-
if self.rendering_mode == RenderingMode.LIGHTWEIGHT:
|
|
357
|
-
return AccessibilityMetrics(
|
|
358
|
-
color_contrast_score=0.7, # Simplified
|
|
359
|
-
keyboard_navigable=True, # Assume yes
|
|
360
|
-
screen_reader_compatible=True, # Assume yes
|
|
361
|
-
aria_labels_present=False, # Unknown
|
|
362
|
-
focus_indicators_present=False, # Unknown
|
|
363
|
-
issues=["Lightweight mode: Limited accessibility analysis"],
|
|
364
|
-
)
|
|
365
|
-
|
|
366
|
-
# Standard/Full mode: Detailed analysis
|
|
367
|
-
color_contrast_score = 0.8 # Simplified - would use actual contrast calculation
|
|
368
|
-
keyboard_navigable = True
|
|
369
|
-
screen_reader_compatible = True
|
|
370
|
-
|
|
371
|
-
# Check for ARIA labels in HTML
|
|
372
|
-
aria_labels_present = False
|
|
373
|
-
if html_content:
|
|
374
|
-
aria_labels_present = (
|
|
375
|
-
"aria-label" in html_content or "aria-labelledby" in html_content
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
# Check for focus indicators
|
|
379
|
-
focus_indicators_present = False
|
|
380
|
-
if html_content:
|
|
381
|
-
focus_indicators_present = (
|
|
382
|
-
":focus" in html_content or "focus-visible" in html_content
|
|
383
|
-
)
|
|
384
|
-
|
|
385
|
-
if not aria_labels_present:
|
|
386
|
-
issues.append("Missing ARIA labels for screen readers")
|
|
387
|
-
if not focus_indicators_present:
|
|
388
|
-
issues.append("Missing focus indicators for keyboard navigation")
|
|
389
|
-
|
|
390
|
-
return AccessibilityMetrics(
|
|
391
|
-
color_contrast_score=max(0.0, min(1.0, color_contrast_score)),
|
|
392
|
-
keyboard_navigable=keyboard_navigable,
|
|
393
|
-
screen_reader_compatible=screen_reader_compatible,
|
|
394
|
-
aria_labels_present=aria_labels_present,
|
|
395
|
-
focus_indicators_present=focus_indicators_present,
|
|
396
|
-
issues=issues,
|
|
397
|
-
)
|
|
398
|
-
|
|
399
|
-
def calculate_quality_score(
|
|
400
|
-
self,
|
|
401
|
-
layout_metrics: LayoutMetrics,
|
|
402
|
-
accessibility_metrics: AccessibilityMetrics,
|
|
403
|
-
weights: dict[str, float] | None = None,
|
|
404
|
-
) -> float:
|
|
405
|
-
"""
|
|
406
|
-
Calculate overall quality score.
|
|
407
|
-
|
|
408
|
-
Args:
|
|
409
|
-
layout_metrics: Layout analysis metrics
|
|
410
|
-
accessibility_metrics: Accessibility analysis metrics
|
|
411
|
-
weights: Optional weights for different metrics
|
|
412
|
-
|
|
413
|
-
Returns:
|
|
414
|
-
Quality score from 0.0 to 1.0
|
|
415
|
-
"""
|
|
416
|
-
if weights is None:
|
|
417
|
-
weights = {"layout": 0.6, "accessibility": 0.4}
|
|
418
|
-
|
|
419
|
-
layout_score = (
|
|
420
|
-
layout_metrics.spacing_consistency * 0.2
|
|
421
|
-
+ layout_metrics.alignment_score * 0.2
|
|
422
|
-
+ layout_metrics.visual_hierarchy * 0.2
|
|
423
|
-
+ layout_metrics.whitespace_balance * 0.2
|
|
424
|
-
+ layout_metrics.grid_consistency * 0.2
|
|
425
|
-
)
|
|
426
|
-
|
|
427
|
-
accessibility_score = (
|
|
428
|
-
accessibility_metrics.color_contrast_score * 0.3
|
|
429
|
-
+ (1.0 if accessibility_metrics.keyboard_navigable else 0.0) * 0.2
|
|
430
|
-
+ (1.0 if accessibility_metrics.screen_reader_compatible else 0.0) * 0.2
|
|
431
|
-
+ (1.0 if accessibility_metrics.aria_labels_present else 0.0) * 0.15
|
|
432
|
-
+ (1.0 if accessibility_metrics.focus_indicators_present else 0.0) * 0.15
|
|
433
|
-
)
|
|
434
|
-
|
|
435
|
-
quality_score = layout_score * weights.get(
|
|
436
|
-
"layout", 0.6
|
|
437
|
-
) + accessibility_score * weights.get("accessibility", 0.4)
|
|
438
|
-
|
|
439
|
-
return max(0.0, min(1.0, quality_score))
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
class UIComparator:
|
|
443
|
-
"""Compares UI iterations for improvements."""
|
|
444
|
-
|
|
445
|
-
def __init__(self):
|
|
446
|
-
"""Initialize UI comparator."""
|
|
447
|
-
pass
|
|
448
|
-
|
|
449
|
-
def compare_iterations(
|
|
450
|
-
self, previous: VisualFeedback, current: VisualFeedback
|
|
451
|
-
) -> dict[str, Any]:
|
|
452
|
-
"""
|
|
453
|
-
Compare two iterations to identify improvements.
|
|
454
|
-
|
|
455
|
-
Args:
|
|
456
|
-
previous: Previous iteration feedback
|
|
457
|
-
current: Current iteration feedback
|
|
458
|
-
|
|
459
|
-
Returns:
|
|
460
|
-
Comparison results
|
|
461
|
-
"""
|
|
462
|
-
improvements = []
|
|
463
|
-
regressions = []
|
|
464
|
-
unchanged = []
|
|
465
|
-
|
|
466
|
-
# Compare quality scores
|
|
467
|
-
if current.quality_score > previous.quality_score:
|
|
468
|
-
improvements.append(
|
|
469
|
-
f"Quality score improved from {previous.quality_score:.2f} to {current.quality_score:.2f}"
|
|
470
|
-
)
|
|
471
|
-
elif current.quality_score < previous.quality_score:
|
|
472
|
-
regressions.append(
|
|
473
|
-
f"Quality score decreased from {previous.quality_score:.2f} to {current.quality_score:.2f}"
|
|
474
|
-
)
|
|
475
|
-
else:
|
|
476
|
-
unchanged.append("Quality score unchanged")
|
|
477
|
-
|
|
478
|
-
# Compare layout metrics
|
|
479
|
-
if previous.layout_metrics and current.layout_metrics:
|
|
480
|
-
prev_layout = previous.layout_metrics
|
|
481
|
-
curr_layout = current.layout_metrics
|
|
482
|
-
|
|
483
|
-
if curr_layout.spacing_consistency > prev_layout.spacing_consistency:
|
|
484
|
-
improvements.append("Spacing consistency improved")
|
|
485
|
-
elif curr_layout.spacing_consistency < prev_layout.spacing_consistency:
|
|
486
|
-
regressions.append("Spacing consistency decreased")
|
|
487
|
-
|
|
488
|
-
if curr_layout.alignment_score > prev_layout.alignment_score:
|
|
489
|
-
improvements.append("Alignment score improved")
|
|
490
|
-
elif curr_layout.alignment_score < prev_layout.alignment_score:
|
|
491
|
-
regressions.append("Alignment score decreased")
|
|
492
|
-
|
|
493
|
-
if curr_layout.visual_hierarchy > prev_layout.visual_hierarchy:
|
|
494
|
-
improvements.append("Visual hierarchy improved")
|
|
495
|
-
elif curr_layout.visual_hierarchy < prev_layout.visual_hierarchy:
|
|
496
|
-
regressions.append("Visual hierarchy decreased")
|
|
497
|
-
|
|
498
|
-
# Compare accessibility metrics
|
|
499
|
-
if previous.accessibility_metrics and current.accessibility_metrics:
|
|
500
|
-
prev_acc = previous.accessibility_metrics
|
|
501
|
-
curr_acc = current.accessibility_metrics
|
|
502
|
-
|
|
503
|
-
if curr_acc.color_contrast_score > prev_acc.color_contrast_score:
|
|
504
|
-
improvements.append("Color contrast improved")
|
|
505
|
-
elif curr_acc.color_contrast_score < prev_acc.color_contrast_score:
|
|
506
|
-
regressions.append("Color contrast decreased")
|
|
507
|
-
|
|
508
|
-
if curr_acc.keyboard_navigable and not prev_acc.keyboard_navigable:
|
|
509
|
-
improvements.append("Keyboard navigation added")
|
|
510
|
-
elif not curr_acc.keyboard_navigable and prev_acc.keyboard_navigable:
|
|
511
|
-
regressions.append("Keyboard navigation removed")
|
|
512
|
-
|
|
513
|
-
# Compare issues
|
|
514
|
-
if len(current.issues) < len(previous.issues):
|
|
515
|
-
improvements.append(
|
|
516
|
-
f"Reduced issues from {len(previous.issues)} to {len(current.issues)}"
|
|
517
|
-
)
|
|
518
|
-
elif len(current.issues) > len(previous.issues):
|
|
519
|
-
regressions.append(
|
|
520
|
-
f"Increased issues from {len(previous.issues)} to {len(current.issues)}"
|
|
521
|
-
)
|
|
522
|
-
|
|
523
|
-
return {
|
|
524
|
-
"improvements": improvements,
|
|
525
|
-
"regressions": regressions,
|
|
526
|
-
"unchanged": unchanged,
|
|
527
|
-
"quality_delta": current.quality_score - previous.quality_score,
|
|
528
|
-
"iteration_delta": current.iteration - previous.iteration,
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
def get_improvement_trend(
|
|
532
|
-
self, feedback_history: list[VisualFeedback]
|
|
533
|
-
) -> dict[str, Any]:
|
|
534
|
-
"""
|
|
535
|
-
Analyze improvement trend across multiple iterations.
|
|
536
|
-
|
|
537
|
-
Args:
|
|
538
|
-
feedback_history: List of feedback items
|
|
539
|
-
|
|
540
|
-
Returns:
|
|
541
|
-
Trend analysis
|
|
542
|
-
"""
|
|
543
|
-
if len(feedback_history) < 2:
|
|
544
|
-
return {
|
|
545
|
-
"trend": "insufficient_data",
|
|
546
|
-
"average_improvement": 0.0,
|
|
547
|
-
"iterations": len(feedback_history),
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
quality_scores = [fb.quality_score for fb in feedback_history]
|
|
551
|
-
improvements = []
|
|
552
|
-
|
|
553
|
-
for i in range(1, len(quality_scores)):
|
|
554
|
-
delta = quality_scores[i] - quality_scores[i - 1]
|
|
555
|
-
improvements.append(delta)
|
|
556
|
-
|
|
557
|
-
average_improvement = (
|
|
558
|
-
sum(improvements) / len(improvements) if improvements else 0.0
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
if average_improvement > 0.05:
|
|
562
|
-
trend = "improving"
|
|
563
|
-
elif average_improvement < -0.05:
|
|
564
|
-
trend = "declining"
|
|
565
|
-
else:
|
|
566
|
-
trend = "stable"
|
|
567
|
-
|
|
568
|
-
return {
|
|
569
|
-
"trend": trend,
|
|
570
|
-
"average_improvement": average_improvement,
|
|
571
|
-
"iterations": len(feedback_history),
|
|
572
|
-
"quality_scores": quality_scores,
|
|
573
|
-
"final_quality": quality_scores[-1] if quality_scores else 0.0,
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
class VisualPatternLearner:
|
|
578
|
-
"""Learns visual patterns from feedback."""
|
|
579
|
-
|
|
580
|
-
def __init__(self):
|
|
581
|
-
"""Initialize visual pattern learner."""
|
|
582
|
-
self.patterns: dict[str, Any] = {}
|
|
583
|
-
self.feedback_history: list[VisualFeedback] = []
|
|
584
|
-
|
|
585
|
-
def learn_from_feedback(self, feedback: VisualFeedback):
|
|
586
|
-
"""
|
|
587
|
-
Learn patterns from feedback.
|
|
588
|
-
|
|
589
|
-
Args:
|
|
590
|
-
feedback: Visual feedback to learn from
|
|
591
|
-
"""
|
|
592
|
-
self.feedback_history.append(feedback)
|
|
593
|
-
|
|
594
|
-
# Extract patterns from layout metrics
|
|
595
|
-
if feedback.layout_metrics:
|
|
596
|
-
layout = feedback.layout_metrics
|
|
597
|
-
if layout.spacing_consistency > 0.8:
|
|
598
|
-
self.patterns["high_spacing_consistency"] = (
|
|
599
|
-
self.patterns.get("high_spacing_consistency", 0) + 1
|
|
600
|
-
)
|
|
601
|
-
if layout.alignment_score > 0.8:
|
|
602
|
-
self.patterns["high_alignment"] = (
|
|
603
|
-
self.patterns.get("high_alignment", 0) + 1
|
|
604
|
-
)
|
|
605
|
-
|
|
606
|
-
# Extract patterns from accessibility
|
|
607
|
-
if feedback.accessibility_metrics:
|
|
608
|
-
acc = feedback.accessibility_metrics
|
|
609
|
-
if acc.color_contrast_score > 0.8:
|
|
610
|
-
self.patterns["good_contrast"] = (
|
|
611
|
-
self.patterns.get("good_contrast", 0) + 1
|
|
612
|
-
)
|
|
613
|
-
if acc.keyboard_navigable:
|
|
614
|
-
self.patterns["keyboard_navigable"] = (
|
|
615
|
-
self.patterns.get("keyboard_navigable", 0) + 1
|
|
616
|
-
)
|
|
617
|
-
|
|
618
|
-
def get_recommendations(self) -> list[str]:
|
|
619
|
-
"""
|
|
620
|
-
Get recommendations based on learned patterns.
|
|
621
|
-
|
|
622
|
-
Returns:
|
|
623
|
-
List of recommendations
|
|
624
|
-
"""
|
|
625
|
-
recommendations = []
|
|
626
|
-
|
|
627
|
-
if self.patterns.get("high_spacing_consistency", 0) > 5:
|
|
628
|
-
recommendations.append("Maintain consistent spacing patterns")
|
|
629
|
-
|
|
630
|
-
if self.patterns.get("high_alignment", 0) > 5:
|
|
631
|
-
recommendations.append("Continue using aligned layouts")
|
|
632
|
-
|
|
633
|
-
if self.patterns.get("good_contrast", 0) > 5:
|
|
634
|
-
recommendations.append("Maintain good color contrast")
|
|
635
|
-
|
|
636
|
-
if self.patterns.get("keyboard_navigable", 0) < 3:
|
|
637
|
-
recommendations.append("Improve keyboard navigation support")
|
|
638
|
-
|
|
639
|
-
return recommendations
|
|
640
|
-
|
|
641
|
-
def clear_patterns(self):
|
|
642
|
-
"""Clear learned patterns."""
|
|
643
|
-
self.patterns.clear()
|
|
644
|
-
self.feedback_history.clear()
|
|
1
|
+
"""
|
|
2
|
+
Visual Feedback System for UI/UX Iterative Refinement
|
|
3
|
+
|
|
4
|
+
Provides visual analysis, comparison, and pattern learning for UI generation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from dataclasses import asdict, dataclass, field
|
|
9
|
+
from datetime import UTC, datetime
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from .hardware_profiler import HardwareProfile, HardwareProfiler
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class RenderingMode(Enum):
|
|
19
|
+
"""Rendering mode based on hardware capabilities."""
|
|
20
|
+
|
|
21
|
+
LIGHTWEIGHT = "lightweight" # Minimal analysis for NUC
|
|
22
|
+
STANDARD = "standard" # Balanced analysis for development machines
|
|
23
|
+
FULL = "full" # Full analysis for workstations
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class VisualElementType(Enum):
|
|
27
|
+
"""Types of visual elements."""
|
|
28
|
+
|
|
29
|
+
BUTTON = "button"
|
|
30
|
+
TEXT = "text"
|
|
31
|
+
IMAGE = "image"
|
|
32
|
+
INPUT = "input"
|
|
33
|
+
CONTAINER = "container"
|
|
34
|
+
NAVIGATION = "navigation"
|
|
35
|
+
HEADER = "header"
|
|
36
|
+
FOOTER = "footer"
|
|
37
|
+
SIDEBAR = "sidebar"
|
|
38
|
+
MODAL = "modal"
|
|
39
|
+
CARD = "card"
|
|
40
|
+
LIST = "list"
|
|
41
|
+
GRID = "grid"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class VisualElement:
|
|
46
|
+
"""Represents a visual element in the UI."""
|
|
47
|
+
|
|
48
|
+
element_type: VisualElementType
|
|
49
|
+
position: tuple[float, float] # (x, y)
|
|
50
|
+
size: tuple[float, float] # (width, height)
|
|
51
|
+
text: str | None = None
|
|
52
|
+
color: str | None = None
|
|
53
|
+
background_color: str | None = None
|
|
54
|
+
font_size: float | None = None
|
|
55
|
+
z_index: int | None = None
|
|
56
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class LayoutMetrics:
|
|
61
|
+
"""Layout analysis metrics."""
|
|
62
|
+
|
|
63
|
+
spacing_consistency: float # 0.0 to 1.0
|
|
64
|
+
alignment_score: float # 0.0 to 1.0
|
|
65
|
+
visual_hierarchy: float # 0.0 to 1.0
|
|
66
|
+
whitespace_balance: float # 0.0 to 1.0
|
|
67
|
+
grid_consistency: float # 0.0 to 1.0
|
|
68
|
+
issues: list[str] = field(default_factory=list)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class AccessibilityMetrics:
|
|
73
|
+
"""Accessibility analysis metrics."""
|
|
74
|
+
|
|
75
|
+
color_contrast_score: float # 0.0 to 1.0
|
|
76
|
+
keyboard_navigable: bool
|
|
77
|
+
screen_reader_compatible: bool
|
|
78
|
+
aria_labels_present: bool
|
|
79
|
+
focus_indicators_present: bool
|
|
80
|
+
issues: list[str] = field(default_factory=list)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class VisualFeedback:
|
|
85
|
+
"""Visual feedback data structure."""
|
|
86
|
+
|
|
87
|
+
timestamp: datetime
|
|
88
|
+
iteration: int
|
|
89
|
+
screenshot_path: str | None = None
|
|
90
|
+
layout_metrics: LayoutMetrics | None = None
|
|
91
|
+
accessibility_metrics: AccessibilityMetrics | None = None
|
|
92
|
+
visual_elements: list[VisualElement] = field(default_factory=list)
|
|
93
|
+
user_interactions: list[dict[str, Any]] = field(default_factory=list)
|
|
94
|
+
quality_score: float = 0.0 # 0.0 to 1.0
|
|
95
|
+
issues: list[str] = field(default_factory=list)
|
|
96
|
+
suggestions: list[str] = field(default_factory=list)
|
|
97
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
98
|
+
|
|
99
|
+
def to_dict(self) -> dict[str, Any]:
|
|
100
|
+
"""Convert to dictionary for serialization."""
|
|
101
|
+
data = asdict(self)
|
|
102
|
+
data["timestamp"] = self.timestamp.isoformat()
|
|
103
|
+
data["visual_elements"] = [
|
|
104
|
+
{**asdict(elem), "element_type": elem.element_type.value}
|
|
105
|
+
for elem in self.visual_elements
|
|
106
|
+
]
|
|
107
|
+
return data
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class VisualFeedbackCollector:
|
|
111
|
+
"""Collects visual feedback from generated UIs."""
|
|
112
|
+
|
|
113
|
+
def __init__(self, hardware_profile: HardwareProfile | None = None):
|
|
114
|
+
"""
|
|
115
|
+
Initialize visual feedback collector.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
hardware_profile: Hardware profile for optimization
|
|
119
|
+
"""
|
|
120
|
+
self.hardware_profile = hardware_profile or HardwareProfiler().detect_profile()
|
|
121
|
+
self.rendering_mode = self._get_rendering_mode()
|
|
122
|
+
self.feedback_history: list[VisualFeedback] = []
|
|
123
|
+
|
|
124
|
+
def _get_rendering_mode(self) -> RenderingMode:
|
|
125
|
+
"""Rendering mode. Workstation-like default (hardware taxonomy removed)."""
|
|
126
|
+
return RenderingMode.FULL
|
|
127
|
+
|
|
128
|
+
def collect_feedback(
|
|
129
|
+
self,
|
|
130
|
+
iteration: int,
|
|
131
|
+
screenshot_path: str | None = None,
|
|
132
|
+
visual_elements: list[VisualElement] | None = None,
|
|
133
|
+
user_interactions: list[dict[str, Any]] | None = None,
|
|
134
|
+
metadata: dict[str, Any] | None = None,
|
|
135
|
+
) -> VisualFeedback:
|
|
136
|
+
"""
|
|
137
|
+
Collect visual feedback for an iteration.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
iteration: Iteration number
|
|
141
|
+
screenshot_path: Path to screenshot
|
|
142
|
+
visual_elements: List of visual elements
|
|
143
|
+
user_interactions: List of user interactions
|
|
144
|
+
metadata: Additional metadata
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
VisualFeedback object
|
|
148
|
+
"""
|
|
149
|
+
feedback = VisualFeedback(
|
|
150
|
+
timestamp=datetime.now(UTC),
|
|
151
|
+
iteration=iteration,
|
|
152
|
+
screenshot_path=screenshot_path,
|
|
153
|
+
visual_elements=visual_elements or [],
|
|
154
|
+
user_interactions=user_interactions or [],
|
|
155
|
+
metadata=metadata or {},
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
self.feedback_history.append(feedback)
|
|
159
|
+
return feedback
|
|
160
|
+
|
|
161
|
+
def get_feedback_history(self, limit: int | None = None) -> list[VisualFeedback]:
|
|
162
|
+
"""
|
|
163
|
+
Get feedback history.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
limit: Maximum number of feedback items to return
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
List of VisualFeedback objects
|
|
170
|
+
"""
|
|
171
|
+
if limit:
|
|
172
|
+
return self.feedback_history[-limit:]
|
|
173
|
+
return self.feedback_history.copy()
|
|
174
|
+
|
|
175
|
+
def clear_history(self):
|
|
176
|
+
"""Clear feedback history."""
|
|
177
|
+
self.feedback_history.clear()
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class VisualAnalyzer:
|
|
181
|
+
"""Analyzes visual elements and layout."""
|
|
182
|
+
|
|
183
|
+
def __init__(self, hardware_profile: HardwareProfile | None = None):
|
|
184
|
+
"""
|
|
185
|
+
Initialize visual analyzer.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
hardware_profile: Hardware profile for optimization
|
|
189
|
+
"""
|
|
190
|
+
self.hardware_profile = hardware_profile or HardwareProfiler().detect_profile()
|
|
191
|
+
self.rendering_mode = self._get_rendering_mode()
|
|
192
|
+
|
|
193
|
+
def _get_rendering_mode(self) -> RenderingMode:
|
|
194
|
+
"""Rendering mode. Workstation-like default (hardware taxonomy removed)."""
|
|
195
|
+
return RenderingMode.FULL
|
|
196
|
+
|
|
197
|
+
def analyze_layout(
|
|
198
|
+
self,
|
|
199
|
+
visual_elements: list[VisualElement],
|
|
200
|
+
design_spec: dict[str, Any] | None = None,
|
|
201
|
+
) -> LayoutMetrics:
|
|
202
|
+
"""
|
|
203
|
+
Analyze layout quality.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
visual_elements: List of visual elements
|
|
207
|
+
design_spec: Optional design specification
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
LayoutMetrics object
|
|
211
|
+
"""
|
|
212
|
+
if not visual_elements:
|
|
213
|
+
return LayoutMetrics(
|
|
214
|
+
spacing_consistency=0.0,
|
|
215
|
+
alignment_score=0.0,
|
|
216
|
+
visual_hierarchy=0.0,
|
|
217
|
+
whitespace_balance=0.0,
|
|
218
|
+
grid_consistency=0.0,
|
|
219
|
+
issues=["No visual elements found"],
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Lightweight mode: Basic analysis only
|
|
223
|
+
if self.rendering_mode == RenderingMode.LIGHTWEIGHT:
|
|
224
|
+
return self._analyze_layout_lightweight(visual_elements)
|
|
225
|
+
|
|
226
|
+
# Standard/Full mode: Detailed analysis
|
|
227
|
+
return self._analyze_layout_detailed(visual_elements, design_spec)
|
|
228
|
+
|
|
229
|
+
def _analyze_layout_lightweight(
|
|
230
|
+
self, elements: list[VisualElement]
|
|
231
|
+
) -> LayoutMetrics:
|
|
232
|
+
"""Lightweight layout analysis for NUC devices."""
|
|
233
|
+
if len(elements) < 2:
|
|
234
|
+
return LayoutMetrics(
|
|
235
|
+
spacing_consistency=0.5,
|
|
236
|
+
alignment_score=0.5,
|
|
237
|
+
visual_hierarchy=0.5,
|
|
238
|
+
whitespace_balance=0.5,
|
|
239
|
+
grid_consistency=0.5,
|
|
240
|
+
issues=["Insufficient elements for analysis"],
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Basic spacing check
|
|
244
|
+
spacing_scores = []
|
|
245
|
+
for i in range(len(elements) - 1):
|
|
246
|
+
elem1 = elements[i]
|
|
247
|
+
elem2 = elements[i + 1]
|
|
248
|
+
distance = abs(elem1.position[1] - elem2.position[1])
|
|
249
|
+
spacing_scores.append(1.0 if distance > 0 else 0.0)
|
|
250
|
+
|
|
251
|
+
spacing_consistency = (
|
|
252
|
+
sum(spacing_scores) / len(spacing_scores) if spacing_scores else 0.5
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
return LayoutMetrics(
|
|
256
|
+
spacing_consistency=spacing_consistency,
|
|
257
|
+
alignment_score=0.7, # Simplified
|
|
258
|
+
visual_hierarchy=0.6, # Simplified
|
|
259
|
+
whitespace_balance=0.6, # Simplified
|
|
260
|
+
grid_consistency=0.7, # Simplified
|
|
261
|
+
issues=[],
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def _analyze_layout_detailed(
|
|
265
|
+
self, elements: list[VisualElement], design_spec: dict[str, Any] | None
|
|
266
|
+
) -> LayoutMetrics:
|
|
267
|
+
"""Detailed layout analysis for workstations."""
|
|
268
|
+
issues = []
|
|
269
|
+
|
|
270
|
+
# Spacing consistency
|
|
271
|
+
spacing_scores = []
|
|
272
|
+
for i in range(len(elements) - 1):
|
|
273
|
+
elem1 = elements[i]
|
|
274
|
+
elem2 = elements[i + 1]
|
|
275
|
+
if abs(elem1.position[0] - elem2.position[0]) < 10: # Same column
|
|
276
|
+
distance = abs(elem1.position[1] + elem1.size[1] - elem2.position[1])
|
|
277
|
+
if distance < 5:
|
|
278
|
+
spacing_scores.append(0.0)
|
|
279
|
+
issues.append(f"Elements {i} and {i+1} are too close")
|
|
280
|
+
elif distance > 100:
|
|
281
|
+
spacing_scores.append(0.5)
|
|
282
|
+
issues.append(f"Elements {i} and {i+1} have excessive spacing")
|
|
283
|
+
else:
|
|
284
|
+
spacing_scores.append(1.0)
|
|
285
|
+
|
|
286
|
+
spacing_consistency = (
|
|
287
|
+
sum(spacing_scores) / len(spacing_scores) if spacing_scores else 0.7
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Alignment score
|
|
291
|
+
x_positions = [elem.position[0] for elem in elements]
|
|
292
|
+
y_positions = [elem.position[1] for elem in elements]
|
|
293
|
+
|
|
294
|
+
x_alignment = (
|
|
295
|
+
1.0 - (max(x_positions) - min(x_positions)) / 1000.0 if x_positions else 0.5
|
|
296
|
+
)
|
|
297
|
+
y_alignment = (
|
|
298
|
+
1.0 - (max(y_positions) - min(y_positions)) / 1000.0 if y_positions else 0.5
|
|
299
|
+
)
|
|
300
|
+
alignment_score = (x_alignment + y_alignment) / 2.0
|
|
301
|
+
|
|
302
|
+
# Visual hierarchy (based on size and z-index)
|
|
303
|
+
sizes = [elem.size[0] * elem.size[1] for elem in elements]
|
|
304
|
+
if sizes:
|
|
305
|
+
max_size = max(sizes)
|
|
306
|
+
hierarchy_scores = [size / max_size for size in sizes]
|
|
307
|
+
visual_hierarchy = sum(hierarchy_scores) / len(hierarchy_scores)
|
|
308
|
+
else:
|
|
309
|
+
visual_hierarchy = 0.5
|
|
310
|
+
|
|
311
|
+
# Whitespace balance (simplified)
|
|
312
|
+
total_area = sum(elem.size[0] * elem.size[1] for elem in elements)
|
|
313
|
+
whitespace_balance = min(1.0, total_area / 100000.0) # Simplified calculation
|
|
314
|
+
|
|
315
|
+
# Grid consistency
|
|
316
|
+
grid_scores = []
|
|
317
|
+
for i in range(len(elements) - 1):
|
|
318
|
+
for j in range(i + 1, len(elements)):
|
|
319
|
+
elem1 = elements[i]
|
|
320
|
+
elem2 = elements[j]
|
|
321
|
+
# Check if aligned on grid
|
|
322
|
+
x_diff = abs(elem1.position[0] - elem2.position[0])
|
|
323
|
+
y_diff = abs(elem1.position[1] - elem2.position[1])
|
|
324
|
+
if x_diff < 10 or y_diff < 10:
|
|
325
|
+
grid_scores.append(1.0)
|
|
326
|
+
else:
|
|
327
|
+
grid_scores.append(0.5)
|
|
328
|
+
|
|
329
|
+
grid_consistency = sum(grid_scores) / len(grid_scores) if grid_scores else 0.7
|
|
330
|
+
|
|
331
|
+
return LayoutMetrics(
|
|
332
|
+
spacing_consistency=max(0.0, min(1.0, spacing_consistency)),
|
|
333
|
+
alignment_score=max(0.0, min(1.0, alignment_score)),
|
|
334
|
+
visual_hierarchy=max(0.0, min(1.0, visual_hierarchy)),
|
|
335
|
+
whitespace_balance=max(0.0, min(1.0, whitespace_balance)),
|
|
336
|
+
grid_consistency=max(0.0, min(1.0, grid_consistency)),
|
|
337
|
+
issues=issues[:10], # Limit issues
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
def analyze_accessibility(
|
|
341
|
+
self, visual_elements: list[VisualElement], html_content: str | None = None
|
|
342
|
+
) -> AccessibilityMetrics:
|
|
343
|
+
"""
|
|
344
|
+
Analyze accessibility features.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
visual_elements: List of visual elements
|
|
348
|
+
html_content: Optional HTML content for deeper analysis
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
AccessibilityMetrics object
|
|
352
|
+
"""
|
|
353
|
+
issues = []
|
|
354
|
+
|
|
355
|
+
# Lightweight mode: Basic checks only
|
|
356
|
+
if self.rendering_mode == RenderingMode.LIGHTWEIGHT:
|
|
357
|
+
return AccessibilityMetrics(
|
|
358
|
+
color_contrast_score=0.7, # Simplified
|
|
359
|
+
keyboard_navigable=True, # Assume yes
|
|
360
|
+
screen_reader_compatible=True, # Assume yes
|
|
361
|
+
aria_labels_present=False, # Unknown
|
|
362
|
+
focus_indicators_present=False, # Unknown
|
|
363
|
+
issues=["Lightweight mode: Limited accessibility analysis"],
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# Standard/Full mode: Detailed analysis
|
|
367
|
+
color_contrast_score = 0.8 # Simplified - would use actual contrast calculation
|
|
368
|
+
keyboard_navigable = True
|
|
369
|
+
screen_reader_compatible = True
|
|
370
|
+
|
|
371
|
+
# Check for ARIA labels in HTML
|
|
372
|
+
aria_labels_present = False
|
|
373
|
+
if html_content:
|
|
374
|
+
aria_labels_present = (
|
|
375
|
+
"aria-label" in html_content or "aria-labelledby" in html_content
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Check for focus indicators
|
|
379
|
+
focus_indicators_present = False
|
|
380
|
+
if html_content:
|
|
381
|
+
focus_indicators_present = (
|
|
382
|
+
":focus" in html_content or "focus-visible" in html_content
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
if not aria_labels_present:
|
|
386
|
+
issues.append("Missing ARIA labels for screen readers")
|
|
387
|
+
if not focus_indicators_present:
|
|
388
|
+
issues.append("Missing focus indicators for keyboard navigation")
|
|
389
|
+
|
|
390
|
+
return AccessibilityMetrics(
|
|
391
|
+
color_contrast_score=max(0.0, min(1.0, color_contrast_score)),
|
|
392
|
+
keyboard_navigable=keyboard_navigable,
|
|
393
|
+
screen_reader_compatible=screen_reader_compatible,
|
|
394
|
+
aria_labels_present=aria_labels_present,
|
|
395
|
+
focus_indicators_present=focus_indicators_present,
|
|
396
|
+
issues=issues,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
def calculate_quality_score(
|
|
400
|
+
self,
|
|
401
|
+
layout_metrics: LayoutMetrics,
|
|
402
|
+
accessibility_metrics: AccessibilityMetrics,
|
|
403
|
+
weights: dict[str, float] | None = None,
|
|
404
|
+
) -> float:
|
|
405
|
+
"""
|
|
406
|
+
Calculate overall quality score.
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
layout_metrics: Layout analysis metrics
|
|
410
|
+
accessibility_metrics: Accessibility analysis metrics
|
|
411
|
+
weights: Optional weights for different metrics
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
Quality score from 0.0 to 1.0
|
|
415
|
+
"""
|
|
416
|
+
if weights is None:
|
|
417
|
+
weights = {"layout": 0.6, "accessibility": 0.4}
|
|
418
|
+
|
|
419
|
+
layout_score = (
|
|
420
|
+
layout_metrics.spacing_consistency * 0.2
|
|
421
|
+
+ layout_metrics.alignment_score * 0.2
|
|
422
|
+
+ layout_metrics.visual_hierarchy * 0.2
|
|
423
|
+
+ layout_metrics.whitespace_balance * 0.2
|
|
424
|
+
+ layout_metrics.grid_consistency * 0.2
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
accessibility_score = (
|
|
428
|
+
accessibility_metrics.color_contrast_score * 0.3
|
|
429
|
+
+ (1.0 if accessibility_metrics.keyboard_navigable else 0.0) * 0.2
|
|
430
|
+
+ (1.0 if accessibility_metrics.screen_reader_compatible else 0.0) * 0.2
|
|
431
|
+
+ (1.0 if accessibility_metrics.aria_labels_present else 0.0) * 0.15
|
|
432
|
+
+ (1.0 if accessibility_metrics.focus_indicators_present else 0.0) * 0.15
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
quality_score = layout_score * weights.get(
|
|
436
|
+
"layout", 0.6
|
|
437
|
+
) + accessibility_score * weights.get("accessibility", 0.4)
|
|
438
|
+
|
|
439
|
+
return max(0.0, min(1.0, quality_score))
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class UIComparator:
|
|
443
|
+
"""Compares UI iterations for improvements."""
|
|
444
|
+
|
|
445
|
+
def __init__(self):
|
|
446
|
+
"""Initialize UI comparator."""
|
|
447
|
+
pass
|
|
448
|
+
|
|
449
|
+
def compare_iterations(
|
|
450
|
+
self, previous: VisualFeedback, current: VisualFeedback
|
|
451
|
+
) -> dict[str, Any]:
|
|
452
|
+
"""
|
|
453
|
+
Compare two iterations to identify improvements.
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
previous: Previous iteration feedback
|
|
457
|
+
current: Current iteration feedback
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
Comparison results
|
|
461
|
+
"""
|
|
462
|
+
improvements = []
|
|
463
|
+
regressions = []
|
|
464
|
+
unchanged = []
|
|
465
|
+
|
|
466
|
+
# Compare quality scores
|
|
467
|
+
if current.quality_score > previous.quality_score:
|
|
468
|
+
improvements.append(
|
|
469
|
+
f"Quality score improved from {previous.quality_score:.2f} to {current.quality_score:.2f}"
|
|
470
|
+
)
|
|
471
|
+
elif current.quality_score < previous.quality_score:
|
|
472
|
+
regressions.append(
|
|
473
|
+
f"Quality score decreased from {previous.quality_score:.2f} to {current.quality_score:.2f}"
|
|
474
|
+
)
|
|
475
|
+
else:
|
|
476
|
+
unchanged.append("Quality score unchanged")
|
|
477
|
+
|
|
478
|
+
# Compare layout metrics
|
|
479
|
+
if previous.layout_metrics and current.layout_metrics:
|
|
480
|
+
prev_layout = previous.layout_metrics
|
|
481
|
+
curr_layout = current.layout_metrics
|
|
482
|
+
|
|
483
|
+
if curr_layout.spacing_consistency > prev_layout.spacing_consistency:
|
|
484
|
+
improvements.append("Spacing consistency improved")
|
|
485
|
+
elif curr_layout.spacing_consistency < prev_layout.spacing_consistency:
|
|
486
|
+
regressions.append("Spacing consistency decreased")
|
|
487
|
+
|
|
488
|
+
if curr_layout.alignment_score > prev_layout.alignment_score:
|
|
489
|
+
improvements.append("Alignment score improved")
|
|
490
|
+
elif curr_layout.alignment_score < prev_layout.alignment_score:
|
|
491
|
+
regressions.append("Alignment score decreased")
|
|
492
|
+
|
|
493
|
+
if curr_layout.visual_hierarchy > prev_layout.visual_hierarchy:
|
|
494
|
+
improvements.append("Visual hierarchy improved")
|
|
495
|
+
elif curr_layout.visual_hierarchy < prev_layout.visual_hierarchy:
|
|
496
|
+
regressions.append("Visual hierarchy decreased")
|
|
497
|
+
|
|
498
|
+
# Compare accessibility metrics
|
|
499
|
+
if previous.accessibility_metrics and current.accessibility_metrics:
|
|
500
|
+
prev_acc = previous.accessibility_metrics
|
|
501
|
+
curr_acc = current.accessibility_metrics
|
|
502
|
+
|
|
503
|
+
if curr_acc.color_contrast_score > prev_acc.color_contrast_score:
|
|
504
|
+
improvements.append("Color contrast improved")
|
|
505
|
+
elif curr_acc.color_contrast_score < prev_acc.color_contrast_score:
|
|
506
|
+
regressions.append("Color contrast decreased")
|
|
507
|
+
|
|
508
|
+
if curr_acc.keyboard_navigable and not prev_acc.keyboard_navigable:
|
|
509
|
+
improvements.append("Keyboard navigation added")
|
|
510
|
+
elif not curr_acc.keyboard_navigable and prev_acc.keyboard_navigable:
|
|
511
|
+
regressions.append("Keyboard navigation removed")
|
|
512
|
+
|
|
513
|
+
# Compare issues
|
|
514
|
+
if len(current.issues) < len(previous.issues):
|
|
515
|
+
improvements.append(
|
|
516
|
+
f"Reduced issues from {len(previous.issues)} to {len(current.issues)}"
|
|
517
|
+
)
|
|
518
|
+
elif len(current.issues) > len(previous.issues):
|
|
519
|
+
regressions.append(
|
|
520
|
+
f"Increased issues from {len(previous.issues)} to {len(current.issues)}"
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
return {
|
|
524
|
+
"improvements": improvements,
|
|
525
|
+
"regressions": regressions,
|
|
526
|
+
"unchanged": unchanged,
|
|
527
|
+
"quality_delta": current.quality_score - previous.quality_score,
|
|
528
|
+
"iteration_delta": current.iteration - previous.iteration,
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
def get_improvement_trend(
|
|
532
|
+
self, feedback_history: list[VisualFeedback]
|
|
533
|
+
) -> dict[str, Any]:
|
|
534
|
+
"""
|
|
535
|
+
Analyze improvement trend across multiple iterations.
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
feedback_history: List of feedback items
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
Trend analysis
|
|
542
|
+
"""
|
|
543
|
+
if len(feedback_history) < 2:
|
|
544
|
+
return {
|
|
545
|
+
"trend": "insufficient_data",
|
|
546
|
+
"average_improvement": 0.0,
|
|
547
|
+
"iterations": len(feedback_history),
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
quality_scores = [fb.quality_score for fb in feedback_history]
|
|
551
|
+
improvements = []
|
|
552
|
+
|
|
553
|
+
for i in range(1, len(quality_scores)):
|
|
554
|
+
delta = quality_scores[i] - quality_scores[i - 1]
|
|
555
|
+
improvements.append(delta)
|
|
556
|
+
|
|
557
|
+
average_improvement = (
|
|
558
|
+
sum(improvements) / len(improvements) if improvements else 0.0
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
if average_improvement > 0.05:
|
|
562
|
+
trend = "improving"
|
|
563
|
+
elif average_improvement < -0.05:
|
|
564
|
+
trend = "declining"
|
|
565
|
+
else:
|
|
566
|
+
trend = "stable"
|
|
567
|
+
|
|
568
|
+
return {
|
|
569
|
+
"trend": trend,
|
|
570
|
+
"average_improvement": average_improvement,
|
|
571
|
+
"iterations": len(feedback_history),
|
|
572
|
+
"quality_scores": quality_scores,
|
|
573
|
+
"final_quality": quality_scores[-1] if quality_scores else 0.0,
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
class VisualPatternLearner:
|
|
578
|
+
"""Learns visual patterns from feedback."""
|
|
579
|
+
|
|
580
|
+
def __init__(self):
|
|
581
|
+
"""Initialize visual pattern learner."""
|
|
582
|
+
self.patterns: dict[str, Any] = {}
|
|
583
|
+
self.feedback_history: list[VisualFeedback] = []
|
|
584
|
+
|
|
585
|
+
def learn_from_feedback(self, feedback: VisualFeedback):
|
|
586
|
+
"""
|
|
587
|
+
Learn patterns from feedback.
|
|
588
|
+
|
|
589
|
+
Args:
|
|
590
|
+
feedback: Visual feedback to learn from
|
|
591
|
+
"""
|
|
592
|
+
self.feedback_history.append(feedback)
|
|
593
|
+
|
|
594
|
+
# Extract patterns from layout metrics
|
|
595
|
+
if feedback.layout_metrics:
|
|
596
|
+
layout = feedback.layout_metrics
|
|
597
|
+
if layout.spacing_consistency > 0.8:
|
|
598
|
+
self.patterns["high_spacing_consistency"] = (
|
|
599
|
+
self.patterns.get("high_spacing_consistency", 0) + 1
|
|
600
|
+
)
|
|
601
|
+
if layout.alignment_score > 0.8:
|
|
602
|
+
self.patterns["high_alignment"] = (
|
|
603
|
+
self.patterns.get("high_alignment", 0) + 1
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
# Extract patterns from accessibility
|
|
607
|
+
if feedback.accessibility_metrics:
|
|
608
|
+
acc = feedback.accessibility_metrics
|
|
609
|
+
if acc.color_contrast_score > 0.8:
|
|
610
|
+
self.patterns["good_contrast"] = (
|
|
611
|
+
self.patterns.get("good_contrast", 0) + 1
|
|
612
|
+
)
|
|
613
|
+
if acc.keyboard_navigable:
|
|
614
|
+
self.patterns["keyboard_navigable"] = (
|
|
615
|
+
self.patterns.get("keyboard_navigable", 0) + 1
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
def get_recommendations(self) -> list[str]:
|
|
619
|
+
"""
|
|
620
|
+
Get recommendations based on learned patterns.
|
|
621
|
+
|
|
622
|
+
Returns:
|
|
623
|
+
List of recommendations
|
|
624
|
+
"""
|
|
625
|
+
recommendations = []
|
|
626
|
+
|
|
627
|
+
if self.patterns.get("high_spacing_consistency", 0) > 5:
|
|
628
|
+
recommendations.append("Maintain consistent spacing patterns")
|
|
629
|
+
|
|
630
|
+
if self.patterns.get("high_alignment", 0) > 5:
|
|
631
|
+
recommendations.append("Continue using aligned layouts")
|
|
632
|
+
|
|
633
|
+
if self.patterns.get("good_contrast", 0) > 5:
|
|
634
|
+
recommendations.append("Maintain good color contrast")
|
|
635
|
+
|
|
636
|
+
if self.patterns.get("keyboard_navigable", 0) < 3:
|
|
637
|
+
recommendations.append("Improve keyboard navigation support")
|
|
638
|
+
|
|
639
|
+
return recommendations
|
|
640
|
+
|
|
641
|
+
def clear_patterns(self):
|
|
642
|
+
"""Clear learned patterns."""
|
|
643
|
+
self.patterns.clear()
|
|
644
|
+
self.feedback_history.clear()
|