Backend:
- SPA-Fallback: catch-all-Route liefert index.html, falls keine statische Datei
matcht (mit Ausnahme von /api/* und /audio/*). Dadurch funktionieren Tiefen-
Links wie /ldn oder /neu-denken direkt.
Frontend:
- loadApp() liest pathname und laedt den passenden Podcast direkt, falls die ID
in /api/podcasts vorkommt; sonst klassischer Selector.
- selectPodcast() updated den Pfad per history.pushState, damit Bookmarks und
Sharing funktionieren.
- popstate-Handler reagiert auf Browser-Back/Forward.
- showPodcastList() setzt den Pfad auf '/'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Backend:
- /api/analyses/density: Faktendichte je Episode in 20 Bins ueber die
Paragraph-Achse, getrennt nach total und verifizierbar (#16).
Frontend:
- ShiftsView (#15): Inline-SVG-Sparkline ueber die gesamte Drift-Sequenz je Theme,
mit Schwellen-Linie bei 50% und klickbaren Spike-Markern.
- GapsView (#14): Cluster-Heatmap mit zwei Zeilen (LdN, NEU DENKEN), Cluster-Breite
proportional zur Cluster-Groesse, Farbe interpoliert von kuehl (geringer Anteil im
Podcast) zu warm (hoher Anteil); Klick filtert die darunter liegende Liste.
- DensityView (#16): neue View 'Faktendichte', sortiert nach Claims/Absatz,
pro Episode eine 20-Bin-Heatmap (gruen = verifizierbar, warm = normativ),
Filter nach Podcast und Sortierung; Klick oeffnet die Episode.
- AnalysisView (#17 questions): zeigt jetzt 'Antwort: <Episode>@p<idx>'-Link
fuer Fragen mit answered_by_episode; Klick navigiert zur Antwort-Stelle.
- escAttr-Helper, hide-Cascade um DensityView erweitert, Buttons in Selector
und init() hinzugefuegt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- /api/podcasts/{id}/episodes/{ep}/claims: Behauptungen einer Episode, optional gefiltert nach claim_type.
- /api/podcasts/{id}/episodes/{ep}/questions: Fragen der Episode, gefiltert nach Typ und Antwort-Status.
- /api/podcasts/{id}/episodes/{ep}/analyses-summary: Zaehler fuer die UI-Buttons (claims, questions, unbeantwortet).
- /api/analyses/gaps: Leerstellen aus data/gaps_analysis.json (#14), Filter ueber min_size und missing_in.
- /api/analyses/shifts: Narrative-Shift-Drift aus data/narrative_shifts.json (#15), Filter ueber podcast, theme und min_drift.
- Wort-Timestamps via /api/podcasts/{id}/transcript/{ep}/words; Tabelle wird via _table_exists graceful behandelt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Backend: /api/compare Endpoint für Podcast-Vergleich (Stats, gemeinsame Topics,
Top-Querverbindungen), /api/.../words Endpoint für Wort-Timestamps
- Frontend: Podcast-Vergleichsansicht mit Statistiken und Cross-Links,
Cross-Podcast-Suche-Toggle, semantische Links im Transkript (lazy-loaded),
Podcast-Switcher mit Zurück-Navigation
- PWA: manifest.json, Service Worker (stale-while-revalidate für Assets,
network-first für API, cache-on-success für Audio), Icons
- Scripts: transcribe_words.py (mlx-whisper Batch-Transkription mit Wort-Timestamps),
import_words.py (Wort-Timestamps in DB importieren)
- Dockerfile: PWA-Assets in Container kopieren
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1:
- FastAPI-Backend (backend/app.py) mit REST-API
- SQLite-Datenbank für Podcasts, Episoden, Absätze, Zitate
- Auto-Import aus mindmap_data.json + srt_index.json beim Start
- Webapp als SPA: API-first mit Static-File-Fallback
- Audio als gemountetes Volume statt im Docker-Image
- Docker-Compose mit Traefik-Labels
Phase 2:
- Qwen text-embedding-v3 via DashScope (1024-dim Vektoren)
- Embedding aller Transkript-Absätze (728 für NEU DENKEN)
- Semantische Suche: /api/semantic-search?q=...
- Similarity-API: /api/similar/{podcast}/{episode}/{paragraph}
- Cosine-Similarity auf normalisierten Vektoren, <100ms
- Findet thematisch verwandte Stellen über Episoden hinweg,
auch bei komplett unterschiedlicher Wortwahl
Vorbereitet für Multi-Podcast (#10): Datenstruktur unterstützt
mehrere Podcasts, Cross-Podcast-Similarity ist ein Parameter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>