Folge von #199 (dort Entwurf 4, XLSX). Entschieden am 2026-10-09 im Gespräch mit dem Betreiber. Gebaut in 9.0.0-beta.18, Commit 9868fce; CI grün (Läufe 628 und 629). Die Abnahme mit echten Dateien ist nach #203 verschoben.
Befund
raw derive machte aus einer XLSX eine einzige derived.md mit einer Markdown-Tabelle je Blatt (tools/chemenu/filters/ooxml.py, XlsxFilter). Zwei Schwächen:
Schlecht auswertbar. Eine Markdown-Tabelle kostet mehr Token als nötig, und ein großes Blatt landete ganz im Kontext, obwohl ein Skript (Python, pandas, duckdb) es abfragen könnte, ohne dass der Agent es liest.
Formeln gingen verloren. Es standen nur die zuletzt gespeicherten Werte im Text (<f> wurde verworfen). Wie eine Zahl zustande kommt, ließ sich aus der Ableitung nicht beantworten.
Entscheidungen des Betreibers (2026-10-09)
Eine TSV je Blatt, UTF-8 ohne BOM, LF, RFC-4180-Quoting mit Tab als Trenner: Ein Feld mit Tab, Anführungszeichen oder Zeilenumbruch wird in " gesetzt, " wird verdoppelt. Die Zellen bleiben verlustfrei; keine Normalisierung, kein WARN dafür. Lesen geht mit csv.reader(..., delimiter="\t") und pandas.read_csv(sep="\t"). awk ist dafür kein Werkzeug, weil es gequotete Felder nicht parst.
derived.md ist die Übersicht und bleibt der Einstieg, den die Quellenseite zitiert.
Formeln in einer zweiten Datei je Blatt, in Langform: eine Zeile je Formelzelle. Verworfen wurde ein zweites Raster mit Formeltext.
Abnahme mit echten Dateien in ein eigenes Issue (#203), damit #202 schließen kann (Betreiber, 2026-10-09).
Umsetzung (wie gebaut)
Neben der .md liegt <md-stem>.sheets/ (derived.sheets/ bei der Einzeldatei, Budget.sheets/ neben Budget.md bei einem Mitglied eines ZIP oder einer Mail), darin NN-<blattname>.tsv und, nur bei Blättern mit Formeln, NN-<blattname>.formulas.tsv.
Die TSV beginnt bei A1 und wird nur rechts und unten beschnitten: Zeile n der Datei ist Zeile n des Blattes. Datumszellen bleiben ISO-Datum.
Formelliste: Kopfzeile cell, formula, value. Geteilte Formeln werden pro Zelle durch Verschieben der relativen Bezüge ausgeschrieben (Zeichenketten, Funktionsnamen, Blattnamen in Anführungszeichen, strukturierte Bezüge bleiben unberührt); ist das nicht sicher möglich, steht shared:<Hauptzelle> (bzw. shared:si=N ohne Hauptzelle) und ein WARN mit Anzahl. Array-Formeln: =… (array formula, range REF). Datentabellen: =TABLE(r1,r2).
derived.md: je Blatt ein Abschnitt mit Nummer, Zustand, Bereich, Formelanzahl, Dateiverweisen und Vorschau; Header behält sheets, hidden_sheets und bekommt formulas. Drei CHECK-Zeilen.
Derivation.files trägt die Zusatzdateien; der Platzhalter für den Ordnernamen wird in render durch den tatsächlich vergebenen Namen ersetzt (auch bei -2-Umbenennungen). raw derive prüft Pfadbudget und Kollisionen für jede Datei vor dem ersten Schreiben; ein vorhandener .sheets-Ordner wird nie überschrieben.
Bestehende Ableitungen in raw/ bleiben unverändert; Neuableitung hängt an #201.
Versionsteil: --patch (9.0.0-beta.17 → beta.18).
Betroffene Dateien
tools/chemenu/filters/{__init__,ooxml,archive}.py, tools/chemenu/commands/raw_cmd.py (Kommando-Record), tools/chemenu/tests/test_raw_derive.py, raw/CONTRACT.md, docs/how-to/ingest-a-source.md; generiert: tools/CONTRACT.md, docs/reference/commands/raw-material-and-uploads.md; dazu testfiles/ (README) mit test_raw_derive_testfiles.py.
Nachlese beim Schließen: instructions/wiki-ingest/SKILL.md („read the .md - its output names what to check“) stimmt weiter, weil die .md auf die Blattdateien verweist; kein docs/explanation/-Text betroffen. testfiles/README.md § „What the test checks“ deckt die Blatt-TSVs noch nicht ab; das ist Teil von #203.
Akzeptanzkriterien
Eine XLSX mit mehreren Blättern, eins davon versteckt, ergibt derived.md und derived.sheets/NN-….tsv in Blattreihenfolge; das versteckte Blatt steht in hidden_sheets und in der Übersicht als versteckt. (test_xlsx_becomes_an_overview_and_one_tsv_per_sheet)
Jede TSV liest sich mit csv.reader(delimiter="\t") zurück in genau die Zellwerte, auch bei Tab, Anführungszeichen, Zeilenumbruch und CR. (test_tsv_quotes_per_rfc_4180_…)
Zeile n der TSV ist Zeile n des Blattes, auch bei leeren oberen Zeilen und linker Spalte.
Ein Blatt mit Formeln ergibt eine .formulas.tsv, eins ohne keine.
Geteilte Formel über mehrere Zellen mit korrekt verschobenen Bezügen; nicht sicher umrechenbare ergibt shared:<Hauptzelle> und ein WARN mit Anzahl. (Getestet über 3 Zellen; die Verschiebelogik hängt nicht von der Zeilenanzahl ab.)
Zwei Läufe über dieselben Bytes ergeben byte-identische Dateien.
Ein zu langer Pfad einer Zusatzdatei endet mit exit 1 vor dem ersten Schreiben, incoming/ ist unverändert; --name ist der Ausweg.
Eine XLSX als Mitglied eines ZIP oder als Mail-Anhang bekommt <stamm>.md und <stamm>.sheets/ daneben; raw accept nimmt den Ordner an.
Die echten XLSX in testfiles/office/ laufen durch test_raw_derive_testfiles.py, mit .expect-Zeilen für mindestens einen Formelfall.Verschoben nach #203 (Entscheidung 4): Die Dateien brauchen vorher eine Bereinigung persönlicher Daten, und der Test muss erst die Blatt-TSVs einlesen.
pytest (2686 passed, 4 skipped), docs verify und instructions verify sind grün; CI grün auf 9868fce (Läufe 628 und 629: verify inkl. Version gate, pwsh).
#201: neue Ausgabe eines abgeleiteten Ordner-Bundles (Neuableitung mit neuem Format)
#203: Abnahme mit echten Dokumenten, inkl. XLSX-Formelfall
> Folge von #199 (dort Entwurf 4, XLSX). Entschieden am 2026-10-09 im Gespräch mit dem Betreiber. **Gebaut in 9.0.0-beta.18, Commit 9868fce; CI grün (Läufe 628 und 629).** Die Abnahme mit echten Dateien ist nach #203 verschoben.
## Befund
`raw derive` machte aus einer XLSX eine einzige `derived.md` mit einer Markdown-Tabelle je Blatt (`tools/chemenu/filters/ooxml.py`, `XlsxFilter`). Zwei Schwächen:
- **Schlecht auswertbar.** Eine Markdown-Tabelle kostet mehr Token als nötig, und ein großes Blatt landete ganz im Kontext, obwohl ein Skript (Python, `pandas`, `duckdb`) es abfragen könnte, ohne dass der Agent es liest.
- **Formeln gingen verloren.** Es standen nur die zuletzt gespeicherten Werte im Text (`<f>` wurde verworfen). Wie eine Zahl zustande kommt, ließ sich aus der Ableitung nicht beantworten.
## Entscheidungen des Betreibers (2026-10-09)
1. **Eine TSV je Blatt**, UTF-8 ohne BOM, LF, **RFC-4180-Quoting mit Tab als Trenner**: Ein Feld mit Tab, Anführungszeichen oder Zeilenumbruch wird in `"` gesetzt, `"` wird verdoppelt. Die Zellen bleiben verlustfrei; keine Normalisierung, kein WARN dafür. Lesen geht mit `csv.reader(..., delimiter="\t")` und `pandas.read_csv(sep="\t")`. `awk` ist dafür kein Werkzeug, weil es gequotete Felder nicht parst.
2. **`derived.md` ist die Übersicht** und bleibt der Einstieg, den die Quellenseite zitiert.
3. **Formeln** in einer zweiten Datei je Blatt, in Langform: eine Zeile je Formelzelle. Verworfen wurde ein zweites Raster mit Formeltext.
4. **Abnahme mit echten Dateien** in ein eigenes Issue (#203), damit #202 schließen kann (Betreiber, 2026-10-09).
## Umsetzung (wie gebaut)
- Neben der `.md` liegt `<md-stem>.sheets/` (`derived.sheets/` bei der Einzeldatei, `Budget.sheets/` neben `Budget.md` bei einem Mitglied eines ZIP oder einer Mail), darin `NN-<blattname>.tsv` und, nur bei Blättern mit Formeln, `NN-<blattname>.formulas.tsv`.
- Die TSV beginnt bei A1 und wird nur rechts und unten beschnitten: Zeile n der Datei ist Zeile n des Blattes. Datumszellen bleiben ISO-Datum.
- Formelliste: Kopfzeile `cell`, `formula`, `value`. Geteilte Formeln werden pro Zelle durch Verschieben der relativen Bezüge ausgeschrieben (Zeichenketten, Funktionsnamen, Blattnamen in Anführungszeichen, strukturierte Bezüge bleiben unberührt); ist das nicht sicher möglich, steht `shared:<Hauptzelle>` (bzw. `shared:si=N` ohne Hauptzelle) und ein WARN mit Anzahl. Array-Formeln: `=… (array formula, range REF)`. Datentabellen: `=TABLE(r1,r2)`.
- `derived.md`: je Blatt ein Abschnitt mit Nummer, Zustand, Bereich, Formelanzahl, Dateiverweisen und Vorschau; Header behält `sheets`, `hidden_sheets` und bekommt `formulas`. Drei `CHECK`-Zeilen.
- `Derivation.files` trägt die Zusatzdateien; der Platzhalter für den Ordnernamen wird in `render` durch den tatsächlich vergebenen Namen ersetzt (auch bei `-2`-Umbenennungen). `raw derive` prüft Pfadbudget und Kollisionen für jede Datei vor dem ersten Schreiben; ein vorhandener `.sheets`-Ordner wird nie überschrieben.
- Bestehende Ableitungen in `raw/` bleiben unverändert; Neuableitung hängt an #201.
- Versionsteil: `--patch` (9.0.0-beta.17 → beta.18).
## Betroffene Dateien
`tools/chemenu/filters/{__init__,ooxml,archive}.py`, `tools/chemenu/commands/raw_cmd.py` (Kommando-Record), `tools/chemenu/tests/test_raw_derive.py`, `raw/CONTRACT.md`, `docs/how-to/ingest-a-source.md`; generiert: `tools/CONTRACT.md`, `docs/reference/commands/raw-material-and-uploads.md`; dazu `testfiles/` (README) mit `test_raw_derive_testfiles.py`.
Nachlese beim Schließen: `instructions/wiki-ingest/SKILL.md` („read the `.md` - its output names what to check“) stimmt weiter, weil die `.md` auf die Blattdateien verweist; kein `docs/explanation/`-Text betroffen. `testfiles/README.md` § „What the test checks“ deckt die Blatt-TSVs noch nicht ab; das ist Teil von #203.
## Akzeptanzkriterien
- [x] Eine XLSX mit mehreren Blättern, eins davon versteckt, ergibt `derived.md` und `derived.sheets/NN-….tsv` in Blattreihenfolge; das versteckte Blatt steht in `hidden_sheets` und in der Übersicht als versteckt. (`test_xlsx_becomes_an_overview_and_one_tsv_per_sheet`)
- [x] Jede TSV liest sich mit `csv.reader(delimiter="\t")` zurück in genau die Zellwerte, auch bei Tab, Anführungszeichen, Zeilenumbruch und CR. (`test_tsv_quotes_per_rfc_4180_…`)
- [x] Zeile n der TSV ist Zeile n des Blattes, auch bei leeren oberen Zeilen und linker Spalte.
- [x] Ein Blatt mit Formeln ergibt eine `.formulas.tsv`, eins ohne keine.
- [x] Geteilte Formel über mehrere Zellen mit korrekt verschobenen Bezügen; nicht sicher umrechenbare ergibt `shared:<Hauptzelle>` und ein WARN mit Anzahl. (Getestet über 3 Zellen; die Verschiebelogik hängt nicht von der Zeilenanzahl ab.)
- [x] Zwei Läufe über dieselben Bytes ergeben byte-identische Dateien.
- [x] Ein zu langer Pfad einer Zusatzdatei endet mit exit 1 vor dem ersten Schreiben, `incoming/` ist unverändert; `--name` ist der Ausweg.
- [x] Eine XLSX als Mitglied eines ZIP oder als Mail-Anhang bekommt `<stamm>.md` und `<stamm>.sheets/` daneben; `raw accept` nimmt den Ordner an.
- [ ] ~~Die echten XLSX in `testfiles/office/` laufen durch `test_raw_derive_testfiles.py`, mit `.expect`-Zeilen für mindestens einen Formelfall.~~ **Verschoben nach #203** (Entscheidung 4): Die Dateien brauchen vorher eine Bereinigung persönlicher Daten, und der Test muss erst die Blatt-TSVs einlesen.
- [x] `pytest` (2686 passed, 4 skipped), `docs verify` und `instructions verify` sind grün; CI grün auf 9868fce (Läufe 628 und 629: verify inkl. Version gate, pwsh).
## Bezug
- #199: `raw derive`, Entwurf 4 (XLSX), geschlossen
- #201: neue Ausgabe eines abgeleiteten Ordner-Bundles (Neuableitung mit neuem Format)
- #203: Abnahme mit echten Dokumenten, inkl. XLSX-Formelfall
9.0.0-beta.18 (9868fce): raw derive schreibt eine XLSX je Blatt als TSV (RFC 4180, A1-ausgerichtet) in <stamm>.sheets/, Blätter mit Formeln zusätzlich als .formulas.tsv; derived.md ist die Übersicht. CI grün (Läufe 628, 629). Offen bleibt nur die Abnahme mit echten Dateien in testfiles/office/.
9.0.0-beta.18 (9868fce): `raw derive` schreibt eine XLSX je Blatt als TSV (RFC 4180, A1-ausgerichtet) in `<stamm>.sheets/`, Blätter mit Formeln zusätzlich als `.formulas.tsv`; `derived.md` ist die Übersicht. CI grün (Läufe 628, 629). Offen bleibt nur die Abnahme mit echten Dateien in `testfiles/office/`.
Changelog: Kriterium „echte XLSX in testfiles/office/ mit Formel-.expect“ gestrichen und nach #203 verschoben (Entscheidung 4, Betreiber). Nachlese der Doku beim Schließen ergänzt: nichts veraltet, die testfiles/README.md-Lücke liegt bei #203. Geschlossen.
**Changelog:** Kriterium „echte XLSX in `testfiles/office/` mit Formel-`.expect`“ gestrichen und nach #203 verschoben (Entscheidung 4, Betreiber). Nachlese der Doku beim Schließen ergänzt: nichts veraltet, die `testfiles/README.md`-Lücke liegt bei #203. 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.
Befund
raw derivemachte aus einer XLSX eine einzigederived.mdmit einer Markdown-Tabelle je Blatt (tools/chemenu/filters/ooxml.py,XlsxFilter). Zwei Schwächen:pandas,duckdb) es abfragen könnte, ohne dass der Agent es liest.<f>wurde verworfen). Wie eine Zahl zustande kommt, ließ sich aus der Ableitung nicht beantworten.Entscheidungen des Betreibers (2026-10-09)
"gesetzt,"wird verdoppelt. Die Zellen bleiben verlustfrei; keine Normalisierung, kein WARN dafür. Lesen geht mitcsv.reader(..., delimiter="\t")undpandas.read_csv(sep="\t").awkist dafür kein Werkzeug, weil es gequotete Felder nicht parst.derived.mdist die Übersicht und bleibt der Einstieg, den die Quellenseite zitiert.Umsetzung (wie gebaut)
.mdliegt<md-stem>.sheets/(derived.sheets/bei der Einzeldatei,Budget.sheets/nebenBudget.mdbei einem Mitglied eines ZIP oder einer Mail), darinNN-<blattname>.tsvund, nur bei Blättern mit Formeln,NN-<blattname>.formulas.tsv.cell,formula,value. Geteilte Formeln werden pro Zelle durch Verschieben der relativen Bezüge ausgeschrieben (Zeichenketten, Funktionsnamen, Blattnamen in Anführungszeichen, strukturierte Bezüge bleiben unberührt); ist das nicht sicher möglich, stehtshared:<Hauptzelle>(bzw.shared:si=Nohne Hauptzelle) und ein WARN mit Anzahl. Array-Formeln:=… (array formula, range REF). Datentabellen:=TABLE(r1,r2).derived.md: je Blatt ein Abschnitt mit Nummer, Zustand, Bereich, Formelanzahl, Dateiverweisen und Vorschau; Header behältsheets,hidden_sheetsund bekommtformulas. DreiCHECK-Zeilen.Derivation.filesträgt die Zusatzdateien; der Platzhalter für den Ordnernamen wird inrenderdurch den tatsächlich vergebenen Namen ersetzt (auch bei-2-Umbenennungen).raw deriveprüft Pfadbudget und Kollisionen für jede Datei vor dem ersten Schreiben; ein vorhandener.sheets-Ordner wird nie überschrieben.raw/bleiben unverändert; Neuableitung hängt an #201.--patch(9.0.0-beta.17 → beta.18).Betroffene Dateien
tools/chemenu/filters/{__init__,ooxml,archive}.py,tools/chemenu/commands/raw_cmd.py(Kommando-Record),tools/chemenu/tests/test_raw_derive.py,raw/CONTRACT.md,docs/how-to/ingest-a-source.md; generiert:tools/CONTRACT.md,docs/reference/commands/raw-material-and-uploads.md; dazutestfiles/(README) mittest_raw_derive_testfiles.py.Nachlese beim Schließen:
instructions/wiki-ingest/SKILL.md(„read the.md- its output names what to check“) stimmt weiter, weil die.mdauf die Blattdateien verweist; keindocs/explanation/-Text betroffen.testfiles/README.md§ „What the test checks“ deckt die Blatt-TSVs noch nicht ab; das ist Teil von #203.Akzeptanzkriterien
derived.mdundderived.sheets/NN-….tsvin Blattreihenfolge; das versteckte Blatt steht inhidden_sheetsund in der Übersicht als versteckt. (test_xlsx_becomes_an_overview_and_one_tsv_per_sheet)csv.reader(delimiter="\t")zurück in genau die Zellwerte, auch bei Tab, Anführungszeichen, Zeilenumbruch und CR. (test_tsv_quotes_per_rfc_4180_…).formulas.tsv, eins ohne keine.shared:<Hauptzelle>und ein WARN mit Anzahl. (Getestet über 3 Zellen; die Verschiebelogik hängt nicht von der Zeilenanzahl ab.)incoming/ist unverändert;--nameist der Ausweg.<stamm>.mdund<stamm>.sheets/daneben;raw acceptnimmt den Ordner an.Die echten XLSX inVerschoben nach #203 (Entscheidung 4): Die Dateien brauchen vorher eine Bereinigung persönlicher Daten, und der Test muss erst die Blatt-TSVs einlesen.testfiles/office/laufen durchtest_raw_derive_testfiles.py, mit.expect-Zeilen für mindestens einen Formelfall.pytest(2686 passed, 4 skipped),docs verifyundinstructions verifysind grün; CI grün auf9868fce(Läufe 628 und 629: verify inkl. Version gate, pwsh).Bezug
raw derive, Entwurf 4 (XLSX), geschlossen9.0.0-beta.18 (
9868fce):raw deriveschreibt eine XLSX je Blatt als TSV (RFC 4180, A1-ausgerichtet) in<stamm>.sheets/, Blätter mit Formeln zusätzlich als.formulas.tsv;derived.mdist die Übersicht. CI grün (Läufe 628, 629). Offen bleibt nur die Abnahme mit echten Dateien intestfiles/office/.Changelog: Kriterium „echte XLSX in
testfiles/office/mit Formel-.expect“ gestrichen und nach #203 verschoben (Entscheidung 4, Betreiber). Nachlese der Doku beim Schließen ergänzt: nichts veraltet, dietestfiles/README.md-Lücke liegt bei #203. Geschlossen.