Skip to content

fix: a Calendar Condition sensor follows its calendar to the next event, matching its user by name or slot - #1789

Merged
raman325 merged 6 commits into
mainfrom
fix/calendar-condition-follows-events
Oct 28, 2026
Merged

raman325 merged 6 commits into
mainfrom
fix/calendar-condition-follows-events

Conversation

@raman325

@raman325 raman325 commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

Breaking change

The Calendar Condition blueprint no longer takes a free-form condition template. It has a Match choice and an optional Match text field instead. After re-importing the blueprint:

  • A sensor that never set a condition template keeps working as Any event, which is what its old default {{ true }} meant.
  • A sensor that set its own condition template becomes unavailable, so its user's PIN stays inactive until you choose a Match. That includes one that spelled out {{ true }}: the blueprint can't read the stored template back to tell a default from a real filter.
  • A templated slot number (for example one read out of the event description) is no longer evaluated per event. Use the "slot N" in the event description match with the user's own slot number instead.

What to do: re-import the blueprint, then open each Calendar Condition sensor and choose a Match. For a rule the choices don't cover, make your own template binary sensor and use it as the condition entity.

Proposed change

The Calendar Condition blueprint matched its user against the event that was current when the sensor loaded. A state-based template entity renders its variables once at startup (homeassistant/components/template/template_entity.py:478-481), and the event attributes, the user's name and the condition result were all variables. On one shared booking calendar, the first guest's sensor stayed on through every later booking, and the next guest's never turned on until template entities were reloaded.

The fix: everything that can change now lives in the state: template. Home Assistant tracks every entity a state template reads, so the sensor updates as soon as the calendar moves to another event or the user is renamed, with no timer. If state: fails to render, the sensor goes unknown: with an availability template present, Home Assistant sets the state to none rather than making the sensor unavailable. Only on makes a PIN active, so that leaves it inactive.

That rules out a free-form condition template: a blueprint !input replaces a whole YAML value (annotatedyaml/input.py:43-56), so a user's template can only reach the event through variables, which are frozen. The template is replaced by:

Match The sensor is on while the current event…
Any event is any event
User's name in the event title has the user's name in its title
User's name in the event description has the user's name in its description
"slot N" in the event description says slot 3, for the user on slot 3 (slot 12 doesn't count as slot 1)

Match text narrows any of them: the title or description must also contain it. Names match as whole words and ignore case, so test1 doesn't match test10 and Al doesn't match Alice. Match text is a plain substring, so clean finds Cleaning. A user the sensor can't find (no such slot, or the name entity unavailable and so without attributes) matches no event. An empty name would otherwise be in every title.

Why Match has a default of "not set" rather than being required: a blueprint instance missing an input raises MissingInput, a HomeAssistantError (blueprint/errors.py:73). The template integration only skips entries that raise vol.Invalid (template/config.py:444), so one stale sensor without Match would stop every template entity in the user's configuration from loading. I reproduced this with a second, unrelated template entity. The default instead keeps old sensors that never filtered working, and fails closed only for those that did.

An earlier version of this PR made the blueprint trigger-based with a one-minute backstop. Review found it failed open, keeping its last state when a template errored, and it needed the timer. This version needs neither.

Tests: tests/test_blueprint_behavior.py

  • Each Match choice and Match text (17 cases): case-insensitive, whole-word names (test10 isn't test1), names between punctuation, slot 12 not matching slot 1, title versus description, text narrowing a name match.
  • A state template that fails to render leaves the sensor unknown, not on.
  • Follows a shared calendar from one guest's event to the next and back, with no reload.
  • Follows a rename at once.
  • A user it can't find matches no event.
  • Unavailable with its calendar.
  • Upgrade: no condition template → any event; a custom template, or an explicit {{ true }} → unavailable; choosing a Match brings a sensor with an old template back.

Mutations checked, each failing at least one test: substring name matching, the empty-name guard, the exact slot match, case-folding, Match text, treating an old template as any event, the availability check on Match, and freezing the event title in variables (the original bug).

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:

🤖 Generated with Claude Code

The blueprint matched its condition template against the event that was
current when the sensor loaded, because a state-based template entity
renders its variables once at startup. On a shared booking calendar the
first guest's sensor stayed on through later bookings and the next guest's
never turned on until template entities were reloaded.

Make it trigger-based, which renders the variables after every trigger: the
calendar's state or attributes changing, Home Assistant starting, template
entities reloading, and once a minute as a backstop for a user renamed just
after their booking starts and for templates that read the time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 11565057bfa8
Copilot AI balanced review requested due to automatic review settings October 27, 2026 03:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@github-actions github-actions Bot added python Pull requests that update Python code documentation Documentation changes blueprints Changes to shipped automation blueprints bug Something isn't working labels Oct 27, 2026
…es empty

A trigger-based template entity skips the update when a variable fails to
render, so the sensor kept its last state. The documented slot_number
example goes empty when the event ends and int raised, leaving a past
guest's sensor on. int(0) finds no user instead.

Guard the shared-calendar example with name_state and, since name_state is
empty when the name entity can't be found and an empty string is in every
message. Document that a condition template that raises keeps the sensor
where it was, and double the backslash in the regex examples.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 1f9f13140e49
@codecov

codecov Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.89%. Comparing base (23a3464) to head (cc941b2).
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1789   +/-   ##
=======================================
  Coverage   98.89%   98.89%           
=======================================
  Files          72       72           
  Lines       10299    10299           
  Branches      569      569           
=======================================
  Hits        10185    10185           
  Misses        114      114           
Flag Coverage Δ
python 99.38% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Replace the free-form condition template with a Match choice (any event,
the user's name in the title or description, or "slot N" in the
description) and optional Match text, evaluated in the state template. A
state-based template entity tracks everything its state template reads, so
the sensor follows the calendar and a rename at once, and a render error
makes it unavailable, which leaves the PIN inactive.

Match defaults to "not set" rather than being required: a blueprint
instance missing an input raises MissingInput, which the template
integration doesn't catch, so it would stop every template entity from
loading. A sensor from before Match that never set a condition template
keeps working as any event; one that set its own is unavailable until it
has a Match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: cd13dbe43947
@raman325 raman325 changed the title fix: a Calendar Condition sensor follows its calendar to the next event fix: a Calendar Condition sensor follows its calendar to the next event, matching its user by name or slot Oct 27, 2026
@github-actions github-actions Bot added breaking-change Pull requests that break existing functionality and removed bug Something isn't working labels Oct 27, 2026
A plain substring match turned one user's sensor on for another user's
event: test1 during test10's, Al during Alice's. Normalise punctuation and
spacing on both sides and match the name between word boundaries.

Say what a render error does: the sensor goes unknown, not unavailable,
because the availability template takes precedence. Update the two
BLUEPRINTS.md passages that still described a templated slot number for
the Calendar Condition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 3d6a10be98e9
raman325 and others added 2 commits October 27, 2026 21:20
The blueprint still declares the condition template input so an old
sensor that set one goes unavailable instead of failing to load, so the
inputs table documents it and the breaking note no longer says it is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 7300de11f870
@raman325
raman325 merged commit 7021133 into main Oct 28, 2026
17 of 18 checks passed
@raman325
raman325 deleted the fix/calendar-condition-follows-events branch October 28, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blueprints Changes to shipped automation blueprints breaking-change Pull requests that break existing functionality documentation Documentation changes python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants