Repository navigation
Releases: mhyrr/dobby
Releases · mhyrr/dobby
Release list
Dobby v0.2.0
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/adminor in the file; it takes effect at the next reply, and a pin the model in force cannot take is refused and named, the wayroutingis - 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
/adminshows 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-roomin 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'...
Dobby v0.1.0
0.1.0 - 2026-09-04
The first tagged release. Linux tarballs for amd64 and arm64 are attached to it, and the guide's box chapter covers installing one.
Added
- Three pages:
/is the shared thread, with a board of device rows above the conversation./houseshows every device with its controls; a control offers an undo after it acts, never a confirm dialog before./adminshows health, schedules, the topology of the running house, and the full activity log. A name entered on a browser is remembered on that browser. It labels who said what; it is not a login - The Home Assistant client: one WebSocket connection owning authentication, subscriptions, service calls, and reconnect. Dobby starts whether or not Home Assistant is reachable, including a host that accepts the connection and then stalls
- Sixteen device types: thermostat, light, speaker, camera, doorbell, lock, access cover, power switch, shade, fan, environment monitor, contact sensor, occupancy sensor, safety sensor, vacuum, and wifi endpoint. Types are semantic, not per vendor: Home Assistant owns the integrations and credentials, Dobby owns what each type may do. Permissions are per action: the lock can report and lock but not unlock, the garage door can report and close but not open. Discovery groups a doorbell's event, camera, and motion entities into one proposal and never offers a diagnostic entity
- The house file:
home.yamlis read, validated, and written back. An editor, the/houseand/adminforms, Dobby proposing a device in the thread, and an agent over MCP all write the same file. Credentials areenv:references, never values. If the file is missing, the error names the variable that pointed at it - MCP: the full tool set at
/mcpfor an external agent, behind bearer tokens minted and revoked on/admin. Each token has a label, and the label is recorded as the speaker on every call. Tested end to end with Claude Code as the client - Command confirmation: every accepted command becomes an expectation with a per-type deadline, checked by code with no model call. If the device reports the change, the board updates. If Home Assistant refuses the call, a HELD line is written beneath Dobby's reply. If nothing is reported by the deadline, one NOT KNOWN line is written and the board shows NOT KNOWN. A reply that made no tool call is marked
asked nothing of the house hands_only: trueon a device: the model may read it and may not command it, from the thread, from MCP, or through a schedule the model created. Card taps and schedules made on/adminstill work- Models: Dobby answers through OpenRouter. GPT-5.6 Luna is the default and GLM 5.3 Flash is the second model.
reasoningandroutingare settings inhome.yaml, in effect at the next reply. A setting the current model does not accept is refused at boot and on save - Releases:
mix release, with migrations run before every start under systemd. GitHub Actions builds tarballs for Linux amd64 and arm64 from av*tag. Tested on a Debian 12 VM: install, reboot, and an upgrade with two seconds of downtime - The guide: nine pages at mhyrr.github.io/dobby. Every example of output on those pages comes from a real run
- Eval tests: twelve scenarios run the sixteen types against a real model, and a second model judges each reply against a rubric. A separate test derives, per device type, which Home Assistant services each tool is allowed to call
Changed
- Replies after a command: Dobby may state the commanded value as done ("Coffee station's on, Greg"), because HELD or NOT KNOWN is written beneath the reply if the command did not arrive. It still may not report a reading it never took or a command it never sent
- Two people asking for different settings: Dobby carries out both in order and tells the second person what the first asked for, instead of stopping to ask which to keep
config/soul.mdno longer contains an example reply to a command. The last one changed the wording of five replies while every test stayed green. What a reply may claim is decided in code
Fixed
- An activity row could record a tool call against no device when the completion event arrived before the start event. Events now carry a sequence number, and a finished step can no longer show as running
- A slow Home Assistant could crash the confirmation watcher and lose every pending expectation. The watcher no longer calls into a device agent that is blocked on a service call; each expectation carries its own snapshot, taken before the call
- A finished turn could disconnect the thread page: the end-of-turn broadcast had no handler in the LiveView
- In production, the LiveView socket refused a page opened by IP address. The origin check now uses the connection's own host
dobby.localon Linux:avahi-publishwithout-Rcollided with avahi-daemon's own reverse record
Security
- MCP tokens are stored as SHA-256 digests and shown once, at minting
- The test environment reads no environment variables, so a stale
DOBBY_*export cannot pointmix testat a real house - The release build's ignore file is an allowlist, so
.envand the local Home Assistant's storage never enter a build
Upgrade and Migration
- First release. Six migrations create
schedules,speakers,messages,activity_entries,device_proposals, andmcp_tokens. The installed service runs them before every start
What's Changed
- Dobby v0.10: Single app, runtime config, capability discovery by @mhyrr in #1
- Phase A step 4: the household surface by @mhyrr in #2
- The real house: HA client, new device agents, the topology, and a board that fits a hand by @mhyrr in #3
- One config story: a file anybody — or any agent — can write by @mhyrr in #4
- A library of common device agents for the Home Assistant world (TK-014) by @mhyrr in #5
- A missing home file names the variable that chose it by @mhyrr in #6
- A named browser is not asked twice, and switching really switches (TK-012) by @mhyrr in #7
- The turn stops trusting the order its two tool events arrive in (TK-008) by @mhyrr in #9
- The house boots while Home Assistant is still deciding whether to answer (TK-017) by @mhyrr in #8
- The whole library meets a real model, and a second one reads the reply back (TK-030) by @mhyrr in #10
- The doctrine learns that most devices are not thermostats by @mhyrr in #11
- The judge gets principles to reason from, not rules to match by @mhyrr in #12
- Dobby says what it did in its own voice by @mhyrr in #13
- Dobby answers through OpenRouter, with GLM 5.3 Flash as the second model by @mhyrr in #14
- The house declares intent, reports outcomes, and keeps chosen devices in human hands by @mhyrr in #15
- The witness survives a slow house, and the records catch up with the confirm loop by @mhyrr in #16
- One decision about which model answers, and a save has to ask it too by @mhyrr in #17
- The record speaks beneath every reply by @mhyrr in #18
- The judge learns that hands-only is the house's word for the setting by @mhyrr in #19
- Dobby may say the coffee is on, because the house will say if it is not by @mhyrr in #20
- Dobby ships as a release, walked on a stand-in box by @mhyrr in #21
New Contributors
Full Changelog: https://github.com/mhyrr/dobby/commits/v0.1.0