Die Plandokumente waren durchweg veraltet: 85 von 91 Punkten im
UMSETZUNGSPLAN standen auf offen, obwohl der Code sie enthielt, und in
FIXPLAN-UI-Ranglisten war keine einzige der 18 Aufgaben abgehakt, obwohl
beide zugehoerigen Commits laengst im Zweig stecken. Alles abschnittsweise
gegen den Code geprueft und die Haekchen gesetzt - mit Belegstellen, damit
die naechste Pruefung nicht wieder bei null anfaengt.
Neu: STATUS.md als Einstiegsseite - wo das Projekt steht, was fertig ist,
was offen ist, und was beim Aufraeumen bewusst stehengeblieben ist. CLAUDE.md
verweist darauf.
Nachgezogen:
* UMSETZUNGSPLAN.md - 66 Punkte abgehakt. Offen bleiben A4 (Strategie-
Klassifikation), B2 (Secrets) sowie C3/D1/D2 (SQL-Arbeiten des Nutzers).
* FIXPLAN-UI-Ranglisten.md - abgeschlossen bis auf den als "Optional"
markierten Pfeilrichtungs-Punkt.
* FIXPLAN-TODO.md - Teil D und F abgehakt; die Test-Baseline "16 gruen"
auf die heutigen 126 korrigiert. Offen: F5 und zwei Tests aus F6.
* FIXPLAN-G-Speicher.md - G1 bis G4 als erledigt vermerkt, Baseline "39/1"
korrigiert, Pfad auf die nicht mehr existierende WinFormsHost/appsettings.json
richtiggestellt.
* docs/PLAN-Linux-Portierung.md - der Watchdog-Warnhinweis war ueberholt
(DcHeartbeatService meldet an /api/watchdog/v1/ping). Abschnitt 11 empfahl
noch, mit Phase 0 zu beginnen; jetzt benennt er Phase 5 und 6 als das, was
wirklich aussteht. Die Randnotiz zu Zugangsdaten in LicenseGuard.cs ist
gegenstandslos, die Datei laeuft ueber den Deploymentcenter.Client.
Zwei Befunde, die keine Aufraeumarbeit sind und deshalb nur dokumentiert
wurden - beide in STATUS.md Abschnitt 3:
1. In src/Predictalytics.Api/appsettings.json steht ein echter
OpenRouter-API-Key im Klartext, versioniert seit 7045002. Nicht
eigenmaechtig entfernt: ohne Rotation beim Anbieter bringt das nichts
(die History behaelt ihn), wuerde aber die KI-Analyse abschalten.
Der Schluessel muss zurueckgezogen und neu ausgestellt werden.
2. Die Portierung ist auf keinem Linux-System je ausgefuehrt worden. Die
Verifikation vom 2026-08-08 lief unter Windows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
10 KiB
FIXPLAN Teil UI — Ranglisten & Showcases sichtbar/korrekt machen
✅ ABGESCHLOSSEN. Umgesetzt in den Commits „UI-U3: server-side min-winrate/min-copyability filters" und „UI-U1/U2/U4/U5: dashboard showcases + server-side leaderboard sort", beide in
feature/linux-net10enthalten. Am 2026-08-23 Punkt für Punkt gegen den Code nachgeprüft:loadShowcases()(app.js:393) wird ausloadDashboard()heraus aufgerufen (app.js:307), Red Flags heben sich übershowcase-card--warnab,takesteht auf 200 mit serverseitigemsort-Parameter (app.js:466,470),minWinRate/minCopyabilitygehen bis inTraderEndpoints.cs:16durch (Test inAnalyticsServiceTests.cs:135),#tradersSortführt alle sieben Metriken, und der Empty-State steht aufcolspan="10".Offen bleibt nur der als „Optional" markierte Punkt in U5 (Pfeilrichtung ▲/▼ in der aktiven Sortierspalte) — die Tabellenköpfe zeigen weiterhin statisches ↕. Reine Politur, kein Fehlverhalten.
Eigenständiger Plan für die Web-UI (
src/Predictalytics.Api/wwwroot/). Von oben nach unten abarbeiten. Nach jeder Aufgabe im Browser gegen die laufende API prüfen und committen.
0. Regeln (zuerst lesen)
- Backend-Test-Baseline bleibt grün. Vor Beginn einmal
dotnet test src/Predictalytics.Application.Testslaufen lassen und die aktuelle Zahl (grün/übersprungen) notieren. Keine Aufgabe hier darf sie senken. Assertions bestehender Tests niemals ändern. - Reine Frontend-Änderungen (
index.html,app.js,style.css) brauchen keine Migration. Die zwei kleinen API-Ergänzungen (U3) sind additiv und nullable/optional. - Nichts „drumherum" umbauen. Kleinste sichere Variante wählen. Bestehende Optik/Klassen
(
card,data-table,tier-badge,platform-select, CSS-Variablen) wiederverwenden, keine neuen Farbwelten erfinden. - Zahlen: Prozente 0–100, Beträge USD, Zeiten UTC — konsistent zum restlichen UI.
- Nach jeder Aufgabe: Browser-Check gegen
page-dashboardbzw.page-traders, danngit commit.
Kontext — was ist kaputt (im Code verifiziert 2026-07-23)
Der Commit „Add showcase leaderboards endpoint + sortable trader list" hat das Backend erweitert, aber das Frontend nicht nachgezogen:
GET /api/traders/showcasesliefert 7 kuratierteShowcaseSection(copy_ready,smooth_operators,rising_stars,high_conviction,specialists,insider_watch,red_flags— sieheShowcaseBuilder.cs). Kein Frontend-Code ruft das je auf → das Feature ist unsichtbar.GetTradersAsync(sort)unterstützt serverseitigpnl,pnl30d,winrate,copytrading,calmar,conviction,profitfactor(AnalyticsService.cs:184). Das Frontend übergibt keinensort-Param, holt stattdessentake=100in Default-Order und sortiert clientseitig (app.js:392,420). → Die aussagekräftigen Metriken (Calmar, Conviction, Profit-Faktor) sind nicht wählbar, und jede Sortierung reiht nur die ersten 100 der Default-Order um statt die echten Top-N zu zeigen.filterWinrateMin/filterCopyabilityMinfiltern clientseitig nach demtake=100-Fetch (app.js:416) → ein passender Trader jenseits Rang 100 erscheint nie.- Zwei Sort-Dropdowns schreiben beide
currentSort: global#sortSelect(app.js:121) und lokal#tradersSort(index.html:209), mit unterschiedlichen Optionssätzen. - Empty-State nutzt
colspan="11"(app.js:407), die Tabelle hat aber 10 Spalten (index.html:270).
Aufgabe U1 — Showcases auf dem Dashboard rendern (größter Hebel)
Ziel: Die 7 kuratierten Sektionen sichtbar machen — je Sektion Titel, Beschreibung und die Top-Trader
als klickbare Kacheln/Zeilen (Klick → viewTrader(id)).
- HTML: In
index.htmlim#page-dashboardeinen Container<div id="showcaseSections"></div>ergänzen (unter den bestehenden Dashboard-Karten, vor/nach „Top Traders" — Platzierung so, dass es nicht mit den bestehenden Kacheln kollidiert). - JS: Neue Funktion
loadShowcases()inapp.js: -const sections = await api('/api/traders/showcases');- Response-Shape (camelCase):[{ key, title, description, traders: [TraderDto, ...] }]. - Pro Sektion einecardrendern:titleals Überschrift,descriptionalspage-subtitle-artiger Untertitel, darunter die Trader als kompakte Liste/Grid mit Name (+🤖beiisSuspectedBot), Plattform,combinedScore,copytradingCopyabilityScore,totalPnl(viafmt.pnl), Trait-Chips (dieselbe Chip-Logik wie inloadTraders,getTraitDisplayName/Description/Class). - Leere Sektionen liefert das Backend gar nicht erst — kein Sonderfall nötig; aber wenn die ganze Antwort leer/nullist, freundlicher Empty-State. - Jede Trader-Zeile:onclick="viewTrader(${t.id})". loadShowcases()inloadDashboard()aufrufen (bzw. beim Aktivieren vonpage-dashboard).- Optik:
insider_watchundred_flagsoptisch abheben (z. B. Warn-Akzent für Red Flags über vorhandene CSS-Variablen--pnl-negative), aber im bestehenden Kartenstil bleiben.
U1 fertig, wenn: Dashboard zeigt die vom Backend gelieferten Sektionen; Klick auf einen Trader öffnet die Detailseite; keine Konsolenfehler. Commit: „UI-U1: render dashboard showcases".
Aufgabe U2 — Server-seitige Sortierung statt Client-Sort auf 100 Zeilen
Ziel: Die Rangliste zeigt die echten Top-N nach der gewählten Metrik, nicht nur eine Umsortierung der ersten 100.
- JS: In
loadTraders()den gewählten Sort als Query-Param an die API hängen:url += '&sort=' + encodeURIComponent(serverSortKey). Mapping UI→Server:score→(leer/default),winrate→winrate,copyability→copytrading,pnl→pnl,pnl30d→pnl30d,calmar→calmar,conviction→conviction,profitfactor→profitfactor. (Der Server ordnet absteigend — das ist für alle diese Metriken die sinnvolle Richtung.) - JS: Den clientseitigen
data.sort(...)-Block inloadTraders()entfernen bzw. nur noch als Fallback für die rein clientseitigen Keysname/platformbehalten (die kennt der Server nicht). - take von 100 auf einen sinnvollen Wert erhöhen (z. B. 200) — die serverseitige Sortierung liefert jetzt die richtige Reihenfolge, die Tabelle kann eine echte Bestenliste zeigen.
- Die Klick-Sortierung der Tabellenköpfe (
setTraderSort,app.js:376) auf denselben Pfad umstellen: Sort setzen →loadTraders()(das nun serverseitig sortiert). Die↕-Header behalten.
U2 fertig, wenn: Auswahl „Calmar/Conviction/Profit-Faktor" (nach U4) verändert die Reihenfolge sichtbar und zeigt Trader, die vorher nicht in den ersten 100 waren. Commit: „UI-U2: server-side leaderboard sort".
Aufgabe U3 — Min-Filter serverseitig (Winrate/Copyability) — additive API-Ergänzung
Ziel: Die Kennzahl-Mindestfilter dürfen nicht an der 100/200-Grenze abschneiden.
- API:
IAnalyticsService.GetTradersAsyncund die Implementierung (AnalyticsService.cs:165) um zwei optionale nullable Parameter erweitern:decimal? minWinRate = null, decimal? minCopyability = null. In der In-Memory-Filterkette (dort wird ohnehin schonhighlyCopyableundtraitFiltergefiltert) anwenden:if (minWinRate is > 0) traders = traders.Where(t => t.WinRate >= minWinRate).ToList();und analogt.Analytics?.CopytradingCopyabilityScore >= minCopyability. - Endpoint: In
TraderEndpoints.csdie/api/traders-Route um die zwei Query-Parameter durchreichen. - JS: In
loadTraders()filterWinrateMin/filterCopyabilityMinals Query-Param senden statt clientseitig zu filtern; den clientseitigen Filter-Block entfernen. - Test: Kleiner Service-Test (SQLite-Muster wie vorhandene
AnalyticsService/Repository-Tests): drei Trader mit WinRate 40/60/80,minWinRate=55→ nur zwei zurück. Baseline bleibt grün.
U3 fertig, wenn: Ein hoher Mindest-Copyability-Wert zeigt auch Trader, die in der Default-Order weit hinten stehen. Commit: „UI-U3: server-side min-winrate/min-copyability filters".
Aufgabe U4 — Sort-Dropdown vereinheitlichen & vervollständigen
Ziel: Ein einziges, vollständiges Sort-Steuerelement für die Rangliste.
- HTML:
#tradersSort(index.html:209) um die aussagekräftigen Metriken erweitern:pnl30d(PnL 30 T),calmar(Rendite/Drawdown),conviction(Conviction-Edge),profitfactor(Profit-Faktor),copyability(bereits da),score/winrate/pnl/namebehalten. - JS: Klarstellen, welches Dropdown die Traders-Seite steuert.
#tradersSortbleibt maßgeblich fürpage-traders; das globale#sortSelect(falls es die Traders-Seite mitsteuert) entkoppeln oder auf denselben State spiegeln, sodass es kein widersprüchlichescurrentSortmehr gibt. - Sicherstellen, dass Header-Klick (
setTraderSort) und Dropdown denselbencurrentSortschreiben und beideloadTraders()(serverseitig, U2) auslösen.
U4 fertig, wenn: Alle Dropdown-Optionen sortieren korrekt (serverseitig), Header-Klick und Dropdown bleiben synchron. Commit: „UI-U4: unify + extend leaderboard sort control".
Aufgabe U5 — Kleinkram / Konsistenz
- colspan-Fix: Empty-State in
loadTraders()(app.js:407) voncolspan="11"auf die echte Spaltenzahl 10 korrigieren. - Spalten-Parität: Prüfen, dass Tabellenkopf (
index.html:270) und Zeilen-Template (app.js:435) dieselbe Spaltenzahl/-reihenfolge haben. - Optional: Aktive Sortierspalte im Header visuell markieren (Pfeilrichtung ▲/▼ statt neutralem ↕).
U5 fertig, wenn: Leere Tabelle rendert sauber über die volle Breite; kein Spaltenversatz. Commit: „UI-U5: leaderboard table consistency".
Gesamt-Abnahme
dotnet buildfehlerfrei;dotnet test= notierte Baseline weiter grün + neuer U3-Test grün.- Dashboard zeigt die 7 Showcase-Sektionen mit echten Tradern (U1).
- Sortierung nach Calmar/Conviction/Profit-Faktor zeigt Trader jenseits der alten Top-100 (U2/U4).
- Mindest-Filter schneiden nicht mehr an der Fetch-Grenze ab (U3).
- Keine JS-Konsolenfehler; Tabelle ohne Spaltenversatz (U5).
Reihenfolge: U1 (Sichtbarkeit, reines Frontend) → U2 (Sort-Korrektheit) → U3 (Filter-Korrektheit, kleine API-Ergänzung) → U4 (Bedien-Konsistenz) → U5 (Politur).