fix(naming): Recreate entity IDs proposes what the panel says now - #256
Closed
cayossarian wants to merge 4 commits into
Closed
fix(naming): Recreate entity IDs proposes what the panel says now#256cayossarian wants to merge 4 commits into
cayossarian wants to merge 4 commits into
Conversation
Renaming a circuit in the SPAN app left "Recreate entity IDs" offering the entity its own ID, so the button appeared to do nothing (#252). The registry generates an ID from the user's `name` override, else `suggested_object_id`, else `object_id_base`. Friendly-names mode writes no registry `name` -- the panel name arrives as `original_name` -- so the suggestion decides, and `construct_single_circuit_entity_id` was handing back the entity's stored ID on every reload. The suggestion was therefore frozen at whatever the circuit was called the day it was added. It now computes the ID from current panel data and the naming flags, for existing entities as much as new ones. That cannot move a live entity ID: an entity_id set before add is only a suggestion, and for a unique_id already on file `async_get_or_create` routes to `_async_update_entity` with no `new_entity_id` before `entity.entity_id` is reassigned from the stored entry. Unique IDs are untouched -- they derive from the description key and never read a name. Circuit-numbers mode is deliberately unchanged, guarded by a test. There the registry `name` phase 2 sync writes is both what shows the panel's name in the UI and what outranks the suggestion, so Recreate keeps composing from that name. Correcting it would mean rerouting phase 2 sync, which is a product decision, not part of this fix. The registry lookup was the only use of the `unique_id` argument, and `existing_entity_id` the only use of that parameter on `_construct_entity_id`; both are gone rather than left as parameters that no longer decide anything. Every test reloads before asserting -- asserting straight after creation exercises the first-add path, where the suggestion is trivially current and the bug cannot appear. The three that demonstrate the bug fail on the previous code; the five guards pass on both.
cayossarian
force-pushed
the
fix/recreate-entity-ids
branch
from
August 23, 2026 04:19
fb7d857 to
87c640e
Compare
Cut from the entity-id branch so the "Recreate entity IDs" fix gets field time before it merges. Carries span-panel-api 3.0.1 and both adapters at 1.0.0.
Both are outward facing and neither was recorded. Written against 2.1.0, not a beta -- the changelog describes the public release, and the steps between betas are not what a reader is looking for.
Recreate offered 74 renames on a real panel after the previous beta: every circuit energy sensor, `_consumed_energy` to `_energy_consumed`. Only one of the 74 was a circuit the owner had renamed, and that one was buried. Installs predating the point where the suffix mapping reached entity ids took their id from the descriptor name, so they carry `_consumed_energy` while their own unique id carries `_energy_consumed`. The two have disagreed all along; recomputing the suggestion is what made the disagreement visible. The descriptor rename is not the cause and reverting it would not have removed a single offer: in friendly-names mode the registry holds no `name`, so `suggested_object_id` -- our suffix-based preset -- outranks `original_name` and the descriptor name never reaches the id. Measured both ways; the proposal is `_energy_consumed` either way. So an existing entity keeps the suffix it shipped with and only the circuit-name half of its id follows the panel. `LEGACY_ENTITY_ID_SUFFIXES` records the older spellings; comparing with the suffix removed means a renamed circuit still gets the computed id, which is the whole point of #252. A trailing segment that merely looks like a suffix change -- "Kitchen Outlets" renamed to "Kitchen" -- is a rename and is still offered. `_construct_entity_id` takes `existing_entity_id` again. It no longer decides whether to compute an id, only which suffix the computed one carries. Four tests, two of which fail with preservation disabled. The earlier ones all built their entities with current code, where preset and live id are the same string by construction and this could not appear -- which is why it reached a beta.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #252.
Renaming a circuit in the SPAN app left "Recreate entity IDs" offering the entity
its own ID, so the button appeared to do nothing.
Cause
The registry generates an ID from the user's
nameoverride, elsesuggested_object_id, elseobject_id_base. Friendly-names mode writes noregistry
name— the panel name arrives asoriginal_name— so the suggestiondecides.
construct_single_circuit_entity_idwas handing back the entity'sstored ID on every reload, which HA recorded as the suggestion, so the field was
frozen at whatever the circuit was called the day it was added.
Fix
It now computes the ID from current panel data and the naming flags, for existing
entities as much as new ones.
The three constraints, and why each holds
entity_idset before add is only asuggestion:
EntityPlatformsplits it intosuggested_object_id, and for aunique_idalready on fileasync_get_or_createroutes to_async_update_entitywith nonew_entity_id, then reassignsentity.entity_idfrom the stored entry. Structural, not a matter of care.a name. Untouched here.
namewritesites are gated on
USE_CIRCUIT_NUMBERS, and nothing in that mode changes.Circuit-numbers mode is deliberately unchanged
There the registry
namephase 2 sync writes is both what shows the panel's namein the UI and what outranks the suggestion during regeneration — one write, two
effects. So Recreate in that mode keeps composing from the name rather than the
tab-based ID. That is pre-existing, and a test pins it so this change cannot
disturb it. Correcting it means rerouting phase 2 sync, which is a product
decision recorded in the design doc, not part of this fix.
Cleanup
The registry lookup was the only use of the
unique_idargument, andexisting_entity_idthe only use of that parameter on_construct_entity_id.Both are removed rather than left as parameters that no longer decide anything.
Tests
Eight new cases, all reloading before asserting — asserting straight after
creation exercises the first-add path, where the suggestion is trivially current
and the bug cannot appear. Three demonstrate the bug and fail on the previous
code (sensor suggestion,
async_regenerate_entity_id, breaker switch); five areguards that pass on both (entity ID unmoved, unique ID unmoved, unrenamed circuit
offered its own ID, circuit-numbers mode unchanged).
1261 passing, up from the 1253 baseline. Full
prekhook set green, mypy strictand vulture included.