# REPORT — localisation slice 3 Part B: the box sends its sentence in the household's language **controller v0.256.0** · base `8fb2f9ef9d5a` · 2026-09-18 · R-558 Part B · MinAgent 0.131.0 (unchanged) ## What shipped The hub half (v0.118.0/0.118.1) writes a household's e-mails in their language. This is the other half: about a third of those mails carry a sentence the BOX composed — naming a drive, an app, a number — and the hub cannot translate one. The box now sends it twice. - **`message_customer`** on the event wire: the same sentence in the household's language, beside the unchanged Hungarian `message`. `omitempty`, and **a Hungarian household sends nothing extra**, so its payload stays byte-for-byte what every box in the fleet sends today. - **19 producers converted** to bundle keys, both renderings from ONE key. - **`customer.language` bootstraps a new box**: stored choice → config → Hungarian. The config value is never persisted into `settings.json`; doing so would record a choice nobody made. ## The Hungarian did not move, measured twice - `TestEventMessageWireTextIsFrozen` — goldens captured at the slice-2 base commit. - **The Go parity gate** — all 19 new keys checked byte-for-byte against the base-commit literals (`688 slice-2 keys listed, 34 pre-existing, 484 named in Go`, gate OK). ## Three guards had to learn the change, and one caught me - **The test seam** `pushFn` now carries `messageCustomer`. A seam that cannot see a new field cannot test it — the lesson this repo recorded one release ago when `PushEvent` had to become the seam. - **The R-329 severity contract** walks call sites by FUNCTION NAME. Converting producers moved two dynamic-severity sites off `PushEvent` and the register reported them as no longer existing — the "a stale register entry is also a failure" half doing its job. The three new helpers are registered; the walk now checks **36** severity literals, up from 20. - **`TestConfigLanguageIsWiredInMain`** reads `main.go` and asserts the setter is CALLED. `cmd/` is gitignored, so ripgrep skips `main.go` and a reviewer's search finds nothing — which is exactly how a seam gets built and never wired in this repo. Red-proofed by deleting the call. ## A mistake, named The first pass of the conversion **dropped the `displayName` argument from three producers** (`app_deployed`, `app_deploy_started`, `app_removed`). Shipped, that would have mailed customers `Alkalmazás telepítve: %!s(MISSING)`. Caught by reading my own diff, and now pinned by a test that refuses any sentence containing `%!`, `MISSING`, `%s` or `%d` in either language. ## What is NOT converted, and why - **The operator-tier types** (15 of them, listed in the hub's `operatorOnlyEvents`): the operator reads Hungarian, and these never reach a customer. - **Producers whose sentence is composed in another package** and reaches the notifier already finished — `backup_failed`, `db_dump_failed`, `backup_integrity_ok`/`_failed`, `offbox_enlarge_blocked`, `local_api_endpoint_drift`. They still send Hungarian only, so an English household can still see one Hungarian line in some mails. **Filed as a row rather than left as prose.** - The R-570 sentence, which stays Hungarian until that row closes. ## Green `go build` / `go vet` / `go test ./...` clean. All 17 controller gates OK. All 23 decoys behave.