""" trilium_init.py — Initialisation idempotente de l'arborescence Trilium Usage : python trilium_init.py python trilium_init.py --with-example python trilium_init.py --show-ids """ import argparse import json import os from trilium_api import (check_api, create_note, get_note_id, find_note_by_title, set_label, update_note_content) GREEN, YELLOW, RESET, BOLD = "\033[32m", "\033[33m", "\033[0m", "\033[1m" def ok(m): print(f" {GREEN}✓{RESET} {m}") def warn(m): print(f" {YELLOW}⚠{RESET} {m}") def head(m): print(f"\n{BOLD}{m}{RESET}") IDS_FILE = os.path.join(os.path.dirname(__file__), "trilium_ids.json") def get_or_create(parent_id, title, note_type="text", labels=None): existing = find_note_by_title(title, parent_id) if existing: warn(f"Existant : {title} (ID: {existing})") return existing result = create_note(parent_id, title, note_type=note_type) note_id = get_note_id(result) if labels: for k, v in labels.items(): set_label(note_id, k, v) ok(f"Créé : {title} (ID: {note_id})") return note_id def init_structure(): head("Initialisation de l'arborescence Trilium") ids = {} root_id = get_or_create("root", "Context Continuity", "book", {"type": "projet"}) ids["root"] = root_id children_map = { "Projets": "Projets", "Conversations": "Conversations", "Backlog": "Backlog", "Décisions": "Decisions", "Historique": "Historique", "Glossaire": "Glossaire", "Contextes Reprise": "ContextesReprise", } for title, key in children_map.items(): ids[key] = get_or_create(root_id, title, "book", {"type": "container"}) with open(IDS_FILE, "w") as f: json.dump(ids, f, indent=2, ensure_ascii=False) ok(f"IDs sauvegardés dans {IDS_FILE}") return ids def create_example_project(ids): head("Création du projet exemple : Sliding Automation") projet_id = get_or_create( ids["Projets"], "Sliding Automation", "text", {"type": "projet", "projet": "SlidingAutomation", "statut": "actif"} ) update_note_content(projet_id, "

Sliding Automation

" "

Objectif : Pipeline de génération automatique de " "présentations PPTX via agents Mistral.

" "

Stack : Python, python-pptx, Mistral Large/Small, YAML

" "

LLM : Claude → architecture & rédaction longue | " "Le Chat → génération code & itérations

" ) head("Backlog Items") backlog_items = [ ("Déployer patch_render_engine.py (chantiers A/B/C/D)", "haute", "à faire"), ("Analyser feedbacks slides 5-17", "haute", "à faire"), ("Fix two_cols_text : tirets Markdown visibles", "moyenne", "à faire"), ("Fix executive_summary : blocs SCR mal positionnés", "moyenne", "à faire"), ("Initialiser versioning Git (Forgejo ou Codeberg)", "basse", "à faire"), ] for titre, prio, statut in backlog_items: get_or_create(ids["Backlog"], titre, "text", {"type": "backlogItem", "projet": "SlidingAutomation", "priorite": prio, "statut": statut}) head("Historique") historique = [ ("Fix semantic key : self.theme['semantic']", "Fait établi", "Clé corrigée dans render_engine.py — ne pas revenir en arrière."), ("Fix polices : détection via assets/fonts/ (pas fc-list)", "Fait établi", "fc-list indisponible sur DS218 ARM64. Détection locale obligatoire."), ("Fix Python 3.9 : Union[X|Y] non supporté", "Contrainte découverte", "DS218 tourne Python 3.9. Utiliser Union[X, Y] / Optional[X]."), ] for titre, type_h, detail in historique: nid = get_or_create(ids["Historique"], titre, "text", {"type": "historiqueItem", "projet": "SlidingAutomation", "typeHistorique": type_h, "encoreValide": "true"}) update_note_content(nid, f"

{detail}

") head("Glossaire") glossaire = [ ("render_engine.py", "Script principal de rendu PPTX. " "NE PAS confondre avec facilitator.py."), ("Chantier A/B/C/D", "4 ensembles de corrections visuelles regroupées " "dans patch_render_engine.py."), ("Layout", "Template de slide défini dans layouts.yaml. " "28 layouts disponibles (L01-L28)."), ] for terme, definition in glossaire: nid = get_or_create(ids["Glossaire"], terme, "text", {"type": "termeGlossaire", "projet": "SlidingAutomation"}) update_note_content(nid, f"

Définition : {definition}

") ok("Projet Sliding Automation initialisé.") def show_ids(): if not os.path.exists(IDS_FILE): print("❌ trilium_ids.json introuvable. " "Lance d'abord : python trilium_init.py") return with open(IDS_FILE) as f: ids = json.load(f) head("IDs Trilium") for k, v in ids.items(): print(f" {k:<20} : {v}") def main(): parser = argparse.ArgumentParser( description="Initialise l'arborescence Trilium") parser.add_argument("--with-example", action="store_true", help="Crée aussi les données Sliding Automation") parser.add_argument("--show-ids", action="store_true", help="Affiche les IDs existants") args = parser.parse_args() if args.show_ids: show_ids() return check_api() ids = init_structure() if args.with_example: create_example_project(ids) head("Done ✓") print(" Lance : python trilium_context.py list-backlog " "--projet SlidingAutomation") if __name__ == "__main__": main()