Zum Inhalt

Physarum Ambiance — Native Apple App (Design Spec)

Status: Draft · 2026-06-02 · author: Johannes (brainstormed with Claude) Supersedes for native scope: the "validate on Mac DMG first" sequencing. Web app: continues in parallel as the free, open artifact (Codeberg Pages + embeddable <physarum-player>).

1. Kontext & Ziel

Physarum ist heute eine WebGPU/WGSL-PWA (Solid + Vite), ausgeliefert als Web-App, embeddable Player und macOS-DMG (WKWebView-Wrapper). Ziel ist ein natives Apple-Ambiance-Produkt: ein generativer „Mood/Living-Screensaver", dessen Hero-Surface der Apple TV ist, gekoppelt mit Echtzeit-Philips-Hue-Light-Sync. Verfügbar als Universal-App über tvOS + iOS + iPadOS + macOS.

Die WebGPU-Web-App bleibt unangetastet und lebt parallel weiter.

2. Festgezurrte Entscheidungen (aus dem Brainstorming)

Achse Entscheidung
Sequencing Direkt die volle native Vision (nicht erst Mac-Wrapper validieren).
Plattformen tvOS (Hero) + iOS + iPadOS + macOS, eine native Universal-App.
Renderer Ansatz 3 — WGSL bleibt Single-Source; Build-Zeit-Transpile nach MSL; Laufzeit reines Metal + Swift. Web-App lebt parallel, kein Shader-Drift.
Hue Echtzeit von Anfang an — Hue Entertainment API (DTLS-Streaming, bis ~50 Hz).
Geräte-Rollen iPhone/iPad/Mac = Authoring (Editor); Apple TV = Playback/Recall (lean-back); später Second-Screen (iPad/iPhone als Echtzeit-Fernbedienung der TV).
Preset-Sync iCloud (SwiftData + CloudKit, privater Container) — kein eigener Server.
Preset-Format Kompatibel zum bestehenden Web-Zod-Schema (JSON) → die 19 Built-ins portieren 1:1, Presets zwischen Web & Nativ austauschbar.
Monetarisierung Gratis, kein IAP („build for the artifact").
Audio-Reaktivität v1-out-of-scope, später (Echtzeit-Hue-Kanal macht es dann fast geschenkt).

3. North-Star-Architektur

┌─────────────────────────────────────────────────────────────┐
│  App-Targets (SwiftUI Multiplatform, ein Codebase)           │
│   • tvOS   → Fullscreen-Playback, Lean-back-Preset-Browser   │
│             (Focus-Engine), Top-Shelf · treibt Hue           │
│   • iOS/iPadOS → Authoring (Editor) + Library + Live-Preview  │
│   • macOS  → wie iOS · DMG-Web-Pfad bleibt separat bestehen   │
└───────────────┬──────────────┬───────────────┬──────────────┘
                │              │               │
        ┌───────▼──────┐ ┌─────▼──────┐ ┌──────▼─────────┐
        │ PhysarumEngine│ │ PresetStore│ │   HueSync       │
        │ (Swift Package│ │ SwiftData +│ │ Entertainment   │
        │  plattform-   │ │ CloudKit   │ │ API (DTLS)      │
        │  agnostisch)  │ │ (iCloud)   │ │                 │
        └───────────────┘ └────────────┘ └─────────────────┘
                │
        ┌───────▼───────────────────────────────┐
        │ WGSL-Quellen (src/engine/shaders/*.wgsl)│ ← geteilt mit Web-App
        │   → wgsl2msl (naga-lib) → *.metal       │
        └─────────────────────────────────────────┘

Schichten:

  1. PhysarumEngine (Swift Package, plattform-agnostisch) — der wiederverwendbare Kern:
  2. Shaders/ — die WGSL-Quellen aus src/engine/shaders/ (Single-Source), via wgsl2msl (siehe §6) zu .metal transpiliert.
  3. Renderer — Metal-Device/Pipeline-Setup, Ping-Pong-Buffers, Sim-Step (agentStep→deposit→diffuse) + Post-FX (bloom/blur/feedback/composite/render), zeichnet in einen CAMetalLayer. Port von src/engine/Engine.ts.
  4. Model — Swift-Structs, die das bestehende Buffer-Layout exakt spiegeln (Params 304 B/76 floats, PostParams 80 B/20 floats) + Preset-Datenmodell kompatibel zum Web-Zod-Schema, inkl. der 19 Built-in-Presets.
  5. Headless-testbar (Metal offscreen) + GPU-Limits-aware.

  6. App-Targets — SwiftUI Multiplatform, ein Codebase, plattform-konditionale UI.

  7. PresetStore — SwiftData-Modell mit CloudKit-Backing (privater iCloud-Container). Built-ins read-only; Custom-Presets syncen automatisch.

  8. HueSync — Bridge-Discovery (mDNS _hue._tcp + Cloud-Discovery-Fallback), Press-Link-Pairing (Credentials in iCloud-Keychain → alle Geräte teilen Pairing), Entertainment-Area-Auswahl, DTLS-Stream, Mapper Sim-Farb-/Energie-Zustand → Lichtkanäle.

  9. Später — SecondScreen (Multipeer-Connectivity iPad/iPhone ↔ Apple TV), AudioReactivity (Audio-Capture → BASS/MID/HIGH → speist Engine und HueSync).

4. Constraints

  • WebGPU/WebKit irrelevant für Nativ — wir gehen direkt auf Metal, daher kein OS-26-Floor wegen WebGPU. ABER: Metal-Feature-Floor + min-OS pro Plattform noch festzulegen.
  • Xcode-Pflicht für App-Targets. Aktuell nur Command Line Tools installiert (/Library/Developer/CommandLineTools, kein Xcode.app, kein Offline-metal-Compiler, keine tvOS/iOS-SDKs). Engine-Kern + Spike laufen ohne Xcode (macOS-Metal kompiliert MSL zur Laufzeit via device.makeLibrary(source:)). tvOS/iOS-Targets, CloudKit-/HomeKit- Entitlements, Device/Simulator-Builds und Offline-.metallib-Bake brauchen volles Xcode. → Blocker für Johannes: Xcode aus dem App Store installieren.
  • Solo-Dev / artifact-first — Wartbarkeit vor Feature-Breite, Single-Toolchain bevorzugt.

5. Spike-Ergebnis (2026-06-02) — Ansatz 3 verifiziert ✅

Keystone-Spike (apple/spike/spike.swift): - naga 29.0.3 (via cargo install naga-cli) transpiliert alle 8 WGSL-Shader fehlerfrei nach MSL. - agentStep.metal zur Laufzeit via device.makeLibrary(source:) auf macOS 26 / CLT ohne Xcode kompiliert, lief auf Apple M5 Pro, 1024/1024 Agenten korrekt gestept. - Werte exakt (out = pos + (cos θ, sin θ)·moveSpeed, θ aus turnSpeed) → das 304-B-Params-Layout stimmt end-to-end. - Einziger Gap: naga-CLI emittiert [[user(fake0)]]-Platzhalter statt [[buffer(N)]]-Indizes (kennt das Pipeline-Layout nicht). Deterministisch lösbar via naga-Library (fake_missing_bindings=false + expliziter binding_map) → das wgsl2msl-Tool (§6).

6. wgsl2msl — die Transpile-Pipeline

Kleines Rust-Binary (naga als Library), Teil des Builds: - Input: .wgsl. Output: .metal + .json-Manifest. - Parst + validiert WGSL, baut einen msl::BindingMap: jede @group(g) @binding(b)-Resource bekommt einen Metal-Slot pro Klasse (buffer/texture/sampler), Index = WGSL-Binding. fake_missing_bindings=false erzwingt vollständiges Mapping. - Bounds-Check-Policy: Restrict (sicher gegen OOB; naga fügt dann den _buffer_sizes-Buffer ein — Index im Manifest dokumentiert). - Das JSON-Manifest (Resource-Name → {entryPoint, class, metalIndex}) liest die Swift- Renderer-Schicht, um Buffers/Textures/Samplers deterministisch zu binden — kein Hardcoding. - Aufruf über apple/scripts/transpile-shaders.sh (pre-build), liest src/engine/shaders/*.wgsl, schreibt nach apple/PhysarumEngine/Sources/PhysarumEngine/Shaders/. - Laufzeit jetzt: MSL-Source als Resource bündeln, makeLibrary(source:) (kein Xcode nötig). Später (mit Xcode): offline zu .metallib baken (xcrun metal), schnellerer App-Start.

7. Zerlegung in Increments + Build-Reihenfolge

Jedes Increment = eigener Spec→Plan→Implement-Zyklus. Risiko- und wertorientiert:

  • Inc 0 — Keystone-Spike. ✅ ERLEDIGT (§5).
  • Inc 1 — PhysarumEngine-Foundation (Sim-Kern). wgsl2msl-Tool + Transpile-Skript; Swift-Datenmodell (Preset/Params/Types); Params-Packing (304 B / 80 B exakt); Renderer-Port der Sim-Passes (agentStep→deposit→diffuse) inkl. Ping-Pong + Seeding; headless N-Frame-Lauf mit verifizierter Pheromon-Feld-Evolution. Ohne Xcode bau-/testbar.
  • Inc 2 — Post-FX + Bild-Output. bloom/blur/feedback/composite/render-Passes; Render in Offscreen-Texture; PNG-Bake aus einem Built-in-Preset (headless, macOS). Verifiziert die komplette Pipeline visuell. Ohne Xcode.
  • Inc 3 — tvOS-App (Playback). (braucht Xcode) SwiftUI-tvOS-Target, CAMetalLayer- Fullscreen-Playback, Lean-back-Preset-Browser (Focus-Engine), Built-in-Presets, Top-Shelf.
  • Inc 4 — HueSync (Echtzeit). (braucht Xcode + Hue Bridge) Discovery + Pairing + Entertainment-Stream + Sim→Licht-Mapper, auf tvOS. → 🎯 MVP-Meilenstein: Apple TV spielt Built-in-Presets mit Echtzeit-Hue-Sync.
  • Inc 5 — Authoring-App (iOS/iPad/macOS). (braucht Xcode) Editor + Library + Live-Preview.
  • Inc 6 — Preset-Sync (iCloud). (braucht Xcode) SwiftData + CloudKit; Custom-Presets vom Handheld erscheinen auf der TV.
  • Später — Second-Screen-Live-Remote, Audio-Reaktivität.

MVP = Inc 1–4. Authoring/Sync (5–6) erweitern das Erlebnis, sind aber nicht für die Kern-Ambiance-Schleife (TV + Hue mit Built-ins) nötig.

8. Increment 1 im Detail (der nächste Plan)

Ziel: Der Physarum-Sim-Kern läuft nativ in Swift/Metal, headless verifiziert, ohne Xcode.

Komponenten & Dateien: - apple/tools/wgsl2msl/ (Rust) — Cargo.toml, src/main.rs (siehe §6). - apple/scripts/transpile-shaders.sh — ruft wgsl2msl über alle 8 Shader. - apple/PhysarumEngine/Package.swift — Swift Package, macOS-Plattform (später + tvOS/iOS). - Sources/PhysarumEngine/Model/Types.swift — Enums (SpawnPattern, BlendMode, SignalName, ModTarget, AudioBand), SpeciesParams, InteractionMatrix, RGB. Port von src/engine/types.ts. - Sources/PhysarumEngine/Model/Preset.swift — Preset, PresetParams, AudioReactive, AudioRoute. JSON-Codable, kompatibel zum Web-Schema (snake/camel beachten). - Sources/PhysarumEngine/Model/Params.swift — packParams() -> [UInt8] (304 B) und packPostParams() -> [UInt8] (80 B), byte-genau wie src/engine/params.ts. - Sources/PhysarumEngine/Model/BuiltInPresets.swift — Port von src/presets/builtIn.ts (19 Presets; in Inc 1 mind. 1–2 zum Testen, Rest in Inc 2/3). - Sources/PhysarumEngine/Renderer/SimEngine.swift — Device/Queue, Buffer-Allokation (agents ping-pong, pheromone ping-pong, heads), Seeding (Port seeding.ts), Pipeline-States aus den transpilierten Shadern (via Manifest gebunden), step()-Dispatch (agentStep→deposit→diffuse mit diffusionFreq-Kadenz), simSpeed-Schleife. - Sources/PhysarumEngine/Shaders/ — generierte .metal + .json (gitignored; via Skript erzeugt). - Tests/PhysarumEngineTests/ — ParamsLayoutTests (Byte-für-Byte gegen bekannte Offsets), SimEngineTests (N Frames, Pheromon-Feld wird nicht-trivial → Summe/Varianz > 0, Agenten bleiben im Feld, kein NaN).

Definition of Done (Inc 1): - [ ] wgsl2msl baut alle 8 Shader fehlerfrei zu .metal + Manifest. - [ ] swift test grün auf macOS (CLT): Params-Layout byte-genau, Sim läuft N Frames, Pheromon-Feld evolviert nicht-trivial, kein GPU-Error/NaN. - [ ] Keine [[user(fake0)]]-Platzhalter mehr (echte Indizes via Manifest). - [ ] Headless-Demo-Run (z.B. swift run Beispiel) gibt Feld-Statistik aus.

9. Offene Risiken / noch zu verifizieren

  • Restrict-Bounds-Checks Perf auf großen Agent-Counts (500k) — ggf. Unchecked für Release.
  • min-OS pro Plattform (Metal-Feature-Floor) — festzulegen, sobald Xcode da ist.
  • Hue Entertainment API Details (DTLS-Lib auf Swift/Network.framework, Entertainment-Area- Limits, max Lights) — eigener Spike in Inc 4.
  • CloudKit-Schema-Migration (Built-ins vs. Custom) — Inc 6.
  • tvOS Memory/GPU-Budget für hohe Agent-Counts auf Apple-TV-Hardware — auf Gerät messen.

10. Out of scope (v1)

Audio-Reaktivität, PNG/WebM-Export/Capture, voller Editor auf der TV, Second-Screen-Remote, Nicht-Hue-Lampen (generisches HomeKit) — alles spätere Increments oder bewusst weggelassen.