⚡ Supamoe · Self-Learning Loop

Den Loop schließen

Was in den letzten 2 Tagen gebaut wurde, damit aus einem gewinnenden Creative automatisch die nächste Generation entsteht — Winner erkennen → labeln → züchten → zurück in den Pool. Plus: wo überall Tags entstehen, was in welchem Schritt ingested wird, und wie du alles E2E testest.

Stand 2026-06-05 · Build 1 (Benchmark) + Build 2 (Breed) live · Brand: Iron Brothers Collagen

Überblick

Der geschlossene Loop auf einen Blick

Der Kern: ein Creative wird gebaut, läuft auf Meta, die Performance wird gemessen und in DNA-Tags übersetzt. Aus den Tags errechnet sich, welcher Angle/welche Mechanik gewinnt. Der gewinnende Creative wird gelabelt und gezüchtet — die nächste Generation erbt die DNA und variiert ein Element. So lernt das System aus deinen eigenen Ergebnissen.

01

Erzeugen

Creative Engine baut Bilder/Videos. DNA-Tags werden schon hier gesetzt.

on-demand
02

Launch (PAUSED)

1-Klick auf Meta, pausiert. Du aktivierst.

on-demand
03

Meta-Import

Performance + meta_ad_id zurück ins System.

stündlich · 0 * * * *
04

Cold-Start Vision

Importierte Ads ohne Tags → Vision schlägt Labels vor.

19:00 · 0 19 * * *
05

DNA-Rollup

Tags × Performance → creative_dna + Winner je Achse.

20:30 · 30 20 * * *
06

Benchmark / Winner

Ranking gegen deine KPI-Benchmark. Du siehst die Gewinner.

live · Build 1
07

Labeln

Vision schlägt Angle vor, du korrigierst. Tag = „customer".

live · Build 1
08

Züchten

Erbt DNA, variiert Headline → 3 Drafts in den Pool.

live · Build 2
09

→ Launch & messen

Drafts launchen → Schritt 03 misst sie → Kreis geschlossen.

on-demand

Orange = automatischer Backend-Schritt (Cron oder async-Job) · „NEU" = in diesen 2 Tagen gebaut/freigeschaltet

Was „den Loop schließen" konkret heißt

Vor 2 Tagen war der Loop read-only: das System erkannte Winner und sagte dem Menschen „mach mehr davon" — aber jeder neue Zyklus musste manuell angestoßen werden, und importierte Ads hatten gar keine Tags. Jetzt: Cold-Start-Tags (04) geben jedem Ad eine DNA, die Benchmark (06) macht Winner sichtbar, Labeln (07) gibt ihnen den richtigen Angle, und Züchten (08) erzeugt die nächste Generation per Klick — mit geerbter DNA. Der Mensch bleibt im Steuer (Phase 1), aber die Mechanik des Kreises steht.

Mechanik

Jede Stage: was passiert & was wird ingested
StageWas passiertWas wird geschrieben / ingestedTrigger
01 ErzeugenCreative Engine generiert Varianten (generateCreativeVariants).ad_pool_items (Bild/Video + DNA-Tags) · Asset in R2.on-demand
02 LaunchPush als PAUSED Meta-Ad (handleLaunchpadPush). Mensch aktiviert.Meta-Ad-Objekt · pool.meta_status, launched_at.on-demand
03 ImportHolt Spend/Revenue/Klicks je Ad/Tag von Meta (handleMetaImport).ad_performance_daily (spend, meta_revenue/nc_revenue, roas, clicks, nc_orders …) · setzt pool.meta_ad_id.stündlich
04 Cold-StartFür importierte Ads ohne Labels: Vision liest das Creative + schlägt DNA-Tags vor.Tag-Spalten auf ad_pool_items (wo vorher NULL).19:00 täglich
05 RollupJoint Tags × Performance (14-Tage-Fenster) → Snapshots + Winner je Achse (MIN 4 Ads / 50 €, James-Stein-Shrinkage).creative_dna (hook_rate, hold_rate, link_ctr, roas, cpa) · Performance-Learnings in den Agent-Kontext.20:30 täglich
06 BenchmarkRankt deine Ads gegen die KPI-Benchmark der Marke (ROAS/CPA/CPC, 2×CPA-Spend-Riegel). Join: pool.meta_ad_id = ad_performance_daily.ad_id.brand_benchmarks (deine KPI-Ziele, persistent) · Winner-Liste live berechnet.live (Tab)
07 LabelnVision schlägt Angle (gegen deine echten Angles gematcht) + Hook/Headline/Template/Format vor; du korrigierst.Tag-Spalten + payload.angle_source='customer' (Cron überschreibt das nie mehr).live (Drawer)
08 ZüchtenBreed-Job erbt die exakten Tags des Winners, lässt die Headline frei → 3 Bild-Varianten.async generation_jobs (type agent-tool-job) → 3 neue ad_pool_items (status draft, geerbte Tags, source='breed_variant').live (Button)
09 RelaunchDrafts als PAUSED launchen → Stage 03 misst sie → Stage 05 faltet sie zurück.(zurück zu 02/03)on-demand

Der async-Job-Pfad (Stage 08) — wie ein Breed technisch läuft

Klick „Züchten" → POST /winners/breed legt eine pending-Row in generation_jobs an (mit dem vollen Replay-Payload). Der */2-Min-Cron claimt sie atomar (pending→processing), ruft sich per SELF.fetch intern selbst auf (kein 150s-Wall-Limit), generiert die Varianten, verrechnet genau einmal Credits, legt die Drafts an, setzt completed. Du siehst den Fortschritt in der Jobs-Leiste. Exakt dasselbe Muster wie b-roll/Creative-Engine — heute end-to-end in Prod bewiesen.

Die DNA

Wo kommen die Tags her? — 4 Quellen

„Tags" = die kanonische Creative-DNA eines Ads: angle_idhook_typetemplate_categoryvisual_familyad_formatawareness_leveloffer_labelcopy_framework (+ headline). Sie sind load-bearing: das Rollup (05) gruppiert per exaktem String — deshalb müssen geerbte Tags exakt gleich sein, sonst zerfällt das Lernen. Tags entstehen an genau 4 Stellen:

🛠️

1 · Bei der Erzeugung

Wenn die Creative Engine ein Ad baut, kennt sie Angle + Template + Format und schreibt die Tags direkt mit.

Stage 01 · creative.js → ad_pool_items
👁️

2 · Cold-Start Vision (Auto)

Ads, die du vor Supamoe geschaltet hast, kommen beim Import ohne Tags. Der 19:00-Cron lässt Vision sie nachträglich labeln (nur wo Tags NULL sind).

Stage 04 · coldstart cron · gated auf template_category IS NULL
✍️

3 · Deine Korrektur

Im „Labeln"-Drawer schlägt Vision den Angle vor (gegen deine echten Angles gematcht), du bestätigst/korrigierst. Markiert als angle_source='customer' — der Cron fasst das nie wieder an.

Stage 07 · Build 1 · ad_pool_items + payload
🧬

4 · Vererbung beim Züchten

Der gezüchtete Draft erbt die exakten Tag-Strings des Winners (Angle + Template fix), nur die Headline ist neu. So landet die Variante im Rollup in derselben Gruppe wie der Parent → Lernen verdichtet sich.

Stage 08 · Build 2 · createDraftPoolItem(poolLabelRecordFromPayload)

Warum die exakte Vererbung kritisch ist

Genau hier saß einer der gefixten Bugs: das Speichern eines Labels hat 4 DNA-Spalten genullt, die der Drawer nicht mitschickt. Das hätte beim Labeln die Cold-Start-DNA zerstört. Jetzt wird nur noch geschrieben, was du wirklich änderst — der Rest bleibt erhalten.

Changelog

Was in 2 Tagen gebaut + gefixt wurde

Build 1 — „Benchmark"-Step (Winner-Fundament)

Die Hälfte des Loops, die Winner sichtbar + labelbar macht (Stages 06 + 07).

Benchmark-Persistenz — eigene KPI-Ziele pro Marke (ROAS/CPA/CPC), gespeichert in brand_benchmarks + 30-Tage-Vorschlag-Button.
Winner-Ranking — phasenabhängig: Testing = CPA mit 2×-CPA-Riegel, Evergreen = du wählst die Metrik. Live verifiziert auf echten Daten (12 Winner @ Vorschlag-Benchmark).
„Benchmark"-Tab + Vision-Label-Vorschlag + Korrektur-Drawer (Cold-Start: Vision schlägt vor, du korrigierst).

Fixes — was kaputt war & jetzt läuft

Async-Pfad war tot prod — ein DB-Constraint (type-CHECK) + ein output:null-Insert blockierten jeden async-Job (Breed, Creative-Engine-Batch, Agent-Tools). Beide gefixt → der SELF.fetch-Dispatch ist jetzt end-to-end bewiesen.
Label-Speichern nullte 4 DNA-Spalten — siehe oben. Jetzt partielles Patchen, DNA bleibt erhalten.
Leer-Vorschlag — der 30-Tage-Vorschlag speicherte bei fehlenden Daten eine 0-Benchmark (alles gewinnt). Jetzt mit Guard.
Brand-Switch-Race — beim schnellen Markenwechsel konnten KPIs auf die falsche Marke geschrieben werden. Gefixt + adversarial verifiziert.
Aggregat-Doppelzählung — Härtung gegen vor-aggregierte Performance-Rows (latent, jetzt ausgeschlossen).

Build 2 — „Züchten" (Loop geschlossen)

Die zweite Hälfte: aus einem gelabelten Winner die nächste Generation (Stage 08).

breed-payload — erbt Angle + Template (fix), lässt Headline frei (Headline-Sweep). breed-policy — 3 Varianten Default, 1–6 geklemmt.
breed-runner — generiert Varianten → legt sie als Drafts mit geerbten Tags an; 0 gerendert → Credit-Refund.
Endpoint + „Züchten"-Button — auf jeder Winner-Card. 422 wenn unlabeled → koppelt Züchten zwingend an Labeln (kein DNA-loser Breed).

Alles über den bewährten async-Pfad, 0 Edits an FROZEN-Files (creative.js/db.js/routes.js nur importiert). Phase 2 (nightly Auto-Breed hinter Marken-Flag) ist bewusst noch nicht gebaut — der Mensch steuert die Frequenz.

Anleitung

E2E-Test — Schritt für Schritt

Vorbedingungen

① Dev-Account (der Benchmark-Tab ist dev-only). ② Marke Iron Brothers Collagen mit verbundenem Meta-Konto (Ads sind schon importiert). ③ Credits auf der Marke: 3 Varianten ≈ 33 Credits — falls leer, vorher aufladen, sonst schlägt Stage 08 mit „insufficient credits" fehl.

1

Benchmark setzen

Benchmark-Tab öffnen → Marke wählen → „Vorschlag aus 30 Tagen" klicken (oder Werte manuell). Speichern (Auto-Save nach ~1 s).

Erwartung: Vorschlag ≈ ROAS 2,08 · CPA 23,61 € · CPC 0,71 € (auf Basis ~40 Ads / 95 k € Spend). Darunter erscheinen ~12 Gewinner.
Ich prüfe in DB: eine Row in brand_benchmarks für brand_id 761465fe mit deinen Werten.
2

Winner labeln (Tag setzen)

Auf einem Winner (z.B. einem Whey-Ad) „Labeln" → der Drawer öffnet, Vision schlägt einen Angle vor. Angle wählen/korrigieren (+ optional Hook/Headline/Template/Format) → Speichern.

Erwartung: Drawer schließt, Winner-Liste refresht. Der Winner hat jetzt einen Angle.
Ich prüfe in DB: ad_pool_items des Winners hat angle_id gesetzt + payload.angle_source='customer'; die anderen DNA-Spalten unverändert (kein Nullen mehr).
3

Züchten (Breed-Job starten)

Auf derselben Card „Züchten" klicken.

Erwartung: Inline-Meldung „🧬 3 Varianten werden gezüchtet — Draft im Pool (~1–3 Min)". Ein Job taucht in der Jobs-Leiste auf. Wenn der Winner nicht gelabelt ist → „Erst labeln, dann züchten." (das ist der 422-Guard, kein Bug).
Ich prüfe in DB: neue generation_jobs-Row, type agent-tool-job, input.tool='breed_variant', output:{}, Status pending.
4

Job läuft durch

Nichts tun — der */2-Min-Cron übernimmt. Innerhalb von ~2 Min: pending → processing, dann rendern die Bilder, dann completed.

Erwartung: Jobs-Leiste zeigt Fortschritt → fertig.
Ich prüfe in DB live: die Row läuft pending→processing→completed; output.result.bred = Anzahl Drafts; genau 1 credit_transactions-Eintrag (charge-once).
5

Varianten prüfen (DNA-Vererbung)

In den Pool / Creative Engine schauen — 3 neue Drafts vom gezüchteten Winner.

Erwartung: 3 neue Bild-Drafts, gleicher Angle + gleiches Template wie der Winner, aber neue Headlines. Status „Draft" (noch nicht live).
Ich prüfe in DB: 3 neue ad_pool_items mit source='breed_variant', source_ref=Winner-ID, status draft, exakt geerbte Tag-Strings (angle_id/template_category/… identisch zum Parent), je eine eigene Headline.
6

(Optional) Loop schließen

Einen Draft als PAUSED auf Meta launchen → aktivieren. Ab da misst der stündliche Import (Stage 03) die Variante, der nächtliche Rollup (Stage 05) faltet sie zurück in die DNA-Statistik — und beim nächsten Mal taucht sie selbst als Winner-Kandidat auf.

Erwartung: nach dem nächsten Import erscheint die Variante mit eigener meta_ad_id + Performance. Der Kreis ist geschlossen.

Sag mir einfach „los"

Wenn du den „Züchten"-Klick machst (Schritt 3), gib mir kurz Bescheid oder nenn den Winner — dann tracke ich den ganzen Lauf live in der DB und bestätige dir jede Stufe (Job-Status, geerbte Tags, Credit-Charge). Genau wie beim b-roll-Smoke-Test heute früh.