01 โ Architecture Overview¶
Scope. The shape of the system: what the layers are, which direction they depend, where a run travels, and which boundaries are load-bearing. Every claim here is a pointer โ the detail lives in the document named beside it.
Read this first if you are new. Read 03 โ The Data Model second; between them they are the map, and everything from 05 onward is territory.
1. What this integration is¶
It manages rooms, runs and learned timing for a robot vacuum that some other integration already talks to. It has no protocol client of its own and never has had one.
That single fact explains more of the architecture than anything else:
- The vacuum, its sensors and its buttons are entities owned by another component. Everything this system knows arrives through Home Assistant's state machine, and everything it does is a service call on somebody else's entity.
- Those entities may not exist yet when setup runs, which is why setup runs twice (39 ยง2).
- Entity naming is a brand's convention rather than a contract, which is why there is a resolution and rescue layer (23 ยง4, 34).
2. Five layers, and which way they point¶
Home Assistant
โ
โโโโโโโโโโโโดโโโโโโโโโโโ
โ entry point (39) โ four contract functions; constructs everything
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ services (36) โโ entities (37) โโ panels (44)
โ public surface โ the API a person or an automation actually touches
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ
โ manager + store โ one facade (33), one persistent document (32)
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ runs ยท rooms ยท learning ยท mapping ยท maintenance ยท themes โฆ
โ subsystems โ fifteen, constructed in order, each owning its own store section
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ
โ adapters โ the only layer that knows a brand's words (22 ยท 23 ยท 24)
โโโโโโโโโโโโโโโโโโโโโโโ
Dependencies point down, and the bottom layer is data. A subsystem asks the adapter registry what this brand calls something; the adapter never calls back up. That is what makes a second brand a declaration rather than a fork.
The one deliberate exception is documented at its site: the CV segmenter lives in the Eufy package and is imported by the brand-agnostic engine registry, because its optional imaging stack makes a lazy registration awkward (25).
3. Where a run actually goes¶
A run is the spine of the product, and it crosses almost every layer:
| stage | what happens | doc |
|---|---|---|
| select | rooms are chosen and ordered; a queue is built | 05 |
| gate | can this start at all โ map, rooms, lifecycle, blocked rooms | 05 ยท 36 ยง3 |
| resolve | stored slugs become the ids this device uses right now | 42 ยง1 |
| pre-call | device-global settings pushed, after everything that can refuse has | 42 ยง2 |
| dispatch | the adapter's wire envelope goes out | 42 |
| observe | counters, current room, faults, pose โ no geometry | 43 ยท 35 |
| end | one status machine, many authorities, exactly-once finalization | 06 |
| record | the durable job record is written | 26 |
| judge | is this evidence worth learning from | 27 |
| derive | records become per-room statistics | 28 |
| predict | the next run's estimate, and how confident it is | 29 |
A run the user did not start enters at observe and leaves at record through a human review step instead of a gate โ 30.
4. The four boundaries that carry the design¶
Most defects in this system have been a boundary crossed rather than a function written wrong. Four are worth knowing by name.
Whose word is this¶
Core owns keys; an adapter owns values. A framework default that happens to be one brand's word is the failure mode this project keeps rediscovering โ in core's fallbacks (23 ยง2), in a migration loop that stamped a brand axis onto every room of every brand (33 ยง4), and in what is deliberately not configurable (35 ยง5).
Own it, or address it¶
State the system owns may be created on demand. State the caller addresses must be able to come back not found โ otherwise a typo becomes a durable record. The same rule was arrived at independently four times (45 ยง3).
Read, or write¶
A read is how a card discovers state, so it answers honestly with an empty shape and a reason. A write refuses with a reason or succeeds carrying what it applied. The split is decidable by inspecting the handler (36 ยง3).
Observe, or perturb¶
A diagnostic must not change what it reports (40 ยง1); a dock action offered by a wrong gate corrupted the measurement of the run it interrupted (41 ยง3).
5. Two persistence layers, and they are not alike¶
| the store | the tree | |
|---|---|---|
| what | rooms, maps, profiles, themes, capabilities, adapter config | job records, learned statistics, captures, the pose ring |
| where | one Home Assistant store document | files under the config directory |
| written | whole, every time | per record, append-mostly |
| on removal | deleted | kept, deliberately |
The second row is why they are separate: a single document rewritten on every change is the wrong shape for a growing history. The last row is a ruling โ the tree is the user's own record of their own home, and removing an integration is not obviously a request to destroy it (39 ยง5).
6. What the front end is, from here¶
The card is a separate corpus (frontend/) and this document does not describe it. Two facts about the boundary matter from the backend side:
- The backend decides; the card renders. Protection levels, start blockers and capability flags are computed here and displayed there, so the same rule applies to an automation as to a button (31 ยง5).
- Except where the vocabulary belongs to the display layer โ system tag words and facet derivation live in the card on purpose, so the backend validates format and lets meaning resolve where the vocabulary lives (38 ยง4).
7. How to find things¶
- By subsystem โ the table in README.
- By rule โ 00b-invariants.md, which names the constraints that bind across files, and the anchor each one is cited by.
- By duplicate โ 00c-replicas.md, for values that exist in more than one place on purpose.
- By shape โ 03 โ The Data Model.
Retired documents under
docs/retired/dev/are as-of-their-date records. Several are the only written account of their subsystem's history. Read them for orientation; do not treat them as current.