feature/swirl-family #186

Merged
Nora merged 10 commits from feature/swirl-family into develop 2026-09-12 13:11:52 +00:00
Owner
No description provided.
Nora added 10 commits 2026-09-12 12:58:02 +00:00
Sept fiches jouables en /tdd, périmètre réduit aux deux algos marqués
« à reprendre avec swirl » dans le tableau §1 du plan. Le banc de contact
(03) est un aiguillage : un verdict « on ne touche rien » sur
sierpinski-chaos annule 04 et 05.

Trois écarts plan ↔ code relevés, le code faisant foi : le bump
VIDEO_ENGINE_VERSION touche aussi le jumeau PHP et son test (le plan dit
« rien d'autre à versionner ») ; l'extraction de rotateTransforms
concerne deux importeurs GPU que le plan ne cite pas ; le ternaire de
cadrage annoncé en T04 glisse en 05, faute de RED capable de le prouver
sans le knob.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
La rotation d'une banque d'affines servait déjà la motion vidéo `swirl`
de flame-ifs ; elle va servir le chaos game plat (random-ifs,
sierpinski-chaos). Faire importer le moteur des flammes non-linéaires
par un algo de chaos game serait une dépendance à l'envers, d'où un
module à part. Précédent : lib/rivulet.js, extrait de wax-crypt pour
blood-drip.

Déplacement pur : la fonction ne lit que a…f et répand le reste avec
...t. Pas de ré-export de compatibilité, les trois importeurs changent
de chemin ici (flame-ifs et les deux fichiers de cadrage GPU). Sept des
huit tests de la section 12 déménagent ; le huitième reste dans
flame.test.js, il assert la composition affine → variation via
applyTransform, qui est une affaire de flamme.

Aucun octet de rendu ne bouge : golden flame-ifs et ENGINE_VERSION
inchangés.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
Knob `swirl` en radians, défaut 0, appliqué à la banque d'affines APRÈS
son tirage : zéro rng ajouté ou déplacé, golden et ENGINE_VERSION
inchangés. Le knob est vidéo, déjà couvert par MOTION_KNOBS, donc aucun
paramSpec ni sync de catalogue.

L'algo cadre déjà sur le nuage qu'il vient de tirer, donc la rotation est
absorbée sans travail de cadrage — c'est ce qui en fait le jumeau plat de
flame-ifs, et ce qui rend `zoom`/`phase` inutilisables ici (overrides de
viewport absorbés, frames identiques). Pas de meta.videoParams : 161
ms/frame à la taille de tournage, cet algo filme à la qualité de
l'estampe.

La boucle se referme mieux que chez la flamme : le tour complet rend
0,0000 d'écart moyen sur quatre hashes, contre 4,7 à 13,2 pour le
demi-tour. Les affines sont contractantes, donc la perturbation de
2,4e-16 de sin(2π) décroît le long de l'orbite au lieu d'être amplifiée
par des variations non-linéaires. Seuil du test posé à 0,5, chiffres
consignés dans la fiche.

Contrepartie assumée : `draw-on` est perdu pour cet algo. C'est
l'arbitrage du plan §2, tranché — le banc (T03) peut encore le renverser.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
Six planches de contact à la taille de tournage réelle (1557 x 1920),
palettes du catalogue. Verdicts : tour complet pour random-ifs comme pour
sierpinski-chaos, donc 04 et 05 se jouent et l'item va-et-vient (T08)
reste non atomisé.

Les chiffres du plan §4 sont reproduits à la décimale sur le triangle
(envergure x0,97 / x0,97 / x0,95 / x1,00 aux quarts de tour) et la
colonne qui manquait est mesurée : sans cadrage dynamique, 14 % du nuage
sort du canevas dès 1/16 de tour, les deux tiers dès 1/8. Le saut de
cadrage de la frame 0 vaut -0,22 % d'envergure, invisible au raccord.

Deux choses que les planches apprennent et que le plan ne disait pas :
l'encre de random-ifs varie de 0,31 % à 3,49 % selon le hash, donc le
banc a été refait sur les deux tirages qu'une curation garderait ; et la
silhouette du triangle casse entre 5,6° et 11,3°, ce qui situe la fenêtre
utile si l'amplitude partielle revenait un jour sur la table.

Conséquence assumée du verdict (a) sur le triangle, écrite dans la
fiche : environ 420 frames sur 450 ne montrent pas de triangle alors que
le titre public en promet un. L'estampe, elle, ne bouge pas d'un octet.

Scripts de banc jetés, comme le veut le précédent Halloween.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
La boîte englobante d'un nuage quitte random-ifs pour lib/chaos-game.js :
le triangle va en avoir besoin, et une copie privée par algo aurait
divergé. Elle y côtoie buildProjection, dont elle nourrit l'argument
`bounds`, avec la note qui dit en quoi elle diffère de robustBounds
(affines contractantes, aucun outlier à rogner).

sierpinski-chaos passe de chaosGame (streaming) à iterateChaos + nuage
matérialisé + boucle d'émission, la forme qu'a déjà random-ifs. Le
cadrage reste les bornes ANALYTIQUES : sans banque tournée, rien ne
justifie de mesurer le nuage, et le golden le prouve — inchangé, comme
celui de random-ifs. chaosGame reste en place pour barnsley-fern et
pentaflake.

Aucun tirage ajouté ni déplacé : le nuage utile EST l'échantillon du
cadrage. Pas de bump engine_version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
Knob `swirl` en radians, défaut 0, sur une banque FIGÉE cette fois : la
rotation s'applique aux trois contractions de rapport un demi, et le
cadrage devient conditionnel. À angle nul les bornes analytiques du
triangle, donc l'estampe reste byte-identique (golden inchangé). Dès que
la banque tourne, les bornes se mesurent sur le nuage : sans ça, 64,5 %
des points sortent du canevas à un quart de tour, mesuré au banc.

Le test qui porte la tranche est celui-là — un quart de tour doit changer
le rendu ET garder tous les points dans le cadre. Il échoue pour deux
raisons différentes selon la pièce qui manque : rendu identique sans le
knob, points dehors sans les bornes du nuage.

La boucle se referme à 0,69 / 0,94 / 1,10 d'écart moyen selon le hash,
contre 22,1 à 22,3 au demi-tour. Le résidu n'est pas du bruit flottant
comme chez random-ifs : à 2π l'angle n'est plus nul, donc le cadrage
passe par le nuage quand l'estampe cadre sur l'analytique. C'est le saut
de cadrage de la frame 0 mesuré au banc, -0,22 % d'envergure, et il tombe
sur le raccord de boucle.

Verdict du banc appliqué : tour complet. Conséquence assumée et écrite
dans le module, ~420 frames sur 450 sans triangle. Zéro rng ajouté ou
déplacé, pas de bump engine_version, pas de paramSpec touché.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
Une entrée de journal pour toute la tranche, et le bump en lockstep :
constante Node, jumeau PHP, et le test unitaire qui épingle le jumeau.
Le plan disait « rien d'autre à versionner » ; pipeline-guard-video.js
refuse loud tout body dont la version ne correspond pas, donc bumper un
seul côté aurait cassé la génération vidéo au premier appel.

L'entrée garde ce qui ne se redevine pas dans six mois : pourquoi
rotateTransforms a quitté le moteur des flammes, en quoi les deux algos
diffèrent (leur caméra, et elle seule), les 64,5 % de points hors canevas
qui justifient les bornes conditionnelles du triangle, le saut de cadrage
de -0,22 % au raccord de boucle, l'absence de meta.videoParams justifiée
par les 126 à 161 ms/frame, et le coût éditorial accepté.

Les estampes ne bougent pas : engine_version inchangée, aucun paramSpec
touché, aucune migration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
Deux reels complets, pleine résolution de prod, vrai ffmpeg, musique
muxée, deux passes chacun : 243 ms/frame pour sierpinski-chaos et 262
pour random-ifs, contre un budget de 315. Le reel tient en moins de deux
minutes, facteur 8 sous le timeout de 900 s et moitié du reel flame-ifs.

L'estimation du plan était pessimiste : le poste letterbox + bandes +
encodage coûte ~100 ms/frame ici et non ~170, la frame étant un semis de
points et non un histogramme plein.

Les reels ont été regardés, pas seulement chronométrés. Le raccord de
boucle a été mesuré sur les frames encodées et comparé au pas courant du
milieu de clip : 1,5 à 1,6 fois un pas, donc pas un saut — swirlPath
s'arrête une marche avant le tour complet, exprès. Le surplus vient du
changement de cadrage au point de boucle pour le triangle et, pour les
deux, d'une image-clé h264 comparée à une image prédite.

Aucun code modifié : les deux algos passent, les meta.motion posés en
T02 et T05 restent. Script de banc jeté. La tranche est complète, reste
le go-live (rebuild de l'image renderer puis force-recreate).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
docs: le plan swirl dit quelles tranches sont jouées
All checks were successful
CI / Renderer - couverture JS (pull_request) Has been skipped
CI / Renderer - audit des dépendances JS (pull_request) Successful in 44s
CI / PHP - tests + static + lint (pull_request) Successful in 9m48s
CI / Renderer - tests + lint JS (pull_request) Successful in 10m36s
2801571cba
random-ifs et sierpinski-chaos sont livrés, pentaflake et barnsley-fern
restent ouverts : le plan ne peut donc pas être supprimé, il dit
désormais où il en est. Chaque tâche du §5 porte son état et son commit,
et une ligne « → » dit ce que l'exécution a appris quand elle diverge du
plan.

Trois endroits où le plan avait tort, corrigés sur mesure et non sur
raisonnement : le chaos game plat ne « amplifie » pas la perturbation de
sin(2π), il la contracte (d'où une boucle qui referme à 0,0000 chez
random-ifs) ; le bump de version touche trois fichiers et non un ; et
l'estimation du reel était pessimiste de 70 ms/frame, le poste
letterbox + bandes + encodage coûtant ~100 ms sur un semis de points.

Ce que les deux algos restants héritent, chiffré : la forme technique est
livrée et testée (lib/affine.js, boundsOf au lib, bornes
conditionnelles), mais leur banc et leur reel sont à refaire — la fougère
est estimée à 323 ms/frame, au-dessus du budget de 315, et son
effondrement x4,7 reste le vrai sujet. Le verdict « tour complet » du
banc porte sur le triangle et random-ifs, pas sur elle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiB1vcz5CtmpKnDfnqZUoq
Nora merged commit 8412b44d41 into develop 2026-09-12 13:11:52 +00:00
Nora deleted branch feature/swirl-family 2026-09-12 13:11:58 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Nora/ArtAutomatic!186
No description provided.