01629780f4
Code du systeme de memoire multi-LLM sur Trilium : - trilium_api.py : wrapper trilium-py (notes, labels, relations) - mcp_server.py : serveur MCP Starlette (19 tools, OAuth + Bearer) - api_context.py : API REST FastAPI - trilium_context.py : workflow CLI - watchdog.sh, start_*.sh : supervision et demarrage - skills, docs et ontologie associes Secrets (.env, oauth_state.json) exclus via .gitignore.
470 lines
14 KiB
Markdown
470 lines
14 KiB
Markdown
# SKILL — Sliding Design System (Pernod Ricard)
|
||
|
||
Ce skill décrit le **design system « PR Editorial »** et le format de données
|
||
que consomme le moteur de rendu `render_engine_v2.py` pour produire des
|
||
présentations PowerPoint au format Pernod Ricard.
|
||
|
||
**Périmètre de ce skill : design et production uniquement.** Il ne traite pas
|
||
de la structuration narrative, de la rédaction ou de la rhétorique. Il répond
|
||
à une seule question : *comment produire un fichier YAML valide qui, passé au
|
||
moteur, génère un PPTX conforme à la charte Pernod Ricard.*
|
||
|
||
---
|
||
|
||
## 1. Principe de fonctionnement
|
||
|
||
Le moteur prend en entrée un fichier **YAML** décrivant une liste de slides.
|
||
Chaque slide déclare un `layout` (parmi 21) et les champs de contenu de ce
|
||
layout. Le moteur applique automatiquement la charte (couleurs, polices,
|
||
grille, centrage vertical). Tu n'as jamais à spécifier de couleur, de police
|
||
ou de position en mode standard : tu fournis le contenu, le moteur compose.
|
||
|
||
Commande de rendu :
|
||
```bash
|
||
python3 render_engine_v2.py presentation.yaml sortie.pptx \
|
||
--theme theme_v2.yaml --components components_v2.yaml --layouts layouts_v2.yaml
|
||
```
|
||
|
||
Structure générale du YAML :
|
||
```yaml
|
||
slides:
|
||
- layout: cover_split
|
||
titre: "..."
|
||
- layout: kpi_grid
|
||
titre: "..."
|
||
items: [...]
|
||
```
|
||
|
||
---
|
||
|
||
## 2. La charte (appliquée automatiquement)
|
||
|
||
Tu n'écris jamais ces valeurs en mode standard ; elles sont là pour information.
|
||
|
||
**Couleurs**
|
||
| Token | Hex | Usage |
|
||
|---|---|---|
|
||
| navy | `#061033` | dominant — fonds sombres, titres |
|
||
| navy_light | `#10204D` | cercles décoratifs sur fond sombre |
|
||
| coral | `#F4795B` | accent UNIQUE — chiffres, badges, lignes |
|
||
| glacier | `#8FA9D0` | sous-titres sur fond sombre, 3e couleur |
|
||
| slate | `#46505A` | 2e couleur de cycle |
|
||
| card | `#F4F1EC` | fond des cartes (gris chaud) |
|
||
| card_alt | `#EAF0F8` | variante froide |
|
||
| body | `#2B3440` | texte courant sur fond clair |
|
||
| muted | `#8A93A0` | légendes, sources |
|
||
|
||
**Polices** : Cambria (titres, chiffres) / Calibri (corps).
|
||
**Format slide** : 33,87 × 19,05 cm (16:9).
|
||
**Règle d'accent** : le corail est rare. Un seul élément corail dominant par slide ; le navy domine.
|
||
**Rythme sandwich** : ouverture, transitions et clôture sur fond sombre (navy) ; contenu sur fond clair.
|
||
|
||
---
|
||
|
||
## 3. Les 21 layouts standards
|
||
|
||
Chaque layout liste ses champs **requis** (obligatoires) et **optionnels**.
|
||
`titre` doit être une formulation affirmative (le message du slide), pas un label.
|
||
|
||
### Ouverture / Clôture / Structure
|
||
|
||
**cover_split** — couverture (fond sombre)
|
||
Requis : `titre` · Optionnel : `sous_titre`
|
||
```yaml
|
||
- layout: cover_split
|
||
titre: "Titre de la présentation"
|
||
sous_titre: "Tagline en une phrase"
|
||
```
|
||
|
||
**section_divider** — transition de section (fond sombre, numéro auto)
|
||
Requis : `titre`
|
||
```yaml
|
||
- layout: section_divider
|
||
titre: "Nom de la section"
|
||
```
|
||
|
||
**end_slide** — clôture (fond sombre)
|
||
Requis : `message`
|
||
```yaml
|
||
- layout: end_slide
|
||
message: "Phrase de conclusion"
|
||
```
|
||
|
||
### Synthèse / Message
|
||
|
||
**executive_summary** — synthèse situation/complication/résolution
|
||
Requis : `titre, situation, complication, resolution`
|
||
```yaml
|
||
- layout: executive_summary
|
||
titre: "Le So What en une phrase affirmative"
|
||
situation: "État des lieux factuel"
|
||
complication: "Le problème ou la tension"
|
||
resolution: "La réponse proposée"
|
||
```
|
||
|
||
**key_message** — citation/message fort (fond sombre)
|
||
Requis : `message` · Optionnel : `detail`
|
||
```yaml
|
||
- layout: key_message
|
||
message: "Le message clé en une phrase forte."
|
||
detail: "Sous-texte optionnel."
|
||
```
|
||
|
||
### Données
|
||
|
||
**big_stat** — un chiffre héro plein écran
|
||
Requis : `titre, valeur` · Optionnel : `description, source`
|
||
```yaml
|
||
- layout: big_stat
|
||
titre: "Titre affirmatif"
|
||
valeur: "78%"
|
||
description: "ce que le chiffre signifie"
|
||
source: "Référence — 2026"
|
||
```
|
||
|
||
**kpi_grid** — 2 à 6 cartes KPI
|
||
Requis : `titre, items`
|
||
```yaml
|
||
- layout: kpi_grid
|
||
titre: "Titre affirmatif"
|
||
items:
|
||
- label: "Indicateur 1"
|
||
valeur: "+13%"
|
||
description: "Source ou contexte"
|
||
- label: "Indicateur 2"
|
||
valeur: "85%"
|
||
description: "Source ou contexte"
|
||
```
|
||
Note : `valeur` est une chaîne. Les valeurs courtes (≤6 car.) s'affichent en
|
||
très grand, les valeurs longues sont réduites automatiquement.
|
||
|
||
### Comparaison
|
||
|
||
**two_cols_text** — deux colonnes en cartes (gauche navy, droite corail)
|
||
Requis : `titre, left, right`
|
||
```yaml
|
||
- layout: two_cols_text
|
||
titre: "Titre affirmatif"
|
||
left:
|
||
titre: "Titre colonne gauche"
|
||
bullets:
|
||
- texte: "Premier point"
|
||
- texte: "Deuxième point"
|
||
right:
|
||
titre: "Titre colonne droite"
|
||
bullets:
|
||
- texte: "Premier point"
|
||
```
|
||
|
||
**comparison_table** — tableau comparatif multi-critères
|
||
Requis : `titre, headers, rows` (max ~5 colonnes, 8 lignes)
|
||
```yaml
|
||
- layout: comparison_table
|
||
titre: "Titre affirmatif"
|
||
headers: ["Critère", "Option A", "Option B"]
|
||
rows:
|
||
- label: "Premier critère"
|
||
values: ["Valeur A", "Valeur B"]
|
||
- label: "Deuxième critère"
|
||
values: ["Valeur A", "Valeur B"]
|
||
```
|
||
|
||
**from_to_pairs** — transformation avant/après
|
||
Requis : `titre, pairs` · Optionnel : `label_from, label_to` (max 5 paires)
|
||
```yaml
|
||
- layout: from_to_pairs
|
||
titre: "Titre affirmatif"
|
||
label_from: "SITUATION ACTUELLE"
|
||
label_to: "SITUATION CIBLE"
|
||
pairs:
|
||
- from: "État de départ"
|
||
to: "État cible"
|
||
- from: "Autre point"
|
||
to: "Autre cible"
|
||
```
|
||
|
||
### Concept / Texte
|
||
|
||
**circular_diagram** — 3 à 6 cercles + légende
|
||
Requis : `titre, segments`
|
||
```yaml
|
||
- layout: circular_diagram
|
||
titre: "Titre affirmatif"
|
||
segments:
|
||
- label: "Concept 1"
|
||
description: "Description courte"
|
||
- label: "Concept 2"
|
||
description: "Description courte"
|
||
- label: "Concept 3"
|
||
description: "Description courte"
|
||
```
|
||
|
||
**default_bullets** — liste de points (max 5)
|
||
Requis : `titre, bullets`
|
||
Le format « Mot-clé : explication » met le mot-clé en gras navy.
|
||
```yaml
|
||
- layout: default_bullets
|
||
titre: "Titre affirmatif"
|
||
bullets:
|
||
- texte: "Mot-clé : explication du point"
|
||
niveau: 1
|
||
- texte: "Autre mot-clé : explication"
|
||
niveau: 1
|
||
```
|
||
|
||
### Process / Planning
|
||
|
||
**numbered_steps** — étapes en cartes avec badge numéroté (2 à 5)
|
||
Requis : `titre, steps`
|
||
```yaml
|
||
- layout: numbered_steps
|
||
titre: "Titre affirmatif"
|
||
steps:
|
||
- numero: 1
|
||
titre: "Première étape"
|
||
description: "Ce que ça implique"
|
||
- numero: 2
|
||
titre: "Deuxième étape"
|
||
description: "Ce que ça implique"
|
||
```
|
||
|
||
**process_arrow** — flux horizontal de 3 à 6 étapes (sans dates)
|
||
Requis : `titre, steps`
|
||
```yaml
|
||
- layout: process_arrow
|
||
titre: "Titre affirmatif"
|
||
steps:
|
||
- titre: "Étape 1"
|
||
description: "Ce qui se passe"
|
||
- titre: "Étape 2"
|
||
description: "Ce qui se passe"
|
||
- titre: "Étape 3"
|
||
description: "Ce qui se passe"
|
||
```
|
||
|
||
**phases_timeline** — phases avec périodes
|
||
Requis : `titre, phases`
|
||
```yaml
|
||
- layout: phases_timeline
|
||
titre: "Titre affirmatif"
|
||
phases:
|
||
- label: "Mois 1-2"
|
||
periode: "Ce qui se passe"
|
||
- label: "Mois 3-8"
|
||
periode: "Ce qui se passe"
|
||
```
|
||
|
||
**gantt_timeline** — Gantt par workstreams
|
||
Requis : `titre, periods, workstreams` (max 3 workstreams, 4 tâches chacun)
|
||
`start`/`end` = index dans `periods` (0-based).
|
||
```yaml
|
||
- layout: gantt_timeline
|
||
titre: "Titre affirmatif"
|
||
periods: ["Juin", "Juil", "Août", "Sept"]
|
||
workstreams:
|
||
- label: "Workstream 1"
|
||
tasks:
|
||
- label: "Tâche A"
|
||
start: 0
|
||
end: 2
|
||
- label: "Workstream 2"
|
||
tasks:
|
||
- label: "Tâche B"
|
||
start: 1
|
||
end: 3
|
||
```
|
||
|
||
**yearly_timeline** — frise chronologique
|
||
Requis : `titre, milestones` (max 6, `actif: true` met le jalon en corail)
|
||
```yaml
|
||
- layout: yearly_timeline
|
||
titre: "Titre affirmatif"
|
||
milestones:
|
||
- annee: "2024"
|
||
label: "Premier jalon"
|
||
- annee: "2025"
|
||
label: "Deuxième jalon"
|
||
- annee: "2026"
|
||
label: "Jalon courant"
|
||
actif: true
|
||
```
|
||
|
||
### Gouvernance / Organisation / Décision
|
||
|
||
**raci_table** — matrice RACI
|
||
Requis : `titre, roles, tasks` (max 4 rôles, 8 tâches)
|
||
Lettres : R (Responsable, corail), A (Autorité, navy), C (Consulté, slate), I (Informé, muted).
|
||
```yaml
|
||
- layout: raci_table
|
||
titre: "Titre affirmatif"
|
||
roles: ["Rôle 1", "Rôle 2", "Rôle 3"]
|
||
tasks:
|
||
- label: "Première activité"
|
||
raci: ["A", "R", "C"]
|
||
- label: "Deuxième activité"
|
||
raci: ["A", "I", "R"]
|
||
```
|
||
|
||
**org_chart** — organigramme (max 3 niveaux)
|
||
Requis : `titre, root`
|
||
Les `children` peuvent être des objets `{label, children}` OU de simples
|
||
chaînes. Max 4 enfants directs, 3 petits-enfants par enfant (au-delà, ça serre).
|
||
```yaml
|
||
- layout: org_chart
|
||
titre: "Titre affirmatif"
|
||
root:
|
||
label: "Responsable racine"
|
||
children:
|
||
- label: "Manager 1"
|
||
children:
|
||
- "Équipe A"
|
||
- "Équipe B"
|
||
- label: "Manager 2"
|
||
children:
|
||
- "Équipe C"
|
||
```
|
||
|
||
**matrix_2x2** — matrice effort/impact
|
||
Requis : `titre, items` · Optionnel : `axis_x, axis_y, quadrants` (max 8 items)
|
||
`x` et `y` vont de 0 à 100.
|
||
```yaml
|
||
- layout: matrix_2x2
|
||
titre: "Titre affirmatif"
|
||
axis_x:
|
||
label: "Effort"
|
||
low: "Faible"
|
||
high: "Élevé"
|
||
axis_y:
|
||
label: "Impact"
|
||
low: "Faible"
|
||
high: "Élevé"
|
||
quadrants:
|
||
top_left: "Gains rapides"
|
||
top_right: "Projets stratégiques"
|
||
bottom_left: "Déprioritiser"
|
||
bottom_right: "À planifier"
|
||
items:
|
||
- label: "Initiative A"
|
||
x: 30
|
||
y: 80
|
||
- label: "Initiative B"
|
||
x: 70
|
||
y: 75
|
||
```
|
||
|
||
**recommendation_card** — carte de recommandation (sidebar navy)
|
||
Requis : `titre, headline, bullets` · Optionnel : `numero, cta`
|
||
```yaml
|
||
- layout: recommendation_card
|
||
numero: 1
|
||
titre: "Nom court de la recommandation"
|
||
headline: "TROIS DÉCISIONS À PRENDRE MAINTENANT"
|
||
cta: "Décider en réunion du 30 juin"
|
||
bullets:
|
||
- texte: "Première décision précise"
|
||
- texte: "Deuxième décision précise"
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Le flux libre (freeform) — composition sur mesure
|
||
|
||
Pour les slides qui ne rentrent dans aucun layout standard, utilise
|
||
`layout: freeform`. La slide est composée de **blocs positionnés sur une
|
||
grille 12 × 12** (colonnes 0-12, lignes 0-12). La charte reste **imposée** :
|
||
les couleurs ne peuvent être que des tokens nommés (jamais de hex).
|
||
|
||
Règles de la grille :
|
||
- `col` (0-12) = colonne de départ, `row` (0-12) = ligne de départ
|
||
- `w` = largeur en colonnes, `h` = hauteur en lignes
|
||
- Contraintes : `col + w ≤ 12` et `row + h ≤ 12`
|
||
- Maximum 8 blocs par slide
|
||
- `mode: light` (fond blanc) ou `mode: dark` (fond navy)
|
||
- `footer: false` pour masquer le pied de page (affiché par défaut, même sur fond sombre)
|
||
|
||
Note : `freeform` est géré directement par le moteur de rendu et ne figure pas
|
||
dans `layouts_v2.yaml`. Un validateur basé sur ce fichier peut donc le signaler
|
||
comme « layout inconnu » — c'est sans effet, le rendu fonctionne normalement.
|
||
|
||
Types de blocs disponibles :
|
||
| type | description | champs spécifiques |
|
||
|---|---|---|
|
||
| `title` / `heading` | titre serif | `size` (déf. 28), `align`, `color` |
|
||
| `text` | texte courant (Calibri) | `size`, `bold`, `italic`, `serif`, `align`, `color` |
|
||
| `stat` | grand chiffre serif corail | `size` (déf. 72), `align`, `color` |
|
||
| `circle` | cercle plein (motif charte) | `color` (diamètre = min(w,h)) |
|
||
| `badge` | cercle numéroté, texte blanc centré | `text`, `color` |
|
||
| `card` | carte arrondie avec ombre | `color` (déf. card) |
|
||
| `rect` | rectangle plein | `color`, `rounded` |
|
||
| `line` | ligne / séparateur | `color`, `weight` (h:0 = horizontale) |
|
||
|
||
Tokens couleur autorisés : `navy, navy_light, coral, glacier, slate, card,
|
||
white, body, muted`. Aucun hex.
|
||
|
||
Exemple — slide manifeste (fond sombre, grand chiffre + titre + accent) :
|
||
```yaml
|
||
- layout: freeform
|
||
mode: dark
|
||
blocks:
|
||
- type: stat
|
||
text: "3"
|
||
col: 0.5
|
||
row: 1
|
||
w: 3
|
||
h: 4
|
||
size: 150
|
||
color: coral
|
||
align: center
|
||
- type: title
|
||
text: "trois convictions structurantes"
|
||
col: 4
|
||
row: 1.5
|
||
w: 7.5
|
||
h: 3
|
||
size: 30
|
||
color: white
|
||
- type: line
|
||
col: 4
|
||
row: 4.5
|
||
w: 7
|
||
h: 0
|
||
color: coral
|
||
weight: 2
|
||
- type: text
|
||
text: "Le sous-texte en glacier, italique."
|
||
col: 4
|
||
row: 5
|
||
w: 7.5
|
||
h: 2
|
||
size: 18
|
||
italic: true
|
||
color: glacier
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Règles de production (à respecter pour un YAML valide)
|
||
|
||
1. **Layouts** : utiliser uniquement les 21 noms listés (+ `freeform`).
|
||
2. **Champs requis** : chaque layout doit avoir tous ses champs requis, non vides.
|
||
3. **Chaînes** : toujours entre guillemets. Échapper les guillemets internes.
|
||
4. **Chiffres de contenu** (`valeur`, `stat`) : toujours des chaînes (`"78%"`).
|
||
5. **Entiers de structure** (`numero`, `niveau`, `start`, `end`, `x`, `y`) : sans guillemets.
|
||
6. **`titre`** : formulation affirmative (le message), jamais un label thématique.
|
||
7. **Pas de syntaxe Markdown** dans les valeurs : pas de `**gras**`, pas de `#`.
|
||
Le formatage est géré par le moteur, pas par le texte.
|
||
8. **Champ optionnel absent** : l'omettre (ne pas mettre `null`).
|
||
9. **Freeform** : respecter `col+w ≤ 12`, `row+h ≤ 12`, max 8 blocs, tokens charte uniquement.
|
||
10. **Densité** : respecter les maxima par layout (ex. kpi_grid ≤ 6, bullets ≤ 5,
|
||
org_chart ≤ 4 branches). Au-delà, le rendu se dégrade.
|
||
|
||
---
|
||
|
||
## 6. Sortie attendue
|
||
|
||
Quand on te demande de produire une présentation au format Pernod Ricard,
|
||
tu produis **uniquement le YAML** décrit ci-dessus — rien d'autre. Ce YAML
|
||
est destiné à être passé tel quel à `render_engine_v2.py`. Pas de texte
|
||
d'introduction, pas de commentaire, pas de Markdown autour : le YAML brut,
|
||
directement exploitable.
|