docs/novaberg-embedding-casing-blind_b.md
Rama master · réplica de lectura del repositorio original.
# EMBEDDING-CASING-BLIND (Bauplan und Umstellung)
**Teil 3 von 5 — Bauplan und Umstellung.** Absicht und Kopfblock: [`novaberg-embedding-casing-blind_k.md`](novaberg-embedding-casing-blind_k.md) · Ausarbeitung: [`novaberg-embedding-casing-blind_t.md`](novaberg-embedding-casing-blind_t.md) · Diskussion und Ergänzungen: [`novaberg-embedding-casing-blind_e.md`](novaberg-embedding-casing-blind_e.md) · Messungen: [`novaberg-embedding-casing-blind_m.md`](novaberg-embedding-casing-blind_m.md). Die Abschnittsnummern sind die des ungeteilten Konzepts; welche Datei einen Abschnitt trägt, sagt die Tabelle *„§ → Datei“* in `_k`.
---
## 5. Sprint-Plan
### Phase 0 — Prompt↔Knoten-Kalibrierung ✅ teilerledigt Chat 107
Abdeckungsmessung (100 Prompts × 302 Knoten) durchgeführt; `anker_retrieval`
gemessen gesetzt, die übrigen 6 als begründete Startwerte mit
Wachposten-Kommentar (§4.2). Rest-Nachmessung nach Live-Betrieb.
### Phase 1 — Längen-Vorprüfung der übrigen fünf Spalten ⚠ offen
Nur `lzg_knoten` wurde gegen das 512-Token-Limit geprüft. **`entitaeten`, `fakten`,
`ziele`, `delegations_akten.themen`, `langzeitgedaechtnis` sind ungeprüft.**
```sql
SELECT 'entitaeten' AS t, max(length(name || ' ' || coalesce(zusammenfassung,''))) FROM entitaeten
UNION ALL SELECT 'fakten', max(length(inhalt)) FROM fakten
UNION ALL SELECT 'ziele', max(length(beschreibung)) FROM ziele;
```
Grenze: ~1500 Zeichen. Alles darüber wird still abgeschnitten.
### Phase 2 — Re-Embedding-Werkzeug bauen
**Es existiert kein Re-Embedding-Pfad.** Der Audit ist eindeutig: *„Kein `UPDATE
lzg_knoten SET embedding` im ganzen Repo."* Vorhandene Backfills laufen nur auf
`WHERE embedding IS NULL`.
Vorlage: `tools/migrate_lzg_synapsen.py` (Dry-Run-Modus, `--commit`, direkter
Embed-Call). Muss abdecken: 6 Postgres-Spalten + KZG-Hashes in Redis (float32-Bytes,
`raw_redis` ohne decode) + Shadow-Stack (JSON).
### Phase 3 — Umschaltung ⚠ Reihenfolge ist zwingend
Ein **Mischbestand ist schlimmer als der jetzige Zustand**: Alte und neue Vektoren
liegen in verschiedenen Räumen, der Kosinus zwischen ihnen ist bedeutungslos, und
pgvector merkt nichts.
1. **Server stoppen** (kein Turn darf in den Mischzustand fallen)
2. Schwellwerte setzen (Phase 0 + §4.1) — ✅ Code-Commit `3adc682` (Chat 107).
⚠ Ab hier gilt: KEIN Server-Neustart vor Schritt 3 (Modellwechsel) — die
neuen Schwellen gegen den alten Raum ließen das Retrieval komplett tot laufen.
3. `EMBED_MODEL` umschalten an **drei** Orten — ✅ Chat 107 (Commit `0eb1584`):
- `~/ki-assistent/docker-compose.yml` (**wirksam** — Env schlägt Config-Default!)
⚠ Liegt AUSSERHALB des Repos und wurde **von Hand geändert** — im Repo
nicht zu finden, nicht danach suchen.
- `novaberg/docker-compose.template.yml` ✅
- `novaberg/server/config.py` (Default) ✅ — samt Begründungs-Kommentar
(Casing-Blindheit, keine Task-Präfixe, Pull-Schritt).
Mitgezogen: READMEs (Architektur, VRAM-Tabelle, `ollama pull`-Block),
Docstrings embed_worker/registry, Enricher-Kommentar; toter
`EMBED_MODEL`-Import in `main.py` entfernt.
⚠ Phase B muss den Container NEU ERZEUGEN (`docker compose up -d`) —
ein bloßer Restart liest die Compose-Env nicht neu.
4. Re-Embedding laufen lassen (Dry-Run → Diff prüfen → `--commit`) —
`python -m tools.reembed_all --commit` (deckt inkl. Shadow-Leerung alles ab;
Werkzeug ✅ Chat 107, Commit `f866e1b`)
5. **Gewichts-Reset** — `--target reset` (✅ gebaut Chat 107, NICHT in "all"):
2910 Reinforcements (93 %) entstanden durch Skelett-Kollisionen
(cosine_max = 1.0000 im pipeline_log); `haeufigkeit` speist
`gewicht_absolut`, `gewicht_absolut` speist die Charakter-Destillation —
Nova trägt einen Charakter aus Zufallsgewichten. Der Reset rechnet den
Anlagezustand EXAKT zurück (`initial_roh = roh − (haeufigkeit−1) × Boost`,
dann die echte `gewicht_absolut_berechnen`; belegt: einziger Schreiber ist
`knoten_verstaerken`, Boost seit Einführung unverändert 0.1) und setzt
`verstaerkt_am := erstellt_am` — der Verfallsanker war von den
Zufalls-Reinforcements auf „frisch" gezogen. Löscht zugleich alle
`lzg_kanten` (1378 Stand 12.7.).
6. **Kanten-Neuaufbau** — `--target kanten_rebuild` (✅ gebaut Chat 107,
NICHT in "all"). ⚠ **Reihenfolge zwingend, kein Stil:**
`kanten_staerke_berechnen` liest `gewicht_absolut` — ein Aufbau VOR dem
Reset würde die Zufallsgewichte in die Kantenstärken einfrieren (der
Zufall wanderte aus den Knoten in die Kanten, wo ihn niemand mehr sucht).
Also: **Re-Embedding → Reset → Rebuild.** Chronologisch über
`kzg_erstellt_am` mit den echten Bausteinen (`kandidaten_mit_cosine_laden`
+ Trigger 1). Der bloße Cosine-Refresh (`--target kanten`) bleibt für
Refresh-OHNE-Reset-Szenarien erhalten, wird in Phase B aber durch den
Rebuild ersetzt.
7. **Server-Container NEU ERZEUGEN** (`docker compose up -d`, kein blosser
Restart) → löst nebenbei den `_strategie_embeddings_cache`
### Phase 4 — Abnahme
- Live-Turn: Anker-Retrieval liefert Treffer? Spreading feuert?
- `sim(Matcha, Kakao) < sim(Matcha, Paraphrase)` im Live-System
- Gravitation feuert wieder (war unter v1 immer an, wird jetzt selektiv)
- Wachposten: KZG-Kontext nicht leer, Magnete lösen auf
---
> **Hinweis zur Aufteilung (19.09.2026):** §6 *Offene Punkte / Landminen* steht in [`novaberg-embedding-casing-blind_e.md`](novaberg-embedding-casing-blind_e.md), Abschnitt C.