Fruehjahrsputz 2/2: Dokumentation auf den tatsaechlichen Stand gebracht
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>
This commit is contained in:
+33
-15
@@ -1,9 +1,27 @@
|
||||
# Fix- und Datenreparatur-Plan (Stand 2026-07-09, Übergabe an Gemini)
|
||||
|
||||
> **Abnahmekriterium für alle Code-Änderungen:** `dotnet test src/Predictalytics.Application.Tests` muss
|
||||
> **16 grün + 1 übersprungen** liefern (der Skip `CheckpointResetAndReplay_DoesNotDoubleCountBalance` ist eine
|
||||
> dokumentierte, bewusste Entscheidung). Die Assertions der Invarianten-Tests dürfen **nicht** verändert werden —
|
||||
> sie definieren das Soll-Verhalten. Wenn ein Test rot wird, ist der Code falsch, nicht der Test.
|
||||
> **Status 2026-08-23: Teil D und Teil F sind umgesetzt**, nachgeprüft gegen den Code.
|
||||
> Offen sind nur noch drei Detailpunkte, jeweils unten als `- [ ]` stehengeblieben:
|
||||
> der gezielte Nachlade-Schritt in F5 und die zwei Tests aus F6 (Event-Tag-Vererbung,
|
||||
> Backfill). Belege:
|
||||
> * **D3** — `IngestMode` (`Domain/Enums/IngestMode.cs`), Einstufung in
|
||||
> `TradeHistoryWorker.cs:174-177` inklusive der geforderten Hysterese
|
||||
> (Rückstufung erst unter halber Schwelle, Richtung `Full` zusätzlich erst nach
|
||||
> 7 Tagen), wöchentliche Biopsie in `TradeHistoryWorker.cs:127`,
|
||||
> Aggregations-Buckets in `TradeAggregation.cs`, Trait `not_copyable_hf` in
|
||||
> `TraderTraitCalculator.cs`. Tests: `IngestModeTests.cs`.
|
||||
> * **F1/F2** — `CanonicalTags` und `BlacklistTags`/`IsNoiseTag` in
|
||||
> `Infrastructure/Helpers/MarketCategoryMapper.cs`.
|
||||
> * **F3/F4** — Tag-Nachladen in `PolymarketProvider.cs:187-196`, Offline-Backfill
|
||||
> aus Event-Tags in `PredictalyticsHost.cs:114-135`.
|
||||
>
|
||||
> **Abnahmekriterium für alle Code-Änderungen:** `dotnet test` muss grün bleiben.
|
||||
> Die damals notierte Zahl (16 grün + 1 übersprungen) ist überholt — Stand
|
||||
> 2026-08-23 sind es **126 grün + 1 übersprungen** (der Skip
|
||||
> `CheckpointResetAndReplay_DoesNotDoubleCountBalance` ist weiterhin eine
|
||||
> dokumentierte, bewusste Entscheidung). Die Assertions der Invarianten-Tests dürfen
|
||||
> **nicht** verändert werden — sie definieren das Soll-Verhalten. Wenn ein Test rot
|
||||
> wird, ist der Code falsch, nicht der Test.
|
||||
|
||||
## Hintergrund
|
||||
|
||||
@@ -95,35 +113,35 @@ Reihenfolge: **D1 → D2/D2b/D2c → D3** (D2c ist klein und gehört in denselbe
|
||||
|
||||
### F1. Mapper: kanonischen Tag zuerst, dann Heuristik
|
||||
|
||||
- [ ] In `MarketCategoryMapper.Map`: **zuerst** prüfen, ob **irgendein Tag exakt** einer bekannten
|
||||
- [x] In `MarketCategoryMapper.Map`: **zuerst** prüfen, ob **irgendein Tag exakt** einer bekannten
|
||||
Kategorie entspricht (Polymarkets Tag-Vokabular enthält fast immer den kanonischen Top-Level-Tag:
|
||||
`Sports`, `Politics`, `Crypto`, `Business`/`Economy`, `Pop Culture`, `Science`, ...). Mapping-Tabelle
|
||||
Tag→`MarketCategory` (inkl. Synonyme: `Finance`/`Business`→Economy, `Pop Culture`→PopCulture).
|
||||
Erst wenn **kein** kanonischer Tag matcht, die bestehende Keyword-Heuristik auf Frage+Tags anwenden.
|
||||
- [ ] **Kategorie über die gesamte Tag-Menge** bestimmen, nie über `tags[0]`.
|
||||
- [x] **Kategorie über die gesamte Tag-Menge** bestimmen, nie über `tags[0]`.
|
||||
|
||||
### F2. Subcategory: Noise filtern, sinnvoll wählen, leer normalisieren
|
||||
|
||||
- [ ] Organisations-/Müll-Tags herausfiltern (Blacklist: `Hide From New`, `Tournament Futures`,
|
||||
- [x] Organisations-/Müll-Tags herausfiltern (Blacklist: `Hide From New`, `Tournament Futures`,
|
||||
`Main Election`, `Recurring`, Jahres-Tags wie `2025 Predictions`, `2026 FIFA World Cup`→ok als Sub?, …).
|
||||
- [ ] Subcategory = spezifischster **verbleibender** Tag, der **nicht** die Kategorie selbst ist
|
||||
- [x] Subcategory = spezifischster **verbleibender** Tag, der **nicht** die Kategorie selbst ist
|
||||
(bei World-Cup-Tags → `Soccer`, nicht `Sports`). Kein passender → leerer String.
|
||||
- [ ] **NULL/`""` einheitlich als `""`** speichern (behebt die doppelten „Sports/-"-Zeilen: heute
|
||||
- [x] **NULL/`""` einheitlich als `""`** speichern (behebt die doppelten „Sports/-"-Zeilen: heute
|
||||
entstehen zwei Gruppen-Keys aus NULL vs. "").
|
||||
|
||||
### F3. On-Demand-Markt: Tags nachladen statt `Other` zu speichern
|
||||
|
||||
- [ ] In `GetMarketAsync`: wenn `parentTags` leer ist, aber ein Event mit Id vorhanden ist →
|
||||
- [x] In `GetMarketAsync`: wenn `parentTags` leer ist, aber ein Event mit Id vorhanden ist →
|
||||
**`/events?id=<eventId>` nachladen** (liefert Tags, 1 Extra-Call pro neuem Markt, cachebar) und die
|
||||
Tags fürs Mapping verwenden. Über den `IRateLimiter` drosseln.
|
||||
- [ ] Alternativ/zusätzlich: existiert das Parent-Event bereits in unserer DB (aus dem Events-Sync,
|
||||
- [x] Alternativ/zusätzlich: existiert das Parent-Event bereits in unserer DB (aus dem Events-Sync,
|
||||
`Event.Tags` gefüllt) → **Tags von dort erben**, ganz ohne API-Call.
|
||||
|
||||
### F4. Kategorie aus Event-Tags ableiten + Offline-Backfill (der große Hebel)
|
||||
|
||||
- [ ] Markt-Kategorie primär aus den **Event-Tags** (`market.Event.Tags`) ableiten, nicht aus den
|
||||
- [x] Markt-Kategorie primär aus den **Event-Tags** (`market.Event.Tags`) ableiten, nicht aus den
|
||||
(leeren) Markt-Feldern. On-Demand-Märkte erben so die Kategorie ihres Events.
|
||||
- [ ] **Einmaliger Offline-Backfill** (keine API-Calls!): über alle Märkte iterieren, deren Event
|
||||
- [x] **Einmaliger Offline-Backfill** (keine API-Calls!): über alle Märkte iterieren, deren Event
|
||||
Tags hat, und Kategorie/Subcategory aus `Event.Tags` neu ableiten (mit F1/F2). Als Methode in
|
||||
`RunRecalculateAllTradersAsync` einhängen ODER eigener Dev-Endpoint. Danach `TraderCategoryPerformance`
|
||||
neu rechnen (passiert durch die ohnehin folgende Trader-Neuberechnung).
|
||||
@@ -136,9 +154,9 @@ Reihenfolge: **D1 → D2/D2b/D2c → D3** (D2c ist klein und gehört in denselbe
|
||||
|
||||
### F6. Tests
|
||||
|
||||
- [ ] Mapper: kanonischer Tag gewinnt über Reihenfolge (`"Ethiopia, Elections, ..., Politics"` → Politics;
|
||||
- [x] Mapper: kanonischer Tag gewinnt über Reihenfolge (`"Ethiopia, Elections, ..., Politics"` → Politics;
|
||||
`"Sports, Soccer, ..."` → Sports, Subcategory `Soccer`).
|
||||
- [ ] Subcategory: Müll-Tags werden gefiltert; NULL und `""` erzeugen denselben Gruppen-Key
|
||||
- [x] Subcategory: Müll-Tags werden gefiltert; NULL und `""` erzeugen denselben Gruppen-Key
|
||||
(kein Duplikat mehr).
|
||||
- [ ] Event-Tag-Vererbung: Markt ohne eigene Tags, Event mit `['Crypto',...]` → Markt wird Crypto.
|
||||
- [ ] Backfill: Markt in DB als `Other`, Event.Tags = `['Politics',...]` → nach Backfill Politics,
|
||||
|
||||
Reference in New Issue
Block a user