Files
swp-02-aufbereitung/NOTES.md
T
irrlichtandClaude Opus 5 3a9c000a0e Landtage und Regierungen im Lexikon, Rang als Gleichstandsregel
Drei neue Spiegelabfragen schliessen die gemessene Luecke im
Akteurslexikon: landtage (1539), regierung (2003), sondergesandte (5).
Lexikon 5540 -> 8856 Akteure, Aufloesung 21,1 % -> 23,2 % ueber 5018
Items. Der Gewinn steckt in wenigen Personen - Siegmund 123, Witkoff
102, Kushner 93, Lawrow 21.

Drei Abfragen, weil Wikidata drei Wege verlangt:

  landtage        P31/P279*, nicht P279* - "Mitglied des Landtag
                  Sachsen-Anhalt" ist eine Instanz von Q1939559, keine
                  Unterklasse. Dazu ein schaerferer Datumsfilter: von
                  11464 je gewaehlten Personen tragen 9700 keinerlei
                  Zeitangabe, ein blosses "kein Ende gesetzt" liesse die
                  Weimarer Republik herein.
  regierung       P1308, Amt -> derzeitiger Inhaber. Ueber die Amtszeit
                  der Person faellt Lawrow (amtiert seit 2004) aus jedem
                  Datumsfenster, ohne Fenster kommen Tausende Minister
                  herein, deren Amtszeit nie zu Ende gepflegt wurde.
  sondergesandte  Der andere Weg, fuer Witkoff - sein Amt traegt kein
                  P1308. Beide Wege in einer Abfrage laufen in die
                  Zeitgrenze der WDQS.

Kushner steht in hand.json: sein Amt endete 2021, seine Rolle nicht.

Die Erweiterung hat zuerst Schaden angerichtet. Mit den Landtagen kamen
Janine und Heiner Merz ins Lexikon, "Merz" wurde mehrdeutig, und 125
Nennungen des Bundeskanzlers fielen aus. Aus jedem "Hamburg" wurde eine
Kultusministerin (22-mal), aus "KI" ein Nachname (16-mal). Daher sieben
neue Sperreintraege und eine dritte Regel in waehle(): traegt genau ein
Kandidat den niedrigsten Rang, gewinnt er. Der Rang kommt aus der
Spiegelabfrage, Staatsfuehrung vor Bundestag vor Landtag - keine
Wichtigkeitsordnung, sondern eine Erwartung darueber, wen eine deutsche
Schlagzeile mit blossem Nachnamen meint. Abschlag 0,15, Grund steht in
der Nutzlast. Die Amtstabelle bekommt den schlechtesten Rang: sie reicht
bis 1794 zurueck, mit Rang 0 wurde aus "Teufel" ein
Ministerpraesident a. D.

Dabei fiel ein Loch im Fingerabdruck auf: NACHNAMEN_SPERRE stand nicht
in EINSTELLUNGEN_FEST. Ein Eintrag mehr aenderte das Ergebnis von 4868
auf 4820 aufgeloeste Nennungen unter derselben coder_version - genau
der Fehler, den die Version verhindern soll. Sperrliste und Rangordnung
gehen jetzt als Hash ein.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 12:11:56 +02:00

508 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Befunde aus dem Dublettenmodul
Gemessen am Bestand vom 4.–7.9.2026: 3407 Items, 12 Quellen, 106 Slots.
## Das Verfahren der Spezifikation findet keine Übernahmen
67 Gruppen, 147 Mitglieder, **null davon über Häuser hinweg**. Alle gefundenen
Gruppen sind Wiederholungen innerhalb eines Feeds.
Das ist kein Schwellenproblem, das sich durch Nachjustieren lösen ließe. Ein
vollständiger Vergleich aller 599.004 hausübergreifenden Paare des stärksten
Tages (6.9., 1162 vergleichbare Items) ergibt:
| Jaccard über Titel+Teaser | Paare über Häuser |
|---|---|
| ≥ 0.85 (Schwelle der Spec) | **0** |
| ≥ 0.7 | 1 |
| ≥ 0.5 | 3 |
| ≥ 0.3 | 8 |
Der höchste erreichte Wert im gesamten Tag liegt bei 0.65. Die Schwelle wird
nie berührt.
Die Hamming-Grenze ist dabei unschuldig: von 224 Paaren mit Jaccard ≥ 0.85
verwirft sie 6. Der Vorfilter über SimHash-Bänder kostet also fast nichts —
er ist gut, er hat nur nichts zu tun.
## Warum: der Titel wird übernommen, der Teaser nicht
Die Übernahmen sind da, sie sehen nur anders aus als angenommen. Beispiele
vom 6.9., alle mit **zeichengleichem Titel** nach Normalisierung:
```
zeit / handelsblatt Wahl in Sachsen-Anhalt: Klüssendorf: Frage nach SPD-Vorsitz …
zeit / handelsblatt Ukraine-Krieg: Selenskyj mit wenig Hoffnung auf baldigen Frieden
heise / tagesschau Deutsche Isar-Aerospace-Rakete erfolgreich ins All gestartet
handelsblatt / tagesschau +++ Iran-Krieg +++: Tote und Verletzte bei neuen Angriffen
```
Die Häuser übernehmen die Agenturüberschrift wörtlich und schreiben den
Teaser selbst. Werden beide in einen Sack geworfen, verdünnt der Teaser genau
das Signal, das trägt: dieselben Paare landen bei Jaccard 0.29 bis 0.38.
Gemessen, wenn **nur der Titel** verglichen wird (6.9., 1144 Items mit
mindestens fünf Titelwörtern):
| Kriterium | Paare | davon über Häuser |
|---|---|---|
| Titel zeichengleich | 61 | **22** |
| Titel-Jaccard ≥ 0.75 | 16 | **9** |
31 hausübergreifende Übernahmen an einem Tag statt null. Die Differenz
zwischen „zeichengleich" und „≥ 0.75" ist fast immer ein vorangestelltes
Ressortkürzel des Hauses: `Raumfahrt: Deutsche Isar-Aerospace-Rakete …` gegen
`Deutsche Isar-Aerospace-Rakete …`, oder `Notfälle:` gegen `Flugverkehr:` vor
derselben dpa-Zeile.
## Vorschlag
Vergleichsbasis auf den **Titel** umstellen, den Teaser nur noch als
Bestätigung heranziehen, wo er auf beiden Seiten vorliegt. Zusätzlich das
führende Ressortpräfix (`Wort:` am Anfang) in der Normalisierung abtrennen —
danach fällt ein Teil der 0.75er-Fälle in die Zeichengleichheit.
Das ist eine Änderung an Abschnitt 3 der Spezifikation, nicht an ihrer Absicht:
„near-exact, kein thematisches Clustering" bleibt. Die Abnahmekriterien wären
neu zu setzen, weil sich mit der Basis auch die Grundgesamtheit ändert.
## Umgesetzt, mit diesem Ergebnis
Der Vorschlag ist gebaut und ist jetzt die Vorgabe (`--basis titel`, dazu das
abgetrennte Ressortkürzel). Auf demselben Bestand:
| | Titel + Teaser | Titel |
|---|---|---|
| Gruppen gesamt | 67 | 135 |
| Mitglieder | 147 | 290 |
| **Gruppen über mehrere Häuser** | **0** | **63** |
| Items in solchen Gruppen | 0 | 143 |
Gruppengrößen: 240 Paare, 33 Dreier, 12 Vierer, 5 Fünfer. Die größte ist
dieselbe Zeile über den Start der Isar-Aerospace-Rakete bei handelsblatt,
heise, tagesschau und zeit.
Auf dem gemessenen Tag (6.9.) erreicht das Verfahren 42 von 45
hausübergreifenden Paaren mit Jaccard ≥ 0.70. Die Schwellen kosten dabei
nichts: an der Jaccard-Schwelle gehen 0 Paare verloren, an der
Hamming-Grenze 0. Die drei fehlenden scheitern am SimHash-Bandvorfilter —
bei sechs bis acht Trigrammen je Titel ist SimHash ein grobes Werkzeug. Ein
Trigramm-Index als zweiter Kandidatenweg würde sie einfangen.
Die Schwelle selbst ist unkritisch: zwischen Jaccard 0.70 und 0.85 liegt auf
diesem Bestand kein einziges Paar. Nach dem Abtrennen des Ressortkürzels sind
die Übernahmen entweder zeichengleich oder deutlich verschieden.
## Nebenbefund: Volltext hilft hier nicht
Auf den ersten Blick läge nahe, den Volltext zu nehmen, wo er da ist. Genau
das verbietet sich: die Abdeckung ist ungleich (faz 311/489, heise 174/196,
aber derstandard, welt, dlf, taz, sz jeweils 0), und ein Paar aus einem Haus
mit und einem ohne Volltext ist der häufigste Fall überhaupt. Eine je Item
verschiedene Vergleichsbasis macht genau die Paare unauffindbar, um die es
geht.
## Nebenbefund: `agentur_vermutet` greift kaum
Zwei Belege im gesamten Bestand, beide `reuters`. Die Agenturkennung steht in
RSS-Titeln und -Teasern praktisch nie; sie taucht erst im Volltext oder in der
Bildunterschrift auf. Das Feld bleibt, liefert aber auf RSS-Basis fast immer
`null`.
## Was beim Aufräumen weggefallen ist
Nach den Experimenten einmal gemessen, welche Regel auf den 3407 Items
überhaupt jemals greift:
| Regel | Treffer |
|---|---|
| Ressortkürzel abtrennen | 1870 |
| Anführungszeichen/Striche vereinheitlichen | 654 |
| `+++ … +++` entfernen | 8 |
| NFKC | 4 |
| `Eilmeldung:` entfernen | **0** |
| Ortsmarke `Berlin (dpa) -` entfernen | **0** |
| HTML-Tags entfernen | **0** (auch im Teaser) |
| Entities auflösen im Titel | **0** |
Entfernt wurden `_EILMELDUNG` und `_ORTSMARKE`. Beide stehen so in Abschnitt 3
der Spezifikation, greifen aber auf RSS-Titeln nie — die Ortsmarke steht im
Volltext einer Agenturmeldung, nicht in der Überschrift. Kommt Volltext als
Quelle hinzu, gehören sie zurück.
Das Entfernen von HTML-Tags bleibt trotz null Treffern: Phase 1 zieht die
`links` aus dem Teaser-HTML, HTML ist im Feed also grundsätzlich zu erwarten.
Der doppelte Entity-Durchlauf (vor *und* nach dem Tag-Entfernen) ist auf einen
reduziert.
Ebenfalls raus: der ungenutzte `anzahl`-Parameter von `baender()`, zwei
ungenutzte Argumente von `stichprobe()`, der `version`-Parameter von
`eintragen()`, ein `__main__`-Block in `version.py`, der eine Version ohne
Moduleinstellungen ausgab und damit nie die echte.
Zusammengelegt: `lade()` hatte am Ende selbst gruppiert, und `main()` rechnete
dieselbe Gruppierung anschließend ein zweites Mal. Beides steckt jetzt in
`lade_und_gruppiere()` — beim Slot-Lauf gehört es ohnehin zusammen, weil sich
erst an den Gruppen zeigt, wieviel geladen werden muss.
Zwei Kommentarblöcke zur Vergleichsbasis widersprachen sich nach der
Umstellung; der ältere behauptete noch „verglichen wird immer Titel + Teaser".
Die Schwellen selbst sind alle belegt. Von 778 Kandidatenpaaren verwirft das
Datumsfenster 223, die Regel „gleiches Haus, anderer Tag" 48 und die
Hamming-Grenze 330; 177 werden bestätigt. Nur die Jaccard-Bestätigung verwirft
nichts mehr — sie bleibt als Präzisionszusage, weil SimHash kollidieren kann.
Der Kettenschnitt trifft genau eine von 135 Komponenten und bleibt aus
demselben Grund.
# Befunde aus dem Revisionsmodul
Bestand vom 4.–7.9.2026, 3407 Items, 3974 Fassungen.
## Wieviel überhaupt geändert wird
| | Items |
|---|---|
| nie geändert | 3084 |
| mindestens eine neue Fassung | 323 |
| davon mit geändertem **Titel** | 206 (357 Übergänge) |
| davon nur Teaser geändert | 111 |
| URL geändert | 78 Übergänge |
Rund 6 Prozent aller Schlagzeilen werden nach der Veröffentlichung noch
angefasst. Das ist häufiger, als man erwartet, und es verteilt sich über alle
zwölf Häuser.
## Art der Änderung (erste gegen letzte Fassung)
| Einstufung | gesamt | ohne Fortschreibung |
|---|---|---|
| umformulierung | 83 | 77 |
| neufassung | 56 | 22 |
| kopfwechsel | 26 | 26 |
| erweiterung | 14 | 13 |
| kuerzung | 11 | 11 |
| formal | 9 | 9 |
| tippfehler | 6 | 6 |
| zurueckgenommen | 1 | 0 |
»Ohne Fortschreibung« zieht die 10 selbstbenannten Ticker und die 33 Items mit
stabiler Rubrik und ausgetauschtem Stand ab. Die Spalte zeigt, wozu das nötig
ist: bei `neufassung` bleiben von 56 nur 22 übrig — zwei Drittel der scheinbar
komplett neu geschriebenen Schlagzeilen sind Liveticker, die von einem Stand
zum nächsten weiterzählen.
## Umgeschriebene Schlagzeilen je Haus (ohne Fortschreibung)
spiegel 39, zeit 26, derstandard 18, faz 17, ntv 13, tagesschau 10, welt 10,
heise 9, taz 9, handelsblatt 8, dlf 3, sz 2.
Vorsicht bei der Deutung: die Zahlen hängen an der Feedgröße (zeit 550 Items,
sz 73) und an der Frage, ob ein Haus überhaupt denselben Item-Key beibehält,
wenn es die Überschrift ändert. Wer die URL mitwechselt, erscheint bei Ingest
als neues Item und taucht hier gar nicht auf. Als Rangliste taugt das nicht,
als Nachweis, dass es geschieht, sehr wohl.
## Warum der Pluskasten hier stehen bleiben muss
`normalisierung.normalisiere()` entfernt für das Dublettenmodul »++ … ++«, weil
verschiedene Häuser denselben Agenturtext verschieden einrahmen. Die tagesschau
führt ihren Liveticker aber vollständig darin:
++ Liveticker zur Sachsen-Anhalt-Wahl: Wahllokale haben geöffnet ++
Nach der Dublettennormalisierung bleibt davon der leere String. 31 der 357
Übergänge wären damit unvergleichbar gewesen. Deshalb `pluskasten=False`.
## Was das Verfahren nicht kann
* **Unmarkierte Fortschreibungen.** Die Welt schrieb »54,4 Prozent am
Nachmittag …« zu »Schon 65,3 Prozent …« um — ein Wahlabend-Dauerartikel ohne
jedes Tickerwort und ohne feste Rubrik. Er zählt als `neufassung`. `fassungen`
und `zahlen_geaendert` stehen in der Nutzlast, damit sich das nachträglich
eingrenzen lässt; automatisch erkannt wird es nicht.
* **Getrennt- und Zusammenschreibung.** »Drohnenattacken:« → »Drohnen-Attacken:«
gilt als `kopfwechsel`, nicht als `formal`, weil die Normalisierung
Satzzeichen entfernt und daraus zwei Wörter werden. Ein Fall im Bestand.
* **Das Gewicht einer Änderung.** `kopfwechsel` sagt, *wo* geändert wurde, nicht
wie schwer es wiegt. Für die Unterscheidung sind `hinzu` und `entfernt` da.
## Nebenwirkung auf die coder_version
`version.KOMPONENTEN` bekam den Schlüssel `revision`. Weil der Hash über den
ganzen Komponentensatz läuft, ändert sich damit auch die Version des
Dublettenmoduls (`10cea100` → `51e03f9b`), obwohl an dessen Verfahren nichts
anders ist. Das ist die in `version.py` beschriebene Semantik der
Spezifikation, kein Versehen. Der Backfill kostet 0,3 Sekunden; die alte
Version wurde verworfen.
# Befunde aus dem Embeddingmodul
## Die Stapelzusammensetzung ist das eigentliche Problem
Nicht die CPU, nicht die Bibliothek, nicht der Container: dass ein Encoder
stapelweise rechnet und die Matrizenform mit dem Stapel wechselt. Wer nur bis
zur längsten Zeile des Stapels auffüllt, bekommt für dieselbe Zeile
verschiedene letzte Stellen, je nachdem, wer mit ihr im Stapel lag.
Mit fester Länge (128 Token für jede Zeile) verschwindet der Effekt
vollständig — nicht »klein«, sondern exakt null:
| Vergleich | bitgleich | größte Abweichung |
|---|---|---|
| voller Stapel gegen einzeln | 64/64 | 0.00e+00 |
| voller Stapel gegen rückwärts | 64/64 | 0.00e+00 |
Der Preis: jede Zeile kostet 128 Token Rechenzeit, auch wenn sie 62 braucht.
Bei Median 62 ist das gut Faktor zwei. Für die Zusage aus Invariante 2 ist er
es wert — und bei 7 s je Slot fällt er nicht auf.
## Tokenlängen im Bestand
Median 62, p95 90, p99 107, Maximum 233. Über 128 liegen 3 von 3407 Items:
zweimal »tagesschau 20:00 Uhr« (Sendungsablauf mit vollständiger Themenliste)
und einmal eine DLF-Hochrechnung. 256 statt 128 würde die Rechenzeit
verdoppeln, um 0,09 Prozent der Items vollständig zu erfassen — nicht
lohnend.
## Was die Vektoren finden, was SimHash nicht findet
Hausübergreifende Paare über 0.94 Kosinus, die das Dublettenmodul nicht
zusammengeführt hat — dieselbe Geschichte, anderer Wortlaut:
0.994 faz / handelsblatt Wasserdefizit in Deutschland
0.992 spiegel / handelsblatt Drohne trifft Geheimdienstzentrale in Kiew
0.992 zeit / faz Michael Mendl gestorben ("Schauspieler" / "Charakterdarsteller")
0.991 tagesschau / welt Trump-Gesandte reisen nach Moskau und Kiew
0.985 heise / handelsblatt Isar-Aerospace-Rakete erfolgreich gestartet
Das ist der Beleg dafür, dass Modul 1 und Modul 5 verschiedene Fragen
beantworten und keins das andere ersetzt.
## Container
Die regelbasierten Module liefern im Container (Debian trixie, Python 3.13)
für alle 3407 Items bitgleich dieselbe Nutzlast wie auf der
Entwicklungsmaschine (Fedora, Python 3.14). Damit ist die Portabilität nicht
behauptet, sondern gemessen.
`sentence-transformers` fiel zugunsten von `transformers` weg: es kapselt das
Auffüllen der Stapel weg — also genau die Stelle, an der hier die
Reproduzierbarkeit entschieden wird — und zieht scipy und scikit-learn nach.
Ein Stolperstein beim Volume: der Container läuft als UID 10001, ein frisch
angelegtes Podman-Volume gehört root im User-Namespace. Ohne `:U` am
Volume-Argument scheitert der erste Schreibzugriff auf den Modell-Cache.
Dieselbe Klasse Problem wie bei pgAdmin, nur mit anderem Symptom.
# Befunde aus der Vorarbeit zu Akteuren
## Ein Datenfehler aus Phase 1: `"None"` als Teaser
382 der 550 zeit-Items tragen als Teaser die Zeichenkette `None` — nicht
`NULL`, sondern Pythons `None` in Text verwandelt. Das sind 69 Prozent des
Hauses.
Der Fehler entsteht im Ingest und ist in Phase 2 bereits wirksam geworden:
- die Embeddings dieser 382 Items kodieren ein bedeutungsloses Wort mit,
- die Dublettenprüfung vergleicht es mit,
- die NER hält es 112-mal für einen Ort oder eine Organisation.
Zu reparieren ist er richtigerweise in Phase 1. Phase 2 kann ihn abfangen,
das entwertet aber jede bestehende `coder_version` und erzwingt einen
vollständigen Neuaufbau.
Bemerkenswert ist, wie lange er unentdeckt blieb: keine der drei bisherigen
Auswertungen schaute je auf einen einzelnen Teaser, und in der Aggregation
ist `None` ein Wort wie jedes andere.
## `de_core_news_sm` gegen `de_core_news_lg`, 3407 Items
| | sm | lg |
|--------------------------|--------|--------|
| Entitäten | 14 249 | 14 261 |
| Durchsatz | 465/s | 428/s |
| Items ohne jede Entität | 81 | — |
Die Gesamtzahlen sind fast gleich. Das ist eine Falle: die beiden Modelle
finden **nicht dieselben** Entitäten.
| Vergleich | Wert |
|------------------------------------|-------|
| Items mit identischem Ergebnis | 10,7 %|
| Items mit identischen Spannen | 18,2 %|
| Jaccard über alle Spannen | 0,590 |
Auch wenn man die Typen ignoriert und nur die Spannen vergleicht, stimmen
die Modelle bei zwei von fünf Nennungen nicht überein.
Entscheidend ist, *welche* Nennungen das sind. `lg` findet 170-mal
zusätzlich `AfD` und je 80-mal `Kushner` und `Witkoff`, dazu `Merz`, `Putin`,
`Trump`, `Siegmund` — also genau die Akteure, um die es in diesem Korpus
geht. `sm` stuft `AfD` 226-mal als MISC und 23-mal als LOC ein, `lg` 392-mal
als ORG.
Daraus folgen zwei Dinge:
1. **`lg`**, denn der Zeitunterschied ist mit 7,3 zu 8,0 Sekunden für den
Gesamtbestand kein Argument. Der Preis sind 568 MB im Image.
2. **Den NER-Typen ist nicht zu trauen.** Beide Modelle halten `Merz` für
einen Ort, `Landtagswahl` für einen Ort und `Ukraine-Krieg` für eine
Person. Die NER liefert deshalb nur *Kandidatenspannen*; welchen Typ eine
Nennung hat, entscheidet das Lexikon, nicht das Modell.
## Was das Akteursmodul auflöst — und was nicht
Gesamtbestand, 3407 Items, 21,1 Sekunden:
| | |
|---|---|
| Nennungen | 14 652 |
| aufgelöst | 2 889 (19,7 %) |
| Lexikon | 5540 Akteure, 416 Amtszeiten |
Ein Slot-Lauf erzeugt bitgleich dieselbe Nutzlast wie der Gesamtlauf
(3407 Codings, 0 Abweichungen).
Die 19,7 Prozent klingen niedrig und sind es nicht. Die häufigsten
unaufgelösten Formen zeigen, warum:
| Nennungen | Form | wessen Zuständigkeit |
|---|---|---|
| 567 | Sachsen-Anhalt | Geokodierung |
| 382 | `None` | Ingest-Fehler, siehe oben |
| 170 | Landtagswahl in Sachsen-Anhalt | Ereignis, kein Akteur |
| 143 | Berlin | Geokodierung |
| 119 | Kiew | Geokodierung |
| 95 | Witkoff | echte Lexikonlücke |
| 87 | Kushner | echte Lexikonlücke |
| 56 | Siegmund | echte Lexikonlücke |
Drei verschiedene Dinge, die als eine Zahl erscheinen: Orte gehören dem
nächsten Modul, `None` ist ein Datenfehler, und nur der Rest ist wirklich
eine Lücke im Lexikon.
### Die Lücke hat ein Muster
`Witkoff`, `Kushner`, `Siegmund` — US-Sondergesandte und
Landtagsabgeordnete. Der Spiegel deckt Bundestag, Staats- und
Regierungschefs, Parteien, Staaten, Leitindex-Unternehmen und internationale
Organisationen ab. **Landtagsabgeordnete fehlen**, und ausgerechnet dieser
Korpus wird von einer Landtagswahl beherrscht.
Die Spezifikation nennt Landtagsabgeordnete nicht; die Auslassung ist also
regelkonform, aber für diesen Bestand teuer. Eine zusätzliche
Spiegelabfrage würde sie schließen.
### Zwei Fallen beim Spiegeln
**Geratene QIDs.** `Q157617` ist nicht der Bundesrat, sondern die
Commerzbank. Weil der Lader Einträge über die QID zusammenführt, trug er
prompt »Bundesrat« als Alias der Commerzbank ein. Handgesetzte QIDs gehören
geprüft, und `hand.json` sagt das jetzt in seinem Kopf.
**`FILTER (lang(?name) = "de")`.** Apple, Microsoft und Meta haben kein
deutsches Label in Wikidata und fallen deshalb aus jeder Spiegelabfrage —
lautlos. Ein Rückfall auf `en` wäre beim nächsten Spiegellauf die bessere
Wahl.
### spaCy ist stapelunabhängig
Bei Stapelgröße 64, 7 und 1 sowie rückwärts durchlaufen liefert
`de_core_news_lg` für 400 Items identische Spannen. Der Kunstgriff mit der
festen Tokenlänge, den die Embeddings brauchen, ist hier nicht nötig.
## Woher `None` wirklich kommt
Reproduziert am Live-Feed, nicht erschlossen: bei Items mit leerer
`<description>` fällt der Poller korrekt auf `content:encoded` zurück, und
dort liefert die ZEIT
```
<a href="https://www.zeit.de/news/..."><img ...>None</a>
```
Der Ankertext *ist* die Zeichenkette `None` — ein Renderfehler im CMS der
ZEIT. `klartext()` entfernt die Tags, und übrig bleibt `None`. Phase 1
schreibt also getreu mit; der Fehler ist stromaufwärts.
Am 8. September 2026 betraf das 8 von 15 Items im Feed. Im Prod-Bestand:
| Tag | `None` / zeit-Items |
|---|---|
| 2026-09-04 | 12 / 20 |
| 2026-09-05 | 83 / 136 |
| 2026-09-06 | 187 / 262 |
| 2026-09-07 | 305 / 400 |
| 2026-09-08 | 67 / 79 |
Gleichbleibend rund 70 bis 85 Prozent — der Fehler läuft weiter.
## Container mit spaCy
Das Abbild wächst durch `de_core_news_lg` von 1,28 auf 2,12 GB. Das Modell
liegt im Abbild, nicht im Cache-Volume: 568 MB, die sich nie ändern, und der
erste Lauf auf Prod soll nicht an einem Download hängen.
Gemessen, nicht behauptet: ein Slot-Lauf im Container (Debian trixie,
Python 3.13) erzeugt für die Akteure bitgleich dieselbe Nutzlast wie die
Workstation (Fedora, Python 3.14) — 3407 Codings, 0 Abweichungen, gleiche
`coder_version`.
## Landtage und Regierungen: was die Lexikonerweiterung gekostet hat
Zwei neue Spiegelabfragen, 08.09.2026, gemessen an 5018 Items:
| | vorher | nachher |
|---|---|---|
| Akteure im Lexikon | 5540 | 8856 |
| aufgelöste Nennungen | 4539 (21,1 %) | 4982 (23,2 %) |
Der Gewinn steckt fast vollständig in wenigen Personen: Witkoff 102,
Kushner 93, Siegmund 123, Lawrow 21. Der lange Schwanz bleibt liegen —
von 1757 unaufgelösten PER-Formen trugen 1344 genau eine Nennung.
### Zwei Wege zum amtierenden Minister, und beide werden gebraucht
`P1308` (Amt → derzeitiger Inhaber) fängt Lawrow, der seit 2004 amtiert
und aus jedem Datumsfenster fällt. Der Weg über die Amtszeit der Person
fängt Witkoff, dessen Amt kein `P1308` trägt. Beides in einer Abfrage zu
vereinen, läuft in die Zeitgrenze der WDQS — deshalb zwei Dateien.
Die Landtagslisten sind nicht über Unterklassen erreichbar: "Mitglied des
Landtag Sachsen-Anhalt" ist eine *Instanz* von Q1939559, keine
Unterklasse. `P31/P279*` statt `P279*`.
### Die Erweiterung hat zuerst Schaden angerichtet
Mit den Landtagen kamen Janine und Heiner Merz ins Lexikon. "Merz" war
damit mehrdeutig, und **125 Nennungen des Bundeskanzlers fielen aus** —
der teuerste Einzelposten des Korpus, verloren durch einen Zugewinn.
Ebenso wurde aus jedem "Hamburg" eine niedersächsische Kultusministerin
(22-mal) und aus "KI" ein südkoreanischer Nachname (16-mal).
Daraus zwei Änderungen:
1. Die Sperrliste wuchs um sieben Einträge, alle mit Begründung.
2. `waehle()` hat eine dritte Regel: trägt genau ein Kandidat den
niedrigsten Rang, gewinnt er. Der Rang kommt aus der Spiegelabfrage —
Staatsführung vor Bundestag vor Landtag. Das ist kein Münzwurf,
sondern eine Erwartung darüber, wen eine deutsche Schlagzeile mit
blossem Nachnamen meint; Abschlag 0,15 auf die Konfidenz, und der
Grund steht als `grund` in der Nutzlast.
Die Amtstabelle bekam dabei den *schlechtesten* Rang, nicht den besten.
Sie reicht bis 1794 zurück und besteht überwiegend aus Verstorbenen; mit
Rang 0 wurde aus "Teufel" ein Ministerpräsident a. D. und aus "Otto" ein
Bremer Bürgermeister des 18. Jahrhunderts.
### Ein Loch im Fingerabdruck
`NACHNAMEN_SPERRE` stand nicht in `EINSTELLUNGEN_FEST`. Ein Eintrag mehr
änderte das Ergebnis von 4868 auf 4820 aufgelöste Nennungen — unter
derselben `coder_version`. Genau der Fehler, den die Version verhindern
soll, und er war zwei Module lang unentdeckt. Die Sperrliste geht jetzt
als Hash in den Fingerabdruck ein, die Rangordnung ebenso.