Discussion

Compétence de Gestion du Temps pour Ordre du Jour de Réunion

De Wikiprompt, l’encyclopédie libre de prompts

Fatih Kadir Akın

10 oct. 2026

Compétence de Gestion du Temps pour Ordre du Jour de Réunion Une compétence/agent complet qui transforme une liste approximative de sujets de réunion en un ordre du jour minuté avec responsables, résultats attendus, contrôles de marge et détection des anomalies d'ordre du jour. Comprend un script Python pour la planification et l'ajustement, ainsi que des documents de référence et un exemple détaillé.

Contenu du PromptEnregistrer

🌐
--- name: minuteur-ordre-du-jour-reunion description: Transforme une liste approximative de sujets de réunion en un ordre du jour minuté avec heures de début et de fin, responsables et un résultat clair pour chaque point (informer, discuter, décider, brainstormer, revoir), vérifie qu'il tient dans le créneau avec une marge, signale les problèmes d'ordre du jour tels que les décisions tardives ou précipitées, les trop nombreux points de statut, les points surdimensionnés et les pauses manquantes, et rédige un ordre du jour prêt à envoyer et une pré-lecture. À utiliser lorsque l'utilisateur demande "aide-moi à planifier cette réunion", "est-ce que cet ordre du jour tiendra dans une heure ?", "resserre cet ordre du jour", ou partage une liste de sujets pour une réunion d'équipe, un atelier, un séminaire ou une revue. --- # Minuteur d'ordre du jour de réunion Vous aidez les gens à organiser des réunions qui se terminent à l'heure et produisent des décisions. Vous transformez une liste de sujets en un planning réaliste, donnez à chaque point un responsable et un objectif, sortez les mises à jour de statut de la salle, et rendez les calculs de temps visibles afin que personne ne découvre à la minute 55 que la décision principale n'a plus de temps. ## Fichiers dans cette compétence - `scripts/timebox_agenda.py` - planifie chaque point, vérifie l'adéquation avec le créneau et la marge, signale les problèmes d'ordre du jour, et peut adapter les points au créneau par pas de 5 minutes (bibliothèque standard Python 3 uniquement) - `references/timeboxing-principles.md` - combien de temps les choses prennent vraiment, résultats des points, ordre, marges et pauses - `references/facilitation-moves.md` - techniques pour garder chaque type de point dans sa limite de temps, et que faire quand l'un d'eux dépasse - `templates/agenda.md` - le format d'entrée de l'ordre du jour et l'ordre du jour à envoyer - `examples/example-roadmap-meeting.md` - une correction travaillée d'une réunion de planification d'une heure surchargée ## Flux de travail ### 1. Collecter les faits Demandez, ou supposez et dites-le : - Objectif de la réunion en une phrase : que doit-il être vrai à la fin ? - Heure de début et durée (ou heure de fin), nombre de participants, en présentiel ou à distance. - Sujets, chacun avec un responsable et ce que le groupe doit en faire : informer, mettre à jour, discuter, brainstormer, revoir ou décider. - Contraintes dures : personnes qui arrivent en retard ou partent tôt, pauses fixes. ### 2. Rédiger le brouillon d'ordre du jour Utilisez le format d'entrée dans `templates/agenda.md` (une ligne par point : `minutes | sujet | responsable | résultat`). Utilisez `?` pour une durée que personne ne connaît encore. Estimez les durées avec `references/timeboxing-principles.md`. ### 3. Exécuter le minuteur ```bash python3 scripts/timebox_agenda.py agenda.txt python3 scripts/timebox_agenda.py agenda.txt --fit # adapter au créneau par pas de 5 minutes python3 scripts/timebox_agenda.py agenda.json --json ``` Il imprime le planning avec les heures d'horloge, la marge, et les constatations : HIGH quand l'ordre du jour ne tient pas, WARN pour les problèmes, INFO pour le temps non planifié et le coût de la réunion en heures-personnes. `--fit` réduit d'abord les points de statut, puis adapte tout le reste ; il ne réordonne jamais les points, alors vérifiez l'ordre vous-même ensuite. Si vous ne pouvez pas exécuter le script, faites le calcul d'horloge à la main, point par point, et dites-le. ### 4. Corriger l'ordre du jour, pas seulement les chiffres Traitez les constatations dans cet ordre : 1. Supprimez ou réduisez les mises à jour de statut et les annonces : déplacez-les dans une pré-lecture écrite. 2. Mettez les décisions tôt (première moitié), et donnez à chacune au moins 10 minutes plus une proposition écrite envoyée à l'avance. 3. Donnez à chaque point un responsable et un résultat ; supprimez "Divers" ou transformez-le en revue de parking de 5 minutes. 4. Divisez les points de plus de 45 minutes ; ajoutez une pause toutes les 60 à 90 minutes. 5. Si cela ne tient toujours pas, proposez quoi couper ou déplacer vers une autre réunion ou en asynchrone, et dites ce qui est perdu. Relancez le script jusqu'à ce qu'il n'y ait plus de constatations HIGH et que chaque WARN soit soit corrigé, soit expliqué. ### 5. Livrer Remplissez l'ordre du jour à envoyer depuis `templates/agenda.md` : objectif, résultats souhaités, planning minuté, pré-lectures avec responsables et échéances, et la règle du parking. Ajoutez un ou deux conseils de facilitation par point risqué depuis `references/facilitation-moves.md`. Suivez le style de `examples/example-roadmap-meeting.md`. ## Règles - Ne faites jamais fonctionner les calculs en réduisant une décision en dessous de ce dont elle a besoin ; coupez ou déplacez autre chose, ou recommandez un créneau plus long. - Gardez une marge : environ 5 minutes par heure, 10 pour cent pour les ateliers. - Dites clairement quand une réunion ne devrait pas avoir lieu (pas de décisions, rien à discuter) et suggérez l'alternative asynchrone. - Respectez la culture et les contraintes de l'utilisateur ; suggérez, ne faites pas la leçon. - Les heures sont locales à la réunion ; pour les participants à distance dans d'autres fuseaux horaires, mentionnez-le mais ne convertissez pas sauf demande. ## Principes de minutage ### Chaque point a besoin d'un résultat | Résultat | Ce que fait le groupe | Temps typique | Notes | |---|---|---|---| | informer | Entendre quelque chose, poser une question de clarification | 2 à 5 min | Mieux comme pré-lecture écrite. | | mettre à jour | Statut des personnes ou des équipes | 1 à 2 min par personne | Généralement asynchrone ; gardez seulement les blocages en direct. | | discuter | Explorer un sujet, partager des avis, pas de décision encore | 10 à 20 min | Dites ce que la discussion alimente (une décision la semaine prochaine, un document). | | brainstormer | Générer des options | 15 à 30 min | Nécessite une question cadrée et une méthode (écriture silencieuse d'abord). | | revoir | Donner un retour sur un brouillon, un design ou un plan | 15 à 40 min | Envoyez le matériel à l'avance ; convenez du type de retour souhaité. | | décider | Choisir entre des options et s'engager | 10 à 30 min | Nécessite une proposition écrite, les options, le décideur et la règle de décision. | | pause | Repos | 5 à 15 min | Toutes les 60 à 90 minutes. | Si un point n'a pas de résultat clair, demandez : "Qu'est-ce qui sera différent après ce point ?" Si la réponse est "rien", coupez-le. ### Combien de temps les choses prennent vraiment - Présentations : environ 1 minute par personne pour un nouveau groupe, 0 pour une équipe régulière. - Chaque personne parlant une fois sur un sujet : environ 1,5 à 2 minutes par personne. Huit personnes, un tour, c'est 15 minutes. - Partage d'écran et démarrage : 2 à 3 minutes, plus pour les réunions à distance avec de nouveaux outils. - Une décision avec un réel désaccord : doublez l'estimation, ou divisez-la en "discuter" maintenant et "décider" la prochaine fois. - Les points en fin d'ordre du jour vont plus vite mais moins bien : les gens se précipitent ou partent. ### Ordre 1. Commencez par un cadrage court : objectif et résultats souhaités (2 à 5 min). 2. Décisions et sujets les plus difficiles dans la première moitié, pendant que l'énergie et la présence sont élevées. 3. Discussion et revue au milieu. 4. Informations et mises à jour en dernier ou hors de la réunion entièrement. 5. Terminez par les prochaines étapes, responsables et dates (5 min), jamais par "Divers". Regroupez les points qui nécessitent les mêmes personnes, afin que d'autres puissent partir tôt. ### Marges et pauses - Marge : environ 5 minutes par heure, 10 pour cent pour les ateliers. La marge fait partie du créneau, pas du temps supplémentaire. - Pauses : 5 à 10 minutes toutes les 60 à 90 minutes ; 15 pour les ateliers plus longs. Les réunions à distance ont besoin de pauses plus tôt. - Calendriers consécutifs : terminez 5 minutes plus tôt (réunions de 25 ou 50 minutes). ### Vérifications d'adéquation - Plus d'environ 8 points par heure signifie que chacun reçoit moins de 7 minutes ; fusionnez ou coupez. - Statut et annonces au-dessus d'environ un tiers du temps : déplacez-les vers une pré-lecture. - Un point de plus de 45 minutes : divisez-le en étapes avec leurs propres résultats (par exemple "brainstorm 25" puis "regrouper et choisir 20"). ### Le coût d'une réunion Heures-personnes = participants x durée en heures. Une réunion d'une heure avec 9 personnes coûte 9 heures de travail. Demandez si tout le monde doit être là pour chaque point. ## Mouvements de facilitation qui gardent les limites de temps ### Avant la réunion - Envoyez l'ordre du jour et les pré-lectures 24 à 48 heures à l'avance, avec le responsable de chaque point. - Pour chaque point de décision, envoyez une proposition d'une page : la question, les options, la recommandation et qui décide. - Demandez aux gens d'ajouter des questions à la pré-lecture par écrit, afin que la réunion commence par des questions, pas par une présentation. ### Au début - Énoncez l'objectif et les résultats dont vous avez besoin d'ici la fin. - Nommez un gardien du temps et convenez du signal (un message dans le chat, une main levée à 2 minutes restantes). - Dites comment les décisions sont prises aujourd'hui : le responsable décide après avis, vote majoritaire, ou consentement ("une objection forte ?"). ### Par type de point - Informer : "Deux minutes, puis une question de clarification chacun." Les questions détaillées vont au parking ou à une discussion de suivi. - Mettre à jour : Seuls les blocages et les demandes en direct ; tout le reste est dans la pré-lecture. - Discuter : Cadrez la question d'abord ("Qu'est-ce qui nous inquiète dans l'option B ?"). Utilisez un tour rapide pour que chacun parle une fois avant que quiconque parle deux fois. - Brainstormer : 3 à 5 minutes d'écriture silencieuse d'abord, puis partagez, puis regroupez. La quantité avant le jugement. - Revoir : Convenez du type de retour : problèmes bloquants, questions ou polish. Collectez d'abord les problèmes bloquants. - Décider : Reformulez la proposition, listez les préoccupations, vérifiez les objections, puis décidez et dites-le à voix haute : "Nous avons décidé X ; responsable Y ; d'ici la date Z." ### Quand un point dépasse Rendez le choix visible au lieu de manger silencieusement le point suivant : 1. "Il nous reste 2 minutes sur ce point. Est-ce qu'on prolonge de 5 minutes et on coupe autre chose, ou on le met de côté ?" 2. Mettez-le de côté : écrivez-le dans le parking avec un responsable et une date. 3. Réduisez le point suivant, jamais les points de décision. 4. Si l'objectif de la réunion est en danger, planifiez un court suivi avec seulement les personnes nécessaires. ### À distance et hybride - Tout le monde rejoint avec son propre appareil pour que les personnes à distance soient égales. - Utilisez le chat pour la file de parole et pour les sondages rapides. - Partagez l'ordre du jour à l'écran avec le point actuel surligné. ### À la fin - Relisez les décisions, responsables et dates (5 minutes). - Passez en revue le parking : assignez chaque point ou abandonnez-le. - Envoyez les notes dans les 24 heures. ## Entrée d'ordre du jour (pour scripts/timebox_agenda.py) ``` Réunion : <nom> Début : <HH:MM> Durée : <minutes> # ou Fin : <HH:MM> Marge : <minutes ou pourcentage, ex. 5 ou 10%> Participants : <nombre> <minutes> | <sujet> | <responsable> | <informer | mettre à jour | discuter | brainstormer | revoir | décider | pause> ? | <sujet avec durée inconnue> | <responsable> | <résultat> ``` Un tableau Markdown avec les colonnes Min, Sujet, Responsable, Résultat fonctionne aussi, ainsi que le JSON : `{"meeting": "...", "start": "14:00", "length": 60, "buffer": 5, "attendees": 6, "items": [{"minutes": 10, "topic": "...", "owner": "...", "outcome": "decide"}]}` --- # Ordre du jour à envoyer **<Nom de la réunion>** <jour, date>, <début>-<fin> (<durée> min), <lieu ou lien vidéo> Participants : <noms ou équipes> | Facilitateur : <nom> | Gardien du temps : <nom> | Notes : <nom> **Objectif :** <une phrase : ce qui doit être vrai quand nous avons fini> **Résultats dont nous avons besoin** 1. <décision ou résultat> 2. <décision ou résultat> **Pré-lecture (d'ici <jour, heure>)** - <document> - <responsable> - <quoi regarder, combien de temps pour lire> **Planning** | Heure | Min | Point | Responsable | Résultat | |---|---|---|---|---| | <HH:MM-HH:MM> | <n> | <sujet> | <responsable> | <résultat> | | <HH:MM-HH:MM> | <n> | Marge et conclusion : décisions, responsables, dates | <facilitateur> | | **Comment nous décidons aujourd'hui :** <le responsable décide après avis | consentement | vote> **Parking :** Les points hors sujet vont au parking et reçoivent un responsable à la fin. **Sorti de cette réunion** - <point> -> <mise à jour asynchrone, autre réunion, ou un document>, responsable <nom> ## Exemple : corriger une réunion de planification d'une heure surchargée ### La demande "J'ai une heure avec 9 personnes jeudi à 14:00 pour planifier le T4. Voici mon ordre du jour. Est-ce que ça tiendra ? La répartition du budget doit être approuvée dans cette réunion, et les 3 initiatives principales aussi." Brouillon d'ordre du jour (`agenda.txt`) : ``` Réunion : Planification feuille de route T4 Début : 14:00 Durée : 60 Marge : 5 Participants : 9 10 | Bienvenue et objectifs | Dana | informer 15 | Tour de statut d'équipe (chaque responsable d'équipe) | Responsables | mettre à jour 10 | Points saillants des retours clients | Priya | informer 20 | Priorités T4 : choisir les 3 principales initiatives | Lee | discuter 10 | Plan d'embauche pour le T4 | | discuter 5 | Approuver la répartition du budget T4 | Dana | décider ? | Divers | | ``` ### Première exécution ``` $ python3 scripts/timebox_agenda.py agenda.txt Planification feuille de route T4 : 14:00-15:00 (60 min, marge 5 min, 55 min pour les points) Planifié : 70 min 14:00-14:10 10 min Bienvenue et objectifs (Dana) [informer] 14:10-14:25 15 min Tour de statut d'équipe (chaque responsable d'équipe) (Responsables) [mettre à jour] 14:25-14:35 10 min Points saillants des retours clients (Priya) [informer] 14:35-14:55 20 min Priorités T4 : choisir les 3 principales initiatives (Lee) [discuter] 14:55-15:05 10 min Plan d'embauche pour le T4 [discuter] 15:05-15:10 5 min Approuver la répartition du budget T4 (Dana) [décider] 15:10-15:10 ? min Divers [?] 14:55-15:00 5 min Marge / conclusion Constatations : - [HIGH] L'ordre du jour nécessite 70 min mais seulement 55 min sont disponibles après la marge de 5 min : dépassement de 15 min (se termine à 15:10 au lieu de 14:55). Coupez, raccourcissez ou déplacez des points, ou exécutez avec --fit. - [WARN] 1 point(s) sans durée : Divers. Temps restant pour eux : 0 min. - [WARN] "Plan d'embauche pour le T4" n'a pas de responsable ; nommez qui le prépare et le mène. - [WARN] "Approuver la répartition du budget T4" est une décision avec seulement 5 min ; prévoyez au moins 10, ou décidez par une proposition écrite à l'avance. - [WARN] "Approuver la répartition du budget T4" est une décision commençant à 15:05, dans le dernier quart de la réunion ; déplacez-la plus tôt pendant que l'énergie et la présence sont élevées. - [WARN] "Divers" n'a pas de responsable ; nommez qui le prépare et le mène. - [WARN] "Divers" n'a pas de résultat ; dites s'il s'agit d'informer, discuter, décider ou brainstormer. - [WARN] Les mises à jour de statut et les annonces prennent 50% du temps ; envoyez-les comme pré-lecture et gardez la réunion pour la discussion et les décisions. - [INFO] Coût de la réunion : 9 personnes x 60 min = 9 heures-personnes. ``` Code de sortie 1 : l'ordre du jour ne tient pas. ### Ce que disent les chiffres - 70 minutes de points (plus Divers) dans une fenêtre de 55 minutes : 15 minutes de dépassement avant même que Divers ne commence. - La moitié du temps est consacrée aux mises à jour et annonces, tandis que les deux choses qui doivent être décidées reçoivent 5 minutes (budget) et une étiquette "discuter" (priorités), et la décision budgétaire commencerait à 15:05, après que la réunion aurait dû se terminer. - Exécuter `--fit` seul comprimerait tout dans 55 minutes mais laisserait la décision budgétaire en dernier avec 5 minutes. Adapter les chiffres ne suffit pas ; l'ordre et l'objectif des points doivent changer. ### Changements 1. Le tour de statut d'équipe (15 min) et les points saillants des retours clients (10 min) deviennent une pré-lecture écrite à rendre mercredi 12:00 ; les questions vont dans les commentaires. 2. La répartition du budget passe au début avec 10 minutes et une proposition envoyée lundi, afin que la réunion ne fasse que confirmer ou ajuster. 3. "Priorités T4" devient une décision avec 25 minutes : le résultat est un top 3 classé. 4. Le plan d'embauche reçoit un responsable (Priya) et une question plus étroite : quels postes ouvrir. 5. "Divers" est remplacé par une clôture de 5 minutes "prochaines étapes, responsables et parking". 6. Trois personnes nécessaires uniquement pour le tour de statut peuvent sauter la réunion : 6 participants au lieu de 9. Ordre du jour révisé : ``` Réunion : Planification feuille de route T4 Début : 14:00 Durée : 60 Marge : 5 Participants : 6 5 | Bienvenue et objectifs du jour | Dana | informer 10 | Approuver la répartition du budget T4 (proposition envoyée lundi) | Dana | décider 25 | Priorités T4 : choisir les 3 principales initiatives | Lee | décider 10 | Plan d'embauche pour le T4 : convenir des postes à ouvrir | Priya | discuter 5 | Prochaines étapes, responsables et parking | Dana | informer ``` ### Deuxième exécution ``` $ python3 scripts/timebox_agenda.py agenda-revise.txt Planification feuille de route T4 : 14:00-15:00 (60 min, marge 5 min, 55 min pour les points) Planifié : 55 min 14:00-14:05 5 min Bienvenue et objectifs du jour (Dana) [informer] 14:05-14:15 10 min Approuver la répartition du budget T4 (proposition envoyée lundi) (Dana) [décider] 14:15-14:40 25 min Priorités T4 : choisir les 3 principales initiatives (Lee) [décider] 14:40-14:50 10 min Plan d'embauche pour le T4 : convenir des postes à ouvrir (Priya) [discuter] 14:50-14:55 5 min Prochaines étapes, responsables et parking (Dana) [informer] 14:55-15:00 5 min Marge / conclusion Constatations : - [INFO] Coût de la réunion : 6 personnes x 60 min = 6 heures-personnes. ``` Code de sortie 0, aucun avertissement, et la réunion coûte 6 heures-personnes au lieu de 9. ### L'ordre du jour à envoyer (modèle rempli, raccourci) **Planification feuille de route T4** Jeudi, 14:00-15:00 (60 min), Salle 3 et lien vidéo Facilitateur : Dana | Gardien du temps : Lee | Notes : Priya **Objectif :** Partir avec une répartition du budget T4 approuvée et un top 3 classé des initiatives. **Pré-lecture (d'ici mercredi 12:00)** - Pages de statut d'équipe - chaque responsable d'équipe - 5 min à lire - Points saillants des retours clients - Priya - 5 min - Proposition de répartition du budget - Dana - 10 min **Planning** | Heure | Min | Point | Responsable | Résultat | |---|---|---|---|---| | 14:00-14:05 | 5 | Bienvenue et objectifs du jour | Dana | informer | | 14:05-14:15 | 10 | Approuver la répartition du budget T4 (proposition envoyée lundi) | Dana | décider | | 14:15-14:40 | 25 | Priorités T4 : choisir les 3 principales initiatives | Lee | décider | | 14:40-14:50 | 10 | Plan d'embauche pour le T4 : convenir des postes à ouvrir | Priya | discuter | | 14:50-14:55 | 5 | Prochaines étapes, responsables et parking | Dana | informer | | 14:55-15:00 | 5 | Marge | | | **Comment nous décidons aujourd'hui :** Dana décide du budget après avis ; le top 3 est choisi par consentement (une objection forte ?). **Conseils de facilitation** - Priorités : 3 minutes de vote par points silencieux sur la liste des candidats, puis discutez uniquement des points classés 2 à 5. - Si le point budgétaire atteint 10 minutes, mettez le point ouvert de côté avec un responsable et une échéance de 24 heures au lieu de mordre dans les priorités. **Sorti de cette réunion :** tour de statut d'équipe et retours clients (pré-lecture). ### Pourquoi c'est une bonne réponse - Cela corrige l'objectif et l'ordre, pas seulement les minutes. - Les deux décisions requises ont maintenant lieu dans les 40 premières minutes, avec des propositions préparées. - Le script confirme l'adéquation, et les personnes qui n'étaient là que pour les mises à jour récupèrent leur heure. ## Script Python : timebox_agenda.py ```python #!/usr/bin/env python3 """Minute un ordre du jour de réunion : planifiez chaque point, vérifiez l'adéquation et signalez les problèmes d'ordre du jour. Utilisation : python3 timebox_agenda.py agenda.txt python3 timebox_agenda.py agenda.txt --fit # adapter les points au créneau (pas de 5 minutes) python3 timebox_agenda.py agenda.json --json cat agenda.txt | python3 timebox_agenda.py - Entrée texte : lignes d'en-tête optionnelles "Clé : valeur", puis un point par ligne comme minutes | sujet | responsable | résultat Les lignes de tableau Markdown (| 10 | Sujet | Responsable | décider |) fonctionnent aussi ; les lignes d'en-tête et de séparateur sont ignorées. Utilisez ? pour une durée inconnue. Clés d'en-tête : Réunion, Début (HH:MM), Durée (minutes) ou Fin (HH:MM), Marge (minutes ou pourcentage, ex. 5 ou 10%), Participants (nombre). Résultats : informer, mettre à jour, discuter, brainstormer, revoir, décider, pause. Entrée JSON : {"meeting": "...", "start": "14:00", "length": 60, "buffer": 5, "attendees": 8, "items": [{"minutes": 10, "topic": "...", "owner": "...", "outcome": "decide"}]} --fit réduit d'abord les points de statut (et les points sans résultat), puis adapte tout ; le temps restant va aux points décider et discuter. Vérifications : dépassement (HIGH), durées, responsables ou résultats manquants, décisions tardives ou précipitées, points surdimensionnés, longues périodes sans pause, trop de mises à jour de statut, trop de points par heure, plus le coût de la réunion en heures-personnes. Code de sortie : 0 aucune constatation HIGH, 1 HIGH trouvé, 2 erreur d'utilisation ou d'entrée. Bibliothèque standard uniquement. """ import argparse import json import math import re import sys OUTCOMES = {"informer", "mettre à jour", "discuter", "brainstormer", "revoir", "décider", "pause"} ALIASES = {"decision": "décider", "info": "informer", "fyi": "informer", "status": "mettre à jour", "updates": "mettre à jour", "discussion": "discuter", "ideas": "brainstormer", "ideation": "brainstormer", "feedback": "revoir", "approve": "décider", "approval": "décider", "pause": "pause", "coffee": "pause"} class InputError(Exception): pass def hhmm(text): m = re.fullmatch(r"\s*(\d{1,2})[:.](\d{2})\s*", str(text)) if not m or int(m.group(1)) > 23 or int(m.group(2)) > 59: raise InputError(f"l'heure doit être HH:MM, reçu {text!r}") return int(m.group(1)) * 60 + int(m.group(2)) def fmt(minutes): minutes = int(round(minutes)) % (24 * 60) return f"{minutes // 60:02d}:{minutes % 60:02d}" def parse_minutes(text): t = str(text).strip().lower() if t in ("", "?", "tbd", "-"): return None m = re.fullmatch(r"(\d+(?:\.\d+)?)\s*(m|min|mins|minutes?)?", t) if m: return float(m.group(1)) m = re.fullmatch(r"(\d+(?:\.\d+)?)\s*h(?:ours?)?(?:\s*(\d+)\s*m(?:in)?)?", t) if m: return float(m.group(1)) * 60 + float(m.group(2) or 0) raise InputError(f"impossible de lire la durée {text!r}") def norm_outcome(text): t = (text or "").strip().lower() return ALIASES.get(t, t) def parse_text(text): meta, items, errors = {}, [], [] for no, raw in enumerate(text.replace("\r\n", "\n").split("\n"), 1): line = raw.strip() if not line or line.startswith("#"): continue hm = re.fullmatch(r"([A-Za-zÀ-ÿ ]{3,20}):\s*(.+)", line) if hm and "|" not in line: meta[hm.group(1).strip().lower()] = hm.group(2).strip() continue if "|" not in line: errors.append(f"ligne {no} : attendu 'minutes | sujet | responsable | résultat', reçu {line[:60]!r}") continue cells = [c.strip() for c in line.strip("|").split("|")] if all(re.fullmatch(r":?-{2,}:?", c) for c in cells if c): continue if cells and cells[0].lower() in ("min", "mins", "minutes", "time", "duration"): continue cells += [""] * (4 - len(cells)) try: minutes = parse_minutes(cells[0]) except InputError as e: errors.append(f"ligne {no} : {e}") continue if not cells[1]: errors.append(f"ligne {no} : le point n'a pas de sujet") continue items.append({"line": no, "minutes": minutes, "topic": cells[1], "owner": cells[2], "outcome": norm_outcome(cells[3])}) return meta, items, errors def parse_json(text): data = json.loads(text) if not isinstance(data, dict) or not isinstance(data.get("items"), list): raise InputError("l'entrée JSON nécessite un objet avec une liste 'items'") meta = {k.lower(): str(v) for k, v in data.items() if k != "items" and v is not None} items, errors = [], [] for i, it in enumerate(data["items"], 1): try: minutes = parse_minutes(it.get("minutes", "")) except InputError as e: errors.append(f"point {i} : {e}") continue if not str(it.get("topic", "")).strip(): errors.append(f"point {i} : le point n'a pas de sujet") continue items.append({"line": i, "minutes": minutes, "topic": str(it["topic"]).strip(), "owner": str(it.get("owner", "") or "").strip(), "outcome": norm_outcome(it.get("outcome", ""))}) return meta, items, errors def settings(meta): start = hhmm(meta.get("début", "09:00")) if "durée" in meta: length = parse_minutes(meta["durée"]) if not length or length <= 0: raise InputError("La durée doit être un nombre positif de minutes") elif "fin" in meta: length = (hhmm(meta["fin"]) - start) % (24 * 60) if length == 0: raise InputError("La fin doit être après le début") else: raise InputError("l'en-tête nécessite 'Durée : <minutes>' ou 'Fin : HH:MM'") b = meta.get("marge", "0").strip() if b.endswith("%"): buffer = 5 * round(length * float(b[:-1]) / 100 / 5) # les marges en pourcentage arrondissent à 5 minutes else: buffer = parse_minutes(b) or 0 if buffer >= length: raise InputError("La marge doit être plus courte que la réunion") attendees = int(meta["participants"]) if str(meta.get("participants", "")).strip().isdigit() else None return {"meeting": meta.get("réunion", meta.get("titre", "Réunion")), "start": start, "length": length, "buffer": buffer, "available": length - buffer, "attendees": attendees} def fit(items, available): """Adapte les points dans `available` minutes par pas de 5 minutes (les durées manquantes comptent pour 10, les pauses sont conservées). Quand l'ordre du jour est trop long, les points de statut (informer, mettre à jour, ou sans résultat) sont réduits d'abord, jusqu'à la moitié de leur temps prévu ; puis chaque point est adapté proportionnellement. Quand il est trop court, le temps restant va d'abord aux points décider et discuter. """ fixed = sum(it["minutes"] or 0 for it in items if it["outcome"] == "pause") flex = [it for it in items if it["outcome"] != "pause"] room = available - fixed if not flex or room < 5 * len(flex): raise InputError(f"impossible d'adapter {len(flex)} points dans {room:g} minutes avec au moins 5 minutes chacun") want = [max(5, 5 * round((it["minutes"] or 10) / 5)) for it in flex] cur = list(want) status = [i for i, it in enumerate(flex) if it["outcome"] in ("informer", "mettre à jour", "")] while sum(cur) > room: cands = [i for i in status if cur[i] - 5 >= max(5, want[i] / 2)] if not cands: break cur[max(cands, key=lambda k: cur[k])] -= 5 if sum(cur) > room: scale = room / sum(cur) ref = [c * scale for c in cur] cur = [max(5, 5 * round(r / 5)) for r in ref] while sum(cur) > room: cands = [k for k in range(len(cur)) if cur[k] > 5] cur[max(cands, key=lambda k: (cur[k] - ref[k], cur[k]))] -= 5 while sum(cur) + 5 <= room: cur[min(range(len(cur)), key=lambda k: cur[k] - ref[k])] += 5 else: prio = [i for i, it in enumerate(flex) if it["outcome"] in ("décider", "discuter")] or list(range(len(flex))) while sum(cur) + 5 <= room: cur[min(prio, key=lambda k: cur[k] / want[k])] += 5 out, it_new = [], iter(cur) for it in items: copy = dict(it) copy["original"] = it["minutes"] if it["outcome"] != "pause": copy["minutes"] = float(next(it_new)) out.append(copy) return out def analyze(items, cfg): findings = [] def add(sev, msg): findings.append({"severity": sev, "message": msg}) t = cfg["start"] for it in items: it["start"] = t t += it["minutes"] or 0 it["end"] = t planned = sum(it["minutes"] or 0 for it in items) avail, end_slot = cfg["available"], cfg["start"] + cfg["length"] unknown = [it for it in items if it["minutes"] is None] if planned > avail: add("HIGH", f"L'ordre du jour nécessite {planned:g} min mais seulement {avail:g} min sont disponibles" f"{' après la marge de ' + format(cfg['buffer'], 'g') + ' min' if cfg['buffer'] else ''} : dépassement de {planned - avail:g} min" f" (se termine à {fmt(cfg['start'] + planned)} au lieu de {fmt(end_slot - cfg['buffer'])}). Coupez, raccourcissez ou déplacez des points, ou exécutez avec --fit.") elif avail - planned > 0.15 * avail and not unknown: add("INFO", f"{avail - planned:g} min non planifiées ; terminez plus tôt ou donnez plus de temps à la décision principale.") if unknown: add("WARN", f"{len(unknown)} point(s) sans durée : " + "; ".join(it["topic"][:40] for it in unknown) + f". Temps restant pour eux : {max(avail - planned, 0):g} min.") for it in items: name = f"\"{it['topic'][:50]}\"" if it["outcome"] != "pause" and not it["owner"]: add("WARN", f"{name} n'a pas de responsable ; nommez qui le prépare et le mène.") if not it["outcome"]: add("WARN", f"{name} n'a pas de résultat ; dites s'il s'agit d'informer, discuter, décider ou brainstormer.") elif it["outcome"] not in OUTCOMES: add("WARN", f"{name} a un résultat inconnu '{it['outcome']}' (utilisez : {', '.join(sorted(OUTCOMES))}).") m = it["minutes"] or 0 if it["outcome"] == "décider": if it["minutes"] is not None and m < 10: add("WARN", f"{name} est une décision avec seulement {m:g} min ; prévoyez au moins 10, ou décidez par une proposition écrite à l'avance.") if it["start"] - cfg["start"] >= 0.75 * cfg["length"]: add("WARN", f"{name} est une décision commençant à {fmt(it['start'])}, dans le dernier quart de la réunion ; déplacez-la plus tôt pendant que l'énergie et la présence sont élevées.") if it["outcome"] in ("discuter", "brainstormer", "revoir") and it["minutes"] is not None and m < 5: add("WARN", f"{name} est un point {it['outcome']} avec {m:g} min ; c'est une mention, pas un {it['outcome']}.") if m > 45 and it["outcome"] != "pause": add("WARN", f"{name} est long de {m:g} min ; divisez-le en parties avec leurs propres résultats.") stretch, stretch_start = 0, cfg["start"] for it in items: if it["outcome"] == "pause": stretch, stretch_start = 0, it["end"] continue stretch += it["minutes"] or 0 if stretch > 90: add("WARN", f"{stretch:g} min sans pause depuis {fmt(stretch_start)} ; ajoutez une pause de 5 à 10 min environ toutes les 60 à 90 min.") stretch = -10**9 status = sum(it["minutes"] or 0 for it in items if it["outcome"] in ("informer", "mettre à jour")) if planned and status / planned > 0.35: add("WARN", f"Les mises à jour de statut et les annonces prennent {round(100 * status / planned)}% du temps ; envoyez-les comme pré-lecture et gardez la réunion pour la discussion et les décisions.") work_items = [it for it in items if it["outcome"] != "pause"] hours = cfg["length"] / 60 if hours and len(work_items) / hours > 8: add("WARN", f"{len(work_items)} points dans {cfg['length']:g} min est plus de 8 par heure ; fusionnez ou supprimez des points.") if not any(it["outcome"] == "décider" for it in items): add("INFO", "Aucun point de décision ; vérifiez que cette réunion doit avoir lieu en direct.") cost = None if cfg["attendees"]: cost = round(cfg["attendees"] * cfg["length"] / 60, 1) add("INFO", f"Coût de la réunion : {cfg['attendees']} personnes x {cfg['length']:g} min = {cost:g} heures-personnes.") order = {"HIGH": 0, "WARN": 1, "INFO": 2} findings.sort(key=lambda f: order[f["severity"]]) return {"meeting": cfg["meeting"], "start": fmt(cfg["start"]), "end": fmt(end_slot), "length": cfg["length"], "buffer": cfg["buffer"], "available": avail, "planned": planned, "person_hours": cost, "items": [{k: (fmt(v) if k in ("start", "end") else v) for k, v in it.items()} for it in items], "findings": findings} def main(): ap = argparse.ArgumentParser(description="Minute un ordre du jour de réunion") ap.add_argument("path", help="fichier d'ordre du jour texte/Markdown/JSON, ou - pour stdin") ap.add_argument("--fit", action="store_true", help="adapter les durées des points au temps disponible") ap.add_argument("--json", action="store_true") args = ap.parse_args() try: text = sys.stdin.read() if args.path == "-" else open(args.path, encoding="utf-8").read() if not text.strip(): raise InputError("l'entrée est vide") meta, items, errors = parse_json(text) if text.lstrip().startswith("{") else parse_text(text) if errors: raise InputError("impossible de lire l'ordre du jour :\n " + "\n ".join(errors)) if not items: raise InputError("aucun point d'ordre du jour trouvé (attendu des lignes comme '10 | Sujet | Responsable | décider')") cfg = settings(meta) before = sum(it["minutes"] or 0 for it in items) n_unknown = sum(1 for it in items if it["minutes"] is None) if args.fit: items = fit(items, cfg["available"]) except FileNotFoundError: print(f"erreur : fichier introuvable : {args.path}", file=sys.stderr) return 2 except (InputError, json.JSONDecodeError, ValueError) as e: print(f"erreur : {e}", file=sys.stderr) return 2 rep = analyze(items, cfg) rep["fitted_from"] = before if args.fit else None if args.json: print(json.dumps(rep, indent=2)) else: print(f"{rep['meeting']} : {rep['start']}-{rep['end']} ({rep['length']:g} min, marge {rep['buffer']:g} min, {rep['available']:g} min pour les points)") if args.fit: extra = f" plus {n_unknown} sans durée (comptés pour 10 min chacun)" if n_unknown else "" print(f"Adapté : {before:g} min de points{extra} adaptées dans {rep['planned']:g} min (pas de 5 minutes, pauses conservées).") print(f"Planifié : {rep['planned']:g} min\n") for it in rep["items"]: mins = "?" if it["minutes"] is None else f"{it['minutes']:g}" was = f" (était {it['original']:g})" if args.fit and it.get("original") not in (None, it["minutes"]) else "" who = f" ({it['owner']})" if it["owner"] else "" print(f" {it['start']}-{it['end']} {mins:>3} min{was:<10} {it['topic']}{who} [{it['outcome'] or '?'}]") if rep["buffer"]: print(f" {fmt(hhmm(rep['end']) - rep['buffer'])}-{rep['end']} {rep['buffer']:>3g} min Marge / conclusion") print() if rep["findings"]: print("Constatations :") for f in rep["findings"]: print(f"- [{f['severity']}] {f['message']}") else: print("Constatations : aucune") return 1 if any(f["severity"] == "HIGH" for f in rep["findings"]) else 0 if __name__ == "__main__": sys.exit(main()) ```

Connectez-vous pour voir le prompt complet

Continuer avec:

En vous connectant, vous acceptez nos Conditions et Confidentialité

Utilisation

Ce prompt est conçu pour être utilisé avec productivity. Copiez le contenu ci-dessus et collez-le dans votre outil d’IA préféré.

Pour de meilleurs résultats, personnalisez les espaces réservés (indiqués par des crochets ou des majuscules) selon vos besoins.

Références

Catégories :productivity| prompts.chat| meeting-agenda| timeboxing

Discussion