fix(dashboard): UX-Konsistenz P4–P8 — kategoriale Palette, Einheiten/Ticks, Tooltip-Limit, tote UI-Reste (#204)#221
Merged
Merged
Conversation
…Ticks, Tooltip-Limit, tote UI-Reste (#204) P4: --enc-1/--enc-4 (kategoriale Palette fuer PDF-Serien/Agenten) von Coral auf Violet umgestellt — Coral war bit-identisch mit der Ampel-Bad-Farbe, dieselbe Kachel-Farbe stand gleichzeitig fuer "Ampel schlecht", "1. PDF" und "1. Agent" (Scatter + Agenten-Chart betroffen). P5: "Laufzeit je Agent" (ch8) baute die Achse bisher auf Sekunden-Rohdaten auf und rechnete erst zur Anzeige in Minuten um — Chart.js waehlte "schoene" Tick-Schritte in Sekunden (2000er-Schritte), die nach der min-Umrechnung krumm wirkten (0/33/67/100min). Fix: Daten vor dem Chart-Aufbau in Minuten konvertiert, Achse jetzt nativ minutenbasiert wie ch6 (0/50/100/.../300 min, mit Leerzeichen). Ausserdem vier gleichnamige "Laufzeit"-Scopes ohne Kennzeichnung: Titel "Token-Verbrauch/Laufzeit pro Run" -> "... je Version" (Achse zeigte schon immer Versionen, nicht Runs), KPI-Label "Laufzeit" -> "Laufzeit (aktuell)", Strip-Zelle "... Laufzeit" -> "... Laufzeit (gesamt)" (dabei Locale-Fund an derselben Stelle mitgefixt: Punkt statt Komma). P6: bereits durch PR #205 gefixt (Tooltip-Limit 3 + "+n weitere"), hier nur verifiziert. P7: toggleRow() war nie verdrahtet (kein Caller, kein .detail-row-Markup) — Funktion + die dafuer reservierte leere Gutter-Spalte in der Vergleichs- tabelle entfernt (colspan 9 -> 8). P8 (gesammelt): (a) Filterwechsel/15s-Poll ohne Lade-Feedback -> .refreshing dimmt bestehenden Inhalt waehrend fetch; (b) Trade-off-Legende (ch3) von ~19 Farben auf Top-5 + graue "Weitere"-Sammelserie reduziert (Muster wie im Scatter, PR 38), Bubble-Groessen-Bedeutung im Untertitel ergaenzt; (c) _chart_longitudinal liefert jetzt "n" (Runs) pro Punkt, Tooltip warnt bei n=1 vor duenner Basis; (d) Kalibrierungs-Tabelle: leere Spalten (Human- Fehlerquote/Agreement) mit min-width + Hover-Hinweis gegen Spalten-Kollaps; (e) KPI "Automatisch akzeptiert" markiert (n=X*) mit Tooltip, wenn die n-Basis von Fehlerquote/Belegrate abweicht (Log-Runs vs. evaluierte Notes); (f) Sektions-Untertitel "Qualitaet" korrigiert (nannte "nach Version", keiner der beiden Charts ist ein Versions-Chart); (g) redundante Klick-Sparkline an der Accept-Kachel entfernt (Duplikat zu ch4 "Akzeptanzrate ueber Versionen"); (h) natives PDF-<select> bekommt text-overflow:ellipsis (vorher hartes Abschneiden ohne Hinweis). TDD fuer P8c: 2 neue Tests fuer _chart_longitudinal (RED vor Implementierung, GREEN danach). Suite 5693 -> 5695, 0 failed. Verifikation: Playwright (Vorher/Nachher-Screenshots hell+dunkel + programmatische Checks, alle GREEN). Mistral-Cross-Review: keine Befunde. Konfliktflaeche mit ungemergten PRs #217/#219 (beide aendern dieselbe HTML): Chart-Titel/-Untertitel und die KPI-nTag-Zeile ueberschneiden sich mit #219s Tooltip-Markup — Details in PR-Body. Closes #204
…nden-Randfaelle (#204 Nachbesserung) Externes Review (Fable + Qwen) an PR #221 fand 5 Nachbesserungspunkte: 1. loadAndRender(): catch-Block entfernte .refreshing bisher unbedingt, obwohl der Erfolgspfad per seq-Guard vor Stale-Renders schuetzt — bei ueberlappenden Requests (schneller Filterwechsel) riss ein fehlschlagender AELTERER Request die Dimmung fuer einen noch laufenden NEUEREN weg. Entfernung jetzt an denselben seq-Guard gebunden. 2. Refresh-Dimmung (pointer-events:none auf .main) sperrte kurzzeitig auch die Filterbar beim automatischen 15s-Poll. loadAndRender(manual=true) -Parameter; Poll ruft loadAndRender(false) — dimmt nur bei manuellem Filterwechsel. 3. ch8-Achse erzeugte bei kleinen Datenstaenden (kumulierte Laufzeit <60s, Onboarding-Szenario) fraktionale Ticks mit voller Float-Praezision. ticks.precision:1 + Ausgabe ueber bestehendes _fmtDE (Komma, 1 Dezimale). 4. ch3-Legende gruppierte schon ab >5 Keys statt wie Vorbild ch2 ab >6 (t.enc.length) — bei exakt 6 PDFs erschien unnoetig "Weitere (1 PDFs)" inkl. Singular-Fehler. Schwelle angeglichen, Label pluralisiert korrekt. 5. renderKpis: bei gleichzeitigem n<20 UND abweichender Stichprobenbasis erklaerte der title nur die n<20-Bedeutung, der Asterisk blieb unerklaert. title kombiniert jetzt beide Bedeutungen. Test-Assertion in test_dashboard_quick_wins.py an den neuen setInterval(() => loadAndRender(false), 15000)-Aufruf angepasst. PR-Body von PR #221 korrigiert: "#217 keine Ueberschneidung" war falsch (.kpi.no-spark kollidiert mit #217s mehrzeiligem .top-Block), #219-Konflikt- liste war unvollstaendig (renderStrip-cell()-Aufrufe fehlten, Tokens-Zelle). Suite: pytest generative lib/decision_engine/tests shared/tests -q -> 5695 passed, 3 skipped, 4 deselected, 0 failed. ruff format/check clean.
# Conflicts: # internal/dashboard/eval_dashboard.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Schliesst #204 (Punkte P4–P8; P1–P3 bereits in PR #207 gemergt).
Punkt-für-Punkt
--enc-1/--enc-4(kategoriale Palette) von Coral auf Violet umgestellt,--enc-2/3/5/6(Teal/Amber) unverändert--coral(Ampel-Bad) — dieselbe Kachel-Farbe stand für "Ampel schlecht", "1. PDF-Serie" (Scatter, Trade-off-Scaling) und "1. Agent" (Balken) gleichzeitig. Nur Rot/Grün laut Issue-Wortlaut ausgetauscht, Amber blieb (nicht als Problem benannt, Prinzip Scope-Discipline).i<3+ „+n weitere"-Footer)toggleRow()entfernt (nicht angeschlossen)onclick), kein.detail-row-Markup existierte je — kein halbfertiges Feature mit erkennbarem Fortsetzungspfad, sondern komplett totes Konstrukt. Zusätzlich die dafür reservierte leere Gutter-Spalte (width:28px, Header + jede Zeile) entfernt,colspan9→8 angepasst. Der sichtbare Hinweis-Text war bereits in PR #205 entfernt worden..main.refreshing(Opacity .55,pointer-events:none) beim Filterwechsel, entfernt nach Render/Fehler.chart-body.loading, voller Shimmer) — der würde alten, noch gültigen Inhalt komplett verdecken statt nur zu dimmen. Nachbesserung: dimmt nur bei manuellem Filterwechsel, nicht beim 15s-Poll (s. unten).p-sub, nicht imp-title(der trägt bereits den #219-Hint)._chart_longitudinalliefert neu"n"(Run-Anzahl) pro Datenpunkt; ch4-Tooltip zeigt bei n=1 „n=1 Run — dünne Basis"_n/PDFs-Tooltip). TDD: 2 neue Tests, RED vor Implementierung.<th>für Human-Fehlerquote/Agreement mitmin-width; Dash-Platzhalter bekommentitle="Noch nicht human-gelabelt"(n=X*)+ Tooltip, wenn die Basis von der gepoolten Fehlerquote/Belegrate-Basis abweichtonclick,.no-spark-Klasse, defensiver Guard in_openKpiSpark).fselectbekommtoverflow:hidden; text-overflow:ellipsis; white-space:nowrapNachbesserung (Fable + Qwen Cross-Review, 2026-07-12)
Externes Review (Fable + Qwen, konsolidiert) fand 5 Code-Punkte + 2 fehlerhafte/unvollständige Angaben in diesem PR-Body. Alle umgesetzt bzw. korrigiert:
loadAndRender(): Erfolgspfad rendert nur beiseq===_loadSeq(Stale-Schutz gegen überholte Requests), aber dercatch-Block entfernte.refreshingunbedingt — bei überlappenden Requests (schneller Filterwechsel) verschwand die Lade-Dimmung, obwohl ein neuerer Request noch lief.catchan denselbenseq-Guard gebunden (if (seq === _loadSeq) ...classList.remove('refreshing')).pointer-events:noneauf.main, das auch die Filterbar enthält) sperrte kurzzeitig auch beim automatischen 15s-Poll die Filterleiste — nicht nur bei manuellen Filterwechseln.loadAndRender(manual = true)-Parameter; dersetInterval-Poll ruftloadAndRender(false)— dimmt nur noch bei vom Nutzer angestoßenen Loads.ticks.precision:1(rundet den Tick-Schritt auf 1 Dezimale) + Ausgabe über das bestehende_fmtDE(Komma statt Punkt, konsistent zum Tooltip derselben Achse).t.enc.length) — bei exakt 6 PDFs erschien dadurch unnötig eine „Weitere (1 PDFs)"-Gruppe trotz vollständig eindeutiger Farbzuordnung, plus Singular-Fehler ("1 PDFs").MAX_COLORED_SCALINGvon hartcodiert5auft.enc.length(= 6) umgestellt, identisch zu ch2; Label pluralisiert korrekt ("1 PDF" vs. "N PDFs").renderKpis: wenn n<20-Warnung UND abweichende Stichprobenbasis (nDiffers) gleichzeitig zutrafen, erklärte dertitlenur die n<20-Bedeutung — der Asterisk (abweichende Basis) blieb unerklärt, weil der ternary rein exklusiv war (nWarn ? ... : (nDiffers ? ... : '')).titlekombiniert jetzt beide Erklärungen, wenn beide Bedingungen zutreffen.renderStripscell()-Aufrufe fehlten). Beide jetzt korrigiert, siehe unten.Verifikation:
node --checkauf extrahiertem<script>-Block (Syntax), volle Suite +ruff format --check+ruff checkerneut grün (s. „Suite & Lint" unten, inkl. 1 angepasster Test-Assertion für den neuensetInterval(() => loadAndRender(false), 15000)-Aufruf).Konfliktflächen mit #217 / #219 (beide ungemergt, ändern dieselbe HTML)
Empfohlene Merge-Reihenfolge: #217 → #219 → dieser PR.
Korrektur ggü. der ersten Fassung dieses Abschnitts (Fable-Review, 2026-07-12): „#217 keine Überschneidung" war falsch — es gibt eine echte Kollisionsstelle (s. u.). Die #219-Liste war zudem unvollständig (
renderStrip/cell()fehlte)..strip .cell .sub,.kpis-Gridcontainer-type,.kpi .top/.value-row/.v/.u). Eine echte Kollision: dieser PR fügt.kpi.no-spark { cursor: default; }+.kpi.no-spark:hover { background: none; }direkt vor der Zeile.kpi .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }ein; fix(dashboard): KPI-Kachel-Layout — Einheit-Umbruch, Grundlinien-Versatz, Sub-Label-Ellipsis #217 baut genau diese.kpi .top-Zeile zu einem mehrzeiligen Block um (zusätzlichesmin-height: 30px+ Kommentar). Beide Diffs berühren denselben Kontextbereich derselben Zeile — ein Merge-Tool wird hier voraussichtlich einen Konflikt melden statt sauber automatisch zusammenzuführen (inhaltlich aber kompatibel: neue Regel davor + geänderter Block danach). Alle anderen fix(dashboard): KPI-Kachel-Layout — Einheit-Umbruch, Grundlinien-Versatz, Sub-Label-Ellipsis #217-Selektoren bleiben überschneidungsfrei..hint/.hint-pop-Markup an Chart-Titeln, KPI-Kacheln, Tabellen-Headern undrenderStrip()scell()-Helper an. Konkrete Überschneidungen:<span class="hint">; dieser PR ändert den Titeltext selbst auf „... je Version". Textkonflikt beim Merge — die feat(dashboard): Erklär-Tooltips für Fachbegriffe auf KPI-Kacheln und Chart-Überschriften #219-Hint-Texte sagen bereits "trotz Titel ..." bzw. "Median-Laufzeit je Pipeline-Version — nicht die Summe wie bei der Kachel oben" (die Tooltip-Erklärung wird nach diesem Fix z. T. redundant, da der Titel selbst jetzt stimmt; beim Mergen ggf. kürzen).hint:'...'an dasselbe Objekt-Literal an, in dem dieser PRlabel:'Laufzeit'→label:'Laufzeit (aktuell)'ändert (gleiche Zeile, unterschiedliche Objekt-Properties) — sollte automatisch mergen, aber manuell gegenprüfen.nTag-Zeile: feat(dashboard): Erklär-Tooltips für Fachbegriffe auf KPI-Kacheln und Chart-Überschriften #219 baut dienTag-Konstruktion zu einem Hint-Span um; dieser PR erweitert dieselbe Zeile um dennDiffers-Marker (P8e, nach Nachbesserung um die kombinierte Titel-Erklärung ergänzt). Moderater Konflikt, manuelle Zusammenführung nötig (beide Änderungen sind additiv, keine strukturellen Gegensätze).renderStrip()scell()-Aufrufe: feat(dashboard): Erklär-Tooltips für Fachbegriffe auf KPI-Kacheln und Chart-Überschriften #219 ändert diecell()-Signatur von(k,v,u,sub)auf(k,v,u,sub,hint)und damit jeden Aufruf, inklusive der Tokens-Zelle; dieser PR ändert exakt dieselbe Tokens-Zeile (cell('Tokens', tok, '', kpis.total_dur_h ? ... : '')→ Locale-Fix via_fmtDE+ „(gesamt)"-Suffix, s. P5). Direkter Zeilenkonflikt, manuell zusammenführen (inhaltlich kompatibel: Hint-Parameter + Text-/Locale-Fix schließen sich nicht aus).Screenshots (hell + dunkel, Vorher/Nachher via
git stash)Verzeichnis:
C:/tmp/verify-204/pre|post-p4-p5-agents-{light,dark}.png(Agenten-Sektion: Balkenfarben + Achsen-Ticks)post-p6-scatter-tooltip-{light,dark}.png(Tooltip auf dichtem Cluster, 3 Einträge + „+16 weitere"-Footer)pre|post-p7-compare-table-{light,dark}.png(Gutter-Spalte weg)pre|post-p8b-tradeoff-{light,dark}.png(Legende 19→6 Einträge)post-p8h-select-longtext.png(Ellipsis statt Hart-Abschnitt)Hinweis: Screenshots stammen aus dem ursprünglichen PR-Stand (vor der Nachbesserung); für die 5 Nachbesserungs-Punkte (kein UI-Layout-Wechsel, reine Logik-/Rand-Fälle) keine erneute Playwright-Session — Verifikation per Code-Inspektion + Testsuite (s. oben).
Suite & Lint
pytest generative lib/decision_engine/tests shared/tests -q: 5695 passed, 3 skipped, 4 deselected, 0 failed — erneut verifiziert nach der Nachbesserung (1 Test-Assertion an den neuensetInterval(() => loadAndRender(false), 15000)-Aufruf angepasst, Testanzahl unverändert ggü. ursprünglichem PR-Stand: Baseline 5693 + 2 Tests für_chart_longitudinal).ruff format --check .: 246 files already formatted.ruff check .: All checks passed.Cross-Model-Review (Mistral
magistral-medium-latest)Keine Befunde. Reasoning-Trace ging Python-Änderung (
_chart_longitudinal) und alle JS-Blöcke (Palette, ch3-Top-N, ch8-Minuten-Konvertierung, nDiffers-Bedingung, toggleRow-Entfernung,.refreshing-Lifecycle) einzeln durch, keine erfundenen Findings.Zusätzlich: externes Fable+Qwen-Review der Nachbesserung (s. Abschnitt oben) — 5 Findings, alle umgesetzt.
Read-only
Keine Eval-Daten verändert, keine Pipeline-Läufe. Nur
internal/dashboard/eval_dashboard.html+generative/eval_dashboard.py(Datenfunktion_chart_longitudinal, additiv) + Tests.