Second Brain documentation

ADR 0051 – Modèles avec enfants et aperçu avant création

Accepté (2026-10-16, mode autonome ; ligne 23 du backlog, prise sur la recommandation du fil coordinateur)

← Toutes les décisions

ADR 0051 – Modèles avec enfants et aperçu avant création

Statut : Accepté (2026-10-16, mode autonome ; ligne 23 du backlog, prise sur la recommandation du fil coordinateur)

La ligne 23 du backlog (jalon 3, vague 2) demande que les modèles puissent créer des enfants, avec un aperçu avant la création. L’exemple type : un modèle « Projet de rénovation » qui crée le projet et ses premières tâches, chacune avec son échéance et rattachée au projet.

Ce qui existe (ADR 0016) :

  • un modèle préremplit le formulaire de création, sans rien écrire ;
  • son brouillon (GET /api/definitions/templates/{name}/draft) résout {{today}} et {{now}} ;
  • la création passe par le POST /api/nodes habituel ;
  • un modèle ne cite aucun nœud (ni parent, ni champ référence), car un identifiant écrit dans config/ n’est pas portable.

Décision

Format : clé children, récursive

name: projet-renovation
label: Projet de rénovation
type: projet
title: "Rénovation "
children:
  - title: Demander trois devis
    type: tache
    aspects:
      tache: { echeance: "{{today + 1w}}", projet: "{{root}}" }
  - title: Choisir l'artisan
    type: tache
    aspects:
      tache: { echeance: "{{today + 3w}}", projet: "{{root}}" }
    children:
      - { title: Signer le devis, type: tache, aspects: { tache: { projet: "{{root}}" } } }
  • Contenu d’un enfant. Les mêmes clés que le nœud créé : title (obligatoire), type, aspects, tags, body, et children.

  • Variables. {{today}} et {{now}}, avec la même grammaire et les mêmes contrôles que l’ADR 0016.

  • Bornes. Trois niveaux sous le nœud créé, et 50 enfants en tout. Contrôlé au chargement.

  • Références au nœud créé. Un champ référence (format: node-ref) d’un enfant n’admet que deux valeurs entières :

    • "{{root}}" : le nœud créé par le formulaire ;
    • "{{parent}}" : le nœud juste au-dessus de l’enfant.

    Le chargeur vérifie que le nœud désigné convient au x-target du champ, d’après ce qu’il portera à coup sûr : ses aspects cités et ceux que son type rend obligatoires. Par exemple, tache.projet: "{{parent}}" sous une tâche est refusé, car une tâche ne porte pas projet. Si l’utilisateur change ensuite le type de la racine dans le formulaire, la création peut être refusée (400 avec le chemin de l’enfant) : rien n’est alors créé.

    C’est la seule exception à « aucune référence dans un modèle ». Ces deux valeurs ne désignent pas un nœud existant : elles restent portables. Le nœud créé lui-même n’en admet pas. Toute autre valeur dans un champ référence rend le fichier invalide.

  • Contrôles au chargement. Ce sont ceux de l’ADR 0016, appliqués à chaque enfant avec son chemin (children[1].children[0].aspects.tache.echeance) :

    • type et aspects connus ;
    • champs connus ;
    • variables strictes ;
    • valeurs conformes au schéma, champs requis exceptés.

Brouillon et création

  • Brouillon. NodeDraft gagne children. Chaque enfant a ses variables de date résolues. {{root}} et {{parent}} restent tels quels, car le nœud n’existe pas encore.
  • Création. CreateNodeRequest gagne children, de même forme. Le serveur crée le nœud, puis chaque enfant sous son parent, dans la même transaction. Une erreur sur un enfant annule tout. Elle est rendue en 400 avec son chemin (children[1].aspects.tache.statut).
    • Chaque nœud passe par NodeService.create : aspects obligatoires, valeurs par défaut, validation, workflow et événement node.created, qui garde la provenance template.
    • {{root}} et {{parent}} sont remplacés par les identifiants juste avant la validation de l’enfant, dans ses seuls champs référence. Ailleurs, le jeton reste une chaîne ordinaire.
    • Une erreur d’enfant s’affiche avec son titre : « « Choisir l’artisan » › Tâche › Statut : … ».
  • Pas d’application côté serveur. Comme pour la racine (ADR 0016), le serveur ne relit pas le modèle à la création : il crée ce que le client envoie. Le client envoie le brouillon, tel que l’utilisateur l’a confirmé dans l’aperçu. Les enfants passent les mêmes contrôles que toute création, et la borne de 50 vaut aussi pour la requête.

Aperçu avant création

Le formulaire de création est l’aperçu du nœud lui-même : titre, type, champs et corps préremplis, modifiables. Sous les propriétés, une section « Créé avec ce nœud » montre l’arbre des enfants :

  • une case par enfant, cochée par défaut ; décocher un enfant retire aussi ses descendants ;
  • son type (badge), son titre et ses dates. Un champ qui vaut {{root}} affiche « → ce nœud », et {{parent}} affiche « → le nœud au-dessus » ;
  • le compte de ce qui sera créé : « 3 nœuds enfants seront créés ».

Le bouton « Enregistrer » crée le tout. L’annonce dit combien de nœuds ont été créés. Les cases ne comptent pas comme une modification non enregistrée : quitter le formulaire les oublie, comme le reste du brouillon.

Reporté

  • Modifier le titre ou les champs d’un enfant dans l’aperçu (pour l’instant : cocher ou décocher, puis modifier après la création).
  • Variables tirées du nœud créé ({{root.title}}) dans les titres des enfants.
  • Liens typés entre enfants (« bloqué par » entre deux tâches du modèle).
  • Créer des enfants sous un nœud existant à partir d’un modèle (« Appliquer le modèle »).

Conséquences

  • Les modèles existants restent valides : children est facultatif.
  • CreateNodeRequest grossit d’un champ facultatif. Les scripts qui créent des nœuds peuvent aussi créer un arbre en une requête.
  • Le journal garde un node.created par nœud, et chaque enfant est un nœud ordinaire : il se modifie, se déplace ou se place dans la corbeille seul.