ADR-0065: Chrome/PDFium-Viewerregression und getrenntes Semantikgate

  • Status: angenommen; Slice G implementiert, CI-/Preview-verifiziert und produktiv ausgeliefert; Tag-Semantik offen
  • Datum: 4. September 2026
  • Issues: #547, #333
  • Vorgänger: ADR-0064

Befund und Entscheidung

Nach Slice F fehlt eine wiederholbare Prüfung der synthetischen vier Tiers im Chrome/PDFium-Viewer. Der Browser muss die PDF selbst anzeigen: HTML-Druck, Poppler-Raster oder eine erfolgreiche Downloadantwort belegen diesen Pfad nicht.

Slice G verwendet den vorhandenen Pin Playwright 1.60.0, Chrome for Testing 148.0.7778.96, Revision 1223. Der vollständige Browser läuft mit seinem standardmäßigen PDF-Viewer und OOPIF-Verhalten im neuen Headless-Modus. Das separate Headless-Shell-Artefakt wird nicht verwendet. Es gibt keinen PdfTags-Override und keine Änderung an einem persönlichen Browserprofil.

  1. qa:pdf:ua-shadow prüft dieselben vier kurzlebigen Slice-E-Dateien mit veraPDF, Poppler, auf macOS Apple PDFKit/Quartz und zusätzlich Chrome/PDFium. qa:pdf:chrome führt den Chrome-Anteil separat aus, auch gegen zuvor aus einem geschützten Preview geladene Dateien.
  2. Der Browser öffnet ausschließlich die vier lokalen PDFs. Die Ressourcenpolicy blockiert andere Inhaltsressourcen und WebSockets; blockierte Versuche schließen den Lauf. Keine DB, Session, Provider, Nutzerdaten oder persönlichen Browserprofile sind erforderlich.
  3. Pro Tier werden alle acht Seiten über das Seitennummernfeld des echten Viewers erreicht. Bei 100 % und 1.200 × 1.400 Pixeln muss der gesamte A4-Seitenausschnitt innerhalb des Viewports liegen. PNGs stammen aus dem Browser-Compositor; RGB wird für die vorhandenen Grenzen zu Graustufen gewichtet. Weiße Ränder, Helligkeit, Schwarzflächen und sichtbarer Body-Ink sind verpflichtend. Leere, schwarze, abgeschnittene oder Thumbnail-Raster bestehen nicht. Die Prüfung wiederholt bei asynchronem Paint nur echte Screenshots und hat ein festes Timeout.
  4. chrome://accessibility liefert mit API-Typ blink den zusammengeführten Browserbaum einschließlich pdfRoot. Ein CDP-DOM-Baum mit lediglich EmbeddedObject genügt nicht. Acht Seitenregionen liefern Text für den bestehenden seitenspezifischen Slice-E-Inhalts- und Tiervertrag. Zwei benannte Linkobjekte müssen exakt Methodik und Datenschutz adressieren.
  5. Darstellungs-/Textregression und Tag-Semantik sind getrennte Gates. Die Rollenbilanz verlangt für das Strukturprobe-Gate 20 Überschriften (Slice H; zuvor 19 in Slice G), sieben Tabellen, sechs Listen, drei beschriebene Bilder und zwei benannte Links. Fehlende Rollen erscheinen explizit als accepted: false im JSON-Nachweis. --require-tagged-semantics beendet einen solchen Lauf mit Exit 1. Die normale CI-Darstellungsregression darf bestanden sein, während die vollständige Chrome-Barrierefreiheitsabnahme offen bleibt. Selbst ein positiver Rollenzähler ersetzt keine Prüfung von Inhalt und Lesereihenfolge mit assistiver Bedienung.
  6. Dateihashes, tatsächliche Browserversion, Textzeichen, Rollen, Baumhash und 32 Screenshot-Hashes werden erfasst. Ohne explizites --output-dir räumt der Prüfer seine temporären Dateien auch bei Fehlern auf; mit diesem Parameter bleiben die synthetischen QA-Artefakte für die visuelle Abnahme.
  7. CI nutzt das bereits SHA-256-gepinnte Linux-Browserarchiv aus Slice A. Über PDF_CHROME_EVIDENCE_DIR hält der integrierte CI-Lauf seine synthetischen Screenshots, Bäume und JSON-Zusammenfassung als privates GitHub-Actions-Artefakt für sieben Tage vor. pngjs@7.0.0 ist ausschließlich eine Entwicklungsabhängigkeit. Weder Browser noch QA-Helfer werden in den öffentlichen PDF-Produktpfad eingebaut.

Nachgewiesene Grenze

Im ersten Lauf des unveränderten Standardviewers wurden Text und zwei Links, aber keine Tabellen-, Listen- oder Bildrollen exponiert. Das passt zur Quellcodekonfiguration genau dieser Chrome-Version: kPdfTags ist standardmäßig deaktiviert. Das ist ein Befund des getesteten Stacks, keine Aussage über jede Chrome-Version oder jedes Endgerät. Eine experimentelle Aktivierung darf nicht als Standardviewer-Abnahme gelten.

Der öffentliche Renderer bleibt React-PDF, der synthetische Shadow bleibt slice-e-1 und Preview-only. Chrome-Tag-Semantik, echte Karteninhalte, kontrollierter Produktrollout und PDF/UA-Live-Readback eines echten Nutzerreports bleiben offen. Issue #333 bleibt offen.

Reproduktion

npm run qa:pdf:chrome
npm run qa:pdf:chrome -- --output-dir .tmp/chrome-local
npm run qa:pdf:chrome -- --pdf-dir .tmp/preview-pdfs --output-dir .tmp/chrome-preview
npm run qa:pdf:chrome -- --pdf-dir .tmp/preview-pdfs --require-tagged-semantics
npm run qa:pdf:ua-shadow

Das Eingabeverzeichnis enthält free.pdf, standard.pdf, premium.pdf und planer.pdf aus dem synthetischen Shadow. Der letzte strikte Chrome-Aufruf muss beim dokumentierten Semantikdefizit fehlschlagen. Er ist ein Produktfreigabegate, kein als Erfolg maskierter Negativtest.

Slice-G-Nachweis