The Unofficial and Awesome Home Assistant MCP Server
This report presents the forensic synthetic code analysis of homeassistant-ai/ha-mcp, a Python project with 3,976 GitHub stars. SynthScan v2.0 examined 380,662 lines of code across 869 source files, recording 10202 pattern matches distributed across 20 syntactic categories. The overall adjusted score of 32.3 places this repository in the Strong AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 10202 distinct pattern matches across 20 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | packaging/mcpb/generate_manifest.py | 12 | def _get_docstring_description(node: ast.AsyncFunctionDef) -> str: | CODE |
| LOW | packaging/mcpb/generate_manifest.py | 18 | def _extract_title_and_decorator_description( | CODE |
| LOW | homeassistant-addon/start.py | 57 | def get_or_create_secret_path(data_dir: Path, custom_path: str = "") -> str: | CODE |
| LOW | homeassistant-addon/start.py | 140 | def maybe_persist_secret_path( | CODE |
| LOW | homeassistant-addon/start.py | 205 | def resolve_effective_log_level() -> int: | CODE |
| LOW | homeassistant-addon/start.py | 265 | def maybe_auto_enable_beta_master(config: dict[str, Any]) -> None: | CODE |
| LOW | homeassistant-addon/start.py | 311 | def cleanup_stale_migration_marker(data_dir: Path) -> None: | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 762 | async def test_none_when_model_not_listed(self, monkeypatch): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 771 | async def test_none_when_entry_has_no_quant(self, monkeypatch): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 778 | async def test_none_on_transport_error(self, monkeypatch): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 787 | async def test_none_on_http_error_status(self, monkeypatch): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 811 | def test_extracts_requested_and_context_tokens(self): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 817 | def test_none_for_unrelated_bad_request(self): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 821 | def test_marker_without_numbers_returns_none_pair(self): | CODE |
| LOW⚡ | tests/uat/test_openai_agent.py | 826 | def test_extracts_from_sdk_wire_format(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 24 | def test_missing_required_args_exits(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 49 | def test_basic_tool_conversion(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 79 | def test_tool_with_no_parameters(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 98 | async def test_direct_text_response(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 125 | async def test_no_think_sends_enable_thinking_false(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 159 | async def test_no_think_default_omits_extra_body(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 181 | async def test_no_think_warns_when_backend_still_reasons(self, caplog): | CODE |
| LOW | tests/uat/test_openai_agent.py | 209 | async def test_no_think_silent_when_backend_honors_it(self, caplog): | CODE |
| LOW | tests/uat/test_openai_agent.py | 237 | async def test_reasoning_tokens_captured_in_tokens_thoughts(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 264 | async def test_tokens_thoughts_zero_when_backend_omits_details(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 289 | async def test_no_think_warns_on_reasoning_content_without_token_detail( | CODE |
| LOW | tests/uat/test_openai_agent.py | 321 | async def test_no_think_warns_on_inline_think_block(self, caplog): | CODE |
| LOW | tests/uat/test_openai_agent.py | 350 | async def test_no_think_warns_only_once_across_turns(self, caplog): | CODE |
| LOW | tests/uat/test_openai_agent.py | 444 | async def test_tool_call_failure_counted(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 485 | async def test_malformed_tool_arguments_reported_as_error(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 526 | async def test_max_iterations_reached(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 591 | async def test_empty_choices_raises(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 629 | async def test_no_think_prepends_token_and_sends_kwarg(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 647 | async def test_default_omits_prepend_and_kwarg(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 670 | def test_non_text_content_falls_back_to_str(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 680 | def test_no_content_falls_back_to_str(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 694 | async def test_returns_first_model_id(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 703 | async def test_raises_when_no_models(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 845 | async def test_overflow_raises_context_window_exceeded(self): | CODE |
| LOW | tests/uat/test_openai_agent.py | 868 | async def test_unrelated_bad_request_propagates(self): | CODE |
| LOW | tests/uat/openai_agent.py | 500 | async def create_and_warm_openai_client( | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 74 | def test_tokens_thoughts_defaults_to_zero_when_absent(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 83 | def test_model_from_call_site_param(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 89 | def test_model_call_site_arg_wins_over_test_phase(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 95 | def test_model_from_test_phase(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 101 | def test_model_defaults_to_none_when_absent(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 108 | def test_quantization_threaded_into_record(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 114 | def test_quantization_defaults_to_none_when_absent(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 121 | def test_extract_model_reads_claude_session(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 127 | def test_extract_model_none_on_malformed_session(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 134 | def test_model_from_claude_session_fallback(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 144 | def test_compute_passed_incomplete_run_fails_despite_verify(): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 233 | def test_clean_record_omits_error_fields(tmp_path): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 245 | def test_run_completed_uses_explicit_flag(): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 251 | def test_run_completed_fail_closed_on_missing_summary(): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 261 | def test_run_completed_present_summary_missing_flag_uses_exit_code(): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 268 | async def test_context_overflow_degraded_counts_still_fails(monkeypatch): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 430 | def test_suite_exit_code_abort_is_never_success(): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 439 | def test_suite_exit_code_clean_pass(): | CODE |
| LOW⚡ | tests/uat/stories/test_run_story_record.py | 444 | def test_suite_exit_code_failure_without_abort(): | CODE |
| 7179 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/uat/run_uat.py | 73 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 75 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 137 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 139 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 296 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 298 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 574 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 576 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 690 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/run_uat.py | 692 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/conftest.py | 43 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/conftest.py | 45 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/conftest.py | 62 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/conftest.py | 64 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/conftest.py | 123 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/conftest.py | 125 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/conftest.py | 135 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/conftest.py | 137 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/test_run_story_record.py | 141 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/test_run_story_record.py | 143 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/test_run_story_record.py | 240 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/test_run_story_record.py | 244 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/test_run_story_record.py | 304 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/test_run_story_record.py | 309 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 91 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 93 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 100 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 102 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 284 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 286 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 328 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 347 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 349 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 656 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/run_story.py | 658 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 170 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 172 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 624 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 626 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 709 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 711 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 909 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/run_story.py | 911 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/scripts/verify_story.py | 130 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/uat/stories/scripts/verify_story.py | 132 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 26 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 28 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 209 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 211 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 300 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 302 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 360 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 362 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 386 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/uat/stories/scripts/verify_story.py | 388 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/haos_image_build/build_image.py | 103 | # ┌──────────────────────┬────────────────────────────────────────────────┐ | COMMENT |
| MEDIUM | tests/haos_image_build/build_image.py | 105 | # ├──────────────────────┼────────────────────────────────────────────────┤ | COMMENT |
| MEDIUM | tests/haos_image_build/build_image.py | 119 | # └──────────────────────┴────────────────────────────────────────────────┘ | COMMENT |
| MEDIUM | tests/haos_image_build/build_image.py | 258 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/haos_image_build/build_image.py | 260 | # --------------------------------------------------------------------------- | COMMENT |
| 885 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | AGENTS.md | 572 | except Exception as e: | CODE |
| LOW | CLAUDE.md | 572 | except Exception as e: | CODE |
| LOW | homeassistant-addon/start.py | 97 | except Exception as e: | CODE |
| LOW | homeassistant-addon/start.py | 107 | except Exception as e: | CODE |
| LOW | homeassistant-addon/start.py | 226 | except Exception as e: | CODE |
| LOW | homeassistant-addon/start.py | 542 | except Exception as e: | CODE |
| LOW | homeassistant-addon/start.py | 786 | except Exception as e: | CODE |
| LOW | tests/test_env_manager.py | 230 | except Exception as e: | CODE |
| LOW | tests/test_env_manager.py | 260 | except Exception: | CODE |
| LOW | tests/test_env_manager.py | 343 | except Exception as e: | CODE |
| LOW | tests/uat/run_uat.py | 124 | except Exception: | CODE |
| LOW | tests/uat/openai_agent.py | 160 | except Exception as e: # best-effort enrichment, never fatal | CODE |
| LOW | tests/uat/openai_agent.py | 389 | except Exception as e: | CODE |
| LOW | tests/uat/openai_agent.py | 545 | except Exception: | CODE |
| LOW | tests/uat/openai_agent.py | 556 | except Exception: | CODE |
| LOW⚡ | tests/uat/stories/conftest.py | 146 | except Exception as e: | CODE |
| LOW | tests/uat/stories/conftest.py | 159 | except Exception as e: | CODE |
| LOW⚡ | tests/uat/stories/run_story.py | 277 | except Exception as exc: | CODE |
| LOW⚡ | tests/uat/stories/run_story.py | 337 | except Exception: | CODE |
| LOW⚡ | tests/uat/stories/run_story.py | 650 | except Exception: | CODE |
| LOW | tests/uat/stories/run_story.py | 148 | except Exception: | CODE |
| LOW | tests/uat/stories/run_story.py | 206 | except Exception as exc: | CODE |
| LOW | tests/uat/stories/run_story.py | 232 | except Exception as exc: | CODE |
| LOW | tests/uat/stories/run_story.py | 504 | except Exception as e: | CODE |
| LOW | tests/uat/stories/run_story.py | 639 | except Exception: | CODE |
| LOW | tests/uat/stories/run_story.py | 1004 | except Exception as e: | CODE |
| LOW | tests/uat/stories/run_story.py | 1032 | except Exception as e: | CODE |
| LOW | tests/uat/stories/scripts/verify_story.py | 69 | except Exception: | CODE |
| LOW | tests/uat/stories/scripts/verify_story.py | 88 | except Exception: | CODE |
| LOW | tests/uat/stories/scripts/verify_story.py | 151 | except Exception: | CODE |
| LOW | tests/uat/stories/scripts/verify_story.py | 231 | except Exception as e: | CODE |
| LOW | tests/uat/stories/scripts/verify_story.py | 257 | except Exception as e: | CODE |
| LOW | tests/uat/stories/scripts/verify_story.py | 285 | except Exception as e: | CODE |
| MEDIUM | tests/uat/stories/scripts/ha_query.py | 200 | print(f"Error: {args.agent} CLI not found", file=sys.stderr) | CODE |
| LOW | tests/uat/stories/scripts/measure_tools.py | 146 | except Exception as e: | STRING |
| LOW | tests/haos_image_build/build_image.py | 402 | except Exception as e: | CODE |
| LOW | tests/haos_image_build/build_image.py | 2009 | except Exception: | CODE |
| LOW | …itial_test_state/custom_components/hacs/data_client.py | 56 | except Exception as exception: | CODE |
| LOW | …t_state/custom_components/hacs/websocket/repository.py | 50 | except Exception as exception: # pylint: disable=broad-except | CODE |
| LOW | …t_state/custom_components/hacs/websocket/repository.py | 266 | except Exception as exception: # pylint: disable=broad-except | CODE |
| LOW | …t_state/custom_components/hacs/websocket/repository.py | 351 | except Exception as exception: | CODE |
| LOW | …ate/custom_components/hacs/repositories/integration.py | 216 | except Exception: # pylint: disable=broad-except | CODE |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 1374 | except Exception: # pylint: disable=broad-except | CODE |
| LOW | tests/src/unit/_embedded_stubs.py | 268 | except Exception as err: # matches real HA's broad catch-and-log | CODE |
| MEDIUM | tests/src/unit/_embedded_stubs.py | 265 | def async_refresh(self) -> None: | CODE |
| LOW | tests/src/unit/test_identifier_validation_family.py | 874 | except Exception: | CODE |
| MEDIUM | tests/src/unit/test_usage_logger.py | 112 | def writer_thread(thread_id): | CODE |
| MEDIUM | tests/src/unit/test_usage_logger.py | 124 | def reader_thread(): | CODE |
| LOW | tests/src/unit/test_usage_logger.py | 121 | except Exception as e: | CODE |
| LOW | tests/src/unit/test_usage_logger.py | 129 | except Exception as e: | CODE |
| LOW | tests/src/e2e/conftest.py | 1219 | except Exception as exc: | CODE |
| LOW | tests/src/e2e/conftest.py | 1277 | except Exception as exc: | CODE |
| LOW | tests/src/e2e/conftest.py | 1382 | except Exception as exc: | CODE |
| LOW | tests/src/e2e/conftest.py | 1858 | except Exception as e: | CODE |
| LOW | tests/src/e2e/conftest.py | 2133 | except Exception as e: | CODE |
| LOW | tests/src/e2e/conftest.py | 2323 | except Exception as e: | CODE |
| LOW | tests/src/e2e/tools/test_bm25_fuzzy_search.py | 178 | except Exception as e: | CODE |
| LOW | tests/src/e2e/tools/test_bm25_fuzzy_search.py | 235 | except Exception as e: | CODE |
| LOW⚡ | tests/src/e2e/tools/test_search_entities.py | 1432 | except Exception as exc: # pragma: no cover | CODE |
| LOW⚡ | tests/src/e2e/tools/test_search_entities.py | 1439 | except Exception as exc: # pragma: no cover | CODE |
| 458 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | packaging/mcpb/generate_manifest.py | 4 | CODE | |
| LOW | packaging/binary/pyinstaller_hooks/runtime_hook.py | 7 | CODE | |
| LOW | packaging/binary/pyinstaller_hooks/runtime_hook.py | 15 | CODE | |
| LOW | tests/uat/run_uat.py | 18 | CODE | |
| LOW | tests/uat/_logging.py | 3 | CODE | |
| LOW | tests/uat/ha_wait.py | 8 | CODE | |
| LOW | tests/uat/test_openai_agent.py | 3 | CODE | |
| LOW | tests/uat/openai_agent.py | 15 | CODE | |
| LOW | tests/uat/_inprocess.py | 8 | CODE | |
| LOW | tests/uat/stories/conftest.py | 10 | CODE | |
| LOW | tests/uat/stories/test_stories.py | 13 | CODE | |
| LOW | tests/uat/stories/test_run_story_record.py | 3 | CODE | |
| LOW | tests/uat/stories/test_verify_story.py | 3 | CODE | |
| LOW | tests/uat/stories/run_story.py | 35 | CODE | |
| LOW | tests/uat/stories/scripts/verify_story.py | 3 | CODE | |
| LOW | tests/uat/stories/scripts/ha_query.py | 22 | CODE | |
| LOW | tests/uat/stories/scripts/measure_tools.py | 19 | CODE | |
| LOW | tests/haos_image_build/build_image.py | 16 | CODE | |
| LOW | tests/haos_image_build/screenshot_engine_mock/server.py | 24 | CODE | |
| LOW | …ts/initial_test_state/custom_components/hacs/update.py | 3 | CODE | |
| LOW | …itial_test_state/custom_components/hacs/coordinator.py | 3 | CODE | |
| LOW | …itial_test_state/custom_components/hacs/diagnostics.py | 3 | CODE | |
| LOW | …/initial_test_state/custom_components/hacs/frontend.py | 3 | CODE | |
| LOW | …/initial_test_state/custom_components/hacs/__init__.py | 7 | CODE | |
| LOW | …/initial_test_state/custom_components/hacs/__init__.py | 112 | CODE | |
| LOW | …ts/initial_test_state/custom_components/hacs/switch.py | 3 | CODE | |
| LOW | …s/initial_test_state/custom_components/hacs/repairs.py | 3 | CODE | |
| LOW | …itial_test_state/custom_components/hacs/data_client.py | 3 | CODE | |
| LOW | …ts/initial_test_state/custom_components/hacs/entity.py | 3 | CODE | |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 3 | CODE | |
| LOW | …itial_test_state/custom_components/hacs/config_flow.py | 3 | CODE | |
| LOW | …ustom_components/hacs/validate/integration_manifest.py | 1 | CODE | |
| LOW | …l_test_state/custom_components/hacs/validate/issues.py | 1 | CODE | |
| LOW | …test_state/custom_components/hacs/validate/archived.py | 1 | CODE | |
| LOW | …t_state/custom_components/hacs/validate/description.py | 1 | CODE | |
| LOW | …t_state/custom_components/hacs/validate/information.py | 1 | CODE | |
| LOW | …test_state/custom_components/hacs/validate/hacsjson.py | 1 | CODE | |
| LOW | …l_test_state/custom_components/hacs/validate/topics.py | 1 | CODE | |
| LOW | …l_test_state/custom_components/hacs/validate/brands.py | 1 | CODE | |
| LOW | …l_test_state/custom_components/hacs/validate/images.py | 1 | CODE | |
| LOW | …_test_state/custom_components/hacs/validate/manager.py | 3 | CODE | |
| LOW | …ial_test_state/custom_components/hacs/validate/base.py | 3 | CODE | |
| LOW | …est_state/custom_components/hacs/websocket/critical.py | 3 | CODE | |
| LOW | …est_state/custom_components/hacs/websocket/__init__.py | 3 | CODE | |
| LOW | …state/custom_components/hacs/websocket/repositories.py | 3 | CODE | |
| LOW | …t_state/custom_components/hacs/websocket/repository.py | 3 | CODE | |
| LOW | …tial_test_state/custom_components/hacs/utils/backup.py | 3 | CODE | |
| LOW | …ial_test_state/custom_components/hacs/utils/version.py | 3 | CODE | |
| LOW | …l_test_state/custom_components/hacs/utils/decorator.py | 3 | CODE | |
| LOW | …al_test_state/custom_components/hacs/utils/validate.py | 3 | CODE | |
| LOW | …test_state/custom_components/hacs/utils/file_system.py | 3 | CODE | |
| LOW | …nitial_test_state/custom_components/hacs/utils/path.py | 3 | CODE | |
| LOW | …nitial_test_state/custom_components/hacs/utils/json.py | 3 | CODE | |
| LOW | …itial_test_state/custom_components/hacs/utils/regex.py | 3 | CODE | |
| LOW | …ial_test_state/custom_components/hacs/utils/filters.py | 3 | CODE | |
| LOW | …nitial_test_state/custom_components/hacs/utils/data.py | 3 | CODE | |
| LOW | …st_state/custom_components/hacs/utils/queue_manager.py | 3 | CODE | |
| LOW | …est_state/custom_components/hacs/repositories/theme.py | 3 | CODE | |
| LOW | …_state/custom_components/hacs/repositories/__init__.py | 3 | CODE | |
| LOW | …ate/custom_components/hacs/repositories/integration.py | 3 | CODE | |
| 315 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/haos_image_build/build_image.py | 1665 | # the config_entries/disable WS command (disabled_by=null). | COMMENT |
| HIGH⚡ | tests/lab-setup/test_setup_script.py | 14 | assert 'git -C "$SETUP_HOME/ha-mcp" pull --ff-only || true' not in content | CODE |
| HIGH | tests/src/conftest.py | 8 | cd tests && uv run pytest src/unit/ -n2 | STRING |
| HIGH | tests/src/conftest.py | 9 | cd tests && uv run pytest src/e2e/ -n2 --dist loadscope | STRING |
| HIGH | tests/src/unit/test_helper_list_registry_join.py | 112 | """When the registry entry has no custom name (name is null), the current | STRING |
| HIGH | tests/src/unit/test_anti_fouc_behavior.py | 168 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH | tests/src/unit/test_anti_fouc_behavior.py | 246 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH | tests/src/unit/test_anti_fouc_behavior.py | 295 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH⚡ | tests/src/unit/test_server_prefs_seed.py | 55 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH⚡ | tests/src/unit/test_server_prefs_seed.py | 63 | value: {{ getAttribute: (name) => name === 'data-prefs' ? serverPrefsJson : null }}, | CODE |
| HIGH⚡ | tests/src/unit/test_server_prefs_seed.py | 83 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH⚡ | tests/src/unit/test_server_prefs_seed.py | 90 | value: { getAttribute: (name) => name === 'data-prefs' ? '__HA_MCP_THEME_PREFS__' : null }, | CODE |
| HIGH⚡ | tests/src/unit/test_server_prefs_seed.py | 105 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH⚡ | tests/src/unit/test_server_prefs_seed.py | 111 | value: { getAttribute: (name) => name === 'data-prefs' ? 'not valid json {{{' : null }, | CODE |
| HIGH | tests/src/unit/test_server_prefs_seed.py | 130 | getItem: (k) => _storage[k] || null, | CODE |
| HIGH | tests/src/unit/test_server_prefs_seed.py | 137 | value: {{ getAttribute: (name) => name === 'data-prefs' ? serverPrefsJson : null }}, | CODE |
| HIGH⚡ | tests/src/unit/test_graceful_shutdown.py | 372 | """Stdin should not be available when char device but not tty (like /dev/null).""" | STRING |
| HIGH | tests/src/unit/test_astro_setup_js_behavior.py | 492 | document.body.dataset.configCode = (codeEl && codeEl.textContent) || ''; | CODE |
| HIGH | tests/src/unit/test_astro_setup_js_behavior.py | 494 | (instructionsEl && instructionsEl.innerHTML || '').length | CODE |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 88 | # returns null) and the behavioural tests find an empty body. | COMMENT |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 3874 | !!notice && notice.classList.contains('show')); | CODE |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 4020 | + `dismiss=${!!(t && t.querySelector('.ha-toast-dismiss'))}`); | CODE |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 4058 | + `dismiss=${!!(t && t.querySelector('.ha-toast-dismiss'))}`); | CODE |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 4348 | if (document.activeElement && document.activeElement.blur) { | CODE |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 4416 | const checkedBefore = !!(before && before.checked); | CODE |
| HIGH | tests/src/unit/test_settings_ui_js_behavior.py | 4421 | document.body.setAttribute('data-after', String(!!(after && after.checked))); | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 109 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 161 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 218 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 264 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 324 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 423 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 523 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 588 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 665 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 671 | let _mqlListener = null; | CODE |
| HIGH | tests/src/unit/test_theme_toggle_behavior.py | 742 | getItem: (k) => _storage.hasOwnProperty(k) ? _storage[k] : null, | CODE |
| HIGH | tests/src/unit/test_util_helpers.py | 752 | instead of ``{"data": null}``, which would be indistinguishable from a | STRING |
| HIGH | tests/src/unit/test_e2e_wait_helpers.py | 59 | wrapper = _mcp_result('{"data": null}') | CODE |
| HIGH | tests/src/unit/test_websocket_client.py | 419 | emits ``{"id": N, "type": "result", "success": true, "result": null}``. | STRING |
| HIGH | tests/src/e2e/workflows/convenience/test_backup.py | 5 | export HAMCP_ENV_FILE=tests/.env.test && uv run pytest tests/src/e2e/workflows/convenience/test_backup.py -v | STRING |
| HIGH | tests/src/e2e/workflows/convenience/test_backup.py | 8 | cd tests && docker compose up -d | STRING |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 535 | if (window.parent === window) return null; | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 537 | const auth = root && root.hass && root.hass.auth; | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 538 | if (!auth) return null; | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 539 | if (auth.expired && typeof auth.refreshAccessToken === "function") {{ | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 544 | return null; | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 547 | return auth.accessToken || (auth.data && auth.data.access_token) || null; | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 547 | return auth.accessToken || (auth.data && auth.data.access_token) || null; | CODE |
| HIGH⚡ | custom_components/ha_mcp_tools/ui_panel.py | 549 | return null; // cross-origin parent: not embedded in the HA frontend | CODE |
| HIGH | custom_components/ha_mcp_tools/ui_panel.py | 493 | let timer = null; | CODE |
| HIGH | src/ha_mcp/read_only.py | 376 | unparseable string, a non-dict JSON value (list/scalar/null), or | STRING |
| HIGH | src/ha_mcp/__main__.py | 194 | When Docker runs without the -i flag, stdin is connected to /dev/null, | CODE |
| HIGH | src/ha_mcp/tools/util_helpers.py | 1754 | # ``{"data": null}`` with a successful zero-payload fetch. | COMMENT |
| HIGH | src/ha_mcp/tools/util_helpers.py | 1906 | a segment can't be resolved (missing key, descent into non-dict / null, | STRING |
| HIGH | src/ha_mcp/tools/tools_entities.py | 1507 | 'Use null value to clear: {"automation": null}. ' | CODE |
| HIGH | src/ha_mcp/tools/tools_entities.py | 1779 | aliases and the device_class override come back as defaults ([]/null). | STRING |
| HIGH⚡ | src/ha_mcp/tools/tools_entities.py | 1798 | - enabled: Boolean shorthand (True if disabled_by is null) | STRING |
| HIGH⚡ | src/ha_mcp/tools/tools_entities.py | 1798 | - enabled: Boolean shorthand (True if disabled_by is null) | STRING |
| HIGH⚡ | src/ha_mcp/tools/tools_entities.py | 1799 | - hidden: Boolean shorthand (True if hidden_by is not null) | STRING |
| 1 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_env_manager.py | 34 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | tests/uat/stories/conftest.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/uat/stories/test_stories.py | 25 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | …ts/initial_test_state/custom_components/hacs/update.py | 148 | def _update_download_progress(self, data: dict) -> None: | CODE |
| LOW⚡ | …ts/initial_test_state/custom_components/hacs/update.py | 155 | def _update_in_progress(self, progress: int | bool) -> None: | CODE |
| LOW | …ts/initial_test_state/custom_components/hacs/entity.py | 68 | def _update_and_write_state(self, _: Any) -> None: | CODE |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 136 | def update_from_dict(self, data: dict) -> None: | CODE |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 388 | def set_stage(self, stage: HacsStage | None) -> None: | CODE |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 765 | def set_active_categories(self) -> None: | CODE |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 994 | async def update_repository(repository: HacsRepository) -> None: | CODE |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 1010 | async def update_coordinators() -> None: | CODE |
| LOW | …nitial_test_state/custom_components/hacs/utils/json.py | 5 | __all__ = ["json_loads"] | CODE |
| LOW | …est_state/custom_components/hacs/repositories/theme.py | 113 | def update_filenames(self) -> None: | CODE |
| LOW | …st_state/custom_components/hacs/repositories/plugin.py | 111 | def update_filenames(self) -> None: | CODE |
| LOW | …st_state/custom_components/hacs/repositories/plugin.py | 205 | async def update_dashboard_resources(self) -> None: | CODE |
| LOW | …e/custom_components/hacs/repositories/python_script.py | 105 | def update_filenames(self) -> None: | CODE |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 194 | def update_data(self, data: dict, action: bool = False) -> None: | CODE |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 256 | def update_data(self, data: dict) -> None: | CODE |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 467 | async def update_repository(self, ignore_issues=False, force=False) -> None: | CODE |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 1018 | def update_filenames(self) -> None: | CODE |
| LOW | tests/src/unit/_embedded_stubs.py | 354 | def set_cookie(self, name: str, value: str, **attrs: Any) -> None: | CODE |
| LOW | tests/src/unit/test_ha_search_component_routing.py | 117 | def _setup_visibility_disabled(tmp_path: Any, monkeypatch: Any) -> None: | CODE |
| LOW | tests/src/unit/test_ha_overview_component_routing.py | 148 | def _setup_visibility_disabled(tmp_path: Any, monkeypatch: Any) -> None: | CODE |
| LOW | tests/src/unit/test_wait_helpers.py | 374 | def set_unsubscribe_failure(self, exc: Exception | None) -> None: | CODE |
| LOW | tests/src/e2e/conftest.py | 91 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/conftest.py | 511 | def _setup_config_permissions(config_path: Path) -> None: | CODE |
| LOW | tests/src/e2e/tools/test_radio_management.py | 35 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | tests/src/e2e/tools/test_deep_search_exact_match.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_bm25_fuzzy_search.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_skills_resources.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_search_entities.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_create_custom_tool.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_dev_mode_tools.py | 26 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_deep_search_bulk_fetch.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_deep_search.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_logbook.py | 13 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_tools_knx.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_tools_energy.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/tools/test_ha_call_event.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | …s/src/e2e/haos_only/test_dashboard_screenshot_addon.py | 202 | async def _set_options(mcp_client: Any, slug: str, options: dict[str, Any]) -> None: | CODE |
| LOW | tests/src/e2e/haos_only/test_manage_addon_modes.py | 63 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | tests/src/e2e/haos_only/test_webhook_proxy_addon.py | 164 | async def _set_options(mcp_client: Any, slug: str, options: dict[str, Any]) -> None: | CODE |
| LOW | tests/src/e2e/basic/test_connection.py | 11 | logger = logging.getLogger(__name__) | CODE |
| LOW | …/src/e2e/workflows/webhook_proxy/test_webhook_proxy.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/scenes/test_lifecycle.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/blueprints/test_blueprints.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/device_control/test_lights.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | …/e2e/workflows/device_control/test_operation_status.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/calendar/test_calendar.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_service.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_templates.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_assist_pipeline.py | 9 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_bulk.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_state.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_history.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/core/test_get_states.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/zones/test_lifecycle.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | …sts/src/e2e/workflows/config/test_config_entry_flow.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/config/test_label_crud.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/src/e2e/workflows/config/test_ws_event_waiter.py | 30 | logger = logging.getLogger(__name__) | CODE |
| 166 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/src/unit/test_alias_fetch_chunking.py | 0 | create smartsearchtools with mocked global settings. | STRING |
| HIGH | tests/src/unit/test_deep_search_tier3_parallel.py | 0 | create smartsearchtools with mocked global settings. | STRING |
| HIGH | tests/src/unit/test_performance_parallelization.py | 0 | create smartsearchtools with mocked global settings. | STRING |
| HIGH | tests/src/unit/test_smart_search_flow_helpers.py | 0 | construct smartsearchtools without loading global settings. | STRING |
| HIGH | tests/src/unit/test_smart_search_scene_phase25.py | 0 | construct smartsearchtools without loading global settings. | STRING |
| HIGH | …/src/unit/test_deep_search_helper_dashboard_partial.py | 0 | construct smartsearchtools without loading global settings. | STRING |
| HIGH | tests/src/unit/test_deep_search_helper_rename_1794.py | 0 | construct smartsearchtools without loading global settings. | STRING |
| HIGH | tests/src/unit/test_radio_management.py | 0 | register tools onto a mock mcp and return {tool_name: bound_method}. | STRING |
| HIGH | tests/src/unit/test_radio_thread.py | 0 | register tools onto a mock mcp and return {tool_name: bound_method}. | STRING |
| HIGH | tests/src/unit/test_radio_zwave.py | 0 | register tools onto a mock mcp and return {tool_name: bound_method}. | STRING |
| HIGH | tests/src/unit/test_radio_zigbee.py | 0 | register tools onto a mock mcp and return {tool_name: bound_method}. | STRING |
| HIGH | tests/src/unit/test_helper_param_rejection.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_helper_registry_id_validation.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_action_and_collision.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_helper_update_persistence.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_helper_field_persistence.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_flow_name_injection.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_action_discriminator.py | 0 | register helper config tools and return the captured tool functions. | STRING |
| HIGH | tests/src/unit/test_yaml_themes.py | 0 | minimal hass mock that runs executor jobs synchronously. | STRING |
| HIGH | tests/src/unit/test_yaml_whole_file_replace.py | 0 | minimal hass mock that runs executor jobs synchronously. | STRING |
| HIGH | tests/src/unit/test_yaml_edit_untouched_content.py | 0 | minimal hass mock that runs executor jobs synchronously. | STRING |
| HIGH | tests/src/unit/test_yaml_dashboards.py | 0 | minimal hass mock that runs executor jobs synchronously. | STRING |
| HIGH | …/unit/test_ha_config_list_helpers_component_routing.py | 0 | a non-unknown command error → legacy path and a warnings[] entry. | STRING |
| HIGH | tests/src/unit/test_ha_search_component_routing.py | 0 | a non-unknown command error → legacy path and a warnings[] entry. | STRING |
| HIGH | tests/src/unit/test_ha_get_zone_component_routing.py | 0 | a non-unknown command error → legacy path and a warnings[] entry. | STRING |
| HIGH | tests/src/unit/test_ha_overview_component_routing.py | 0 | a non-unknown command error → legacy path and a warnings[] entry. | STRING |
| HIGH | tests/src/e2e/conftest.py | 0 | parse a streamable-http mcp response (json body or sse) to a json-rpc dict. | STRING |
| HIGH | tests/src/e2e/haos_only/test_embedded_server_haos.py | 0 | parse a streamable-http mcp response (json body or sse) to a json-rpc dict. | STRING |
| HIGH | …sts/src/e2e/workflows/embedded/test_embedded_server.py | 0 | parse a streamable-http mcp response (json body or sse) to a json-rpc dict. | STRING |
| HIGH | …/src/e2e/workflows/dashboards/test_python_transform.py | 0 | test that python_transform is mutually exclusive with config. | STRING |
| HIGH | …sts/src/e2e/workflows/scripts/test_python_transform.py | 0 | test that python_transform is mutually exclusive with config. | STRING |
| HIGH | …/src/e2e/workflows/automation/test_python_transform.py | 0 | test that python_transform is mutually exclusive with config. | STRING |
| HIGH | custom_components/ha_mcp_tools/mcp_webhook.py | 0 | absolute url of the protected webhook resource under ``base_url``. | STRING |
| HIGH | …sistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth.py | 0 | absolute url of the protected webhook resource under ``base_url``. | STRING |
| HIGH | homeassistant-addon-webhook-proxy/mcp_proxy/oauth.py | 0 | absolute url of the protected webhook resource under ``base_url``. | STRING |
| HIGH | custom_components/ha_mcp_tools/mcp_webhook.py | 0 | issuer / authorization-server url under ``base_url``. | STRING |
| HIGH | …sistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth.py | 0 | issuer / authorization-server url under ``base_url``. | STRING |
| HIGH | homeassistant-addon-webhook-proxy/mcp_proxy/oauth.py | 0 | issuer / authorization-server url under ``base_url``. | STRING |
| HIGH | homeassistant-addon-webhook-proxy-dev/start.py | 0 | write ``data`` to ``path`` with 0600, atomically and race-free. writes to a sibling temp file created 0600 (the mode is | STRING |
| HIGH | …sistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth.py | 0 | write ``data`` to ``path`` with 0600, atomically and race-free. writes to a sibling temp file created 0600 (the mode is | STRING |
| HIGH | homeassistant-addon-webhook-proxy/start.py | 0 | write ``data`` to ``path`` with 0600, atomically and race-free. writes to a sibling temp file created 0600 (the mode is | STRING |
| HIGH | homeassistant-addon-webhook-proxy/mcp_proxy/oauth.py | 0 | write ``data`` to ``path`` with 0600, atomically and race-free. writes to a sibling temp file created 0600 (the mode is | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …s/uat/stories/catalog/s02_automation_motion_light.yaml | 18 | # Create an input_boolean to simulate a motion sensor | COMMENT |
| MEDIUM | …ories/catalog/s07_automation_update_add_condition.yaml | 18 | # Create the automation to be modified | COMMENT |
| MEDIUM | …ories/catalog/s07_automation_update_add_condition.yaml | 34 | # Create a presence indicator | COMMENT |
| MEDIUM | tests/addon/test_webhook_proxy.py | 327 | # Create the package object first so submodules have a parent with __path__. | COMMENT |
| MEDIUM | tests/src/unit/test_oauth.py | 376 | # Create a stateless refresh token (as exchange_authorization_code would) | COMMENT |
| MEDIUM | tests/src/unit/test_oauth.py | 1297 | # Create a cached client | COMMENT |
| MEDIUM | tests/src/unit/test_graceful_shutdown.py | 73 | # Create a mock event | COMMENT |
| MEDIUM | tests/src/unit/test_graceful_shutdown.py | 225 | # Create a mock MCP that runs forever | COMMENT |
| MEDIUM | tests/src/unit/policy/test_approval_queue.py | 275 | # Create a second entry — forces eviction of 'a' (only one pending) | COMMENT |
| MEDIUM | tests/src/e2e/test_entity_visibility.py | 141 | # Create a label and assign it to the probe so the entity-registry entry | COMMENT |
| MEDIUM⚡ | tests/src/e2e/tools/test_deep_search_exact_match.py | 25 | # Create an automation with a distinctive entity reference | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search_exact_match.py | 141 | # Create a dashboard with a distinctive entity reference | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_bm25_fuzzy_search.py | 106 | # Create an automation with terms that are non-adjacent | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search.py | 46 | # Create the automation | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search.py | 116 | # Create a test script with distinctive content | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search.py | 128 | # Create the script | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search.py | 203 | # Create a test input_select helper with distinctive options | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search.py | 209 | # Create the helper | COMMENT |
| MEDIUM | tests/src/e2e/workflows/calendar/test_calendar.py | 214 | # Create an event for tomorrow | COMMENT |
| MEDIUM | tests/src/e2e/workflows/core/test_service.py | 194 | # Create a test automation first | COMMENT |
| MEDIUM | tests/src/e2e/workflows/core/test_service.py | 373 | # Create a test input_boolean | COMMENT |
| MEDIUM⚡ | tests/src/e2e/workflows/config/test_label_crud.py | 271 | # Create a test label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_label_crud.py | 361 | # Create a test label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_label_crud.py | 402 | # Create a test label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_label_crud.py | 443 | # Create a test label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_helper_crud.py | 1829 | # Create a dedicated area | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_helper_crud.py | 1893 | # Create a dedicated label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_helper_crud.py | 1964 | # Create a dedicated area | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_helper_crud.py | 2254 | # Create a dedicated area + label | COMMENT |
| MEDIUM | …/e2e/workflows/auto_backup/test_capture_and_restore.py | 228 | # Create an automation to snapshot. We do NOT edit it — the | COMMENT |
| MEDIUM | tests/src/e2e/workflows/labels/test_label_operations.py | 49 | # Create the test label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/labels/test_label_operations.py | 341 | # Create a test label | COMMENT |
| MEDIUM | tests/src/e2e/workflows/filesystem/test_yaml_config.py | 626 | # Create a file with a list value | COMMENT |
| MEDIUM | tests/src/e2e/workflows/filesystem/test_yaml_config.py | 931 | # Create a file with !secret tag under 'template' key | COMMENT |
| MEDIUM | tests/src/e2e/workflows/filesystem/test_yaml_config.py | 1157 | # Create the theme file. | COMMENT |
| MEDIUM | tests/src/e2e/workflows/filesystem/test_yaml_config.py | 1330 | # Create the key — no prior value, so capture is skipped. | COMMENT |
| MEDIUM | …s/src/e2e/workflows/filesystem/test_file_operations.py | 642 | # Create a file to delete | COMMENT |
| MEDIUM | tests/src/e2e/workflows/groups/test_verification.py | 69 | # Create a group first | COMMENT |
| MEDIUM | …/workflows/integrations/test_integration_management.py | 94 | # Create a temporary light group helper | COMMENT |
| MEDIUM | tests/src/e2e/workflows/system/test_system_tools.py | 825 | # Create a test notification | COMMENT |
| MEDIUM | tests/src/e2e/workflows/dashboards/test_resources.py | 310 | # Create a resource first | COMMENT |
| MEDIUM | …sts/src/e2e/workflows/registry/test_voice_assistant.py | 96 | # Create a test entity first | COMMENT |
| MEDIUM | …sts/src/e2e/workflows/registry/test_voice_assistant.py | 145 | # Create a test entity | COMMENT |
| MEDIUM | …sts/src/e2e/workflows/registry/test_voice_assistant.py | 202 | # Create a test entity | COMMENT |
| MEDIUM | tests/src/e2e/workflows/automation/test_lifecycle.py | 912 | # Create the automation - THIS IS THE KEY TEST | COMMENT |
| MEDIUM | …/src/e2e/workflows/automation/test_python_transform.py | 578 | # Create a category | COMMENT |
| MEDIUM | tests/src/e2e/workflows/convenience/test_backup.py | 264 | # Create a backup (which internally retrieves config/password) | COMMENT |
| MEDIUM⚡ | …2e/workflows/categories/test_config_tool_categories.py | 28 | # Create a category first | COMMENT |
| MEDIUM | …2e/workflows/categories/test_config_tool_categories.py | 87 | # Create a category first | COMMENT |
| MEDIUM | …2e/workflows/categories/test_config_tool_categories.py | 145 | # Create a category | COMMENT |
| MEDIUM | …2e/workflows/categories/test_config_tool_categories.py | 254 | # Create a category | COMMENT |
| MEDIUM | …2e/workflows/categories/test_config_tool_categories.py | 317 | # Create a category | COMMENT |
| MEDIUM | …2e/workflows/categories/test_config_tool_categories.py | 361 | # Create a category for helpers | COMMENT |
| MEDIUM | …sts/src/e2e/workflows/categories/test_category_crud.py | 235 | # Create a test category | COMMENT |
| MEDIUM | …sts/src/e2e/workflows/categories/test_category_crud.py | 281 | # Create a test category | COMMENT |
| MEDIUM⚡ | tests/src/e2e/workflows/entities/test_entity_remove.py | 19 | # Create a temporary input_boolean to remove | COMMENT |
| MEDIUM | …s/src/e2e/workflows/entities/test_entity_management.py | 41 | # Create a test area | COMMENT |
| MEDIUM | …s/src/e2e/workflows/entities/test_entity_management.py | 349 | # Create a test area | COMMENT |
| MEDIUM | site/src/data/tools.json | 553 | "description": "Create a new event in a calendar.\n\nCreates a one-off event via the calendar.create_event service, | CODE |
| MEDIUM | site/src/data/tools.json | 1388 | "description": "Write a file to allowed directories in the Home Assistant config.\n\nCreates or updates files in res | CODE |
| 5 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-compose.screenshot.yml | 1 | # Example: dashboard-screenshot engine sidecar for Docker / Container installs | COMMENT |
| LOW | docker-compose.screenshot.yml | 41 | container_name: ha-mcp-screenshot | COMMENT |
| LOW | docker-compose.yml | 21 | - HOMEASSISTANT_URL=http://homeassistant:8123 | COMMENT |
| LOW | homeassistant-addon/config.yaml | 21 | # homeassistant-addon-dev/config.yaml. | COMMENT |
| LOW | homeassistant-addon/start.py | 241 | # Per-key sub-gates of enable_yaml_config_editing. Kept in lockstep | COMMENT |
| LOW | homeassistant-addon/start.py | 581 | ).lower() | COMMENT |
| LOW | homeassistant-addon/start.py | 681 | ) | COMMENT |
| LOW | homeassistant-addon/start.py | 761 | # the basicConfig above could only hardcode INFO. Without this, the | COMMENT |
| LOW | tests/pytest.ini | 61 | not_on_embedded: skip on the embedded backend (E2E_BACKEND=embedded) — provably redundant with the lane's own in-pro | COMMENT |
| LOW | tests/uat/stories/run_story.py | 481 | # A request timed out, but the backend may well be alive: a slow or | COMMENT |
| LOW | tests/haos_image_build/requirements.txt | 1 | # Build-script dependencies. Installed in CI by the haos-e2e-tests and | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 101 | # | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 121 | # Dropped vs the original #1281 set: Frigate (~2 GB) and Zigbee2MQTT (~220 | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 141 | Addon(repo=None, name="Matter Server"), | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 181 | # inaddon HAOS E2E tier (#1349 item 7). The dev addon's config.yaml lives at | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 201 | # ``tests/src/e2e/haos_only/test_embedded_server_haos.py`` fixture enables it via | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 221 | # embedded-server test times out, rather than silently installing wrong code. | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 241 | # repeatedly broke the bake under floating Supervisor versions, and real | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 801 | # hassio-addons/addon-node-red/node-red/config.yaml) but ships no | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 821 | # ``ha_manage_addon``'s proxy mode to work against this | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 881 | # - ``options`` is a FULL-REPLACE field; the value must satisfy | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 1581 | time.sleep(10.0) | COMMENT |
| LOW | tests/haos_image_build/build_image.py | 1961 | # Entry point | COMMENT |
| LOW | tests/initial_test_state/configuration.yaml | 41 | step: 1 | COMMENT |
| LOW | tests/addon/test_webhook_proxy.py | 3061 | COMMENT | |
| LOW | tests/src/haos_runtime.py | 81 | HAOS_IMAGE_ENV = "HAOS_TEST_IMAGE_PATH" | COMMENT |
| LOW | tests/src/haos_runtime.py | 101 | HA_MCP_SERVER_DOMAIN = "ha_mcp_tools" | COMMENT |
| LOW | tests/src/haos_runtime.py | 341 | } | COMMENT |
| LOW | tests/src/haos_runtime.py | 441 | LOG.info("Shifted recorder timestamps by %+.0fs", offset) | COMMENT |
| LOW | tests/src/haos_runtime.py | 1281 | last_err = e | COMMENT |
| LOW | tests/src/haos_runtime.py | 1881 | COMMENT | |
| LOW | tests/src/unit/test_backup_manager.py | 1421 | # ``unchanged`` must be False under ``entity_missing``: the empty | COMMENT |
| LOW | tests/src/unit/test_settings_ui_js_behavior.py | 81 | "policy-save-global-btn", | COMMENT |
| LOW | tests/src/unit/test_embedded_setup.py | 1301 | # resolves ``from a.b.c import x`` through the immediate parent | COMMENT |
| LOW | tests/src/unit/test_helper_classifier.py | 161 | "error_str,expected_code", | COMMENT |
| LOW | tests/src/unit/test_advanced_settings_coverage.py | 181 | # and unreachable for add-on users. That is exactly how the three | COMMENT |
| LOW | …/unit/test_fields_projection_docstring_completeness.py | 41 | # ``fields=`` Annotated[..., Field(description=...)] text | COMMENT |
| LOW | tests/src/unit/test_webhook_proxy_sync.py | 181 | assert lines[lines.index("stage: experimental") - 1].startswith("url:") | COMMENT |
| LOW | tests/src/unit/test_webhook_proxy_sync.py | 281 | tmp_path / src.addon_dir, | COMMENT |
| LOW | tests/src/unit/test_context_injection.py | 661 | # Sequential mode attempts dispatch (0) + per-op (1) + completion (2) = 3 emits. | COMMENT |
| LOW | tests/src/unit/test_wait_helpers.py | 321 | mock_client, | COMMENT |
| LOW | tests/src/unit/test_identifier_validation_family.py | 681 | # Control: when ``list_only=True`` and ``url_path`` is omitted, | COMMENT |
| LOW | tests/src/unit/test_identifier_validation_family.py | 701 | # Positive proof: at least one WS message was attempted (the | COMMENT |
| LOW | tests/src/unit/test_identifier_validation_family.py | 781 | # service call and surface as a misleading HA service-call failure. | COMMENT |
| LOW | tests/src/e2e/conftest.py | 101 | _READINESS_TIMINGS: list[dict[str, Any]] = [] | COMMENT |
| LOW | tests/src/e2e/conftest.py | 121 | _EMBEDDED_WEBHOOK_ID = "mcp_e2e_embedded_0123456789abcdef" | COMMENT |
| LOW | tests/src/e2e/conftest.py | 221 | del config | COMMENT |
| LOW | tests/src/e2e/conftest.py | 281 | # it joins the skip; those tests keep full coverage on the container lane. | COMMENT |
| LOW | tests/src/e2e/conftest.py | 301 | # would double-enable the entry and race the session backend, so they skip | COMMENT |
| LOW | tests/src/e2e/conftest.py | 561 | COMMENT | |
| LOW | tests/src/e2e/conftest.py | 601 | # exists then but its contents are partial. On the success path the | COMMENT |
| LOW | tests/src/e2e/conftest.py | 1521 | # image path unchanged. | COMMENT |
| LOW | tests/src/e2e/conftest.py | 1541 | # enables the entry. Best-effort — a failure only affects that one test. | COMMENT |
| LOW | tests/src/e2e/conftest.py | 1621 | # 200 but state was 'unknown'". | COMMENT |
| LOW | tests/src/e2e/conftest.py | 1681 | # defence against race conditions on slow CI runners. | COMMENT |
| LOW | tests/src/e2e/conftest.py | 1801 | ), | COMMENT |
| LOW | tests/src/e2e/conftest.py | 1921 | COMMENT | |
| LOW | tests/src/e2e/conftest.py | 1981 | # observed on PR #1268 ARM E2E (2026-05-12) where ``ruamel.yaml`` | COMMENT |
| LOW | tests/src/e2e/conftest.py | 2061 | logger.info("🗑️ Removed .HA_RESTORE file from config") | COMMENT |
| LOW | tests/src/e2e/conftest.py | 2081 | # ``SUN_WAIT = 5`` is the residual tight poll: | COMMENT |
| 173 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | packaging/mcpb/generate_manifest.py | 18 | CODE | |
| LOW | homeassistant-addon/start.py | 57 | CODE | |
| LOW | tests/test_env_manager.py | 282 | CODE | |
| LOW | tests/test_env_manager.py | 145 | CODE | |
| LOW | tests/uat/run_uat.py | 483 | CODE | |
| LOW | tests/uat/ha_wait.py | 24 | CODE | |
| LOW | tests/uat/openai_agent.py | 137 | CODE | |
| LOW | tests/uat/openai_agent.py | 216 | CODE | |
| LOW | tests/uat/stories/run_story.py | 173 | CODE | |
| LOW | tests/uat/stories/run_story.py | 213 | CODE | |
| LOW | tests/uat/stories/run_story.py | 245 | CODE | |
| LOW | tests/uat/stories/run_story.py | 912 | CODE | |
| LOW | tests/haos_image_build/build_image.py | 327 | CODE | |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 430 | CODE | |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 523 | CODE | |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 838 | CODE | |
| LOW | tests/initial_test_state/custom_components/hacs/base.py | 433 | CODE | |
| LOW | …t_state/custom_components/hacs/validate/information.py | 21 | CODE | |
| LOW | …ial_test_state/custom_components/hacs/utils/filters.py | 8 | CODE | |
| LOW | …nitial_test_state/custom_components/hacs/utils/data.py | 156 | CODE | |
| LOW | …st_state/custom_components/hacs/repositories/plugin.py | 111 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 194 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 360 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 410 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 657 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 781 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 1046 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 1171 | CODE | |
| LOW | …test_state/custom_components/hacs/repositories/base.py | 684 | CODE | |
| LOW | tests/src/haos_runtime.py | 288 | CODE | |
| LOW | tests/src/haos_runtime.py | 1245 | CODE | |
| LOW | tests/src/haos_runtime.py | 1389 | CODE | |
| LOW | tests/src/haos_runtime.py | 1408 | CODE | |
| LOW | tests/src/haos_runtime.py | 1643 | CODE | |
| LOW | tests/src/unit/test_read_only.py | 746 | CODE | |
| LOW | tests/src/unit/test_read_only.py | 762 | CODE | |
| LOW | tests/src/unit/test_settings_ui_handler_selection.py | 84 | CODE | |
| LOW | tests/src/unit/test_settings_ui_js_behavior.py | 110 | CODE | |
| LOW | tests/src/unit/test_server_bridge_strip.py | 19 | CODE | |
| LOW | tests/src/unit/test_server_bridge_strip.py | 65 | CODE | |
| LOW | tests/src/unit/test_advanced_settings_coverage.py | 229 | CODE | |
| LOW | …/unit/test_fields_projection_docstring_completeness.py | 234 | CODE | |
| LOW | …/unit/test_fields_projection_docstring_completeness.py | 274 | CODE | |
| LOW | …/unit/test_fields_projection_docstring_completeness.py | 351 | CODE | |
| LOW | …/unit/test_fields_projection_docstring_completeness.py | 367 | CODE | |
| LOW | …/unit/test_fields_projection_docstring_completeness.py | 610 | CODE | |
| LOW | tests/src/unit/test_skill_content_wiring.py | 282 | CODE | |
| LOW | tests/src/unit/test_skill_content_wiring.py | 306 | CODE | |
| LOW | tests/src/e2e/conftest.py | 413 | CODE | |
| LOW | tests/src/e2e/conftest.py | 533 | CODE | |
| LOW | tests/src/e2e/conftest.py | 884 | CODE | |
| LOW | tests/src/e2e/conftest.py | 1074 | CODE | |
| LOW | tests/src/e2e/conftest.py | 1173 | CODE | |
| LOW | tests/src/e2e/conftest.py | 1504 | CODE | |
| LOW | tests/src/e2e/conftest.py | 2578 | CODE | |
| LOW | tests/src/e2e/run_tests.py | 13 | CODE | |
| LOW | …s/src/e2e/haos_only/test_dashboard_screenshot_addon.py | 97 | CODE | |
| LOW | tests/src/e2e/haos_only/test_manage_addon_modes.py | 309 | CODE | |
| LOW | tests/src/e2e/haos_only/test_addon_debug_log_level.py | 152 | CODE | |
| LOW | tests/src/e2e/haos_only/test_addon_debug_log_level.py | 203 | CODE | |
| 150 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/src/unit/test_oauth.py | 752 | # Step 5: Verify access token contains only ha_token (no ha_url - SSRF fix) | COMMENT |
| LOW⚡ | tests/src/unit/test_oauth.py | 758 | # Step 6: Use stateless refresh token to get new access token | COMMENT |
| LOW⚡ | tests/src/unit/test_oauth.py | 772 | # Step 7: Verify refreshed access token is valid and carries HA credentials | COMMENT |
| LOW⚡ | tests/src/unit/test_oauth.py | 779 | # Step 8: Verify chained refresh also works | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 682 | # Step 1: Client registration | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 696 | # Step 2: Authorization request | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 716 | # Step 3: Simulate consent form submission | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 740 | # Step 4: Exchange auth code for tokens | COMMENT |
| LOW⚡ | tests/src/unit/test_flow_multistep.py | 355 | # Step 1: the user step | COMMENT |
| LOW⚡ | tests/src/unit/test_flow_multistep.py | 363 | # Step 2: the state_characteristic step — MUST receive its key, | COMMENT |
| LOW⚡ | tests/src/e2e/tools/test_create_custom_tool.py | 1053 | # Step 1: save a tool we'll then delete. | COMMENT |
| LOW | tests/src/e2e/tools/test_create_custom_tool.py | 1065 | # Step 2: delete it from inside the sandbox. | COMMENT |
| LOW | tests/src/e2e/tools/test_create_custom_tool.py | 1086 | # Step 3: confirm running it now fails (entry is gone). | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 350 | # Step 1: List automation blueprints | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 360 | # Step 2: List script blueprints | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 370 | # Step 3: If blueprints exist, explore one | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 436 | # Step 1: List available blueprints | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 451 | # Step 2: Get blueprint details to understand required inputs | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 460 | # Step 3: Create automation from blueprint (no trigger/action fields) | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 508 | # Step 4: Wait for automation to be registered, then verify no trigger/action fields | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 516 | # Step 5: Clean up | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/system/test_system_tools.py | 716 | # Step 1: Check configuration (folded into ha_get_system_health) | COMMENT |
| LOW | tests/src/e2e/workflows/system/test_system_tools.py | 728 | # Step 2: Reload automations | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1174 | # Step 2: Get blueprint details to understand required inputs | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1183 | # Step 3: Create script from blueprint (no sequence field) | COMMENT |
| LOW | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1229 | # Step 4: Wait for script to be registered, then verify no sequence field | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 373 | # Step 1: Discover light services (use full detail to see fields) | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 383 | # Step 2: Find a light entity to test with | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 400 | # Step 3: Use discovered service to control light | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 410 | # Step 4: Call discovered service | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 31 | ## Step 0: Triage (Diff Analysis + Custom Story Design) | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 108 | ## Step 1: Run Baseline Version | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 163 | ## Step 2: Run Target Version | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 178 | ## Step 3: White-Box Analysis | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 211 | ## Step 4: Score & Compare | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 255 | ## Step 5: Update JSONL | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 264 | ## Step 6: Report | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 321 | ## Step 7: Investigate Outliers | COMMENT |
| LOW | .claude/skills/bat-story-eval/SKILL.md | 335 | ## Step 8: Tool Description Size | COMMENT |
| LOW | …kills/bat-story-eval/references/regression-protocol.md | 29 | ## Step 1: Re-Run (Flakiness Check) | COMMENT |
| LOW | …kills/bat-story-eval/references/regression-protocol.md | 45 | ## Step 2: Control Run (Baseline Version) | COMMENT |
| LOW | …kills/bat-story-eval/references/regression-protocol.md | 62 | ## Step 3: Cross-Agent Check | COMMENT |
| LOW | …kills/bat-story-eval/references/regression-protocol.md | 92 | ## Step 4: Diagnose | COMMENT |
| LOW | …kills/bat-story-eval/references/regression-protocol.md | 133 | ## Step 5: Report | COMMENT |
| LOW | .claude/skills/my-pr-checker/SKILL.md | 12 | ## Step 1: Full PR Assessment | COMMENT |
| LOW | .claude/skills/my-pr-checker/SKILL.md | 34 | ## Step 2: Triage Comments | COMMENT |
| LOW | .claude/skills/my-pr-checker/SKILL.md | 42 | ## Step 3: Fix Code Issues | COMMENT |
| LOW | .claude/skills/my-pr-checker/SKILL.md | 59 | ## Step 4: Resolve Each Thread (both steps required) | COMMENT |
| LOW | .claude/skills/my-pr-checker/SKILL.md | 80 | ## Step 5: Wait and Re-check | COMMENT |
| LOW | .claude/skills/my-pr-checker/SKILL.md | 91 | ## Step 6: Final Report | COMMENT |
| LOW | .claude/skills/issue-analysis/SKILL.md | 15 | ## Step 1: Fetch Issue Details | COMMENT |
| LOW⚡ | .claude/skills/issue-analysis/SKILL.md | 26 | ## Step 2: Research Phase (before drawing conclusions) | COMMENT |
| LOW⚡ | .claude/skills/issue-analysis/SKILL.md | 33 | ## Step 3: Assess Other Open Issues (for priority context) | COMMENT |
| LOW⚡ | .claude/skills/issue-analysis/SKILL.md | 39 | ## Step 4: Determine Labels | COMMENT |
| LOW | .claude/skills/issue-analysis/SKILL.md | 51 | ## Step 5: Draft Analysis for User | COMMENT |
| LOW | .claude/skills/issue-analysis/SKILL.md | 57 | ## Step 6: Apply Labels and Post Comment | COMMENT |
| LOW | docs/macOS-uv-guide.md | 7 | ## Step 1: Create a Claude Account | COMMENT |
| LOW | docs/macOS-uv-guide.md | 11 | ## Step 2: Run the Installer | COMMENT |
| LOW⚡ | docs/macOS-uv-guide.md | 60 | ## Step 3: Install or Restart Claude Desktop | COMMENT |
| LOW⚡ | docs/macOS-uv-guide.md | 66 | ## Step 4: Test It | COMMENT |
| 19 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/src/e2e/workflows/device_control/test_lights.py | 28 | Validate and return entity state data. Args: state_data: Parsed MCP result from ha_get_state entity | STRING |
| HIGH | tests/src/e2e/utilities/wait_helpers.py | 344 | Poll an MCP tool until the result satisfies a predicate. Useful when an entity was just created and needs time | STRING |
| HIGH | tests/src/e2e/utilities/wait_helpers.py | 584 | Subscribe → sample-after-subscribe → wait-for-event pattern, test-side. Mirrors :func:`ha_mcp.tools.util_helpers._w | STRING |
| HIGH | src/ha_mcp/tools/backup.py | 152 | Retrieve default backup password from Home Assistant configuration. Args: ws_client: Connected WebSock | STRING |
| HIGH | src/ha_mcp/tools/device_control.py | 70 | Universal smart device control with async verification. This tool provides intelligent device control | STRING |
| HIGH | src/ha_mcp/tools/util_helpers.py | 107 | Parse flexibly JSON string or return existing dict/list. Args: param: JSON string, dict, list, or None | STRING |
| HIGH | src/ha_mcp/tools/tools_utility.py | 1257 | Evaluate Jinja2 templates using Home Assistant's template engine. This tool allows testing and debuggi | STRING |
| HIGH | src/ha_mcp/tools/helpers.py | 89 | Reject ``None``, empty, or whitespace-only identifier values. Surfaces a structured ``VALIDATION_INVALID_PARAMETER` | STRING |
| HIGH | src/ha_mcp/tools/helpers.py | 409 | Convert an exception to a structured error response. This function maps common exception types to appropriate | STRING |
| HIGH | src/ha_mcp/tools/smart_search/_entities.py | 39 | Search entities with fuzzy matching and typo tolerance. Args: query: Search query (can be | STRING |
| HIGH | src/ha_mcp/utils/python_sandbox.py | 340 | Execute a validated Python expression in a restricted environment. The expression runs with ``variables`` avai | STRING |
| HIGH | src/ha_mcp/utils/python_sandbox.py | 410 | Execute validated Python expression against a ``config`` dict. Thin wrapper around :func:`safe_execute_express | STRING |
| HIGH | src/ha_mcp/client/supervisor_client.py | 37 | Construct an ``httpx.AsyncClient`` pre-configured for the Supervisor REST API. Args: timeout: Per-request t | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 282 | Make authenticated request to Home Assistant API and parse JSON body. Args: method: HTTP m | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 336 | Set entity state. Args: entity_id: Entity ID state: New state value | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 895 | Convert entity_id to unique_id if needed, or return unique_id as-is. Args: identifier: Eit | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 931 | Get automation configuration by unique_id or entity_id. Args: identifier: Either automatio | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 962 | Create new automation or update existing one. Args: config: Automation configuration dicti | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1089 | Delete automation configuration by entity_id or unique_id. Args: identifier: Either automa | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1145 | Start a config entry flow. Args: handler: Integration domain (e.g., "template", "group") | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1168 | Submit data for a config flow step. Args: flow_id: Flow ID from start_config_flow or previ | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1187 | Abort an in-progress config entry flow. Args: flow_id: Flow ID to abort Returns: | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1203 | Start an options flow for a config entry. The options flow allows configuring an existing integration | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1229 | Submit data for an options flow step. Args: flow_id: Flow ID from start_options_flow or pr | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1250 | Abort an in-progress options flow without saving changes. Args: flow_id: Flow ID to abort | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1337 | Get config entry details. Note: Home Assistant doesn't have a direct REST API endpoint for individual | STRING |
| HIGH | src/ha_mcp/client/rest_client.py | 1375 | Delete a config entry via REST API. The WebSocket command ``config_entries/delete`` is not supported by | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | homeassistant-addon/start.py | 84 | # Check if we have a stored secret path | COMMENT |
| LOW | tests/src/unit/_js_harness.py | 436 | # Check if this is a data-purpose script and incorporate that | COMMENT |
| LOW | tests/src/e2e/conftest.py | 644 | # Check if HACS is installed and frontend is missing or invalid. | COMMENT |
| LOW | tests/src/e2e/conftest.py | 2119 | # Check if container is actually running | COMMENT |
| LOW | tests/src/e2e/workflows/blueprints/test_blueprints.py | 482 | # Check if it was our validation or HA's validation that failed | COMMENT |
| LOW | tests/src/e2e/workflows/device_control/test_lights.py | 40 | # Check if this is a successful response with entity data | COMMENT |
| LOW | tests/src/e2e/workflows/core/test_history.py | 527 | # Check if requested types are in response | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/config/test_label_crud.py | 281 | # Assign label to entity | COMMENT |
| LOW | tests/src/e2e/workflows/config/test_helper_crud.py | 1098 | # Check if 'data' key exists (not 'success' key which doesn't exist in parse_mcp_result) | COMMENT |
| LOW | tests/src/e2e/workflows/config/test_helper_crud.py | 1117 | # Check if 'data' key exists (not 'success' key which doesn't exist in parse_mcp_result) | COMMENT |
| LOW | …s/src/e2e/workflows/filesystem/test_file_operations.py | 154 | # Check if we got the "not installed" error | COMMENT |
| LOW | …s/src/e2e/workflows/filesystem/test_file_operations.py | 594 | # Write file with nested directories | COMMENT |
| LOW | …s/src/e2e/workflows/filesystem/test_file_operations.py | 920 | # Check if the ha_mcp_tools service is actually available | COMMENT |
| LOW | tests/src/e2e/workflows/todo/test_lifecycle.py | 577 | # Check if any todo entities found | COMMENT |
| LOW | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1203 | # Check if it was our validation or HA's validation that failed | COMMENT |
| LOW | tests/src/e2e/workflows/scripts/test_lifecycle.py | 324 | if state_data.get("success"): # Check if state is accessible | CODE |
| LOW | tests/src/e2e/workflows/automation/test_helpers.py | 54 | # Check if we have valid entity data | COMMENT |
| LOW | tests/src/e2e/workflows/automation/test_helpers.py | 1145 | # Check if our test helper is in the results | COMMENT |
| LOW | tests/src/e2e/workflows/convenience/test_backup.py | 52 | # Check if backup password is configured | COMMENT |
| LOW | tests/src/e2e/workflows/convenience/test_backup.py | 124 | # Check if backup password is configured | COMMENT |
| LOW | tests/src/e2e/workflows/convenience/test_backup.py | 282 | # Check if error is about missing password | COMMENT |
| LOW | …sts/src/e2e/workflows/categories/test_category_crud.py | 247 | # Assign category to entity | COMMENT |
| LOW | …s/src/e2e/workflows/entities/test_entity_management.py | 52 | # Assign entity to area | COMMENT |
| LOW | …s/src/e2e/workflows/entities/test_entity_management.py | 96 | # Assign entity to area first | COMMENT |
| LOW | tests/src/e2e/error_handling/test_network_errors.py | 355 | # Check if partial success is reported | COMMENT |
| LOW | tests/src/e2e/utilities/wait_helpers.py | 170 | # Check if 'data' key exists (not 'success' key which doesn't exist in parse_mcp_result) | COMMENT |
| LOW | tests/src/e2e/utilities/assertions.py | 39 | # Check if this is an error response (isError=true from ToolError) | COMMENT |
| LOW | tests/src/e2e/utilities/cleanup.py | 242 | # Check if entity ID or name contains test patterns | COMMENT |
| LOW | custom_components/ha_mcp_tools/__init__.py | 927 | # Check if it's one of the explicitly allowed files in config root | COMMENT |
| LOW | custom_components/ha_mcp_tools/__init__.py | 931 | # Check if path starts with an allowed directory | COMMENT |
| LOW | scripts/install.sh | 250 | # Check if config file exists and handle accordingly | COMMENT |
| LOW | scripts/install.sh | 258 | # Check if ha-mcp is already configured | COMMENT |
| LOW | .github/workflows/_build-and-release.yml | 187 | # Check if release exists and is draft | COMMENT |
| LOW | .github/workflows/pr-validate-hotfix.yml | 39 | # Check if stable tag exists | COMMENT |
| LOW | .github/workflows/pr-validate-hotfix.yml | 60 | # Check if there are commits on master that are NOT in stable but ARE in the hotfix | COMMENT |
| LOW | .github/workflows/pr-validate-hotfix.yml | 72 | # Check if merge base is at or before stable | COMMENT |
| LOW | .github/workflows/pr-validate-hotfix.yml | 78 | # Check if stable is ancestor of merge base (hotfix branched after stable) | COMMENT |
| LOW | site/src/data/tools.json | 3346 | "description": "Evaluate Jinja2 templates using Home Assistant's template engine.\n\nThis tool allows testing and de | CODE |
| LOW | homeassistant-addon-webhook-proxy-dev/start.py | 947 | # Check if integration already loaded (user restarted fast) | COMMENT |
| LOW | homeassistant-addon-webhook-proxy/start.py | 947 | # Check if integration already loaded (user restarted fast) | COMMENT |
| LOW | src/ha_mcp/__main__.py | 741 | # Check if stdin is available (fails in Docker without -i flag) | COMMENT |
| LOW | src/ha_mcp/__main__.py | 197 | # Check if stdin is closed | STRING |
| LOW | src/ha_mcp/tools/tools_yaml_config.py | 461 | # Check if custom component is available | COMMENT |
| LOW⚡ | src/ha_mcp/tools/tools_traces.py | 476 | # Check if enabled (state is 'on' for automations, 'off' is disabled) | COMMENT |
| LOW⚡ | src/ha_mcp/tools/tools_traces.py | 486 | # Check if tracing is stored - only for automations | COMMENT |
| LOW | src/ha_mcp/tools/tools_filesystem.py | 435 | # Check if custom component is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_filesystem.py | 553 | # Check if custom component is available | COMMENT |
| LOW⚡ | src/ha_mcp/tools/tools_filesystem.py | 692 | # Check if custom component is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_filesystem.py | 816 | # Check if custom component is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_updates.py | 389 | # Check if rate limited | COMMENT |
| LOW | src/ha_mcp/tools/tools_updates.py | 451 | # Check if rate limited | COMMENT |
| LOW | src/ha_mcp/tools/tools_config_dashboards.py | 1749 | # Check if request failed (after potential retry) | COMMENT |
| LOW | src/ha_mcp/tools/tools_hacs.py | 324 | # Check if HACS is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_hacs.py | 388 | # Check if HACS is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_hacs.py | 468 | # Check if HACS is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_hacs.py | 518 | # Check if HACS is available | COMMENT |
| LOW | src/ha_mcp/tools/tools_utility.py | 1309 | {{ is_state('light.living_room', 'on') }} # Check if entity has specific state | STRING |
| LOW | src/ha_mcp/tools/tools_service.py | 331 | # Check if this is a timeout - for service calls, timeouts typically | COMMENT |
| LOW | src/ha_mcp/auth/provider.py | 595 | # Check if authorization request is expired (5 minutes) | COMMENT |
| LOW | src/ha_mcp/utils/operation_manager.py | 134 | # Check if operation has timed out | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/src/unit/test_oauth.py | 752 | # Step 5: Verify access token contains only ha_token (no ha_url - SSRF fix) | COMMENT |
| LOW⚡ | tests/src/unit/test_oauth.py | 758 | # Step 6: Use stateless refresh token to get new access token | COMMENT |
| LOW⚡ | tests/src/unit/test_oauth.py | 772 | # Step 7: Verify refreshed access token is valid and carries HA credentials | COMMENT |
| LOW⚡ | tests/src/unit/test_oauth.py | 779 | # Step 8: Verify chained refresh also works | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 682 | # Step 1: Client registration | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 696 | # Step 2: Authorization request | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 716 | # Step 3: Simulate consent form submission | COMMENT |
| LOW | tests/src/unit/test_oauth.py | 740 | # Step 4: Exchange auth code for tokens | COMMENT |
| LOW⚡ | tests/src/unit/test_flow_multistep.py | 355 | # Step 1: the user step | COMMENT |
| LOW⚡ | tests/src/unit/test_flow_multistep.py | 363 | # Step 2: the state_characteristic step — MUST receive its key, | COMMENT |
| LOW⚡ | tests/src/e2e/tools/test_create_custom_tool.py | 1053 | # Step 1: save a tool we'll then delete. | COMMENT |
| LOW | tests/src/e2e/tools/test_create_custom_tool.py | 1065 | # Step 2: delete it from inside the sandbox. | COMMENT |
| LOW | tests/src/e2e/tools/test_create_custom_tool.py | 1086 | # Step 3: confirm running it now fails (entry is gone). | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 350 | # Step 1: List automation blueprints | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 360 | # Step 2: List script blueprints | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 370 | # Step 3: If blueprints exist, explore one | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 436 | # Step 1: List available blueprints | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 451 | # Step 2: Get blueprint details to understand required inputs | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 460 | # Step 3: Create automation from blueprint (no trigger/action fields) | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 508 | # Step 4: Wait for automation to be registered, then verify no trigger/action fields | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/blueprints/test_blueprints.py | 516 | # Step 5: Clean up | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/system/test_system_tools.py | 716 | # Step 1: Check configuration (folded into ha_get_system_health) | COMMENT |
| LOW | tests/src/e2e/workflows/system/test_system_tools.py | 728 | # Step 2: Reload automations | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1174 | # Step 2: Get blueprint details to understand required inputs | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1183 | # Step 3: Create script from blueprint (no sequence field) | COMMENT |
| LOW | tests/src/e2e/workflows/scripts/test_lifecycle.py | 1229 | # Step 4: Wait for script to be registered, then verify no sequence field | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 373 | # Step 1: Discover light services (use full detail to see fields) | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 383 | # Step 2: Find a light entity to test with | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 400 | # Step 3: Use discovered service to control light | COMMENT |
| LOW⚡ | tests/src/e2e/workflows/services/test_list_services.py | 410 | # Step 4: Call discovered service | COMMENT |
| LOW | scripts/install.sh | 89 | # Step 1: Check/install uv | COMMENT |
| LOW | scripts/install.sh | 200 | # Step 3: Pre-download dependencies | COMMENT |
| LOW⚡ | scripts/install.sh | 239 | # Step 2: Configure Claude Desktop | COMMENT |
| LOW | scripts/install.sh | 372 | # Step 3: Pre-download dependencies | COMMENT |
| LOW⚡ | src/ha_mcp/tools/tools_integrations.py | 1856 | # Step 2: collect sub-entity IDs for the wait phase | COMMENT |
| LOW⚡ | src/ha_mcp/tools/tools_integrations.py | 1862 | # Step 3: delete the config entry | COMMENT |
| LOW | src/ha_mcp/tools/tools_integrations.py | 1746 | # Step 1: resolve target → entry_id (typed reason on failure) | COMMENT |
| LOW | src/ha_mcp/tools/tools_integrations.py | 1912 | # Step 4: wait for all sub-entities to be removed in parallel | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | pyproject.toml | 139 | "ASYNC", # async best practices | CODE |
| MEDIUM | pyproject.toml | 141 | "LOG", # logging best practices | CODE |
| MEDIUM | tests/haos_image_build/build_image.py | 186 | # The secret_path option must be set deterministically so the test harness | COMMENT |
| MEDIUM | tests/src/unit/_js_harness.py | 27 | # Path to the harness — repo-relative, resolved once at import time. | COMMENT |
| MEDIUM | tests/src/unit/_js_harness.py | 168 | # degrade to U+FFFD and surface in the harness's own error reporting. | COMMENT |
| MEDIUM⚡ | tests/src/unit/test_server_prefs_seed.py | 71 | # the harness result, but we can infer correctness by re-running the | STRING |
| MEDIUM | tests/src/unit/test_triage_prompt_budget.py | 141 | # min() rather than the first match so a future reorder of the harness | COMMENT |
| MEDIUM | tests/src/unit/test_tools_utility_supervisor_logs.py | 248 | # module attribute) is robust to either `import httpx` or a future | COMMENT |
| MEDIUM⚡ | tests/src/unit/test_build_skill_content.py | 115 | assert result == {"SKILL.md": "# best practices\n"} | CODE |
| MEDIUM | tests/src/unit/test_build_skill_content.py | 49 | (skill / "SKILL.md").write_text("# best practices\n") | CODE |
| MEDIUM | tests/src/unit/test_settings_ui_js_behavior.py | 454 | // assertion below — querying via JS is more robust than | COMMENT |
| MEDIUM | tests/src/unit/test_settings_ui_js_behavior.py | 485 | # flipped one. The harness's `responses: [...]` shape advances | STRING |
| MEDIUM | tests/src/unit/test_settings_ui_js_behavior.py | 2340 | # The harness serialises window globals into result.dom — pick | STRING |
| MEDIUM⚡ | tests/src/unit/test_helper_schema_inline.py | 511 | """The high-leverage simple-helper validation gates inside | STRING |
| MEDIUM | tests/src/e2e/tools/test_radio_management.py | 68 | # robust to exactly where they land. | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_search_entities.py | 1709 | # penalty → 80. Asserting ``< 100`` keeps the test robust to small | COMMENT |
| MEDIUM | tests/src/e2e/tools/test_deep_search_bulk_fetch.py | 120 | # failing setup — keeps the fixture robust if the WS path drops | COMMENT |
| MEDIUM | …/e2e/workflows/auto_backup/test_capture_and_restore.py | 515 | # ``replace`` ops on a path ending in ``/alias`` to stay robust | COMMENT |
| MEDIUM | tests/src/e2e/workflows/filesystem/test_yaml_config.py | 1437 | # robust whether the read fails because the file is missing or | COMMENT |
| MEDIUM | tests/src/e2e/workflows/system/test_system_tools.py | 783 | # Log comprehensive overview | COMMENT |
| MEDIUM | tests/src/e2e/workflows/automation/test_lifecycle.py | 131 | # Extract automation entity ID with robust error handling | COMMENT |
| MEDIUM⚡ | custom_components/ha_mcp_tools/ui_panel.py | 471 | # harness for every surface); coverage = the node --check syntax test plus the | COMMENT |
| MEDIUM | scripts/bake_pagination_seed.py | 38 | HOST_PORT = 32788 # off the dev-harness 32769 to avoid clashes | CODE |
| MEDIUM | .github/workflows/pr.yml | 285 | # (harness in tests/js/) — they spawn `node tests/js/harness.mjs` | COMMENT |
| MEDIUM | src/ha_mcp/settings_ui/__init__.py | 99 | # esbuild/jsdom JS harness (tests/js/harness.mjs) -- `const DEFAULT_PINNED = | COMMENT |
| MEDIUM | src/ha_mcp/tools/tools_bug_report.py | 527 | # Broad by design — the bug-report path must stay robust whatever the | COMMENT |
| MEDIUM | src/ha_mcp/utils/fuzzy_search.py | 465 | """Calculate a comprehensive fuzzy score for an entity name/domain. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/src/unit/test_settings_ui_js_behavior.py | 122 | # Full modal scaffold (mirrors settings.html) so the focus-trap | COMMENT |
| MEDIUM | tests/src/unit/test_e2e_wait_helpers.py | 3 | The test-side migration in #1382 added a WS-event-driven path to three | STRING |
| MEDIUM⚡ | tests/src/unit/test_tools_bug_report.py | 1688 | # what biases agents and invites hallucinations). | COMMENT |
| MEDIUM⚡ | tests/src/unit/test_tools_bug_report.py | 1696 | # hallucination bait we removed. | COMMENT |
| MEDIUM | tests/src/unit/test_tools_bug_report.py | 1518 | # hallucination-bait we removed. | COMMENT |
| MEDIUM | tests/src/e2e/haos_only/test_integration_setup.py | 59 | # substantial new test scaffolding; for now the integration-setup | COMMENT |
| MEDIUM | tests/src/e2e/workflows/config/test_ws_event_waiter.py | 2 | E2E regression coverage for #1152 — WS-event-driven entity-registration wait. | STRING |
| MEDIUM | tests/src/e2e/workflows/config/test_ws_event_waiter.py | 46 | """Regression coverage for the #1152 WS-event-driven waiter.""" | STRING |
| MEDIUM | tests/src/e2e/utilities/wait_helpers.py | 255 | # event-driven re-samples against the right baseline. | COMMENT |
| MEDIUM | tests/src/e2e/utilities/wait_helpers.py | 426 | PR #1382 for the broader event-driven-wait migration. | STRING |
| MEDIUM | tests/src/e2e/utilities/wait_helpers.py | 941 | # the sample-after-subscribe pattern the other event-driven waiters | COMMENT |
| MEDIUM | src/ha_mcp/config.py | 905 | # Bounds added purely as UI/POST guardrails (no Field constraint): | COMMENT |
| MEDIUM | src/ha_mcp/tools/util_helpers.py | 731 | # --- WS-event-driven wait helpers (#1152) ----------------------------------- | COMMENT |
| MEDIUM | src/ha_mcp/tools/util_helpers.py | 742 | # The new pattern is WS-event-driven with a REST sample after subscribe and a | COMMENT |
| MEDIUM | src/ha_mcp/tools/tools_hacs.py | 729 | # dominant cost in the HAOS E2E suite per #1515); 10 s still leaves event-driven | COMMENT |
| MEDIUM | src/ha_mcp/tools/tools_hacs.py | 819 | # we subscribed successfully but the event-driven path | COMMENT |
| MEDIUM | src/ha_mcp/tools/tools_utility.py | 444 | # the LLM context window during debugging workflows. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/uat/stories/run_story.py | 350 | CODE | |
| LOW | tests/src/unit/test_config_get_component_routing.py | 88 | CODE | |
| LOW | tests/src/unit/_js_harness.py | 114 | CODE | |
| LOW | tests/src/unit/test_component_ws_search.py | 129 | CODE | |
| LOW | tests/src/unit/test_component_ws_search.py | 315 | CODE | |
| LOW | src/ha_mcp/tools/tools_config_helpers.py | 4033 | CODE | |
| LOW | src/ha_mcp/tools/tools_energy.py | 379 | CODE | |
| LOW | src/ha_mcp/tools/tools_history.py | 136 | CODE | |
| LOW | src/ha_mcp/tools/backup.py | 1060 | CODE | |
| LOW | src/ha_mcp/tools/tools_search.py | 1379 | CODE | |
| LOW | src/ha_mcp/tools/tools_search.py | 1854 | CODE | |
| LOW | src/ha_mcp/tools/tools_search.py | 2613 | CODE | |
| LOW | src/ha_mcp/tools/tools_search.py | 3143 | CODE | |
| LOW | src/ha_mcp/tools/tools_traces.py | 48 | CODE | |
| LOW | src/ha_mcp/tools/tools_registry.py | 625 | CODE | |
| LOW | src/ha_mcp/tools/tools_config_automations.py | 459 | CODE | |
| LOW | src/ha_mcp/tools/tools_system.py | 513 | CODE | |
| LOW | src/ha_mcp/tools/tools_dashboard_screenshot.py | 108 | CODE | |
| LOW | src/ha_mcp/tools/tools_config_dashboards.py | 1268 | CODE | |
| LOW | src/ha_mcp/tools/tools_config_dashboards.py | 1822 | CODE | |
| LOW | src/ha_mcp/tools/tools_voice_assistant.py | 378 | CODE | |
| LOW | src/ha_mcp/tools/tools_utility.py | 407 | CODE | |
| LOW | src/ha_mcp/tools/tools_utility.py | 1175 | CODE | |
| LOW | src/ha_mcp/tools/tools_integrations.py | 301 | CODE | |
| LOW | src/ha_mcp/tools/tools_addons.py | 909 | CODE | |
| LOW | src/ha_mcp/tools/tools_addons.py | 1491 | CODE | |
| LOW | src/ha_mcp/tools/tools_addons.py | 2670 | CODE | |
| LOW | src/ha_mcp/tools/tools_entities.py | 1409 | CODE | |
| LOW | src/ha_mcp/tools/smart_search/_deep.py | 33 | CODE | |
| LOW | src/ha_mcp/tools/smart_search/_deep.py | 953 | CODE | |
| LOW | src/ha_mcp/tools/smart_search/_deep.py | 1039 | CODE | |
| LOW | src/ha_mcp/tools/smart_search/_overview.py | 19 | CODE | |
| LOW | src/ha_mcp/dashboard_screenshot/capture.py | 776 | CODE | |
| LOW | src/ha_mcp/transforms/categorized_search.py | 203 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-compose.screenshot.yml | 52 | # Usage: | COMMENT |
| LOW | docker-compose.yml | 31 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/src/unit/test_config.py | 389 | monkeypatch.setenv("SUPERVISOR_TOKEN", "fake-token-for-test") | CODE |
| LOW | tests/src/unit/test_config.py | 426 | monkeypatch.setenv("SUPERVISOR_TOKEN", "fake-token-for-test") | CODE |
| LOW | src/ha_mcp/tools/tools_bug_report.py | 1444 | - Email addresses -> Replace with "user@example.com" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/src/unit/test_python_sandbox.py | 330 | expr = "def helper():\n return 1" | CODE |