Aus #231 (Betreiber, 2026-10-14): Der Vergleich, den die Sitzung zu #225/#231 von Hand gemacht hat – eigene Ableitung gegen pymupdf4llm/MuPDF am realen Korpus, gemessen in Mehrlänge, falscher und fehlender Auszeichnung, Struktur und Laufzeit –, soll immer wieder durchgeführt werden, als instructions/dev-Anweisung. Generalisiert für alle Nicht-Text-Quellen: DOCX, PPTX und XLSX können ähnliche Effekte zeigen (Tabellenschattierung, Folienflächen, Farbe als Gestaltung).
Stand: abgeschlossen
Stack, Commit d393e2f (Kandidat 10.1.0-beta.3): die Anweisung, ihre Verweise und der Absatz in docs/dev/development.md.
Nachzug beim Abschluss, Commit 01360e9 (10.1.0-beta.4): Die Anweisung nennt harness/compare/README.md als Ort der Einrichtung. Vorher schrieb Schritt 1 fälschlich „die README des privaten Repos“.
Privates Repo torben/chemenu-testfiles, Commit 916a718: Harness harness/compare/ und Grundlinie harness/baseline.json, mit Freigabe des Betreibers direkt per git push dort.
Verifiziert durch:
d393e2f: CI-Läufe 708 und 709 grün.
converters.yml Lauf 710, von Hand per workflow_dispatch auf main gestartet, weil sich nur das private Repo geändert hatte: grün. Er lud das private Repo auf 916a718 und meldete 46 bestanden (33 Korpus-Tests und 13 aus test_compare.py).
01360e9: CI-Läufe 711 und 712 grün.
Lokal: pytest mit 3064 bestanden und 4 übersprungen; docs verify und instructions verify OK.
Drei volle Läufe über das ganze Korpus (31 Dateien):
Lauf 1 war der erste Durchgang. Seine Laufzeiten sind durch parallel laufendes pytest verfälscht; er diente nur zum Prüfen.
Lauf 2 lief ungestört und hat die Grundlinie geschrieben.
Lauf 3 lief ohne Änderung gegen diese Grundlinie: kein Unterschied.
Ein voller Lauf dauert etwa 15–20 min, davon pymupdf4llm allein rund 440 s.
Warum eine Anweisung und nicht nur ein Test
Die Korpus-Tests (#232) prüfen, ob eine Ableitung gelingt, stabil ist und erwartete Texte enthält. Ob sie gut ist, prüfen sie nicht: ob eine Auszeichnung stimmt, ob Lärm entsteht, ob ein verfügbares Werkzeug es besser kann. Das braucht ein Urteil am Original und lässt sich nur teilweise als Zahl fassen. #225 hat gezeigt, was ohne diesen Schritt passiert: Erst am echten Korpus fielen 190 falsche Durchstreichungen und 24 % Mehrlänge auf.
Umsetzung
Anweisung instructions/dev/converter-comparison.md (Typ types/instruction.md), verlinkt aus stack-mode.md § Where the procedures are und aus testing-conventions.md § Scope. Inhalt:
Wann: vor dem Entwurf einer Konverter-Änderung (Ausgangslage messen), nach dem Bau vor dem Publish (Unterschied messen), wenn eine neue Datei ins Korpus kommt, und wenn ein Format neue Effekte zeigt.
Was: jedes Format mit Filter: PDF, DOCX, PPTX, XLSX/XLSM, EML/MSG, HTML. ZIP ist nur ein Behälter und wird übersprungen. Im Korpus gibt es derzeit kein HTML und kein XLSM.
Referenzwerkzeuge je Format als Tabelle mit Rolle; die Versionen stehen voll gepinnt in harness/compare/requirements-reference.txt.
DOCX: die document.xml (Änderungen, Kommentare, Run-Formatierung)
PPTX: python-pptx (Notizen)
XLSX: openpyxl (ausgeblendete Blätter, Formeln)
Maße je Datei (wie gebaut):
Wortlaut-Treue: Bei PDF ist der Text ohne Auszeichnung derselbe wie die Ableitung ohne Layoutanalyse (pdf_layout.analyse im Harness auf leer gesetzt, also pypdf allein). Die anderen Formate haben keinen getrennten Stil-Durchgang; dort ist Maß 1 die Wort-Übereinstimmung mit jeder Referenz (Recall/Präzision über Wörter mit Vielfachheit). Das wurde beim Bau festgelegt, weil der Body für diese Formate keinen Vergleichstext nannte.
Kontext-Mehrlänge: Auszeichnungszeichen / Textzeichen; bei PDF genau das, was die Layoutanalyse hinzufügt, einschließlich Legende.
Präzision: Stichprobe der Auszeichnungen (samples.md) gegen das Original, per Seitenbild (--render, PDF). Sitzungsarbeit.
Fehlende Semantik gegenüber Referenz und Orakel: Durchstreichung, Textmarker, fett/kursiv; bei DOCX Änderungsverfolgung und Kommentare, bei XLSX ausgeblendete Blätter und Formeln, bei PPTX Notizen.
CHECK-Präzision: die vom Bild-CHECK genannten Seiten gegen die Seiten mit inhaltlichem Bild. Nicht inhaltlich ist:
ein Hintergrund (> 80 % der Seite),
ein Füllbild (Quelle ≤ 4 px oder gezeichnet < 10 pt),
ein Vorlagenbild (dasselbe Bild auf ≥ 20 % der Seiten, mindestens 3).
Die Kriterien stammen aus #231 Punkt 6, hier unabhängig über MuPDF umgesetzt. Dazu kommen die gedrehten Seiten, sowohl über /Rotate als auch über seitwärts laufenden Text.
Beim Bau ergänzt: Der erste Lauf verglich nur mit „Seite hat irgendein Bild“, und das ist trivial immer erfüllt. Gegenprobe: Für IHF liefert das Orakel genau {1, 2, 6–8, 29, 48–55, 81, 96}, also die Seiten, die #231 von Hand bestimmt hat. Die gedrehten Seiten von Girokonten (7–13) erkennt nur das Text-Signal; /Rotate meldet dort keine.
Laufzeit.
Präzision vor Trefferquote: Falsche Auszeichnung wiegt schwerer als fehlende.
Ausgang:
Ein Bericht mit den Maßen je Datei und dem Unterschied zur letzten Grundlinie.
Die Grundlinie (harness/baseline.json im privaten Repo) wird nur bewusst fortgeschrieben (--write-baseline), mit Stack-Version und Begründung im Commit.
Befunde gehen in den Body des Issues, an dem gearbeitet wird, oder in das Issue des Themas.
Eine Schwelle wird nie ohne Korpuslauf geändert.
Was vom Korpus in ein Issue darf, regelt weiterhin dev-setup.md Schritt 6; die Anweisung verweist darauf.
Vergleichs-Harness im privaten Repo unter harness/compare/:
compare.py läuft mit tools/.venv des Checkouts und misst also dessen Filter.
reference.py läuft in harness/compare/.ref-venv, als eigener Prozess je Datei.
metrics.py nutzt nur die Standardbibliothek.
test_compare.py enthält 13 Tests der Maße; sie laufen im converters-Workflow mit und brauchen keine Referenz-Umgebung.
README.md beschreibt Einrichtung in einem Befehl, Optionen und Ausgabe.
.ref-venv/ und out/ sind dort gitignored.
Laufzeit-Unterschiede zählen erst ab Faktor 1,5 und 2 s.
Ausgangspunkt waren die Prototypen der Sitzung zu #231 (run.py, check2.py, mu1.py, mu2.py, proto*.py); sie sind auf alle Formate verallgemeinert.
Erster Lauf über das ganze Korpus. Die Grundlinie zeigt den Stand der Filter von 10.1.0-beta.1: Sie sind seit a829560 unter tools/chemenu/filters/ und commands/raw/ unverändert. Gemessen wurde im Checkout von 10.1.0-beta.3 (Stack c439dc6 vor dem Publish, Korpus c4965e6). Die Zusammenfassung je Format steht in #231 § Ausgangslage.
Doku:docs/dev/development.md nennt die Anweisung neben dem Konverter-Workflow; die README des privaten Repos nennt harness/compare/ und harness/baseline.json.
Akzeptanzkriterien
instructions/dev/converter-comparison.md existiert, besteht instructions verify und ist aus stack-mode.md und testing-conventions.md verlinkt. (d393e2f, Wortlaut berichtigt in 01360e9)
Das Harness unter harness/compare/ erzeugt für jede Korpusdatei jedes Formats mit Filter einen Bericht mit den Maßen 1, 2, 4–7. Für PDF, DOCX, PPTX und XLSX läuft mindestens ein Referenzwerkzeug. (31 Dateien: 17 PDF, 2 DOCX, 3 PPTX, 3 XLSX, 3 MSG, 3 EML; Referenz für alle außer EML.)
Ein Lauf ohne Änderung gegen die eigene Grundlinie meldet keinen Unterschied (Wiederholbarkeit). (Lauf 3: „No difference.“)
Der erste Lauf ist durchgeführt; Grundlinie im privaten Repo, Zusammenfassung je Format in #231. (Grundlinie 916a718; #231 § Ausgangslage.)
Kein Referenzwerkzeug steht in tools/requirements.txt oder landet in tools/.venv. (import von pymupdf, fitz, pymupdf4llm, markitdown, pypandoc, openpyxl und pptx scheitert in tools/.venv; requirements.txt unverändert.)
pytest, docs verify, instructions verify grün; CI auf dem veröffentlichten Commit grün. (Lokal: pytest 3064 bestanden, 4 übersprungen; docs verify und instructions verify OK. CI 708, 709 und converters 710 grün; nach dem Nachzug 711, 712 grün.)
Versionsteil
Patch im laufenden Kandidaten (Kandidatenzähler): instructions/ liegt im Version-Gate. Drop-in: instructions/dev/ geht mit dist export nicht in eine Instanz. Gehoben auf 10.1.0-beta.3, mit dem Nachzug auf 10.1.0-beta.4.
Aus #231 (Betreiber, 2026-10-14): Der Vergleich, den die Sitzung zu #225/#231 von Hand gemacht hat – eigene Ableitung gegen pymupdf4llm/MuPDF am realen Korpus, gemessen in Mehrlänge, falscher und fehlender Auszeichnung, Struktur und Laufzeit –, soll **immer wieder** durchgeführt werden, als `instructions/dev`-Anweisung. **Generalisiert für alle Nicht-Text-Quellen:** DOCX, PPTX und XLSX können ähnliche Effekte zeigen (Tabellenschattierung, Folienflächen, Farbe als Gestaltung).
## Stand: abgeschlossen
- **Stack, Commit `d393e2f`** (Kandidat `10.1.0-beta.3`): die Anweisung, ihre Verweise und der Absatz in `docs/dev/development.md`.
- **Nachzug beim Abschluss, Commit `01360e9`** (`10.1.0-beta.4`): Die Anweisung nennt `harness/compare/README.md` als Ort der Einrichtung. Vorher schrieb Schritt 1 fälschlich „die README des privaten Repos“.
- **Privates Repo `torben/chemenu-testfiles`, Commit `916a718`:** Harness `harness/compare/` und Grundlinie `harness/baseline.json`, mit Freigabe des Betreibers direkt per `git push` dort.
**Verifiziert durch:**
- `d393e2f`: CI-Läufe 708 und 709 grün.
- `converters.yml` Lauf 710, von Hand per `workflow_dispatch` auf `main` gestartet, weil sich nur das private Repo geändert hatte: grün. Er lud das private Repo auf `916a718` und meldete 46 bestanden (33 Korpus-Tests und 13 aus `test_compare.py`).
- `01360e9`: CI-Läufe 711 und 712 grün.
- Lokal: pytest mit 3064 bestanden und 4 übersprungen; `docs verify` und `instructions verify` OK.
**Drei volle Läufe über das ganze Korpus** (31 Dateien):
- Lauf 1 war der erste Durchgang. Seine Laufzeiten sind durch parallel laufendes pytest verfälscht; er diente nur zum Prüfen.
- Lauf 2 lief ungestört und hat die Grundlinie geschrieben.
- Lauf 3 lief ohne Änderung gegen diese Grundlinie: **kein Unterschied**.
Ein voller Lauf dauert etwa 15–20 min, davon pymupdf4llm allein rund 440 s.
## Warum eine Anweisung und nicht nur ein Test
Die Korpus-Tests (#232) prüfen, ob eine Ableitung gelingt, stabil ist und erwartete Texte enthält. Ob sie **gut** ist, prüfen sie nicht: ob eine Auszeichnung stimmt, ob Lärm entsteht, ob ein verfügbares Werkzeug es besser kann. Das braucht ein Urteil am Original und lässt sich nur teilweise als Zahl fassen. #225 hat gezeigt, was ohne diesen Schritt passiert: Erst am echten Korpus fielen 190 falsche Durchstreichungen und 24 % Mehrlänge auf.
## Umsetzung
1. **Anweisung `instructions/dev/converter-comparison.md`** (Typ `types/instruction.md`), verlinkt aus `stack-mode.md` § Where the procedures are und aus `testing-conventions.md` § Scope. Inhalt:
- **Wann:** vor dem Entwurf einer Konverter-Änderung (Ausgangslage messen), nach dem Bau vor dem Publish (Unterschied messen), wenn eine neue Datei ins Korpus kommt, und wenn ein Format neue Effekte zeigt.
- **Was:** jedes Format mit Filter: PDF, DOCX, PPTX, XLSX/XLSM, EML/MSG, HTML. ZIP ist nur ein Behälter und wird übersprungen. Im Korpus gibt es derzeit kein HTML und kein XLSM.
- **Referenzwerkzeuge je Format** als Tabelle mit Rolle; die Versionen stehen voll gepinnt in `harness/compare/requirements-reference.txt`.
- PDF → pymupdf4llm 1.28.2
- DOCX → markitdown 0.1.8, pandoc 3.9 (über `pypandoc_binary`, kein System-Pandoc nötig)
- PPTX, XLSX, MSG → markitdown
- HTML → markitdown, pandoc
- EML → keins
- Docling nur von Hand nach Bedarf.
- **Orakel je Format**, das die Datei direkt liest:
- PDF: MuPDF-Stil-Flags (`TEXT_COLLECT_STYLES`)
- DOCX: die `document.xml` (Änderungen, Kommentare, Run-Formatierung)
- PPTX: python-pptx (Notizen)
- XLSX: openpyxl (ausgeblendete Blätter, Formeln)
- **Maße je Datei** (wie gebaut):
1. Wortlaut-Treue: Bei PDF ist der Text ohne Auszeichnung derselbe wie die Ableitung ohne Layoutanalyse (`pdf_layout.analyse` im Harness auf leer gesetzt, also `pypdf` allein). Die anderen Formate haben keinen getrennten Stil-Durchgang; dort ist Maß 1 die Wort-Übereinstimmung mit jeder Referenz (Recall/Präzision über Wörter mit Vielfachheit). Das wurde beim Bau festgelegt, weil der Body für diese Formate keinen Vergleichstext nannte.
2. Kontext-Mehrlänge: Auszeichnungszeichen / Textzeichen; bei PDF genau das, was die Layoutanalyse hinzufügt, einschließlich Legende.
3. Präzision: Stichprobe der Auszeichnungen (`samples.md`) gegen das Original, per Seitenbild (`--render`, PDF). Sitzungsarbeit.
4. Fehlende Semantik gegenüber Referenz und Orakel: Durchstreichung, Textmarker, fett/kursiv; bei DOCX Änderungsverfolgung und Kommentare, bei XLSX ausgeblendete Blätter und Formeln, bei PPTX Notizen.
5. Struktur: Überschriften, Gliederung (Eintrag trifft Seitenmarke), Tabellenzeilen, Listen, Codeblöcke.
6. CHECK-Präzision: die vom Bild-CHECK genannten Seiten gegen die Seiten mit **inhaltlichem** Bild. Nicht inhaltlich ist:
- ein Hintergrund (> 80 % der Seite),
- ein Füllbild (Quelle ≤ 4 px oder gezeichnet < 10 pt),
- ein Vorlagenbild (dasselbe Bild auf ≥ 20 % der Seiten, mindestens 3).
Die Kriterien stammen aus #231 Punkt 6, hier unabhängig über MuPDF umgesetzt. Dazu kommen die gedrehten Seiten, sowohl über `/Rotate` als auch über seitwärts laufenden Text.
Beim Bau ergänzt: Der erste Lauf verglich nur mit „Seite hat irgendein Bild“, und das ist trivial immer erfüllt. Gegenprobe: Für IHF liefert das Orakel genau {1, 2, 6–8, 29, 48–55, 81, 96}, also die Seiten, die #231 von Hand bestimmt hat. Die gedrehten Seiten von Girokonten (7–13) erkennt nur das Text-Signal; `/Rotate` meldet dort keine.
7. Laufzeit.
- **Präzision vor Trefferquote:** Falsche Auszeichnung wiegt schwerer als fehlende.
- **Ausgang:**
- Ein Bericht mit den Maßen je Datei und dem Unterschied zur letzten Grundlinie.
- Die Grundlinie (`harness/baseline.json` im privaten Repo) wird nur bewusst fortgeschrieben (`--write-baseline`), mit Stack-Version und Begründung im Commit.
- Befunde gehen in den Body des Issues, an dem gearbeitet wird, oder in das Issue des Themas.
- Eine Schwelle wird nie ohne Korpuslauf geändert.
- Was vom Korpus in ein Issue darf, regelt weiterhin `dev-setup.md` Schritt 6; die Anweisung verweist darauf.
2. **Vergleichs-Harness im privaten Repo unter `harness/compare/`:**
- `compare.py` läuft mit `tools/.venv` des Checkouts und misst also dessen Filter.
- `reference.py` läuft in `harness/compare/.ref-venv`, als eigener Prozess je Datei.
- `metrics.py` nutzt nur die Standardbibliothek.
- `test_compare.py` enthält 13 Tests der Maße; sie laufen im `converters`-Workflow mit und brauchen keine Referenz-Umgebung.
- `README.md` beschreibt Einrichtung in einem Befehl, Optionen und Ausgabe.
- `.ref-venv/` und `out/` sind dort gitignored.
- Laufzeit-Unterschiede zählen erst ab Faktor 1,5 und 2 s.
- Ausgangspunkt waren die Prototypen der Sitzung zu #231 (`run.py`, `check2.py`, `mu1.py`, `mu2.py`, `proto*.py`); sie sind auf alle Formate verallgemeinert.
3. **Erster Lauf** über das ganze Korpus. Die Grundlinie zeigt den Stand der Filter von 10.1.0-beta.1: Sie sind seit `a829560` unter `tools/chemenu/filters/` und `commands/raw/` unverändert. Gemessen wurde im Checkout von 10.1.0-beta.3 (Stack `c439dc6` vor dem Publish, Korpus `c4965e6`). Die Zusammenfassung je Format steht in #231 § Ausgangslage.
4. **Doku:** `docs/dev/development.md` nennt die Anweisung neben dem Konverter-Workflow; die README des privaten Repos nennt `harness/compare/` und `harness/baseline.json`.
## Akzeptanzkriterien
- [x] `instructions/dev/converter-comparison.md` existiert, besteht `instructions verify` und ist aus `stack-mode.md` und `testing-conventions.md` verlinkt. (`d393e2f`, Wortlaut berichtigt in `01360e9`)
- [x] Das Harness unter `harness/compare/` erzeugt für jede Korpusdatei jedes Formats mit Filter einen Bericht mit den Maßen 1, 2, 4–7. Für PDF, DOCX, PPTX und XLSX läuft mindestens ein Referenzwerkzeug. (31 Dateien: 17 PDF, 2 DOCX, 3 PPTX, 3 XLSX, 3 MSG, 3 EML; Referenz für alle außer EML.)
- [x] Ein Lauf ohne Änderung gegen die eigene Grundlinie meldet keinen Unterschied (Wiederholbarkeit). (Lauf 3: „No difference.“)
- [x] Der erste Lauf ist durchgeführt; Grundlinie im privaten Repo, Zusammenfassung je Format in #231. (Grundlinie `916a718`; #231 § Ausgangslage.)
- [x] Kein Referenzwerkzeug steht in `tools/requirements.txt` oder landet in `tools/.venv`. (`import` von pymupdf, fitz, pymupdf4llm, markitdown, pypandoc, openpyxl und pptx scheitert in `tools/.venv`; `requirements.txt` unverändert.)
- [x] `pytest`, `docs verify`, `instructions verify` grün; CI auf dem veröffentlichten Commit grün. (Lokal: pytest 3064 bestanden, 4 übersprungen; `docs verify` und `instructions verify` OK. CI 708, 709 und `converters` 710 grün; nach dem Nachzug 711, 712 grün.)
## Versionsteil
Patch im laufenden Kandidaten (Kandidatenzähler): `instructions/` liegt im Version-Gate. Drop-in: `instructions/dev/` geht mit `dist export` nicht in eine Instanz. Gehoben auf `10.1.0-beta.3`, mit dem Nachzug auf `10.1.0-beta.4`.
## Kette
Kette „Konverter-Qualität“
- Vorgänger: #232
- Nachfolger: #231
#232 ist geschlossen: Das private Repo torben/chemenu-testfiles mit corpus/ und harness/ steht, converters.yml läuft (zuletzt Lauf 707 grün). Damit ist der einzige Blocker weg; status/blocked entfernt. Für das Harness unter harness/compare/: Es läuft wie harness/ mit cd tools && .venv/bin/python -m pytest -c pytest.ini ../testfiles/harness; Referenzwerkzeuge gehören laut Body nicht in tools/.venv.
#232 ist geschlossen: Das private Repo `torben/chemenu-testfiles` mit `corpus/` und `harness/` steht, `converters.yml` läuft (zuletzt Lauf 707 grün). Damit ist der einzige Blocker weg; `status/blocked` entfernt. Für das Harness unter `harness/compare/`: Es läuft wie `harness/` mit `cd tools && .venv/bin/python -m pytest -c pytest.ini ../testfiles/harness`; Referenzwerkzeuge gehören laut Body nicht in `tools/.venv`.
Changelog: Gebaut und veröffentlicht. Stack d393e2f (10.1.0-beta.3) mit der Anweisung, den Verweisen und dem Doku-Absatz; im privaten Repo 916a718 mit Harness und Grundlinie. Alle Kriterien erfüllt: CI 708, 709 und converters 710 grün, der Wiederholungslauf zeigt keinen Unterschied. Zusammenfassung je Format in #231. Beim Bau festgelegt und im Body vermerkt: Maß 1 ist für Nicht-PDF-Formate die Wort-Übereinstimmung mit der Referenz. Maß 6 vergleicht gegen Seiten mit inhaltlichem Bild nach den Kriterien von #231 und erkennt gedrehte Seiten auch über seitwärts laufenden Text. Orakel je Format ergänzt. „Blockiert durch“ entfernt, #232 ist geschlossen.
**Changelog:** Gebaut und veröffentlicht. Stack `d393e2f` (10.1.0-beta.3) mit der Anweisung, den Verweisen und dem Doku-Absatz; im privaten Repo `916a718` mit Harness und Grundlinie. Alle Kriterien erfüllt: CI 708, 709 und `converters` 710 grün, der Wiederholungslauf zeigt keinen Unterschied. Zusammenfassung je Format in #231. Beim Bau festgelegt und im Body vermerkt: Maß 1 ist für Nicht-PDF-Formate die Wort-Übereinstimmung mit der Referenz. Maß 6 vergleicht gegen Seiten mit inhaltlichem Bild nach den Kriterien von #231 und erkennt gedrehte Seiten auch über seitwärts laufenden Text. Orakel je Format ergänzt. „Blockiert durch“ entfernt, #232 ist geschlossen.
Changelog: Abschluss. Die Anweisung schrieb in Schritt 1 fälschlich „die README des privaten Repos“; sie nennt jetzt harness/compare/README.md (Nachzug 01360e9, 10.1.0-beta.4, CI 711 und 712 grün). Sonst ist kein Dokument veraltet: docs/dev/development.md, stack-mode.md und testing-conventions.md beschreiben, was gebaut ist. Body im Endzustand, geschlossen.
**Changelog:** Abschluss. Die Anweisung schrieb in Schritt 1 fälschlich „die README des privaten Repos“; sie nennt jetzt `harness/compare/README.md` (Nachzug `01360e9`, 10.1.0-beta.4, CI 711 und 712 grün). Sonst ist kein Dokument veraltet: `docs/dev/development.md`, `stack-mode.md` und `testing-conventions.md` beschreiben, was gebaut ist. Body im Endzustand, geschlossen.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Aus #231 (Betreiber, 2026-10-14): Der Vergleich, den die Sitzung zu #225/#231 von Hand gemacht hat – eigene Ableitung gegen pymupdf4llm/MuPDF am realen Korpus, gemessen in Mehrlänge, falscher und fehlender Auszeichnung, Struktur und Laufzeit –, soll immer wieder durchgeführt werden, als
instructions/dev-Anweisung. Generalisiert für alle Nicht-Text-Quellen: DOCX, PPTX und XLSX können ähnliche Effekte zeigen (Tabellenschattierung, Folienflächen, Farbe als Gestaltung).Stand: abgeschlossen
d393e2f(Kandidat10.1.0-beta.3): die Anweisung, ihre Verweise und der Absatz indocs/dev/development.md.01360e9(10.1.0-beta.4): Die Anweisung nenntharness/compare/README.mdals Ort der Einrichtung. Vorher schrieb Schritt 1 fälschlich „die README des privaten Repos“.torben/chemenu-testfiles, Commit916a718: Harnessharness/compare/und Grundlinieharness/baseline.json, mit Freigabe des Betreibers direkt pergit pushdort.Verifiziert durch:
d393e2f: CI-Läufe 708 und 709 grün.converters.ymlLauf 710, von Hand perworkflow_dispatchaufmaingestartet, weil sich nur das private Repo geändert hatte: grün. Er lud das private Repo auf916a718und meldete 46 bestanden (33 Korpus-Tests und 13 austest_compare.py).01360e9: CI-Läufe 711 und 712 grün.docs verifyundinstructions verifyOK.Drei volle Läufe über das ganze Korpus (31 Dateien):
Ein voller Lauf dauert etwa 15–20 min, davon pymupdf4llm allein rund 440 s.
Warum eine Anweisung und nicht nur ein Test
Die Korpus-Tests (#232) prüfen, ob eine Ableitung gelingt, stabil ist und erwartete Texte enthält. Ob sie gut ist, prüfen sie nicht: ob eine Auszeichnung stimmt, ob Lärm entsteht, ob ein verfügbares Werkzeug es besser kann. Das braucht ein Urteil am Original und lässt sich nur teilweise als Zahl fassen. #225 hat gezeigt, was ohne diesen Schritt passiert: Erst am echten Korpus fielen 190 falsche Durchstreichungen und 24 % Mehrlänge auf.
Umsetzung
instructions/dev/converter-comparison.md(Typtypes/instruction.md), verlinkt ausstack-mode.md§ Where the procedures are und austesting-conventions.md§ Scope. Inhalt:harness/compare/requirements-reference.txt.pypandoc_binary, kein System-Pandoc nötig)TEXT_COLLECT_STYLES)document.xml(Änderungen, Kommentare, Run-Formatierung)Wortlaut-Treue: Bei PDF ist der Text ohne Auszeichnung derselbe wie die Ableitung ohne Layoutanalyse (
pdf_layout.analyseim Harness auf leer gesetzt, alsopypdfallein). Die anderen Formate haben keinen getrennten Stil-Durchgang; dort ist Maß 1 die Wort-Übereinstimmung mit jeder Referenz (Recall/Präzision über Wörter mit Vielfachheit). Das wurde beim Bau festgelegt, weil der Body für diese Formate keinen Vergleichstext nannte.Kontext-Mehrlänge: Auszeichnungszeichen / Textzeichen; bei PDF genau das, was die Layoutanalyse hinzufügt, einschließlich Legende.
Präzision: Stichprobe der Auszeichnungen (
samples.md) gegen das Original, per Seitenbild (--render, PDF). Sitzungsarbeit.Fehlende Semantik gegenüber Referenz und Orakel: Durchstreichung, Textmarker, fett/kursiv; bei DOCX Änderungsverfolgung und Kommentare, bei XLSX ausgeblendete Blätter und Formeln, bei PPTX Notizen.
Struktur: Überschriften, Gliederung (Eintrag trifft Seitenmarke), Tabellenzeilen, Listen, Codeblöcke.
CHECK-Präzision: die vom Bild-CHECK genannten Seiten gegen die Seiten mit inhaltlichem Bild. Nicht inhaltlich ist:
Die Kriterien stammen aus #231 Punkt 6, hier unabhängig über MuPDF umgesetzt. Dazu kommen die gedrehten Seiten, sowohl über
/Rotateals auch über seitwärts laufenden Text.Beim Bau ergänzt: Der erste Lauf verglich nur mit „Seite hat irgendein Bild“, und das ist trivial immer erfüllt. Gegenprobe: Für IHF liefert das Orakel genau {1, 2, 6–8, 29, 48–55, 81, 96}, also die Seiten, die #231 von Hand bestimmt hat. Die gedrehten Seiten von Girokonten (7–13) erkennt nur das Text-Signal;
/Rotatemeldet dort keine.Laufzeit.
harness/baseline.jsonim privaten Repo) wird nur bewusst fortgeschrieben (--write-baseline), mit Stack-Version und Begründung im Commit.dev-setup.mdSchritt 6; die Anweisung verweist darauf.harness/compare/:compare.pyläuft mittools/.venvdes Checkouts und misst also dessen Filter.reference.pyläuft inharness/compare/.ref-venv, als eigener Prozess je Datei.metrics.pynutzt nur die Standardbibliothek.test_compare.pyenthält 13 Tests der Maße; sie laufen imconverters-Workflow mit und brauchen keine Referenz-Umgebung.README.mdbeschreibt Einrichtung in einem Befehl, Optionen und Ausgabe..ref-venv/undout/sind dort gitignored.run.py,check2.py,mu1.py,mu2.py,proto*.py); sie sind auf alle Formate verallgemeinert.a829560untertools/chemenu/filters/undcommands/raw/unverändert. Gemessen wurde im Checkout von 10.1.0-beta.3 (Stackc439dc6vor dem Publish, Korpusc4965e6). Die Zusammenfassung je Format steht in #231 § Ausgangslage.docs/dev/development.mdnennt die Anweisung neben dem Konverter-Workflow; die README des privaten Repos nenntharness/compare/undharness/baseline.json.Akzeptanzkriterien
instructions/dev/converter-comparison.mdexistiert, bestehtinstructions verifyund ist ausstack-mode.mdundtesting-conventions.mdverlinkt. (d393e2f, Wortlaut berichtigt in01360e9)harness/compare/erzeugt für jede Korpusdatei jedes Formats mit Filter einen Bericht mit den Maßen 1, 2, 4–7. Für PDF, DOCX, PPTX und XLSX läuft mindestens ein Referenzwerkzeug. (31 Dateien: 17 PDF, 2 DOCX, 3 PPTX, 3 XLSX, 3 MSG, 3 EML; Referenz für alle außer EML.)916a718; #231 § Ausgangslage.)tools/requirements.txtoder landet intools/.venv. (importvon pymupdf, fitz, pymupdf4llm, markitdown, pypandoc, openpyxl und pptx scheitert intools/.venv;requirements.txtunverändert.)pytest,docs verify,instructions verifygrün; CI auf dem veröffentlichten Commit grün. (Lokal: pytest 3064 bestanden, 4 übersprungen;docs verifyundinstructions verifyOK. CI 708, 709 undconverters710 grün; nach dem Nachzug 711, 712 grün.)Versionsteil
Patch im laufenden Kandidaten (Kandidatenzähler):
instructions/liegt im Version-Gate. Drop-in:instructions/dev/geht mitdist exportnicht in eine Instanz. Gehoben auf10.1.0-beta.3, mit dem Nachzug auf10.1.0-beta.4.Kette
Kette „Konverter-Qualität“
#232 ist geschlossen: Das private Repo
torben/chemenu-testfilesmitcorpus/undharness/steht,converters.ymlläuft (zuletzt Lauf 707 grün). Damit ist der einzige Blocker weg;status/blockedentfernt. Für das Harness unterharness/compare/: Es läuft wieharness/mitcd tools && .venv/bin/python -m pytest -c pytest.ini ../testfiles/harness; Referenzwerkzeuge gehören laut Body nicht intools/.venv.Changelog: Gebaut und veröffentlicht. Stack
d393e2f(10.1.0-beta.3) mit der Anweisung, den Verweisen und dem Doku-Absatz; im privaten Repo916a718mit Harness und Grundlinie. Alle Kriterien erfüllt: CI 708, 709 undconverters710 grün, der Wiederholungslauf zeigt keinen Unterschied. Zusammenfassung je Format in #231. Beim Bau festgelegt und im Body vermerkt: Maß 1 ist für Nicht-PDF-Formate die Wort-Übereinstimmung mit der Referenz. Maß 6 vergleicht gegen Seiten mit inhaltlichem Bild nach den Kriterien von #231 und erkennt gedrehte Seiten auch über seitwärts laufenden Text. Orakel je Format ergänzt. „Blockiert durch“ entfernt, #232 ist geschlossen.Changelog: Abschluss. Die Anweisung schrieb in Schritt 1 fälschlich „die README des privaten Repos“; sie nennt jetzt
harness/compare/README.md(Nachzug01360e9, 10.1.0-beta.4, CI 711 und 712 grün). Sonst ist kein Dokument veraltet:docs/dev/development.md,stack-mode.mdundtesting-conventions.mdbeschreiben, was gebaut ist. Body im Endzustand, geschlossen.