Commit Graph
5 Commits
Author SHA1 Message Date
mhoennigandClaude Fable 5.1 28ff6844b0 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>
2026-09-04 12:34:01 +02:00
mhoennigandClaude Fable 5 67d0ef421b fix(teilen): Basis-Adresse per Lebendprobe prüfen, sonst fragen (D81-Nachtrag)
Auf einer Instanz ohne eigenes Backend (GitHub Pages) endete Teilen mit
HTTP 405: Die Vorgabe "eigene Herkunft" (D76-Nachtrag 8) stimmt nur auf der
produktiven Installation. serverBaseOrAsk() prüft die Vorgabe jetzt mit
GET /api/v1/info (D77), bevor gePOSTet wird, und fragt sonst nach der
Server-Adresse; gemerkt wird nur eine Adresse, die die Probe besteht.
Von Pages aus trägt man werkbaum.javagil.de ein — CORS erlaubt es.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 05:23:19 +02:00
mhoennig e19a119966 fix(live): der Client stritt mit sich selbst (D76-Nachtrag 9)
Gemeldet: zwei Browser am selben Dokument, einen Knoten zuklappen, und es
kommt "Someone changed the same lines. Whose version should win?".

Der Feed beantwortet "was ist seit Version N geschehen" - und wer da
mitgeschrieben hat, steht nicht in der Frage. Er liefert also die EIGENE
Aenderung zurueck, und wacht er im Moment des eigenen Sendens auf, kommt sie
an, bevor die Antwort darauf da ist. Die Schattenkopie steht dann noch auf dem
Stand davor: Der Client haelt die eigene Aenderung fuer fremd, sieht sie sich
mit dem eigenen Text ueberschneiden und fragt. Die Erkennung hatte recht,
falsch war nur, wen sie fuer den anderen hielt. Der zweite Browser ist dafuer
gar nicht noetig; das Falten ist nur die kuerzeste Geste, die eine ganze Zeile
aendert.

Auf localhost liegen PATCH- und Feed-Antwort 7 ms auseinander und die
PATCH-Antwort gewinnt - der Fehler tritt dort nie auf. Reproduziert mit im
Client um 500 ms verzoegerter PATCH-Antwort (eine Reihenfolge, die uebers Netz
jederzeit auftritt): PATCH an 200 / FEED an 200 / KONFLIKT-BANNER.

Behoben in feedAction() (live.js) - dort steht ohnehin, wann eine Feed-Antwort
angewendet werden darf; Gegenprobe: Sperre entfernt => genau die zwei neuen
Zusicherungen fallen. Dieselbe Sperre gehoert in die runFeed-Schleife, sonst
fragt sie sofort wieder und dreht eine enge Runde uebers Netz.

Dabei gefunden: pushLive() las seine Basis erst NACH dem await und nahm damit
an, dass sich dazwischen nichts aendert - der Feed brach genau die Annahme und
haette die eigene Aenderung ein zweites Mal aufgerechnet. Jetzt vorher
festgehalten.

Nachgemessen: Falten erzeugt kein Banner mehr, fremde Aenderungen kommen
weiterhin an, und der ECHTE Konflikt wird weiterhin erkannt (A haelt
ungesendeten Text auf Zeile 1, B aendert dieselbe Zeile). 525 Tests.
2026-08-26 20:12:42 +02:00
mhoennigandClaude Opus 5 ea1979d567 feat(frontend): "Auf den Server legen" im Dokumenten-Menue (D76-Nachtrag 8)
Bis hierher kam ein Plan nur per curl auf den Server — der Menueintrag war im
Konzept vorgesehen und fehlte. Jetzt legt der Knopf das aktive Dokument an,
schaltet dorthin um und schreibt den Link in die Adresszeile und in die
Zwischenablage. Die Adresszeile IST der Link: dort sucht man ihn, und ein
Neuladen fuehrt ins selbe Dokument zurueck.

Die Basis-Adresse ist die eigene Herkunft — produktiv liegt das Backend hinter
derselben Domain, wer nichts konfiguriert bekommt also das Richtige. Darueber
liegen ?server= (Entwicklung) und die Adresse des offenen Server-Dokuments.
Traegt nichts, wird gefragt.

Das lokale Dokument bleibt: Wer sein einziges Exemplar einem Server
anvertraut, soll es nicht im selben Zug verlieren. Dafuer nennt der Waehler
jetzt den Host neben Server-Dokumenten — im Test standen sonst zwei Eintraege
"Nur lokal" da, unterscheidbar nur am Tooltip. Und der Knopf verschwindet bei
Dokumenten, die schon auf einem Server liegen.

Geprueft im Browser gegen ein echtes Backend: Knopf sichtbar bei einem lokalen
Dokument, nach dem Klick steht ?live=... in der Adresszeile, das lokale
Dokument ist noch da, der Knopf verborgen — und eine getippte Zeile erreicht
den Server als Version 2.

523 Frontend-Tests (5 neue fuer serverBase/documentsUrl).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 19:39:28 +02:00
mhoennigandClaude Opus 5 5881be1a2c feat(frontend): Zeilen-Diff und Adressen fuer Server-Dokumente (live.js)
Die entscheidbare Haelfte des Live-Editing-Clients (D76), headless und
geprueft: ?live=-Adressen normalisieren, Zeilen-Diff berechnen und anwenden,
die Cursor-Zeile durch fremde Aenderungen mitfuehren, und die Regel, wann eine
Feed-Antwort ueberhaupt angewendet werden darf.

Zerlegen und Hashen liegen hier und nicht verstreut in app.js: Beide Seiten
muessen Text gleich in Zeilen zerlegen, sonst zeigen die Indizes auseinander.
Das Diff-Modell ist dasselbe wie im Backend (de.werkbaum.diff.LineDiff).

Die Cursor-Rechnung ist der Teil, ohne den "kein Neuladen" nichts wert waere:
Ohne sie spraenge die Schreibmarke bei jeder fremden Aenderung weiter oben im
Dokument.

518 Tests (31 neu). Gegenprobe: Feed-Basis nicht geprueft, Zeile im Eingriff
wie darunter behandelt, Protokoll nicht geprueft -> es faellt jeweils genau
die danach benannte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 17:32:59 +02:00