Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 43 additions & 19 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ qui ont déjà coûté cher. `docs/madmapper-osc-api.md` = référence OSC MadMa
## Lancer / tester

- `node server.js` → http://localhost:3333 (config générée : `cascade-config.json`).
- **`npm test`** (= `node --test`) : 341 tests, zéro dépendance. **À lancer avant
- **`npm test`** (= `node --test`) : 346 tests, zéro dépendance. **À lancer avant
de conclure toute modif du serveur.** ⚠ `node --test tests/` échoue sur Node 24
(chemin pris pour un module) — utiliser `node --test` tout court.
- Instance isolée pour tester à la main : `CASCADE_PORT=3461 CASCADE_NO_BROWSER=1
CASCADE_NO_AUTOQUIT=1 CASCADE_CONFIG=/tmp/x.json node server.js` (voir aussi
`CASCADE_OSCIN`, `CASCADE_FEEDBACK`, `CASCADE_MMPORT`, `CASCADE_MMHOST`).
- Faux Carabiner = serveur TCP local port 17000 qui pousse
`status { :peers 1 :bpm 128.0 ... }\n`.
- UI : les 45 tests d'interface pilotent un vrai navigateur en CDP maison
- UI : les 46 tests d'interface pilotent un vrai navigateur en CDP maison
(`tests/browser.js`, zéro dépendance) — **pas** Playwright. Sans navigateur ils
s'annoncent ignorés SANS faire rougir la suite : vérifier le compte (341), pas
s'annoncent ignorés SANS faire rougir la suite : vérifier le compte (346), pas
la couleur. `CASCADE_NAVIGATEUR=<binaire>` impose un navigateur ;
`PLAYWRIGHT_BROWSERS_PATH` est balayé tout seul. Si tu passes par Playwright
à la main, `waitUntil: 'domcontentloaded'` (`networkidle` ne vient jamais,
Expand Down Expand Up @@ -120,9 +120,13 @@ dossiers et fondu · 7 modes de fusion · perspective atmosphérique · palette
N arrêts, branchable sur la profondeur ou la hauteur · décalage réparti ·
crossfader A/B · modulateurs (LFO) par couche et global · coupure de secours · renvoi de disposition · démos · repère 3D.

**328 tests, 38 mutations sur 38 détectées** — campagne complète passée d'un bloc
le 2026-08-05 : zéro aveugle, zéro motif absent, `server.js` restauré à
l'identique (le chiffre était additionné à la main avant).
**41 mutations, chacune détectée au moins une fois** — campagne complète passée
d'un bloc le 2026-08-05 (36 à l'époque, `CHANGELOG.md` le dit), puis campagne
CIBLÉE le 2026-08-17 sur les 25 mutations dont le test avait bougé depuis la
2.1.0 : zéro aveugle, zéro motif absent, `server.js` restauré à l'identique.
⚠ La formulation est exacte au mot près : **aucune campagne n'a éprouvé les 41
d'un bloc**, et 16 n'ont pas été rejouées depuis le 2026-08-05. Ne pas écrire
« 41 sur 41 » sans avoir relancé `node tests/mutation.js` en entier.
⚠ La lancer dans une COPIE du dépôt : elle modifie `server.js` en place pendant
une heure, et un commit parti à ce moment-là emporterait un mutant. Manuel PDF, README, CHANGELOG et
exécutables des 4 plateformes sont à jour ; l'exécutable Windows a été lancé et
Expand Down Expand Up @@ -182,15 +186,34 @@ nœud OSC. Le patch de Pym est relevé dans `docs/madmapper-osc-api.md`.
1. ✅ **Icône de zone de notification : FAITE** (2026-08-05), en PowerShell +
`NotifyIcon`, donc zéro dépendance. ⚠ **Windows uniquement — décidé avec
Pym**, macOS n'a pas d'équivalent scriptable : ne pas « réparer » cette
absence. ⚠ **Éteinte par défaut et JAMAIS EXÉCUTÉE** : écrite depuis Linux.
Le premier essai sur une vraie machine Windows reste à faire — c'est la
première chose à confirmer avec lui. Le script vit dans `SYSTRAY_PS1`
(embarqué, car le distribuable est un exécutable unique).

⚠ **Avant l'essai, savoir ceci** : Windows range **toute nouvelle icône dans
le tiroir caché** (chevron `^`). L'issue la plus probable d'un premier essai
est « le script tourne, l'icône existe, Pym ne la voit pas ». La note est
dans les Réglages et dans le manuel — la lui montrer.
absence. Éteinte par défaut. Le script vit dans `SYSTRAY_PS1` (embarqué, car
le distribuable est un exécutable unique).

✅ **ESSAYÉE POUR DE VRAI le 2026-08-17**, sur la machine Windows 11 de Pym,
qui a vu et manipulé l'icône. Elle n'avait jamais été exécutée jusque-là
(écrite depuis Linux) : c'est fait, et voici ce que l'essai a établi.
- Pastille rouge à l'arrêt, infobulle `Cascade - a l arret`, menu au clic
droit (4 entrées) et double-clic qui ouvre l'interface : **tout répond**.
- Le script survit au sondage long (~60 cycles de 1,5 s sans partir), et le
serveur n'a émis aucun avertissement `[cascade] icône de notification`.
- **Retrait sans pastille fantôme.** Mesuré sur les trois sorties : décocher
la case le fait partir de lui-même en 2,5 s ; « Quitter Cascade » du menu
l'efface avant d'appeler le serveur ; le bouton ⏻ le TUE en 0,4 s
(`killSystray()` sans le mode doux, cf. `server.js`) — et malgré ça,
**Windows 11 retire l'icône tout seul**, constaté par Pym. Le risque décrit
dans le commentaire de `server.js` ne se matérialise pas ici. ⚠ C'est une
mesure sur SA machine, pas une garantie : sur un Windows plus ancien, la
pastille morte reste jusqu'au survol de la souris.

⚠ **Windows range toute nouvelle icône dans le tiroir caché** (chevron `^`) :
c'est bien là que Pym l'a trouvée. Le garder en tête pour toute autre
machine — « le script tourne, l'icône existe, personne ne la voit » reste
l'issue la plus probable d'un premier lancement. La note est dans les
Réglages et dans le manuel.

⚠ Un `npm test` sur Windows **lance réellement l'icône** quelques secondes :
`tests/api.test.js` active le réglage. C'est sans conséquence, mais ça
explique un `cascade-systray.ps1` daté dans `%TEMP%`.

⚠ Le script sonde **`/api/ping`, jamais `/api/state`** : `/api/state` remet
`lastUiPollAt` à jour et **désactivait l'arrêt automatique** (défaut réel,
Expand All @@ -200,10 +223,11 @@ nœud OSC. Le patch de Pym est relevé dans `docs/madmapper-osc-api.md`.
⚠ **Ce que la CI dit, et ce qu'elle ne dira jamais.** Depuis le 2026-08-05 il
y a un passage `windows-latest` : il **analyse** `SYSTRAY_PS1` avec
`[Parser]::ParseInput` (aucune session graphique requise) et lance la suite
entière — 328 tests, 0 ignoré, le premier passage est vert. Une parenthèse
manquante ne partira donc plus en régie. Mais **aucun runner ne posera jamais
l'icône** : `NotifyIcon` demande un bureau. L'essai en vrai reste à faire.
`tests/systray.test.js` lit le source en plus — c'est mieux que rien.
entière, 0 ignoré, et le premier passage était vert. Une parenthèse manquante
ne partira donc plus en régie. Mais **aucun runner ne posera jamais l'icône**
: `NotifyIcon` demande un bureau — d'où l'essai à la main ci-dessus, qui
restera toujours le seul moyen de la voir. `tests/systray.test.js` lit le
source en plus — c'est mieux que rien.
2. **Capture ou GIF dans le README** — nécessite une vraie session MadMapper.
3. Suite de l'audit : voir la section « À faire » de `../Cascade-AUDIT.md` (hors dépôt).
✅ Repli « avancé » du panneau Couches : FAIT (replis `advMiroirs` et
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

*Pierre-Yves Mansour — Collectif WSK*

![version](https://img.shields.io/badge/version-2.1.0-orange) ![licence](https://img.shields.io/badge/licence-MIT-blue) ![dépendances](https://img.shields.io/badge/d%C3%A9pendances-aucune-brightgreen) ![tests](https://img.shields.io/badge/tests-341-green) ![plateformes](https://img.shields.io/badge/plateformes-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey)
![version](https://img.shields.io/badge/version-2.1.0-orange) ![licence](https://img.shields.io/badge/licence-MIT-blue) ![dépendances](https://img.shields.io/badge/d%C3%A9pendances-aucune-brightgreen) ![tests](https://img.shields.io/badge/tests-346-green) ![plateformes](https://img.shields.io/badge/plateformes-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey)

---

Expand Down Expand Up @@ -140,7 +140,7 @@ Le préfixe historique `/chaser/…` reste accepté.
## Développement

```bash
npm test # 262 tests, sans aucune dépendance
npm test # sans aucune dépendance (le compte exact est sur le badge, en haut)
node build.js # exécutables des 4 plateformes → build/
```

Expand Down
14 changes: 10 additions & 4 deletions dist/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -1259,10 +1259,16 @@ function killCarabiner() { if (linkChild) { try { linkChild.kill(); } catch (e)
* l'environnement de bureau. Plutôt qu'une fonction bancale partout, une
* fonction franche là où se trouve la régie.
*
* ⚠ DÉSACTIVÉE PAR DÉFAUT, parce qu'elle n'a jamais pu être exécutée : elle a
* été écrite depuis Linux, où PowerShell n'existe pas. Tout est donc enveloppé :
* un échec est silencieux et ne touche jamais le serveur. À activer dans
* Réglages, et à confirmer sur une vraie machine Windows.
* ⚠ DÉSACTIVÉE PAR DÉFAUT. Tout est enveloppé : un échec est silencieux et ne
* touche jamais le serveur. À activer dans Réglages.
*
* ✅ ESSAYÉE SUR UNE VRAIE MACHINE WINDOWS 11 le 2026-08-17 — elle avait été
* écrite depuis Linux et n'avait jamais tourné. Icône visible (dans le tiroir
* caché, comme prévu), infobulle, menu et double-clic : tout répond. Le retrait
* ne laisse pas de pastille fantôme, y compris par le chemin brutal décrit sous
* `killSystray()` : Windows 11 nettoie de lui-même. Détail des mesures dans
* `docs/ETAT-DU-PROJET.md`. Le réglage reste éteint au démarrage : c'est un
* choix, pas une réserve sur la fonction.
*
* Le script est EMBARQUÉ ici, pas dans un fichier à côté : le distribuable est
* un exécutable unique, et un `.ps1` externe n'existerait pas à côté de lui.
Expand Down
53 changes: 35 additions & 18 deletions docs/ETAT-DU-PROJET.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ nom de couche, nom de projet, message d'erreur du serveur — se pose par
`tests/interface.test.js` relit le source et échoue si la règle est enfreinte
(garde-fou vérifié en réintroduisant volontairement le motif fautif).

### Tests — `npm test` (262 tests, zéro dépendance)
### Tests — `npm test` (346 tests, zéro dépendance)

`tests/helpers.js` lance un **vrai** serveur en sous-processus (ports libres,
config jetable) et écoute l'OSC réellement émis avec un décodeur **indépendant**
Expand All @@ -289,11 +289,11 @@ paquets hostiles), `madmapper.test.js` (voyant dans les deux sens),
rafale, scéno changée 12 fois, START/STOP martelés), `interface.test.js`
(garde-fous de source : pas d'`innerHTML` avec donnée externe, version cohérente,
sémantiques non négociables toujours présentes, `dist/` synchrone, aucun mutant
resté dans `server.js`), et `ui.test.js` (**32 tests dans un vrai navigateur**).
resté dans `server.js`), et `ui.test.js` (**46 tests dans un vrai navigateur**).

⚠ **Les 32 tests d'interface peuvent ne pas tourner sans que rien ne rougisse.**
⚠ **Les 46 tests d'interface peuvent ne pas tourner sans que rien ne rougisse.**
Sans navigateur, `ui.test.js` s'annonce « ignoré » et la suite reste VERTE : on
lit 230 tests au lieu de 262 et personne ne le voit. **Vérifier le compte, pas la
lit 300 tests au lieu de 346 et personne ne le voit. **Vérifier le compte, pas la
couleur.** `tests/browser.js` cherche dans l'ordre : `CASCADE_NAVIGATEUR` (chemin
imposé), l'installation Playwright (`PLAYWRIGHT_BROWSERS_PATH`), puis les chemins
système. En CI l'absence de navigateur fait désormais échouer le job.
Expand Down Expand Up @@ -339,7 +339,7 @@ Cascade/
├── server.js ← moteur + API (source de travail, ~3020 l.)
├── public/index.html ← interface complète (source de travail, ~3320 l.)
├── build.js ← génère les exécutables des 4 plateformes
├── tests/ ← npm test — 262 tests en 17 fichiers, zéro dép.
├── tests/ ← npm test — 346 tests en 21 fichiers, zéro dép.
│ ├── helpers.js ← lance un vrai serveur + faux MadMapper
│ ├── api.test.js · engine.test.js · control.test.js · madmapper.test.js
├── dist/ ← DISTRIBUABLE : copie autonome à envoyer
Expand Down Expand Up @@ -529,17 +529,34 @@ d'attente ; partir au premier échec ferait disparaître l'icône *définitiveme
icône de barre de menus sans logiciel supplémentaire (`rumps`, un `.app`
Swift, `xbar`…), ce que le zéro-dépendance interdit. La case est grisée sur
Mac et le dit. **Ne pas « réparer » cette absence.**
- **JAMAIS EXÉCUTÉE.** Le script a été écrit depuis Linux, sans PowerShell pour
le lancer, et **la CI ne tourne que sur Ubuntu** : aucune ligne de ce dossier
ne sera jamais couverte par une exécution réelle. `tests/systray.test.js` lit
le source — c'est mieux que rien, à condition de savoir que c'est tout ce que
c'est. Le premier essai sur une vraie machine Windows reste à faire, et c'est
la première chose à confirmer avec Pym. À l'arrêt, l'icône *disparaît* au lieu
de rougir : le processus qui la dessine est parti avec Cascade.
- **Windows range toute nouvelle icône dans le tiroir caché** (le chevron `^`).
Sans la note posée dans les Réglages, le premier essai n'aurait rien prouvé :
le script tourne, l'icône existe, personne ne la voit, et on conclut que c'est
mort. C'est de loin l'issue la plus probable d'un premier essai.
- **ESSAYÉE POUR DE VRAI le 2026-08-17**, sur le Windows 11 de Pym, qui l'a vue
et manipulée. Elle avait été écrite depuis Linux, sans PowerShell pour la
lancer, et **la CI ne tourne que sur Ubuntu** (le passage Windows *analyse* le
script sans le poser : `NotifyIcon` demande un bureau). Aucun runner ne
couvrira jamais ces lignes — cet essai à la main restera le seul moyen de voir
l'icône. Ce qu'il a établi :
- pastille rouge à l'arrêt, infobulle `Cascade - a l arret`, menu au clic
droit (4 entrées), double-clic qui ouvre l'interface : **tout répond** ;
- le script encaisse ~60 cycles de sondage à 1,5 s sans partir, et le serveur
n'a émis aucun avertissement `[cascade] icône de notification` ;
- **aucune pastille fantôme.** Les trois sorties ont été chronométrées :
décocher la case → le script part de lui-même en 2,5 s (il voit
`systray: false` et s'efface) · « Quitter Cascade » du menu → il s'efface
avant même d'appeler le serveur · **bouton ⏻ ou fermeture de la fenêtre →
il est TUÉ en 0,4 s**, car `process.on('exit')` appelle `killSystray()` sans
le mode doux, et le `setTimeout` de 3 s de ce mode ne pourrait de toute
façon jamais s'exécuter (Node meurt avant). C'est exactement le cas que le
commentaire de `server.js` redoute — mais **Windows 11 retire l'icône tout
seul**, constaté de visu. ⚠ Mesure sur UNE machine, pas une garantie : sur
un Windows plus ancien, la pastille morte peut rester jusqu'au survol.
- **Windows range toute nouvelle icône dans le tiroir caché** (le chevron `^`) —
et c'est bien là que Pym a dû aller la chercher. Sans la note posée dans les
Réglages, l'essai n'aurait rien prouvé : le script tourne, l'icône existe,
personne ne la voit, et on conclut que c'est mort. Le garder en tête pour
toute autre machine.
- ⚠ Un `npm test` sur Windows **lance réellement l'icône** quelques secondes :
`tests/api.test.js` active le réglage, donc `startSystray()` s'exécute. Sans
conséquence, mais ça explique un `cascade-systray.ps1` frais dans `%TEMP%`.
- ⚠ **`SYSTRAY_PS1` est un littéral de gabarit JavaScript.** Un accent grave
(l'échappement de PowerShell) ou une séquence `${…}` casserait `server.js` **au
chargement** — Cascade ne démarrerait plus du tout, pas seulement l'icône. Un
Expand All @@ -558,7 +575,7 @@ d'attente ; partir au premier échec ferait disparaître l'icône *définitiveme
3. **macOS + WhatsApp/mail** : le `.command` arrive en quarantaine → « fichier endommagé » / Terminal −128. Fix utilisateur : `xattr -cr <dossier>` puis `chmod +x <.command>`. Documenté dans `LISEZ-MOI.txt` et le manuel. Seule solution définitive : signer + notariser (compte Apple Developer, 99 $/an).
4. **Manuel PDF** : régénéré en v1.2 (Link, mode app, quitter, sauvegarde). Le script est désormais **conservé** : `docs/build-manuel.py` (`python3 build-manuel.py <dossier_sortie>`, reportlab + polices DejaVu). ⚠️ DejaVu n'a **pas** les glyphes ⏻ (U+23FB) ni ⧉ (U+29C9) ni les exposants/indices Unicode — ils rendent des carrés vides : écrire les mots (« bouton Quitter », « ABLETON LINK »). Copier le PDF généré à la racine **et** dans `dist/`.
5. **Playwright dans le sandbox** : `waitUntil: 'networkidle'` ne se déclenche jamais (polling 120 ms) → utiliser `domcontentloaded`. ⚠ Les tests d'interface du dépôt n'utilisent **pas** Playwright : c'est du CDP maison (`tests/browser.js`), pour tenir le zéro-dépendance.
6. **Une suite verte ne prouve pas que tout a tourné.** `ui.test.js` s'annonce « ignoré » sans navigateur, sans faire rougir quoi que ce soit — 32 tests muets. Lire le **compte** (262), pas la couleur. Même famille que le mutant resté dans `server.js` le 28/07 : les deux fois, la suite était verte.
6. **Une suite verte ne prouve pas que tout a tourné.** `ui.test.js` s'annonce « ignoré » sans navigateur, sans faire rougir quoi que ce soit — 46 tests muets. Lire le **compte** (346), pas la couleur. Même famille que le mutant resté dans `server.js` le 28/07 : les deux fois, la suite était verte.
7. **Les fichiers hors dépôt n'existent pas partout.** `../Cascade-AUDIT.md` et `../Cascade-RELECTURES.md` sont absents des clones frais (sessions distantes, CI). Une consigne qui en dépend est inapplicable là-bas : recopier dans le dépôt ce qui doit survivre.

## Historique des décisions
Expand Down Expand Up @@ -602,7 +619,7 @@ sera périmée à l'un des deux.
phase Link** (livrée en 1.6.0), le **`dist/` généré** (`sync-dist.js`, avec un
test qui échoue si la copie diverge), et les **tests d'interface** — réputés « à
faire en Playwright » alors qu'ils existent en CDP maison depuis la 2.0
(`tests/browser.js`, 32 tests). Ce fichier est censé être lu en premier à chaque
(`tests/browser.js`, 46 tests). Ce fichier est censé être lu en premier à chaque
reprise : le laisser mentir coûte une demi-journée à celui qui reprend.

⚠ **Purger cette liste fait partie du travail de livraison**, au même titre que
Expand Down
Loading
Loading