25 KiB
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 | ✅ 22 Tabellen, Indizes, 5 Buckets, Team internal – live und vollständig, scripts/setup-appwrite.mjs reproduziert diesen Stand idempotent (Stand 14.08.2026) |
| Prompts | P1–P18 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 |
Nachtrag 14.08.2026 – E0 ist erledigt. Der Abschnitt unten beschreibt den Stand vom 28.07. und ist ab hier Historie, keine Aufgabenliste mehr. Die Live-Datenbank war bereits vollständig migriert (alle 7 neuen Tabellen, alle 4 Enum-Erweiterungen,
attributesaufgetrennt, 5. Bucket) – nursetup-appwrite.mjsim Repo hing auf dem alten Stand hinterher und hätte beim Ausführen die Score-Spalten inattributeswieder angelegt. Das Skript ist inzwischen auf den Live-Stand gezogen und gegen ihn geprüft: 0 angelegt, 251 existierten schon, 0 Warnungen. Auch die beiden Enum-Entscheidungen aus §7.1 (Nischen-Liste,typ_tags) sind getroffen und stehen alsNISCHENundTYP_TAGSim Skript.
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 ✅ erledigt (14.08.2026)
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.
Abnahme erfüllt: 22 Tabellen und 5 Buckets stehen live; das Skript läuft ohne eine einzige Änderung durch (0 angelegt, 251 existierten schon, 0 Warnungen).
Datenbestand: nur Stammdaten – 4 Zeilen rules, 22 Zeilen prompt_templates (P1–P18, P8 als Familie). Keine Brand-Daten. Enum-Änderungen sind ab jetzt trotzdem nicht mehr gefahrlos, weil prompt_templates.key gefüllt ist.
Lehre aus dieser Etappe: Die Datenbank war der Quelle voraus, nicht umgekehrt. Wer
setup-appwrite.mjsin diesem Zustand ausgeführt hätte, hätte die sieben Score-Spalten inattributesneu angelegt und die Auftrennung halb zurückgedreht – ein idempotentes Skript schützt nur vor doppeltem Anlegen, nicht vor einer veralteten Definition. Deshalb: nach jeder Schema-Änderung an der Konsole das Skript nachziehen und mitscripts/check-appwrite.mjsgegenprüfen.
E1 · Projektgerüst Expo ✅ erledigt im Browser (14.08.2026), nativ ungeprüft
Inhalt: Expo-Projekt in client/, TypeScript, Expo Router (Stack + Tabs), Appwrite-SDK verdrahtet, Theme aus dem Prototyp. Fake-Tastatur und setInterval-Shader sind bewusst nicht übernommen.
Abnahme: npx tsc --noEmit fehlerfrei · npx expo export --platform web erzeugt alle drei Routen · im Browser rendern /, /erstellen und /profil mit Tab-Leiste, keine Konsolen-Fehler. Offen: der Start auf einem echten Gerät – dafür fehlt ein Testgerät bzw. ein Dev-Build.
Struktur (client/src/):
| Pfad | Inhalt |
|---|---|
app/_layout.tsx |
Wurzel-Stack, nicht direkt die Tabs – Willkommen/Anmelden liegen laut app-aufbau.md §3 vor den Tabs, das Onboarding als Modal darüber. Beide brauchen eine Ebene ohne Tab-Leiste. |
app/(tabs)/ |
Feed · Erstellen · Profil |
lib/appwrite.ts + .web.ts |
plattform-getrennter Client. react-native-appwrite läuft nicht im Browser, das Web-SDK appwrite kennt kein React Native – beide exportieren dieselben Klassen, der Rest der App importiert nur @/lib/appwrite. |
lib/config.ts |
Endpoint, Projekt-ID, DB-ID aus app.json → expo.extra.appwrite. Kein Server-Key – der landet sonst im Bundle. |
theme/tokens.ts |
Farben, Radien, Abstände aus prototyp-app.html. Dark-only, weil der Prototyp kein Light-Theme hat. |
Zwei bewusste Abweichungen: Das ➕ ist vorerst ein normaler Tab statt des Popovers aus §3 – der kommt mit den drei Erstellen-Abläufen in E6. Und der Profil-Screen zeigt provisorisch Endpoint und Projekt-ID, damit belegt ist, dass der Client wirklich lädt; das fliegt in E2 raus.
E2 · Auth und Mandant ✅ erledigt (14.08.2026)
Inhalt: Willkommen/Registrieren/Anmelden/Abmelden, Session-Persistenz, bei der Registrierung Team + brands-Zeile mit Zeilenrechten.
Abnahme erfüllt: scripts/test-mandanten.mjs legt zwei echte Konten an und prüft über die API: B listet nur die eigene Zeile · Direktzugriff B→A 404 row_not_found · Schreibzugriff B→A 401 user_unauthorized · Gegenprobe, dass der Server-Key beide Zeilen sieht. Räumt sich selbst auf.
Der eigentliche Inhalt war das Rechte-Modell, nicht die Formulare. Zwei Dinge, die vorher niemandem aufgefallen waren:
- Kein Client konnte irgendetwas anlegen. Bei
rowSecurity: trueregeln Zeilenrechte lesen/ändern/löschen – aber eine Zeile, die es noch nicht gibt, hat keine Rechte. Ohne Tabellen-Recht zum Anlegen war jede Client-Schreiboperation blockiert. 16 Tabellen haben jetztcreate("users");score_events,video_metrics,post_metricsundusage_recordsbewusst nicht – sonst könnte ein Nutzer seine eigenen Elo-Werte und Feed-Signale fälschen (§11, „Manipulation des Feed-Scores"). setup-appwrite.mjshat Rechte nie abgeglichen. Bei bestehenden Tabellen liefertePOSTnur ein 409, die Rechte blieben unangetastet. Das Skript vergleicht jetzt und zieht perPUTnach – sonst driftet das Rechte-Modell genauso wie zuvor das Schema.
Nebenfund: SDK-Version passte nicht zum Server. Appwrite läuft in 1.8.1, create-expo-app hatte SDKs mit Response-Format 1.9.5 gezogen. Gepinnt auf appwrite@23.0.0 und react-native-appwrite@0.25.0 (beide Response-Format 1.8.0), exakt statt Caret – der Sinn der Pinnung ist ja gerade der Gleichstand mit dem Server.
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 ✅ Generierung steht (15.08.2026), Verbessern-Strecke offen
Modell generieren ist gebaut. Anlegen erzeugt für Person, Produkt und Kulisse je vier Entwurfs-Versionen plus vier modell_gen-Jobs; freigegeben wird nichts, bis der Nutzer im Ergebnis-Screen eine Variante wählt. Die übrigen werden archiviert, nicht gelöscht, und won_against_version_id hält fest, wogegen sich die Siegerin durchgesetzt hat.
Prompt je Typ mit Identity-Lock am Anfang und am Ende, merkmale wörtlich, nur der Blickwinkel variiert über die vier Varianten. Der Studio-Block ist wörtlich aus P07 übernommen, wie es dort verlangt wird. Gesichter entstehen im 3:4-Headshot, Produkte und Kulissen quadratisch.
Logos: zwei Wege, die sich ausschließen. Die Brand-Regel schützt ein vorhandenes Markenzeichen davor, verzerrt, beschnitten, umgefärbt oder neu interpretiert zu werden. Eine Marke ohne Logo hat nichts zu schützen. Daraus:
- Datei hochgeladen → wird v1 und sofort freigegeben, ab da nie wieder generiert.
- Keine Datei, nur Beschreibung → vier Entwürfe. Es gibt kein Original, das verfremdet werden könnte.
- Ist einmal etwas freigegeben, ist Schluss. Der Dispatcher weist jeden weiteren
modell_gen-Job auf dieses Asset ab – geprüft: „Dieses Logo ist bereits freigegeben und wird laut Brand-Regel nicht neu generiert."
Beim Logo-Entwurf entfallen die globalen Regeln und der Schlusssatz „No text, no logo, no watermark" – beide wären widersinnig, wenn genau ein Schriftzug entstehen soll.
KI-Kennzeichnung sitzt an jeder erzeugten Kachel (EU AI Act, §10).
Durchgespielt über die Oberfläche: Kulisse „Badezimmer, Morgenlicht" ohne Referenzbild angelegt → 4 Varianten erzeugt → v2 freigegeben, v1/v3/v4 archiviert. Fehlerpfad mit ark geprüft: Variante bleibt entwurf, der Screen zeigt „fehlgeschlagen" mit der Anbieter-Meldung und einen Knopf „Nochmal"; nach dem Wiederholen war die Variante da.
Drei Fehler, die ein paralleler Prüflauf über
prompts/gefunden hat: der Kulissen-Prompt hatte keine Schluss-Klammer (die vier Varianten wären auseinandergedriftet); ein gescheiterter Job hat die Version aufarchiviertgesetzt und damit „vom Nutzer verworfen" mit „Generierung kaputt" verwechselt; und der Dispatcher hatlimitvor dem Statusfilter angewendet – bei gefüllterjobs-Tabelle hätte er wartende Jobs irgendwann nie mehr gefunden. Alle drei behoben.
E4 · Grundlage 🟡 Kern steht (14.08.2026), Verbessern-Strecke offen
Inhalt: Modell anlegen (Person, Produkt, Kulisse), echte Referenzbild-Uploads, Versionierung mit Release-Prinzip, Modelle-Übersicht im Profil.
Erledigt: Anlegen mit Typwahl und Mehrfach-Bildauswahl (modell/neu), Upload nach asset-references mit Team-Rechten, Version 1 wird angelegt und sofort freigegeben, assets.released_version_id zeigt darauf. Übersicht im Profil nach Typ gruppiert, mit Titelbild aus der freigegebenen Version.
Belegt: Vier Modelle (2 Produkte, 2 Kulissen) über scripts/seed-demo.mjs als Client angelegt – das beweist nebenbei, dass die Tabellen- und Bucket-Rechte aus E2 ausreichen. Alle vier Bilder laden in der App in Originalgröße.
P7 ist verdrahtet. Der Dispatcher lädt die aktive P7-Zeile aus prompt_templates, füllt die fünf Slots (USER_PROMPT, REGELN, ASSETS, ATTRIBUTE, ANWEISUNGEN – leere bekommen das Literal (leer)) und lässt P7 den englischen Bild-Prompt schreiben. Geprüft: alle fünf Platzhalter werden befüllt, keiner bleibt stehen. Bei Erfolg wird jobs.prompt_template_version mitgeschrieben – sonst wäre später nicht rekonstruierbar, welche Prompt-Fassung ein Bild erzeugt hat.
Ist kein LLM erreichbar (heute: kein OpenRouter-Guthaben), greift der deterministische Zusammenbau als Notlauf und meldet das im Log. Die Kette läuft damit auch ohne Guthaben, nur mit dem einfacheren Prompt. Der Job hält in prompt_sent fest, was wirklich rausging.
Referenzbilder gehen als Bild-Eingabe mit. P7 verlangt es so: bei vorhandener Referenz die Person nicht neu beschreiben, sondern nur einen kurzen visuellen Anker setzen. Der Dispatcher lädt dafür das Bild der freigegebenen Version jedes belegten Slots und hängt es an – bei OpenRouter als image_url, bei Ark als image[]. Höchstens vier, weil mehr die Merkmale mittelt statt sie zu schärfen (§8).
Wirkung, im direkten Vergleich geprüft: Vorher war die Person im Werbebild nur „eine blonde Frau" und die Kulisse ein ähnliches Badezimmer. Danach ist es dieselbe Person bis zu den Trägern des Tops, dieselbe Ablage, dieselbe Armatur, dasselbe Fenster. Die Identitätsdrift zwischen Modell und fertiger Szene ist damit weitgehend erledigt.
Verbessern-Strecke ✅ erledigt (15.08.2026)
Im Ergebnis-Screen gibt es „Nachschärfen": ein Feld für die Korrektur, dann vier weitere Varianten. Die freigegebene Version bleibt gültig, bis bewusst eine neue gewählt wird.
Zwei Dinge, die dabei anders sind als in der ersten Runde:
- Die Korrektur geht in P7s
ANWEISUNGEN-Slot, ausdrücklich mit Vorrang vor den Standardvorgaben. Ohne das gewinnt P7s eigener Satz „Neutral relaxed expression, no smile" gegen den Nutzerwunsch – genau das ist im Test passiert. - Die Runde ankert an der freigegebenen Version, nicht am ursprünglichen Upload. Sonst driftet das Aussehen mit jeder Runde weiter weg.
Durchgespielt an „Lena" mit der Korrektur „weicheres Licht, leichtes Lächeln": Licht und Mimik geändert, Gesicht erhalten.
Drei Fehler, die dieser eine Test aufgedeckt hat:
ANWEISUNGENwar leer, die Korrektur erreichte P7 also nie. Der Blickwinkel-Text schrieb „neutral relaxed expression" fest, was jede Mimik-Änderung unmöglich machte. Und beim Freigeben wurde nurentwurfarchiviert – die abgelöste Version blieb auffreigegebenstehen und erschien in der Liste als „Entwurf".
Offen: Einwilligungs-Upload für Personen.
Enum-Erweiterung: Risiko geprüft, nicht mehr theoretisch
§2.6 warnte, Enum-Änderungen könnten die Spalte neu anlegen und Daten vernichten – mit dem Zusatz „je nach Version". Für Appwrite 1.8.1 am 15.08.2026 gegen eine Wegwerf-Tabelle geprüft: additiver PATCH liefert 200, alle Bestandswerte überleben, der neue Wert ist sofort nutzbar. setup-appwrite.mjs zieht Enums seither automatisch nach – rein additiv, live vorhandene Zusatzwerte werden gemeldet, nie entfernt.
Zwei Auflagen: Nach jedem Appwrite-Upgrade den Test wiederholen, bevor das Skript gegen Produktion läuft. Und prompt_templates.key steht auf einer Tabu-Liste – die Tabelle ist mit 22 Zeilen gefüllt und trägt die Identität jedes Prompts; dort ist jede Enum-Berührung ein bewusstes Migrationsprojekt, kein Skriptlauf.
E5 · Ordner ✅ erledigt (14.08.2026)
Inhalt: Ordner-Liste, Anlegen mit den zwei Schaltern, Ordner-Detail, aktiver Ordner als App-Zustand. Function ordner-initialisieren.
Abnahme erfüllt – nach dem Anlegen über die Oberfläche steht in attribute_scores:
| Ordner | Modus | Scores | start_quelle |
|---|---|---|---|
(brand-weit, folder_id = null) |
– | 12 | neutral |
| Sommerkampagne | erben |
12 | geerbt |
| Cleane Studioshots | aus_posts |
0 | – |
| Herbstlinie (über die App angelegt) | erben |
12 | geerbt |
Zweck und Startwerte sind als Auswahl mit Erklärung umgesetzt, nicht als nackter Schalter: wer sie missversteht, baut sich einen Ordner, der nicht tut, was er erwartet.
Beim Erben wird der Wert kopiert, aber nicht die Sicherheit – k_factor geht zurück auf 32, weil im neuen Scope noch nichts belegt ist.
Abweichung: ordner-initialisieren läuft vorerst im Client statt als Appwrite-Function. Vertretbar, weil nur eigene Zeilen kopiert werden und die Zeilenrechte das ohnehin begrenzen; beim Umzug in eine Function ändert sich nur der Ort.
E6 · Post erstellen 🟡 Rezept-Hälfte steht (14.08.2026), Generierung extern blockiert
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.
Erledigt: erstellen/post mit Ordnerwahl in der Kopfzeile, Format, Kettenlänge und Slot-Auswahl für Kulisse, Produkt und Person – als Bildkacheln, weil bei Kulissen und Produkten das Aussehen die Information ist und ein Name wie „Halle, Metallwand" nichts darüber sagt, ob es passt. Der Post entsteht sofort mit status: entwurf, bevor irgendetwas generiert wird; ohne diese Zeile gäbe es keinen Ort, an den man nach dem Warten zurückkehrt. Je Kettenbild eine jobs-Zeile. Ordner-Detail zeigt die Posts mit aufgelösten Slot-Namen.
Nachweis über die Oberfläche: Post „Serum auf Waschtisch" → Ordner Herbstlinie, 4:5, 3 Bilder, privat, Slots Halle-Metallwand + Refine-&-Renew-Serum, dazu 3 Jobs bild_gen/wartend mit prompt_template_key = P7.
Job-Dispatcher steht – scripts/job-dispatcher.mjs, serverseitig, weil der Anbieter-Schlüssel nicht ins Client-Bundle darf. Er baut aus Slot-Rezept, den Beschreibungen der freigegebenen Asset-Versionen, den Top-Attributen des gewählten Ordners und den globalen Regeln einen Prompt, erzeugt das Bild, legt es in generated-images mit Team-Rechten ab, schreibt post_images und setzt den Post auf generiert, sobald die Kette vollständig ist.
Drei Anbieter über BILD_ANBIETER:
| Wert | Ergebnis (geprüft 14.08.2026) |
|---|---|
stub |
✅ erzeugt Platzhalterbilder – die ganze Kette ist damit prüfbar, ohne einen Cent auszugeben |
ark |
✗ ModelNotOpen: account 3003959567 has not activated seedream-5-0 |
openrouter |
✗ Insufficient credits. This account never purchased credits |
Durchgespielt mit stub: Post „Serum auf Waschtisch" → 3 Jobs → 3 Bilder erzeugt, hochgeladen, Post auf generiert, Kette im Ordner-Detail sichtbar (3/3 geladen). Bei den echten Anbietern greift der Fehlerpfad: Job auf fehler mit der Anbieter-Meldung, Post auf fehler.
Damit fehlt nur noch die Freischaltung. Sobald eines der beiden Konten offen ist, liefert BILD_ANBIETER=ark node scripts/job-dispatcher.mjs echte Bilder – ohne Codeänderung.
Offen: Umzug des Dispatchers in eine Appwrite-Function (läuft jetzt lokal/per Cron), P7 als versionierter Prompt statt der Vorstufe im Skript, P22 als Tagger, Wartezustand mit Realtime, Ergebnis-Screen mit Veröffentlichen.
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 |
| P12–P18, 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 15–20 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
Nischen-Liste und– ✅ entschieden und live. 20 Nischen, 17 Motiv-Tags, stehen alstyp_tags-ListeNISCHENundTYP_TAGSinscripts/setup-appwrite.mjs.- Bildmodell – blockiert nicht E0, aber E6. Der Anbieter steht (OpenRouter, siehe
projekt-uebersicht.md§9); offen ist nur, welches der dortigen Bildmodelle die Multi-Referenz-Komposition trifft. Der Wegwerf-Test dafür sollte parallel zu E1–E5 laufen. - Mindestalter und Moderationsweg – blockiert nicht den Code, aber E7 im Livebetrieb.