slice 3 docs: the ruling, the shipped mechanism, and four rows closed
gates / gates (push) Successful in 17s
gates / gates (push) Successful in 17s
09-update-architecture.md gains the fourth dated operator ruling (2026-09-06, Option 1) and its section 5 is rewritten from a proposed shape into the shipped one: the pin, the stored definition, the render table, the four writers, the startup ordering, and the trap this slice set for slice 2 - the live compose file is now the frozen one, so a badge comparing against it would answer Naprakesz on exactly the apps that are behind. 02-controller-module-map.md said 'copy compose + .felhom.yml'. That stopped being true today, so it is corrected, and the two sections describing the old seam now carry a banner saying they describe v0.234.0 and below - kept because every box under v0.235.0 still behaves that way and because they are the measured account of why it changed. R-447, R-441, R-438 and R-455 closed and compressed into CLOSED-ITEMS; R-458 opened for the .felhom.yml asymmetry, with what would settle it by measurement. Live evidence: two real catalog pushes travelling the real 15-minute cycle, both reverted, the tree byte-identical afterwards. The restart that used to take 18.3 seconds and pull a new image now takes 0.1 seconds and pulls nothing.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# REPORT — update arc slices 1, 1b & 2: documents, register, roadmap, capability map (2026-09-03)
|
||||
# REPORT — update arc slice 3: the version freeze (2026-09-06)
|
||||
|
||||
*Overwritten each session. Nothing durable lives only here.*
|
||||
|
||||
@@ -6,70 +6,57 @@
|
||||
|
||||
| file | change |
|
||||
|---|---|
|
||||
| **`documentation/architecture/09-update-architecture.md`** | **CREATED — the deliverable.** Its absence was R-438. A LIVING document: every slice of this arc updates it in the same session. |
|
||||
| `documentation/tests/VALIDATION-update-slice12-2026-09-02.md` | CREATED — the live evidence, copied off demo-hp at the end of the phase that produced it. |
|
||||
| `documentation/backlog/OPEN-ITEMS.md` | R-438 and R-440 amended (both stay OPEN); **8 new rows: R-446..R-453**. |
|
||||
| `documentation/backlog/ROADMAP.md` | the update arc added as one item, naming the capability-map rows it flips. |
|
||||
| `documentation/architecture/00-capability-map.md` | one new row: what version a box runs, and whether it is behind. |
|
||||
| `STATUS.md` | one new operator item (9) and a new lead paragraph. |
|
||||
| `documentation/architecture/09-update-architecture.md` | **§3 gains the fourth dated operator ruling** (2026-09-06, Option 1); **§5 rewritten** from a proposed shape into the shipped mechanism — the pin, the stored definition, the render table, the four writers, the startup ordering, and §5.6 the trap it set for slice 2; slice 3 moved to shipped; two limitations added (§8.4 frozen-whole, §8.5 the `.felhom.yml` asymmetry). |
|
||||
| `documentation/architecture/02-controller-module-map.md` | its *"copy compose + `.felhom.yml`"* line stopped being true and is corrected; §1/§2 of the app-definition seam now carry a banner saying they describe ≤ v0.234.0 and why they are kept. |
|
||||
| `documentation/tests/VALIDATION-update-slice3-2026-09-06.md` | CREATED — the live evidence. |
|
||||
| `documentation/backlog/OPEN-ITEMS.md` | **R-447, R-441, R-438 and R-455 closed and moved out**; **R-458 opened**. |
|
||||
| `documentation/backlog/CLOSED-ITEMS.md` | the four closed rows, compressed, each naming `bc47dd4ef997` as the commit whose `git show` returns the original. |
|
||||
| `documentation/backlog/ROADMAP.md` | the arc item collapsed to slices 1/1b/2/3 shipped; **R-448 named as the new head of the arc**. |
|
||||
| `documentation/architecture/00-capability-map.md` | one new row, **PROVEN-LIVE**; the pre-v0.235.0 row relabelled rather than deleted, because every box below v0.235.0 still behaves that way. |
|
||||
| `STATUS.md` | new lead + item 10; **items 4 and R-455 closed**. |
|
||||
|
||||
## The architecture document — what it settles
|
||||
## The ruling, recorded
|
||||
|
||||
1. **How an update works today, as measured** — `UpdateStack` is `pull` then `up -d --remove-orphans`;
|
||||
the syncer overwrites a deployed app's compose on a 15-minute cycle with no deployed check;
|
||||
**thirteen** non-API call sites end in `compose up -d`.
|
||||
2. **What was chosen, and by whom** — `RestartStack`'s own comment, quoted. **A design decision is not
|
||||
a defect.** What was never decided is what the syncer does underneath a deployed app.
|
||||
3. **The three operator rulings of 2026-09-02** — verified backup as a precondition; the support window
|
||||
runs on how far behind the CATALOG a box is; automatic within a major, never across one.
|
||||
4. **The vocabulary ruling** — "rollback" is struck. The available shapes are ABORT and RESTORE.
|
||||
5. **The target shape** — the live compose file becomes derived from a pin in `app.yaml`.
|
||||
6. **The seven slices**, each with a status line. 1 and 2 are shipped.
|
||||
7. **Known limitations**, including the floating-tag one.
|
||||
**2026-09-06, Option 1: freeze the version, keep the fixes flowing.** The document records *what the
|
||||
ruling looked at*, not just its outcome: the old behaviour had two halves — a restart silently
|
||||
changing an app's VERSION (unwanted), and template corrections plus self-healing reaching a deployed
|
||||
app (worth keeping) — and the ruling keeps the second while removing the first.
|
||||
|
||||
## Register
|
||||
## Register — 203 open rows before, 203 after; closed 163 → 167
|
||||
|
||||
**194 rows before, 206 after** (205 on 2026-09-02, plus R-457 on 2026-09-03). Nothing closed, and that is stated rather than implied: R-438 and
|
||||
R-440 are **amended and stay OPEN** — the mechanism is now documented, not changed — so nothing moved
|
||||
to `CLOSED-ITEMS.md` and that file is untouched.
|
||||
Four closed and moved, one opened. The count is level by coincidence, not by inaction.
|
||||
|
||||
| row | what | state |
|
||||
|---|---|---|
|
||||
| R-446 | „Naprakész" can be FALSE for the 23 floating pins | OPEN, P2-MEDIUM, CC |
|
||||
| R-447 | slice 3 — make the live compose DERIVED | **BLOCKED** on an operator ruling, P1-HIGH |
|
||||
| R-448 | slice 4 — a guarded update (subsumes R-443) | READY, P2-MEDIUM |
|
||||
| R-449 | slice 5 — an upgrade test that runs again | READY, P2-MEDIUM |
|
||||
| R-450 | slice 6 — version sequence; an engine change gets its own edge | READY, P2-MEDIUM |
|
||||
| R-451 | slice 7 — a fleet sweep (needs a hub change: no image field is reported) | READY, P3-LOW |
|
||||
| R-452 | no gate enforces `catalog_since` (`--depth 1` has no parent to diff) | READY, P3-LOW |
|
||||
| R-453 | **CORRECTED** — the password was fine; `~/.config/credentials` uses SINGLE quotes and the strip was half-applied. The finding is the instrumentation lesson, not the typo | READY, P3-LOW |
|
||||
| R-454 | five `gofmt`-unclean `internal/web` test files, and no gate notices | READY, P3-LOW |
|
||||
| R-455 | **DooPlex has no Docker Hub login — the ceiling now blocks BUILDS, not just gates.** The mirror workaround is **MEASURED byte-identical** to Hub, so it is a sound fallback, not a hope | **WAITING-ON-OPERATOR**, P2-MEDIUM |
|
||||
| R-456 | a partly-dead stack is not a boot orphan, and that rule is written down nowhere | READY, P3-LOW |
|
||||
| R-457 | **a test that hardcodes a date and asserts an age is green only on the day it is written** — one proven, six candidate files named | READY, P3-LOW |
|
||||
| row | disposition |
|
||||
|---|---|
|
||||
| **R-447** | **CLOSED** — slice 3 shipped, controller v0.235.0 |
|
||||
| **R-441** | **CLOSED BY MEASUREMENT** — the restore now pins to what the unit captured; the render obeys it. The live half is §3/§6b of the validation file, not a code reading |
|
||||
| **R-438** | **CLOSED** — both halves discharged: documented 2026-09-02, behaviour changed 2026-09-06 |
|
||||
| **R-455** | **CLOSED** — the operator added a Docker Hub PAT |
|
||||
| **R-458** | **OPENED** (P3-LOW, CC) — `.felhom.yml` keeps flowing to a frozen app, so it can receive a health check written for a newer version. **False alarm, never data loss.** The row states what would settle it by measurement rather than by code |
|
||||
|
||||
## Live validation
|
||||
|
||||
Full evidence: `documentation/tests/VALIDATION-update-slice12-2026-09-02.md`.
|
||||
Full evidence: `documentation/tests/VALIDATION-update-slice3-2026-09-06.md`. **Two REAL catalog pushes
|
||||
travelling the REAL 15-minute cycle**, both reverted in the same session; the catalog tree is
|
||||
byte-identical to `8220f8d` afterwards.
|
||||
|
||||
**PROVEN LIVE on demo-hp at controller 0.233.0**, through a real production caller (the boot
|
||||
reconciler — no hand-set state): `bentopdf` recorded 1 service, `bookstack` recorded **2**, keyed by
|
||||
compose service name, **all three digests matching ground truth read independently beforehand**.
|
||||
Encrypted secrets byte-identical across the write. Both apps up and healthy; nothing provisioned.
|
||||
- **Scenario A** — a non-image change reached the pinned app (08:01:51Z), container untouched.
|
||||
- **Scenario B** — an image change did not (08:20:29Z), and the restart afterwards took **0.1 s, did
|
||||
not recreate the container, and never pulled the new image** — against **18.3 s with a pull** for the
|
||||
identical sequence measured before the change.
|
||||
- **Scenario D** — the Update button still moved the version, with the pin advancing **17 s before**
|
||||
the pull completed.
|
||||
- **Scenario G** — the frozen app read „Frissítés elérhető — 56 napja" while the other eight read
|
||||
„Naprakész".
|
||||
- **Teardown** — the container is back on the baseline digest `sha256:eaeea1e4…`, byte for byte.
|
||||
|
||||
**The badge is ALSO proven live**, on both surfaces and in three of its four states — including the
|
||||
load-bearing one: a deployed app with **no record renders no badge at all**. „Frissítés elérhető —
|
||||
**52 napja**" was produced by editing bentopdf's compose tag only (no restart, no `up -d`) and reverted
|
||||
byte-identically. **One correction of my own is stated in §4.0 of the validation file rather than
|
||||
buried: I first reported the vaulted password as stale on both boxes. It was not — I stripped only
|
||||
double quotes from a single-quoted value.** The operator caught it in one line.
|
||||
**A real gap was found by the live run and fixed in it:** the stored definition did not follow the
|
||||
fixes delivered after the pin, so the first freeze would have reverted them — silently undoing the
|
||||
half of the ruling that says fixes keep flowing. Section 6 of the validation file keeps the
|
||||
observation that proved it.
|
||||
|
||||
## Sibling repos
|
||||
|
||||
- `felhom-controller` **v0.233.0** — `8025304acc0a`, deployed to demo-hp and verified healthy.
|
||||
- `felhom-controller` **v0.234.0** — `38d28b5b624c`, the startup backfill. Deployed to **both** demo
|
||||
boxes and verified: 2 apps seeded on demo-hp with digests matching ground truth, 7 left untouched;
|
||||
all 9 then badged. **Its cause is worth keeping: `09-update-architecture.md` §8.3 was written as an
|
||||
accepted limitation on 2026-09-02 and was a defect by the next morning** — the operator found an app
|
||||
that simply ran and therefore showed nothing.
|
||||
- `app-catalog-felhom.eu` — `69761cf91bfc` (backfill) + `8220f8d` (REPORT).
|
||||
- `felhom-controller` **v0.235.0** — `8a0e0a59adc7` + `2a56f557d048`, deployed to demo-hp, healthy.
|
||||
- `app-catalog-felhom.eu` — `dc7e548`, `09b4ff5` (live-test) and `1798ce6`, `17cc784` (reverts), plus
|
||||
`7b9b9b3` recording them as a measurement rather than a release.
|
||||
|
||||
Reference in New Issue
Block a user