Skip to content

Dobby v0.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 16 Sep 16:32
· 16 commits to main since this release

0.2.0 - 2026-09-16

Dobby now knows thirty-one device types, every writable one has a control on its card, and the house answers questions about its own past and keeps watch on standing rules. Linux tarballs for amd64 and arm64 are attached, and this version runs one database migration before its first start.

Added
  • Fifteen appliance types: dishwasher, oven, cooktop, microwave, refrigerator, wine cooler, ice maker, coffee maker, washer, dryer, water heater, humidifier, dehumidifier, air purifier, and range hood. Ten of them only read: Dobby can say whether the dishwasher is running, when the washer finishes, and what the refrigerator is holding. Five take a hand: the water heater's setpoint and mode, a humidifier's or dehumidifier's target and mode, and the speed and power of the air purifier and range hood. The example house file binds each one to Home Assistant, with the Home Connect bindings a real kitchen reported
  • Each appliance has its own word on the board. A read-only appliance says AWAKE with its reading beside it, the way the sensors do. A writable one says SET with the value somebody asked for. Still eight words: an appliance in the middle of a cycle would want a ninth, and does not get one yet
  • The rig house holds a water heater and a dishwasher, one writable and one read-only, so the eval tier can put an appliance in front of a real model. Two scenarios do: "is the dishwasher running?" and "set the hot water to 125"
  • Dobby can answer questions about recorded household events: who changed a device, when something last happened, how many times, and which commands did not arrive. Dates and counts come from the house clock and the record, never from the model
  • The household can ask Dobby to keep watch: a condition that holds for a stated time, or no recorded change for a stated time, all day or in a daily window. Dobby proposes the exact rule in words, waits for agreement in a later message, and only then watches. A breach is said once in the thread and stands above it until acknowledged. Rules only report; they never change a device
  • Standing rules can be added, paused, resumed, and deleted on The House page, with an undo, and no model involved
  • Dobby knows the house's date, time, and clock offset when it answers, so a question about a named day ("what happened on September 1st?") reaches the record as that day
  • The house file can pin the one OpenRouter endpoint that serves the model (system.provider), with no fallback to another, so the first word arrives from the same place every time instead of wherever OpenRouter's routing lands that minute. Set it on /admin or in the file; it takes effect at the next reply, and a pin the model in force cannot take is refused and named, the way routing is
  • A paid eval sweeps every endpoint under a model and times each one to its first token, so the pin is a measurement
  • Every request records what it cost: model turns, input, output, cached, and reasoning tokens, and the end to end, on its own row in the record. The activity feed on /admin shows them on the request's line, and the eval tier prints the cache read and the thinking beside the tokens it already printed
  • Every writable device takes a hand on its card. Only the thermostat had a control on The House; thirteen writable types had none. A device now says what a hand may do to it, and the card draws that. A fader between the two ends the device reported: the water heater's setpoint, a humidifier's or dehumidifier's target, a fan's, purifier's, or hood's speed, and a dimmable light's brightness. A row of the device's own words: the water heater's mode, away mode, and power; a humidifier's mode and power; power on the fan, purifier, hood, light, and switch; the lock's lock and the garage's close. Every bound is read from what the device reported and none is invented on the card. A card cannot set the hot water to 200°F: it is held with the heater's own reason and nothing reaches Home Assistant. No model is involved, and the thread says who did it
  • The choice row is a new part of the design, and DESIGN.md carries its section. The word the device holds is written in the record voice and is not a button, because the board never offers to set a thing to what it already says. The others are the quiet underlined verbs; tapping one commits at once and offers the undo line for the same eight seconds a fader does. Power is the same part with two words, ON · off, which reads as a row and not a toggle. A row with nothing left to offer is not drawn: a locked door already says Locked, and unlock and open are on no surface
  • The vacuum's start and stop and the shade's move have no control on the card yet. A verb with no argument is neither a number between two ends nor one attribute's words, and the card has no part for it
Changed
  • Every timestamp Dobby is handed is already on the household's clock, and the house block says so. A doorbell that rang at 3:41 PM in New York was handed to the model as 19:41 with an offset to apply, which is arithmetic, and two models read it back as 7:41 PM. The conversion now happens once, where the house is rendered for the model, and the device agents still hold exactly what Home Assistant said
  • Every status tool names the device the same way. Four appliance tools named it under a different key from the rest of the library, which is a contract that lies to the model about what a device reference is called
  • A whole reading stays whole: the refrigerator reports 38, not 38.0. A finish time reads on the household's clock rather than as a Z-stamped string. A door reads in whatever case the integration sends
  • Dobby is told, before every turn, what each device can be watched for and which standing rules and notices exist, so asking for a rule no longer costs a turn spent reading the list first: a proposal is two model turns, and so is a pause or an acknowledgment
  • A rule added on The House page takes its id from its name, the way Dobby writes one from the thread: "Warm room" becomes warm-room in the house file, where it used to be a UUID. A second rule with a name that makes the same id is refused and says so, rather than replacing the first
  • Dobby remembers what was said in the thread and forgets what it fetched to say it: earlier requests' tool calls and their results leave the conversation it carries to the model, while the words stay. The record still holds every row, and a rule or device proposal awaiting agreement is listed before every turn with the id its confirmation takes, so saying yes a message later still lands
  • A card's second line is the device's other number, not the time its row flipped. The row carries what somebody asked for and the detail carries what the device reads: the water heater says the tank's water, a humidifier says the room's air, an oven says its target under its temperature. A type with no second number keeps "Since 4:12 PM"
  • A fader's bounds sit on the device's own step, so a humidifier target the device would refuse cannot be reached from the card. A fan's fader is in whole percent, and Home Assistant snaps to the nearest notch
Fixed
  • The house stops crediting a person with its own commands. Home Assistant echoes a value at the entity's own precision, and one service call moves several attributes at once. A Fahrenheit setpoint on a Celsius house came back two hundredths off and cost two lines: NOT KNOWN for a command that had arrived, and a thread line saying somebody walked up to the heater. A three-speed fan asked for 50 answered 66 and did the same. Turning the water heater off moved its mode and its power together, and the thread wrote "changed at the hot water" under Dobby's own reply. Arrival is now judged at half of Home Assistant's own reporting step, or one notch on a fan, and a command names every attribute it explains
  • A device going quiet is not somebody turning it off. A fan dropping off the network wrote "changed at the air purifier" into the thread, naming a person for a Wi-Fi blip. Stopped answering goes in the log and nowhere else
  • A Home Assistant restart is not somebody at the door. Every outage rang the doorbell twice in the thread and handed the model the word "unavailable" as a time
  • An intervention line names the attribute that moved. A hand on the fan's speed dial used to report "On", because power outranked speed
  • A device event during a Home Assistant restart no longer loses its confirmation and becomes a false NOT KNOWN
  • An attribute nobody had reported yet wrote the word "Nil" on the board, and the board capitalised a Home Connect cycle name into "Delayedstart"
  • The example house bound a Home Connect washer's remaining time, which Home Connect never reports. It binds the finish time now
  • The model catalog Dobby ships with now knows GLM 5.3 and GLM 5.3 Flash (LLMDB 2026.9.1, ReqLLM 1.22), so a house naming either boots without a warning per reply and with the model's pricing, context, and capabilities on record. GLM 5.3 is not yet a model in force: its paid tool-streaming and judgment evals have not run
  • A date the household names ("what did you record on January 5th?") reaches the record as that date, and the house places it on its own clock. Dobby was told to add the clock's offset itself, and in winter it added summer's
  • Asking Dobby for a rule whose name a standing rule already has now says which rule the new one would replace before asking for agreement, instead of quietly replacing it on yes
  • A slow moment in the rules watcher or the database no longer ends a thermostat request or leaves the thread waiting; the house block says the rules were not readable that second and the reply goes on
  • The rules watcher survives a database restart while a rule is recovering, where it used to crash and, restarting into the same outage, could take the house down
  • Dobby's conversation memory keeps what was said and no longer keeps an earlier turn's whole chain of thought, and it no longer mistakes a message the model runtime injects for something a person said
  • A house file whose rules: key has nothing under it boots as a house with no rules. The board no longer opens on an empty plate before Home Assistant has reported. Older request rows in the activity feed say "cost not recorded" rather than shouting their action
  • The record's rows reach Dobby on the house's own clock rather than in UTC, so a door that unlocked at 11:10 PM is no longer read as 3:10 AM by a model doing the conversion in its head
  • Dobby is shown each device's last known state before every turn. It had been told "state not yet known" for every device since the first release, and asked the device for its status before answering; a question the board could already answer no longer costs that extra round trip
Tech-Debt/Refactor
  • The direct control path goes through the device type, not a central switch. Every type declares its controls, and a tap finds its action in the type's own schedulable surface exactly as a schedule firing does, with the browser's value typed by the same coercion a schedule row goes through. The thermostat moved onto the new path with its tests unchanged
Upgrade and Migration
  • Run the database migration for rule proposals and occurrences before starting this version. Rule definitions live under house.rules in the house file; the guide's house page shows the shape
Verification
  • The paid hot-water scenario captured "Hot water set to 125°." with the tool call and the Home Assistant call exactly as asked. The humidifier and ventilation rigs read the thread after issuing real commands, and the ventilation one found the quiet-device bug on its first run
  • mix precommit before merge: 664 tests, 0 failures, the paid evals excluded. The 22 record-and-rules scenarios ran against two real models through OpenRouter, GPT-5.6 Luna and GLM 5.2, 22 of 22 on both. The tools were reshaped until the replies read as the house should: "The vacuum was last recorded starting cleaning Thursday, September 3, at 7:35 AM." The provider sweep that chose the pins timed 62 endpoints across three models, one run each. In the browser at phone and desktop widths: the notice under the board, the standing-rule line in the thread, and the rules panel on The House, console clean
  • Each writable type is tested through the rig in the shape of turning the dial: the command reaches Home Assistant, the thread says who did it, a way back is offered. The choice row and the detail line were looked at in the browser on every card of the rig house, which is how the empty-row rule was found

What's Changed

  • The house answers questions about its past, keeps standing rules, and carries less per turn by @mhyrr in #22
  • The house understands its appliances, and stops crediting a person with its own commands by @mhyrr in #23
  • Every device that can be commanded takes a hand from its card, and no type is named on the way by @mhyrr in #24

Full Changelog: v0.1.0...v0.2.0