Zwei Standards, 26 Kantone · Teil 12 von 14
12 · Was wir gebaut haben — und was es nicht kann
Wer über Schema-Drift schreibt, muss die eigene Punktzahl mitliefern. Also zuerst sie, ungeschönt.
Unser Generator emittiert für die 42 Positionen der OR-Mindestgliederung 42 Pfade in eine eCH-0276-Instanz. Gegen die auf ech.ch publizierte Fassung V1.0.0 halten 42 von 42. Gegen die Fassung, die im swissdec-Transmitterpaket vom 06.03.2026 mitgeliefert wird — eCH-0276-1-0-4_20260115.xsd —, halten 40 von 42. Gegen den V2.0.0-Entwurf vom 23.07.2026 halten 39 von 42. Drei Dateien, zwei davon mit identischem Namensraum http://www.ech.ch/xmlns/eCH-0276/1 und identischer Versionsangabe, alle drei heissen eCH-0276 — und in zweien davon ist unsere Datei fehlerhaft. Das ist der einzige Absatz dieses Kapitels, der gegen uns spricht, und deshalb der einzige, den ein Leser ohne Weiteres glauben sollte.
Die Provenienz unseres Build-Ziels haben wir selbst nachgerechnet, nicht behauptet. Die in unserem Code liegende eCH-0276-1-0.xsd und die von ech.ch gezogene Datei tragen dieselbe SHA-256:
14a0d6cb3abce06b2bb55c5b9a311ec79ceea42d16314e5f7f705d1fea2accad
Wir bauen also gegen die publizierte Fassung des Standards. Teil 10 hat gezeigt, was das wert ist: der Container von swissdec bindet denselben Namensraum per schemaLocation an eine andere Datei. Wer über den Distributor fährt, validiert nicht gegen das, was auf ech.ch steht. Unsere 42/42 gelten gegen die Norm; unsere 40/42 gelten gegen die Leitung.
Das Artefakt, das wir haben und das niemand publiziert hat
Zwischen der OR-Jahresrechnung, dem Deklarationsformat eCH-0276 und der XBRL-CH-Taxonomie gibt es öffentlich keine Zeile, die alle drei zusammenführt. Wir haben sie: mapping-42-to-ch-taxonomy.csv, 42 Zeilen, jede mit dem eCH-0276-Pfad und dem ct:-Konzept der CH-Taxonomie in derselben Zeile, dazu Bilanzseite und Kontexttyp.
Die Verteilung, heute nachgezählt: 38 DIRECT · 2 CONTEXT · 2 DERIVE. 30 instant, 12 duration. 22 credit, 20 debit. 42 Schlüssel landen auf 41 verschiedenen ct:-Konzepten — gewinnvortrag und gewinnvortrag_neu treffen dasselbe Konzept ct:ProfitOrLossCarriedForward und werden allein durch den Kontext-Stichtag getrennt, Periodenanfang gegen Periodenende. eCH-0276 braucht dafür zwei Elemente, XBRL braucht ein Konzept und zwei Kontexte. Das ist keine Feinheit, das ist der Unterschied zwischen einem Formularfeld und einem Datenmodell.
Im selben Verzeichnis liegt der Gegenbeleg, und er gehört dazu: ch-taxonomy-uncovered-concepts.txt, 167 Konzepte der CH-Taxonomie, die unsere 42-Schlüssel-Oberfläche nicht abdeckt — von ct:AdvertisingExpense über ct:CapitalLossesOnInvestments bis ct:ChangesInventoriesUnfinishedFinishedGoodsAndUnbilledServices. Eine Abbildung, die ihre eigene Lücke nicht mitzählt, ist eine Verkaufsunterlage.
Die zwei DERIVE-Zeilen sind die interessantesten, weil sie zeigen, wo eine Abbildung ehrlich aufhört. Wörtlich aus der Notizspalte:
«
ct:OperatingIncome= ‹Betrieblicher Ertrag, insgesamt› is BROADER than our eCHtotalOperatingRevenueFromDeliveriesAndServices: it also rolls up OtherOperatingIncome + ChangesInventories … Not the same number unless those are nil.»
«BALANCE-SHEET concept (Bilanzgewinn), instant. Group 400 has NO ‹zur Verfügung der GV› total; in XBRL it is the roll-up ProfitOrLossCarriedForward(start) + ProfitOrLoss.»
Zwei Standards, die dasselbe Land beschreiben, und an zwei von 42 Stellen bedeutet dieselbe deutsche Bezeichnung nicht dieselbe Zahl. Wer die beiden Formate für austauschbar hält, hat sie nicht nebeneinandergelegt.
Die Grössenordnung, weil sie eine Tatsache ist
Die CH-Engine sind 494 Zeilen über sechs Module — line_items.py 150, structured_input.py 123, preview.py 97, engine.py 70, eligibility.py 25. Die Arbeit steckt nicht im Code. Sie steckt im Mapping, und das Mapping ist eine Lesearbeit an fremden Dokumenten.
In engine.py steht eine Zeile, die den ganzen Rahmen setzt:
submitted: bool = False # ALWAYS False — CH is generate-only
Wir erzeugen eine Datei. Wir übermitteln nichts. Wir haben nie eine Datei in ein kantonales Portal importiert — nicht in Zürich, nicht anderswo, in keinem Format. Alles in diesem Text steht auf Dokumenten, nicht auf einem Test.
Wo wir uns weigern — und wo der Kanton dasselbe sagt
Die schärfste Designentscheidung unseres Generators ist eine Weigerung. Wörtlich aus unserer Quelle, line_items.py:
«Die Gewinnverwendung ist ein Beschluss Ihrer Organe, keine Rechnung — eBilanz Fabrik unterstellt sie nicht.»
Fehlt die Gewinnverwendung, bricht der Lauf ab, statt «keine Ausschüttung» zu unterstellen. Eine Software, die das Register E stillschweigend mit Nullen füllt, legt eine materielle Erklärung in eine Datei, die zur Steuerverwaltung geht.
Und nun daneben, unabhängig davon formuliert, das Steueramt des Kantons Zürich in seinen Fragen und Antworten vom 08.09.2025, auf die Frage, wie die Angaben ab Steuerjahr 2025 in die Erklärung kommen:
«Gemäss aktuellem Informationsstand wird XBRL entsprechende Informationen enthalten. Dort wo diese Informationen nicht enthalten sind, werden manuelle Eingaben (z.B. für Dividenden) oder das Hochladen von zusätzlichen Beilagen möglich sein.»
Zwei Häuser, dieselbe Stelle, dieselbe Antwort: die Dividende kommt nicht aus der Buchhaltung. Sie kommt aus einem Beschluss, und einen Beschluss tippt jemand ein.
Warum «auf Knopfdruck» arithmetisch nicht aufgehen kann
Das ist kein Werturteil, es ist eine Auszählung. eCH-0276 V1.0.0 deklariert 890 verschiedene Elementnamen (heute mit einem XML-Parser über die publizierte XSD gezählt, nicht mit grep). Die XBRL-CH-Taxonomie deklariert 453 Konzepte in der Fassung 2024-06-23 und 465 in der Fassung 2025.
Das Deklarationsformat ist rund doppelt so gross wie die Jahresrechnungstaxonomie. Deutlich mehr als die Hälfte der Zielfelder hat keine Quelle in den Büchern — weil sie dort nie war. Dasselbe Bild zeigt das SSK-Regelwerk von der anderen Seite: 401 seiner 1'432 Regeln entfallen allein auf die Dialoge L (Steuerausscheidung) und P (verdecktes Eigenkapital), also auf Sachverhalte, die keine Buchhaltung kennt. Eine E-Bilanz füllt die Jahresrechnung. Die Steuererklärung füllt sie nicht.
Der einzige extern gezählte Teil unseres Protokolls
Alles bisher Genannte haben wir selbst gemessen. Es gibt genau eine Zahl über uns, die eine Behörde erhoben hat. Sie kam am 03.08.2026 von statistikauswertung@elster.de, HerstellerID 43877, und der ganze Bericht ist zwei Zeilen lang:
"Zeitraum";"Verfahren";"Datenart";"Anzahl NDB"
"2026-07";"ElsterBilanz";"Bilanz";"15"
Semantik laut Begleitmail: «Anzahl der übermittelten echten (= ohne Testfälle) Nutzdatenblöcke». Unsere Abstimmung dagegen: 19 Produktivversuche, minus 4 von ELSTER abgewiesene Zertifikatsfälle, ergibt 15 angenommene Übermittlungen, gegen 15 fakturierte Einreichungen, mit identischen Transferticket-Mengen. Null Abweichung.
Und die Grenze gehört mitgeliefert, sonst ist die Zahl eine Behauptung: «Ein Monat ohne Verkehr und ein weggelassener Monat sehen im Bericht gleich aus.» Jedes Argument, das wir aus einem fehlenden Monat ziehen würden, wäre ein Argument aus Schweigen — und ist als solches markiert.
Diese deutsche Basis ist es auch, die die Schweizer Aufwandschätzung überhaupt trägt: ein produktiver, von ERiC akzeptierter XBRL-Adapter mit 1'028 Zeilen, der bereits xbrli:xbrl, link:schemaRef, instant- und duration-Kontexte, xbrli:entity/identifier mit Scheme-URI, iso4217-Einheiten sowie decimals= und unitRef= emittiert. Nichts davon muss für die Schweiz erfunden werden.
Was es nicht trägt, steht in unserer eigenen Aufwandsnotiz vom 04.08.2026. Sieben Arbeitstage für einen CH-XBRL-Adapter sind schätzbar; die Einreichung ist es nicht:
«‹Days› buys a file that Arelle validates offline. It does not buy a filing.»
«Arelle ist ein Spezifikations-Orakel, kein Akzeptanz-Orakel. Eine Zahl für Teil B zu nennen hiesse, einen Erfolg zu behaupten, den ich nicht wissen kann.»
In Deutschland schliesst EricPruefe diese Lücke — ein Prüfaufruf, der die Annahme vorab bestätigt. Für die Schweiz enthält unser Korpus kein publiziertes Werkzeug mit dieser Funktion; ob eines existiert, das wir nicht gezogen haben, ist ungeprüft.
Der Watch — mit der Korrektur, die dazugehört
Damit dieser Text prüfbar bleibt, haben wir am 04.08.2026 einen Beobachter gebaut: 10 Quellen (zwei Zendesk-APIs, sechs Seitenzählungen, zwei Asset-Hashes) und 8 Wortgrenzen-Signalbegriffe. Ausgangsstand aufgezeichnet 04.08.2026 20:58:32 +0200. Die Ehrlichkeitsregel steht im Quelltext und ist wörtlich publizierbar:
«Silence means nothing changed — never that the check failed. A fetch failure is reported as
manual-check-due, never as green.»
Und die Korrektur, die mitpubliziert wird: der Watch läuft nicht täglich. Es gibt kein launchd-Plist, keinen Cron-Eintrag, keinen Eintrag in expected-crons.json. Er ist einmal gelaufen, um den Ausgangsstand zu schreiben. Wer prüfen will, ob wir es ernst meinen, schaut nicht auf diese Seite, sondern darauf, ob der nächste Bericht erscheint.
Der Ausgangsstand selbst ist die Falsifikationsgrundlage für Teil 14. zh-help: 70 Artikel, alle acht Begriffe 0. zh-jp und zh-umsteigen: alle acht 0. drtax-help: eCH-0276 0, XBRL 0, E-Bilanz 0. ow-publik: E-Bilanz 5. swissdec: E-Bilanz 42. Die erste Zahl, die sich bewegt, entscheidet mehr über die nächsten zwei Jahre als alles, was in diesem Kapitel steht.