Files
videogen/planung/programmier-plan.md
2026-08-06 12:44:41 +02:00

193 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Programmier-Plan
**Stand:** 28. Juli 2026
**Repo:** `git.webklar.com/knso/videogen` · Backend: Appwrite `appwrite.webklar.com/v1`, Projekt `6a5cee34002bb8360c34`, DB `brandloop`
**Grundlage:** `app-aufbau.md` (Screens) · `konzept-bilder-feed.md` (Konzept) · `datenbank-aufbau.md` (Schema)
---
## 1. Ausgangslage was schon da ist
| | Stand |
|---|---|
| **Appwrite-Schema** | 15 Tabellen, Indizes, 4 Buckets, Team `internal` angelegt durch `scripts/setup-appwrite.mjs`, idempotent |
| **Prompts** | P1P18 als 22 Zeilen geseedet (P8 = Kern + 4 Adapter) via `scripts/seed-prompts.mjs`, versioniert |
| **Regeln** | 4 globale Brand-Regeln in `rules` |
| **Prototyp** | `prototyp-app.html`, 21 Screens, Handy-Ansicht, vollständig ohne Backend |
| **App-Code** | **existiert noch nicht** es gibt einen Expo-QR-Code, aber keine Anwendung |
**Der entscheidende Punkt:** Das Schema im Repo bildet den Stand **vor** dem Bild-/Feed-Konzept ab. Es fehlen alle Tabellen des neuen Produktteils. Wer jetzt anfängt, UI zu bauen, baut gegen Tabellen, die es nicht gibt.
---
## 2. Schema-Delta was konkret fehlt
Abgeglichen gegen `scripts/setup-appwrite.mjs`.
### 2.1 Neue Tabellen (6)
| Tabelle | Zweck |
|---|---|
| `folders` | Wissens-Scope: `brand_id`, `name`, `theme_md`, `zweck`, `startwert_modus`, `ist_default`, `post_count`, `signal_count` |
| `attribute_scores` | Score je Attribut je Ordner **Herzstück** |
| `posts` | Slot-Rezept, `slot_summary`, `sichtbarkeit`, `feed_score` |
| `post_images` | Bilderkette, `typ` = motiv \| text_overlay |
| `post_folders` | m:n Post ↔ Ordner, `ist_fremd`, `quelle` |
| `post_metrics` | Views, Likes, Kopien, Social-Reichweite |
### 2.2 Neue Tabelle wegen des Folgen-Konzepts (1)
| Tabelle | Zweck |
|---|---|
| `follows` | `follower_brand_id`, `followed_brand_id`, unique auf beide, Index in beide Richtungen |
### 2.3 Änderungen an bestehenden Tabellen
| Tabelle | Änderung | Art |
|---|---|---|
| `brands` | `+ nische`, `+ plan`, `+ anzeigename`, `+ avatar_file_id`, `+ follower_count`, `+ ist_oeffentlich` | Spalten ergänzen |
| `attributes` | ` score, k_factor, start_value, used_count, wins, losses, last_used_at` → wandern nach `attribute_scores`; Index `idx_topn` entfällt hier | **Umbau** |
| `categories` | `+ folder_id` | Spalte + Index |
| `assets` | `+ nische`, `+ typ_tags[]`, `+ feed_score`, `+ feed_score_updated_at`, `+ ist_teilbar`; `typ`-Enum **um `kulisse`** | Spalten + **Enum-Änderung** |
| `score_events` | `+ folder_id`, `+ post_id`; `event_type`-Enum **um `feed_import`, `post_reichweite`** | Spalten + **Enum-Änderung** |
| `scenes` | `+ folder_id` | Spalte |
| `jobs` | `typ`-Enum **um `slot_analyse`, `ordner_vorschlag`, `werbetext`** | **Enum-Änderung** |
| `prompt_templates` | `key`-Enum **P18 → P22** (`P_KEYS` im Skript: `length: 18``22`) | **Enum-Änderung** |
### 2.4 Neuer Bucket
`generated-images` öffentlich lesbar, sobald der zugehörige Post veröffentlicht ist.
### 2.5 Neue Functions (4)
`ordner-initialisieren` · `feed-score-berechnen` (Cron) · `feed-import` · `social-reichweite-holen` (Cron)
Dazu die aus dem alten Plan noch offenen: `elo-update`, `favorit-berechnen`, `ads-metriken-holen`, `kategorie-durchschnitt`, `archivierung`, `job-dispatcher`.
### 2.6 Zwei Fallen bei der Migration
**Enum-Änderungen sind kein Anhängen.** Vier Spalten brauchen neue Enum-Werte (`assets.typ`, `score_events.event_type`, `jobs.typ`, `prompt_templates.key`). Appwrite behandelt das als Spaltenänderung, nicht als Ergänzung je nach Version bedeutet das Löschen und Neuanlegen der Spalte, also **Datenverlust**. Das ist der Grund, warum diese Änderung **jetzt** passieren muss, solange die Tabellen leer sind. In sechs Wochen mit echten Daten ist es ein Migrationsprojekt.
**Die `attributes`-Auftrennung ist ein Umbau, kein Zusatz.** Sieben Spalten verschwinden aus einer Tabelle und tauchen in einer neuen wieder auf, mit einer zusätzlichen Dimension. Solange keine Brand existiert, ist das eine Textänderung im Setup-Skript. Danach ist es eine Datenwanderung mit Ausfallzeit.
> **Deshalb ist „Fundament zuerst" nicht nur die aufgeräumte, sondern die einzig günstige Reihenfolge.**
---
## 3. Etappen
Jede Etappe hat ein Abnahmekriterium etwas, das man vorführen kann. Ohne das ist nicht entscheidbar, ob sie fertig ist.
### E0 · Schema nachziehen
**Inhalt:** `setup-appwrite.mjs` um die 7 neuen Tabellen, die geänderten Spalten, die Enum-Erweiterungen und den Bucket ergänzen. `attributes` auftrennen. `P_KEYS` auf 22. Skript einmal komplett gegen eine **leere** Datenbank laufen lassen.
**Abnahme:** Skript läuft zweimal hintereinander fehlerfrei durch (idempotent), 22 Tabellen und 5 Buckets stehen in der Appwrite-Konsole.
**Aufwand:** klein. Reine Skriptarbeit, kein UI.
### E1 · Projektgerüst Expo
**Inhalt:** Expo-Projekt anlegen, TypeScript, Navigation (Tabs + Stacks), Appwrite-SDK verdrahten, Theme aus dem Prototyp übernehmen (Farben, Typo, Glas-Effekte **ohne** die Fake-Tastatur und ohne die Shader-Spielerei per `setInterval`).
**Abnahme:** App startet auf Handy und im Browser, drei Tabs sind klickbar, jeder Tab zeigt einen leeren Screen mit seinem Namen.
**Aufwand:** mittel. Hier entscheidet sich die Ordnerstruktur des Codes sorgfältig sein.
### E2 · Auth und Mandant
**Inhalt:** Registrieren, Anmelden, Abmelden. Bei der Registrierung: Appwrite-Team anlegen, `brands`-Zeile anlegen, Zeilenrechte setzen. Session-Persistenz.
**Abnahme:** Zwei Konten anlegen; Konto B sieht **keine** Daten von Konto A geprüft über die API, nicht über das UI.
**Aufwand:** mittel. Die Rechte-Prüfung ist der eigentliche Inhalt, nicht die Formulare.
> Das ist die Etappe, bei der man am ehesten schludert und es am teuersten wird. Die Mandantentrennung ist das Fundament des Rechte-Modells aus `datenbank-aufbau.md` §5.
### E3 · Onboarding
**Inhalt:** Die vier Onboarding-Screens mit echten Feldern, inklusive **Nische**. Uploads in den Bucket `uploads`. P2 als erster echter LLM-Aufruf über `jobs`.
**Abnahme:** Nach dem Onboarding stehen in `brands` sechs ausgefüllte Felder und in `attribute_scores` die ersten Attribute auf der brand-weiten Ebene (`folder_id = null`).
**Aufwand:** mittel.
### E4 · Modelle
**Inhalt:** Modell anlegen (Person, Produkt, **Kulisse**), echte Referenzbild-Uploads, Versionierung mit Release-Prinzip, Modelle-Übersicht im Profil.
**Abnahme:** Ein Produkt-Modell mit 4 Referenzbildern anlegen, freigeben, in der Übersicht sehen. `assets.released_version_id` zeigt auf die richtige Version.
**Aufwand:** mittel. Ohne Modelle kann nichts generiert werden deshalb vor der Generierung.
### E5 · Ordner
**Inhalt:** Ordner-Liste, Anlegen mit den zwei Schaltern, Ordner-Detail, aktiver Ordner als App-Zustand. Function `ordner-initialisieren`.
**Abnahme:** Zwei Ordner anlegen einen mit `erben`, einen mit `aus_posts`. In `attribute_scores` stehen danach unterschiedliche Startwerte mit korrekt gesetzter `start_quelle`.
**Aufwand:** mittel. Fachlich der anspruchsvollste Teil bis hierher.
### E6 · Post erstellen (erste echte Generierung)
**Inhalt:** Create-Screen mit Ordner, Format, Kette, Slots. `jobs` + `job-dispatcher` + Realtime-Wartezustand. P7 auf das Slot-System umbauen. P22 als Bild-Tagger. Post-Ergebnis mit privat/veröffentlichen.
**Abnahme:** Ein Prompt erzeugt eine dreiteilige Bilderkette, die im Entwürfe-Screen auftaucht, auch wenn man die App zwischendurch schließt.
**Aufwand:** groß. Hier hängt die Auswahl des Bildmodells dran **offener Punkt 1**.
### E7 · Feed
**Inhalt:** Veröffentlichen mit Zeilen-Permission, Feed-Deck mit den drei Reitern, Post-Detail, `post_metrics` schreiben, Function `feed-score-berechnen` mit Decay und Explorations-Slot.
**Abnahme:** Ein veröffentlichter Post von Konto A erscheint im Feed von Konto B. `prompt_sent` ist über die API von Konto B **nicht** abrufbar.
**Aufwand:** groß.
### E8 · Kopieren
**Inhalt:** P19 (Slot-Analyst), Kopier-Screen mit Chips und Kompatibilitätsprüfung, P21 (Werbetext), Function `feed-import`, `copied_from_post_id`, Kopien-Zähler.
**Abnahme:** Konto B kopiert den Post von Konto A, ersetzt beide Modelle, generiert und in der Knowledge Base von Konto B stehen danach neue Attribute mit `start_quelle = feed_import` im gewählten Ordner.
**Aufwand:** groß. Das ist der Moment, in dem das Produkt das tut, was es verspricht.
### E9 · Folgen
**Inhalt:** `follows`, Fremdprofil, Folgen-Button, Reiter „Folge ich" chronologisch, Blockieren und Melden.
**Abnahme:** Konto B folgt Konto A und sieht dessen neuen Post im Reiter „Folge ich", vor allem anderen.
**Aufwand:** mittel.
### E10 · Video-Strecke
**Inhalt:** Die bestehende Video-Strecke aus dem Prototyp echt machen: `scenes`, P3/P4/P5/P8, `videos`, Vote, `elo-update`, gezielte Frage.
**Abnahme:** Ein Prompt erzeugt vier Videos von vier KI-Modellen; nach dem Vote haben sich Scores in `attribute_scores` messbar verändert und `score_events` hat die passenden Zeilen.
**Aufwand:** sehr groß, und mit laufenden Kosten ab dem ersten Test.
---
## 4. Reihenfolge und Abhängigkeiten
```
E0 Schema
└─ E1 Gerüst
└─ E2 Auth ──────────────┐
├─ E3 Onboarding │
├─ E4 Modelle ───────┤
└─ E5 Ordner ────────┤
└─ E6 Post erstellen
├─ E7 Feed
│ ├─ E8 Kopieren
│ └─ E9 Folgen
└─ E10 Video
```
**E3, E4 und E5 sind untereinander unabhängig** sie können in beliebiger Reihenfolge oder parallel entstehen. Alles ab E6 hängt an allen dreien.
**E10 (Video) steht bewusst hinten,** obwohl es das Kernprodukt ist: Es ist die teuerste Strecke in der Umsetzung *und* im Betrieb, und der Bild-Strang erzeugt vorher die Daten, mit denen sich der Video-Teil überhaupt sinnvoll testen lässt.
---
## 5. Was im ersten Durchgang bewusst wegbleibt
| Weggelassen | Warum |
|---|---|
| Desktop-Ansicht | Handy zuerst; der Handoff im Repo ist laut dir noch nicht gültig |
| Stripe / Abrechnung | Preismodell ist offen (offener Punkt 3) ohne Entscheidung nicht baubar |
| Meta-/TikTok-Ads-Anbindung | App-Reviews dauern; Antrag trotzdem **jetzt** stellen, unabhängig vom Code |
| Social-Reichweite (echte Instagram-Zahlen) | eigene App-Review; bis dahin läuft der Feed-Score nur auf In-App-Signalen |
| P12P18, P20 | nachrüstbar, ohne sie funktioniert der Loop |
| Verbessern-Strecke | vorhanden im Prototyp, aber nicht auf dem kritischen Pfad |
| Developer-Modus | intern, kein Nutzerwert erst wenn es echte Prompts zu debuggen gibt |
---
## 6. Risiken
| Risiko | Wirkung | Gegenmaßnahme |
|---|---|---|
| **Enum-Migration nach dem Livegang** | Datenverlust in vier Spalten | E0 vor allem anderen, solange die DB leer ist |
| **Multi-Referenz-Komposition** (Person + Produkt + Kulisse konsistent in einem Bild) | Der Kern des Bild-Modus funktioniert nicht wie gedacht | Vor E6 mit zwei, drei Kandidatenmodellen einen Wegwerf-Test fahren **bevor** UI dafür gebaut wird |
| **Generierungskosten im Test** | schleichende Kosten ohne Gegenwert | `jobs.cost_usd` ab E6 mitschreiben und ein hartes Tageslimit einbauen |
| **Leerer Feed** | E7 ist nicht bewertbar, E8 nicht testbar | Vor E7 mit dem eigenen Konto 1520 Posts erzeugen |
| **Prototyp als Vorlage überschätzt** | Screens werden 1:1 übernommen inklusive der Attrappen | `app-aufbau.md` §6 ist die verbindliche Liste, nicht die HTML-Datei |
| **Öffentlich/privat nur im UI durchgesetzt** | fremde Knowledge Bases werden über die API auslesbar | Abnahme von E7 ausdrücklich **über die API** prüfen, nicht über den Bildschirm |
---
## 7. Was vor E0 zu entscheiden ist
1. **Nischen-Liste** und **`typ_tags`-Liste** beide sind Enums und wandern in E0 ins Schema. Später zu ändern heißt: dieselbe Migrationsfalle wie oben.
2. **Bildmodell** blockiert nicht E0, aber E6. Der Test dafür sollte parallel zu E1E5 laufen.
3. **Mindestalter und Moderationsweg** blockiert nicht den Code, aber E7 im Livebetrieb.