Files
pgr/docs/architecture/003-RULE_PROFILE_MODEL.md

9.7 KiB

Modèle de profils de règles PGR

Rôle

Un profil PGR est un ensemble cohérent de règles réutilisables dont le scope est plus spécifique que les règles générales.

Un profil ne constitue ni un catalogue de dépendances, ni un template technique, ni un skeleton de projet. Il définit uniquement les règles durables réellement propres à un langage, un écosystème, une plateforme, un framework, un type de projet ou un sous-système.

Les règles générales restent héritées implicitement. Elles ne sont pas recopiées dans chaque profil.

Axes de spécialisation

La composition normative suit l'ordre général :

GENERAL
    ↓
ecosystem / language
    ↓
platform
    ↓
framework
    ↓
project type / subsystem
    ↓
project-specific
    ↓
explicit exception

Cet ordre exprime la spécificité des scopes. Il ne signifie pas qu'un projet doit posséder un profil à chaque niveau.

Un projet peut par exemple combiner uniquement :

GENERAL
+ Rust / Cargo

ou :

GENERAL
+ Java
+ Gradle
+ Android

Une technologie absente du projet ne rend aucun profil correspondant applicable.

Propriétaire normatif

Toute règle durable doit posséder un seul propriétaire normatif canonique.

Lorsqu'une règle est déjà correctement possédée par un document général, un profil spécifique doit la référencer si nécessaire, mais ne doit pas la recopier sous une formulation équivalente.

Inversement, une contrainte réellement propre à un profil ne doit pas être remontée vers un owner général uniquement pour réduire le nombre de fichiers.

Le propriétaire est choisi selon le scope le plus général dans lequel la règle reste vraie sans exception implicite.

Applicabilité

Un profil doit rendre son scope explicite : l'utilisateur ou le skeleton futur doit pouvoir déterminer à partir de faits du projet si le profil s'applique.

L'applicabilité doit reposer sur des propriétés concrètes, par exemple :

  • langage ou écosystème réellement utilisé ;
  • build tool réellement utilisé ;
  • plateforme réellement ciblée ;
  • framework réellement présent ;
  • type de projet ou sous-système réellement concerné.

PGR ne doit pas appliquer un profil uniquement parce qu'il est fréquent, recommandé ailleurs ou présent dans un projet source historique.

Composition et résolution

La résolution d'un ensemble de profils suit ces étapes :

  1. appliquer les règles générales ;
  2. ajouter les profils langage/écosystème applicables ;
  3. ajouter les profils plateforme applicables ;
  4. ajouter les profils framework applicables ;
  5. ajouter les profils de type de projet ou sous-système applicables ;
  6. appliquer les règles propres au projet ;
  7. appliquer les exceptions explicites et bornées.

Une règle plus spécifique peut raffiner, renforcer ou remplacer une règle plus générale dans son scope.

Lorsqu'elle contredit volontairement une règle héritée, le profil spécifique doit identifier l'override, son scope et sa raison. L'ordre des fichiers dans un répertoire ne crée jamais une priorité normative.

Deux règles applicables de même niveau qui se contredisent sans relation explicite ne sont pas départagées arbitrairement : la situation constitue un défaut de conformité ou de modélisation à résoudre.

Spécialisation interne à une famille

Une famille peut posséder plusieurs niveaux internes lorsque cela réduit la duplication.

Par exemple, un profil de langage peut être complété par un build tool particulier :

Java
    ↓
Maven

ou :

Java
    ↓
Gradle

Cette relation interne ne modifie pas la hiérarchie globale. Une contrainte de plateforme plus spécifique peut encore raffiner le résultat lorsqu'elle s'applique.

Lorsque langage et build tool sont pratiquement indissociables pour le scope visé, PGR peut les documenter dans un même profil si cette fusion évite une séparation artificielle. Le choix du découpage doit suivre les responsabilités réelles, pas une taxonomie rigide.

Baseline contrôlée et projet imposé

La même combinaison de technologies peut être gouvernée avec des degrés de liberté différents.

Pour une baseline créée et contrôlée par le projet, les profils sélectionnés s'appliquent intégralement puis une skeleton specification MAY fixer des choix réutilisables supplémentaires : layout, stack frontend, conventions de manifests ou organisation des fichiers.

Pour un projet existant ou imposé par un tiers, PGR doit d'abord préserver les contraintes externes réellement obligatoires. Toute divergence avec le profil préféré devient une règle project-specific ou une exception explicite et bornée ; elle ne modifie pas automatiquement le profil général.

Cette distinction évite deux erreurs opposées : forcer le skeleton interne d'une organisation sur un dépôt qu'elle ne contrôle pas, ou affaiblir ses propres conventions sous prétexte qu'un framework accepte plusieurs formes.

Profils composites

PGR ne crée pas automatiquement un profil composite pour chaque combinaison possible.

Un profil composite n'est justifié que lorsque l'intersection de plusieurs profils possède des règles propres qui ne peuvent être correctement possédées par chacun séparément.

Ainsi, la simple coexistence de Rust et Android ne suffit pas à créer un profil Rust + Android. Un tel profil devient pertinent seulement lorsqu'un contrat propre à leur interaction, par exemple une frontière FFI/JNI, doit être normé.

Choix ouverts

Un choix encore indécis n'est pas une règle.

Lorsqu'un profil révèle plusieurs options légitimes sans critère permettant d'en retenir une, PGR doit conserver la question comme décision ouverte, étude ou point de planification approprié plutôt que d'inventer une valeur par défaut arbitraire.

Une contrainte issue d'un framework, d'une plateforme ou d'un outil externe peut devenir une règle spécifique lorsque son caractère obligatoire est établi.

Non-duplication

Un profil doit contenir uniquement ce qui ajoute une information normative dans son scope.

Il ne doit pas recopier les règles générales relatives notamment à la gouvernance, aux documents, aux secrets, au lifecycle des releases ou à la validation lorsque ces règles s'appliquent déjà sans modification.

Une règle transversale découverte pendant la création de plusieurs profils doit être remontée vers un propriétaire commun uniquement si elle est réellement indépendante de ces profils.

Croissance documentaire

PGR matérialise uniquement les familles et profils possédant un contenu normatif réel.

Pour 0.0.2, les familles nécessaires sont :

500 — languages / ecosystems
600 — platforms

Les familles 700 — frameworks et 800 — architecture restent réservées tant qu'un premier profil réel ne justifie pas leur activation normative.

Le modèle architectural présent n'oblige pas à créer des fichiers placeholders pour les profils différés.

Réconciliation des profils matérialisés en 0.0.2

La première implémentation réelle du modèle comporte trois profils :

510 — Rust / Cargo
520 — Java / Maven / Gradle
610 — Android

Leur composition observée confirme que la taxonomie n'a pas besoin d'un profil composite supplémentaire dans 0.0.2.

Un projet Rust ordinaire peut appliquer :

GENERAL
+ 500
+ 510

Un projet Java/Gradle Android peut appliquer :

GENERAL
+ 500
+ 520
+ 600
+ 610

La forme condensée de cette composition est GENERAL + 500 + 520 + 600 + 610.

Le profil Android raffine localement les contraintes JDK/Gradle lorsque la matrice AGP/Gradle/JDK l'exige ; cette spécialisation ne modifie pas le profil Java/Gradle hors Android.

Aucune contradiction non résolue de même niveau n'a été identifiée entre les profils 510, 520 et 610.

La revue beta n'a pas justifié l'activation d'une famille 700 — frameworks ou 800 — architecture. Les règles réellement transversales rencontrées restent déjà possédées par RULES.md, les familles existantes ou le présent modèle architectural.

Activation de la famille framework en 0.0.5

La réconciliation indépendante de KSP et Games apporte le premier framework suffisamment répété pour activer la famille 700 : Tauri 2. Le profil 710-TAURI.md se compose au-dessus de Rust/Cargo et, selon les targets, des profils plateforme applicables.

Cette activation ne change pas la hiérarchie : Tauri ne devient propriétaire ni des règles Rust générales, ni d'Android, ni du choix du frontend. Il possède uniquement l'orchestration Tauri, sa configuration/capabilities, ses hooks, sa version applicative et les gates d'intégration propres au framework.

La famille 800 — architecture reste réservée : aucune règle nouvelle n'en justifie encore la matérialisation.

La réconciliation a également confirmé qu'une règle générale ne doit pas être recopiée comme si le profil spécifique en devenait propriétaire. Un profil peut rappeler une conséquence spécifique au contexte, mais doit référencer l'owner général lorsque le contrat lui-même n'est pas spécialisé.

Instanciation par skeleton

Les skeleton specifications sélectionnent les profils applicables et identifient les règles à reprendre ou adapter dans la baseline locale du projet créé. Leur contrat transversal de composition appartient à ../rules/220-SKELETONS.md ; le présent document reste propriétaire de la hiérarchie et de la résolution des profils eux-mêmes.

Le projet instancié reste autonome : la composition de profils sert à construire sa baseline initiale, pas à créer une dépendance dynamique vers PGR.