105 lines
3.4 KiB
Python
105 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
patch_layouts_c5c.py — Chantier C5 lot 3 (catalogue : agenda, pyramid)
|
|
======================================================================
|
|
Append sécurisé à layouts_v2.yaml (mécanique verrouillée C4/C5b).
|
|
Après ce patch, propager : python3 prompt_injection_v2.py && python3
|
|
build_gallery.py.
|
|
|
|
Usage (dossier du pipeline, single-line) :
|
|
python3 patch_layouts_c5c.py
|
|
"""
|
|
|
|
import shutil
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
TARGET = Path("layouts_v2.yaml")
|
|
NEW_KEYS = ("agenda", "pyramid")
|
|
|
|
FRAGMENT = """
|
|
# ── Chantier C5 lot 3 — retours v1 restylés ───────────────────────
|
|
agenda:
|
|
id: L40
|
|
famille: Structure
|
|
mode: light
|
|
champs: [titre, sections]
|
|
champs_requis: [titre, sections]
|
|
agent_hint: >-
|
|
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.
|
|
|
|
pyramid:
|
|
id: L41
|
|
famille: Concept
|
|
mode: light
|
|
champs: [titre, niveaux]
|
|
champs_requis: [titre, niveaux]
|
|
agent_hint: >-
|
|
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.
|
|
"""
|
|
|
|
|
|
def fail(msg):
|
|
print(" ! %s" % msg)
|
|
sys.exit(1)
|
|
|
|
|
|
def main():
|
|
if not TARGET.exists():
|
|
fail("%s introuvable — lancer depuis le dossier du pipeline."
|
|
% TARGET)
|
|
raw = TARGET.read_text(encoding="utf-8")
|
|
try:
|
|
data = yaml.safe_load(raw)
|
|
except yaml.YAMLError as e:
|
|
fail("layouts_v2.yaml actuel illisible : %s" % e)
|
|
layouts = (data or {}).get("layouts")
|
|
if not isinstance(layouts, dict):
|
|
fail("Bloc layouts: introuvable dans le fichier.")
|
|
for key in NEW_KEYS:
|
|
if key in layouts:
|
|
fail("'%s' déjà présent — rien à faire." % key)
|
|
|
|
last = next((l for l in reversed(raw.splitlines())
|
|
if l.strip() and not l.strip().startswith("#")), "")
|
|
if not last.startswith(" "):
|
|
fail("Le fichier ne se termine pas dans le bloc layouts: — "
|
|
"fusion manuelle requise.")
|
|
|
|
shutil.copy2(TARGET, str(TARGET) + ".bak-c5c")
|
|
print(" + Sauvegarde : %s.bak-c5c" % TARGET)
|
|
|
|
with open(TARGET, "a", encoding="utf-8") as f:
|
|
if not raw.endswith("\n"):
|
|
f.write("\n")
|
|
f.write(FRAGMENT)
|
|
|
|
try:
|
|
check = yaml.safe_load(TARGET.read_text(encoding="utf-8"))
|
|
nl = check["layouts"]
|
|
assert all(k in nl for k in NEW_KEYS)
|
|
assert len(nl) == len(layouts) + len(NEW_KEYS)
|
|
except Exception as e:
|
|
shutil.copy2(str(TARGET) + ".bak-c5c", TARGET)
|
|
fail("Contrôle post-append échoué (%s) — fichier restauré." % e)
|
|
|
|
print(" + agenda (L40) et pyramid (L41) ajoutés (%d layouts au "
|
|
"total)." % (len(layouts) + len(NEW_KEYS)))
|
|
print("\n Propager : python3 prompt_injection_v2.py && python3 "
|
|
"build_gallery.py")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|