diff --git a/REPORT.md b/REPORT.md index 2891870..4f3b363 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,96 +1,109 @@ -# REPORT — controller v0.246.0: an interrupted restore is told; the recovery-code reminder waits +# REPORT — controller v0.247.0: the i18n spike — English on three pages, Hungarian byte-identical -**2026-09-17.** R-550 (operator ruling „fix") and R-546. Architecture read first: -`felhom.eu/documentation/architecture/07-backup-architecture.md` §3 (Lane 1) and -`08-alarm-ladder.md` §6.2. +**Date:** 2026-09-17 · **Task:** localisation starter (spike + design), Phase 1 · **Baseline:** `main` +`89dd3e94b1de` (v0.246.0, MinAgent 0.131.0) · **Released:** `612c417` → image +`gitea.dooplex.hu/admin/felhom-controller:0.247.0` · **MinAgent:** 0.131.0 (unchanged). +**Architecture read before any claim:** `felhom.eu/documentation/architecture/02-controller-module-map.md` +(templates, setup wizard obsolete) and `05-hub-architecture.md` (report ingestion, config push). +**Design written after the spike ran:** `felhom.eu/documentation/architecture/10-localisation.md`. +**Inventory:** `felhom.eu/documentation/audits/I18N-INVENTORY-2026-09-17.md`. ## Claims in the brief that turned out wrong — named first -1. **„Readiness = `escrow.pbs_storage_id` set."** Readiness is the agent's own preflight `ok` over - **five** blocking items (`pbs_storage_id`, `dr_tier`, `age_binary`, `hub_upload`, `sudo_grant`; - `felhom-agent/internal/localapi/escrow_ceremony.go` `handleEscrowPreflight`). `pbs_storage_id` was the - one item R-546's box happened to show. The controller now reads the combined `ok`, never a copy. -2. **„The failure shows a raw error"** — not in a browser. The escrow page already listed the checklist - and showed its start form only when the preflight was `ok`. The raw `-storage` stderr came from the - chaos-night harness calling `POST /api/escrow/start` directly. What a browser user DID meet: red - crosses, the agent's English detail in muted brackets, no start button and no word about waiting. - Both paths are fixed; the direct one is now refused server-side. -3. **„The backup tiers persist their records atomically"** (read from `07`, not re-checked) — **checked - and TRUE.** The tier run records live in `settings.json`, and `Settings.save()` - (`internal/settings/settings.go:727-752`) writes a `.tmp` and renames it, with `.bak` recovery on a - corrupt primary. The restore record follows the same shape through the backup package's own - `atomicWrite` (tmp + rename; like `save()`, no fsync). +The brief named four already. Further ones (details and methods in the inventory §0): + +1. **„`fmtTime`, `fmtBytes`, `timeAgo` do not exist; `fmtMB` is the one size helper"** — all three + exist (`internal/web/funcmap.go` L265/L318/L403), plus nine more copy- or locale-producing helpers + and four size helpers. `timeAgo` builds „%d perce" — the plural problem lives there. +2. **„`fmtMB` used 10× in templates"** — 8×. +3. **„~13 `.Format(` layout calls in `internal/web`"** — 10 at the baseline (plus 8 `time.RFC3339`). +4. **Template lines 1 613 / 1 838** — 1 553, by two methods; neither figure reproduced by four variants. +5. **Go literals 1 234 in 99 files** — 1 141 in 84 (a lexer, comments skipped); comments explain most of + the difference. +6. **Banner 33 lines** — 34 once ASCII-only Hungarian words count (method difference). ## What shipped -**B.1 — the restore record survives a restart (R-550).** A design REVERSED by ruling, recorded in the -file header, in `07` §3 and in `CONTEXT.md`: `restore-status.json` in `DataDir`, written at both ends of an -op (`internal/backup/restore_record.go`). A record still marked running at startup becomes a failed, -`Interrupted` result — „A visszaállítás megszakadt (a doboz újraindult) — indítsd el újra." — kept per -app until that app's next restore; `restore_interrupted` (warning, household) pushed once. Wired from -`main()` (`cmd/controller/restore_record_wiring.go`). Shown as a card on `/backups/restore` and in the -off-site wizard's outcome card. Notification cooldowns stay in memory. +- **Mechanism (b), expanded at template LOAD:** `internal/i18n` (`Bundle`, `Expand`, `Msg`, `Plural`, + embedded `locales/hu.json` + `en.json`). `loadTemplates` parses one template set per language via + `parseTemplateSet` (= `ParseFS` + `Expand`); `s.tmpl` stays Hungarian. Why not a runtime `T` func: the + escaper changes `+ ' "` bytes and 618 of 1 867 template strings are inside `