From 5f30f566873c313b554f087c0f7e132efa54d64a Mon Sep 17 00:00:00 2001
From: Matthias Andreas Benkard <code@mail.matthias.benkard.de>
Date: Tue, 28 Jul 2026 06:00:16 +0200
Subject: Recognise word-anchored insertions; close quotes at the next item
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The documented next step was the word-anchored structural insertion
("Vor den Wörtern „Aus dem Bereich Verkehr:“ wird folgender Absatz 5
eingefügt", Berlin Artikel 1 Nr. 2 b) bb)). StrukturEinfuegung now
carries an optional WortAnker, the recogniser has a pattern for the form
— placed before STRUKTUR_EINFUEGUNG, which bails out of recognition
entirely when the StellenParser cannot read "den Wörtern «0»" — and the
applier positions the new unit at the anchor line instead of a structural
boundary.

Two blockers turned up next to it, both measured on the corpus rather
than assumed:

The command was not cleanly recognisable at all. Its closing quotation
mark is missing in the official text, so the quote swallowed items cc)
and c); an anchor alone would have made the command look applicable with
a huge foreign quote as its payload. The docs called a boundary at
enumeration markers impossible, and that holds for the unguarded form: a
quoted amendment provision carries command language itself. Guarded by
four conditions together — the article's quotation marks demonstrably do
not balance, the next line's marker is at the same or a shallower level
than the one the quote opened on, that line carries command language, and
closing here leaves the rest of the article balanced — it fires exactly
twice in the whole sample corpus, both times where the missing mark
belongs: Berlin before cc), and GV. NRW. Artikel 2 before 12. Without the
guards it also fires inside quoted amendment provisions in the BayJG and
GModG documents; the balance gate rules those out.

The GV.-NRW. gazette encodes part of its umlauts decomposed (u + U+0308,
79 places, dozens of them "eingefügt:"/"angefügt:"). Invisible in the
text, but a different word to every command pattern, so those commands
could never match. TextBereiniger now normalises to NFC first — not
NFKC, which would flatten the official sentence numbers ¹²³ and take
SatzTeiler and Superskript their basis. Every other sample document,
every gii-XML stem and every hand-kept plain-text stem is already NFC, so
the pinned figures stay bit-identical.

Berlin Artikel 1 is thereby fully recognised (6 of 6 commands, none
unknown). One pinned statement changed for a stated reason: the NRW
acceptance test asserted the article-heading warning, which is now
preempted by the item boundary inside Artikel 2 — Nr. 12 survives
instead of being swallowed. 241 tests green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Ic579bec6fecc2495a61b3dcf87c9ad71b42f34ae
---
 .../sampledata/Landesrecht-Beispiele.adoc          | 31 +++++++++++-----------
 1 file changed, 16 insertions(+), 15 deletions(-)

(limited to 'src/main/resources/sampledata/Landesrecht-Beispiele.adoc')

diff --git a/src/main/resources/sampledata/Landesrecht-Beispiele.adoc b/src/main/resources/sampledata/Landesrecht-Beispiele.adoc
index dbfe8b7..9a661f3 100644
--- a/src/main/resources/sampledata/Landesrecht-Beispiele.adoc
+++ b/src/main/resources/sampledata/Landesrecht-Beispiele.adoc
@@ -106,8 +106,10 @@ folgt geändert").
   abgeglichen. Die übrigen Artikel (WDR-Gesetz, Landesmediengesetz, 17. RÄStV-AusfG) bleiben offen.
 * *Berlin* ist bis zur Befehlserkennung umgesetzt (`EndToEndTest.asogLafAendGBerlin`): Artikel 2
   (LAF-Errichtungsgesetz) wird vollständig erkannt, beide Punkte erben ihr Ziel aus der
-  Änderungsformel. Von Artikel 1 werden drei der vier Befehle erkannt, einschließlich der
-  Änderungen an der unnummerierten Anlage; der vierte nutzt einen Wortanker (siehe „Noch offen“).
+  Änderungsformel. Artikel 1 wird seit der Wortanker-Einfügung und der Zitatgrenze am
+  Aufzählungspunkt *vollständig* erkannt — alle sechs Befehle, einschließlich der Änderungen an der
+  unnummerierten Anlage. Ein voller Akzeptanztest bleibt an der Stammfassung hängen (siehe „Noch
+  offen“).
 * Baden-Württemberg (GBl 2026 Nr. 26): großes Anlage-lastiges Änderungsgesetz (§§ 4–57a + Anlagen
   1/3b/4b); Stammfassung/Akzeptanztest noch offen.
 
@@ -142,6 +144,13 @@ Fällt das Portal aus, bleibt der Weg über das Gesetzblatt selbst: Trägt der E
 Stammfassung (so bei Niedersachsen). Die Extraktion zweispaltiger Hefte übernimmt `--extract-only`
 des Werkzeugs selbst; `pdftotext -layout` verschränkt dort die Spalten.
 
+Ein Fallstrick beim Prüfen extrahierter Hefte: Das GV.-NRW.-Heft 7/2026 kodiert einen Teil seiner
+Umlaute *zerlegt* (`u` + U+0308 statt `ü`, 79 Stellen, darunter dutzende „eingefügt:“/„angefügt:“).
+Im Text ist das unsichtbar, für jedes Befehlsmuster aber ein anderes Wort. `TextBereiniger.bereinige`
+normalisiert deshalb ganz früh nach NFC — nicht NFKC, das plättete die amtlichen Satznummern ¹²³ zu
+gewöhnlichen Ziffern. Wer Klartext von Hand aufbereitet, sollte ihn ebenfalls in NFC ablegen; der
+Klartext-Zweig des Loaders normalisiert zur Sicherheit mit.
+
 == Noch offen
 
 * *Schleswig-Holstein — Stammfassung nicht beschaffbar*: Das Landesportal
@@ -163,14 +172,6 @@ des Werkzeugs selbst; `pdftotext -layout` verschränkt dort die Spalten.
   „Art.“-Normköpfe: Eine handgepflegte Stammfassung kann *keine* Anlage tragen. Das ist die
   konkrete Lücke für Berlin (Artikel 1) und Baden-Württemberg (Anlagen 1/3b/4b) — sie wird erst
   behebbar, wenn für eines der beiden eine Stammfassung vorliegt.
-* *Struktureinfügung mit Wortanker*: „Vor den Wörtern „Aus dem Bereich Verkehr:“ wird folgender
-  Absatz 5 eingefügt“ (Berlin Artikel 1 Nr. 2 b) bb)) — die Position der neuen Einheit bestimmt
-  ein Wortanker statt einer Stellenangabe. `StrukturEinfuegung` trägt bislang nur eine Stelle.
-* *Unbalancierte Anführungszeichen innerhalb eines Artikels*: Die Strukturgrenze des
-  Zitatextraktors greift nur an Artikel-Überschriften. In Berlin Artikel 1 fehlt bei Nummer 2 b) bb)
-  das schließende Anführungszeichen; das Zitat verschlingt daher die folgenden Punkte cc) und c).
-  Eine Grenze an Aufzählungsmarkern ist nicht möglich — zitierter Gesetzestext enthält selbst
-  Aufzählungen (dafür gibt es die Fortführungszeichen-Erkennung).
 * *Berlin, ganzseitenbreite Rahmen*: Titelblock und Impressum stehen im Inhaltsstrom an anderer
   Stelle als im Satzbild (der Titelblock mitten im Fließtext der ersten Seite). Das zu beheben
   verlangt eine geometrische Lesereihenfolge (XY-Cut), nicht bloß eine Spaltenerkennung.
@@ -184,13 +185,13 @@ des Werkzeugs selbst; `pdftotext -layout` verschränkt dort die Spalten.
 Kein Land scheitert noch an reiner Extraktionsschwäche; offen sind Modell- und Beschaffungsfragen.
 Nach absteigendem Nutzen:
 
-. *Struktureinfügung mit Wortanker* (siehe „Noch offen“). Rein im Modell zu lösen, ohne neue
-  Stammfassung: `StrukturEinfuegung` um einen Wortanker ergänzen, wie ihn `WoerterEinfuegung`
-  bereits trägt. Belegfall ist Berlin Artikel 1 Nr. 2 b) bb); prüfbar bis zur Befehlserkennung.
 . *Weitere Artikel des NRW-Heftes* (WDR-Gesetz, Landesmediengesetz). Die Stammfassungen sind über
   das oben beschriebene recht.nrw.de-Rezept unmittelbar greifbar, und die Nachfassungen erlauben
-  wieder den Abgleich gegen den amtlichen Text. Ergibt einen Massentest mit über hundert Befehlen.
-. *Anlagen-Normköpfe im `LandesRechtTextParser`* — lohnt erst zusammen mit (2) oder sobald für
+  wieder den Abgleich gegen den amtlichen Text. Ergibt einen Massentest mit über hundert Befehlen:
+  Seit der NFC-Normalisierung erkennt der Parser in Artikel 1 (WDR-Gesetz) 103 Befehle, davon 20
+  noch nicht, in Artikel 2 (Landesmediengesetz) 18 Befehle, davon 5 noch nicht — diese Reste sind
+  der eigentliche Ertrag des Massentests.
+. *Anlagen-Normköpfe im `LandesRechtTextParser`* — lohnt erst zusammen mit (1) oder sobald für
   Berlin bzw. Baden-Württemberg eine Stammfassung vorliegt, sonst nicht end-to-end prüfbar.
 . *Hessen* als Sperrsatz-Härtetest („3 . F e bru a r 2 02 6“). Betrifft nur Datums- und
   Signaturzeilen, nicht die Befehle — kosmetisch, aber ein eigener Extraktionsfall.
-- 
cgit v1.2.1

