| = ÄndGgner -- Nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen anhand von Änderungsvorschriften des Bundes und der Länder |
| Matthias Andreas Benkard |
| // Meta |
| :experimental: |
| :data-uri: |
| :sectnums!: |
| :toc: |
| :stem: |
| :toclevels: 2 |
| :description: Handbuch der Nichtamtlichen Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen: Werkzeug, das Änderungsgesetze und Gesetzentwürfe selbsttätig auf ein Stammgesetz anwendet und das Ergebnis als Synopse ausgibt |
| :keywords: mulk |
| // Settings |
| :icons: font |
| :source-highlighter: pygments |
| |
| |
| [.lead] |
| Ein Änderungsgesetz sagt nicht, was künftig gilt. Es sagt nur, was zu tun ist: |
| „In § 4 Absatz 2 Satz 1 werden die Wörter „X“ durch die Wörter „Y“ ersetzt.“ |
| Wer wissen will, wie die Vorschrift danach lautet, muss Hunderte solcher Befehle |
| von Hand nachvollziehen — und wer wissen will, was ein Entwurf bewirken _würde_, |
| findet in keinem amtlichen Angebot eine Antwort, denn konsolidiert wird erst nach |
| der Verkündung. |
| |
| ÄndGgner nimmt diese Arbeit ab. Eingegeben werden ein Stammgesetz in geltender |
| Fassung und ein oder mehrere Änderungsdokumente — verkündete Änderungsgesetze aus |
| dem Bundesgesetzblatt und den Gesetz- und Verordnungsblättern der Länder ebenso |
| wie Referenten-, Regierungs- und Fraktionsentwürfe, Änderungsanträge und |
| Beschlussempfehlungen. Ausgegeben wird eine zweispaltige Synopse: links die |
| bisherige, rechts die künftige Fassung, die Unterschiede wortweise hervorgehoben. |
| |
| [source,shell script] |
| ---- |
| ./mvnw package |
| java -jar target/aendggner-0.1.0-SNAPSHOT.jar stammgesetz.xml aenderungsgesetz.pdf -o synopse.html |
| ---- |
| |
| Ohne Einrichtung läuft dasselbe im Browser unter |
| https://matthias.benkard.de/aendggner/; die dort angebotenen zwei |
| durchgerechneten Beispiele sind der kürzeste Weg zum ersten Ergebnis |
| (§ 14). |
| |
| |
| [[gegenstand]] |
| == § 1 Gegenstand und Zweck |
| |
| (1) Dieses Handbuch regelt Herstellung, Betrieb und Anwendung des |
| Softwareerzeugnisses „ÄndGgner“ (nachstehend: das Erzeugnis). |
| |
| (2) Das Erzeugnis dient der maschinellen Fortschreibung von Stammgesetzen anhand |
| von Änderungsvorschriften des Bundes und der Länder. Es erschließt aus einem |
| Änderungsdokument die darin enthaltenen Änderungsbefehle, wendet sie auf die |
| geltende Fassung des Stammgesetzes an und stellt beide Fassungen einander |
| gegenüber. |
| |
| (3) Das Erzeugnis ist nichtamtlich. Seine Ausgabe ist weder eine amtliche |
| Bekanntmachung noch eine Rechtsauskunft; maßgeblich bleibt allein der Wortlaut |
| des Gesetz- und Verordnungsblattes. Bei Entwürfen, Anträgen und |
| Beschlussempfehlungen zeigt die Synopse überdies nur, was gälte, wenn die Vorlage |
| so beschlossen würde; sie trägt hierauf den Hinweis *Entwurfsfassung — nicht |
| geltendes Recht*. |
| |
| (4) Es gilt der Grundsatz der Nichtverwerfung: Ein Befehl, der sich nicht |
| zweifelsfrei anwenden lässt — etwa weil er gegen eine ältere Gesetzesfassung |
| gerichtet ist, deren Zieltext nicht mehr besteht —, wird mitsamt der Begründung |
| seines Scheiterns in den Abschnitt *Manuell prüfen* der Synopse aufgenommen. Er |
| wird niemals stillschweigend übergangen. |
| |
| |
| [[begriffe]] |
| == § 2 Begriffsbestimmungen |
| |
| Im Sinne dieses Handbuchs ist |
| |
| Stammgesetz:: |
| das zu ändernde Gesetz in seiner geltenden (konsolidierten) Fassung, also |
| dasjenige Werk, dessen Fortschreibung begehrt wird. Bundesrecht wird als |
| gii-Norm-XML von https://www.gesetze-im-internet.de/[gesetze-im-internet.de] |
| angenommen, Landesrecht als konsolidierte Fassung aus dem jeweiligen |
| Landesportal (§ 5). |
| Änderungsdokument:: |
| das Werk, das die Änderung anordnet. Hierzu zählen das verkündete |
| Änderungsgesetz, der Gesetzentwurf, der Änderungsantrag und die |
| Beschlussempfehlung (§ 10). |
| Änderungsbefehl:: |
| die einzelne Anordnung innerhalb des Änderungsdokuments, gerichtet auf eine |
| bestimmte Stelle des Stammgesetzes („In § 4 Absatz 2 Satz 1 werden die Wörter |
| „X“ durch die Wörter „Y“ ersetzt“). Welche Befehlsformen erkannt werden, |
| bestimmt § 7. |
| Norm:: |
| die kleinste selbständig bezeichnete Einheit des Stammgesetzes, im Bundesrecht |
| und im Landesrecht der übrigen Länder der Paragraph, im bayerischen Landesrecht |
| der Artikel (§ 13). Auch die Inhaltsübersicht und die Gesetzesüberschrift |
| werden als Normen geführt, weil Änderungsbefehle auf sie zielen. |
| Synopse:: |
| die Ausgabe des Erzeugnisses: eine zweispaltige Gegenüberstellung der bisherigen |
| und der künftigen Fassung im Format HTML, gefolgt vom Protokoll der Anwendung |
| und dem Abschnitt *Manuell prüfen* nach § 1 Absatz 4. |
| Angewandt:: |
| gilt ein Befehl erst, wenn er im Wortlaut des Stammgesetzes gegriffen hat. Bei |
| Verbünden mehrerer Teile (§ 8 Absatz 3) gilt der Befehl nur dann als angewandt, |
| wenn jeder seiner Teile gegriffen hat. |
| |
| |
| [[bezugsquellen]] |
| == § 3 Bezugsquellen und Anschriften |
| |
| (1) Die Browserfassung wird betrieben unter |
| https://matthias.benkard.de/aendggner/. |
| |
| (2) Fortlaufende Quelltextquelle ist |
| https://gerrit.benkard.de/plugins/gitiles/aendggner. Die jeweils betriebene |
| Fassung liegt der Browserfassung überdies als `aendggner-quelltext.tar.gz` bei |
| (§ 15 Absatz 5). |
| |
| (3) Das Erzeugnis steht unter der GNU Affero General Public License, Fassung 3; |
| der Lizenztext ist der Datei `COPYING` zu entnehmen. |
| |
| (4) Der Stand des Quelltextes wird nach Kalendertagen im Verzeichnis der |
| Fassungen (`FASSUNGEN.txt`) geführt. |
| |
| |
| [[herstellung]] |
| == § 4 Herstellung des Erzeugnisses |
| |
| (1) Die ausführbare Archivdatei wird durch den nachstehenden Befehl unter |
| `target/aendggner-${REVISION}.jar` erzeugt: |
| |
| [source,shell script] |
| ---- |
| ./mvnw package |
| ---- |
| |
| (2) Die Fassungsbezeichnung `${REVISION}` nach Absatz 1 lautet |
| `0.1.0-SNAPSHOT`, soweit sie nicht durch Übergabe des Schalters `-Drevision` an |
| `mvnw` abweichend bestimmt wird. |
| |
| (3) Vorausgesetzt wird ein Java-Entwicklungsbausatz der Fassung 21 oder neuer. |
| Für die Herstellung der Browserfassung gilt abweichend § 14 Absatz 3. |
| |
| |
| [[eingaben]] |
| == § 5 Zulässige Eingaben |
| |
| (1) Als Stammgesetz des Bundes wird XML im gii-norm-Format von |
| https://www.gesetze-im-internet.de/[gesetze-im-internet.de] angenommen. Das |
| Portal gibt seine Werke nur als Archiv aus (`…/<kurz>/xml.zip`); das Archiv wird |
| unmittelbar angenommen und der enthaltene XML-Eintrag daraus entpackt, ein |
| Zwischenschritt von Hand entfällt. |
| |
| (2) Als Stammgesetz eines Landes wird die konsolidierte Fassung als PDF oder als |
| kanonischer Klartext im Format der `--extract-only`-Ausgabe (§ 6 Absatz 2) |
| angenommen. Hierbei gilt: |
| |
| 1. Eine Zeile „Inhaltsübersicht“ eröffnet die gleichnamige Norm, auf die die |
| Angabe-Befehle zielen; ihre Zeilen tragen das Übersichtsformat |
| „§ N | Titel“. |
| 2. Amtliche Satznummern und Fußnotenmarker stehen als Unicode-Superskripte im |
| Text („¹Die freilebende Tierwelt …“, „Enteignung⁶)“). Ob sie erhalten bleiben, |
| ergibt sich aus der geladenen Stammfassung, nicht aus einer Länderkennung. |
| 3. Das Zitiersigel (§ oder Art.) folgt gleichfalls aus den Normköpfen der |
| Stammfassung. |
| |
| (3) Als Änderungsdokument werden PDF-Dateien des Bundesgesetzblattes, der |
| Gesetz- und Verordnungsblätter der Länder und der Drucksachen von Bundestag, |
| Bundesrat und Landtagen sowie Klartext angenommen. Die Dokumentart wird aus dem |
| Text erschlossen, nicht aus dem Dateinamen (§ 10). Änderungsanträge dürfen |
| zusammen mit demjenigen Entwurf angegeben werden, den sie ändern (§ 11). |
| |
| |
| [[betrieb]] |
| == § 6 Betrieb der Befehlszeilenfassung |
| |
| (1) Nach der Herstellung nach § 4 wird das Erzeugnis wie folgt aufgerufen: |
| |
| [source,shell script] |
| ---- |
| java -jar target/aendggner-0.1.0-SNAPSHOT.jar \ |
| stammgesetz.xml aenderungsgesetz.pdf -o synopse.html |
| ---- |
| |
| (2) Von den Schaltern sind die folgenden von allgemeiner Bedeutung: |
| |
| `-o, --output <file>`:: |
| Ausgabedatei (Vorgabe `synopse.html`; „`-`“ bezeichnet die Standardausgabe). |
| `--vollstaendig`:: |
| Auch unveränderte Normen in die Synopse aufnehmen. |
| `--artikel <n>`:: |
| Nur den bezeichneten Artikel des Änderungsgesetzes anwenden. Ohne diese Angabe |
| werden alle Artikel angewandt, deren Einleitung das Stammgesetz nennt. |
| `--extract-only`:: |
| Nur den bereinigten Lineartext des Änderungsdokuments ausgeben. Dies ist |
| angezeigt, wenn die PDF-Aufbereitung (§ 9) fehlerhaft bleibt: Der Text ist zu |
| prüfen, von Hand zu berichtigen und als Klartextdatei wieder einzuspeisen. |
| |
| (3) Ein Aufruf unmittelbar aus dem Arbeitsbaum, ohne vorherige Herstellung nach |
| § 4, ist zulässig: |
| |
| [source,shell script] |
| ---- |
| ./mvnw exec:java |
| ---- |
| |
| (4) Die vollständige Schalterliste einschließlich der Schalter für die |
| Fehlersuche gibt `--help` aus. |
| |
| |
| [[befehle]] |
| == § 7 Erkannte Änderungsbefehle |
| |
| (1) Erkannt werden die gebräuchlichsten Änderungsbefehle des Handbuchs der |
| Rechtsförmlichkeit, nämlich Ersetzen, Neufassung, Einfügen, Anfügen, Aufheben, |
| Streichen und Umnummerierung. |
| |
| (2) Von den Sonderformen sind erkannt: |
| |
| 1. Bereichs- und Koordinationsziele („Die Absätze 8 und 9 werden durch die |
| folgenden Absätze 8 bis 10 ersetzt“); |
| 2. strukturelle Streichungen ganzer Einheiten („§ 9 wird gestrichen“); |
| 3. §- und Gliederungs-Umnummerierungen („§ 9a wird zu § 9“, „Der bisherige |
| Abschnitt 2 wird zu Abschnitt 3“); |
| 4. das Einfügen und Ersetzen ganzer §-Blöcke; |
| 5. Chapeau-Lokatoren („Im Satzteil vor Nummer 1 …“); |
| 6. Änderungen an Anhängen und Anlagen („Der Anhang wird wie folgt geändert: … |
| Nach Nummer 2 wird die folgende Nummer 2a eingefügt“); |
| 7. Angabe-Befehle auf die Inhaltsübersicht (gefasst, ersetzt, eingefügt, |
| gestrichen); sie werden auf die Inhaltsübersichts-Norm angewandt; |
| 8. das Einfügen und Ersetzen von Gliederungs-Überschriften („Nach § 33 werden |
| die folgenden Überschriften zu Teil 3 … eingefügt“); |
| 9. Voranstellungen; |
| 10. Mehrfach-Ersetzungs- und -Einfügepaare; |
| 11. Einfügungen, deren Position ein Wortanker statt einer Stellenangabe bestimmt |
| („Vor den Wörtern „Aus dem Bereich Verkehr:“ wird folgender Absatz 5 |
| eingefügt“); |
| 12. Verbünde aus Umnummerierung und Folgeänderung („§ 50 wird zu § 38 und wird |
| wie folgt geändert“, „Die bisherige Nr. 7 wird Nr. 5 und das Komma wird durch |
| das Wort „und“ ersetzt“). Eine Satzzeichen-Operation meint dabei stets die |
| soeben umnummerierte Einheit, weil ihr Zieltext nichts unterscheidet; |
| 13. Verb-Rahmen, deren Unterpunkte allein die Fundstelle tragen („Es werden |
| ersetzt: … in § 35 Absatz 3 die Angabe „X“ jeweils durch die Angabe „Y“,“), |
| sowie |
| 14. die Neufassung der Gesetzesüberschrift. |
| |
| (3) Landesrechtliche Befehlsformen bestimmt ergänzend § 13. |
| |
| |
| [[reihenfolge]] |
| == § 8 Reihenfolge der Anwendung |
| |
| (1) Angewandt wird nicht stur in Dokumentreihenfolge. Umnummerierungen beziehen |
| sich stets auf die ursprüngliche Zählung, nicht auf den Stand nach den |
| vorangegangenen Punkten; wer eine Bezeichnung räumt, kommt deshalb vor den, der |
| sie neu besetzt. |
| |
| (2) Aus Absatz 1 folgt |
| |
| 1. die absteigende Abarbeitung einer aufsteigenden Kaskade („Der bisherige |
| Absatz 3 wird Absatz 4“, „Der bisherige Absatz 4 wird Absatz 5“, …) sowie |
| 2. der Vorrang einer Umnummerierung vor derjenigen Einfügung, die deren |
| Bezeichnung neu vergibt. |
| |
| Wer vorrückt, nimmt dabei seine eigenen Räumer mit: Auch eine über mehrere Punkte |
| verschränkte Kaskade („Die bisherige Nr. 15 wird Nr. 16“, „Die bisherigen Nrn. 13 |
| und 14 werden die Nrn. 14 und 15“, „Nach Nr. 12 wird folgende Nr. 13 eingefügt“) |
| tritt geschlossen vor die Einfügung, nicht bloß mit ihrem letzten Glied. |
| |
| (3) Geordnet werden nicht die Befehle, sondern die einzelnen Anwendungsschritte. |
| Ein Verbund aus Umnummerierung und Folgeänderung (§ 7 Absatz 2 Nummer 12) trägt |
| nämlich zwei gegenläufige zeitliche Ansprüche: Die Umnummerierung gehört nach |
| vorn, die Folgeänderung dagegen an ihre Dokumentstelle, weil sie die |
| vorangegangenen Punkte als vollzogen voraussetzt — „Die bisherige Nr. 11 wird |
| Nr. 12 und die Angabe „schriftliche“ wird gestrichen“ ist vorgezogen mehrdeutig, |
| weil erst ein früherer Punkt die zweite Fundstelle des Wortes beseitigt. |
| Verschoben wird stets nur nach vorn. |
| |
| (4) Das Protokoll bleibt gleichwohl befehlsweise: Ein Verbund gilt nur dann als |
| angewandt, wenn jeder seiner Teile gegriffen hat; sonst nennt die Meldung den |
| Teil und den Grund. |
| |
| |
| [[aufbereitung]] |
| == § 9 Aufbereitung der Druckwerke |
| |
| (1) Die PDF-Aufbereitung toleriert die üblichen Drucksachen-Artefakte, nämlich |
| Seitenköpfe und -füße, Vorabfassungs-Wasserzeichen, vertauschte oder gerade |
| Anführungszeichen, verklebte Wortgrenzen und zerlegt kodierte Umlaute. Die |
| Brotschrift wird seitenweise bestimmt, sodass auch Ministeriumsentwürfe mit |
| gemischten Layouts vollständig ausgelesen werden. |
| |
| (2) Fehlt im amtlichen Satz ein schließendes Anführungszeichen, so endet das |
| Zitat an der nächsten Strukturgrenze, nämlich an einer Artikel-Überschrift oder — |
| dort, wo die Anführungszeichen eines Artikels nachweislich nicht aufgehen — am |
| nächsten Aufzählungspunkt des Änderungsdokuments. Der Vorgang wird als Warnung |
| gemeldet. |
| |
| (3) Auf den Beispieldaten (§ 17 Absatz 2) werden hiernach alle Befehle der |
| Fassungen des Bundesgesetzblattes und der aktuellen Entwürfe angewandt; für |
| UWG, AGG und ProdHaftG verbleibt kein Befehl zur Prüfung von Hand. Im Übrigen |
| gilt § 1 Absatz 4. |
| |
| (4) Bleibt die Aufbereitung im Einzelfall fehlerhaft, so ist nach § 6 Absatz 2 |
| mittels des Schalters `--extract-only` zu verfahren. |
| |
| |
| [[quellformate]] |
| == § 10 Quellformate: Gesetz, Entwurf, Antrag |
| |
| Ein Änderungsbefehl steht nicht nur im verkündeten Gesetzblatt. Dasselbe Vorhaben |
| durchläuft als Referenten-, Regierungs- und Fraktionsentwurf, als Änderungsantrag |
| und als Beschlussempfehlung mehrere Fassungen, und die Frage „was gälte, wenn das |
| durchkommt?“ stellt sich in jeder davon. Das Erzeugnis erschließt die Art eines |
| Dokuments deshalb aus seinem Kopf — nie aus dem Dateinamen, der lügen kann (im |
| Beispielkorpus heißt ein Entschließungsantrag |
| `BT-Drs-21-7071_Beschlussempfehlung.pdf`), und nie aus einer Kennung, die von |
| außen mitzugeben wäre. |
| |
| Unterschieden werden: |
| |
| Änderungsgesetz:: |
| Das verkündete Artikelgesetz aus BGBl, GVBl oder GVOBl. Der Regelfall. |
| Gesetzentwurf:: |
| Referenten-, Regierungs- und Fraktionsentwürfe, auch als Drucksache von |
| Bundestag, Bundesrat oder Landtag. Der Begründungsteil hinter dem |
| Regelungstext erzeugt keine Befehle; erkannt wird er an „Begründung“ ebenso wie |
| an den Entwurfsvarianten („A. Allgemeiner Teil“, „Zu Artikel 1“). |
| Änderungsantrag:: |
| Ändert nicht das Stammgesetz, sondern eine *Drucksache*; das Nähere bestimmt |
| § 11. |
| Beschlussempfehlung:: |
| Trägt ihre Fassung in einer zweispaltigen Zusammenstellung, die aufgelöst wird; |
| die Synopse zeigt alsdann die vom Ausschuss beschlossene Fassung. Das Nähere |
| bestimmt § 12. |
| Dokument ohne Änderungsbefehle:: |
| Entschließungs- und schlichter Antrag, Plenarprotokoll, Bericht. Sie werden |
| übergangen und gemeldet — nicht stillschweigend zu null Befehlen verarbeitet. |
| |
| Sobald ein Entwurf, ein Antrag oder eine Beschlussempfehlung beteiligt ist, trägt |
| die Synopse den Hinweis *Entwurfsfassung — nicht geltendes Recht* (§ 1 Absatz 3); |
| die Quellenzeile nennt je Datei die erkannte Art. |
| |
| |
| [[antraege]] |
| == § 11 Änderungsanträge |
| |
| (1) Ein Änderungsantrag ist eine Meta-Änderung: Er ändert den Entwurf, nicht das |
| Gesetz. Sein Rahmensatz adressiert deshalb zwei Ebenen zugleich — „In § 3 Nr. 22 |
| wird § 18 Nr. 1 wie folgt geändert:“ nennt erst die Stelle _in der Drucksache_ |
| (den 22. Änderungsbefehl ihres dritten Paragraphen) und dann die Stelle _in dem |
| Text, den dieser Befehl zitiert_. |
| |
| (2) Der Antrag ist zusammen mit seinem Entwurf anzugeben: |
| |
| [source,shell script] |
| ---- |
| java -jar target/aendggner-0.1.0-SNAPSHOT.jar \ |
| BayJG-alt.txt Ltg-Drs-19-9707_Gesetzentwurf.pdf \ |
| Ltg-Drs-19-10365_Aenderungsantrag-Gruene.pdf -o synopse.html |
| ---- |
| |
| (3) Angewandt wird alsdann erst der Antrag auf den Entwurf und danach der so |
| geänderte Entwurf auf das Stammgesetz; die Synopse zeigt also, was gälte, wenn |
| Entwurf _und_ Antrag durchkämen. Welcher Entwurf gemeint ist, entscheidet die |
| Drucksachennummer, die der Antrag selbst nennt („(Drs. 19/9707)“), nicht die |
| Reihenfolge der Argumente. |
| |
| (4) Fehlt der Entwurf, so bleibt der Antrag unangewandt und wird gemeldet. Ihn |
| ersatzweise auf das Stammgesetz loszulassen wäre falsch, denn seine |
| Stellenangaben zielen auf die Drucksache. |
| |
| (5) Erkannt wird auch die elliptische Antragsform, die das Hilfsverb nur einmal |
| in der Beschlussformel führt („1. In Nr. 1.29 die Angabe „,“ am Ende durch die |
| Angabe „;“ ersetzt.“). |
| |
| |
| [[zusammenstellung]] |
| == § 12 Beschlussempfehlungen; die beschlossene Fassung |
| |
| (1) Die maßgebliche Fassung einer Beschlussempfehlung steht in einer |
| zweispaltigen Zusammenstellung: links der Entwurf, rechts die Beschlüsse des |
| Ausschusses. Anders als beim alten BGBl und beim Berliner GVBl stehen die Spalten |
| *nicht* nacheinander im Inhaltsstrom, sondern zeilenweise verschränkt; getrennt |
| werden sie deshalb über die Koordinaten (`PatchTextExtraktor.extrahiereSpalten`, |
| Schnitt an der Blattmitte, aber nur an einem tatsächlichen Spaltensteg, damit |
| ganzseitenbreite Zeilen ungeschnitten bleiben). |
| |
| (2) Die rechte Spalte für sich gelesen ist kein vollständiges Dokument: Sie druckt |
| Unverändertes nicht ab, sondern vermerkt bloß „unverändert“ — und zwar nicht nur |
| je Gliederungspunkt, sondern auch zeilenweise innerhalb zitierter Blöcke, weshalb |
| ihre Anführungszeichen nicht aufgehen. Eine Auflösung über die Gliederungspfade |
| scheitert daran nachweislich. |
| |
| (3) Maßgeblich ist stattdessen die *Grundlinie*: Beide Spalten sind zeilensynchron |
| gesetzt, jeder Vermerk steht auf der Höhe der Entwurfszeile, die er meint. Der |
| `ZusammenstellungsLeser` führt beide Spalten über Seite und Grundlinie in eine |
| gemeinsame Lesereihenfolge zusammen und entscheidet dann Zeile für Zeile: |
| „unverändert“ holt den Wortlaut aus der Entwurfsspalte, „entfällt“ streicht ihn, |
| sonst gilt die Ausschussspalte. Dabei meint „unverändert“ den Wortlaut, nicht die |
| Zählung; streicht der Ausschuss einen Punkt, so rücken die folgenden auf, und |
| seine Marke tritt an die Stelle derjenigen des Entwurfs. |
| |
| (4) Die Quellenzeile der Synopse weist die verwendete Spalte als |
| `[Beschlussempfehlung …, Ausschussfassung]` aus. |
| |
| (5) Lässt sich die Zusammenstellung nicht auflösen, so wird die Datei mit |
| Begründung übergangen, samt Hinweis auf die Drucksachennummer des Entwurfs, der |
| sich stattdessen eignet. Eine halb aufgelöste Fassung auszugeben wäre schlimmer |
| als keine. |
| |
| (6) Belegt ist beides: dass die *linke* Spalte Befehl für Befehl den |
| Regierungsentwurf ergibt, aus dem die Zusammenstellung gebaut ist, und dass die |
| aufgelöste Fassung mehr Befehle trägt als er — der Ausschuss hat der GEG-Novelle |
| zwei Artikel hinzugefügt. Zwei Beispiele stehen im Test: BT-Drs. 20/7619 (GEG) |
| und BT-Drs. 19/24334 (Drittes Bevölkerungsschutzgesetz). |
| |
| |
| [[landesrecht]] |
| == § 13 Landesrecht |
| |
| (1) Für das bayerische Landesrecht versteht das Erzeugnis die dortigen |
| Konventionen. Stammgesetze gliedern sich in Artikel („Art. 6 Abs. 2 Satz 1 |
| Nr. 2“, durchgängig abgekürzt zitiert), Änderungsgesetze dagegen in Paragraphen — |
| auch mehrere Gesetze in einem GVBl-Heft, aus denen die auf das Stammgesetz |
| zielenden §§ (einschließlich „Weitere Änderung“) anhand des Einleitungssatzes |
| ausgewählt werden. Amtliche Satznummern bleiben als Superskripte erhalten und |
| dienen als exakte Satzgrenzen. Zusätzlich erkannt werden |
| |
| 1. die bayerischen Befehlsformen („Fußnote 1 wird aufgehoben“, „In Satz 1 wird |
| die Satznummerierung „1“ gestrichen“, „Dem Wortlaut werden die folgenden |
| Abs. 1 bis 4 vorangestellt“, „Der bisherige Wortlaut wird Abs. 5“), |
| Halbsatz-Ziele und Klauselketten mit gemeinsamem Schlussverb sowie |
| 2. das Fortführungszeichen des GVBl, wonach jedes neugefasste Aufzählungsglied |
| erneut mit „ öffnet. |
| |
| Der Fall ist gegen die amtliche Nachfassung belegt: Alle 154 auf das BayJG |
| zielenden Befehle des Heftes 6/2026 werden an 54 Normen selbsttätig angewandt, |
| auch die verschränkte Neunummerierung des Bußgeldkatalogs in Art. 56. |
| |
| (2) Die übrigen Länder gliedern ihre Stammgesetze wie der Bund in Paragraphen; |
| die Unterschiede liegen im Gesetzblatt-Satz und in den Befehlsidiomen. Belegt sind |
| Sachsen (SächsBeamtVG), Niedersachsen (NEFG), Thüringen (ThürKigaFinVO) und |
| Nordrhein-Westfalen — dort alle vier ändernden Artikel eines Heftes: |
| Telemedienzuständigkeitsgesetz, Landesmediengesetz, Ausführungsgesetz zum |
| 17. Rundfunkänderungsstaatsvertrag und, mit 101 Befehlen an 31 Normen der größte |
| Fall des Heftes, das WDR-Gesetz —, jeweils mit Akzeptanztests gegen die amtlichen |
| Nachfassungen. |
| |
| (3) Für Schleswig-Holstein, Berlin und Hessen reicht die Prüfung bis zur |
| Befehlserkennung — dort vollständig, aber ohne Anwendung —, weil deren |
| Landesportale ihre Stammfassungen nur über eine anmeldepflichtige Schnittstelle |
| ausgeben. Thüringens Portal gibt sie ebensowenig aus; dort ist die konsolidierte |
| Fassung aus dem Stammheft und den drei Änderungsheften des Gesetzblattes |
| zusammengesetzt, die die Parlamentsdatenbank des Landtags frei ausgibt. |
| |
| (4) Welche Konvention welches Land beisteuert, welche Stammfassungen woher |
| stammen und was noch offen ist, verzeichnet |
| `src/test/resources/sampledata/Landesrecht-Beispiele.adoc`. |
| |
| |
| [[web]] |
| == § 14 Browserfassung |
| |
| (1) Neben der Befehlszeilenfassung besteht eine Browserfassung, die dieselbe |
| Pipeline (`eu.mulk.aendggner.Pipeline`, § 16 Absatz 1) über ein |
| Upload-Formular zugänglich macht: Stammgesetz- und Änderungsgesetz-Datei(en) |
| wählen, Synopse erhalten. |
| |
| (2) Über dem Formular steht ein zugeklappter Einführungsblock, der zwei |
| durchgerechnete Fälle mit Verweisen auf die amtlichen Fundstellen anbietet, |
| nämlich das UWG (`gesetze-im-internet.de/uwg_2004/xml.zip`) mit dem Dritten Gesetz |
| zu seiner Änderung (BGBl. 2026 I Nr. 43) und das AGG |
| (`gesetze-im-internet.de/agg/xml.zip`) mit dem Regierungsentwurf BT-Drs. 21/6178. |
| Mitausgeliefert wird nichts; die Seite ruft die Dateien auch nicht selbst ab, sie |
| verweist nur darauf. |
| |
| (3) Ein Server ist nicht erforderlich: Die vollständige Verarbeitung — |
| PDF-Textgewinnung mit PDFBox eingeschlossen — läuft als WebAssembly-Modul im |
| Browser, übersetzt mit GraalVM Web Image aus demselben Java-Quelltext. |
| Ausgeliefert werden nur statische Dateien; die gewählten Dokumente verlassen den |
| Rechner der Nutzer:innen nicht. Die Herstellung verlangt abweichend von § 4 |
| Absatz 3 Oracle GraalVM 25.1 oder neuer, denn Web Image ist nur dort enthalten, |
| nicht in der Community Edition: |
| |
| [source,shell script] |
| ---- |
| JAVA_HOME=/pfad/zu/oracle-graalvm ./mvnw -Pwasm package |
| ---- |
| |
| (4) Ergebnis ist `target/web/` mit `index.html`, `app.js`, `worker.js`, |
| `style.css`, `favicon.svg`, `aendggner.js` und `aendggner.js.wasm` (rund 17 MB, |
| komprimiert etwa 5 MB). Das Verzeichnis ist so, wie es dasteht, auslieferbar: |
| `deploy/webpaket.sh` läuft am Ende desselben Befehls, wirft den mehrere hundert |
| Megabyte großen Textzwischenschritt `aendggner.js.wat` fort, schickt das Modul |
| durch `wasm-opt -Oz` und legt den Quelltext der gebauten Fassung als |
| `aendggner-quelltext.tar.gz` samt `quelltext-fassung.txt` bei. |
| |
| (5) Die Größe des Moduls beruht auf vier Vorkehrungen; wer eine davon zurücknimmt, |
| handelt sich die Megabyte wieder ein: |
| |
| 1. `-Os` beim Übersetzen statt der auf Durchsatz gerichteten Voreinstellung; |
| 2. kein Picocli-Annotationsprozessor im Profil `wasm`. Er meldete die |
| Befehlszeilenklasse zur Reflexion an, worauf die Erreichbarkeitsanalyse die |
| gesamte Befehlszeilenfassung ins Browser-Image zog, die dort niemand aufruft; |
| 3. ein enger Ressourcen-Glob in `reachability-metadata.json`. Das frühere |
| `org/apache/fontbox/**` bettete 3,3 MB CJK-CMaps, `Scripts.txt` und — weil |
| `**` auch Klassendateien trifft — 0,7 MB `.class`-Dateien ein, von denen |
| deutsche Gesetzes-PDFs nichts brauchen. Geblieben sind die beiden |
| Identity-CMaps; `org/apache/pdfbox/resources/**` bleibt vollständig, damit die |
| Breitenberechnung bei nicht eingebetteten Schriften unangetastet ist; |
| 4. `wasm-opt -Oz` als Nachlauf. Die zugelassenen Wasm-Merkmale sind in |
| `webpaket.sh` einzeln aufgezählt und nicht als `--all-features` erteilt: Sonst |
| nutzt Binaryen auch Vorschläge, die noch kein Browser annimmt, und das Modul |
| scheitert erst beim Instanziieren. |
| |
| (6) Im Quelltextarchiv fehlt der Beispielkorpus; `.gitattributes` nimmt |
| `src/test/resources/sampledata` von `git archive` aus. Es sind Gesetzes- und |
| Drucksachentexte fremder Urheberschaft, an denen allein die Tests messen — |
| Quelltext im Sinne der AGPLv3 sind sie nicht, gebaut wird ohne sie, und sie |
| machten das Archiv dreißigmal so groß wie den Quelltext (29,7 MB statt 0,26 MB). |
| `quelltext-fassung.txt` sagt dies und verweist für den vollständigen Korpus auf |
| die Anschrift nach § 3 Absatz 2. Wächst das Archiv wieder über 8 MiB, so bricht |
| `webpaket.sh` ab; alsdann sind Massendaten ins Repository geraten, die dort nicht |
| hingehören. |
| |
| (7) Trägt der Arbeitsbaum uneingecheckte Änderungen, so bricht die Herstellung |
| nach Absatz 3 ab, denn der beigelegte Quelltext wäre alsdann nicht der gebaute. |
| Für einen Probelauf hilft `QUELLTEXT_UNGEPRUEFT=1`. |
| |
| (6) Zur örtlichen Ansicht genügt `file://` nicht; Browser laden Wasm-Module und |
| Worker nur über HTTP (http://localhost:8000/): |
| |
| [source,shell script] |
| ---- |
| jwebserver -d target/web |
| ---- |
| |
| (7) Die Befehlszeilenfassung (§ 6) bleibt hiervon unberührt und ist weiterhin der |
| Weg für Massenläufe. |
| |
| |
| [[ausrollen]] |
| == § 15 Ausrollen |
| |
| (1) Erforderlich ist nur ein Ort für statische Dateien. Ausgeliefert wird über |
| Cloudflare Workers. Dort gilt eine Grenze von 25 MiB je Datei — unkomprimiert |
| gemessen —, und komprimiert wird beim Ausliefern ohnehin. `webpaket.sh` legt |
| deshalb keine `.gz`/`.br`-Beilagen mehr an und hält am Ende jede Datei gegen |
| diese Grenze; überschreitet eine sie, so bricht der Bau ab, statt das Hochladen |
| scheitern zu lassen. |
| |
| [source,shell script] |
| ---- |
| JAVA_HOME=/pfad/zu/oracle-graalvm ./mvnw -Pwasm package |
| ---- |
| |
| (2) Wer die Fassung stattdessen selbst ausliefert — unter einem Unterpfad einer |
| bestehenden Domain, wie zuvor unter https://matthias.benkard.de/aendggner/ —, |
| braucht die Vorkompression und fordert sie beim Bau an: |
| |
| [source,shell script] |
| ---- |
| JAVA_HOME=/pfad/zu/oracle-graalvm VORKOMPRIMIEREN=1 ./mvnw -Pwasm package |
| rsync -av --delete target/web/ server:/var/www/aendggner/ |
| ---- |
| |
| (3) `deploy/nginx-aendggner.conf` ist kein eigener `server`-Block, sondern ein |
| Schnipsel zum Einfügen in den vorhandenen (`include`). Er bringt mit: |
| |
| 1. die Weiterleitung von `/aendggner` auf `/aendggner/`, ohne die alle relativen |
| Verweise der Seite auf die Domainwurzel zielten; |
| 2. den MIME-Typ `application/wasm`, ohne den der Browser die Instanziierung des |
| Moduls verweigert; |
| 3. `gzip_static`/`brotli_static` für die nach Absatz 2 vorkomprimierten Dateien, |
| statt 17 MB je Abruf neu zu packen; |
| 4. `Cache-Control: no-cache` statt einer Haltefrist. Die Dateinamen tragen keine |
| Fassungskennung, und ein Browser mit altem `app.js` und neuem `.wasm` bekäme |
| sonst eine Mischfassung, die es nie gegeben hat. Revalidiert wird per ETag; das |
| unveränderte Modul kostet alsdann ein 304 ohne Rumpf; |
| 5. die Sicherheitskopfzeilen samt einer Content-Security-Policy. Zwei ihrer |
| Freigaben sind unvermeidlich und in der Datei begründet: `'wasm-unsafe-eval'` |
| für die Instanziierung des Moduls und `'unsafe-inline'` für Stile, weil die |
| Synopse als `blob:`-Dokument die Richtlinie der erzeugenden Seite erbt, ihr |
| Stylesheet aber eingebettet trägt. |
| |
| (4) `impressum.html` und `datenschutz.html` tragen die Angaben nach § 5 DDG und |
| Art. 13 DSGVO. Für den Regelfall — Auslieferung über Cloudflare — nennt |
| `datenschutz.html` Cloudflare als Auftragsverarbeiter nach Art. 28 DSGVO samt |
| Drittlandsübermittlung und sagt, dass Zugriffsprotokolle dort anfallen und vom |
| Verantwortlichen nicht abgerufen werden. Die daneben für die eigene Auslieferung |
| (Absatz 2) genannte Frist von 14 Tagen muss zu derjenigen des eigenen Servers |
| passen. Wer bei Cloudflare weitere Funktionen einschaltet — Web Analytics, |
| Logpush, Bot Management, Turnstile —, muss die Erklärung ergänzen; sie ist so |
| gefasst, dass keine davon in Betrieb ist. |
| |
| (5) Der Footer der Startseite verweist auf den beigelegten Quelltext-Tarball; dies |
| verlangt AGPLv3 § 13 für den Netzwerkbetrieb. Als fortlaufende Zweitquelle ist |
| die Anschrift nach § 3 Absatz 2 genannt. |
| |
| |
| [[aufbau]] |
| == § 16 Aufbau des Quelltextes |
| |
| (1) Gemeinsamer Kern von Befehlszeile und Browser ist `eu.mulk.aendggner.Pipeline`: |
| Stammgesetz laden, Änderungsdokumente erkennen, zerlegen und anwenden, Synopse |
| ausgeben. Die Pipeline kennt kein Dateisystem; Eingaben erreichen sie als |
| `eu.mulk.aendggner.Quelle` (Name und Bytes). |
| |
| (2) Die Pakete unterhalb von `src/main/java/eu/mulk/aendggner/` gliedern sich wie |
| folgt: |
| |
| `aenderung/`:: |
| Erkennen der Dokumentart, Textbereinigung und Zerlegung in Änderungsbefehle |
| (`parse/`), Herkunftsnachweis (`Provenienz`), Stellenangaben (`Stelle`). |
| `anwendung/`:: |
| Anwenden der Befehle auf die Stammfassung, Auflösen der Stellenangaben, Zerlegen |
| in Sätze, Fortschreiben der Inhaltsübersicht. |
| `gesetz/`:: |
| Die Stammfassung nebst Gliederung, Normen, Absätzen und Superskripten; `gii/` |
| liest das Bundesformat, `land/` die Fassungen der Länder. |
| `synopse/`:: |
| Wortdiff, Aufbau und HTML-Ausgabe der Synopse. |
| |
| (3) Der Kern ist reines Java ohne Dateisystem- und ohne Netzzugriff; nur vier |
| Stellen berühren die Plattform (PDFBox, MIME-Erkennung, XML-Parser, |
| Dateizugriff). Sie sind hinter `eu.mulk.aendggner.Quelle` (Name und Bytes) und |
| `eu.mulk.aendggner.DateiTyp` (Signaturbytes statt Tika) gebündelt; hierauf beruht, |
| dass Befehlszeile und Browser dieselbe Pipeline speisen. Ein Java-Server ist |
| deshalb entbehrlich. |
| |
| (4) Zwei Eigenheiten von Web Image sind zu beachten und im Quelltext vermerkt: |
| |
| 1. Die nativen zlib-Bindungen des JDK fehlen (`java.util.zip.Inflater`), ohne die |
| kein PDF lesbar ist. `src/wasm/java/.../InflaterErsatz.java` ersetzt sie durch |
| die reine Java-Umsetzung von jzlib. |
| 2. Typisierte Felder lassen sich derzeit nicht nach `byte[]` umsetzen; der |
| Dateiinhalt wandert deshalb als Base64-Text über die JS-Grenze. |
| |
| |
| [[pruefung]] |
| == § 17 Prüfung |
| |
| (1) Herstellung und Prüfung erfolgen durch den nachstehenden Befehl: |
| |
| [source,shell script] |
| ---- |
| ./mvnw verify |
| ---- |
| |
| (2) Die Prüfung umfasst neben den Einzelprüfungen Akzeptanzprüfungen, die |
| vollständige Änderungshefte auf die zugehörige Stammfassung anwenden und das |
| Ergebnis gegen die amtliche Nachfassung stellen. Die hierfür verwendeten |
| Beispieldaten nebst Herkunftsnachweis (`SOURCES`) liegen unter |
| `src/test/resources/sampledata/`. |