github goruck/home-generative-agent v3.44.0

2 hours ago

Summary

Before upgrading

  • The Critical Action PIN is now accepted only in your reply to the PIN prompt. A PIN in the request itself ("unlock the front door, PIN 1234") no longer confirms it. An automation that puts the PIN in the text it sends to conversation.process must send it as a second message in the same conversation.
  • A PIN saved by an earlier version in non-Latin digits no longer confirms. Save it again in Global Options.

Safety

  • Opening a garage door, gate or door cover by voice or chat now asks for the PIN. Your own protected-action rules for valves, buttons and scripts now apply to voice commands too (#770).
  • The PIN prompt says exactly what your PIN will run, and the reply says whether it ran, failed or may have run.
  • A PIN can no longer be supplied by the model or confirm an action requested at another voice satellite.
  • A level-increase PIN set in Sentinel Basic setup is now enforced (#762).
  • The agent can no longer read the history of devices hidden from Assist (#716).

New

  • House notification cooldown: one event seen by several cameras sounds once instead of once per camera (#721).
  • The Sentinel proposals card is translated into Czech (#697).

Reliability

  • A fallback chain moves on when a provider doesn't have the configured model (#752, #759).
  • The integration recovers by itself after its database was unreachable at startup or reload (#748).
  • Setup on your own PostgreSQL server explains what to fix when pgvector isn't ready (#756).
  • Scripts and other tools stay usable when the tool index is unavailable, and an Ollama embedding model that was never pulled is reported (#757).

Fewer and clearer Sentinel pushes

  • A standing condition no longer re-alerts every 30 minutes (#723).
  • A large group of findings no longer arrives as one push after another.
  • Open-door and open-window pushes name the door or window (#729).
  • Low-battery and other discovery-approved rules have readable subtitles (#696).

History answers

  • History questions no longer miss events by several hours (#719).
  • The agent no longer says "I don't have access to the history" when it does (#715).

Details

Added

  • New option House notification cooldown (video_analyzer_house_notification_cooldown_s, 0 = off, up to 60 seconds, in Global Options) for the video analyzer (#721). The camera notification cooldown works per camera, so one event seen by several cameras, such as people walking past the house, still made every camera's first notification sound a second or two apart. With the house cooldown set, a camera notification that sounds starts a short window for all cameras: notifications from other cameras inside it still post their own card, with their own description and image, but quietly. A camera made quiet this way then stays quiet for its own camera cooldown (or the house cooldown, if longer), counted from the sound that covered it; with the camera cooldown off, every camera, including the one that sounded, is quiet for the house cooldown. With face recognition on, the first Unknown Person in the window still sounds, once, whichever camera sees it. It works with the per-camera cooldown on or off, needs a single companion-app notify service (notify.mobile_app_*), is verified on iOS only (on Android a quiet card may still sound), and is a time window only, so two unrelated events on different cameras within it sound once. Start around 15 seconds: each camera's clip is analyzed separately, so on slower vision hardware one event reaches the cameras' notification decisions 10 to 30 seconds apart, and the reporter's setup grouped nothing at 5 seconds and every walk-past at 15; see House notification cooldown.

  • The Sentinel proposals card now follows your Home Assistant profile language: Czech when the profile is set to Czech, English otherwise (other languages fall back to English). Section titles, buttons, field labels, progress and error messages, the dedupe reasons, and the known proposal statuses are translated at display time; unknown statuses and reasons are shown as they are. Candidate titles and summaries are shown as the discovery model wrote them, untranslated, and the text pre-filled into a GitHub rule request stays English. Long candidate ids now wrap inside the card instead of overflowing a narrow panel. The browser caches the card for up to a month, so after updating, bump the query string on the card's dashboard resource URL (or hard-refresh) to see the change (#697, #714, @hruba202).

Fixed

  • Opening a garage door, gate or door cover by voice or chat now asks for the Critical Action PIN. With the recommended protected actions on, "open the garage door" ran at once when the agent used Home Assistant's on/off command (HassTurnOn), which is how it normally controls a cover: the PIN check needed a service name, such as open_cover, and that command carries none, so only an automation or a direct service call that opened the door was held. The check now works out what Home Assistant will do with the command: it finds the devices the command targets the way Home Assistant does (by name, alias, area or floor, reading a number such as floor 1 the way Home Assistant does), and checks each one with the service Home Assistant runs for it: on opens a cover or a valve and off closes it, on presses a button, "set position" sets a cover's or a valve's position, and "stop" stops one. So a garage door is held whether the agent names it, gives its entity id, or names only its area or floor, and a door named without "door", "gate" or "garage" is held when its entity id has one; closing a door, and opening blinds or a window, still run without a PIN. A command the check cannot read is held. A lock named without "lock" ("Front Door") with no device type is held too, as an unlock. Your own protected actions for other devices now apply to these commands as well, such as a rule for button.press on a garage-opener button, valve.open_valve, light.turn_on, or a script's own service (script.open_garage, which turning the script on runs). The PIN prompt now names what Home Assistant will do in these cases: "unlock "Front Door"" rather than "turn off "Front Door"", "open "Garage Door"" rather than "turn on", "press "Garage Opener"", "set "Garage Door" to 100%" for a position, and for a command over a whole area or floor with several kinds of device, every action it takes and the place: "lock every lock in Shed, open every cover in Shed", "unlock every lock in Porch, turn off every light device in Porch". A lock command for floor 0 or area 0 now keeps that floor or area; before, the number was dropped and the command went to every lock in the home (#770).

  • The Critical Action PIN now has to come from you, in your reply to the PIN prompt. Before, the model could supply it itself: once you had given the PIN, it stayed in the conversation, so when a confirmed action (unlocking a lock, disarming the alarm, opening a cover) failed, the model could confirm it again, or request it again and confirm the new prompt, without asking you. A device that half-acted before reporting the failure, such as an alarm arm that timed out, could act twice. A small local model was also seen confirming with a PIN it made up before you had answered, using up one of your attempts. Now, when you ask for a protected action, the agent asks for the PIN, and only your next message can confirm it: a reply with a number that is exactly the PIN, written ("1234", "1,234"), said in groups ("12 34") or read out digit by digit ("1, 2, 3, 4", or spoken digit words in English or Czech: "one two three four", "jedna dva tři čtyři"); digits typed in other scripts (full-width, circled, Arabic-Indic) count too. A PIN in the request itself ("unlock the front door, PIN 1234") no longer confirms; you are asked for it. An automation that passes the PIN in the text it sends to conversation.process needs to send it as a second message in the same conversation. This is what stops text the model reads while handling your request (a camera description, a device name, a tool result) from starting a different protected action that your PIN would then run. Any other reply cancels the prompt ("never mind", a question, another request), so a number that happens to equal the PIN later in the conversation cannot confirm it. A PIN the model supplies any other way is refused without counting an attempt, and a correct PIN refused this way is logged as a warning. A longer number that contains the PIN ("12345", "555 1234", "1, 2, 3, 4, 5", a phone number read digit by digit) does not count, and neither does a date, time, decimal, measurement, range or address ("2024-10-14", "12:34", "12.34", "1234.56 kWh", "50%", "555 - 1234", "1.2.3.4"); say only the PIN, since "1 2 3 4, 2 doors" reads as 12342. A number on its own that equals the PIN does count, whatever you meant by it. One message is one attempt and confirms one action. While you are still answering, your next message can answer the prompt again: after a wrong PIN, a PIN that could not be read (the agent asks you to say the digits one by one), your request said again, or a reply whose turn failed with an error; at most three replies per prompt, and five wrong PINs per request. If the action fails, the reply says so and you ask again; if it fails in an unexpected way after starting, or the confirmation takes longer than 25 seconds, the reply says it may have run and to check the device. An automation whose install fails after you confirm it now always says it may have been installed, so check your automations before asking again. One protected request at a time: a new request replaces one still waiting in the same conversation, and a second protected request in the same message is refused with a note to ask for it after the first; for two doors, ask for and confirm each in turn. Two confirmations sent together no longer both run. A pending action can also no longer be confirmed from another conversation: voice satellites and automations all run as the same user, so before, a PIN said at one satellite could confirm an unlock requested at another. A Critical Action PIN entered in full-width, circled or Arabic-Indic digits is now stored as ASCII digits, and one in digits that cannot be read as ASCII is refused. A PIN saved by an earlier version in non-Latin digits no longer confirms: save it again in Global Options.

  • The PIN prompt now says, in fixed words, which action your PIN will confirm: "Your PIN will confirm: unlock "Playroom Door Lock"." After the PIN, the reply says how it ended: "PIN accepted: unlock "Playroom Door Lock"." when it ran, "PIN accepted, but unlock "Playroom Door Lock" failed." when the device refused, and "PIN accepted; unlock "Playroom Door Lock" may have run. Check the device." when it ended in an unexpected error or a timeout. The lines come from the action being held, not from the model, and are spoken on voice satellites; they go in front of the model's reply, so the reply still ends with its question and a satellite keeps listening for the PIN. The verb is the one Home Assistant runs for the device: lock or unlock a lock, open or close a cover or valve, turn a switch on or off, whatever the model wrote. A request that names no device says what it covers ("unlock every lock", "unlock every lock in Garage", "on floor Upstairs"), because that is what Home Assistant does with it; a confirmed lock command that gave only an entity id now runs on that one lock, as the unconfirmed path always did, instead of on every exposed lock. An automation is named by its alias and by the protected calls inside it: "add the automation "Lock up at night", which runs lock.unlock (lock.front_door)". A prompt counts only once its line has been delivered: a request whose turn was interrupted or failed before the reply has to be made again. Before, only the model described the action, and it could be wrong. In a field test, "lock the playroom lock" was heard as "Block the playroom, block". The model then called the command that unlocks a lock while asking for the PIN "to lock the playroom door", and after the PIN it said "now locked". The door was unlocked. That happened because the tool search offered only one of Home Assistant's two on/off commands (HassTurnOff, which unlocks a lock), so the model's first, correct call (HassTurnOn, which locks) was rejected as not available. The two commands are now always offered together, per Home Assistant API and also when one of them is an always-included tool, unless you excluded one. If the model confirms with the id of a request it has since repeated, the conversation's one waiting request is the one it means, so the PIN is not refused. When the reply does not end with a question (the model wrote "Please enter the PIN."), or the fixed line is the whole reply, "What is your PIN?" is added, so a satellite keeps listening: Home Assistant keeps the microphone open only after a reply that ends with a question mark. The command the prompt is waiting for stays available to the model while it waits, so a request the model repeats in your reply (after a wrong PIN, for example) is not refused as unavailable. Two small changes to how lock and other on/off commands are sent to Home Assistant follow from this: a command that names an area or floor but no device now keeps that area or floor (before, a lock command for "the garage" was sent for every lock), and a command that gives an entity id but no name is sent for that one device (Home Assistant ignores entity ids on these commands and would have acted on every device of the kind). A lock command with the right name and a wrong area now fails instead of acting on the named lock. A lock command that gave only an entity id and a name without "lock" in it was not PIN-gated at all; it is now. English and Czech.

  • The PIN prompt is spoken once, and the turn no longer ends in "I wasn't able to complete this request after several tool-use attempts" when the model tries to confirm a protected action before you have given the PIN. The PIN is accepted only from your reply to the prompt, so a model that confirms in the request turn with a PIN of its own (a local model did this three times in one turn, repeating "please provide your security PIN" each time) was refused each time until the tool-round limit cut the turn off with that apology, and the fixed "Your PIN will confirm: …" line came only after it. The turn now ends at the first such refusal, with the fixed line and "What is your PIN?" as the reply, so a satellite keeps listening. A wrong PIN now also gets a fixed sentence, "That PIN was incorrect.", before the prompt (and "Make the request again." when no reply is left), so you are told even when the model says nothing useful. When the tool-round limit is still reached on a refused confirmation while a PIN line is the reply, no apology is added; and the calls the limit cuts off now get a "not run" result, so the next message (your PIN, for one) is not rejected by a model provider over an unanswered tool call.

  • A model fallback chain now moves on to the next provider when a provider does not have the configured model. Before, an Ollama model that was never pulled, or a model name a provider does not offer, answered with a "model not found" error that stopped the whole chain, so a fallback that would have worked was never tried, and every later call stopped at the same provider. This held for chat, camera image analysis, summarization and embeddings, and for the primary as well as the fallbacks: with the primary embedding model not pulled, long-term memory search and the tool index failed on every turn even with a working embedding fallback configured. The chain now skips such a provider, counts it toward the circuit breaker, and logs an ERROR saying the provider does not have the configured model, so a typo or an unpulled model on the primary stays visible while a fallback covers for it. Other errors, such as a rejected API key, still stop the chain. The repair issue for a missing Ollama embedding model now says a fallback takes over (#752, #759).

  • Home Generative Agent no longer stays down after its database was unreachable during startup or a reload. If PostgreSQL was not up yet, for example the PostgreSQL with pgvector app starting after Home Assistant on a cold boot, or it restarted while the integration reloaded (an options save, or the automatic reload after a model provider comes back), setup failed for good and the integration stayed in "Failed to set up" until it was reloaded by hand. Setup now tells Home Assistant to retry, so it recovers on its own once the database is back: during Home Assistant startup the first retry comes once startup finishes, and after that it waits 5 seconds at first and longer each time, up to every 10 minutes. Saving corrected settings in the Database subentry reloads the integration at once instead of waiting for the next retry. The integration card shows why, using the server's own message: "Cannot reach the PostgreSQL database yet: connection failed: connection to server at …, port 5432 failed: Connection refused" (or "password authentication failed …" for a wrong password, which is retried the same way, since PostgreSQL's messages can be translated and a database that is still starting up reads like a refusal). Before, the log showed only a pool timeout, 30 seconds later, whatever the cause. An error that is not about reaching the database, such as a failed schema migration or an index pgvector cannot build, still fails setup as before, and an unknown option in the Database subentry's extra connection parameters now fails setup with its own message. A database user name or password containing @, /, :, ?, # or % now works: it was put into the connection address unencoded, so the connection failed and part of the password could show in the error (#748).

  • A level-increase PIN entered in Sentinel Basic setup is now enforced. Before, it was checked and stored, but Basic setup left "Require PIN for autonomy level increases" off, so sentinel_set_autonomy_level raised the autonomy level, including to the levels that let Sentinel act on its own, without asking for it, and nothing was logged. Saving a PIN in Basic or Advanced setup now turns the requirement on. A PIN stored by an earlier version is enforced after the update with nothing to redo: re-running Basic setup keeps it, and the Advanced form shows the checkbox as on. To remove the PIN, open Advanced setup, uncheck the box and leave the PIN field blank. Three related gaps are closed too. With the PIN on, asking for the level you already have no longer restarts its timer, so a raised level now always runs out after sentinel_runtime_override_ttl_minutes (60 by default) unless renewed with the PIN; lowering the level still needs no PIN. A raised level now ends when the integration reloads, for example when Sentinel options are saved, so turning the PIN on also ends a level raised before it existed; a level you lowered is kept until it runs out. Returning to your configured level after lowering it, and lowering the level with an out-of-date PIN in the call, no longer need the current PIN. Advanced setup no longer saves "Require PIN for autonomy level increases" with no PIN stored, which refused every increase: it now asks for the PIN, including when the form comes back after an error in another field with the PIN box cleared (a setup already saved that way now gets an error naming the fix, "Sentinel requires a PIN to raise the autonomy level, but none is set. Set one in Sentinel setup (Advanced), or turn off 'Require PIN for autonomy level increases'.", instead of asking the caller for a PIN) (#762).

  • Setup on your own PostgreSQL server no longer fails with only a raw PostgreSQL error when pgvector is not ready. HGA needs the vector extension enabled in its own database, and an extension enabled in a different database does not count (CloudNativePG's postInitSQL runs in the postgres database, not yours). Before this, setup failed with permission denied to create extension "vector", or with type "vector" does not exist when no embedding model was configured. Setup now checks first and enables the extension itself when its user is allowed to. Otherwise it fails with a message on the integration card that names the database and gives the CREATE EXTENSION IF NOT EXISTS vector; to run there once as a superuser; the integration's user does not need to be a superuser itself. A server without pgvector at all gets its own message. The new Using your own PostgreSQL section covers both (#756).

  • The agent could not use your exposed scripts, or any tool past the first few, while its tool index was unavailable, and an Ollama embedding model that was never pulled went unreported. Without working embeddings HGA cannot rank tools by meaning, and its fallback then bound the first 5 tools (the retrieval limit) in the order Home Assistant lists them, whatever you asked; Home Assistant lists scripts after its built-in tools, so the model said it had no access to them. The fallback now ranks every available tool by the words its name and description share with your request, so "run the door history script" finds that script, while a request to control something still keeps three of the five slots for control tools such as HassTurnOn; the log line now reads Tool retrieval using keyword-ranked fallback and says how many tools matched (it used to say "keyword-filtered", but nothing was filtered). The most common cause, an Ollama embedding model that is not installed on the server, is now caught. Saving the Embeddings feature with an Ollama provider checks the model against that server and any Ollama fallback servers, and shows an error naming the ollama pull command (names are compared the way Ollama resolves them, and submitting the same name again saves it anyway). A startup where any reachable Ollama server that embeds, fallbacks included, lacks the model raises a repair issue under Settings → System → Repairs naming the server; it clears on the first reload after the model is pulled. An Ollama embedding model of the wrong vector size fails the same quiet way, since the memory store keeps the vector size it was created with (1024 by default; nomic-embed-text produces 768): the form now reads both sizes and refuses a mismatch (submitting again overrides it), and startup raises a repair issue for a wrong-size primary and a separate one for a wrong-size Ollama fallback (#757, reported in #755).

  • Sentinel pushes about an open door or window now name it in the subtitle, for example "Breakfast Nook Center Right Window open" (Czech: "Breakfast Nook Center Right Window: otevřeno"), instead of "Open entry while away". The push body is often the model's explanation, and it could leave the device out: on one install, two pushes 24 minutes apart about two windows in the same room read "the window in the breakfast nook", so the second looked like a duplicate. This covers the built-in open-entry-while-away rule and rules approved from the open-entry templates (open entry while away, when home, or at night, and any window open at night while away). The name is the device's friendly name, with control and invisible characters removed and capped at 64 characters, and it is used only for a door, window or cover, so an approved rule that picked a lock or a window heater by its name never calls it "open". The "…open, alarm disarmed" subtitle now uses the friendly name too, and the "open for 3 h" subtitle of a rule approved from the "in a state too long" template now says "open" only for a door, window or cover and "unlocked" only for a lock; a motion sensor that has been on for 3 hours reads "unchanged for 3 h" (#729).

  • Sentinel no longer re-alerts a standing condition every 30 minutes. A rule that fires once something has been in a state too long (for example, a lock unlocked for more than 2 hours, approved from discovery) gave its alert a new identity on every check, because the identity included the elapsed time. So the "already alerted, waiting for your response" guard, which holds a repeat for 4 hours (sentinel_pending_prompt_ttl_minutes), never matched it. Each time the 30-minute cooldown ran out, it pushed again, and because it was grouped with related alerts on the same device, the push often repeated one of those instead. On one install an unlocked garage door lock pushed every 30 minutes for about 9 hours. The identity now changes only when the condition starts again. When related findings are grouped into one push, the push now shows a finding that is actually due, the most severe one first, rather than the most confident one even if it was already sent or held back, so a confident low-severity alert no longer hides a high-severity one in the same group. Only the finding the push shows waits out the 4-hour guard; a related finding it did not show becomes due again after its cooldown and is shown next, unless a more severe one in the group is due again, instead of staying hidden behind its partner for 4 hours. The same identity fix applies to rules that fire when a sensor has stopped reporting for too long. Replaying three days of one install's alerts removes about a fifth of the pushes; most of the rest are new events, such as a camera sighting or a door opening (#723).

  • Sentinel no longer sends a push for each finding in a large group, one after another. When related findings are grouped into one push, the push showed only one of them, and since the #723 fix each other finding came due again after its 30-minute cooldown and got its own push. On one install, with nobody home and five windows open, a group of 15–17 findings sent 10 pushes in two hours, each about a different window. The push now ends with a line naming the devices of the group's other due findings, for example "Also: Kitchen Window, Landing Window +2 more" (Czech: "Také: …"), and every finding it names waits out the same 4-hour "already alerted" hold as the shown one. The line has its own 120-character budget, so the alert text above it is never cut, and a push carrying it is never held back for the burst summary. A finding is named only when it is the same type of finding as the shown one, all its own devices are on the line (a device the shown finding also has, such as the alarm panel, is not repeated), no other device in the home shares its name, it goes to the same phone as the shown finding (per-area routing), and Sentinel would not act on it automatically. Any other finding still comes due on its own and gets its own push, so nothing is hidden: a stranger on camera or an unlocked lock grouped with an open door is never reduced to a device name. Findings about the same door or window as the shown one are folded in by their condition, for example "Also: Garage and Play Room Windows (open while home, alarm disarmed, open too long)" when they come due in the same run; this covers the open-entry, alarm-disarmed-with-open-entry and open-too-long rules, and any other approved rule on that window still gets its own push. Each rule still keeps its own reminder clock, so a window that stays open all night can still get a push from each rule at a different time (#736). The buttons still act on the shown finding only. A response to a grouped push is now recorded on the audit record of the push it answered, not on a later push that showed a different finding from the same group (#727).

  • Sentinel pushes from a rule approved from discovery no longer show a bare number as their subtitle (for example "1" for a rule named candidate_1). The rule's subtitle came from its internal name with the candidate_ prefix removed, and some approved rules have nothing else in their name. Rules built on the "in a state too long" template (such as a window open for over 2 hours) now name the device, its state and how long, for example "Breakfast Nook Side Right Window open for 3 h" or "Garage Door Lock unlocked for 2 h" (Czech: "…: otevřeno 3 h", "…: odemčeno 2 h"; other states read "unchanged for", "beze změny"), and use "Unchanged too long" (Czech: "Příliš dlouho beze změny") in the batch summary and snooze confirmation, rules built on the night-motion-while-disarmed template read "Motion at night, alarm disarmed" (Czech: "Pohyb v noci při vypnutém alarmu"), and any other rule whose name leaves no words reads "Sentinel alert" (Czech: "Upozornění Sentinelu"). These pushes became visible once grouped alerts started showing the finding that is due (#723).

  • Sentinel no longer logs "Audit store at capacity ... Consider increasing audit_hot_max_records" as a warning on every finding. A home that gets more alerts than the audit store holds (500 by default) fills it with notified findings, and from then on dropping the oldest one is normal, so this is now one INFO line. The audit store is also no longer rewritten in full on every finding: on a busy home it is several megabytes, so this was about 2 GB of writes a day, which wears an SD card or SSD. Findings are now written within 15 seconds of the first unsaved one, so a burst shares one write; a record of an action Sentinel took and your responses to alerts are still written immediately, and records of actions taken are kept over plain notifications when the store is full. A push the notifier dropped as a repeat of the same alert within its own cooldown is now recorded as notifier_duplicate rather than as having reached you, so the daily digest and the Sentinel health sensor's notification counts no longer include it.

  • The agent could read the history of devices you had hidden from Assist. Its history lookup searched every entity by name, so anyone at a voice satellite could ask, for example, when a person tracker last changed or when an unexposed lock was opened, as long as they knew the device's name. History questions now resolve only entities exposed to Assist, and a hidden device gets the same "not found" answer as one that does not exist. The agent's entity-id lookup no longer "corrects" a guessed id to a hidden device's real id either. If you ask about the history of a sensor Home Assistant does not expose by default (a power meter, a battery level, a leak or smoke sensor), expose it under Settings → Voice assistants → Expose (#716).

  • History answers could miss events by several hours. The history tool asked the model for times with a UTC offset, but the model only ever sees the local clock time and a timezone name, so it guessed the offset, and on one install it labelled local times as UTC in 4 of 14 calls. A question such as "did I leave this morning?" then searched from 5 PM the previous day to just before 7 AM and answered that nobody had left. History times are now read as the home's local time, and any offset the model adds is ignored, which also keeps winter (standard-time) windows from shifting by an hour.

  • The agent no longer answers a history question with "I don't have access to the history" when tool retrieval left the history tool out. A question phrased around the device ("When did the mudroom lights turn off today?") ranked the turn-off and date/time tools above get_entity_history, and nothing told the model its tools are a per-request subset, so it reported a missing capability. Questions about past states ("when did", "how many times", "how long has", "last time", "history", a span like "in the last hour" or "past 24 hours", or a past-tense question with a time reference like "today", "yesterday", "last week" or "at 8 pm") now always bind the history tool, on top of the retrieval limit, and so does the follow-up turn ("And yesterday?"). For any other retrieval miss the system prompt now tells the model its tools are a subset, so it says it could not find a suitable tool and suggests rephrasing; an error or empty result from a tool it did call is handled as before (retried when it can be corrected, otherwise reported). The intent patterns are English-only; other languages rely on ranking and the new prompt line (#715).

  • Sentinel pushes for a low-battery rule approved from discovery now carry a readable subtitle, "Low battery" (Czech: "Slabá baterie"), in place of the rule's internal id ("V1 subject sensor predicate low battery night any"). The low_battery_sensors template had no curated label, so the subtitle, the batch summary, the snooze confirmation, and the explanation text used as the push body when the model call fails fell back to the slugified rule id (#696, @hruba202).

Don't miss a new home-generative-agent release

NewReleases is sending notifications on new releases.