# 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 : ```text 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 : ```text GENERAL + Rust / Cargo ``` ou : ```text 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 : ```text Java ↓ Maven ``` ou : ```text 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 : ```text 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 : ```text 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 : ```text GENERAL + 500 + 510 ``` Un projet Java/Gradle Android peut appliquer : ```text 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. ## Scission Java / Maven / Gradle en `0.1.2` La réévaluation pratique de `0.1.2` confirme que le profil historique combiné `520 — Java / Maven / Gradle` ne constitue plus le meilleur owner courant. Maven et Gradle sont deux build tools interchangeables possédant chacun des règles propres significatives ; les rendre tous deux applicables par l'intermédiaire d'un unique profil Java crée une ambiguïté de sélection contraire au contrat de [`../rules/500-LANGUAGES.md`](../rules/500-LANGUAGES.md). Le découpage courant devient : ```text 520 — Java 521 — Maven 522 — Gradle ``` Les spécialisations de build restent dans la famille `500` et se composent explicitement avec le langage réellement utilisé. Par exemple : ```text GENERAL + 500 + 520 + 521 Java + Maven GENERAL + 500 + 520 + 522 Java + Gradle GENERAL + 500 + 520 + 522 + 600 + 610 Java + Gradle + Android ``` Un projet Gradle sans Java n'applique pas `520` uniquement parce qu'il utilise `522`. De même, Maven et Gradle ne sont jamais rendus applicables l'un par l'autre. Les contraintes Android restent possédées par `610` et raffinent `522`, ainsi que `520` uniquement lorsque Java est réellement présent. Cette scission remplace l'owner courant combiné sans réécrire les documents historiques qui décrivent fidèlement l'état `0.0.2` à `0.1.1`. L'ancien chemin `520-JAVA_MAVEN_GRADLE.md` reste un bridge `SUPERSEDED` non normatif afin de préserver leurs liens. ## 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é. ## Owners frontend matérialisés en `0.1.1` L'audit Games/KSP et la revue opérateur de `0.1.1-alpha.1` justifient quatre owners distincts dans la famille `500` : ```text 530 — TypeScript 540 — JavaScript package ecosystem 550 — Vite 560 — CSS / Sass ``` Cette séparation évite un profil monolithique « Web moderne » : TypeScript, Vite et Sass sont des recommandations fortes pour les nouveaux frontends contrôlés lorsqu'ils apportent une valeur proportionnée, mais chacun reste sélectionnable indépendamment. Le package manager est également indépendant et PGR n'impose pas npm. Une composition complète peut par exemple être : ```text GENERAL + 500 + 530 TypeScript + 540 JavaScript package ecosystem + 550 Vite + 560 CSS / Sass ``` Un frontend minimal peut n'en sélectionner qu'une partie. Un host Tauri qui utilise cette stack ajoute ensuite `700 + 710` sans transférer à Tauri l'ownership des règles frontend : ```text GENERAL + 500 + 510 + 530 + 540 + 550 + 560 + 700 + 710 ``` WASM et serveur Web Rust restent des responsabilités séparées et ne sont pas activés par cette composition. ## 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`](../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.