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:
PhysarumEngine(Swift Package, plattform-agnostisch) — der wiederverwendbare Kern:Shaders/— die WGSL-Quellen aussrc/engine/shaders/(Single-Source), viawgsl2msl(siehe §6) zu.metaltranspiliert.Renderer— Metal-Device/Pipeline-Setup, Ping-Pong-Buffers, Sim-Step (agentStep→deposit→diffuse) + Post-FX (bloom/blur/feedback/composite/render), zeichnet in einenCAMetalLayer. Port vonsrc/engine/Engine.ts.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.-
Headless-testbar (Metal offscreen) + GPU-Limits-aware.
-
App-Targets — SwiftUI Multiplatform, ein Codebase, plattform-konditionale UI.
-
PresetStore— SwiftData-Modell mit CloudKit-Backing (privater iCloud-Container). Built-ins read-only; Custom-Presets syncen automatisch. -
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. -
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 viadevice.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.Uncheckedfü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.