Skip to content

Vier Punkte aus dem Usability-Test (v2.40.3) - #119

Merged
daimpad merged 7 commits into
mainfrom
claude/fix-data-prep-errors-kJYpl
Aug 27, 2026
Merged

Vier Punkte aus dem Usability-Test (v2.40.3)#119
daimpad merged 7 commits into
mainfrom
claude/fix-data-prep-errors-kJYpl

Conversation

@daimpad

@daimpad daimpad commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Aus den acht Anmerkungen eines Usability-Tests die vier, die keine Entscheidung brauchten. Die übrigen vier sind entschieden und liegen als Arbeitspakete bereit.

1. Pflichtfeld-Hinweis

„* Pflichtfeld für die Veröffentlichung. Als Entwurf können Sie den Datensatz jederzeit speichern."

Der bisherige Satz stolperte über sich selbst.

2. Beispiele in Tooltips fester Auswahllisten

Ein Beispiel, das nur die Optionen des Dropdowns wiederholt, hilft niemandem. Der Tester fand einen Fall (Thema) — eine systematische Suche nach select-Feldern mit add_options und „Beispiel:" im Hilfetext ergab acht:

Thema · Sprache · Format · Lizenz · Verfügbarkeit · Aktualisierungsfrequenz · Verwaltungsebene · HVD-Kategorie

Erklärende Sätze sind geblieben („Diese bestimmt, wie andere die Daten nutzen dürfen."), gestrichen wurde nur der Beispielteil.

3. „Kardinalität" → „Multiplizität"

Den Begriff verwendet die deutsche Spezifikation DCAT-AP.de. 52 Stellen im Feld-Katalog plus die daraus generierte Feld-Referenz.

Offenlegung: Hier verlasse ich mich auf die Quellenangabe des Testers. Die gebündelten deutschen Shape-Dateien verwenden keinen der beiden Begriffe, und dcat-ap.de ist über den Egress-Proxy dieser Umgebung nicht erreichbar — ich konnte es nicht selbst nachschlagen.

4. dct:subject war fälschlich als DCAT-AP-Definition ausgewiesen

Der Tester vermutete es, ich habe es nachgeprüft: Ein Abgleich aller 43 Katalog-Eigenschaften gegen die gebündelten offiziellen SHACL-Shapes ergibt genau zwei Ausreißer.

Eigenschaft Befund
dct:subject Gehört nicht zum Profil — in den Shapes für Datensätze nirgends
dcatap:hvdCategory Stammt aus der HVD-Erweiterung (EU-VO 2023/138), nicht aus DCAT-AP 3.0

Beides steht jetzt in der jeweiligen Definition. Die Eigenschaften bleiben erhalten: RDF erlaubt zusätzliche Aussagen, unsere SHACL-Prüfung bleibt grün, und CESSDA wie ZiviZ sind für die Zielgruppe gewollt.

Beim ersten Anlauf hatte ich mich hier selbst vertan — mein Skript warf dct:title als „nicht im Profil" aus, was unmöglich stimmen kann. Ursache: Turtle-Präfixe gelten pro Datei, und Dublin Core heißt in den Shapes dc:, nicht dct:. Nach der Korrektur bestehen die Kontrollfragen (dct:title ✓, dcat:theme ✓).

Aus der Gegenprüfung nachgezogen

Ich habe die Änderung von vier unabhängigen Prüfern gegenlesen lassen, jeder Befund adversarisch gegengeprüft. Zwei haben es durch die Widerlegung geschafft:

  • Die Beschreibung der Verwaltungsebene nannte „Kreis" und „Kommune"; die Auswahlliste bietet „Landkreis" und „Gemeinde". Vorbestehend, fiel aber erst auf, als der Tooltip dort nur noch das technische Label trug.
  • Zehn verwaiste Übersetzungseinträge blieben ohne Fundstelle im Code zurück. bin/check-i18n.py prüft nur auf fehlende, nicht auf überzählige Einträge — die CI hätte das nie gemeldet.

Geprüft

243 Tests grün · PHPCS ohne Befund · bin/verify-package.py und bin/check-i18n.py sauber · Feld-Referenz neu generiert.

Version 2.40.2 → 2.40.3.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq


Generated by Claude Code

claude added 7 commits August 27, 2026 10:03
Aus den acht Anmerkungen des Testers die vier, die keine Entscheidung
brauchten. Die übrigen vier sind entschieden und als Arbeitspakete notiert.

1. Pflichtfeld-Hinweis umformuliert. Der bisherige Satz stolperte über sich
selbst; der Vorschlag des Testers ist schlicht besser.

2. Beispiele aus den Tooltips fester Auswahllisten entfernt. Ein Beispiel, das
nur die Optionen des Dropdowns wiederholt, hilft niemandem. Der Tester fand
einen Fall — eine systematische Suche nach select-Feldern mit add_options und
"Beispiel:" im Hilfetext ergab acht: Thema, Sprache, Format, Lizenz,
Verfügbarkeit, Aktualisierungsfrequenz, Verwaltungsebene, HVD-Kategorie.
Erklärende Sätze sind geblieben, gestrichen wurde nur der Beispielteil.

3. "Kardinalität" heißt jetzt durchgängig "Multiplizität" — so nennt es die
deutsche Spezifikation DCAT-AP.de. 52 Stellen im Katalog plus die generierte
Feld-Referenz. Offenlegung: Ich verlasse mich hier auf die Quellenangabe des
Testers. Die gebündelten deutschen Shape-Dateien verwenden keinen der beiden
Begriffe, und dcat-ap.de ist über den Egress-Proxy nicht erreichbar.

4. dct:subject war fälschlich als "DCAT-AP-Definition" ausgewiesen. Ein
Abgleich aller 43 Katalog-Eigenschaften gegen die gebündelten offiziellen
SHACL-Shapes (Turtle-Präfixe dateiweise aufgelöst — Dublin Core heißt dort
"dc:", nicht "dct:") zeigt genau zwei Ausreißer: dct:subject gehört nicht zum
Profil, und dcatap:hvdCategory stammt aus der HVD-Erweiterung statt aus
DCAT-AP 3.0. Beides steht jetzt in der jeweiligen Definition. Die Eigenschaften
bleiben erhalten — RDF erlaubt zusätzliche Aussagen, und CESSDA wie ZiviZ sind
für die Zielgruppe gewollt.

Aus der Gegenprüfung nachgezogen: Die Beschreibung der Verwaltungsebene nannte
"Kreis" und "Kommune", die Auswahlliste bietet "Landkreis" und "Gemeinde".
Außerdem zehn verwaiste Übersetzungseinträge entfernt, die durch die
Textänderungen ohne Fundstelle im Code zurückblieben; bin/check-i18n.py prüft
nur auf fehlende, nicht auf überzählige Einträge.

243 Tests grün, PHPCS ohne Befund, Paketprüfung und i18n sauber.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
Eine adversarische Prüfung des vorigen Commits durch vier unabhängige Linsen
hat neun Befunde bestätigt. Sechs davon waren echte Halbheiten meinerseits:

- Der neue Pflichtfeld-Wortlaut stand nur in der Legende unter dem Formular.
  "Als Entwurf können Sie jederzeit unvollständig speichern" lebte weiter in
  der Meldung nach blockierter Veröffentlichung (class-validation.php), auf der
  Einstiegsseite (class-admin.php) und im README.
- Die Einstiegsseite versprach "Jedes Feld hat hilfreiche Beispiele, die Sie
  über das ⓘ-Symbol einblenden" — nach dem Entfernen der acht Beispiele für
  fünf Felder schlicht falsch. Der Satz benennt jetzt die Aufteilung: ⓘ zeigt
  den DCAT-AP-Begriff, "Mehr erfahren" die ausführliche Erklärung.
- "Kardinalität" blieb in TECHNICAL-SPEC.md stehen — ausgerechnet dort, wo
  dieselbe Feld-Registry beschrieben wird, deren Docblock ich umgestellt hatte.
  Die Behauptung "durchgängig" im Changelog stimmte damit nicht.
- Die Spaltenabkürzung "Norm-Kard." in zwei Tabellen hätte eine Wortersetzung
  nie erfasst. Jetzt "Norm-Mult." samt Legende — eine Legende, die eine
  Abkürzung auf ein anderes Wort auflöst, wäre schlimmer als der alte Begriff.
- Die Kreis/Kommune-Korrektur war halb: Der fachliche Beschreibungstext nannte
  weiter die falschen Ebenen.
- "die mitgelieferten Kern-Shapes prüfen sie deshalb nicht" war zu schwach
  formuliert: KEINE der sechs Shape-Dateien erwähnt hvdCategory (case-insensitive
  Suche über config/shacl/*.ttl: null Treffer).

Zwei weitere Befunde bleiben bewusst offen, weil sie die eben getroffene
Entscheidung U-1 vorwegnehmen: Die Beispiele stehen weiterhin im
"Mehr erfahren"-Panel, und fünf Tooltips zeigen nur noch den technischen
Begriff. Genau so ist die Rollentrennung gedacht — U-1 räumt die verbliebene
Doppelung auf.

243 Tests grün, PHPCS ohne Befund, i18n und Paketprüfung sauber,
Feld-Referenz neu generiert.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
… + U-2)

Zwei Punkte aus dem Usability-Test, die zusammengehören.

U-1 — Rollentrennung: Das ⓘ-Tooltip trägt nur noch den DCAT-AP-Begriff, alles
Erklärende steht im "Mehr erfahren"-Panel. Vorher stand beides an beiden Orten,
beim Herausgeber sogar mit unterschiedlichen Beispielen. Betrifft 42 Felder.

Eine Inventur über alle Tooltips hat dabei zwei Dinge zutage gefördert, die ein
blindes Kürzen zerstört hätte:

- Neun Tooltips trugen BEDIENHINWEISE, die im Katalog fehlten — die Vorbelegung
  der Zugriffsrechte, "zwei Wege, einer genügt" bei der Zugriffs-URL, dass HVD
  nur öffentliche Stellen betrifft, dass bei Auflösung, Medientyp und Typ eine
  URL statt einer Bezeichnung erwartet wird. Diese Sätze sind jetzt in
  desc_human überführt, statt verloren zu gehen.
- Fünf Felder hatten überhaupt keinen Fachbegriff im Tooltip, sondern schon
  dort Prosa: die drei Kontaktfelder, die eigene Lizenz-URI und die
  HVD-Kennzeichnung. Sie tragen jetzt den Begriff, den das JSON-LD tatsächlich
  ausgibt (vcard:fn, vcard:hasEmail, vcard:hasURL, dct:license,
  dcatap:applicableLegislation) — am Builder nachgeprüft.

Eine Ausnahme mit Begründung: Das Wiederholfeld für weitere Distributionen
behält seinen Hilfetext. Für dieses Feld gibt es keinen Katalogeintrag, das
Panel erscheint dort also gar nicht — der Tooltip ist die einzige Erklärung.

U-2 — Merkmalsliste: Über der Definition stehen jetzt zwei Zeilen, Eigenschaft
und Multiplizität. Meine ursprüngliche Annahme, beides läge in
config/dcat-ap-fields.php strukturiert vor, war falsch: Das ist die
Punkte-Registry der Qualitätsberechnung mit zehn Einträgen, sie deckt 13 der 53
Felder ab. Die Multiplizität stand dafür in 49 Definitionstexten
maschinenlesbar; vier habe ich präzisiert, dann ist sie als eigener Schlüssel
`cardinality` in alle 53 Einträge gewandert. Der Wertebereich bleibt außen vor
— er wäre für 40 Felder geraten gewesen.

Zwei neue Unit-Tests halten den strukturierten Wert und die Angabe im
Definitionstext zusammen. Zwei neue E2E-Tests prüfen das Panel (beide Zeilen mit
Wert, darunter beide Langtexte) und dass im Tooltip kein Beispiel zurückkehrt.

Nebenbei behoben: bin/check-i18n.py hat config/ nie gescannt, obwohl
mqa-metrics.php und dcat-ap-fields.php ihre Beschriftungen über __() führen —
für 31 Zeichenketten hätte eine fehlende Übersetzung also nie jemand gemeldet.
Aufgefallen, weil ich beim Aufräumen der Kataloge beinahe genau diese Einträge
gelöscht hätte; die Prüfung hätte geschwiegen.

Dazu die Schlagwort-Beschreibung, deren Beispiel der eigenen Regel widersprach
(ein Wort je Zeile, dann ein Komma-Beispiel), und die README, die noch
"Jedes Feld hat konkrete Beispiele" im Tooltip versprach.

245 Tests grün, PHPCS ohne Befund, i18n und Paketprüfung sauber.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
Am Fuß jedes „Mehr erfahren"-Panels steht jetzt „Im Standard nachlesen:
Datensatz" bzw. „: Distribution" mit Verweis auf den passenden Abschnitt von
DCAT-AP.de 3.0. Auch in der Feld-Referenz als eigene Tabellenzeile.

Bewusst je Klasse und nicht je Feld: Die feldgenauen Anker der Spezifikation
(etwa #datensatz-herausgeber) ließen sich von hier aus nicht überprüfen, weil
dcat-ap.de über den Egress-Proxy nicht erreichbar ist. 53 ungeprüfte Anker
hätten geheißen, dass einige ins Leere zeigen; bei den drei Klassen-Ankern
führt ein Irrtum schlimmstenfalls an den Anfang des richtigen Dokuments.

Damit der Link auf den richtigen Abschnitt zeigt, trägt der Katalog jetzt
`entity`: 41 Felder am Datensatz, 12 an der Distribution. Die Zuordnung ist
nicht geschätzt, sondern aus odw_build_distribution_node() abgeleitet — dort
steht, welche Werte in den Distributions-Knoten wandern. Gegen die
Registry-Angaben in config/dcat-ap-fields.php geprüft: null Abweichungen über
den eindeutigen Meta-Key.

Zwei scheinbare Abweichungen bei dist_title und dist_description waren
Artefakte der Gegenprobe selbst: Beide tragen dct:title bzw. dct:description,
und über diesen Fallback traf die Prüfung den Datensatz-Eintrag der Registry.
Am Builder gegengelesen — beide werden tatsächlich in den Distributions-Knoten
geschrieben.

Drei neue Unit-Tests: jeder Eintrag hat eine gültige Klasse, jede Klasse löst
sich zu einer URL auf der offiziellen Domain auf, und die Liste der
Distributions-Felder stimmt mit dem Builder überein. Dazu eine E2E-Zusicherung
auf den Link im Panel.

248 Tests grün, PHPCS ohne Befund, i18n und Paketprüfung sauber.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
Das Auswahlfeld in Tab 1 und das Tipp-Feld unter „Erweiterte Angaben" sind
durch ein Mehrfachfeld mit den EU-Themen ersetzt. dcat:theme erlaubt laut
Profil 0..n Themen; vorher waren es höchstens zwei, auf zwei verschiedene Arten
zu bedienen.

Der Umbau war größer als mein Kostenvoranschlag: Carbon Fields legt
Mehrfachwerte nicht unter `_odw_theme` ab, sondern unter `_odw_theme|||N|value`.
Damit hätten zwei Stellen still ihre Funktion verloren, die die Datenbank
direkt abfragen:

- der Themenfilter des Katalogs (?theme=…) über eine meta_query, und
- die Sortierung der Listenspalte über meta_key/meta_value.

Beides läuft jetzt über eine flache Spiegelung, die bei jedem Speichern
mitgeschrieben wird: `_odw_theme_index` mit einer Zeile je Thema für den
Filter, `_odw_theme_sort` mit dem Label des ersten Themas für die Sortierung.
Der bestehende E2E-Test auf ?theme=Bildung prüft den Filter mit.

Eine einmalige Migration überführt bestehende Datensätze beim ersten Aufruf des
Backends: alter Einzelwert plus das frühere Zusatzfeld werden zusammengeführt,
über carbon_set_post_meta() geschrieben und die alten flachen Zeilen entfernt.
Bewusst über die öffentliche API und nicht über selbstgebaute Schlüssel — das
Format ist ein Interna von Carbon Fields.

Ein Normalisierer trägt die Last: normalize_themes() nimmt Array, einzelnen
String und die deutschen Kurzlabels der Auswahlliste vor v2.5.0 („Bildung"),
löst alles zu EU-URIs auf und entdoppelt. Sieben Fälle als Datenprovider
abgesichert — darunter, dass „Bildung" und „Kultur" beide auf EDUC zeigen und
nur einmal erscheinen.

Mit angepasst: JSON-LD-Builder, Qualitätsprüfung, Listenspalte, Shortcode,
Batch-Import (nimmt jetzt mehrere Themen an), Demo-Datensatz, E2E-Saat,
SHACL-Fixtures und der Feld-Katalog (theme_uri entfällt, 52 statt 53 Felder).

Zwei bestehende Tests haben den Umbau erwischt und mussten mitziehen: Der
Abdeckungstest kannte den Feldtyp „multiselect" nicht, und das
Terminologie-Glossar verlangte „Thema" im Singular. Beide prüfen jetzt das
Richtige, statt das Alte.

255 Tests grün, PHPCS ohne Befund, i18n und Paketprüfung sauber.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
…ck (U-5)

Engagementfeld und Contributor-ID waren Textfelder mit einer <datalist>
dahinter. Man musste erst tippen, um überhaupt zu sehen, dass es eine
Auswahl gibt — und wer daneben tippte, bekam einen Wert ohne URI. 16 bzw.
69 Einträge passen in eine Liste:

- odw_engagementfeld → multiselect (dct:subject erlaubt 0..n)
- odw_contributor_id → select

CESSDA bleibt bei mehreren hundert Konzepten eine Vorschlagsliste, aber
eine eigene statt des nativen <datalist>: Sie klappt beim Anklicken auf,
grenzt beim Tippen ein und lässt sich mit Pfeiltasten, Enter und Escape
bedienen. Nebeneffekt: gleiches Verhalten in allen Browsern und im
E2E-Test überhaupt prüfbar — ein datalist-Popup ist Browser-Chrome.

Speicherform: Wie beim Thema ändert die Mehrfachauswahl das Meta-Layout
(Carbon Fields legt Mehrfachwerte unter _odw_engagementfeld|||N|value ab).
Die einmalige Migration aus U-4 überführt jetzt beide Felder und löst
dabei einen von Hand eingetippten Namen zur Vokabular-URI auf. Ein
Flach-Spiegel wie _odw_theme_index ist hier nicht nötig: Auf keines der
beiden Felder läuft eine meta_query.

Weiter:
- odw_build_dataset_jsonld() gibt alle gewählten Engagementfelder aus
- Shortcode zeigt alle Labels statt der rohen URI
- resolve_label() kennt engagementfeld und contributors
- data-odw-vocab entfällt samt Auslieferung der Vokabulare an jede
  Admin-Seite — es hatte keine Nutzer mehr

Tests: 265 grün (10 neue), PHPCS sauber, Paketprüfung ok, i18n vollständig.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
Drei Befunde aus dem roten Lauf zu U-4:

- /catalog?theme=Bildung fand nichts mehr. Der Filter löste den Parameter
  über resolve_theme_uri() auf, der Index wird aber über normalize_themes()
  geschrieben — und das EU-Vokabular kennt „Bildung" nicht, dort heißt es
  „Bildung, Kultur und Sport". Der Filter nimmt jetzt dieselbe Auflösung
  wie das Speichern; Harvester mit dem alten deutschen Kurznamen bekommen
  weiter Treffer. Genau der Fall, für den der E2E-Test da ist.

- PHPStan kannte carbon_set_post_meta nicht. Das Ignore-Muster listete nur
  den Getter; class-setup.php fiel nicht auf, weil dort ein
  function_exists()-Guard steht.

- Die E2E-Selektoren auf die Mehrfachauswahl trafen nichts. Carbon Fields
  3.6 rendert multiselect über react-select: ein <div class="cf-multiselect__select">,
  kein <select multiple>. „cf-multiselect" allein gibt es nicht, das ist
  nur der classNamePrefix. Der Test auf das Engagementfeld öffnet das Menü
  jetzt außerdem, bevor er auf einen Optionstext prüft — react-select hängt
  die Optionen erst dann ins DOM.

https://claude.ai/code/session_01JB1xUQM892bVZ4Yv3MZjvq
@daimpad
daimpad merged commit d3a14f0 into main Aug 27, 2026
22 checks passed
@daimpad
daimpad deleted the claude/fix-data-prep-errors-kJYpl branch August 27, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants