- Gateway-Beschriftungen bekommen eine feste Position (BPMNLabel), weil PICTURE sie aus der Datei übernimmt: 45° wie im PICTURE-Editor, sonst 45° rechts vom Ost-Stub, 315°, 135°, 225° – die erste Stelle ohne Kante, Kantenbeschriftung oder Element. Gesetzt nach allen Kanten. - Kantenbeschriftungen waagrecht aus einem Gateway stehen unter der Linie (darüber steht die Gateway-Beschriftung). - Anmerkungen rechts neben dem Pool untereinander, Höhe passend zum Text (text_zeilen(), anmerkung_groesse()); Pool ohne Anmerkungen bemessen. - Beispiele neu erzeugt. Alle 17 Gateway-Beschriftungen auf 45° bzw. 45° rechts vom Stub, keine im Lane-Kopf oder in einer Nachbar-Lane. - Strukturtests für alle Beispiele (Beschriftung ungeschnitten, in der eigenen Lane; Anmerkungen ohne Überlappung, neben dem Pool, groß genug) und drei Einzeltests. - Tests: python -m pytest -q -> 117 bestanden, 1 übersprungen (leere Parameterliste der bekannten Kreuzungen). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
128 lines
11 KiB
Markdown
128 lines
11 KiB
Markdown
# 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)
|
||
|
||
- **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 `<script>` schreiben.** Eine Beschriftung mit `</script>` würde den Skriptblock beenden.
|
||
`scripts/vorschau.py` maskiert jedes `<` im Diagramm als `\u003c`; die Bibliothek selbst wird nicht verändert,
|
||
sondern nur auf `<script`/`</script` geprüft. (23.09.2026)
|
||
|
||
- **Jede Änderung an der Ausgabe von `md_to_bpmn.py` macht die abgelegten `.bpmn` rot.** Der Test in
|
||
`tests/test_pruefe_prozesse.py` vergleicht jede `.bpmn` der Prozessbibliothek und in `beispiele/` byte-genau mit
|
||
der Umwandlung ihrer `.md`. Nach einer Konverteränderung `python scripts/pruefe_prozesse.py --erzeugen` ausführen;
|
||
die neuen `.bpmn` der Beispiele gehören in den Pull Request, die der Bibliothek in einen eigenen Pull Request dort
|
||
(ADR 0004). Das setzt voraus, dass der Konverter deterministisch
|
||
bleibt: keine Zufalls-IDs, keine Zeitstempel, keine Reihenfolge aus `set`-Iteration. (ADR 0003, 23.09.2026; ADR 0004, 25.09.2026)
|
||
- **Zusätzliche Zeilen in einer Arbeitsschritt-`.md` nur ganz oben oder mit `#`.** `parse_markdown()` bricht
|
||
nach dem ersten Schritt bei jeder unbekannten Zeile ab; davor überspringt es Zeilen, die nicht wie
|
||
`Schlüssel: Wert` aussehen. Deshalb steht der Einlese-Vermerk (`<!-- eingelesen: … -->`) als erste Zeile.
|
||
(23.09.2026, `scripts/einlesen.py`)
|
||
- **`Path.read_text()` macht aus CRLF stillschweigend LF.** Wer eine Datei liest und mit Zusatz zurückschreibt,
|
||
stellt so Windows-Dateien unbemerkt um. `scripts/einlesen.py` liest deshalb als Bytes. (23.09.2026, Test)
|
||
- **Metadaten gehören nicht als Kopfzeile in die Arbeitsschritt-`.md`.** `parse_markdown()` liest eine Zeile wie
|
||
`Verantwortliche Stelle: …` als Schritt mit ID `Verantwortliche` und Typ `Stelle` und bricht ab. Status und Stand
|
||
stehen deshalb im Steckbrief `README.md` des Prozessordners. (23.09.2026)
|
||
- **Zuständigkeit gilt auch für Gateways und Ereignisse.** Ohne `Rolle:`-Präfix landen sie in der Lane
|
||
„Nicht zugeordnet“. Ein `?` stört nur vor dem Doppelpunkt: `Sachbearbeitung: Antrag vollständig?` funktioniert.
|
||
(23.09.2026, beim Erstellen der Beispiele)
|
||
|
||
- **Ein Gateway hat in PICTURE nur vier feste Anschlusspunkte (N/O/S/W auf der Rautenkontur), keinen
|
||
variablen Rand wie ein Rechteck.** Eine Kante, die diesen Punkt verlässt bzw. dort ankommt, darf sich
|
||
danach **nicht** direkt zur Ziel-/Quellkoordinate drehen, wenn diese auf der anderen Achse liegt – sonst
|
||
läuft der rechtwinklige Streckenzug quer durchs Innere der Raute zurück, statt außen herumzugehen
|
||
(`orthogonal_points()` in `md_to_bpmn.py`, behoben BPMN-Skill 21.09.2026). Ursache: die feste
|
||
Anschlusspunkt-Zuteilung (`assign_gateway_sides()`, Präferenzreihenfolge S/O/W/N bzw. N/W/O/S) kennt die
|
||
tatsächliche Lage des anderen Endes nicht. Die Kante muss beim Verlassen/Ankommen an einer Raute zuerst
|
||
ein Stück auf der sicheren Stub-Achse bleiben (die einzige garantiert freie Koordinate außerhalb der
|
||
Kontur), bevor sie zur anderen Achse abbiegt – sonst reicht ein einfacher Bounding-Box-Test nicht, um den
|
||
Fehler zu erkennen (ein Punkt auf der Rautenkontur liegt immer innerhalb der Bounding-Box). Prüfen mit
|
||
echter Diamant-Geometrie (Manhattan-Abstand zum Mittelpunkt, skaliert auf die Halbachsen, < 1 heißt innen),
|
||
nicht mit der Bounding-Box – siehe `test_kante_fuehrt_nicht_durchs_innere_eines_gateways` in
|
||
`test_md_to_bpmn.py`.
|
||
|
||
## Text und Sprache
|
||
|
||
- **Deutscher Text ohne Umlaute/ß ist ein eigenständiges Muster, kein Einzelfall.** KI-generierter Text weicht
|
||
gern auf ASCII aus (`gueltig` statt `gültig`, `ueber` statt `über`) – in AG_QGIS über alle Plugins verteilt
|
||
gefunden (Plugin_SN_Basis #42), im BPMN-Skill in Elementnamen und Docstrings. Neuen deutschen Text
|
||
(Beschriftungen im Modell, Kommentare, Docstrings) immer mit echten Umlauten/ß schreiben. Vor dem Commit
|
||
`python scripts/pruefe_umlaute.py` laufen lassen – findet das Muster in `.py`-Dateien (String-Inhalte und
|
||
Kommentare mit Leerzeichen). Die Wortstammliste ist bewusst konservativ; Ersatz fürs Lesen ist sie nicht.
|
||
Arbeitsschritt-`.md` prüft das Skript nicht. (AG_QGIS 09/2026)
|
||
|
||
## Umgebung und Werkzeuge
|
||
|
||
- **Öffentliche Organisation heißt nicht öffentliches Repo.** In Gitea haben Organisation und Repo getrennte
|
||
Sichtbarkeit. `AG_Prozesse` war öffentlich, `Projektwissen` privat: Die Weboberfläche zeigte es angemeldeten
|
||
Personen normal, die API ohne Anmeldung lieferte 404. `scripts/gitea.py` liest bewusst ohne Token und braucht deshalb
|
||
ein öffentliches Repo; es prüft das jetzt vor jeder Abfrage. Prüfen ohne Anmeldung:
|
||
`curl -s -o /dev/null -w "%{http_code}" https://entwicklung.flurneuordnung-sachsen.de/api/v1/repos/AG_Prozesse/Projektwissen`
|
||
muss `200` liefern. (23.09.2026)
|
||
|
||
- **Gitea ordnet Commits über die E-Mail-Adresse zu.** Stimmt `user.email` nicht mit einer im Gitea-Konto
|
||
hinterlegten Adresse überein, erscheinen die Commits ohne Zuordnung zum Benutzer. Es gilt die dienstliche
|
||
Adresse, die im Gitea-Konto hinterlegt ist. Wer den Rechner auch privat nutzt, setzt sie je Repository mit
|
||
`git config --local` statt global. Nachträglich nur durch Umschreiben der Historie korrigierbar. (AG_QGIS 04.09.2026)
|
||
- **`pytest` ist die einzige Abhängigkeit außerhalb der Standardbibliothek.** Die Tests des Konverters brauchen
|
||
es; `md_to_bpmn.py` selbst läuft ohne. (23.09.2026)
|
||
- **`.vscode/` gehört nicht ins Repository.** Einstellungen mit Pfaden eines einzelnen Arbeitsplatzes gehören in
|
||
die Benutzereinstellungen, siehe `docs/leitfaden/04_werkzeuge_einrichten.md`. (AG_QGIS 04.09.2026)
|
||
|
||
## Zusammenarbeit
|
||
|
||
- **Tool-Gedächtnis ist lokal.** Die Claude-Auto-Memory sieht niemand sonst. Geteiltes Wissen nur in diesem Ordner.
|
||
- **Issues sind teils Diskussionen**, nicht Aufträge (Label `Diskussion`). Vor der Umsetzung Konsens im Issue
|
||
abwarten oder im PR als Annahme kennzeichnen.
|
||
- **Quelldokumente enthalten oft Interna.** Word/PDF-Prozessbeschreibungen nur lokal unter `referenz/` ablegen
|
||
(nicht versioniert). Vor dem Committen eines Arbeitsschritt-Entwurfs prüfen, dass keine Namen, Aktenzeichen
|
||
oder Verfahrensdaten darin stehen. (23.09.2026)
|