From f6166f25d95434c00bc9fbbc8ea3beb8e6cf1cc0 Mon Sep 17 00:00:00 2001 From: orchestrator-agent Date: Sat, 19 Sep 2026 14:50:59 -0400 Subject: [PATCH] Compare celebration stamps as whole entries; queue events Child ids sharing a prefix no longer suppress each other (split and compare entries for equality), and queued mode keeps a second child's day-complete event from being dropped while the first notify runs. --- .../automation/day_complete_celebration.yaml | 13 +++++++++---- tests/test_blueprint_celebration.py | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/custom_components/nestquest/blueprints/automation/day_complete_celebration.yaml b/custom_components/nestquest/blueprints/automation/day_complete_celebration.yaml index 9165a84..3672adc 100644 --- a/custom_components/nestquest/blueprints/automation/day_complete_celebration.yaml +++ b/custom_components/nestquest/blueprints/automation/day_complete_celebration.yaml @@ -60,7 +60,7 @@ blueprint: filter: - domain: input_text -mode: single +mode: queued variables: celebrate: !input celebrate @@ -74,12 +74,17 @@ conditions: - condition: template value_template: "{{ celebrate | bool }}" # Once-per-child-per-day dedupe: celebrate only when THIS child has - # no entry for today in the helper. An unset or missing helper reads - # as '' and celebrates. + # no equal entry for today in the helper. Entries compare as whole + # comma-separated tokens — a substring check would wrongly suppress + # child 1 after child 11 was celebrated. An unset or missing helper + # reads as '' and celebrates. - condition: template value_template: >- {{ (trigger.payload.child_id ~ ':' ~ now().strftime('%Y-%m-%d')) - not in (states(last_celebrated_helper) or '') }} + not in ((states(last_celebrated_helper) or '') + .split(',') + | select('ne', '') + | list) }} actions: - action: !input notify_target diff --git a/tests/test_blueprint_celebration.py b/tests/test_blueprint_celebration.py index e86eca4..9d61277 100644 --- a/tests/test_blueprint_celebration.py +++ b/tests/test_blueprint_celebration.py @@ -255,4 +255,20 @@ def test_celebration_never_hard_codes_notify_target() -> None: assert re.search(r"notify\.[a-z_]+", target_description), ( "the input description should show a placeholder example" ) - assert bp["actions"][0]["action"] == BlueprintInput("notify_target") \ No newline at end of file + assert bp["actions"][0]["action"] == BlueprintInput("notify_target") + +def test_celebration_dedupe_entry_equality_not_substring() -> None: + """Child ids sharing a prefix must not suppress each other: after + child 11 is celebrated, child 1 still celebrates (whole-entry + comparison, not substring).""" + assert render_dedupe("11:2026-09-19", child_id=11) == "False" + assert render_dedupe("11:2026-09-19", child_id=1) == "True", ( + "child 1's entry must not be found inside child 11's entry" + ) + assert render_dedupe("1:2026-09-19", child_id=11) == "True" + + +def test_celebration_mode_is_queued() -> None: + """Two children completing at nearly the same time must both be + processed: queued mode does not drop the second event.""" + assert celebration()["mode"] == "queued"