# 08 — Changelog Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum, Was, Warum, betroffene Dateien/Backups). ## 2026-07-16 — A/B-Test Qwen2.5-3B vs Gemma-3-4B im neuen Chunk-Pfad: Gemma bleibt Auf User-Wunsch das noch vorhandene `qwen2.5-3b.rkllm` gegen die neuen 4,2k-Chunk-Prompts getestet (Test-Binary mit ctx 4096 in /tmp, direkt übers Stdin-Protokoll — kein App-Umbau). Ergebnis: **3 von 3 Outputs unbrauchbar** (Feldbeschreibungs-Echo ohne Inhalt; Abbruch nach ~100 Zeichen mitten im Satz; Struktur-Müll mit der Feldbeschreibung als JSON-Key) — Gemma lieferte im selben Job 8/8 verwertbare Sektionen. Dazu prinzipiell: Qwen2.5 hat fix 4096 Kontext → der validierte Whole-Pass (≤ 20k Zeichen) wäre unmöglich. Testartefakte entfernt. Offene Alternative (ungetestet, ~½ Tag): Qwen3-4B neu konvertieren. ## 2026-07-16 — Sektions-Konglomerat statt LLM-Reduce (Abend, `.bak-sectionsum`) Auftrag: Lang-Transkript-Summary (> 20k Zeichen) inhaltlich retten. Prompt-Lab auf #70 mit temporärem `/api/debug/ask`-Endpoint (nach Abschluss wieder entfernt), ~15 Reduce-/Chunk-Varianten in je ~2 min statt 9-min-Vollanalysen. - **Befund 1: Chunk-Größe ist der Fidelity-Hebel.** 8k-Chunks → generisches namenloses Blabla; 4k-Chunks → geerdete Summaries mit echten Eigennamen (Com4Tec, René, Tobi+Niklas, 20 Bewerbungen). `CHUNK_CHARS` 8000 → **4200**. - **Befund 2: Cross-Section-Synthese unmöglich auf Gemma-3-4B.** Jede LLM-Reduce-Variante (Gewichtungsregeln, Abschnitts-Labels, Themen-Tabellen) → Regeln ignoriert, Namen durch Rollen ersetzt, Dubletten, Loops. **LLM-Reduce abgeschafft.** - **Neue `analyzeLong`-Pipeline** (`llm.js`): 4,2k-Chunks sequenziell mit **Rolling Context** (1-Satz- Kurzfassungen der Vorgänger → erkennt geänderte Entscheidungen: „jetzt X, vorher Y") + **eigennamen- Extraktionsfeld**; Echo-Guard (Feldbeschreibungs-Echo ist INHALTS-abhängig reproduzierbar → bis 3 Versuche mit variiertem Prompt: ohne Kontext, ohne Hint) + Feld-Salvage per Regex + Prosa-Rettung (≥ 60 Zeichen); **Titel-Mikro-Call** ohne letzten Abschnitt (Smalltalk-Filter); **Konglomerat baut Code**: „Gesprächsverlauf in n Teilen — genannte Namen: …" + „Teil i/n: …" chronologisch. Kap. 05 (Mermaid + Marotten aktualisiert). - **E2E #70 (3 Läufe):** Titel ohne Auto-Smalltalk ✅, alle Abschnitte mit echten Namen ✅, Auto nur noch in Teil 7 ✅, 12-14 min für 26-min-Aufnahme. Restgrenze: Abschnitts-Summaries variieren pro Lauf in Schärfe (Sampling), keine thematische Verdichtung ÜBER Abschnitte (4B-Decke). ≤ 20k Zeichen weiter Whole-Pass. ## 2026-07-16 — #70-Debug: Phantom-Sprecher, Summary-Fehlgewichtung, Thermal-Leck (Nachmittag) Auslöser: Aufnahme #70 (26 min, 4 Personen) — 7 Sprecher erkannt, Titel/Summary aus Randthemen (Auto-Smalltalk der letzten 3 min statt Recruiting-Hauptteil). 9 Analyse-Iterationen auf #70. - **Diarization Stufe 3 „Weak-Fold"** (`diar.js`, `.bak-weakfold`): finale Sprecher < `DIAR_MIN_TOTAL_SEC` (20 s, Segment-Zeiten!) werden in den akustisch nächsten starken Sprecher gefaltet — ein einzelner ≥ 3-s-Streu-Cluster konnte vorher einen Phantom-Anchor eröffnen (#70: 3 Phantome mit 2,5–4,8 s). 10 s reichte NICHT (9,2-s-Phantom kam durch). **Verifiziert: #70 konstant 50 Roh-Cluster → exakt 4.** Kap. 04. - **Whole-Pass-Grenze = Modellgrenze bewiesen** (Runden 2–5): rkllm-Runtime-Kontext 8192 → **12288** (`rkllm_server.cpp`, `.bak-ctx12k`, Rebuild) und `WHOLE_MAX_CHARS` testweise 32k → Gemma-3-4B kippt > ~6k Input-Token reproduzierbar: englisches Geplauder statt Analyse, Recency-Bias (fasst nur das Gesprächsende zusammen), JSON-Zerfall (typografische Quotes, Wiederholungsschleifen). `WHOLE_MAX_CHARS` zurück auf **20 000** (dort validiert gut); ctx 12288 bleibt (Headroom). Kap. 05 neuer Abschnitt. - **Robustheit `llm.js`** (`.bak-ctx12k`): End-Instruktion nach dem Transkript (ohne Platzhalter-Skelett — Gemma kopiert `...` wörtlich!); JSON-Repair-Call (repariert kaputten Output OHNE das große Transkript); Sanity-Check (Zusammenfassung ≥ 20 Zeichen) → sonst Chunk-Fallback statt Hard-Error; `extractJson()` repariert typografische Anführungszeichen + trailing commas; **1 Retry pro Chunk** (Parse = Sampling- Münzwurf: 3/3 ok vs 1/3 im nächsten Lauf; Retry live bestätigt); Reduce-Input mit „Abschnitt i von n"- Labels + Gewichtungsregeln (Hauptthema = mehrere Abschnitte; Nur-letzter-Abschnitt = Smalltalk). - **Regression bestätigt: Chunk-Prompt MUSS minimal bleiben** — eine zusätzliche Anweisungszeile (Namen/Firmen/Zusagen) kippte 2/3 Chunks in Prosa (Runde 6). Zurückgebaut. - **Thermal-Leck geschlossen** (`server.js`, `.bak-anacap`): `analyzeRecording()` lief als einziger schwerer Pfad OHNE A76-Takt-Cap → 95–97 °C bei langer Gemma-Generierung (lüfterlos!). Jetzt Cap wie `transcribeWav`/`rediarize`. Kap. 03/05. - **Ehrliches Ergebnis #70:** Sprecher exakt 4 ✅, Analyse crashfrei in ~9 min ✅, Summary führt jetzt mit Recruiting, ABER Auto-Smalltalk bleibt in Titel/Kernpunkten und konkrete Namen (Com4Tec, Kandidaten) fehlen — **Qualitätsdecke des 4B-Modells im Chunk-Pfad (> 20k Zeichen)**. Aufnahmen ≤ ~23 min laufen über den validierten Whole-Pass. ## 2026-07-16 - **Codebase ins Repo aufgenommen:** `app/` = Spiegel von `/opt/callrec` (Backend, Frontend-Quellen, Inferenz-Python, Skripte, `rkllm_server.cpp`), `system/` = systemd-Units + WirePlumber/PipeWire-Drop-ins + sudoers. Modelle/Binaries/Aufnahmen bewusst außen vor (`.gitignore`). - **Projekt umbenannt in „Aime“** (vormals CallRec, wie der BT-Name des Boards): Gitea-Repo → `sascha/Aime`, Web-GUI-Titel/Header → „Aime“ (Bundle `index-CuWeUh1j.js`, Backups `index.html.bak-aime`/`main.js.bak-aime`), Doku rebranded. Technische Bezeichner auf dem Board bleiben `callrec*` (Stabilität). - **Doku-Repo angelegt** (dieses Repo). Ab jetzt verbindliche Ablage inkl. Diagrammen. ## 2026-07-15/16 — Strukturierte Analyse + Teilnehmer-Fix (`.bak-structsum`) - Teilnehmer kommen aus der **Diarization** statt vom LLM (das listete alle *erwähnten* Namen → 11 statt 3 bei #69). - Summary strukturiert: Überblick + „Kernpunkte“ + „Entscheidungen“ als Bullets (`composeSummary`, CSS `pre-line`). - Chunk-Salvage-JSON-Leak gefixt; Reduce-Input gekappt + Retry; `cleanList` filtert `null`/`[object Object]`/Objekt-Todos. - Referenz #69 (71,6 min): Analyse ~20 min, Ergebnis sauber. Bundle `index-B2dSaBty.js`. ## 2026-07-15 — LLM-Wechsel auf Gemma-3-4B + Marker-Fix - Qwen2.5-3B → **Gemma-3-4B-it** (`gemma3-4b-w8a8g128-16k.rkllm`, grouped w8a8; plain w8a8 kaputt, w4a16 nicht unterstützt). - rkllm-Runtime 1.2.1 → **1.3.0**. `analyzeWhole` (≤ 20k Zeichen) ersetzt Map-Reduce im Mittelbereich. - Qualität ≈ Gemini, ~3× langsamer. Wort-Highlight-Marker lief ~1 Wort voraus → SYNC_MS=250 (`index-CLero27-.js`). ## 2026-07-14 — Kurzclip-Beschleunigung + Analyse-Timer - Clips ≤ 30 s über warmen CPU-Whisper-Daemon ohne rkllm-Swap: 10-s-Clip 120 s → **53 s** (`.bak-shortdaemon`). - GUI zeigt Analysezeit live (`analysis_ms`/`analysis_started_at`, `.bak-anatimer`). ## 2026-07-13 — Diarization stabil + NPU-Meilenstein 2 + iPhone-Repair - **Greedy-Anchor-Merge** ersetzt Union-Find: derselbe Call ergab vorher 2/3/7 Sprecher, jetzt konstant 27→3 (`.bak-anchor`). - **Meilenstein 2:** Whisper-turbo-Encoder auf NPU produktiv — RTF 1,51 → 0,61, Temp 90 °C → 59 °C; batched (batch=8) → RTF 0,389. - iPhone neu gekoppelt, `Trusted=yes` gesetzt (fehlte → keine HFP-Nodes → #58 ohne Gegenseite). ## 2026-07-09 — Meilenstein-1-Snapshot, Auto-Diarization, Glossar, Whisper-Kalibrierung - Snapshot `/opt/callrec/milestones/m1-20260709/` (Rollback-Punkt). - Auto-Diarization: 2-stufige Konsolidierung (17→2 verifiziert), `reanalyze` re-diarisiert immer (0=auto / >0=gepinnt). - **Glossar Phase 1:** deterministische Ganzwort-Ersetzung + LLM-Hinweis, GUI-Tab, „Aime“ geseedet. - Whisper-Kalibrierung: medium beam1 optimal (11,3 % WER vs large-v3); `--initial-prompt` mit Termliste = Echo-Loop (tabu). - 46-min-E2E über Nacht sauber (Long-Rec-Fixes produktionsvalidiert). ## 2026-07-08 — Echo-Fix, Thermal-Crashes, Whisper medium, Sprecher-Lernen, Long-Rec-Analyse - **Selbst-Echo der Gegenseite gelöst:** LADSPA-Noise-Gate `micgate` im Mikro→PC-Pfad (Thr −45 dB, Mic-HW niedrig); AEC verworfen. Reboot-verifiziert. - **Thermal-Schutzabschaltungen gefixt:** A76-Cap 1,6 GHz über die ganze `transcribeWav` (Whisper+Diar), SIGSTOP-Guard >90 °C; crash-sicheres asynchrones Speichern (`stopAndSave` persistiert vor Transkription); `/retranscribe` für hängende Zeilen. - Whisper small → **medium** (Hörfehler). - **Sprecher-Umbenennen + Stimm-Lernen** (Voiceprint-Zentroide) + Leertaste Play/Pause. - Lange Aufnahmen (> 20 min) analysierbar: Chunked Map-Reduce gegen 4096-Token-Limit; Diar-Timeout skaliert mit Dauer; Lösch-Confirm. ## 2026-07-07 — MEILENSTEIN 1: USB-Headset-Pfad komplett - Logi H390 ersetzt toten ES8323-Mikrofonpfad; callmix + 4 Loopbacks + `callrec_mix`-Remap; Volume-Bridge; Inline-Tasten. - Kaltstart-verifiziert. Clip-sicheres Gain-Staging (PC→Mix 60 %) — Übersteuerung hatte Diarization zerstört (14 Sprecher, #41). - Re-Diarization mit fester Sprecherzahl (`numSpeakers`), #41 14→2 verifiziert. - LLM-Fixes: Phantom-Todo (Prompt-Beispiel-Echo) entfernt, KV-Cache-Clear, leere Todos → `[]`. ## 2026-07-06 - ES8323-3,5mm-Mikro als defekt diagnostiziert (Verstärkung fest −42,14 dB) → Entscheidung für USB-Headset. ## 2026-07-05 — „Helikopter“-Debugging (Referenz) - ES8323 S16-Modus = Treiberbug (S24 nutzen); PipeWire/alsaloop-Capture des ES8323 injizierte ~13 Klicks/s, arecord nicht; Windows-Shared-Mode-AGC = separates 20-Hz-Pumpen (exklusiv sauber). - Sauberer Fallback damals: dual native-clock arecord. Durch Headset-Pfad obsolet. ## Früher - iPhone-BT-HFP-Pfad aufgebaut (Rollen-Drop-in, frischer Pair, Echo-Fix Uplink←micgate, Route-Watcher) — Details Kap. 06. - BT-Buds No-Bonding-Quirk: LinkKey manuell persistiert (Referenz, Dongle entfernt).