Aller au contenu

ADR-0014 — Cockpit de pilotage (portefeuille, charge, flux)

Statut : accepté (2026-06-15, arbitrages user) — cockpit complet (P0→P4) implémenté (2026-06-16) : moteur + oracles, grille de portefeuille, panneaux équipe & flux, décliné aux personas (client = son portefeuille ; junior/externe = les leurs ; senior = tout). Contexte : /cabinet est un outil de production unitaire — on prend une demande dans la file et on agit dessus. Le senior voit toutes les demandes (demandes_visibles ne filtre rien pour lui) mais sans vue agrégée : pas de portefeuille, pas de charge par junior, pas de métrique de flux. Le rail staff est identique pour junior/senior/externe — zéro différenciation de pilotage. Besoin : un cockpit pour piloter le portefeuille clients, la charge des juniors et des experts externes, et la performance — d'abord pour le senior, puis décliné à tous les personas.

🎯 À retenir

Le cockpit dérive toutes ses métriques du journal EvenementDemande (aucune nouvelle capture, tout est auditable). Un seul moteur + une seule grille scopés par persona (réutilise demandes_visibles). On mesure la santé du flux (temps de séjour par stade), jamais un classement de personnes.

La question

Comment ajouter une couche de pilotage sans (a) construire un système de capture de données parallèle, (b) contourner le workflow gardé, ni (c) instaurer une surveillance injuste des personnes ?

Décisions

# Décision Arbitrage
D-PILOT-1 Tout se dérive du journal EvenementDemande (event log horodaté, 10 types journaliséssoumission n'est qu'une notification e-mail, jamais un événement ; vérifié à la source 2026-06-16). Aucune nouvelle capture ; chaque métrique est retraçable à des événements (auditable). Pendant « ops » de la philosophie moteur-de-trace : on dérive depuis les faits, on ne stocke pas des compteurs. Subtilité confirmée : le statut soumis n'écrit aucun événement (sauf instigation cabinet → creation_pour_compte) ; l'horloge du premier stade s'ancre donc sur Demande.created_at, pas sur un événement. l'insight directeur
D-PILOT-2 Grille de portefeuille (lecture + drill), pas de tableur éditable. Tableau dense triable / filtrable / groupable, avec drill-down vers le Cabinet pour agir. On ne fait jamais avancer une demande en tapant dans une cellule — les transitions restent gardées (persona + statut, 403/409). user, 2026-06-15
D-PILOT-3 Métriques de santé du FLUX, pas de classement de PERSONNES. On mesure le temps de séjour par stade (où ça stagne : démarrage tardif ? revue qui traîne ? audit lent ?) — process-focused, juste, actionnable. Charge et débit objectifs ; signaux qualité (renvois, réserves) normalisés par complexité (effectif, genre mixte, causes). Distributions et tendances, jamais un score nu ni une alerte couperet tant qu'il n'y a pas de base de référence (les premières données servent à calibrer, pas à juger). user, 2026-06-15 ; cf. principes dashboards
D-PILOT-4 Un seul moteur + une seule grille, SCOPÉS par persona (réutilise demandes_visibles), pas quatre écrans bespoke. Senior = tout ; junior = son pipeline (auto-coaching) ; externe = ses audits ; client = son portefeuille. Une lentille, pas quatre layouts (leçon ADR-0010). Cockpit senior d'abord, décliné ensuite. user, 2026-06-15
D-PILOT-5 Section de rail dédiée « Pilotage », distincte du Cabinet : le Cabinet reste l'action unitaire, le Pilotage est la vue d'ensemble. séparation des intentions

Catalogue de métriques (tout dérivé du journal)

Famille Mesures Angle
Charge (courant, objectif) WIP par junior/externe, répartition par stade, âge du plus ancien en cours surcharge / dossiers qui dorment
Débit (historique, objectif) livrées / période, tendance capacité réelle
Cycle (par stade) dwell assignation→démarrage, démarrage→soumission_revue, revue→validation, transmission→audit où ça stagne (process)
Qualité (signal + contexte) taux de renvoi (critique_revue/livrées), taux de réserves (audit_reserves/transmissions) normalisé complexité
Valeur (portefeuille) DBO sous gestion par client/secteur/pays, # clients actifs segmentation business

⚠️ Piège

Le statut soumis n'écrit aucun événement (sauf instigation cabinet → creation_pour_compte). L'horloge du premier stade s'ancre donc sur Demande.created_at, pas sur un événement du journal — sinon le séjour initial serait invisible.

Le cœur testable : pour une demande, événements triés par created_at → séjours entre transitions consécutives (cycle = t(livraison) − t(soumission), renvois = count(critique_revue)…). Couche pure → oracles de cycle time sur des séquences de journal connues (comme les oracles K-* du moteur).

Mécanique (implémentée — P1 backend, P2-P3 front)

  • Backend app/pilotage.py : trois endpoints scopés par persona (demandes_visibles) — GET /api/pilotage/portefeuille (la grille, tous personas), GET /api/pilotage/equipe (charge par acteur, staff), GET /api/pilotage/flux (séjour par stade + débit, staff). Cœur pur (construire_sejours / metriques_demande, ancrage sur created_at) verrouillé par 10 oracles de cycle time.
  • Front : section « Pilotage » du rail staff, en trois feuilles sœurs /pilotage/{portefeuille,equipe,flux} — grille (tri/filtre/group-by junior·client·stade·secteur, tri par défaut sur l'âge, drill → /cabinet?demande=id), panneau équipe (charge en distributions) et panneau flux (« où ça stagne » ; état terminal livre exclu des barres).
  • Guide d'usage : Piloter le portefeuille.

Conséquences

  • + Le senior passe d'un outil de production à un outil de pilotage sans nouvelle saisie ; les métriques sont auditables (dérivées du journal immuable).
  • + Décliné à tous les personas presque gratuitement (le scope existe déjà).
  • −/assumé Dépend de la qualité des timestamps : un junior peut « démarrer » puis laisser dormir — le dwell le révèle, mais il faut calibrer avant de juger.
  • Phases : P1 moteur + oracles ✓ · P2 grille (senior) ✓ · P3 panneaux équipe & flux ✓ · P4 déclinaison junior/externe/client ✓ — cockpit complet.

Voir mémoire projet. S'appuie sur le workflow d'audit en chaîne (ADR-0006) et son journal EvenementDemande ; prolonge les vues par persona (ADR-0007).