From 0825b35463918e724c4b368a7e88d6f6bd9e45af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Wed, 13 May 2026 10:56:55 +0200 Subject: [PATCH] docs: add nested CLAUDE.md tree Root CLAUDE.md (overview, where-to-look, conventions) plus nested files for data_only_viz, oscope-of, launcher. sound_algo already had its own nested tree. Sized for the ~150-instruction budget: root 43 lines, each nested 43-52 lines, telegraphic style. --- CLAUDE.md | 43 ++++++++++++++++++++++++++++++++++ data_only_viz/CLAUDE.md | 52 +++++++++++++++++++++++++++++++++++++++++ launcher/CLAUDE.md | 43 ++++++++++++++++++++++++++++++++++ oscope-of/CLAUDE.md | 43 ++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 CLAUDE.md create mode 100644 data_only_viz/CLAUDE.md create mode 100644 launcher/CLAUDE.md create mode 100644 oscope-of/CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..11cdd7c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,43 @@ +# AV-Live + +Live coding audio-visual performance system : moteur SuperCollider, visualiseur openFrameworks piloté par un oscilloscope Hantek 6022BL, app menubar macOS qui orchestre le tout. + +## Communication + +Toujours répondre en français à l'utilisateur. Code, commentaires de code, commits et docs en anglais. + +## Stack par sous-projet + +| Sous-projet | Stack | +|-------------|-------| +| `sound_algo/` | SuperCollider (sclang + scsynth), 1099 SynthDefs, 345 tracks | +| `oscope-of/` | openFrameworks C++, libusb (Hantek bulk), GLSL 150 GL 3.2 core | +| `launcher/` | SwiftUI menubar app, Swift Package Manager | +| `data_only_viz/` | Python 3.11+ via `uv`, Metal natif (pyobjc), multi-backends pose | +| `web_realart/` | Node.js, Express, OSC bridge | + +## Where to Look + +| Tâche | Emplacement | +|-------|-------------| +| Ajouter / modifier un SynthDef, track, palette | `sound_algo/` (déjà documenté en nested) | +| Toucher au visualiseur, shaders, FFT, Hantek | `oscope-of/` | +| Modifier l'app menubar macOS | `launcher/` | +| Détection pose / mesh / body tracking | `data_only_viz/` | +| Bridge web / UI de live coding | `web_realart/` | +| Plans / specs en cours | `docs/superpowers/plans/` | + +## Conventions globales + +- Python : **uv** systématiquement (jamais pip/poetry/conda directs). +- Pas d'emojis dans code/docs/commits sauf demande explicite. +- Commits : sujet ≤ 50 char, body ≤ 72 char/ligne, pas d'attribution AI, pas de `--no-verify`, pas d'underscore dans le scope (hooks enforcent). +- `*.pt`, `*.ckpt`, `*.safetensors`, `*.mlpackage` exclus par `.gitignore` racine. + +## Agent Workflow + +Explore localise → librarian lit (>500 lignes) → tu raisonnes → general-purpose implémente → validator vérifie. Lance les tâches indépendantes en parallèle. + +## Guidance imbriquée + +Chaque sous-projet majeur a son propre `CLAUDE.md`. Claude charge automatiquement le plus proche du fichier édité (« closest wins »). N'ajouter ici que ce qui s'applique à TOUS les sous-projets. diff --git a/data_only_viz/CLAUDE.md b/data_only_viz/CLAUDE.md new file mode 100644 index 0000000..a4434e0 --- /dev/null +++ b/data_only_viz/CLAUDE.md @@ -0,0 +1,52 @@ +# data_only_viz + +Visualiseur natif Metal (pyobjc) pour le mode data-only d'AV-Live : capture caméra → détection pose multi-personne → tracker → rendu Metal → OSC out vers `oscope-of`. + +## Environnement + +```bash +cd data_only_viz +uv sync # base +uv sync --extra pose # MediaPipe + YOLO + Ultralytics +uv sync --extra nlf # Neural Localizer Fields (SMPL body mesh) +uv sync --extra detrpose # DETRPose transformer (clone manuel — voir detrpose.py) +uv run python -m data_only_viz.main # lancement standard +``` + +Python **3.11+** requis. `pyproject.toml` est la source de vérité — ne jamais éditer `uv.lock` à la main. + +## Backends pose disponibles + +| Backend | Fichier | Statut | +|---------|---------|--------| +| MediaPipe Holistic | `holistic.py` | stable | +| Ultralytics YOLOv8-pose | `pose.py` | stable, modèle `yolov8n-pose.pt` à la racine repo | +| Apple Vision (Core ML) | `apple_vision_pose.py`, `coreml_pose.py` | macOS uniquement | +| DETRPose | `detrpose.py` | clone manuel + checkpoint, voir docstring | +| NLF (SMPL body mesh) | `nlf_worker.py` | TorchScript, **bloqué CPU/MPS** (NotImplementedError 2026-05-13), CUDA-only ; checkpoints via `scripts/setup_nlf.sh` | +| Multi-HMR | `multi_hmr_scaffold.md` | scaffold seulement | +| SMPLER-X / WHAM-TRAM | `*_scaffold.md` | scaffold seulement | + +## Conventions + +- État partagé multi-thread : `state.py` expose `State.lock()` — toujours mutationner sous lock. +- Filtrage temporel : `euro_filter.py` (One Euro Filter) sur les keypoints avant tracker. +- Association multi-personne : `tracker.py` IoU-based, `scipy.optimize.linear_sum_assignment`. +- Shaders Metal dans `shaders/` (`.metal`), recompilés au runtime ; topologie mesh (SMPL faces) en binaire dans `mesh_topology.py`. +- OSC out : `osc_listener.py` / `pose_bridge.py` — destination `oscope-of` sur `:57123`. + +## Tests + +```bash +uv run pytest tests/ -v +``` + +Tests TDD-first pour `nlf_worker.py` ; valider avant chaque commit qui touche un worker. + +## Anti-patterns + +- Ne pas charger un modèle ML sans guard `try/except ImportError` — les optional-extras peuvent manquer. +- Ne pas committer `*.pt`, `*.ckpt`, `*.safetensors`, `*.mlpackage` (gitignore racine). +- Ne pas appeler `state.persons_nlf = ...` hors `with state.lock():`. +- Ne pas hardcoder le device (`cuda`/`mps`/`cpu`) : détecter via `torch.backends.mps.is_available()` puis fallback. +- Pas de `print` dans la boucle de rendu — utiliser un logger conditionnel. diff --git a/launcher/CLAUDE.md b/launcher/CLAUDE.md new file mode 100644 index 0000000..33ff04d --- /dev/null +++ b/launcher/CLAUDE.md @@ -0,0 +1,43 @@ +# launcher — AVLiveLauncher + +App menubar macOS (SwiftUI, SwiftPM, macOS 11+) qui démarre/arrête `sclang+scsynth`, le serveur web et `oscope-of`, log les sorties, et expose un mode picker. + +## Build + +```bash +cd launcher +./build.sh # script standard +# ou manuellement : +swift build -c release +.build/release/AVLiveLauncher +``` + +Cible : **macOS 11+**, Swift 5.7+. Package Swift, pas de Xcode project requis. + +## Modules + +| Fichier | Rôle | +|---------|------| +| `AVLiveLauncherApp.swift` | `@main`, scene menubar, app lifecycle | +| `MenuBarContent.swift` | UI du menu (start/stop, état des process) | +| `ModePickerWindow.swift` | Fenêtre picker de mode (data-only vs full vs ...) | +| `ProcessManager.swift` | Spawn / kill / monitor des process enfants | +| `OSCSender.swift` | Envoi OSC (typiquement vers `:57121` sclang, `:57123` oscope) | +| `LogView.swift` | UI live des logs stdout/stderr des process | +| `AV-Live-Body/` | Ressources / modèles annexes (body mesh assets) | + +## Conventions + +- Toute opération asynchrone : `Task { @MainActor in ... }` pour UI updates. +- Pas de bloc `DispatchQueue.main.sync` (deadlock garanti depuis MainActor). +- `ProcessManager` est `@MainActor` — interactions process via async/await, jamais `Process.waitUntilExit()` bloquant en main. +- Chemins absolus vers les binaires (sclang, node, oscope-of) résolus une fois au startup et stockés ; ne pas redécouvrir à chaque démarrage. +- Logs ring-buffer borné (pas de croissance illimitée dans `LogView`). + +## Anti-patterns + +- Ne pas committer `build/` ni `.build/`. +- Ne pas hardcoder un chemin utilisateur (`/Users/electron/...`) — passer par `FileManager` + chemins relatifs au repo ou bookmarks. +- Ne pas mélanger `Process.terminate()` et `kill -9` sans escalade (SIGTERM → wait → SIGKILL). +- Pas d'AppKit `NSApp.terminate` direct depuis un closure background — toujours hop sur MainActor. +- Ne pas dépendre d'un Xcode project : le SwiftPM `Package.swift` est la source de vérité. diff --git a/oscope-of/CLAUDE.md b/oscope-of/CLAUDE.md new file mode 100644 index 0000000..b1e1c81 --- /dev/null +++ b/oscope-of/CLAUDE.md @@ -0,0 +1,43 @@ +# oscope-of + +Visualiseur openFrameworks C++ : capture Hantek 6022BL via libusb → FFT 2048 → 41 backgrounds + 14 OS pixel-art + 10 scrollers + chaîne post-FX GLSL. + +## Build + +```bash +cd oscope-of +make # debug +make Release # release +make RunRelease # lance bin/oscope-of (Release) +``` + +Dépendances oF dans `addons.make`. Cible macOS principale (Hantek via libusb bulk transfers). + +## Architecture + +| Composant | Fichier | +|-----------|---------| +| Capture USB Hantek (1-48 MS/s, 2 ch 8-bit) | `HantekDevice.{h,cpp}` | +| Downsampling + FFT 2048 bandes bass/mid/treble/kick/snare | `AudioAnalyzer.{h,cpp}`, `FFT.{h,cpp}` | +| Données scope partagées | `ScopeData.h` | +| 41 backgrounds + 5 OS shaders + 14 logos + scrollers | `visualizers/` | +| Chaîne post-FX (ACES, bloom, chroma, scanlines, glitch...) | `PostFx.{h,cpp}` | +| Demo FX (copper bars, sine scroller, bobs) | `DemoFx.{h,cpp}` | +| OSC reçu depuis sound_algo (`:57123`) + envoyé | `OscClient.{h,cpp}` | +| App lifecycle | `ofApp.{h,cpp}`, `main.cpp` | + +## Conventions + +- **GLSL 150 GL 3.2 core** uniquement — pas de GL 2.1 legacy. Shaders en `bin/data/shaders/`. +- Pas d'allocations dans `update()` / `draw()` — buffers FFT préalloués. +- Hantek bulk transfer : timeout court, fallback gracieux si scope absent (mode démo). +- Les 15 demoparties touchent un état global `currentDemo` dans `ofApp` — toujours mettre à jour les bindings clavier (`keyPressed`) AZERTY (`&é"'(§è!` → `1-8`). +- `greetings.txt` (sine scroller) chargé depuis `bin/data/` au startup — éviter relectures. + +## Anti-patterns + +- Ne pas appeler `glDrawArrays` sans bind VAO préalable (GL 3.2 core l'exige). +- Ne pas faire `new` dans la hot loop — utiliser `ofVbo` / `ofFbo` membres. +- Ne pas faire d'I/O fichier dans `draw()`. +- Ne pas committer `bin/oscope-of*` (binaires) ni `bin/data/*.mov` (gros). +- Ne pas ajouter de dépendance non-headless sans l'inscrire dans `addons.make`.