From c1b123c64955a21480f373a9937d834b78afbe9d Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Thu, 1 Oct 2026 08:39:51 +0200 Subject: [PATCH] =?UTF-8?q?REPORT:=20v0.285.0=20=E2=80=94=20two=20controll?= =?UTF-8?q?er=20versions=20per=20box,=20R-751,=20live=20results?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- REPORT.md | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/REPORT.md b/REPORT.md index c0c6ecd..149a949 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,16 +1,40 @@ -# REPORT — v0.284.0 + v0.284.1 + v0.284.2 (2026-09-30 late evening) +# REPORT — v0.285.0: a box keeps two controller versions (decision 56); the update clean-up's crash (R-751) — 2026-10-01 -- **v0.284.2:** the retention lists images with `-a` — digest-pulled app images are untagged and were invisible (found - live on 9202); marker `image-retention-v2.done`. 0.284.0/0.284.1 were never floored. +Full session report: `felhom.eu/REPORT-rulings-2026-10-01.md`. Evidence: `felhom.eu/documentation/audits/rulings-2026-10-01/B/`. +Architecture read: `09` §3 decisions 30, 45, 52, 53, 56; `03-host-agent.md` (the controller swap); agent +`internal/localapi/controllerswap.go`. -- **v0.284.1:** the remove half of decision 53 wired into `RemoveStack` (the household's Remove button — v0.284.0 wired only - `DeleteStack`, found live on 9202); one summary line per retention pass. v0.284.0 was never floored (9202 only). +## What changed -- **Image retention (`09` §3 decision 53, R-736):** after a done/undone guarded Update and at remove, an app's older - images are deleted; the box-wide keep set (containers, installed composes, installed/previous records) is read at - delete time; exact id, never forced/pruned; paused while any update runs; a one-time sweep 3 min after start. -- **Install hold (R-741):** an `after_install` app is held behind the setup gate's door from its first start until the - known login is replaced (after_install, or the household's "I changed it"). -- Tests: `TestImageRetention_*` (6), `TestInstallHold_*` (6), parity fixture `app_info_install_hold`; red-proofs in - `felhom.eu/documentation/audits/night-rulings-2026-09-30/{B,C}/`. Green gate: build, vet, test ./... rc=0. -- Evidence and the live proofs: `felhom.eu/documentation/audits/night-rulings-2026-09-30/`. +- `internal/stacks/controller_image_retention.go` — `RetainControllerImages(ControllerImageRecord)`: keeps every image a + container uses, the running version's tag, the previous one (the swap record, `selfupdate.UpdateState.RecordedPrevious`; + version order only when the record names none present), every version above the running one and every non-version tag; + deletes older and untagged controller images by exact name/ID; nothing while the controller swaps itself. Called 3 + minutes after every start (`cmd/controller/main.go`). +- `internal/stacks/image_retention.go` — R-751: `RetainImagesAfterUpdate` returns when the app is gone after its rescan + (it dereferenced a nil stack in a goroutine; a panic there ends the process). +- `internal/stacks/r650_main_test.go` — both retention seams are no-ops in the package's tests. + +## Measured before building + +The agent's swap rolls back to what `/etc/felhom-controller-image` named when the swap began — the running image. The +controller never hands it a previous image (`SwapController(ctx, target)`). So the self-update's own roll-back needs only +the running image; "the previous" is kept for a roll-back by hand, as ruled. + +## Tests and red-proofs + +`TestControllerRetention_*` (6), `TestRecordedPrevious`, `TestRetainImagesAfterUpdate_AppGoneDoesNotPanic`. Each guard was +broken on purpose and its test failed with the wrong value visible: the previous dropped from the keep switch (0.284.2 +deleted), the record ignored (0.283.1 deleted), the swap check removed (deleted while swapping), the in-use check removed +(an image a container uses deleted), the success check removed (a failed swap's image named as previous), the nil-stack +check removed (panic). Full suite `go build/vet/test ./...` green; `controller_gates.py --fast` OK. + +## Live + +| box | controller images before → after | Docker images (`system df`) | how | +|---|---|---|---| +| 9202 | 5 → 2 | 3.17 → 3.10 GB | bootstrap deploy (self-update is off there); previous by version order | +| demo-hp 9201 | 84 → 2 | 15.2 → 11.65 GB | floor 0.285.0; previous from the swap record | +| N100 9201 | 76 → 2 | 6.07 → 1.11 GB | floor 0.285.0; previous from the swap record | + +Each kept 0.285.0 (running) and 0.284.2 (previous). Every app container stayed up. Golden 0.285.0 baked and vouched.