# THE MORNING AFTER — probe fix, gate, and the promotion train, 2026-09-22 Evidence: `probe-fix-2026-09-22/`. The night this follows: `DRILL-update-night-2026-09-21.md`. --- ## Not done, or changed from the brief **Read this first. Everything else in this document is a claim; this section is where the claims are bounded.** 1. **The brief said "the fourteen proven versions". FIFTEEN moved.** The night's fourteen included `nextcloud`'s MariaDB engine move; tandoor was re-walked today and became the fifteenth. Both are named below with why. 2. **I nearly dropped `nextcloud`'s engine move on a wrong assumption, and the gate corrected me.** I assumed `check-engine-major.py` would refuse `mariadb:11.6 -> 12.3` and had written it up as "dropped, named". Running the gate against that exact commit instead of assuming it ALLOWED the move by name, citing **R-469** (Slice 4 shipped; `MARIADB_AUTO_UPGRADE=1` is already in that template, verified by reading it). The brief forbade **PostgreSQL** engine moves; this is MariaDB and it was proven end to end in 217.4 s. It moved. **This is the second time in two days that running the instrument beat reasoning about it** — see R-628. 3. **The first push of the fifteen moves FAILED CI, and I found it by checking rather than by being told.** Job **877** on `15d7c2b` read `conclusion: failure`: the CI runner has no PyYAML and the new gate answered INCONCLUSIVE, which the runner rightly refuses to call a pass. Fixed with a degraded line-reader mode and five more decoy cases; job **878** on `1ad1f34` is `success`. **The moves themselves were never in doubt — the gate that shipped beside them was.** 4. **bookstack's phase trace on demo-hp is INCOMPLETE and the reason is my own instrument.** A 115-second probe run, meant only to list which apps were installed, pressed the Update as designed and then hit its timeout mid-update. Its phases are recorded to `+21.6 s starting`; the rest was read off the box afterwards (`done`, pin and installed both at `26.05.5`). The second, full run then pressed Update on an already-current app and completed in **3.1 s**, moving nothing. That second trace is real and is reported, but it is **not** a `26.05.2 -> 26.05.5` trace. Said here rather than presented as one. 5. **The brief asked me to "list templates the night's sweep could not judge". The honest answer needed three categories, not one** — 20 with a verdict record, 4 deployed as props with no edge walked, 1 deployed only to measure its probe, and **28 never deployed at all**. Filed as R-632 with the machine-readable list. 6. **Two things the brief could not have known, both found by the new gate and both left OPEN:** `paperless-ngx`'s health probe has never run on any box (R-630), and five templates cannot be judged by any static rule (R-631). Neither is fixed here: R-630's fix is product code or a container rename on live boxes, and the brief forbade product code. **One brief claim that turned out wrong:** none. All three probe faults the brief named were verified against the files before any edit and all three were exactly as stated — tandoor's compose line 42 dials `127.0.0.1:80/accounts/login/`, zipline's line 38 dials `/api/healthcheck`, wger's line 42 dials `127.0.0.1:8000`. --- ## Part 1 — the probes ### 1.1 The fix One commit, `app-catalog-felhom.eu@793c4fb`. No `image:` line moved, so no `catalog_since` moved. | app | was | is | the oracle that was already in the file | |---|---|---|---| | tandoor | port `8080` | port `80` | `wget --spider -q http://127.0.0.1:80/accounts/login/` | | zipline | path `/api/health` | path `/api/healthcheck` | `http.get('http://127.0.0.1:3000/api/healthcheck', …)` | | wger | port `80` | port `8000` | `wget --spider -q http://127.0.0.1:8000` | ### 1.2 Red-proofed live on 9202, through the product, in both directions Deployed at the **live (unfixed) pin** first. Evidence `probe-fix-2026-09-22/probe-before-observe.json`, `front-door-before.json`, `probe-after.json`. | | tandoor | zipline | wger | |---|---|---|---| | **BEFORE — controller state** | `unhealthy` | `unhealthy` | `unhealthy` | | **BEFORE — the app page, HU** | `Nem egészséges` | `Nem egészséges` | `Nem egészséges` | | **BEFORE — the app page, EN** | `Not healthy` | `Not healthy` | `Not healthy` | | **BEFORE — docker's own healthcheck** | `healthy, healthy` | `healthy, healthy` | `healthy` | | **BEFORE — the front door, followed** | **200** `Login / Sign In` | **200** `Zipline` | **200** `wger Workout Manager` | | **AFTER — controller state** | `running` | `running` | `running` | | **AFTER — the app page, HU / EN** | `Fut` / `Running` | `Fut` / `Running` | `Fut` / `Running` | The fix arrived through the **real sync**: `POST /api/sync` answered *„Sablonok frissítve — frissítve: tandoor, wger, zipline"*, and all three read `running` at the next poll — **no redeploy, no container restart**. **The badge I quote is the HEALTH word, not the version badge.** The version badge reads `Naprakész` / `Up to date` in both states and would have proved nothing; a first pass captured it and it was corrected. The scan strips `