v0.256.0: the box sends its own sentence in the household's language (R-558 Part B)
gates / gates (push) Successful in 24s

MinAgent: 0.131.0 (unchanged). Needs hub v0.118.0+, which shipped first and
tolerates a box that sends none of this - every box in the fleet is that box
until this release reaches it.

The hub writes a household's e-mails in their language now, but about a third
of those mails carry a sentence the BOX composed, naming a drive, an app or a
number. The hub cannot translate one. So the box sends it twice.

- message_customer on POST /api/v1/event, omitempty. A HUNGARIAN household
  sends nothing extra at all, so its payload stays byte-for-byte what every box
  sends today and the hub's fallback path keeps being the one production
  exercises rather than a branch nobody takes.
- 19 producers render both sentences from ONE bundle key. `message` stays
  Hungarian always: it is what the operator is mailed and what the hub logs.
- customer.language bootstraps a new box - stored choice, then config, then
  Hungarian. The config value is NEVER written into settings.json: that would
  record a choice the household never made.

The Hungarian did not move, measured twice: the wire golden from the slice-2
base commit, and the Go parity gate over all 19 new keys.

Three guards had to learn the change and one caught me: the test seam now
carries the new field; the R-329 severity register reported two dynamic sites
as no longer existing the moment they moved off PushEvent (the walk now checks
36 severity literals, up from 20); and TestConfigLanguageIsWiredInMain reads
main.go, because cmd/ is gitignored and ripgrep does not.

A mistake, named: the first pass dropped displayName from three producers,
which would have mailed customers "Alkalmazás telepítve: %!s(MISSING)". Caught
reading the diff; now pinned by a test that refuses %!/MISSING/%s/%d in either
language.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-18 16:54:20 +02:00
parent 8fb2f9ef9d
commit bef39598d0
16 changed files with 1601 additions and 1068 deletions
+46
View File
@@ -1,3 +1,49 @@
## v0.256.0 — the box sends its own sentence in the household's language (2026-09-18, R-558 Part B)
**MinAgent: 0.131.0** (unchanged). **Needs hub v0.118.0+**, which shipped first and tolerates a box
that sends none of this — every box in the fleet is that box until this release reaches it.
Slice 3's other half. The hub now writes the household's e-mails in their language, but roughly a
third of those mails carry a sentence the BOX composed, naming a drive, an app or a number. The hub
cannot translate one. So the box sends it twice.
- **`message_customer`** on `POST /api/v1/event` — the same sentence in the household's language,
beside the unchanged Hungarian `message`. `omitempty`, and **a Hungarian household sends nothing
extra at all**: its payload stays byte-for-byte what it is today, so the hub's fallback path — the
one the whole fleet uses — keeps being the path production exercises, rather than becoming a branch
nobody takes.
- **19 producers converted** to bundle keys, rendered twice from ONE key: health ×3, controller
started/updated/update-failed, storage disconnected/reconnected, backup target absent/restored,
app deployed/deploy-started/deploy-failed/removed, crossdrive ×2, disaster recovery ×2, db-dump
completed. `message` stays Hungarian **always** — it is what the operator is mailed and what
`notification_log` records.
- **The Hungarian is byte-identical, and it is measured twice over**: `TestEventMessageWireTextIsFrozen`
(goldens captured at the slice-2 base commit) and the **Go parity gate**, which now checks all 19
keys against the base-commit literals and passes.
- **`customer.language` bootstraps a new box.** `GetLanguage` prefers the household's stored choice,
then `controller.yaml`'s `customer.language`, then Hungarian. The config value is **never written to
`settings.json`** — persisting it would record a choice the household never made, and a later
config pull could no longer be told apart from a deliberate switch.
- **The untranslatable tail** (a docker error, a validator's sentence) is appended to BOTH renderings,
so an English household gets an English sentence with a foreign tail rather than no sentence.
**Three guards had to learn the change, and one of them caught me:**
- The test seam `pushFn` now carries `messageCustomer`. A seam that cannot see a new field cannot test
it — the lesson this file already records one release back, 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 immediately reported them as no longer
existing — the "a stale register entry is also a failure" half doing exactly its job. The three new
push 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 precisely
how a seam gets built and never wired in this repo.
**A mistake worth recording:** the first pass of the conversion dropped the `displayName` argument
from three producers, which would have mailed customers `Alkalmazás telepítve: %!s(MISSING)`. It was
caught by reading the diff, and is now pinned by a test that refuses any sentence containing `%!`,
`MISSING`, `%s` or `%d` in either language.
## v0.255.0 — The globe on the sign-in-flow pages: styled, and inside the card (2026-09-18, fixes v0.254.0)
**MinAgent: 0.131.0** (unchanged). **No hub release needed.** Nothing on the wire moved. One Hungarian