# Projektanalyse: Aufbau und Zusammenspiel der Komponenten Momentaufnahme vom 02.09.2026 (alle Repos auf ihrem Default-Branch, siehe `00_gesamtueberblick_2026-09-02.md`). Zielgruppe: neue Entwickler und KI-Agenten, die das Gesamtbild brauchen, bevor sie einzelne Dateien öffnen. Die lebenden Referenzen dazu sind `../architektur/modulkarte.md` und `../architektur/schnittstellen.md`. ## 1. Kurzfassung - Das Vorhaben ist eine **Plugin-Familie** für QGIS: `sn_basis` als Plattform (UI-Rahmen, Wrapper, Prüfer, Datenmodule, Druck) und Fachplugins, die sich beim Start in Menü und Toolbar von `sn_basis` einhängen. Produktiv ausgebaut sind `sn_verfahrensgebiet` und `sn_plan41`; `sn_widmung` ist ein Gerüst, drei weitere Repos sind Platzhalter. - Die Architekturidee ist tragfähig: Wrapper-Schicht mit Mock-Modus, einheitliches Prüfmodell, gemeinsame Tabs, klare Registrierung der Fachplugins. Sie ist aber **nur im Code** dokumentiert und an einigen Stellen aufgeweicht (Fachlogik in UI-Dateien, Rückwärtsimport, doppelte Variablennamen, zwei Linklisten). - Die Codequalität entspricht dem Entstehungsprozess: fachlich fundiert, in KI-erzeugten Fragmenten gewachsen, mit sehr großen Dateien (zehn Dateien über 600 Zeilen, Spitze 1 674), verbreiteten `try/except: pass`-Mustern, Debug-`print`, auskommentiertem Code und uneinheitlicher Namensgebung. - Es gibt **umfangreiche Tests im Mock-Modus** (332 Tests), die ohne QGIS in unter einer Sekunde laufen. Sie sind der wichtigste Hebel für KI-gestützte Arbeit, aber derzeit nicht vollständig grün und nicht in CI. - Prozessseitig existiert bereits ein funktionierender Kern: Feature-Branches, Pull Requests auf `unstable`, Issues mit Labels, dreistufiger Release-Prozess mit Gitea Actions. Es fehlen Test-CI, Abhängigkeitsdeklaration, Dokumentation und ein organisationsweiter Versionsstand. ## 2. Bestand | Repository | Paket | Rolle | Reife | Python-Dateien / Tests | |---|---|---|---|---| | `Plugin_SN_Basis` | `sn_basis` | Plattform und Bibliothek | aktiv, unstable | 40 / 13 Testdateien (87 Tests) | | `Plugin_SN_Verfahrensgebiet` | `sn_verfahrensgebiet` | Fachplugin Verfahrensgebiet | aktiv, unstable | 17 / 12 (201 Tests) | | `Plugin_SN_Plan41` | `sn_plan41` | Fachplugin Plan § 41 | aktiv, unstable | 10 / 5 (44 Tests) | | `Plugin_SN_Widmung` | `sn_widmung` | Fachplugin Widmung | Gerüst | 5 / 0 | | `Plugin_SN_FLT`, `_Topografie`, `_Template` | – | Platzhalter | leer | 0 | | `Plugin_Test_Action` | – | Testplugin für Release | Werkzeug | 1 | | `Repository` | – | Plugin-Feeds, Release-Orchestrierung | Werkzeug | – | | `Linkliste` | – | Dienstekatalog CSV → XML/JSON/YAML | Daten | – | | `Defaults` | – | Beispiel-Verfahrensdaten, ein QML | Daten, unreferenziert | – | Beteiligte laut Git-Historie: Daniel Helbig (LK Meißen, Hauptentwickler der Fachlogik), Michael Otto (LK Mittelsachsen, Release-Infrastruktur, Linkliste, seit 08/2026 auch Fachlogik), Erik Sefkow (VLN Sachsen, VLN-API), Issue-Autoren `22munzke` und „Kai“ (Copilot-Nutzer, Issue Basis #36). Entwicklungsschub 03–04/2026 (92 Commits in `Plugin_SN_Basis`), seitdem gleichmäßig 10–11 Commits pro Monat. Der Ordner `Alternativansatz/` (außerhalb dieses Workspace) enthält einen unabhängigen Prototyp „LNO-Fachschale“; seine Bewertung steht in `00_vergleich_alternativansatz_2026-09-02.md`. Kurz: die Idee eines versionierten GeoPackage-Datenvertrags ist wertvoll, der Prototyp selbst ist kein Ersatz für die Plugin-Familie. ## 3. Architektur zur Laufzeit ```mermaid flowchart TB subgraph QGIS["QGIS 3.40 (Qt5) / QGIS 4 (Qt6)"] subgraph BASIS["sn_basis – Plattform"] NAV["ui: Navigation, DockManager, BaseDockWidget, PrintTab, SettingsTab"] MOD["modules: Pruefmanager, pruef_ergebnis, *pruefer, DataGrabber, Datenabruf, LayerLoader, Datenschreiber, print_*"] FUN["functions: qt_/qgiscore_/qgisui_/dialog_/message_/variable_wrapper, verfahrensgebiet_manager"] NAV --> MOD --> FUN end VG["sn_verfahrensgebiet"] --> NAV VG --> MOD VG --> FUN P41["sn_plan41"] --> NAV P41 --> MOD P41 --> FUN WID["sn_widmung (Gerüst)"] --> NAV MOD -. Lazy-Import Listenauswerter .-> P41 FUN --> PROJ[("QGIS-Projekt: Variablen sn_*, Layer")] end VG --> ALKIS["ALKIS-WFS Sachsen"] P41 --> LUIS["LUIS/RAPIS ArcGIS REST, WFS"] P41 --> VLN["VLN-Karten-API v2"] P41 --> GPKG[("Verfahrens-GeoPackage")] ``` ### Schichten in `sn_basis` 1. **functions/ – Wrapper.** Jede Qt-, QGIS- und OS-Abhängigkeit geht durch ein Wrapper-Modul, das bei fehlendem QGIS Mock-Klassen bereitstellt. Das ist die Grundlage dafür, dass Tests und KI-Agenten ohne QGIS arbeiten können, und gleichzeitig die Brücke zwischen Qt5 und Qt6. `qgiscore_wrapper.py` (1 122 Zeilen) und `qt_wrapper.py` (796) enthalten zusätzlich Fachhelfer (`create_buffer_layer`, `polygon_zu_linie`), die dort nicht hingehören. 2. **modules/ – Prüfen, Laden, Schreiben, Drucken.** Einheitliches Ergebnisobjekt `pruef_ergebnis` mit Aktionscode; `Pruefmanager` entscheidet über Dialoge oder Standardantworten. Die Datenpipeline (`DataGrabber` → `Datenabruf` → `LayerLoader` → `Datenschreiber`) ist generisch gedacht, wird aber nur von Plan41 vollständig genutzt. Die Druckmodule (2 800 Zeilen) sind der größte zusammenhängende Block. 3. **ui/ – Rahmen.** Navigation (Menü/Toolbar), DockManager (nur ein Dock sichtbar), BaseDockWidget (Tabs aus Klassenattribut), gemeinsame Tabs Druck und Projekteigenschaften. ### Fachplugins Beide großen Fachplugins folgen demselben Muster: `main.py` (Registrierung, Services), `ui/dockwidget.py` (Tabs), ein großer Arbeits-Tab (`working_tab.py` 873 Zeilen bzw. `tab_a_ui.py` + `tab_a_logic.py` 1 872 Zeilen) und Fachfunktionen in `functions/` bzw. `modules/`. Der Verfahrensgebiet-Tab enthält viel Ablaufsteuerung, die eigentlich in die Fachfunktionen gehört; Plan41 hat Logik und UI bereits getrennt. ## 4. Zusammenspiel im Detail ### 4.1 Start und Registrierung QGIS instanziiert alle Plugins; die Ladereihenfolge ist nicht garantiert. `sn_basis.initGui()` baut die Navigation und ruft anschließend `initGui()` **aller** Plugins mit Präfix `sn_` nach. Ein Fachplugin registriert in `initGui()` eine Action mit Priorität (Verfahrensgebiet 10, Plan41 20, Widmung 30), erzeugt beim Klick sein Dock (`sn_dock_`) und übergibt es an `DockManager.show()`. Sequenzdiagramm und Vertrag: `schnittstellen.md` Abschnitt 1–2. Bewertung: funktioniert, ist aber fragil. Die Abhängigkeit von `sn_basis` ist in keiner `metadata.txt` deklariert; QGIS kann die Fachplugins ohne Basis aktivieren, und sie scheitern dann still. Mehrfaches `initGui()` erzeugt neue Action-Objekte, alte Referenzen bleiben im Fachplugin bis zum nächsten `run()`. ### 4.2 Gemeinsamer Zustand Der Zustand lebt in **QGIS-Projektvariablen** mit Präfix `sn_` (Tabelle in `schnittstellen.md` Abschnitt 3) und in **Layer-Anzeigenamen**. Beides ist stringbasiert und ohne zentrale Definition. Befund: - 20 verschiedene Schlüssel; die zehn Einstellungsfelder sind in `SettingsLogic.VARIABLEN` gelistet, alle anderen verteilt im Code. - Zwei Schreibweisen für denselben Zweck (`verfahrensgebiet_layer` / `verfahrensgebietslayer`) und ein doppeltes Präfix (`sn_sn_abdeckungslayer`). - Layer werden über Namen wie „Verfahrensgebiet“ oder `BROR_LAYER_NAME` gefunden; der `verfahrensgebiet_manager` verfolgt den Verfahrensgebiet-Layer über Projektsignale und schreibt seine ID in die Variable. ### 4.3 Datenflüsse **Verfahrensgebiet aus ALKIS** (Diagramme im Repo unter `docs/`): Projektvariablen (VKZ/Landkreis) → WFS-Suche `BauRaumOderBodenordnungsrecht` → Auswahl → Layer → Gemarkungen (vereinfachter WFS) → Flurstücke je Gemarkung (SF-WFS, BBOX-Batches) → Flächenvergleich → Detailprüfung (Grenzpunkte, Knickpunkte). Viele Dialoge, blockierende Requests im QGIS-Prozess, manuell gepumpte Fortschrittsdialoge. **Verfahrensgebiet aus Shape/ZIP:** Mehrfachauswahl → Entpacken → `FBSchl`-Klassifikation → Vereinigung je Gebietstyp → Abgleich mit BROR → gleicher weiterer Ablauf. **Plan41-Fachdaten:** `assets/Linkliste.xlsx` → `DataGrabber` (Klassifikation) → `Listenauswerter` (Validierung; lebt in `sn_plan41`, wird von `sn_basis` lazy importiert) → `Datenabruf` (WFS/REST/OGR mit Raumfilter) → `LayerLoader` (Filter, Stil) → `Datenschreiber` (GeoPackage, Laden, HTML-Protokoll). **Plan41 ↔ VLN-API:** Login → Verfahren → GeoJSON → Memory-Layer je Geometriefamilie → Bearbeitung → Upload als eine FeatureCollection (ersetzt Serverbestand). **Druck:** PrintTab (in jedem Fachplugin-Dock eingebettet) → `PrintLogic` (Bereich, Maßstab, Atlas) → `PrintLayout` (§ 38/§ 41) bzw. `PrintLayoutBaufreigabe`. ### 4.4 Release und Verteilung Tag `v-u|-t|` im Plugin-Repo → Repo-Workflow sendet Payload an `Repository` (Branch `hidden/workflows`) → zentraler Workflow baut **den Kanal-Branch**, erzeugt `metadata.txt` aus dem Template, packt das ZIP unter dem in Gitea hinterlegten Paketnamen, legt ein Release an und aktualisiert `plugins-.xml`. Der Kanal `stable` ist leer und hat keinen Branch. Details und Fallstricke: `schnittstellen.md` Abschnitt 9, `fallstricke.md`. ### 4.5 Nebenrepositories `Linkliste` erzeugt automatisch drei Formate aus einer CSV, wird aber von keinem Plugin gelesen. `Defaults` wird nirgends referenziert. Beide sind Kandidaten für die Konsolidierung (eine Dienstquelle, generierte Laufzeitdatei). ## 5. Qualitätsbefund ### 5.1 Struktur und Stil | Beobachtung | Beispiele | Auswirkung für KI-gestützte Arbeit | |---|---|---| | Sehr große Dateien | zehn Dateien > 600 Zeilen (Modulkarte) | teure Kontexte, ungenaue Änderungen; Agenten müssen per `grep` navigieren | | Fachlogik in UI-Klassen | `working_tab.py`, `print_tab.py` | schwer testbar, Änderungen streuen | | Wrapper enthält Fachhelfer | `qgiscore_wrapper.create_buffer_layer`, `polygon_zu_linie` | Schichtgrenze verwischt | | Rückwärtsabhängigkeit | `sn_basis.DataGrabber` → `sn_plan41.Listenauswerter` | Basis ist nicht eigenständig; seit PR #57 nur noch lazy | | Stringbasierter Zustand | Projektvariablen, Layernamen | Tippfehler brechen Abläufe still; siehe Doppelnamen | | Breite `try/except Exception: pass` | `base_dockwidget`, `dockmanager`, viele Fachfunktionen | Fehler werden verschluckt, Ursachensuche teuer | | Debug-Reste | `print()` in `navigation.py`, `main.py`, `tab_a_logic.py`; `TEST ACTION` im Menü | Nutzer sehen Entwicklungsballast | | Auskommentierter Code | `Verfahrensgebiet.run()` doppelt (alt/neu) | Unsicherheit, welche Fassung gilt | | Uneinheitliche Namen | `schreibe_Daten`, `lade_Layer` neben `create_layer`; deutsche/englische Mischung | Stil je Datei beibehalten (Regel), Vereinheitlichung im Refactoring | | Fehlende Typen/Docstrings in Teilen | Widmung, ältere Funktionen | Agenten raten Signaturen | | Personenbezogene IDE-Pfade | `.vscode/settings.json` | irritiert neue Entwickler | Das Muster ist typisch für **schrittweise per Chatbot erzeugten Code**: jedes Fragment ist für sich plausibel und gut kommentiert, die Gesamtstruktur wurde aber nie gegen ein Zielbild geprüft. Positiv hervorzuheben: die Wrapper-Idee, das Prüfmodell, der Mock-Modus und die konsequente deutsche Dokumentation in Docstrings und Changelogs. ### 5.2 Tests Ausführung im Mock-Modus mit Python 3.14 am 02.09.2026 (`python scripts/run_tests.py`): | Paket | Gesamt | Grün | Fehlschläge | Fehler | Übersprungen | |---|---:|---:|---:|---:|---:| | `sn_basis` | 87 | 87 | 0 | 0 | 0 | | `sn_plan41` | 44 | 43 | 0 | 1 | 0 | | `sn_verfahrensgebiet` | 201 | 157 | 15 | 21 | 8 | Die roten Verfahrensgebiet-Tests betreffen überwiegend `verfahrensgebiet_shape_komplett`, `flurstueck_alkis`, `grenzpunkt_alkis`, `gemarkung_alkis` und `working_tab`: Tests erwarten die Einzeldatei-/Einzellayer-Schnittstellen vor dem Umbau auf Mehrfachauswahl. Es handelt sich also überwiegend um **veraltete Tests, nicht um Regressionen**; das muss aber je Test entschieden werden. Es gibt keine CI, die Tests bei Push/PR ausführt; die vorhandenen Actions dienen nur Releases. ### 5.3 Dokumentation Fünf README-Dateien sind leer oder zweizeilig. Wertvoll sind die Mermaid-Abläufe in `Plugin_SN_Verfahrensgebiet/docs/`, das ERD in `Plugin_SN_Plan41/doc/`, die Changelogs und die Docstrings. Es gibt keine Beschreibung der Gesamtarchitektur, der Verträge, der Entwicklungsumgebung oder des Arbeitsablaufs – genau das, was Agenten und neue Entwickler brauchen. ### 5.4 Prozess - Branch-Modell `feature/*` → PR → `unstable` → PR → `testing` wird gelebt (57 PRs in Basis). - Issues mit `Bug`/`Feature`/`Diskussion`; ein Teil sind Diskussionen ohne Auftragscharakter. - Kein Manifest für kompatible Versionsstände; `sn_basis` und Fachplugins werden unabhängig getaggt. - Keine Abhängigkeitsdeklaration (`openpyxl`, Basisplugin). - Individuelle Werkzeuge: VS Code + Copilot (mit lokalem `/memories`), diverse Chatbots; künftig Claude Code und Codex. ## 6. Risiken mit Blick auf die nächste Phase 1. **Rote Tests werden zur Gewohnheit.** Ohne Baseline und CI verlieren Tests ihre Aussagekraft, und Agenten „reparieren“ Tests statt Code. → Baseline festhalten, neue rote Tests verbieten, Rot→Grün als eigene Aufgaben. 2. **Kontextexplosion.** Zehn Dateien über 600 Zeilen und keine Modulkarte führen dazu, dass jeder Agent das Projekt neu erkundet. → Modulkarte, Schnittstellen, Fallstricke als Pflichtlektüre; Regeln zum gezielten Lesen. 3. **Wissensinseln.** Erkenntnisse liegen in Copilot-Memories, Chat-Verläufen und Köpfen. → Versionierte Wissensbasis. 4. **Unbeabsichtigte API-Brüche in `sn_basis`.** Jede Änderung trifft drei Fachplugins in drei Repos. → Regel „grep vor Änderung“, später Manifest kompatibler Stände. 5. **Release-Fehler.** Kanal-Branch statt Tag, Template-Fehler, Workspace-Dateien im ZIP. → Skill `sn-release`, Excludes. 6. **Refactoring zu früh.** Ein Umbau bei roten Tests und ohne dokumentierte Verträge zerstört Wissen. → Reihenfolge: Vorbereitung → grüne Basis → Verträge festschreiben → Refactoring in Scheiben. ## 7. Konsequenzen für die Vorbereitung Aus der Analyse folgen die Bausteine des Konzepts (`../konzept/02_zusammenarbeit_ki_agenten.md`): ein Workspace-Meta-Repository mit kanonischer `AGENTS.md`, Modulkarte und Schnittstellen als Pflichtkontext, eine versionierte Wissensbasis als geteiltes Gedächtnis, Skills für wiederkehrende Abläufe, ein werkzeugunabhängiger Testlauf mit Baseline und ein leichter, aber verbindlicher Arbeitszyklus über Gitea-Issues und Pull Requests.