# 04-interactions – Vue fonctionnelle

Ce document décrit comment un utilisateur définit et utilise des **actions** dans Skyboard :
des procédures “Avant / Après” qui observent des conditions et produisent des effets sur le board.

On se concentre ici sur **l’expérience utilisateur** et les concepts, pas sur la technique interne.

---

## 1. Contexte / Problème

Sans le pack Interactions, tout changement dans un board doit être :

- déclenché directement par l’utilisateur,
- exécuté “à la main” (création, suppression, modification d’items),
- appliqué item par item.

Cela devient vite limité dès qu’on veut :

- **automatiser des routines** (ex. créer un ensemble d’items à chaque fois qu’un template est terminé),
- **propager des changements** (ex. passer certains items à un autre état quand une condition est remplie),
- **gérer des consommations de ressources** (ex. décrémenter des stocks, consommer des matériaux),
- **réagir à des événements** (ex. “quand cette action est terminée, alors…”).

Le pack Interactions introduit un concept central :

- l’**Action** = une configuration dédiée attachée à un **item porteur** qui :
  - est associée à un **événement déclencheur** (trigger),
  - décrit un bloc “Avant” (conditions),
  - décrit un bloc “Après” (effets),
  - cible un ou plusieurs items/conteneurs, avec un niveau de précision choisi par l’utilisateur.

L’UI peut représenter certains items comme des “items d’action” pour aider la compréhension,
mais structurellement il s’agit toujours d’items ordinaires portant une configuration
`ext.interactions.actions` : il n’existe pas de type de node “recette” ou “action” séparé du porteur.

Dans une première version, l’événement déclencheur par défaut est simple et très puissant :

- **événement par défaut** : *“Quand l’item porteur de l’action est marqué comme terminé”*
  - autrement dit : quand l’item porteur reçoit le tag d’état “done” / “terminé” (transition `absent → présent`, non rejouable si déjà `done`).
- plus tard, le pack Logique pourra étendre la liste des événements possibles :
  - autres changements d’état,
  - événements temporels,
  - événements basés sur d’autres items, etc.
- l’exécution V1 est pensée **atomique** : le plan est validé puis appliqué en une seule opération ; pas de best-effort en V1.

---

## 2. Objectifs fonctionnels

### 2.0. Événement déclencheur (Trigger)

Une action est toujours pensée comme : **Événement → Conditions → Effets**.

- L’**Événement** répond à la question :
  - *“Quand est-ce que l’action doit être envisagée ?”*
- Les **Conditions (Avant)** répondent à la question :
  - *“Dans quel contexte précis est-elle autorisée à s’exécuter ?”*
- Les **Effets (Après)** répondent à la question :
  - *“Que va-t-elle faire concrètement ?”*

En V1 :

- il existe un événement principal, fixé par le pack Interactions :
  - *“Quand l’item porteur est terminé”* (tag d’état `done` appliqué / atteint).
- cet événement est **toujours centré sur l’item porteur** de l’action en V1 :
  - Interactions ne définit pas d’événements “globaux” ou “abstraits” ;
  - pour des événements plus généraux (temps, items spécifiques, patterns globaux), c’est le rôle du pack Logique.
- les **conditions** dans “Avant” peuvent être vides (aucun prérequis dans le board),
  ou au contraire détaillées (ressources nécessaires, états d’autres items, etc.).
- les **effets** dans “Après” ne sont évalués que si l’événement a eu lieu et que
  toutes les conditions “Avant” sont satisfaites.

### 2.1. Interface “Avant / Après”

Une action se configure via une interface en deux colonnes claires :

- **Colonne Avant** :
  - décrit ce qui doit être vrai pour que l’action puisse s’exécuter **une fois l’événement survenu**,
  - décrit éventuellement ce qu’elle “attend” comme ressources ou état (pré-requis).
- **Colonne Après** :
  - décrit ce que l’action va produire comme effets sur le board,
  - peut créer, supprimer, modifier des items, tags, dates, relations, etc.

Chaque colonne est composée de **lignes** représentant des “briques” logiques :

- ligne Avant = “cible + condition” (sélection / filtre, **sans mutation directe**),
- ligne Après = “cible + effet”.

### 2.2. Ciblage générique vs ciblage précis

L’utilisateur doit pouvoir choisir son niveau de précision :

- **Ciblage précis** :
  - il désigne explicitement un item ou un container (via le moteur de sélection),
  - l’action s’exécute exactement sur cette cible.
- **Ciblage générique** :
  - il désigne un container ou un ensemble (ex. “ce projet”, “ce stock”),
  - l’action contient une “politique de choix” (ex. “prendre un item de type X avec telle quantité”),
  - le système choisit automatiquement l’item concret à utiliser lors de l’exécution.

Le même action peut mélanger des cibles précises et des cibles génériques.

Pour le ciblage générique, le système applique une **intelligence de sélection** :

- à partir d’un container / scope (board, workspace, container) + d’un filtre (tags, type, nom, relations…),
  il détermine automatiquement :
  - quel(s) item(s) seront utilisés comme cibles “réelles” au moment de l’exécution ;
- cette sélection automatique :
  - est **prévisualisée** dans l’interface (par exemple : “Actuellement, cela ciblerait : Stock Eau (50 L)”),
  - peut être **remplacée manuellement** par l’utilisateur :
    - en forçant une cible précise (via le moteur de sélection),
    - ou en ajustant les filtres.

Ainsi :

- un utilisateur pressé peut s’appuyer sur la sélection automatique,
- un utilisateur exigeant peut aller **au niveau granulaire** et choisir exactement les items,
  tout en profitant du même moteur de base.

Scopes V1 (bornés, pas de “board entier”) :
- self (porteur), container (parent), same-container (fratrie), container-children,
- related-dependents (items qui dépendent du porteur, distance 1),
- related-blocked (items bloqués par le porteur, distance 1).
Les scopes via relations à distance >1 relèvent du pack Logique.

Conditions V1 disponibles (implémentées) :
- state-is, tag-has, progress-at-least, resource-at-least, actor-has-capability.

Conditions prévues (V1.x, selon disponibilité des hooks) :
- deadline-passed, relation-exists.

Effets V1 disponibles :
- create-item, update-state/tags, set-progress, adjust-resource (non négatif), create-relation, delete-relation.
- Pas de création d’actions planifiées en V1, pas de mutation Teams/Logic/packs, pas de mutation cross-board.


### 2.3. Réutilisabilité et portabilité des actions

Une action doit pouvoir :

- être **réutilisée** sur différents containers / contextes (ex. même logique de consommation, mais sur différents stocks),
- être configurée pour “s’accrocher” à un container parent :
  - ex. “cette action consomme des ressources dans le container où elle se trouve”,
- être exécutée en **mode atomique** : plan complet validé puis appliqué en une seule opération. Le mode best-effort (effets indépendants) est réservé à des cas avancés non exposés en V1.

En clair : l’utilisateur peut soit :

- fixer toutes les cibles à l’avance (très précis),
- soit laisser l’action “s’adapter” au container où elle est placée (générique, réutilisable),
- choisir si l’action exige une confirmation (dry-run + récap) avant l’exécution atomique.

### 2.4. Clarté : expliquer ce qui va se passer

Avant d’utiliser une action, l’utilisateur doit pouvoir :

- **voir** en un coup d’œil :
  - quelles conditions la déclenchent,
  - quels effets elle va produire,
  - sur quels types de cibles.
- avoir une indication visuelle claire lorsqu’une action :
  - est prête à être exécutée (conditions remplies),
  - ne peut pas l’être (conditions non remplies ou ressources insuffisantes).

L’interface doit rendre lisible la logique, pas la cacher.

---

## 3. Scénarios d’usage

### 3.1. Action simple : “Quand cette tâche est terminée, créer une tâche de suivi”

1. L’utilisateur crée un item et lui applique un type “Action” (ou ouvre un panneau “Action” dédié).
2. **Événement déclencheur** (implicite en V1) :
   - “Quand cet item (porteur de l’action) est marqué comme terminé”.
3. Dans la colonne **Avant** :
   - aucune condition supplémentaire n’est nécessaire (aucun prérequis sur d’autres items ou ressources).
3. Dans la colonne **Après** :
   - il ajoute une ligne :
     - Cible : “Même container que cet item”,
     - Effet : “Créer un item” avec :
       - titre prédéfini (“Tâche de suivi pour …”),
       - tags prédéfinis (ex. `state/todo`, catégorie).
4. Quand la tâche passe à l’état “terminé” :
   - l’action se déclenche,
   - une nouvelle tâche de suivi est créée automatiquement dans le même container.

### 3.2. Action de consommation générique : “Prendre 10 L d’eau dans le stock du container”

1. L’utilisateur a un container “Projet X” contenant :
   - un sous-container “Stock de ressources” avec plusieurs items (Eau, Bois, etc.).
2. Il crée une action “Consommer eau” à l’intérieur du container “Projet X”.
3. Dans la colonne **Avant** :
   - Cible : “Un item dans ce container (ou sous-container défini)”,
   - Condition : “Type = Ressource” & “Nom = Eau” & “Quantité ≥ 10 L”.
   - Ciblage : **générique** (aucun item précis choisi).
4. Dans la colonne **Après** :
   - Cible : “L’item trouvé par la condition Avant”,
   - Effet : “Quantité = Quantité - 10 L”.
5. Lors de l’exécution :
   - le système cherche automatiquement un item dans le container (ou son stock) qui respecte ces conditions,
   - s’il le trouve → l’action consomme les 10 L,
   - s’il ne le trouve pas → l’action est affichée comme impossible (raison explicite : “Pas assez d’eau disponible”).

### 3.3. Action multi-cibles : “Répartir une ressource dans plusieurs projets”

1. L’utilisateur veut répartir 100 unités d’une ressource A entre plusieurs projets B, C et D.
2. Il crée une action “Répartition” :
   - Côté **Avant** :
     - Ligne 1 :
       - Cible : “Stock global” (sélectionné via le moteur de sélection),
       - Condition : Ressource A, quantité ≥ 100.
     - Ligne 2 :
       - Cible : “Liste des projets bénéficiaires” (sélection multiple via sélection universelle),
       - Condition : Type = Projet actif.
   - Côté **Après** :
     - Ligne 1 :
       - Cible : Stock global,
       - Effet : quantité -= 100.
     - Ligne 2 :
       - Cible : “Pour chaque projet sélectionné”,
       - Effet : créer un item “Lot de ressource A” avec la part allouée.
3. L’action explique clairement :
   - sur quel stock elle opère,
   - quels projets seront alimentés,
   - comment la répartition se fait (égale, pondérée, etc. – à préciser dans la technique).

### 3.4. Action basée sur les relations : “Marquer tous les dépendants comme prêts”

1. L’utilisateur a un item X dont plusieurs tâches Y1, Y2, Y3 dépendent (via le pack Relations).
2. Il crée une action “Tout est prêt” sur X.
3. Dans la colonne **Avant** :
   - Cible : “Cet item (X)”,
   - Condition : État = terminé.
4. Dans la colonne **Après** :
   - Cible : “Tous les items qui **dépendent de** X” (filtre basé sur les relations),
   - Effet : appliquer le tag “Prêt” ou changer l’état (“En attente de validation”, etc.).
5. Quand X est terminé :
   - l’action se déclenche,
   - tous les items dépendants sont mis à jour automatiquement.

### 3.5. Action avec confirmation et visibilité

1. Une action a des effets importants (ex. suppression de nombreux items, déplacement massif).
2. L’utilisateur déclenche l’action (en la marquant comme “terminée” ou via un bouton “Exécuter”).
3. Avant d’appliquer les effets, l’UI affiche un **récapitulatif** :
   - nombre d’items affectés,
   - types d’opérations (créations, suppressions, modifications),
   - éventuellement une prévisualisation partielle.
4. L’utilisateur confirme ou annule.
5. Après exécution, un message indique ce qui a été fait (au moins un résumé).

---

## 4. Contraintes & invariants métiers

### 4.1. Lisibilité et explicabilité

- Toute action doit pouvoir être **relue** :
  - comprendre ses conditions,
  - comprendre ses effets,
  - comprendre son périmètre (quels types de cibles, quels containers).
- Lorsqu’une action s’exécute :
  - l’utilisateur doit pouvoir savoir **pourquoi** elle s’est exécutée,
  - sur quoi elle a agi (au moins sous forme de résumé).
  - en mode atomique, un identifiant de “run” unique regroupe tous les effets et leur statut.

### 4.2. Maîtrise des effets de bord

- Une action ne doit pas :
  - se déclencher en boucle infinie (ex. une action qui déclenche une autre qui la re-déclenche),
  - casser les invariants structurels (container/leaf, relations, etc.).
- Le système doit :
  - cadrer les triggers (événements déclencheurs),
  - limiter l’imbrication non maîtrisée (via budget de règles, garde-fous techniques),
  - appliquer un **plafond** au nombre d’actions / mutations déclenchées en chaîne par une même exécution,
  - refuser ou stopper une action si elle risque de produire un comportement dangereux,
    en remontant une erreur claire à l’utilisateur,
  - en V1, exécuter les actions Interactions uniquement en **mode atomique** : valider le plan complet
    avant d’appliquer, sinon rollback total ; aucun mode best‑effort n’est exposé dans Interactions
    (les comportements best‑effort restent réservés aux actions purement UI hors Interactions).

### 4.3. Respect de la structure et des relations

- Les actions ne doivent jamais violer :
  - les invariants de structure (pas de leaf avec des enfants, pas de cycles structurels),
  - les invariants de relations (pas de cycles logiques si on manipule les relations).
- Si une action **modifie** les relations :
  - elle doit le faire de manière contrôlée,
  - et les restrictions de Relations (pas de cycle, etc.) restent prioritaires.

### 4.4. Autorisations (lien avec Teams)

- L’exécution d’une action est soumise aux droits de l’utilisateur :
  - l’utilisateur doit avoir le droit de faire chacune des opérations que l’action implique
    (créer / supprimer / modifier / relier des items).
- Si l’utilisateur n’a pas certains droits :
  - l’action doit soit être interdite,
  - soit être partiellement exécutée avec un message clair (décision à prendre dans Teams).

### 4.5. Portée des actions (scope raisonnable)

- Une action Interactions reste **locale** : son événement déclencheur concerne l’item porteur et ses effets
  doivent s’appliquer sur un scope limité et explicite (cibles sélectionnées, container ciblé, items reliés, etc.).
- Une action NE DOIT PAS nécessiter de parcourir systématiquement l’ensemble du board à chaque déclenchement
  (recherche globale non bornée, scan intégral) :
  - si un scénario exige ce type de comportement “global”, il relève du pack Logique, pas d’Interactions.
- L’interface de configuration des actions DOIT rendre visibles ces limites de scope (sélection, filtres, relations),
  afin d’éviter les “règles globales déguisées” en actions locales.

---

## 5. Interactions avec les autres systèmes

### 5.1. Avec Foundations (adressage, sélection)

- Les actions s’appuient directement sur :
  - l’**adressage** `{ boardId, nodeId }` pour cibler les items,
  - le **moteur de sélection universelle** pour choisir des cibles (items ou containers) lors de la configuration.
- Les cibles d’une action sont toujours définies en termes d’adresses / filtres, jamais par position visuelle seule.

### 5.2. Avec Relations

- Les actions peuvent utiliser les relations :
  - comme **critères de sélection** de cibles (“tous les items qui dépendent de X”, “tous les items bloqués par Y”),
  - comme **cibles d’effets** (création/suppression de relations, changement d’état basé sur les liens).
- Le pack Interactions ne redéfinit pas les relations :
  - il se contente de les exploiter comme un graphe de sélection / propagation.

### 5.3. Avec Progression

- Les actions peuvent :
  - utiliser la progression comme condition (“cet item doit être à 100 %”, “au moins 50 % des items d’un ensemble ciblé
    – par exemple des items liés ou sélectionnés – sont terminés”),
  - modifier la progression (“mettre cette tâche à 0 %”, “passer ce groupe à 100 %”).
- Les règles de cohérence de Progression (ex. agrégation, limitations) restent prioritaires :
  - une action ne doit pas pouvoir mettre la progression dans un état incohérent.

### 5.4. Avec Logique

- Le pack Logique pourra :
  - ajouter de nouveaux types d’événements déclencheurs (autres que “item terminé”),
  - ajouter de nouveaux types d’effets exploitables dans les actions,
  - permettre à des utilisateurs avancés de définir des **patterns d’action** réutilisables.
- Interactions est l’interface “guidée” pour configurer la logique :
  - Logique est la couche plus avancée qui étend ce que Interactions peut exprimer.

### 5.5. Avec Teams

- Les actions respectent les droits définis dans Teams :
  - un utilisateur ne peut pas configurer une action qui agirait sur des items qu’il ne peut pas toucher,
  - un utilisateur ne peut pas exécuter une action si ses effets dépassent ses droits,
  - lors d’un run, l’**acteur** est celui qui déclenche l’événement (ex. marque `done`) : chaque effet est filtré selon ses capabilities.
- Certaines actions pourront être :
  - réservées à certains rôles (ex. admin de board),
  - visibles mais non exécutables par d’autres (ex. “voir l’action mais pas la déclencher”).

### 5.6. Avec Community

- Une action définie dans un board publié :
  - ne doit pas exposer d’informations sur des items privés,
  - peut être affichée comme “partie de la logique interne” d’un template.
- Community pourra :
  - montrer l’existence d’actions dans un template partagé,
  - décider si la logique est visible, masquée, ou paramétrable par les utilisateurs qui importent le template.

---

Ce document fixe le **comportement attendu côté utilisateur** pour le pack Interactions :
les spécifications techniques détailleront ensuite comment encoder ces actions (modèle de données,
triggers, intégration au RulesEngine) en respectant ces attentes. 
