Skip to content

Conversation

frenck
Copy link
Owner

@frenck frenck commented Sep 25, 2025

Description

fixes #1068

Motivation and Context

How has this been tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Other

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

@frenck frenck added the bugfix Inconsistencies or issues which will cause a problem for users or implementors. label Sep 25, 2025
Copy link

coderabbitai bot commented Sep 25, 2025

📝 Walkthrough

Walkthrough

Propagates a hass: HomeAssistant parameter through automation and script unknown-entity repairs and shared util functions. Updates template/config extraction signatures and call sites to be hass-aware, and adds regex-based filtering of known Home Assistant services during template parsing to avoid misclassifying service names as entities.

Changes

Cohort / File(s) Summary
Automation repairs: hass-aware extraction
custom_components/spook/ectoplasms/automation/repairs/unknown_entity_references.py
Adds hass parameter to extraction functions; updates calls to hass-aware config/template extractors; adjusts control flow to source config via hass.
Script repairs: hass-aware extraction
custom_components/spook/ectoplasms/script/repairs/unknown_entity_references.py
Introduces typed HomeAssistant import (TYPE_CHECKING); adds hass parameter to extract_template_entities_from_script_entity; updates internal calls to pass hass.
Utilities: hass-threaded template/config parsing and service filtering
custom_components/spook/util.py
Changes signatures to include hass across template/config extraction helpers; propagates hass through processing; adds regex extraction that filters out known services from hass; updates async_extract_entities_from_config and related helpers.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant AutomationRepair as Automation Repair
  participant ScriptRepair as Script Repair
  participant Util as util.py
  participant HA as hass (HomeAssistant)

  User->>AutomationRepair: async_inspect()
  AutomationRepair->>Util: async_extract_entities_from_config(hass, config)
  Util->>Util: parse config, collect template strings
  Util->>Util: async_extract_entities_from_template_string(hass, str)
  Util->>Util: extract_entities_from_template_regex(hass, str)
  Util->>HA: get known services
  Util->>Util: subtract services from found tokens
  Util-->>AutomationRepair: entity_ids (services filtered)
  AutomationRepair-->>User: unknown entity references

  User->>ScriptRepair: async_inspect()
  ScriptRepair->>Util: async_extract_entities_from_config(hass, config)
  Util-->>ScriptRepair: entity_ids (services filtered)
  ScriptRepair-->>User: unknown entity references
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

In wires and whispers I hop and I peep,
Found “turn_on” ghosts I shouldn’t keep.
With hass at my side, I sift and I see,
Services aren’t specters—let entities be.
Tap-tap my paws, the scan is clean—
No more phantoms in the template machine! 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly describes the primary fix of preventing service actions from being misidentified as entities and directly reflects the bug addressed in the pull request without extraneous detail or vague wording. It clearly communicates the main change from the developer’s perspective, enabling a reviewer to quickly grasp the intent. This aligns with the changes focused on filtering service calls out of the entity extraction process.
Linked Issues Check ✅ Passed The pull request threads the HomeAssistant context through all template entity extraction utilities and explicitly filters out known services via hass, thereby preventing service action names like switch.turn_on and switch.turn_off from appearing as unknown entities. These changes implement the core requirement of issue #1068 by subtracting known service identifiers from the extracted entity set. The modifications fully satisfy the linked issue’s objective of eliminating these false positives.
Out of Scope Changes Check ✅ Passed All alterations are confined to automation and script repair modules and the util.py helper functions responsible for template parsing and regex-based entity extraction. No unrelated code paths, tests, or documentation have been modified, and every change directly supports the service-action filtering objective. There are no out-of-scope changes present.
Description Check ✅ Passed The description references the correct issue number (#1068) which aligns with the bug being fixed and therefore remains on topic. Although it lacks detailed implementation or testing information, it still relates directly to the changeset. The lenient criteria require only that the description is not completely unrelated, which it is not.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch frenck-2025-0402

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@frenck frenck merged commit 679cd55 into main Sep 25, 2025
17 of 18 checks passed
@frenck frenck deleted the frenck-2025-0402 branch September 25, 2025 15:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
custom_components/spook/util.py (2)

83-91: Restricting entity domain regex to a fixed list risks missing custom domains (false negatives)

Using KNOWN_DOMAINS in _DOMAIN means entity IDs from custom integrations (and possibly core domains not listed) won’t be detected in templates. That undermines the repair’s ability to catch unknown entities outside the curated list.

Prefer HA’s canonical entity-id domain pattern (same as _OBJECT_ID) or derive domains dynamically from current entity_registry/states:

-# Modified _DOMAIN pattern to only match known domains
-_DOMAIN = r"(?:" + "|".join(KNOWN_DOMAINS) + r")"
+# Domain: same pattern as HA core uses for object IDs (allow any valid domain)
+_DOMAIN = _OBJECT_ID

This still pairs well with your service filtering and avoids missing real entity references from custom domains.


400-413: Bug: floors filter uses label IDs instead of floor IDs

known_floor_ids defaults to async_get_all_label_ids, which is incorrect and will misclassify floors.

Apply:

-    if known_floor_ids is None:
-        known_floor_ids = async_get_all_label_ids(hass)
+    if known_floor_ids is None:
+        known_floor_ids = async_get_all_floor_ids(hass)
custom_components/spook/ectoplasms/automation/repairs/unknown_entity_references.py (1)

26-43: New hass-aware automation template extractor

Approach is sound. Same docstring note: it mentions RenderInfo but returns regex-only results via util.

Align docstring or add RenderInfo extraction for parity with the description.

🧹 Nitpick comments (3)
custom_components/spook/util.py (2)

499-533: Filtering out known services from regex matches fixes the false positives

This directly addresses #1068 by subtracting hass-known services. LGTM.

Optional: normalize to lowercase for both sets to be extra safe against any case variance (entities are lowercase by convention, but templates may vary):

-    known_services = async_get_all_services(hass)
-    return entities - known_services
+    known_services = {s.lower() for s in async_get_all_services(hass)}
+    return {e.lower() for e in entities} - known_services

670-697: hass-aware config extraction

Good change and correct forwarding to the hass-aware template extractor. Consider minor optimization: pass a precomputed known_services set into regex extraction if you end up calling it in tight loops (micro).

custom_components/spook/ectoplasms/automation/repairs/unknown_entity_references.py (1)

223-258: Template value extraction now hass-aware

Correctly routes template strings through hass-aware extractor; fallback for dotted strings preserved. Consider filtering out known services here too as a belt-and-braces (rare, but harmless).

-        elif "." in value and not value.startswith("!"):
+        elif "." in value and not value.startswith("!"):
             # Check if it looks like an entity ID
-            entities.add(value)
+            entities.add(value)

(If you adopt this, subtract known services via util before adding.)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3438a07 and 4428a26.

📒 Files selected for processing (3)
  • custom_components/spook/ectoplasms/automation/repairs/unknown_entity_references.py (4 hunks)
  • custom_components/spook/ectoplasms/script/repairs/unknown_entity_references.py (5 hunks)
  • custom_components/spook/util.py (9 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
custom_components/spook/ectoplasms/automation/repairs/unknown_entity_references.py (1)
custom_components/spook/util.py (5)
  • async_extract_entities_from_config (670-696)
  • async_extract_entities_from_template_string (471-496)
  • async_filter_known_entity_ids_with_templates (583-625)
  • async_get_all_entity_ids (190-223)
  • is_template_string (464-468)
custom_components/spook/ectoplasms/script/repairs/unknown_entity_references.py (1)
custom_components/spook/util.py (3)
  • async_extract_entities_from_config (670-696)
  • async_filter_known_entity_ids_with_templates (583-625)
  • async_get_all_entity_ids (190-223)
🔇 Additional comments (9)
custom_components/spook/util.py (2)

562-571: hass propagated into template-string processing

Good propagation; consistent with the new signatures.


472-496: async_extract_entities_from_template_string: all call sites updated All invocations now pass both hass and template_str.

custom_components/spook/ectoplasms/script/repairs/unknown_entity_references.py (4)

14-17: Updated util import: hass-aware call path

Importing the hass-aware extractor is correct for the new flow.


19-21: TYPE_CHECKING HomeAssistant import

Nice to keep runtime surface clean while retaining type hints.


76-76: Forwarding hass into config extractor

Correct fix; leverages service filtering from util.


145-147: Call site updated to pass hass

Consistent with new signature. LGTM.

custom_components/spook/ectoplasms/automation/repairs/unknown_entity_references.py (3)

15-20: Imports updated to hass-aware utilities

Good; is_template_string reuse keeps logic centralized.


45-73: Config-level extraction flow

Breakdown across trigger/condition/action is clear and avoids scanning “service” fields, preventing the original false positives.


305-307: Call site updated to pass hass

Matches new signature. LGTM.

Comment on lines +54 to 57
async def extract_template_entities_from_script_entity(
hass: HomeAssistant, entity: Any
) -> set[str]:
"""Extract entities from script configuration using Template analysis.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

hass added to extractor signature; docstring overpromises RenderInfo

Function returns regex-based results via util, not RenderInfo. Either update the docstring or implement RenderInfo-based extraction here.

I can provide a RenderInfo-based implementation if desired.

🤖 Prompt for AI Agents
In
custom_components/spook/ectoplasms/script/repairs/unknown_entity_references.py
around lines 54 to 57, the docstring falsely claims the function returns
RenderInfo while the implementation actually returns a set of entity IDs
extracted via the regex-based util; update the docstring to accurately state
that the function returns a set[str] of entity ids extracted using the util
(e.g., util.extract_entities_from_template or the specific helper used), include
expected input (hass, entity) and format of output, or alternatively replace the
current extraction logic with a RenderInfo-based implementation by calling Home
Assistant's async render-info helpers (async_get_render_info /
template.async_render) and deriving entities from the RenderInfo object — pick
one approach and make the docstring consistent with the chosen implementation.

Comment on lines +536 to 550
hass: HomeAssistant,
template: Template,
known_entity_ids: set[str],
unknown_entities: set[str],
) -> None:
"""Process a Template object and add unknown entities to the set."""
template_entities = set()

# Use regex patterns on the template string
try:
if hasattr(template, "template") and template.template:
regex_entities = extract_entities_from_template_regex(template.template)
regex_entities = extract_entities_from_template_regex(
hass, template.template
)
template_entities.update(regex_entities)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Template processing only uses regex; docstring mentions RenderInfo

Docstring implies RenderInfo/Template.async_render_to_info(), but only regex extraction is used here. Align docs or add RenderInfo-based extraction if intended.

Happy to draft a RenderInfo-based pass to complement regex for higher fidelity.

🤖 Prompt for AI Agents
In custom_components/spook/util.py around lines 536 to 550, the function
docstring promises RenderInfo-based extraction but the code only uses regex; add
a RenderInfo pass to complement regex by attempting to call
template.async_render_to_info(...) (awaiting it), extract entities from the
returned RenderInfo (e.g., render_info.entities or render_info.extract_entities)
and update template_entities with those, catching and ignoring any exceptions
and falling back to the existing regex extraction; ensure the call is guarded
with hasattr(template, "async_render_to_info") and that you await it properly,
then keep the regex step as a fallback so both sources are combined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix Inconsistencies or issues which will cause a problem for users or implementors.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Spook sees action names in templates as unknown entities
1 participant