testfiles: Abnahme von raw derive mit echten Dokumenten, inkl. XLSX-Formelfall #203

Closed
opened 2026-10-09 12:39:17 +00:00 by torben · 4 comments
Owner

Aus #202 abgespalten (dort das letzte Akzeptanzkriterium), damit #202 schließen konnte. Stand 2026-10-09: Der Betreiber hatte Dateien in den Arbeitsbaum gelegt; die ursprüngliche Fassung dieses Bodys (u. a. „zip/ leer“, fünf Office-Dateien) stimmte nicht mehr und wurde gegen den Baum geprüft. Gebaut und publiziert (2026-10-09): Dateien bereinigt und umbenannt, Test erweitert, README ergänzt, Version 9.0.0-beta.19, Commit be049217a9ecf7d71123169dca9a8422d26ed95e auf main. CI grün: Läufe 630 (verify) und 631 (pwsh) auf diesem Commit, beide success. Abgeschlossen 2026-10-09; die eine Beobachtung, die über dieses Issue hinausgeht, ist #204.

Worum es ging

testfiles/ (eingeführt mit 9.0.0-beta.18) hält echte Dokumente, die CI durch raw derive schickt. tools/chemenu/tests/test_raw_derive_testfiles.py prüft je Datei: Es gibt einen Filter, die Ableitung gelingt, das Original kommt byte-genau zurück, ein zweiter Lauf ergibt denselben Text (außer derived:), raw accept nimmt den Ordner an, und optionale <datei>.expect-Zeilen kommen im abgeleiteten Text vor. Regeln: testfiles/README.md.

Gebaut wurde: die Dateien bereinigen, umbenennen und committen, die Testlücke bei den Blatt-TSVs schließen und den Formelfall mit einer .expect-Zeile belegen.

Befund vor dem Build (2026-10-09, gegen den Baum geprüft)

Lokal grün: tools/.venv/bin/python -m pytest chemenu/tests/test_raw_derive_testfiles.py → 20 passed (40 s) für alle Dateien unten. Es gab keinen Fehler einer Ableitung zu beheben; offen war, was committet werden darf, und die Testlücke.

Dateien, damals untracked (Größen gerundet):

Ordner Inhalt
mail/ je ein Newsletter von GitHub, GOG, TLDR als .eml (Roundcube, 26–57 KB) und .msg (Outlook, 125–159 KB)
office/ 3 .xlsx (Business, künstlich, wissenschaftlich; 42 KB / 33 KB / 778 KB), 2 .docx (einfach 25 KB, komplex 522 KB), 3 .pptx (Baseline, Master-Test, Objekttest; 30–52 KB)
pdf/ Einstein-Dissertation (593 KB), Informationsfreiheitsgesetz (57 KB), NIST AI 600-1 (1,2 MB), NIST SP 800-218A (651 KB), Pelletskaminofen-Datenblatt (8,5 MB, nicht committet, s. Entscheidung 8)
zip/ Archive.zip (188 KB): enthielt Kopien von Excel Business.xlsx, Github (via Outlook).msg, Informationsfreiheistgesetz.pdf, Master-Test.pptx, Testdokument … (einfach).docx, TLDR Product (via Roundcube).eml

Persönliche Daten (Scan über UTF-8 und UTF-16LE, Inhalte von docx/xlsx/pptx/zip entpackt):

  • Alle sechs Mails: Mailadresse und Hostdomain des Betreibers in Delivered-To:, Received:, Empfängeradresse; in den .msg zusätzlich in den Adressfeldern (SMTP:…, auch groß geschrieben) und als Anzeigename in UTF-16. TLDR … .msg trug die Adresse außerdem in einem Verwaltungslink (…manage?email=…). Nicht per Namensscan findbar: Links mit empfängerbezogenem Token (Abmelden, Einstellungen, Tracking-Pixel). Solche Links können im öffentlichen Repo das Konto des Betreibers beim Absender ansprechen; sie gehörten zum Befund, auch wenn kein Name darin stand.
  • Alle acht Office-Dateien: Vor- und Nachname in docProps/core.xml (dc:creator, cp:lastModifiedBy). app.xml ist leer (kein Company/Manager).
  • Excel wissenschaftlich.xlsx: zusätzlich eine Zelle (xl/sharedStrings.xml) mit der Repo-URL des Betreibers.
  • Archive.zip: die darin liegenden Kopien trugen dieselben Treffer.
  • PDFs: kein Treffer auf den Betreiber. NIST SP 800-218A hat im /Author den Namen des Dokumentautors (Bundesbehörde, Teil des veröffentlichten Werks); das Pelletskaminofen-PDF den Namen einer Person des Herstellers, es fiel weg.

Lizenz (Einschätzung, keine Rechtsberatung; die Bestätigung ist die des Betreibers, Entscheidungen unten):

Datei(en) Einschätzung
NIST AI 600-1, NIST SP 800-218A Werk der US-Bundesregierung, gemeinfrei
Informationsfreiheitsgesetz amtliches Werk (§ 5 UrhG), frei
Einstein-Dissertation (1905) Werk gemeinfrei; Scan aus einem Web-Download, Nutzungsbedingungen des Digitalisierers nicht geprüft
Newsletter GitHub, GOG, TLDR fremde Inhalte (Werbe-/Informationsmails), vom Betreiber als Testfixtures freigegeben
Office-Dateien, Archive.zip Eigenbau des Betreibers

Dateinamen hatten Leerzeichen, Umlaute, Klammern und einen Tippfehler (Informationsfreiheistgesetz); testfiles/README.md verlangt kurze Namen ohne Leerzeichen.

Testlücke seit #202 (geschlossen): _texts() las nur *.md. Die Blatt-TSVs in <stem>.sheets/ (NN-<blatt>.tsv, NN-<blatt>.formulas.tsv) fielen aus Stabilitätsvergleich und .expect-Suche heraus. Formeln gibt es in allen drei echten Arbeitsmappen (Business 431, künstlich 143, wissenschaftlich 3108 <f>-Zellen).

Entschieden

Vom Betreiber (2026-10-09):

  1. Pelletskaminofen-Datenblatt: gestrichen. Nicht committet; aus dem Repo-Verzeichnis herausgenommen (verschoben, nicht gelöscht; Standardziel ~/testfiles-aside/). Verbleibende Größe ca. 4,6 MB.
  2. Newsletter: alle sechs bleiben, bereinigt nach Entscheidung 2. Der Betreiber gibt die Weitergabe als Testfixtures frei.
  3. Einstein-Dissertation bleibt. Herkunft laut Betreiber: Web-Download, über Perplexity identifiziert; behalten wegen der Scans (OCR-Abdeckung). Die README-Tabelle (Entscheidung 6) sagt das genau so: gemeinfreies Werk (1905), Scan aus Web-Download, Nutzungsbedingungen des Digitalisierers nicht geprüft, vom Betreiber bewusst behalten – nicht mehr behaupten, als bekannt ist.
  4. Eigenbau-Dateien (office/, archive.zip): Weitergabe vom Betreiber bestätigt.

Aus der Entwurfssitzung:

  1. Namen: Vor dem ersten Commit wurden alle Dateien auf kurze ASCII-Namen in Kleinbuchstaben mit Bindestrich umbenannt: mail/{github,gog,tldr}-outlook.msg und -roundcube.eml; office/excel-business.xlsx, excel-artificial.xlsx, excel-science.xlsx, word-simple.docx, word-complex.docx, pptx-baseline.pptx, pptx-master.pptx, pptx-objects.pptx; pdf/einstein-dissertation.pdf, ifg.pdf, nist-ai-rmf.pdf, nist-ssdf-genai.pdf; zip/archive.zip. Die Frage, ob Leerzeichen und Umlaute in Dateinamen sonst getestet sind, ist beantwortet, kein eigenes Issue nötig: test_raw_derive.py leitet Angebot XYZ.docx ab (Leerzeichen im Namen der Quelle, Zeile 244 ff.) und entpackt Übersicht Ä.txt und sub/Budget 2024.xlsx aus einem Zip (Zeilen 988 und 663).
  2. Bereinigung durch Ersetzen gleicher Länge, nicht durch Umbau. Mails: Adresse, Name, Hostdomain und empfängerbezogene Token wurden durch Füllzeichen derselben Byte- bzw. UTF-16-Länge ersetzt (jede Schreibweise: groß/klein, %40/%2540, Base64 in allen drei Ausrichtungen, quoted-printable über Zeilenumbrüche). Gleiche Länge hält die Streamgrößen im .msg (OLE) gültig und lässt .eml ohne Umkodierung. Office-Dateien: dc:creator und cp:lastModifiedBy in docProps/core.xml geleert, die Zelle mit der Repo-URL durch neutralen Text ersetzt; alle übrigen Zip-Einträge unverändert in derselben Reihenfolge zurückgeschrieben. archive.zip wurde neu aus den bereinigten, umbenannten Mitgliedern gebaut. Die Bereinigung war ein einmaliges Skript im Scratchpad, nicht Teil des Repos.
  3. Bereinigung ändert nur, was sie soll. Je Datei wurde vor und nach der Bereinigung abgeleitet; der abgeleitete Text (derived.md und Blatt-TSVs) unterscheidet sich nur in den ersetzten Zeichenketten.
  4. Test erweitert: _texts() nimmt zusätzlich *.sheets/*.tsv (relativ zum Ordner) auf, die TSVs unverändert, ohne den derived:-Filter. Damit umfassen Stabilitätsvergleich und .expect-Suche die TSVs. Dazu ein kleiner Test direkt auf _texts() (test_texts_covers_the_sheet_tsvs_beside_the_markdown, Ordner mit .md und x.sheets/01-a.tsv): die TSV ist im Ergebnis, und eine geänderte TSV-Zelle ändert das Ergebnis. Ein Test über echte Ableitungen kann das nicht erzeugen, weil zwei Läufe über dieselben Bytes denselben Text geben müssen.
  5. .expect-Nadel für den Formelfall: der Formeltext allein, nicht die Tab-getrennte Zeile – ein Tab im Sidecar überlebt Editoren schlecht. Die Nadel fehlt in derived.md und steht nur in einer .formulas.tsv; sonst bewiese sie nicht, dass die TSVs durchsucht werden.
  6. Quellen-Tabelle: testfiles/README.md hat je Datei bzw. Gruppe eine Zeile „Herkunft und Weitergabegrundlage“ (Lizenztabelle oben plus Entscheidung 10). Das ist die dauerhafte Form der Bestätigung des Betreibers. Dieselbe Änderung ergänzt „What goes in“: Autorennamen eines veröffentlichten Werks (NIST, Gesetzgeber) sind Teil des Werks und kein Verstoß gegen „keine realen Personen“; Links, die ein Konto ansprechen (Abmelden, Einstellungen, Tracking), zählen zu den persönlichen Daten.
  7. Kein dauerhafter Namens-Scan als Test. Ein Test, der den Namen des Betreibers als Verbotsliste trägt, schriebe genau die Zeichenkette ins Repo, die er fernhalten soll, und kennt Token nicht. Die Regel steht in der README; der Scan war einmalige Abnahme (Ergebnis unten).

Abweichung im Build (2026-10-09)

Der Entwurf kannte die Treffer nur aus dem Namensscan. Beim Bereinigen kamen weitere Kennungen hinzu, die dieselbe Regel (Entscheidung 2, Ersetzen gleicher Länge) abdeckt; kein Entwurfsbruch, aber der Umfang war größer als beschrieben:

  • eine zweite Mailadresse auf einer zweiten Domain des Betreibers in den .msg-Streams 5D0A/5D0B;
  • Exchange-DN und Empfänger-GUIDs (4023/4025/8011) sowie die CID-GUID (800B) samt binärem Zwilling; die Windows-Konto-SID (0E58/0E59) wurde auf eine Beispiel-SID gesetzt;
  • die interne IP und interne Hostnamen in den .eml-Kopfzeilen;
  • der GitHub-Empfänger-Login;
  • empfängergebundene Token in List-Unsubscribe-mailto, in Kopfzeilen (X-Entity-Ref-Id, X-EmailOctopus-List-Contact-Id) und in URLs (email_token, track, refer.tldr.tech/<code>, hub.sparklp.co/sub_*, Tracking-Pfade). Je Newsletter wurde der Tokenvorrat aus .eml und .msg vereinigt und überall wörtlich ersetzt.

Ersetzt wurde zeichenweise mit Erhalt der Schreibweise (klein → x, groß → X, Ziffer → 0). Mail-Ableitungen unterscheiden sich vorher/nachher nur in diesen Stellen und in original_name:.

Scan (einmalige Abnahme, Entscheidung 7): 19 Dateien, 0 Treffer. Gesucht wurde nach Vor- und Nachname, beiden Domains des Betreibers, den internen Hostnamen und dem internen IP-Präfix sowie nach allen 69 ursprünglichen Token als Literal. Schichten: UTF-8, UTF-16LE, Base64 (drei Ausrichtungen), quoted-printable (auch über Zeilenumbrüche und Soft Breaks), Header-Unfolding, %-Kodierung (zweifach), HTML-Entitäten, rekursiv in Zip und OLE (.msg), gzip-Streams und PDF-Flate-Streams.

Rest, bewusst belassen: öffentliche Namen und Adressen Dritter in den GitHub-/TLDR-/GOG-Mails (Absender, Releaseautor, Projekt); zufällige binäre Suchschlüssel im .msg.

Beobachtung beim Lesen der Ableitungen → #204: gog-roundcube.eml hat einen text/plain-Teil von 32 Zeichen („Plain text version not available“) neben 40 204 Zeichen HTML. Der Mailfilter bevorzugt text/plain, deshalb ist derived.md fast leer. Die .msg desselben Newsletters hat keinen Plaintext-Stream und bekommt den HTML-Text. msg.py hat dieselbe Vorrangregel. Das ist kein Fehler der Testdateien und wurde hier nicht gefixt; die Regelfrage ist #204 (kind/decision).

Version

version bump --patch, --impact low: geändert wurde unter tools/ nur eine Testdatei (test_raw_derive_testfiles.py), kein Verhalten, keine Schnittstelle, kein Schema. Drop-in in beide Richtungen: Eine Instanz, die tools/ darüberkopiert, überspringt den Test ohne testfiles/; nichts im Bestand muss migriert werden. testfiles/ selbst liegt außerhalb dessen, was dist export ausliefert. Ergebnis: 9.0.0-beta.19.

Beteiligte Dateien

tools/chemenu/tests/test_raw_derive_testfiles.py (_texts(), neuer Test), testfiles/README.md, testfiles/** (umbenannt, bereinigt, office/excel-business.xlsx.expect), CHANGES.md und VERSION über version bump. Ableitung gelesen: tools/chemenu/filters/ooxml.py (XLSX/TSV-Layout, nur gelesen).

Abschluss (2026-10-09)

Doku-Prüfung nach dem Publish: Außerhalb von testfiles/ nennt nur docs/dev/development.md (Zeile 43 f.) den Ordner, und die Aussage dort („committed, so CI derives them too … that README says what may go in“) stimmt weiter. Kein Contract, kein Kommando-Datensatz, keine Installationsanleitung und keine docs/explanation/-Seite wurde berührt oder ist veraltet. Der Changelog-Stichpunkt in 9.0.0-beta.19 stimmt mit dem Gebauten überein. Deshalb gab es keinen weiteren Doku-Durchgang, keine Version und keinen Publish in der Abschlussphase.

Akzeptanzkriterien

  • Alle Dateien unter testfiles/ haben die Namen aus Entscheidung 1; das Pelletskaminofen-PDF liegt nicht mehr im Repo-Verzeichnis (Entscheidung 8); archive.zip ist aus bereinigten Mitgliedern neu gebaut.
  • Scan sauber: Über jede committete Datei, rekursiv in docx/xlsx/pptx/zip, im Mail-Inhalt nach Dekodierung (quoted-printable, Base64, %-Kodierung) und in UTF-8 wie UTF-16LE, gibt es keinen Treffer auf Vor-/Nachname, Mailadresse oder Domain des Betreibers. In keiner Mail führt ein Link ein empfängerbezogenes Token (Abmelden, Einstellungen, Tracking-Pixel). (19 Dateien, 0 Treffer, Schichten oben.)
  • Der Vorher/Nachher-Vergleich aus Entscheidung 3 zeigt je Datei nur die ersetzten Zeichenketten als Unterschied; alle .msg öffnen mit olefile.
  • testfiles/README.md hat die Quellen-Tabelle (Entscheidung 6) für jede committete Datei und den ergänzten Abschnitt „What goes in“; „What the test checks“ nennt die Blatt-TSVs.
  • _texts() nimmt *.sheets/*.tsv auf; der Test auf _texts() (Entscheidung 4) besteht, und derselbe Test schlägt fehl, wenn _texts() auf *.md zurückgesetzt wird.
  • Mindestens eine echte XLSX hat eine .expect-Zeile mit einem Formeltext, der in einer ihrer .formulas.tsv vorkommt und in derived.md nicht (Entscheidung 5). Das erfüllt das aus #202 übernommene Kriterium. (office/excel-business.xlsx.expect: SUM(Sales!L6:L29).)
  • Jede Datei unter testfiles/ besteht test_raw_derive_testfiles.py lokal und in CI; jede Ableitung ist gelesen. Echte Fehler einer Ableitung werden eigene Issues und hier nicht nebenbei gefixt. (Lokal 20 passed, Ableitungen gelesen; CI-Läufe 630 und 631 auf be04921 grün. Die eine Beobachtung ist #204.)
  • pytest, docs verify und instructions verify grün; version bump --patch --impact low ausgeführt (9.0.0-beta.19); publish erreichte bei 24 Dateien das Mass-Update-Gate (Exit 42), der Betreiber gab frei; CI grün auf dem publizierten Commit be049217a9ecf7d71123169dca9a8422d26ed95e (Läufe 630 und 631).

Bezug

  • #202: XLSX zu TSV plus Formelliste (geschlossen; dieses Kriterium stammt von dort)
  • #199: raw derive (geschlossen)
  • #204: Platzhalter-Plaintext verdrängt HTML in den Mailfiltern (Folge-Issue aus der Beobachtung oben)
> Aus #202 abgespalten (dort das letzte Akzeptanzkriterium), damit #202 schließen konnte. Stand 2026-10-09: Der Betreiber hatte Dateien in den Arbeitsbaum gelegt; die ursprüngliche Fassung dieses Bodys (u. a. „zip/ leer“, fünf Office-Dateien) stimmte nicht mehr und wurde gegen den Baum geprüft. **Gebaut und publiziert (2026-10-09):** Dateien bereinigt und umbenannt, Test erweitert, README ergänzt, Version 9.0.0-beta.19, Commit `be049217a9ecf7d71123169dca9a8422d26ed95e` auf `main`. **CI grün:** Läufe 630 (verify) und 631 (pwsh) auf diesem Commit, beide `success`. **Abgeschlossen 2026-10-09**; die eine Beobachtung, die über dieses Issue hinausgeht, ist #204. ## Worum es ging `testfiles/` (eingeführt mit 9.0.0-beta.18) hält echte Dokumente, die CI durch `raw derive` schickt. `tools/chemenu/tests/test_raw_derive_testfiles.py` prüft je Datei: Es gibt einen Filter, die Ableitung gelingt, das Original kommt byte-genau zurück, ein zweiter Lauf ergibt denselben Text (außer `derived:`), `raw accept` nimmt den Ordner an, und optionale `<datei>.expect`-Zeilen kommen im abgeleiteten Text vor. Regeln: `testfiles/README.md`. Gebaut wurde: die Dateien bereinigen, umbenennen und committen, die Testlücke bei den Blatt-TSVs schließen und den Formelfall mit einer `.expect`-Zeile belegen. ## Befund vor dem Build (2026-10-09, gegen den Baum geprüft) **Lokal grün:** `tools/.venv/bin/python -m pytest chemenu/tests/test_raw_derive_testfiles.py` → 20 passed (40 s) für alle Dateien unten. Es gab keinen Fehler einer Ableitung zu beheben; offen war, was committet werden darf, und die Testlücke. **Dateien, damals untracked** (Größen gerundet): | Ordner | Inhalt | |---|---| | `mail/` | je ein Newsletter von GitHub, GOG, TLDR als `.eml` (Roundcube, 26–57 KB) und `.msg` (Outlook, 125–159 KB) | | `office/` | 3 `.xlsx` (Business, künstlich, wissenschaftlich; 42 KB / 33 KB / 778 KB), 2 `.docx` (einfach 25 KB, komplex 522 KB), 3 `.pptx` (Baseline, Master-Test, Objekttest; 30–52 KB) | | `pdf/` | Einstein-Dissertation (593 KB), Informationsfreiheitsgesetz (57 KB), NIST AI 600-1 (1,2 MB), NIST SP 800-218A (651 KB), Pelletskaminofen-Datenblatt (8,5 MB, **nicht committet**, s. Entscheidung 8) | | `zip/` | `Archive.zip` (188 KB): enthielt Kopien von `Excel Business.xlsx`, `Github (via Outlook).msg`, `Informationsfreiheistgesetz.pdf`, `Master-Test.pptx`, `Testdokument … (einfach).docx`, `TLDR Product (via Roundcube).eml` | **Persönliche Daten** (Scan über UTF-8 und UTF-16LE, Inhalte von docx/xlsx/pptx/zip entpackt): - **Alle sechs Mails:** Mailadresse und Hostdomain des Betreibers in `Delivered-To:`, `Received:`, Empfängeradresse; in den `.msg` zusätzlich in den Adressfeldern (`SMTP:…`, auch groß geschrieben) und als Anzeigename in UTF-16. `TLDR … .msg` trug die Adresse außerdem in einem Verwaltungslink (`…manage?email=…`). **Nicht per Namensscan findbar:** Links mit empfängerbezogenem Token (Abmelden, Einstellungen, Tracking-Pixel). Solche Links können im öffentlichen Repo das Konto des Betreibers beim Absender ansprechen; sie gehörten zum Befund, auch wenn kein Name darin stand. - **Alle acht Office-Dateien:** Vor- und Nachname in `docProps/core.xml` (`dc:creator`, `cp:lastModifiedBy`). `app.xml` ist leer (kein `Company`/`Manager`). - **`Excel wissenschaftlich.xlsx`:** zusätzlich eine Zelle (`xl/sharedStrings.xml`) mit der Repo-URL des Betreibers. - **`Archive.zip`:** die darin liegenden Kopien trugen dieselben Treffer. - **PDFs:** kein Treffer auf den Betreiber. NIST SP 800-218A hat im `/Author` den Namen des Dokumentautors (Bundesbehörde, Teil des veröffentlichten Werks); das Pelletskaminofen-PDF den Namen einer Person des Herstellers, es fiel weg. **Lizenz** (Einschätzung, keine Rechtsberatung; die Bestätigung ist die des Betreibers, Entscheidungen unten): | Datei(en) | Einschätzung | |---|---| | NIST AI 600-1, NIST SP 800-218A | Werk der US-Bundesregierung, gemeinfrei | | Informationsfreiheitsgesetz | amtliches Werk (§ 5 UrhG), frei | | Einstein-Dissertation (1905) | Werk gemeinfrei; Scan aus einem Web-Download, Nutzungsbedingungen des Digitalisierers nicht geprüft | | Newsletter GitHub, GOG, TLDR | fremde Inhalte (Werbe-/Informationsmails), vom Betreiber als Testfixtures freigegeben | | Office-Dateien, `Archive.zip` | Eigenbau des Betreibers | **Dateinamen** hatten Leerzeichen, Umlaute, Klammern und einen Tippfehler (`Informationsfreiheistgesetz`); `testfiles/README.md` verlangt kurze Namen ohne Leerzeichen. **Testlücke seit #202 (geschlossen):** `_texts()` las nur `*.md`. Die Blatt-TSVs in `<stem>.sheets/` (`NN-<blatt>.tsv`, `NN-<blatt>.formulas.tsv`) fielen aus Stabilitätsvergleich und `.expect`-Suche heraus. Formeln gibt es in allen drei echten Arbeitsmappen (Business 431, künstlich 143, wissenschaftlich 3108 `<f>`-Zellen). ## Entschieden **Vom Betreiber (2026-10-09):** 8. **Pelletskaminofen-Datenblatt: gestrichen.** Nicht committet; aus dem Repo-Verzeichnis herausgenommen (verschoben, nicht gelöscht; Standardziel `~/testfiles-aside/`). Verbleibende Größe ca. 4,6 MB. 9. **Newsletter: alle sechs bleiben**, bereinigt nach Entscheidung 2. Der Betreiber gibt die Weitergabe als Testfixtures frei. 10. **Einstein-Dissertation bleibt.** Herkunft laut Betreiber: Web-Download, über Perplexity identifiziert; behalten wegen der Scans (OCR-Abdeckung). Die README-Tabelle (Entscheidung 6) sagt das genau so: gemeinfreies Werk (1905), Scan aus Web-Download, Nutzungsbedingungen des Digitalisierers nicht geprüft, vom Betreiber bewusst behalten – nicht mehr behaupten, als bekannt ist. 11. **Eigenbau-Dateien** (`office/`, `archive.zip`): Weitergabe vom Betreiber bestätigt. **Aus der Entwurfssitzung:** 1. **Namen:** Vor dem ersten Commit wurden alle Dateien auf kurze ASCII-Namen in Kleinbuchstaben mit Bindestrich umbenannt: `mail/{github,gog,tldr}-outlook.msg` und `-roundcube.eml`; `office/excel-business.xlsx`, `excel-artificial.xlsx`, `excel-science.xlsx`, `word-simple.docx`, `word-complex.docx`, `pptx-baseline.pptx`, `pptx-master.pptx`, `pptx-objects.pptx`; `pdf/einstein-dissertation.pdf`, `ifg.pdf`, `nist-ai-rmf.pdf`, `nist-ssdf-genai.pdf`; `zip/archive.zip`. Die Frage, ob Leerzeichen und Umlaute in Dateinamen sonst getestet sind, ist beantwortet, **kein eigenes Issue nötig**: `test_raw_derive.py` leitet `Angebot XYZ.docx` ab (Leerzeichen im Namen der Quelle, Zeile 244 ff.) und entpackt `Übersicht Ä.txt` und `sub/Budget 2024.xlsx` aus einem Zip (Zeilen 988 und 663). 2. **Bereinigung durch Ersetzen gleicher Länge, nicht durch Umbau.** Mails: Adresse, Name, Hostdomain und empfängerbezogene Token wurden durch Füllzeichen **derselben Byte- bzw. UTF-16-Länge** ersetzt (jede Schreibweise: groß/klein, `%40`/`%2540`, Base64 in allen drei Ausrichtungen, quoted-printable über Zeilenumbrüche). Gleiche Länge hält die Streamgrößen im `.msg` (OLE) gültig und lässt `.eml` ohne Umkodierung. Office-Dateien: `dc:creator` und `cp:lastModifiedBy` in `docProps/core.xml` geleert, die Zelle mit der Repo-URL durch neutralen Text ersetzt; alle übrigen Zip-Einträge unverändert in derselben Reihenfolge zurückgeschrieben. `archive.zip` wurde **neu aus den bereinigten, umbenannten Mitgliedern gebaut**. Die Bereinigung war ein einmaliges Skript im Scratchpad, nicht Teil des Repos. 3. **Bereinigung ändert nur, was sie soll.** Je Datei wurde vor und nach der Bereinigung abgeleitet; der abgeleitete Text (`derived.md` und Blatt-TSVs) unterscheidet sich nur in den ersetzten Zeichenketten. 4. **Test erweitert:** `_texts()` nimmt zusätzlich `*.sheets/*.tsv` (relativ zum Ordner) auf, die TSVs unverändert, ohne den `derived:`-Filter. Damit umfassen Stabilitätsvergleich und `.expect`-Suche die TSVs. Dazu ein kleiner Test direkt auf `_texts()` (`test_texts_covers_the_sheet_tsvs_beside_the_markdown`, Ordner mit `.md` und `x.sheets/01-a.tsv`): die TSV ist im Ergebnis, und eine geänderte TSV-Zelle ändert das Ergebnis. Ein Test über echte Ableitungen kann das nicht erzeugen, weil zwei Läufe über dieselben Bytes denselben Text geben müssen. 5. **`.expect`-Nadel für den Formelfall:** der Formeltext allein, **nicht** die Tab-getrennte Zeile – ein Tab im Sidecar überlebt Editoren schlecht. Die Nadel fehlt in `derived.md` und steht nur in einer `.formulas.tsv`; sonst bewiese sie nicht, dass die TSVs durchsucht werden. 6. **Quellen-Tabelle:** `testfiles/README.md` hat je Datei bzw. Gruppe eine Zeile „Herkunft und Weitergabegrundlage“ (Lizenztabelle oben plus Entscheidung 10). Das ist die dauerhafte Form der Bestätigung des Betreibers. Dieselbe Änderung ergänzt „What goes in“: Autorennamen eines veröffentlichten Werks (NIST, Gesetzgeber) sind Teil des Werks und kein Verstoß gegen „keine realen Personen“; Links, die ein Konto ansprechen (Abmelden, Einstellungen, Tracking), zählen zu den persönlichen Daten. 7. **Kein dauerhafter Namens-Scan als Test.** Ein Test, der den Namen des Betreibers als Verbotsliste trägt, schriebe genau die Zeichenkette ins Repo, die er fernhalten soll, und kennt Token nicht. Die Regel steht in der README; der Scan war einmalige Abnahme (Ergebnis unten). ## Abweichung im Build (2026-10-09) Der Entwurf kannte die Treffer nur aus dem Namensscan. Beim Bereinigen kamen weitere Kennungen hinzu, die dieselbe Regel (Entscheidung 2, Ersetzen gleicher Länge) abdeckt; kein Entwurfsbruch, aber der Umfang war größer als beschrieben: - eine **zweite Mailadresse auf einer zweiten Domain** des Betreibers in den `.msg`-Streams `5D0A`/`5D0B`; - **Exchange-DN und Empfänger-GUIDs** (`4023`/`4025`/`8011`) sowie die CID-GUID (`800B`) samt binärem Zwilling; die Windows-Konto-SID (`0E58`/`0E59`) wurde auf eine Beispiel-SID gesetzt; - die **interne IP und interne Hostnamen** in den `.eml`-Kopfzeilen; - der **GitHub-Empfänger-Login**; - **empfängergebundene Token** in `List-Unsubscribe`-mailto, in Kopfzeilen (`X-Entity-Ref-Id`, `X-EmailOctopus-List-Contact-Id`) und in URLs (`email_token`, `track`, `refer.tldr.tech/<code>`, `hub.sparklp.co/sub_*`, Tracking-Pfade). Je Newsletter wurde der Tokenvorrat aus `.eml` und `.msg` vereinigt und überall wörtlich ersetzt. Ersetzt wurde zeichenweise mit Erhalt der Schreibweise (klein → `x`, groß → `X`, Ziffer → `0`). Mail-Ableitungen unterscheiden sich vorher/nachher nur in diesen Stellen und in `original_name:`. **Scan (einmalige Abnahme, Entscheidung 7):** 19 Dateien, **0 Treffer**. Gesucht wurde nach Vor- und Nachname, beiden Domains des Betreibers, den internen Hostnamen und dem internen IP-Präfix sowie nach allen 69 ursprünglichen Token als Literal. Schichten: UTF-8, UTF-16LE, Base64 (drei Ausrichtungen), quoted-printable (auch über Zeilenumbrüche und Soft Breaks), Header-Unfolding, `%`-Kodierung (zweifach), HTML-Entitäten, rekursiv in Zip und OLE (`.msg`), gzip-Streams und PDF-Flate-Streams. **Rest, bewusst belassen:** öffentliche Namen und Adressen Dritter in den GitHub-/TLDR-/GOG-Mails (Absender, Releaseautor, Projekt); zufällige binäre Suchschlüssel im `.msg`. **Beobachtung beim Lesen der Ableitungen → #204:** `gog-roundcube.eml` hat einen `text/plain`-Teil von 32 Zeichen („Plain text version not available“) neben 40 204 Zeichen HTML. Der Mailfilter bevorzugt `text/plain`, deshalb ist `derived.md` fast leer. Die `.msg` desselben Newsletters hat keinen Plaintext-Stream und bekommt den HTML-Text. `msg.py` hat dieselbe Vorrangregel. Das ist kein Fehler der Testdateien und wurde hier nicht gefixt; die Regelfrage ist #204 (`kind/decision`). ## Version `version bump --patch`, `--impact low`: geändert wurde unter `tools/` nur eine Testdatei (`test_raw_derive_testfiles.py`), kein Verhalten, keine Schnittstelle, kein Schema. Drop-in in beide Richtungen: Eine Instanz, die `tools/` darüberkopiert, überspringt den Test ohne `testfiles/`; nichts im Bestand muss migriert werden. `testfiles/` selbst liegt außerhalb dessen, was `dist export` ausliefert. Ergebnis: **9.0.0-beta.19**. ## Beteiligte Dateien `tools/chemenu/tests/test_raw_derive_testfiles.py` (`_texts()`, neuer Test), `testfiles/README.md`, `testfiles/**` (umbenannt, bereinigt, `office/excel-business.xlsx.expect`), `CHANGES.md` und `VERSION` über `version bump`. Ableitung gelesen: `tools/chemenu/filters/ooxml.py` (XLSX/TSV-Layout, nur gelesen). ## Abschluss (2026-10-09) Doku-Prüfung nach dem Publish: Außerhalb von `testfiles/` nennt nur `docs/dev/development.md` (Zeile 43 f.) den Ordner, und die Aussage dort („committed, so CI derives them too … that README says what may go in“) stimmt weiter. Kein Contract, kein Kommando-Datensatz, keine Installationsanleitung und keine `docs/explanation/`-Seite wurde berührt oder ist veraltet. Der Changelog-Stichpunkt in 9.0.0-beta.19 stimmt mit dem Gebauten überein. Deshalb gab es keinen weiteren Doku-Durchgang, keine Version und keinen Publish in der Abschlussphase. ## Akzeptanzkriterien - [x] Alle Dateien unter `testfiles/` haben die Namen aus Entscheidung 1; das Pelletskaminofen-PDF liegt nicht mehr im Repo-Verzeichnis (Entscheidung 8); `archive.zip` ist aus bereinigten Mitgliedern neu gebaut. - [x] **Scan sauber:** Über jede committete Datei, rekursiv in docx/xlsx/pptx/zip, im Mail-Inhalt nach Dekodierung (quoted-printable, Base64, `%`-Kodierung) und in UTF-8 wie UTF-16LE, gibt es keinen Treffer auf Vor-/Nachname, Mailadresse oder Domain des Betreibers. In keiner Mail führt ein Link ein empfängerbezogenes Token (Abmelden, Einstellungen, Tracking-Pixel). *(19 Dateien, 0 Treffer, Schichten oben.)* - [x] Der Vorher/Nachher-Vergleich aus Entscheidung 3 zeigt je Datei nur die ersetzten Zeichenketten als Unterschied; alle `.msg` öffnen mit `olefile`. - [x] `testfiles/README.md` hat die Quellen-Tabelle (Entscheidung 6) für jede committete Datei und den ergänzten Abschnitt „What goes in“; „What the test checks“ nennt die Blatt-TSVs. - [x] `_texts()` nimmt `*.sheets/*.tsv` auf; der Test auf `_texts()` (Entscheidung 4) besteht, und derselbe Test schlägt fehl, wenn `_texts()` auf `*.md` zurückgesetzt wird. - [x] Mindestens eine echte XLSX hat eine `.expect`-Zeile mit einem Formeltext, der in einer ihrer `.formulas.tsv` vorkommt und in `derived.md` nicht (Entscheidung 5). Das erfüllt das aus #202 übernommene Kriterium. *(`office/excel-business.xlsx.expect`: `SUM(Sales!L6:L29)`.)* - [x] Jede Datei unter `testfiles/` besteht `test_raw_derive_testfiles.py` lokal und in CI; jede Ableitung ist gelesen. Echte Fehler einer Ableitung werden eigene Issues und hier nicht nebenbei gefixt. *(Lokal 20 passed, Ableitungen gelesen; CI-Läufe 630 und 631 auf `be04921` grün. Die eine Beobachtung ist #204.)* - [x] `pytest`, `docs verify` und `instructions verify` grün; `version bump --patch --impact low` ausgeführt (9.0.0-beta.19); `publish` erreichte bei 24 Dateien das Mass-Update-Gate (Exit 42), der Betreiber gab frei; CI grün auf dem publizierten Commit `be049217a9ecf7d71123169dca9a8422d26ed95e` (Läufe 630 und 631). ## Bezug - #202: XLSX zu TSV plus Formelliste (geschlossen; dieses Kriterium stammt von dort) - #199: `raw derive` (geschlossen) - #204: Platzhalter-Plaintext verdrängt HTML in den Mailfiltern (Folge-Issue aus der Beobachtung oben)
torben added the prio/plannedsize/Marea/kbkind/build labels 2026-10-09 12:39:17 +00:00
torben added kind/decision and removed kind/build labels 2026-10-09 12:55:45 +00:00
Author
Owner

Changelog: Body gegen den Baum geprüft und neu geschrieben. Korrigiert: zip/ ist nicht leer (Archive.zip mit Kopien), es liegen 8 Office-Dateien (3 .pptx neu), nicht 5; Testlauf lokal 20 passed, es gibt keinen Ableitungsfehler. Neu: Befund zu empfängerbezogenen Links (kein Namensscan findet sie), Fremdnamen in PDF-Metadaten, Repo-URL in einer XLSX-Zelle, Formelzahlen je Arbeitsmappe. Entschieden: ASCII-Namen, Gleichlängen-Ersetzung statt Umbau, Prüfung „Bereinigung ändert nur ersetzte Zeichenketten“, Test direkt auf _texts(), Formel-Nadel nur im .formulas.tsv, Quellen-Tabelle in der README, --patch. kind/build → kind/decision wegen drei offener Betreiberfragen (Pelletkamin-PDF, Newsletter, Herkunft Einstein-Scan); der Body wird bereit, sobald sie beantwortet sind.

**Changelog:** Body gegen den Baum geprüft und neu geschrieben. Korrigiert: `zip/` ist nicht leer (`Archive.zip` mit Kopien), es liegen 8 Office-Dateien (3 `.pptx` neu), nicht 5; Testlauf lokal 20 passed, es gibt keinen Ableitungsfehler. Neu: Befund zu empfängerbezogenen Links (kein Namensscan findet sie), Fremdnamen in PDF-Metadaten, Repo-URL in einer XLSX-Zelle, Formelzahlen je Arbeitsmappe. Entschieden: ASCII-Namen, Gleichlängen-Ersetzung statt Umbau, Prüfung „Bereinigung ändert nur ersetzte Zeichenketten“, Test direkt auf `_texts()`, Formel-Nadel nur im `.formulas.tsv`, Quellen-Tabelle in der README, `--patch`. `kind/build` → `kind/decision` wegen drei offener Betreiberfragen (Pelletkamin-PDF, Newsletter, Herkunft Einstein-Scan); der Body wird bereit, sobald sie beantwortet sind.
torben added kind/build and removed kind/decision labels 2026-10-09 13:10:44 +00:00
Author
Owner

Changelog: Die drei offenen Fragen sind beantwortet und stehen als Entscheidungen 8–11: Pelletskaminofen-PDF gestrichen (wird aus dem Repo-Verzeichnis verschoben, nicht gelöscht), alle sechs Newsletter bleiben, Einstein-Scan bleibt (Web-Download, Herkunft so in der README), Weitergabe der Eigenbau-Dateien bestätigt. Abschnitt „Offene Fragen“ entfernt, Abschnitt „Beteiligte Dateien“ ergänzt, erstes Akzeptanzkriterium um das Verschieben des PDFs erweitert. kind/decision → kind/build.

**Changelog:** Die drei offenen Fragen sind beantwortet und stehen als Entscheidungen 8–11: Pelletskaminofen-PDF gestrichen (wird aus dem Repo-Verzeichnis verschoben, nicht gelöscht), alle sechs Newsletter bleiben, Einstein-Scan bleibt (Web-Download, Herkunft so in der README), Weitergabe der Eigenbau-Dateien bestätigt. Abschnitt „Offene Fragen“ entfernt, Abschnitt „Beteiligte Dateien“ ergänzt, erstes Akzeptanzkriterium um das Verschieben des PDFs erweitert. `kind/decision` → `kind/build`.
Author
Owner

Changelog: Build published as 9.0.0-beta.19 (be04921), CI runs 630 and 631 green. New in the body: section "Abweichung im Build" (extra identifiers beyond the name scan, scan result 19 files / 0 hits, residuals, the GOG placeholder-plaintext observation as a candidate for a separate issue). Decisions 1-7 rewritten from plan to past tense, the file table and test-gap paragraph now say what was before the build, all eight criteria ticked, the version section names the result.

Co-Authored-By: Claude Code noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2

**Changelog:** Build published as 9.0.0-beta.19 (`be04921`), CI runs 630 and 631 green. New in the body: section "Abweichung im Build" (extra identifiers beyond the name scan, scan result 19 files / 0 hits, residuals, the GOG placeholder-plaintext observation as a candidate for a separate issue). Decisions 1-7 rewritten from plan to past tense, the file table and test-gap paragraph now say what was before the build, all eight criteria ticked, the version section names the result. Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
Author
Owner

Changelog: Closed. The open question about spaces/umlauts in file names is answered in decision 1 (already tested in test_raw_derive.py, no issue needed). The GOG observation moved to #204, which also notes that msg.py has the same plain-before-HTML rule. New section "Abschluss" records the post-publish docs check (only docs/dev/development.md mentions testfiles/, still accurate; no contract, command record or install doc touched), so no pull-through, bump or publish in this phase.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2

**Changelog:** Closed. The open question about spaces/umlauts in file names is answered in decision 1 (already tested in `test_raw_derive.py`, no issue needed). The GOG observation moved to #204, which also notes that `msg.py` has the same plain-before-HTML rule. New section "Abschluss" records the post-publish docs check (only `docs/dev/development.md` mentions `testfiles/`, still accurate; no contract, command record or install doc touched), so no pull-through, bump or publish in this phase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#203