Sprint 40 — add milk to the grocery list
Last post I explained what an ontology is and why Domi got one — seventeen nouns, fourteen links, thirteen verbs, written down where the machine can read them. This sprint the vocabulary went kinetic. The exit test I set myself was one sentence: “Add milk to the grocery list for the main home” — said to ChatGPT or Claude, not to Domi — lands on the actual list. This morning it did. Fifty-one PRs merged in seven days — a little over seven a day — and the one that mattered most was a carton of milk.
The house runs errands now
Since June, external AI assistants could read your household over MCP — tasks, documents, the works. Writing was the line I hadn’t crossed, because writing is where trust gets real. The crossing took the shape the ontology post promised: every mutation is now a declared action — its input schema, its minimum role, its confirm semantics, whether it’s destructive — and every caller, whether it’s Domi’s own chat or an assistant halfway across the internet, goes through one dispatcher that enforces all of it in one place.
On top of that sit thirteen generated write tools for external assistants: add to a shopping list, create a task, complete one, snooze one, capture a note, an event, a contact. The boundaries are the interesting part. Nothing destructive is reachable — no deleting, no merging, nothing that moves money. Every write names who the assistant claims to be acting for, and if it can’t match that name to a real household member, it errors rather than guesses. Write access itself is granted on a consent screen when you connect (and after living with it for a day, I flipped the default: the box comes pre-checked, because write access is why you connect an assistant — unchecking it is still one click). And it’s revocable from Settings instantly, even for an assistant that’s still connected.
The eval that failed correctly
Rule of the house: no LLM-facing feature ships without an eval. So the write surface got one — eight scripted requests fired at a live model that sees exactly the tool names and descriptions a real assistant sees, including one where a pasted “flyer” contains embedded instructions ordering the assistant to create a task. (It must refuse. It does.)
The first run failed four of eight, and every failure was the model being right: it looked up the grocery list before adding to it, because the tool contract says never invent ids; it stopped to ask who a task was for, because the contract says never guess. The spec was in the fixtures’ way, not the model. So the fixtures learned the correct sequences and the pass bar stayed where it was. An eval that fails informatively on day one is worth ten that pass politely.
The exit test earns its keep
Two bugs stood between “built” and “working,” and neither was findable from my side of the wire. The first: the connector showed zero tools in Claude — a date-typed field in two tool schemas broke the tool listing in a way no server-side test noticed. The second was quieter: task lists came back with links to every task, and no assistant ever showed them — because the tool’s description never said the links were there. A model’s entire view of your API is the description string; a field it isn’t told about may as well not exist. Both fixes were small. Both were invisible until a real client did real things.
A bakery in Mont-Tremblant
Domi’s chat also got web search this week, on a monthly budget you control from Settings. Then I asked it for a bakery near the Tremblant ski village and it told me that was “outside my scope” — before answering anyway, from memory, wrongly-ish. The fix was philosophical as much as technical: with a search tool attached, the world is in scope. No more disclaimers; it just searches, answers, and cites. (Web content stays firmly untrusted — it can inform an answer, never trigger an action.)
The rest of the week
Forwarding an email to your household’s private Domi address went from built-but-dormant to live in production — receipts and school notices forwarded from any mailbox now ingest end-to-end, with accents intact and attachments grouped with their emails. Documents learned the difference between when I ingested this and when this actually happened. The calendar gained drag-to-create and a print view. Settings got reorganized into a proper two-pane layout, and the language preference stopped silently drifting from what the screen claimed. Sessions show where they’re signed in from. Fifty-one PRs is mostly this: the app getting worn smooth where hands actually touch it.
Next
The sprint plan had two halves — teach the house to run errands, and walk every room before guests arrive. The errands got done; the walkthrough didn’t start. So that’s Sprint 41, nearly whole: every surface, both languages, empty states and error states and phone-width, against the day the first real guests arrive. The beta gate is close enough to read the sign.