2026-07-06-0ne-studio-ai-driven-tools-design.md

docs/superpowers/specs/2026-07-06-0ne-studio-ai-driven-tools-design.md

0ne Studio — KI bedient die visuellen Tools, du schaust live zu


1. Nordstern

Eine KI (Claude, von außen per Browser-Automation) soll die verstreuten visuellen Tools von 0nefinity wie ein Mensch bedienen können: Regler drehen, direkt auf dem Canvas ziehen, das Ergebnis sehen, beurteilen, nachjustieren, Video rausrendern. Tim schaut dabei in Echtzeit zu — ein Livestream davon, wie die KI spielt und Erkenntnisse gewinnt.

Zweitrangig, aber als angenehme Konsequenz: das ist zugleich der Weg zur Vereinheitlichung. Jedes Tool, das auf controls.js gehoben wird, wird dadurch automatisch KI-fähig. Kein separater Umbau nötig.


2. Kernidee: ein Vertrag, zwei Nutzer

Meta-Tool und KI-Steuerung sind dasselbe Problem. Wenn jedes Tool eine Standard-Schnittstelle freilegt — „hier sind meine Regler und ihre Grenzen, lies und setz sie, nimm ein Video auf" — dann kann sowohl ein Menschen-Hub als auch eine KI (von außen) alle Tools gleich bedienen.

Der Angelpunkt existiert bereits: tools/controls.js kennt intern jeden Regler samt Grenzen (~15–20 der neueren Tools nutzen es). Eine Änderung an dieser einen Datei schaltet alle diese Tools gleichzeitig frei.


3. Architektur — drei Bausteine

Baustein 1 — Der Vertrag: window.OneTool in controls.js

Eine schlanke Fassade, die über alle registrierten ControlPanel-Instanzen introspiziert und sie programmatisch bedient.

Was controls.js heute schon hat (verankert am Code):

Verifizierte Realitäten, die das Design einpreisen muss (Code-Sonde):

Was zu bauen ist:

  1. Panel-Registry. In Controls.createPanel(...) jede neu erzeugte ControlPanel in ein Modul-globales Array registeredPanels pushen.

  2. window.OneTool-Fassade mit:

    • OneTool.schema() → Array aller Regler über alle Panels. Pro Eintrag: { key, type, label, value, min?, max?, step?, decimals?, options? }. Zusammengesetzt aus params (value), _sliderConfigs (min/max/step/decimals für Slider), _selectControls (options), sowie Typ-Erkennung (slider / toggle / select / countpicker / text) anhand der vorhandenen internen Maps.
    • OneTool.get(key) → aktueller Wert (delegiert an das Panel, das key führt).
    • OneTool.set(key, value)muss den Effekt wirklich auslösen. Ablauf: panel.set(key, value) (UI + params aktualisieren) danach panel.callbacks[key]?.(value, key) (onChange feuern → im Tool wird die lose let-Variable gesetzt und draw() gerufen). Genau dieser Zwei-Schritt ist der eine notwendige Fix.
    • OneTool.setMany(patch) → mehrere Werte auf einmal ({fractalCount: 500, fractalScale: 1.2}), am Ende genau ein Redraw pro betroffenem Tool ist akzeptabel (jeder set triggert eh draw(); Tools sind idempotent im draw()).
    • OneTool.record(seconds, opts?) → generischer Video-Export. Findet den Tool-Canvas (Heuristik oben; optional opts.selector), canvas.captureStream(opts.fps ?? 30), MediaRecorder mit isTypeSupported()-Fallback-Kette vp9 → vp8 → video/webm (NICHT hart vp9), sammelt Chunks, nach seconds Stop → Blob → Auto-Download und Rückgabe der Blob-URL. Generalisiert das verifizierte Muster aus millionen_Kreise_aufnehmen.html:250-269. Canvas muss während der Aufnahme sichtbar bleiben (kein display:none, sonst friert der Stream). CSP ist bereits kompatibel (media-src/img-src/worker-src erlauben blob:/data:, .htaccess:101) — keine Header-Änderung nötig.
    • OneTool.snapshot(opts?)canvas.toDataURL('image/png') des Tool-Canvas (Bonus für den Menschen-Hub; für die KI ist der Playwright-Screenshot der primäre Sehkanal, siehe Baustein 3).
    • OneTool.reset() → delegiert an vorhandene Reset-Buttons/addResetButton, falls registriert (best effort).

Wichtige Randbedingungen:

Baustein 2 — Das Schaufenster: noVNC-Livestream

Claude läuft headless auf dem VPS; localhost ist für Tim nicht erreichbar. Deshalb ein sichtbarer Browser, dessen Bild als Webseite zu Tim gestreamt wird.

Verifizierter Bestand (Infra-Sonde): Xvfb 21.1, x11vnc 0.9.16, websockify 0.10, noVNC 1.3 sind bereits installiert; Playwright 1.61 + gecachte Chromium-Builds vorhanden. 16 Cores / ~41 GiB frei — Budget locker. Nächster freier expose-Port: 9004 (9xxx laut Erfahrung vom Hoster nicht gefiltert). Kein /dev/dri → reines Software-Rendering (für Canvas2D egal, siehe unten). System-Chromium ist ein Snap (Confinement-Zicken) → Playwright-Chromium verwenden, headed gegen DISPLAY=:99.

Kette:

  1. Virtuelles DisplayXvfb :99 (1920×1080).
  2. Sichtbarer Playwright-Chromium in diesem Display (headless: false, env DISPLAY=:99).
  3. VNC-Serverx11vnc -display :99 -viewonly -rfbauth <passwd-file>.
  4. Web-Brückewebsockify --web /usr/share/novnc (noVNC-Viewer, zusätzlich view_only).
  5. Öffentlich machensudo expose 0ne-studio 9004ff → HTTPS-URL für Tim.

SICHERHEITS-HÄRTUNG (PFLICHT, verifizierter Befund): Das expose-Skript (/usr/local/bin/expose) erzeugt nginx-Blöcke ohne jede Auth — kein Basic-Auth, kein Token, keine IP-Allowlist; self-signed-Warnung ist kein Schutz. Ein ungeschützter Live-Browser wäre für jeden Port-Scanner einsehbar und (bei VNC-Default) steuerbar — und ein steuerbarer Browser auf dem Prod-VPS kann auf localhost-Services/interne Dashboards navigieren (SSRF-artiges Loch). Deshalb, bevor irgendetwas online geht, alle drei:

  1. x11vnc -viewonly (Server nimmt keine Eingaben an) und noVNC view_only,
  2. Zugangsschutz — VNC-Passwort (-rfbauth) und/oder auth_basic im nginx-Block,
  3. Browser einsperren: die Chromium-Instanz nur auf dev.0nefinity.love fahren (Playwright-Kontext ohne weitere Tabs; keine internen URLs öffnen).

Ergebnis: Tim öffnet die URL und sieht den echten Browser — Mauszeiger, springende Slider, sich änderndes Canvas — live, während Claude arbeitet. Claudes Erkenntnisse laufen parallel im Chat.

Werkzeug-agnostisch: der Stream zeigt jede Seite, auch Ad-hoc-Tools ohne OneTool.

Baustein 3 — Der Fahrer: Claude via Playwright, zwei Eingabekanäle

Kein separates CLI-Werkzeug. Claude fährt ad-hoc, verbindet sich mit dem sichtbaren Chromium (Baustein 2). Zwei Eingabekanäle, beide im Stream sichtbar:

Sehkanal (Feedback-Loop): page.screenshot() → Datei → Claude liest das Bild (Vision) → beurteilt → justiert nach. Der Loop: öffnen → schema() lesen → set()/Geste → screenshot → beurteilen → nachjustieren → bei Gefallen record().

Ehrliche Grenzen des Sehkanals (eingepreist):


4. Gestufte Einführung

  1. Fundament (Baustein 1 + 2): OneTool in controls.js + noVNC-Livestream.
  2. Erster Beweis (dieser Task): eine Live-Session an circleheart.html mit Fraktalmodus. Claude schaltet isFractal ein, fährt fractalScale, fractalCount, fractalRotation, fractalOpacity; zieht per Geste am Fraktal-Zentrum und an den Deformations-Punkten; nimmt am Ende ~5 s Video auf. Tim schaut live zu.
  3. Danach (spätere Tasks), auf demselben Fundament:
    • Prompt → Video (autonomer Batch): „mach ein hypnotisches Muster, 10 s, dunkel" → Tool wählen, Werte drehen, rendern, abliefern.
    • Explorer/Kurator: Parameterraum systematisch absuchen, visuell bewerten, kuratierte Auswahl präsentieren.
    • Explorer mit Nicht-LLM-Stack (Tims Frage nach „anderen KI-Formen"): LLMs sind für Echtzeit-Visuelles nicht optimal — aber spezialisierte Komponenten ergänzen sie: ein Ästhetik-Scorer (CLIP-artiges Vision-Modell, ~100 ms/Bild, CPU-tauglich) bewertet Varianten massenhaft; ein Optimierer (CMA-ES / evolutionäre Suche) fährt den Parameterraum mit dem Scorer als Fitness-Funktion (etabliertes Feld: CLIP-guided evolution). Der Scorer lässt sich auf Tims Geschmack kalibrieren (100–200 bewertete Screenshots → kleiner Kopf auf CLIP-Features; Inferenz auf dem VPS machbar, kein GPU-Training nötig). Rollen: Optimierer/Scorer erkunden schnell und dumm, Claude dirigiert und kuratiert, Tim lenkt. Genau dafür ist schema() von Tag 1 optimierer-tauglich (sauberes JSON, Typen, Ranges = Genom-Definition). Echtes RL-Training auf den Tools: bewusst verworfen (Reward-Funktion ungelöst, Forschungsaufwand).
    • Gesten-Deklaration (hotspots()-Hook): Tools melden ihre Ziehpunkte und Gesten-Semantik → KI-Gesten generisch statt per Code-Lektüre. Phase 2.
    • Look speichern (config→URL-Serialisierung): gefundene Einstellungen festhalten/teilen; ohne das ist ein Fund nach Reload weg (nur Video bleibt). Phase 2.
    • Migration weiterer Ad-hoc-Tools auf controls.js = Vereinheitlichung, jedes migrierte Tool wird automatisch KI-fähig. WebGL-Tools (12 Dateien, u.a. fractal0ne, shadows) brauchen dabei Extra-Sorgfalt: SwiftShader-Flags, ggf. preserveDrawingBuffer, Framerate pro Tool empirisch testen.

5. Nicht-Ziele (YAGNI)


6. Acceptance Criteria (messbar, wo möglich auto-prüfbar)

AC1 — Introspektion. Auf circleheart.html liefert window.OneTool.schema() Einträge für mindestens isFractal (type toggle), fractalScale (min −100, max 100, step 0.01), fractalCount (min 0, max 1000, step 1), fractalRotation (min −360, max 360), bendMode (type select mit Optionen). Auto-Check: Playwright evaluate → JSON gegen erwartete Keys/Ranges assert.

AC2 — Setzen wirkt sichtbar UND rendert. Nach window.OneTool.set('fractalCount', 600) gilt: (a) sichtbarer Slider zeigt 600 (DOM [data-key="fractalCount"] range/input value === "600"), (b) der Canvas hat sich verändert. Auto-Check: Screenshot vor/nach, Pixel-Differenz über Schwelle (> 1 % geänderte Pixel); DOM-Value-Assert. Voraussetzung erfüllt, weil OneTool.set den onChange-Callback feuert (nicht nur panel.set).

AC3 — Video-Export. window.OneTool.record(3) erzeugt eine .webm-Datei ≥ 10 KB mit gültigem WebM-Header. Auto-Check: Download-Datei existiert, Größe, Magic-Bytes 1A 45 DF A3.

AC4 — Livestream erreichbar UND abgesichert. (a) Die veröffentlichte noVNC-URL zeigt den Chromium; Aktionen aus Playwright erscheinen im Stream. (b) Ohne Credentials kein Zugriff: curl -sI <url> ohne Auth → 401 (bzw. VNC-Connect ohne Passwort scheitert). (c) View-only: Maus/Tastatur-Events aus dem noVNC-Client bewegen den Browser NICHT (x11vnc -viewonly). Auto-Check: curl mit/ohne Auth; view-only per Test-Input. Manuell: Tim sieht den Browser live.

AC5 — Gesten-Eingabe wirkt. Ein per Playwright synthetisierter vertikaler Zug nahe des oberen Kontrollpunkts ändert deformationTop (bzw. sichtbar die Herz-/Kreis-Kurve). Auto-Check: Canvas-Pixel-Differenz vor/nach dem Zug über Schwelle; optional Debug-Read des Werts.

AC6 — End-to-End-Beweis. Eine Live-Session an circleheart (Fraktalmodus) läuft durch: Fraktal an → mehrere Parameter gefahren → mindestens eine Canvas-Geste → 5 s Video gespeichert. Tim hat live zugeschaut. Manuell + Artefakt: die gespeicherte .webm + der Chatverlauf mit Screenshots.


7. Offene Punkte / bewusst vertagt


8. Betroffene Dateien & Arbeitsteilung

Fable 5 (Code, Repo):

Claude im Chat, mit Tim-Freigabe (Prod-Infra, NICHT Fable):

Kein Cache-Buster vorhanden (controls.js wird unversioniert von 92 Seiten via SSI-Include geladen) — dev-Domain ist No-Cache, daher kein Busting nötig; für die Live-Domain bei späterem Deploy prüfen.