#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ patch_prompts_c1_c4.py — Mises à jour des prompts sources (C3 + C4) =================================================================== Insère dans les prompts SOURCES les règles hors-catalogue accumulées depuis C1 (le catalogue, lui, se propage tout seul via prompt_injection_v2.py — ne jamais l'éditer à la main) : 1. prompt_the_narrator_v4.md - Notes du présentateur (C3) : ligne facultative « Notes : » par slide à la formalisation. - Images du projet (C4) : référencer les fichiers listés par /lire dans les slides visuelles. 2. prompt_the_free_designer.md - Nouveau bloc « image » (C4) dans le vocabulaire freeform. 3. prompt_the_encoder_v2.md (fallback agent — mode express uniquement ; en mode schema le prompt est embarqué dans encoder_schema.py) - Transcription du champ notes. Ancres = titres de section Markdown (stables). Refuse de patcher deux fois. Sauvegardes .bak-prompts. Usage (dossier du pipeline, single-line) : python3 patch_prompts_c1_c4.py APRÈS ce patch, la séquence complète de propagation est : python3 prompt_injection_v2.py && python3 build_gallery.py puis recoller dans Mistral Studio : - Agent Narrator ← prompt_the_narrator_v4.md (source) - Agent Designer ← prompt_the_designer_injected_v3.md - Agent Encoder ← prompt_the_encoder_injected_v2.md - Agent Free Designer ← prompt_the_free_designer.md (source) """ import shutil import sys from pathlib import Path JOBS = [ { "file": "prompt_the_narrator_v4.md", "marker": "## IMAGES DU PROJET", "anchor": "## RÈGLES ABSOLUES", "block": """## NOTES DU PRÉSENTATEUR (formalisation) À la formalisation, tu peux ajouter sous chaque slide une ligne facultative : Notes : [2-3 phrases de narration orale pour le présentateur — le ton parlé, les transitions, l'exemple à raconter. Pas une répétition du contenu affiché.] Ces notes seront placées dans la zone commentaires de PowerPoint, invisibles à l'audience. N'en mets que là où elles apportent quelque chose. ## IMAGES DU PROJET Quand la commande /lire t'a fourni une liste « IMAGES DISPONIBLES DANS assets/ », tu peux construire des slides visuelles autour de ces fichiers : ouverture de chapitre sur une image forte, slide image + points clés. Référence toujours le nom de fichier EXACT tel que listé. Ne référence JAMAIS une image absente de la liste. """, }, { "file": "prompt_the_free_designer.md", "marker": "- type: image", "anchor": "## FORMAT DE SORTIE", "block": """### Bloc image (nouveau) - type: image # image du dossier assets/ du projet image: photo.png # nom de fichier EXACT (liste fournie en contexte) fit: cover # cover (remplit, recadrage centré) | contain # x/y/w/h : grille habituelle. Jamais de déformation. # Ne référence JAMAIS un fichier absent de la liste fournie. """, }, { "file": "prompt_the_encoder_v2.md", "marker": "champ `notes`", "anchor": "## GESTION DE LA LONGUEUR", "block": """### Notes du présentateur Si une slide du plan contient une ligne « Notes : ... », transcris son contenu dans un champ `notes` de la slide YAML (chaîne simple). Les lignes de justification du Designer (commençant par →) ne sont NI du contenu NI des notes : ignore-les. """, }, ] def fail(msg): print(" ! %s" % msg) sys.exit(1) def main(): patched = 0 for job in JOBS: path = Path(job["file"]) if not path.exists(): print(" ~ %s introuvable — sauté." % path) continue content = path.read_text(encoding="utf-8") if job["marker"] in content: print(" = %s : déjà à jour." % path) continue n = content.count(job["anchor"]) if n != 1: fail("%s : ancre %r trouvée %d fois — insertion manuelle " "requise (bloc dans ce script)." % (path, job["anchor"], n)) shutil.copy2(path, str(path) + ".bak-prompts") content = content.replace(job["anchor"], job["block"] + job["anchor"]) path.write_text(content, encoding="utf-8") print(" + %s : bloc inséré avant %r." % (path, job["anchor"])) patched += 1 if patched == 0: print("\n Rien à faire.") return print("\n Propager : python3 prompt_injection_v2.py && " "python3 build_gallery.py") print(" Puis recoller dans Mistral Studio :") print(" Narrator ← prompt_the_narrator_v4.md (source)") print(" Designer ← prompt_the_designer_injected_v3.md") print(" Encoder ← prompt_the_encoder_injected_v2.md") print(" Free Designer ← prompt_the_free_designer.md (source)") if __name__ == "__main__": main()