Flow
Un éditeur d'automatisations dont le graphe s'exécute vraiment.
Projet conceptuel : un atelier visuel où l'on pose des blocs, où on les relie à la souris, et où l'on regarde l'exécution parcourir le graphe étape par étape. Changez le seuil d'une condition, relancez : l'autre branche s'exécute. Tout tourne dans le navigateur, sans compte ni serveur.
Le problème que cette démonstration attaque
Les éditeurs de workflow font de belles captures d'écran. Des boîtes, des courbes, des couleurs — et, la plupart du temps, une animation. On appuie sur « Exécuter », quelque chose clignote dans l'ordre prévu, et rien n'a été décidé : le chemin était écrit d'avance.
Flow prend le problème par l'autre bout. Le graphe n'illustre pas l'exécution, il la détermine. Un moteur parcourt les liens réellement posés, transmet les données d'un bloc au suivant, évalue les conditions et n'emprunte qu'une branche. Retirez un lien, l'aval ne s'exécute plus. Ajoutez-en un, il s'exécute.
L'essai qui tranche tient en dix secondes : chargez « Commande à montant élevé », lancez, la branche VRAI s'allume et l'autre est marquée ignorée. Passez le total de 730 à 120, relancez : tout bascule de l'autre côté, dans le graphe comme dans le journal.
Ce qu'un éditeur de logique n'a pas le droit d'être
Un éditeur où l'utilisateur écrit des conditions est une porte ouverte s'il les évalue naïvement. `eval("total > 500")` ferait de cette page un moyen d'exécuter du code arbitraire — exactement ce qu'un tel outil ne doit jamais devenir.
Il n'y a donc nulle part de `eval`, de `new Function`, ni d'import qui dépende d'une saisie. Les comparaisons passent par une liste fermée de sept opérateurs, évalués par notre propre code. Le catalogue de blocs est fermé lui aussi : un fichier importé ne peut nommer qu'un type que nous avons écrit, sinon il est refusé avec la raison exacte.
Un fichier importé est traité comme hostile : schéma validé champ par champ, liens orphelins rejetés, nombre de blocs, de liens et longueur des textes plafonnés. Et l'état d'exécution ne s'enregistre jamais — un fichier décrit un graphe, jamais un statut « en cours » que la relecture rejouerait comme réel.
Ce que l'écran doit dire sans qu'on lise le code
Un moteur juste ne sert à rien si l'écran ne le montre pas. La condition a donc son anatomie propre : sa formule écrite en clair, puis deux lignes nommées VRAI et FAUX, chacune portant sa prise. Deux prises anonymes empilées obligent à deviner laquelle est laquelle — et on se trompe une fois sur deux.
Chaque état porte trois marques : un mot, une icône et un changement de surface. La couleur seule exclurait les lecteurs qui ne la distinguent pas, et disparaîtrait sur une impression. Pendant l'exécution, un point parcourt le lien réellement emprunté ; au repos il n'existe pas dans le DOM, et rien ne bouge dans un onglet oublié. Qui demande moins d'animations ne le voit jamais, et comprend pourtant tout : états écrits, branche choisie marquée, branche écartée en pointillé.
Le journal horodate ce qui s'est réellement passé — « commande.total = 730 · est supérieur à 500 → Vrai » sort de la comparaison faite, pas d'un script. L'inspecteur montre les données JSON reçues et produites par le bloc choisi. Sur téléphone, le canevas reste un canevas qu'on déplace, et les panneaux deviennent des feuilles : ce n'est pas un écran de bureau rétréci.
Aperçus




Ce qu'il y a dedans
- Graphe éditable à la souris : poser un bloc, relier deux prises, supprimer un lien
- Moteur d'exécution déterministe qui parcourt les liens réellement posés
- Conditions à branches : une seule est empruntée, l'autre est marquée ignorée
- Validation qui sépare ce qui empêche d'exécuter de ce qui mérite un avertissement, et refuse les cycles à la création du lien
- Journal horodaté qui consigne la comparaison réellement faite, et inspecteur qui montre les données reçues et produites
- Annuler/refaire sur cinquante niveaux, où un glissement entier compte pour un seul pas
- Import/export JSON à schéma fermé : un type de bloc inconnu est refusé avec sa raison
- Aucune évaluation de code : sept opérateurs fermés, quatorze types de blocs fermés, toutes les actions simulées
- Bilingue, persistance locale au navigateur, aucune donnée envoyée nulle part
