# Fallstricke und Erkenntnisse
Gemeinsames Gedächtnis: Dinge, die man **nicht aus dem Code ablesen kann** und die schon einmal Zeit gekostet haben.
Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik. Veraltetes löschen, nicht auskommentieren.
## BPMN und PICTURE (Skill sn-bpmn, md_to_bpmn.py)
- **Echte Daten brechen, was die Beispiele nicht zeigen.** Der Stresstest mit 23 Diagrammen aus PICTURE ist
strukturell sauber (keine Kante durch ein Element). Er zeigt aber: Gateway-Fragen über 80 Zeichen werden
geschnitten, 31 Datenobjekte in einer Reihe machen das Diagramm über 11 000 breit, und ein unbeschriftetes
Gateway lässt sich keiner Lane zuordnen (`TG:` wird zum Namen). Exportformat, Abbildungsregeln und alle Befunde:
`picture_import.md`. (28.09.2026)
- **PICTURE-Exporte enthalten interne Kopfdaten.** Mandant, Mandanten-URL, Arbeitsbereich und REST-URLs in jeder
Verknüpfung, dazu in Anmerkungen gelegentlich Raumnummern und Standorte. Exporte gehören nach `referenz/`, nie
nach `docs/`; beim Rückwandeln nur Namen übernehmen, Anmerkungen vor dem Ablegen durchsehen. (28.09.2026)
- **Vorwärtskanten kennen die übrigen Elemente nur im Notfall.** `orthogonal_points()` rechnet rein geometrisch
zwischen zwei Anschlusspunkten. Das reicht, solange das Layout regelmäßig ist. Eine Querverbindung zwischen
Geschwisterzweigen schiebt aber eine Aufgabe eine Ebene tiefer in eine Zwischenspalte. Deshalb prüft
`build_bpmn()` jeden Standardweg gegen alle fremden Elemente und sucht nur bei einer Kreuzung mit
`umweg_points()` einen Weg über freie Linien (Lückenmitten, 15 neben jedem Element; erst ein, dann zwei
Zwischenknicke; kürzester gewinnt). So bleiben saubere Kanten byte-gleich. Der Belastungstest aus #12 ist jetzt
ein dauerhafter Test (`test_belastung_keine_kante_durch_ein_element_und_rechtwinklig`, 126 Fälle). (#22,
25.09.2026)
- **Auch das Aufgaben-Ende einer Gateway-Kante braucht ein gerades Stück.** Das Gateway-Ende bekommt einen festen
Anschlusspunkt (N/O/S/W), das Aufgaben-Ende die Layout-Seite (mit Lanes O/W, ohne Lanes N/S). Liegen beide auf
verschiedenen Achsen, lief die Kante früher direkt an der Aufgabenkante entlang. Jetzt bekommt die Aufgabe einen
Stub (`RECHTECK_STUB = 20`) senkrecht zu ihrer Seite, danach geht es wie zwischen zwei Rauten von Stub zu Stub.
Geprüft mit `test_kanten_setzen_an_aufgaben_rechtwinklig_an` über alle Beispiele. Im Belastungstest aus #12 sind
378 schräge Anschlüsse verschwunden. Dafür laufen in 4 künstlichen Fällen mit Querverbindung zwischen Zweigen
Kanten durch eine Aufgabe, in 2 anderen nicht mehr (Art von #22). (#23, 25.09.2026)
- **PICTURE übernimmt Beschriftungspositionen und Kästchengrößen aus der Datei.** Ohne `BPMNLabel` setzt es die
Gateway-Beschriftung auf 180° (unter die Raute), wo der südliche Pfad und dessen Beschriftung sie schneiden. Im
PICTURE-Editor steht sie auf 45°. Der Konverter setzt die Position deshalb selbst: 45°, sonst 45° rechts vom
Ost-Stub, 315°, 135°, 225° – die erste Stelle, die keine Kante, Kantenbeschriftung oder kein Element schneidet.
Dafür werden die Gateway-Beschriftungen **nach** allen Kanten gesetzt. Zu kleine Anmerkungs-Kästchen vergrößert
PICTURE beim Import, dann überlappen sie Nachbarn und Lane-Grenzen. Deshalb richtet sich die Höhe nach dem Text
(`text_zeilen()`, grobe Schätzung 7 je Zeichen), und die Anmerkungen stehen rechts neben dem Pool.
`GATEWAY_LABEL_BREITE = 90` hängt an `AUSWEICHABSTAND` (#8): Bei 100 ragte die Beschriftung über die
Ausweichachse bei x + 130. Pool-Name über dem Namen der ersten Lane: nur in der Vorschau beobachtet, in PICTURE
kein Problem. (PICTURE 2026.4.1, #14, 25.09.2026)
- **Nachrichtenflüsse enden senkrecht unter ihrem Start, nicht an einem verteilten Punkt.** Der externe Pool ist
ein breites Rechteck, jeder Punkt an seiner Oberkante ist ein gültiger Anschluss. Die frühere Verteilung der
Anschlusspunkte über die Pool-Oberkante erzeugte schräge Linien quer durch das Diagramm. Steht unter dem Schritt
ein Element, geht der Fluss über einen Gang: mit Lanes 20 neben dem Gang der Rücksprungkanten und mit längerem
Stub (30 statt 20), damit sich beide nicht überdecken; ohne Lanes rechts neben allen Elementen, dafür wird der
Pool breiter. Belastungstest mit 342 Varianten: vorher 182 Fälle mit Kreuzung, jetzt keiner. (#13, 25.09.2026)
- **Rücksprungkanten brauchen je Layout eine eigene Führung.** Mit Lanes stehen die Elemente in festen Spalten
(linksbündig, 190 auseinander). Der Rückweg läuft senkrecht nur in den Gängen zwischen den Spalten und waagrecht
in einem Kanalband, das am Boden der letzten Lane **nach** der Platzierung angehängt wird. So bleiben die
Elemente, wo sie sind, und die Kante bleibt im eigenen Pool. Ohne Lanes gibt es keine festen Spalten, parallele
Zweige stehen versetzt zur Mitte. Der Kanal liegt deshalb seitlich an **allen** Elementen zwischen Quelle und
Ziel vorbei. Steht ein Nachbar in derselben Zeile im Weg, geht die Kante unten hinaus bzw. oben hinein.
Geprüft mit allen 126 Rücksprung-Varianten zweier Testmodelle, mit und ohne Lanes. (#12, 25.09.2026)
- **Vorschau und PICTURE können sich unterscheiden, auch ohne Fehler im Modell.** Beispiel XOR-Gateway: PICTURE
zeichnet das „X“ nach eigenen Regeln, auch ohne `isMarkerVisible`. Die Vorschau (bpmn-js) hält sich an das
Attribut und zeigte ohne es leere Rauten. Seit #15 setzt der Konverter das Attribut, beide zeigen das X. Wirkt
etwas nur in der Vorschau falsch, erst in PICTURE gegenprüfen, bevor der Konverter geändert wird.
(PICTURE 2026.4.1, #15, 25.09.2026)
- **Gateway → Gateway mit Ziel „hinter“ dem Start-Stub braucht einen seitlichen Umweg.** Liegt der Stub des
Start-Gateways schon jenseits des Ziel-Anschlusspunkts (z. B. Südpunkt unten, Ziel höher mit Nordpunkt), läuft
das letzte gerade Stück durch die Ziel-Raute. `orthogonal_points()` weicht dann über `_ausweichachse()` aus.
Die Achse liegt **im Gang direkt vor der Ziel-Spalte** (Abstand 85 zur Mitte), **nicht in der Mitte zwischen
Quelle und Ziel**: Liegen die beiden zwei Spalten auseinander, steht dort eine Aufgabe (im Referenzmodell S43).
(#8, 25.09.2026)
- **Bekannte Layoutfehler je Kreuzung als xfail, nie je Modell.** Stünde ein ganzes Modell auf `xfail`, bliebe
jede neue Kreuzung darin unsichtbar, solange der alte Fehler besteht. Deshalb prüft
`test_keine_unbekannte_kante_fuehrt_durch_ein_element` alle Kanten gegen alle Elemente und meldet alle Funde
außer den Paaren in `BEKANNTE_KREUZUNGEN`. Jedes dieser Paare hat einen eigenen strikten xfail-Test. Anlass: Die
alte Gateway-Prüfung brach beim ersten Fund ab; bei #8 stand nur S12→S13 im Issue, tatsächlich waren es sieben
Kreuzungen. (#16, 25.09.2026)
- **Zusammenführende Gateways brauchen eine Beschriftung mit Zuständigkeit**, sonst landen sie in der Lane
„Nicht zugeordnet“ (`split_lane()` braucht Text nach dem Doppelpunkt). In BPMN bleiben Zusammenführungen
üblicherweise unbeschriftet – ein Fall für eine spätere Konverteränderung. (23.09.2026, Referenzmodell)
- **Das bpmn.io-Wasserzeichen ist Lizenzauflage.** bpmn-js steht unter MIT, verlangt aber, dass das Wasserzeichen
unten rechts sichtbar bleibt und nicht überdeckt wird. In `werkzeuge/vorschau/vorschau.html` deshalb nichts in die
untere rechte Ecke der Zeichenfläche legen. (bpmn-js `LICENSE`, 23.09.2026)
- **Diagramme nie roh in ein `` würde den Skriptblock beenden.
`scripts/vorschau.py` maskiert jedes `<` im Diagramm als `\u003c`; die Bibliothek selbst wird nicht verändert,
sondern nur auf `