platform-docs/adr/0023-ubiquity-priority-critical-fuer-echte-stille.md
2026-08-29 17:46:57 +02:00

470 lines
26 KiB
Markdown

# ADR-0023: `priority=critical` fürs wirklich unbeaufsichtigte Mint-Install
**Status:** Beschlossen
**Datum:** 28.08.2026
## Kontext
Beim ersten echten Self-Service-Flow-Test auf physischer Hardware (Notebook,
Organisation "Liebherr", 28.08.2026) zeigte die Installation trotz
"Tuxflotte Auto-Install"-Bootmenüeintrag (`automatic-ubiquity noprompt` im
Kernel-Append, korrekter, vollständig aufgelöster Preseed mit allen
nötigen Werten — Netzwerk, Zeitzone, Partitionierung, Benutzer, Codecs)
**jede** Ubiquity-Seite interaktiv an: Zeitzone-Bestätigung,
Multimedia-Codecs-Frage, "Vorhandene Installation überschreiben?" und
Benutzeranlage.
Ausführliche Live-Fehlersuche (siehe [[project_e2e_flow_dogfooding_2026-08-28]]
für den vollständigen Verlauf) hat mehrere naheliegende Verdächtige
geprüft und ausgeschlossen, bevor die eigentliche Ursache gefunden wurde:
- Falsch gewählter Bootmenüeintrag — ausgeschlossen (User hat "Tuxflotte
Auto-Install" korrekt gewählt, bestätigt durch Bildschirm: kein
Cinnamon-Desktop sichtbar, nur Ubiquitys eigenes Vollbildfenster — Abbruch
legt den normalen Desktop darunter frei, das automatische Ubiquity läuft
also tatsächlich).
- Fehlende/kaputte WLAN-Zugangsdaten im Preseed — ausgeschlossen (`/opt/
tuxflotte/config/installer.conf` enthielt alle vier erwarteten Zeilen
korrekt; dasselbe Verhalten trat auch mit funktionierendem Ethernet auf).
- Dateiberechtigungen (`installer.conf`, `sudoers.d/90-tuxflotte`) —
ausgeschlossen, per `xorriso -lsdl` an der echten gebauten ISO
gegengeprüft, beide unauffällig (644 bzw. das für sudoers.d korrekte 440
root:root).
- Fehlende Codec-Preseed-Zeile — ausgeschlossen, `ubiquity ubiquity/
use_nonfree boolean true` war bereits korrekt gesetzt (die dokumentierte
Lösung für ein bekanntes Mint-21-Problem, siehe
https://github.com/linuxmint/mint21-beta/issues/34).
**Tatsächliche Ursache:** `automatic-ubiquity` allein bewirkt laut Ubiquity-
Dokumentation nur, dass Seiten übersprungen werden, deren Fragen *alle*
bereits beantwortet ("seen") sind — reicht in der Praxis oft nicht aus, um
wirklich jede Seite zu unterdrücken. Der fehlende Baustein ist die
Debconf-Priorität: ohne `priority=critical` zeigt der Installer weiterhin
Seiten an, auch wenn die zugehörigen Fragen vorbelegt sind. Durch mehrere
unabhängige Quellen bestätigt (siehe Recherche im Chat).
## Entscheidung
`priority=critical` zum Kernel-Append des "Tuxflotte Auto-Install"-
Menüeintrags ergänzt — in `grub/mint-boot-grub.cfg` und `grub/mint-
isolinux-live.cfg`, jeweils nur bei diesem einen Eintrag (die übrigen
Menüpunkte wie "Start Linux Mint"/"OEM install" bleiben bewusst
unverändert interaktiv). Beide Dateien werden sowohl vom echten
Kunden-ISO-Bau (`scripts/build_customer_iso.sh`) als auch vom lokalen/
QEMU-Testpfad (`scripts/build.sh`) verwendet — der Fix deckt also beide
Wege ab, ohne eine zweite Stelle anfassen zu müssen.
## Konsequenzen
Reine Boot-Parameter-Änderung, kein Preseed-/Server-/Agent-Code betroffen.
Noch **nicht live verifiziert** — die nächste ISO, die für "Liebherr" (oder
jede andere Organisation) gebaut wird, enthält den Fix automatisch, da
`build_customer_iso.sh` die Dateien bei jedem Bau frisch kopiert. Die
eigentliche Verifikation folgt beim nächsten Installationsversuch des
Users.
Offen, falls `priority=critical` allein nicht ausreicht: die
Zusammenfassungsseite (`ubiquity ubiquity/summary note`) müsste laut
Recherche ggf. auf einen leeren Wert gesetzt werden, um ebenfalls
übersprungen zu werden — nicht vorab geändert, da nicht durch eigene
Beobachtung bestätigt, nur in der Recherche als möglicher Zusatzpunkt
aufgetaucht.
## Nachtrag (28.08.2026): `priority=critical` war notwendig, aber nicht hinreichend — echte Ursache tiefer
Live-Verifikation in der QEMU-Test-VM (`tuxflotte-mint-autoinstall-test`,
siehe [[project_e2e_flow_dogfooding_2026-08-28]]) hat den in dieser ADR
angenommenen Rahmen korrigiert:
1. **Der "Tuxflotte Auto-Install"-Bootmenüeintrag selbst ist strukturell
kaputt und war nie der richtige Pfad.** Er referenziert
`file=/cdrom/preseed/tuxflotte.seed` — dieses Verzeichnis existiert auf
keiner gebauten ISO (`ls /cdrom/` bestätigt: kein `preseed/`-Ordner).
`build_customer_iso.sh` bäckt bewusst keinen Preseed auf die ISO (siehe
eigener Kommentar dort) — Hostname/Geräte-ID/Partitionierung werden
erst live aufgelöst.
2. **Der tatsächlich funktionierende Mechanismus existiert bereits seit
06.08.2026 (Commit `d6a0146`): `backend_launch()` in
`backends/mint/backend.sh`.** Er baut zur Laufzeit einen echten,
vollständig aufgelösten Preseed, hängt ihn als zusätzlichen
cpio-Layer an `/cdrom/casper/initrd.lz` an und bootet per `kexec` neu
mit `automatic-ubiquity noprompt file=/preseed.cfg …`. Erreicht wird
dieser Pfad aber nur über den **"Start Linux Mint"-Eintrag** (bzw.
jeden Nicht-`automatic-ubiquity`-Eintrag) → `start-kiosk.sh` erkennt
`TUXFLOTTE_AUTO_MODE=true` → `installer.sh` → `40_backend.sh` →
`backend_launch()`. Live bestätigt: `/sbin/init`-Cmdline im zweiten
Boot lautet `automatic-ubiquity noprompt splash`, `ubiquity --automatic
--only` und `debconf-communicate -fnoninteractive` laufen tatsächlich.
Der Nutzer hatte diesen Mechanismus korrekt in Erinnerung, meine
eigene Aussage in einer früheren Session, `backend_launch()` sei ein
Stub, war falsch (nicht ausreichend im Git-Log/in den ADRs
nachgeprüft).
3. **Trotz vollständig aufgelöstem Preseed und korrekt gesetztem
`priority=critical` bleibt Ubiquitys GTK-"Automatic"-Frontend auf
diesem Mint-22.3-Ubiquity-Build an mehreren Seiten hängen und wartet
auf einen manuellen Klick.** Live beobachtet: Multimedia-Codecs-Seite
blieb >60s ohne jede neue Zeile in `/var/log/installer/debug`
(`widget found for ubiquity/use_nonfree` war die letzte Zeile) —
erst ein per QMP `input-send-event` simulierter Mausklick auf
"Continue" brachte Fortschritt. Gleiches Muster danach bei
"Installation type" und beim "Änderungen auf Speichergerät
schreiben?"-Bestätigungsdialog — jede Seite pausiert bis zum Klick,
obwohl die zugrunde liegenden Debconf-Werte laut Preseed bereits
beantwortet sind. Das deckt sich exakt mit dem realen Befund auf der
physischen Hardware (Zeitzone/Codecs/Überschreiben/Benutzeranlage
alle interaktiv) — es lag nie an einem fehlenden Preseed-Wert oder an
`priority=critical`, sondern daran, dass Ubiquitys automatischer
GTK-Modus auf diesem Fork Werte vorbelegt, aber die
Seitennavigation selbst nicht automatisch durchläuft.
**Korrigierter Stand:** `priority=critical` bleibt eine sinnvolle, nicht
schädliche Ergänzung, löst das eigentliche Problem aber nicht. Die
offene Frage — GUI-Auto-Klick-Mechanismus (z. B. `xdotool`, von
`installer.sh` nach dem kexec-Sprung gestartet) vs. Ubiquity im
Backend-/Textmodus ohne GTK-Frontend ansteuern vs. bewusster Verzicht auf
volle Klick-Freiheit — ist mit dem User noch zu klären, siehe
[[project_e2e_flow_dogfooding_2026-08-28]] Fund 8.
## Zweiter Nachtrag (28.08.2026): Ursache endgültig gefunden und behoben — zwei unabhängige Bugs
Der Nutzer erinnerte sich korrekt, dass die kexec-Automatisierung schon
einmal (06.08., Commit `d6a0146`) bis zum Login-Bildschirm durchgelaufen
war. Live-Nachstellung in der QEMU-VM (frische Disk, sauberer Boot über
"Start Linux Mint") deckte zwei komplett unabhängige, bis dahin nie
bemerkte Bugs auf, die zusammen jede automatisierte Installation seit
langem verhindert haben:
**1. `start-kiosk.sh` hatte `/home/liveuser` hartkodiert** (`mkdir -p
/home/liveuser/...` und der Epiphany-Profilpfad). Der tatsächliche
Live-Benutzername auf dieser ISO ist überall `mint` (siehe
`grub/mint-*.cfg`, `username=mint`). `/home/liveuser` existiert nicht
und kann vom Live-User nicht angelegt werden (`/home` ist nicht
schreibbar) — mit `set -euo pipefail` brach das Skript dort sofort mit
"Permission denied" ab, **noch bevor** die `TUXFLOTTE_AUTO_MODE`-Prüfung
überhaupt erreicht wurde. `installer.sh` lief dadurch nie los, `NoDisplay=true`
im Autostart-Eintrag verschluckte den Fehler komplett lautlos — nach
außen sah es wie ein ganz normaler, nicht-automatisierter Live-Desktop
aus. **Fix:** `${HOME}` statt hartkodiertem Pfad.
**2. `backend_launch()`s kexec-Sprung nutzte nur `automatic-ubiquity`.**
Das lässt Casper weiterhin Ubiquitys GTK-Oberfläche starten
(`ubiquity-dm`), die zwar alle Preseed-Werte korrekt vorbelegt, aber pro
Seite trotzdem auf einen Klick wartet — live beobachtet: die
Multimedia-Codecs-Seite blieb ohne Klick über 60 Sekunden unverändert
stehen (kein neuer Eintrag in `/var/log/installer/debug`), ein per QMP
simulierter Mausklick brachte erst Fortschritt, dasselbe Muster
wiederholte sich bei "Installation type" und beim
"Änderungen schreiben?"-Bestätigungsdialog. Das erklärt exakt das auf
echter Hardware beobachtete Verhalten (Zeitzone/Codecs/Überschreiben/
Benutzeranlage alle interaktiv trotz "automatischem" Modus) — nie ein
fehlender Preseed-Wert, sondern eine grundsätzliche Eigenschaft von
Ubiquitys GTK-Automatic-Modus auf diesem Codestand.
**Fix:** Zusätzliches Boot-Keyword `noninteractive` im kexec-Append
(siehe `/usr/share/ubiquity/start-ubiquity-dm`: bei diesem Keyword ruft
Casper direkt `ubiquity noninteractive` auf, statt die GTK-Oberfläche zu
starten). Das ist Ubiquitys eigenes, mitgeliefertes Headless-Frontend
(`ubiquity/frontend/noninteractive.py`) — verarbeitet jede Seite mit
`auto_process=True` rein über Debconf, ohne je ein Fenster zu zeichnen;
`question_dialog()` ist absichtlich nicht implementiert (wirft
`NotImplementedError`) für alles, was sich nicht aus dem Preseed
beantworten lässt — sauberes Scheitern statt stillem Hängenbleiben.
**Live-Verifikation (QEMU, frische 40-GB-Disk):**
- Zweiter Boot nach kexec hat `noninteractive` korrekt im
`/proc/cmdline`.
- `pgrep -a ubiquity` zeigt keinen laufenden GTK-`ubiquity-dm`-Prozess.
- `/var/log/installer/debug` bestätigt den Frontend-Wechsel eindeutig
per Exception-Traceback: `ubiquity.frontend.noninteractive.Wizard
does not implement question_dialog`.
- **Verbleibende, jetzt exakt lokalisierte Lücke:** `ubi-partman.py`
(Zeile 3484) stellt beim Partitionieren eine Frage, die im aktuellen
Preseed noch nicht beantwortet ist — welche genau, ist noch offen
(nächster Schritt). Das ist ein erheblicher Fortschritt gegenüber
vorher: statt eines unklaren, seitenübergreifenden Hängenbleibens gibt
es jetzt einen einzigen, exakt benannten fehlenden Preseed-Wert.
Beide Fixes committed und gepusht (`backends/mint/backend.sh`,
`live-updates/opt/tuxflotte/kiosk/start-kiosk.sh`,
`live-updates/etc/sudoers.d/90-tuxflotte`), siehe
[[project_e2e_flow_dogfooding_2026-08-28]] für den vollständigen
Untersuchungsverlauf.
## Nachtrag (29.08.2026): `noninteractive` verworfen, Umstieg auf
## `automatic-ubiquity` + eigener Autoklicker, mehrere echte Bugs gefunden
Die "verbleibende Lücke" oben (eine unbeantwortete Preseed-Frage in
`ubi-partman.py`) erwies sich als der erste von mehreren Funden in einer
langen, sehr tief gehenden Sitzung. Kurzfassung des Ergebnisses vorab:
**`noninteractive` wurde komplett verworfen**, `automatic-ubiquity`
(echte GTK-Oberfläche) plus ein eigener Autoklicker sind jetzt der
Ansatz. Drei reale, unabhängige Bugs wurden gefunden und behoben. Ein
letzter Schritt (der Klick auf "Jetzt installieren" auf der
Partitionierungs-Übersichtsseite) ist noch nicht zuverlässig
automatisiert - siehe "Offen" am Ende.
### `noninteractive` selbst ist strukturell nicht tragfähig
Iteratives Beantworten einzelner fehlender Preseed-Werte (über 30 Stück,
per `config.dat`/`templates.dat`-Abgleich auf dem laufenden Live-System
diagnostiziert) brachte `ubi-partman.py` immer weiter, endete aber
zuverlässig in einer echten Endlosschleife im `choose_partition`-Zustand
(über 100.000 Debconf-Protokollzeilen in wenigen Sekunden, kein
Fortschritt). Ursache, per Quelltextanalyse gefunden: `choose_partition`
ist die Frage des MANUELLEN Partitionierers; deren Bearbeitung in
`ubi-partman.py` baut einen internen Cache auf und wartet danach auf
einen echten GTK-Button-Klick (`ok_handler()`), der über
`PageNoninteractive` nie kommt - `PageNoninteractive.get_autopartition_choice()`
und verwandte Methoden sind nur Stubs (`pass`/`None`). Das ist keine
fehlende Preseed-Zeile, sondern eine strukturelle Lücke im mitgelieferten
Headless-Frontend selbst.
**Entscheidung:** zurück zu `automatic-ubiquity` (echte GTK-Oberfläche,
`PageGtk` - der von Ubiquity selbst produktiv genutzte, echte
Code-Pfad), dafür ein eigener Autoklicker
(`live-updates/opt/tuxflotte/scripts/autoclicker.sh` + systemd-Service),
ausgelöst durch das eigene Boot-Keyword `tuxflotte-autoclick`.
### Bug 1: `jq` fehlt beim automatisierten Start über den Kiosk (real blockierend)
Der reale Self-Service-Auslöser (`start-kiosk.sh` im Auto-Modus:
`exec sudo installer.sh`, kein Terminal, keine sichtbare Ausgabe) blieb
sofort im allerersten Modul (`10_hardware.sh`) mit "Benötigtes Programm
nicht gefunden: jq" hängen - unsichtbar, nur in `~/.xsession-errors`
sichtbar, nicht in `journalctl` (kein systemd-Unit). Alle bisherigen
Testläufe in dieser Untersuchung sind daran nie gescheitert, weil `jq`
vor jedem manuellen `installer.sh`-Aufruf von Hand nachinstalliert wurde
(bekannte, bisher bewusst zurückgestellte Lücke, siehe
`backend_init()`-Kommentar in `backends/mint/backend.sh`) - der reale
Kiosk-Auslöser hat diesen manuellen Schritt naturgemäß nie bekommen.
`backend_init()` installiert `jq` zwar nach, aber erst in Modul 40
(`40_backend.sh`) - viel zu spät für Modul 10.
**Fix:** neues Modul `scripts/modules/00_preflight.sh` (lief bisher leer),
installiert `jq` als allererstes, vor jedem anderen Modul. Live über den
echten Kiosk-Auslöser (nicht manuell) verifiziert: `installer.sh` lief
danach vollständig automatisch bis zum `kexec`-Sprung durch.
### Bug 2: Ubiquity-GTK-Absturz in `ubi-prepare.py` (echter Ubiquity-Bug)
Mit `automatic-ubiquity` stürzte der Installer auf der "Vorbereiten"-Seite
reproduzierbar ab: `TypeError: Argument 1 does not allow None as a value`,
in `ubi-prepare.py::enable_download_updates()`,
`self.label_download_updates.set_label(self.controller.get_string(template))`.
Das Argument, nicht das Widget, ist None: `get_string('ubiquity/text/label_download_updates_na')`
liefert keinen Wert (fehlende Übersetzung/Vorlage für diesen Zustand),
GTK akzeptiert dafür kein `None`. Preseeden von
`ubiquity/download_updates` half nicht - der auslösende Callback
(`plugin_set_online_state`, an einen NetworkManager-Online-Status-Wechsel
gebunden) feuert unabhängig vom Preseed-Wert.
**Fix:** gezielter Sed-Patch statt Ersatz der kompletten
Drittanbieter-Datei, eingehängt im bestehenden
`initrd-hooks/casper-bottom/99casperboot`-Hook (läuft bei jedem
Casper-Boot, auch nach dem Kexec-Sprung):
```sh
sed -i "s/self\.controller\.get_string(template))/self.controller.get_string(template) or '')/" \
/root/usr/lib/ubiquity/plugins/ubi-prepare.py
```
Live verifiziert: derselbe Ablauf, der vorher exakt an dieser Stelle
abstürzte, lief danach sauber weiter bis zur Partitionierungsseite.
### Bug 3: `partman/choose_partition select finish` erzwingt denselben Endlosschleifen-Zustandsautomaten wie bei `noninteractive` - auch im GTK-Modus
Nach Fix 1+2 lief die Installation weiter, hing aber erneut in derselben
`choose_partition`-Endlosschleife wie beim verworfenen
`noninteractive`-Versuch (>100.000 Debconf-Zeilen in Sekunden) - diesmal
mit `automatic-ubiquity`. Ursache identisch zur strukturellen Analyse
oben: das direkte Preseeden von `partman/choose_partition select finish`
zwingt `ubi-partman.py` in den manuellen Partitionierer-Zustandsautomaten,
unabhängig vom Frontend - der ist für einen echten, interaktiv
aufgebauten Seitenwechsel gedacht, nicht für ein direkt vorausgefülltes
Ergebnis ohne echten Seitenaufbau.
**Fix:** die Zeile `d-i partman/choose_partition select finish` ersatzlos
aus `preseed.tpl` entfernt. `partman-auto/method` + `expert_recipe` +
`choose_recipe` (bereits vorhanden) genügen, um die geführte
Partitionierung auf dem dafür vorgesehenen Weg laufen zu lassen. Live
verifiziert: Endlosschleife verschwunden (Debug-Log-Länge sank von
>100.000 auf ~1.700 Zeilen für denselben Ablaufabschnitt), Installer
zeigt danach korrekt die echte Partitionierungs-Übersichtsseite mit dem
tatsächlich konfigurierten Layout (ESP + 42-GB-ext4-Root gemäß Rezept).
### Nebenfund: GRUB/isolinux-Standardeintrag "von lokaler Festplatte
### booten" ist ABSICHTLICH so, kein Bug
Während der Fehlersuche wirkte ein per QEMU/SeaBIOS beobachtetes
Boot-Hängenbleiben zunächst wie ein Infrastrukturproblem (ausführlich
mit Bisektion über mehrere xorriso-Neubauten eingegrenzt). Tatsächliche
Ursache: das ISO bootet per Voreinstellung "von lokaler Festplatte" (auf
der frischen Test-Disk naturgemäß leer/nicht bootfähig) - das ist eine
bewusste, bereits am 01.08.2026 getroffene Sicherheitsentscheidung
(siehe ADR-0009, Abschnitt "Bootmenü als eigentlicher Sicherheits-Gate"):
die destruktive Installation soll nur bei aktiver Menüauswahl starten,
nie automatisch beim bloßen Verstreichen des Countdowns. Kein Fix nötig
- für Tests (und für Kunden) muss der Eintrag "Start Linux Mint" (bzw.
in Produktion später ein reparierter "Tuxflotte Auto-Install"-Eintrag)
aktiv ausgewählt werden.
### Offen: automatisierter Klick auf "Jetzt installieren" noch nicht
### zuverlässig
Nach Fix 3 erreicht der Installer real die Partitionierungs-Übersichts-
seite korrekt und wartet dort auf einen Klick auf "Jetzt installieren".
`autoclicker.sh` (Enter-Taste an das Hauptfenster) hat auf dieser
speziellen Seite keinen Effekt - Enter aktiviert dort einen
Ausklapp-Pfeil eines Status-Panels ("Konfiguration der Installation wird
überprüft ..."), nicht den Installieren-Button. Mausklick-Versuche per
`xdotool`/QMP auf berechnete Fensterkoordinaten scheiterten an
unzuverlässiger Fenstererkennung (mehrere überlappende X11-Fenster
ähnlicher Größe durch Metacity-Fensterdekoration, "größtes sichtbares
Fenster"-Heuristik traf wiederholt das falsche Fenster) - bewusst NICHT
in den produktiven Autoklicker übernommen, um kein Risiko fehlgeleiteter
Klicks (z. B. versehentlich eine "Formatieren?"-Checkbox) einzugehen.
Zusätzlich wurde dabei ein eigener, unabhängiger Bug in der
Fenstersuche gefunden und behoben: `autoclicker.sh` suchte bisher nach
einem Fenster namens "ubiquity" - der tatsächliche Fenstertitel ("Installation
(as superuser)") enthält dieses Wort nie, die Suche fand also nie
etwas. Das ist jetzt korrigiert (Suche nach jedem betitelten sichtbaren
Fenster statt nach dem Namen "ubiquity"), der eigentliche Klick-Schritt
bleibt aber offen.
**Nächster Schritt, nicht mehr in dieser Sitzung verfolgt:** vermutlich
robusteste Lösung wäre AT-SPI (Accessibility-API) statt Pixel-/Fenster-
Heuristik - findet Buttons über ihre Rolle ("Push Button") und ihren
(übersetzten) Namen, unabhängig von X11-Fensterüberlappung. Nicht
recherchiert, da Zeitrahmen dieser Sitzung erschöpft.
## Nachtrag (29.08.2026): AT-SPI-Autoklicker gebaut, live verifiziert -
## neuer, tieferer Blocker in ubi-partman.py selbst gefunden
**AT-SPI-Umbau, Status: fertig und live verifiziert.** `autoclicker.sh`
klickt jetzt über die Linux-Barrierefreiheits-API (`python3-pyatspi`)
statt über Bildschirmkoordinaten/Enter-Taste:
- `live-updates/usr/share/ubiquity/tuxflotte-atspi-env.sh` (neu, per
Ein-Zeilen-Sed-Patch in `start-ubiquity-dm` eingebunden, *vor* dem
GTK-Start von Ubiquity, da die Bruecke sich nachtraeglich nicht mehr
laden laesst): aktiviert `GTK_MODULES=gail:atk-bridge`, startet bei
Bedarf einen Session-Bus (`dbus-launch`) und `at-spi-bus-launcher`.
- `live-updates/opt/tuxflotte/scripts/atspi_click.py` (neu): findet den
zu klickenden Button ueber Rolle (`PUSH_BUTTON`) im Accessibility-Baum.
**Wichtig, real beim Testen entdeckt:** trotz festem
`debian-installer/language=de` ist nicht jede Seite deutsch beschriftet
- die Mint-eigene "Multimedia-Codecs"-Seite zeigt reale englische
Buttons ("Quit"/"Back"/"Continue"), vermutlich derselbe fehlende
.mo-Uebersetzungskatalog wie beim schon gepatchten
ubi-prepare.py-None-Bug (siehe oben). Eine anfaengliche reine deutsche
Werteliste blieb dort haengen. Umgestellt auf eine sprachunabhaengige
Strategie: bekannte rueckwaerts-/abbrechende Beschriftungen (zweisprachig)
werden ausgeschlossen, von den verbleibenden Kandidaten wird bevorzugt
wer eine bekannte vorwaerts-Beschriftung traegt, sonst der einzige
uebrige Kandidat (Sole-Survivor-Regel); bei echter Mehrdeutigkeit wird
bewusst NICHT geklickt.
- **Live-Beleg, dass AT-SPI selbst zuverlaessig funktioniert:** Log zeigt
103 aufeinanderfolgende, korrekt erkannte Klicks auf "Jetzt
installieren" im 2-Sekunden-Takt, ueber mehrere Minuten, ohne einen
einzigen Fehlklick. Die Fenstergeometrie-/Dekorationsprobleme, an denen
der xdotool-Ansatz scheiterte, treten mit AT-SPI nicht mehr auf.
**Nebenfund beim Testen, live gefixt:** der Kexec-Append in
`backend_launch()` setzte anders als der Grub-Eintrag des ersten Boots
kein `username=`/`hostname=` - dadurch verlangte der Live-Nutzer beim
zweiten (Kexec-)Boot ein echtes, unbekanntes Passwort statt des sonst
leeren Live-Session-Passworts (fuer den GTK-Assistenten selbst
folgenlos, erschwerte aber die Fehlersuche via Konsole unnoetig). Fix:
`username=mint hostname=mint` ergaenzt, Konsistenz zum ersten Boot
wiederhergestellt.
### Neuer, tieferer Blocker (noch offen): `ubiquity/partman-rebuild-cache`
### fuehrt nach erfolgreichem Klick zurueck in die Partitionierung
Mit funktionierendem AT-SPI-Klick wurde ein neues, von der Klick-Technik
unabhaengiges Problem sichtbar: der Klick auf "Jetzt installieren" auf der
manuellen Partitionierungsseite ("Etwas Anderes" - Ubiquity zeigt diese
Seite fuer jedes nicht eingebaute/custom `expert_recipe`, korrektes
Verhalten) wird tatsaechlich ausgefuehrt und fuehrt laut
`/var/log/installer/debug` nachweislich in den Erfolgspfad
(`grub-installer/bootdev seen` wurde erreicht - das passiert laut
Quelltext direkt nach `self.finish_partitioning = True; self.succeeded =
True; self.exit_ui_loops()`), aber kurz danach springt der Installer
zurueck in dieselbe Partitionierungsseite, und der Autoklicker beginnt
von vorn - ueber 100 Zyklen beobachtet, ohne jemals durchzukommen.
Quelltext-Analyse (`/usr/lib/ubiquity/plugins/ubi-partman.py` auf dem
Live-Medium, per Konsole gelesen) zeigt die Ursache strukturell:
```python
def rebuild_cache(self):
assert self.current_question == 'partman/choose_partition'
self.building_cache = True
```
aufgerufen, wann immer Debconf die Frage `ubiquity/partman-rebuild-cache`
stellt (Zeile ~2195: `if question == 'ubiquity/partman-rebuild-cache':`).
Diese Frage kommt von partmans eigenen Shell-Skripten (nicht von
ubi-partman.py selbst), noch nicht bis zur Quelle zurueckverfolgt, ob
partman sie hier zu Recht/wiederholt stellt oder ob unser eigenes
`expert_recipe` (insb. das `$reusemethod{ }`-Flag auf der ESP-Stanza,
siehe `_tuxflotte_render_partman_recipe()` - laut Code-Kommentar dort
bewusst aus der eingebauten "atomic"-Recipe uebernommen, weil ohne dieses
Flag die ESP frueher nicht als gueltig erkannt wurde) eine partman-interne
Neubewertung immer wieder auf "muss neu validiert werden" kippen laesst.
**Wichtig fuer die weitere Suche:** dieser Loop ist strukturell derselbe
wie der oben (Fix 3) bereits dokumentierte `choose_partition`/
`building_cache`-Loop, tritt hier aber nachweislich auch bei einem
tatsaechlichen, korrekten GTK-Klick auf (nicht nur bei direktem
Preseeden einer Debconf-Antwort ohne echten Seitenaufbau) - die Ursache
liegt also tiefer in partmans eigener Zustandsverwaltung bzw. in unserem
Rezept, nicht (nur) im Preseed-Mechanismus.
**Status:** AT-SPI-Klick-Mechanismus als Aufgabe abgeschlossen und
verifiziert - die verbleibende Blockade ist ein eigenstaendiges,
partman-internes Problem, keine Klick-Zuverlaessigkeitsfrage mehr.
### Getestete Hypothese, WIDERLEGT: `$bootable{ }` auf der Root-Partition
Vermutung: die Original-Recipe `/usr/lib/partman/recipes-amd64-efi/30atomic`
(Quelle unserer ESP-Stanza) markiert im UEFI-Fall NUR die ESP als boot-
faehig (`method{ efi }`), nicht zusaetzlich die Root-Partition - unser
Rezept setzte dagegen unbedingt `$primary{ } $bootable{ }` auf Root,
unabhaengig von EFI/BIOS. `_tuxflotte_render_partman_recipe()` entsprechend
angepasst (`root_extra_flags` bedingt: kein `$bootable{ }` mehr im
EFI-Zweig, weiterhin gesetzt im BIOS-Zweig, wo keine ESP existiert).
**Live getestet (29.08.2026) - Ergebnis: KEIN Unterschied.** Nach dem Fix
weiterhin exakt dasselbe Verhalten: Autoklicker-Log zeigt 119
aufeinanderfolgende Klicks auf "Jetzt installieren" ohne jeden
Fortschritt, identisch zum Verhalten vor dem Fix. Die Aenderung bleibt im
Code (harmlos, entspricht der Original-Recipe und ist an sich korrekter),
loest aber nicht das eigentliche Problem - `$bootable{ }` auf Root war
NICHT die (alleinige) Ursache des Loops.
**Nebenfund waehrend dieses Testlaufs:** der zum Testen verwendete
Aktivierungscode (enrollment_sessions.id, Liebherr-Org) erschoepfte real
sein Kontingent (`devices_used = max_devices = 20`) nach den vielen
Testlaeufen dieser Sitzung - `/activate` schlaegt dann mit
"invalid_activation_code" fehl, obwohl der Code selbst nicht abgelaufen
oder widerrufen ist (siehe `find_enrollment_session()` in
`provisioning-server/app.py`). Kein Bug, aber fuer weitere Testrunden
relevant: entweder `recharge_enrollment_session()`-Semantik per direktem
`UPDATE enrollment_sessions SET max_devices = max_devices + N` nachbilden,
oder von vornherein mit einem grosszuegigen `max_devices` fuer
Testsessions arbeiten.
**Naechste sinnvolle Schritte (nicht mehr in dieser Sitzung verfolgt):**
(a) die partman-Shell-Skripte (nicht nur ubi-partman.py) daraufhin
durchsuchen, was `ubiquity/partman-rebuild-cache` sonst noch ausloesen
koennte (`$reusemethod{ }` auf der ESP selbst ist noch nicht einzeln
getestet - nur die Root-Flags wurden bisher angepasst), (b) pruefen, ob
eine der eingebauten Recipes (z. B. "atomic" direkt statt eines eigenen
`expert_recipe`) fuer unsere Anforderungen ausreicht und damit die
manuelle "Etwas Anderes"-Seite (und ihre rebuild-cache-Interaktion) ganz
umgeht, oder (c) untersuchen, ob AT-SPIs `doAction(0)` auf dem Button
tatsaechlich denselben Codepfad ausloest wie ein echter Mausklick (das
Debug-Log erreichte in einem frueheren Testlauf einmalig
"grub-installer/bootdev seen", also einen Schritt NACH der
Partitionierung - dieser Fortschritt trat aber nur einmal auf und wurde
seither nicht reproduziert, was auf einen nicht-deterministischen Faktor
hindeutet statt auf einen stets gleich reproduzierbaren Blocker).