Skip to main content
falzmarke — Briefe schreiben mit KI, nach Norm, nicht nach Gefühl. DIN-5008-Briefe aus Markdown, als PDF/A gesetzt und auf den Millimeter geprüft.

CI Release License: MIT Python 3.11+ DIN 5008


Andere Werkzeuge erzeugen ein PDF. falzmarke prüft das Ergebnis.

Du schreibst den Inhalt als Markdown. falzmarke setzt daraus einen Geschäftsbrief nach DIN 5008:2020 als PDF/A — und misst anschließend das fertige PDF nach. Sitzt die Falzmarke nicht auf 105,0 mm, endet der Lauf mit einem Fehler statt mit einem Brief, der nur ungefähr stimmt.

falzmarke.com — Anleitung ohne Terminal · ⬇ Als Claude-Skill laden · In 60 Sekunden ausprobieren · Beispielbrief ansehen

Linux · macOS · Windows · 34 Maße je Seite · PDF/A-2b · MIT


In Bewegung

Ein Terminal zeigt den Musterbrief als Markdown, danach den Lauf von falzmarke render: PDF und Vorschau werden geschrieben, anschließend läuft der Messbericht durch und endet mit der Zeile, die die eingehaltenen Maße zählt.

Aufgezeichnet aus der echten CLI mit vhs; das Drehbuch steht in docs/marke/video/readme.tape. Ein Test hält den Mitschnitt gegen einen frischen Lauf, damit hier kein Terminal steht, das es so nie gab (tests/test_tape.py).


Was dabei herauskommt

Briefkopf, Anschriftfeld, Informationsblock und Betreff

Und was danach geprüft wird — Auszug aus dem Bericht, den jeder Lauf ausgibt:

OK    Falzmarke 1, y: soll 105.00 ist 105.00 (tol ±0.3)
OK    Infoblock, x-links: soll 125.00 ist 125.00 (tol ±0.5)
OK    Betreff, y-Oberkante: soll 98.47 ist 97.91 (tol -1.75/+0.6)
OK    Abstand Betreff → Anrede (2 Leerzeilen): soll 12.70 ist 12.70 (tol ±0.2)

Das sind vier von 33 Zeilen des Geometrieberichts. Der Film zeigt, wie die übrigen entstehen: Eine Linie fährt das Blatt ab und hält an jedem gemessenen Höhenmaß. Sie hält dort, wo die Messung es sagt — bei diesen Prüfungen ist der gemessene Wert zugleich die Stelle.

Ein Beispielbrief, daneben ein Textfeld. Eine grüne waagerechte Linie wandert von oben nach unten über das Blatt und hält nacheinander an acht Stellen: Rücksendeangabe bei 46,26 Millimetern, Infoblock bei 50,34, Anschrift erste Zeile bei 62,69 und letzte Zeile bei 77,86, Betreff bei 98,45, Falzmarke 1 bei 105,00, Lochmarke bei 148,50 und Falzmarke 2 bei 210,00. Bei jedem Halt stehen daneben der Name der Prüfung, Sollwert, gemessener Wert, Toleranz und das Wort eingehalten. Am Ende liegen alle acht Linien gleichzeitig auf dem Blatt und daneben steht: 33 von 33 Prüfungen eingehalten.

Acht der 33 Geometrieprüfungen tragen eine Höhe auf dem Blatt; die übrigen messen Breiten, Abstände und Eigenschaften ohne Ort auf der Seite. Die Zahl 34 weiter oben zählt eine mehr: Nach einem render sieht die CLI zusätzlich die PDF/A-Konformität nach, und die liegt auf keinem Millimeter. Beide Zahlen stimmen, sie zählen Verschiedenes.

Keine Zahl im Film ist abgetippt — sie kommen alle aus verify --json, und tests/test_messfilm.py hält den Film gegen einen frischen Messlauf. Verschiebt jemand die Falzmarke um 2 mm, muss der betroffene Halt rot werden; tut er es nicht, schlägt der Test fehl.

Die erste Zeile des Berichts oben spricht von einem Strich, den man auf einem Vorschaubild kaum sieht — er ist 0,25 pt stark. Vergrößert sieht die Stelle so aus:

Ausschnitt vom linken Rand eines Briefes, sechs mal vier Millimeter groß: Eine gestrichelte grüne Hilfslinie markiert die Sollposition bei 105,00 Millimetern und geht auf gleicher Höhe in die kurze schwarze Falzmarke über, die knapp die halbe Bildbreite einnimmt. Daneben das ganze Blatt verkleinert, mit einem Rahmen um die vergrößerte Stelle. Darunter steht die gemessene Position 105,00 Millimeter.

Dort wird der Bogen gefaltet, damit die Anschrift im Fensterumschlag steht. Sitzt die Marke falsch, faltet der Stapel falsch — und das fällt erst nach dem Druck auf.

Das Problem

Eine Briefvorlage kann nicht prüfen, ob das Ergebnis stimmt. Sie wird kopiert, jemand verschiebt eine Zeile, und der Fehler fällt erst am fertigen Stapel auf: Die Anschrift steht nicht mehr im Fensterausschnitt, alles muss neu gedruckt und kuvertiert werden — und wer mit Automationsrabatt einliefert, verliert ihn für diese Sendung.

Sprachmodelle verschärfen das. Sie formulieren gut, aber sie können keinen Text auf 45,0 mm setzen. Wer einen Brief von einer KI schreiben lässt, bekommt zuverlässig guten Inhalt in unzuverlässigem Layout.

Und ein Renderer kann ebenfalls Fehler haben — auch dieser hier.

Deshalb trennt falzmarke drei Dinge: Inhalt kommt als Markdown, lesbar und versionierbar. Das Layout setzt ein Renderer, der es immer gleich macht. Und die Prüfung misst das fertige PDF, statt dem Renderer zu glauben.

Warum nicht einfach Word oder ein Prompt?

Verglichen wird der typische Arbeitsablauf, nicht das Werkzeug an sich — mit einer sorgfältig gepflegten Vorlage lässt sich vieles davon erreichen.

Vorlage in Word / LibreOffice Brief direkt von einer KI falzmarke
Quelle diffbar und versionierbar teilweise selten ja — Markdown und YAML
Layout reproduzierbar hängt an Vorlage und Umgebung nicht zugesichert ja — derselbe Renderer, dieselbe Ausgabe
Fertiges PDF wird nachgemessen nein nein ja — 34 Maße, jede Seite, Abweichung ist ein Fehler
Absenderprofile von Hand gepflegt uneinheitlich ja — einmal anlegen, überall nutzen
Prüfbericht maschinenlesbar nein nein ja — --json und Exit-Codes
PDF/A als Voreinstellung nicht automatisch nicht zugesichert ja — ohne zusätzliches Flag

Was du davon hast

  • Der Brief sitzt im Fensterumschlag — Anschriftfeld, Falz- und Lochmarken werden am fertigen PDF vermessen, nicht beim Setzen angenommen.
  • Änderungen bleiben nachvollziehbar — Markdown und YAML sind Textdateien. Ein Diff zeigt, was sich geändert hat; das PDF ist Ergebnis, nicht Quelle.
  • Ein Auftritt, viele Briefe — Profile bündeln Briefkopf, Fußzeile, Logo, Farben und Voreinstellungen. Auch die Unterschrift, je Brief überschreibbar.
  • Fehler sind maschinenlesbar — eigene Exit-Codes für Eingabe-, Geometrie- und Umgebungsfehler, dazu --json. Damit läuft es in CI und in Automatisierungen.
  • Für Langzeitarchivierung ausgelegt — PDF/A-2b ohne zusätzliches Flag. Dass die Datei die Konformität wirklich einhält, sagt nicht dieses Werkzeug, sondern veraPDF — die Referenzimplementierung der PDF Association, in CI bei jedem Push. Optional PDF/UA-1 mit --pdfua, ebenfalls dort geprüft.
  • Im Gespräch oder im Terminal — als Claude-Skill oder als CLI, ohne Systeminstallation.

Woran man sieht, dass es stimmt

Das ist der Teil, an dem sich das Versprechen entscheidet — deshalb steht er vor der Installation.

  • Gemessen wird das fertige PDF, nicht die Eingabe. verify liest das erzeugte Dokument mit pdfplumber und vergleicht Zonen, Marken und Abstände gegen die Sollwerte.

  • Jede tragende Prüfung hat eine Gegenprobe. Sie läuft gegen ein absichtlich verschobenes Layout und muss dort anschlagen — ein Prüfmittel, das nie rot werden kann, wäre kein Nachweis. Das gilt auch für das Bild oben: Es entsteht zweimal, einmal aus dem ausgelieferten Layout und einmal aus einem, in dem die Marke 2 mm zu tief sitzt.

    Ein wechselndes Bild desselben Ausschnitts. Im ersten Zustand liegt die Falzmarke auf der gestrichelten Sollinie bei 105,00 Millimetern, darunter steht 105,00 Millimeter und der Hinweis, dass so ausgeliefert wird. Im zweiten springt die Marke deutlich nach unten, die Sollinie bleibt wo sie war, darunter steht 107,00 Millimeter und der Hinweis, dass verify hier anschlägt.

    Unterscheiden sich die beiden Ausschnitte nicht, zeigt der Ausschnitt die Marke gar nicht — dann ist das Bild oben wertlos, und tests/test_detailbild.py schlägt fehl.

  • CI auf Linux, macOS und Windows, bei jedem Push.

  • Ein Frischinstallations-Test führt die Befehle aus dieser README wirklich aus. Hier steht kein Befehl, den niemand ausprobiert hat.

  • Alle Beispielbriefe werden in CI gerendert und vermessen.

  • Die PDF-Konformität bestätigt ein fremdes Werkzeug. Alles andere auf dieser Liste misst mit demselben Code, der das PDF erzeugt hat — das belegt Selbsttreue, nicht Konformität. veraPDF hat den Brief nicht geschrieben und teilt keine Zeile mit dem Renderer. Geprüft wird, was die Datei selbst deklariert, auf der ausgelieferten Datei, mit Prüfsummen-Abgleich — und mit einer Gegenprobe, die ein absichtlich nicht-konformes PDF durchfallen lässt (scripts/pdf_konformitaet.py).

  • Die Layoutbasis ist vendort und prüfsummengesichertvendor/README.md.

Zwei Aussagen, die gern verwechselt werden, hält das Projekt auseinander:

Der Sollwert ist fachlich belegt und der Verifier erkennt eine Abweichung davon sind verschiedene Dinge. Das Zweite ist bewiesen. Das Erste hat Grenzen.

Woher die Sollwerte stammen: Maße und Schreibregeln folgen öffentlich dokumentierten Quellen (Liste in skill/references/din5008.md); der Abgleich mit dem Originaltext der DIN 5008:2020-03 einschließlich Berichtigung 1:2020-07 steht aus. Regeln aus einzelnen Quellen wirken nur als Warnung. Welche Regel worauf beruht, steht in der Quellenlage je Regel; was daraus rechtlich folgt, in docs/recht.md.

python3 -m pytest -q

Sicherheit

Genannt wird nur, was im Code steht und geprüft ist. falzmarke ist nicht unabhängig auditiert — Sicherheitsrelevantes bitte nach SECURITY.md, nicht als Issue.

  • Verarbeitung bleibt lokal. Der Renderpfad importiert keine Netzwerkbibliothek.
  • YAML wird ausschließlich mit safe_load gelesen — an jeder Stelle, auch beim eingebetteten Profil.
  • Markdown läuft gegen eine Positivliste von Knotentypen. Was nicht daraufsteht, ist ein Fehler mit Zeilenangabe — nie ein stilles Durchreichen.
  • Brieftext wird nie zu Typst-Code. Der Emitter übergibt ihn als maskierte Zeichenkette; Sonderzeichen können die Struktur nicht verlassen.
  • Profil- und Briefdateien bleiben in ihrem Ordner. Logo, Unterschrift und eigener Briefkopf dürfen nicht darüber hinauszeigen, Symlinks werden aufgelöst (Gegenproben).
  • Typst läuft auf ein eigenes Wurzelverzeichnis begrenzt, Systemschriften sind abgeschaltet.
  • Alle Abhängigkeiten des Programms sind permissiv lizenziertTHIRD_PARTY_LICENSES.md.
  • Die CI-Aktionen hängen an vollständigen Commit-SHAs, nicht an verschiebbaren Tags.

Das Release-Asset lässt sich auf seine Herkunft prüfen:

gh attestation verify falzmarke.skill --repo blitzsicht/falzmarke

Das belegt, aus welchem Lauf und welchem Commit die Datei stammt — nicht, dass sie fehlerfrei ist. Die SHA-256-Summe steht in der Release-Notiz und als falzmarke.skill.sha256 daneben.

In 60 Sekunden

Vier Wege, und sie können nicht dasselbe:

Weg rendert ohne Netz Größe wofür
falzmarke.skill hochladen nein, der erste Lauf lädt nach ~0,8 MB claude.ai — der Upload-Dialog nimmt höchstens 30 MB
falzmarke-offline.skill ja — der Typst-Compiler reist mit ~34 MB Sandboxen ohne PyPI-Zugriff; zu groß für den Upload-Dialog
pipx / uvx nein, der erste Lauf lädt nach ~1 MB Terminal
Repository klonen nein, der erste Lauf lädt nach ~1 MB Mitarbeit am Werkzeug

Die beiden Skill-Pakete unterscheiden sich in genau einer Datei: Das Offline-Paket trägt das typst-Wheel in vendor/, das schlanke nicht. Warum es zwei sind und nicht eines, steht in skill/vendor/README.md.

Mit Claude

  1. falzmarke.skill herunterladen
  2. In Claude unter Einstellungen › Capabilities hochladen (Tarif mit Code-Ausführung nötig). Für Claude Code genügt ein Symlink:
    ln -s "$PWD/skill" ~/.claude/skills/falzmarke
    
  3. „Schreib einen Brief an die Muster GmbH, Angebot über …"

Im Terminal

uvx falzmarke init brief.md --profil example --betreff "Angebot Nr. 2026-0815"

oder dauerhaft installiert, danach genügt falzmarke render brief.md --png:

pipx install falzmarke

Das Paket liegt auf PyPI. Wer den unveröffentlichten Stand von main will, nimmt weiterhin die Adresse:

pipx install git+https://github.com/blitzsicht/falzmarke

Der Typst-Compiler kommt als Python-Wheel mit: keine Systeminstallation, kein LaTeX, kein wkhtmltopdf, keine Schriftinstallation.

In einem Repository voller Briefe

Wer seine Briefe versioniert, lässt sie bei jedem Push setzen und nachmessen:

- uses: blitzsicht/falzmarke@main
  with:
    briefe: "briefe/*.md"
    profile: "profile"

Die PDFs hängen danach als Artefakt am Lauf. Hält ein Brief die Maße nicht ein, wird der Lauf rot und nennt Datei und Maß — ein Serienbrief-Archiv merkt einen verrutschten Betreff damit beim Push und nicht beim Empfänger. Die Eingaben stehen in action.yml; die Aktion installiert falzmarke von PyPI und baut keine zweite Installationsstrecke auf. Wer den Lauf nachfahrbar halten will, nennt eine feste Fassung: paket: "falzmarke==0.7.3".

In einem anderen KI-Client

falzmarke spricht MCP — damit setzen auch Clients Briefe, die keinen Claude-Skill kennen.

pip install 'mcp>=2,<3'          # das SDK ist nicht in der Grundausstattung
falzmarke mcp                    # Server über stdio

Drei Werkzeuge: brief_rendern, brief_pruefen, profile_auflisten. Der Messbericht kommt bei jedem Rendern mit — ein Dienst, der ein PDF zurückgibt und offenlässt, ob die Maße stimmen, wäre ein PDF-Generator wie jeder andere.

Das Absenderprofil darf als Objekt im Aufruf stehen. Ein Client ohne Zugriff auf das Dateisystem des Servers kann so seinen eigenen Absender mitgeben, statt mit den Profilen zu leben, die dort zufällig liegen.

Was der Dienst nicht tut: versenden, ablegen, zustellen. Er setzt und prüft (ADR 0029).

Aus einem Clone, ohne Installation
git clone https://github.com/blitzsicht/falzmarke.git
cd falzmarke
python3 skill/scripts/bootstrap.py
python3 skill/scripts/falzmarke.py render examples/brief-form-b.md --png

Einen Brief schreiben

---
profil: example
empfaenger:
  - Muster GmbH
  - Frau Erika Muster
  - Musterstraße 1
  - 12345 Musterstadt
datum: 2026-08-25
betreff: Angebot Nr. 2026-0815 über die Neugestaltung Ihrer Website
anrede: Sehr geehrte Frau Muster,
anlagen:
  - Angebot 2026-0815
---
vielen Dank für Ihre Anfrage vom 20. August 2026. Anbei erhalten Sie unser Angebot.

Die Umsetzung dauert ab Ihrer Freigabe **sieben Werktage**.
python3 skill/scripts/falzmarke.py render brief.md --png

Alle Felder stehen im Datenvertrag. Ein Feld, das dort nicht steht, bricht mit Zeilennummer und Vorschlag ab — es wird nie stillschweigend verworfen.

Was im Brieftext erlaubt ist

Der Text unter dem Frontmatter ist falzmarke-Markdown, eine dokumentierte Teilmenge von CommonMark:

Das geht Das erledigt falzmarke selbst
Absätze, **fett**, *kursiv* z. B., 10 %, § 5 bekommen geschützte Leerzeichen
Aufzählungen und nummerierte Listen -- wird zum Halbgeviertstrich – so
Harter Umbruch mit \ am Zeilenende "Wort" wird zu „Wort“
Pipe-Tabellen mit Ausrichtung Tag und Monat bleiben zusammen: 25. August

Links, Bilder und HTML sind Fehler — mit Zeile, Grund und Korrektur, nie stillschweigend. Auf Papier gibt es keinen Link, und ein Bild im Fließtext verschöbe die Geometrie, die danach gemessen wird.

Zwischenüberschriften (# bis ####), tiefere Aufzählungen, Blockzitate und wortgetreue Auszüge gibt es für lange Schreiben: dialekt: "1.1" im Frontmatter schaltet sie frei. Ein Auszug bleibt Zeichen für Zeichen stehen — keine typografischen Ersetzungen, kein Umbruch, keine Einfärbung, und nichts darin wird ausgeführt. Ohne das Feld gilt Fassung 1.0, und ein bestehender Brief rendert unverändert.

Die vollständige Liste: falzmarke-Markdown.

Dieselbe Datei als E-Mail

Ein Schreiben mit typ: email im Frontmatter wird keine PDF-Seite, sondern eine .eml — dieselbe Quelle, dasselbe Profil, dieselbe Signatur.

falzmarke email nachricht.md --html
OK  geschrieben: nachricht.eml
OK  geschrieben: nachricht.html
OK  verify: 22/22 Prüfungen bestanden

Die .eml öffnet das Mailprogramm, die .html der Browser. Geprüft wird die fertige Datei: MIME-Aufbau, format=flowed, Space-Stuffing, die Signaturtrennzeile, und ob im HTML nichts steht, was dort nicht hingehört — kein Skript, kein externes Stylesheet, kein Zählpixel, keine Tabelle als Layout. falzmarke verify --email misst auch Dateien, die von woanders kommen.

falzmarke versendet nichts. Es gibt keinen Versandbefehl und keine Option, die sendet: Wer eine Datei erzeugt, haftet für ihren Inhalt; wer sie befördert, für Zustellung und Nachweis. Das sind zwei Versprechen, und falzmarke gibt nur das erste (ADR 0034).

Wie die Datei aufgebaut ist, was bewusst fehlt und wo die Grenzen liegen: Die E-Mail-Fassung. Vier Beispiele liegen unter examples/email/.

Beispiele

Standardbrief Einschreiben Mehrseitig
Form B Vermerkzone Folgeseiten
Form B mit Informationsblock Zusatz- und Vermerkzone Kopfzeile und Seitenzählung

Dazu Form A, Auslandsanschrift, Tabelle, ein Brief mit langem Informationsblock und einer mit englischer Beschriftung (sprache: en — deutsche Maße, englische Wörter) — alle Beispiele und ihre vollständigen Renderings.

Grenzen

  • falzmarke-Markdown (CommonMark-Teilmenge): Absätze, fett, kursiv, Aufzählungen, nummerierte Listen, harter Umbruch, Pipe-Tabellen. Alles andere bricht mit Zeilenangabe ab, statt still etwas anderes zu setzen.
  • Zonengrößen der Norm: Anschrift höchstens 6 Zeilen, Vermerke höchstens 3, Werte im Informationsblock höchstens 32 Zeichen.
  • Keine Bilder im Fließtext — ein Logo gehört ins Profil.
  • Nur DIN 5008. Schweiz (SN 010130) und Österreich (ÖNORM A 1080) sind vorgemerkt (#10); das Frontmatter-Feld norm: ist dafür reserviert.
  • Keine Signatur. Das Unterschriftsbild ist Erscheinungsbild, kein Nachweis. Eine kryptografische Signatur ist Gegenstand von #14.

Weiterlesen

Befehle alle Unterbefehle, Exit-Codes, was geprüft wird
Absenderprofile Profil anlegen, Suchreihenfolge, eigener Briefkopf
Die E-Mail-Fassung Aufbau der .eml, ihre Teile und Grenzen
Datenvertrag jedes Frontmatter-Feld mit Beispiel
falzmarke-Markdown was im Brieftext möglich ist
Normmaße und Quellenlage Sollwerte und ihre Herkunft
Was falzmarke behauptet — und was nicht Grenzen der Normaussage
Aufbau des Repositorys Schichten, Vendoring, warum das Paket unter skill/ liegt
Roadmap in welcher Reihenfolge gearbeitet wird, und was noch offen ist
Changelog · Releases was sich geändert hat

Mitmachen

Fehlerberichte und Vorschläge sind willkommen — siehe CONTRIBUTING.md. Bei einem Geometriefehler bitte die Ausgabe von verify mitschicken; ohne sie lässt sich nicht unterscheiden, ob das Layout oder die Messung danebenliegt.

Sicherheitsrelevantes bitte nicht als Issue, sondern nach SECURITY.md.

Herkunft und Dank

Markdown wurde 2004 von John Gruber gemeinsam mit Aaron Swartz entworfen. Die Spezifikation dazu ist CommonMark (John MacFarlane und Mitwirkende). falzmarke setzt eine dokumentierte Teilmenge davon um — falzmarke-Markdown — und weicht an drei Stellen bewusst ab: HTML wird nie durchgereicht, Links werden nie gesetzt, und eine einzelne 2. Text-Zeile ohne weitere Listenpunkte wird gemeldet — gesetzt mit erhaltenem Startwert, damit nichts still umnummeriert wird.

Das Seitenlayout stammt von typst-letter-pro (MIT) von Sematre und ist unverändert vendort — Prüfsumme in vendor/README.md. falzmarke ergänzt die Schicht darüber: Datenvertrag, Profile, Markdown-Eingabe, Messung und den Skill.

Gesetzt wird mit Typst (Apache-2.0), geparst mit markdown-it-py (MIT), gemessen mit pdfplumber (MIT) und pypdf (BSD-3). Schriften: Libertinus und Source Sans 3 (beide OFL 1.1). Die vollständige Aufstellung samt der Begründung, warum PyMuPDF (AGPL-3.0) ersetzt wurde, steht in THIRD_PARTY_LICENSES.md.

Alle Abhängigkeiten des Programms sind permissiv lizenziert — falzmarke lässt sich damit auch in geschlossene Systeme einbauen. Nicht permissiv ist allein Remotion, womit der Erklärfilm gerendert wird: am Programm ist es nicht beteiligt und wird nicht mitgeliefert.

DIN 5008 ist eine Norm des DIN Deutsches Institut für Normung e. V. falzmarke ist kein Produkt des DIN, steht in keiner Verbindung zum DIN und behauptet keine Zertifizierung. Wie die Maße gemessen wurden, steht in docs/normmasse.md.

Was sich zuletzt getan hat

Die letzten zwei Versionen im Wortlaut. Erzeugt aus CHANGELOG.md — dort ändern, dann python3 scripts/changelog.py.

v0.9.1 — 01.09.2026

verify schlug bei zwei ganz gewöhnlichen Dingen fehl: einem Link und einer nummerierten Liste. Beide Male fehlte inhaltlich nichts — die Prüfung verglich Darstellungsreste.

v0.9.0 ist nicht auf PyPI erschienen. Der Fehler unten (#213) war dreizehn Minuten vor dem Tag gemeldet worden; die Veröffentlichung wurde deshalb angehalten. Auf PyPI folgt v0.9.0 zusammen mit dieser Fassung. Das GitHub-Release v0.9.0 mit den Skill-Paketen ist unverändert gültig.

Behoben

  • verify --email schlug bei jeder nummerierten Liste fehl. Der HTML-Teil setzt die Liste als <ol><li>; die Ziffern erzeugt der Browser über CSS-Counter und stehen deshalb nicht im Textstrom. Der Textteil schreibt sie aus (1. , 2. ). Die Prüfung „Text und HTML sagen dasselbe" zählte sie als fehlende Wörter — einen je Listenpunkt. (#216)
  • verify --mit-quelle schlug bei jedem Markdown-Link fehl. Verglichen wurde die rohe Quelle Token für Token gegen den gesetzten Text, und die Markdown-Schreibweise für Links überlebt das nicht: Gemeldet wurden Syntaxreste wie Blitzsicht](https://…, während inhaltlich nichts fehlte. Damit war Regel 0 — „kein Versand ohne grünen verify --email" — für jede Mail mit Link unerfüllbar. Das ist die schlechtere Sorte Fehlalarm: Sie trainiert darauf, ein rotes verify zu übergehen. (#213)

Infrastruktur

  • Der Sollwert der Ruleset-Durchsetzung steht nur noch an einer Stelle. Er stand zweimal: DURCHSETZUNG in scripts/repo-einstellungen.sh setzte ihn, SOLL_ENFORCEMENT in scripts/repo_pruefung.py prüfte dagegen — zwei unabhängige Konstanten, die nichts zusammenhielt. Der Wächter prüfte also gegen eine Kopie, die nichts setzt. Beide lesen jetzt aus scripts/durchsetzung.py. (#212)
  • Der Drift-Wächter schlägt keinen Fehlalarm mehr, wenn die Domain nicht antwortet. Steht die Homepage dann auf der Release-Seite, ist das der dokumentierte Rückfall und keine Abweichung. Ein Wächter, der grundlos anschlägt, wird abgeschaltet. (#210)

v0.9.0 — 01.09.2026

Aus einem Brief werden viele. Serienbriefe, Brief und Begleitmail in einem Zug, lange Schreiben mit Überschriften und Zitaten — und ein Weg zurück aus einem bestehenden Brief ins Markdown.

Neu

  • Serienbrief aus CSV oder JSON. Eine Vorlage plus Datenquelle ergibt n Briefe: falzmarke serie vorlage.md --daten empfaenger.csv --ziel briefe/. (#3)
  • Brief und Begleitmail in einem Zug — das PDF hängt an der eigenen Mail. Beides konnte das Werkzeug seit der E-Mail-Phase, bisher aber nur nacheinander. (#78)
  • Lange Schreiben: Überschriften, Listen, Zitate und wörtliche Auszüge. Dialekt 1.1 führt ein Versionsfeld ein und schreibt nieder, was 1.0 und 1.1 jeweils zulassen; darauf bauen die neuen Elemente auf. Die Abnahme misst am fertigen PDF, ob ein langes Schreiben mit allem darin trägt — nicht nur jedes Element für sich. (#135, #136, #137, #138)
  • Einen bestehenden Brief einlesen. Alle zwölf Befehle gingen bisher in eine Richtung: Markdown → PDF. Wer einen alten Brief neu setzen wollte, tippte ihn ab. Das Einlesen liefert ein Gerüst mit benannten Lücken statt geratener Inhalte — was es nicht weiß, behauptet es nicht. (#191)
  • PDF/A-3b: eine Datei im PDF statt dahinter. Die Einbettung, die ADR 0033 als wählbare Stufe entschieden und in ein eigenes Issue verwiesen hatte. Sie ist die Vorbedingung für ZUGFeRD. (#114)
  • Die Signatur bekommt drei Blöcke — und ein Gesicht. Person, Kontakt und Recht stehen getrennt statt in einem Block; dazu Logo, Farbe und ein dunkles Schema. Ob das Logo auf dunklem Grund trägt, wird seither gemessen, nicht angenommen. (#105, #142, #154)
  • Was in einer Geschäftsmail steht — und was nicht. Ein Abschnitt in der Stilreferenz, wie es ihn für den Brief gibt: Betreff → Anrede → Grund des Schreibens → Information → gewünschte Handlung → Frist → Gruß → Signatur. (#106)
  • Links gibt es in E-Mails. Im Brief bleiben sie ein Fehler — auf Papier gibt es keinen Link, in einer E-Mail gibt es ihn. Dazu ein Beispiel mit Links und sechs Prüfungen, die daran anschlugen. (#103, #107)
  • Ein Bildzeichen ohne Wortmarke, für Browser-Tabs und überall dort, wo das volle Zeichen mit Schrift zu klein würde. (#82)
  • Vier Anlässe, die im Beispielbestand fehlten, dazu eine Markenkarte im Hochformat. (#139, #146)

Geändert

  • Form A steht nicht mehr auf der eigenen Layoutbasis. Die Maße nannten als einzige Quelle typst-letter-pro — und die liegt unter skill/falzmarke/typst/vendor/. falzmarke setzte das Layout damit und belegte es mit sich selbst. Form A trägt jetzt einen externen Beleg. (#18)
  • Anhanggrenzen in Stufen statt einer Wand, mit Fundstelle je Stufe statt einer einzigen Grenze ohne Begründung. (#183)
  • Adressen werden auf Form geprüft, nicht nur zerlegt. email.utils.parseaddr aus der Standardbibliothek ließ vier von acht ungültigen Adressen durch. (#125)
  • Das 12-pt-Zeilenraster wird gemessen. Der Briefsatz rechnet in einer Grundzeile von 4,2333 mm, und jede „Leerzeile" der Norm ist genau eine Rasterzeile. Darauf beruhen alle Abstände zwischen Betreff, Anrede, Text und Gruß — geprüft wurde bisher alles außer dem Raster selbst. (#140)
  • Zitieren, ohne den Wortlaut anzufassen, und ein Auszug, der über den Seitenwechsel läuft. (#137, #168)
  • Eine zweite freie Umsetzung als Quelle: dinbrief. Die Quellenlage einer Regel wiegt schwerer, wenn sie nicht von einer einzigen fremden Umsetzung abhängt. (#134)
  • Was im PDF steht, ist jetzt auch als das ausgezeichnet, was es ist. (#138)
  • Die Fundstellenprüfung wächst mit dem Regelbestand, statt eine gepflegte Zahl zu führen. (#124)
  • PyPI-Freigabe: eine Wartezeit statt einer Freigabe von Hand (ADR 0036). (#132)

Behoben

  • Telefonnummern mit fünf- oder sechsstelliger Vorwahl wurden als abweichend gemeldet — also die Vorwahlen kleinerer Orte und damit ein erheblicher Teil aller deutschen Festnetzanschlüsse. Gefunden beim ersten Einsatz an einem echten Absenderprofil. (#133)

  • Der HTML-Teil kam in Outlook nicht an, wie er gedacht war. (#104)

  • Jede Frontmatter-Meldung nannte eine Zeile zu viel. (#184)

  • Eine zu lange Auszugszeile wird gemeldet, bevor sie gesetzt wird — vorher fiel sie erst im fertigen PDF auf. (#173)

  • Die Meldung nennt das Zeichen, das wirklich dasteht. Eine einelementige Liste wurde als „einzelner Strich" gemeldet, auch wenn dort ein Stern stand. (#162)

  • Ein Befund nennt die Stelle in der Eingabe, nicht nur das Maß. (#163)

  • pillow fehlte in requirements.txt und im Bootstrap — es war nur transitiv vorhanden und hätte mit der nächsten Abhängigkeitsänderung still verschwinden können. (#194)

  • Auf PyPI zeigten alle sechs Links aufs Repository, keiner auf die Website. (#178)

  • Der Kontrast des Grün-Textes war gegen die falsche Fläche gemessen. docs/marke/erscheinungsbild.md nannte für #2F8642 4,56 : 1 und wies das als gemessen aus. Das stimmte — gegen Papier. Auf der Website steht grüner Text aber überwiegend auf #F4F6F8 und #EAF6EE; dort fiel er auf 4,21 : 1 und 4,10 : 1 und verfehlte WCAG AA. Gefunden hat es axe-core auf falzmarke.com, nicht das Erscheinungsbild: 57 Verstöße auf zehn Seiten.

    Für Text auf hellem Grund gilt jetzt #2A783B — Papier 5,46 : 1, Karte 5,04 : 1, Marke 4,92 : 1. Als Fläche bleibt #3EB057 unverändert.

    Die eigentliche Ursache war nicht die Farbe, sondern die Messung: Die beiden hellen Flächen hatten keinen Namen und tauchten deshalb in keiner Tabelle auf. Sie stehen jetzt als eigene Zeilen im Erscheinungsbild, und das dort eingebettete Prüfskript rechnet gegen alle vier Flächen statt gegen zwei — mit einer Gegenprobe, die den abgelösten Wert weiterhin durchfallen lässt. Website-seitig behoben in customer-falzmarke #27. (#182)

  • Im Feed verlor der Film die Hälfte seiner Aussage, und die Berichtszeile passte nicht mehr in die Aufnahme. (#164, #158)

  • Die Schaufensterbilder zeigten einen Wert, gemessen werden dreiunddreißig. (#159)

  • Dass Tabellenzeilen nicht auf dem Raster stehen, steht jetzt in der Referenz. Ob es so bleibt, ist offen (#151). (#177)

Infrastruktur

Diese Punkte ändern nichts am erzeugten Brief. Sie stehen hier, weil vier davon dieselbe Fehlerart betreffen: Eine Einstellung des Repositories wurde aus dem Zustand des Aufrufs abgeleitet statt aus einem Wert im Repository — und fiel jedes Mal nur auf, weil ein Mensch nachgemessen hat.

  • Kein Workflow schreibt mehr auf main. (#188)
  • Die Pflicht-Checks des Rulesets kommen aus ci.yml, nicht aus dem letzten CI-Lauf. Lief die CI beim Scharfstellen noch, fehlte ein Job in der Liste, ohne dass sich am Workflow etwas geändert hätte — das Ruleset verlor einen Pflicht-Check. (#196)
  • Das main-Ruleset bleibt scharf, wenn niemand etwas anderes verlangt. active ist jetzt der Default; ein Herunterstufen braucht FALZMARKE_RULESET_EVALUATE=1 und wird eigens gemeldet. Vorher hätte ein gewöhnlicher Lauf ohne Umgebungsvariablen den Schutz von main entwaffnet. (#201)
  • Die Homepage des Repositories hängt nicht mehr an einer ungesetzten Variablen. (#199)
  • Ein Drift-Wächter meldet, wenn die gelebten Einstellungen von den Sollwerten abweichenrepo-einstellungen.sh --pruefen, ohne zu schreiben. Er deckt Homepage, Ruleset-Durchsetzung und Pflicht-Check-Liste ab; Beschreibung, Topics und Labels folgen. (#206)
  • Die Lint-Regeln haben Gegenproben. Bis dahin waren nur Geometrie und Emitter sabotiert: Eine Prüfung, deren Bedingung man versehentlich invertiert, wäre grün geblieben. (#197)
  • Ein externer Prüfkatalog wurde gegen den Bestand gemessen, statt als Bauplan übernommen zu werden. (#193)
  • Die Textkanon-Beschreibung nennt die PDF-Prüfung zuerst, nicht das, was es auf GitHub achtmal gibt. (#204)

Davor liegen 19 weitere Versionen — der vollständige Verlauf steht in CHANGELOG.md.

Lizenz

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

falzmarke-0.9.1.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

falzmarke-0.9.1-py3-none-any.whl (889.4 kB view details)

Uploaded Python 3

File details

Details for the file falzmarke-0.9.1.tar.gz.

File metadata

  • Download URL: falzmarke-0.9.1.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for falzmarke-0.9.1.tar.gz
Algorithm Hash digest
SHA256 1598c42716393da7628d4d55959a18470fdc5f700304d54904122dd5ef5b116a
MD5 c30d744dd30867ff3a324edb62cb590d
BLAKE2b-256 bc6534fd17240aae4e29a874e40666991e368ebd1ba3ad2493bf62a740e825d0

See more details on using hashes here.

Provenance

The following attestation bundles were made for falzmarke-0.9.1.tar.gz:

Publisher: release.yml on blitzsicht/falzmarke

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file falzmarke-0.9.1-py3-none-any.whl.

File metadata

  • Download URL: falzmarke-0.9.1-py3-none-any.whl
  • Upload date:
  • Size: 889.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for falzmarke-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a1b8c9bb7a8234f361e4fa79a1d153d6f848653cb2f86d228f73d7db33ff6b98
MD5 d9db934cffc36f14d021877ae5c4e6de
BLAKE2b-256 7964e92207ed07d3e54db7af6a2323595964a048c0e055c0e98bd66db1e5db66

See more details on using hashes here.

Provenance

The following attestation bundles were made for falzmarke-0.9.1-py3-none-any.whl:

Publisher: release.yml on blitzsicht/falzmarke

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.9.8

2 files

0.9.7

2 files

0.9.6

2 files

0.9.5

2 files

0.9.4

2 files

0.9.2

2 files

This release

0.9.1 This release

2 files

0.8.2

2 files

0.7.3

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page