fix(live): Wiederverbindung sendet nie von selbst — Server-Stand oder Rückfrage (D89-Nachtrag 2)
Deploy to GitHub Pages / build (push) Canceled after 0s
Deploy to GitHub Pages / deploy (push) Canceled after 0s

Ein Fenster, das mit altem Text aufwachte, schickte ihn beim Wiederverbinden
als Diff und überschrieb den aktuellen Plan (v660, v679). Jetzt entscheidet,
ob seit dem letzten Abgleich hier gearbeitet wurde: nein → Server-Stand
übernehmen (lokaler Text in die Sicherungen), ja → Konflikt-Band fragt.
Regel headless in live.js (reconnectAction), Bandtext in neun Sprachen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-09-04 12:34:01 +02:00
co-authored by Claude Fable 5.1
parent 2e408d956c
commit 28ff6844b0
6 changed files with 134 additions and 7 deletions
+52
View File
@@ -7815,6 +7815,58 @@ Entscheidungen: **D94** und `docs/rfc/002-mehrfenster.md`. Der Präsenz-Kanal
(Herzschlag, Timeout, Notluke) und der modale Dialog sind ersatzlos
ausgebaut; die drei anderen Netze (Sicherungen, Rettung, Wachhund) bleiben.
**Nachtrag 2 — die Wiederverbindung sendet nie von selbst (2026-09-04).**
Der zweite Datenverlust am selben Dokument, diesmal nachgemessen bis zur
Ursache: Version 679 (11:49 Uhr) kam von einem anderen Client (der PWA auf
dem Telefon) und war byte-genau Version 667 — der letzte Stand, den das
Telefon am Vortag gesehen hatte — plus drei Faltmarken. Die 16 Zeilen aus
668 bis 671 waren weg; der Nutzer hat 671 per Rollback (v680) zurückgeholt.
Dasselbe Muster wie v660 am Abend davor (byte-gleich mit v339).
**Der Mechanismus stand im D90-Nachtrag, als Rettung gemeint.** Die
Wiederverbindung nach einer toten Sitzung holte den Server-Stand als
Schattenkopie und schickte dann jeden abweichenden lokalen Text als Diff —
„ungesendeter Text bleibt stehen, die keepMine-Semantik". Sie konnte nicht
unterscheiden, ob der lokale Text **neuer** ist als der Server (ungesendete
Arbeit) oder **älter** (ein Fenster, das lange geschlafen hat): In beiden
Fällen ist er „anders", und die alte Fassung ging als Diff gegen den
aktuellen Server hinaus, was einer Vollersetzung gleichkommt. Die Kette auf
dem Telefon: Die PWA wacht auf, der erste Abruf scheitert (Funk noch aus),
die Sitzung ist tot, der Editor zeigt den lokal gespeicherten Text vom
Vortag. Ein Tipp auf ein Falt-Zeichen ändert ihn (Falten schreibt in den
Text, D38-Nachtrag 2). Der Wachhund verbindet neu, sieht „lokal ≠ Server"
und schickt.
**Entscheidend ist nicht der Vergleich der Texte, sondern ob hier gearbeitet
wurde.** Zwei Zähler in app.js: einer zählt jede Textänderung an einem
Server-Dokument — mit oder ohne Sitzung, denn das Falten auf einem toten
Telefon ist genau der Fall —, der andere hält den Stand, den der Server
zuletzt bestätigt hat oder den wir von ihm übernommen haben (gelungenes
Senden, Laden, Volltext aus dem Feed, *Fremde übernehmen*). Ein Senden,
während weiter getippt wird, bestätigt nur, was es getragen hat. Die Regel
selbst steht headless in `live.js` (`reconnectAction`, D54-Nachtrag 3):
Texte gleich → nichts zu entscheiden; nicht gearbeitet → der Server gilt,
der lokale Text wandert in die lokalen Sicherungen; gearbeitet → das
vorhandene Konflikt-Band fragt, mit eigenem Text („Dieses Fenster war
getrennt und hat eigene Änderungen — der Stand auf dem Server weicht ab").
Nichts geschieht stumm, und beide Stände existieren, bis ein Mensch
entscheidet.
**Nachgemessen** im Browser gegen ein lokales Backend, das Telefon-Szenario
nachgestellt: Server auf v2 gesetzt, Backend gestoppt, Seite geladen — Chip
„getrennt", Editor zeigt den alten Spiegel (v1). Backend wieder da, nichts
angefasst: nach ≤ 20 s zeigt der Editor v2, der Server steht **unverändert
auf v2** (vorher hätte das Fenster hier v3 mit dem alten Text geschrieben).
Zweiter Durchlauf mit einer getippten Zeile im getrennten Zustand: Das Band
erscheint mit dem neuen Text, der Server bleibt auf v2, der lokale Text
steht; *Eigene durchsetzen* schreibt v3 mit genau dieser Zeile. 669 Tests,
davon 3 neue.
**Was bleibt:** Ein Fenster, das mit **ungesendeter** Arbeit ganz beendet
wird (Android räumt die PWA ab), startet mit dem Server-Stand; die Arbeit
liegt dann in den lokalen Sicherungen (Netz 3 aus dem Haupttext), nicht im
Editor — unverändert seit D89.
## D90 — Die Dokumentart steht grau hinter dem Namens-Chip
Nutzerwunsch, unmittelbar aus dem D89-Vorfall: Hinter der Brotkrume
(„Werkbaum Name", D81) soll erkennbar sein, was für ein Dokument vorn ist —