From c59f1b187c71393f2ec45008b6922579b7af0859 Mon Sep 17 00:00:00 2001
From: nillys <univers.hearth@gmail.com>
Date: Fri, 28 Nov 2025 11:37:16 +0100
Subject: [PATCH] update doc

---
 .gitignore                                    |   3 +-
 design-evolution/01-foundations/functional.md |   9 +
 design-evolution/01-foundations/technical.md  |   3 +-
 design-evolution/02-gestion/functional.md     |  41 +-
 design-evolution/02-gestion/technical.md      |  52 +-
 design-evolution/03-relations/functional.md   |   5 +-
 design-evolution/03-relations/technical.md    | 383 ++++++++++++-
 .../04-interactions/functional.md             |  41 +-
 design-evolution/04-interactions/technical.md | 514 +++++++++++++++++-
 design-evolution/05-logic/functional.md       |   1 +
 design-evolution/05-logic/technical.md        |  85 ++-
 design-evolution/06-teams/technical.md        |  51 +-
 design-evolution/07-community/functional.md   |  12 +-
 design-evolution/07-community/technical.md    |  45 +-
 design-evolution/08-library/functional.md     |  11 +-
 design-evolution/08-library/technical.md      |  37 +-
 design-evolution/09-activity/functional.md    |  50 ++
 design-evolution/09-activity/technical.md     |  84 ++-
 .../ZZ-global-synthesis/functional.md         |  26 +-
 .../ZZ-global-synthesis/technical.md          |  63 ++-
 20 files changed, 1391 insertions(+), 125 deletions(-)

diff --git a/.gitignore b/.gitignore
index 81b380e..9d4183e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,5 @@ AGENT.md
 *.tmp
 .DS_Store
 Thumbs.db
-*.patch
\ No newline at end of file
+*.patch
+*.zip
\ No newline at end of file
diff --git a/design-evolution/01-foundations/functional.md b/design-evolution/01-foundations/functional.md
index 0602701..a6cb537 100644
--- a/design-evolution/01-foundations/functional.md
+++ b/design-evolution/01-foundations/functional.md
@@ -155,6 +155,10 @@ L’objectif global : que Progression, Relations, Interactions, Logic, Teams et
   - visible (feedback clair),
   - annulable (Esc, bouton “Annuler”),
   - pouvant être filtré (containers seulement, items avec tels tags, etc.).
+- **Contrat UX minimal** :
+  - prévisualisation obligatoire avant exécution : nombre de cibles et aperçu des 3–5 premiers items,
+  - si la sélection renvoie 0 item : bouton d’exécution désactivé + message clair “Aucune cible ne correspond à ces critères.”,
+  - V1 ne persiste pas le résultat de la sélection (liste d’items) ; seuls les critères (scope + filtres) utilisés par une action sont conservés.
 - La sélection ne fait en elle-même **aucune mutation** :
   - elle se contente de retourner une ou plusieurs adresses `{ boardId, nodeId }`
     à la fonctionnalité appelante.
@@ -180,6 +184,7 @@ L’objectif global : que Progression, Relations, Interactions, Logic, Teams et
     - documentés, interprétés par des règles explicites,
   - les **tags utilisateur** :
     - libres, non interprétés globalement par le noyau.
+- Les préfixes réservés (`state/`, `rel/`, `resource/`, `type/`, `assigned/`, `sys/`, `event/`, `team/`…) sont **interdits** pour les tags utilisateur ; toute tentative de création échoue avec un message explicite.
 - Les comportements métiers ne naissent pas de tags “magiques” isolés, mais de :
   - **règles** qui disent explicitement : “si item possède tel tag, alors…”.
 - Les tags structurels (comme ceux qui influent sur `container`/`leaf`) sont :
@@ -198,6 +203,10 @@ L’objectif global : que Progression, Relations, Interactions, Logic, Teams et
   - “échéance dépassée”,
   - “tag ajouté/supprimé”,
   - “relation créée/supprimée”.
+- Visibilité minimale du temps/événements :
+  - chaque item dispose d’un bloc “Historique” dans sa vue détaillée (création, dernière modification, dernière transition d’état),
+  - Activity affiche tous les événements horodatés filtrés par Teams,
+  - sur les vignettes, des aides visuelles peuvent afficher “modifié il y a X jours” et “échéance dans X jours / dépassée depuis X jours” à partir des timestamps.
 - Les fondations se contentent de reconnaître que ces événements existent comme concepts ;
   leur exploitation concrète (progression automatique, notifications, actions…) sera définie
   dans les phases suivantes (Progression, Interactions, Logic).
diff --git a/design-evolution/01-foundations/technical.md b/design-evolution/01-foundations/technical.md
index 0ef33b1..011fc08 100644
--- a/design-evolution/01-foundations/technical.md
+++ b/design-evolution/01-foundations/technical.md
@@ -198,7 +198,7 @@ dans les phases Progression, Interactions, Logic, mais les fondations actent que
 
 - le temps est évalué côté backend,
 - les événements sont soit dérivés des données, soit générés par le scheduler,
-- il n’y a pas (pour l’instant) de stockage persistant d’événements individuels.
+- dans la V4 actuelle (sans le pack Activity), il n’y a pas de stockage persistant d’événements individuels ; Activity introduira ce stockage dédié en s’appuyant sur ces mêmes concepts de temps/événements.
 
 ## 2. Points d’intégration dans le code existant
 
@@ -443,4 +443,3 @@ Les événements métier ne sont pas stockés comme entités persistées, mais r
   - les fondations actent que `sys.shape` est structurel,
   - les tags ne sont pas le principal vecteur pour encoder de nouveaux comportements structurels :
     on privilégie les règles et les assistants.
-
diff --git a/design-evolution/02-gestion/functional.md b/design-evolution/02-gestion/functional.md
index e5e53c8..63bb88d 100644
--- a/design-evolution/02-gestion/functional.md
+++ b/design-evolution/02-gestion/functional.md
@@ -87,11 +87,17 @@ Le pack Gestion vise à :
   - `late` : l’item n’est pas terminé alors qu’une échéance importante est dépassée,
   - `blocked` : l’item ne peut pas avancer pour des raisons externes (dépendances non résolues, manque de ressources…),
   - `failed` : l’objectif de l’item est considéré comme manqué/abandonné.
-- Ces états doivent pouvoir :
+- Sémantique par défaut :
+  - `blocked` est un flag **informatif** (pas de veto moteur) ; l’UI le signale fortement et peut demander une confirmation sur certaines actions (ex. suppression, passage en `done`). Des règles Logique peuvent rendre ce flag bloquant si besoin.
+  - `failed` et `done` sont exclusifs (cf. matrice).
+- États principaux **exclusifs** : exactement un parmi `{todo, doing, done, failed}`.  
+  - `done` et `failed` sont mutuellement exclusifs.
+- Flags :
+  - `blocked` et `late` **seulement** avec `todo` ou `doing` ; toute transition vers `done/failed` les retire automatiquement.
+- Ces états/flags doivent pouvoir :
   - être appliqués manuellement (par l’utilisateur),
-  - être appliqués automatiquement (via dates, relations, interactions ou logique).
-  - ne jamais se substituer entièrement aux états de base `todo/doing/done` : un item est toujours dans
-    exactement un de ces états de base, puis éventuellement complété par `late/blocked/failed`.
+  - être appliqués automatiquement (via dates, relations, interactions ou logique),
+  - sans jamais créer de combinaison interdite (`done+blocked`, `done+failed`, etc.) : ces commandes sont rejetées.
 
 ### 2.2. Dates & échéances
 
@@ -106,6 +112,11 @@ Le pack Gestion vise à :
 - Lier les échéances aux états :
   - ex. si la date actuelle dépasse une échéance de type `deadline` et que l’item n’est pas terminé,
     alors l’item est éligible au tag `state/late` (application manuelle ou automatique via règles).
+- Politique `late` configurable par board :
+  - `manual-only` (par défaut) : pas d’auto-tag, simple éligibilité + signal,
+  - `auto-tag` : application automatique de `state/late` quand la deadline est dépassée si pas `done`,
+  - `eligible-only` : warning UI, sans appliquer le tag.
+- Par défaut (même sans auto-tag), les échéances dépassées sont signalées visuellement : date en style “retard”, badge “en retard” sur la carte.
 
 ### 2.3. Progression numérique
 
@@ -115,12 +126,17 @@ Le pack Gestion vise à :
 - La progression effective est toujours comprise entre 0 et la progression maximale :
   - 0 = aucun progrès,
   - progression effective = progression maximale = “100 %” pour cet item.
+- Progression affichée :
+  - si progression connue (`max > 0`) : affichage en pourcentage (ex. “37 %”) avec tooltip “37 / 100”,
+  - si progression inconnue : `max` nul/absent, barre neutre ou “N/A”.
+- Si la progression maximale change, la progression effective est **rescalée** pour conserver le même ratio puis clampée au nouveau max (arrondi).
 - Dans l’édition d’un item :
   - l’utilisateur peut saisir/modifier la progression effective et la progression maximale,
   - des contrôles adaptés (inputs, sliders) facilitent la mise à jour.
 - Dans le board :
   - une **barre de progression** apparaît sur la vignette de l’item,
   - visuellement, la barre reflète “progression effective / progression maximale”.
+- Si `progression effective = progression maximale` mais que l’état n’est pas `done`, une incohérence est signalée (warning UI + journalisation), sans basculer automatiquement l’état.
 - La **barre d’état verticale** (qui reflète le tag d’état : todo/doing/done, etc.) peut voir sa **largeur varier**
   en fonction de la progression maximale :
   - en dessous de 10 points, la barre d’état conserve sa largeur initiale,
@@ -128,10 +144,7 @@ Le pack Gestion vise à :
   - cela donne une indication visuelle de “l’importance” relative de l’item.
 - La progression est définie **par item**, qu’il soit leaf ou container :
   - il n’y a pas de comportement spécial basé uniquement sur `sys.shape`,
-  - les éventuels comportements d’agrégation ou de mise à jour automatique seront explicitement définis
-    via les Relations et/ou Logique, à partir du **graphe de relations** (par exemple, un item dont la progression
-    dépend de celle de ses dépendances), et **jamais** en lisant directement “tous les enfants d’un container”
-    ou en se basant uniquement sur la structure visuelle.
+  - la seule agrégation V1 est une **readiness fonctionnelle** = `min` des progressions fonctionnelles de ses dépendances (`rel/depends-on`/`rel/blocks`), jamais par simple structure.
 
 ### 2.4. Ressources matérielles
 
@@ -211,6 +224,10 @@ Le pack Gestion vise à :
 - Il peut :
   - ajuster les quantités manuellement (entrées / sorties),
   - plus tard, lier ces quantités à des actions Interactions (consommer 10 L d’eau, répartir du bois, etc.).
+- V1 : la quantité est un entier **≥ 0** (pas de stock négatif), l’unité reste libre mais l’UI propose une liste suggérée pour éviter les agrégations incohérentes.
+- Inventaire minimal :
+  - la même ressource (ex. `resource/water`) peut exister sur plusieurs items,
+  - une vue d’inventaire au niveau board (et filtrable par sous-arbre) agrège par `(type, unité)` et affiche les totaux.
 
 ## Contraintes & invariants métiers
 
@@ -261,8 +278,10 @@ Le pack Gestion vise à :
   - Les états `late`, `blocked`, `failed` sont **complémentaires** et ne remplacent pas `todo/doing/done` :
     - un item DOIT toujours pouvoir être positionné sur au moins un de ces états de base,
     - certaines combinaisons sont autorisées (ex. `todo + blocked`, `doing + late`) tant qu’elles restent lisibles.
-  - Certaines combinaisons sont considérées comme incohérentes et DOIVENT être interdites
-    (ex. `done + todo`, `done + doing`, `done + failed`).
+  - Combinaisons explicites V1 :
+    - interdites : `done+todo`, `done+doing`, `done+failed`, `todo+failed`, `done+blocked`, `done+late`,
+    - autorisées : `todo|doing` avec `late/blocked` selon le contexte.
+    - Toute transition vers `done` ou `failed` supprime automatiquement `blocked/late` et refuse qu’ils restent présents.
 - Dates & échéances :
   - Pour une catégorie donnée (`start`, `due`, `review`, `deadline`…), un item NE DOIT PAS avoir plus d’une échéance.
   - Un item marqué `state/late` DOIT avoir au moins une échéance pertinente (ex. `deadline`) qui a été dépassée.
@@ -276,7 +295,7 @@ Le pack Gestion vise à :
   - La progression agrégée d’un groupe NE DOIT PAS être déduite des seuls enfants structurels ; elle DOIT être
     définie par des relations et/ou des règles Logique explicites.
 - Ressources :
-  - Un item “ressource” DOIT préciser au minimum un type (`resource/*`) et une quantité.
+  - Un item “ressource” DOIT préciser au minimum un type (`resource/*`) et une quantité (entier ≥ 0 en V1 ; stock négatif interdit).
   - Les unités restent configurables, mais les agrégations (totaux, stocks globaux…) NE DOIVENT combiner que
     des ressources de même type et de même unité :
     - pas de “total” mélangeant des litres et des kilogrammes,
diff --git a/design-evolution/02-gestion/technical.md b/design-evolution/02-gestion/technical.md
index ea2d0bd..e53f8a2 100644
--- a/design-evolution/02-gestion/technical.md
+++ b/design-evolution/02-gestion/technical.md
@@ -13,9 +13,9 @@ les choix décrits ici servent de garde‑fous pour l’implémentation.
 
 **Rappel fonctionnel :**
 
-- États de base : `todo/doing/done` (colonne vertébrale).
-- États avancés complémentaires : `late`, `blocked`, `failed`.
-- Pour un item donné, il doit y avoir **exactement un** état de base actif.
+- États principaux exclusifs : `{todo, doing, done, failed}`.
+- Flags complémentaires : `late`, `blocked`.
+- Pour un item donné, il doit y avoir **exactement un** état principal actif.
 
 **Décision technique : tags système `state/*`**
 
@@ -24,34 +24,35 @@ les choix décrits ici servent de garde‑fous pour l’implémentation.
   - `state/todo`
   - `state/doing`
   - `state/done`
+  - `state/failed`
   - `state/late`
   - `state/blocked`
-  - `state/failed`
 - Ces tags sont ajoutés/retirés via les commandes standard de tags (`AddTagV3Command`, `RemoveTagV3Command`).
 
 **Invariants techniques :**
 
-- **Unicité de l’état de base :**
-  - Pour un node donné, l’ensemble `{state/todo, state/doing, state/done}` doit contenir **exactement un** élément.
-  - Toute opération qui conduirait à 0 ou >1 états de base est refusée (`422 INVALID_STATE_COMBINATION`).
-- **Combinaisons interdites :**
-  - Les combinaisons suivantes sont explicitement rejetées :
-    - `state/done` + `state/todo`
-    - `state/done` + `state/doing`
-    - `state/done` + `state/failed`
-  - Le handler de tags (ou une règle Gestion) vérifie ces combinaisons et met en veto en cas de conflit.
+- **Unicité de l’état principal :**
+  - Pour un node donné, l’ensemble `{state/todo, state/doing, state/done, state/failed}` doit contenir **exactement un** élément.
+  - Toute opération qui conduirait à 0 ou >1 états principaux est refusée (`422 INVALID_STATE_COMBINATION`).
+- **Combinaisons interdites / autorisées :**
+  - Refusées :
+    - `state/done` avec `state/blocked`, `state/failed` ou tout autre état principal,
+    - `state/failed` avec `state/todo/doing/done`,
+    - `state/blocked` ou `state/late` avec `state/done` ou `state/failed`.
+  - Autorisées :
+    - `state/blocked` et/ou `state/late` uniquement avec `state/todo` ou `state/doing`.
+  - Le handler de tags (ou une règle Gestion) vérifie ces combinaisons et met en veto si interdit.
 - **États avancés :**
-  - `state/late`, `state/blocked`, `state/failed` peuvent être présents ou absents indépendamment,
-    sous réserve de règles métier (ex. `failed` généralement incompatible avec `todo`).
+  - `state/late`, `state/blocked` ne peuvent coexister qu’avec un état principal `todo/doing`.
   - Les incompatibilités supplémentaires (plus fines) peuvent être introduites dans des règles MCC,
-    mais ne doivent jamais casser l’invariant “exactement un état de base”.
+    mais ne doivent jamais casser l’invariant “exactement un état principal”.
 
 ### 1.2. Progression numérique
 
 **Rappel fonctionnel :**
 
 - Chaque item a une progression effective et maximale, bornée à 10 000.
-- Progression agrégée uniquement via Relations + Logique, jamais via les seuls enfants structurels.
+- Progression agrégée uniquement via Relations + Logique, jamais via les seuls enfants structurels ; agrégation V1 = readiness = `min` des dépendances fonctionnelles (`rel/depends-on` / `rel/blocks`).
 
 **Décision technique : champs `ext.progress`**
 
@@ -89,11 +90,9 @@ les choix décrits ici servent de garde‑fous pour l’implémentation.
 
 - Aucune agrégation “structurelle” n’est codée dans le modèle (pas de champ `aggregatedProgress` calculé
   à partir des enfants).
-- Si une progression agrégée est persistée, elle doit être :
-  - calculée à partir de relations explicites (`rel/partOf`, `rel/depends-on`, etc.),
-  - produite par des règles Logique/Gestion,
-  - stockée dans un champ d’extension distinct (ex. `ext.gestion.progressAggregated`) clairement identifié
-    comme dérivé.
+- La seule agrégation V1 est une **readiness fonctionnelle** :
+  - `functionalProgress(node) = min(functionalProgress(dep))` sur les relations `depends=true` (`rel/depends-on` / `rel/blocks`),
+  - calculée à la volée par un service de projection (runtime) à partir du graphe de Relations/Logic, jamais par la structure ; aucun champ persisté n’est la “vérité” de cette readiness.
 
 ### 1.3. Dates & échéances
 
@@ -131,6 +130,11 @@ les choix décrits ici servent de garde‑fous pour l’implémentation.
 - Les commandes de mise à jour d’échéances :
   - créent ou remplacent l’entrée pour la catégorie concernée,
   - ne laissent jamais de structure invalide (pas de `deadlines = []` mélangé à des objets).
+- Un tag `state/late` ne peut être appliqué que si au moins une échéance pertinente est présente et dépassée ; sinon veto ou warning configurable.
+- Politique par board :
+  - `manual-only` : aucune auto-application,
+  - `auto-tag` : ajout automatique de `state/late` si `deadline` dépassée et pas `done`,
+  - `eligible-only` : l’item est étiqueté “éligible” côté UI/Activity, sans appliquer le tag.
 
 **Lien avec `state/late` :**
 
@@ -170,14 +174,14 @@ les choix décrits ici servent de garde‑fous pour l’implémentation.
   ```
 
 - `type` est un tag système `resource/*` déclaré dans un pack MCC.
-- `quantity` est un entier (ou décimal si besoin, à préciser plus tard).
+- `quantity` est un entier non négatif (V1 n’autorise pas les décimales).
 - `unit` est une chaîne libre, mais fortement recommandée parmi un set projetable en UI (m, kg, L, €, etc.).
 
 **Invariants techniques :**
 
 - Si `ext.gestion.resource` est présent :
   - `type` DOIT être non vide et commencer par `resource/`,
-  - `quantity` DOIT être >= 0 (aucun stock négatif par défaut),
+  - `quantity` DOIT être un entier >= 0 (aucun stock négatif par défaut),
   - `unit` peut être nullable/omise, mais si deux ressources sont agrégées, leurs `unit` DOIVENT correspondre.
 - Les commandes “Gestion Ressource” (à définir) :
   - effectuent des opérations atomiques (`add`, `subtract`, `set`) sur `quantity`,
diff --git a/design-evolution/03-relations/functional.md b/design-evolution/03-relations/functional.md
index a43ebef..8fe1076 100644
--- a/design-evolution/03-relations/functional.md
+++ b/design-evolution/03-relations/functional.md
@@ -39,9 +39,9 @@ L’utilisateur doit pouvoir manipuler au minimum :
 - une relation de type **“dépend de”** (dépendance / hiérarchie fonctionnelle) :
   - “A dépend de B” = A ne peut pas être considéré comme complètement résolu tant que B ne l’est pas ;
 - une relation de type **“bloque”** (blocage explicite) :
-  - “A bloque B” = tant que A n’est pas respecté/terminé, B ne peut pas avancer ;
+  - “A bloque B” = tant que A n’est pas respecté/terminé, B ne peut pas avancer ; **fait partie du même DAG de dépendance** (acyclique).
 - (optionnel / à discuter) une relation de type **“lié à”** (lien souple / référence croisée) :
-  - “A lié à B” = lien sémantique sans logique métier forte.
+  - “A lié à B” = lien sémantique sans logique métier forte ; hors DAG, symétrique logique (stockée une seule fois).
 
 Ces types sont vus **côté interface** comme des options simples dans un menu ou un picker,
 éventuellement extensibles plus tard (via le pack Logique).
@@ -191,6 +191,7 @@ ils ne doublent pas la logique, ils offrent juste des points d’entrée plus ra
 
 - Il ne doit jamais être possible de créer un **cycle de dépendances** logique, du type :
   - A dépend de B, B dépend de C, C dépend de A.
+- Toutes les relations porteuses de dépendance (`depends=true`, incluant “bloque”) appartiennent à ce même graphe acyclique.
 - L’interface doit :
   - soit prévenir en amont (option grisée, message),
   - soit refuser avec une explication claire.
diff --git a/design-evolution/03-relations/technical.md b/design-evolution/03-relations/technical.md
index 32d4c9f..2dbed02 100644
--- a/design-evolution/03-relations/technical.md
+++ b/design-evolution/03-relations/technical.md
@@ -1,22 +1,385 @@
 # 03-relations – Spécifications techniques
 
-## Concepts techniques clés
+Ce document traduit les objectifs fonctionnels du pack Relations en décisions techniques :
+modèle JSON dans le snapshot, invariants du graphe, gestion du mode “liste suivie”
+et points d’intégration avec Gestion, Logique, Interactions, Teams et Activity.
 
-*(À définir : modèle de relation (from/to/type), adressage, métadonnées éventuelles.)*
+On reste volontairement au niveau design : rien n’est encore “figé” dans le code, mais
+les choix décrits ici servent de garde‑fous pour l’implémentation.
 
-## Points d’intégration
+---
 
-*(À recenser : stockage des relations (snapshot ou table dédiée), règles de validation, exposition dans les packs.)*
+## 1. Concepts techniques clés
 
-## Structures de données
+### 1.1. Modèle de relation (arêtes)
 
-*(À figer : schéma JSON des relations, clés, index, formats de sérialisation.)*
+**Rappel fonctionnel :**
 
-## Flux types
+- Le pack Relations introduit un graphe de relations entre items d’un **même board**.
+- Types de base : “dépend de”, “bloque”, “lié à”.
+- On doit pouvoir lier des items de containers différents, y compris de workspaces différents,
+  tant que c’est le même board.
+- Les relations de dépendance sont **acycliques** (cf. `data-model-invariants.md`).
 
-*(À décrire : création d’une relation, recalcul automatique lors d’un ré‑ordonnancement, détection de cycles.)*
+**Décision technique : bloc `rel.edges` au niveau du snapshot de board**
 
-## Questions ouvertes / risques
+Les relations sont stockées au niveau du snapshot du board, sous la forme d’une liste d’arêtes :
 
-*(À lister : coût des vérifications d’acyclicité, gestion des relations cross‑board, impact sur les performances.)*
+```json
+{
+  "rel": {
+    "edges": [
+      {
+        "id": "uuid-edge-1",
+        "from": "uuid-node-A",
+        "to": "uuid-node-B",
+        "kind": "rel/depends-on",
+        "source": {
+          "mode": "manual"
+        }
+      }
+    ]
+  }
+}
+```
 
+- `id` : identifiant unique de la relation (UUID, unique à l’intérieur du board).
+- `from` : `nodeId` source (item A).
+- `to` : `nodeId` cible (item B).
+- `kind` : type de la relation, par exemple :
+  - `rel/depends-on`  (A dépend de B, `depends=true`),
+  - `rel/blocks`      (A bloque B, `depends=true`),
+  - `rel/linked-to`   (lien souple sans logique forte, `depends=false`).
+  Chaque type `rel/*` est déclaré dans un dataset MCC avec un flag `depends` qui le place (ou non) dans le DAG acyclique.
+- `source` : métadonnées de provenance, par ex. :
+  - `{ "mode": "manual" }`  (créée manuellement),
+  - `{ "mode": "list", "listContainerId": "uuid-container-L" }`
+    pour les relations générées automatiquement par une liste suivie.
+
+Les items eux‑mêmes ne portent pas de copie locale des relations : elles sont résolues
+en lisant `rel.edges` (graphe centralisé).
+
+**Invariants techniques de base :**
+
+- `from` et `to` DOIVENT :
+  - être différents (`from != to`) → **pas de self‑loop**,
+  - référencer des `nodeId` existants dans le snapshot du board.
+- `kind` DOIT être une valeur déclarée par le pack Relations dans un dataset MCC (`rel/*`).
+- Aucune relation cross‑board n’est stockée dans `rel.edges` :
+  - un edge ne peut relier que des items du **même board**.
+- Les doublons exacts (`from`, `to`, `kind`, `source.mode`, `source.listContainerId` identiques)
+  DOIVENT être traités comme strictement idempotents :
+  - si un edge identique existe déjà, aucune nouvelle entrée n’est créée et aucune erreur n’est renvoyée,
+  - l’Applier ne doit jamais produire deux arêtes identiques dans `rel.edges`.
+
+### 1.2. Sémantique des directions et types
+
+Pour éviter toute ambiguïté :
+
+- Une relation `rel/depends-on` avec `{ "from": A, "to": B }` signifie :
+  - **“A dépend de B”** : A ne peut pas être considéré comme complètement résolu tant que B ne l’est pas ;
+  - B est un **prérequis** de A.
+- Une relation `rel/blocks` avec `{ "from": A, "to": B }` signifie :
+  - **“A bloque B”** : tant que A n’est pas respecté/terminé, B ne peut pas avancer.
+- `rel/blocks` reste distinct de `rel/depends-on` ; aucune arête miroir implicite n’est créée. Les deux sont cependant marquées `depends=true` et appartiennent au même DAG acyclique.
+
+**Réprésentation canonique de `rel/linked-to` :**
+
+- Une relation de type `rel/linked-to` est stockée comme une **seule arête** `{ "from": A, "to": B }`.
+- Les consommateurs (UI, Logique, Gestion, Interactions) la considèrent comme un **lien non orienté** :
+  - “A lié à B” ≡ “B lié à A” du point de vue métier.
+- La création d’une arête miroir inverse (`from = B, to = A, kind = "rel/linked-to"`) alors qu’une arête
+  `A → B` existe déjà DOIT être rejetée ou normalisée en no‑op :
+  - le graphe ne doit jamais contenir deux arêtes `rel/linked-to` pour le même couple `(A, B)`.
+
+Ces définitions de direction sont utilisées par Gestion/Logique pour calculer :
+
+- les items bloqués (via `rel/depends-on` ou `rel/blocks`),
+- les chaînes de dépendances pour la progression agrégée.
+
+### 1.3. Acyclicité des relations de dépendance
+
+**Rappel fonctionnel :**
+
+- Le graphe de dépendances ne doit jamais contenir de cycle logique
+  (A dépend de B, B dépend de C, C dépend de A).
+- `data-model-invariants.md` énonce “Acyclicité des relations” : dans le cadre de Relations,
+  cela est précisé comme suit.
+
+**Décision technique : périmètre de l’acyclicité**
+
+- L’invariant d’acyclicité s’applique au **graphe des relations de dépendance** :
+  - toute arête dont le type est déclaré avec `depends=true` (incluant `rel/depends-on` et `rel/blocks`),
+  - les types `depends=false` (ex. `rel/linked-to`) ne sont pas concernés et peuvent cycler sans impact.
+
+**Invariants techniques :**
+
+- Pour tout edge `E = (from, to, kind = "rel/depends-on")` ajouté au graphe :
+  - il NE DOIT PAS exister de chemin de `to` vers `from` dans le graphe courant des `rel/depends-on`,
+  - sinon l’opération est rejetée (`422 RELATION_CYCLE_DETECTED` ou équivalent).
+- Toute modification d’un edge de dépendance est traitée comme une suppression + ajout :
+  - suppression de l’ancienne version (ne peut pas créer de cycle),
+  - tentative d’ajout de la nouvelle version, avec vérification d’acyclicité.
+
+Un algorithme incrémental (par ex. DFS limité au composant concerné) DOIT être utilisé en pratique
+pour éviter de parcourir tout le graphe à chaque création de relation.
+
+### 1.4. Mode “liste suivie”
+
+**Rappel fonctionnel :**
+
+- Sur un container L, l’utilisateur peut activer un mode “Rendre cette liste fonctionnelle / Suivre l’ordre” :
+  - une première chaîne de dépendances est générée à partir de l’ordre des enfants,
+  - tant que le mode est actif, les relations générées automatiquement sont recalculées à chaque
+    ajout/suppression/déplacement dans la liste.
+- Ce mode est une **configuration interne** du pack Relations, pas un tag système.
+
+**Décision technique : config `ext.relations.followedList` sur le container**
+
+Sur un node container L, on introduit un bloc d’extension :
+
+```json
+{
+  "ext": {
+    "relations": {
+      "followedList": {
+        "enabled": true,
+        "mode": "linear-chain",
+        "kind": "rel/depends-on",
+        "options": {
+          "childrenDependOnParent": false
+        }
+      }
+    }
+  }
+}
+```
+
+- `enabled` : active ou non le mode “liste suivie”.
+- `mode` :
+  - V1 : `linear-chain` (B dépend de A, C dépend de B, D dépend de C…).
+- `kind` :
+  - V1 : `rel/depends-on` (type de relation utilisé pour la chaîne).
+- `options.childrenDependOnParent` :
+  - permet d’exprimer l’option “tous les enfants dépendent du container lui‑même”.
+
+Les relations générées par ce mode sont stockées dans `rel.edges` avec un `source` explicite :
+
+```json
+{
+  "source": {
+    "mode": "list",
+    "listContainerId": "uuid-container-L"
+  }
+}
+```
+
+**Invariants techniques du mode “liste suivie” :**
+
+- Si `ext.relations.followedList.enabled == true` sur L :
+  - il DOIT exister dans `rel.edges` un ensemble d’arêtes taguées
+    `{ "source": { "mode": "list", "listContainerId": L } }` cohérent avec l’ordre courant
+    des enfants de L (pour le `mode` et le `kind` configurés).
+- Lorsqu’on désactive le mode (passage à `enabled = false`) :
+  - toutes les arêtes `source.mode = "list"` associées à `listContainerId = L`
+    DOIVENT être supprimées,
+  - les relations manuelles (source `mode = "manual"`) NE DOIVENT PAS être affectées.
+- En cas de contradiction entre une relation auto (liste suivie) et une relation manuelle, les deux
+  coexistent : l’auto est recalculée, la manuelle reste ; l’UI DOIT signaler le conflit mais aucune
+  suppression automatique n’a lieu.
+- Les opérations de DnD (move, reorder) sur les enfants de L DOIVENT déclencher une recomposition
+  de cet ensemble d’arêtes (cf. flux types).
+
+---
+
+## 2. Points d’intégration
+
+### 2.1. CommandBus & handlers Relations
+
+Le pack Relations n’introduit pas de nouveau bus :
+
+- toutes les mutations passent par `POST /api/commands`.
+
+On introduit des commandes dédiées, par exemple :
+
+- `Relations.CreateEdge`
+- `Relations.DeleteEdge`
+- `Relations.UpdateEdgeKind`
+- `Relations.SetFollowedListConfig` (activer/désactiver le mode liste suivie, changer ses options)
+
+**Handlers :**
+
+Chaque handler DOIT :
+
+- valider les invariants de base :
+  - nodes existants,
+  - même board,
+  - pas de self‑loop,
+  - `kind` déclaré dans MCC ;
+- rejeter les doublons exacts (ou les traiter comme idempotents) ;
+- vérifier l’acyclicité pour les arêtes de dépendance (`rel/depends-on`) ;
+- mettre à jour `rel.edges` et/ou `ext.relations.followedList` de manière atomique
+  (Apply = tout ou rien) ;
+- émettre des événements métier comme :
+  - `RelationCreated`,
+  - `RelationDeleted`,
+  - `FollowedListEnabled`,
+  - `FollowedListDisabled`,
+  - `FollowedListRelationsRebuilt`.
+
+**Respect de Teams :**
+
+- Tous les handlers Relations DOIVENT appliquer les règles de Teams :
+  - aucune création/modification/suppression d’edge n’est effectuée si l’utilisateur
+    n’a pas les droits nécessaires sur les items concernés (lecture/écriture structurelle
+    ou fonctionnelle, selon le cas).
+
+Ces événements sont consommables par :
+
+- Gestion (pour marquer `state/blocked`, alimenter la progression agrégée),
+- Logique (règles globales),
+- Activity (journal d’activité),
+- Interactions (actions déclenchées sur événements de relation).
+
+### 2.2. RulesEngine & pack MCC Relations
+
+Le pack MCC Relations :
+
+- déclare les types de relation disponibles (`rel/depends-on`, `rel/blocks`, `rel/linked-to`, etc.)
+  dans un dataset exploitable par l’UI,
+- fournit des règles génériques, par exemple :
+  - empêcher la création d’un edge si elle violerait l’acyclicité,
+  - normaliser certains patterns (ex. création simultanée de A blocks B et B depends-on A, si on le souhaite).
+
+Logique peut :
+
+- désactiver ou compléter ces règles,
+- définir des politiques globales (ex. comment propager des retards ou des blocages le long du graphe).
+
+### 2.3. Intégration avec Gestion, Logique, Interactions
+
+**Avec Gestion :**
+
+- Gestion lit le graphe des `rel/depends-on` / `rel/blocks` pour :
+  - déterminer quels items sont bloqués (candidats à `state/blocked`),
+  - alimenter la progression agrégée (en s’appuyant sur le graphe, pas sur la structure).
+- Les règles Gestion/Logique DOIVENT considérer `rel.edges` comme source de vérité pour
+  les dépendances.
+
+**Avec Logique :**
+
+- Logique peut :
+  - parcourir le graphe de relations pour détecter des patterns
+    (chaînes critiques, composants, dépendances orphelines…),
+  - déclencher des effets globaux (propagation d’états, correction d’incohérences).
+- L’acyclicité des `rel/depends-on` garantit qu’un parcours en profondeur ou un tri topologique
+  est toujours possible pour ces dépendances.
+
+**Avec Interactions :**
+
+- Les actions Interactions peuvent utiliser les relations comme scope ou filtre :
+  - “Quand cette tâche est terminée, marquer tous les items qui en dépendent comme prêts”,
+  - “Quand ce blocage est levé, enlever `state/blocked` sur les dépendants immédiats”.
+- Les scopes basés sur les relations DOIVENT respecter les limites d’Interactions :
+  - pas de scan implicite du board entier,
+  - scopes explicites (dépendants directs, voisins à distance 1, listes ciblées, etc.).
+
+---
+
+## 3. Flux types
+
+### 3.1. Création manuelle d’une relation “A dépend de B”
+
+1. Le front ouvre le panneau Relations de A et l’utilisateur choisit :
+   - type : “dépend de” → `kind = "rel/depends-on"`,
+   - cible : B (sélection universelle).
+2. Le front envoie une commande `Relations.CreateEdge` avec :
+   - `boardId`,
+   - `from = nodeId(A)`,
+   - `to   = nodeId(B)`,
+   - `kind = "rel/depends-on"`,
+   - `source = { "mode": "manual" }`.
+3. Le handler :
+   - vérifie que A et B appartiennent au board,
+   - vérifie `from != to`,
+   - vérifie qu’il n’existe pas déjà un edge identique,
+   - vérifie que l’ajout ne crée pas de cycle dans le graphe des `rel/depends-on`,
+   - en cas de violation → `422 RELATION_CYCLE_DETECTED`,
+   - sinon, ajoute l’edge à `rel.edges`.
+4. Un événement `RelationCreated` est émis.
+
+### 3.2. Activation du mode “Rendre cette liste fonctionnelle”
+
+1. L’utilisateur active, sur un container L, l’action “Rendre cette liste fonctionnelle / Suivre l’ordre”.
+2. Le front récupère la liste des enfants actuels de L, calcule un aperçu des relations :
+   - par exemple liste `[A, B, C, D]` → B dépend de A, C dépend de B, D dépend de C.
+3. En cas de confirmation, le front envoie une commande `Relations.SetFollowedListConfig` :
+   - `boardId`,
+   - `listContainerId = nodeId(L)`,
+   - `enabled = true`,
+   - `mode = "linear-chain"`,
+   - `kind = "rel/depends-on"`,
+   - `options.childrenDependOnParent` selon le choix UI.
+4. Le handler :
+   - met à jour `ext.relations.followedList` sur L,
+   - supprime toutes les arêtes existantes avec `source.mode = "list"` et `listContainerId = L`,
+   - génère la nouvelle chaîne de relations à partir de l’ordre des enfants (`childrenIds`) :
+     - pour une liste `[n1, n2, n3, …]`, crée des edges `(n2 depends-on n1)`, `(n3 depends-on n2)`, etc. ;
+     - crée éventuellement des edges “enfants dépendent du container” si l’option est active,
+   - ajoute ces edges dans `rel.edges` avec `source = { "mode": "list", "listContainerId": L }`,
+   - vérifie l’acyclicité (si conflit, l’opération est refusée dans son ensemble).
+5. Un événement `FollowedListEnabled` / `FollowedListRelationsRebuilt` est émis.
+
+### 3.3. Déplacement d’un item dans ou entre des listes suivies
+
+1. L’utilisateur déplace un item X :
+   - soit en changeant sa position à l’intérieur d’un même container L,
+   - soit en le déplaçant d’un container L1 vers un autre container L2.
+2. Le front envoie une commande de ré‑ordonnancement standard (`Node.Move` ou équivalent),
+   qui modifie le parent et/ou la position de X.
+3. Après application de cette commande, un reactor (ou une règle) vérifie :
+   - si l’ancien parent (L1) avait `ext.relations.followedList.enabled == true`,
+   - si le nouveau parent (L2) a `ext.relations.followedList.enabled == true`.
+4. Le reactor :
+   - si L1 était suivie :
+     - regénère les edges `source.mode = "list"` pour `listContainerId = L1` à partir du nouvel ordre
+       de ses enfants (sans X),
+     - remplace l’ancien ensemble par le nouveau (suppression + ajout) ;
+   - si L2 est suivie :
+     - regénère les edges `source.mode = "list"` pour `listContainerId = L2` à partir de l’ordre de ses enfants
+       (avec X à sa nouvelle position),
+     - remplace l’ancien ensemble par le nouveau.
+5. À chaque recomposition, l’acyclicité est re‑vérifiée.
+6. Les relations manuelles (source `manual`) ne sont jamais touchées par ces recalculs.
+
+### 3.4. Suppression d’un item impliqué dans des relations
+
+1. L’utilisateur supprime l’item X.
+2. Le front envoie une commande `Node.Delete` (ou équivalent).
+3. Lors de l’application :
+   - toutes les arêtes de `rel.edges` où `from = X` ou `to = X` DOIVENT être supprimées,
+   - si X est un container avec `followedList.enabled == true` :
+     - `ext.relations.followedList` est supprimé ou remis à son état par défaut,
+     - toutes les arêtes `source.mode = "list"` associées à `listContainerId = X` disparaissent.
+4. Un ou plusieurs événements (`RelationDeleted`, `FollowedListDisabled`, etc.) sont émis.
+
+---
+
+## 4. Questions ouvertes / risques
+
+- **Coût de la vérification d’acyclicité :**
+  - sur des boards avec beaucoup de dépendances, il faudra veiller à ce que l’algorithme
+    de détection de cycle soit incrémental et raisonnable (par ex. DFS limité au composant concerné).
+- **Volume de relations générées par les listes suivies :**
+  - une liste avec des centaines d’items génère des centaines d’arêtes ; à surveiller côté perf,
+    surtout en cas de recalcul fréquent après DnD massif.
+- **Évolution des types de relations :**
+  - si de nouveaux types de relations “porteuses de dépendance” sont ajoutés, il faudra clarifier
+    s’ils rentrent dans le périmètre de l’acyclicité (même graphe ou graphe séparé).
+- **Relations cross‑board :**
+  - considérées comme hors périmètre V1 ; si nécessaires, elles nécessiteront une réflexion spécifique
+    (adressage multi‑boards, invariants, impact sur les packs).
+- **Rétro‑compatibilité :**
+  - les boards existants sans `rel.edges` ni `ext.relations.followedList` doivent être considérés comme valides ;
+    les handlers doivent initialiser ces blocs avec précaution (structures absentes = absence de relations,
+    pas d’erreur).
diff --git a/design-evolution/04-interactions/functional.md b/design-evolution/04-interactions/functional.md
index 42ccd65..3293518 100644
--- a/design-evolution/04-interactions/functional.md
+++ b/design-evolution/04-interactions/functional.md
@@ -24,20 +24,25 @@ Cela devient vite limité dès qu’on veut :
 
 Le pack Interactions introduit un concept central :
 
-- l’**Action** = un item spécial (ou une configuration dédiée) qui :
-  - est associé à un **événement déclencheur** (trigger),
+- 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 (ou possède) le tag d’état “done” / “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.
 
 ---
 
@@ -113,6 +118,23 @@ Ainsi :
 - 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),
+- selection-explicit (adresses fournies par l’UI).
+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
 
@@ -120,12 +142,14 @@ 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”.
+  - 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).
+- 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
 
@@ -240,6 +264,7 @@ L’interface doit rendre lisible la logique, pas la cacher.
 - 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
 
@@ -251,7 +276,8 @@ L’interface doit rendre lisible la logique, pas la cacher.
   - 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 remontant une erreur claire à l’utilisateur,
+  - en mode atomique : valider le plan complet avant d’appliquer, sinon rollback total ; en best-effort, tracer ce qui passe/échoue.
 
 ### 4.3. Respect de la structure et des relations
 
@@ -322,7 +348,8 @@ L’interface doit rendre lisible la logique, pas la cacher.
 
 - 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.
+  - 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”).
diff --git a/design-evolution/04-interactions/technical.md b/design-evolution/04-interactions/technical.md
index 9d0c3c0..c27e74c 100644
--- a/design-evolution/04-interactions/technical.md
+++ b/design-evolution/04-interactions/technical.md
@@ -1,22 +1,516 @@
 # 04-interactions – Spécifications techniques
 
-## Concepts techniques clés
+Ce document traduit les objectifs fonctionnels du pack Interactions en décisions techniques :
+modèle JSON des actions “Avant / Après”, déclencheurs, résolution des cibles et intégration
+avec le RulesEngine, Gestion, Relations, Teams et Activity.
 
-*(À définir : représentation d’une action, déclencheurs, conditions, effets, lien avec le RulesEngine.)*
+On reste volontairement au niveau design : rien n’est encore “figé” dans le code, mais
+les choix décrits ici servent de garde‑fous pour l’implémentation.
 
-## Points d’intégration
+---
 
-*(À recenser : types de commandes déclenchées, événements observés, slots UI dédiés.)*
+## 1. Concepts techniques clés
 
-## Structures de données
+### 1.1. Action = configuration attachée à un item porteur
 
-*(À figer : format interne des actions (JSON), schéma des conditions/effets, stockage éventuel dans le snapshot.)*
+**Rappel fonctionnel :**
 
-## Flux types
+- Une action est toujours pensée comme : **Événement → Conditions (Avant) → Effets (Après)**.
+- En V1, l’événement principal est : *“quand l’item porteur est terminé”* (`state/done` appliqué).
+- L’action est **centrée sur l’item porteur** :
+  - l’événement est observé sur cet item,
+  - les conditions peuvent se référer à cet item et à son contexte,
+  - les cibles sont définies par rapport à lui (même container, items dépendants, etc.).
 
-*(À décrire : exécution d’une action à la fin d’un item, résolution des cibles, application des effets.)*
+**Décision technique : bloc `ext.interactions.actions` sur le node porteur**
 
-## Questions ouvertes / risques
+Une action est modélisée comme un objet JSON dans un tableau `actions` attaché à l’item porteur :
 
-*(À lister : complexité de l’UI, risque de boucles d’actions, stratégie de débogage et d’audit.)*
+```json
+{
+  "ext": {
+    "interactions": {
+      "actions": [
+        {
+          "id": "uuid-action-1",
+          "enabled": true,
+          "label": "Créer une tâche de suivi",
+          "trigger": {
+            "kind": "on-state-enter",
+            "state": "state/done"
+          },
+          "before": {
+            "conditions": [],
+            "targets": [
+              {
+                "id": "target-1",
+                "scope": "same-container",
+                "filters": []
+              }
+            ]
+          },
+          "after": {
+            "effects": [
+              {
+                "id": "effect-1",
+                "type": "create-item",
+                "targetRef": "target-1",
+                "params": {
+                  "titleTemplate": "Tâche de suivi pour {{porteur.title}}",
+                  "defaultTags": ["state/todo"]
+                }
+              }
+            ]
+          },
+          "meta": {
+            "needsConfirmation": false,
+            "description": "À la fin de cette tâche, créer une tâche de suivi dans le même container."
+          }
+        }
+      ]
+    }
+  }
+}
+```
 
+- `id` : identifiant unique de l’action (UUID).
+- `enabled` : action active ou non.
+- `label` / `description` : métadonnées pour l’UI (sans impact métier).
+- `trigger` : décrit l’événement.
+- `before` :
+  - `conditions` : liste de conditions à vérifier avant exécution,
+  - `targets` : descriptions de scopes/cibles possibles.
+- `after` :
+  - `effects` : effets à appliquer sur les cibles (ou le porteur).
+- `meta.needsConfirmation` : indique si l’UI doit afficher un récapitulatif avant exécution.
+- `meta.executionMode` : `"atomic"` en V1 (plan validé puis appliqué en un seul Apply). Le mode “best-effort” n’est pas exposé en V1.
+
+Un “item de type Action” dans l’UI n’est qu’un node dont `ext.interactions.actions` est peuplé
+(et éventuellement un style particulier), pas un type structurel distinct dans le snapshot.
+
+### 1.2. Événement déclencheur (Trigger)
+
+**Rappel fonctionnel :**
+
+- V1 : un seul événement de base → *“quand l’item porteur est terminé”*.
+- L’événement est **toujours local** à l’item porteur en V1.
+- Les autres événements (temps, patterns globaux…) sont du ressort du pack Logique.
+
+**Décision technique : champ `trigger`**
+
+Le champ `trigger` de l’action a la forme :
+
+```json
+"trigger": {
+  "kind": "on-state-enter",
+  "state": "state/done"
+}
+```
+
+- `kind = "on-state-enter"` : déclenché quand un tag d’état est ajouté.
+- `state` : tag d’état cible (V1 : `state/done`).
+
+**Sémantique précise de `on-state-enter` :**
+
+- `on-state-enter` est déclenché uniquement lors d’une **transition** où :
+  - l’item ne possède pas le tag `state/done` avant l’opération,
+  - l’item possède le tag `state/done` après l’opération.
+- L’événement métier sous‑jacent (`StateTagAdded(boardId, nodeId, "state/done")`) NE DOIT être émis
+  que pour cette transition “absent → présent”.
+  - Ré‑envoyer une commande qui ajoute `state/done` alors qu’il est déjà présent ne doit pas ré‑émettre
+    `StateTagAdded`, donc ne pas re‑déclencher l’action.
+- Si l’item repasse par un autre état (`doing` par exemple) puis revient à `done`, un nouvel événement `on-state-enter done` est émis (pas de blocage temporel arbitraire).
+
+**Invariants techniques V1 :**
+
+- `kind` DOIT être `"on-state-enter"`.
+- `state` DOIT être `"state/done"`.
+
+Plus tard, le pack Logique pourra introduire d’autres `kind`/`state` pour enrichir les triggers
+porteur‑centrés (progression, ressources, `state/late`, etc.), mais Interactions NE DOIT PAS
+introduire de trigger “global board” (du type “quand n’importe quel item du board…”).
+
+Le moteur d’Interactions est abonné aux événements de changement d’état (`state/*`)
+produits par les handlers de Gestion.
+
+### 1.3. Bloc “Avant” : conditions & cibles
+
+Le bloc `before` décrit :
+
+- les **conditions** qui doivent être vraies pour que l’action soit exécutée,
+- les **cibles candidates** sur lesquelles les effets vont s’appliquer.
+
+#### 1.3.1. Conditions
+
+Les conditions sont une liste d’objets de forme :
+
+```json
+{
+  "id": "cond-1",
+  "type": "state-is",
+  "target": {
+    "kind": "porteur"
+  },
+  "params": {
+    "state": "state/done"
+  }
+}
+```
+
+Exemples possibles de `type` en V1 :
+
+- `state-is` : vérifier qu’un item a (ou n’a pas) un certain tag d’état.
+- `tag-has` : vérifier la présence d’un tag arbitraire.
+- `progress-at-least` : vérifier que la progression d’un item atteint un seuil.
+- `resource-at-least` : vérifier que la ressource cible a une quantité suffisante.
+- `relation-exists` : vérifier qu’il existe au moins une relation d’un certain type.
+- `deadline-passed` : vérifier qu’une échéance est dépassée.
+- `actor-has-capability` : vérifier que l’acteur courant possède une capability Teams donnée.
+
+**Target de condition :**
+
+- `target.kind` peut être :
+  - `"porteur"` : l’item porteur,
+  - `"scope"` + `scopeRef` : une des cibles définies dans `before.targets`,
+  - `"explicit"` : un item désigné explicitement (rare en V1, plutôt géré via scope).
+
+Les conditions sont évaluées en conjonction (AND) : toutes doivent être vraies pour que l’action
+soit exécutable.
+
+#### 1.3.2. Cibles (targets)
+
+Un “target” décrit **comment trouver des items** à partir du contexte du porteur :
+
+```json
+{
+  "id": "target-1",
+  "scope": "same-container",
+  "filters": [
+    {
+      "type": "tag-has",
+      "params": { "tag": "state/todo" }
+    }
+  ]
+}
+```
+
+Exemples de valeurs de `scope` V1 (toutes **locales** au porteur) :
+
+- `"self"` : l’item porteur lui-même.
+- `"same-container"` : les siblings du porteur dans le même container.
+- `"container"` : le container direct du porteur.
+- `"container-children"` : les enfants du container du porteur.
+- `"related-dependents"` : items qui **dépendent du porteur** (via `rel/depends-on`, pack Relations), distance = 1 uniquement.
+- `"related-blocked"` : items **bloqués par le porteur** (via `rel/blocks`), distance = 1 uniquement.
+- `"selection-explicit"` : liste d’adresses `{boardId, nodeId}` fournie explicitement par le front.
+
+**Invariants techniques sur le scope :**
+
+- Un scope DOIT être **borné** :
+  - pas de scope implicite “tous les items du board”,
+  - tout scope doit pouvoir être évalué à partir de :
+    - l’item porteur,
+    - ses relations directes,
+    - son container/voisinage immédiat,
+    - ou une sélection explicite fournie par le front.
+- Les scopes basés sur les relations sont limités à la **distance 1** en V1 ; au-delà, passer par Logique.
+- Les scopes qui nécessiteraient de parcourir tout le board DOIVENT passer par le pack Logique,
+  pas par Interactions.
+- La résolution des scopes DOIT être filtrée par Teams :
+  - les items que l’utilisateur n’a pas le droit de voir sont exclus du scope,
+  - les items qu’il peut voir mais pas modifier sont exclus des cibles effectives pour les effets
+    (ils peuvent éventuellement être pris en compte dans des conditions purement en lecture) ;
+  - en tout état de cause, l’ensemble effectif des cibles doit rester cohérent avec les droits Teams.
+
+- Pour les scopes `selection-explicit`, tous les `boardId` fournis DOIVENT être égaux au `boardId`
+  de l’item porteur :
+  - toute adresse `{boardId, nodeId}` pointant vers un autre board est ignorée ou provoque
+    une erreur explicite, mais ne doit jamais être utilisée comme cible effective.
+
+Les `filters` sont appliqués après la résolution brute du scope (tags, états, types, etc.).
+
+### 1.4. Bloc “Après” : effets
+
+Le bloc `after` liste les effets à appliquer, chacun faisant référence à une cible via `targetRef` :
+
+```json
+{
+  "id": "effect-1",
+  "type": "create-item",
+  "targetRef": "target-1",
+  "params": {
+    "titleTemplate": "Tâche de suivi pour {{porteur.title}}",
+    "defaultTags": ["state/todo"]
+  }
+}
+```
+
+Exemples d’effets V1 :
+
+- `create-item` :
+  - crée un nouvel item dans un container cible,
+  - paramètres : titre, tags par défaut, position (avant/après le porteur, en fin de liste, etc.).
+- `update-state` :
+  - ajoute/enlève des tags d’état (`state/*`) sur les items cibles,
+  - DOIT respecter les invariants de Gestion (exactement un état de base, combinaisons interdites).
+- `update-tags` :
+  - ajoute/enlève des tags arbitraires.
+- `set-progress` :
+  - met à jour la progression effective/maximale, en respectant les bornes de Gestion.
+- `adjust-resource` :
+  - envoie une commande Gestion pour ajuster `ext.gestion.resource.quantity`
+    (consommation de ressources), en respectant la non-négativité configurée.
+- `create-relation` / `delete-relation` :
+  - crée ou supprime des relations via les commandes Relations appropriées,
+  - DOIT respecter les invariants de Relations (acyclicité, pas de self‑loop).
+
+**Invariants techniques sur les effets :**
+
+- Aucun effet ne doit :
+  - modifier directement les permissions (Teams reste unique source de vérité),
+  - créer des items ou des relations dans un autre board que celui du porteur,
+  - créer des actions planifiées ou modifier Logique/Teams/packs.
+- Tout effet DOIT se traduire en une ou plusieurs **commandes standards** (`/api/commands`) :
+  - création d’item,
+  - ajout/retrait de tag,
+  - mise à jour de progression,
+  - ajustement de ressource,
+  - création/suppression de relation, etc.
+- Les erreurs des effets sont remontées action par action (pas de “silent fail”) et
+  loggées dans Activity (avec code d’erreur et message).
+
+### 1.5. Confirmation et explicabilité
+
+Le champ `meta.needsConfirmation` permet de marquer une action comme “sensible” :
+
+- l’UI DOIT, pour ces actions :
+  - afficher un récapitulatif (nombre d’items affectés, types d’opérations),
+  - attendre une confirmation explicite avant d’envoyer les commandes d’effets.
+
+Les exécutions d’actions DOIVENT être traçables :
+
+- chaque exécution porte un identifiant de “run”,
+- les commandes générées sont liées à ce run dans Activity.
+
+---
+
+## 2. Points d’intégration
+
+### 2.1. RulesEngine & déclenchement
+
+Le moteur d’Interactions s’appuie sur le RulesEngine existant :
+
+1. Lorsqu’un handler de Gestion applique un changement d’état (`state/*`) à un item :
+   - il émet un événement métier (ex. `StateTagAdded(boardId, nodeId, tag)`).
+2. Le pack MCC Interactions contient des règles :
+   - “si `StateTagAdded` avec `tag = state/done` pour un node qui possède `ext.interactions.actions`…”
+3. Pour chaque action de ce node :
+   - si `trigger.kind = "on-state-enter"` et `trigger.state = "state/done"`,
+   - alors la règle enfile une “évaluation d’action” (job interne ou message dans un canal dédié).
+4. L’évaluation d’action :
+   - résout les conditions (`before.conditions`),
+   - si elles sont toutes vraies :
+     - résout les cibles (`before.targets`),
+     - prépare les effets (`after.effects`),
+     - si `needsConfirmation = false` : exécution directe,
+     - sinon : l’UI est notifiée pour confirmation.
+- L’**acteur** d’une exécution est l’utilisateur qui a déclenché l’événement (ex. celui qui a posé `state/done`) ;
+  chaque effet est vérifié vis-à-vis de ses capabilities Teams avant émission des commandes.
+
+Logique peut :
+
+- ajouter de nouveaux types d’événements porteur‑centrés (par ex. `on-progress-threshold`, `on-late`, etc.),
+- exposer ces événements comme triggers supplémentaires pour Interactions,
+- mais NE DOIT PAS introduire de trigger global qui ne soit pas ancré sur un porteur.
+
+### 2.2. CommandBus & exécution des effets
+
+L’exécution des effets passe toujours par le CommandBus (`POST /api/commands`) :
+
+- pas de canal parallèle, pas de mutation “hors bus”.
+
+Pour un run d’action donné :
+
+- l’exécuteur d’Interactions construit une liste de commandes :
+  - `CreateNode`,
+  - `AddTagV3Command` / `RemoveTagV3Command`,
+  - `Gestion.SetProgress`,
+  - `Gestion.AdjustResource`,
+  - `Relations.CreateEdge` / `Relations.DeleteEdge`,
+  - etc.
+- ces commandes sont envoyées via le bus regroupées dans une **commande unique** (mode atomic) qui applique le plan en un seul Apply.
+
+**Granularité d’atomicité :**
+
+- Chaque commande appliquée via le CommandBus est atomique (Apply = tout ou rien au niveau de la commande).
+- En V1, un run correspond à **une seule commande** `RunAtomicAction` : le plan complet passe ou échoue en bloc (aucun mode best-effort exposé).
+
+### 2.3. UI & datasets
+
+Le pack MCC Interactions fournit :
+
+- un dataset des types de conditions (`state-is`, `tag-has`, `progress-at-least`, …),
+- un dataset des types d’effets (`create-item`, `update-state`, `adjust-resource`, …),
+- un dataset des scopes (`self`, `same-container`, `related-dependents`, …),
+
+que l’UI utilise pour construire le panneau d’édition des actions :
+
+- chaque action est éditable via un formulaire structuré basé sur ces datasets,
+- l’UI ne construit pas de JSON “libre” : elle remplit le schéma prévu pour `ext.interactions.actions`.
+
+### 2.4. Budget d’exécution & garde‑fous
+
+Pour éviter les boucles infinies ou les explosions combinatoires :
+
+- Interactions DOIT appliquer un **budget d’exécution** par événement source (par exemple un `StateTagAdded`
+  donné sur un porteur) :
+  - limite sur le nombre total de runs d’actions déclenchés en cascade,
+  - limite sur la profondeur de chaîne (A déclenche B qui déclenche C…),
+  - limite sur le nombre total de commandes générées dans ce contexte.
+- Lorsque ce budget est dépassé :
+  - l’évaluation en cours est interrompue,
+  - le run (ou la branche concernée) est marqué comme échoué pour cause de budget dépassé,
+  - un événement d’erreur explicite est loggé dans Activity.
+
+Les valeurs exactes de ce budget (limites, configuration) peuvent être définies dans une phase
+ultérieure, mais l’existence même de ce garde‑fou est **obligatoire**.
+
+### 2.5. Modes d’exécution (`meta.executionMode`)
+
+- V1 : uniquement le mode `atomic` exposé.
+- Sémantique `atomic` :
+  1. Évaluer conditions et cibles (dry run).
+  2. Construire un plan complet (cibles résolues + effets).
+  3. Émettre une **commande unique** `Interactions.RunAtomicAction` avec le plan.
+  4. Le handler revalide le plan contre le snapshot courant, applique tout en un seul Apply, ou rejette intégralement.
+- Le handler ne fait pas confiance au plan client : recalcul ou validation stricte obligatoire.
+- Pas de mode best-effort exposé en V1 (reste éventuel mode interne de débogage).
+
+---
+
+## 3. Structures de données
+
+### 3.1. Schéma JSON d’une action
+
+Sans figer un JSON Schema complet, les champs minimaux sont :
+
+- `id: string` (UUID)
+- `enabled: boolean`
+- `label: string`
+- `trigger: { kind: string, state?: string }`
+- `before: { conditions: Condition[], targets: Target[] }`
+- `after: { effects: Effect[] }`
+- `meta: { needsConfirmation?: boolean, description?: string, executionMode?: "atomic" }` (V1 : toujours `"atomic"`, champ non exposé à l’UI)
+
+**Condition (V1) :**
+
+- `id: string`
+- `type: "state-is" | "tag-has" | "progress-at-least" | "resource-at-least" | "relation-exists" | "deadline-passed" | "actor-has-capability" | ..."`
+- `target: { kind: "porteur" | "scope" | "explicit", scopeRef?: string, nodeId?: string }`
+- `params: object` (dépend du type)
+
+**Target (V1) :**
+
+- `id: string`
+- `scope: "self" | "same-container" | "container" | "container-children" | "related-dependents" | "related-blocked" | "selection-explicit" | ..."`
+- `filters: Filter[]`
+
+**Effect (V1) :**
+
+- `id: string`
+- `type: "create-item" | "update-state" | "update-tags" | "set-progress" | "adjust-resource" | "create-relation" | "delete-relation" | ..."`
+- `targetRef: string` (référence à un `Target.id`)
+- `params: object` (dépend du type)
+
+**Meta (V1) :**
+
+- `needsConfirmation?: boolean`
+- `description?: string`
+- `executionMode?: "best-effort" | "atomic"` (V1 : `"atomic"` seulement ; `"best-effort"` réservé à des usages internes / futurs, non exposé à l’UI)
+
+### 3.2. Stockage & versioning
+
+- Le bloc `ext.interactions` est optionnel :
+  - absence = aucun comportement d’Interactions pour ce node.
+- Le format des actions DOIT être versionné implicitement :
+  - soit via un champ `version` sur chaque action,
+  - soit via une convention de migration dans le pack MCC Interactions.
+
+Les migrations de format (V1 → V2…) DOIVENT être gérées par des scripts/mécanismes dédiés,
+pas par l’UI.
+
+---
+
+## 4. Flux types
+
+### 4.1. “Quand cette tâche est terminée, créer une tâche de suivi”
+
+1. L’utilisateur configure une action sur un item T (ou utilise un item de type “Action”) :
+   - `trigger = { "kind": "on-state-enter", "state": "state/done" }`,
+   - `before.conditions = []`,
+   - `before.targets = [ { "id": "t-container", "scope": "same-container", "filters": [] } ]`,
+   - `after.effects = [ { "type": "create-item", "targetRef": "t-container", "params": {...} } ]`.
+2. Au moment où T reçoit `state/done` :
+   - le handler Gestion émet `StateTagAdded(boardId, T, "state/done")`,
+   - le pack Interactions repère les actions de T et programme leur évaluation.
+3. L’évaluation :
+   - vérifie `conditions` (ici : vide → OK),
+   - résout la target `"t-container"` comme le container de T.
+4. L’exécution :
+   - construit une commande `CreateNode` dans ce container avec le titre/tag définis,
+   - envoie la commande via le CommandBus,
+   - logge un run d’action dans Activity.
+
+### 4.2. Action “Tout est prêt” basée sur les relations
+
+1. Un item X a plusieurs dépendants Y1, Y2, Y3 (via `rel/depends-on`).
+2. Une action “Tout est prêt” est définie sur X :
+   - `trigger` : `on-state-enter` sur `state/done`,
+   - `before.targets` contient un `scope = "related-dependents"`,
+   - `after.effects` contient un `update-state` pour ajouter un tag `state/ready` sur ces cibles.
+3. Quand X est marqué `state/done` :
+   - Interactions résout le scope `related-dependents` via le pack Relations (lecture de `rel.edges`),
+   - applique, via des commandes de tags, le tag `state/ready` sur Y1, Y2, Y3,
+   - respecte les invariants de Gestion (aucune combinaison d’états interdite).
+
+### 4.3. Action de consommation de ressources
+
+1. Une action est définie sur une tâche T pour consommer `10` unités d’une ressource R :
+   - `before.targets` : `target-1` avec `scope = "selection-explicit"` pointant vers R,
+   - `after.effects` : `effect-1` de type `adjust-resource` avec `targetRef = "target-1"` et `delta = -10`.
+2. Quand T passe en `state/done` :
+   - Interactions vérifie que R existe et a assez de quantité (via une condition `resource-at-least`),
+   - envoie une `Gestion.AdjustResource(boardId, nodeId=R, delta=-10)`,
+   - en cas de refus (quantité insuffisante, politique stricte…) :
+     - l’effet est marqué comme échoué,
+     - Activity enregistre l’erreur.
+
+### 4.4. Exécution manuelle avec confirmation
+
+1. Une action potentiellement destructive (ex. suppression en masse) a `needsConfirmation = true`.
+2. L’UI propose un bouton “Exécuter l’action” sur l’item porteur.
+3. Lors du clic :
+   - au lieu d’exécuter immédiatement les effets, un “dry run” est effectué côté Interactions :
+     - résolution des cibles,
+     - construction de la liste des commandes **sans les envoyer**.
+4. Le résultat (cibles + types d’opérations) est renvoyé au front pour affichage d’un résumé.
+5. Si l’utilisateur confirme :
+   - les commandes sont envoyées via le CommandBus,
+   - Activity enregistre le run et les commandes associées.
+
+---
+
+## 5. Questions ouvertes / risques
+
+- **Boucles d’actions complexes :**
+  - même avec un budget, certains scénarios de configurations croisées peuvent produire
+    des comportements non intuitifs ; il faudra prévoir de bons outils de debug (traces, visualisation).
+- **Complexité de l’UI :**
+  - besoin d’un mode “simple” (actions guidées prédéfinies) vs “avancé” (édition complète),
+  - éviter que l’utilisateur se perde dans des configurations trop abstraites.
+- **Performance et scopes :**
+  - même avec des scopes bornés, certaines actions peuvent toucher beaucoup d’items ;
+  - nécessité de prévoir une exécution incrémentale / paginée pour des effets massifs.
+- **Debug & audit :**
+  - prévoir des outils de visualisation dans Activity (filtre “actions exécutées”, détail des runs),
+  - faciliter le débogage pour un utilisateur avancé (“Pourquoi cette action ne s’est pas déclenchée ?”).
diff --git a/design-evolution/05-logic/functional.md b/design-evolution/05-logic/functional.md
index a3008c5..50e6f87 100644
--- a/design-evolution/05-logic/functional.md
+++ b/design-evolution/05-logic/functional.md
@@ -180,6 +180,7 @@ Logique étend donc la puissance d’Interactions sans en changer la nature :
 - Toute modification effective des droits (ajout/retrait de permissions, changement de rôle, etc.)
   DOIT passer par les mécanismes Teams (commandes et règles dédiées) ; au mieux, une règle Logique peut
   suggérer ou préparer une telle modification, jamais l’appliquer directement.
+- Hiérarchie d’override : invariants noyau > règles pack non overridables > règles pack overridables > règles Logique custom. Une règle custom ne peut supplanter qu’une règle pack marquée overridable ; en cas de conflit d’effets, on échoue explicitement plutôt que de faire du “last-wins” implicite.
 
 ### 5.5. Avec Community
 
diff --git a/design-evolution/05-logic/technical.md b/design-evolution/05-logic/technical.md
index da1c2f9..d88801f 100644
--- a/design-evolution/05-logic/technical.md
+++ b/design-evolution/05-logic/technical.md
@@ -1,22 +1,87 @@
 # 05-logic – Spécifications techniques
 
-## Concepts techniques clés
+## 1. Format et stockage des règles
 
-*(À définir : format des règles utilisateur, vocabulaire (types, événements, actions), mode d’extension du RulesEngine.)*
+- Stockage par board dans un bloc versionné `ext.logic.rules` (ou table dédiée) : pas dans les manifests MCC système.
+- Une règle :
 
-## Points d’intégration
+```json
+{
+  "id": "rule-id",
+  "enabled": true,
+  "priority": 100,
+  "scope": "board",
+  "triggers": ["state:enter:state/late", "time:tick-daily"],
+  "conditions": { "op": "and", "conditions": [ { "type": "tag-missing", "target": "self", "tag": "state/done" } ] },
+  "actions": [ { "type": "add-tag", "target": "self", "tag": "state/late" } ],
+  "budget": { "actions": 50, "depth": 3 }
+}
+```
 
-*(À recenser : stockage des règles custom, chargement dans le moteur, priorités avec les règles système/packs.)*
+- `priority` : ordre d’évaluation (plus petit = évalué d’abord).
+- `scope` : V1 = `board` (règle s’applique au board courant).
+- `budget` : limites locales (nombre d’actions, profondeur de cascade).
 
-## Structures de données
+## 2. Triggers disponibles V1
 
-*(À figer : schéma des règles (JSON ou autre), liens avec les tags/datasets.)*
+- Temps : `time:tick-daily`, `time:tick-hourly`.
+- États : `state:enter:<state>`, `state:exit:<state>`.
+- Deadlines : `deadline:passed`.
+- Progression : `progress:threshold-crossed` (>= valeur donnée).
+- Relations : `relation:created`, `relation:deleted`.
+- Commandes : `command:<type>` (optionnel, si exposé).
+- Les triggers porteur-centrés supplémentaires peuvent être exposés à Interactions (toujours centrés sur l’item porteur).
 
-## Flux types
+## 3. Conditions (vocabulaire V1)
 
-*(À décrire : cycle de vie d’une règle (création, modification, exécution), résolution des conflits potentiels.)*
+- Predicates typés, combinables via arbres AND/OR :
+  - `tag-has` / `tag-missing`
+  - `state-is`
+  - `progress-at-least`
+  - `deadline-passed`
+  - `relation-exists` (avec `kind`, direction, distance max)
+  - `in-container` (appartenance à un container)
+  - `actor-has-capability` (rôles/capabilities Teams)
+  - `assigned-to-actor` (présence `assigned/<actor>`)
+- `target` : `self` (item concerné par le trigger) ou `scope` (cibles résolues par un projector) ; distance via relations bornée configurablement.
 
-## Questions ouvertes / risques
+## 4. Actions (effets V1)
 
-*(À lister : facilité d’usage, risques de configuration dangereuse, besoin d’outils d’inspection.)*
+- `add-tag` / `remove-tag` (états compris, respect des invariants Gestion).
+- `set-progress` (respect des bornes).
+- `set-deadline`.
+- `create-relation` / `delete-relation` (respect acyclicité/contraintes Relations).
+- `create-item` / `delete-item`.
+- `veto` : refuser une mutation en cours avec code/ message explicite.
+- Aucun effet sur Teams (permissions) ni sur des boards externes.
+- Toutes les actions se traduisent en commandes standards via le CommandBus.
 
+## 5. Priorités et overrides
+
+- Hiérarchie : invariants noyau > règles packs non overridables > règles packs overridables > règles custom (triées par `priority`).
+- Une règle custom ne peut supplanter qu’une règle pack marquée `overridable=true`; sinon elle coexiste sans effet d’override.
+- En cas de conflit d’effets détectable (même trigger/scope/champ avec actions opposées) : l’évaluation échoue explicitement (pas de last-wins implicite) avec log Activity.
+- Les règles désactivées sont ignorées mais restent persistées.
+
+## 6. Budget et garde-fous
+
+- Budget global par **déclenchement de trigger / cascade** :
+  - nb max de règles évaluées pour un même trigger,
+  - nb max d’actions produites dans cette cascade,
+  - profondeur max de cascade (règle déclenche Interactions qui déclenche Logique, etc.).
+- Dépassement budget ⇒ arrêt de l’évaluation, log Activity avec un code explicite (ex. `LOGIC_BUDGET_EXCEEDED`).
+- Détection de cycles entre règles : tracer les runs (runId, source trigger) et stopper si on boucle sur la même combinaison trigger+cible.
+
+## 7. Points d’intégration
+
+- **Chargement** : `RulesCatalog` charge règles packs + règles custom (ext.logic.rules) au boot du board.
+- **Évaluation** : `RulesEngine` reçoit les triggers issus des handlers/ scheduler, projette le contexte (`boardId`, `nodeId`, tags, deadlines, relations, capabilities acteur).
+- **Permissions** : chaque action générée est vérifiée via Teams (acteur = déclencheur du trigger). Pas de bypass “système”.
+- **Interactions** : Logique peut publier des triggers porteur-centrés supplémentaires utilisables par Interactions (ex. `on-progress-threshold`, `on-late`).
+- **Activity** : chaque run (règle évaluée) est journalisé avec `ruleId`, `runId`, `actorId`, `actions exécutées/échouées`, budget consommé.
+
+## 8. Questions / risques
+
+- Performance sur gros boards : projection du contexte doit rester incrémentale (éviter scans complets).
+- UX : éditeur de règles lisible (phrases proches du métier) + outil de debug “pourquoi ma règle ne s’est pas déclenchée ?”.
+- Sécurité : pas d’effet sur Teams, pas de cross-board ; surveiller la dérive des distances dans `relation-exists`.
diff --git a/design-evolution/06-teams/technical.md b/design-evolution/06-teams/technical.md
index 91a221e..8e6e525 100644
--- a/design-evolution/06-teams/technical.md
+++ b/design-evolution/06-teams/technical.md
@@ -1,22 +1,53 @@
 # 06-teams – Spécifications techniques
 
-## Concepts techniques clés
+## 1. Modèle d’authz
 
-*(À définir : modèle de permission (sujets, ressources, actions), scopes, héritage éventuel.)*
+- **Sujet** : `userId`.
+- **Ressource** : `(boardId, scope)` où `scope` ∈ `{ board | subtree(containerId) | node(nodeId) }`.
+- **Action primitive** (exemples) : `read`, `write-content`, `write-structure`, `set-state`, `set-progress`, `set-deadline`, `manage-relations`, `manage-actions`, `manage-logic`, `manage-teams`, `publish`, `manage-community`, `upload`.
+- **Capability** : lot cohérent de primitives (ex. `content-editor`, `structure-editor`, `relations-manager`, `actions-runner`, `logic-admin`, `teams-admin`, `publisher`).
+- **Rôle** : combinaison de capabilities (Owner, Maintainer, Contributor, Reader + customs).
+- **Affectation** : tags `assigned/*` sont des signaux métier. Une règle builtin optionnelle : “peut modifier contenu + état des items où il est assigné”.
 
-## Points d’intégration
+## 2. Héritage et résolution
 
-*(À recenser : middleware d’authz, hooks dans le CommandBus/Arbitre, stockage des droits.)*
+- Un grant sur `board` s’applique à tout le board.
+- Un grant sur `subtree(containerId)` s’applique au sous-arbre.
+- Un grant sur `node(nodeId)` s’applique à ce node uniquement.
+- **Deny** explicite sur un scope précis > grant plus large, sauf Owner (ignore les deny).
+- Principe de moindre privilège : pas de droits implicites hors grants/rôles.
+- Rôles customs = listes de capabilities ; modification d’un rôle répercute les capabilities associées immédiatement.
 
-## Structures de données
+## 3. Vérification des droits
 
-*(À figer : tables/JSON des droits, représentation des scopes (par board, par container, par item…).)*
+- **CommandBus** : chaque handler appelle une vérification `authorize(actorId, boardId, scope, primitive)` avant de produire le patch. Refus → `403 FORBIDDEN` (code symbolique).
+- **Interactions/Logic** : l’acteur d’un run est l’utilisateur qui déclenche l’événement. Chaque effet issu d’un run vérifie les primitives requises pour chaque cible ; les cibles visibles mais non éditables peuvent être utilisées en lecture (conditions), jamais en écriture.
+- **Sélection universelle** : filtrée par Teams → on ne peut pas sélectionner ce qu’on ne peut pas voir. Les cibles d’effets sont en plus filtrées par les droits d’édition.
+- **Publish/Community** : `publish` ou `manage-community` requis en plus des droits de lecture sur les items publiés.
+- **Owner** : bypass des deny, mais passe quand même par la vérification (utile pour le logging).
 
-## Flux types
+## 4. Structures de données (suggestion)
 
-*(À décrire : vérification d’un droit avant une commande, délégation de droit, révocation.)*
+- Table/JSON `roles`: `{ id, label, capabilities[] }` (standard + customs).
+- Table/JSON `memberships`: `{ userId, boardId, roleId, scopes[] }` où `scopes` liste de `board` ou `subtree(containerId)` ou `node(nodeId)`.
+- Table/JSON `grants`: pour exceptions (deny/grant explicite sur scope).
+- Flag board : `assignmentRuleEnabled` (active la règle builtin sur `assigned/*`).
 
-## Questions ouvertes / risques
+## 5. Flux types
 
-*(À lister : complexité perçue, performances, gestion des cas limites (droits contradictoires).)*
+- **Vérification commande** : `MoveNode` → primitive `write-structure` sur parent source + parent cible ; refus si manque un des deux.
+- **Run Interactions atomic** : chaque effet génère une commande ; avant envoi, vérifier que l’acteur possède les primitives associées (`create-item`, `set-state`, `manage-relations`, etc.) sur les cibles résolues.
+- **Logique** : lors d’un veto ou d’une action générée, la vérification est identique (acteur = déclencheur de la règle). Aucune règle ne “se connecte” comme système pour bypasser.
+- **Affectation** : si la règle builtin est active, un utilisateur est autorisé à `write-content` + `set-state` sur les items où `assigned/<user>` est présent (ou hérités d’un container assigné), sans conférer `write-structure` ni `manage-actions`.
 
+## 6. Traçabilité et garde-fous
+
+- Chaque commande logge : `actorId`, `boardId`, `nodeIds` touchés, `capability`/`primitive` consommée, `result`.
+- Activity projette ces logs en respectant Teams (pas de fuite de nodes invisibles, détail masqué si nécessaire).
+ - Safeguard “dernier owner” : toute opération qui retirerait ou rétrograderait le dernier Owner d’un board est refusée (`403`, code métier dédié, ex. `LAST_OWNER_PROTECTION`) et journalisée dans Activity.
+
+## 7. Questions / risques
+
+- Performance : cache des résolutions de scope pour gros boards (arbre + ACL).
+- UX : rendre visible “d’où vient le droit” (rôle, scope, exception, affectation) ; outil de diagnostic.
+- Conflits de rôles/customs : clarifier que deny scoped prime sur grant (sauf Owner).
diff --git a/design-evolution/07-community/functional.md b/design-evolution/07-community/functional.md
index ab8d02a..929bd4b 100644
--- a/design-evolution/07-community/functional.md
+++ b/design-evolution/07-community/functional.md
@@ -43,7 +43,8 @@ Le pack Community fournit un **hub** :
 - La publication doit être :
   - **explicite** (acte volontaire, pas implicite),
   - **réversible** (possibilité de retirer un contenu publié),
-  - **configurable** (niveau de visibilité : public, limité à un cercle, etc. – à préciser plus tard).
+  - **configurable** (niveau de visibilité : public, limité à un cercle, etc. – à préciser plus tard),
+  - **expurgée** des données sensibles (Teams, assigned, données internes) ; les actions/règles publicables sont incluses mais arrivent inactives chez l’importeur.
 
 ### 2.2. Visibilité & découverte
 
@@ -63,7 +64,8 @@ Le pack Community fournit un **hub** :
     - ou insérer un container publié dans un de ses boards.
 - L’import/fork ne doit pas :
   - affecter le contenu d’origine,
-  - transférer des informations confidentielles non voulues.
+  - transférer des informations confidentielles non voulues,
+  - activer automatiquement des actions/règles importées : elles arrivent inactives, scheduler/logique désactivés par défaut tant qu’ils ne sont pas explicitement activés.
 
 ### 2.4. Exposer les besoins & contributions possibles
 
@@ -140,9 +142,13 @@ Le pack Community fournit un **hub** :
 - Ce qui est visible dans Community :
   - ne doit montrer que ce que le propriétaire accepte explicitement de rendre public,
   - ne doit pas exposer des informations privées (notes internes, commentaires sensibles, etc.).
-- Le fait de publier un contenu dans Community n’accorde AUCUN droit supplémentaire sur le board source :
+  - Le fait de publier un contenu dans Community n’accorde AUCUN droit supplémentaire sur le board source :
   - consulter ou forker un contenu publié ne donne pas d’accès en écriture au board original,
   - toute contribution externe passe par des mécanismes dédiés, vérifiés par Teams.
+- Nettoyage de publication :
+  - les tags d’affectation `assigned/*` et autres données sensibles sont supprimés ou anonymisés avant publication,
+  - la logique interne (Interactions/Logique) n’est pas publiée par défaut ; inclusion optionnelle explicite si le propriétaire le souhaite.
+  - les notes/commentaires marqués comme internes/ne devant pas sortir du board sont exclus par défaut ; seuls les contenus explicitement marqués comme publiables peuvent être embarqués.
 
 ### 4.2. Séparation original / fork
 
diff --git a/design-evolution/07-community/technical.md b/design-evolution/07-community/technical.md
index 3ce418b..8e80f2d 100644
--- a/design-evolution/07-community/technical.md
+++ b/design-evolution/07-community/technical.md
@@ -2,21 +2,54 @@
 
 ## Concepts techniques clés
 
-*(À définir : modèle de publication (quoi, comment, avec quelles métadonnées), notion de « contribution ».)*
+- Publication explicite : board entier, sous-arbre, ou modèle Library.
+- Expurgation systématique : suppression Teams (rôles, grants, denies), `assigned/*`, données internes/notes privées non publiables.
+- Actions/règles publicables : incluses mais **inactives** dans l’importeur ; l’admin doit les activer explicitement. Scheduler/logique désactivés par défaut dans le board importé/forké.
+- IDs : réécriture des `boardId/nodeId` à l’import/fork ; aucun lien vivant vers la source.
 
 ## Points d’intégration
 
-*(À recenser : endpoints HTTP, stockage des entités publiques, interactions avec les boards privés.)*
+- Endpoints : publication/retrait (POST/DELETE), import/fork (POST), liste/recherche (GET).
+- Respect Teams : seules les personnes autorisées peuvent publier/retraiter ; aucun droit nouveau n’est accordé par la publication (lecture seule côté hub).
+- Activity : publication/retrait/import/fork journalisés (`community.publish`, `community.fork`, etc.).
 
 ## Structures de données
 
-*(À figer : schémas des entités publiées, liens vers les boards source, anonymisation éventuelle.)*
+- Entité publiée (exemple) :
+
+  ```json
+  {
+    "id": "public-uuid",
+    "sourceBoardPublicId": "uuid",
+    "kind": "board|container|template",
+    "snapshot": { ...expurgé... },
+    "actions": [ ... inactives ... ],
+    "rules": [ ... inactives ... ],
+    "metadata": { "title": "...", "description": "...", "tags": ["..."], "owner": "userId" },
+    "createdAt": 1736463600,
+    "updatedAt": 1736463600
+  }
+  ```
+
+- Le snapshot expurgé ne contient aucune donnée de permissions ni d’assignation.
 
 ## Flux types
 
-*(À décrire : publication d’un container, mise à jour, retrait, contribution externe, synchronisation.)*
+- Publication :
+  - auteur choisit périmètre (board/sous-arbre/template),
+  - expurgation,
+  - stockage avec `publicId`,
+  - log Activity.
+- Retrait : marque le contenu comme non listé, supprime les liens du hub.
+- Import/fork :
+  - récupération du snapshot expurgé,
+  - régénération des `nodeId` et attribution d’un nouveau `boardId`,
+  - actions/règles importées stockées **désactivées**,
+  - scheduler/logique désactivés tant qu’ils ne sont pas activés manuellement,
+  - log Activity avec source/target.
 
 ## Questions ouvertes / risques
 
-*(À lister : sécurité, abus potentiels, scalabilité du hub, cohérence avec la roadmap produit.)*
-
+- Modération/abus sur le hub.
+- Poids et volumétrie des snapshots publiés.
+- Gestion des dépendances vers des packs privés/licenciés lors de la publication.
diff --git a/design-evolution/08-library/functional.md b/design-evolution/08-library/functional.md
index 45a459b..a065ad1 100644
--- a/design-evolution/08-library/functional.md
+++ b/design-evolution/08-library/functional.md
@@ -29,7 +29,7 @@ Library doit permettre à un utilisateur de :
 
 1. **Enregistrer des modèles**
    - Modèle d’item :
-     - tags, progression, champs, propriétés, relations, actions associées…
+     - tags, progression (bornée), champs, propriétés, relations, actions associées (importées inactives), règles associées (importées inactives).
    - Modèle de container / sous-arbre :
      - structure d’items et de containers imbriqués,
      - paramètres (tags, dates relatives, actions et relations “prêtes à l’emploi”).
@@ -41,10 +41,11 @@ Library doit permettre à un utilisateur de :
    - Depuis une palette de “templates” :
      - insérer un item basé sur un modèle,
      - insérer un sous-arbre (container + contenu),
-     - cloner une action préconfigurée.
+     - cloner une action préconfigurée (arrive inactive par défaut).
    - Choisir le comportement pour :
      - les dates (relatives, recalculées à partir de “aujourd’hui”),
-     - certains tags (ex. tags d’affectation).
+     - certains tags (ex. tags d’affectation),
+     - l’activation ou non des actions/règles importées (par défaut : inactives).
 
 3. **Gérer la visibilité des modèles**
    - Modèles **privés** :
@@ -53,6 +54,10 @@ Library doit permettre à un utilisateur de :
      - partagés avec l’équipe sur un board donné (en fonction des droits Teams).
    - Modèles **publics** :
      - publiés via Community, réutilisables par d’autres utilisateurs.
+   - Nettoyage publication :
+     - suppression/anonymisation des tags d’affectation `assigned/*` et données sensibles,
+     - inclusion de la logique/actions internes uniquement sur opt-in explicite lors de la publication (et elles arrivent inactives par défaut chez l’importeur),
+     - les notes/commentaires marqués comme internes ne sont pas exportés par défaut ; seuls ceux explicitement marqués comme publiables sont inclus.
 
 4. **Organiser la bibliothèque**
    - Classer les modèles (catégories, tags, recherche).
diff --git a/design-evolution/08-library/technical.md b/design-evolution/08-library/technical.md
index 26ab2b7..79aac00 100644
--- a/design-evolution/08-library/technical.md
+++ b/design-evolution/08-library/technical.md
@@ -2,21 +2,46 @@
 
 ## Concepts techniques clés
 
-*(À définir : représentation des modèles (items, sous-arbres, actions), stockage, liens éventuels avec Community.)*
+- Modèles = snapshots partiels (item, sous-arbre, action/config) sérialisés avec métadonnées (auteur, visibilité, dates relatives).
+- Actions/règles incluses sont importées **inactives** par défaut ; activation explicite par le consommateur.
+- Dates : stockées en relatif par défaut (offsets), conversion à l’insertion.
+- Nettoyage publication : suppression/anonymisation `assigned/*`, données sensibles ; aligné sur Community.
 
 ## Points d’intégration
 
-*(À recenser : UI (palette de modèles), commandes de création à partir de modèle, interactions avec Teams et Community.)*
+- UI : palette de modèles avec options (dates relatives, activer actions/règles ou non).
+- Commandes : `CreateFromTemplate` (ou équivalent) qui remappe `nodeId`, applique dates relatives, insère dans un container cible.
+- Teams : contrôle de visibilité/usage des modèles (privé/équipe/public).
+- Community : export/import avec même pipeline d’expurgation qu’en publication Community.
 
 ## Structures de données
 
-*(À figer : schémas JSON des modèles, métadonnées (auteur, portée, visibilité), format d’export/import.)*
+- Schéma modèle (exemple) :
+
+  ```json
+  {
+    "id": "template-uuid",
+    "visibility": "private|team|public",
+    "kind": "item|subtree|action|config",
+    "snapshot": { ... },
+    "actions": [ ... inactives ... ],
+    "rules": [ ... inactives ... ],
+    "metadata": { "title": "...", "description": "...", "tags": ["..."], "createdAt": 1736463600 }
+  }
+  ```
+
+- `snapshot` utilise des `nodeId` propres au modèle ; ils sont régénérés à l’insertion.
+- Dates relatives : stockées sous forme d’offsets (en jours/secondes) à appliquer lors de l’insertion.
 
 ## Flux types
 
-*(À décrire : enregistrement d’un modèle, insertion dans un board, publication dans Community, import depuis Community.)*
+- Enregistrement : sélection d’un item/sous-arbre → sérialisation + métadonnées + options (inclure actions/règles, dates relatives).
+- Insertion : choix du container cible → remap `nodeId` + application des offsets de dates → actions/règles insérées **désactivées** par défaut → log Activity.
+- Publication : passage par le pipeline Community (expurgation, génération d’un `publicId`).
+- Import depuis Community : instanciation identique à l’insertion locale, avec actions/règles désactivées tant que l’admin ne les active pas.
 
 ## Questions ouvertes / risques
 
-*(À lister : complexité des mises à jour de modèles, gestion des IDs et des liens lors de l’instanciation, sécurité des modèles publics.)*
-
+- Gestion de la compatibilité des modèles avec des packs privés/licenciés.
+- Taille des modèles complexes (sous-arbres profonds).
+- Évolution du format si on introduit un “modèle lié” (non prévu en V1).
diff --git a/design-evolution/09-activity/functional.md b/design-evolution/09-activity/functional.md
index e73b0f8..ec164bb 100644
--- a/design-evolution/09-activity/functional.md
+++ b/design-evolution/09-activity/functional.md
@@ -83,6 +83,7 @@ Activity doit fournir :
 
 - L’activité visible pour un utilisateur ne doit montrer que :
   - les événements qui concernent des items qu’il a le droit de voir,
+  - et masquer toute référence aux items invisibles (pas de fuite de contenu ni de compteur d’items masqués) ; si un item est partiellement visible, seules les parties autorisées sont montrées.
   - des détails en cohérence avec ses permissions (pas d’infos cachées révélées par le journal).
 - Le moteur Activity conserve un journal interne complet, mais chaque vue (board, utilisateur, item)
   est une **projection filtrée** selon Teams :
@@ -94,6 +95,7 @@ Activity doit fournir :
 - L’activité doit rester lisible :
   - regroupements par période,
   - résumés, possibilité de “déplier” pour voir le détail.
+  - l’UI PEUT regrouper plusieurs événements homogènes sur un même item et une fenêtre courte en un résumé, avec détail déroulable.
 
 ### 4.3. Performances
 
@@ -110,3 +112,51 @@ Activity doit fournir :
   - certaines entrées du journal concernent les actions/règles exécutées, utile pour le débogage.
 - **Avec Community** :
   - certaines actions (publication, contributions) apparaissent aussi dans l’activité.
+
+---
+
+## 6. Décisions fonctionnelles détaillées
+
+### 6.1. Taxonomie des événements
+
+- Chaque entrée Activity appartient à une taxonomie stricte `kind.subkind` avec champs obligatoires par type (pas de texte libre) :
+  - `structure.move` (fromParent, toParent, positions), `structure.rename`, `structure.delete/create`.
+  - `state.change` (from, to), `deadline.set` (category, from, to), `progress.set` (from, to, max?).
+  - `relation.created/deleted` (from, to, kind).
+  - `interaction.run` (runId, status, actionsSuccess/Failed, reason).
+  - `logic.rule` (ruleId, status, budgetUsed/Limit, reason).
+  - `teams.roleChanged/invite/deny/grant`.
+  - `community.publish/import/fork/unpublish` (sourceBoardId/publicBoardId, targetBoardId).
+- Cette taxonomie alimente des messages templatisés côté UI (pas d’heuristique).
+
+### 6.2. Projection Teams (lecture)
+
+- Projection basée sur les droits **courants** du lecteur :
+  - si toutes les `nodeRefs` sont invisibles → événement masqué entièrement (aucun stub, aucun compteur caché).
+  - si mix visible/invisible → seules les références visibles sont montrées, sans mention du volume masqué.
+  - `actorId` invisible/supprimé → rendu générique (“hidden”/“externe”), sans fuite d’ID.
+  - payload redigé : suppression des champs sensibles (contenu, tags non visibles).
+- Deux utilisateurs peuvent voir des journaux différents pour un même board ; divergence assumée.
+
+### 6.3. Lisibilité & anti-bruit
+
+- Regroupements par jour/utilisateur/type + coalescing lecture sur fenêtre courte (ex. 60 s) pour les mises à jour répétées (`progress.set`, `state.change`).
+- Résumé “dépliable” pour voir le détail fusionné.
+- Pagination obligatoire ; horizon par défaut 90 jours configurable par board (requête au-delà → code explicite).
+
+### 6.4. Traçabilité des runs Interactions/Logique
+
+- Chaque run génère deux événements liés par `runId` :
+  - `run.start` (actor, contexte).
+  - `run.end` (status success/partial/failed, actionsSuccess, actionsFailed, budgetUsed/Limit, reason ou code de rollback).
+- Utile pour répondre “pourquoi cette action/règle ne s’est pas exécutée ?”.
+
+### 6.5. Community / Library
+
+- Les événements cross-board incluent toujours `sourceBoardId`/`publicBoardId` et `targetBoardId` (fork/import).
+- Les publications/imports/forks sont journalisés côté source et côté cible (quand le board existe), toujours filtrés par Teams.
+
+### 6.6. Exports / anonymisation
+
+- Export audit complet (JSONL) avec option `anonymizeActors=true` (pseudonymes stables par board).
+- Le journal persiste complet ; la projection et l’anonymisation d’export couvrent le besoin de confidentialité.
diff --git a/design-evolution/09-activity/technical.md b/design-evolution/09-activity/technical.md
index 84b7b6d..3f02aa6 100644
--- a/design-evolution/09-activity/technical.md
+++ b/design-evolution/09-activity/technical.md
@@ -1,22 +1,86 @@
 # 09-activity – Spécifications techniques
 
-## Concepts techniques clés
+## 1. Modèle d’événement
 
-*(À définir : modèle d’événement d’activité, lien avec les commandes / logs existants, granularité.)*
+- Entrée canonique :
 
-## Points d’intégration
+```json
+{
+  "id": "uuid",
+  "boardId": "123",
+  "actorId": "user-1",
+  "kind": "command",
+  "subkind": "structure.move",
+  "timestamp": 1736463600,
+  "nodeRefs": ["node-a", "node-b"],    // optionnel
+  "runId": "run-123",                  // optionnel (Interactions/Logic)
+  "status": "success|partial|failed",
+  "code": "STATE_CONFLICT",
+  "message": "Lisible",
+  "details": { "...": "..." }
+}
+```
 
-*(À recenser : CommandBus, CommandAuditLogger, tables d’audit, API d’exposition de l’historique.)*
+- `subkind` est strictement enuméré ; exemples et champs obligatoires :
+  - `structure.move` : `fromParent`, `toParent`, `fromPos`, `toPos`.
+  - `structure.rename` : `titleBefore`, `titleAfter`.
+  - `structure.create/delete` : `nodeId`, `parentId`, `position`.
+  - `state.change` : `from`, `to`.
+  - `progress.set` : `from`, `to`, `max?`.
+  - `deadline.set` : `category`, `from`, `to`.
+  - `relation.created/deleted` : `from`, `to`, `kind`.
+  - `interaction.run` : `runId`, `actionId`, `status`, `actionsSuccess`, `actionsFailed`, `reason`, `budgetUsed/Limit`.
+  - `logic.rule` : `ruleId`, `status`, `actionsSuccess`, `actionsFailed`, `reason`, `budgetUsed/Limit`.
+  - `teams.roleChanged/invite/deny/grant` : infos rôle/scope.
+  - `community.publish/import/fork/unpublish` : `sourceBoardId`, `publicBoardId?`, `targetBoardId?`.
+- Chaque `subkind` DOIT respecter ce contrat minimal de champs dans `details` ; les consommateurs peuvent se baser dessus sans heuristique.
+- `nodeRefs` liste les nodes concernés (pour filtrage ciblé).
+- `runId` relie les événements d’un même run Interactions/Logique.
 
-## Structures de données
+## 2. Filtrage par Teams (projection)
 
-*(À figer : schémas des entrées d’activité (boardId, userId, type, payload, timestamps…), index pour la recherche.)*
+- Projection basée sur les droits **courants** du lecteur :
+  - événements touchant uniquement des nodes invisibles → masqués totalement (aucun stub, aucun compteur “caché”),
+  - mix visible/invisible → seules les références visibles sont projetées, sans mention de volume masqué,
+  - `actorId` invisible/supprimé → rendu générique (pseudonyme “hidden”), pas de fuite d’ID,
+  - redaction des champs sensibles (contenu, tags non visibles) dans `details`.
+- Les journaux peuvent diverger entre utilisateurs.
+- La réponse API PEUT porter :
+  - un flag `partial: true` si la projection ou la rétention ont supprimé des événements pour le lecteur,
+  - un tableau optionnel `partialReasons: ["permissions","retention", ...]` pour le debug/admin, sans révéler combien ni quels événements manquent.
 
-## Flux types
+## 3. Lisibilité / anti-bruit
 
-*(À décrire : enregistrement d’un événement d’activité lors d’une commande, récupération filtrée pour un board / user / item.)*
+- Regroupements par jour/utilisateur/type ; coalescing lecture sur fenêtre courte (ex. 60s) pour `progress.set`, `state.change` répétés sur le même node.
+- Résumé “replié” par défaut, avec détail déroulable.
+- Pagination obligatoire ; horizon par défaut 90 jours configurable par board (requête au-delà → code explicite).
+ - Le back ne coalesce pas les entrées stockées ; il fournit `timestamp`, `nodeRefs`, `kind/subkind` pour permettre un regroupement côté UI.
 
-## Questions ouvertes / risques
+## 4. Points d’intégration
 
-*(À lister : volume de données, politique de rétention, anonymisation éventuelle pour les exports / partages.)*
+- **CommandBus** : chaque commande logge un événement (succès ou échec) selon la taxonomie.
+- **Interactions/Logic** : chaque run logge un `interaction.run` / `logic.rule` avec `runId`, stats de succès/échec, budget consommé/dépassement.
+- **Teams** : invitations/changes de rôle/deny/grant loggés.
+- **Community/Library** : publication, fork/import, retrait loggés avec `sourceBoardId`/`publicBoardId`/`targetBoardId` quand applicable.
+- Visibilité cross-board : le détail d’un événement Community/Library n’est visible qu’aux utilisateurs disposant des capabilities adéquates (ex. `manage-community`) ; sinon un message générique est projeté.
+- **Scheduler** : actions automatisées loggées avec actor “system”/“scheduler” mais toujours projetées via Teams.
 
+## 5. Structures de persistance (suggestion)
+
+- Table `activity` avec colonnes normalisées : `id`, `boardId`, `actorId`, `kind`, `subkind`, `timestamp`, `runId`, `status`, `code`, `message`, `details`, `nodeRefs`.
+- Index : `boardId+timestamp`, `actorId`, `kind`, `runId`, GIN/BTREE sur `nodeRefs` (ou table de jonction si SGBD l’exige).
+- API de lecture : filtres `boardId`, `actorId`, `nodeId`, `kind/subkind`, plage temporelle ; pagination.
+
+## 6. Flux types
+
+- **Commande utilisateur** : avant Apply → audit minimal ; après Apply → event `command.<subkind>` success/failed.
+- **Run Interactions atomic** : `interaction.run.start` puis `interaction.run.end` avec liste des effets (succès/échec) + `runId`.
+- **Règle Logique** : `logic.rule` après évaluation (actions appliquées, budget, raison d’échec).
+- **Teams** : `teams.roleChanged` lors d’un changement de rôle/scope.
+- **Publication** : `community.publish/import/fork/unpublish` aux actions correspondantes.
+
+## 7. Rétention / export / risques
+
+- Horizon par défaut 90 jours (configurable par board) ; les réponses peuvent être tronquées par rétention (voir `partial/partialReasons`).
+- Export audit : JSONL complet, option `anonymizeActors=true` (pseudonymes stables par board, pseudonymisation et non anonymisation forte).
+- Volume : surveiller taille de `details`; envisager archivage froid pour vieux événements.
diff --git a/design-evolution/ZZ-global-synthesis/functional.md b/design-evolution/ZZ-global-synthesis/functional.md
index 9dc9bbf..b2fa23e 100644
--- a/design-evolution/ZZ-global-synthesis/functional.md
+++ b/design-evolution/ZZ-global-synthesis/functional.md
@@ -5,17 +5,33 @@ Il servira de vue d’ensemble fonctionnelle consolidée.
 
 ## Principes globaux retenus
 
-*(À remplir : synthèse des décisions majeures sur IDs, adressage, container/leaf, tags, progression, relations, interactions, logique, droits, communauté.)*
+- Identité : adresse canonique `{ boardId, nodeId }`, `nodeId` = UUID global, isolation stricte intra-board en V1. `boardId` interne reste la référence, `publicBoardId` (UUID opaque) sert aux publications/templates. Le node racine est toujours `root`, non supprimable ni déplaçable.
+- Structure : `sys.shape` unique vérité (container/leaf), un leaf n’a jamais d’enfants, ordre strict. Aucun tag, hors `type/list` existant, ne peut muter `sys.shape`.
+- États : état principal obligatoire parmi `{ todo, doing, done, failed }` (exclusifs). `blocked` et `late` ne sont autorisés qu’avec `todo/doing` et sont retirés automatiquement à la transition vers `done/failed`. Combinaisons interdites rejetées (`done+blocked`, `done+failed`, etc.).
+- Progression : champs par item, `progressMax` borné (≤ 10 000). `progressMax = 0/null` = progression inconnue. Incohérence `eff = max` sans `done` signalée, jamais autocorrigée. Aucune agrégation par structure ; la seule agrégation V1 est une “readiness” = `min` des dépendances explicites.
+- Relations : toute relation avec sémantique de dépendance (`depends=true`, incluant `rel/depends-on` et `rel/blocks`) appartient au même DAG acyclique ; `rel/linked` reste hors DAG.
+- Droits : Teams est l’unique source de permissions. Aucun pack (Interactions, Logic, Community, Library, Activity) ne peut donner/retirer un droit effectif hors Teams.
+- Interactions vs Logique : Interactions = actions locales porteur-centrées, scopes bornés, atomicité V1 ; Logique = règles globales, politique de board, peut fournir des triggers supplémentaires. Priorités/overrides définies dans Logic.tech.
+- Publication : export/fork expurge Teams/assigned/données internes ; actions/règles publicables arrivent inactives et doivent être activées explicitement dans le board cible. Scheduler/logique désactivés par défaut à l’import.
+- Activity : journal filtré par Teams ; aucun événement n’est visible sans droit de lecture ; références invisibles masquées, pas de fuite de quantités ou de nombres d’items.
 
 ## Décisions structurantes
 
-*(À remplir : arbitrages entre stratégies possibles, conventions globales, points non négociables.)*
+- Commandes : toutes mutations via `POST /api/commands` (CommandBus/Arbitre/RulesEngine/Applier). Pas de flux REST mutants.
+- Packs MCC : déclaratifs (tags/datasets/règles/slots UI), pas d’API back custom.
+- Atomicité Interactions V1 : commande `RunAtomicAction` obligatoire ; best-effort en option avancée seulement.
+- Acyclicité : structure parent/enfant et `rel/depends-on` (et relations porteuses de dépendance flaggées) doivent rester acycliques.
 
 ## Contrats transverses
 
-*(À remplir : contrats entre systèmes (qui a le droit de modifier quoi), règles d’or, invariants globaux.)*
+- Sélection universelle : service unique, prévisualisation obligatoire. Pour Interactions/Logique, la sélection est recalculée côté back au run ; si 0 cible ou cible non éditable → échec global. Pour les actions ponctuelles UI, best-effort avec avertissements. Sélection vide = exécution désactivée.
+- Tags : préfixes réservés (`state/`, `rel/`, `resource/`, `type/`, `assigned/`, `sys/`, `event/`, `team/`…) interdits pour les tags utilisateur. Registre central unique des tags système.
+- Progression/états : incohérences signalées (ex. eff=max sans `done`), jamais autocorrigées silencieusement. États invalides refusés avec code explicite.
+- Permissions dans les runs automatiques : acteur = déclencheur ; chaque effet vérifié via Teams ; pas de bypass “système”. Interactions/Logique exécutées en mode atomique (tout ou rien). Pas de création d’actions planifiées en Interactions V1.
+- Anti-boucles : budget de cascade (profondeur/effets) et mémo des règles/actions déjà appliquées dans la même cascade ; en cas de dépassement, la cascade est arrêtée et journalisée.
 
 ## Plan de mise en œuvre fonctionnel
 
-*(À remplir : ordre logique d’activation des packs, conditions pour considérer une phase « terminée » fonctionnellement.)*
-
+- Fondations verrouillées (IDs, sélection, tags, temps).
+- Packs métiers : Gestion (états/échéances/progression/ressources) → Relations → Interactions (atomicité V1) → Logic → Teams → Community/Library → Activity.
+- Clôturer chaque pack fonctionnel avant d’entrer en technique ; maintenir ce document à jour en cas de décision transversale.
diff --git a/design-evolution/ZZ-global-synthesis/technical.md b/design-evolution/ZZ-global-synthesis/technical.md
index 4847143..bef8dd3 100644
--- a/design-evolution/ZZ-global-synthesis/technical.md
+++ b/design-evolution/ZZ-global-synthesis/technical.md
@@ -4,17 +4,70 @@ Ce document fige les choix techniques finaux après relecture croisée de tous l
 
 ## Décisions techniques clés
 
-*(À remplir : format des adresses, stockage des relations, représentation des actions/règles, modèle de permissions, etc.)*
+- **Identifiants & adresses**  
+  - `boardId` interne (id existant) reste la clé métier ; `publicBoardId` (UUID opaque) pour Community/Library.  
+  - Adresse canonique d’un node : `{ boardId, nodeId }`. Isolation stricte intra-board V1 (aucune commande multi-board).  
+  - Node racine : `root` constant, non supprimable ni déplaçable.
+
+- **Structure & tags système**  
+  - `sys.shape` seule vérité structurelle (`container`/`leaf`), aucun enfant pour un `leaf`.  
+  - Seul le réacteur `type/list` peut muter `sys.shape`; tout autre tag “structurel” est refusé.  
+  - Registre global des tags système ; préfixes réservés bloqués côté back si non déclarés.
+
+- **États & progression**  
+  - État principal obligatoire `{ todo, doing, done, failed }` exclusifs. Flags `blocked/late` autorisés seulement avec `todo/doing`; transition vers `done/failed` supprime automatiquement ces flags. Combinaisons interdites rejetées (`STATE_COMBINATION_INVALID`).  
+  - Progression : `progressMax ∈ [0, 10_000]`, `progressCurrent ∈ [0, progressMax]`; `max=0/null` = progression inconnue. Rescale ratio (round + clamp) lors d’un changement de `max`.  
+  - Agrégation V1 = readiness fonctionnelle : `min` des dépendances (`depends=true`). Aucun calcul par structure.
+
+- **Relations**  
+  - Chaque type déclare `depends: boolean`. Toutes les relations `depends=true` (dont `rel/depends-on` et `rel/blocks`) appartiennent au même DAG acyclique ; création rejetée en cas de cycle.  
+  - `rel/linked` (symétrique) hors DAG ; stockage unique, refus du miroir.  
+  - Relations auto (liste suivie) taguées `source=auto-list/<containerId>` ; recalcul sur DnD (debounce), suppression auto si enfant supprimé ; sanity job supprime seulement l’auto invalide et journalise les manuelles invalides.
+
+- **Sélection & atomicité**  
+  - Service UI de sélection : prévisualisation, critères persistés, pas les résultats.  
+  - Interactions/Logic : sélection recalculée back au run ; 0 cible ou cible non éditable → 422/409, aucun effet (tout ou rien).  
+  - Actions UI ponctuelles : best-effort (ignore cibles disparues ou non éditables) + avertissements.  
+  - Commandes atomiques utilisent la version de snapshot ; conflit de version → rejet ; support `idempotencyKey` (acteur + key) pour éviter les doublons réseau.
+
+- **Interactions / Logic**  
+  - Trigger Interactions V1 : transition `non-done → done` du porteur. Pas d’actions planifiées créées depuis Interactions V1.  
+  - Effets autorisés : create-item, update état/tags, set-progress, adjust-resource (non négatif), create/delete relation (`depends` acyclique). Effets interdits : mutation Teams, mutation Logic/packs, mutation cross-board.  
+  - Cascade guard : contexte global avec `maxDepth`, `maxEffects`, set `(rule/action, item, triggerSignature)` pour éviter les répétitions dans la même cascade.  
+  - Logic : règles customs après packs overridables ; conflit d’effets détectable (même trigger/scope/champ) → échec explicite, pas de last-wins implicite. Triggers supplémentaires exposables : progression (seuils), deadline, resource-below-threshold, relation added/removed.
+
+- **Permissions & visibilité**  
+  - Teams seule source de droits ; chaque effet vérifié côté back.  
+  - Activity filtrée : événements invisibles si aucun droit de lecture ; redaction des références invisibles, pas de fuite de quantités.
+
+- **Publication / import**  
+  - Fork/import : remap `boardId/nodeId`, actions/règles importées inactives par défaut, scheduler désactivé tant qu’il n’est pas explicitement activé.  
+  - Publication Community/Library : snapshot expurgé (Teams, assigned, données internes), actions/règles marquées publicables seulement, inactives à l’import.
 
 ## Contrats techniques transverses
 
-*(À remplir : qui a le droit de modifier quels champs, quelles couches peuvent connaître quels concepts, conventions communes.)*
+- Invariants noyau non overridables : acyclicité (`depends=true`), `leaf` sans enfants, états principaux exclusifs, ressources non négatives, bornes de progression.  
+- Hiérarchie : Invariants noyau > règles packs non override > règles packs override > règles Logic custom > configurations Interactions.  
+- Sélection : Interactions/Logic atomiques → recalcul back obligatoire ; commandes UI batch → best-effort consigné.  
+- Permissions : aucune mutation effective sans validation Teams ; Interactions/Logic ne modifient jamais Teams.  
+- Idempotence : réseau via `idempotencyKey`; métier via conditions explicites/flags dans les règles, pas via heuristique temporelle.  
+- Aucune relation ou état invalide ne doit être persisté (création refusée) ; sanity jobs ne suppriment que les artefacts auto.
 
 ## Plan d’implémentation
 
-*(À remplir : roadmap technique, ordre des chantiers, dépendances fortes, points de migration.)*
+- Fondations : root constant, registre de tags système, garde `sys.shape`, adresses `{boardId, nodeId}`, `publicBoardId`.  
+- Gestion : matrice d’états/flags, progression bornée + rescale, readiness=min, politique `late` (manual/eligible/auto).  
+- Relations : types avec `depends`, DAG acyclique, mode liste suivie, sanitation auto.  
+- Interactions V1 : RunAtomicAction, trigger done, effets autorisés, anti-boucles, sélection recalculée.  
+- Logic V1 : DSL MCC (triggers/conditions/actions), hiérarchie overrides, détection simple de conflits, triggers supplémentaires (progress, deadline, resource, relation).  
+- Teams : rôles/capabilities, denies > allows (sauf owner), safeguards (dernier owner), filtrage Activity/selection.  
+- Community/Library : publication expurgée, import/fork remap IDs, logique inactive par défaut, templates dates relatives.  
+- Activity : taxonomie fixée, runId pour runs d’actions/règles, filtrage par Teams, rétention configurable.
 
 ## Points de vigilance & risques résiduels
 
-*(À remplir : zones où la complexité restera élevée, risques acceptés, garde‑fous.)*
-
+- Conflits de règles Logic : détection statique limitée V1 (même trigger/scope/champ) → risque de collisions non détectées si conditions complexes.  
+- Sélection duale (best-effort UI vs échec global Interactions) : bien afficher les avertissements côté UI pour éviter l’incompréhension.  
+- Cap progression 10 000 : suffisant pour V1, mais surveiller les besoins “metrics” avant d’augmenter la borne.  
+- Sanity cycles : ne pas supprimer de relations manuelles automatiquement ; prévoir une UI de diagnostic pour aider les users.  
+- Publication : veiller à ne pas exposer d’artefacts de permissions ou d’actions non publicables ; checklist d’expurgation à automatiser.
-- 
2.43.0

