Second Brain documentation

ADR 0037 – Revue hebdomadaire guidée, prochaine action et fréquence de revue

Accepté (2026-10-16, mode autonome)

← Toutes les décisions

ADR 0037 – Revue hebdomadaire guidée, prochaine action et fréquence de revue

Statut : Accepté (2026-10-16, mode autonome)

La ligne « Revue hebdomadaire » du jalon 2 demandait une vue dédiée : en retard, sans échéance, projets sans prochaine action, inbox. La vague 1 (validée par Aurélien le 2026-10-15) y ajoute :

  • un champ revueTousLes sur projet (7 jours par défaut) et un bouton « Marquer revu » ;
  • une revue qui ne montre que les projets dus ;
  • la prochaine action du projet (la première tâche ouverte par échéance, ou un champ) en haut de la fiche ;
  • une revue guidée en étapes (inbox, retards, sans échéance, projets à revoir ou sans prochaine action, en attente), avec un compteur par étape et un résumé final.

Tout reste dans config/, et le moteur de vues (ADR 0028) porte chaque étape. Le code ne nomme ni projet, ni tache, ni echeance.

Décision

Prochaine action : clé nextAction d’un aspect

nextAction:
  label: Prochaine action      # défaut
  field: prochaineAction       # facultatif : référence forcée
  from: tache.projet           # candidats : nœuds dont ce champ référence pointe vers ce nœud
  states: [a-faire, en-cours]  # facultatif : états de workflow d'un candidat
  sort: [tache.echeance asc, tache.priorite desc]
  • Règle de choix. La prochaine action est le nœud du champ forcé, s’il existe, est hors corbeille et candidat. Sinon, c’est le premier candidat hors corbeille, trié par sort (valeurs absentes en dernier, un texte sans casse, un enum dans l’ordre du schéma), puis par date de création et par id.
  • Candidat. Son état de workflow (aspect de from) est l’un de states. Sans states, il suffit qu’il soit absent ou non final (workflow.final, ADR 0026). Le projet déclare states: [a-faire, en-cours] : une tâche en attente ou mise de côté n’est pas une prochaine action, et un projet qui n’a qu’elle reste « sans prochaine action » dans la revue (relevé en revue).
  • Champ calculé <aspect>.nextAction. Le calcul est une sous-requête SQL corrélée, construite par ViewSql. Elle a deux usages :
    • dans les vues : on peut filtrer (projet.nextAction == null) et afficher le champ en colonne (type REF, avec le titre de la cible dans ViewResult.nodes). Il n’est ni triable ni modifiable. Le nom nextAction est réservé dans le schéma d’un aspect qui déclare la clé ;
    • sur la fiche : NodeView.nextActions donne, pour chaque aspect porté qui déclare la clé, son libellé et son nœud (nul s’il n’y en a pas). La fiche l’affiche en bandeau sous le titre : un lien, ou « aucune · ajoutez une tâche ouverte ou choisissez-en une ».
  • Contrôles au chargement, après la lecture de tous les aspects, puisque la clé en cite un autre : from est un champ référence d’un aspect chargé ; field est un champ référence de l’aspect ; states sont des états du workflow de l’aspect de from ; chaque clé de sort est un champ triable de l’aspect de from ; le nom nextAction est libre. Un aspect fautif est ignoré et signalé, comme tout fichier invalide. Le contrôle est répété tant qu’un aspect est écarté, puisqu’un aspect écarté peut invalider ceux qui le citent.
  • Traduction tolérante. Une version gardée au rechargement n’est pas recontrôlée contre les aspects frais : une clé de tri devenue inconnue est ignorée, et un aspect de from disparu donne « pas de prochaine action ». Il n’y a donc jamais d’erreur 500.
  • Index. Les candidats sont cherchés par contenance (data @> {"projet": "<id>"}), que sert l’index GIN de node_aspect.data. Le champ forcé est comparé à l’id typé (un texte qui n’est pas un UUID est ignoré), que sert la clé primaire.
  • Pourquoi calculer plutôt que stocker. Une prochaine action matérialisée devrait être recalculée à chaque écriture de tâche (état, échéance, projet, corbeille). C’est le terrain des règles du jalon 3. La sous-requête reste exacte et s’appuie sur les index existants.

Fréquence de revue et « Marquer revu »

  • Champs de projet : revueTousLes (entier, de 1 à 365, défaut 7), derniereRevue et prochaineRevue (dates), et prochaineAction (référence forcée vers une tâche).
  • « Marquer revu » est un bouton de report (ADR 0025). Il écrit derniereRevue: {{today}} et prochaineRevue: {{today + revueTousLes d}}.
  • Décalage nommé. Un bouton de report peut donner comme décalage un champ entier de son aspect : {{today + revueTousLes d}}. La valeur est lue dans les données de l’aspect, ou dans le default du schéma pour un projet antérieur au champ (ou dont la valeur est nulle). Elle est bornée à 9999 comme un littéral : une donnée ancienne démesurée laisse la variable non résolue, et la validation la refuse (400). Un modèle ne peut pas utiliser de décalage nommé : il n’a pas de données d’aspect, et la variable y reste inconnue. Le décalage nommé est contrôlé au chargement ; pour la validation, chaque champ entier vaut 1.
  • Projet dû. La revue montre un projet actif dont prochaineRevue est absente ou passée, ou qui n’a pas de prochaine action. Stocker la date de la prochaine revue garde la condition dans le langage de vue existant, sans arithmétique entre champs. En contrepartie, changer revueTousLes ne déplace pas la revue déjà prévue : la nouvelle fréquence s’applique au « Marquer revu » suivant, et la date reste modifiable à la main.

État « en attente » des tâches

L’étape « En attente » a besoin d’un état. tache.statut gagne donc en-attente (GTD : en attente de quelqu’un ou de quelque chose), qui est atteignable depuis et vers les états non terminés. Il n’est pas final. Le kanban « Tâches ouvertes » (ADR 0035) gagne la colonne correspondante, et sa condition inclut l’état : une carte glissée dans cette colonne reste sur le plateau.

Revues guidées : config/reviews/<name>.yaml

name: hebdomadaire
label: Revue hebdomadaire
icon: fact_check
description: …
steps:
  - { label: Inbox, inbox: true, help: … }
  - { label: En retard, view: revue-retards, help: … }
  • Définition. Un nouveau type de définition, avec son méta-schéma (review.schema.json, 12 étapes au plus) : chaque étape a soit inbox: true, soit le nom d’une vue chargée. GET /api/definitions/reviews les liste par libellé. Au rechargement, une revue gardée de la version précédente est revalidée contre les vues.
  • Quatre vues ordinaires portent la revue hebdomadaire : revue-retards, revue-sans-echeance, revue-projets et revue-en-attente.
  • Page /reviews/:name, accessible par le menu « Vue », section « Revues » :
    • en tête, la liste des étapes, chacune avec son compteur, puis « Résumé ». Tous les comptes sont lus à l’ouverture, et celui d’une étape est relu à chaque passage ;
    • une étape affiche sa consigne puis :
      • pour l’inbox, ses 50 derniers éléments et « Trier dans l’inbox » ;
      • pour une vue, ses lignes : badge de type, titre en lien, valeurs des colonnes en métadonnées et boutons de report des aspects de la vue que la ligne porte (« Demain », « Marquer revu »…). Un bouton dont le workflow interdit la transition depuis l’état affiché est désactivé ;
    • après une action, l’étape est relue et l’action est annoncée (role=status). Elle est relue aussi au retour sur l’onglet ;
    • « Étape précédente » et « Étape suivante » permettent de naviguer, et la dernière étape mène au résumé. Le résumé compare, étape par étape, le compte au début et le compte actuel, et signale les étapes vidées ;
    • l’état survit à une visite de fiche. L’étape est dans l’URL (?etape=), et les comptes du début sont gardés pour la session du navigateur, par revue. Ouvrir une ligne puis revenir ramène donc à la même étape, et le résumé compare toujours au vrai début. « Recommencer la revue » relit les comptes du début ;
    • accessibilité : un bouton de report que le workflow interdit depuis l’état affiché n’est pas montré. Après une action, le focus revient au titre de l’étape, car la ligne a pu disparaître. « (vidée) » est dit en texte, pas seulement par une icône.
  • Pourquoi des boutons de report sur les lignes. Ils couvrent les gestes de la revue (replanifier, mettre de côté, marquer revu) sans quitter l’étape, et ils sont déclarés dans config/. Classer l’inbox ou choisir une prochaine action reste dans la page Inbox et dans la fiche.

Reporté

  • Arithmétique entre champs dans where (derniereRevue <= today - revueTousLes d) : le décalage nommé suffit ici.
  • Création d’une tâche rattachée au projet depuis le bandeau « aucune prochaine action » : /nodes/new ne sait pas encore préremplir un champ référence.
  • Historique des revues (date et résumé de chaque revue faite), rappel hebdomadaire.
  • Compteur des revues dans GET /api/definitions/status.

Conséquences

  • Tout nouveau parcours en étapes se décrit dans config/reviews/ avec des vues, sans code.
  • Le moteur de vues connaît un champ calculé. Les champs calculés à venir (rollups, jalon 3) suivront le même chemin : résolution par Fields, SQL par ViewSql, ni tri ni édition par défaut.