# Notes for the next agent — Hearth

Read `AGENTS.md` at the project root first. What this rework decided, and where the
rules bent:

1. **Sidebar, labelled, three groups.** Thirteen destinations. The third group holds
   four items rather than §6.3's 5–9, because splitting the house from the money from
   the people is worth more than an even count. Do not add a second row of
   destinations to the top bar — it is utility only.
2. **Cards are the only surface.** One hairline, `--radius-2xl`, one elevation step,
   never nested, on a neutral `--muted` plane. If a new screen wants a bordered box
   inside a card, it wants a `Row` or a `hh-split` tile instead.
3. **Two geometries draw all the data.** `Bar` for a proportion, `DayStrip` for a
   24-cell day. A third chart type needs a reason, and the reason has to be a question
   neither can answer.
4. **Nothing stores a temperature that a person's preference decides.** Stepping a
   living zone moves the *setter's* comfort preference, because that is where the
   number comes from; a zone with its own setpoint (hot water) moves its own. If you
   add a zone, decide which it is and set `targetC` accordingly — `null` means it
   follows the household chain.
5. **A consumable's due date is a machine's hours.** `jobRows` reads `runtimeHours`
   off the device, and completing the job resets it. Never write a due date onto a
   consumable job and expect it to mean anything.
6. **`ENTRY_FLAGS.insecure` is the only security predicate.** It takes the alarm and
   the clock. Do not add a second one for a screen — change this and everything moves,
   which is the point.
7. **Settings write into the live objects.** `saveResidence` and `saveTariff`
   `Object.assign` into `HOUSE_POLICY` and `TARIFF` on purpose: those are what
   `enums.js` and `metrics.js` read at render. Copying them into React state as well
   would give the product two sources that drift.
8. **The photograph is a form field.** `PhotoUpload` previews through `FileReader` and
   writes on Save like every other field, because `/account/profile` is staged. A
   staged screen may not hold an instant control, so "remove photograph" clears the
   field rather than saving.
9. **Requests are answered by acting.** Granting an unlock request actually unlocks
   the door and granting a lights request turns the lamp on. An answer nobody acts on
   is not an answer.
10. **`App.jsx` is the router and the commit index.** Commits live in
    `HouseCommits.jsx` behind `makeHouseCommits(ctx)`. Give a new commit family the
    same treatment rather than growing App.
11. **`formatSince` is its own column rule.** A "since" date is a month and a year,
    because `formatWhen` renders a six-year-old date as "7 Oct" and reads as this week.
    Use `formatWhen` for anything within a week of now, `formatSince` for provenance.
12. **A wide table scrolls because of one rule.** `.hh-tablewrap .o-table` is
    `width:max-content;min-width:100%`, and the element that actually scrolls is the
    design system's own `.o-table-container`. With `width:100%` the nowrap cells push
    the box past the container and the overflow is clipped unreachably — the row's
    action column disappears. Measure `.o-table-container`, not the outer wrap.
13. **The clock is frozen at 19:10 local.** Several flags depend on it: Iris asleep
    (or not, depending on the browser's timezone), the peak window just closed, dark
    since 18:20. If you move `HEARTH_NOW`, re-read the derived flags on Today before
    trusting a screenshot.
