From 0008bf5832161c6204742a53343f674ef3cd6d98 Mon Sep 17 00:00:00 2001 From: Master Date: Thu, 9 Jul 2026 22:03:15 +0200 Subject: [PATCH] chore: outils preview, mesure, design system et Dockerfile --- SKILL_sliding_design_system.md | 469 ++++++++++++++++++++++++ build_gallery.py | 154 ++++++++ docker/preview/Dockerfile | 26 ++ docker/preview/preview_inner.sh | 68 ++++ index.html | 620 ++++++++++++++++++++++++++++++++ preview.sh | 53 +++ prompt_the_designer_v3.md | 151 ++++++++ 7 files changed, 1541 insertions(+) create mode 100644 SKILL_sliding_design_system.md create mode 100644 build_gallery.py create mode 100644 docker/preview/Dockerfile create mode 100644 docker/preview/preview_inner.sh create mode 100644 index.html create mode 100644 preview.sh create mode 100644 prompt_the_designer_v3.md diff --git a/SKILL_sliding_design_system.md b/SKILL_sliding_design_system.md new file mode 100644 index 0000000..662007c --- /dev/null +++ b/SKILL_sliding_design_system.md @@ -0,0 +1,469 @@ +# 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. diff --git a/build_gallery.py b/build_gallery.py new file mode 100644 index 0000000..17bb738 --- /dev/null +++ b/build_gallery.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +build_gallery.py — Génère la galerie HTML du design system v2 +depuis layouts_v2.yaml. Relancer après tout ajout de layout. +Usage : python3 build_gallery.py → produit index.html +""" +import yaml +from pathlib import Path +from datetime import datetime + +LAYOUTS = yaml.safe_load(open("layouts_v2.yaml", encoding="utf-8"))["layouts"] +THEME = yaml.safe_load(open("theme_v2.yaml", encoding="utf-8")) + +C = THEME["colors"] +NAVY = C["primary"]["navy"] +NAVY2 = C["primary"]["navy_light"] +CORAL = C["accent"]["coral"] +GLACIER = C["secondary"]["glacier"] +SLATE = C["secondary"]["slate"] +CARD = C["backgrounds"]["card"] + +# Familles regroupées dans l'ordre d'apparition +families = {} +for name, cfg in LAYOUTS.items(): + fam = cfg.get("famille", "Autres") + families.setdefault(fam, []).append((name, cfg)) + +n_layouts = len(LAYOUTS) +n_families = len(families) + +def card(name, cfg): + lid = cfg.get("id", "") + mode = cfg.get("mode", "light") + hint = " ".join(cfg.get("agent_hint", "").split()) + champs = ", ".join(cfg.get("champs", [])) + requis = ", ".join(cfg.get("champs_requis", [])) + mode_badge = { + "light": ("Clair", "#f4f1ec", NAVY), + "dark": ("Sombre", NAVY, "#ffffff"), + "panel": ("Panel", GLACIER, NAVY), + }.get(mode, ("Clair", "#f4f1ec", NAVY)) + return f""" +
+
+ {lid} + {mode_badge[0]} +
+

{name}

+

{hint}

+
+
Champs{champs}
+
Requis{requis}
+
+
""" + +sections = "" +for fam, items in families.items(): + cards = "\n".join(card(n, c) for n, c in items) + sections += f""" +
+
+
+
{len(items)} layout{'s' if len(items)>1 else ''}
+

{fam}

+
+
+
{cards}
+
""" + +palette = "".join( + f'
' + f'
{label}
' + f'
{hexv}
' + for label, hexv in [ + ("Navy", NAVY), ("Navy light", NAVY2), ("Coral", CORAL), + ("Glacier", GLACIER), ("Slate", SLATE), ("Card", CARD)]) + +html = f""" + + + + +Sliding Design System v2 — Pernod Ricard + + + + + +
+
Pernod Ricard · Data Governance
+

Sliding Design System v2

+

Catalogue des layouts disponibles dans le pipeline de génération automatique de présentations. Design system « PR Editorial » : navy dominant, accent corail, grille fixe et centrage vertical systématique.

+
+
Layouts{n_layouts}
+
Familles{n_families}
+
Version2.0
+
+
+
+
Palette
+

Charte chromatique

+
{palette}
+
+{sections} + + +""" + +Path("index.html").write_text(html, encoding="utf-8") +print(f"index.html généré — {n_layouts} layouts, {n_families} familles") diff --git a/docker/preview/Dockerfile b/docker/preview/Dockerfile new file mode 100644 index 0000000..2c5c193 --- /dev/null +++ b/docker/preview/Dockerfile @@ -0,0 +1,26 @@ +# Dockerfile — conteneur sliding-preview · Chantier C2 +# PPTX → PDF → PNG par slide, sur GrosseBertha (ARM64, DSM 7.3.2). +# Polices : Carlito/Caladea (métriquement compatibles Calibri/Cambria) +# installées dans l'image ; les TTF PR réelles peuvent être montées en +# volume sur /fonts (prioritaires, voir preview_inner.sh). +# +# Build (dossier docker/preview/, single-line) : +# docker build -t sliding-preview . + +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libreoffice-impress \ + poppler-utils \ + fontconfig \ + fonts-crosextra-carlito \ + fonts-crosextra-caladea \ + fonts-liberation \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY preview_inner.sh /usr/local/bin/preview_inner.sh +RUN chmod +x /usr/local/bin/preview_inner.sh + +ENTRYPOINT ["/usr/local/bin/preview_inner.sh"] diff --git a/docker/preview/preview_inner.sh b/docker/preview/preview_inner.sh new file mode 100644 index 0000000..7131edc --- /dev/null +++ b/docker/preview/preview_inner.sh @@ -0,0 +1,68 @@ +#!/bin/sh +# preview_inner.sh — exécuté DANS le conteneur sliding-preview · Chantier C2 +# Usage : preview_inner.sh /work/chemin/deck.pptx [dpi] +# Produit : /_previews/slide-NN.png + index.html +set -e + +PPTX="$1" +DPI="${2:-110}" + +if [ -z "$PPTX" ] || [ ! -f "$PPTX" ]; then + echo "preview_inner: fichier introuvable: $PPTX" >&2 + exit 1 +fi + +# Polices PR réelles montées en volume (prioritaires sur Carlito/Caladea) +if [ -d /fonts ]; then + mkdir -p /usr/local/share/fonts/custom + cp -f /fonts/*.ttf /fonts/*.TTF /fonts/*.otf \ + /usr/local/share/fonts/custom/ 2>/dev/null || true + fc-cache -f >/dev/null 2>&1 || true +fi + +BASE=$(basename "$PPTX" .pptx) +DIR=$(dirname "$PPTX") +OUT="$DIR/${BASE}_previews" +TMP=/tmp/lo +mkdir -p "$OUT" "$TMP" +rm -f "$OUT"/slide-*.png "$OUT/index.html" + +# 1. PPTX → PDF (profil LibreOffice jetable : pas de lock, RAM contenue) +echo "preview_inner: conversion PDF ($BASE)..." +soffice --headless --norestore \ + -env:UserInstallation=file:///tmp/louser \ + --convert-to pdf --outdir "$TMP" "$PPTX" >/dev/null + +PDF="$TMP/$BASE.pdf" +if [ ! -f "$PDF" ]; then + echo "preview_inner: la conversion PDF a échoué." >&2 + exit 2 +fi + +# 2. PDF → PNG par page +echo "preview_inner: rasterisation PNG (${DPI} dpi)..." +pdftoppm -png -r "$DPI" "$PDF" "$OUT/slide" + +# 3. Normalisation slide-N.png → slide-0N.png (decks < 10 slides) +for f in "$OUT"/slide-?.png; do + [ -f "$f" ] || continue + n=$(basename "$f") + mv "$f" "$OUT/slide-0${n#slide-}" +done + +# 4. Galerie index.html (consultable via File Station ou partage web) +{ + printf '%s\n' '' + printf '%s\n' "$BASE" + printf '%s\n' '' + printf '

%s

\n' "$BASE" + for f in "$OUT"/slide-*.png; do + n=$(basename "$f") + printf '
%s
\n' "$n" "$n" + done + printf '%s\n' '
' +} > "$OUT/index.html" + +rm -f "$PDF" +NB=$(ls "$OUT"/slide-*.png 2>/dev/null | wc -l | tr -d ' ') +echo "preview_inner: $NB slides -> $OUT" diff --git a/index.html b/index.html new file mode 100644 index 0000000..aa2caa4 --- /dev/null +++ b/index.html @@ -0,0 +1,620 @@ + + + + + +Sliding Design System v2 — Pernod Ricard + + + + + +
+
Pernod Ricard · Data Governance
+

Sliding Design System v2

+

Catalogue des layouts disponibles dans le pipeline de génération automatique de présentations. Design system « PR Editorial » : navy dominant, accent corail, grille fixe et centrage vertical systématique.

+
+
Layouts31
+
Familles18
+
Version2.0
+
+
+
+
Palette
+

Charte chromatique

+
Navy
#061033
Navy light
#10204D
Coral
#F4795B
Glacier
#8FA9D0
Slate
#46505A
Card
#F4F1EC
+
+ +
+
+
+
1 layout
+

Ouverture

+
+
+
+
+
+ L01 + Sombre +
+

cover_split

+

Slide de couverture. titre = titre de la présentation, sous_titre = tagline en une phrase.

+
+
Champstitre, sous_titre
+
Requistitre
+
+
+
+
+
+
+
1 layout
+

Synthèse

+
+
+
+
+
+ L05 + Clair +
+

executive_summary

+

Synthèse SCR. Titre = So What. 3 cartes pleine largeur : situation, complication, resolution (1-2 phrases chacune).

+
+
Champstitre, situation, complication, resolution
+
Requistitre, situation, complication, resolution
+
+
+
+
+
+
+
2 layouts
+

Structure

+
+
+
+
+
+ L03 + Sombre +
+

section_divider

+

Transition de section. titre = nom de la section. Le numéro est incrémenté automatiquement par le moteur.

+
+
Champstitre
+
Requistitre
+
+
+ +
+
+ L40 + Clair +
+

agenda

+

Sommaire du deck : à placer en slide 2 pour toute présentation de plus de 15 minutes. sections = liste de {label, numero?, duree?, actif?}, 2 à 8 entrées. actif: true met la section en corail (utile pour les rappels d'agenda en cours de deck). duree (ex "10 min") s'affiche à droite en discret.

+
+
Champstitre, sections
+
Requistitre, sections
+
+
+
+
+
+
+
6 layouts
+

Données

+
+
+
+
+
+ L10 + Clair +
+

big_stat

+

Un chiffre héro plein écran. valeur = le chiffre (ex "78%"), description = ce qu'il signifie, source = référence.

+
+
Champstitre, valeur, description, source
+
Requistitre, valeur
+
+
+ +
+
+ L09 + Clair +
+

kpi_grid

+

2 à 6 cartes KPI. items = [{label, valeur, description}]. valeur en grand corail, label en en-tête, description en source.

+
+
Champstitre, items
+
Requistitre, items
+
+
+ +
+
+ L42 + Clair +
+

bar_chart

+

Comparaison de valeurs par catégories — graphique NATIF éditable. Max 8 catégories × 3 séries. series = liste de {label, values} ; values = nombres SANS guillemets, alignés sur categories. horizontal: true pour des barres (libellés longs). unite (ex M€) et source optionnels. Couleurs imposées : navy, coral, glacier.

+
+
Champstitre, categories, series, unite, source, horizontal
+
Requistitre, categories, series
+
+
+ +
+
+ L43 + Clair +
+

line_chart

+

Évolution temporelle — graphique NATIF éditable. Max 12 points × 3 séries. points_x = libellés d'axe (mois, années...) ; series = {label, values}, nombres sans guillemets. Le dernier point de la première série est automatiquement mis en valeur (corail).

+
+
Champstitre, points_x, series, unite, source
+
Requistitre, points_x, series
+
+
+ +
+
+ L44 + Clair +
+

donut_split

+

Répartition d'un tout : anneau à gauche + légende détaillée à droite. 2 à 6 segments = {label, valeur} (nombres sans guillemets). valeur_centrale (optionnelle) s'affiche au centre de l'anneau (ex : total « 120 M€ »). Couleurs = cycle PR imposé.

+
+
Champstitre, segments, valeur_centrale, source
+
Requistitre, segments
+
+
+ +
+
+ L45 + Clair +
+

waterfall

+

Pont de valeur (waterfall) : expliquer un écart entre deux montants par des variations successives. depart et arrivee = {label, valeur} ; marches = liste de {label, delta} SIGNÉ (positif ou négatif, max 8). Le moteur calcule les cumuls — ne jamais fournir de cumul. Idéal pour : évolution de budget, pont d'effectifs, décomposition d'un résultat.

+
+
Champstitre, depart, marches, arrivee, unite, source
+
Requistitre, depart, marches, arrivee
+
+
+
+
+
+
+
3 layouts
+

Comparaison

+
+
+
+
+
+ L07 + Clair +
+

two_cols_text

+

Deux colonnes en cartes avec en-tête coloré. left/right = {titre, bullets[]}. Gauche = navy, droite = corail.

+
+
Champstitre, left, right
+
Requistitre, left, right
+
+
+ +
+
+ L34 + Clair +
+

comparison_table

+

Tableau structuré multi-critères. headers = liste de colonnes (1ère = critères). rows = [{label, values: []}] ou listes plates. Max 5 colonnes, 8 lignes.

+
+
Champstitre, headers, rows
+
Requistitre, headers, rows
+
+
+ +
+
+ L46 + Clair +
+

heatmap_table

+

Tableau à intensité : évaluer plusieurs items sur plusieurs critères. headers = colonnes (max 6) ; rows = {label, scores} avec score ENTIER de 0 (faible) à 4 (fort), max 8 lignes. Le moteur traduit chaque score en teinte de navy — aucune autre donnée. Idéal pour : maturité, couverture fonctionnelle, cartographie de risques.

+
+
Champstitre, headers, rows, legende
+
Requistitre, headers, rows
+
+
+
+
+
+
+
1 layout
+

Message

+
+
+
+
+
+ L08 + Sombre +
+

key_message

+

Message clé en citation plein écran. message = la phrase forte, detail = sous-texte optionnel.

+
+
Champsmessage, detail
+
Requismessage
+
+
+
+
+
+
+
2 layouts
+

Concept

+
+
+
+
+
+ L17 + Clair +
+

circular_diagram

+

3 à 6 valeurs en cercles + légende à droite. segments = [{label, description, couleur?}].

+
+
Champstitre, segments
+
Requistitre, segments
+
+
+ +
+
+ L41 + Clair +
+

pyramid

+

Argumentation pyramidale : la conclusion au sommet, les fondations à la base. niveaux = liste de {label, description?}, EXACTEMENT 3 ou 4 niveaux, du sommet vers la base. Largeurs d'étages fixes gérées par le moteur. Idéal pour : message clé et ses appuis, hiérarchie stratégie/tactiques/moyens.

+
+
Champstitre, niveaux
+
Requistitre, niveaux
+
+
+
+
+
+
+
1 layout
+

Texte structuré

+
+
+
+
+
+ L06 + Clair +
+

default_bullets

+

Liste de points clés. Si texte au format "Mot : explication", le moteur met le mot en gras navy. Max 5 bullets. bullets = [{niveau, texte}].

+
+
Champstitre, bullets
+
Requistitre, bullets
+
+
+
+
+
+
+
3 layouts
+

Process

+
+
+
+
+
+ L19 + Clair +
+

numbered_steps

+

Étapes en cartes pleine largeur avec badge rond numéroté. steps = [{numero, titre, description}].

+
+
Champstitre, steps
+
Requistitre, steps
+
+
+ +
+
+ L36 + Clair +
+

process_arrow

+

Flux horizontal de 3 à 6 étapes. steps = [{titre, description}]. Badges numérotés corail, couleurs cycle alternées. Max 6 étapes.

+
+
Champstitre, steps
+
Requistitre, steps
+
+
+ +
+
+ L47 + Clair +
+

funnel

+

Entonnoir de conversion : volumes décroissants d'étape en étape. etapes = {label, valeur, description?} du haut vers le bas, 3 à 5 étages. Largeurs proportionnelles aux valeurs (plancher de lisibilité), dernier étage corail. Idéal pour : pipeline commercial, adoption, qualification progressive.

+
+
Champstitre, etapes, source
+
Requistitre, etapes
+
+
+
+
+
+
+
2 layouts
+

Planning

+
+
+
+
+
+ L23 + Clair +
+

phases_timeline

+

Phases reliées par une ligne pointillée. phases = [{label, periode}]. Couleurs du cycle theme.

+
+
Champstitre, phases
+
Requistitre, phases
+
+
+ +
+
+ L32 + Clair +
+

gantt_timeline

+

Gantt par workstreams. periods = liste de labels (ex ["Juin","Juil"]). workstreams = [{label, tasks: [{label, start, end}]}]. start/end = index dans periods (0-based). Max 3 workstreams, 4 tâches chacun.

+
+
Champstitre, periods, workstreams
+
Requistitre, periods, workstreams
+
+
+
+
+
+
+
1 layout
+

Acteurs & décision

+
+
+
+
+
+ L28 + Panel +
+

recommendation_card

+

Carte de recommandation. Sidebar = numero + titre + cta. Corps = headline + bullets.

+
+
Champsnumero, titre, cta, headline, bullets
+
Requistitre, headline, bullets
+
+
+
+
+
+
+
1 layout
+

Clôture

+
+
+
+
+
+ L30 + Sombre +
+

end_slide

+

Slide de fin. message = phrase de conclusion.

+
+
Champsmessage
+
Requismessage
+
+
+
+
+
+
+
1 layout
+

Transformation

+
+
+
+
+
+ L31 + Clair +
+

from_to_pairs

+

Transformation avant/après en paires alignées. pairs = [{from, to}]. label_from/label_to = en-têtes colonnes. Max 5 paires. Idéal pour tangibiliser un changement.

+
+
Champstitre, pairs, label_from, label_to
+
Requistitre, pairs
+
+
+
+
+
+
+
1 layout
+

Historique

+
+
+
+
+
+ L33 + Clair +
+

yearly_timeline

+

Frise chronologique horizontale. milestones = [{annee, label, actif?}]. actif = true pour le jalon courant (corail). Labels alternent haut/bas. Max 6 jalons.

+
+
Champstitre, milestones
+
Requistitre, milestones
+
+
+
+
+
+
+
1 layout
+

Gouvernance

+
+
+
+
+
+ L35 + Clair +
+

raci_table

+

Matrice RACI. roles = liste de rôles. tasks = [{label, raci: [R/A/C/I]}]. R=Responsable(corail), A=Autorité(navy), C=Consulté(slate), I=Informé(muted). Max 4 rôles, 8 tâches.

+
+
Champstitre, roles, tasks
+
Requistitre, roles, tasks
+
+
+
+
+
+
+
1 layout
+

Organisation

+
+
+
+
+
+ L37 + Clair +
+

org_chart

+

Organigramme hiérarchique max 3 niveaux. root = {label, children: [{label, children?: [{label}]}]}. Max 4 enfants directs, 3 petits-enfants par enfant.

+
+
Champstitre, root
+
Requistitre, root
+
+
+
+
+
+
+
1 layout
+

Priorisation

+
+
+
+
+
+ L38 + Clair +
+

matrix_2x2

+

Matrice effort/impact. axis_x/axis_y = {label, low, high}. quadrants = {top_left, top_right, bottom_left, bottom_right}. items = [{label, x, y}] avec x/y de 0 à 100. Max 8 items.

+
+
Champstitre, axis_x, axis_y, quadrants, items
+
Requistitre, items
+
+
+
+
+
+
+
2 layouts
+

Visuel

+
+
+
+
+
+ L50 + Clair +
+

image_split

+

Image d'appui sur 40 % de la slide (side: left par défaut, right possible) + titre et points clés (max 4 bullets). À utiliser quand une image du dossier assets/ du projet illustre le propos ; image = nom de fichier exact tel que listé par /lire. legende (optionnelle) s'affiche sur un bandeau navy sous l'image.

+
+
Champstitre, image, bullets, side, legende
+
Requistitre, image, bullets
+
+
+ +
+
+ L51 + Sombre +
+

image_full

+

Ouverture de chapitre visuelle : image plein cadre + voile navy + titre display blanc. Alternative à section_divider quand un asset du projet s'y prête. image = nom de fichier exact de assets/.

+
+
Champstitre, image, sous_titre
+
Requistitre, image
+
+
+
+
+ Généré automatiquement depuis layouts_v2.yaml · 09/07/2026 · 31 layouts +
+ + \ No newline at end of file diff --git a/preview.sh b/preview.sh new file mode 100644 index 0000000..9a5d21d --- /dev/null +++ b/preview.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# preview.sh — wrapper hôte GrosseBertha · Chantier C2 +# Usage : ./preview.sh [dpi] +# Convertit le deck en PNG par slide via le conteneur sliding-preview. +# Sortie : /_previews/ (slide-NN.png + index.html) +# +# Prérequis : image construite (cd docker/preview && docker build -t +# sliding-preview .) et droits docker pour l'utilisateur (voir notes C2). +# +# Env optionnels : +# FONTS_DIR — dossier des TTF PR (défaut ./assets/fonts s'il existe) +# DOCKER_BIN — binaire docker (défaut docker) +# PREVIEW_MEM — limite RAM du conteneur (défaut 1200m — DS218 2 Go) + +PPTX="$1" +DPI="${2:-110}" +DOCKER_BIN="${DOCKER_BIN:-docker}" +PREVIEW_MEM="${PREVIEW_MEM:-1200m}" + +# Docker exige root sur ce NAS : s'auto-élever si besoin (C2) +if [ "$(id -u)" -ne 0 ]; then + exec sudo "$0" "$@" +fi + +if [ -z "$PPTX" ]; then + echo "usage: preview.sh [dpi]" >&2 + exit 1 +fi +if [ ! -f "$PPTX" ]; then + echo "preview: fichier introuvable: $PPTX" >&2 + exit 1 +fi + +# Chemins absolus (le dossier du pptx est monté sur /work) +WORK=$(cd "$(dirname "$PPTX")" && pwd) +NAME=$(basename "$PPTX") + +# Polices PR : défaut ./assets/fonts relatif au dossier de ce script +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +if [ -z "$FONTS_DIR" ] && [ -d "$SCRIPT_DIR/assets/fonts" ]; then + FONTS_DIR="$SCRIPT_DIR/assets/fonts" +fi + +FONT_MOUNT="" +if [ -n "$FONTS_DIR" ] && [ -d "$FONTS_DIR" ]; then + FONT_MOUNT="-v $FONTS_DIR:/fonts:ro" +fi + +exec "$DOCKER_BIN" run --rm \ + --memory "$PREVIEW_MEM" --memory-swap "$PREVIEW_MEM" \ + -v "$WORK:/work" \ + $FONT_MOUNT \ + sliding-preview "/work/$NAME" "$DPI" diff --git a/prompt_the_designer_v3.md b/prompt_the_designer_v3.md new file mode 100644 index 0000000..7dc0c06 --- /dev/null +++ b/prompt_the_designer_v3.md @@ -0,0 +1,151 @@ +# THE DESIGNER (mode annotation) +# Sliding Pipeline v3 — Pernod Ricard · Design System "PR Editorial" +# Mistral Large · Temperature 0.4 · Format : Markdown annoté + +## RÔLE + +Tu es The Designer. Tu reçois le Markdown narratif approuvé par Bastien et tu +le **réécris à l'identique en y ajoutant, sous chaque slide, une annotation +de layout**. Tu ne produis PAS un plan séparé : tu enrichis le Markdown lui-même. + +L'objectif : Bastien voit son contenu ET la structure visuelle proposée dans une +seule vue, et peut te donner du feedback dessus (« slide 4 plutôt en big_stat », +« regroupe 6 et 7 »). Une fois validé, ce Markdown annoté est transmis à +l'Encoder. + +Tu prends des décisions éditoriales : quel layout rend ce contenu le plus +lisible ? L'enchaînement est-il fluide ? Trop de slides texte d'affilée ? + +--- + +## CE QUE TU REÇOIS + +Un Markdown narratif : +- `#` = titre de la présentation +- `##` = sections +- `###` = slides avec leur contenu brut + +--- + +## CE QUE TU PRODUIS + +**Le même Markdown, repris intégralement, avec une ligne `@layout` ajoutée +juste sous chaque titre `###`** (et sous le `#` pour la couverture). + +Format de l'annotation : + +``` +### [Titre du slide — inchangé] +@layout: nom_du_layout +@note: justification courte du choix (1 phrase) +[contenu original du slide, inchangé] +``` + +Pour la couverture et la clôture, annote aussi : + +``` +# [Titre de la présentation] +@layout: cover_split +*[sous-titre original]* +``` + +À la toute fin, ajoute une ligne de clôture si elle manque : + +``` +## Clôture +### [Message de fin] +@layout: end_slide +``` + +**Règles :** +- Tu NE modifies PAS le texte narratif. Tu ajoutes seulement les lignes `@layout` et `@note`. +- Tu n'inventes pas de contenu. Si une slide manque d'un champ requis par le + layout choisi, tu l'indiques dans `@note` (ex : « @note: valeur chiffrée à fournir »). +- Le premier bloc est TOUJOURS `cover_split`, le dernier `end_slide`. +- Les `##` deviennent des `section_divider` si la présentation fait plus de 6 slides. + +--- + +## LES 21 LAYOUTS DISPONIBLES + +[CE BLOC EST GÉNÉRÉ AUTOMATIQUEMENT PAR prompt_injection_v2.py] +[NE PAS MODIFIER MANUELLEMENT] + +{{LAYOUTS_CATALOGUE}} + +--- + +## RÈGLES DE SÉQUENÇAGE + +[CE BLOC EST GÉNÉRÉ AUTOMATIQUEMENT PAR prompt_injection_v2.py] +[NE PAS MODIFIER MANUELLEMENT] + +{{SEQUENCING_RULES}} + +--- + +## PATTERNS NARRATIFS + +[CE BLOC EST GÉNÉRÉ AUTOMATIQUEMENT PAR prompt_injection_v2.py] +[NE PAS MODIFIER MANUELLEMENT] + +{{NARRATIVE_PATTERNS}} + +--- + +## GESTION DU FEEDBACK + +Quand Bastien te donne du feedback sur le Markdown annoté (« slide 5 en +two_cols_text », « ajoute un big_stat après la 3 »), tu renvoies le Markdown +annoté complet mis à jour, pas seulement la partie modifiée. + +--- + +## RÈGLES ABSOLUES + +- Tu utilises UNIQUEMENT les 21 layouts du catalogue. +- Tu reprends le Markdown INTÉGRALEMENT — aucune perte de contenu. +- Tu ajoutes UNIQUEMENT les lignes `@layout:` et `@note:`. +- Tu ne produis ni YAML, ni plan séparé, ni JSON. +- `cover_split` en premier, `end_slide` en dernier, toujours. + +--- + +## EXEMPLE + +**Entrée :** +```markdown +# Le télétravail chez Pernod Ricard +*Intégrer durablement le télétravail* + +## Pourquoi agir + +### Le télétravail est devenu un critère de choix décisif +78% des salariés en Europe le considèrent comme non négociable. Source à valider. + +### Nos concurrents ont déjà agi +Diageo et Bacardi ont lancé leurs programmes il y a 2 ans. +``` + +**Sortie :** +```markdown +# Le télétravail chez Pernod Ricard +@layout: cover_split +*Intégrer durablement le télétravail* + +## Pourquoi agir + +### Le télétravail est devenu un critère de choix décisif +@layout: big_stat +@note: un seul chiffre fort (78%) → big_stat plutôt que bullets +78% des salariés en Europe le considèrent comme non négociable. Source à valider. + +### Nos concurrents ont déjà agi +@layout: two_cols_text +@note: opposition Diageo / Bacardi → deux colonnes +Diageo et Bacardi ont lancé leurs programmes il y a 2 ans. + +## Clôture +### Le télétravail, une opportunité à saisir +@layout: end_slide +```