feat(editor): Mehr-Fenster-Betrieb gebaut — Ablageschema v3, Tombstones, docsync, Sperre je Dokument (RFC 002, D94)

Kein Fenster schreibt mehr den Schlüssel eines anderen: Text, Meta und
frühere Stände liegen je Dokument unter eigenen Schlüsseln, der Index ist
nur noch Reihenfolge-Hinweis und löscht nie, Löschungen hinterlassen einen
Tombstone (7 Tage). Der Voll-Flush weicht dem Dirty-Flush. Damit sind
Befund 2 und 3 des RFC weg — verschiedene Dokumente in zwei Fenstern
kollidieren gar nicht mehr. docsync.js zieht Liste, Namen, Tombstones und
den Stände-Cache aus dem storage-Ereignis nach; am aktiven Dokument die
drei Fälle umbenannt / anderswo gelöscht (behalten, bis getippt wird) /
fremd geschrieben. Der modale D89-Dialog samt Präsenz-Kanal ist ersatzlos
raus; den einen Verlustfall — dasselbe nicht-`live:`-Dokument in beiden
Fenstern vorn — findet eine Sperre per Web Locks, und das zweite Fenster
bekommt drei Auswege statt „trotzdem fortfahren".

Im Browser mit zwei echten Tabs nachgemessen (RFC §10): Fälle 1–8 grün,
Fall 1 im Vor-v3-Build gegengeprüft und dort nachweislich rot. Fall 9
deckte auf, dass reviveGoneDoc() den Index-Hinweis nicht mitschrieb — ein
durch Tippen wiederbelebtes Dokument hing bis zum nächsten Flush allein an
seinen eigenen Schlüsseln und wäre bei einem Rückbau auf einen Build vor
v3 still verlorengegangen; behoben, Gegenprobe per Mutation gezogen.
Headless 666 Tests grün. Offen bleibt die Handarbeit: PWA neben Tab,
Firefox, Safari, ein Browser ohne Locks-API.

SPEC §9, D94, D89-Nachtrag, RFC (Status, §10, Revisionsgeschichte),
CHANGELOG und Plan-Knoten #ed.docs.windows nachgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-09-02 20:07:20 +02:00
co-authored by Claude Opus 5
parent 112ada4e58
commit caaf7c15e1
15 changed files with 1633 additions and 395 deletions
+9 -5
View File
@@ -52,10 +52,14 @@
droht beim Neuladen; zeilenlos, steht
zuoberst und verschwindet, sobald ein
Schreiben wieder gelingt
- tabConflict { } — ein weiterer Tab schreibt in dieselbe
Dokument-Ablage (D84): der letzte Flush
gewinnt; zeilenlos, bleibt bis zum
Neuladen stehen
- tabConflict { name, where } — dasselbe nicht geteilte Dokument wird
in einem anderen Fenster bearbeitet
(RFC 002/D94, der Restfall): der letzte
Tastendruck gewinnt; zeilenlos, bleibt
stehen, solange das Dokument aktiv ist.
`where` ist ein i18n-Schlüssel für
„in der App" / „im Browser" — aus der
Sicht des eigenen Fensters gefolgert
- liveUnsent { min } — Änderungen an einem Server-Dokument seit
{min} Minuten nicht angekommen (D89):
sie existieren nur in diesem Fenster;
@@ -117,7 +121,7 @@ function build(w, t, esc){
case 'storeFailed':
return t('storeFailedWarn');
case 'tabConflict':
return t('tabConflictWarn');
return t('tabConflictWarn', {name: esc(w.name || ''), where: t(w.where || 'windowKindBrowser')});
case 'liveUnsent':
return t('liveUnsentWarn', {min: w.min});
case 'liveEnded':