50 Commits

Author SHA1 Message Date
4893a04f49 0.1.1 2026-09-27 12:27:09 +02:00
fbde0c2073 0.1.1-rc.1 2026-09-27 12:08:21 +02:00
9ef9549f2d 0.1.1-beta.1 2026-09-27 11:57:09 +02:00
55c6f7b05d 0.1.1-alpha.5 2026-09-27 11:43:09 +02:00
89b8ea88c1 0.1.1-alpha.4 2026-09-27 11:33:12 +02:00
56e3d37879 0.1.1-alpha.3.fix.2 2026-09-27 11:15:26 +02:00
889d9cbcbd 0.1.1-alpha.3.fix.1 2026-09-27 11:03:58 +02:00
5033547534 0.1.1-alpha.3 2026-09-27 10:56:05 +02:00
e351f57be4 0.1.1-alpha.2.fix.1 2026-09-27 10:42:38 +02:00
dc63b543ac 0.1.1-alpha.2 2026-09-27 10:18:43 +02:00
7b7565d5d4 0.1.1-alpha.1 2026-09-27 10:09:35 +02:00
2ed8742f3b 0.1.0 2026-09-26 23:31:54 +02:00
d5e1fc4300 0.1.0-rc.1 2026-09-26 23:26:23 +02:00
5393257d93 0.1.0-beta.1 2026-09-26 23:10:02 +02:00
a65a183ee4 0.1.0-alpha.5 2026-09-26 20:33:53 +02:00
e4b5992266 0.1.0-alpha.4 2026-09-26 19:31:22 +02:00
351025b4f2 0.1.0-alpha.3.fix.1 2026-09-26 19:19:20 +02:00
f37481627a 0.1.0-alpha.3 2026-09-26 19:06:59 +02:00
3230356cd6 0.1.0-alpha.2.fix.1 2026-09-26 19:00:32 +02:00
62f3d252d8 0.1.0-alpha.2 2026-09-26 17:33:23 +02:00
c22cf39ba9 0.1.0-alpha.1 2026-09-26 17:25:10 +02:00
9a7f4f7c67 0.0.5-rel.001.fix.1 2026-09-25 18:27:36 +02:00
436680207f 0.0.5-rel.001 2026-09-25 18:24:10 +02:00
390dd63e21 0.0.5-rc.1 2026-09-25 18:13:53 +02:00
c97ca5f21a 0.0.5-beta.1 2026-09-25 18:07:50 +02:00
5a83968813 0.0.5-alpha.9 2026-09-25 18:00:24 +02:00
9f596f30b2 0.0.5-alpha.9 2026-09-25 17:59:25 +02:00
c331da5114 0.0.5-alpha.8 2026-09-25 17:41:26 +02:00
ecd9de4d4e 0.0.5-alpha.7.fix.1 2026-09-25 17:22:10 +02:00
ac03b78708 0.0.5-alpha.7 2026-09-25 11:45:10 +02:00
4e1c1cd6f0 0.0.5-alpha.6.fix.3 2026-09-25 10:47:38 +02:00
b7e65d9100 0.0.5-alpha.6.fix.2 2026-09-25 10:35:20 +02:00
33bf835b7f 0.0.5-alpha.6.fix.1 2026-09-25 10:19:35 +02:00
0f6a2e21eb 0.0.5-alpha.6 2026-09-25 09:16:06 +02:00
81c7a720f5 0.0.5-alpha.5.fix.1 2026-09-25 08:14:57 +02:00
f03f8640d4 0.0.5-alpha.5 2026-09-25 00:36:24 +02:00
defc9ca4b5 0.0.5-alpha.4 2026-09-25 00:03:51 +02:00
a954d7f90a 0.0.5-alpha.3.fix.1 2026-09-24 23:40:02 +02:00
1b1a7092e5 0.0.5-alpha.3 2026-09-24 22:23:59 +02:00
d7282dc33b 0.0.5-alpha.2 2026-09-24 21:21:44 +02:00
3ca2518c5c 0.0.5-alpha.1 2026-09-24 20:43:57 +02:00
bd9aadf0cf 0.0.4 2026-09-24 17:50:47 +02:00
c6af96b6bc 0.0.4-rc.1 2026-09-24 17:45:22 +02:00
3f8fa6b34e 0.0.4-beta.1.fix.1 2026-09-24 17:38:05 +02:00
fdaaa357d4 0.0.4-beta.1 2026-09-24 15:07:20 +02:00
ea80396828 0.0.4-alpha.4.fix.1 2026-09-24 14:57:25 +02:00
c0735d1d63 0.0.4-alpha.4 2026-09-24 14:48:17 +02:00
5471ea6283 0.0.4-alpha.3 2026-09-24 14:39:29 +02:00
7408616909 0.0.4-alpha.2 2026-09-24 14:30:13 +02:00
bf306daea6 0.0.4-alpha.1 2026-09-24 14:02:30 +02:00
161 changed files with 22977 additions and 99 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: CHANGELOG.md -->
<!-- version: 5 -->
<!-- version: 13 -->
# Changelog Project Governance Rules
@@ -7,6 +7,41 @@ Ce fichier décrit les changements utiles aux utilisateurs ou intégrateurs des
Les tranches `alpha`, `beta`, `rc`, fixes, validations, audits et détails de développement appartiennent aux plans, deltas et historiques. Ils ne sont pas recopiés ici par défaut.
## 0.1.1
- établit une fondation frontend Web composable avec quatre owners indépendants : TypeScript, écosystème de package JavaScript, Vite et CSS/Sass, sans transformer un outil concret en obligation universelle ;
- recommande TypeScript pour les frontends durables avec vérification stricte et `noEmit`, tout en distinguant les types embarqués des packages `@types/*` réellement nécessaires à l'analyse, à l'intégration IDE et aux API consommées ;
- formalise un écosystème de package neutre vis-à-vis de npm/pnpm/yarn, un script `typecheck` indépendant et une politique de lockfile dépendant du rôle application/bibliothèque plutôt qu'une règle unique artificielle ;
- recommande Vite lorsque son modèle convient, avec ownership explicite du dev server, du cache, des outputs, des assets et des paramètres de sécurité, sans fournir de `vite.config.ts`, port, `base` ou layout universels ;
- conserve CSS comme baseline valide et recommande Sass lorsqu'il apporte une valeur réelle, notamment pour les packages exposant une API Sass, avec préférence pour `@use` / `@forward` et séparation stricte entre sources et styles générés ;
- ajoute une validation frontend indépendante du host et un skeleton Web composable, puis confirme que les cinq prérequis Web du futur réexamen Tauri sont couverts sans lever le `DEFER`, qui reste réservé à `0.1.4`.
## 0.1.0
- établit la première baseline PGR réellement réutilisable pour initialiser de nouveaux projets et adopter progressivement des projets existants, avec une fondation de gouvernance, des skeleton specifications composables et une validation proportionnée ;
- stabilise le socle Rust/Cargo réutilisable : cinq templates techniques, composition `001 + 002`, dry-run `NEW` avec Cargo/rustfmt/Clippy et chemin `ADOPTION` non destructif ;
- formalise l'adoption de projets existants avec baseline autoritaire, migration progressive et décisions `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`, sans réécriture rétroactive de l'historique ;
- corrige la convention de clôture stable vers `rel.N` sans zéro de padding et garantit que la première clôture qui obtient réellement `PASS` produit le commit produit `X.Y.Z` avant le tag `vX.Y.Z` ;
- rend obligatoire le handoff automatique des commandes opérateur entre history, commit/push, delta suivant et publication stable, avec distinction entre objet tag, commit déréférencé et rapport `publish.*` post-tag ;
- matérialise la revue d'horizon suivante : frontend Web, Java/Gradle, Android, Tauri conditionnel, adoption Games puis KSP et audits Rust/Clippy statiques Python-only, tout en laissant WASM, serveur Rust et deployment/operations sans réservation prématurée.
## 0.0.5
- consolide le lifecycle inter-release de PGR : prompts de reprise versionnés, contrats locaux de fichiers/familles, responsabilités de fermeture et revue d'horizon sans création artificielle de releases futures ;
- renforce le profil Rust/Cargo des nouveaux projets contrôlés avec Rust 2024, chemins explicites, façade crate-root, contrats de suffixes de crates, séparation bibliothèque/exécutable, erreurs explicites et ownership du tracing ;
- ajoute et sépare les validations Rust structurelles utiles : complétude des réexports/chemins `crate::Item`, espacement des items, ordre des modules, blocs d'imports de traits et blocs de réexports, tout en conservant les contrôles à ordre sémantique comme opt-in ;
- active les profils framework et Tauri 2, avec host Rust direct, frontière frontend explicite, TS-RS pour les DTO partagés, plugins/capabilities gouvernés, versions produit classifiées et exception Tauri encadrée au principe de séparation `lib`/`bin` ;
- enregistre le skeleton Tauri contrôlé comme trajectoire `DEFER` jusqu'à matérialisation d'owners Web suffisants, sans créer de skeleton décoratif ni réserver une release ;
- réconcilie les décisions avec les corpus KSP/Games, conserve leurs architectures métier locales hors du noyau PGR et prépare le prompt de reprise `006` vers la première baseline réutilisable `0.1.0`.
## 0.0.4
- définit un contrat transversal de skeleton specifications pour sélectionner et composer règles, profils, templates, décisions destinataire, overrides et validation sans dupliquer les propriétaires normatifs ;
- ajoute une fondation composable de gouvernance locale pour initialiser version, documentation minimale, workflow retenu et validation proportionnée d'un projet utilisant PGR ;
- ajoute une spécialisation Rust/Cargo workspace composant la fondation avec les profils `500 + 510` et les cinq templates Rust/Cargo existants ;
- explicite les décisions à adapter avant instanciation, notamment version, édition/toolchain, membres, métadonnées, dépendances/features, `Cargo.lock`, lints, chemins d'artefacts et audits facultatifs ;
- conserve Java/Maven/Gradle, Android, Web, JNI, Tauri et les autres familles insuffisamment matérialisées comme domaines différés plutôt que créer des skeletons prématurés.
## 0.0.3
- fournit cinq fichiers modèles Rust/Cargo : `rustfmt.toml`, `clippy.toml`, `.cargo/config.toml`, un manifest workspace et un manifest de crate membre, avec instructions d'adaptation ;

View File

@@ -1,5 +1,5 @@
<!-- file: README.md -->
<!-- version: 6 -->
<!-- version: 19 -->
# Project Governance Rules
@@ -11,9 +11,9 @@ Le dépôt officiel est `https://git.sasedev.com/Sasedev/pgr`.
## Statut
PGR est actuellement en phase de fondation `0.0.x`.
PGR a clôturé sa phase de fondation `0.0.x`, dispose avec `0.1.0` de sa première baseline réutilisable stable et avec `0.1.1` d’une fondation frontend Web stable, composable et indépendante du host.
La version courante est définie par [`VERSION`](VERSION). La release `0.0.1` établit la gouvernance normative et documentaire de PGR lui-même. La release `0.0.2` ajoute les premiers profils réutilisables Rust/Cargo, Java/Maven/Gradle et Android, ainsi que deux audits Markdown. La release `0.0.3` fournit les premiers modèles Rust/Cargo, deux audits de style Rust facultatifs, l'audit des headers Markdown et la spécification du message manuel de reprise. La série `0.0.x` se poursuit avec les spécifications de skeletons prévues pour `0.0.4`.
La version courante est définie par [`VERSION`](VERSION). La release `0.0.1` établit la gouvernance normative et documentaire de PGR lui-même. La release `0.0.2` ajoute les premiers profils réutilisables Rust/Cargo, Java/Maven/Gradle et Android, ainsi que deux audits Markdown. La release `0.0.3` fournit les premiers modèles Rust/Cargo, deux audits de style Rust facultatifs, l'audit des headers Markdown et la spécification du message manuel de reprise. La release `0.0.4` définit le contrat transversal des skeleton specifications, ajoute une fondation composable de gouvernance locale et une première spécialisation Rust/Cargo workspace fondée sur les profils `500 + 510` et les cinq templates existants. La release `0.0.5` réconcilie PGR avec les baselines réelles de `khadhroony-solana-project` et `sasedev-games` : prompts versionnés, contrats documentaires locaux, lifecycle inter-release, profil Rust strict et audits monotâches, premier profil Tauri 2 et décision explicite de différer son skeleton complet jusqu'à matérialisation d'owners Web suffisants. La release `0.1.0` stabilise la première baseline réutilisable : adoption `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`, skeletons/templates Rust/Cargo exercés par dry-run, clôture `rel.N`, handoff opérateur automatique et trajectoire `0.1.1` à `0.1.7` issue d'une revue d'horizon explicite. La release `0.1.1` stabilise la fondation frontend Web : owners indépendants TypeScript/package/Vite/CSS-Sass, déclarations de types externes conditionnelles, package manager neutre, validation frontend indépendante du host et skeleton Web composable, tout en conservant le skeleton Tauri en `DEFER` jusqu’à son réexamen `0.1.4`.
## Entrées principales
@@ -27,6 +27,15 @@ La version courante est définie par [`VERSION`](VERSION). La release `0.0.1` é
- [`docs/plans/001-V0_0_1_FOUNDATION_PLAN.md`](docs/plans/001-V0_0_1_FOUNDATION_PLAN.md) — plan historique de fondation `0.0.1` ;
- [`docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md`](docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md) — plan historique des premiers profils `0.0.2` ;
- [`docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md`](docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md) — plan historique des templates et audits `0.0.3` ;
- [`docs/plans/004-V0_0_4_SKELETONS_PLAN.md`](docs/plans/004-V0_0_4_SKELETONS_PLAN.md) — plan historique des skeleton specifications `0.0.4` ;
- [`docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md`](docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md) — plan historique de réconciliation `0.0.5` ;
- [`docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md`](docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md) — plan historique de la première baseline réutilisable `0.1.0` ;
- [`docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md`](docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md) — plan historique de la fondation frontend Web stable `0.1.1` ;
- [`docs/studies/001-KSP_GAMES_RECONCILIATION.md`](docs/studies/001-KSP_GAMES_RECONCILIATION.md) — étude de réconciliation et classification des écarts entre PGR, KSP et Games ;
- [`docs/skeletons/000-README.md`](docs/skeletons/000-README.md) — index des skeleton specifications et de leur contrat de composition ;
- [`docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md`](docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md) — fondation composable de gouvernance locale pour un projet adoptant PGR ;
- [`docs/skeletons/002-RUST_CARGO_WORKSPACE.md`](docs/skeletons/002-RUST_CARGO_WORKSPACE.md) — specialization composable pour un workspace Rust/Cargo gouverné ;
- [`docs/skeletons/003-WEB_FRONTEND.md`](docs/skeletons/003-WEB_FRONTEND.md) — specialization composable pour un frontend Web contrôlé, avec TypeScript/Vite recommandés, Sass optionnel et validation indépendante du host ;
- [`docs/validation/001-VALIDATION_MATRIX.md`](docs/validation/001-VALIDATION_MATRIX.md) — matrice de validation.
## Langue et nomenclature

View File

@@ -1,9 +1,9 @@
<!-- file: ROADMAP.md -->
<!-- version: 4 -->
<!-- version: 12 -->
# Roadmap Project Governance Rules
Le roadmap décrit le découpage macro des releases PGR. Il ne remplace ni les objectifs globaux du projet ni les plans détaillés de version.
Le roadmap décrit le découpage macro engagé des releases PGR. Il ne remplace ni les objectifs globaux du projet ni les plans détaillés de version et ne sert pas à inventer des versions futures uniquement pour prolonger l'horizon.
Statuts : `( )` planifié, `(x)` terminé, `(d)` différé, `(c)` annulé.
@@ -12,11 +12,35 @@ Statuts : `( )` planifié, `(x)` terminé, `(d)` différé, `(c)` annulé.
- `(x) 0.0.1` — fondation normative et documentaire : gouvernance, lifecycle des releases, rôles documentaires, workflow delta/history/handoff et validation proportionnée ;
- `(x) 0.0.2` — premiers profils de règles réutilisables : Rust/Cargo, Java/Maven/Gradle et Android, avec modèle de composition et audits Markdown initiaux ;
- `(x) 0.0.3` — templates techniques initiaux et premiers patterns d'audit réutilisables issus de besoins réels ;
- `( ) 0.0.4` — spécifications Markdown de skeletons et règles de composition des profils/templates ;
- `( ) 0.0.5` — réconciliation réelle de PGR avec `khadhroony-solana-project` et `sasedev-games`.
- `(x) 0.0.4` — spécifications Markdown de skeletons et règles de composition des profils/templates ;
- `(x) 0.0.5` — réconciliation réelle de PGR avec `khadhroony-solana-project` et `sasedev-games`, incluant la consolidation du lifecycle inter-release et de la revue d'horizon.
## Première baseline réutilisable
- `( ) 0.1.0` — première baseline PGR destinée à initialiser de nouveaux projets à partir de règles, templates et skeleton specifications éprouvés.
- `(x) 0.1.0` — première baseline PGR destinée à initialiser de nouveaux projets et à adopter progressivement des projets existants à partir de règles, templates, skeleton specifications et validations éprouvés.
## Trajectoire engagée `0.1.x`
La revue d'horizon de `0.1.0-beta.1` engage les releases suivantes, chacune avec un domaine cohérent et une session/release indépendante :
- `(x) 0.1.1` — fondation frontend Web : TypeScript, Vite, Sass/CSS, package/build outputs et validation frontend indépendante ;
- `( ) 0.1.2` — réévaluation pratique du profil Java/Maven/Gradle existant et matérialisation des artefacts génériques réellement nécessaires ;
- `( ) 0.1.3` — réévaluation pratique du profil Android existant à partir de Games, sans absorber les décisions propres aux jeux ou à SDL ;
- `( ) 0.1.4` — domaine Tauri : réexamen du `DEFER` et matérialisation du skeleton contrôlé seulement si les owners Web issus de `0.1.1` satisfont réellement les conditions de sortie ;
- `( ) 0.1.5` — adoption réelle de PGR par `sasedev-games` avec mapping `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` ;
- `( ) 0.1.6` — adoption réelle de PGR par `khadhroony-solana-project`, principalement sur Rust/Cargo + Tauri et sans dépendance aux profils non applicables ;
- `( ) 0.1.7` — audits Python read-only d'un sous-ensemble statique des conventions Rust/Clippy, après les deux adoptions, sans prétendre remplacer `cargo clippy`.
Le détail et les conditions de cette séquence sont conservés dans [`docs/studies/003-V0_1_0_HORIZON_REVIEW.md`](docs/studies/003-V0_1_0_HORIZON_REVIEW.md).
## Trajectoires différées ou non numérotées
- `(d) skeleton Tauri jusqu'au réexamen 0.1.4` — le `DEFER` de `0.0.5-alpha.9` a été maintenu pendant `0.1.1`; `0.1.1-beta.1` confirme que ses cinq prérequis Web disposent désormais d'owners PGR, mais seul `0.1.4` peut réexaminer le candidat à partir du corpus alors courant ;
- `WASM` — candidat séparé à réévaluer pendant l'adoption Games si un owner PGR apporte une valeur immédiate ;
- `serveur Web Rust / Actix Web ou alternative` — candidat à partir d'un corpus d'implémentation réel, pas sur la seule base d'une trajectoire roadmap ;
- `saselang-bible`, projets documentaires/spécifications et généricité hors logiciel — candidats d'une trajectoire ultérieure `0.2.x` / `0.3.x` à décider ;
- `deployment & operations` — famille future pour reverse proxies, bases de données, Docker/Compose, services Linux, secrets, migrations/backups, health et observabilité ; un horizon `0.4.x` ou `0.5.x` est plausible mais aucun numéro précis n'est réservé.
Une nouvelle revue d'horizon doit intervenir si un prérequis réel invalide l'ordre engagé, notamment si `0.1.1` doit être scindée, si `0.1.4` ne peut pas lever le `DEFER` Tauri ou si Games exige un owner WASM/serveur avant une adoption proportionnée.
Le contenu détaillé et le nombre de tranches de chaque release sont définis par son plan actif, créé ou consolidé pendant `alpha.1`.

View File

@@ -1,5 +1,5 @@
<!-- file: RULES.md -->
<!-- version: 9 -->
<!-- version: 13 -->
# Index normatif Project Governance Rules
@@ -76,13 +76,21 @@ Familles actuellement actives :
- [`docs/rules/200-GOVERNANCE.md`](docs/rules/200-GOVERNANCE.md) — versioning, lifecycle des releases, fixes, cadrage, replan et abandon/supersession.
- [`docs/rules/210-WORKFLOW.md`](docs/rules/210-WORKFLOW.md) — plans, deltas, histories, prompts, handoffs, manifests, commits, baselines et reprise de session.
- [`docs/rules/220-SKELETONS.md`](docs/rules/220-SKELETONS.md) — sélection, composition, adaptation et validation des skeleton specifications.
- [`docs/rules/230-ADOPTION.md`](docs/rules/230-ADOPTION.md) — adoption proportionnée de PGR par un projet existant, mapping des owners, décisions locales et migration progressive.
- [`docs/rules/300-DOCUMENTATION.md`](docs/rules/300-DOCUMENTATION.md) — rôles documentaires, taxonomie, révisions internes, documents vivants et conservation historique.
- [`docs/rules/400-VALIDATION.md`](docs/rules/400-VALIDATION.md) — sélection proportionnelle des preuves, catégories de validation, tests utiles, doubles de test et autorité opérateur.
- [`docs/rules/500-LANGUAGES.md`](docs/rules/500-LANGUAGES.md) — contrat commun des profils langage, écosystème et spécialisations de build associées.
- [`docs/rules/510-RUST_CARGO.md`](docs/rules/510-RUST_CARGO.md) — profil Rust/Cargo : workspace, manifests, dépendances, lints, API, formatage, tests et validation spécialisée.
- [`docs/rules/520-JAVA_MAVEN_GRADLE.md`](docs/rules/520-JAVA_MAVEN_GRADLE.md) — profil Java et spécialisations Maven/Gradle : toolchain LTS, structure, dépendances, tests et validation de build.
- [`docs/rules/530-TYPESCRIPT.md`](docs/rules/530-TYPESCRIPT.md) — profil TypeScript : recommandation contrôlée, type-check et frontières typées.
- [`docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md) — manifest `package.json`, sélection du package manager, dépendances et responsabilité du lockfile.
- [`docs/rules/550-VITE.md`](docs/rules/550-VITE.md) — profil Vite : build tool/dev server recommandé, cache, outputs et frontière avec le host.
- [`docs/rules/560-CSS_SASS.md`](docs/rules/560-CSS_SASS.md) — profil CSS/Sass : styles sources, prétraitement optionnel recommandé et dépendances de styles.
- [`docs/rules/600-PLATFORMS.md`](docs/rules/600-PLATFORMS.md) — contrat commun des profils plateforme et de leur compatibilité de target/runtime.
- [`docs/rules/610-ANDROID.md`](docs/rules/610-ANDROID.md) — profil Android : structure, toolchain/SDK, compatibilité, packaging, configuration locale et validation plateforme.
- [`docs/rules/700-FRAMEWORKS.md`](docs/rules/700-FRAMEWORKS.md) — contrat commun des profils framework et de leur orchestration avec langages, plateformes et outils de build.
- [`docs/rules/710-TAURI.md`](docs/rules/710-TAURI.md) — profil Tauri 2 : host Rust, configuration/capabilities, hooks frontend, version produit, artefacts générés et validation d'intégration.
Le modèle de composition et d'ownership des profils est défini dans [`docs/architecture/003-RULE_PROFILE_MODEL.md`](docs/architecture/003-RULE_PROFILE_MODEL.md).

View File

@@ -1 +1 @@
0.0.3
0.1.1

150
deltas/0.0.4/alpha.1.md Normal file
View File

@@ -0,0 +1,150 @@
<!-- file: deltas/0.0.4/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.1 — audit de baseline et cadrage des skeletons
## Baseline et version
Baseline : archive source fournie `pgr-v0.0.3.zip`, déclarée téléchargée depuis le tag Gitea `v0.0.3`, accompagnée du rapport externe `pgr-0.0.3-publish.001-report.md` avec statut `PASS`.
SHA-256 vérifié de l'archive :
```text
517fb46ada098fdc221ae53a8ff4b409b81e0244ec5ce4d0e6fca0c3da61b866
```
Le rapport post-tag annonce le même hash et reste extérieur à la stable. L'archive sans `.git` est contrôlée par son contenu ; elle n'est pas utilisée comme preuve autonome du commit ou de la référence distante du tag.
Version avant application :
```text
0.0.3
```
Version après application :
```text
0.0.4-alpha.1
```
## Objet
Exécuter la gate de cadrage imposée par `prompts/004-V0_0_4_START_PROMPT.md` avant toute matérialisation importante : vérifier la stable, les règles `200` à `610`, la gouvernance documentaire, les templates et audits existants, la chaîne delta/history et les limites annoncées ; déterminer ensuite quels skeletons disposent déjà d'entrées suffisantes et planifier les tranches de `0.0.4`.
Le résultat détaillé de cette revue et le découpage prévisionnel sont consignés dans `docs/plans/004-V0_0_4_SKELETONS_PLAN.md`. Aucun défaut bloquant de `0.0.3` n'impose une correction rétroactive avant ce cadrage.
Le plan retient comme premières cibles la fondation composable d'un projet gouverné PGR puis un skeleton Rust/Cargo workspace. Java/Maven/Gradle, Android, Web, JNI, Tauri et les autres familles sans pièces suffisantes restent différés.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
```
ADD :
```text
docs/plans/004-V0_0_4_SKELETONS_PLAN.md
deltas/0.0.4/alpha.1.md
```
DELETE : aucun.
L'archive delta contient uniquement ces cinq fichiers complets avec leurs chemins relatifs. Aucun history, skeleton concret, nouvelle règle, template technique, script ou manifest de suppression n'appartient à `alpha.1`.
`README.md` et `docs/000-README.md` sont des documents vivants : ils ajoutent le plan actif comme point d'entrée. `ROADMAP.md` annonce déjà `0.0.4` comme planifiée et `CHANGELOG.md` reste limité aux releases publiées ; ils n'ont pas besoin d'une modification cérémonielle dans cette tranche.
## Validation opérateur
Après application sur le commit stable `0.0.3`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.4-alpha.1'
test -f docs/plans/004-V0_0_4_SKELETONS_PLAN.md
test -f deltas/0.0.4/alpha.1.md
test ! -e history/0.0.4/alpha.1.md
grep -Fx '<!-- version: 7 -->' README.md
grep -Fx '<!-- version: 5 -->' docs/000-README.md
grep -F '004-V0_0_4_SKELETONS_PLAN.md' README.md
grep -F '004-V0_0_4_SKELETONS_PLAN.md' docs/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
expected_counts = {'0.0.1': 12, '0.0.2': 12, '0.0.3': 10}
for release, expected in expected_counts.items():
deltas = {path.name for path in Path('deltas', release).glob('*.md')}
histories = {path.name for path in Path('history', release).glob('*.md')}
assert len(deltas) == expected, (release, len(deltas))
assert deltas == histories, (release, sorted(deltas ^ histories))
for path in Path('history/0.0.3').glob('*.md'):
text = path.read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', text), path
for path in (
Path('scripts/audit_rust_blank_lines.py'),
Path('scripts/audit_rust_const_blocks.py'),
Path('scripts/_rust_audit_common.py'),
):
assert path.is_file(), path
print('Baseline structural audit: clean (34 prior delta/history pairs, 10/10 histories 0.0.3 PASS, 5 TOML parsed)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/004-V0_0_4_SKELETONS_PLAN.md deltas/0.0.4/alpha.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M README.md
M VERSION
A deltas/0.0.4/alpha.1.md
M docs/000-README.md
A docs/plans/004-V0_0_4_SKELETONS_PLAN.md
```
La vérification du ZIP et du rapport post-tag appartient à l'intake de cette tranche et a été utilisée pour préparer le plan. L'opérateur confirme également que les fichiers fournis sont bien ceux téléchargés pour la reprise, que le hash de l'archive concorde avec le rapport, que le rapport est `PASS` et qu'il n'est pas copié dans le dépôt.
La revue opérateur doit confirmer que le plan ne transforme pas une prévision en règle active, que les valeurs Rust/Cargo d'exemple restent adaptables et que les domaines différés ne sont pas matérialisés par anticipation.
## Transition
### PASS
Rédiger et livrer séparément `history/0.0.4/alpha.1.md` avec les résultats réellement observés ; l'appliquer et committer la tranche. Préparer seulement ensuite `0.0.4-alpha.2` pour le contrat de composition des skeletons.
### FAIL
Consigner le résultat réel dans le history de `alpha.1`, puis corriger le cadrage dans `0.0.4-alpha.1.fix.1` ou produire un REPLAN motivé. Aucun contenu de `alpha.2` ne doit être absorbé silencieusement dans un fix.

189
deltas/0.0.4/alpha.2.md Normal file
View File

@@ -0,0 +1,189 @@
<!-- file: deltas/0.0.4/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.2 — contrat de composition des skeletons
## Baseline et version
Baseline : commit opérateur `bf306da` (`0.0.4-alpha.1`) après application de `history/0.0.4/alpha.1.md` avec statut `PASS`, puis push sur `origin/master`.
La baseline attendue contient donc le delta, le plan et le history de `alpha.1`, sans contenu `alpha.2` préalable.
Version avant application :
```text
0.0.4-alpha.1
```
Version après application :
```text
0.0.4-alpha.2
```
## Objet
Matérialiser le contrat transversal annoncé par le plan `0.0.4` sans anticiper les skeletons concrets des tranches suivantes.
La tranche crée `docs/rules/220-SKELETONS.md` comme propriétaire normatif unique de l'applicabilité, de la sélection, de la composition, des décisions projet, des overrides et de la validation initiale des skeleton specifications. Elle active également `docs/skeletons/` avec un index réel décrivant la responsabilité de la collection.
Les index normatifs et documentaires ainsi que les deux documents d'architecture concernés sont réconciliés avec ce nouveau propriétaire. Le modèle des profils reste possédé par `docs/architecture/003-RULE_PROFILE_MODEL.md` ; le nouveau document `220` le référence au lieu de dupliquer sa hiérarchie.
Aucun skeleton de fondation, Rust/Cargo, Java/Android, Web, JNI, Tauri ou autre domaine technologique n'appartient à cette tranche.
## Scope
REPLACE :
```text
VERSION
README.md
RULES.md
docs/000-README.md
docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/rules/000-README.md
```
ADD :
```text
docs/rules/220-SKELETONS.md
docs/skeletons/000-README.md
deltas/0.0.4/alpha.2.md
```
DELETE : aucun.
L'archive delta contient uniquement ces dix fichiers complets avec leurs chemins relatifs. Elle ne contient pas `history/0.0.4/alpha.1.md`, déjà committé dans la baseline, ni `history/0.0.4/alpha.2.md`, qui sera produit après la gate opérateur.
Le plan `docs/plans/004-V0_0_4_SKELETONS_PLAN.md` n'est pas modifié : la tranche réalise son étape `alpha.2` sans replan ni changement substantiel de trajectoire.
## Décisions normatives matérialisées
Le contrat commun impose notamment qu'un skeleton :
- déclare son objectif et son applicabilité à partir de faits du projet ;
- identifie les règles, profils, templates, fichiers, décisions, options, overrides, ordre utile, validation et hors-scope nécessaires ;
- référence les owners normatifs existants au lieu de devenir propriétaire implicite de leurs règles ;
- conserve les projets instanciés autonomes et sans dépendance runtime/build vers PGR ;
- distingue les valeurs obligatoires, exemples, recommandations et choix libres lorsqu'une confusion serait possible ;
- n'applique pas tous les profils PGR par défaut ;
- n'utilise pas l'ordre de composition comme priorité normative implicite ;
- ne crée pas de skeleton composite sans interaction réelle à posséder ;
- utilise une validation proportionnée au contenu réellement matérialisé.
La collection `docs/skeletons/` reste vide de specification concrète dans `alpha.2` hormis son index. Sa création n'est pas un placeholder : l'index documente le contrat de collection réellement activé par le nouveau owner normatif.
## Validation opérateur
Après application sur le commit `bf306da`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.4-alpha.2'
test -f history/0.0.4/alpha.1.md
test -f deltas/0.0.4/alpha.2.md
test -f docs/rules/220-SKELETONS.md
test -f docs/skeletons/000-README.md
test ! -e history/0.0.4/alpha.2.md
test ! -e docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
test ! -e docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 8 -->' README.md
grep -Fx '<!-- version: 10 -->' RULES.md
grep -Fx '<!-- version: 6 -->' docs/000-README.md
grep -Fx '<!-- version: 3 -->' docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
grep -Fx '<!-- version: 3 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 11 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 1 -->' docs/rules/220-SKELETONS.md
grep -Fx '<!-- version: 1 -->' docs/skeletons/000-README.md
grep -F 'docs/rules/220-SKELETONS.md' RULES.md
grep -F '220-SKELETONS.md' docs/rules/000-README.md
grep -F 'skeletons/' docs/000-README.md
grep -F '220-SKELETONS.md' docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
grep -F '220-SKELETONS.md' docs/architecture/003-RULE_PROFILE_MODEL.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
expected_counts = {'0.0.1': 12, '0.0.2': 12, '0.0.3': 10, '0.0.4': 1}
for release, expected in expected_counts.items():
histories = {path.name for path in Path('history', release).glob('*.md')}
if release == '0.0.4':
assert histories == {'alpha.1.md'}, histories
continue
deltas = {path.name for path in Path('deltas', release).glob('*.md')}
assert len(deltas) == expected, (release, len(deltas))
assert deltas == histories, (release, sorted(deltas ^ histories))
text = Path('history/0.0.4/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', text)
assert sorted(path.name for path in Path('docs/skeletons').glob('*.md')) == ['000-README.md']
rule = Path('docs/rules/220-SKELETONS.md').read_text(encoding='utf-8')
for phrase in (
'## Applicabilité',
'## Contenu minimal d\'une specification',
'## Sélection des règles et profils',
'## Templates et artefacts techniques',
'## Décisions propres au projet',
'## Composition de plusieurs skeletons',
'## Overrides et exceptions',
'## Validation de l\'instanciation',
):
assert phrase in rule, phrase
print('Skeleton contract audit: clean (alpha.1 PASS baseline, alpha.2 contract/index only)')
PY
git diff --check
git add VERSION README.md RULES.md docs/000-README.md \
docs/architecture/002-GOVERNANCE_ARCHITECTURE.md \
docs/architecture/003-RULE_PROFILE_MODEL.md \
docs/rules/000-README.md docs/rules/220-SKELETONS.md \
docs/skeletons/000-README.md deltas/0.0.4/alpha.2.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M README.md
M RULES.md
M VERSION
A deltas/0.0.4/alpha.2.md
M docs/000-README.md
M docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/rules/000-README.md
A docs/rules/220-SKELETONS.md
A docs/skeletons/000-README.md
```
La revue opérateur doit également confirmer que `220-SKELETONS.md` reste transversal, ne duplique pas les règles de profils ou de validation et ne matérialise aucun choix technologique futur par anticipation.
## Transition
### PASS
Rédiger et livrer `history/0.0.4/alpha.2.md` avec les résultats réellement observés ; l'appliquer puis committer la tranche. La tranche suivante est `0.0.4-alpha.3`, consacrée à la première skeleton specification de fondation d'un projet gouverné.
Le history `alpha.2` et le delta `alpha.3` MAY être livrés dans la même réponse après la gate `PASS`, tout en restant deux archives séparées. Le delta `alpha.3` MUST NOT être appliqué avant le commit complet de `alpha.2`.
### FAIL
Consigner le résultat réel dans le history de `alpha.2`, puis corriger le contrat dans `0.0.4-alpha.2.fix.1` ou produire un REPLAN motivé. Aucun skeleton concret de `alpha.3` ne doit être absorbé silencieusement dans un fix.

167
deltas/0.0.4/alpha.3.md Normal file
View File

@@ -0,0 +1,167 @@
<!-- file: deltas/0.0.4/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.3 — fondation de projet gouverné
## Baseline et version
Baseline attendue : commit opérateur de `0.0.4-alpha.2`, réalisé après application de `history/0.0.4/alpha.2.md` avec statut `PASS`.
Le hash de ce commit n'est volontairement pas anticipé : le history `alpha.2` et le présent delta peuvent être livrés dans le même échange, mais restent deux archives séparées et le delta `alpha.3` MUST NOT être appliqué avant le commit de `alpha.2`.
Version avant application :
```text
0.0.4-alpha.2
```
Version après application :
```text
0.0.4-alpha.3
```
## Objet
Matérialiser la première skeleton specification concrète prévue par le plan `0.0.4` : une fondation composable de gouvernance locale pour un projet qui adopte PGR, sans sélectionner de langage, plateforme, framework ou architecture applicative.
La specification doit rendre actionnables les responsabilités générales déjà possédées par `200`, `210`, `300` et `400` : version courante, point d'entrée normatif, documentation minimale, workflow réellement retenu, décisions destinataire, overrides et validation initiale proportionnée.
Elle ne crée aucun template générique, ne copie pas la structure complète du dépôt PGR et ne précrée aucun répertoire documentaire ou workflow sans contenu réel.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
docs/skeletons/000-README.md
```
ADD :
```text
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
deltas/0.0.4/alpha.3.md
```
DELETE : aucun.
L'archive delta contient uniquement ces six fichiers complets avec leurs chemins relatifs. Elle ne contient ni `history/0.0.4/alpha.2.md`, livré séparément pour clôturer la tranche précédente, ni `history/0.0.4/alpha.3.md`, qui sera produit après la gate opérateur.
Le plan `docs/plans/004-V0_0_4_SKELETONS_PLAN.md` et la règle `docs/rules/220-SKELETONS.md` ne sont pas modifiés : cette tranche exécute leur trajectoire et leur contrat sans REPLAN.
## Contenu matérialisé
`docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md` :
- déclare son objectif, son applicabilité et son hors-scope ;
- sélectionne les owners généraux `200`, `210`, `300` et `400` sans sélectionner de profil technologique ;
- distingue le rôle de `220` comme contrat d'instanciation de celui des règles à reprendre localement ;
- impose de résoudre les décisions destinataire avant de présenter l'instanciation comme terminée ;
- rend le point d'entrée normatif local et la version courante explicites ;
- rend `docs/`, `ROADMAP.md`, `CHANGELOG.md` et les collections spécialisées conditionnels à un contenu réel ;
- conserve `deltas/`, `history/`, `prompts/`, `handoffs/` et `manifests/` comme répertoires créés à la demande ;
- fournit une validation initiale proportionnée sans imposer de copier les scripts PGR ;
- définit l'ordre de composition attendu pour les futures spécialisations ;
- exclut explicitement architecture applicative, toolchain, CI/CD universel, branching universel et migration rétroactive.
Aucun template générique n'est nécessaire pour rendre cette specification actionnable : elle décrit les owners, décisions, fichiers conditionnels et preuves à matérialiser sans prétendre générer leur contenu automatiquement. Le point de REPLAN du plan n'est donc pas déclenché par cette tranche.
## Validation opérateur
Après avoir appliqué `history/0.0.4/alpha.2.md`, committé `0.0.4-alpha.2`, puis appliqué le présent delta, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.4-alpha.3'
test -f history/0.0.4/alpha.2.md
test -f deltas/0.0.4/alpha.3.md
test -f docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
test ! -e history/0.0.4/alpha.3.md
test ! -e docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 9 -->' README.md
grep -Fx '<!-- version: 7 -->' docs/000-README.md
grep -Fx '<!-- version: 2 -->' docs/skeletons/000-README.md
grep -Fx '<!-- version: 1 -->' docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
grep -F '001-PROJECT_GOVERNANCE_FOUNDATION.md' README.md
grep -F '001-PROJECT_GOVERNANCE_FOUNDATION.md' docs/000-README.md
grep -F '001-PROJECT_GOVERNANCE_FOUNDATION.md' docs/skeletons/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
histories = {path.name for path in Path('history/0.0.4').glob('*.md')}
assert histories == {'alpha.1.md', 'alpha.2.md'}, histories
for name in sorted(histories):
text = Path('history/0.0.4', name).read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', text), name
skeletons = sorted(path.name for path in Path('docs/skeletons').glob('*.md'))
assert skeletons == ['000-README.md', '001-PROJECT_GOVERNANCE_FOUNDATION.md'], skeletons
text = Path('docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md').read_text(encoding='utf-8')
for phrase in (
'## Applicabilité',
'## Owners sélectionnés',
'## Décisions destinataire avant matérialisation',
'## Baseline locale à matérialiser',
'### Version',
'### Documentation minimale',
'### Workflow retenu',
'### Validation initiale',
'## Ordre de composition',
'## Overrides et exceptions',
'## Hors scope',
):
assert phrase in text, phrase
for owner in ('200-GOVERNANCE.md', '210-WORKFLOW.md', '300-DOCUMENTATION.md', '400-VALIDATION.md'):
assert owner in text, owner
for forbidden in (
'templates/generic',
'docs/skeletons/002-RUST_CARGO_WORKSPACE.md',
):
assert forbidden not in text, forbidden
print('Governance foundation audit: clean (alpha.1/alpha.2 PASS baseline, one concrete non-technological skeleton)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/skeletons/000-README.md \
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md \
deltas/0.0.4/alpha.3.md
git diff --cached --check
git status --short
```
## Revue opérateur
En complément des commandes, vérifier que :
- la fondation reste une procedure composable et non un template ou générateur implicite ;
- aucun document ou répertoire n'est rendu obligatoire uniquement pour reproduire le layout PGR ;
- aucune règle technologique `500+` ou `600+` n'est sélectionnée par défaut ;
- les décisions destinataire restent explicites et aucune valeur d'exemple n'est universalisée ;
- l'ordre de composition permet au futur skeleton Rust/Cargo d'ajouter ses responsabilités sans dupliquer les owners généraux.
## Transition
PASS : produire `history/0.0.4/alpha.3.md`, l'appliquer puis committer `0.0.4-alpha.3`. La tranche suivante prévue par le plan est `0.0.4-alpha.4`, consacrée au skeleton Rust/Cargo workspace et à sa validation d'instanciation.
FAIL : rester dans le scope de `alpha.3` via `alpha.3.fix.1` sauf si l'échec démontre qu'un template générique ou une nouvelle décision normative est indispensable, auquel cas déclencher le REPLAN prévu par le plan.

View File

@@ -0,0 +1,231 @@
<!-- file: deltas/0.0.4/alpha.4.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.4.fix.1 — correction du smoke Rust/Cargo
## Baseline
Version attendue avant application :
```text
0.0.4-alpha.4
```
Le history `history/0.0.4/alpha.4.md` avec statut `FAIL` MUST avoir été appliqué et committé avant ce correctif.
Version après application :
```text
0.0.4-alpha.4.fix.1
```
## Objet
Corriger uniquement la procédure de smoke Rust/Cargo qui a échoué pendant la gate opérateur de `alpha.4`.
Le workspace temporaire était fonctionnel et les commandes Cargo ont réussi, mais l'adaptation de `.cargo/config.toml` remplaçait les chemins contenant `project-name` sans adapter le commentaire de guidance qui contenait encore ce placeholder. L'assertion d'absence de placeholders échouait donc avant le smoke Cargo.
Ce fix adapte explicitement ce commentaire dans la fixture temporaire avant de vérifier l'absence de placeholders.
Aucune règle, aucun skeleton, aucun template et aucun script PGR n'est ajouté ou modifié.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
deltas/0.0.4/alpha.4.fix.1.md
```
DELETE : aucun.
Les snapshots suivants restent inchangés :
```text
deltas/0.0.4/alpha.4.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
templates/rust-cargo/rustfmt.toml
templates/rust-cargo/clippy.toml
templates/rust-cargo/.cargo/config.toml
templates/rust-cargo/Cargo.toml
templates/rust-cargo/crates/project-core-lib/Cargo.toml
```
## Validation opérateur
```bash
test "$(cat VERSION)" = '0.0.4-alpha.4.fix.1'
test -f history/0.0.4/alpha.4.md
test -f deltas/0.0.4/alpha.4.md
test -f deltas/0.0.4/alpha.4.fix.1.md
test -f docs/skeletons/002-RUST_CARGO_WORKSPACE.md
test ! -e history/0.0.4/alpha.4.fix.1.md
grep -A2 '^## Statut$' history/0.0.4/alpha.4.md | grep -Fx 'FAIL'
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
expected = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'PASS',
'alpha.4.md': 'FAIL',
}
histories = {path.name for path in Path('history/0.0.4').glob('*.md')}
assert histories == set(expected), histories
for name, status in expected.items():
text = Path('history/0.0.4', name).read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
skeletons = sorted(path.name for path in Path('docs/skeletons').glob('*.md'))
assert skeletons == [
'000-README.md',
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
], skeletons
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
print('Rust/Cargo fix audit: clean (alpha.4 FAIL recorded, skeleton/templates unchanged)')
PY
command -v cargo
command -v rustfmt
cargo --version
rustc --version
rustfmt --version
cargo clippy --version
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/.cargo" "$tmp/crates/smoke-core-lib/src"
cp templates/rust-cargo/Cargo.toml "$tmp/Cargo.toml"
cp templates/rust-cargo/rustfmt.toml "$tmp/rustfmt.toml"
cp templates/rust-cargo/clippy.toml "$tmp/clippy.toml"
cp templates/rust-cargo/.cargo/config.toml "$tmp/.cargo/config.toml"
cp templates/rust-cargo/crates/project-core-lib/Cargo.toml "$tmp/crates/smoke-core-lib/Cargo.toml"
printf '1.2.3\n' > "$tmp/VERSION"
python3 -B - "$tmp" <<'PY'
from pathlib import Path
import sys
root = Path(sys.argv[1])
replacements = {
root / 'Cargo.toml': (
('# file: templates/rust-cargo/Cargo.toml', '# file: Cargo.toml'),
('members = ["crates/project-core-lib"]', 'members = ["crates/smoke-core-lib"]'),
('version = "0.1.0"', 'version = "1.2.3"'),
),
root / 'rustfmt.toml': (
('# file: templates/rust-cargo/rustfmt.toml', '# file: rustfmt.toml'),
),
root / 'clippy.toml': (
('# file: templates/rust-cargo/clippy.toml', '# file: clippy.toml'),
),
root / '.cargo/config.toml': (
('# file: templates/rust-cargo/.cargo/config.toml', '# file: .cargo/config.toml'),
(
'# Replace project-name with a unique name before using this configuration.',
'# Smoke fixture: project-specific build directory already selected.',
),
('../builds/project-name/target', 'target-smoke'),
),
root / 'crates/smoke-core-lib/Cargo.toml': (
(
'# file: templates/rust-cargo/crates/project-core-lib/Cargo.toml',
'# file: crates/smoke-core-lib/Cargo.toml',
),
('name = "project-core-lib"', 'name = "smoke-core-lib"'),
),
}
for path, pairs in replacements.items():
text = path.read_text(encoding='utf-8')
for old, new in pairs:
assert old in text, (path, old)
text = text.replace(old, new)
path.write_text(text, encoding='utf-8')
for path in root.rglob('*'):
if path.is_file() and path.name != 'Cargo.lock':
text = path.read_text(encoding='utf-8')
assert 'project-name' not in text, path
assert 'project-core-lib' not in text, path
print('Temporary Rust/Cargo template adaptation: clean')
PY
cat > "$tmp/crates/smoke-core-lib/src/lib.rs" <<'RS'
//! Minimal crate used to validate the PGR Rust/Cargo templates.
/// Returns the deterministic smoke value.
pub fn smoke_value() -> u8 {
return 1;
}
RS
(
cd "$tmp"
cargo metadata --format-version 1 --no-deps >/dev/null
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
)
rm -rf "$tmp"
trap - EXIT
git diff --check
git add VERSION deltas/0.0.4/alpha.4.fix.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.0.4/alpha.4.fix.1.md
```
## Transition
### PASS
Créer et appliquer séparément `history/0.0.4/alpha.4.fix.1.md`, committer et pousser le correctif, puis reprendre le plan `0.0.4` à la tranche suivante prévue.
Le history `alpha.4.fix.1` et le delta de la tranche suivante MAY être livrés ensemble sous forme de deux archives séparées après observation de la gate opérateur.
### FAIL
Rester dans `0.0.4-alpha.4.fix.M`. Le scope MUST rester limité au smoke Rust/Cargo de cette tranche tant qu'aucun défaut plus large ne justifie un REPLAN.

277
deltas/0.0.4/alpha.4.md Normal file
View File

@@ -0,0 +1,277 @@
<!-- file: deltas/0.0.4/alpha.4.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.4 — skeleton Rust/Cargo workspace
## Baseline et version
Baseline attendue : commit opérateur de `0.0.4-alpha.3`, réalisé après application de `history/0.0.4/alpha.3.md` avec statut `PASS`.
Le hash de ce commit n'est volontairement pas anticipé : le history `alpha.3` et le présent delta peuvent être livrés dans le même échange, mais restent deux archives séparées et le delta `alpha.4` MUST NOT être appliqué avant le commit de `alpha.3`.
Version avant application :
```text
0.0.4-alpha.3
```
Version après application :
```text
0.0.4-alpha.4
```
## Objet
Matérialiser la première specialization technologique prévue par le plan `0.0.4` : un skeleton Rust/Cargo workspace composable avec la fondation `001`, les profils `500 + 510`, les cinq templates Rust/Cargo existants et leurs guides d'adaptation.
La specification doit rendre explicites les décisions destinataire avant copie, la relation entre `VERSION` et la version Cargo, les membres du workspace, l'édition/toolchain, les métadonnées, les dépendances/features, `Cargo.lock`, les lints, les paramètres Rustfmt/Clippy, les artefacts Cargo et la sélection éventuelle des audits de style Rust.
Aucun template Rust/Cargo ni owner normatif n'est modifié dans cette tranche : la spécialisation doit composer les pièces déjà éprouvées sans universaliser leurs valeurs d'exemple.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
docs/skeletons/000-README.md
```
ADD :
```text
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
deltas/0.0.4/alpha.4.md
```
DELETE : aucun.
L'archive delta contient uniquement ces six fichiers complets avec leurs chemins relatifs. Elle ne contient ni `history/0.0.4/alpha.3.md`, livré séparément pour clôturer la tranche précédente, ni `history/0.0.4/alpha.4.md`, qui sera produit après la gate opérateur.
Les documents suivants restent inchangés :
```text
docs/rules/220-SKELETONS.md
docs/rules/500-LANGUAGES.md
docs/rules/510-RUST_CARGO.md
docs/templates/001-RUST_CARGO_TOOLING.md
docs/templates/002-CARGO_MANIFESTS.md
docs/validation/002-RUST_STYLE_AUDITS.md
templates/rust-cargo/rustfmt.toml
templates/rust-cargo/clippy.toml
templates/rust-cargo/.cargo/config.toml
templates/rust-cargo/Cargo.toml
templates/rust-cargo/crates/project-core-lib/Cargo.toml
```
La tranche exécute donc le plan sans REPLAN et sans déplacer les propriétaires existants.
## Contenu matérialisé
`docs/skeletons/002-RUST_CARGO_WORKSPACE.md` :
- se compose explicitement avec `001-PROJECT_GOVERNANCE_FOUNDATION.md` ;
- sélectionne `500-LANGUAGES.md` et `510-RUST_CARGO.md` sans absorber leurs règles ;
- référence les guides `001-RUST_CARGO_TOOLING.md` et `002-CARGO_MANIFESTS.md` ;
- identifie exactement les cinq templates Rust/Cargo copiables existants ;
- rend explicites les décisions de release unit, membres, édition/toolchain, publication, métadonnées, dépendances/features, lockfile, lints, formatage, Clippy et artefacts ;
- rappelle que `0.1.0`, `2024`, `project-name`, `project-core-lib`, les seuils Clippy et les chemins de build doivent être revus avant adoption ;
- ne fournit aucun `src/lib.rs` ou `src/main.rs` universel ;
- conserve les audits de style Rust comme option explicitement sélectionnée avec corpus ciblé ;
- définit une validation Cargo initiale fondée sur `cargo metadata`, Rustfmt, `cargo check` et Clippy ;
- permet aux futurs profils plateforme/framework de s'ajouter après le workspace sans créer un composite artificiel.
## Validation opérateur
Après avoir appliqué `history/0.0.4/alpha.3.md`, committé `0.0.4-alpha.3`, puis appliqué le présent delta, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.4-alpha.4'
test -f history/0.0.4/alpha.3.md
test -f deltas/0.0.4/alpha.4.md
test -f docs/skeletons/002-RUST_CARGO_WORKSPACE.md
test ! -e history/0.0.4/alpha.4.md
grep -Fx '<!-- version: 10 -->' README.md
grep -Fx '<!-- version: 8 -->' docs/000-README.md
grep -Fx '<!-- version: 3 -->' docs/skeletons/000-README.md
grep -Fx '<!-- version: 1 -->' docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -F '002-RUST_CARGO_WORKSPACE.md' README.md
grep -F '002-RUST_CARGO_WORKSPACE.md' docs/000-README.md
grep -F '002-RUST_CARGO_WORKSPACE.md' docs/skeletons/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
histories = {path.name for path in Path('history/0.0.4').glob('*.md')}
assert histories == {'alpha.1.md', 'alpha.2.md', 'alpha.3.md'}, histories
for name in sorted(histories):
text = Path('history/0.0.4', name).read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', text), name
skeletons = sorted(path.name for path in Path('docs/skeletons').glob('*.md'))
assert skeletons == [
'000-README.md',
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
], skeletons
text = Path('docs/skeletons/002-RUST_CARGO_WORKSPACE.md').read_text(encoding='utf-8')
for phrase in (
'## Applicabilité et composition',
'## Owners, guides et artefacts sélectionnés',
'## Décisions destinataire avant copie',
'## Matérialisation du workspace',
'### Cargo.lock',
'### Audits de style facultatifs',
'## Validation initiale',
'## Ordre de composition et extensions',
'## Overrides et exceptions',
'## Hors scope',
):
assert phrase in text, phrase
for owner in ('500-LANGUAGES.md', '510-RUST_CARGO.md'):
assert owner in text, owner
for template in (
'templates/rust-cargo/rustfmt.toml',
'templates/rust-cargo/clippy.toml',
'templates/rust-cargo/.cargo/config.toml',
'templates/rust-cargo/Cargo.toml',
'templates/rust-cargo/crates/project-core-lib/Cargo.toml',
):
assert template in text, template
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
print('Rust/Cargo skeleton audit: clean (alpha.1-alpha.3 PASS baseline, five templates parsed)')
PY
command -v cargo
command -v rustfmt
cargo --version
rustc --version
rustfmt --version
cargo clippy --version
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/.cargo" "$tmp/crates/smoke-core-lib/src"
cp templates/rust-cargo/Cargo.toml "$tmp/Cargo.toml"
cp templates/rust-cargo/rustfmt.toml "$tmp/rustfmt.toml"
cp templates/rust-cargo/clippy.toml "$tmp/clippy.toml"
cp templates/rust-cargo/.cargo/config.toml "$tmp/.cargo/config.toml"
cp templates/rust-cargo/crates/project-core-lib/Cargo.toml "$tmp/crates/smoke-core-lib/Cargo.toml"
printf '1.2.3\n' > "$tmp/VERSION"
python3 -B - "$tmp" <<'PY'
from pathlib import Path
import sys
root = Path(sys.argv[1])
replacements = {
root / 'Cargo.toml': (
('# file: templates/rust-cargo/Cargo.toml', '# file: Cargo.toml'),
('members = ["crates/project-core-lib"]', 'members = ["crates/smoke-core-lib"]'),
('version = "0.1.0"', 'version = "1.2.3"'),
),
root / 'rustfmt.toml': (
('# file: templates/rust-cargo/rustfmt.toml', '# file: rustfmt.toml'),
),
root / 'clippy.toml': (
('# file: templates/rust-cargo/clippy.toml', '# file: clippy.toml'),
),
root / '.cargo/config.toml': (
('# file: templates/rust-cargo/.cargo/config.toml', '# file: .cargo/config.toml'),
('../builds/project-name/target', 'target-smoke'),
),
root / 'crates/smoke-core-lib/Cargo.toml': (
('# file: templates/rust-cargo/crates/project-core-lib/Cargo.toml', '# file: crates/smoke-core-lib/Cargo.toml'),
('name = "project-core-lib"', 'name = "smoke-core-lib"'),
),
}
for path, pairs in replacements.items():
text = path.read_text(encoding='utf-8')
for old, new in pairs:
assert old in text, (path, old)
text = text.replace(old, new)
path.write_text(text, encoding='utf-8')
for path in root.rglob('*'):
if path.is_file() and path.name != 'Cargo.lock':
text = path.read_text(encoding='utf-8')
assert 'project-name' not in text, path
assert 'project-core-lib' not in text, path
PY
cat > "$tmp/crates/smoke-core-lib/src/lib.rs" <<'RS'
//! Minimal crate used to validate the PGR Rust/Cargo templates.
/// Returns the deterministic smoke value.
pub fn smoke_value() -> u8 {
return 1;
}
RS
(
cd "$tmp"
cargo metadata --format-version 1 --no-deps >/dev/null
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
)
rm -rf "$tmp"
trap - EXIT
git diff --check
git add VERSION README.md docs/000-README.md \
docs/skeletons/000-README.md \
docs/skeletons/002-RUST_CARGO_WORKSPACE.md \
deltas/0.0.4/alpha.4.md
git diff --cached --check
git status --short
```
## Revue opérateur
En complément des commandes, vérifier que :
- `002` reste une specialization composable de `001` et ne redéfinit pas les owners généraux ;
- les cinq templates sont référencés comme artefacts à adapter, jamais comme valeurs universelles ;
- la politique `Cargo.lock`, les membres, dépendances/features, métadonnées et éventuelles exceptions de lints/safety restent des décisions explicites du projet ;
- les audits Rust facultatifs ne sont ni copiés ni exécutés sans sélection de leur convention et de leur corpus ;
- aucune règle Java/Android/Web/JNI/Tauri ou autre plateforme/framework n'entre dans la tranche ;
- l'instanciation temporaire prouve l'adoption minimale des templates sans ajouter de workspace Rust au dépôt PGR.
## Transition
PASS : produire `history/0.0.4/alpha.4.md`, l'appliquer puis committer `0.0.4-alpha.4`. La tranche suivante prévue par le plan est `0.0.4-beta.1`, consacrée à la réconciliation interne de la release : ownership, liens, index, duplication normative, valeurs d'exemple, limites des audits et confirmation des domaines différés.
FAIL : rester dans le scope de `alpha.4` via `alpha.4.fix.1` sauf si l'instanciation démontre qu'un template ou une décision normative existante est insuffisante, auquel cas déclencher le REPLAN prévu par le plan.

View File

@@ -0,0 +1,200 @@
<!-- file: deltas/0.0.4/beta.1.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-beta.1.fix.1 — correction de la gate de réconciliation
## Baseline et version
Baseline : tranche `0.0.4-beta.1` enregistrée `FAIL`, avec `history/0.0.4/beta.1.md` appliqué, committé et poussé. Le delta et le history `beta.1` restent des snapshots historiques et MUST NOT être réécrits.
Version avant application :
```text
0.0.4-beta.1
```
Version après application :
```text
0.0.4-beta.1.fix.1
```
## Motif
La gate `beta.1` a échoué avant l'exécution de son audit Python de réconciliation à cause d'une chaîne délimitée par apostrophes simples contenant l'apostrophe de `l'arborescence` :
```text
SyntaxError: unterminated string literal
```
Les tests, audits Markdown et contrôles précédant cette commande ont réussi. Aucun défaut des règles, skeletons, templates ou documents vivants n'a été observé.
Le présent fix corrige uniquement la gate en utilisant une chaîne Python correctement délimitée, puis rejoue les preuves nécessaires de la réconciliation.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
deltas/0.0.4/beta.1.fix.1.md
```
DELETE : aucun.
Aucun document vivant, règle, skeleton, template, script, test ou history antérieur n'est modifié.
## Validation opérateur
Après commit et push de `0.0.4-beta.1` avec son history `FAIL`, appliquer ce delta puis exécuter à la racine :
```bash
test "$(cat VERSION)" = '0.0.4-beta.1.fix.1'
git cat-file -e HEAD:history/0.0.4/beta.1.md
test -f history/0.0.4/beta.1.md
test -f deltas/0.0.4/beta.1.md
test -f deltas/0.0.4/beta.1.fix.1.md
test ! -e history/0.0.4/beta.1.fix.1.md
grep -A2 '^## Statut$' history/0.0.4/beta.1.md | grep -Fx 'FAIL'
grep -A2 '^## Statut$' history/0.0.4/alpha.4.fix.1.md | grep -Fx 'PASS'
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
expected_histories = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'PASS',
'alpha.4.md': 'FAIL',
'alpha.4.fix.1.md': 'PASS',
'beta.1.md': 'FAIL',
}
histories = {path.name for path in Path('history/0.0.4').glob('*.md')}
assert histories == set(expected_histories), histories
for name, status in expected_histories.items():
text = Path('history/0.0.4', name).read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
deltas = {path.name for path in Path('deltas/0.0.4').glob('*.md')}
assert deltas == set(expected_histories) | {'beta.1.fix.1.md'}, deltas
skeletons = sorted(path.name for path in Path('docs/skeletons').glob('*.md'))
assert skeletons == [
'000-README.md',
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
], skeletons
root_index = Path('README.md').read_text(encoding='utf-8')
docs_index = Path('docs/000-README.md').read_text(encoding='utf-8')
skel_index = Path('docs/skeletons/000-README.md').read_text(encoding='utf-8')
for name in (
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
):
assert name in root_index, name
assert name in docs_index, name
assert name in skel_index, name
foundation = Path('docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md').read_text(encoding='utf-8')
for owner in (
'200-GOVERNANCE.md',
'210-WORKFLOW.md',
'300-DOCUMENTATION.md',
'400-VALIDATION.md',
):
assert owner in foundation, owner
rust = Path('docs/skeletons/002-RUST_CARGO_WORKSPACE.md').read_text(encoding='utf-8')
for owner in ('500-LANGUAGES.md', '510-RUST_CARGO.md'):
assert owner in rust, owner
for value in ('0.1.0', '2024', 'project-name', 'project-core-lib'):
assert value in rust, value
assert 'Ils ne deviennent jamais des valeurs universelles par simple copie.' in rust
assert 'Cargo.lock' in rust
rule = Path('docs/rules/220-SKELETONS.md').read_text(encoding='utf-8')
assert 'Un skeleton sélectionne les owners normatifs applicables ; il ne redéfinit pas leur contenu.' in rule
assert 'MUST NOT devenir une valeur universelle par simple copie' in rule
validation = Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8')
for audit_id in ('PGR-MD-HEADER-001', 'PGR-MD-TABLE-001', 'PGR-NAV-001'):
assert audit_id in validation, audit_id
assert "vérifie uniquement l'existence des cibles de liens Markdown locaux inline" in validation
rust_audits = Path('docs/validation/002-RUST_STYLE_AUDITS.md').read_text(encoding='utf-8')
assert 'facultatif' in rust_audits.lower()
assert "Les audits ne modifient ni les fichiers inspectés ni l'arborescence de build." in rust_audits
plan = Path('docs/plans/004-V0_0_4_SKELETONS_PLAN.md').read_text(encoding='utf-8')
for deferred in (
'Java / Maven / Gradle — différé',
'Android — différé',
'Web, JNI, Tauri et autres familles absentes — différés',
):
assert deferred in plan, deferred
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
print('Skeleton beta reconciliation fix audit: clean (beta.1 FAIL recorded, 3 skeleton docs, 5 TOML parsed)')
PY
git diff --check
git add VERSION deltas/0.0.4/beta.1.fix.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.0.4/beta.1.fix.1.md
```
## Revue opérateur complémentaire
Confirmer que :
- le `FAIL beta.1` reste visible et n'est pas réécrit ;
- le fix ne change aucune règle, aucun skeleton, aucun template et aucun audit ;
- `220` reste le propriétaire du contrat transversal et `001`/`002` restent des orchestrateurs/compositeurs de leurs owners ;
- les valeurs de templates restent adaptables et non universelles ;
- Java/Android/Web/JNI/Tauri restent différés sans placeholder anticipé.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.4/beta.1.fix.1.md`, committer et pousser le fix, puis préparer `0.0.4-rc.1`.
Le history du fix et le delta `rc.1` MAY être livrés ensemble sous forme de deux archives séparées après observation de cette gate opérateur.
### FAIL
Enregistrer le diagnostic réel dans `history/0.0.4/beta.1.fix.1.md`, puis poursuivre par `beta.1.fix.2` limité à la réconciliation ou faire un REPLAN explicite si un défaut de contenu est réellement découvert.

225
deltas/0.0.4/beta.1.md Normal file
View File

@@ -0,0 +1,225 @@
<!-- file: deltas/0.0.4/beta.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-beta.1 — réconciliation interne des skeletons
## Baseline
Version attendue avant application :
```text
0.0.4-alpha.4.fix.1
```
Le history `history/0.0.4/alpha.4.fix.1.md` avec statut `PASS` MUST avoir été appliqué, committé et poussé avant ce delta. Le `FAIL` de `history/0.0.4/alpha.4.md` reste un snapshot historique et MUST NOT être réécrit.
Version après application :
```text
0.0.4-beta.1
```
## Objet
Exécuter la réconciliation interne prévue par `docs/plans/004-V0_0_4_SKELETONS_PLAN.md` après la fondation gouvernée, le skeleton Rust/Cargo et la correction de sa gate d'instanciation.
La revue porte sur :
```text
ownership normatif
navigation et index
absence de duplication normative
composition 001 -> 002
valeurs d'exemple non universalisées
limites des audits et de la validation
spécialisations technologiques différées
continuité delta/history de 0.0.4
```
Cette tranche n'ajoute aucune fonctionnalité, aucun profil, aucun skeleton, aucun template et aucun audit.
## Résultat de la réconciliation préparatoire
Aucune correction de document vivant n'est nécessaire pour entrer en beta.
Le contrat transversal reste possédé par `docs/rules/220-SKELETONS.md`. La fondation `001-PROJECT_GOVERNANCE_FOUNDATION.md` orchestre les owners généraux sans les redéfinir. La specialization `002-RUST_CARGO_WORKSPACE.md` ajoute uniquement `500 + 510`, les guides/templates Rust/Cargo et les décisions de son scope.
La navigation courante expose les deux specifications depuis `README.md`, `docs/000-README.md` et `docs/skeletons/000-README.md`. Aucun troisième skeleton ou placeholder de skeleton n'existe.
Les valeurs Rust/Cargo telles que `0.1.0`, `2024`, `project-name`, `project-core-lib`, les seuils Clippy et les chemins de build restent explicitement décrites comme exemples, baselines ou décisions destinataire à revoir. `Cargo.lock` reste une décision propre au type de produit et au besoin de reproductibilité.
Les limites des audits restent séparées : headers, tableaux et liens Markdown sont des contrôles monotâches ; les audits de style Rust sont facultatifs, read-only et ne remplacent ni Rustfmt, ni Clippy, ni la toolchain Cargo. La validation d'instanciation appartient au skeleton qui prétend matérialiser une baseline utilisable et n'est pas transformée en build global permanent de PGR.
Java/Maven/Gradle et Android possèdent des profils normatifs mais pas encore les templates/corpus nécessaires à un skeleton concret. Web, JNI, Tauri et les autres domaines insuffisamment cadrés restent également différés. Aucun fichier placeholder n'est créé pour réserver ces futurs scopes.
Le `FAIL` de `alpha.4` et le `PASS` attendu de `alpha.4.fix.1` forment une chaîne historique explicite ; le fix ne réécrit pas le delta ou le history échoué.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
deltas/0.0.4/beta.1.md
```
DELETE : aucun.
Les documents vivants, règles, skeletons, templates, scripts, tests et histories antérieurs restent inchangés. Cette absence de modification supplémentaire est intentionnelle : la réconciliation n'a pas identifié de correction réelle qui justifierait une révision artificielle.
## Validation opérateur
Après commit et push de `0.0.4-alpha.4.fix.1`, appliquer ce delta puis exécuter à la racine :
```bash
test "$(cat VERSION)" = '0.0.4-beta.1'
git cat-file -e HEAD:history/0.0.4/alpha.4.fix.1.md
test -f history/0.0.4/alpha.4.fix.1.md
test -f deltas/0.0.4/beta.1.md
test ! -e history/0.0.4/beta.1.md
test -f docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
test -f docs/skeletons/002-RUST_CARGO_WORKSPACE.md
test ! -e docs/skeletons/003-JAVA_MAVEN_GRADLE.md
test ! -e docs/skeletons/003-ANDROID.md
grep -A2 '^## Statut$' history/0.0.4/alpha.4.md | grep -Fx 'FAIL'
grep -A2 '^## Statut$' history/0.0.4/alpha.4.fix.1.md | grep -Fx 'PASS'
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
expected_histories = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'PASS',
'alpha.4.md': 'FAIL',
'alpha.4.fix.1.md': 'PASS',
}
histories = {path.name for path in Path('history/0.0.4').glob('*.md')}
assert histories == set(expected_histories), histories
for name, status in expected_histories.items():
text = Path('history/0.0.4', name).read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
deltas = {path.name for path in Path('deltas/0.0.4').glob('*.md')}
assert deltas == set(expected_histories) | {'beta.1.md'}, deltas
skeletons = sorted(path.name for path in Path('docs/skeletons').glob('*.md'))
assert skeletons == [
'000-README.md',
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
], skeletons
root_index = Path('README.md').read_text(encoding='utf-8')
docs_index = Path('docs/000-README.md').read_text(encoding='utf-8')
skel_index = Path('docs/skeletons/000-README.md').read_text(encoding='utf-8')
for name in (
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
):
assert name in root_index, name
assert name in docs_index, name
assert name in skel_index, name
foundation = Path('docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md').read_text(encoding='utf-8')
for owner in (
'200-GOVERNANCE.md',
'210-WORKFLOW.md',
'300-DOCUMENTATION.md',
'400-VALIDATION.md',
):
assert owner in foundation, owner
rust = Path('docs/skeletons/002-RUST_CARGO_WORKSPACE.md').read_text(encoding='utf-8')
for owner in ('500-LANGUAGES.md', '510-RUST_CARGO.md'):
assert owner in rust, owner
for value in ('0.1.0', '2024', 'project-name', 'project-core-lib'):
assert value in rust, value
assert 'Ils ne deviennent jamais des valeurs universelles par simple copie.' in rust
assert 'Cargo.lock' in rust
rule = Path('docs/rules/220-SKELETONS.md').read_text(encoding='utf-8')
assert 'Un skeleton sélectionne les owners normatifs applicables ; il ne redéfinit pas leur contenu.' in rule
assert 'MUST NOT devenir une valeur universelle par simple copie' in rule
validation = Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8')
for audit_id in ('PGR-MD-HEADER-001', 'PGR-MD-TABLE-001', 'PGR-NAV-001'):
assert audit_id in validation, audit_id
assert 'vérifie uniquement l\'existence des cibles de liens Markdown locaux inline' in validation
rust_audits = Path('docs/validation/002-RUST_STYLE_AUDITS.md').read_text(encoding='utf-8')
assert 'facultatif' in rust_audits.lower()
assert 'Les audits ne modifient ni les fichiers inspectés ni l'arborescence de build.' in rust_audits
plan = Path('docs/plans/004-V0_0_4_SKELETONS_PLAN.md').read_text(encoding='utf-8')
for deferred in ('Java / Maven / Gradle — différé', 'Android — différé', 'Web, JNI, Tauri et autres familles absentes — différés'):
assert deferred in plan, deferred
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
print('Skeleton beta reconciliation audit: clean (5 prior histories, 3 skeleton docs, 5 TOML parsed)')
PY
git diff --check
git add VERSION deltas/0.0.4/beta.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history `beta.1` est exactement :
```text
M VERSION
A deltas/0.0.4/beta.1.md
```
## Revue opérateur complémentaire
Confirmer que :
- `220` reste le propriétaire du contrat transversal et que `001`/`002` n'en dupliquent pas les obligations ;
- `001` reste sans spécialisation technologique et `002` n'élargit pas `510` vers Android, WASM, Tauri, FFI ou un framework ;
- les valeurs de templates restent des exemples adaptables et non des politiques globales ;
- les audits documentaires et Rust restent délimités par leur propriété réellement vérifiée ;
- Java/Android/Web/JNI/Tauri restent différés faute de pièces suffisantes, sans placeholder ni skeleton composite anticipé ;
- le `FAIL alpha.4` reste visible et la correction `alpha.4.fix.1` est enregistrée séparément.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.4/beta.1.md`, committer et pousser `beta.1`, puis préparer `0.0.4-rc.1`.
La RC doit geler le scope, préparer l'entrée candidate `0.0.4` du changelog et `prompts/005-V0_0_5_START_PROMPT.md` si la trajectoire est confirmée, puis rejouer uniquement les validations réellement invalidées par la release.
Le history `beta.1` et le delta `rc.1` MAY être livrés ensemble sous forme de deux archives séparées après observation de la gate opérateur.
### FAIL
Enregistrer le diagnostic réel dans `history/0.0.4/beta.1.md`, puis corriger uniquement la réconciliation dans `0.0.4-beta.1.fix.N` ou faire un REPLAN explicite si un défaut révèle un changement de scope.

265
deltas/0.0.4/rc.1.md Normal file
View File

@@ -0,0 +1,265 @@
<!-- file: deltas/0.0.4/rc.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-rc.1 — gel du scope et préparation de release
## Baseline et version
Baseline : `0.0.4-beta.1.fix.1`, avec `history/0.0.4/beta.1.fix.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Le commit exact de cette baseline sera celui produit par l'opérateur après la gate `beta.1.fix.1` ; il n'est pas anticipé dans cette livraison simultanée du history et du delta suivant.
Version avant application :
```text
0.0.4-beta.1.fix.1
```
Version après application :
```text
0.0.4-rc.1
```
## Objet et gel
La réconciliation `beta.1.fix.1` est `PASS`. La RC gèle le scope fonctionnel de `0.0.4` sur :
- le contrat transversal des skeleton specifications sous `docs/rules/220-SKELETONS.md` ;
- la collection `docs/skeletons/` et son index ;
- `001-PROJECT_GOVERNANCE_FOUNDATION.md` comme fondation composable sans spécialisation technologique ;
- `002-RUST_CARGO_WORKSPACE.md` comme première spécialisation technologique, composée avec les profils `500 + 510` ;
- les cinq templates Rust/Cargo déjà introduits avant `0.0.4`, utilisés avec des décisions destinataire explicites et une instanciation temporaire vérifiable.
Le changelog reçoit une entrée candidate `0.0.4` orientée utilisateurs. Le plan enregistre les résultats `FAIL → fix PASS` des gates `alpha.4` et `beta.1`, puis le gel RC. Le prompt `005` prépare `0.0.5`, dont la roadmap confirme la mission de réconciliation réelle avec `khadhroony-solana-project` et `sasedev-games` à partir de baselines explicitement fournies.
Aucun nouveau skeleton, profil, template, audit, générateur ou domaine technologique n'entre en RC. Java/Maven/Gradle, Android, Web, JNI, Tauri et les autres familles différées restent hors scope.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/plans/004-V0_0_4_SKELETONS_PLAN.md
```
ADD :
```text
prompts/005-V0_0_5_START_PROMPT.md
deltas/0.0.4/rc.1.md
```
DELETE : aucun.
L'archive contient exactement ces fichiers complets. Le history `beta.1.fix.1` est livré séparément ; le history `rc.1` sera produit après la gate opérateur.
## Gate opérateur de release candidate
Après application sur le commit `beta.1.fix.1`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.4-rc.1'
git cat-file -e HEAD:history/0.0.4/beta.1.fix.1.md
test -f history/0.0.4/beta.1.fix.1.md
test -f deltas/0.0.4/rc.1.md
test -f prompts/005-V0_0_5_START_PROMPT.md
test ! -e history/0.0.4/rc.1.md
grep -Fx '<!-- version: 6 -->' CHANGELOG.md
grep -Fx '## 0.0.4 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 2 -->' docs/plans/004-V0_0_4_SKELETONS_PLAN.md
grep -F '`beta.1.fix.1` a rejoué la réconciliation et est `PASS`' docs/plans/004-V0_0_4_SKELETONS_PLAN.md
grep -F 'pgr-v0.0.4.zip' prompts/005-V0_0_5_START_PROMPT.md
grep -F 'khadhroony-solana-project' prompts/005-V0_0_5_START_PROMPT.md
grep -F 'sasedev-games' prompts/005-V0_0_5_START_PROMPT.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
expected_histories = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'PASS',
'alpha.4.md': 'FAIL',
'alpha.4.fix.1.md': 'PASS',
'beta.1.md': 'FAIL',
'beta.1.fix.1.md': 'PASS',
}
histories = {path.name for path in Path('history/0.0.4').glob('*.md')}
assert histories == set(expected_histories), histories
for name, status in expected_histories.items():
text = Path('history/0.0.4', name).read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
deltas = {path.name for path in Path('deltas/0.0.4').glob('*.md')}
assert deltas == set(expected_histories) | {'rc.1.md'}, deltas
skeletons = sorted(path.name for path in Path('docs/skeletons').glob('*.md'))
assert skeletons == [
'000-README.md',
'001-PROJECT_GOVERNANCE_FOUNDATION.md',
'002-RUST_CARGO_WORKSPACE.md',
], skeletons
rule = Path('docs/rules/220-SKELETONS.md').read_text(encoding='utf-8')
assert 'Un skeleton sélectionne les owners normatifs applicables ; il ne redéfinit pas leur contenu.' in rule
foundation = Path('docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md').read_text(encoding='utf-8')
for owner in ('200-GOVERNANCE.md', '210-WORKFLOW.md', '300-DOCUMENTATION.md', '400-VALIDATION.md'):
assert owner in foundation, owner
rust = Path('docs/skeletons/002-RUST_CARGO_WORKSPACE.md').read_text(encoding='utf-8')
for owner in ('500-LANGUAGES.md', '510-RUST_CARGO.md'):
assert owner in rust, owner
assert 'Ils ne deviennent jamais des valeurs universelles par simple copie.' in rust
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
prompt = Path('prompts/005-V0_0_5_START_PROMPT.md').read_text(encoding='utf-8')
for value in ('pgr-v0.0.4.zip', 'pgr-0.0.4-publish.001-report.md', '0.0.5-alpha.1', 'khadhroony-solana-project', 'sasedev-games'):
assert value in prompt, value
assert 'Ne pas déduire leur version, leur commit ou leur contenu' in prompt
print('RC integration audit: clean (7 prior histories, 3 skeleton docs, 5 TOML parsed, prompt 005 ready)')
PY
command -v cargo
command -v rustfmt
cargo --version
rustc --version
rustfmt --version
cargo clippy --version
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/.cargo" "$tmp/crates/smoke-core-lib/src"
cp templates/rust-cargo/Cargo.toml "$tmp/Cargo.toml"
cp templates/rust-cargo/rustfmt.toml "$tmp/rustfmt.toml"
cp templates/rust-cargo/clippy.toml "$tmp/clippy.toml"
cp templates/rust-cargo/.cargo/config.toml "$tmp/.cargo/config.toml"
cp templates/rust-cargo/crates/project-core-lib/Cargo.toml "$tmp/crates/smoke-core-lib/Cargo.toml"
printf '1.2.3\n' > "$tmp/VERSION"
python3 -B - "$tmp" <<'PY'
from pathlib import Path
import sys
root = Path(sys.argv[1])
replacements = {
root / 'Cargo.toml': (
('# file: templates/rust-cargo/Cargo.toml', '# file: Cargo.toml'),
('members = ["crates/project-core-lib"]', 'members = ["crates/smoke-core-lib"]'),
('version = "0.1.0"', 'version = "1.2.3"'),
),
root / 'rustfmt.toml': (
('# file: templates/rust-cargo/rustfmt.toml', '# file: rustfmt.toml'),
),
root / 'clippy.toml': (
('# file: templates/rust-cargo/clippy.toml', '# file: clippy.toml'),
),
root / '.cargo/config.toml': (
('# file: templates/rust-cargo/.cargo/config.toml', '# file: .cargo/config.toml'),
(
'# Replace project-name with a unique name before using this configuration.',
'# Smoke fixture: project-specific build directory already selected.',
),
('../builds/project-name/target', 'target-smoke'),
),
root / 'crates/smoke-core-lib/Cargo.toml': (
(
'# file: templates/rust-cargo/crates/project-core-lib/Cargo.toml',
'# file: crates/smoke-core-lib/Cargo.toml',
),
('name = "project-core-lib"', 'name = "smoke-core-lib"'),
),
}
for path, pairs in replacements.items():
text = path.read_text(encoding='utf-8')
for old, new in pairs:
assert old in text, (path, old)
text = text.replace(old, new)
path.write_text(text, encoding='utf-8')
for path in root.rglob('*'):
if path.is_file() and path.name != 'Cargo.lock':
text = path.read_text(encoding='utf-8')
assert 'project-name' not in text, path
assert 'project-core-lib' not in text, path
print('RC temporary Rust/Cargo template adaptation: clean')
PY
cat > "$tmp/crates/smoke-core-lib/src/lib.rs" <<'RS'
//! Minimal crate used to validate the PGR Rust/Cargo templates.
/// Returns the deterministic smoke value.
pub fn smoke_value() -> u8 {
return 1;
}
RS
(
cd "$tmp"
cargo metadata --format-version 1 --no-deps >/dev/null
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
)
rm -rf "$tmp"
trap - EXIT
git diff --check
git add VERSION CHANGELOG.md docs/plans/004-V0_0_4_SKELETONS_PLAN.md \
prompts/005-V0_0_5_START_PROMPT.md deltas/0.0.4/rc.1.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M VERSION
A deltas/0.0.4/rc.1.md
M docs/plans/004-V0_0_4_SKELETONS_PLAN.md
A prompts/005-V0_0_5_START_PROMPT.md
```
## Revue opérateur complémentaire
Confirmer que le changelog décrit la release et non ses tranches internes, que les deux `FAIL` historiques restent visibles avec leurs fixes `PASS`, que le prompt `005` ne présume aucune version KSP/Games non fournie et que la RC n'étend pas le périmètre fonctionnel.
Une gate RC `PASS` n'est ni la promotion stable, ni le tag `v0.0.4`, ni la vérification de l'archive publiée après le tag.
## Transition
### PASS
Produire séparément `history/0.0.4/rc.1.md`, l'appliquer puis committer/pousser la RC avant le delta stable `rel.001`.
Le history RC et le delta stable MAY être livrés ensemble sous forme de deux archives séparées après observation de cette gate opérateur.
### FAIL
Consigner l'échec réel dans `history/0.0.4/rc.1.md` et corriger uniquement le scope gelé dans `rc.1.fix.1`, sauf REPLAN explicite si la candidate révèle un défaut fonctionnel plus large.

152
deltas/0.0.4/rel.001.md Normal file
View File

@@ -0,0 +1,152 @@
<!-- file: deltas/0.0.4/rel.001.md -->
<!-- version: 1 -->
# Delta 0.0.4 rel.001 — promotion stable pré-tag
## Baseline et version
Baseline : `0.0.4-rc.1`, avec `history/0.0.4/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Le commit exact de cette baseline sera celui produit par l'opérateur après application du history RC ; il n'est pas anticipé dans cette livraison simultanée du history et du delta stable.
Version avant application :
```text
0.0.4-rc.1
```
Version après application :
```text
0.0.4
```
`rel.001` identifie la clôture opérationnelle ; il ne fait pas partie de la version SemVer du produit.
## Objet
Promouvoir la RC validée vers la stable `0.0.4`. La tranche finalise uniquement la présentation de la release : version stable, roadmap terminée, changelog sans marqueur candidate, index documentaires et plan historique.
Le scope fonctionnel reste celui validé en RC : contrat transversal des skeleton specifications, fondation gouvernée `001`, spécialisation Rust/Cargo `002`, utilisation gouvernée des cinq templates Rust/Cargo existants et différé explicite des autres familles non suffisamment matérialisées.
La validation de cette tranche est **pré-tag**. Ni le tag `v0.0.4`, ni l'archive `pgr-v0.0.4.zip` téléchargée depuis Gitea, ni un rapport `pgr-0.0.4-publish.001-report.md` ne sont déclarés existants par ce delta. Ils suivent le history PASS, le commit stable et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/004-V0_0_4_SKELETONS_PLAN.md
```
ADD :
```text
deltas/0.0.4/rel.001.md
```
DELETE : aucun.
L'archive contient uniquement ces fichiers complets. `history/0.0.4/rc.1.md` est livré séparément ; le history de `rel.001` sera produit après sa gate. Le rapport post-tag restera extérieur à l'archive source taggée.
## Validation opérateur pré-tag
Après application sur le commit `rc.1`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.4'
git cat-file -e HEAD:history/0.0.4/rc.1.md
test -f history/0.0.4/rc.1.md
test -f deltas/0.0.4/rel.001.md
test -f prompts/005-V0_0_5_START_PROMPT.md
test ! -e history/0.0.4/rel.001.md
grep -Fx '<!-- version: 11 -->' README.md
grep -Fx '<!-- version: 5 -->' ROADMAP.md
grep -Fx '<!-- version: 7 -->' CHANGELOG.md
grep -Fx '<!-- version: 9 -->' docs/000-README.md
grep -Fx '<!-- version: 3 -->' docs/plans/004-V0_0_4_SKELETONS_PLAN.md
grep -F 'La release `0.0.4` définit le contrat transversal des skeleton specifications' README.md
grep -F 'plan historique des skeleton specifications `0.0.4`' README.md
grep -F -- '- `(x) 0.0.4`' ROADMAP.md
grep -Fx '## 0.0.4' CHANGELOG.md
grep -F 'périmètre et décisions de la release `0.0.4`' docs/000-README.md
grep -F 'La gate opérateur de `rc.1` est `PASS`' docs/plans/004-V0_0_4_SKELETONS_PLAN.md
grep -F 'pgr-0.0.4-publish.001-report.md' docs/plans/004-V0_0_4_SKELETONS_PLAN.md
python3 -B - <<'PY'
from pathlib import Path
import re
expected = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'PASS',
'alpha.4.md': 'FAIL',
'alpha.4.fix.1.md': 'PASS',
'beta.1.md': 'FAIL',
'beta.1.fix.1.md': 'PASS',
'rc.1.md': 'PASS',
}
for name, status in expected.items():
delta = Path('deltas/0.0.4', name)
history = Path('history/0.0.4', name)
assert delta.is_file(), name
assert history.is_file(), name
text = history.read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
pending = {p.name for p in Path('deltas/0.0.4').glob('*.md')} - \
{p.name for p in Path('history/0.0.4').glob('*.md')}
assert pending == {'rel.001.md'}, pending
print('Stable history audit: clean (8 prior histories with expected statuses, rel.001 pending)')
PY
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION README.md ROADMAP.md CHANGELOG.md docs/000-README.md \
docs/plans/004-V0_0_4_SKELETONS_PLAN.md deltas/0.0.4/rel.001.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M README.md
M ROADMAP.md
M VERSION
A deltas/0.0.4/rel.001.md
M docs/000-README.md
M docs/plans/004-V0_0_4_SKELETONS_PLAN.md
```
Les `15` tests, les cinq TOML et le smoke Rust/Cargo complets validés en RC restent des preuves applicables parce qu'aucun code, script, test, template ou skeleton technique n'est modifié pendant `rel.001`. La gate stable se concentre donc sur l'intégrité de la chaîne historique, la présentation stable et les audits documentaires affectés.
## Revue opérateur complémentaire
Confirmer que le scope fonctionnel de la RC ne change pas, que README/roadmap/changelog/index/plan décrivent la même stable, que les `FAIL` historiques restent conservés avec leurs fixes `PASS`, que le prompt `005` reste conditionnel à une vraie publication et à des baselines KSP/Games fournies, et qu'aucune preuve post-tag n'est anticipée.
## Transition
### PASS
Produire séparément `history/0.0.4/rel.001.md`, l'appliquer puis committer la stable. Ensuite seulement créer et publier le tag canonique `v0.0.4`, télécharger son archive source depuis Gitea, vérifier cette archive et conserver séparément la preuve post-tag `pgr-0.0.4-publish.001-report.md`.
Le message manuel de reprise de `prompts/005-V0_0_5_START_PROMPT.md` n'est remis à l'opérateur qu'après vérification effective de l'archive et d'un rapport post-tag PASS réel.
### FAIL
Consigner le diagnostic réel dans `history/0.0.4/rel.001.md`, ne pas tagger et corriger la clôture dans une tranche explicite avant publication.

193
deltas/0.0.5/alpha.1.md Normal file
View File

@@ -0,0 +1,193 @@
<!-- file: deltas/0.0.5/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.1 — réconciliation des baselines et cadrage
## Baseline et sources
Baseline PGR : archive source fournie `pgr-v0.0.4.zip`, déclarée téléchargée depuis le tag Gitea `v0.0.4`, accompagnée du rapport externe `pgr-0.0.4-publish.001-report.md` avec statut `PASS`.
SHA-256 vérifié :
```text
pgr-v0.0.4.zip 7137bb084f017362323a2043d13ba71490be15b8786adc8d645981bf455b80ae
khadhroony-solana-project-v0.3.16.zip db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0
games-v0.3.5.zip 5f5fdee1a271386766d059657d6eaa831acdc263b3e722fed738808335c0a105
```
Les deux archives externes sont des corpus autoritaires de réconciliation pour cette session, pas des projets déjà gouvernés par PGR. Elles ne sont ni modifiées ni incorporées à l'archive delta.
Version avant application :
```text
0.0.4
```
Version après application :
```text
0.0.5-alpha.1
```
## Objet
Exécuter la gate de cadrage imposée par `prompts/005-V0_0_5_START_PROMPT.md` : vérifier indépendamment la stable PGR et sa preuve post-tag, contrôler les deux snapshots externes fournis, inventorier leurs responsabilités et audits, puis classer les écarts avant toute modification normative importante.
L'analyse détaillée vit dans `docs/studies/001-KSP_GAMES_RECONCILIATION.md`. Elle confirme que KSP `v0.3.16` et Games `v0.3.5` n'ont pas encore adopté PGR et ne doivent donc pas être jugés comme des projets non conformes. La plupart des mécanismes de gouvernance, documentation, validation et Rust/Cargo observés sont déjà correctement possédés par PGR.
Quatre axes communs restent suffisamment étayés pour le plan `0.0.5` : contrat générique des prompts versionnés, pattern facultatif de contrats de fichiers/familles, audit Rust de façade/export completeness, et Tauri comme premier candidat réel à la famille framework `700`.
Aucun de ces axes n'est matérialisé normativement dans `alpha.1`. Web/Vite/WASM, JNI, les audits composites et les règles métier ou de distribution spécifiques restent différés ou locaux.
## Vérifications d'intake déjà exécutées
Le ZIP PGR est lisible, possède une racine unique `pgr/`, `139` fichiers et `28` répertoires, sans doublon, collision de casse, chemin dangereux, lien symbolique ni `.git`. Son hash concorde avec le rapport post-tag.
Les deux corpus externes passent les contrôles ZIP équivalents. Leurs audits statiques fournis ont également été exécutés avec succès : audits Rust généraux/export/workspace et tableaux Markdown pour KSP ; audits Rust généraux/export/workspace, tableaux Markdown et distribution layout pour Games.
Sur la stable PGR extraite, les `15` tests Python passent, les trois audits Markdown sont propres et les cinq TOML Rust/Cargo se parsèrent. La toolchain `cargo` n'est pas disponible dans l'environnement de préparation ; aucune commande Cargo externe n'est donc présentée comme exécutée.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
```
ADD :
```text
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/studies/000-README.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
deltas/0.0.5/alpha.1.md
```
DELETE : aucun.
L'archive delta contient uniquement ces sept fichiers complets avec leurs chemins relatifs. Aucun history, règle normative, script, template technique, profil framework, skeleton ou modification KSP/Games n'appartient à cette tranche.
`ROADMAP.md` annonce déjà `0.0.5` comme planifiée et `CHANGELOG.md` reste limité aux releases publiées ; aucun changement cérémoniel de ces deux fichiers n'est requis ici.
## Validation opérateur
Après application sur le commit stable `0.0.4`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.1'
test -f docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
test -f docs/studies/000-README.md
test -f docs/studies/001-KSP_GAMES_RECONCILIATION.md
test -f deltas/0.0.5/alpha.1.md
test ! -e history/0.0.5/alpha.1.md
grep -Fx '<!-- version: 12 -->' README.md
grep -Fx '<!-- version: 10 -->' docs/000-README.md
grep -F '005-V0_0_5_RECONCILIATION_PLAN.md' README.md docs/000-README.md
grep -F '001-KSP_GAMES_RECONCILIATION.md' README.md docs/000-README.md docs/studies/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
import tomllib
expected_hashes = {
'pgr-v0.0.4.zip': '7137bb084f017362323a2043d13ba71490be15b8786adc8d645981bf455b80ae',
'khadhroony-solana-project-v0.3.16.zip': 'db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0',
'games-v0.3.5.zip': '5f5fdee1a271386766d059657d6eaa831acdc263b3e722fed738808335c0a105',
}
study = Path('docs/studies/001-KSP_GAMES_RECONCILIATION.md').read_text(encoding='utf-8')
plan = Path('docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md').read_text(encoding='utf-8')
for name, digest in expected_hashes.items():
assert name in study or name in plan, name
assert digest in study or digest in plan, digest
for path in (
Path('templates/rust-cargo/rustfmt.toml'),
Path('templates/rust-cargo/clippy.toml'),
Path('templates/rust-cargo/.cargo/config.toml'),
Path('templates/rust-cargo/Cargo.toml'),
Path('templates/rust-cargo/crates/project-core-lib/Cargo.toml'),
):
with path.open('rb') as stream:
tomllib.load(stream)
expected_counts = {'0.0.1': 12, '0.0.2': 12, '0.0.3': 10, '0.0.4': 9}
for release, expected in expected_counts.items():
deltas = {path.name for path in Path('deltas', release).glob('*.md')}
histories = {path.name for path in Path('history', release).glob('*.md')}
assert len(deltas) == expected, (release, len(deltas))
assert deltas == histories, (release, sorted(deltas ^ histories))
statuses_004 = {}
for path in Path('history/0.0.4').glob('*.md'):
text = path.read_text(encoding='utf-8')
match = re.search(r'## Statut\s+(PASS|FAIL|PARTIAL|BLOCKED)\s', text)
assert match is not None, path
statuses_004[path.name] = match.group(1)
assert statuses_004['alpha.4.md'] == 'FAIL'
assert statuses_004['alpha.4.fix.1.md'] == 'PASS'
assert statuses_004['beta.1.md'] == 'FAIL'
assert statuses_004['beta.1.fix.1.md'] == 'PASS'
assert statuses_004['rc.1.md'] == 'PASS'
assert statuses_004['rel.001.md'] == 'PASS'
assert 'ne sont pas encore gouvernés par PGR' in plan
assert 'aucune migration de KSP ou Games' in plan
assert 'Tauri' in plan
assert 'audit_rust_export_completeness.py' in study
print('0.0.5 alpha.1 structural audit: clean (43 prior pairs, 5 TOML parsed, reconciliation sources recorded)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/studies/000-README.md docs/studies/001-KSP_GAMES_RECONCILIATION.md \
deltas/0.0.5/alpha.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M README.md
M VERSION
A deltas/0.0.5/alpha.1.md
M docs/000-README.md
A docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
A docs/studies/000-README.md
A docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
La revue opérateur doit en outre confirmer que :
- les trois archives/hashes consignés correspondent bien aux sources autoritaires fournies pour cette reprise ;
- l'étude traite KSP et Games comme corpus non encore migrés vers PGR ;
- le plan n'atteste aucun profil Tauri, audit de façade ou template avant sa tranche dédiée ;
- les conventions métier et plateforme locales ne sont pas promues en règles PGR par simple similarité ;
- aucune modification des deux projets externes n'est cachée dans le delta.
## Transition
### PASS
Rédiger et livrer séparément `history/0.0.5/alpha.1.md` avec les résultats réellement observés ; l'appliquer et committer la tranche. Préparer seulement ensuite `0.0.5-alpha.2` pour le contrat générique des prompts versionnés.
### FAIL
Consigner le résultat réel dans le history de `alpha.1`, puis corriger le cadrage dans `0.0.5-alpha.1.fix.1` ou produire un REPLAN motivé. Aucun contenu de `alpha.2` ne doit être absorbé silencieusement dans un fix.

179
deltas/0.0.5/alpha.2.md Normal file
View File

@@ -0,0 +1,179 @@
<!-- file: deltas/0.0.5/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.2 — contrat générique des prompts de démarrage
## Baseline et version
Baseline attendue : commit opérateur de `0.0.5-alpha.1`, réalisé après application de `history/0.0.5/alpha.1.md` avec statut `PASS`.
Le hash de ce commit n'est volontairement pas anticipé : le history `alpha.1` et le présent delta peuvent être livrés dans le même échange, mais restent deux archives séparées et le delta `alpha.2` MUST NOT être appliqué avant le commit de `alpha.1`.
Version avant application :
```text
0.0.5-alpha.1
```
Version après application :
```text
0.0.5-alpha.2
```
## Objet
Exécuter la deuxième tranche du plan `0.0.5` en renforçant l'owner `docs/rules/210-WORKFLOW.md` pour les prompts de démarrage versionnés.
Les prompts PGR récents et les baselines KSP/Games montrent qu'un bon prompt de reprise ne se limite pas à nommer une baseline et une mission : il doit permettre de reconstruire explicitement l'état utile, les sources à lire, les décisions déjà acquises, les limites de scope, la première gate et la trajectoire de validation sans réimporter toute la documentation du projet.
La tranche généralise ce contrat sémantique sans copier la structure exhaustive des prompts KSP/Games. Elle ne crée ni nouveau template manuel ni nouveau type d'artefact.
## Scope
REPLACE :
```text
VERSION
docs/rules/000-README.md
docs/rules/210-WORKFLOW.md
```
ADD :
```text
deltas/0.0.5/alpha.2.md
```
DELETE : aucun.
L'archive delta contient uniquement ces quatre fichiers complets avec leurs chemins relatifs. Elle ne contient pas `history/0.0.5/alpha.1.md`, livré séparément pour clôturer la tranche précédente, ni `history/0.0.5/alpha.2.md`, qui sera produit après la gate opérateur.
Le plan `docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md`, l'étude `docs/studies/001-KSP_GAMES_RECONCILIATION.md` et `docs/templates/003-NEW_SESSION_PROMPT.md` restent inchangés : cette tranche exécute leur trajectoire et préserve explicitement la séparation entre prompt versionné et message manuel de nouvelle session.
## Contrat matérialisé
`docs/rules/210-WORKFLOW.md` porte désormais un contrat réutilisable des prompts de démarrage versionnés couvrant :
- baseline autoritaire, cible et première tranche ;
- ordre de lecture nécessaire à une reprise fiable ;
- état déjà acquis et traçabilité des décisions conservées ;
- mission et résultat attendu ;
- scope et hors-scope ;
- décisions gelées et questions ouvertes ;
- première gate et travaux éventuellement interdits avant sa fermeture ;
- trajectoire prévisionnelle explicitement non contraignante ;
- validation et responsabilité de la preuve ;
- comportement fail-closed lorsqu'une source externe requise manque.
Le contrat reste sémantique : il n'impose pas neuf titres littéraux ni une longueur uniforme. Les projets importants peuvent détailler leur ordre de lecture et leurs questions de cadrage ; les projets simples conservent une forme courte dès lors que les mêmes responsabilités sont couvertes.
Les règles locales de langage, plateforme, framework, architecture ou métier ne deviennent pas des règles PGR parce qu'elles apparaissent dans un prompt. Le prompt doit renvoyer vers les owners existants au lieu de les dupliquer.
`docs/templates/003-NEW_SESSION_PROMPT.md` conserve son rôle distinct : produire la courte phrase manuelle de reprise après une stable publiée. Il ne remplace pas le prompt versionné et n'est pas dupliqué par cette tranche.
## Validation opérateur
Après avoir appliqué `history/0.0.5/alpha.1.md`, committé `0.0.5-alpha.1`, puis appliqué le présent delta, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.2'
test -f history/0.0.5/alpha.1.md
test -f deltas/0.0.5/alpha.2.md
test ! -e history/0.0.5/alpha.2.md
grep -Fx '<!-- version: 12 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 4 -->' docs/rules/210-WORKFLOW.md
grep -F 'prompts versionnés' docs/rules/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
required = (
'## Prompt de démarrage versionné',
'### Contrat minimal',
'baseline autoritaire et cible',
'ordre de lecture',
'état déjà acquis',
'mission et résultat attendu',
'scope et hors-scope',
'décisions gelées et questions ouvertes',
'première gate',
'trajectoire prévisionnelle',
'validation et responsabilité',
'### Sources externes et données manquantes',
'### Décisions acquises et détails locaux',
'### Création et clôture',
'003-NEW_SESSION_PROMPT.md',
)
for phrase in required:
assert phrase in workflow, phrase
for forbidden in (
'prompts/036-V0_3_17_START_PROMPT.md',
'prompts/007-V0_3_6_START_PROMPT.md',
'tokio-postgres',
'WebTransport',
'Uroburas',
):
assert forbidden not in workflow, forbidden
assert 'MUST NOT les recopier exhaustivement' in workflow
assert 'Le prompt n\'a pas à reproduire littéralement cette numérotation.' in workflow
assert 'MUST NOT autoriser à reconstituer silencieusement' in workflow
assert 'Les contraintes locales de langage, plateforme, framework, architecture ou métier restent chez leurs owners respectifs.' in workflow
manual = Path('docs/templates/003-NEW_SESSION_PROMPT.md').read_text(encoding='utf-8')
assert '<!-- version: 1 -->' in manual
assert 'une seule phrase' in manual
print('0.0.5 alpha.2 prompt contract audit: clean (versioned prompt strengthened, manual restart template unchanged)')
PY
git diff --check
git add VERSION docs/rules/000-README.md docs/rules/210-WORKFLOW.md \
deltas/0.0.5/alpha.2.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M VERSION
A deltas/0.0.5/alpha.2.md
M docs/rules/000-README.md
M docs/rules/210-WORKFLOW.md
```
La revue opérateur doit en outre confirmer que :
- le nouveau contrat décrit des responsabilités de reprise et non une liste obligatoire de titres ;
- la baseline et les sources manquantes restent fail-closed : aucun état externe n'est reconstruit depuis un souvenir ou un workspace non fourni ;
- les décisions acquises sont résumées seulement lorsqu'elles empêchent une régression utile et restent traçables vers leur owner ;
- les contraintes KSP/Games spécifiques ne sont pas aspirées dans la règle générale ;
- le template `003-NEW_SESSION_PROMPT.md` reste la forme courte post-publication et n'est ni remplacé ni dupliqué.
## Transition
### PASS
Rédiger et livrer séparément `history/0.0.5/alpha.2.md` avec les résultats réellement observés ; l'appliquer et committer la tranche. Préparer seulement ensuite `0.0.5-alpha.3` pour le pattern facultatif de contrats de fichiers/familles.
### FAIL
Consigner le résultat réel dans le history de `alpha.2`, puis corriger le contrat dans `0.0.5-alpha.2.fix.1` ou produire un REPLAN motivé. Aucun contenu de `alpha.3` ne doit être absorbé silencieusement dans un fix.

View File

@@ -0,0 +1,164 @@
<!-- file: deltas/0.0.5/alpha.3.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.3.fix.1 — couverture des tables dans les exemples Markdown fenced
## Baseline et version
Baseline attendue : commit opérateur de `0.0.5-alpha.3`, réalisé après application de `history/0.0.5/alpha.3.md` avec statut `FAIL`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.0.5-alpha.3
```
Version après application :
```text
0.0.5-alpha.3.fix.1
```
## Objet
Corriger le faux négatif découvert pendant la gate opérateur de `alpha.3` : `audit_markdown_tables.py` ignorait toutes les tables placées dans des blocs fenced, y compris les exemples explicitement `markdown` du template `004-FILE_FAMILY_CONTRACTS.md`.
Le fix étend uniquement le contrat de l'audit de tables. Il ne transforme pas l'audit en analyseur général des blocs de code et n'introduit aucun contenu de la tranche Rust `alpha.4`.
## Scope
REPLACE :
```text
VERSION
scripts/audit_markdown_tables.py
docs/templates/004-FILE_FAMILY_CONTRACTS.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
tests/test_markdown_tables.py
deltas/0.0.5/alpha.3.fix.1.md
```
DELETE : aucun.
Le history `history/0.0.5/alpha.3.md` appartient au commit baseline du FAIL et n'est pas inclus dans l'archive du fix.
## Correction
`scripts/audit_markdown_tables.py` passe en révision interne `2`.
L'audit continue de contrôler les tables Markdown ordinaires. Dans un bloc fenced :
- une fence explicitement `markdown` est auditée ;
- une fence explicitement `md` est auditée ;
- une fence d'un autre langage ou sans langage reste ignorée.
Cette frontière évite les faux positifs sur les sorties terminal, extraits de code ou tableaux ASCII qui utilisent éventuellement des pipes sans être du Markdown à gouverner.
`tests/test_markdown_tables.py` verrouille quatre cas :
1. table ordinaire et table fenced Markdown valides toutes deux comptées ;
2. table mal alignée dans une fence `markdown` rejetée ;
3. alias `md` audité ;
4. fence non Markdown conservée hors scope.
`docs/templates/004-FILE_FAMILY_CONTRACTS.md` passe en révision `2` et réaligne les deux tables fenced révélées par le nouvel audit.
`docs/validation/001-VALIDATION_MATRIX.md` passe en révision `10` et explicite la frontière de `PGR-MD-TABLE-001`.
## Validation opérateur
Après application du history `FAIL`, commit de `alpha.3`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.3.fix.1'
test -f history/0.0.5/alpha.3.md
test -f deltas/0.0.5/alpha.3.md
test -f deltas/0.0.5/alpha.3.fix.1.md
test -f tests/test_markdown_tables.py
test ! -e history/0.0.5/alpha.3.fix.1.md
grep -A2 '^## Statut$' history/0.0.5/alpha.3.md | grep -Fx 'FAIL'
grep -Fx '# version: 2' scripts/audit_markdown_tables.py
grep -Fx '<!-- version: 2 -->' docs/templates/004-FILE_FAMILY_CONTRACTS.md
grep -Fx '<!-- version: 10 -->' docs/validation/001-VALIDATION_MATRIX.md
grep -Fx '# version: 1' tests/test_markdown_tables.py
python3 -B -m unittest discover -s tests -p 'test_markdown_tables.py' -v
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py docs/templates/004-FILE_FAMILY_CONTRACTS.md
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.3.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
script = Path('scripts/audit_markdown_tables.py').read_text(encoding='utf-8')
assert '_MARKDOWN_FENCE_LANGUAGES = frozenset({"markdown", "md"})' in script
assert 'audit_fenced_markdown' in script
template = Path('docs/templates/004-FILE_FAMILY_CONTRACTS.md').read_text(encoding='utf-8')
assert template.count('```markdown') == 2
matrix = Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8')
assert 'fences explicitement `markdown` ou `md`' in matrix
assert 'sorties terminal' in matrix
print('0.0.5 alpha.3.fix.1 fenced Markdown table audit: clean (regression covered, two template examples governed)')
PY
git diff --check
git add VERSION scripts/audit_markdown_tables.py tests/test_markdown_tables.py \
docs/templates/004-FILE_FAMILY_CONTRACTS.md \
docs/validation/001-VALIDATION_MATRIX.md \
deltas/0.0.5/alpha.3.fix.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.3.fix.1.md
M docs/templates/004-FILE_FAMILY_CONTRACTS.md
M docs/validation/001-VALIDATION_MATRIX.md
M scripts/audit_markdown_tables.py
A tests/test_markdown_tables.py
```
Le contrôle ciblé du template doit désormais compter ses deux exemples :
```text
Markdown table audit: clean (2 table(s), 1 file(s))
```
La suite Python doit compter `19` tests si aucun autre test n'est ajouté localement avant exécution.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.5/alpha.3.fix.1.md`, committer et pousser le fix, puis reprendre le plan `0.0.5` à `alpha.4`.
### FAIL
Rester dans `0.0.5-alpha.3.fix.M`. Le scope MUST rester limité au contrat de `PGR-MD-TABLE-001` et aux tables révélées par ce contrôle tant qu'aucun défaut plus large ne justifie un REPLAN.

173
deltas/0.0.5/alpha.3.md Normal file
View File

@@ -0,0 +1,173 @@
<!-- file: deltas/0.0.5/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.3 — pattern facultatif de contrats de fichiers ou familles
## Baseline et version
Baseline attendue : commit opérateur de `0.0.5-alpha.2`, réalisé après application de `history/0.0.5/alpha.2.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé. Le history `alpha.2` et le présent delta peuvent être livrés dans le même échange, mais restent deux archives séparées et le delta `alpha.3` MUST NOT être appliqué avant le commit de `alpha.2`.
Version avant application :
```text
0.0.5-alpha.2
```
Version après application :
```text
0.0.5-alpha.3
```
## Objet
Exécuter la troisième tranche du plan `0.0.5` en généralisant un besoin observé indépendamment dans les deux corpus externes : expliciter, lorsque la complexité le justifie, la responsabilité et la règle de modification de certaines familles de fichiers locales.
La tranche normalise le pattern et non les catalogues KSP/Games. Elle n'impose ni le nom `FILE_CONTRACTS.md`, ni une table exhaustive, ni la reprise de leurs chemins, règles métier ou conventions de release.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/rules/300-DOCUMENTATION.md
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
```
ADD :
```text
docs/templates/004-FILE_FAMILY_CONTRACTS.md
deltas/0.0.5/alpha.3.md
```
DELETE : aucun.
L'archive delta contient uniquement ces six fichiers complets avec leurs chemins relatifs. Elle ne contient pas `history/0.0.5/alpha.2.md`, livré séparément pour clôturer la tranche précédente, ni `history/0.0.5/alpha.3.md`, qui sera produit après la gate opérateur.
## Contrat matérialisé
`docs/rules/300-DOCUMENTATION.md` possède désormais le pattern générique :
- un registre local est facultatif et ne doit exister que pour lever une ambiguïté réelle ;
- il décrit au minimum fichier/famille, responsabilité durable et règle de modification ;
- source de vérité, statut généré/versionné, owner ou validation restent des champs optionnels ;
- le registre ne doit ni recopier les owners existants ni devenir un miroir exhaustif de l'arborescence ;
- son nom, son emplacement et sa forme appartiennent au projet destinataire ;
- l'ajout d'un fichier déjà couvert par une famille ne force pas une entrée supplémentaire.
`docs/templates/004-FILE_FAMILY_CONTRACTS.md` fournit une forme d'adaptation courte avec critères d'usage, modèle minimal, règles d'instanciation et exemple abstrait.
La fondation `001-PROJECT_GOVERNANCE_FOUNDATION.md` référence ce pattern uniquement comme possibilité pour un projet dont plusieurs familles durables deviennent ambiguës. Elle confirme explicitement qu'un projet simple n'a rien à matérialiser.
## Validation opérateur
Après avoir appliqué `history/0.0.5/alpha.2.md`, committé `0.0.5-alpha.2`, puis appliqué le présent delta, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.3'
test -f history/0.0.5/alpha.2.md
test -f deltas/0.0.5/alpha.3.md
test -f docs/templates/004-FILE_FAMILY_CONTRACTS.md
test ! -e history/0.0.5/alpha.3.md
grep -Fx '<!-- version: 11 -->' docs/000-README.md
grep -Fx '<!-- version: 3 -->' docs/rules/300-DOCUMENTATION.md
grep -Fx '<!-- version: 2 -->' docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
grep -Fx '<!-- version: 1 -->' docs/templates/004-FILE_FAMILY_CONTRACTS.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
doc = Path('docs/rules/300-DOCUMENTATION.md').read_text(encoding='utf-8')
template = Path('docs/templates/004-FILE_FAMILY_CONTRACTS.md').read_text(encoding='utf-8')
foundation = Path('docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md').read_text(encoding='utf-8')
index = Path('docs/000-README.md').read_text(encoding='utf-8')
required_doc = (
'## Registre local de contrats de fichiers ou familles',
'outil de désambiguïsation, pas un inventaire exhaustif',
'le fichier, motif de chemin ou famille concernée',
'sa responsabilité durable',
'la règle ou le déclencheur pertinent de modification',
'PGR n\'impose ni `FILE_CONTRACTS.md`',
'l\'ajout d\'un fichier conforme à une famille déjà décrite ne force pas une nouvelle entrée',
)
for phrase in required_doc:
assert phrase in doc, phrase
required_template = (
'# Pattern — contrats locaux de fichiers ou familles',
'Quand l\'utiliser',
'Forme minimale',
'Règles d\'adaptation',
'Critère de sortie',
'`docs/rules/FILE_CONTRACTS.md` est un nom possible, pas une convention PGR obligatoire',
)
for phrase in required_template:
assert phrase in template, phrase
assert '004-FILE_FAMILY_CONTRACTS.md' in foundation
assert 'Ce registre reste facultatif' in foundation
assert '004-FILE_FAMILY_CONTRACTS.md' in index
for text in (doc, template, foundation):
for forbidden in ('tokio-postgres', 'WebTransport', 'Uroburas'):
assert forbidden not in text, forbidden
print('0.0.5 alpha.3 file-family contract audit: clean (optional registry, short reusable pattern, no project-specific contract imported)')
PY
git diff --check
git add VERSION docs/000-README.md docs/rules/300-DOCUMENTATION.md \
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md \
docs/templates/004-FILE_FAMILY_CONTRACTS.md deltas/0.0.5/alpha.3.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M VERSION
A deltas/0.0.5/alpha.3.md
M docs/000-README.md
M docs/rules/300-DOCUMENTATION.md
M docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
A docs/templates/004-FILE_FAMILY_CONTRACTS.md
```
La revue opérateur doit en outre confirmer que :
- le pattern réduit une ambiguïté réelle au lieu d'imposer une nouvelle cérémonie ;
- `FILE_CONTRACTS.md` reste un exemple de nom, jamais une obligation ;
- le registre ne devient pas un catalogue exhaustif de chaque fichier du dépôt ;
- une règle détaillée déjà possédée ailleurs est référencée plutôt que dupliquée ;
- la fondation n'impose aucun nouveau document aux petits projets ou aux projets dont les responsabilités sont déjà claires.
## Transition
### PASS
Rédiger et livrer séparément `history/0.0.5/alpha.3.md` avec les résultats réellement observés ; l'appliquer et committer la tranche. Préparer seulement ensuite `0.0.5-alpha.4` pour l'audit Rust facultatif de façade/export completeness.
### FAIL
Consigner le résultat réel dans le history de `alpha.3`, puis corriger le pattern dans `0.0.5-alpha.3.fix.1` ou produire un REPLAN motivé. Aucun contenu de l'audit Rust `alpha.4` ne doit être absorbé silencieusement dans un fix.

221
deltas/0.0.5/alpha.4.md Normal file
View File

@@ -0,0 +1,221 @@
<!-- file: deltas/0.0.5/alpha.4.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.4 — REPLAN du lifecycle inter-release et de l'horizon
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.3.fix.1`, réalisé après application de `history/0.0.5/alpha.3.fix.1.md` avec statut `PASS`.
Le hash de ce futur commit n'est pas anticipé.
Version avant application :
```text
0.0.5-alpha.3.fix.1
```
Version après application :
```text
0.0.5-alpha.4
```
## Rôle de la tranche
`alpha.4` est un `REPLAN` déclenché après la gate réussie du fix précédent. Il traite un besoin de gouvernance général découvert en relisant le plan `0.0.5`, `ROADMAP.md` et les historiques de conception PGR `0.0.1` à `0.0.4` : les responsabilités de fermeture sont connues séparément mais ne sont pas encore reliées par un contrat explicite de plan, et l'horizon des versions futures ne possède pas de mécanisme de revue.
La tranche ne remet pas en cause `alpha.3.fix.1`, ne commence pas le chantier Rust de façade et ne matérialise aucun profil Tauri.
## Scope
REPLACE :
```text
VERSION
ROADMAP.md
docs/000-README.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/200-GOVERNANCE.md
docs/rules/210-WORKFLOW.md
docs/rules/300-DOCUMENTATION.md
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
docs/templates/003-NEW_SESSION_PROMPT.md
```
ADD :
```text
docs/templates/005-RELEASE_PLAN.md
deltas/0.0.5/alpha.4.md
```
DELETE : aucun.
Le history `alpha.3.fix.1` appartient au commit baseline et n'est pas inclus dans l'archive du présent delta.
## Décisions matérialisées
### Plan de release
Un plan complexe doit désormais expliciter sa **clôture et transition** : réconciliation documentaire, `CHANGELOG`, `ROADMAP`, prompt/handoff suivant, fermeture du plan, stable et publication.
Il doit aussi indiquer si une **revue d'horizon** est nécessaire. Une cible future inconnue reste inconnue : PGR interdit d'inventer une version ou une mission uniquement pour remplir le plan.
### Revue d'horizon
`ROADMAP.md` devient explicitement une trajectoire macro engagée à horizon fini. Une revue d'horizon est déclenchée lorsque la dernière release connue approche, qu'un jalon change la trajectoire ou que les ideas/studies/décisions accumulées justifient de rediscuter la suite.
La revue peut vivre dans une session stratégique séparée sans changement de `VERSION`.
Pour PGR, l'après-`0.1.0` reste volontairement ouvert. Le plan `0.1.0` devra programmer sa propre revue avant fermeture au lieu de spéculer dès `0.0.5`.
### Continuité et productivité
Lorsque la gate courante est `PASS` et que la suite est déjà déterminée, le générateur peut remettre `history` courant et `delta` suivant dans la même réponse. Les archives restent séparées et le delta suivant reste interdit d'application avant le commit de la tranche courante.
Le message manuel après publication devient spontané lorsque la prochaine cible est connue. S'il existe une preuve post-tag externe requise, la consigne finale indique explicitement qu'elle doit être fournie avec l'archive taggée.
### Pattern de plan
`docs/templates/005-RELEASE_PLAN.md` fournit une forme courte réutilisable pour KSP, Games et les futurs projets : mission, état acquis/ouvert, scope, validation, forecast, déclencheurs de REPLAN, clôture/transition et revue d'horizon.
Le pattern ne crée pas un journal de revisions obligatoire ; les deltas/histories restent la trace détaillée.
## Replan de 0.0.5
L'ancien forecast est décalé :
```text
alpha.4 REPLAN lifecycle inter-release / horizon
alpha.5 audit Rust façade/export completeness
alpha.6 profil Tauri
alpha.7 décision skeleton Tauri
beta.1 réconciliation intégrée
rc.1 candidate gelée / CHANGELOG / ROADMAP / prompt 006
stable 0.0.5 + publish.001 séparé
```
Aucun ancien objectif n'est abandonné par ce décalage.
## Validation opérateur
Après application du history `PASS` de `alpha.3.fix.1`, commit/push de ce fix, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.4'
test -f history/0.0.5/alpha.3.fix.1.md
test -f deltas/0.0.5/alpha.4.md
test -f docs/templates/005-RELEASE_PLAN.md
test ! -e history/0.0.5/alpha.4.md
grep -A2 '^## Statut$' history/0.0.5/alpha.3.fix.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 2 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -Fx '<!-- version: 3 -->' docs/rules/200-GOVERNANCE.md
grep -Fx '<!-- version: 5 -->' docs/rules/210-WORKFLOW.md
grep -Fx '<!-- version: 4 -->' docs/rules/300-DOCUMENTATION.md
grep -Fx '<!-- version: 6 -->' ROADMAP.md
grep -Fx '<!-- version: 2 -->' docs/templates/003-NEW_SESSION_PROMPT.md
grep -Fx '<!-- version: 1 -->' docs/templates/005-RELEASE_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.3.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
plan = Path('docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'## REPLAN alpha.4 — lifecycle inter-release et horizon',
'## Clôture et transition',
'## Revue d\'horizon',
'### alpha.5 — audit Rust de façade/export completeness',
'### alpha.6 — premier profil framework : Tauri',
'### alpha.7 — décision de skeleton Tauri',
):
assert phrase in plan, phrase
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
for phrase in (
'clôture et transition',
'revue d\'horizon',
'archive history de la tranche courante',
'archive delta de la tranche suivante',
'MUST remettre spontanément',
'preuve future extérieure au tag',
):
assert phrase in workflow, phrase
doc = Path('docs/rules/300-DOCUMENTATION.md').read_text(encoding='utf-8')
for phrase in (
'### Revue d\'horizon',
'Une roadmap à horizon fini est valide.',
'roadmap ou plan lorsqu\'un engagement de réalisation existe',
):
assert phrase in doc, phrase
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '## Horizon après `0.1.0`' in roadmap
assert 'L\'horizon est volontairement ouvert.' in roadmap
assert '0.2.0' in roadmap # cité uniquement comme version à ne pas réserver arbitrairement
template = Path('docs/templates/005-RELEASE_PLAN.md').read_text(encoding='utf-8')
for phrase in ('## Contrat minimal', '## Clôture et transition', '## Revue d\'horizon', '## Critère de sortie'):
assert phrase in template, phrase
manual = Path('docs/templates/003-NEW_SESSION_PROMPT.md').read_text(encoding='utf-8')
assert 'doit être remis spontanément' in manual
assert 'horizon reste ouvert' in manual
print('0.0.5 alpha.4 lifecycle audit: clean (closure assigned, horizon review explicit, deterministic handoff optimized)')
PY
git diff --check
git add VERSION ROADMAP.md docs/000-README.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/200-GOVERNANCE.md docs/rules/210-WORKFLOW.md \
docs/rules/300-DOCUMENTATION.md \
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md \
docs/templates/003-NEW_SESSION_PROMPT.md docs/templates/005-RELEASE_PLAN.md \
deltas/0.0.5/alpha.4.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history `alpha.4` est exactement :
```text
M ROADMAP.md
M VERSION
A deltas/0.0.5/alpha.4.md
M docs/000-README.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/200-GOVERNANCE.md
M docs/rules/210-WORKFLOW.md
M docs/rules/300-DOCUMENTATION.md
M docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
M docs/templates/003-NEW_SESSION_PROMPT.md
A docs/templates/005-RELEASE_PLAN.md
```
## Transition
### PASS
Créer/appliquer `history/0.0.5/alpha.4.md`, committer/pousser `0.0.5-alpha.4`, puis poursuivre le forecast révisé à `0.0.5-alpha.5` pour l'audit Rust de façade/export completeness.
### FAIL
Rester dans `0.0.5-alpha.4.fix.M` tant que le défaut concerne le lifecycle inter-release ou la documentation livrée par cette tranche. Si la revue révèle qu'un autre chantier substantiel doit être absorbé avant l'audit Rust, refaire explicitement le REPLAN plutôt que l'introduire dans un fix.

View File

@@ -0,0 +1,217 @@
<!-- file: deltas/0.0.5/alpha.5.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.5.fix.1 — canonicalisation réelle des références crate-root
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.5`, réalisé après application de `history/0.0.5/alpha.5.md` avec statut `FAIL`.
Version avant application :
```text
0.0.5-alpha.5
```
Version après application :
```text
0.0.5-alpha.5.fix.1
```
## Cause du fix
La gate mécanique de `alpha.5` est passée, mais la revue fonctionnelle opérateur a identifié un blind spot dans `RUST-IMPORT-201` : la `version: 1` détecte `crate::module::Item` lorsque `crate::Item` existe, mais ne détecte pas un usage nu ou autrement non canonique de ce même item dans son module propriétaire ou un autre module.
Or le contrat recherché est bien :
```text
item partagé pub/pub(crate)
↓
façade crate-root
↓
toutes les références intra-crate détectées utilisent crate::Item
```
Le compilateur et Clippy ne possèdent pas cette convention. Une seule référence correcte à `crate::Item` peut rendre le réexport utilisé tout en laissant subsister d'autres `Item`, `self::Item`, `super::Item` ou chemins internes.
## Scope
REPLACE :
```text
VERSION
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/510-RUST_CARGO.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
docs/validation/003-RUST_EXPORT_COMPLETENESS.md
scripts/audit_rust_export_completeness.py
tests/test_rust_export_completeness.py
```
ADD :
```text
deltas/0.0.5/alpha.5.fix.1.md
```
DELETE : aucun.
Le history `alpha.5` appartient au commit baseline et n'est pas inclus dans l'archive du présent delta.
## Décisions matérialisées
### RUST-IMPORT-201 couvre toute référence non canonique détectable
Pour un item possédant une identité crate-root, la seule forme intra-crate canonique est :
```text
crate::Item
```
Le diagnostic couvre désormais les formes suivantes lorsqu'elles désignent cet item partagé :
```text
Item
self::Item
super::Item
module::Item
crate::module::Item
```
La règle s'applique au module propriétaire lui-même : signatures, `impl`, constructeurs, appels et références de types doivent employer la façade crate-root lorsqu'ils portent l'item partagé.
Les déclarations qui créent l'item et les lignes de réexport qui construisent la façade sont exemptées. Les éléments strictement privés restent hors de cette règle ; leurs tests attachés peuvent utiliser `super::PrivateItem`.
### Targets Cargo distinctes
Le fix évite également de confondre bibliothèque et binaire d'un même package. `src/lib.rs`, `src/main.rs`, les bins standard et les targets explicites sont traités comme des crates compilées distinctes. Le graphe de modules de chaque target est suivi via `mod name;` et `#[path = "..."]`.
Cette correction est nécessaire pour ne pas qualifier à tort `owner_crate::Item` dans un binaire comme référence intra-crate de la bibliothèque du même package.
### Analyse lexicale bornée
L'audit reste read-only et standard library. Il ne prétend pas remplacer un parseur Rust :
- les commentaires et littéraux sont masqués ;
- les chemins qualifiés par une crate externe ne sont pas assimilés à l'item local homonyme ;
- un appel de méthode `.name()` n'est pas assimilé à une fonction libre locale de même nom ;
- les fonctions libres sont contrôlées dans les contextes d'appel directs ; leur usage comme valeur de premier ordre peut nécessiter une revue humaine.
### Réconciliation corrigée
En `--report-only --summary-only`, la `version: 2` observe sur les baselines de `alpha.1` :
```text
KSP 0.3.16
22 package(s)
1525 candidate(s)
RUST-IMPORT-201: 1525
Games 0.3.5
23 package(s)
181 candidate(s)
RUST-API-201: 2
RUST-IMPORT-201: 179
```
Ces nombres sont des lignes candidates à revoir, pas des déclarations distinctes. Ils ne constituent pas une non-conformité rétroactive : KSP et Games ne sont pas encore gouvernés par ce PGR. Ils montrent pourquoi une future adoption doit commencer par un inventaire `--report-only` et une migration proportionnée.
## Validation opérateur
Après application du history `FAIL` de `alpha.5`, commit/push de cette tranche, puis application du présent fix :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.5.fix.1'
test -f history/0.0.5/alpha.5.md
test -f deltas/0.0.5/alpha.5.fix.1.md
test ! -e history/0.0.5/alpha.5.fix.1.md
grep -A2 '^## Statut$' history/0.0.5/alpha.5.md | grep -Fx 'FAIL'
grep -Fx '# version: 2' scripts/audit_rust_export_completeness.py
grep -Fx '# version: 2' tests/test_rust_export_completeness.py
grep -Fx '<!-- version: 2 -->' docs/validation/003-RUST_EXPORT_COMPLETENESS.md
grep -Fx '<!-- version: 4 -->' docs/rules/510-RUST_CARGO.md
python3 -B -m unittest discover -s tests -p 'test_rust_export_completeness.py' -v
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.5.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
script = Path('scripts/audit_rust_export_completeness.py').read_text(encoding='utf-8')
for phrase in (
'def target_roots(',
'def target_modules(',
'def _canonical_reference_candidates(',
'RUST-API-201',
'RUST-IMPORT-201',
'non-canonical same-crate reference',
):
assert phrase in script, phrase
validation = Path('docs/validation/003-RUST_EXPORT_COMPLETENESS.md').read_text(encoding='utf-8')
for phrase in (
'Item\nself::Item\nsuper::Item\nmodule::Item\ncrate::module::Item',
'dans le module qui déclare l\'item',
'1525 candidate(s)',
'181 candidate(s)',
'pas des déclarations distinctes',
):
assert phrase in validation, phrase
rules = Path('docs/rules/510-RUST_CARGO.md').read_text(encoding='utf-8')
assert 'toute référence dans la même crate MUST utiliser `crate::Item`' in rules
assert 'y compris depuis son module de déclaration' in rules
print('0.0.5 alpha.5.fix.1 canonical Rust path audit: clean (owner module, cross-module, attached tests, distinct Cargo targets)')
PY
git diff --check
git add VERSION \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/510-RUST_CARGO.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
docs/validation/003-RUST_EXPORT_COMPLETENESS.md \
scripts/audit_rust_export_completeness.py \
tests/test_rust_export_completeness.py \
deltas/0.0.5/alpha.5.fix.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.5.fix.1.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/510-RUST_CARGO.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
M docs/validation/003-RUST_EXPORT_COMPLETENESS.md
M scripts/audit_rust_export_completeness.py
M tests/test_rust_export_completeness.py
```
## Transition
### PASS
Créer/appliquer `history/0.0.5/alpha.5.fix.1.md`, committer/pousser `0.0.5-alpha.5.fix.1`, puis poursuivre à `0.0.5-alpha.6` pour le profil Tauri prévu par le plan.
### FAIL
Rester dans `0.0.5-alpha.5.fix.M`. Aucun travail Tauri ne doit être absorbé tant que le contrat de façade Rust n'est pas correctement fermé.

205
deltas/0.0.5/alpha.5.md Normal file
View File

@@ -0,0 +1,205 @@
<!-- file: deltas/0.0.5/alpha.5.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.5 — audit Rust de façade/export completeness
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.4`, réalisé après application de `history/0.0.5/alpha.4.md` avec statut `PASS`.
Le hash de ce futur commit n'est pas anticipé.
Version avant application :
```text
0.0.5-alpha.4
```
Version après application :
```text
0.0.5-alpha.5
```
## Rôle de la tranche
`alpha.5` extrait un audit Rust facultatif réellement réutilisable à partir du corpus KSP/Games, mais corrige avant généralisation une limite découverte dans le script historique : Games organise ses crates sous plusieurs niveaux et n'était pas réellement couvert par le glob `crates/*/Cargo.toml`.
La tranche reste limitée à la façade crate-root et aux chemins same-crate canoniques. Elle ne copie pas `audit_rust_general_rules.py`, ne commence pas Tauri et ne transforme pas PGR en workspace Rust.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/510-RUST_CARGO.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
docs/validation/003-RUST_EXPORT_COMPLETENESS.md
scripts/audit_rust_export_completeness.py
tests/test_rust_export_completeness.py
deltas/0.0.5/alpha.5.md
```
DELETE : aucun.
Le history `alpha.4` appartient au commit baseline et n'est pas inclus dans l'archive du présent delta.
## Décisions matérialisées
### Audit monotâche
Le nouveau script possède exactement deux responsabilités :
```text
RUST-API-201
façade crate-root absente pour un élément public, ou crate-public clairement partagé
RUST-IMPORT-201
chemin `crate::module::Item` alors qu'un réexport explicite fournit déjà `crate::Item`
```
Les conventions des tests unitaires séparés du script historique ne sont pas reprises. Le contrôle d'un symbole `crate::X` inexistant n'est pas repris non plus, car le compilateur Rust possède déjà la résolution de noms.
### Découverte des crates
La découverte des `Cargo.toml` devient récursive et accepte les crates imbriquées. Les arbres générés usuels (`target`, `build`, `builds`, `dist`, `node_modules`, etc.) restent ignorés.
Le module fichier `foo/mod.rs` est interprété comme `foo`, et les réexports crate-root simples, groupés ou aliasés couverts par les tests sont reconnus.
### Adoption facultative
Le contrat général Rust reste un `SHOULD`. Un projet existant peut commencer avec `--report-only`, traiter les écarts ou exceptions locales, puis rendre l'audit bloquant seulement après décision explicite.
L'audit est documenté dans `docs/validation/003-RUST_EXPORT_COMPLETENESS.md` et référencé par le skeleton Rust/Cargo sans devenir obligatoire.
### Mesure de réconciliation
La prévalidation générateur sur les baselines autoritaires de `alpha.1` observe :
```text
KSP 0.3.16 22 crate(s) 0 candidate(s)
Games 0.3.5 23 crate(s) 2 candidate(s)
```
Le résultat Games antérieur `0 candidate(s)` provenait d'une découverte de crates incomplète. Les deux candidats actuels ne sont pas traités comme des défauts historiques, car Games n'est pas encore gouverné par PGR.
## Validation opérateur
Après application du history `PASS` de `alpha.4`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.5'
test -f history/0.0.5/alpha.4.md
test -f deltas/0.0.5/alpha.5.md
test -f scripts/audit_rust_export_completeness.py
test -f tests/test_rust_export_completeness.py
test -f docs/validation/003-RUST_EXPORT_COMPLETENESS.md
test ! -e history/0.0.5/alpha.5.md
grep -A2 '^## Statut$' history/0.0.5/alpha.4.md | grep -Fx 'PASS'
grep -Fx '# version: 1' scripts/audit_rust_export_completeness.py
grep -Fx '# version: 1' tests/test_rust_export_completeness.py
grep -Fx '<!-- version: 1 -->' docs/validation/003-RUST_EXPORT_COMPLETENESS.md
grep -Fx '<!-- version: 3 -->' docs/rules/510-RUST_CARGO.md
grep -Fx '<!-- version: 2 -->' docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 11 -->' docs/validation/001-VALIDATION_MATRIX.md
python3 -B -m unittest discover -s tests -p 'test_rust_export_completeness.py' -v
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.4.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
script = Path('scripts/audit_rust_export_completeness.py').read_text(encoding='utf-8')
for phrase in (
'def crate_roots(',
'root.rglob("Cargo.toml")',
'RUST-API-201',
'RUST-IMPORT-201',
'--report-only',
'--summary-only',
):
assert phrase in script, phrase
for forbidden in ('RUST-IMPORT-202', 'RUST-IMPORT-203', 'RUST-IMPORT-204', 'RUST-IMPORT-205'):
assert forbidden not in script, forbidden
validation = Path('docs/validation/003-RUST_EXPORT_COMPLETENESS.md').read_text(encoding='utf-8')
for phrase in (
'22` crates KSP',
'23` crates Games',
'0 candidate(s)',
'2 candidate(s)',
'ne sont pas qualifiés de défauts rétroactifs',
):
assert phrase in validation, phrase
plan = Path('docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md').read_text(encoding='utf-8')
assert 'KSP = 0 candidate(s) / 22 crates' in plan
assert 'Games = 2 candidate(s) / 23 crates' in plan
print('0.0.5 alpha.5 Rust façade audit: clean (recursive crate discovery, narrow ownership, regression coverage)')
PY
git diff --check
git add VERSION docs/000-README.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/510-RUST_CARGO.md \
docs/skeletons/002-RUST_CARGO_WORKSPACE.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
docs/validation/001-VALIDATION_MATRIX.md \
docs/validation/003-RUST_EXPORT_COMPLETENESS.md \
scripts/audit_rust_export_completeness.py \
tests/test_rust_export_completeness.py \
deltas/0.0.5/alpha.5.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history `alpha.5` est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.5.md
M docs/000-README.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/510-RUST_CARGO.md
M docs/skeletons/002-RUST_CARGO_WORKSPACE.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
M docs/validation/001-VALIDATION_MATRIX.md
A docs/validation/003-RUST_EXPORT_COMPLETENESS.md
A scripts/audit_rust_export_completeness.py
A tests/test_rust_export_completeness.py
```
## Transition
### PASS
Créer/appliquer `history/0.0.5/alpha.5.md`, committer/pousser `0.0.5-alpha.5`, puis poursuivre à `0.0.5-alpha.6` pour le premier profil framework Tauri.
### FAIL
Rester dans `0.0.5-alpha.5.fix.M` si le défaut concerne l'audit, ses tests, sa documentation ou l'intégration Rust/Cargo. Ne pas absorber le profil Tauri dans un fix.

View File

@@ -0,0 +1,178 @@
<!-- file: deltas/0.0.5/alpha.6.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.6.fix.1 — composition Tauri/Rust/frontend et gate corrigé
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.6`, réalisé après application de `history/0.0.5/alpha.6.md` avec statut `FAIL`.
Version avant application :
```text
0.0.5-alpha.6
```
Version après application :
```text
0.0.5-alpha.6.fix.1
```
## Cause du fix
Deux défauts appartiennent au scope exact de `alpha.6` :
1. le heredoc Python de la gate `alpha.6` contient une chaîne multilignes entre quotes simples et échoue avec `SyntaxError: unterminated string literal` ;
2. le profil livré ne distingue pas encore assez explicitement le contrat Tauri universel des conventions de structure/stack retenues pour les projets Tauri que l'organisation contrôle.
La clarification opérateur confirme aussi un écart plus large dans le profil Rust strict PGR. Ce troisième sujet ne doit pas être absorbé par le présent fix : il est replanifié en `alpha.7`, puis la décision de skeleton Tauri passe à `alpha.8`.
## Scope
REPLACE :
```text
VERSION
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/700-FRAMEWORKS.md
docs/rules/710-TAURI.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
ADD :
```text
deltas/0.0.5/alpha.6.fix.1.md
```
DELETE : aucun.
## Décisions corrigées
Le fix précise que :
- un host Tauri est un projet Rust/Cargo et n'obtient aucune exception implicite aux règles Rust sélectionnées ;
- un projet externe/imposé peut conserver des règles différentes via le niveau project-specific ou des overrides explicites ;
- le profil Tauri universel ne possède pas le choix `frontend/`, Vite, TypeScript, Sass, Bootstrap ou du package manager ;
- ces choix forment un candidat de skeleton pour les futurs projets contrôlés ;
- WASM n'est pas une composante implicite de Tauri et reste normalement une unité séparée avec ses propres owners ;
- `cargo tauri add` est une commodité, pas une obligation : l'ajout explicite des dépendances et de l'initialisation à partir de la documentation officielle des plugins est valide et peut être préféré pour garder le contrôle des manifests ;
- un POC mobile non concluant pour Games ne permet pas de rejeter Tauri Android/iOS pour d'autres produits.
## REPLAN borné
La clarification révèle qu'une décision Rust déjà retenue historiquement n'est pas complètement matérialisée dans `510-RUST_CARGO.md`. `alpha.7` devient donc une tranche normale de complétude du profil Rust strict, puis l'ancienne décision de skeleton Tauri devient `alpha.8`.
Le présent fix ne modifie pas `510-RUST_CARGO.md` et n'ajoute aucun nouvel audit Rust : cela constituerait un nouveau scope fonctionnel.
## Validation opérateur
Après application du history `FAIL` de `alpha.6`, commit/push de cette tranche, puis application du présent fix :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.6.fix.1'
test -f history/0.0.5/alpha.6.md
test -f deltas/0.0.5/alpha.6.fix.1.md
test ! -e history/0.0.5/alpha.6.fix.1.md
grep -A2 '^## Statut$' history/0.0.5/alpha.6.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 2 -->' docs/rules/700-FRAMEWORKS.md
grep -Fx '<!-- version: 2 -->' docs/rules/710-TAURI.md
grep -Fx '<!-- version: 5 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 5 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 6 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.6.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
frameworks = Path('docs/rules/700-FRAMEWORKS.md').read_text(encoding='utf-8')
for phrase in (
"Il n'annule pas silencieusement les conventions des owners qu'il compose.",
'Un projet existant ou imposé de l'extérieur MAY conserver des contraintes différentes.',
'## Profil framework et convention d'instanciation',
):
assert phrase in frameworks, phrase
tauri = Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8')
for phrase in (
'## Héritage Rust du host Tauri',
'Tauri ne crée aucune exception implicite aux règles Rust sélectionnées par le projet.',
'PGR MUST NOT imposer universellement Vite, TypeScript, Sass, Bootstrap, Tailwind CSS',
'WASM n'est pas une composante implicite d'un projet Tauri.',
'PGR ne définit aucun catalogue de plugins Tauri obligatoires et ne rend pas `cargo tauri add` obligatoire.',
'Un POC Tauri mobile non concluant pour un produit particulier ne constitue pas une preuve',
):
assert phrase in tauri, phrase
version_chain = '\n'.join((
'VERSION',
'↓',
'workspace.package.version',
'↓',
'package Cargo du host',
'↓',
'version applicative Tauri',
))
assert version_chain in tauri
study = Path('docs/studies/001-KSP_GAMES_RECONCILIATION.md').read_text(encoding='utf-8')
assert 'candidat de skeleton pour projets contrôlés' in study
assert 'WASM n'est pas une dépendance implicite de Tauri' in study
assert 'écart antérieur dans le profil Rust PGR' in study
plan = Path('docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md').read_text(encoding='utf-8')
assert '### alpha.7 — complétude du profil Rust strict' in plan
assert '### alpha.8 — décision de skeleton Tauri pour projets contrôlés' in plan
print('0.0.5 alpha.6.fix.1 Tauri composition audit: clean (Rust inherited, frontend/skeleton separated, WASM independent, gate valid)')
PY
git diff --check
git add VERSION \
docs/architecture/003-RULE_PROFILE_MODEL.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/700-FRAMEWORKS.md docs/rules/710-TAURI.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
deltas/0.0.5/alpha.6.fix.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.6.fix.1.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/700-FRAMEWORKS.md
M docs/rules/710-TAURI.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
## Transition
### PASS
Créer/appliquer `history/0.0.5/alpha.6.fix.1.md`, committer/pousser le fix, puis poursuivre à `0.0.5-alpha.7` pour réconcilier les conventions Rust strictes déjà décidées avant toute matérialisation d'un skeleton Tauri.
### FAIL
Rester dans `0.0.5-alpha.6.fix.M`. Aucun changement du profil Rust ni skeleton Tauri ne doit être absorbé tant que la frontière Tauri/Rust/frontend n'est pas correctement fermée.

View File

@@ -0,0 +1,167 @@
<!-- file: deltas/0.0.5/alpha.6.fix.2.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.6.fix.2 — convention Tauri contrôlée et gate robuste
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.6.fix.1`, réalisé après application de `history/0.0.5/alpha.6.fix.1.md` avec statut `FAIL`.
Version avant application :
```text
0.0.5-alpha.6.fix.1
```
Version après application :
```text
0.0.5-alpha.6.fix.2
```
## Cause du fix
`alpha.6.fix.1` conserve une gate Python invalide : une phrase contenant `l'extérieur` est placée dans une chaîne simple et son apostrophe provoque encore `SyntaxError: unterminated string literal`.
La revue opérateur demande en parallèle de confronter le profil non seulement aux configurations Tauri mais aux règles complètes KSP/Games. Cette seconde passe montre qu'une convention de projet contrôlé plus riche est déjà éprouvée et doit être distinguée du contrat Tauri universel.
## Scope
REPLACE :
```text
VERSION
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/710-TAURI.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
ADD :
```text
deltas/0.0.5/alpha.6.fix.2.md
```
DELETE : aucun.
## Décisions
Le fix établit pour les nouveaux projets Tauri contrôlés une convention forte mais adaptable :
- host Cargo direct, sans `src-tauri/` ajouté par réflexe ;
- fichiers Tauri/frontend principaux à la racine de la crate et sources Rust sous `src/` ;
- frontend versionné sous `frontend/` ;
- `lib.rs` comme façade, `main.rs` comme launcher mince et `tauri.rs` comme owner de l'assemblage et des wrappers `#[tauri::command]` ;
- modules cohérents par fenêtre/responsabilité et modules communs pour les helpers réellement partagés ;
- TS-RS obligatoire dans le profil strict lorsque des DTO/enum/struct Rust possédés par le host sont partagés avec un frontend TypeScript, sauf incompatibilité documentée ;
- bindings générés reconstruisibles et non modifiés manuellement ;
- intégration explicite des plugins préférée à une commande de commodité opaque ;
- WASM séparé du host Tauri par défaut.
Vite, TypeScript, Sass et Bootstrap restent le candidat de stack/skeleton pour les projets contrôlés ; ils ne deviennent pas des invariants universels du framework Tauri tant que leurs owners Web ne sont pas matérialisés.
## Replanification
La seconde lecture des règles KSP/Games montre que `alpha.7` serait trop large si elle mélangeait conventions sémantiques, nomenclature et tous les audits de formatage. Le forecast devient :
```text
alpha.7 profil Rust strict + chemins + nomenclature des crates
alpha.8 formatage Rust structurel + audits monotâches
alpha.9 décision de skeleton Tauri pour projets contrôlés
beta.1 réconciliation intégrée
```
KSP est utilisé comme référence stricte ; Games sert à identifier ce qui doit rester `SHOULD`, sélectionnable ou project-specific.
## Validation opérateur
Après application du history `FAIL` de `alpha.6.fix.1`, commit/push de cette tranche, puis application du présent fix :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.6.fix.2'
test -f history/0.0.5/alpha.6.fix.1.md
test -f deltas/0.0.5/alpha.6.fix.2.md
test ! -e history/0.0.5/alpha.6.fix.2.md
grep -A2 '^## Statut$' history/0.0.5/alpha.6.fix.1.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 3 -->' docs/rules/710-TAURI.md
grep -Fx '<!-- version: 6 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 7 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.6.fix.1.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+FAIL\s", history)
tauri = Path("docs/rules/710-TAURI.md").read_text(encoding="utf-8")
for phrase in (
"## Convention renforcée pour les projets contrôlés",
"sans couche `src-tauri/` ajoutée uniquement pour reproduire `create-tauri-app`",
"`src/tauri.rs` SHOULD posséder l'assemblage Tauri et les wrappers `#[tauri::command]`",
"partagés avec le frontend MUST utiliser TS-RS comme source de génération",
"WASM reste normalement une unité séparée de la crate Tauri",
):
assert phrase in tauri, phrase
study = Path("docs/studies/001-KSP_GAMES_RECONCILIATION.md").read_text(encoding="utf-8")
for phrase in (
"Commun aux `8` hosts Tauri observés",
"aucun ne possède `src-tauri/`",
"KSP plus strict mais réutilisable",
"Nomenclature des crates",
):
assert phrase in study, phrase
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### alpha.7 — profil Rust strict, chemins et nomenclature explicite",
"### alpha.8 — formatage Rust structurel et audits monotâches",
"### alpha.9 — décision de skeleton Tauri pour projets contrôlés",
):
assert phrase in plan, phrase
print("0.0.5 alpha.6.fix.2 Tauri convention audit: clean (8 hosts reconciled, strict controlled layout separated from universal framework)")
PY
git diff --check
git add VERSION \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/710-TAURI.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
deltas/0.0.5/alpha.6.fix.2.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.6.fix.2.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/710-TAURI.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
## Transition
### PASS
Créer/appliquer `history/0.0.5/alpha.6.fix.2.md`, committer/pousser le fix, puis poursuivre avec `alpha.7`.
### FAIL
Rester dans `0.0.5-alpha.6.fix.M`. Ne pas commencer la réconciliation Rust tant que la convention Tauri et sa gate ne sont pas fermées proprement.

View File

@@ -0,0 +1,140 @@
<!-- file: deltas/0.0.5/alpha.6.fix.3.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.6.fix.3 — politique de versions Tauri/frontend
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.6.fix.2`, réalisé après application de `history/0.0.5/alpha.6.fix.2.md` avec statut `FAIL`.
Version après application :
```text
0.0.5-alpha.6.fix.3
```
## Motif
La gate mécanique de `alpha.6.fix.2` est propre, mais la revue fonctionnelle identifie une convention mal généralisée : KSP et Games ont tous deux utilisé l'omission de `tauri.conf.json > version` et une `package.json > version` rarement synchronisée comme moyen de réduire le churn des prereleases. PGR ne doit pas transformer cette solution historique en obligation.
L'objectif réel est de conserver `VERSION` comme identité exacte de travail tout en évitant de modifier les miroirs produit qui n'ont pas besoin de suivre chaque `alpha`, `.fix`, beta ou RC.
## Scope
REPLACE :
```text
VERSION
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/200-GOVERNANCE.md
docs/rules/710-TAURI.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
ADD :
```text
deltas/0.0.5/alpha.6.fix.3.md
```
DELETE : aucun.
## Décisions
Le fix rétablit une classification explicite des valeurs de version :
- `CANONICAL` pour `VERSION` ;
- `MIRROR-EXACT` pour les miroirs techniques qui doivent suivre chaque prerelease ;
- `MIRROR-STABLE` pour les champs qui portent seulement la cible `X.Y.Z` ;
- catégories indépendantes pour compteurs, schémas et révisions documentaires.
Pour une application Tauri contrôlée appartenant au même produit, `tauri.conf.json > version` et `package.json > version`, lorsqu'ils sont conservés, SHOULD être `MIRROR-STABLE` par défaut et porter `X.Y.Z` pendant tout le développement de cette cible. Ils ne sont pas modifiés uniquement pour passer de `alpha.N` à un autre alpha/fix/beta/RC.
Si des bundles prerelease sont réellement distribués et doivent être identifiables séparément, le projet MAY sélectionner `MIRROR-EXACT` ou une politique de jalons de packaging documentée. L'omission d'un champ reste possible lorsqu'il est réellement inutile, mais elle n'est plus la stratégie PGR recommandée uniquement pour éviter le churn.
La revue obligatoire déclenchée par `.fix.3` conclut `CONTINUE` : `alpha.6` reste bornée au profil Tauri ; `alpha.7`, `alpha.8` et `alpha.9` conservent leurs scopes distincts.
## Hors scope
Ce fix ne modifie ni les règles Rust strictes prévues en `alpha.7`, ni les audits de formatage de `alpha.8`, ni le skeleton Tauri de `alpha.9`. Il ne modifie pas non plus la politique Cargo existante de `510-RUST_CARGO.md`.
## Validation opérateur
Après application du history `FAIL` de `alpha.6.fix.2`, commit/push de cette tranche, puis application du présent fix :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.6.fix.3'
test -f history/0.0.5/alpha.6.fix.2.md
test -f deltas/0.0.5/alpha.6.fix.3.md
test ! -e history/0.0.5/alpha.6.fix.3.md
grep -A2 '^## Statut$' history/0.0.5/alpha.6.fix.2.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 4 -->' docs/rules/200-GOVERNANCE.md
grep -Fx '<!-- version: 4 -->' docs/rules/710-TAURI.md
grep -Fx '<!-- version: 7 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 8 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.6.fix.2.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+FAIL\s", history)
governance = Path("docs/rules/200-GOVERNANCE.md").read_text(encoding="utf-8")
for phrase in (
"MIRROR-EXACT",
"MIRROR-STABLE",
"Seul un `MIRROR-EXACT` est normalement modifié à chaque changement de `VERSION`.",
"PGR MUST NOT imposer la suppression d'un champ utile uniquement pour éviter de le modifier à chaque prerelease",
):
assert phrase in governance, phrase
tauri = Path("docs/rules/710-TAURI.md").read_text(encoding="utf-8")
for phrase in (
"PGR MUST NOT imposer l'une de ces deux formes uniquement pour réduire le nombre de fichiers modifiés.",
"la politique recommandée lorsque les prereleases ne sont pas distribuées comme produits installables distincts est `MIRROR-STABLE`",
"tauri.conf.json version = X.Y.Z",
"package.json version = X.Y.Z",
"remplace explicitement les conventions historiques KSP/Games",
):
assert phrase in tauri, phrase
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
assert "`alpha.6.fix.3` restaure la classification générale" in plan
assert "résultat `CONTINUE`" in plan
print("0.0.5 alpha.6.fix.3 version policy audit: clean (canonical/exact/stable mirrors classified, Tauri/frontend churn bounded)")
PY
git diff --check
git add VERSION \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/200-GOVERNANCE.md docs/rules/710-TAURI.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
deltas/0.0.5/alpha.6.fix.3.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.6.fix.3.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/200-GOVERNANCE.md
M docs/rules/710-TAURI.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
```

189
deltas/0.0.5/alpha.6.md Normal file
View File

@@ -0,0 +1,189 @@
<!-- file: deltas/0.0.5/alpha.6.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.6 — premier profil framework : Tauri 2
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.5.fix.1`, réalisé après application de `history/0.0.5/alpha.5.fix.1.md` avec statut `PASS`.
Version avant application :
```text
0.0.5-alpha.5.fix.1
```
Version après application :
```text
0.0.5-alpha.6
```
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/000-README.md
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/000-README.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
ADD :
```text
docs/rules/700-FRAMEWORKS.md
docs/rules/710-TAURI.md
deltas/0.0.5/alpha.6.md
```
DELETE : aucun.
Le history `alpha.5.fix.1` appartient au commit baseline et n'est pas inclus dans l'archive du présent delta.
## Preuve de généralisation
Les baselines autoritaires étudiées en `alpha.1` contiennent :
```text
KSP 0.3.16 6 applications Tauri
Games 0.3.5 2 applications Tauri
```
Les huit applications utilisent Tauri 2 avec un host Rust/Cargo, `tauri-build`, `tauri.conf.json`, des capability files, des hooks frontend et un `frontendDist`. Elles divergent en revanche sur fenêtres, ports, CSP, bundling, plugins, ressources et contenu réel des hooks.
Le profil normalise donc les responsabilités et l'orchestration communes, pas ces valeurs locales.
## Décisions matérialisées
### Famille `700 — frameworks`
`700-FRAMEWORKS.md` devient l'owner des règles communes aux frameworks : composition avec les owners langage/plateforme, ownership des commandes d'intégration, classification des artefacts générés, cohérence de version produit et validation proportionnée.
La famille interdit notamment de supposer qu'un framework absorbe automatiquement son frontend, sa plateforme ou son package manager.
### Profil `710 — Tauri 2`
Le profil Tauri :
- se compose au-dessus de Rust/Cargo et des plateformes réellement ciblées ;
- ne rend pas Vite, WASM, TypeScript ou npm obligatoires ;
- ne rend pas `src-tauri/` obligatoire lorsque la toolchain supporte clairement un autre layout ;
- possède l'orchestration via le CLI Tauri lorsque les hooks/config/capabilities/bundles sont concernés ;
- distingue un check Rust, un build frontend et une preuve d'intégration Tauri ;
- préfère une chaîne de version unique `VERSION → workspace Cargo → package host → Tauri` lorsque l'application partage le release train et que la configuration Tauri peut omettre sa propre version ;
- traite les capability files comme source de sécurité intentionnelle ;
- ne généralise ni plugins, CSP, fenêtres, bundles, ports ni ressources des corpus ;
- ne généralise pas l'ignorance de tout `gen/`, car un projet mobile généré peut recevoir des personnalisations intentionnelles ;
- sélectionne `tauri dev/build` ou leur équivalent seulement lorsque la propriété à prouver le justifie.
### Pas de skeleton dans cette tranche
`alpha.6` ne crée aucun `tauri.conf.json`, package frontend, template Tauri ou skeleton. La décision de matérialiser une specialization Tauri appartient explicitement à `alpha.7`.
## Validation opérateur
Après application du history `PASS` de `alpha.5.fix.1`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.6'
test -f history/0.0.5/alpha.5.fix.1.md
test -f deltas/0.0.5/alpha.6.md
test -f docs/rules/700-FRAMEWORKS.md
test -f docs/rules/710-TAURI.md
test ! -e history/0.0.5/alpha.6.md
grep -A2 '^## Statut$' history/0.0.5/alpha.5.fix.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 11 -->' RULES.md
grep -Fx '<!-- version: 13 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 4 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 1 -->' docs/rules/700-FRAMEWORKS.md
grep -Fx '<!-- version: 1 -->' docs/rules/710-TAURI.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.0.5/alpha.5.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
frameworks = Path('docs/rules/700-FRAMEWORKS.md').read_text(encoding='utf-8')
for phrase in (
'# Règles de profils framework',
"Ownership des commandes d'intégration",
'PGR MUST NOT appliquer une règle globale « tout `gen/` est ignoré »',
'Les profils spécifiques utilisent la plage `710` à `799`.',
):
assert phrase in frameworks, phrase
tauri = Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8')
for phrase in (
'# Profil Tauri 2',
'PGR MUST NOT imposer Vite, TypeScript, npm, pnpm, yarn, Bun, WASM',
"le CLI Tauri est l'owner de l'orchestration",
'VERSION
↓
workspace.package.version
↓
package Cargo du host
↓
version applicative Tauri',
'PGR MUST NOT appliquer en revanche une exclusion universelle de tout répertoire `gen/`',
'## Validation proportionnée',
'de `tauri.conf.json` universel',
):
assert phrase in tauri, phrase
study = Path('docs/studies/001-KSP_GAMES_RECONCILIATION.md').read_text(encoding='utf-8')
assert 'KSP contient `6` applications Desk Tauri et Games `2` hôtes Tauri' in study
assert 'Décision `alpha.6` : classer Tauri `COMMON`' in study
plan = Path('docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md').read_text(encoding='utf-8')
assert '`6` applications Tauri KSP et `2` applications Tauri Games' in plan
assert 'La tranche active `700-FRAMEWORKS.md` et `710-TAURI.md`.' in plan
print('0.0.5 alpha.6 Tauri profile audit: clean (700 activated, Tauri 2 responsibilities bounded, no frontend/layout overreach)')
PY
git diff --check
git add VERSION RULES.md docs/000-README.md docs/architecture/003-RULE_PROFILE_MODEL.md docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md docs/rules/000-README.md docs/rules/700-FRAMEWORKS.md docs/rules/710-TAURI.md docs/studies/001-KSP_GAMES_RECONCILIATION.md deltas/0.0.5/alpha.6.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history `alpha.6` est exactement :
```text
M RULES.md
M VERSION
A deltas/0.0.5/alpha.6.md
M docs/000-README.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/000-README.md
A docs/rules/700-FRAMEWORKS.md
A docs/rules/710-TAURI.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
```
## Transition
### PASS
Créer/appliquer `history/0.0.5/alpha.6.md`, committer/pousser `0.0.5-alpha.6`, puis poursuivre à `0.0.5-alpha.7` pour décider si une skeleton specification Tauri apporte réellement une valeur de composition au-dessus des profils existants.
### FAIL
Rester dans `0.0.5-alpha.6.fix.M` ou REPLAN si le profil exige encore une valeur applicative arbitraire. Aucun skeleton Tauri ne doit être créé tant que le profil framework n'est pas correctement fermé.

View File

@@ -0,0 +1,186 @@
<!-- file: deltas/0.0.5/alpha.7.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.7.fix.1 — contrats de suffixes, packaging Rust et tracing
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.7`, réalisé après application de `history/0.0.5/alpha.7.md` avec statut `FAIL`.
Version après application :
```text
0.0.5-alpha.7.fix.1
```
## Motif
La gate mécanique de `alpha.7` est propre, mais la revue fonctionnelle opérateur révèle que la nomenclature livrée reste trop descriptive. Dans les projets contrôlés, les suffixes doivent également porter un contrat architectural : `-api` désigne une frontière de contrats réellement justifiée, `-lib` une implémentation/fonctionnalité réutilisable, tandis que les exécutables restent normalement des packages distincts et minces.
La relecture ciblée des corpus confirme plusieurs éléments réutilisables :
- KSP distingue explicitement `ksp-<domain>-api` et `ksp-<role>-lib`, interdit une crate `*-api` créée uniquement par symétrie et garde les APIs purement déclaratives sans logging runtime ;
- Games sépare explicitement la crate lib de jeu et ses launchers ;
- KSP et Games convergent sur `tracing`, la composition du subscriber et une crate transverse de logging ;
- les six hosts Tauri KSP et les deux hosts Tauri Games observés utilisent tous un package mixte lib/bin avec des noms de targets distincts.
Une ancienne règle KSP préférait un package worker mixte lib/bin. Cette préférence n'est pas généralisée : la décision PGR actuelle est la séparation par défaut, Tauri restant l'exception framework explicitement reconnue.
## Scope
REPLACE :
```text
VERSION
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/510-RUST_CARGO.md
docs/rules/710-TAURI.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
docs/templates/002-CARGO_MANIFESTS.md
```
ADD :
```text
deltas/0.0.5/alpha.7.fix.1.md
```
DELETE : aucun.
## Décisions
Pour une nouvelle baseline Rust contrôlée :
- `-api` signifie contrat extensible/passif ; une crate `-api` n'est créée que si une séparation réelle est justifiée par extension, backend, lifecycle, implémentations multiples ou implémentation externe ;
- une crate `-api` purement déclarative reste normalement sans logging/tracing runtime ;
- lorsqu'une seule implémentation est utile et qu'aucune frontière séparée n'apporte de valeur, une seule crate `-lib` est préférée ;
- `-lib` signifie implémentation ou fonctionnalité réutilisable et ne contient normalement pas de cible binaire ;
- hors exception explicite de framework/plateforme, une bibliothèque réutilisable et son exécutable sont des packages Cargo distincts ;
- l'exécutable porte un rôle lisible lorsqu'il existe (`cli`, `desk`, `worker`, `job`, `server`, etc.), dépend des libs nécessaires et conserve `main.rs` comme couche de bootstrap/composition mince ;
- Tauri reste l'exception framework actuelle au package séparé lib/bin ; son profil impose alors des noms de targets réellement distincts, y compris après normalisation Cargo `-` -> `_`.
Pour les diagnostics :
- `tracing` est le mécanisme recommandé pour les nouveaux projets Rust contrôlés ;
- `log` reste acceptable comme bridge de compatibilité mais n'est pas la façade par défaut sans contrainte externe ;
- lorsqu'un workspace possède plusieurs runtimes partageant subscriber, filtres, sinks ou lifecycle, une crate transverse de logging/tracing SHOULD centraliser cette responsabilité ;
- `tracing-subscriber` et `tracing-appender` appartiennent normalement à cet owner de composition ;
- une bibliothèque métier/technique peut émettre des événements mais ne configure pas silencieusement le subscriber global.
## Hors scope
Ce correctif ne traite toujours pas l'ordre des blocs, le regroupement par visibilité, l'espacement interne, l'ordre alphabétique des items ou les audits de forme : ces sujets restent réservés à `alpha.8`.
Il ne crée aucun nouvel audit Python et ne transforme pas le profil Rust en catalogue exhaustif de suffixes. Les vocabulaires métier exacts restent locaux.
## Validation opérateur
Après application du history `FAIL` de `alpha.7`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.7.fix.1'
test -f history/0.0.5/alpha.7.md
test -f deltas/0.0.5/alpha.7.fix.1.md
test ! -e history/0.0.5/alpha.7.fix.1.md
grep -A2 '^## Statut$' history/0.0.5/alpha.7.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 6 -->' docs/rules/510-RUST_CARGO.md
grep -Fx '<!-- version: 5 -->' docs/rules/710-TAURI.md
grep -Fx '<!-- version: 4 -->' docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 3 -->' docs/templates/002-CARGO_MANIFESTS.md
grep -Fx '<!-- version: 9 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 10 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.7.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+FAIL\s", history)
rules = Path("docs/rules/510-RUST_CARGO.md").read_text(encoding="utf-8")
for phrase in (
"### Les suffixes portent un contrat architectural",
"Une crate `-api` MUST NOT être créée uniquement pour obtenir une paire de noms symétrique.",
"Lorsqu'une seule implémentation est réellement prévue",
"### Séparation bibliothèques / exécutables",
"Tauri constitue l'exception framework actuellement reconnue par PGR",
"## Diagnostics structurés et ownership du logging",
"`tracing` est le mécanisme recommandé",
"SHOULD NOT installer silencieusement un subscriber global",
):
assert phrase in rules, phrase
tauri = Path("docs/rules/710-TAURI.md").read_text(encoding="utf-8")
for phrase in (
"le package mixte `lib + bin` constitue l'exception framework explicite",
"leurs noms MUST être distincts même après la normalisation Cargo usuelle des tirets en underscores",
"project_feature_desk_lib",
"Un plugin Tauri de tracing sert alors d'adapter",
):
assert phrase in tauri, phrase
skeleton = Path("docs/skeletons/002-RUST_CARGO_WORKSPACE.md").read_text(encoding="utf-8")
for phrase in (
"les frontières `-api` / `-lib` réellement justifiées",
"Les exécutables sont des packages distincts des bibliothèques",
"crate transverse de logging/tracing",
):
assert phrase in skeleton, phrase
template = Path("docs/templates/002-CARGO_MANIFESTS.md").read_text(encoding="utf-8")
assert "une bibliothèque réutilisable et son exécutable sont normalement deux packages Cargo distincts" in template
assert "Tauri est une exception framework" in template
study = Path("docs/studies/001-KSP_GAMES_RECONCILIATION.md").read_text(encoding="utf-8")
for phrase in (
"#### Correction `alpha.7.fix.1` — suffixes, packaging et tracing",
"KSP-WORKER-014",
"les `6` hosts Tauri KSP `0.3.16` et les `2` hosts Tauri Games `0.3.5`",
"PGR retient donc `tracing` par défaut",
):
assert phrase in study, phrase
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
assert "`alpha.7.fix.1` complète donc la tranche" in plan
assert "### alpha.8 — formatage Rust structurel et audits monotâches" in plan
print("0.0.5 alpha.7.fix.1 crate contract audit: clean (api/lib semantics, binary split, tracing owner, Tauri exception)")
PY
git diff --check
git add VERSION \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/510-RUST_CARGO.md docs/rules/710-TAURI.md \
docs/skeletons/002-RUST_CARGO_WORKSPACE.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
docs/templates/002-CARGO_MANIFESTS.md \
deltas/0.0.5/alpha.7.fix.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.7.fix.1.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/510-RUST_CARGO.md
M docs/rules/710-TAURI.md
M docs/skeletons/002-RUST_CARGO_WORKSPACE.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
M docs/templates/002-CARGO_MANIFESTS.md
```

175
deltas/0.0.5/alpha.7.md Normal file
View File

@@ -0,0 +1,175 @@
<!-- file: deltas/0.0.5/alpha.7.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.7 — profil Rust strict, chemins et nomenclature explicite
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.6.fix.3`, réalisé après application de `history/0.0.5/alpha.6.fix.3.md` avec statut `PASS`.
Version après application :
```text
0.0.5-alpha.7
```
## Motif
La réconciliation Tauri a confirmé qu'un host contrôlé hérite du profil Rust au lieu de redéfinir ses conventions. La relecture des règles autoritaires KSP/Games révèle alors un écart PGR plus ancien : la conception initiale avait retenu un profil de forte explicité, mais `510-RUST_CARGO.md` matérialisé conservait encore une politique permissive sur les `use` non-traits et ne formalisait pas la nomenclature des crates.
KSP `RULES_RUST.md` version `10` fournit la référence stricte : Rust 2024, `use` réservé aux traits, chemins externes publics explicites et courts, réexports internes `self::`, façade crate-root, `crate::Item`, absence d'alias/globs et contrôle de flux explicite. Games `RULES_RUST.md` version `7` confirme le noyau Rust 2024/façade/erreurs mais reste plus léger sur certains imports et règles de forme. `alpha.7` retient donc le profil strict comme défaut des **nouvelles baselines contrôlées** tout en conservant des overrides explicites pour les projets externes ou historiques.
## Scope
REPLACE :
```text
VERSION
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/510-RUST_CARGO.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
docs/templates/002-CARGO_MANIFESTS.md
```
ADD :
```text
deltas/0.0.5/alpha.7.md
```
DELETE : aucun.
## Décisions
Pour une nouvelle baseline Rust contrôlée :
- Rust 2024 devient la baseline normative actuelle ; une contrainte externe doit être documentée explicitement ;
- `use` est réservé aux traits qui doivent réellement être mis en scope ; les autres symboles sont appelés par chemins explicites ;
- un symbole externe utilise le chemin public le plus court exposé par sa crate ;
- les réexports internes utilisent `self::`, restent explicites ligne par ligne et ne masquent pas les collisions par alias ;
- les glob imports, regroupements par accolades de façade et imports non-traits de commodité sont interdits ;
- les modules d'implémentation restent privés ; les items partagés passent par la façade crate-root et `crate::Item`, y compris dans leur module propriétaire ;
- `pub(super)`/`pub(in ...)` ne remplacent pas cette façade dans une baseline contrôlée ;
- tout `pub`/`pub(crate)` et tout réexport crate-root porte une rustdoc utile ;
- `unwrap`, `expect` et `?` sont interdits en production dans le profil strict ; la propagation d'erreur et les retours restent explicites.
Le marqueur historique KSP `rust-rules: trait-import` n'est pas généralisé : il appartient à l'enforcement local, pas à la règle sémantique.
Pour la nomenclature des crates d'un nouveau projet contrôlé :
```text
<project>-<responsibility>-<role-or-target>
```
est la forme recommandée. Le préfixe projet/abréviation est obligatoire ; le classificateur (`lib`, `api`, `worker`, `job`, `cli`, `desk`, `desktop`, `tauri`, `wasm`, `server`, etc.) est utilisé lorsqu'il apporte une information réelle. Le vocabulaire exact reste local, aucun suffixe n'est ajouté par symétrie et aucun projet historique n'est renommé rétroactivement uniquement pour adopter cette grammaire.
Le skeleton Rust/Cargo et le guide des manifests adoptent ces choix pour les futures baselines contrôlées. L'audit de façade déjà livré devient une sélection recommandée du skeleton strict ; l'adoption d'un projet existant commence toujours en `--report-only`.
## Hors scope
Cette tranche ne modifie pas les règles de blocs homogènes, ordre alphabétique, espacement, regroupement par visibilité ou organisation structurelle des items : elles restent réservées à `alpha.8` avec leurs audits monotâches.
Elle n'importe pas `audit_rust_general_rules.py` depuis KSP/Games, ne crée aucun parser Rust général et ne modifie pas le skeleton Tauri prévu en `alpha.9`.
## Validation opérateur
Après application du history `PASS` de `alpha.6.fix.3`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.7'
test -f history/0.0.5/alpha.6.fix.3.md
test -f deltas/0.0.5/alpha.7.md
test ! -e history/0.0.5/alpha.7.md
grep -A2 '^## Statut$' history/0.0.5/alpha.6.fix.3.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 5 -->' docs/rules/510-RUST_CARGO.md
grep -Fx '<!-- version: 3 -->' docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 2 -->' docs/templates/002-CARGO_MANIFESTS.md
grep -Fx '<!-- version: 8 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 9 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.6.fix.3.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
rules = Path("docs/rules/510-RUST_CARGO.md").read_text(encoding="utf-8")
for phrase in (
"nouveau projet Rust contrôlé MUST utiliser l'édition Rust 2024",
"### Nomenclature des crates dans un projet contrôlé",
"<project>-<responsibility>-<role-or-target>",
"### `use` réservé aux traits",
"le code utilise directement le **chemin public le plus court**",
"Les réexports d'éléments internes commencent par `self::`",
"toute référence dans la même crate MUST utiliser `crate::Item`",
"`unwrap()` et `expect()` MUST NOT être utilisés",
"l'opérateur `?` MUST NOT être utilisé",
):
assert phrase in rules, phrase
for forbidden in (
"PGR ne généralise pas l'interdiction KSP plus stricte de tous les `use` non-traits",
"le profil de façade crate-root est seulement facultatif pour une nouvelle baseline contrôlée",
):
assert forbidden not in rules, forbidden
skeleton = Path("docs/skeletons/002-RUST_CARGO_WORKSPACE.md").read_text(encoding="utf-8")
for phrase in (
"nom court/abréviation canonique du projet",
"édition Rust 2024",
"façade crate-root et les chemins explicites sont sélectionnés par défaut",
"audit_rust_export_completeness.py",
):
assert phrase in skeleton, phrase
study = Path("docs/studies/001-KSP_GAMES_RECONCILIATION.md").read_text(encoding="utf-8")
assert "#### Décision `alpha.7` — profil Rust strict et nomenclature" in study
assert "KSP `RULES_RUST.md` version `10`" in study
assert "Games `RULES_RUST.md` version `7`" in study
assert "Les règles de blocs homogènes" in study
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
assert "La réconciliation des règles versionnées KSP/Games retient KSP comme référence stricte" in plan
assert "### alpha.8 — formatage Rust structurel et audits monotâches" in plan
assert "### alpha.9 — décision de skeleton Tauri pour projets contrôlés" in plan
print("0.0.5 alpha.7 strict Rust profile audit: clean (explicit paths, crate-root facade, controlled naming, alpha.8 formatting deferred)")
PY
git diff --check
git add VERSION \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/510-RUST_CARGO.md \
docs/skeletons/002-RUST_CARGO_WORKSPACE.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
docs/templates/002-CARGO_MANIFESTS.md \
deltas/0.0.5/alpha.7.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.7.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/510-RUST_CARGO.md
M docs/skeletons/002-RUST_CARGO_WORKSPACE.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
M docs/templates/002-CARGO_MANIFESTS.md
```

248
deltas/0.0.5/alpha.8.md Normal file
View File

@@ -0,0 +1,248 @@
<!-- file: deltas/0.0.5/alpha.8.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.8 — formatage Rust structurel et audits monotâches
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.7.fix.1`, réalisé après application de `history/0.0.5/alpha.7.fix.1.md` avec statut `PASS`.
Version après application :
```text
0.0.5-alpha.8
```
## Mission
Fermer le chantier de réconciliation du formatage Rust structurel sans importer les anciens `audit_rust_general_rules.py` composites de KSP/Games.
La tranche attribue chaque propriété à un owner identifiable : Rustfmt lorsqu'il sait réellement réécrire la forme, audits PGR monotâches lorsqu'une structure stable n'est pas possédée par l'outil officiel, et revue humaine lorsque l'ordre peut être métier/protocolaire.
## Scope
REPLACE :
```text
VERSION
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/rules/510-RUST_CARGO.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
docs/studies/001-KSP_GAMES_RECONCILIATION.md
docs/validation/001-VALIDATION_MATRIX.md
docs/validation/002-RUST_STYLE_AUDITS.md
tests/test_rust_audits.py
```
ADD :
```text
deltas/0.0.5/alpha.8.md
scripts/audit_rust_item_spacing.py
scripts/audit_rust_module_order.py
scripts/audit_rust_reexport_blocks.py
scripts/audit_rust_trait_import_blocks.py
```
DELETE : aucun.
## Décisions de formatage
Pour une nouvelle baseline Rust contrôlée sélectionnant le profil strict :
- les lignes vides consécutives et les lignes vides dans fonctions/méthodes/`struct`/`enum` sont interdites ;
- deux items Rust distincts voisins d'un même scope sont séparés par exactement une ligne vide lorsque rien d'intermédiaire ne possède lui-même l'espacement ;
- les blocs compacts `const` restent sous un owner séparé et ne sont pas interprétés par l'audit d'espacement général ;
- les modules de production précèdent les modules de tests et chaque groupe est alphabétique lorsque cet ordre est sans sémantique ;
- les `use` non exportés autorisés par le profil strict restent dans un bloc module-level compact avant les déclarations métier ;
- les `pub use` précèdent les `pub(crate) use`, sans ligne vide interne et avec exactement une ligne vide entre les deux visibilités lorsqu'elles coexistent ;
- Rustfmt reste l'owner du tri intra-bloc des `use`, réexports et modules qu'il sait réécrire ; les audits PGR ne créent pas un tri concurrent.
PGR conserve comme fortes conventions de lisibilité le rapprochement d'un `struct` et de ses `impl`, ainsi que la préférence des éléments visibles avant les helpers privés lorsque cela clarifie le fichier. Aucun audit lexical n'impose cependant un ordre global `enum → struct → impl → fn` ou un tri visible/privé susceptible d'écraser une organisation métier.
## Audits ajoutés
Quatre contrôles read-only monotâches sont extraits :
```text
audit_rust_item_spacing.py
séparation exacte des items distincts voisins
audit_rust_module_order.py
ordre production/tests et ordre alphabétique des modules
audit_rust_trait_import_blocks.py
placement/contiguïté des use non exportés
audit_rust_reexport_blocks.py
ordre de visibilité et espacement des blocs de réexports
```
Ils utilisent `_rust_audit_common.py` pour la sélection et le masquage lexical. Ils ne tentent pas de remplacer un parser Rust ni de déterminer la nature sémantique d'un import.
Les audits déjà existants gardent leurs responsabilités :
```text
audit_rust_blank_lines.py
blancs consécutifs / blancs dans certains corps
audit_rust_const_blocks.py
consts sélectionnées : visibilité, ordre, espacement
audit_rust_export_completeness.py
façade crate-root et chemins canoniques
```
## Mesure croisée
Les quatre nouveaux audits ont été exécutés pendant la préparation sur tous les fichiers Rust sous `crates/` des baselines autoritaires :
```text
KSP 0.3.16 603 file(s) item/module/trait-import/reexport: clean
Games 0.3.5 87 file(s) item/module/trait-import/reexport: clean
```
`audit_rust_blank_lines.py` est également propre sur ces `603` et `87` fichiers.
En revanche, `audit_rust_const_blocks.py` exécuté aveuglément sur l'ensemble produit `18` signaux KSP et `0` Games. Certains signaux correspondent à des tables/schémas à ordre intentionnel. Il reste donc un audit à sélection explicite par fichier et ne devient pas une gate globale.
Ces mesures servent à qualifier la réutilisabilité des règles PGR ; elles ne constituent pas une validation opérateur de KSP/Games.
## Horizon documenté sans engagement
La revue d'horizon du plan conserve `0.1.0` comme seule prochaine release engagée, mais mémorise trois candidats sans numéro ni engagement :
1. profils techniques composables par langage/framework/target/plateforme et préoccupation transverse, notamment observability/logging ;
2. profil documentaire/spécification, avec `saselang-bible` comme corpus pilote possible ;
3. audit de généricité de PGR pour des projets hors développement logiciel.
Ces candidats ne deviennent ni `Study`, ni `ROADMAP`, ni release plan tant qu'une décision explicite ne les promeut pas.
## Hors scope
Cette tranche ne :
- crée pas de parser Rust général ;
- réimporte pas `audit_rust_general_rules.py` ;
- impose pas un ordre alphabétique à une séquence sémantique ;
- crée pas d'audit dédié `static/type` uniquement pour la symétrie ;
- modifie pas les contrats de suffixes/packaging/tracing fermés par `alpha.7.fix.1` ;
- commence pas le skeleton Tauri réservé à `alpha.9` ;
- transforme pas les candidats d'horizon en versions promises.
## Validation opérateur
Après application du history `PASS` de `alpha.7.fix.1`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.8'
test -f history/0.0.5/alpha.7.fix.1.md
test -f deltas/0.0.5/alpha.8.md
test -f scripts/audit_rust_item_spacing.py
test -f scripts/audit_rust_module_order.py
test -f scripts/audit_rust_reexport_blocks.py
test -f scripts/audit_rust_trait_import_blocks.py
test ! -e scripts/audit_rust_general_rules.py
test ! -e history/0.0.5/alpha.8.md
grep -A2 '^## Statut$' history/0.0.5/alpha.7.fix.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 7 -->' docs/rules/510-RUST_CARGO.md
grep -Fx '<!-- version: 5 -->' docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 10 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 12 -->' docs/validation/001-VALIDATION_MATRIX.md
grep -Fx '<!-- version: 2 -->' docs/validation/002-RUST_STYLE_AUDITS.md
grep -Fx '<!-- version: 11 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -Fx '# version: 2' tests/test_rust_audits.py
grep -Fx '# version: 1' scripts/audit_rust_item_spacing.py
grep -Fx '# version: 1' scripts/audit_rust_module_order.py
grep -Fx '# version: 1' scripts/audit_rust_reexport_blocks.py
grep -Fx '# version: 1' scripts/audit_rust_trait_import_blocks.py
python3 -B -m unittest discover -s tests -p 'test_rust_audits.py' -v
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.7.fix.1.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
rules = Path("docs/rules/510-RUST_CARGO.md").read_text(encoding="utf-8")
for phrase in (
"Le profil structurel strict fait partie du défaut des nouvelles baselines Rust contrôlées.",
"audit_rust_item_spacing.py",
"audit_rust_module_order.py",
"audit_rust_trait_import_blocks.py",
"audit_rust_reexport_blocks.py",
"PGR n'impose toutefois pas un ordre global automatique `enum → struct → impl → fn`",
):
assert phrase in rules, phrase
validation = Path("docs/validation/002-RUST_STYLE_AUDITS.md").read_text(encoding="utf-8")
for phrase in (
"603` fichiers KSP `0.3.16`",
"87` fichiers Games `0.3.5`",
"18` signaux KSP",
"0` Games",
"Rustfmt reste l'owner de l'ordre intra-bloc",
):
assert phrase in validation, phrase
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"quatre extractions monotâches complètent le profil",
"maturation de profils techniques composables",
"`saselang-bible` comme corpus pilote possible",
"audit du noyau PGR hors développement logiciel",
"### alpha.9 — décision de skeleton Tauri pour projets contrôlés",
):
assert phrase in plan, phrase
print("0.0.5 alpha.8 Rust structure audit: clean (owners split, four monotask audits, semantic order protected, horizon candidates recorded)")
PY
git diff --check
git add VERSION \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/rules/510-RUST_CARGO.md \
docs/skeletons/002-RUST_CARGO_WORKSPACE.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
docs/validation/001-VALIDATION_MATRIX.md \
docs/validation/002-RUST_STYLE_AUDITS.md \
scripts/audit_rust_item_spacing.py \
scripts/audit_rust_module_order.py \
scripts/audit_rust_reexport_blocks.py \
scripts/audit_rust_trait_import_blocks.py \
tests/test_rust_audits.py \
deltas/0.0.5/alpha.8.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.8.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/rules/510-RUST_CARGO.md
M docs/skeletons/002-RUST_CARGO_WORKSPACE.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
M docs/validation/001-VALIDATION_MATRIX.md
M docs/validation/002-RUST_STYLE_AUDITS.md
A scripts/audit_rust_item_spacing.py
A scripts/audit_rust_module_order.py
A scripts/audit_rust_reexport_blocks.py
A scripts/audit_rust_trait_import_blocks.py
M tests/test_rust_audits.py
```

178
deltas/0.0.5/alpha.9.md Normal file
View File

@@ -0,0 +1,178 @@
<!-- file: deltas/0.0.5/alpha.9.md -->
<!-- version: 1 -->
# Delta 0.0.5-alpha.9 — décision de skeleton Tauri contrôlé
## Baseline et version
Baseline attendue : commit opérateur complet de `0.0.5-alpha.8`, réalisé après application de `history/0.0.5/alpha.8.md` avec statut `PASS`.
Version après application :
```text
0.0.5-alpha.9
```
## Mission
Décider si les owners PGR réellement matérialisés permettent de créer un skeleton Tauri actionnable pour les projets contrôlés sans transformer ce skeleton en propriétaire implicite de règles Web encore absentes.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
docs/skeletons/000-README.md
docs/studies/000-README.md
```
ADD :
```text
deltas/0.0.5/alpha.9.md
docs/studies/002-TAURI_SKELETON_DECISION.md
```
DELETE : aucun.
Aucun fichier `docs/skeletons/003-TAURI*.md` n'est créé.
## Décision
Résultat :
```text
DEFER
```
Le host Tauri est suffisamment cadré par les owners existants : Rust/Cargo, Tauri, plateformes applicables et règles générales de skeleton. La partie frontend candidate ne l'est pas encore : PGR ne possède aucun profil Web/Vite/TypeScript/Sass.
Créer maintenant le skeleton obligerait donc sa specification à posséder de fait la structure et la validation Web, alors qu'un skeleton doit composer des owners et non compenser leur absence.
## Candidat conservé
La décision ne rejette pas le skeleton organisationnel. Elle conserve comme hypothèse à réévaluer lorsque les owners Web existeront :
```text
host Cargo direct
+ frontend/
+ Vite
+ TypeScript
+ Sass
+ Bootstrap lorsque pertinent
+ TS-RS pour les DTO Rust partagés
+ tauri.rs comme owner Tauri
+ plugins/capabilities explicitement intégrés
+ WASM séparé par défaut
```
Aucune de ces lignes ne crée dans `0.0.5` un owner Web qui n'existe pas encore.
## Sources et vérification
La décision repose d'abord sur les baselines KSP `0.3.16` et Games `0.3.5` déjà autoritaires pour la réconciliation. La préparation a également vérifié la documentation Tauri 2 courante concernant la flexibilité du frontend, le scaffold `src-tauri/`, l'initialisation manuelle et l'installation explicite des plugins/capabilities.
L'étude détaillée est `docs/studies/002-TAURI_SKELETON_DECISION.md`.
## Hors scope
Cette tranche ne :
- crée pas un skeleton décoratif ;
- matérialise pas les futurs profils Web ;
- modifie pas `710-TAURI.md` ;
- choisit pas un package manager universel ;
- modifie pas les règles Rust fermées par `alpha.7/alpha.8` ;
- réserve pas une release pour le futur skeleton.
## Validation opérateur
Après application du history `PASS` de `alpha.8`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-alpha.9'
test -f history/0.0.5/alpha.8.md
test -f deltas/0.0.5/alpha.9.md
test -f docs/studies/002-TAURI_SKELETON_DECISION.md
test ! -e docs/skeletons/003-TAURI.md
test ! -e docs/skeletons/003-TAURI_CONTROLLED_PROJECT.md
test ! -e history/0.0.5/alpha.9.md
grep -A2 '^## Statut$' history/0.0.5/alpha.8.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 15 -->' docs/000-README.md
grep -Fx '<!-- version: 12 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -Fx '<!-- version: 4 -->' docs/skeletons/000-README.md
grep -Fx '<!-- version: 2 -->' docs/studies/000-README.md
grep -Fx '<!-- version: 1 -->' docs/studies/002-TAURI_SKELETON_DECISION.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.8.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
study = Path("docs/studies/002-TAURI_SKELETON_DECISION.md").read_text(encoding="utf-8")
for phrase in (
"Décision `alpha.9` :",
"DEFER",
"Aucun des `8` hosts n'utilise `src-tauri/`.",
"PGR `0.0.5` **ne crée pas** de skeleton Tauri `003`.",
"PGR `0.0.5` ne possède aucun profil Web dédié",
"001-PROJECT_GOVERNANCE_FOUNDATION",
"002-RUST_CARGO_WORKSPACE",
"Bootstrap comme baseline de présentation lorsqu'un framework CSS généraliste est utile",
):
assert phrase in study, phrase
index = Path("docs/skeletons/000-README.md").read_text(encoding="utf-8")
assert "Aucun `003-TAURI...` n'est donc créé dans `0.0.5`." in index
assert "profils Web réellement matérialisés" in index
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
assert "### alpha.9 — décision de skeleton Tauri pour projets contrôlés — DEFER" in plan
assert "aucun skeleton Tauri `003` n'est créé dans `0.0.5`" in plan
assert "### beta.1 — réconciliation intégrée" in plan
assert not any(Path("docs/skeletons").glob("003-TAURI*.md"))
print("0.0.5 alpha.9 Tauri skeleton decision: clean (host ready, Web owners missing, decorative skeleton rejected, exit conditions recorded)")
PY
git diff --check
git add VERSION \
docs/000-README.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/skeletons/000-README.md \
docs/studies/000-README.md \
docs/studies/002-TAURI_SKELETON_DECISION.md \
deltas/0.0.5/alpha.9.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.5/alpha.9.md
M docs/000-README.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/skeletons/000-README.md
M docs/studies/000-README.md
A docs/studies/002-TAURI_SKELETON_DECISION.md
```

208
deltas/0.0.5/beta.1.md Normal file
View File

@@ -0,0 +1,208 @@
<!-- file: deltas/0.0.5/beta.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-beta.1 — réconciliation intégrée et transition vers 0.1.0
## Baseline
Version attendue avant application :
```text
0.0.5-alpha.9
```
Le history `history/0.0.5/alpha.9.md` avec statut `PASS` MUST avoir été appliqué, committé et poussé avant ce delta.
Version après application :
```text
0.0.5-beta.1
```
## Objet
Fermer la phase alpha de `0.0.5` par une réconciliation intégrée des décisions réellement matérialisées, puis préparer la transition vers la première baseline réutilisable `0.1.0` sans inventer d'owners, de skeletons ou de releases futures.
Cette tranche :
- rejoue la classification KSP/Games sur l'état PGR obtenu ;
- vérifie que chaque responsabilité nouvelle possède un owner identifiable et que les conventions locales non généralisées restent hors du noyau ;
- inscrit durablement le skeleton Tauri contrôlé comme trajectoire `DEFER` dans `ROADMAP.md`, sans numéro de release réservé ;
- maintient les trois autres axes discutés pendant `alpha.8` au stade de candidats d'horizon, hors roadmap engagée ;
- réconcilie les points d'entrée durables ;
- prépare `prompts/006-V0_1_0_START_PROMPT.md` puisque la mission `0.1.0` est suffisamment connue.
## Décision de roadmap
La décision `alpha.9` a déjà établi qu'un skeleton Tauri complet ne peut pas être matérialisé proprement avant l'existence d'owners Web suffisants. Ce report est plus qu'une idée : il résulte d'une étude et possède des conditions de sortie explicites.
`ROADMAP.md` enregistre donc :
```text
(d) skeleton Tauri pour projets contrôlés
```
sans associer cette trajectoire à `0.1.1`, `0.2.0` ou une autre release hypothétique.
Les axes suivants restent en revanche hors roadmap tant qu'une revue d'horizon ne les engage pas :
- maturation plus large des profils techniques composables ;
- projet documentaire/spécification avec `saselang-bible` comme corpus pilote possible ;
- audit de généricité de PGR hors développement logiciel.
Cette distinction applique directement `300-DOCUMENTATION.md` : une décision de report réelle peut être conservée comme trajectoire différée, tandis qu'un candidat d'horizon ne devient pas automatiquement un engagement macro.
## Réconciliation intégrée
L'étude `001-KSP_GAMES_RECONCILIATION.md` reçoit une matrice de sortie `beta.1` qui confirme notamment :
```text
prompt versionné OWNED
contrats de fichiers/familles OWNED
lifecycle inter-release / horizon OWNED
profil Rust contrôlé OWNED
audits Rust monotâches OWNED
profil Tauri 2 OWNED
skeleton Tauri complet DEFER
Web/Vite/TypeScript/Sass DEFER
Android/JNI spécifique LOCAL/DEFER
architectures métier KSP/Games LOCAL
```
La présence d'un owner PGR n'impose pas sa sélection à tous les projets. Applicabilité, composition et overrides restent gouvernés par le modèle de profils.
## Prompt 006
`prompts/006-V0_1_0_START_PROMPT.md` prépare la reprise après publication réelle de `v0.0.5`.
Il fixe uniquement ce qui est déjà décidé :
- baseline autoritaire `pgr-v0.0.5.zip` et rapport post-tag séparé lorsqu'il existe et est `PASS` ;
- cible `0.1.0`, première tranche `0.1.0-alpha.1` ;
- audit complet de la stable avant extension ;
- mission de première baseline réellement réutilisable ;
- nécessité de produire/consolider le plan `0.1.0` pendant `alpha.1` ;
- revue d'horizon obligatoire avant fermeture ;
- skeleton Tauri conservé `DEFER` tant que ses préconditions ne sont pas réellement satisfaites.
Le prompt MUST NOT être interprété comme un plan détaillé de `0.1.0` ni comme une promesse de matérialiser tous les candidats d'horizon.
## Documentation durable
`README.md` résume désormais les capacités réellement apportées par `0.0.5` sans recopier le plan de release.
`docs/000-README.md` expose les deux contrats de validation Rust et le prompt de reprise candidat `006`.
Le plan `005` enregistre le résultat de la réconciliation intégrée et conserve les responsabilités `rc.1`, stable et `publish.001` déjà attribuées.
## Hors scope
Cette tranche ne :
- crée pas de skeleton Tauri `003` ;
- crée pas de profil Web placeholder ;
- attribue pas de release au travail Tauri différé ;
- ajoute pas les trois candidats d'horizon à la roadmap engagée ;
- modifie pas `CHANGELOG.md`, réservé à la préparation RC puis à la stable ;
- migre pas KSP ou Games ;
- change pas les règles Rust/Tauri fermées pendant les alphas.
## Validation opérateur
Après application du history `PASS` de `alpha.9`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-beta.1'
test -f history/0.0.5/alpha.9.md
test -f deltas/0.0.5/beta.1.md
test -f prompts/006-V0_1_0_START_PROMPT.md
test ! -e history/0.0.5/beta.1.md
grep -A2 '^## Statut$' history/0.0.5/alpha.9.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 13 -->' README.md
grep -Fx '<!-- version: 7 -->' ROADMAP.md
grep -Fx '<!-- version: 16 -->' docs/000-README.md
grep -Fx '<!-- version: 13 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -Fx '<!-- version: 11 -->' docs/studies/001-KSP_GAMES_RECONCILIATION.md
grep -Fx '<!-- version: 1 -->' prompts/006-V0_1_0_START_PROMPT.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path("history/0.0.5/alpha.9.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "(d) skeleton Tauri pour projets contrôlés" in roadmap
assert "Aucun numéro de release n'est réservé pour ce travail" in roadmap
assert "saselang-bible" not in roadmap
study = Path("docs/studies/001-KSP_GAMES_RECONCILIATION.md").read_text(encoding="utf-8")
for phrase in (
"## Réconciliation intégrée `beta.1`",
"skeleton Tauri contrôlé complet",
"`DEFER`",
"repris dans `ROADMAP.md` sans numéro de release",
"Les trois axes plus larges identifiés pendant `alpha.8` restent des **candidats d'horizon**",
):
assert phrase in study, phrase
plan = Path("docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"Le `DEFER` du skeleton Tauri contrôlé est suffisamment décidé",
"`prompts/006-V0_1_0_START_PROMPT.md` est préparé",
"il ne transforme pas le skeleton Tauri différé en obligation de `0.1.0`",
):
assert phrase in plan, phrase
prompt = Path("prompts/006-V0_1_0_START_PROMPT.md").read_text(encoding="utf-8")
for phrase in (
"# Prompt de démarrage 0.1.0 — première baseline réutilisable",
"pgr-v0.0.5.zip",
"pgr-0.0.5-publish.001-report.md",
"Version cible : `0.1.0`. Première tranche attendue : `0.1.0-alpha.1`.",
"Le skeleton Tauri contrôlé reste `DEFER`",
"Le plan `0.1.0` MUST programmer une revue d'horizon avant la clôture stable.",
):
assert phrase in prompt, phrase
assert not any(Path("docs/skeletons").glob("003-TAURI*.md"))
print("0.0.5 beta.1 integrated reconciliation: clean (owners reconciled, Tauri defer roadmapped, horizon candidates remain uncommitted, prompt 006 prepared)")
PY
git diff --check
git add VERSION README.md ROADMAP.md \
docs/000-README.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
docs/studies/001-KSP_GAMES_RECONCILIATION.md \
prompts/006-V0_1_0_START_PROMPT.md \
deltas/0.0.5/beta.1.md
git diff --cached --check
git status --short
```
La sortie Git attendue avant ajout du history est exactement :
```text
M README.md
M ROADMAP.md
M VERSION
A deltas/0.0.5/beta.1.md
M docs/000-README.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
M docs/studies/001-KSP_GAMES_RECONCILIATION.md
A prompts/006-V0_1_0_START_PROMPT.md
```

190
deltas/0.0.5/rc.1.md Normal file
View File

@@ -0,0 +1,190 @@
<!-- file: deltas/0.0.5/rc.1.md -->
<!-- version: 1 -->
# Delta 0.0.5-rc.1 — gel du scope et préparation de release
## Baseline et version
Baseline : `0.0.5-beta.1`, avec `history/0.0.5/beta.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Le commit exact de cette baseline sera celui produit par l'opérateur après application du history beta ; il n'est pas anticipé dans cette livraison simultanée du history et du delta suivant.
Version avant application :
```text
0.0.5-beta.1
```
Version après application :
```text
0.0.5-rc.1
```
## Objet et gel
La réconciliation `beta.1` est `PASS`. La RC gèle le scope fonctionnel de `0.0.5` sur :
- les prompts versionnés, contrats documentaires facultatifs et responsabilités de lifecycle/revue d'horizon ;
- le profil Rust strict des projets contrôlés, ses contrats de nomenclature/packaging/tracing et ses audits monotâches ;
- l'audit de complétude de façade et l'usage canonique `crate::Item` ;
- les profils framework et Tauri 2, leurs frontières Rust/frontend, TS-RS, plugins/capabilities, politique de versions produit et exception encadrée `lib + bin` ;
- la décision explicite `DEFER` du skeleton Tauri contrôlé jusqu'à matérialisation d'owners Web suffisants ;
- la réconciliation KSP/Games et le prompt candidat `006` vers `0.1.0`.
Le changelog reçoit une entrée candidate `0.0.5` orientée utilisateurs. `ROADMAP.md` est vérifié mais reste inchangé : `0.0.5` n'est marqué terminé qu'à la promotion stable ; `0.1.0` reste la prochaine release engagée ; le skeleton Tauri reste différé sans numéro réservé. Le prompt `006` est vérifié sans être réécrit si son contrat est déjà correct.
Aucun nouvel owner, profil Web, skeleton, template, audit, règle fonctionnelle ou version postérieure à `0.1.0` n'entre en RC.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
```
ADD :
```text
deltas/0.0.5/rc.1.md
```
DELETE : aucun.
L'archive contient exactement ces fichiers complets. Le history `beta.1` est livré séparément ; le history `rc.1` sera produit après la gate opérateur.
## Gate opérateur de release candidate
Après application du history `PASS` de `beta.1`, commit/push de cette tranche, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.0.5-rc.1'
git cat-file -e HEAD:history/0.0.5/beta.1.md
test -f history/0.0.5/beta.1.md
test -f deltas/0.0.5/rc.1.md
test -f prompts/006-V0_1_0_START_PROMPT.md
test ! -e history/0.0.5/rc.1.md
grep -A2 '^## Statut$' history/0.0.5/beta.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 8 -->' CHANGELOG.md
grep -Fx '## 0.0.5 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 14 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -Fx '<!-- version: 7 -->' ROADMAP.md
grep -Fx '<!-- version: 1 -->' prompts/006-V0_1_0_START_PROMPT.md
grep -F 'La gate opérateur de `beta.1` est `PASS`' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -F '(d) skeleton Tauri pour projets contrôlés' ROADMAP.md
grep -F 'Le skeleton Tauri contrôlé reste `DEFER`' prompts/006-V0_1_0_START_PROMPT.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'FAIL',
'alpha.3.fix.1.md': 'PASS',
'alpha.4.md': 'PASS',
'alpha.5.md': 'FAIL',
'alpha.5.fix.1.md': 'PASS',
'alpha.6.md': 'FAIL',
'alpha.6.fix.1.md': 'FAIL',
'alpha.6.fix.2.md': 'FAIL',
'alpha.6.fix.3.md': 'PASS',
'alpha.7.md': 'FAIL',
'alpha.7.fix.1.md': 'PASS',
'alpha.8.md': 'PASS',
'alpha.9.md': 'PASS',
'beta.1.md': 'PASS',
}
histories = {path.name for path in Path('history/0.0.5').glob('*.md')}
assert histories == set(expected), histories
for name, status in expected.items():
text = Path('history/0.0.5', name).read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
deltas = {path.name for path in Path('deltas/0.0.5').glob('*.md')}
assert deltas == set(expected) | {'rc.1.md'}, deltas
changelog = Path('CHANGELOG.md').read_text(encoding='utf-8')
assert '## 0.0.5 (candidate)' in changelog
for forbidden in ('alpha.6.fix.3', 'alpha.7.fix.1', 'beta.1'):
assert forbidden not in changelog, forbidden
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `( ) 0.0.5`' in roadmap
assert '- `( ) 0.1.0`' in roadmap
assert '(d) skeleton Tauri pour projets contrôlés' in roadmap
assert 'saselang-bible' not in roadmap
prompt = Path('prompts/006-V0_1_0_START_PROMPT.md').read_text(encoding='utf-8')
for value in (
'pgr-v0.0.5.zip',
'pgr-0.0.5-publish.001-report.md',
'0.1.0-alpha.1',
'Le skeleton Tauri contrôlé reste `DEFER`',
"revue d'horizon avant la clôture stable",
):
assert value in prompt, value
for path in (
'scripts/audit_rust_item_spacing.py',
'scripts/audit_rust_module_order.py',
'scripts/audit_rust_reexport_blocks.py',
'scripts/audit_rust_trait_import_blocks.py',
'scripts/audit_rust_export_completeness.py',
):
assert Path(path).is_file(), path
assert Path('docs/rules/710-TAURI.md').is_file()
assert not any(Path('docs/skeletons').glob('003-TAURI*.md'))
print('0.0.5 rc.1 integration audit: clean (16 prior histories, frozen scope, candidate changelog, roadmap/prompt 006 verified)')
PYGATE
git diff --check
git add VERSION CHANGELOG.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
deltas/0.0.5/rc.1.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M VERSION
A deltas/0.0.5/rc.1.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que le changelog décrit les capacités de la release plutôt que ses tranches internes, que le `DEFER` Tauri reste visible sans numéro de release, que les trois autres candidats d'horizon ne sont pas promus en roadmap, que le prompt `006` ne présume aucune publication post-tag et que la RC n'étend pas le périmètre fonctionnel.
Une gate RC `PASS` n'est ni la promotion stable, ni le tag `v0.0.5`, ni la vérification de l'archive publiée après le tag.
## Transition
### PASS
Produire séparément `history/0.0.5/rc.1.md`, l'appliquer puis committer/pousser la RC avant le delta stable `rel.001`.
### FAIL
Consigner l'échec réel dans `history/0.0.5/rc.1.md` et corriger uniquement le scope gelé dans `rc.1.fix.1`, sauf REPLAN explicite si la candidate révèle un défaut fonctionnel plus large.

View File

@@ -0,0 +1,170 @@
<!-- file: deltas/0.0.5/rel.001.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.5 rel.001.fix.1 — correction de la gate stable pré-tag
## Baseline et version
Baseline : état stable `0.0.5` issu de `rel.001`, avec `history/0.0.5/rel.001.md` appliqué et committé en `FAIL`.
`VERSION` reste :
```text
0.0.5
```
Ce correctif est strictement documentaire et opérationnel. Il ne change ni la version produit, ni le scope fonctionnel validé par `rc.1`, ni les fichiers de présentation stable déjà promus par `rel.001`.
## Diagnostic corrigé
La gate `rel.001` devait confirmer la présence exacte du heading stable `## 0.0.5` dans `CHANGELOG.md`. Le delta livré a généré une chaîne Python simple contenant un retour à la ligne physique :
```python
assert '## 0.0.5
' in changelog
```
Le heredoc est donc invalide et produit `SyntaxError: unterminated string literal` avant la preuve attendue.
`rel.001.fix.1` remplace cette forme fragile par une vérification ligne par ligne :
```python
assert '## 0.0.5' in changelog.splitlines()
```
Le delta historique `rel.001.md` reste immuable.
## Scope
REPLACE :
```text
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
```
ADD :
```text
deltas/0.0.5/rel.001.fix.1.md
```
DELETE : aucun.
Aucun fichier `VERSION`, `README`, `ROADMAP`, `CHANGELOG`, règle, script, test, template ou skeleton n'est modifié par ce correctif.
## Validation opérateur pré-tag
Après application sur le commit qui contient le history `FAIL` de `rel.001` :
```bash
test "$(cat VERSION)" = '0.0.5'
git cat-file -e HEAD:history/0.0.5/rel.001.md
test -f history/0.0.5/rel.001.md
test -f deltas/0.0.5/rel.001.fix.1.md
test -f prompts/006-V0_1_0_START_PROMPT.md
test ! -e history/0.0.5/rel.001.fix.1.md
grep -A2 '^## Statut$' history/0.0.5/rel.001.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 16 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -Fx '<!-- version: 14 -->' README.md
grep -Fx '<!-- version: 8 -->' ROADMAP.md
grep -Fx '<!-- version: 9 -->' CHANGELOG.md
grep -Fx '## 0.0.5' CHANGELOG.md
grep -F -- '- `(x) 0.0.5`' ROADMAP.md
grep -F 'Le skeleton Tauri contrôlé reste `DEFER`' prompts/006-V0_1_0_START_PROMPT.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'FAIL',
'alpha.3.fix.1.md': 'PASS',
'alpha.4.md': 'PASS',
'alpha.5.md': 'FAIL',
'alpha.5.fix.1.md': 'PASS',
'alpha.6.md': 'FAIL',
'alpha.6.fix.1.md': 'FAIL',
'alpha.6.fix.2.md': 'FAIL',
'alpha.6.fix.3.md': 'PASS',
'alpha.7.md': 'FAIL',
'alpha.7.fix.1.md': 'PASS',
'alpha.8.md': 'PASS',
'alpha.9.md': 'PASS',
'beta.1.md': 'PASS',
'rc.1.md': 'PASS',
'rel.001.md': 'FAIL',
}
for name, status in expected.items():
delta = Path('deltas/0.0.5', name)
history = Path('history/0.0.5', name)
assert delta.is_file(), name
assert history.is_file(), name
text = history.read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
pending = {p.name for p in Path('deltas/0.0.5').glob('*.md')} - \
{p.name for p in Path('history/0.0.5').glob('*.md')}
assert pending == {'rel.001.fix.1.md'}, pending
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `(x) 0.0.5`' in roadmap
assert '- `( ) 0.1.0`' in roadmap
assert '(d) skeleton Tauri pour projets contrôlés' in roadmap
assert 'saselang-bible' not in roadmap
changelog = Path('CHANGELOG.md').read_text(encoding='utf-8')
assert '## 0.0.5' in changelog.splitlines()
assert '## 0.0.5 (candidate)' not in changelog
prompt = Path('prompts/006-V0_1_0_START_PROMPT.md').read_text(encoding='utf-8')
assert 'pgr-v0.0.5.zip' in prompt
assert 'pgr-0.0.5-publish.001-report.md' in prompt
assert '0.1.0-alpha.1' in prompt
assert 'Le skeleton Tauri contrôlé reste `DEFER`' in prompt
plan = Path('docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md').read_text(encoding='utf-8')
assert "La gate opérateur de `rel.001` est toutefois `FAIL`" in plan
assert '`rel.001.fix.1` corrige uniquement cette preuve de clôture' in plan
print('0.0.5 rel.001.fix.1 stable history audit: clean (18 prior histories, failed rel preserved, corrected pre-tag proof)')
PYGATE
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md \
deltas/0.0.5/rel.001.fix.1.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history du fix est exactement :
```text
A deltas/0.0.5/rel.001.fix.1.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que `VERSION` reste `0.0.5`, que la présentation stable de `rel.001` reste inchangée, que le `FAIL` de `rel.001` est conservé historiquement, que le fix ne modifie aucun owner fonctionnel et qu'aucun tag n'est créé avant le history PASS de ce correctif.
## Transition
### PASS
Produire séparément `history/0.0.5/rel.001.fix.1.md`, l'appliquer puis committer/pousser la clôture stable corrigée. Ensuite seulement créer et publier le tag canonique `v0.0.5`, télécharger son archive source depuis Gitea et exécuter la vérification externe `publish.001`.
### FAIL
Consigner le diagnostic réel dans `history/0.0.5/rel.001.fix.1.md`, ne pas tagger et poursuivre avec un nouveau `.fix.N` ou un REPLAN si le problème dépasse la gate de clôture.

179
deltas/0.0.5/rel.001.md Normal file
View File

@@ -0,0 +1,179 @@
<!-- file: deltas/0.0.5/rel.001.md -->
<!-- version: 1 -->
# Delta 0.0.5 rel.001 — promotion stable pré-tag
## Baseline et version
Baseline : `0.0.5-rc.1`, avec `history/0.0.5/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Le commit exact de cette baseline sera celui produit par l'opérateur après application du history RC ; il n'est pas anticipé dans cette livraison simultanée du history et du delta stable.
Version avant application :
```text
0.0.5-rc.1
```
Version après application :
```text
0.0.5
```
`rel.001` identifie la clôture opérationnelle ; il ne fait pas partie de la version SemVer du produit.
## Objet
Promouvoir la RC validée vers la stable `0.0.5`. La tranche finalise uniquement la présentation de la release : version stable, roadmap terminée, changelog sans marqueur candidate, index documentaires et plan historique.
Le scope fonctionnel reste celui validé en RC : lifecycle inter-release, prompts versionnés, contrats documentaires locaux, profil Rust strict et audits monotâches, contrats architecturaux des suffixes de crates, ownership du tracing, profil Tauri 2, classification des versions produit, réconciliation KSP/Games et décision `DEFER` du skeleton Tauri contrôlé jusqu'à matérialisation d'owners Web suffisants.
La validation de cette tranche est **pré-tag**. Ni le tag `v0.0.5`, ni l'archive `pgr-v0.0.5.zip` téléchargée depuis Gitea, ni un rapport `pgr-0.0.5-publish.001-report.md` ne sont déclarés existants par ce delta. Ils suivent le history PASS, le commit stable et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
```
ADD :
```text
deltas/0.0.5/rel.001.md
```
DELETE : aucun.
L'archive contient uniquement ces fichiers complets. `history/0.0.5/rc.1.md` est livré séparément ; le history de `rel.001` sera produit après sa gate. Le rapport post-tag restera extérieur à l'archive source taggée.
## Validation opérateur pré-tag
Après application sur le commit `rc.1`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.5'
git cat-file -e HEAD:history/0.0.5/rc.1.md
test -f history/0.0.5/rc.1.md
test -f deltas/0.0.5/rel.001.md
test -f prompts/006-V0_1_0_START_PROMPT.md
test ! -e history/0.0.5/rel.001.md
grep -Fx '<!-- version: 14 -->' README.md
grep -Fx '<!-- version: 8 -->' ROADMAP.md
grep -Fx '<!-- version: 9 -->' CHANGELOG.md
grep -Fx '<!-- version: 17 -->' docs/000-README.md
grep -Fx '<!-- version: 15 -->' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -F 'plan historique de réconciliation `0.0.5`' README.md
grep -F -- '- `(x) 0.0.5`' ROADMAP.md
grep -Fx '## 0.0.5' CHANGELOG.md
grep -F 'périmètre et décisions de la release `0.0.5`' docs/000-README.md
grep -F 'La gate opérateur de `rc.1` est `PASS`' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -F 'pgr-0.0.5-publish.001-report.md' docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
grep -F 'Le skeleton Tauri contrôlé reste `DEFER`' prompts/006-V0_1_0_START_PROMPT.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'PASS',
'alpha.3.md': 'FAIL',
'alpha.3.fix.1.md': 'PASS',
'alpha.4.md': 'PASS',
'alpha.5.md': 'FAIL',
'alpha.5.fix.1.md': 'PASS',
'alpha.6.md': 'FAIL',
'alpha.6.fix.1.md': 'FAIL',
'alpha.6.fix.2.md': 'FAIL',
'alpha.6.fix.3.md': 'PASS',
'alpha.7.md': 'FAIL',
'alpha.7.fix.1.md': 'PASS',
'alpha.8.md': 'PASS',
'alpha.9.md': 'PASS',
'beta.1.md': 'PASS',
'rc.1.md': 'PASS',
}
for name, status in expected.items():
delta = Path('deltas/0.0.5', name)
history = Path('history/0.0.5', name)
assert delta.is_file(), name
assert history.is_file(), name
text = history.read_text(encoding='utf-8')
assert re.search(rf'## Statut\s+{status}\s', text), (name, status)
pending = {p.name for p in Path('deltas/0.0.5').glob('*.md')} - \
{p.name for p in Path('history/0.0.5').glob('*.md')}
assert pending == {'rel.001.md'}, pending
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `(x) 0.0.5`' in roadmap
assert '- `( ) 0.1.0`' in roadmap
assert '(d) skeleton Tauri pour projets contrôlés' in roadmap
assert 'saselang-bible' not in roadmap
changelog = Path('CHANGELOG.md').read_text(encoding='utf-8')
assert '## 0.0.5
' in changelog
assert '## 0.0.5 (candidate)' not in changelog
prompt = Path('prompts/006-V0_1_0_START_PROMPT.md').read_text(encoding='utf-8')
assert 'pgr-v0.0.5.zip' in prompt
assert 'pgr-0.0.5-publish.001-report.md' in prompt
assert '0.1.0-alpha.1' in prompt
assert 'Le skeleton Tauri contrôlé reste `DEFER`' in prompt
print('0.0.5 stable history audit: clean (17 prior histories with expected statuses, rel.001 pending)')
PYGATE
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION README.md ROADMAP.md CHANGELOG.md docs/000-README.md \
docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md deltas/0.0.5/rel.001.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M README.md
M ROADMAP.md
M VERSION
A deltas/0.0.5/rel.001.md
M docs/000-README.md
M docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md
```
Les `48` tests Python et les validations structurelles validés en RC restent des preuves applicables parce qu'aucun code, script, test, règle, template ou skeleton technique n'est modifié pendant `rel.001`. La gate stable se concentre donc sur l'intégrité de la chaîne historique, la présentation stable et les audits documentaires affectés.
## Revue opérateur complémentaire
Confirmer que le scope fonctionnel de la RC ne change pas, que README/roadmap/changelog/index/plan décrivent la même stable, que les `FAIL` historiques restent conservés avec leurs fixes `PASS`, que le skeleton Tauri reste différé sans release réservée, que le prompt `006` reste conditionnel à une vraie publication et qu'aucune preuve post-tag n'est anticipée.
## Transition
### PASS
Produire séparément `history/0.0.5/rel.001.md`, l'appliquer puis committer la stable. Ensuite seulement créer et publier le tag canonique `v0.0.5`, télécharger son archive source depuis Gitea, vérifier cette archive et conserver séparément la preuve post-tag `pgr-0.0.5-publish.001-report.md`.
Le message manuel de reprise de `prompts/006-V0_1_0_START_PROMPT.md` n'est remis à l'opérateur qu'après vérification effective de l'archive et d'un rapport post-tag PASS réel.
### FAIL
Consigner le diagnostic réel dans `history/0.0.5/rel.001.md`, ne pas tagger et corriger la clôture dans une tranche explicite avant publication.

202
deltas/0.1.0/alpha.1.md Normal file
View File

@@ -0,0 +1,202 @@
<!-- file: deltas/0.1.0/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.1 — audit de la stable et cadrage de la baseline réutilisable
## Baseline et sources
Baseline PGR autoritaire : `pgr-v0.0.5.zip`, archive source téléchargée depuis le tag Gitea `v0.0.5`, accompagnée du rapport externe `pgr-0.0.5-publish.001-report.md` avec statut `PASS`.
SHA-256 vérifiés :
```text
pgr-v0.0.5.zip 1fb72bafb24b5a0f3406561b96caa8245142a5f099e692842d9ef1ba44f41b49
pgr-0.0.5-publish.001-report.md a6727fd1f3122dbb19eb79d6b904ebaed2bbfc360ed4a34cc1299cb2166efd96
games-v0.3.6.zip ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
khadhroony-solana-project-v0.3.16.zip db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0
```
Games et KSP sont uniquement des corpus de pression pour préparer l'adoption future ; ils ne sont ni modifiés ni incorporés à cette archive delta.
Version avant application :
```text
0.0.5
```
Version après application :
```text
0.1.0-alpha.1
```
## Objet
Exécuter `prompts/006-V0_1_0_START_PROMPT.md` : auditer intégralement la stable `v0.0.5`, ses règles, profils, templates, skeletons, audits, décisions différées et chaîne de gouvernance, puis créer le plan de la première baseline réellement réutilisable avant tout changement normatif important.
La tranche consigne également les décisions de cadrage acquises pendant la reprise :
- corriger en `0.1.0` la convention future `rel.001` vers `rel.1` sans réécrire l'historique ;
- distinguer le nom de tranche de fermeture du commit qui établit finalement la stable `X.Y.Z` ;
- formaliser le handoff automatique des commandes Git après chaque history et des commandes/preuves de publication avant/après tag ;
- traiter Web, serveur Rust/Actix, Java/Android, WASM et Tauri dans des releases `0.1.x` séparées, jamais comme un bloc unique `0.1.0` ;
- préparer l'adoption de PGR par Games dès que son sous-ensemble requis est prêt, puis par KSP dont la pression est principalement Rust/Cargo + Tauri.
Aucune de ces corrections n'est encore matérialisée normativement dans `alpha.1`.
## Résultat de l'audit d'intake
La stable et son rapport post-tag sont cohérents. L'archive contient `225` entrées sous `pgr/`, `194` fichiers et `31` répertoires, CRC propre, aucun symlink et aucune métadonnée `.git` attendue.
La suite PGR donne `48/48` tests `PASS`. Les audits Markdown sont propres : `171` fichiers pour les headers, `8` tables sur `171` fichiers et `161` liens locaux sur `171` fichiers.
Les `62` couples delta/history de `0.0.1` à `0.0.5` sont complets. Les `19` histories de `0.0.5` conservent leurs statuts réels, notamment `rel.001` `FAIL` puis `rel.001.fix.1` `PASS`.
Les owners actuels couvrent déjà Rust/Cargo (`510`), Java/Maven/Gradle (`520`), Android (`610`) et Tauri (`710`). Les templates techniques actuels sont Rust/Cargo ; les skeletons concrets sont la fondation de gouvernance et le workspace Rust/Cargo. Le skeleton Tauri reste correctement `DEFER` tant que les owners Web manquants ne sont pas matérialisés.
Games `0.3.6` confirme une pression réelle Web/Vite/TypeScript/Sass, Android/Gradle, Rust/WASM et Tauri, avec `0.3.7` réservé dans son propre roadmap à l'alignement PGR. KSP `0.3.16` contient six applications Tauri et un socle essentiellement Rust/Cargo. Ces observations servent au sizing futur et ne créent aucun profil dans cette tranche.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
```
ADD :
```text
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
deltas/0.1.0/alpha.1.md
```
DELETE : aucun.
`RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, les règles, profils, templates, skeletons, scripts et histories existants restent inchangés dans `alpha.1`.
Aucun `history/0.1.0/alpha.1.md` n'est anticipé avant la gate opérateur.
## Validation opérateur
Après application sur la stable `0.0.5`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.1'
test -f docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
test -f deltas/0.1.0/alpha.1.md
test ! -e history/0.1.0/alpha.1.md
grep -Fx '<!-- version: 15 -->' README.md
grep -Fx '<!-- version: 18 -->' docs/000-README.md
grep -F '006-V0_1_0_REUSABLE_BASELINE_PLAN.md' README.md docs/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
expected = {
'0.0.1': 12,
'0.0.2': 12,
'0.0.3': 10,
'0.0.4': 9,
'0.0.5': 19,
}
for release, count in expected.items():
deltas = {path.name for path in Path('deltas', release).glob('*.md')}
histories = {path.name for path in Path('history', release).glob('*.md')}
assert len(deltas) == count, (release, len(deltas))
assert deltas == histories, (release, sorted(deltas ^ histories))
statuses = {}
for path in Path('history/0.0.5').glob('*.md'):
text = path.read_text(encoding='utf-8')
match = re.search(r'## Statut\s+(PASS|FAIL|PARTIAL|BLOCKED)\s', text)
assert match is not None, path
statuses[path.name] = match.group(1)
assert statuses['rel.001.md'] == 'FAIL'
assert statuses['rel.001.fix.1.md'] == 'PASS'
for path in (
Path('docs/rules/510-RUST_CARGO.md'),
Path('docs/rules/520-JAVA_MAVEN_GRADLE.md'),
Path('docs/rules/610-ANDROID.md'),
Path('docs/rules/710-TAURI.md'),
Path('docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md'),
Path('docs/skeletons/002-RUST_CARGO_WORKSPACE.md'),
Path('docs/studies/002-TAURI_SKELETON_DECISION.md'),
):
assert path.is_file(), path
plan = Path('docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'rel.1',
'première tranche qui obtient le PASS stable',
'Commandes opérateur et publication',
'une release/session par domaine cohérent',
'Games',
'KSP',
'TypeScript',
'Vite',
'Android',
'WASM',
'Tauri',
'Actix Web ou autre framework',
'beta.1 — réconciliation finale et revue d\'horizon',
):
assert phrase in plan, phrase
assert '- `( ) 0.1.0`' in Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `( ) 0.1.1`' not in Path('ROADMAP.md').read_text(encoding='utf-8')
print('0.1.0 alpha.1 structural audit: clean (62 prior pairs, stable workflow truth preserved, future 0.1.x unnumbered)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
deltas/0.1.0/alpha.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M README.md
M VERSION
A deltas/0.1.0/alpha.1.md
M docs/000-README.md
A docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
La revue opérateur doit également confirmer que :
- le plan ne transforme pas les futurs axes `0.1.x` en versions numérotées prématurément ;
- Java/Android et Tauri sont reconnus comme profils existants, non recréés artificiellement ;
- le `DEFER` du skeleton Tauri reste intact dans cette tranche ;
- Games et KSP restent des corpus externes non modifiés ;
- aucune règle Web/WASM/Actix n'est introduite dans `alpha.1` ;
- les anciennes occurrences `rel.001*` restent intactes et historiques.
## Transition
### PASS
Produire `history/0.1.0/alpha.1.md` à partir des résultats réellement observés. Dans la même réponse, si aucune décision nouvelle n'est ouverte, préparer séparément le delta `0.1.0-alpha.2` consacré uniquement à la clôture stable `rel.N` et à l'identité du commit final.
Après remise du history, fournir spontanément le bloc Git exact à exécuter pour fermer `alpha.1` avant application du delta suivant, même si la règle normative des handoffs automatiques ne sera matérialisée qu'en `alpha.3`.
### FAIL
Consigner le résultat réel dans le history, puis ouvrir `0.1.0-alpha.1.fix.1` ou un REPLAN selon la cause. Aucun changement de `alpha.2` ne doit être absorbé silencieusement dans le fix.

View File

@@ -0,0 +1,178 @@
<!-- file: deltas/0.1.0/alpha.2.fix.1.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.2.fix.1 — correction de la gate `rel.N`
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-alpha.2`, réalisé après application de `history/0.1.0/alpha.2.md` avec statut `FAIL`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.0-alpha.2
```
Version après application :
```text
0.1.0-alpha.2.fix.1
```
## Objet
Corriger uniquement la gate opérateur défectueuse de `alpha.2`.
Le contenu normatif de `docs/rules/200-GOVERNANCE.md` et `docs/rules/210-WORKFLOW.md` a déjà été couvert par la preuve Python de `alpha.2` et n'est pas modifié. Le défaut constaté provient de motifs `grep -F` entourés de quotes simples alors qu'ils contenaient des apostrophes littérales, notamment `n'utilise` et `l'exploitation`.
Le delta historique `deltas/0.1.0/alpha.2.md` reste immuable.
## Scope
REPLACE :
```text
VERSION
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
ADD :
```text
deltas/0.1.0/alpha.2.fix.1.md
```
DELETE : aucun.
Aucun owner normatif, profil technologique, skeleton, template, script d'audit ou test n'est modifié par ce correctif.
## Correction
La validation du fix n'utilise plus de `grep` pour les phrases contenant apostrophes, backticks ou autres caractères shell sensibles. Ces assertions sont regroupées dans un bloc Python littéral sous heredoc quoté.
Le fix vérifie à nouveau :
- le history `alpha.2` en `FAIL` ;
- la convention `rel.N` sans padding ;
- la conservation des quatre artefacts historiques `rel.001*` de `0.0.5` ;
- la distinction entre tranche de clôture et commit stable `X.Y.Z` ;
- l'indépendance de `publish.001` ;
- les horizons Clippy statique et deployment/operations différés ;
- l'absence de réservation prématurée de `0.1.1` ;
- les tests/audits globaux et le scope exact du fix.
## Validation opérateur
Après application du history `FAIL`, commit/push de `alpha.2`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.2.fix.1'
git cat-file -e HEAD:history/0.1.0/alpha.2.md
test -f history/0.1.0/alpha.2.md
test -f deltas/0.1.0/alpha.2.md
test -f deltas/0.1.0/alpha.2.fix.1.md
test ! -e history/0.1.0/alpha.2.fix.1.md
grep -A2 '^## Statut$' history/0.1.0/alpha.2.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 5 -->' docs/rules/200-GOVERNANCE.md
grep -Fx '<!-- version: 6 -->' docs/rules/210-WORKFLOW.md
grep -Fx '<!-- version: 3 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path('history/0.1.0/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
governance = Path('docs/rules/200-GOVERNANCE.md').read_text(encoding='utf-8')
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
plan = Path('docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md').read_text(encoding='utf-8')
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for phrase in (
'rel.1',
'rel.1.fix.1',
"représentation canonique n'utilise pas de zéro de padding",
'première tranche de clôture PASS',
'Le commit `X.Y.Z` MUST',
):
assert phrase in governance or phrase in workflow, phrase
for phrase in (
'history rel.1 FAIL / PARTIAL / BLOCKED',
'premier history rel.N[/fix.M] PASS qui établit réellement la stable',
'La présente règle ne renomme pas `publish.001`',
):
assert phrase in workflow, phrase
for phrase in (
'sous-ensemble des conventions Rust/Clippy',
"série dédiée au déploiement et à l'exploitation",
'### alpha.2.fix.1 — correction de la gate `rel.N`',
):
assert phrase in plan, phrase
for path in (
Path('deltas/0.0.5/rel.001.md'),
Path('history/0.0.5/rel.001.md'),
Path('deltas/0.0.5/rel.001.fix.1.md'),
Path('history/0.0.5/rel.001.fix.1.md'),
):
assert path.is_file(), path
assert 'publish.001' in workflow
assert '- `( ) 0.1.1`' not in roadmap
print('0.1.0 alpha.2.fix.1 rel gate audit: clean (failed gate preserved, rel.N content reconfirmed, shell-sensitive assertions safe)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
deltas/0.1.0/alpha.2.fix.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.1.0/alpha.2.fix.1.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que :
- le `FAIL` de `alpha.2` est conservé historiquement ;
- `docs/rules/200-GOVERNANCE.md` et `docs/rules/210-WORKFLOW.md` ne sont pas modifiés par le fix ;
- le delta historique `alpha.2.md` n'est pas réécrit ;
- aucun élément du handoff automatique réservé à `alpha.3` n'est absorbé dans le correctif ;
- aucun profil Web, Java/Android, WASM, Tauri ou serveur n'est ajouté ou modifié.
## Transition
### PASS
Produire `history/0.1.0/alpha.2.fix.1.md`, l'appliquer puis committer/pousser le fix. Dans la même réponse, reprendre la trajectoire normale avec `0.1.0-alpha.3`, consacré au handoff automatique des commandes opérateur.
Après remise du history, fournir spontanément le bloc Git exact permettant de fermer `alpha.2.fix.1` avant application de `alpha.3`.
### FAIL
Consigner le diagnostic réel dans `history/0.1.0/alpha.2.fix.1.md` et rester dans `alpha.2.fix.M`. Le scope MUST rester limité à la correction de la gate `rel.N` tant qu'aucun défaut plus large ne justifie un REPLAN.

201
deltas/0.1.0/alpha.2.md Normal file
View File

@@ -0,0 +1,201 @@
<!-- file: deltas/0.1.0/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.2 — clôture stable et identité `rel.N`
## Baseline
Baseline attendue : `0.1.0-alpha.1` committée avec `history/0.1.0/alpha.1.md` en `PASS`.
Cette tranche MUST être appliquée uniquement après le commit/push complet de `alpha.1` ; elle ne doit pas être superposée au workspace encore non committé de la gate précédente.
Version avant application :
```text
0.1.0-alpha.1
```
Version après application :
```text
0.1.0-alpha.2
```
## Objet
Corriger la convention normative de clôture stable avant diffusion plus large de PGR :
- utiliser `rel.1`, `rel.2`, etc. sans padding pour les nouvelles releases ;
- conserver sans renommage tous les artefacts historiques `rel.001*` déjà publiés ;
- distinguer le nom de la tranche de clôture de l'identité du commit stable ;
- rendre explicite qu'une clôture `FAIL`, `PARTIAL` ou `BLOCKED` conserve le suffixe opérationnel dans son commit ;
- rendre explicite que la première tranche `rel.N[/fix.M]` qui obtient réellement le `PASS` stable est committée sous `X.Y.Z` avant création du tag `vX.Y.Z`.
La tranche ne modifie aucun profil technologique, skeleton, template, script d'audit ou convention de publication post-tag `publish.001`.
## Scope
REPLACE :
```text
VERSION
docs/rules/200-GOVERNANCE.md
docs/rules/210-WORKFLOW.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
ADD :
```text
deltas/0.1.0/alpha.2.md
```
DELETE : aucun.
Le plan actif est révisé parce qu'il enregistre `alpha.1 PASS` et deux horizons différés explicitement décidés pendant la session — audit Python d'un sous-ensemble Clippy après Games/KSP et future famille deployment/operations — sans leur attribuer de numéro ni les absorber dans `0.1.0`.
Aucun `history/0.1.0/alpha.2.md` n'est anticipé avant la gate opérateur.
## Convention obtenue
La représentation future canonique est :
```text
rel.1
rel.1.fix.1
rel.2
...
```
Pour le message du commit de clôture, le défaut PGR devient :
```text
history rel.1 FAIL / PARTIAL / BLOCKED
-> X.Y.Z-rel.1
history rel.1.fix.1 FAIL / PARTIAL / BLOCKED
-> X.Y.Z-rel.1.fix.1
premier history rel.N[/fix.M] PASS établissant réellement la stable
-> X.Y.Z
```
`VERSION` MAY déjà être `X.Y.Z` pendant ces tranches de fermeture : `rel.N` n'est pas une prerelease SemVer. Le tag `vX.Y.Z` intervient uniquement après le commit final `X.Y.Z` contenant le history `PASS` stable.
Les fichiers historiques comme :
```text
deltas/0.0.5/rel.001.md
history/0.0.5/rel.001.md
deltas/0.0.5/rel.001.fix.1.md
history/0.0.5/rel.001.fix.1.md
```
restent intacts.
## Validation opérateur
Après application sur le commit de `0.1.0-alpha.1`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.2'
test -f history/0.1.0/alpha.1.md
test -f deltas/0.1.0/alpha.2.md
test ! -e history/0.1.0/alpha.2.md
grep -Fx '<!-- version: 5 -->' docs/rules/200-GOVERNANCE.md
grep -Fx '<!-- version: 6 -->' docs/rules/210-WORKFLOW.md
grep -Fx '<!-- version: 2 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
grep -F 'représentation canonique n'utilise pas de zéro de padding' docs/rules/200-GOVERNANCE.md
grep -F 'première tranche de clôture PASS' docs/rules/200-GOVERNANCE.md
grep -F 'history rel.1 FAIL / PARTIAL / BLOCKED' docs/rules/210-WORKFLOW.md
grep -F 'premier history rel.N[/fix.M] PASS qui établit réellement la stable' docs/rules/210-WORKFLOW.md
grep -F 'La présente règle ne renomme pas `publish.001`' docs/rules/210-WORKFLOW.md
grep -F 'sous-ensemble des conventions Rust/Clippy' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
grep -F 'série dédiée au déploiement et à l'exploitation' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
history = Path('history/0.1.0/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
governance = Path('docs/rules/200-GOVERNANCE.md').read_text(encoding='utf-8')
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
plan = Path('docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'rel.1',
'rel.1.fix.1',
'représentation canonique n\'utilise pas de zéro de padding',
'première tranche de clôture PASS',
'Le commit `X.Y.Z` MUST',
):
assert phrase in governance or phrase in workflow, phrase
for path in (
Path('deltas/0.0.5/rel.001.md'),
Path('history/0.0.5/rel.001.md'),
Path('deltas/0.0.5/rel.001.fix.1.md'),
Path('history/0.0.5/rel.001.fix.1.md'),
):
assert path.is_file(), path
assert 'publish.001' in workflow
assert 'La présente règle ne renomme pas `publish.001`' in workflow
assert 'sous-ensemble des conventions Rust/Clippy' in plan
assert "série dédiée au déploiement et à l'exploitation" in plan
assert '- `( ) 0.1.1`' not in Path('ROADMAP.md').read_text(encoding='utf-8')
print('0.1.0 alpha.2 rel identity audit: clean (rel.N unpadded, historical rel.001 preserved, stable commit identity explicit)')
PY
git diff --check
git add VERSION docs/rules/200-GOVERNANCE.md docs/rules/210-WORKFLOW.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
deltas/0.1.0/alpha.2.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M VERSION
A deltas/0.1.0/alpha.2.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
M docs/rules/200-GOVERNANCE.md
M docs/rules/210-WORKFLOW.md
```
La revue opérateur doit également confirmer que :
- aucune occurrence historique `rel.001*` n'a été renommée ;
- `publish.001` reste une convention indépendante et n'est pas modifiée par cette tranche ;
- aucune commande de handoff Git automatique n'est encore rendue normative ici — ce sujet appartient à `alpha.3` ;
- les horizons Clippy statique et deployment/operations restent de simples candidats différés dans le plan ;
- aucun profil Web, Java/Android, WASM, Tauri ou serveur n'est ajouté ou modifié.
## Transition
### PASS
Produire `history/0.1.0/alpha.2.md` à partir des résultats réellement observés. Dans la même réponse, si aucune décision nouvelle n'est ouverte, préparer séparément `0.1.0-alpha.3` consacré au handoff automatique des commandes opérateur après history, au commit/push, au tag stable et aux preuves requises pour `publish.001`.
Après remise du history, fournir déjà spontanément le bloc Git exact de fermeture de `alpha.2`, conformément à la décision acquise, même si `alpha.3` sera la tranche qui rendra ce comportement normatif.
### FAIL
Consigner le résultat réel dans le history puis ouvrir `0.1.0-alpha.2.fix.1` ou un REPLAN selon la cause. Aucun élément du handoff automatique prévu pour `alpha.3` ne doit être absorbé silencieusement dans le fix.

View File

@@ -0,0 +1,167 @@
<!-- file: deltas/0.1.0/alpha.3.fix.1.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.3.fix.1 — correction de la gate du handoff opérateur
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-alpha.3`, réalisé après application de `history/0.1.0/alpha.3.md` avec statut `FAIL`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.0-alpha.3
```
Version après application :
```text
0.1.0-alpha.3.fix.1
```
## Objet
Corriger uniquement la syntaxe défectueuse de la gate opérateur de `alpha.3`.
Le contenu normatif de `docs/rules/210-WORKFLOW.md`, le pattern `docs/templates/006-OPERATOR_COMMAND_HANDOFF.md`, l'index `docs/000-README.md` et le delta historique `deltas/0.1.0/alpha.3.md` restent inchangés.
Le défaut observé était un littéral Python entouré de quotes simples alors que son texte contenait l'apostrophe de `d'une` :
```python
'## Fermeture d'une tranche non stable'
```
Le fix rend les assertions textuelles syntaxiquement sûres sans modifier ce qu'elles vérifient.
## Scope
REPLACE :
```text
VERSION
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
ADD :
```text
deltas/0.1.0/alpha.3.fix.1.md
```
DELETE : aucun.
Aucun owner normatif, template, profil technologique, skeleton, script d'audit ou test n'est modifié par ce correctif.
## Validation opérateur
Après application du history `FAIL`, commit/push de `alpha.3`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.3.fix.1'
git cat-file -e HEAD:history/0.1.0/alpha.3.md
test -f history/0.1.0/alpha.3.md
test -f deltas/0.1.0/alpha.3.md
test -f deltas/0.1.0/alpha.3.fix.1.md
test -f docs/templates/006-OPERATOR_COMMAND_HANDOFF.md
test ! -e history/0.1.0/alpha.3.fix.1.md
grep -A2 '^## Statut$' history/0.1.0/alpha.3.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 7 -->' docs/rules/210-WORKFLOW.md
grep -Fx '<!-- version: 1 -->' docs/templates/006-OPERATOR_COMMAND_HANDOFF.md
grep -Fx '<!-- version: 19 -->' docs/000-README.md
grep -Fx '<!-- version: 5 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path('history/0.1.0/alpha.3.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
template = Path('docs/templates/006-OPERATOR_COMMAND_HANDOFF.md').read_text(encoding='utf-8')
plan = Path('docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md').read_text(encoding='utf-8')
index = Path('docs/000-README.md').read_text(encoding='utf-8')
workflow_phrases = (
'## Remise automatique des commandes opérateur',
'le générateur MUST remettre spontanément les commandes nécessaires pour fermer cette tranche',
'Le générateur MUST NOT inventer un remote, une branche ou une politique de tag non établis.',
'première clôture `rel.N[/fix.M]` qui établit réellement la stable',
'refs/tags/vX.Y.Z^{}',
'Le rapport `publish.*` est produit seulement à partir des artefacts et preuves réellement disponibles après publication.',
'../templates/006-OPERATOR_COMMAND_HANDOFF.md',
)
for phrase in workflow_phrases:
assert phrase in workflow, phrase
template_phrases = (
"## Fermeture d'une tranche non stable",
'git diff --cached --check',
'git push <remote> <branche>',
"## Tranche échouée suivie d'un fix",
'## Première clôture qui établit réellement la stable',
'git tag -a vX.Y.Z -m "vX.Y.Z"',
"git ls-remote <remote> 'refs/tags/vX.Y.Z^{}'",
'## Remise nécessaire pour `publish.*`',
'## Après `publish.* PASS`',
)
for phrase in template_phrases:
assert phrase in template, phrase
assert '006-OPERATOR_COMMAND_HANDOFF.md' in index
assert 'Statut opérateur : **FAIL**.' in plan
assert '### alpha.3.fix.1 — correction de la gate du handoff opérateur' in plan
print('0.1.0 alpha.3.fix.1 operator handoff gate: clean (alpha.3 FAIL preserved, workflow/template reconfirmed, Python literals safe)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
deltas/0.1.0/alpha.3.fix.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.1.0/alpha.3.fix.1.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que :
- le `FAIL` de `alpha.3` est conservé historiquement ;
- `docs/rules/210-WORKFLOW.md`, `docs/templates/006-OPERATOR_COMMAND_HANDOFF.md` et `docs/000-README.md` ne sont pas modifiés par le fix ;
- le delta historique `alpha.3.md` n'est pas réécrit ;
- aucun contenu prévu pour `alpha.4` n'est absorbé dans le correctif ;
- aucun profil technologique n'est ajouté ou modifié.
## Transition
### PASS
Produire `history/0.1.0/alpha.3.fix.1.md`, l'appliquer puis committer/pousser le fix. Reprendre ensuite la trajectoire normale avec `0.1.0-alpha.4`, consacré à l'adoption proportionnée de PGR par un projet existant.
Le handoff remis après ce PASS doit lui-même suivre le contrat `210-WORKFLOW` et `006-OPERATOR_COMMAND_HANDOFF.md` désormais reconfirmé.
### FAIL
Consigner le diagnostic réel dans `history/0.1.0/alpha.3.fix.1.md` et rester dans `alpha.3.fix.M`. Le scope MUST rester limité à la correction de la gate du handoff tant qu'aucun défaut plus large ne justifie un REPLAN.

185
deltas/0.1.0/alpha.3.md Normal file
View File

@@ -0,0 +1,185 @@
<!-- file: deltas/0.1.0/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.3 — handoff automatique des commandes opérateur
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-alpha.2.fix.1`, réalisé après application de `history/0.1.0/alpha.2.fix.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.0-alpha.2.fix.1
```
Version après application :
```text
0.1.0-alpha.3
```
## Objet
Rendre normative la remise automatique des commandes opérateur après chaque history et pendant la publication stable.
La tranche doit supprimer le besoin récurrent de demander séparément :
```text
quel message de commit utiliser ?
quand pousser ?
quand appliquer le prochain delta ?
quelles commandes exécuter pour le tag ?
quelles preuves fournir pour produire publish.* ?
```
Le workflow reste l'owner normatif. Un nouveau pattern documentaire fournit uniquement une forme de rendu réutilisable.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
docs/rules/210-WORKFLOW.md
```
ADD :
```text
docs/templates/006-OPERATOR_COMMAND_HANDOFF.md
deltas/0.1.0/alpha.3.md
```
DELETE : aucun.
## Changements normatifs
`210-WORKFLOW.md` impose désormais qu'après production d'un history destiné à l'opérateur, le générateur fournisse spontanément le bloc de fermeture correspondant. Le rendu doit utiliser les valeurs Git réelles lorsqu'elles sont établies et ne doit jamais inventer branche, remote ou politique de tag.
Le contrat distingue explicitement :
- fermeture ordinaire `history -> commit/push -> delta suivant` ;
- fermeture `FAIL/PARTIAL/BLOCKED -> commit de la tranche -> fix` ;
- première clôture `rel.N[/fix.M] PASS -> commit X.Y.Z -> tag` ;
- vérification d'un tag annoté avec distinction objet tag / commit déréférencé ;
- artefacts et preuves que l'opérateur doit fournir pour produire `publish.*` ;
- message manuel de reprise après `publish.* PASS` déjà possédé par `003-NEW_SESSION_PROMPT.md`.
## Nouveau pattern documentaire
`docs/templates/006-OPERATOR_COMMAND_HANDOFF.md` fournit les blocs adaptables pour :
```text
history ZIP
commit / push
fix ou delta suivant
tag stable
preuves post-tag
transition après publish.*
```
Il ne fixe pas `origin`, `master` ou une forge particulière comme valeurs universelles. Une commande concrète livrée à l'opérateur doit employer les valeurs déjà établies pour le projet.
## Validation opérateur
Exécuter depuis la racine du workspace après application du delta :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.3'
test -f history/0.1.0/alpha.2.fix.1.md
test -f deltas/0.1.0/alpha.3.md
test -f docs/templates/006-OPERATOR_COMMAND_HANDOFF.md
test ! -e history/0.1.0/alpha.3.md
grep -Fx '<!-- version: 7 -->' docs/rules/210-WORKFLOW.md
grep -Fx '<!-- version: 19 -->' docs/000-README.md
grep -Fx '<!-- version: 4 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path('history/0.1.0/alpha.2.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
template = Path('docs/templates/006-OPERATOR_COMMAND_HANDOFF.md').read_text(encoding='utf-8')
plan = Path('docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md').read_text(encoding='utf-8')
index = Path('docs/000-README.md').read_text(encoding='utf-8')
for phrase in (
'## Remise automatique des commandes opérateur',
"le générateur MUST remettre spontanément les commandes nécessaires pour fermer cette tranche",
'Le générateur MUST NOT inventer un remote, une branche ou une politique de tag non établis.',
'première clôture `rel.N[/fix.M]` qui établit réellement la stable',
'refs/tags/vX.Y.Z^{}',
'Le rapport `publish.*` est produit seulement à partir des artefacts et preuves réellement disponibles après publication.',
'../templates/006-OPERATOR_COMMAND_HANDOFF.md',
):
assert phrase in workflow, phrase
for phrase in (
'## Fermeture d'une tranche non stable',
'git diff --cached --check',
'git push <remote> <branche>',
'## Tranche échouée suivie d'un fix',
'## Première clôture qui établit réellement la stable',
'git tag -a vX.Y.Z -m "vX.Y.Z"',
"git ls-remote <remote> 'refs/tags/vX.Y.Z^{}'",
'## Remise nécessaire pour `publish.*`',
'## Après `publish.* PASS`',
):
assert phrase in template, phrase
assert '006-OPERATOR_COMMAND_HANDOFF.md' in index
assert 'Statut opérateur : **PASS**.' in plan
assert '### alpha.3 — handoff automatique des commandes opérateur' in plan
print('0.1.0 alpha.3 operator handoff audit: clean (history-to-commit, stable tag and publish evidence rendered explicitly)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/000-README.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
docs/rules/210-WORKFLOW.md \
docs/templates/006-OPERATOR_COMMAND_HANDOFF.md \
deltas/0.1.0/alpha.3.md
git diff --cached --check
git status --short
```
## Résultat attendu
La gate est `PASS` si :
- le history `alpha.2.fix.1` est présent et `PASS` ;
- le workflow impose la remise spontanée des commandes et interdit d'inventer les paramètres Git ;
- le pattern couvre tranche ordinaire, échec + fix, stable/tag et preuves `publish.*` ;
- la vérification d'un tag annoté distingue objet tag et commit déréférencé ;
- les `48` tests existants restent propres ;
- les trois audits Markdown restent propres ;
- le scope Git correspond exactement aux six fichiers de `alpha.3`.
## Transition
Si `PASS` :
1. produire `history/0.1.0/alpha.3.md` ;
2. remettre automatiquement le bloc opérateur conforme au nouveau pattern pour committer/pousser `0.1.0-alpha.3` ;
3. préparer `0.1.0-alpha.4`, consacré à l'adoption proportionnée de PGR par un projet existant.
Si `FAIL` : conserver le history réel et corriger uniquement la cause dans `alpha.3.fix.N`, sauf preuve imposant un REPLAN.

232
deltas/0.1.0/alpha.4.md Normal file
View File

@@ -0,0 +1,232 @@
<!-- file: deltas/0.1.0/alpha.4.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.4 — adoption PGR d’un projet existant
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-alpha.3.fix.1`, réalisé après application de `history/0.1.0/alpha.3.fix.1.md` avec statut `PASS`.
Le hash de ce commit n’est pas anticipé.
Version avant application :
```text
0.1.0-alpha.3.fix.1
```
Version après application :
```text
0.1.0-alpha.4
```
## Objet
Formaliser le contrat d’adoption de PGR par un projet existant, distinct de l’instanciation d’un nouveau projet.
La tranche introduit :
- un owner normatif `230-ADOPTION.md` ;
- un pattern documentaire `007-EXISTING_PROJECT_ADOPTION.md` ;
- la représentation architecturale du flux d’adoption ;
- les index nécessaires pour rendre ces artefacts découvrables ;
- le mapping canonique `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` ;
- la préservation explicite de l’historique antérieur au point d’adoption.
Cette tranche ne migre ni Games ni KSP. Elle ne crée aucun nouveau profil Web, Android, Tauri, WASM ou serveur.
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/000-README.md
docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
docs/rules/000-README.md
```
ADD :
```text
deltas/0.1.0/alpha.4.md
docs/rules/230-ADOPTION.md
docs/templates/007-EXISTING_PROJECT_ADOPTION.md
```
DELETE : aucun.
Les profils technologiques, skeletons existants, scripts d’audit, tests et `ROADMAP.md` restent inchangés.
## Décisions normatives
### Adoption distincte de l’instanciation
Un projet existant part de sa baseline réelle. Un skeleton MAY servir de référence de comparaison, mais PGR ne prétend pas que le dépôt a été créé depuis ce skeleton.
L’adoption ne doit pas imposer toute la bibliothèque PGR ni réécrire l’historique pour simuler une conformité passée.
### Classification canonique
Chaque owner ou contrat candidat dans le scope d’adoption est classifié selon :
```text
ADOPT
KEEP-LOCAL
OVERRIDE
DEFER
```
`KEEP-LOCAL` préserve une décision locale qui n’a pas besoin d’être remplacée. `OVERRIDE` remplace ou raffine explicitement une règle PGR applicable et doit porter scope et justification. `DEFER` enregistre un report réel et ne peut pas être présenté comme une adoption terminée.
### Migration progressive
L’adoption SHOULD être découpée en tranches validables et proportionnées lorsque cela réduit le risque. L’adoption d’un profil n’entraîne pas automatiquement celle des profils voisins.
Les conventions nouvelles commencent au point d’adoption établi ; les commits, tags, histories et autres snapshots antérieurs restent historiques.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.3.fix.1`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.4'
git cat-file -e HEAD:history/0.1.0/alpha.3.fix.1.md
test -f history/0.1.0/alpha.3.fix.1.md
test -f deltas/0.1.0/alpha.4.md
test -f docs/rules/230-ADOPTION.md
test -f docs/templates/007-EXISTING_PROJECT_ADOPTION.md
test ! -e history/0.1.0/alpha.4.md
grep -A2 '^## Statut$' history/0.1.0/alpha.3.fix.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 12 -->' RULES.md
grep -Fx '<!-- version: 14 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 20 -->' docs/000-README.md
grep -Fx '<!-- version: 4 -->' docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
grep -Fx '<!-- version: 1 -->' docs/rules/230-ADOPTION.md
grep -Fx '<!-- version: 1 -->' docs/templates/007-EXISTING_PROJECT_ADOPTION.md
grep -Fx '<!-- version: 6 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path('history/0.1.0/alpha.3.fix.1.md').read_text(encoding='utf-8')
rules = Path('RULES.md').read_text(encoding='utf-8')
rules_index = Path('docs/rules/000-README.md').read_text(encoding='utf-8')
index = Path('docs/000-README.md').read_text(encoding='utf-8')
architecture = Path('docs/architecture/002-GOVERNANCE_ARCHITECTURE.md').read_text(encoding='utf-8')
adoption = Path('docs/rules/230-ADOPTION.md').read_text(encoding='utf-8')
template = Path('docs/templates/007-EXISTING_PROJECT_ADOPTION.md').read_text(encoding='utf-8')
plan = Path('docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md').read_text(encoding='utf-8')
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
for phrase in (
'ADOPT',
'KEEP-LOCAL',
'OVERRIDE',
'DEFER',
'baseline autoritaire',
'Migration progressive',
'Préservation de l’historique',
'MUST NOT demander de réécrire des commits, tags, histories, changelogs',
'Un skeleton PGR MAY servir de checklist de comparaison pour un projet existant.',
'../templates/007-EXISTING_PROJECT_ADOPTION.md',
):
assert phrase in adoption, phrase
for phrase in (
'## Baseline autoritaire',
'## Mapping d’adoption',
'ADOPT / KEEP-LOCAL / OVERRIDE / DEFER',
'## Découpage de migration',
'## Historique et compatibilité',
'## Validation de sortie',
):
assert phrase in template, phrase
for phrase in (
'## Adoption d’un projet existant',
'ADOPT / KEEP-LOCAL / OVERRIDE / DEFER',
'projet autonome avec historique préservé',
'../rules/230-ADOPTION.md',
):
assert phrase in architecture, phrase
assert 'docs/rules/230-ADOPTION.md' in rules
assert '230-ADOPTION.md' in rules_index
assert 'rules/230-ADOPTION.md' in index
assert 'templates/007-EXISTING_PROJECT_ADOPTION.md' in index
assert 'Statut opérateur : **PASS**.' in plan
assert 'Statut opérateur : **à valider**.' in plan
assert 'Cette tranche ne migre ni Games ni KSP.' in Path('deltas/0.1.0/alpha.4.md').read_text(encoding='utf-8')
assert '- `( ) 0.1.1`' not in roadmap
print('0.1.0 alpha.4 existing-project adoption audit: clean (baseline, owner mapping, decision classes, progressive migration and history preservation explicit)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION RULES.md docs/000-README.md \
docs/architecture/002-GOVERNANCE_ARCHITECTURE.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
docs/rules/000-README.md docs/rules/230-ADOPTION.md \
docs/templates/007-EXISTING_PROJECT_ADOPTION.md \
deltas/0.1.0/alpha.4.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `alpha.4` est exactement :
```text
M RULES.md
M VERSION
A deltas/0.1.0/alpha.4.md
M docs/000-README.md
M docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
M docs/rules/000-README.md
A docs/rules/230-ADOPTION.md
A docs/templates/007-EXISTING_PROJECT_ADOPTION.md
```
## Revue opérateur complémentaire
Confirmer que :
- le contrat d’adoption n’impose pas tous les profils PGR à un projet existant ;
- `KEEP-LOCAL` n’est pas utilisé comme alias silencieux d’un override ;
- `OVERRIDE` exige bien scope et justification ;
- `DEFER` reste distinct d’un résultat adopté ;
- un skeleton sert seulement de référence de comparaison lorsqu’il est utile ;
- aucun historique du projet destinataire ne doit être réécrit pour rendre le passé rétroactivement conforme ;
- Games et KSP restent des futurs consommateurs, pas des dépendances de `0.1.0` ;
- aucun numéro futur `0.1.x` n’est réservé par cette tranche.
## Transition
### PASS
Produire `history/0.1.0/alpha.4.md`, l’appliquer puis remettre automatiquement les commandes de commit/push conformément à `210-WORKFLOW.md` et `006-OPERATOR_COMMAND_HANDOFF.md`.
Reprendre ensuite la trajectoire avec `0.1.0-alpha.5`, consacré à la réconciliation de la fondation, du skeleton Rust/Cargo et au dry-run de composition/adoption.
### FAIL
Consigner le diagnostic réel dans `history/0.1.0/alpha.4.md` et rester dans `alpha.4.fix.N` sauf REPLAN justifié. Le fix MUST rester borné au défaut réellement observé.

371
deltas/0.1.0/alpha.5.md Normal file
View File

@@ -0,0 +1,371 @@
<!-- file: deltas/0.1.0/alpha.5.md -->
<!-- version: 1 -->
# Delta 0.1.0-alpha.5 — baseline Rust/Cargo réutilisable et dry-run
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-alpha.4`, réalisé après application de `history/0.1.0/alpha.4.md` avec statut `PASS`.
Le hash de ce commit n’est pas anticipé.
Version avant application :
```text
0.1.0-alpha.4
```
Version après application :
```text
0.1.0-alpha.5
```
## Objet
Prouver que la première baseline Rust/Cargo de PGR est réellement réutilisable dans deux situations distinctes :
```text
NEW nouveau workspace gouverné depuis une baseline vide
ADOPTION workspace Rust existant conservant ses décisions locales légitimes
```
La tranche réconcilie les skeletons `001` / `002`, les guides des templates Rust/Cargo et la validation. Elle ajoute un contrat durable de dry-run, mais aucun générateur de projet permanent et aucun nouveau profil technologique.
Games et KSP ne servent pas de fixtures et ne sont pas modifiés.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
docs/skeletons/000-README.md
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
docs/templates/001-RUST_CARGO_TOOLING.md
docs/templates/002-CARGO_MANIFESTS.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
deltas/0.1.0/alpha.5.md
docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md
```
DELETE : aucun.
Les templates techniques sous `templates/rust-cargo/`, les scripts d’audit, les profils Java/Android/Tauri, `ROADMAP.md` et `CHANGELOG.md` restent inchangés.
## Décisions
### Nouveau projet
Le chemin d’instanciation reste `001 + 002`. Les cinq templates techniques sont adaptés dans un répertoire temporaire, les placeholders sont résolus et une crate source triviale est créée uniquement pour permettre à Cargo de vérifier la baseline.
Le code temporaire du dry-run n’est pas ajouté aux templates PGR.
### Projet existant
Le chemin d’adoption passe par `230-ADOPTION.md`. Les skeletons et templates servent de checklists de comparaison et ne sont jamais copiés aveuglément.
Le dry-run doit inclure plusieurs décisions et prouver qu’un choix local classé `KEEP-LOCAL` ou `DEFER` reste inchangé.
### Autorité de la toolchain
La syntaxe TOML et les assertions structurelles peuvent être prévalidées avec Python. En revanche, le mode `NEW` complet exige Cargo : une absence de toolchain ne peut pas être convertie en `PASS`.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.4`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.0-alpha.5'
git cat-file -e HEAD:history/0.1.0/alpha.4.md
test -f history/0.1.0/alpha.4.md
test -f deltas/0.1.0/alpha.5.md
test -f docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md
test ! -e history/0.1.0/alpha.5.md
grep -A2 '^## Statut$' history/0.1.0/alpha.4.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 21 -->' docs/000-README.md
grep -Fx '<!-- version: 5 -->' docs/skeletons/000-README.md
grep -Fx '<!-- version: 4 -->' docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
grep -Fx '<!-- version: 6 -->' docs/skeletons/002-RUST_CARGO_WORKSPACE.md
grep -Fx '<!-- version: 4 -->' docs/templates/001-RUST_CARGO_TOOLING.md
grep -Fx '<!-- version: 4 -->' docs/templates/002-CARGO_MANIFESTS.md
grep -Fx '<!-- version: 13 -->' docs/validation/001-VALIDATION_MATRIX.md
grep -Fx '<!-- version: 1 -->' docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md
grep -Fx '<!-- version: 7 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
Contrôle structurel et prévalidation TOML :
```bash
python3 -B - <<'PYGATE'
from pathlib import Path
import re
import tomllib
history = Path("history/0.1.0/alpha.4.md").read_text(encoding="utf-8")
foundation = Path("docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md").read_text(encoding="utf-8")
rust_skeleton = Path("docs/skeletons/002-RUST_CARGO_WORKSPACE.md").read_text(encoding="utf-8")
tooling = Path("docs/templates/001-RUST_CARGO_TOOLING.md").read_text(encoding="utf-8")
manifests = Path("docs/templates/002-CARGO_MANIFESTS.md").read_text(encoding="utf-8")
dryrun = Path("docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md").read_text(encoding="utf-8")
plan = Path("docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md").read_text(encoding="utf-8")
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
assert "../rules/230-ADOPTION.md" in foundation
assert "../rules/230-ADOPTION.md" in rust_skeleton
assert "004-RUST_CARGO_BASELINE_DRY_RUN.md" in rust_skeleton
assert "KEEP-LOCAL" in tooling
assert "ADOPT / KEEP-LOCAL / OVERRIDE / DEFER" in manifests
for phrase in (
"NEW nouveau projet",
"ADOPTION projet existant",
"cargo metadata --format-version 1 --no-deps",
"cargo clippy --workspace --all-targets --all-features -- -D warnings",
"KEEP-LOCAL",
"DEFER",
"ne constitue pas un `PASS` de la toolchain",
):
assert phrase in dryrun, phrase
for path in (
Path("templates/rust-cargo/Cargo.toml"),
Path("templates/rust-cargo/clippy.toml"),
Path("templates/rust-cargo/rustfmt.toml"),
Path("templates/rust-cargo/.cargo/config.toml"),
Path("templates/rust-cargo/crates/project-core-lib/Cargo.toml"),
):
with path.open("rb") as handle:
tomllib.load(handle)
assert "Statut opérateur : **PASS**." in plan
assert "Statut opérateur : **à valider**." in plan
assert "Games et KSP ne sont pas utilisés comme fixtures du dry-run." in plan
assert "- `( ) 0.1.1`" not in roadmap
print("0.1.0 alpha.5 structural/TOML audit: clean (NEW and ADOPTION paths explicit, templates parse, external corpora not required)")
PYGATE
```
Dry-run `NEW` avec la toolchain officielle :
```bash
python3 -B - <<'PYNEW'
from pathlib import Path
import shutil
import subprocess
import tempfile
import tomllib
cargo = shutil.which("cargo")
if cargo is None:
raise SystemExit("BLOCKED: cargo is required for the alpha.5 NEW dry-run")
source = Path("templates/rust-cargo")
with tempfile.TemporaryDirectory(prefix="pgr-alpha5-new-") as temporary:
root = Path(temporary)
(root / ".cargo").mkdir(parents=True)
(root / "crates/pgr-dryrun-core-lib/src").mkdir(parents=True)
shutil.copy2(source / "Cargo.toml", root / "Cargo.toml")
shutil.copy2(source / "clippy.toml", root / "clippy.toml")
shutil.copy2(source / "rustfmt.toml", root / "rustfmt.toml")
shutil.copy2(source / ".cargo/config.toml", root / ".cargo/config.toml")
shutil.copy2(source / "crates/project-core-lib/Cargo.toml", root / "crates/pgr-dryrun-core-lib/Cargo.toml")
workspace = (root / "Cargo.toml").read_text(encoding="utf-8")
workspace = workspace.replace("crates/project-core-lib", "crates/pgr-dryrun-core-lib")
workspace = workspace.replace('version = "0.1.0"', 'version = "9.9.9"')
(root / "Cargo.toml").write_text(workspace, encoding="utf-8")
member = (root / "crates/pgr-dryrun-core-lib/Cargo.toml").read_text(encoding="utf-8")
member = member.replace("project-core-lib", "pgr-dryrun-core-lib")
(root / "crates/pgr-dryrun-core-lib/Cargo.toml").write_text(member, encoding="utf-8")
config = (root / ".cargo/config.toml").read_text(encoding="utf-8")
config = config.replace("project-name", "pgr-alpha5-new")
(root / ".cargo/config.toml").write_text(config, encoding="utf-8")
(root / "crates/pgr-dryrun-core-lib/src/lib.rs").write_text(
"//! Minimal source used only by the PGR alpha.5 dry-run.\n\n"
"/// Returns the dry-run marker.\n"
"#[must_use]\n"
"pub const fn dry_run_marker() -> u32 {\n"
" return 1;\n"
"}\n",
encoding="utf-8",
)
for path in (
root / "Cargo.toml",
root / "clippy.toml",
root / "rustfmt.toml",
root / ".cargo/config.toml",
root / "crates/pgr-dryrun-core-lib/Cargo.toml",
):
with path.open("rb") as handle:
tomllib.load(handle)
text = path.read_text(encoding="utf-8")
assert "project-name" not in text
assert "project-core-lib" not in text
commands = (
[cargo, "metadata", "--format-version", "1", "--no-deps"],
[cargo, "fmt", "--all", "--", "--check"],
[cargo, "check", "--workspace"],
[cargo, "clippy", "--workspace", "--all-targets", "--all-features", "--", "-D", "warnings"],
)
for command in commands:
subprocess.run(command, cwd=root, check=True)
print("0.1.0 alpha.5 NEW dry-run: clean (temporary templates accepted by Cargo/rustfmt/Clippy)")
PYNEW
```
Dry-run `ADOPTION` non destructif :
```bash
python3 -B - <<'PYADOPT'
from pathlib import Path
import hashlib
import shutil
import subprocess
import tempfile
cargo = shutil.which("cargo")
if cargo is None:
raise SystemExit("BLOCKED: cargo is required for the alpha.5 ADOPTION dry-run")
valid_decisions = {"ADOPT", "KEEP-LOCAL", "OVERRIDE", "DEFER"}
with tempfile.TemporaryDirectory(prefix="pgr-alpha5-adoption-") as temporary:
root = Path(temporary)
(root / "crates/legacy-core-lib/src").mkdir(parents=True)
(root / "Cargo.toml").write_text(
'[workspace]\nresolver = "3"\nmembers = ["crates/legacy-core-lib"]\n\n'
'[workspace.package]\nversion = "2.3.4"\nedition = "2024"\npublish = false\n',
encoding="utf-8",
)
(root / "rustfmt.toml").write_text('edition = "2024"\nmax_width = 120\n', encoding="utf-8")
(root / "crates/legacy-core-lib/Cargo.toml").write_text(
'[package]\nname = "legacy-core-lib"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n',
encoding="utf-8",
)
(root / "crates/legacy-core-lib/src/lib.rs").write_text(
"//! Existing synthetic library.\n\n"
"/// Returns the existing marker.\n"
"#[must_use]\n"
"pub const fn existing_marker() -> u32 {\n"
" 7\n"
"}\n",
encoding="utf-8",
)
protected = (root / "Cargo.toml", root / "rustfmt.toml", root / "crates/legacy-core-lib/Cargo.toml")
before = {path: hashlib.sha256(path.read_bytes()).hexdigest() for path in protected}
decisions = {
"510-RUST_CARGO": "ADOPT",
"rustfmt.max_width=120": "KEEP-LOCAL",
"PGR external artifact configuration": "DEFER",
"strict crate-root export audit": "DEFER",
}
assert set(decisions.values()) <= valid_decisions
assert "KEEP-LOCAL" in decisions.values()
assert "DEFER" in decisions.values()
for command in (
[cargo, "metadata", "--format-version", "1", "--no-deps"],
[cargo, "fmt", "--all", "--", "--check"],
[cargo, "check", "--workspace"],
[cargo, "clippy", "--workspace", "--all-targets", "--all-features", "--", "-D", "warnings"],
):
subprocess.run(command, cwd=root, check=True)
after = {path: hashlib.sha256(path.read_bytes()).hexdigest() for path in protected}
assert before == after
assert "max_width = 120" in (root / "rustfmt.toml").read_text(encoding="utf-8")
assert not (root / ".cargo/config.toml").exists()
print("0.1.0 alpha.5 ADOPTION dry-run: clean (local KEEP-LOCAL/DEFER choices preserved, workspace remains valid)")
PYADOPT
```
Puis rejouer les preuves PGR :
```bash
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/000-README.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
docs/skeletons/000-README.md \
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md \
docs/skeletons/002-RUST_CARGO_WORKSPACE.md \
docs/templates/001-RUST_CARGO_TOOLING.md \
docs/templates/002-CARGO_MANIFESTS.md \
docs/validation/001-VALIDATION_MATRIX.md \
docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md \
deltas/0.1.0/alpha.5.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `alpha.5` est exactement :
```text
M VERSION
A deltas/0.1.0/alpha.5.md
M docs/000-README.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
M docs/skeletons/000-README.md
M docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
M docs/skeletons/002-RUST_CARGO_WORKSPACE.md
M docs/templates/001-RUST_CARGO_TOOLING.md
M docs/templates/002-CARGO_MANIFESTS.md
M docs/validation/001-VALIDATION_MATRIX.md
A docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md
```
## Revue opérateur complémentaire
Confirmer que :
- le mode `NEW` n’introduit aucun `src/lib.rs` universel dans PGR ;
- le mode `ADOPTION` ne remplace pas les fichiers existants classés `KEEP-LOCAL` ou `DEFER` ;
- les templates techniques eux-mêmes restent inchangés dans cette tranche ;
- la réussite de la prévalidation Python n’est pas confondue avec la réussite Cargo ;
- Games et KSP ne sont ni modifiés ni nécessaires à la preuve ;
- aucun profil Java, Android, Tauri, Web, WASM ou serveur n’est matérialisé ;
- aucun numéro futur `0.1.x` n’est réservé.
## Transition
### PASS
Produire `history/0.1.0/alpha.5.md`, l’appliquer puis remettre automatiquement les commandes de commit/push.
Passer ensuite à `0.1.0-beta.1` pour la réconciliation finale et la revue d’horizon obligatoire avant RC.
### FAIL / BLOCKED
Consigner le résultat réel dans `history/0.1.0/alpha.5.md`. Un défaut des templates/skeletons reste dans `alpha.5.fix.N` sauf REPLAN. Une toolchain Cargo absente qui empêche les dry-runs requis doit être enregistrée `BLOCKED`, pas transformée en `PASS` par la seule prévalidation Python.

237
deltas/0.1.0/beta.1.md Normal file
View File

@@ -0,0 +1,237 @@
<!-- file: deltas/0.1.0/beta.1.md -->
<!-- version: 1 -->
# Delta 0.1.0-beta.1 — réconciliation finale et revue d'horizon
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-alpha.5`, réalisé après application de `history/0.1.0/alpha.5.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.0-alpha.5
```
Version après application :
```text
0.1.0-beta.1
```
## Objet
Fermer la phase alpha de `0.1.0` en réconciliant la baseline réellement validée et en exécutant la revue d'horizon obligatoire avant RC.
La tranche :
- enregistre le `PASS` de `alpha.5` dans le plan actif ;
- matérialise `003-V0_1_0_HORIZON_REVIEW.md` ;
- engage dans `ROADMAP.md` uniquement les prochaines releases `0.1.x` suffisamment décidées ;
- conserve WASM, serveur Rust et deployment/operations sans réservation prématurée ;
- prépare `007-V0_1_1_START_PROMPT.md` pour la prochaine cible Web, sans l'activer avant publication de `v0.1.0`.
Aucun profil technique, template Rust/Cargo, skeleton ou script d'audit n'est modifié dans `beta.1`.
## Scope
REPLACE :
```text
VERSION
ROADMAP.md
docs/000-README.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
docs/studies/000-README.md
```
ADD :
```text
deltas/0.1.0/beta.1.md
docs/studies/003-V0_1_0_HORIZON_REVIEW.md
prompts/007-V0_1_1_START_PROMPT.md
```
DELETE : aucun.
`README.md`, `RULES.md`, `CHANGELOG.md`, les profils, skeletons, templates techniques et scripts restent inchangés.
## Décision de revue d'horizon
Les releases suivantes sont engagées :
```text
0.1.1 fondation frontend Web
0.1.2 réévaluation Java / Gradle
0.1.3 réévaluation Android
0.1.4 domaine Tauri et levée conditionnelle du DEFER
0.1.5 adoption Games
0.1.6 adoption KSP
0.1.7 audits Rust/Clippy statiques Python-only
```
Cette séquence applique le principe « une release/session par domaine cohérent » et conserve Games avant KSP.
`0.1.4` n'autorise pas par avance le skeleton Tauri : la release doit d'abord vérifier que `0.1.1` a réellement fourni les owners Web nécessaires.
WASM et serveur Rust/Actix ou alternative restent non numérotés. Le futur domaine deployment/operations reste un horizon majeur possible, notamment `0.4.x` ou `0.5.x`, sans réservation précise.
## Prochaine cible
Après stable `v0.1.0` et `publish.* PASS`, la prochaine cible engagée est :
```text
0.1.1 — fondation frontend Web
```
Le prompt `prompts/007-V0_1_1_START_PROMPT.md` demande un audit indépendant de la stable et du corpus Games réellement fourni. Il ne migre pas Games et ne crée ni Tauri, ni WASM, ni serveur Rust.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.5`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.0-beta.1'
git cat-file -e HEAD:history/0.1.0/alpha.5.md
test -f history/0.1.0/alpha.5.md
test -f deltas/0.1.0/beta.1.md
test -f docs/studies/003-V0_1_0_HORIZON_REVIEW.md
test -f prompts/007-V0_1_1_START_PROMPT.md
test ! -e history/0.1.0/beta.1.md
grep -A2 '^## Statut$' history/0.1.0/alpha.5.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 9 -->' ROADMAP.md
grep -Fx '<!-- version: 22 -->' docs/000-README.md
grep -Fx '<!-- version: 8 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
grep -Fx '<!-- version: 3 -->' docs/studies/000-README.md
grep -Fx '<!-- version: 1 -->' docs/studies/003-V0_1_0_HORIZON_REVIEW.md
grep -Fx '<!-- version: 1 -->' prompts/007-V0_1_1_START_PROMPT.md
```
Contrôle structurel de la revue :
```bash
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path("history/0.1.0/alpha.5.md").read_text(encoding="utf-8")
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
plan = Path("docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md").read_text(encoding="utf-8")
study = Path("docs/studies/003-V0_1_0_HORIZON_REVIEW.md").read_text(encoding="utf-8")
prompt = Path("prompts/007-V0_1_1_START_PROMPT.md").read_text(encoding="utf-8")
tauri = Path("docs/studies/002-TAURI_SKELETON_DECISION.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
expected = {
"0.1.1": "fondation frontend Web",
"0.1.2": "Java/Maven/Gradle",
"0.1.3": "Android",
"0.1.4": "Tauri",
"0.1.5": "sasedev-games",
"0.1.6": "khadhroony-solana-project",
"0.1.7": "Rust/Clippy",
}
for version, phrase in expected.items():
assert f"- `( ) {version}`" in roadmap, version
assert phrase in roadmap, phrase
assert "- `( ) 0.1.8`" not in roadmap
assert "WASM" in roadmap
assert "serveur Web Rust / Actix Web ou alternative" in roadmap
assert "deployment & operations" in roadmap
assert "aucun numéro précis n'est réservé" in roadmap
for phrase in (
"`0.1.1` — fondation frontend Web",
"`0.1.5` — adoption de Games",
"`0.1.6` — adoption de KSP",
"`0.1.7` — audits Rust/Clippy statiques Python",
"Candidats laissés sans numéro",
"Déploiement et exploitation",
"La décision `DEFER` de `002-TAURI_SKELETON_DECISION.md` reste vraie pendant `0.1.0`.",
):
assert phrase in study, phrase
assert "Statut opérateur : **PASS**." in plan
assert "Statut opérateur : **à valider**." in plan
assert "0.1.7 audits Rust/Clippy statiques Python-only" in plan
assert "WASM, serveur Rust et deployment restent non numérotés." in plan
for phrase in (
"# Prompt de démarrage 0.1.1 — fondation frontend Web",
"games-v0.3.6.zip",
"TypeScript",
"Vite",
"Sass/CSS",
"Le skeleton Tauri reste `DEFER` pendant cette release.",
"0.1.2",
"0.1.3",
):
assert phrase in prompt, phrase
assert "DEFER" in tauri
print("0.1.0 beta.1 horizon review audit: clean (0.1.1..0.1.7 engaged, Tauri conditional, deferred domains remain unnumbered)")
PYGATE
```
Puis rejouer les preuves PGR :
```bash
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION ROADMAP.md docs/000-README.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
docs/studies/000-README.md \
docs/studies/003-V0_1_0_HORIZON_REVIEW.md \
prompts/007-V0_1_1_START_PROMPT.md \
deltas/0.1.0/beta.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `beta.1` est exactement :
```text
M ROADMAP.md
M VERSION
A deltas/0.1.0/beta.1.md
M docs/000-README.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
M docs/studies/000-README.md
A docs/studies/003-V0_1_0_HORIZON_REVIEW.md
A prompts/007-V0_1_1_START_PROMPT.md
```
## Revue opérateur complémentaire
Confirmer que :
- la roadmap n'engage pas un catalogue exhaustif de technologies ;
- chaque release `0.1.1` à `0.1.7` possède un domaine cohérent ;
- Games reste avant KSP ;
- le skeleton Tauri n'est pas présenté comme déjà autorisé ;
- WASM et serveur Rust restent réellement sans numéro ;
- deployment/operations n'est pas artificiellement fixé à `0.4.0` ou `0.5.0` ;
- `007-V0_1_1_START_PROMPT.md` ne doit être exécuté qu'après `v0.1.0` publié et vérifié ;
- aucun profil, skeleton technique ou script d'audit n'est ajouté/modifié dans cette tranche.
## Transition
PASS : produire `history/0.1.0/beta.1.md`, fermer la tranche avec le handoff opérateur automatique, puis préparer `0.1.0-rc.1`.
FAIL : conserver le résultat réel dans le history et corriger par `beta.1.fix.N` ou REPLAN si la revue macro elle-même doit changer.

333
deltas/0.1.0/rc.1.md Normal file
View File

@@ -0,0 +1,333 @@
<!-- file: deltas/0.1.0/rc.1.md -->
<!-- version: 1 -->
# Delta 0.1.0-rc.1 — gel du scope et gate de release candidate
## Baseline et version
Baseline attendue : commit opérateur de `0.1.0-beta.1`, réalisé après application de `history/0.1.0/beta.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.0-beta.1
```
Version après application :
```text
0.1.0-rc.1
```
## Objet et gel
La RC gèle le scope fonctionnel de `0.1.0` sur :
- la fondation de gouvernance et les skeleton specifications réutilisables ;
- le socle Rust/Cargo, ses cinq templates techniques et les dry-runs `NEW` / `ADOPTION` ;
- le contrat d'adoption de projets existants `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` ;
- la convention de clôture stable `rel.N` sans zéro de padding et l'identité du premier commit stable `X.Y.Z` ;
- le handoff automatique des commandes opérateur, du commit/push au tag et à la preuve `publish.*` ;
- la revue d'horizon validée et le prompt `007` vers `0.1.1`.
Le changelog reçoit une entrée candidate `0.1.0` orientée utilisateurs. `ROADMAP.md`, `RULES.md`, les owners, profils, templates techniques, skeletons et scripts d'audit sont vérifiés mais non modifiés.
Aucun scope Web, Java/Gradle, Android, Tauri, WASM, serveur Rust, Games/KSP ou deployment/operations n'entre fonctionnellement dans cette RC au-delà des décisions de trajectoire déjà validées.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
ADD :
```text
deltas/0.1.0/rc.1.md
```
DELETE : aucun.
Le history `beta.1` est livré séparément et MUST être appliqué/committé avant ce delta.
## Gate opérateur de release candidate
Après application du history `PASS` de `beta.1`, commit/push de `beta.1`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.0-rc.1'
git cat-file -e HEAD:history/0.1.0/beta.1.md
test -f history/0.1.0/beta.1.md
test -f deltas/0.1.0/rc.1.md
test -f prompts/007-V0_1_1_START_PROMPT.md
test ! -e history/0.1.0/rc.1.md
grep -A2 '^## Statut$' history/0.1.0/beta.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 10 -->' CHANGELOG.md
grep -Fx '## 0.1.0 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 9 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
grep -Fx '<!-- version: 9 -->' ROADMAP.md
grep -Fx '<!-- version: 1 -->' prompts/007-V0_1_1_START_PROMPT.md
```
Contrôle d'intégration de la RC :
```bash
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
"alpha.1.md": "PASS",
"alpha.2.md": "FAIL",
"alpha.2.fix.1.md": "PASS",
"alpha.3.md": "FAIL",
"alpha.3.fix.1.md": "PASS",
"alpha.4.md": "PASS",
"alpha.5.md": "PASS",
"beta.1.md": "PASS",
}
histories = {path.name for path in Path("history/0.1.0").glob("*.md")}
assert histories == set(expected), histories
for name, status in expected.items():
text = Path("history/0.1.0", name).read_text(encoding="utf-8")
assert re.search(rf"## Statut\s+{status}\s", text), (name, status)
deltas = {path.name for path in Path("deltas/0.1.0").glob("*.md")}
assert deltas == set(expected) | {"rc.1.md"}, deltas
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
assert "## 0.1.0 (candidate)" in changelog
section = changelog.split("## 0.1.0 (candidate)", 1)[1].split("## 0.0.5", 1)[0]
for phrase in (
"première baseline PGR réellement réutilisable",
"ADOPT / KEEP-LOCAL / OVERRIDE / DEFER",
"rel.N",
"publish.*",
"frontend Web",
):
assert phrase in section, phrase
for forbidden in ("alpha.2", "alpha.3", "beta.1", "rc.1"):
assert forbidden not in section, forbidden
workflow = Path("docs/rules/210-WORKFLOW.md").read_text(encoding="utf-8")
for phrase in (
"La famille `rel.N` utilise la représentation sans zéro de padding",
"première de ces tranches qui obtient réellement `PASS` est incluse dans le commit stable `X.Y.Z`",
"Le rapport `publish.*` est produit seulement à partir des artefacts et preuves réellement disponibles après publication.",
"../templates/006-OPERATOR_COMMAND_HANDOFF.md",
):
assert phrase in workflow, phrase
adoption = Path("docs/rules/230-ADOPTION.md").read_text(encoding="utf-8")
for phrase in ("ADOPT", "KEEP-LOCAL", "OVERRIDE", "DEFER", "Préservation de l’historique"):
assert phrase in adoption, phrase
rust_dryrun = Path("docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md").read_text(encoding="utf-8")
assert "NEW nouveau projet" in rust_dryrun
assert "ADOPTION projet existant" in rust_dryrun
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
for version in ("0.1.1", "0.1.2", "0.1.3", "0.1.4", "0.1.5", "0.1.6", "0.1.7"):
assert f"- `( ) {version}`" in roadmap, version
assert "- `( ) 0.1.8`" not in roadmap
assert "WASM" in roadmap
assert "serveur Web Rust / Actix Web ou alternative" in roadmap
assert "deployment & operations" in roadmap
prompt = Path("prompts/007-V0_1_1_START_PROMPT.md").read_text(encoding="utf-8")
for phrase in (
"archive source téléchargée depuis le tag Gitea `v0.1.0`",
"pgr-0.1.0-publish.001-report.md",
"0.1.1-alpha.1",
"games-v0.3.6.zip",
"TypeScript",
"Vite",
"Sass/CSS",
"Le skeleton Tauri reste `DEFER` pendant cette release.",
):
assert phrase in prompt, phrase
plan = Path("docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md").read_text(encoding="utf-8")
assert "### beta.1 — réconciliation finale et revue d'horizon\n\nStatut opérateur : **PASS**." in plan
assert "### rc.1 — release candidate\n\nStatut opérateur : **à valider**." in plan
assert "État : **validée `PASS` par la gate opérateur de `beta.1`**." in plan
print("0.1.0 rc.1 integration audit: clean (8 prior histories, frozen reusable baseline, candidate changelog, horizon and prompt 007 verified)")
PYGATE
```
Rejouer également les deux chemins Rust/Cargo avec la toolchain réelle :
```bash
python3 -B - <<'PYRUST'
from pathlib import Path
import hashlib
import shutil
import subprocess
import tempfile
import tomllib
cargo = shutil.which("cargo")
if cargo is None:
raise SystemExit("BLOCKED: cargo is required for the 0.1.0 RC Rust/Cargo release gate")
commands = (
[cargo, "metadata", "--format-version", "1", "--no-deps"],
[cargo, "fmt", "--all", "--", "--check"],
[cargo, "check", "--workspace"],
[cargo, "clippy", "--workspace", "--all-targets", "--all-features", "--", "-D", "warnings"],
)
source = Path("templates/rust-cargo")
with tempfile.TemporaryDirectory(prefix="pgr-rc1-new-") as temporary:
root = Path(temporary)
(root / ".cargo").mkdir(parents=True)
(root / "crates/pgr-rc-core-lib/src").mkdir(parents=True)
shutil.copy2(source / "Cargo.toml", root / "Cargo.toml")
shutil.copy2(source / "clippy.toml", root / "clippy.toml")
shutil.copy2(source / "rustfmt.toml", root / "rustfmt.toml")
shutil.copy2(source / ".cargo/config.toml", root / ".cargo/config.toml")
shutil.copy2(source / "crates/project-core-lib/Cargo.toml", root / "crates/pgr-rc-core-lib/Cargo.toml")
workspace = (root / "Cargo.toml").read_text(encoding="utf-8")
workspace = workspace.replace("crates/project-core-lib", "crates/pgr-rc-core-lib")
workspace = workspace.replace('version = "0.1.0"', 'version = "9.9.9"')
(root / "Cargo.toml").write_text(workspace, encoding="utf-8")
member = (root / "crates/pgr-rc-core-lib/Cargo.toml").read_text(encoding="utf-8")
member = member.replace("project-core-lib", "pgr-rc-core-lib")
(root / "crates/pgr-rc-core-lib/Cargo.toml").write_text(member, encoding="utf-8")
config = (root / ".cargo/config.toml").read_text(encoding="utf-8")
config = config.replace("project-name", "pgr-rc1-new")
(root / ".cargo/config.toml").write_text(config, encoding="utf-8")
(root / "crates/pgr-rc-core-lib/src/lib.rs").write_text(
"//! Minimal source used only by the PGR RC dry-run.\n\n"
"/// Returns the RC marker.\n"
"#[must_use]\n"
"pub const fn rc_marker() -> u32 {\n"
" return 1;\n"
"}\n",
encoding="utf-8",
)
for path in (
root / "Cargo.toml",
root / "clippy.toml",
root / "rustfmt.toml",
root / ".cargo/config.toml",
root / "crates/pgr-rc-core-lib/Cargo.toml",
):
with path.open("rb") as handle:
tomllib.load(handle)
text = path.read_text(encoding="utf-8")
assert "project-name" not in text
assert "project-core-lib" not in text
for command in commands:
subprocess.run(command, cwd=root, check=True)
with tempfile.TemporaryDirectory(prefix="pgr-rc1-adoption-") as temporary:
root = Path(temporary)
(root / "crates/legacy-core-lib/src").mkdir(parents=True)
(root / "Cargo.toml").write_text(
'[workspace]\nresolver = "3"\nmembers = ["crates/legacy-core-lib"]\n\n'
'[workspace.package]\nversion = "2.3.4"\nedition = "2024"\npublish = false\n',
encoding="utf-8",
)
(root / "rustfmt.toml").write_text('edition = "2024"\nmax_width = 120\n', encoding="utf-8")
(root / "crates/legacy-core-lib/Cargo.toml").write_text(
'[package]\nname = "legacy-core-lib"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n',
encoding="utf-8",
)
(root / "crates/legacy-core-lib/src/lib.rs").write_text(
"//! Existing synthetic library.\n\n"
"/// Returns the existing marker.\n"
"#[must_use]\n"
"pub const fn existing_marker() -> u32 {\n"
" 7\n"
"}\n",
encoding="utf-8",
)
protected = (root / "Cargo.toml", root / "rustfmt.toml", root / "crates/legacy-core-lib/Cargo.toml")
before = {path: hashlib.sha256(path.read_bytes()).hexdigest() for path in protected}
decisions = {
"510-RUST_CARGO": "ADOPT",
"rustfmt.max_width=120": "KEEP-LOCAL",
"PGR external artifact configuration": "DEFER",
"strict crate-root export audit": "DEFER",
}
assert set(decisions.values()) <= {"ADOPT", "KEEP-LOCAL", "OVERRIDE", "DEFER"}
for command in commands:
subprocess.run(command, cwd=root, check=True)
after = {path: hashlib.sha256(path.read_bytes()).hexdigest() for path in protected}
assert before == after
assert "max_width = 120" in (root / "rustfmt.toml").read_text(encoding="utf-8")
print("0.1.0 rc.1 Rust/Cargo release dry-runs: clean (NEW and ADOPTION accepted by Cargo/rustfmt/Clippy)")
PYRUST
```
Puis la suite PGR complète :
```bash
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION CHANGELOG.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
deltas/0.1.0/rc.1.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M VERSION
A deltas/0.1.0/rc.1.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que :
- le changelog décrit les capacités de `0.1.0` et non ses tranches internes ;
- aucune règle/profil/template/skeleton/audit fonctionnel nouveau n'entre dans la RC ;
- `ROADMAP.md` conserve `0.1.0` en cours jusqu'à la promotion stable ;
- `0.1.1..0.1.7` restent la trajectoire engagée et les domaines non numérotés restent réellement différés ;
- le prompt `007` exige bien l'archive taggée `v0.1.0` et le rapport `publish.001` seulement lorsqu'il existe réellement avec statut `PASS` ;
- la RC n'est ni le commit stable `0.1.0`, ni le tag `v0.1.0`, ni la vérification post-tag.
## Transition
### PASS
Produire séparément `history/0.1.0/rc.1.md`, l'appliquer puis committer/pousser `0.1.0-rc.1` avant le delta stable `rel.1`.
### FAIL
Consigner l'échec réel dans `history/0.1.0/rc.1.md` puis corriger uniquement le scope gelé dans `rc.1.fix.1`, sauf REPLAN si la candidate révèle un défaut fonctionnel plus large.

202
deltas/0.1.0/rel.1.md Normal file
View File

@@ -0,0 +1,202 @@
<!-- file: deltas/0.1.0/rel.1.md -->
<!-- version: 1 -->
# Delta 0.1.0 rel.1 — promotion stable pré-tag
## Baseline et version
Baseline : `0.1.0-rc.1`, avec `history/0.1.0/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.1.0-rc.1
```
Version après application :
```text
0.1.0
```
`rel.1` identifie la clôture opérationnelle ; il ne fait pas partie de la version SemVer du produit.
## Objet
Promouvoir mécaniquement la RC validée vers la stable `0.1.0` sans rouvrir le scope fonctionnel.
La tranche finalise uniquement la présentation et les métadonnées de release : version stable, roadmap terminée, changelog sans marqueur `candidate`, README/index en état stable et plan `006` historique. Aucun owner, profil, template, skeleton, script d'audit ou contrat technique n'est modifié.
La validation de cette tranche est **pré-tag**. Le tag `v0.1.0`, son archive source Gitea et le rapport `pgr-0.1.0-publish.001-report.md` ne sont pas déclarés existants par ce delta. Ils suivent uniquement un history `rel.1` `PASS`, le commit stable `0.1.0` et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
ADD :
```text
deltas/0.1.0/rel.1.md
```
DELETE : aucun.
Le history `rc.1` est livré séparément. Le history `rel.1` sera produit uniquement après la gate opérateur.
## Validation opérateur pré-tag
Après application sur le commit contenant `history/0.1.0/rc.1.md` :
```bash
test "$(cat VERSION)" = '0.1.0'
git cat-file -e HEAD:history/0.1.0/rc.1.md
test -f history/0.1.0/rc.1.md
test -f deltas/0.1.0/rel.1.md
test -f prompts/007-V0_1_1_START_PROMPT.md
test ! -e history/0.1.0/rel.1.md
grep -A2 '^## Statut$' history/0.1.0/rc.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 16 -->' README.md
grep -Fx '<!-- version: 10 -->' ROADMAP.md
grep -Fx '<!-- version: 11 -->' CHANGELOG.md
grep -Fx '<!-- version: 23 -->' docs/000-README.md
grep -Fx '<!-- version: 10 -->' docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
grep -F -- '- `(x) 0.1.0`' ROADMAP.md
grep -Fx '## 0.1.0' CHANGELOG.md
grep -F 'première baseline réutilisable stable' README.md
grep -F 'plan historique de la stable `0.1.0`' docs/000-README.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
"alpha.1.md": "PASS",
"alpha.2.md": "FAIL",
"alpha.2.fix.1.md": "PASS",
"alpha.3.md": "FAIL",
"alpha.3.fix.1.md": "PASS",
"alpha.4.md": "PASS",
"alpha.5.md": "PASS",
"beta.1.md": "PASS",
"rc.1.md": "PASS",
}
for name, status in expected.items():
delta = Path("deltas/0.1.0", name)
history = Path("history/0.1.0", name)
assert delta.is_file(), name
assert history.is_file(), name
text = history.read_text(encoding="utf-8")
assert re.search(rf"## Statut\s+{status}\s", text), (name, status)
pending = {path.name for path in Path("deltas/0.1.0").glob("*.md")} - {
path.name for path in Path("history/0.1.0").glob("*.md")
}
assert pending == {"rel.1.md"}, pending
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "- `(x) 0.1.0`" in roadmap
for version in ("0.1.1", "0.1.2", "0.1.3", "0.1.4", "0.1.5", "0.1.6", "0.1.7"):
assert f"- `( ) {version}`" in roadmap, version
assert "- `( ) 0.1.8`" not in roadmap
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
assert "## 0.1.0" in changelog.splitlines()
assert "## 0.1.0 (candidate)" not in changelog
assert "produit produit" not in changelog
readme = Path("README.md").read_text(encoding="utf-8")
assert "première baseline réutilisable stable" in readme
assert "plan historique de la première baseline réutilisable `0.1.0`" in readme
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "plan historique de la stable `0.1.0`" in index
plan = Path("docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md").read_text(encoding="utf-8")
assert "Statut opérateur : **PASS**." in plan
assert "history/0.1.0/rel.1.md" in plan
assert "pgr-0.1.0-publish.001-report.md" in plan
prompt = Path("prompts/007-V0_1_1_START_PROMPT.md").read_text(encoding="utf-8")
assert "tag Gitea `v0.1.0`" in prompt
assert "pgr-0.1.0-publish.001-report.md" in prompt
assert "0.1.1-alpha.1" in prompt
workflow = Path("docs/rules/210-WORKFLOW.md").read_text(encoding="utf-8")
assert "history rel.1 FAIL / PARTIAL / BLOCKED" in workflow
assert "premier history rel.N[/fix.M] PASS qui établit réellement la stable" in workflow
assert "commit X.Y.Z" in workflow
print("0.1.0 rel.1 stable gate audit: clean (9 prior histories, rel.1 pending, stable presentation and post-tag handoff coherent)")
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION README.md ROADMAP.md CHANGELOG.md docs/000-README.md \
docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md \
deltas/0.1.0/rel.1.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M README.md
M ROADMAP.md
M VERSION
A deltas/0.1.0/rel.1.md
M docs/000-README.md
M docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md
```
Les deux dry-runs Rust/Cargo ont été reconfirmés en `rc.1` avec Cargo/rustfmt/Clippy et aucun artefact Rust/Cargo n'est modifié par `rel.1`; ils ne sont donc pas rejoués une troisième fois dans la promotion mécanique. La suite Python PGR et les audits documentaires restent exécutés dans la gate stable.
## Revue opérateur complémentaire
Confirmer que :
- le scope fonctionnel de `rc.1` ne change pas ;
- `0.1.0` est présenté comme stable de manière cohérente dans VERSION/README/ROADMAP/CHANGELOG/index/plan ;
- les `FAIL` historiques `alpha.2` et `alpha.3` restent conservés avec leurs fixes `PASS` ;
- la roadmap engagée `0.1.1` à `0.1.7` reste intacte ;
- WASM, serveur Rust et deployment/operations restent non numérotés ;
- le prompt `007` reste conditionnel à une vraie publication de `v0.1.0` et à un rapport post-tag `PASS` réel ;
- aucune preuve post-tag n'est anticipée.
## Transition
### PASS
Produire séparément `history/0.1.0/rel.1.md`, l'appliquer, puis créer le commit stable sous le message exact :
```text
0.1.0
```
Après push de la branche canonique, créer et publier le tag annoté `v0.1.0`. Vérifier localement et à distance l'objet tag et son commit déréférencé. Télécharger ensuite l'archive source depuis le tag Gitea et la fournir au générateur avec les sorties Git de publication afin de produire `pgr-0.1.0-publish.001-report.md` à partir de preuves réelles.
Le prompt `007-V0_1_1_START_PROMPT.md` n'est remis comme reprise effective de `0.1.1` qu'après un rapport post-tag `PASS`.
### FAIL
Consigner le diagnostic réel dans `history/0.1.0/rel.1.md`, ne pas créer le tag et corriger uniquement la fermeture dans `rel.1.fix.1` avant toute publication.

219
deltas/0.1.1/alpha.1.md Normal file
View File

@@ -0,0 +1,219 @@
<!-- file: deltas/0.1.1/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.1 — audit de la stable et cadrage frontend Web
## Baseline et sources
Baseline PGR autoritaire : `pgr-v0.1.0.zip`, archive source téléchargée depuis le tag Gitea `v0.1.0`, accompagnée du rapport externe `pgr-0.1.0-publish.001-report.md` avec statut `PASS`.
SHA-256 vérifiés :
```text
pgr-v0.1.0.zip bc8f3a8117d04afc1280344eceaaac8c6a4724ca94c285a6234fe42c1023b2be
pgr-0.1.0-publish.001-report.md a64dc4a5a81e1776b641894d8493eec3ef315932fffb2881e52ff4147eb8b6a5
games-v0.3.6(1).zip ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
khadhroony-solana-project-v0.3.17.zip 2a9cabcb9f147a348dcf8d24df8bc6c5029089b6d49feb17bd4a42b4293c329a
```
Le fichier Games fourni sous le nom local `games-v0.3.6(1).zip` a exactement le SHA-256 de la baseline canonique `games-v0.3.6.zip` attendue par le prompt `007`.
KSP `0.3.17` est uniquement un corpus secondaire de corroboration pour éviter de confondre règles frontend génériques et choix d'un host particulier. Il n'est ni requis par la baseline `0.1.1`, ni modifié, ni adopté dans cette tranche.
Version avant application :
```text
0.1.0
```
Version après application :
```text
0.1.1-alpha.1
```
## Objet
Exécuter `prompts/007-V0_1_1_START_PROMPT.md` : vérifier intégralement la stable `v0.1.0`, ses règles, profils, templates, skeletons, audits, décisions différées et chaîne de gouvernance, puis auditer le corpus Games réellement fourni et créer le plan `0.1.1` avant toute normalisation Web importante.
`alpha.1` reste un gate de cadrage. Aucun owner Web, template frontend, skeleton, audit ou règle normative n'est encore créé.
## Résultat de l'audit d'intake
La stable PGR et son rapport post-tag concordent : archive SHA-256 attendue, CRC propre, racine unique `pgr/`, `221` fichiers, `33` répertoires, aucun symlink et absence normale de `.git`.
La suite de tests donne `48/48 PASS`. Les audits Markdown sont propres : `198` fichiers pour les headers, `8` tables sur `198` fichiers et `193` liens locaux sur `198` fichiers. Les cinq templates TOML Rust/Cargo sont parsables et aucun output de build courant n'est embarqué.
Les `72` couples delta/history de `0.0.1` à `0.1.0` sont complets. `0.1.0` conserve explicitement `alpha.2 FAIL`, `alpha.2.fix.1 PASS`, `alpha.3 FAIL`, `alpha.3.fix.1 PASS`, puis `rel.1 PASS`. Le commit stable et le tag suivent la nouvelle convention sans réécrire les historiques antérieurs.
La stable possède déjà les profils `510` Rust/Cargo, `520` Java/Maven/Gradle, `610` Android et `710` Tauri. Le skeleton Tauri reste correctement `DEFER`; la décision existante identifie précisément TypeScript, Vite, Sass/CSS, outputs et validation frontend indépendante comme responsabilités encore manquantes.
Le corpus Games fourni est sain et correspond au hash canonique attendu. Il contient trois packages frontend réels : deux hosts Web directs et un host Tauri. Tous exercent TypeScript, Vite, `frontend/` et des sorties/cache externes à l'arborescence source. Sass/Bootstrap n'est exercé que là où la chaîne de styles le requiert. Les lockfiles Node sont ignorés par Games, mais cette politique reste locale et n'est pas généralisée par `alpha.1`.
KSP `0.3.17` contient six applications Tauri avec frontend Vite/TypeScript et corrobore le caractère transversal de ces owners, sans devenir un corpus d'adoption dans cette release.
Le plan conserve explicitement WASM, serveur Rust/Actix et deployment hors scope, et ne lève pas le `DEFER` Tauri.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
```
ADD :
```text
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
deltas/0.1.1/alpha.1.md
```
DELETE : aucun.
`RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, les règles, profils, templates, skeletons, scripts, studies, validations et histories existants restent inchangés dans `alpha.1`.
Aucun `history/0.1.1/alpha.1.md` n'est anticipé avant la gate opérateur.
## Validation opérateur
Après application sur la stable `0.1.0`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.1'
test -f docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
test -f deltas/0.1.1/alpha.1.md
test ! -e history/0.1.1/alpha.1.md
grep -Fx '<!-- version: 17 -->' README.md
grep -Fx '<!-- version: 24 -->' docs/000-README.md
grep -F '007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md' README.md docs/000-README.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PY'
from pathlib import Path
import re
expected = {
'0.0.1': 12,
'0.0.2': 12,
'0.0.3': 10,
'0.0.4': 9,
'0.0.5': 19,
'0.1.0': 10,
}
for release, count in expected.items():
deltas = {path.name for path in Path('deltas', release).glob('*.md')}
histories = {path.name for path in Path('history', release).glob('*.md')}
assert len(deltas) == count, (release, len(deltas))
assert deltas == histories, (release, sorted(deltas ^ histories))
statuses = {}
for path in Path('history/0.1.0').glob('*.md'):
text = path.read_text(encoding='utf-8')
match = re.search(r'## Statut\s+(PASS|FAIL|PARTIAL|BLOCKED)\s', text)
assert match is not None, path
statuses[path.name] = match.group(1)
assert statuses['alpha.2.md'] == 'FAIL'
assert statuses['alpha.2.fix.1.md'] == 'PASS'
assert statuses['alpha.3.md'] == 'FAIL'
assert statuses['alpha.3.fix.1.md'] == 'PASS'
assert statuses['rel.1.md'] == 'PASS'
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for release in range(1, 8):
assert f'- `( ) 0.1.{release}`' in roadmap, release
assert '0.1.8' not in roadmap
assert 'skeleton Tauri avant owners Web suffisants' in roadmap
assert 'WASM' in roadmap
assert 'serveur Web Rust / Actix Web ou alternative' in roadmap
assert 'deployment & operations' in roadmap
prompt = Path('prompts/007-V0_1_1_START_PROMPT.md').read_text(encoding='utf-8')
for phrase in (
'Version cible : `0.1.1`',
'Première tranche attendue : `0.1.1-alpha.1`',
'ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8',
'TypeScript et configuration applicable',
'Vite, dev server et contrat de build outputs',
'package manager, manifest et lockfile sans imposer arbitrairement npm',
'Le skeleton Tauri reste `DEFER` pendant cette release.',
):
assert phrase in prompt, phrase
study = Path('docs/studies/002-TAURI_SKELETON_DECISION.md').read_text(encoding='utf-8')
for phrase in (
'DEFER',
'TypeScript et conventions Web contrôlées',
'Vite et ownership des commandes/dev server/build outputs',
'Sass/CSS et statut des artefacts générés',
'validation frontend indépendante de la validation Tauri',
):
assert phrase in study, phrase
plan = Path('docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Frontières d\'ownership à décider',
'alpha.2 — frontières d\'ownership Web',
'alpha.3 — TypeScript et écosystème de package',
'alpha.4 — Vite, dev server et outputs',
'alpha.5 — CSS/Sass et validation frontend',
'beta.1 — réconciliation et preuve de préparation Tauri',
'La réussite de `0.1.1` devra produire les owners nécessaires à ce réexamen, mais ne lèvera pas automatiquement le `DEFER`.',
'WASM, sans numéro réservé',
'serveur Web Rust / Actix Web ou alternative',
):
assert phrase in plan, phrase
print('0.1.1 alpha.1 structural audit: clean (72 prior pairs, Web scope bounded, Tauri DEFER preserved)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
deltas/0.1.1/alpha.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M README.md
M VERSION
A deltas/0.1.1/alpha.1.md
M docs/000-README.md
A docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
La revue opérateur doit également confirmer que :
- le plan n'impose pas npm, Sass ou Bootstrap comme obligation frontend universelle ;
- la politique Games sur les lockfiles reste une observation locale, pas une règle PGR acquise ;
- les numéros/frontières exacts des futurs owners Web restent à décider en `alpha.2` ;
- aucun profil WASM ou serveur Rust n'est créé par proximité ;
- aucun skeleton Tauri n'est créé et son `DEFER` n'est pas levé ;
- Games et KSP restent des corpus externes non modifiés ;
- aucun nouveau numéro de release au-delà de `0.1.7` n'est réservé.
## Transition
### PASS
Produire `history/0.1.1/alpha.1.md` à partir des résultats réellement observés. Dans la même réponse, si aucune décision nouvelle n'est ouverte, préparer séparément le delta `0.1.1-alpha.2` consacré aux frontières d'ownership Web et à la classification `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` des choix Games pertinents.
Après remise du history, fournir automatiquement le bloc Git exact de fermeture conformément à `docs/templates/006-OPERATOR_COMMAND_HANDOFF.md`, puis indiquer l'application du delta suivant seulement après succès du commit/push.
### FAIL
Consigner le résultat réel dans le history, puis ouvrir `0.1.1-alpha.1.fix.1` ou un REPLAN selon la cause. Un fix de `alpha.1` doit rester limité au cadrage et ne doit pas absorber les décisions normatives prévues pour `alpha.2`.

View File

@@ -0,0 +1,204 @@
<!-- file: deltas/0.1.1/alpha.2.fix.1.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.2.fix.1 — correction de la gate d'ownership Web
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.2`, réalisé après application de `history/0.1.1/alpha.2.md` avec statut `FAIL`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.2
```
Version après application :
```text
0.1.1-alpha.2.fix.1
```
## Objet
Corriger uniquement la syntaxe défectueuse de la gate opérateur de `alpha.2`.
Les nouveaux owners Web et tous les documents normatifs livrés par `alpha.2` restent inchangés. Le delta historique `deltas/0.1.1/alpha.2.md` reste également inchangé.
Le défaut observé était un littéral Python entouré de quotes simples alors que son texte contenait l'apostrophe de `s'applique` :
```python
'Le profil s'applique uniquement lorsqu'un projet utilise réellement Vite.'
```
Le fix utilise des littéraux syntaxiquement sûrs dans la nouvelle gate sans modifier les assertions sémantiques.
## Scope
REPLACE :
```text
VERSION
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
ADD :
```text
deltas/0.1.1/alpha.2.fix.1.md
```
DELETE : aucun.
Aucun profil, règle normative, template, skeleton, script d'audit ou test n'est modifié par ce correctif.
## Validation opérateur
Après application du history `FAIL`, commit/push de `alpha.2`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.2.fix.1'
git cat-file -e HEAD:history/0.1.1/alpha.2.md
test -f history/0.1.1/alpha.2.md
test -f deltas/0.1.1/alpha.2.md
test -f deltas/0.1.1/alpha.2.fix.1.md
test ! -e history/0.1.1/alpha.2.fix.1.md
grep -A2 '^## Statut$' history/0.1.1/alpha.2.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 13 -->' RULES.md
grep -Fx '<!-- version: 25 -->' docs/000-README.md
grep -Fx '<!-- version: 6 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 3 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 15 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 6 -->' docs/rules/710-TAURI.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path('history/0.1.1/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
expected = {
'530-TYPESCRIPT.md': (
'TypeScript **SHOULD** être préféré',
'TS-RS',
'ni Vite',
),
'540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md': (
'MUST NOT imposer npm',
'Lockfile',
'alpha.3',
),
'550-VITE.md': (
'Vite **SHOULD** être le build tool/dev server privilégié',
"Le profil s'applique uniquement lorsqu'un projet utilise réellement Vite.",
'alpha.4',
),
'560-CSS_SASS.md': (
'Sass **SHOULD** être préféré',
'Bootstrap constitue un exemple concret',
'`@use` / `@forward`',
'`@import` Sass est déprécié',
'alpha.5',
),
}
for name, phrases in expected.items():
profile = Path('docs/rules', name).read_text(encoding='utf-8')
for phrase in phrases:
assert phrase in profile, (name, phrase)
rules = Path('RULES.md').read_text(encoding='utf-8')
rules_index = Path('docs/rules/000-README.md').read_text(encoding='utf-8')
architecture = Path('docs/architecture/003-RULE_PROFILE_MODEL.md').read_text(encoding='utf-8')
tauri = Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8')
plan = Path('docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md').read_text(encoding='utf-8')
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for owner in ('530-TYPESCRIPT.md', '540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md', '550-VITE.md', '560-CSS_SASS.md'):
assert owner in rules
assert owner in rules_index
for phrase in (
'530 — TypeScript',
'540 — JavaScript package ecosystem',
'550 — Vite',
'560 — CSS / Sass',
"Un frontend minimal peut n'en sélectionner qu'une partie.",
):
assert phrase in architecture, phrase
for phrase in (
'TypeScript et Vite sont fortement recommandés mais restent des `SHOULD`',
'Sass est également fortement recommandé',
'profils `530`, `550` et `560`',
):
assert phrase in tauri, phrase
for phrase in (
'Décisions de revue après `alpha.1`',
'**TypeScript** : fortement recommandé',
'**Vite** : fortement recommandé',
'**Sass** : fortement recommandé',
'`@use` / `@forward`',
'| TypeScript pour les frontends durables | `ADOPT`',
'| npm comme package manager concret | `KEEP-LOCAL`',
'| commandes/génération WASM dans les scripts | `DEFER`',
'Statut opérateur : **FAIL**.',
"### alpha.2.fix.1 — correction de la gate d'ownership Web",
):
assert phrase in plan, phrase
assert '0.1.8' not in roadmap
assert 'skeleton Tauri avant owners Web suffisants' in roadmap
print('0.1.1 alpha.2.fix.1 ownership gate: clean (alpha.2 FAIL preserved, 530/540/550/560 reconfirmed, Python literals safe)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
deltas/0.1.1/alpha.2.fix.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.1.1/alpha.2.fix.1.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que :
- le `FAIL` de `alpha.2` est conservé historiquement ;
- `deltas/0.1.1/alpha.2.md` n'est pas réécrit ;
- `RULES.md`, `docs/000-README.md`, `docs/architecture/003-RULE_PROFILE_MODEL.md`, `docs/rules/000-README.md` et `docs/rules/710-TAURI.md` ne sont pas modifiés par le fix ;
- les profils `530-TYPESCRIPT.md`, `540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`, `550-VITE.md` et `560-CSS_SASS.md` ne sont pas modifiés par le fix ;
- aucun contenu prévu pour `alpha.3` n'est absorbé dans le correctif.
## Transition
### PASS
Produire `history/0.1.1/alpha.2.fix.1.md`, l'appliquer puis committer/pousser le fix. Reprendre ensuite la trajectoire normale avec `0.1.1-alpha.3`, consacré à TypeScript et à l'écosystème de package.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.2.fix.1.md` et rester dans `alpha.2.fix.M`. Le scope MUST rester limité à la correction de la gate d'ownership Web tant qu'aucun défaut plus large ne justifie un REPLAN.

269
deltas/0.1.1/alpha.2.md Normal file
View File

@@ -0,0 +1,269 @@
<!-- file: deltas/0.1.1/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.2 — frontières d'ownership frontend Web
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.1`, réalisé après application de `history/0.1.1/alpha.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.1
```
Version après application :
```text
0.1.1-alpha.2
```
## Objet
Matérialiser les frontières d'ownership frontend nécessaires avant d'écrire les configurations détaillées de `alpha.3` à `alpha.5`.
La tranche crée quatre profils indépendants dans la famille `500` :
```text
530 TypeScript
540 JavaScript package ecosystem
550 Vite
560 CSS / Sass
```
Elle inscrit également les trois préférences validées pendant la revue de `alpha.1` : TypeScript, Vite et Sass sont fortement recommandés dans leurs scopes applicables pour les nouveaux frontends contrôlés, donc exprimés en `SHOULD`, mais aucun n'est une obligation universelle.
La tranche ne crée encore aucun template `package.json`, `tsconfig.json` ou `vite.config.ts`, aucun skeleton Web, aucun audit frontend et aucune politique finale de lockfile. Ces responsabilités restent prévues dans les tranches suivantes.
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/000-README.md
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
docs/rules/000-README.md
docs/rules/710-TAURI.md
```
ADD :
```text
deltas/0.1.1/alpha.2.md
docs/rules/530-TYPESCRIPT.md
docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
docs/rules/550-VITE.md
docs/rules/560-CSS_SASS.md
```
DELETE : aucun.
`ROADMAP.md`, `CHANGELOG.md`, les templates, skeletons, scripts, tests, validations et studies restent inchangés.
Aucun `history/0.1.1/alpha.2.md` n'est anticipé.
## Décisions normatives
### TypeScript
Pour un frontend contrôlé portant une logique durable non triviale, TypeScript `SHOULD` être préféré au JavaScript non typé. Du JavaScript direct reste valide lorsqu'il est plus proportionné.
Le type-check TypeScript et la génération éventuelle de bindings depuis une autre source de vérité sont des responsabilités distinctes du bundler. TS-RS reste un outil de frontière Rust/TypeScript lorsqu'un owner plus spécifique l'exige ; il n'est pas une dépendance TypeScript universelle.
### Écosystème de package
`package.json`, le package manager concret, les scripts de package, les dépendances téléchargées et la décision de lockfile appartiennent au profil `540`.
PGR MUST NOT imposer npm par défaut. La politique du lockfile sera définie en `alpha.3` à partir du rôle du package et de la reproductibilité recherchée, pas à partir de l'absence de lockfile observée dans Games.
### Vite
Pour un frontend contrôlé compatible avec ses capacités, Vite `SHOULD` être le build tool/dev server privilégié. Une alternative justifiée reste permise.
Le profil Vite possède sa configuration, son cache et ses outputs ; il ne possède ni TypeScript, ni Sass/CSS, ni le package manager, ni Tauri, ni WASM.
### CSS / Sass
CSS direct reste une baseline valide. Sass `SHOULD` être préféré lorsqu'une chaîne de styles non triviale ou une dépendance Sass/SCSS configurable en tire une valeur claire.
Bootstrap est un exemple réel de bibliothèque pouvant être personnalisée à partir de ses sources Sass et de variables/maps ; il reste un choix de skeleton/projet, pas une dépendance Web universelle.
Pour du nouveau code Sass, `@use` / `@forward` SHOULD être préférés lorsque compatibles. `@import` MAY rester utilisé pour la compatibilité avec des dépendances existantes qui l'exigent.
## Classification Games de cadrage
La classification préparatoire est inscrite dans le plan :
```text
TypeScript durable ADOPT
Vite ADOPT
package.json ADOPT
npm concret KEEP-LOCAL
lockfiles Games KEEP-LOCAL jusqu'à décision alpha.3
Sass ADOPT quand applicable
Bootstrap KEEP-LOCAL
frontend/ layout KEEP-LOCAL / candidat skeleton
ports / aliases / plugins KEEP-LOCAL
WASM dans scripts DEFER
```
Aucun `OVERRIDE` n'est nécessaire avant l'adoption réelle de Games en `0.1.5`.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.1`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.2'
git cat-file -e HEAD:history/0.1.1/alpha.1.md
test -f history/0.1.1/alpha.1.md
test -f deltas/0.1.1/alpha.2.md
test ! -e history/0.1.1/alpha.2.md
for path in docs/rules/530-TYPESCRIPT.md docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md docs/rules/550-VITE.md docs/rules/560-CSS_SASS.md; do
test -f "$path"
done
grep -A2 '^## Statut$' history/0.1.1/alpha.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 13 -->' RULES.md
grep -Fx '<!-- version: 25 -->' docs/000-README.md
grep -Fx '<!-- version: 6 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 2 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 15 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 6 -->' docs/rules/710-TAURI.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path('history/0.1.1/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
expected = {
'530-TYPESCRIPT.md': (
'TypeScript **SHOULD** être préféré',
'TS-RS',
'ni Vite',
),
'540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md': (
'MUST NOT imposer npm',
'Lockfile',
'alpha.3',
),
'550-VITE.md': (
'Vite **SHOULD** être le build tool/dev server privilégié',
'Le profil s'applique uniquement lorsqu'un projet utilise réellement Vite.',
'alpha.4',
),
'560-CSS_SASS.md': (
'Sass **SHOULD** être préféré',
'Bootstrap constitue un exemple concret',
'`@use` / `@forward`',
'`@import` Sass est déprécié',
'alpha.5',
),
}
for name, phrases in expected.items():
text = Path('docs/rules', name).read_text(encoding='utf-8')
for phrase in phrases:
assert phrase in text, (name, phrase)
rules = Path('RULES.md').read_text(encoding='utf-8')
rules_index = Path('docs/rules/000-README.md').read_text(encoding='utf-8')
architecture = Path('docs/architecture/003-RULE_PROFILE_MODEL.md').read_text(encoding='utf-8')
tauri = Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8')
plan = Path('docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md').read_text(encoding='utf-8')
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for owner in ('530-TYPESCRIPT.md', '540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md', '550-VITE.md', '560-CSS_SASS.md'):
assert owner in rules
assert owner in rules_index
for phrase in (
'530 — TypeScript',
'540 — JavaScript package ecosystem',
'550 — Vite',
'560 — CSS / Sass',
'Un frontend minimal peut n'en sélectionner qu'une partie.',
):
assert phrase in architecture, phrase
for phrase in (
'TypeScript et Vite sont fortement recommandés mais restent des `SHOULD`',
'Sass est également fortement recommandé',
'profils `530`, `550` et `560`',
):
assert phrase in tauri, phrase
for phrase in (
'Décisions de revue après `alpha.1`',
'**TypeScript** : fortement recommandé',
'**Vite** : fortement recommandé',
'**Sass** : fortement recommandé',
'`@use` / `@forward`',
'| TypeScript pour les frontends durables | `ADOPT` |',
'| npm comme package manager concret | `KEEP-LOCAL` |',
'| commandes/génération WASM dans les scripts | `DEFER` |',
):
assert phrase in plan, phrase
assert '0.1.8' not in roadmap
assert 'skeleton Tauri avant owners Web suffisants' in roadmap
print('0.1.1 alpha.2 ownership audit: clean (530/540/550/560 independent, SHOULD recommendations explicit, Games classified)')
PYGATE
git diff --check
git add VERSION RULES.md docs/000-README.md docs/architecture/003-RULE_PROFILE_MODEL.md docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md docs/rules/000-README.md docs/rules/710-TAURI.md docs/rules/530-TYPESCRIPT.md docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md docs/rules/550-VITE.md docs/rules/560-CSS_SASS.md deltas/0.1.1/alpha.2.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est :
```text
M RULES.md
M VERSION
A deltas/0.1.1/alpha.2.md
M docs/000-README.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
M docs/rules/000-README.md
A docs/rules/530-TYPESCRIPT.md
A docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
A docs/rules/550-VITE.md
A docs/rules/560-CSS_SASS.md
M docs/rules/710-TAURI.md
```
La revue qualitative doit confirmer que :
- `SHOULD` représente bien « fortement recommandé » et qu'aucun des profils `530`, `550`, `560` n'est activé universellement ;
- TypeScript n'est pas rendu dépendant de Rust ou TS-RS ;
- Vite est recommandé sans interdire un autre build tool ;
- Sass est recommandé conditionnellement et CSS direct reste valide ;
- Bootstrap reste un exemple/choix de skeleton, pas une dépendance universelle ;
- npm et la politique Games des lockfiles restent non généralisés ;
- WASM, serveur Rust et skeleton Tauri restent hors scope de la tranche.
## Transition
### PASS
Produire `history/0.1.1/alpha.2.md`, puis préparer `0.1.1-alpha.3` consacré aux règles et artefacts TypeScript + écosystème de package : `tsconfig`, manifest, scripts utiles, sélection du package manager et politique du lockfile.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.2.md` et rester dans `alpha.2.fix.N` sauf REPLAN justifié. Le fix MUST rester borné au défaut d'ownership ou de formulation observé.

View File

@@ -0,0 +1,242 @@
<!-- file: deltas/0.1.1/alpha.3.fix.1.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.3.fix.1 — déclarations de types externes
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.3`, réalisé après application de `history/0.1.1/alpha.3.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.3
```
Version après application :
```text
0.1.1-alpha.3.fix.1
```
## Objet
Compléter le contrat TypeScript/package de `alpha.3` avec la gestion explicite des déclarations de types externes nécessaires au type-check et à l'intégration IDE.
Le correctif formalise l'ordre de décision suivant :
```text
package consommé
↓
types TypeScript embarqués ?
├─ oui → les utiliser, sans @types redondant
└─ non → rechercher @types/<package> ou une déclaration maintenue équivalente
↓
vérifier besoin et compatibilité
↓
classer correctement dans package.json
```
Pour une application privée, les packages de déclarations nécessaires seulement au développement `SHOULD` normalement appartenir à `devDependencies`. `@types/node` et `@types/bootstrap` sont des exemples conditionnels, pas des dépendances PGR universelles.
Le template `package.json` minimal reste volontairement inchangé : PGR ne connaît ni les dépendances réelles, ni leurs versions, ni la version TypeScript au niveau générique.
Vite reste réservé à `alpha.4`. CSS/Sass et la validation frontend réconciliée restent réservés à `alpha.5`.
## Scope
REPLACE :
```text
VERSION
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
docs/rules/530-TYPESCRIPT.md
docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
```
ADD :
```text
deltas/0.1.1/alpha.3.fix.1.md
```
DELETE : aucun.
`templates/web-typescript/package.json`, `templates/web-typescript/tsconfig.json`, `RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, les profils `550`, `560`, `710`, les skeletons, scripts Python, tests et matrices de validation restent inchangés.
Aucun `history/0.1.1/alpha.3.fix.1.md` n'est anticipé.
## Règles ajoutées
Le correctif précise que :
- un package qui fournit déjà ses propres déclarations TypeScript ne doit pas recevoir arbitrairement un `@types/*` redondant ;
- lorsqu'une dépendance utilisée depuis TypeScript ne fournit pas de déclarations suffisantes, le projet `SHOULD` rechercher un package `@types/<nom>` maintenu ou une autre déclaration appropriée ;
- pour une application privée, les déclarations utilisées seulement au développement `SHOULD` normalement être dans `devDependencies` ;
- `@types/node` est applicable lorsque du code, de la configuration ou de l'outillage TypeScript utilise réellement l'environnement Node ;
- `@types/bootstrap` est applicable lorsque les API JavaScript Bootstrap sont consommées depuis TypeScript et nécessitent des déclarations externes ;
- un usage CSS/Sass seul de Bootstrap ne justifie pas `@types/bootstrap` ;
- si `compilerOptions.types` est utilisé, les packages de déclarations globales nécessaires doivent être sélectionnés explicitement de manière cohérente ;
- pour une bibliothèque publiée, une déclaration externe requise par les `.d.ts` publics doit rester disponible aux consommateurs et ne peut pas être cachée arbitrairement dans les seules `devDependencies` ;
- les versions runtime, `@types/*` et TypeScript doivent rester compatibles.
## Preuve corpus
Games `0.3.6` exerce déjà :
```text
Web/game-snake-poc @types/bootstrap + @types/node
Web/game-realtime-webtransport-browser-smoke @types/node
crates/apps/game-snake-poc-tauri @types/node
```
KSP `0.3.17` corrobore la pratique sur ses applications Tauri avec `@types/bootstrap` et `@types/node` en `devDependencies`.
Cette répétition justifie la règle de découverte/classification, pas l'installation universelle de ces packages.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.3`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.3.fix.1'
git cat-file -e HEAD:history/0.1.1/alpha.3.md
test -f history/0.1.1/alpha.3.md
test -f deltas/0.1.1/alpha.3.md
test -f deltas/0.1.1/alpha.3.fix.1.md
test ! -e history/0.1.1/alpha.3.fix.1.md
grep -A2 '^## Statut$' history/0.1.1/alpha.3.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 5 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 3 -->' docs/rules/530-TYPESCRIPT.md
grep -Fx '<!-- version: 3 -->' docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
grep -Fx '<!-- version: 2 -->' docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
python3 -B - <<'PYGATE'
from pathlib import Path
import json
import re
history = Path('history/0.1.1/alpha.3.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
typescript = Path('docs/rules/530-TYPESCRIPT.md').read_text(encoding='utf-8')
for phrase in (
'Déclarations de types externes et intégration IDE',
'fournit déjà ses propres fichiers de déclaration TypeScript',
'@types/<nom>',
'`devDependencies`',
'`@types/node`',
'`@types/bootstrap`',
'Un projet qui ne consomme que le CSS/Sass de Bootstrap',
'`compilerOptions.types`',
'bibliothèque publiée',
):
assert phrase in typescript, phrase
packages = Path('docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md').read_text(encoding='utf-8')
for phrase in (
'Dépendances de développement et packages de déclarations',
'la dépendance runtime fournit déjà ses propres types',
'@types/<nom>',
'`@types/node` est pertinent',
'`@types/bootstrap` est pertinent',
'Le template PGR générique conserve volontairement un `package.json` sans `devDependencies` préremplies',
'Pour une bibliothèque publiée',
):
assert phrase in packages, phrase
guide = Path('docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md').read_text(encoding='utf-8')
for phrase in (
'`devDependencies` et déclarations de types',
'fournit-il déjà ses propres types ?',
'ne pas ajouter un @types redondant',
'"@types/node": "<si Node est réellement utilisé>"',
'"@types/bootstrap": "<si les API JavaScript Bootstrap sont réellement utilisées et nécessitent des types externes>"',
'qualité TypeScript et à l'expérience IDE',
):
assert phrase in guide, phrase
package = json.loads(Path('templates/web-typescript/package.json').read_text(encoding='utf-8'))
assert package == {
'name': 'project-web',
'private': True,
'scripts': {'typecheck': 'tsc --noEmit'},
}
tsconfig = json.loads(Path('templates/web-typescript/tsconfig.json').read_text(encoding='utf-8'))
assert tsconfig == {
'compilerOptions': {
'strict': True,
'noEmit': True,
'noUnusedLocals': True,
'noUnusedParameters': True,
'noFallthroughCasesInSwitch': True,
}
}
plan = Path('docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Statut opérateur : **PASS**.',
'### alpha.3.fix.1 — déclarations de types externes',
'@types/bootstrap + @types/node',
'types embarqués → @types si nécessaire',
'Vite/CSS/Sass hors scope',
):
assert phrase in plan, phrase
assert Path('docs/rules/550-VITE.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 1 -->'
assert Path('docs/rules/560-CSS_SASS.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 1 -->'
assert Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 6 -->'
print('0.1.1 alpha.3.fix.1 type declarations audit: clean (bundled types first, conditional @types, app/library dependency roles preserved)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md docs/rules/530-TYPESCRIPT.md docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md deltas/0.1.1/alpha.3.fix.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.1.1/alpha.3.fix.1.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
M docs/rules/530-TYPESCRIPT.md
M docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
M docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
```
## Revue opérateur complémentaire
Confirmer que :
- `alpha.3` reste historisé `PASS` et son delta n'est pas réécrit ;
- le fix n'ajoute aucune dépendance fictive au template générique `package.json` ;
- les `@types/*` ne sont recherchés qu'après vérification des types embarqués ;
- `@types/node` et `@types/bootstrap` restent des exemples conditionnels ;
- les applications privées et les bibliothèques publiées conservent des règles de classification distinctes ;
- Vite, CSS/Sass, WASM et Tauri restent hors scope du correctif.
## Transition
### PASS
Produire `history/0.1.1/alpha.3.fix.1.md`, l'appliquer puis committer/pousser le fix. Reprendre ensuite la trajectoire normale avec `0.1.1-alpha.4`, consacré à Vite, au dev server, aux caches et aux outputs de production.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.3.fix.1.md` et rester dans `alpha.3.fix.M`. Le scope MUST rester limité au contrat TypeScript/package tant qu'aucun défaut plus large ne justifie un REPLAN.

View File

@@ -0,0 +1,199 @@
<!-- file: deltas/0.1.1/alpha.3.fix.2.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.3.fix.2 — correction de la gate des déclarations de types
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.3.fix.1`, réalisé après application de `history/0.1.1/alpha.3.fix.1.md` avec statut `FAIL`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.3.fix.1
```
Version après application :
```text
0.1.1-alpha.3.fix.2
```
## Objet
Corriger uniquement la syntaxe défectueuse de la gate opérateur de `alpha.3.fix.1`.
Les règles et guides livrés par `alpha.3.fix.1` restent inchangés. Le delta historique `deltas/0.1.1/alpha.3.fix.1.md` reste également inchangé.
Le défaut observé était un littéral Python entouré de quotes simples alors que son texte contenait l'apostrophe de `l'expérience` :
```python
'qualité TypeScript et à l'expérience IDE'
```
Le fix utilise des littéraux syntaxiquement sûrs dans la nouvelle gate et généralise cette précaution aux assertions contenant des apostrophes, sans modifier leur sens.
## Scope
REPLACE :
```text
VERSION
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
ADD :
```text
deltas/0.1.1/alpha.3.fix.2.md
```
DELETE : aucun.
Aucune règle normative, aucun template, skeleton, script d'audit ou test n'est modifié par ce correctif.
## Validation opérateur
Après application du history `FAIL`, commit/push de `alpha.3.fix.1`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.3.fix.2'
git cat-file -e HEAD:history/0.1.1/alpha.3.fix.1.md
test -f history/0.1.1/alpha.3.fix.1.md
test -f deltas/0.1.1/alpha.3.fix.1.md
test -f deltas/0.1.1/alpha.3.fix.2.md
test ! -e history/0.1.1/alpha.3.fix.2.md
grep -A2 '^## Statut$' history/0.1.1/alpha.3.fix.1.md | grep -Fx 'FAIL'
grep -Fx '<!-- version: 6 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 3 -->' docs/rules/530-TYPESCRIPT.md
grep -Fx '<!-- version: 3 -->' docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
grep -Fx '<!-- version: 2 -->' docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
python3 -B - <<'PYGATE'
from pathlib import Path
import json
import re
history = Path('history/0.1.1/alpha.3.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL\s', history)
typescript = Path('docs/rules/530-TYPESCRIPT.md').read_text(encoding='utf-8')
for phrase in (
'Déclarations de types externes et intégration IDE',
'fournit déjà ses propres fichiers de déclaration TypeScript',
'@types/<nom>',
'`devDependencies`',
'`@types/node`',
'`@types/bootstrap`',
'Un projet qui ne consomme que le CSS/Sass de Bootstrap',
'`compilerOptions.types`',
'bibliothèque publiée',
):
assert phrase in typescript, phrase
packages = Path('docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md').read_text(encoding='utf-8')
for phrase in (
'Dépendances de développement et packages de déclarations',
'la dépendance runtime fournit déjà ses propres types',
'@types/<nom>',
'`@types/node` est pertinent',
'`@types/bootstrap` est pertinent',
'Le template PGR générique conserve volontairement un `package.json` sans `devDependencies` préremplies',
'Pour une bibliothèque publiée',
):
assert phrase in packages, phrase
guide = Path('docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md').read_text(encoding='utf-8')
for phrase in (
'`devDependencies` et déclarations de types',
'fournit-il déjà ses propres types ?',
'ne pas ajouter un @types redondant',
'"@types/node": "<si Node est réellement utilisé>"',
'"@types/bootstrap": "<si les API JavaScript Bootstrap sont réellement utilisées et nécessitent des types externes>"',
"qualité TypeScript et à l'expérience IDE",
):
assert phrase in guide, phrase
package = json.loads(Path('templates/web-typescript/package.json').read_text(encoding='utf-8'))
assert package == {
'name': 'project-web',
'private': True,
'scripts': {'typecheck': 'tsc --noEmit'},
}
tsconfig = json.loads(Path('templates/web-typescript/tsconfig.json').read_text(encoding='utf-8'))
assert tsconfig == {
'compilerOptions': {
'strict': True,
'noEmit': True,
'noUnusedLocals': True,
'noUnusedParameters': True,
'noFallthroughCasesInSwitch': True,
}
}
plan = Path('docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Statut opérateur : **FAIL**.',
"### alpha.3.fix.2 — correction de la gate des déclarations de types",
'types embarqués → @types si nécessaire',
'Aucun défaut normatif du correctif',
'assertions contenant des apostrophes',
):
assert phrase in plan, phrase
assert Path('docs/rules/550-VITE.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 1 -->'
assert Path('docs/rules/560-CSS_SASS.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 1 -->'
assert Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 6 -->'
print('0.1.1 alpha.3.fix.2 type declarations gate: clean (alpha.3.fix.1 FAIL preserved, type declarations reconfirmed, Python literals safe)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
deltas/0.1.1/alpha.3.fix.2.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history du fix est exactement :
```text
M VERSION
A deltas/0.1.1/alpha.3.fix.2.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
## Revue opérateur complémentaire
Confirmer que :
- le `FAIL` de `alpha.3.fix.1` est conservé historiquement ;
- `deltas/0.1.1/alpha.3.fix.1.md` n'est pas réécrit ;
- `docs/rules/530-TYPESCRIPT.md`, `docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md` et `docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md` ne sont pas modifiés par le fix ;
- `templates/web-typescript/package.json` et `templates/web-typescript/tsconfig.json` ne sont pas modifiés par le fix ;
- aucun contenu Vite, CSS/Sass, WASM ou Tauri n'est absorbé dans le correctif.
## Transition
### PASS
Produire `history/0.1.1/alpha.3.fix.2.md`, l'appliquer puis committer/pousser le fix. Reprendre ensuite la trajectoire normale avec `0.1.1-alpha.4`, consacré à Vite, au dev server, aux caches et aux outputs de production.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.3.fix.2.md` et rester dans `alpha.3.fix.M`. Le scope MUST rester limité à la correction de la gate tant qu'aucun défaut plus large ne justifie un REPLAN.

310
deltas/0.1.1/alpha.3.md Normal file
View File

@@ -0,0 +1,310 @@
<!-- file: deltas/0.1.1/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.3 — TypeScript et écosystème de package
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.2.fix.1`, réalisé après application de `history/0.1.1/alpha.2.fix.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.2.fix.1
```
Version après application :
```text
0.1.1-alpha.3
```
## Objet
Détailler les owners `530 TypeScript` et `540 JavaScript package ecosystem`, puis fournir une baseline minimale réutilisable pour une application Web TypeScript privée.
La tranche définit :
- une baseline TypeScript stricte et indépendante du bundler ;
- le script canonique `typecheck` ;
- la responsabilité de `package.json` et de la sélection explicite du package manager ;
- une politique de lockfile fondée sur le rôle du package et la reproductibilité ;
- une paire minimale `package.json` + `tsconfig.json` sans version TypeScript, package manager, Vite, Sass, framework UI, host ou WASM imposés.
Vite reste réservé à `alpha.4`. CSS/Sass et la validation frontend réconciliée restent réservés à `alpha.5`.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
docs/rules/530-TYPESCRIPT.md
docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
```
ADD :
```text
deltas/0.1.1/alpha.3.md
docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
templates/web-typescript/package.json
templates/web-typescript/tsconfig.json
```
DELETE : aucun.
`RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, les profils `550`, `560`, `710`, les skeletons, scripts Python, tests et matrices de validation restent inchangés.
Aucun `history/0.1.1/alpha.3.md` n'est anticipé.
## Décisions TypeScript
La baseline générique contrôlée active :
```text
strict
noEmit
noUnusedLocals
noUnusedParameters
noFallthroughCasesInSwitch
```
Elle n'impose pas :
```text
target
module
moduleResolution
lib
types
jsx
include/exclude
aliases
Vite
WASM
Tauri
```
Ces choix dépendent du runtime, du host, du bundler ou du layout réel.
Le script `typecheck` SHOULD exposer la vérification TypeScript indépendamment du bundler. Le template utilise :
```text
tsc --noEmit
```
Le package manager reste responsable de l'invocation réelle de ce script.
## Décisions package manager / manifest
PGR ne choisit toujours pas npm, pnpm, yarn, Bun ou un autre outil par défaut.
Le projet MUST rendre son choix de package manager explicite dans un owner local approprié. Le champ `packageManager` de `package.json` MAY être utilisé lorsque la toolchain le permet, mais PGR ne peut pas y inscrire une version fictive dans son template générique.
Pour une application non publiée, `private: true` SHOULD être utilisé.
Le template `package.json` n'invente ni version de package, ni dépendance, ni champ de publication. Il fournit seulement un nom d'exemple, `private: true` et le script `typecheck`.
## Politique de lockfile
La politique PGR est désormais :
```text
application privée / déployable
-> lockfile SHOULD être versionné
bibliothèque publiée
-> lockfile MAY être versionné pour dev/CI
mais le manifest reste le contrat consommateur
template / fixture sans résolution réelle
-> lockfile MAY être absent
```
Un package SHOULD NOT conserver plusieurs lockfiles concurrents sauf migration temporaire explicitement documentée.
Lorsqu'un lockfile est versionné, CI SHOULD utiliser le mode gelé/immutable/clean-install équivalent du package manager choisi.
La politique historique Games sans lockfile n'est donc ni réécrite ni qualifiée rétroactivement de défaut. Son adoption `0.1.5` décidera package par package entre `ADOPT` et `OVERRIDE`.
## Templates
Les deux fichiers copiables sont :
```text
templates/web-typescript/package.json
templates/web-typescript/tsconfig.json
```
Ils sont volontairement du JSON strict, donc ne portent pas de commentaires internes `file/version`.
Leur contrat et leurs étapes d'adaptation sont documentés dans :
```text
docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
```
La paire ne constitue pas encore un skeleton frontend.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.2.fix.1`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.3'
git cat-file -e HEAD:history/0.1.1/alpha.2.fix.1.md
test -f history/0.1.1/alpha.2.fix.1.md
test -f deltas/0.1.1/alpha.3.md
test ! -e history/0.1.1/alpha.3.md
grep -A2 '^## Statut$' history/0.1.1/alpha.2.fix.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 26 -->' docs/000-README.md
grep -Fx '<!-- version: 4 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 2 -->' docs/rules/530-TYPESCRIPT.md
grep -Fx '<!-- version: 2 -->' docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
grep -Fx '<!-- version: 1 -->' docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
python3 -B - <<'PYGATE'
from pathlib import Path
import json
import re
history = Path('history/0.1.1/alpha.2.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
typescript = Path('docs/rules/530-TYPESCRIPT.md').read_text(encoding='utf-8')
for phrase in (
'strict = true',
'noEmit = true',
'noUnusedLocals = true',
'noUnusedParameters = true',
'noFallthroughCasesInSwitch = true',
'typecheck',
'tsc --noEmit',
'MUST NOT les figer',
):
assert phrase in typescript, phrase
packages = Path('docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md').read_text(encoding='utf-8')
for phrase in (
'private: true',
'MUST sélectionner explicitement son package manager',
'typecheck',
'SHOULD** être versionné',
'SHOULD NOT** conserver simultanément plusieurs lockfiles',
'MUST NOT transformer `npm ci` en commande universelle',
'`ADOPT` cette recommandation',
'`OVERRIDE`',
):
assert phrase in packages, phrase
package = json.loads(Path('templates/web-typescript/package.json').read_text(encoding='utf-8'))
tsconfig = json.loads(Path('templates/web-typescript/tsconfig.json').read_text(encoding='utf-8'))
assert package == {
'name': 'project-web',
'private': True,
'scripts': {'typecheck': 'tsc --noEmit'},
}
assert tsconfig == {
'compilerOptions': {
'strict': True,
'noEmit': True,
'noUnusedLocals': True,
'noUnusedParameters': True,
'noFallthroughCasesInSwitch': True,
}
}
guide = Path('docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md').read_text(encoding='utf-8')
for phrase in (
'package manager concret',
'version TypeScript',
'target ECMAScript',
'Vite ou autre bundler',
"n'acceptent pas un header commentaire PGR",
'npm run typecheck',
'pnpm typecheck',
'yarn typecheck',
):
assert phrase in guide, phrase
plan = Path('docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Statut opérateur : **PASS**.',
'application privée ou déployable `SHOULD` versionner le lockfile',
"`DEFER` jusqu'à l'adoption `0.1.5`",
'script canonique `typecheck`',
'Vite reste réservé à `alpha.4`',
):
assert phrase in plan, phrase
assert Path('docs/rules/550-VITE.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 1 -->'
assert Path('docs/rules/560-CSS_SASS.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 1 -->'
assert Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8').splitlines()[1] == '<!-- version: 6 -->'
print('0.1.1 alpha.3 TypeScript/package audit: clean (strict typecheck, package-manager neutral, role-based lockfile policy, 2 JSON templates parsed)')
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
docs/rules/530-TYPESCRIPT.md docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md \
docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md \
templates/web-typescript/package.json templates/web-typescript/tsconfig.json \
deltas/0.1.1/alpha.3.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est exactement :
```text
M VERSION
A deltas/0.1.1/alpha.3.md
M docs/000-README.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
M docs/rules/530-TYPESCRIPT.md
M docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md
A docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
A templates/web-typescript/package.json
A templates/web-typescript/tsconfig.json
```
## Revue opérateur complémentaire
Confirmer que :
- la baseline TypeScript générique ne fige aucun choix propre à Vite, Node, WASM ou Tauri ;
- `typecheck` reste une preuve indépendante et ne devient pas une responsabilité du bundler ;
- PGR ne sélectionne aucun package manager universel ;
- le lockfile est recommandé pour les applications privées/déployables sans imposer la même politique aux bibliothèques publiées ;
- le template `package.json` n'invente aucune version de dépendance ou de package manager ;
- les deux JSON restent des templates minimaux, pas un skeleton frontend ;
- aucun contenu de `alpha.4` ou `alpha.5` n'est absorbé.
## Transition
### PASS
Produire `history/0.1.1/alpha.3.md`, l'appliquer puis committer/pousser la tranche. Préparer ensuite `0.1.1-alpha.4` consacré à Vite, au dev server et aux outputs.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.3.md` et rester dans `alpha.3.fix.M` sauf REPLAN explicitement justifié.

226
deltas/0.1.1/alpha.4.md Normal file
View File

@@ -0,0 +1,226 @@
<!-- file: deltas/0.1.1/alpha.4.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.4 — Vite, dev server et outputs
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.3.fix.2`, réalisé après application de `history/0.1.1/alpha.3.fix.2.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.3.fix.2
```
Version après application :
```text
0.1.1-alpha.4
```
## Objet
Compléter l'owner `550-VITE.md` avec un contrat générique de dev server, cache, outputs et assets, puis documenter l'adaptation d'un projet Vite sans inventer un `vite.config.ts` universel.
La tranche conserve Vite comme recommandation `SHOULD`, pas comme obligation.
Elle ne modifie pas :
- la baseline TypeScript/package de `alpha.3` ;
- les règles de déclarations `@types/*` ;
- le profil CSS/Sass réservé à `alpha.5` ;
- le profil Tauri ;
- WASM, backend ou deployment/operations.
## Décisions matérialisées
Le contrat Vite distingue désormais explicitement :
```text
sources versionnées
cache Vite reproductible
outputs build générés
assets sources
assets copiés/transformés
```
Le cache et les outputs `SHOULD` rester hors Git et `SHOULD` être externalisés hors de l'arborescence source lorsqu'un emplacement de build externe est raisonnablement disponible.
`build.emptyOutDir = true` n'est acceptable que sur un répertoire dédié dont Vite possède entièrement le contenu généré.
Le dev server reste local/loopback par défaut. L'exposition réseau est une décision explicite. `server.allowedHosts = true` et `server.cors = true` ne sont pas des défauts PGR.
Lorsqu'une intégration dépend d'un port déterministe, le couple `server.port` + `server.strictPort = true` est recommandé. Les ports eux-mêmes restent locaux.
`vite preview` est classifié comme prévisualisation/smoke local du build, jamais comme serveur de production.
## Pas de `vite.config.ts` générique artificiel
La tranche ajoute [`docs/templates/009-WEB_VITE.md`](../../docs/templates/009-WEB_VITE.md), mais aucun fichier copiable `templates/web-vite/vite.config.ts`.
Cette absence est volontaire : le corpus prouve l'owner et les responsabilités, mais pas une valeur universelle pour `root`, `base`, `cacheDir`, `outDir`, ports, aliases ou plugins.
Un template exécutable pourra être ajouté ultérieurement si une configuration minimale réellement neutre est démontrée. PGR ne crée pas un fichier vide ou rempli de placeholders uniquement pour satisfaire un catalogue.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
docs/rules/550-VITE.md
```
ADD :
```text
docs/templates/009-WEB_VITE.md
deltas/0.1.1/alpha.4.md
```
DELETE : aucun.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.3.fix.2`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.4'
git cat-file -e HEAD:history/0.1.1/alpha.3.fix.2.md
test -f history/0.1.1/alpha.3.fix.2.md
test -f deltas/0.1.1/alpha.4.md
test ! -e history/0.1.1/alpha.4.md
grep -A2 '^## Statut$' history/0.1.1/alpha.3.fix.2.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 27 -->' docs/000-README.md
grep -Fx '<!-- version: 7 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 2 -->' docs/rules/550-VITE.md
grep -Fx '<!-- version: 1 -->' docs/templates/009-WEB_VITE.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path("history/0.1.1/alpha.3.fix.2.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
vite = Path("docs/rules/550-VITE.md").read_text(encoding="utf-8")
for phrase in (
"Vite **SHOULD** être le build tool/dev server privilégié",
"PGR ne fournit pas de `vite.config.ts` universel",
"`cacheDir` **SHOULD** être externalisé",
"Le contenu de `build.outDir` est un output généré",
"`build.emptyOutDir = true`",
"`publicDir` est une capacité optionnelle",
"PGR MUST NOT imposer le nom `frontend/`",
"PGR MUST NOT imposer `./`, `/` ou un chemin de sous-répertoire universel",
"Le dev server **SHOULD** rester limité à la machine locale/loopback",
"`server.port` avec `server.strictPort = true`",
"`server.allowedHosts = true` et `server.cors = true` **SHOULD NOT**",
"Il MUST NOT être présenté comme serveur de production",
"le build de production via le package manager choisi **SHOULD** faire partie de la gate",
):
assert phrase in vite, phrase
guide = Path("docs/templates/009-WEB_VITE.md").read_text(encoding="utf-8")
for phrase in (
"ne fournit volontairement pas de `vite.config.ts` copiable universel",
'"dev": "vite"',
'"build": "vite build"',
'"preview": "vite preview"',
"typecheck -> tsc --noEmit",
"build -> vite build",
"Le nom `frontend/` observé dans Games est une convention locale",
"PGR ne copie donc pas automatiquement `base: \"./\"`",
"Le cache Vite est reproductible",
"`build.outDir` contient des artefacts générés",
"server.allowedHosts = true",
"server.cors = true",
"server.strictPort true",
"Il ne constitue pas un serveur de production PGR",
"PGR ne livre pas encore de `vite.config.ts` exécutable générique",
):
assert phrase in guide, phrase
plan = Path("docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### alpha.3.fix.2 — correction de la gate des déclarations de types",
"Statut opérateur : **PASS**.",
"### alpha.4 — Vite, dev server et outputs",
"sans créer un `vite.config.ts` universel artificiel",
"TypeScript reste validé séparément ; CSS/Sass reste réservé à `alpha.5`.",
):
assert phrase in plan, phrase
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "templates/009-WEB_VITE.md" in index
assert not Path("templates/web-vite/vite.config.ts").exists()
assert Path("docs/rules/530-TYPESCRIPT.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 3 -->"
assert Path("docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 3 -->"
assert Path("docs/rules/560-CSS_SASS.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 1 -->"
assert Path("docs/rules/710-TAURI.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 6 -->"
print("0.1.1 alpha.4 Vite contract audit: clean (outputs/cache explicit, dev server bounded, no fake universal config, alpha.5 untouched)")
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
docs/rules/550-VITE.md docs/templates/009-WEB_VITE.md \
deltas/0.1.1/alpha.4.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `alpha.4` est exactement :
```text
M VERSION
A deltas/0.1.1/alpha.4.md
M docs/000-README.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
M docs/rules/550-VITE.md
A docs/templates/009-WEB_VITE.md
```
## Revue opérateur complémentaire
Confirmer que :
- Vite reste `SHOULD`, jamais `MUST` universel ;
- aucun package manager n'est imposé ;
- aucun port, host, `base`, alias ou plugin n'est transformé en valeur universelle ;
- aucun `vite.config.ts` artificiellement générique n'est ajouté ;
- cache et outputs sont classifiés comme générés et hors Git ;
- `emptyOutDir` ne peut viser qu'un output dédié ;
- `preview` n'est pas présenté comme serveur de production ;
- TypeScript/package ne sont pas réouverts ;
- CSS/Sass reste réservé à `alpha.5` ;
- Tauri/WASM/deployment restent hors scope.
## Transition
### PASS
Produire `history/0.1.1/alpha.4.md`, l'appliquer puis committer/pousser `alpha.4`. Continuer avec `0.1.1-alpha.5`, consacré à CSS/Sass et à la validation frontend indépendante du host.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.4.md`, puis produire `alpha.4.fix.N` ou effectuer un REPLAN si le défaut révèle une frontière d'ownership incorrecte. Ne pas absorber `alpha.5` dans un correctif Vite.

325
deltas/0.1.1/alpha.5.md Normal file
View File

@@ -0,0 +1,325 @@
<!-- file: deltas/0.1.1/alpha.5.md -->
<!-- version: 1 -->
# Delta 0.1.1-alpha.5 — CSS/Sass, validation frontend et skeleton Web
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.4`, réalisé après application de `history/0.1.1/alpha.4.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.4
```
Version après application :
```text
0.1.1-alpha.5
```
## Objet
Compléter l'owner `560-CSS_SASS.md`, définir une validation frontend réutilisable indépendante du host et matérialiser un skeleton Web uniquement parce que les owners `530/540/550/560` sont désormais suffisamment séparés et actionnables.
La tranche conserve les décisions suivantes :
- CSS reste valide sans Sass ;
- Sass reste optionnel mais recommandé (`SHOULD`) lorsqu'il apporte une valeur réelle ;
- `@use` / `@forward` sont préférés pour le nouveau Sass contrôlé ;
- `@import` reste une compatibilité possible pour les dépendances qui l'exigent encore ;
- les sources CSS/Sass et leurs outputs générés sont distingués sans ambiguïté ;
- un package de styles est consommé via son entrypoint public/documenté plutôt que par un chemin interne arbitraire ;
- Bootstrap/Tailwind CSS/alternative restent des choix de projet ou skeleton, pas des obligations de `560` ;
- la validation frontend est séparée de la validation du host ;
- le skeleton Web compose des owners existants et ne devient pas leur propriétaire.
Le `DEFER` Tauri n'est pas levé par cette tranche.
## Validation frontend indépendante du host
[`docs/validation/005-WEB_FRONTEND_VALIDATION.md`](../../docs/validation/005-WEB_FRONTEND_VALIDATION.md) définit les couches de preuve réutilisables :
```text
restore reproductible
TypeScript typecheck
styles si preuve distincte
build frontend de production
browser smoke si nécessaire
host integration séparée
```
La matrice évite les doublons : si Sass est déjà compilé par le build Vite et qu'aucun contrat Sass autonome n'existe, une seconde compilation identique n'est pas requise.
Un `PASS` frontend ne vaut jamais automatiquement `PASS` du host.
## Skeleton Web
[`docs/skeletons/003-WEB_FRONTEND.md`](../../docs/skeletons/003-WEB_FRONTEND.md) devient la première specialization Web PGR.
Il peut composer :
```text
GENERAL + 500 + 530 + 540 + 550 + 560
```
mais chaque profil reste sélectionné selon les faits du projet. TypeScript et Vite restent des recommandations `SHOULD`; Sass reste conditionnel.
Le skeleton MUST NOT imposer :
```text
npm
Bootstrap
Tailwind CSS
frontend/
vite.config.ts générique
main.scss générique
port fixe
base fixe
WASM
Tauri
backend
deployment
```
## Pas de faux templates techniques
La tranche ajoute un guide CSS/Sass :
```text
docs/templates/010-WEB_CSS_SASS.md
```
mais aucun `templates/web-css/main.scss` ni autre source de style factice.
Le skeleton réutilise les templates TypeScript/package existants et les guides Vite/CSS-Sass. Les valeurs réellement dépendantes du projet restent à décider pendant l'instanciation.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
docs/rules/560-CSS_SASS.md
docs/skeletons/000-README.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
docs/skeletons/003-WEB_FRONTEND.md
docs/templates/010-WEB_CSS_SASS.md
docs/validation/005-WEB_FRONTEND_VALIDATION.md
deltas/0.1.1/alpha.5.md
```
DELETE : aucun.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.4`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-alpha.5'
git cat-file -e HEAD:history/0.1.1/alpha.4.md
test -f history/0.1.1/alpha.4.md
test -f deltas/0.1.1/alpha.5.md
test ! -e history/0.1.1/alpha.5.md
grep -A2 '^## Statut$' history/0.1.1/alpha.4.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 18 -->' README.md
grep -Fx '<!-- version: 28 -->' docs/000-README.md
grep -Fx '<!-- version: 8 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 2 -->' docs/rules/560-CSS_SASS.md
grep -Fx '<!-- version: 6 -->' docs/skeletons/000-README.md
grep -Fx '<!-- version: 1 -->' docs/skeletons/003-WEB_FRONTEND.md
grep -Fx '<!-- version: 1 -->' docs/templates/010-WEB_CSS_SASS.md
grep -Fx '<!-- version: 14 -->' docs/validation/001-VALIDATION_MATRIX.md
grep -Fx '<!-- version: 1 -->' docs/validation/005-WEB_FRONTEND_VALIDATION.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
history = Path("history/0.1.1/alpha.4.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
styles = Path("docs/rules/560-CSS_SASS.md").read_text(encoding="utf-8")
for phrase in (
"Sass **SHOULD** être préféré",
"Sass n'est donc jamais requis",
"MUST NOT être modifié manuellement",
"`@use` / `@forward`",
"L'ancien `@import` Sass est déprécié",
"entrypoint Sass public",
"`sass-embedded` **SHOULD** être préféré",
"Un package npm apportant uniquement des styles n'impose pas l'ajout de déclarations `@types/*`",
"un build Vite réussi peut constituer la preuve de compilation des styles",
"005-WEB_FRONTEND_VALIDATION.md",
):
assert phrase in styles, phrase
guide = Path("docs/templates/010-WEB_CSS_SASS.md").read_text(encoding="utf-8")
for phrase in (
"ne fournit volontairement pas de `main.scss`",
"CSS seul reste valide",
"sass-embedded",
"@use",
"@forward",
"Les dépendances `@types/*` ne concernent que les API JavaScript/TypeScript",
"PGR ne fixe ni Bootstrap, ni Bootswatch",
"host gate séparée",
):
assert phrase in guide, phrase
validation = Path("docs/validation/005-WEB_FRONTEND_VALIDATION.md").read_text(encoding="utf-8")
for phrase in (
"Le frontend **SHOULD** être validable indépendamment du host",
"Un résultat frontend `PASS`",
"restauration reproductible des dépendances",
"type-check TypeScript",
"build frontend de production",
"preview / smoke navigateur",
"PGR MUST NOT imposer `npm ci`",
"PGR SHOULD NOT lancer deux compilations équivalentes",
"Un host tel que Tauri",
"Il ne vaut pas `PASS` Tauri",
):
assert phrase in validation, phrase
skeleton = Path("docs/skeletons/003-WEB_FRONTEND.md").read_text(encoding="utf-8")
for phrase in (
"GENERAL",
"+ 530 TypeScript",
"+ 540 JavaScript package ecosystem",
"+ 550 Vite",
"+ 560 CSS / Sass",
"Le skeleton ne transforme pas une recommandation `SHOULD` en `MUST`",
"PGR ne fournit pas de `vite.config.ts` universel",
"PGR ne fournit pas non plus de `main.scss`",
"Le nom `frontend/` est une convention possible",
"le package manager réel",
"Bootstrap, Tailwind CSS ou autre",
"Le skeleton Tauri reste `DEFER` pendant `0.1.1`",
):
assert phrase in skeleton, phrase
matrix = Path("docs/validation/001-VALIDATION_MATRIX.md").read_text(encoding="utf-8")
assert "005-WEB_FRONTEND_VALIDATION.md" in matrix
index = Path("docs/000-README.md").read_text(encoding="utf-8")
for target in (
"templates/010-WEB_CSS_SASS.md",
"validation/005-WEB_FRONTEND_VALIDATION.md",
"skeletons/003-WEB_FRONTEND.md",
):
assert target in index, target
skeleton_index = Path("docs/skeletons/000-README.md").read_text(encoding="utf-8")
assert "003-WEB_FRONTEND.md" in skeleton_index
assert "La création du skeleton Web ne lève pas automatiquement ce `DEFER`." in skeleton_index
plan = Path("docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### alpha.4 — Vite, dev server et outputs",
"Statut opérateur : **PASS**.",
"### alpha.5 — CSS/Sass et validation frontend",
"Les owners `530/540/550/560` sont désormais assez complets",
"Le skeleton ne lève pas le `DEFER` Tauri",
):
assert phrase in plan, phrase
study = Path("docs/studies/002-TAURI_SKELETON_DECISION.md").read_text(encoding="utf-8")
assert "DEFER" in study
for phrase in (
"TypeScript et conventions Web contrôlées",
"Vite et ownership des commandes/dev server/build outputs",
"Sass/CSS et statut des artefacts générés",
"validation frontend indépendante de la validation Tauri",
"choix Bootstrap ou alternative clairement classifié",
):
assert phrase in study, phrase
assert not Path("templates/web-vite/vite.config.ts").exists()
assert not Path("templates/web-css/main.scss").exists()
assert Path("docs/rules/530-TYPESCRIPT.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 3 -->"
assert Path("docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 3 -->"
assert Path("docs/rules/550-VITE.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 2 -->"
assert Path("docs/rules/710-TAURI.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 6 -->"
assert "0.1.8" not in Path("ROADMAP.md").read_text(encoding="utf-8")
print("0.1.1 alpha.5 Web frontend audit: clean (CSS/Sass bounded, host-independent validation explicit, Web skeleton composable, Tauri DEFER preserved)")
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
docs/rules/560-CSS_SASS.md \
docs/skeletons/000-README.md docs/skeletons/003-WEB_FRONTEND.md \
docs/templates/010-WEB_CSS_SASS.md \
docs/validation/001-VALIDATION_MATRIX.md docs/validation/005-WEB_FRONTEND_VALIDATION.md \
deltas/0.1.1/alpha.5.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `alpha.5` est exactement :
```text
M README.md
M VERSION
A deltas/0.1.1/alpha.5.md
M docs/000-README.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
M docs/rules/560-CSS_SASS.md
M docs/skeletons/000-README.md
A docs/skeletons/003-WEB_FRONTEND.md
A docs/templates/010-WEB_CSS_SASS.md
M docs/validation/001-VALIDATION_MATRIX.md
A docs/validation/005-WEB_FRONTEND_VALIDATION.md
```
## Revue opérateur complémentaire
Confirmer que :
- Sass reste `SHOULD` et conditionnel ;
- CSS seul reste une baseline valide ;
- `@use` / `@forward` sont préférés sans casser les dépendances encore basées sur `@import` ;
- aucun CSS compilé n'est présenté comme source à modifier ;
- aucune dépendance Sass/Vite/Bootstrap n'est injectée dans le template `package.json` générique ;
- aucun `main.scss` ou `vite.config.ts` artificiel n'est ajouté ;
- le skeleton `003-WEB_FRONTEND.md` compose les owners au lieu de recopier leurs règles ;
- npm, Bootstrap, Tailwind CSS, `frontend/`, ports et `base` restent des décisions locales ;
- la validation frontend peut être exécutée séparément du host autant que le graphe réel le permet ;
- un `PASS` frontend n'est pas présenté comme un `PASS` Tauri ;
- le `DEFER` du skeleton Tauri reste intact ;
- WASM, backend et deployment restent hors scope.
## Transition
### PASS
Produire `history/0.1.1/alpha.5.md`, l'appliquer puis committer/pousser `alpha.5`. Continuer avec `0.1.1-beta.1` pour la réconciliation large, le dry-run proportionné du skeleton Web et la preuve factuelle de préparation du futur réexamen Tauri.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/alpha.5.md`, puis produire `alpha.5.fix.N` ou effectuer un REPLAN si le défaut révèle une frontière d'ownership incorrecte. Ne pas absorber `beta.1` dans un correctif CSS/Sass.

264
deltas/0.1.1/beta.1.md Normal file
View File

@@ -0,0 +1,264 @@
<!-- file: deltas/0.1.1/beta.1.md -->
<!-- version: 1 -->
# Delta 0.1.1-beta.1 — réconciliation Web et préparation du réexamen Tauri
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-alpha.5`, réalisé après application de `history/0.1.1/alpha.5.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-alpha.5
```
Version après application :
```text
0.1.1-beta.1
```
## Objet
Fermer la phase alpha de `0.1.1` en réconciliant la fondation frontend Web désormais matérialisée et en vérifiant factuellement si les cinq conditions de sortie du `DEFER` Tauri possèdent des owners PGR suffisants.
La tranche :
- enregistre le `PASS` de `alpha.5` dans le plan actif ;
- exécute un dry-run structurel du skeleton `003-WEB_FRONTEND.md` sans simuler les toolchains qu'un projet réel doit exécuter ;
- révise `002-TAURI_SKELETON_DECISION.md` pour comparer chacune des cinq conditions historiques aux owners réels `530/540/550/560`, guides, templates et validation désormais disponibles ;
- met à jour la roadmap pour distinguer « prérequis Web couverts » de « skeleton Tauri adopté » ;
- conserve le skeleton Tauri en `DEFER` jusqu'au réexamen autonome prévu en `0.1.4`.
Aucun profil Web, template technique, skeleton ou contrat de validation n'est modifié dans `beta.1`.
## Dry-run structurel du skeleton Web
Le dry-run vérifie uniquement ce que PGR peut prouver sans inventer un projet concret :
```text
skeleton 003 référence owners 530 / 540 / 550 / 560
skeleton 003 référence validation 005
package.json + tsconfig.json génériques se copient et se parsèrent comme JSON
aucun vite.config.ts universel n'est injecté
aucun main.scss universel n'est injecté
aucun host Tauri n'est injecté
aucune devDependency arbitraire n'est ajoutée au package.json générique
```
Cette preuve ne vaut pas type-check/build Sass/Vite. Une instanciation réelle doit sélectionner ses versions, dépendances, layout et configuration puis exécuter les outils propriétaires conformément à `005-WEB_FRONTEND_VALIDATION.md`.
## Réconciliation des cinq conditions Tauri
`docs/studies/002-TAURI_SKELETON_DECISION.md` enregistre désormais les correspondances suivantes :
```text
TypeScript contrôlé -> 530 + 008 + templates web-typescript
Vite/dev server/build outputs -> 550 + 009
CSS/Sass + artefacts générés -> 560 + 010
validation frontend indépendante du host -> validation 005
framework CSS = choix local -> 560 + skeleton 003
```
Les cinq prérequis sont donc **couverts pour préparer un réexamen**.
Cette conclusion ne signifie pas :
- que Vite, Sass, Bootstrap ou `frontend/` sont obligatoires pour Tauri ;
- que le candidat historique reste optimal en `0.1.4` ;
- que le corpus `0.0.5` peut être réutilisé sans réaudit ;
- que le skeleton Tauri est créé, adopté ou autorisé pendant `0.1.1`.
## Scope
REPLACE :
```text
VERSION
ROADMAP.md
docs/000-README.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
docs/studies/000-README.md
docs/studies/002-TAURI_SKELETON_DECISION.md
```
ADD :
```text
deltas/0.1.1/beta.1.md
```
DELETE : aucun.
`README.md`, `RULES.md`, `CHANGELOG.md`, les profils `530/540/550/560/710`, les skeletons, templates techniques, contrats de validation et scripts restent inchangés.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.5`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-beta.1'
git cat-file -e HEAD:history/0.1.1/alpha.5.md
test -f history/0.1.1/alpha.5.md
test -f deltas/0.1.1/beta.1.md
test ! -e history/0.1.1/beta.1.md
grep -A2 '^## Statut$' history/0.1.1/alpha.5.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 11 -->' ROADMAP.md
grep -Fx '<!-- version: 29 -->' docs/000-README.md
grep -Fx '<!-- version: 9 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 4 -->' docs/studies/000-README.md
grep -Fx '<!-- version: 2 -->' docs/studies/002-TAURI_SKELETON_DECISION.md
```
Réconciliation et dry-run structurel :
```bash
python3 -B - <<'PYGATE'
from pathlib import Path
import json
import re
import shutil
import tempfile
history = Path("history/0.1.1/alpha.5.md").read_text(encoding="utf-8")
assert re.search(r"## Statut\s+PASS\s", history)
plan = Path("docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### alpha.5 — CSS/Sass et validation frontend",
"Statut opérateur : **PASS**.",
"### beta.1 — réconciliation et preuve de préparation Tauri",
"Statut opérateur : **à valider**.",
"dry-run structurel du skeleton Web",
"Ce dry-run ne prétend pas remplacer `tsc`, Vite ou Sass",
):
assert phrase in plan, phrase
study = Path("docs/studies/002-TAURI_SKELETON_DECISION.md").read_text(encoding="utf-8")
for phrase in (
"DEFER",
"## Réexamen de préparation 0.1.1-beta.1",
"### Condition 1 — TypeScript et conventions Web contrôlées",
"### Condition 2 — Vite et ownership des commandes/dev server/build outputs",
"### Condition 3 — Sass/CSS et statut des artefacts générés",
"### Condition 4 — validation frontend indépendante de la validation Tauri",
"### Condition 5 — framework CSS classé comme décision de skeleton/projet",
"Les cinq conditions de sortie formulées en `0.0.5-alpha.9` possèdent désormais des owners PGR matérialisés et non redondants.",
"skeleton Tauri dans 0.1.1 toujours DEFER",
"réexamen autorisé 0.1.4",
"La présente étude ne préjuge pas de cette décision.",
):
assert phrase in study, phrase
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "skeleton Tauri jusqu'au réexamen 0.1.4" in roadmap
assert "0.1.1-beta.1` confirme que ses cinq prérequis Web disposent désormais d'owners PGR" in roadmap
assert "- `( ) 0.1.4`" in roadmap
assert "0.1.8" not in roadmap
skeleton = Path("docs/skeletons/003-WEB_FRONTEND.md").read_text(encoding="utf-8")
for phrase in (
"+ 530 TypeScript",
"+ 540 JavaScript package ecosystem",
"+ 550 Vite",
"+ 560 CSS / Sass",
"005-WEB_FRONTEND_VALIDATION.md",
"Le skeleton Tauri reste `DEFER` pendant `0.1.1`",
):
assert phrase in skeleton, phrase
package_source = Path("templates/web-typescript/package.json")
tsconfig_source = Path("templates/web-typescript/tsconfig.json")
with tempfile.TemporaryDirectory(prefix="pgr-web-skeleton-") as temp_name:
temp = Path(temp_name)
shutil.copy2(package_source, temp / "package.json")
shutil.copy2(tsconfig_source, temp / "tsconfig.json")
package = json.loads((temp / "package.json").read_text(encoding="utf-8"))
tsconfig = json.loads((temp / "tsconfig.json").read_text(encoding="utf-8"))
assert package == {
"name": "project-web",
"private": True,
"scripts": {"typecheck": "tsc --noEmit"},
}
assert tsconfig["compilerOptions"]["strict"] is True
assert tsconfig["compilerOptions"]["noEmit"] is True
assert "dependencies" not in package
assert "devDependencies" not in package
assert not (temp / "vite.config.ts").exists()
assert not (temp / "main.scss").exists()
assert not (temp / "src-tauri").exists()
assert not Path("templates/web-vite/vite.config.ts").exists()
assert not Path("templates/web-css/main.scss").exists()
assert Path("docs/rules/530-TYPESCRIPT.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 3 -->"
assert Path("docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 3 -->"
assert Path("docs/rules/550-VITE.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 2 -->"
assert Path("docs/rules/560-CSS_SASS.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 2 -->"
assert Path("docs/rules/710-TAURI.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 6 -->"
assert Path("docs/skeletons/003-WEB_FRONTEND.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 1 -->"
assert Path("docs/validation/005-WEB_FRONTEND_VALIDATION.md").read_text(encoding="utf-8").splitlines()[1] == "<!-- version: 1 -->"
print("0.1.1 beta.1 reconciliation audit: clean (Web skeleton composes structurally, five Tauri Web prerequisites covered, DEFER preserved for 0.1.4)")
PYGATE
```
Puis rejouer les preuves PGR :
```bash
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION ROADMAP.md docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
docs/studies/000-README.md docs/studies/002-TAURI_SKELETON_DECISION.md \
deltas/0.1.1/beta.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `beta.1` est exactement :
```text
M ROADMAP.md
M VERSION
A deltas/0.1.1/beta.1.md
M docs/000-README.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
M docs/studies/000-README.md
M docs/studies/002-TAURI_SKELETON_DECISION.md
```
## Revue opérateur complémentaire
Confirmer que :
- les cinq conditions historiques du `DEFER` Tauri sont toutes rattachées à des owners/artifacts PGR existants ;
- cette couverture est décrite comme préparation de `0.1.4`, pas comme promotion du skeleton Tauri ;
- le corpus Tauri devra être réexaminé en `0.1.4` au lieu d'être supposé inchangé ;
- le dry-run structurel ne prétend pas remplacer `tsc`, Vite, Sass ou un package manager réel ;
- aucun profil, skeleton, template technique ou contrat de validation n'est modifié dans `beta.1` ;
- `frontend/`, Vite, Sass, Bootstrap, npm, TS-RS et WASM ne deviennent pas des obligations Tauri ;
- `0.1.8` n'est pas réservé et l'horizon engagé reste inchangé.
## Transition
### PASS
Produire `history/0.1.1/beta.1.md`, l'appliquer puis committer/pousser `beta.1`. Continuer avec `0.1.1-rc.1` pour geler le scope, préparer l'entrée `CHANGELOG`, rejouer le release gate complet et vérifier le prompt de reprise `0.1.2` si la roadmap reste valide.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/beta.1.md`, puis produire `beta.1.fix.N` ou effectuer un REPLAN si la réconciliation révèle un owner Web manquant. Ne pas masquer une lacune en créant prématurément le skeleton Tauri.

331
deltas/0.1.1/rc.1.md Normal file
View File

@@ -0,0 +1,331 @@
<!-- file: deltas/0.1.1/rc.1.md -->
<!-- version: 1 -->
# Delta 0.1.1-rc.1 — gel du scope et gate de release candidate
## Baseline et version
Baseline attendue : commit opérateur de `0.1.1-beta.1`, réalisé après application de `history/0.1.1/beta.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.1-beta.1
```
Version après application :
```text
0.1.1-rc.1
```
## Objet et gel
La RC gèle le scope fonctionnel de `0.1.1` sur :
- les quatre owners indépendants `530 — TypeScript`, `540 — JavaScript package ecosystem`, `550 — Vite` et `560 — CSS / Sass` ;
- la baseline TypeScript/package avec `strict`, `noEmit`, script `typecheck`, politique de lockfile par rôle et déclarations de types externes conditionnelles ;
- Vite comme build tool/dev server recommandé mais non obligatoire, avec ownership explicite des caches, outputs, assets et limites d'exposition du dev server ;
- CSS comme baseline valide et Sass recommandé lorsqu'il apporte une valeur réelle, avec préférence `@use` / `@forward`, consommation des entrypoints publics et séparation source/généré ;
- la validation frontend `005` indépendante du host ;
- le skeleton Web `003` composable sans `vite.config.ts`, `main.scss`, package manager, framework CSS ou layout universels ;
- la preuve `beta.1` que les cinq prérequis Web du futur réexamen Tauri sont couverts, sans lever le `DEFER` avant `0.1.4`.
Le changelog reçoit une entrée candidate `0.1.1` orientée utilisateurs. Le prompt `008-V0_1_2_START_PROMPT.md` est préparé pour la prochaine cible engagée Java/Maven/Gradle avec frontière Android explicite.
Aucune nouvelle fonctionnalité normative n'entre dans cette RC. Les profils, skeletons, templates techniques et contrats de validation Web sont vérifiés mais non modifiés.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/000-README.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
ADD :
```text
deltas/0.1.1/rc.1.md
prompts/008-V0_1_2_START_PROMPT.md
```
DELETE : aucun.
Le history `beta.1` est livré séparément et MUST être appliqué/committé avant ce delta.
## Gate opérateur de release candidate
Après application du history `PASS` de `beta.1`, commit/push de `beta.1`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.1-rc.1'
git cat-file -e HEAD:history/0.1.1/beta.1.md
test -f history/0.1.1/beta.1.md
test -f deltas/0.1.1/rc.1.md
test -f prompts/008-V0_1_2_START_PROMPT.md
test ! -e history/0.1.1/rc.1.md
grep -A2 '^## Statut$' history/0.1.1/beta.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 12 -->' CHANGELOG.md
grep -Fx '## 0.1.1 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 30 -->' docs/000-README.md
grep -Fx '<!-- version: 10 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -Fx '<!-- version: 11 -->' ROADMAP.md
grep -Fx '<!-- version: 1 -->' prompts/008-V0_1_2_START_PROMPT.md
```
Contrôle d'intégration de la RC :
```bash
python3 -B - <<'PYGATE'
from pathlib import Path
import json
import re
import shutil
import tempfile
expected = {
"alpha.1.md": "PASS",
"alpha.2.md": "FAIL",
"alpha.2.fix.1.md": "PASS",
"alpha.3.md": "PASS",
"alpha.3.fix.1.md": "FAIL",
"alpha.3.fix.2.md": "PASS",
"alpha.4.md": "PASS",
"alpha.5.md": "PASS",
"beta.1.md": "PASS",
}
histories = {path.name for path in Path("history/0.1.1").glob("*.md")}
assert histories == set(expected), histories
for name, status in expected.items():
text = Path("history/0.1.1", name).read_text(encoding="utf-8")
assert re.search(rf"## Statut\s+{status}\s", text), (name, status)
deltas = {path.name for path in Path("deltas/0.1.1").glob("*.md")}
assert deltas == set(expected) | {"rc.1.md"}, deltas
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
assert "## 0.1.1 (candidate)" in changelog
section = changelog.split("## 0.1.1 (candidate)", 1)[1].split("## 0.1.0", 1)[0]
for phrase in (
"quatre owners indépendants",
"TypeScript",
"@types/*",
"package JavaScript",
"Vite",
"CSS comme baseline valide",
"Sass",
"validation frontend indépendante du host",
"DEFER",
"0.1.4",
):
assert phrase in section, phrase
for forbidden in (
"alpha.2",
"alpha.3",
"alpha.4",
"alpha.5",
"beta.1",
"rc.1",
):
assert forbidden not in section, forbidden
plan = Path("docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### beta.1 — réconciliation et preuve de préparation Tauri\n\nStatut opérateur : **PASS**.",
"### rc.1 — release candidate\n\nStatut opérateur : **à valider**.",
"prompts/008-V0_1_2_START_PROMPT.md",
"Aucune nouvelle fonctionnalité normative ne doit apparaître en RC.",
):
assert phrase in plan, phrase
prompt = Path("prompts/008-V0_1_2_START_PROMPT.md").read_text(encoding="utf-8")
for phrase in (
"archive source téléchargée depuis le tag Gitea `v0.1.1`",
"pgr-0.1.1-publish.001-report.md",
"0.1.2-alpha.1",
"ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8",
"520-JAVA_MAVEN_GRADLE.md",
"610-ANDROID.md",
"ADOPT / KEEP-LOCAL / OVERRIDE / DEFER",
"Gradle système versus Wrapper",
"Maven",
"Frontière Android obligatoire",
"réservé à `0.1.4`",
):
assert phrase in prompt, phrase
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
for version in ("0.1.1", "0.1.2", "0.1.3", "0.1.4", "0.1.5", "0.1.6", "0.1.7"):
assert f"- `( ) {version}`" in roadmap, version
assert "- `( ) 0.1.8`" not in roadmap
assert "skeleton Tauri jusqu'au réexamen 0.1.4" in roadmap
for path, version in (
("docs/rules/530-TYPESCRIPT.md", 3),
("docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md", 3),
("docs/rules/550-VITE.md", 2),
("docs/rules/560-CSS_SASS.md", 2),
("docs/rules/710-TAURI.md", 6),
("docs/skeletons/003-WEB_FRONTEND.md", 1),
("docs/validation/005-WEB_FRONTEND_VALIDATION.md", 1),
("docs/studies/002-TAURI_SKELETON_DECISION.md", 2),
):
lines = Path(path).read_text(encoding="utf-8").splitlines()
assert lines[1] == f"<!-- version: {version} -->", (path, lines[1])
study = Path("docs/studies/002-TAURI_SKELETON_DECISION.md").read_text(encoding="utf-8")
for phrase in (
"DEFER",
"Condition 1 — TypeScript et conventions Web contrôlées",
"Condition 2 — Vite et ownership des commandes/dev server/build outputs",
"Condition 3 — Sass/CSS et statut des artefacts générés",
"Condition 4 — validation frontend indépendante de la validation Tauri",
"Condition 5 — framework CSS classé comme décision de skeleton/projet",
"réexamen autorisé 0.1.4",
):
assert phrase in study, phrase
package_source = Path("templates/web-typescript/package.json")
tsconfig_source = Path("templates/web-typescript/tsconfig.json")
with tempfile.TemporaryDirectory(prefix="pgr-rc1-web-") as temp_name:
temp = Path(temp_name)
shutil.copy2(package_source, temp / "package.json")
shutil.copy2(tsconfig_source, temp / "tsconfig.json")
package = json.loads((temp / "package.json").read_text(encoding="utf-8"))
tsconfig = json.loads((temp / "tsconfig.json").read_text(encoding="utf-8"))
assert package == {
"name": "project-web",
"private": True,
"scripts": {"typecheck": "tsc --noEmit"},
}
assert tsconfig["compilerOptions"] == {
"strict": True,
"noEmit": True,
"noUnusedLocals": True,
"noUnusedParameters": True,
"noFallthroughCasesInSwitch": True,
}
assert not (temp / "vite.config.ts").exists()
assert not (temp / "main.scss").exists()
assert not (temp / "src-tauri").exists()
assert not Path("templates/web-vite/vite.config.ts").exists()
assert not Path("templates/web-css/main.scss").exists()
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "../prompts/008-V0_1_2_START_PROMPT.md" in index
print("0.1.1 rc.1 integration audit: clean (9 prior histories, frozen Web foundation, candidate changelog and prompt 008 verified)")
PYGATE
```
Rejouer ensuite les preuves PGR :
```bash
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
```
Vérifier également l'hygiène texte/JSON sans prétendre remplacer les toolchains frontend :
```bash
python3 -B - <<'PYHYGIENE'
from pathlib import Path
import json
json.loads(Path("templates/web-typescript/package.json").read_text(encoding="utf-8"))
json.loads(Path("templates/web-typescript/tsconfig.json").read_text(encoding="utf-8"))
roots = (
Path("VERSION"),
Path("README.md"),
Path("RULES.md"),
Path("ROADMAP.md"),
Path("CHANGELOG.md"),
Path("docs"),
Path("deltas"),
Path("history"),
Path("prompts"),
Path("templates"),
)
files = []
for root in roots:
if root.is_file():
files.append(root)
elif root.is_dir():
files.extend(path for path in root.rglob("*") if path.is_file())
for path in files:
try:
data = path.read_bytes()
text = data.decode("utf-8")
except UnicodeDecodeError:
continue
assert b"\r" not in data, path
assert text.endswith("\n"), path
for number, line in enumerate(text.splitlines(), 1):
assert line == line.rstrip(" \t"), (path, number)
print("0.1.1 rc.1 text/JSON hygiene: clean")
PYHYGIENE
git diff --check
git add VERSION CHANGELOG.md docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
prompts/008-V0_1_2_START_PROMPT.md \
deltas/0.1.1/rc.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history de `rc.1` est exactement :
```text
M CHANGELOG.md
M VERSION
A deltas/0.1.1/rc.1.md
M docs/000-README.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
A prompts/008-V0_1_2_START_PROMPT.md
```
## Revue opérateur complémentaire
Confirmer que :
- le scope normatif Web est gelé ;
- aucun owner `530/540/550/560`, skeleton, template technique ou contrat de validation n'est modifié par la RC ;
- le changelog candidat décrit les capacités utiles de `0.1.1` sans recopier les tranches internes ;
- TypeScript, Vite et Sass restent des recommandations conditionnelles et non des obligations universelles ;
- le prompt `008` réévalue le profil `520` avant de créer de nouveaux artefacts Java/Gradle ;
- le prompt `008` ne transforme pas les choix Android de Games en règles Java/Gradle générales ;
- Maven reste dans l'owner `520`, mais aucun nouvel artefact Maven n'est anticipé sans corpus réel ;
- le skeleton Tauri reste `DEFER` et son réexamen reste réservé à `0.1.4` ;
- `0.1.8` n'est pas réservé ;
- aucun résultat `tsc`, Vite ou Sass n'est revendiqué alors que PGR ne contient pas de frontend concret ni de dépendances installées pour cette RC.
## Transition
### PASS
Produire `history/0.1.1/rc.1.md`, l'appliquer puis committer/pousser `rc.1`. Continuer avec `0.1.1-rel.1` pour la promotion mécanique vers la stable, la clôture roadmap/plan/changelog et la gate pré-tag.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/rc.1.md`. Corriger uniquement la release candidate dans `rc.1.fix.N` tant qu'aucun défaut normatif plus large ne justifie un REPLAN. Ne pas préparer `rel.1` tant que la RC n'a pas obtenu `PASS`.

252
deltas/0.1.1/rel.1.md Normal file
View File

@@ -0,0 +1,252 @@
<!-- file: deltas/0.1.1/rel.1.md -->
<!-- version: 1 -->
# Delta 0.1.1 rel.1 — promotion stable pré-tag
## Baseline et version
Baseline : `0.1.1-rc.1`, avec `history/0.1.1/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.1.1-rc.1
```
Version après application :
```text
0.1.1
```
`rel.1` identifie la clôture opérationnelle ; il ne fait pas partie de la version SemVer du produit.
## Objet
Promouvoir mécaniquement la RC validée vers la stable `0.1.1` sans rouvrir le scope fonctionnel.
La tranche finalise uniquement la présentation et les métadonnées de release : version stable, roadmap terminée, changelog sans marqueur `candidate`, README/index en état stable et plan `007` historique. Aucun owner, profil, template, skeleton, validation, étude technique ou script d'audit n'est modifié.
La validation de cette tranche est **pré-tag**. Le tag `v0.1.1`, son archive source Gitea et le rapport `pgr-0.1.1-publish.001-report.md` ne sont pas déclarés existants par ce delta. Ils suivent uniquement un history `rel.1` `PASS`, le commit stable `0.1.1` et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
ADD :
```text
deltas/0.1.1/rel.1.md
```
DELETE : aucun.
Le history `rc.1` est livré séparément. Le history `rel.1` sera produit uniquement après la gate opérateur.
## Validation opérateur pré-tag
Après application sur le commit contenant `history/0.1.1/rc.1.md` :
```bash
test "$(cat VERSION)" = '0.1.1'
git cat-file -e HEAD:history/0.1.1/rc.1.md
test -f history/0.1.1/rc.1.md
test -f deltas/0.1.1/rel.1.md
test -f prompts/008-V0_1_2_START_PROMPT.md
test ! -e history/0.1.1/rel.1.md
grep -A2 '^## Statut$' history/0.1.1/rc.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 19 -->' README.md
grep -Fx '<!-- version: 12 -->' ROADMAP.md
grep -Fx '<!-- version: 13 -->' CHANGELOG.md
grep -Fx '<!-- version: 31 -->' docs/000-README.md
grep -Fx '<!-- version: 11 -->' docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
grep -F -- '- `(x) 0.1.1`' ROADMAP.md
grep -Fx '## 0.1.1' CHANGELOG.md
grep -F 'fondation frontend Web stable' README.md
grep -F 'plan historique de la stable `0.1.1`' docs/000-README.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
"alpha.1.md": "PASS",
"alpha.2.md": "FAIL",
"alpha.2.fix.1.md": "PASS",
"alpha.3.md": "PASS",
"alpha.3.fix.1.md": "FAIL",
"alpha.3.fix.2.md": "PASS",
"alpha.4.md": "PASS",
"alpha.5.md": "PASS",
"beta.1.md": "PASS",
"rc.1.md": "PASS",
}
for name, status in expected.items():
delta = Path("deltas/0.1.1", name)
history = Path("history/0.1.1", name)
assert delta.is_file(), name
assert history.is_file(), name
text = history.read_text(encoding="utf-8")
assert re.search(rf"## Statut\s+{status}\s", text), (name, status)
pending = {path.name for path in Path("deltas/0.1.1").glob("*.md")} - {
path.name for path in Path("history/0.1.1").glob("*.md")
}
assert pending == {"rel.1.md"}, pending
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "- `(x) 0.1.1`" in roadmap
for version in ("0.1.2", "0.1.3", "0.1.4", "0.1.5", "0.1.6", "0.1.7"):
assert f"- `( ) {version}`" in roadmap, version
assert "- `( ) 0.1.8`" not in roadmap
assert "skeleton Tauri jusqu'au réexamen 0.1.4" in roadmap
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
assert "## 0.1.1" in changelog.splitlines()
assert "## 0.1.1 (candidate)" not in changelog
section = changelog.split("## 0.1.1", 1)[1].split("## 0.1.0", 1)[0]
for forbidden in ("alpha.2", "alpha.3", "alpha.4", "alpha.5", "beta.1", "rc.1", "rel.1"):
assert forbidden not in section, forbidden
readme = Path("README.md").read_text(encoding="utf-8")
assert "fondation frontend Web stable" in readme
assert "plan historique de la fondation frontend Web stable `0.1.1`" in readme
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "plan historique de la stable `0.1.1`" in index
assert "à utiliser seulement après publication et vérification post-tag de `0.1.1`" in index
plan = Path("docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md").read_text(encoding="utf-8")
assert "### rc.1 — release candidate\n\nStatut opérateur : **PASS**." in plan
assert "history/0.1.1/rel.1.md" in plan
assert "pgr-0.1.1-publish.001-report.md" in plan
assert "commit `0.1.1` avant le tag `v0.1.1`" in plan
prompt = Path("prompts/008-V0_1_2_START_PROMPT.md").read_text(encoding="utf-8")
assert "tag Gitea `v0.1.1`" in prompt
assert "pgr-0.1.1-publish.001-report.md" in prompt
assert "0.1.2-alpha.1" in prompt
for path, version in (
("docs/rules/530-TYPESCRIPT.md", 3),
("docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md", 3),
("docs/rules/550-VITE.md", 2),
("docs/rules/560-CSS_SASS.md", 2),
("docs/rules/710-TAURI.md", 6),
("docs/skeletons/003-WEB_FRONTEND.md", 1),
("docs/validation/005-WEB_FRONTEND_VALIDATION.md", 1),
("docs/studies/002-TAURI_SKELETON_DECISION.md", 2),
):
lines = Path(path).read_text(encoding="utf-8").splitlines()
assert lines[1] == f"<!-- version: {version} -->", (path, lines[1])
workflow = Path("docs/rules/210-WORKFLOW.md").read_text(encoding="utf-8")
assert "history rel.1 FAIL / PARTIAL / BLOCKED" in workflow
assert "premier history rel.N[/fix.M] PASS qui établit réellement la stable" in workflow
assert "commit X.Y.Z" in workflow
print("0.1.1 rel.1 stable gate audit: clean (10 prior histories, rel.1 pending, stable Web presentation and post-tag handoff coherent)")
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B scripts/audit_markdown_links.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
python3 -B - <<'PYHYGIENE'
from pathlib import Path
import json
json.loads(Path("templates/web-typescript/package.json").read_text(encoding="utf-8"))
json.loads(Path("templates/web-typescript/tsconfig.json").read_text(encoding="utf-8"))
roots = (
Path("VERSION"), Path("README.md"), Path("RULES.md"), Path("ROADMAP.md"), Path("CHANGELOG.md"),
Path("docs"), Path("deltas"), Path("history"), Path("prompts"), Path("templates"),
)
files = []
for root in roots:
if root.is_file():
files.append(root)
elif root.is_dir():
files.extend(path for path in root.rglob("*") if path.is_file())
for path in files:
try:
data = path.read_bytes()
text = data.decode("utf-8")
except UnicodeDecodeError:
continue
assert b"\r" not in data, path
assert text.endswith("\n"), path
for number, line in enumerate(text.splitlines(), 1):
assert line == line.rstrip(" \t"), (path, number)
print("0.1.1 rel.1 text/JSON hygiene: clean")
PYHYGIENE
git diff --check
git add VERSION README.md ROADMAP.md CHANGELOG.md docs/000-README.md \
docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md \
deltas/0.1.1/rel.1.md
git diff --cached --check
git status --short
```
Le scope attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M README.md
M ROADMAP.md
M VERSION
A deltas/0.1.1/rel.1.md
M docs/000-README.md
M docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md
```
La RC a déjà reconfirmé le dry-run structurel Web, les owners gelés et le contrat du prompt `008`. Comme `rel.1` ne modifie aucun artefact technique frontend, la promotion stable ne simule pas de nouvelle exécution `tsc`/Vite/Sass sans projet concret ; elle rejoue les tests PGR, les audits documentaires et l'hygiène des artefacts.
## Revue opérateur complémentaire
Confirmer que :
- le scope fonctionnel de `rc.1` ne change pas ;
- `0.1.1` est présenté comme stable de manière cohérente dans VERSION/README/ROADMAP/CHANGELOG/index/plan ;
- les `FAIL` historiques `alpha.2` et `alpha.3.fix.1` restent conservés avec leurs fixes `PASS` ;
- les owners Web `530/540/550/560`, le skeleton Web et la validation Web restent gelés ;
- le skeleton Tauri reste `DEFER` jusqu'au réexamen `0.1.4` ;
- la roadmap engagée `0.1.2` à `0.1.7` reste intacte sans `0.1.8` ;
- le prompt `008` reste conditionnel à une vraie publication de `v0.1.1` et à un rapport post-tag `PASS` réel ;
- aucune preuve post-tag n'est anticipée.
## Transition
### PASS
Produire séparément `history/0.1.1/rel.1.md`, l'appliquer, puis créer le commit stable sous le message exact :
```text
0.1.1
```
Après push de la branche canonique, créer et publier le tag annoté `v0.1.1`. Vérifier localement et à distance l'objet tag et son commit déréférencé. Télécharger ensuite l'archive source depuis le tag Gitea et la fournir au générateur avec les sorties Git de publication afin de produire `pgr-0.1.1-publish.001-report.md` à partir de preuves réelles.
Le prompt `008-V0_1_2_START_PROMPT.md` ne devient la reprise effective de `0.1.2` qu'après un rapport post-tag `PASS`.
### FAIL
Consigner le diagnostic réel dans `history/0.1.1/rel.1.md`, ne pas créer le tag et corriger uniquement la fermeture dans `rel.1.fix.1` avant toute publication.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md -->
<!-- version: 4 -->
<!-- version: 31 -->
# Documentation PGR
@@ -10,7 +10,9 @@ Ce fichier est l'index d'entrée de la documentation structurée de Project Gove
- [`objectives/`](objectives/) — mission, objectifs durables, non-objectifs et contraintes globales ;
- [`architecture/`](architecture/) — état architectural courant de PGR et profils applicables ;
- [`plans/`](plans/) — plans vivants des releases en cours, puis références historiques après fermeture ;
- [`studies/`](studies/) — études bornées utilisées pour comparer des corpus, instruire une décision ou conserver une analyse avant normalisation ;
- [`rules/`](rules/) — règles normatives détaillées, organisées progressivement par scope ;
- [`skeletons/`](skeletons/) — spécifications Markdown de composition et d'initialisation de projets ;
- [`templates/`](templates/) — instructions d'adaptation des templates techniques et spécification du message manuel de reprise ;
- [`validation/`](validation/) — matrices de validation et contrats de preuve.
@@ -18,9 +20,48 @@ D'autres collections telles que `ideas/`, `studies/`, `reference/` ou `formats/`
Les templates techniques copiables sous `templates/` restent séparés des instructions documentaires sous `docs/templates/`. Les répertoires workflow de racine (`deltas/`, `history/`, `handoffs/`, `manifests/`, `prompts/`, `scripts/`) restent séparés de `docs/` parce qu'ils portent le processus de développement et de livraison lui-même.
## Points d'entrée de 0.0.3
## Points d'entrée de 0.1.1
- [`plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md`](plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md) — plan historique de la stable `0.1.1`, de l'audit des corpus à la fondation Web composable et à la préparation du futur réexamen Tauri.
- [`rules/530-TYPESCRIPT.md`](rules/530-TYPESCRIPT.md), [`rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md), [`rules/550-VITE.md`](rules/550-VITE.md) et [`rules/560-CSS_SASS.md`](rules/560-CSS_SASS.md) — owners frontend matérialisés par `0.1.1-alpha.2`, séparant langage typé, écosystème de package, build tool et styles.
- [`templates/008-WEB_TYPESCRIPT_PACKAGE.md`](templates/008-WEB_TYPESCRIPT_PACKAGE.md) — adaptation de la baseline minimale `package.json` + `tsconfig.json` de `alpha.3`, sans package manager, versions ou bundler imposés.
- [`templates/009-WEB_VITE.md`](templates/009-WEB_VITE.md) — guide d'adaptation Vite de `alpha.4` : root, dev server, cache, outputs, assets et scripts sans imposer de layout ni de port universels.
- [`templates/010-WEB_CSS_SASS.md`](templates/010-WEB_CSS_SASS.md) — guide CSS/Sass de `alpha.5` : sources, modules Sass, packages de styles et artefacts générés sans imposer de framework CSS.
- [`validation/005-WEB_FRONTEND_VALIDATION.md`](validation/005-WEB_FRONTEND_VALIDATION.md) — validation frontend réutilisable et indépendante du host : restore, type-check, build/styles et smoke proportionné.
- [`skeletons/003-WEB_FRONTEND.md`](skeletons/003-WEB_FRONTEND.md) — specialization Web composable fondée sur les owners `530/540/550/560`, sans imposer Vite, Sass, npm, Bootstrap ou un layout unique.
- [`studies/002-TAURI_SKELETON_DECISION.md`](studies/002-TAURI_SKELETON_DECISION.md) — décision `DEFER` conservée ; `beta.1` vérifie que ses cinq prérequis Web sont désormais couverts et prépare leur réexamen objectif en `0.1.4` sans créer le skeleton Tauri.
- [`studies/003-V0_1_0_HORIZON_REVIEW.md`](studies/003-V0_1_0_HORIZON_REVIEW.md) — revue ayant engagé `0.1.1` à `0.1.7` et maintenu WASM, serveur Rust et deployment sans réservation prématurée.
- [`../prompts/007-V0_1_1_START_PROMPT.md`](../prompts/007-V0_1_1_START_PROMPT.md) — contrat de reprise autoritaire de la release `0.1.1`.
- [`../prompts/008-V0_1_2_START_PROMPT.md`](../prompts/008-V0_1_2_START_PROMPT.md) — prompt de reprise préparé pour réévaluer Java/Maven/Gradle en `0.1.2`, à utiliser seulement après publication et vérification post-tag de `0.1.1`, avec frontière Android explicite.
## Points d'entrée de 0.1.0
- [`plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md`](plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md) — plan historique de la stable `0.1.0`, depuis l’audit de `v0.0.5` jusqu’à la baseline réutilisable, la clôture/publication et la revue d’horizon.
- [`templates/006-OPERATOR_COMMAND_HANDOFF.md`](templates/006-OPERATOR_COMMAND_HANDOFF.md) — pattern de remise automatique des commandes entre history, commit/push, delta suivant, tag et vérification post-tag.
- [`rules/230-ADOPTION.md`](rules/230-ADOPTION.md) — contrat d’adoption proportionnée de PGR par un projet existant sans réécriture rétroactive de son historique.
- [`templates/007-EXISTING_PROJECT_ADOPTION.md`](templates/007-EXISTING_PROJECT_ADOPTION.md) — pattern court de baseline, mapping `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`, découpage et validation d’une migration existante.
- [`validation/004-RUST_CARGO_BASELINE_DRY_RUN.md`](validation/004-RUST_CARGO_BASELINE_DRY_RUN.md) — contrat de dry-run temporaire pour vérifier la composition d’un nouveau workspace Rust/Cargo et l’adoption non destructive d’un workspace existant.
- [`studies/003-V0_1_0_HORIZON_REVIEW.md`](studies/003-V0_1_0_HORIZON_REVIEW.md) — revue d’horizon de `beta.1` engageant `0.1.1` à `0.1.7` par domaines cohérents et laissant WASM, serveur Rust et deployment sans réservation prématurée.
- [`../prompts/007-V0_1_1_START_PROMPT.md`](../prompts/007-V0_1_1_START_PROMPT.md) — prompt de reprise préparé pour la fondation frontend Web `0.1.1`, à utiliser seulement après publication et vérification post-tag de `0.1.0`.
## Points d'entrée de 0.0.5
- [`plans/005-V0_0_5_RECONCILIATION_PLAN.md`](plans/005-V0_0_5_RECONCILIATION_PLAN.md) — périmètre et décisions de la release `0.0.5` ;
- [`studies/001-KSP_GAMES_RECONCILIATION.md`](studies/001-KSP_GAMES_RECONCILIATION.md) — inventaire comparatif des baselines KSP/Games et décisions de généralisation, maintien local ou différé.
- [`studies/002-TAURI_SKELETON_DECISION.md`](studies/002-TAURI_SKELETON_DECISION.md) — décision `alpha.9` sur la maturité du skeleton Tauri contrôlé et ses prérequis Web encore manquants.
- [`templates/004-FILE_FAMILY_CONTRACTS.md`](templates/004-FILE_FAMILY_CONTRACTS.md) — pattern facultatif pour expliciter les responsabilités et règles de modification de familles de fichiers locales lorsque la complexité le justifie.
- [`templates/005-RELEASE_PLAN.md`](templates/005-RELEASE_PLAN.md) — pattern de plan de release avec clôture/transition explicites et revue d'horizon proportionnée.
- [`validation/002-RUST_STYLE_AUDITS.md`](validation/002-RUST_STYLE_AUDITS.md) et [`validation/003-RUST_EXPORT_COMPLETENESS.md`](validation/003-RUST_EXPORT_COMPLETENESS.md) — contrats et limites des audits Rust monotâches réconciliés depuis les corpus réels.
- [`rules/700-FRAMEWORKS.md`](rules/700-FRAMEWORKS.md) et [`rules/710-TAURI.md`](rules/710-TAURI.md) — activation de la famille framework et premier profil Tauri 2 issu de la réconciliation KSP/Games.
- [`../prompts/006-V0_1_0_START_PROMPT.md`](../prompts/006-V0_1_0_START_PROMPT.md) — prompt de reprise préparé pour la première baseline réutilisable `0.1.0`, à utiliser seulement après publication et vérification post-tag de `0.0.5`.
## Points d'entrée de 0.0.4
- [`plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md`](plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md) — périmètre et décisions de la release `0.0.3` ;
- [`plans/004-V0_0_4_SKELETONS_PLAN.md`](plans/004-V0_0_4_SKELETONS_PLAN.md) — périmètre et décisions de la release `0.0.4` ;
- [`skeletons/000-README.md`](skeletons/000-README.md) — contrat de collection des skeleton specifications ;
- [`skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md`](skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md) — fondation de gouvernance locale composable et sans spécialisation technologique ;
- [`skeletons/002-RUST_CARGO_WORKSPACE.md`](skeletons/002-RUST_CARGO_WORKSPACE.md) — specialization Rust/Cargo workspace composable avec la fondation et les cinq templates existants ;
- [`templates/001-RUST_CARGO_TOOLING.md`](templates/001-RUST_CARGO_TOOLING.md) et [`templates/002-CARGO_MANIFESTS.md`](templates/002-CARGO_MANIFESTS.md) — adaptation des cinq fichiers Rust/Cargo copiables ;
- [`templates/003-NEW_SESSION_PROMPT.md`](templates/003-NEW_SESSION_PROMPT.md) — spécification du message manuel après une stable publiée ;
- [`validation/001-VALIDATION_MATRIX.md`](validation/001-VALIDATION_MATRIX.md) et [`validation/002-RUST_STYLE_AUDITS.md`](validation/002-RUST_STYLE_AUDITS.md) — gates PGR et limites des audits de style Rust facultatifs.
- [`validation/001-VALIDATION_MATRIX.md`](validation/001-VALIDATION_MATRIX.md), [`validation/002-RUST_STYLE_AUDITS.md`](validation/002-RUST_STYLE_AUDITS.md) et [`validation/003-RUST_EXPORT_COMPLETENESS.md`](validation/003-RUST_EXPORT_COMPLETENESS.md) — gates PGR et limites des audits Rust facultatifs.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/002-GOVERNANCE_ARCHITECTURE.md -->
<!-- version: 2 -->
<!-- version: 4 -->
# Architecture de gouvernance PGR
@@ -25,9 +25,9 @@ Après instanciation, le projet possède sa copie et ne dépend plus de PGR.
Un skeleton est une recette Markdown décrivant comment initialiser un type de projet ou composer plusieurs profils.
Il décrit notamment les profils applicables, la structure requise ou optionnelle, les templates à utiliser, les points de décision, la politique de version et la validation de base.
Il décrit notamment les profils applicables, la structure requise ou optionnelle, les templates à utiliser, les points de décision, la politique de version et la validation de base. Le contrat transversal de sélection et de composition appartient à [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md) ; les spécifications concrètes sont indexées sous [`../skeletons/`](../skeletons/000-README.md).
Un skeleton n'est pas un générateur et ne doit pas figer l'évolution future du projet.
Un skeleton n'est pas un générateur et ne doit pas figer l'évolution future du projet. Il orchestre des owners normatifs et des artefacts existants sans devenir lui-même propriétaire d'une règle déjà possédée ailleurs.
### Audit
@@ -44,17 +44,37 @@ Le flux conceptuel est :
```text
PGR rules + templates + skeleton specifications
↓
sélection humaine / IA
applicabilité + décisions du projet
↓
nouveau projet
copie / adaptation contrôlée
↓
copies et règles locales
validation de la baseline
↓
projet autonome et gouverné
```
Une évolution ultérieure de PGR ne modifie jamais automatiquement les projets déjà créés.
## Adoption d’un projet existant
Un dépôt déjà existant ne repasse pas artificiellement par le flux d’instanciation. Son adoption part de sa baseline réelle et compare les owners PGR applicables avec les contrats locaux avant toute migration. Le mapping utilise la classification `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`.
Le flux conceptuel est :
```text
baseline autoritaire du projet
↓
inventaire + owners PGR applicables
↓
ADOPT / KEEP-LOCAL / OVERRIDE / DEFER
↓
migration progressive + validation
↓
projet autonome avec historique préservé
```
Le contrat normatif appartient à [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md). Un skeleton MAY servir de référence de comparaison, mais l’adoption ne prétend pas que le projet existant a été créé depuis ce skeleton et ne réécrit pas rétroactivement ses snapshots historiques.
## Hiérarchie
Les règles générales sont raffinées par les scopes plus spécifiques. Un choix spécialisé, par exemple une contrainte Tauri Android, ne devient pas automatiquement une règle Android ou Java générale.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/003-RULE_PROFILE_MODEL.md -->
<!-- version: 2 -->
<!-- version: 6 -->
# Modèle de profils de règles PGR
@@ -117,6 +117,16 @@ Cette relation interne ne modifie pas la hiérarchie globale. Une contrainte de
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.
@@ -194,10 +204,50 @@ Aucune contradiction non résolue de même niveau n'a été identifiée entre le
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 future
## Owners frontend matérialisés en `0.1.1`
Les futures skeleton specifications sélectionneront les profils applicables et recopieront leurs règles pertinentes dans la baseline locale du projet créé.
L'audit Games/KSP et la revue opérateur de `0.1.1-alpha.1` justifient quatre owners distincts dans la famille `500` :
Le projet instancié restera autonome : la composition de profils sert à construire sa baseline initiale, pas à créer une dépendance dynamique vers PGR.
```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.

View File

@@ -0,0 +1,158 @@
<!-- file: docs/plans/004-V0_0_4_SKELETONS_PLAN.md -->
<!-- version: 3 -->
# Plan 0.0.4 — skeleton specifications et composition
## Statut et sources
Plan historique créé pendant `0.0.4-alpha.1` après audit indépendant de la stable publiée `v0.0.3` demandé par `prompts/004-V0_0_4_START_PROMPT.md`. Les tranches `alpha.1` à `alpha.3` sont `PASS`. `alpha.4` a enregistré `FAIL` sur sa gate d'instanciation, puis `alpha.4.fix.1` a corrigé cette gate et est `PASS`. `beta.1` a enregistré `FAIL` sur une erreur de syntaxe de sa gate de réconciliation, puis `beta.1.fix.1` a rejoué la réconciliation et est `PASS`. La gate opérateur de `rc.1` est `PASS` : intégration documentaire, prompt `005`, cinq TOML et instanciation temporaire Rust/Cargo avec `cargo metadata`, `fmt`, `check` et `clippy -D warnings` ont été validés. Le scope fonctionnel est gelé et `rel.001` ne réalise qu'une promotion stable pré-tag.
La baseline autoritaire est l'archive source fournie `pgr-v0.0.3.zip`, déclarée téléchargée depuis le tag Gitea `v0.0.3`. Son SHA-256 vérifié pendant le cadrage est :
```text
517fb46ada098fdc221ae53a8ff4b409b81e0244ec5ce4d0e6fca0c3da61b866
```
Le rapport externe `pgr-0.0.3-publish.001-report.md` est fourni séparément, conclut `PASS` et annonce le même hash. Il atteste une vérification post-tag distincte et ne fait pas partie de la stable. L'archive source ne contient pas `.git`, ce qui est conforme au contrat de reprise ; l'identité du commit et du tag décrite dans le rapport n'est pas déduite du contenu du ZIP.
Les règles applicables au cadrage sont `RULES.md`, les familles `200`, `210`, `300`, `400`, `500`, `510`, `520`, `600`, `610`, ainsi que `docs/architecture/003-RULE_PROFILE_MODEL.md`. Les guides `docs/templates/001` à `003`, les cinq modèles Rust/Cargo, les trois audits Markdown et les deux audits facultatifs de style Rust complètent l'inventaire réel de la stable.
## Audit indépendant de la stable `v0.0.3`
L'archive fournie est lisible et son contenu distribué est cohérent dans les contrôles effectués :
- SHA-256 égal au rapport post-tag ;
- `140` entrées ZIP : `115` fichiers et `25` répertoires, avec une seule racine `pgr/` ;
- test CRC propre, aucun doublon, aucune collision de casse, aucun chemin absolu ou avec traversée `..`, aucun chemin Windows ambigu et aucun lien symbolique ;
- extraction propre de `115` fichiers ; `VERSION` contient exactement `0.0.3` suivi d'un retour à la ligne ; `.git` est absent comme attendu ;
- les fichiers distribués sont UTF-8, sans octet NUL, retour CR, espace de fin de ligne ou retour final manquant ;
- aucun chemin distribué de build/cache ou secret contrôlé n'est présent ; `.settings/org.eclipse.core.resources.prefs` reste l'exception Eclipse versionnée prévue ;
- `99` fichiers Markdown possèdent des headers `file/version` mécaniquement conformes ;
- les trois audits Markdown sont propres : `99` fichiers pour les headers, `3` tableaux et `79` liens locaux ;
- les `15` tests Python ciblés réussissent ;
- les cinq fichiers TOML sous `templates/rust-cargo/` se parsèrent correctement ;
- les deux audits de style Rust facultatifs n'ont pas de corpus Rust produit à inspecter dans PGR ; leur comportement est couvert par `tests/test_rust_audits.py` et leur sélection doit rester explicite dans un projet destinataire.
La chaîne workflow est complète :
```text
0.0.1 : 12 deltas / 12 histories
0.0.2 : 12 deltas / 12 histories
0.0.3 : 10 deltas / 10 histories
```
Chaque delta possède son history homonyme. Les histories `0.0.3`, de `alpha.1` à `rel.001`, sont tous `PASS`. Les échecs historiques des séries antérieures sont conservés comme snapshots et sont suivis par leurs corrections explicites ; ils ne sont pas réécrits rétroactivement.
Les limites annoncées restent visibles et cohérentes : l'audit des liens ne valide pas les anchors, l'audit des headers ne juge pas la pertinence sémantique d'une révision, les audits Rust utilisent une analyse lexicale ciblée et l'archive source ne prouve pas elle-même une référence Git distante. Aucun de ces points ne constitue un défaut bloquant de la stable.
## Revue des règles, profils et propriétaires
La hiérarchie normative reste cohérente avec le modèle de profils : règles générales, langage/écosystème, plateforme, puis scopes plus spécifiques et exceptions explicites. Aucun profil n'est applicable par simple fréquence ou provenance historique.
Les responsabilités utiles à `0.0.4` sont distinctes :
- `200` possède le lifecycle et le rôle de `alpha.1` comme gate de cadrage ;
- `210` possède plans, deltas, histories, prompts, baselines et séparation pré-tag/post-tag ;
- `300` possède rôles documentaires, documents vivants, snapshots et headers ;
- `400` possède la sélection proportionnelle des preuves et l'autorité du gate opérateur ;
- `500` et `600` possèdent les contrats communs des profils langage et plateforme ;
- `510`, `520` et `610` possèdent respectivement Rust/Cargo, Java/Maven/Gradle et Android ;
- `docs/architecture/003-RULE_PROFILE_MODEL.md` possède le modèle de composition et interdit les profils composites sans contrat propre réel.
La séparation règle / template / skeleton / audit de `docs/architecture/002-GOVERNANCE_ARCHITECTURE.md` reste adaptée. `0.0.4` doit l'étendre par des artefacts concrets sans déplacer les propriétaires normatifs existants.
## Inventaire des capacités disponibles pour des skeletons
### Fondation gouvernée PGR — prête à être spécifiée
Une baseline de projet gouverné constitue une fondation composable, pas une architecture applicative. Les contrats nécessaires existent déjà : versioning, workflow, documentation, validation et modèle de profils. Le skeleton devra indiquer quels artefacts locaux créer ou copier, comment sélectionner les règles réellement applicables et quelles décisions restent propres au projet.
Il ne doit pas recopier l'historique de PGR, imposer toutes les familles de règles ni créer une dépendance dynamique vers le dépôt PGR.
### Rust/Cargo workspace — prêt à être spécifié
Le besoin est suffisamment couvert par des artefacts réels : profil `510`, deux guides d'adaptation, cinq templates Rust/Cargo et deux audits de style facultatifs documentés. Le skeleton pourra composer une fondation gouvernée avec `500 + 510` et sélectionner uniquement les templates nécessaires.
Les décisions destinataire restent explicites : nom du projet et des crates, version de release, édition/toolchain, métadonnées de publication, membres du workspace, dépendances et features, politique `Cargo.lock`, chemin des artefacts Cargo, seuils Clippy, politique de lints et sélection éventuelle des audits de style. Les valeurs d'exemple `0.1.0`, `2024`, `project-name`, `project-core-lib`, les seuils Clippy et les chemins de build ne deviennent jamais universels.
### Java / Maven / Gradle — différé
Le profil `520` définit des règles, mais PGR ne possède encore aucun template Maven/Gradle ou corpus technique éprouvé à instancier. Le choix Maven/Gradle, la politique de wrapper et les versions de toolchain doivent être déterminés dans un chantier justifié avant de produire un skeleton concret.
### Android — différé
Le profil `610` définit la structure de responsabilité et les décisions Android, mais aucun template AGP/Gradle, manifest applicatif, matrice SDK ou projet réel n'existe dans PGR. Un skeleton Android serait prématuré avant ces pièces et avant la sélection explicite de sa composition avec Java/Gradle ou un autre stack réel.
### Web, JNI, Tauri et autres familles absentes — différés
Ces domaines ne possèdent pas encore tous leurs propriétaires normatifs et templates nécessaires. `0.0.4` ne crée pas de profils ou skeletons placeholders pour eux.
## Contrat visé pour une skeleton specification
La tranche de composition devra fixer un contrat commun minimal. Chaque skeleton doit au moins permettre d'identifier :
```text
applicabilité et objectif
profils/règles sélectionnés
fichiers à créer, copier ou adapter
templates applicables et source de leurs choix
décisions obligatoires propres au destinataire
options et exceptions explicites
ordre de composition
validation initiale proportionnée
éléments volontairement hors scope
```
Un skeleton reste une procédure Markdown. Il ne génère pas le projet, ne télécharge pas de dépendances, ne remplace pas les toolchains et ne fige pas l'architecture future. Après instanciation, le projet possède ses copies locales et ses décisions.
Les règles communes de sélection et de composition doivent avoir un propriétaire normatif unique sous `docs/rules/`. Les spécifications concrètes vivront dans une collection documentaire dédiée créée seulement avec son premier contenu réel. Les fichiers techniques copiables restent sous `templates/` et leurs instructions d'adaptation sous `docs/templates/`.
## Découpage prévisionnel de `0.0.4`
### alpha.1 — audit de stable et cadrage
Vérifier indépendamment `v0.0.3`, le rapport post-tag, les règles `200` à `610`, les cinq templates Rust/Cargo, les trois audits Markdown, les deux audits Rust facultatifs et la chaîne de deltas/histories. Inventorier les skeletons réellement justifiés et fixer le présent plan avant toute matérialisation importante.
### alpha.2 — contrat de composition des skeletons
Créer le propriétaire normatif des règles de sélection et de composition des skeletons, puis la collection documentaire des skeleton specifications avec son index. Définir la frontière entre règles copiées/adaptées, templates techniques, décisions propres au projet, overrides et validation. Réconcilier les index et l'architecture sans créer encore de domaine technologique supplémentaire.
Le nom et le numéro exacts du document normatif seront choisis à l'application selon la responsabilité finale ; le plan ne transforme pas un chemin prévisionnel en règle déjà active.
### alpha.3 — fondation de projet gouverné
Matérialiser une première specification composable décrivant la baseline de gouvernance locale d'un projet utilisant PGR : version, règles sélectionnées, documentation minimale, workflow réellement retenu et validation initiale. Elle doit rester proportionnée et permettre d'omettre les collections ou artefacts sans contenu réel.
Cette fondation n'est ni un framework ni une architecture applicative et ne doit pas recopier les deltas, histories ou décisions propres au dépôt PGR.
### alpha.4 — skeleton Rust/Cargo workspace
Matérialiser la première specialization technologique en composant la fondation gouvernée avec `500 + 510`, les cinq templates Rust/Cargo et les guides d'adaptation existants. Documenter les décisions destinataire avant copie et les audits facultatifs explicitement sélectionnés.
La gate doit inclure une instanciation temporaire minimale ou une vérification équivalente lorsque la toolchain Rust est disponible, afin de distinguer la validité syntaxique des templates de leur adoption correcte. Cette preuve ne transforme pas PGR lui-même en workspace Rust.
### beta.1 — réconciliation interne
Vérifier ownership, liens, index, absence de duplication normative, non-universalisation des valeurs d'exemple, limites des audits et cohérence des deux premières specifications. Confirmer explicitement que Java/Android/Web/JNI/Tauri restent différés tant que leurs pièces requises manquent.
Aucun chantier de réconciliation complète avec KSP ou Games n'entre ici : la roadmap réserve cette mission à `0.0.5`.
La première gate `beta.1` a enregistré `FAIL` uniquement parce qu'une chaîne Python de contrôle contenait une apostrophe non échappée. `beta.1.fix.1` a corrigé la gate sans modifier de contenu vivant et a confirmé la réconciliation : owners distincts, trois documents skeletons seulement, valeurs Rust/Cargo adaptables, limites des audits explicites, cinq TOML valides et domaines différés toujours absents.
### rc.1 — gate de release candidate
Geler le scope, préparer l'entrée `0.0.4` du changelog et le prompt `005` de `0.0.5` si la trajectoire est confirmée. Rejouer les validations documentaires, tests et smokes réellement invalidés par la release.
Le scope gelé comprend le contrat transversal `220-SKELETONS.md`, l'index de collection, la fondation gouvernée `001`, la spécialisation Rust/Cargo `002` et l'utilisation des cinq templates Rust/Cargo déjà présents. Aucun nouveau domaine technologique, générateur, template, audit ou règle normative n'entre en RC. La trajectoire `0.0.5` reste celle de la roadmap : réconciliation réelle de PGR avec `khadhroony-solana-project` et `sasedev-games`, à partir de baselines explicites qui devront être fournies à cette future session plutôt que déduites d'un état local implicite.
### stable — 0.0.4
La gate opérateur de `rc.1` est `PASS`. Le delta `rel.001` prépare mécaniquement la stable `0.0.4` : `VERSION`, présentation du dépôt et des index, statut de la roadmap, conversion de l'entrée candidate du changelog et clôture du présent plan comme référence historique. Aucun nouveau skeleton, profil, template, audit ou domaine technologique n'est ajouté pendant cette promotion.
Le résultat réel de la gate pré-tag appartient à `history/0.0.4/rel.001.md`, produit après exécution opérateur. Le commit stable et le tag `v0.0.4` suivent uniquement un `PASS`. La vérification de l'archive effectivement publiée depuis Gitea et le rapport `pgr-0.0.4-publish.001-report.md` constituent ensuite une preuve post-tag séparée ; ils ne sont pas présumés par le delta ni par le history pré-tag.
## Points de décision et stratégie de validation
Un REPLAN devient nécessaire si la fondation gouvernée exige des templates génériques inexistants pour rester actionnable, si le contrat de composition duplique des règles existantes au lieu de les référencer, si le skeleton Rust impose une architecture plus étroite que le profil `510`, ou si l'instanciation minimale révèle qu'un template technique ne peut pas être adopté sans nouvelle décision normative.
Les tranches documentaires utilisent les trois audits Markdown et les contrôles Git applicables. Toute modification des scripts ou de leurs contrats rejoue leurs tests ciblés. Toute modification d'un template Rust/Cargo vérifie sa syntaxe et, lorsqu'elle prétend à une instanciation fonctionnelle, une gate Cargo proportionnée dans un environnement temporaire. Aucun build Java/Android n'est demandé tant qu'aucun artefact concret de ces écosystèmes n'entre dans le scope.

View File

@@ -0,0 +1,222 @@
<!-- file: docs/plans/005-V0_0_5_RECONCILIATION_PLAN.md -->
<!-- version: 16 -->
# Plan 0.0.5 — réconciliation réelle avec KSP et sasedev-games
## Statut et sources
Plan historique créé pendant `0.0.5-alpha.1` conformément à `prompts/005-V0_0_5_START_PROMPT.md`. La release a confronté PGR à deux baselines autoritaires fournies sans présumer qu'elles avaient déjà adopté PGR.
Sources contrôlées :
```text
pgr-v0.0.4.zip 7137bb084f017362323a2043d13ba71490be15b8786adc8d645981bf455b80ae
khadhroony-solana-project-v0.3.16.zip db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0
games-v0.3.5.zip 5f5fdee1a271386766d059657d6eaa831acdc263b3e722fed738808335c0a105
```
Le rapport externe `pgr-0.0.4-publish.001-report.md` est `PASS` et annonce le même hash pour la stable PGR. L'étude détaillée et les limites de l'environnement sont consignées dans [`../studies/001-KSP_GAMES_RECONCILIATION.md`](../studies/001-KSP_GAMES_RECONCILIATION.md).
## Mission et garde-fous
`0.0.5` doit améliorer PGR à partir des besoins réellement répétés dans KSP et Games sans transformer leurs conventions historiques en règles universelles.
Les deux projets ne sont pas encore gouvernés par PGR. Par conséquent :
- aucune divergence de leurs archives n'est qualifiée de défaut PGR par défaut ;
- aucune migration de KSP ou Games n'appartient au scope de cette release ;
- aucune ancienne tranche, nomenclature ou chaîne history n'est reconstruite rétroactivement ;
- tout nouvel owner PGR doit correspondre à un besoin réutilisable et non à un simple copier-coller de projet ;
- les règles métier, architecture, protocoles, distribution et infrastructure spécifiques restent locales.
## Résultat du cadrage alpha.1
L'audit classe la majorité des mécanismes de gouvernance, documentation, validation et Rust/Cargo comme déjà `OWNED` par PGR. Les améliorations candidates réellement communes sont bornées à quatre axes :
1. **prompt de démarrage de projet** : le contrat actuel de `210-WORKFLOW.md` est plus minimal que les prompts opératoires éprouvés dans les deux corpus ;
2. **contrats documentaires locaux** : les deux projets utilisent un registre de responsabilités de fichiers/familles qui peut devenir un pattern facultatif de la fondation ;
3. **façade Rust et export completeness** : les deux projets partagent pratiquement le même audit spécialisé, alors que PGR n'en fournit pas encore de version réutilisable ;
4. **Tauri** : le framework est utilisé indépendamment et de manière répétée dans les deux corpus, ce qui fournit enfin une base réelle pour activer la famille framework `700` sans généraliser Vite/Web/JNI au-delà des preuves disponibles.
Les audits composites, le Web autonome, WASM, JNI, règles serveur, distribution Games et frontières métier KSP restent différés ou locaux.
## REPLAN alpha.4 — lifecycle inter-release et horizon
La gate `alpha.3.fix.1` a validé son correctif local. Une revue séparée du plan, de `ROADMAP.md` et des historiques de conception PGR `0.0.1` à `0.0.4` a ensuite confirmé un besoin général non couvert explicitement par le forecast initial : PGR sait piloter une release active, mais n'assigne pas encore assez strictement **où/quand sa fermeture et sa transition sont préparées**, ni **quand l'horizon des versions futures doit être rediscuté**.
Les historiques montrent que plusieurs briques avaient déjà été décidées séparément — moment du `CHANGELOG`, `ROADMAP`, prompt suivant, `REPLAN`, abandon/supersession, continuation inter-session, handoff et distinction `rel.001`/`publish.001`. Le problème n'est donc pas d'inventer un second workflow, mais de les relier dans le contrat du plan et d'éviter qu'elles restent implicites.
Ce constat déclenche le point de décision `REPLAN` prévu par `alpha.1`. Aucun travail antérieur n'est invalidé. Les anciennes tranches `alpha.4` à `alpha.6` sont décalées d'un numéro et restent dans le scope.
## Trajectoire prévisionnelle
### alpha.1 — audit indépendant, étude et plan
Vérifier la stable PGR, son rapport post-tag et les deux archives externes ; exécuter les audits statiques disponibles ; classifier les écarts ; créer l'étude et le présent plan. Aucun changement normatif, script réutilisable, profil framework ou skeleton nouveau dans cette tranche.
### alpha.2 — contrat générique des prompts de démarrage
Renforcer l'owner `210-WORKFLOW.md` pour les prompts versionnés sans recopier les règles locales KSP/Games. Fournir une spécification réutilisable couvrant au minimum : baseline autoritaire, ordre de lecture, état déjà validé, mission/résultat, scope/hors-scope, décisions gelées/ouvertes, première gate, trajectoire prévisionnelle et validations.
Le template manuel `003-NEW_SESSION_PROMPT.md` reste distinct : il sert au court message remis après publication, alors que cette tranche porte le prompt versionné du projet.
### alpha.3 — pattern de contrats de fichiers/familles
Étendre `300-DOCUMENTATION.md` et la fondation `001` uniquement si nécessaire pour décrire un registre local facultatif des fichiers ou familles dont le rôle et les règles de modification méritent d'être explicites. Fournir une spécification/template documentaire courte plutôt qu'un catalogue universel.
Le pattern ne doit pas imposer `FILE_CONTRACTS.md` à un petit projet, ni recopier les rôles déjà possédés par PGR. Le correctif `alpha.3.fix.1` a en outre renforcé l'audit des tables Markdown fenced sans modifier ce scope fonctionnel.
### alpha.4 — REPLAN : clôture, transition et revue d'horizon
Formaliser le lifecycle inter-release qui manquait au plan initial :
- imposer à un plan de release suffisamment complexe d'attribuer noir sur blanc les responsabilités de clôture/transition ;
- définir la revue d'horizon sans imposer un nombre artificiel de versions futures ;
- expliciter le passage `idea/study → décision durable → roadmap/plan` ;
- confirmer qu'une discussion stratégique peut vivre dans une session séparée sans changer `VERSION` ;
- rendre spontané le message manuel de reprise lorsque la prochaine cible est connue ;
- permettre la livraison `history courant + delta suivant` dans une même réponse lorsque la suite est déterministe, tout en maintenant deux archives et l'ordre commit/apply ;
- fournir un pattern réutilisable de plan de release pour l'adoption future dans KSP, Games et d'autres projets.
Cette tranche ne commence pas l'audit Rust ni le profil Tauri.
### alpha.5 — audit Rust de façade/export completeness
Extraire le noyau réellement commun de `audit_rust_export_completeness.py`, l'aligner avec `510-RUST_CARGO.md`, documenter son caractère facultatif et ses limites, et ajouter des tests positifs/négatifs.
La réconciliation a révélé que le script historique ne découvrait que `crates/*/Cargo.toml` : il couvrait les `22` packages KSP mais aucun des `23` packages Games imbriqués sous des sous-familles. La variante PGR corrige donc la découverte récursive et distingue aussi les cibles `lib`/`bin` d'un même package pour ne pas confondre plusieurs crates Rust compilées séparément.
La première livraison `alpha.5` a ensuite révélé un second défaut de scope pendant la revue opérateur : elle ne détectait que les chemins internes longs tels que `crate::module::Item`, alors que le contrat attendu impose `crate::Item` pour **toute référence intra-crate à un item partagé**, y compris un nom nu dans son module propriétaire. La gate mécanique était verte mais l'acceptation fonctionnelle est donc `FAIL`; `alpha.5.fix.1` corrige ce blind spot sans commencer Tauri.
Mesure `alpha.5.fix.1` en `--report-only --summary-only` : KSP `0.3.16` = `1525` lignes candidates `RUST-IMPORT-201` sur `22` packages ; Games `0.3.5` = `181` lignes candidates sur `23` packages (`2 RUST-API-201`, `179 RUST-IMPORT-201`). Ces nombres forment un inventaire d'adoption future, pas une non-conformité rétroactive des baselines.
Cette tranche ne réimporte pas `audit_rust_general_rules.py` en bloc et ne réintroduit pas le diagnostic historique de résolution `crate::X` déjà possédé par le compilateur. Toute autre règle déjà possédée par Rustfmt, Clippy, le compilateur ou les audits PGR existants reste chez son owner actuel.
### alpha.6 — premier profil framework : Tauri
La preuve commune est confirmée : `6` applications Tauri KSP et `2` applications Tauri Games partagent Tauri 2, un host Rust/Cargo, `tauri-build`, `tauri.conf.json`, des capability files, des hooks frontend et un `frontendDist`. Les valeurs applicatives divergent suffisamment pour exclure toute copie de ports, fenêtres, CSP, bundles, plugins ou commandes frontend particulières.
La première livraison active `700-FRAMEWORKS.md` et `710-TAURI.md`, mais la gate opérateur est `FAIL` pour deux raisons : le contrôle Python ciblé du delta contient une chaîne multilignes invalide et la revue fonctionnelle exige de mieux distinguer le profil Tauri universel des conventions d'instanciation des projets contrôlés. `alpha.6.fix.1` corrige donc le gate et explicite que le host Tauri hérite intégralement des règles Rust sélectionnées, que WASM reste normalement une unité séparée et que l'ajout manuel de plugins à partir de leur documentation officielle est une stratégie valide.
Les préférences récurrentes de l'organisation — frontend sous `frontend/`, Vite, TypeScript, Sass, Bootstrap et contrôle explicite des dépendances — sont consignées comme **candidat de skeleton**, pas comme invariants de `710-TAURI.md`. Un projet imposé de l'extérieur peut conserver une structure différente via ses règles project-specific.
La politique `gen/` n'est pas généralisée : les sorties purement reproductibles restent générées, mais les projets mobiles modifiés intentionnellement doivent être classifiés selon leur rôle réel. L'échec du POC Tauri mobile Games ne constitue pas un rejet général de Tauri Android/iOS pour les autres produits.
La gate `alpha.6.fix.1` révèle un second défaut de quoting Python (`l'extérieur` dans une chaîne simple) et la revue opérateur demande une seconde passe sur les règles réelles KSP/Games. `alpha.6.fix.2` corrige le gate et renforce la convention des projets contrôlés avec le layout direct sans `src-tauri/`, `lib.rs`/`main.rs`/`tauri.rs`, TS-RS lorsque le frontend TypeScript partage des DTO Rust, modules de fenêtres/responsabilités et préférence pour l'intégration explicite des plugins. Les règles Rust générales et la nomenclature des crates restent volontairement dans `alpha.7/alpha.8`.
La gate mécanique de `alpha.6.fix.2` est propre, mais la revue fonctionnelle révèle une troisième divergence : KSP et Games avaient tous deux converti la réduction du churn de version en préférence pour l'absence de `tauri.conf.json > version` et la stagnation de `package.json`. Cette solution ne doit pas devenir une règle PGR. `alpha.6.fix.3` restaure la classification générale `CANONICAL` / `MIRROR-EXACT` / `MIRROR-STABLE` et définit pour Tauri/frontend une synchronisation de jalon `X.Y.Z` par défaut, sans bump à chaque tranche.
Comme `fix.3` atteint le seuil de revue obligatoire des correctifs, le plan est réexaminé : résultat `CONTINUE`. Le scope Tauri reste cohérent et borné après cette correction ; les chantiers Rust `alpha.7`/`alpha.8` et la décision de skeleton `alpha.9` restent séparés et ne sont pas absorbés par le fix.
### alpha.7 — profil Rust strict, chemins et nomenclature explicite
La réconciliation des règles versionnées KSP/Games retient KSP comme référence stricte et Games comme contrôle de généralisation. Pour une nouvelle baseline contrôlée, `510-RUST_CARGO.md` impose désormais Rust 2024, réserve `use` aux traits réellement nécessaires, exige les chemins publics explicites les plus courts pour les autres symboles, les réexports internes `self::`, la façade crate-root et `crate::Item`, et conserve le contrôle de flux explicite sans `unwrap`, `expect` ni `?` en production.
La nomenclature des crates devient également explicite : préfixe projet/abréviation obligatoire ; responsabilité puis rôle/cible lisibles lorsque ce classificateur apporte une information réelle. La forme recommandée est `<project>-<responsibility>-<role-or-target>` sans figer les vocabulaires KSP/Games ni imposer de renommage rétroactif. Les projets externes ou historiquement contraints peuvent documenter un override borné.
Le skeleton Rust/Cargo et le guide de manifest reflètent ces choix. Aucun gros audit composite n'est importé ; le marqueur KSP spécifique des trait imports n'est pas généralisé et les contrôles déjà possédés par Clippy, rustc ou l'audit de façade restent chez leur owner.
La gate mécanique `alpha.7` est propre, mais la revue fonctionnelle post-gate montre que cette première matérialisation ne donnait pas encore de contrat architectural aux suffixes. `alpha.7.fix.1` complète donc la tranche sans la replanifier : `-api` devient un vrai contrat extensible/passif et n'est jamais créé par symétrie ; `-lib` identifie l'implémentation réutilisable ; les exécutables sont des packages distincts et minces par défaut ; `tracing` et un owner de logging commun sont fortement recommandés dans les workspaces multi-runtime. L'ancienne préférence KSP pour un worker mixte lib/bin n'est pas généralisée. Tauri reste l'exception framework actuelle et impose des noms de targets lib/bin réellement distincts.
### alpha.8 — formatage Rust structurel et audits monotâches
La réconciliation des anciens audits composites KSP/Games attribue désormais chaque propriété à un owner précis. Rustfmt reste propriétaire du formatage et du tri qu'il sait réellement réécrire dans un bloc contigu. Les audits PGR existants conservent `blank_lines` et `const_blocks`; quatre extractions monotâches complètent le profil : `item_spacing`, `module_order`, `trait_import_blocks` et `reexport_blocks`.
La mesure sur l'ensemble des sources `crates/**/*.rs` est propre pour les quatre nouveaux audits dans KSP `0.3.16` (`603` fichiers) et Games `0.3.5` (`87` fichiers). `blank_lines` est également propre sur ces corpus. `const_blocks` reste explicitement opt-in : son exécution globale remonte `18` signaux KSP, dont des tables/schémas à ordre intentionnel, contre `0` Games.
Le profil strict des nouvelles baselines contrôlées retient donc les règles mécaniques de lignes vides, séparation exacte des items distincts, modules production/tests, bloc de traits et blocs de réexports. PGR n'automatise pas un ordre global `enum → struct → impl → fn`, ni un tri visible/privé lorsque la structure métier peut être plus informative. Aucun parser Rust général ni audit composite n'est introduit.
### alpha.9 — décision de skeleton Tauri pour projets contrôlés — DEFER
La revue de readiness confirme que le host est suffisamment cadré : `510-RUST_CARGO.md` possède les règles Rust et le packaging, `710-TAURI.md` possède le layout contrôlé, l'exception `lib + bin`, `tauri.rs`, TS-RS à la frontière host/frontend, les plugins/capabilities, les versions produit et les gates d'orchestration Tauri. Les `8` hosts observés confirment également le layout direct sans `src-tauri/`, `frontend/`, Vite et TypeScript.
En revanche, PGR ne possède encore aucun profil Web/Vite/TypeScript/Sass. Le candidat organisationnel Vite + TypeScript + Sass + Bootstrap ne peut donc pas être instancié sans que le skeleton devienne de fait propriétaire de règles frontend, ce qui contredirait `220-SKELETONS.md` et le modèle de profils. La décision `alpha.9` est donc `DEFER` : aucun skeleton Tauri `003` n'est créé dans `0.0.5`.
Le futur skeleton reste un candidat explicite et devra au minimum composer la fondation de gouvernance, le skeleton Rust/Cargo, le profil Tauri et les owners Web alors disponibles. Il pourra ensuite sélectionner le layout direct, `frontend/`, Vite + TypeScript + Sass, Bootstrap comme baseline de présentation lorsque pertinente, TS-RS pour les DTO Rust partagés, intégration explicite des plugins/capabilities et séparation de WASM par défaut. Ces choix ne deviennent pas des règles Web dans la présente release.
La condition de sortie du `DEFER` est la matérialisation d'owners Web suffisants pour posséder la structure des sources frontend, la chaîne Vite/TypeScript, Sass/CSS, les artefacts de build et leur validation sans duplication normative dans le skeleton. La décision détaillée est enregistrée dans `docs/studies/002-TAURI_SKELETON_DECISION.md`.
### beta.1 — réconciliation intégrée
Rejouer la matrice de l'étude sur l'état PGR obtenu. Vérifier : owner unique, navigation, absence de règles KSP/Games aspirées par accident, caractère facultatif des patterns/audits concernés, cohérence des skeletons et domaines encore différés.
La réconciliation intégrée confirme que les owners créés ou renforcés par `0.0.5` restent bornés à leur responsabilité : prompt versionné, contrats documentaires facultatifs, lifecycle inter-release, profil/audits Rust stricts et profil Tauri. Les architectures métier KSP/Games, Android/JNI spécifique, Web autonome et distribution restent hors du noyau central tant qu'un owner réutilisable n'est pas justifié.
Le `DEFER` du skeleton Tauri contrôlé est suffisamment décidé pour devenir une trajectoire explicitement différée dans `ROADMAP.md`, sans numéro de release réservé. Les trois candidats plus larges de revue d'horizon restent volontairement hors de la roadmap engagée tant qu'une décision macro n'existe pas.
La mission `0.1.0` reste suffisamment connue : `prompts/006-V0_1_0_START_PROMPT.md` est préparé dans cette tranche comme prompt candidat de reprise. Il exige l'audit complet de la stable `0.0.5`, la consolidation d'un plan `0.1.0-alpha.1` proportionné et une revue d'horizon avant fermeture ; il ne transforme pas le skeleton Tauri différé en obligation de `0.1.0`.
Cette tranche réconcilie ainsi la documentation durable et confirme que le présent plan possède un contrat de fermeture exécutable avant `rc.1`.
La gate opérateur de `beta.1` est `PASS` : `48/48` tests Python, les trois audits Markdown, le contrôle d'intégration ciblé et les contrôles Git sont propres. La phase beta est donc fermée sans correctif.
### rc.1 — scope gelé et gate candidate
La RC gèle le scope fonctionnel de `0.0.5` sur les capacités déjà validées : contrats de reprise/lifecycle, profil Rust strict et ses audits monotâches, profil Tauri 2, réconciliation KSP/Games et décision `DEFER` du skeleton Tauri contrôlé. Aucun nouvel owner, skeleton, template, script d'audit ou domaine technique n'entre dans la candidate.
`CHANGELOG.md` reçoit l'entrée candidate `0.0.5` orientée utilisateurs. `ROADMAP.md` reste inchangé : `0.0.5` demeure en cours jusqu'à la promotion stable, `0.1.0` reste la prochaine release engagée et le skeleton Tauri reste `(d)` sans numéro de release. `prompts/006-V0_1_0_START_PROMPT.md` est vérifié comme prompt candidat de reprise et n'est pas modifié si son contrat est déjà correct.
La gate RC rejoue la suite Python complète, les audits Markdown et un contrôle d'intégrité historique de toutes les tranches `0.0.5`. Elle vérifie également la présence des owners/audits effectivement livrés et l'absence de skeleton Tauri `003`. Les validations lexicales déjà couvertes par la suite de tests ne sont pas dupliquées par un nouvel audit composite.
Aucune version postérieure à `0.1.0` n'est inventée à cette étape.
La gate opérateur de `rc.1` est `PASS` : `48/48` tests Python, les trois audits Markdown, le contrôle d'intégrité des `16` histories antérieurs et les contrôles Git sont propres. Le scope fonctionnel est donc gelé pour la promotion stable.
### stable — 0.0.5
Promouvoir mécaniquement la RC validée : synchroniser `VERSION`, README/index, `ROADMAP.md`, `CHANGELOG.md` et statut du présent plan sans ajouter de nouveau besoin commun. Après history PASS, commit et tag `v0.0.5`, vérifier séparément l'archive publiée.
La vérification post-tag doit produire, si le mécanisme reste retenu, `pgr-0.0.5-publish.001-report.md` extérieur au tag. Le message manuel final doit alors indiquer spontanément à l'opérateur de fournir l'archive taggée et ce rapport avec le prompt `006` lors de la session `0.1.0`.
La promotion `rel.001` clôt le présent plan sans modifier le scope fonctionnel : `VERSION = 0.0.5`, `ROADMAP.md` marque `0.0.5` terminé, le changelog perd son marqueur `candidate`, les index décrivent le plan comme historique et le prompt `006` reste conditionnel à la publication effective du tag et à son rapport post-tag PASS.
La gate opérateur de `rel.001` est toutefois `FAIL` pour un défaut strictement local à sa commande de validation : l'assertion Python qui cherchait le heading `## 0.0.5` a été livrée avec une chaîne simple coupée par un retour à la ligne et provoque `SyntaxError: unterminated string literal`. Les audits Markdown et les contrôles Git exécutés ensuite sont propres ; aucun défaut du contenu stable n'est établi. `rel.001.fix.1` corrige uniquement cette preuve de clôture, conserve `VERSION = 0.0.5` et ne rouvre pas le scope fonctionnel.
## Clôture et transition
Le présent plan attribue dès maintenant les responsabilités de fermeture :
- la documentation directement liée à chaque capacité évolue dans sa tranche ;
- `beta.1` réalise la réconciliation durable globale et prépare le prompt suivant si sa mission est connue ;
- `rc.1` porte le scope freeze, l'entrée `CHANGELOG` candidate, la vérification `ROADMAP` et le prompt suivant candidat ;
- `rel.001`/stable finalise `CHANGELOG`, marque `0.0.5` terminée dans `ROADMAP`, ferme le présent plan et effectue le promotion gate pré-tag ;
- `publish.001` vérifie l'archive réellement produite après le tag et fournit la preuve externe requise par la reprise suivante ;
- aucune de ces opérations ne doit être repoussée implicitement à la session `0.1.0`.
## Revue d'horizon
Pour PGR, la prochaine release engagée est `0.1.0 — première baseline réutilisable`. La trajectoire au-delà n'est pas suffisamment décidée et reste volontairement ouverte ; ce n'est pas un défaut de roadmap.
`0.0.5` ne doit donc pas inventer `0.1.1`, `0.2.0` ou un catalogue de versions futures. Le plan de `0.1.0-alpha.1` devra en revanche identifier un moment de revue d'horizon avant sa fermeture, une fois la baseline réutilisable suffisamment concrète pour juger la suite. Cette revue pourra se tenir dans une session stratégique séparée sans modifier `VERSION`.
Ses sorties autorisées seront : étendre la roadmap avec des objectifs réellement décidés, maintenir l'horizon ouvert avec un prochain déclencheur, différer/mettre en pause la trajectoire ou constater qu'un objectif macro est accompli.
Trois **candidats d'horizon**, sans numéro de release réservé ni engagement de réalisation, sont maintenant identifiés pour cette revue :
1. maturation de profils techniques composables par langage, framework, target/plateforme et préoccupation transverse — par exemple observability/logging, Web/TypeScript/Vite/Sass, Android, WASM, networking ou persistence — toujours à partir de corpus réels avant normalisation ;
2. profil de projet documentaire/spécification, avec `saselang-bible` comme corpus pilote possible pour tester gouvernance normative, terminologie, décisions, exemples, compatibilité et traduction lorsque la documentation est elle-même le produit ;
3. audit du noyau PGR hors développement logiciel afin d'identifier ce qui est réellement universel et ce qui doit rester dans un profil `software`, sans inventer les règles métier de domaines spécialisés.
Ces sujets restent au stade `horizon candidat`. Ils ne deviennent `Study`, `ROADMAP` ou plan de release qu'après décision explicite selon `300-DOCUMENTATION.md`.
## Points de décision
Un REPLAN est requis si :
- le contrat de prompt devient une copie exhaustive des règles plutôt qu'un artefact de reprise ;
- le pattern de contrats de fichiers ajoute plus de cérémonie qu'il n'en retire ;
- le lifecycle de clôture impose des documents ou versions futures sans valeur opérationnelle ;
- la revue d'horizon devient un quota de versions à prévoir plutôt qu'un mécanisme de décision ;
- l'audit de façade Rust ne peut pas être séparé proprement des conventions strictes KSP/Games ;
- le profil Tauri universel absorbe des choix de skeleton/frontend qui devraient rester project-specific ou appartenir à un owner Web ;
- la réconciliation Rust stricte ne peut pas être séparée en owners fiables et audits monotâches ;
- le skeleton Tauri n'apporte pas de décisions réutilisables au-delà du profil framework et des conventions explicites de projets contrôlés ;
- une autre divergence des corpus apparaît comme un besoin commun critique non couvert par ce plan.
## Stratégie de validation
Les tranches documentaires rejouent les trois audits Markdown et la suite Python PGR. Toute modification d'un script ajoute ou adapte des tests ciblés avant la suite globale. Les templates/configurations structurées sont parsés ou exercés avec l'outil le plus fiable disponible.
PGR ne compile pas KSP ou Games comme gate de sa propre release : ces projets servent de corpus de pression. Une validation croisée MAY exécuter leurs audits statiques sur leurs archives fournies lorsque cela vérifie une propriété précise, mais ne remplace jamais leurs propres gates opérateur.
La toolchain Cargo n'étant pas disponible dans l'environnement de préparation de `alpha.1`, aucune preuve Cargo externe n'est revendiquée pour cette tranche. La gate PGR reste documentaire et structurelle.

View File

@@ -0,0 +1,310 @@
<!-- file: docs/plans/006-V0_1_0_REUSABLE_BASELINE_PLAN.md -->
<!-- version: 10 -->
# Plan 0.1.0 — première baseline PGR réutilisable
## Statut et sources
Plan actif créé pendant `0.1.0-alpha.1` conformément à `prompts/006-V0_1_0_START_PROMPT.md` après audit indépendant de la stable taggée `v0.0.5` et de son rapport post-tag.
Sources autoritaires de reprise :
```text
pgr-v0.0.5.zip 1fb72bafb24b5a0f3406561b96caa8245142a5f099e692842d9ef1ba44f41b49
pgr-0.0.5-publish.001-report.md a6727fd1f3122dbb19eb79d6b904ebaed2bbfc360ed4a34cc1299cb2166efd96
```
Le rapport `publish.001` est `PASS` et porte sur cette même archive. L'absence de `.git` dans l'archive du tag est normale et n'est pas une validation manquante.
Deux corpus récents ont également été fournis pour préparer l'adoption future sans devenir des dépendances de la baseline `0.1.0` :
```text
games-v0.3.6.zip ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
khadhroony-solana-project-v0.3.16.zip db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0
```
Games `0.3.6` conserve explicitement `0.3.7` comme future release d'alignement PGR. KSP `0.3.16` reste principalement un corpus Rust/Cargo avec six applications Tauri ; aucune migration de Games ou KSP n'appartient à `0.1.0`.
## Audit de la stable `v0.0.5`
### Intégrité et chaîne historique
L'archive stable contient `225` entrées sous une racine unique `pgr/`, soit `194` fichiers et `31` répertoires. Son CRC est propre, aucun lien symbolique n'est présent et `.git` est absent comme attendu pour une archive de tag Gitea.
Les `62` couples delta/history des releases `0.0.1` à `0.0.5` sont complets :
```text
0.0.1 12 / 12
0.0.2 12 / 12
0.0.3 10 / 10
0.0.4 9 / 9
0.0.5 19 / 19
```
La vérité opérateur de `0.0.5` est conservée, notamment les `FAIL` intermédiaires et la fermeture finale `rel.001.fix.1` en `PASS`. Aucun ancien delta/history ne sera renommé rétroactivement lorsque la nouvelle convention `rel.N` sera introduite.
### Tests et audits
La stable passe :
```text
python3 -B -m unittest discover -s tests -v
48 tests PASS
Markdown header audit: clean (171 file(s))
Markdown table audit: clean (8 table(s), 171 file(s))
Markdown link audit: clean (161 local link(s), 171 file(s))
```
Les audits PGR restent monotâches et read-only : trois audits Markdown, six audits de style Rust, un audit Rust de façade/export completeness, plus leur helper commun. Aucun audit ne devient un wrapper de build.
### Règles, profils, templates et skeletons
La hiérarchie normative est cohérente et possède un owner explicite pour gouvernance, workflow, skeletons, documentation, validation, langages/écosystèmes, plateformes et frameworks.
Profils techniques déjà matérialisés :
```text
510 Rust / Cargo
520 Java / Maven / Gradle
610 Android
710 Tauri 2
```
La baseline possède cinq templates techniques Rust/Cargo sous `templates/rust-cargo/`, deux skeleton specifications concrètes — fondation de gouvernance et workspace Rust/Cargo — et les contrats de validation associés.
Le profil Rust/Cargo est suffisamment avancé pour servir rapidement de référence à Games et KSP. Les profils Java/Gradle et Android existent déjà normativement ; leur future release `0.1.x` devra donc d'abord réévaluer leur complétude pratique, leurs templates, skeletons et audits nécessaires au cas Games au lieu de recréer les profils depuis zéro.
Le profil Tauri `710` existe également, mais le skeleton Tauri contrôlé reste volontairement `DEFER` : il attend des owners Web suffisants pour TypeScript, Vite, Sass/CSS, sorties frontend et validation frontend indépendante.
## Défauts de gouvernance à corriger en 0.1.0
L'audit ne révèle pas de défaut bloquant de la stable, mais deux conventions doivent être corrigées avant de diffuser PGR plus largement.
### Clôture stable `rel.N`
L'expérience réelle de `0.0.5` montre que la convention actuelle `rel.001` mélange inutilement padding historique et identité de tranche. La convention future doit utiliser :
```text
rel.1
rel.1.fix.1
rel.2
...
```
Les anciens fichiers `rel.001*` restent immuables.
Le nom de tranche et le message du commit qui matérialise finalement la stable doivent être distingués. Par défaut PGR :
```text
rel.1 FAIL -> commit de tranche X.Y.Z-rel.1
rel.1.fix.1 FAIL -> commit de tranche X.Y.Z-rel.1.fix.1
première tranche qui obtient le PASS stable
-> commit final X.Y.Z
```
Le tag `vX.Y.Z` n'est créé qu'après ce commit final stable.
### Commandes opérateur et publication
Après production d'un history constaté, le générateur doit remettre spontanément les commandes exactes à exécuter entre l'application de ce history et le delta suivant. Le défaut PGR retenu est :
```bash
git add -A
git diff --cached --check
git status --short
git commit -m "<message attendu>"
git push origin <branche>
```
Le bloc doit être adapté au projet et au statut réel de la tranche ; il ne doit pas inventer une branche ou un remote lorsqu'ils ne sont pas établis.
Pour la dernière clôture pré-tag, le handoff opérateur doit en plus fournir le bloc de tag/vérification approprié et indiquer explicitement les preuves/artefacts à remettre pour générer la vérification post-tag, notamment l'archive issue du tag et les preuves Git réellement disponibles. Un tag annoté doit être vérifié sans confondre l'objet tag avec son commit déréférencé.
Après `publish.* PASS`, la consigne manuelle de nouvelle session reste produite automatiquement selon `docs/templates/003-NEW_SESSION_PROMPT.md`.
## Mission de `0.1.0`
`0.1.0` doit transformer la fondation `0.0.x` en baseline réellement réutilisable **sans absorber les domaines technologiques futurs**.
La release doit :
1. corriger la sémantique de clôture `rel.N` et des commits stables ;
2. rendre obligatoire le handoff automatique des commandes opérateur après chaque history et lors de la publication ;
3. formaliser une adoption proportionnée de PGR par un projet existant, distincte de l'instanciation d'un nouveau projet ;
4. vérifier que la fondation et le skeleton Rust/Cargo peuvent servir de baseline réutilisable sans dépendre de choix KSP/Games ;
5. effectuer avant RC une revue d'horizon qui engage uniquement les prochaines releases `0.1.x` suffisamment décidées.
`0.1.0` ne crée pas de profil Web, WASM, serveur Rust/Actix, Java, Android ou Tauri supplémentaire. Ces domaines seront traités séparément dans la série `0.1.x` lorsque leur release dédiée sera engagée.
## Direction acquise pour la série `0.1.x`
La série `0.1.x` doit rester composée de releases concrètes indépendantes, en pratique une release/session par domaine cohérent. Il est explicitement exclu de regrouper Web, serveur Rust, Java/Android, Tauri et WASM dans `0.1.0` ou dans une unique grosse release suivante.
La revue d'horizon de `0.1.0` devra ordonner et, seulement lorsque le scope est suffisamment décidé, numéroter les axes suivants :
- owners Web contrôlés : TypeScript, Vite, Sass/CSS, package manager/build outputs et validation frontend ;
- serveur Web Rust — Actix Web ou autre framework seulement à partir d'un besoin et d'un corpus réels, notamment pour les trajectoires HTTP/3 ;
- réévaluation pratique du profil Java/Gradle existant pour Games ;
- réévaluation pratique du profil Android existant pour Games ;
- WASM comme domaine séparé si l'adoption Games démontre qu'un owner PGR apporte une valeur immédiate ;
- levée du `DEFER` Tauri seulement après matérialisation des owners Web nécessaires ;
- adoption de PGR par Games dès que le sous-ensemble requis est réellement prêt ;
- adoption de PGR par KSP ensuite, avec une pression principalement Rust/Cargo + Tauri et sans attendre les profils non pertinents pour KSP.
Les numéros exacts `0.1.1`, `0.1.2`, etc. ne sont pas réservés dans `alpha.1`. Cette attribution appartient à la revue d'horizon lorsque l'ordre réel est suffisamment décidé.
Après cette vague d'adoption `0.1.x`, les axes plus larges — projets documentaires/spécifications tels que `saselang-bible`, généricité hors logiciel et autres familles technologiques — restent candidats pour une trajectoire `0.2.x`/`0.3.x` à décider ultérieurement, sans réservation artificielle aujourd'hui.
Deux horizons supplémentaires sont acquis comme **candidats différés**, sans numéro réservé :
- après application réelle de PGR à Games puis KSP, une release `0.1.x` non prioritaire pourra introduire des audits Python read-only reproduisant uniquement le sous-ensemble des conventions Rust/Clippy vérifiable statiquement sans Cargo ni `rustc`; ces audits devront utiliser les options PGR existantes, documenter explicitement les lints `FULL / LIMITED / UNSUPPORTED` et MUST NOT être présentés comme équivalents à `cargo clippy`, qui reste la validation autoritaire ;
- à plus long terme, une série dédiée au déploiement et à l'exploitation devra être étudiée, potentiellement dans un horizon `0.4.x` ou `0.5.x` mais sans réservation actuelle : reverse proxies tels que Nginx/Apache, bases PostgreSQL/MySQL ou autres, conteneurs Docker/Compose, hébergement Linux/services, environnements et secrets, migrations/backup, health/observabilité et skeletons/audits de déploiement composables.
Ces horizons ne modifient pas la mission de `0.1.0` et ne doivent pas être absorbés par les tranches courantes.
## Trajectoire prévisionnelle de `0.1.0`
### alpha.1 — audit de stable et plan
Statut opérateur : **PASS**.
La stable `v0.0.5`, son rapport post-tag, les owners normatifs, profils, templates, skeletons, audits, chaîne delta/history et décisions différées ont été vérifiés. Le cadrage a été consigné sans changement normatif ni migration externe.
### alpha.2 — clôture stable et identité `rel.N`
Statut opérateur : **FAIL**.
Le contenu normatif prévu a été matérialisé et le contrôle structurel spécifique a confirmé `rel.N` sans padding, la conservation des historiques `rel.001*` et l'identité explicite du commit stable. La gate livrée contenait toutefois des commandes `grep -F` entourées de quotes simples alors que certains motifs contenaient eux-mêmes des apostrophes (`n'utilise`, `l'exploitation`). Le shell a donc mal interprété plusieurs contrôles textuels.
Le défaut appartient à la gate opérateur, pas aux owners `200-GOVERNANCE` / `210-WORKFLOW`. Le delta `alpha.2.md` reste immuable.
### alpha.2.fix.1 — correction de la gate `rel.N`
Statut opérateur : **PASS**.
Le fix a conservé `200-GOVERNANCE.md`, `210-WORKFLOW.md` et le delta historique `alpha.2.md` inchangés. La preuve Python corrigée a reconfirmé la convention `rel.N`, le `FAIL` historique de `alpha.2`, les anciens artefacts `rel.001*` et l'indépendance de `publish.001`.
La validation a exécuté `48/48` tests et les trois audits Markdown sans diagnostic. Aucun nouveau fix ni REPLAN n'est requis.
### alpha.3 — handoff automatique des commandes opérateur
Statut opérateur : **FAIL**.
Le contenu prévu a été matérialisé : `210-WORKFLOW.md` possède le contrat normatif de remise automatique et `006-OPERATOR_COMMAND_HANDOFF.md` fournit la forme de rendu pour tranche ordinaire, échec + fix, clôture stable, tag et preuves `publish.*`. Les `48` tests et les trois audits Markdown sont restés propres.
La gate spécifique n'a toutefois pas pu s'exécuter jusqu'au bout : le littéral Python `'## Fermeture d'une tranche non stable'` utilisait des quotes simples autour d'un texte contenant l'apostrophe de `d'une`, provoquant `SyntaxError: unterminated string literal`. Le défaut appartient à la gate ; aucun défaut normatif du workflow ou du template n'est établi.
### alpha.3.fix.1 — correction de la gate du handoff opérateur
Statut opérateur : **PASS**.
Le fix a conservé `210-WORKFLOW.md`, `006-OPERATOR_COMMAND_HANDOFF.md`, l'index documentaire et le delta historique `alpha.3.md` inchangés. La gate corrigée a reconfirmé le `FAIL` historique de `alpha.3`, le contenu normatif du handoff et le pattern opérateur.
La validation a exécuté `48/48` tests et les trois audits Markdown sans diagnostic. Aucun nouveau fix ni REPLAN n'est requis.
### alpha.4 — adoption d'un projet existant
Statut opérateur : **PASS**.
Le nouvel owner `230-ADOPTION.md` et le pattern `007-EXISTING_PROJECT_ADOPTION.md` ont été validés avec le mapping `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`, la migration progressive et la préservation de l’historique. Les `48` tests et les trois audits Markdown sont propres.
Games et KSP restent des futurs consommateurs : aucune migration externe ni activation de profils non applicables n’a été introduite.
### alpha.5 — baseline réutilisable et dry-run de composition
Statut opérateur : **PASS**.
La fondation `001`, le skeleton Rust/Cargo `002`, les templates Rust/Cargo et la validation minimale ont été réconciliés. Les deux chemins du contrat `004-RUST_CARGO_BASELINE_DRY_RUN.md` ont été exécutés avec Cargo :
```text
NEW PASS — metadata/fmt/check/clippy sur instanciation temporaire
ADOPTION PASS — workspace synthétique valide et choix KEEP-LOCAL / DEFER préservés
```
Les `48/48` tests PGR et les trois audits Markdown sont restés propres. Games et KSP n'ont pas été utilisés comme fixtures et aucun profil technologique supplémentaire n'a été absorbé par la tranche.
### beta.1 — réconciliation finale et revue d'horizon
Statut opérateur : **PASS**.
La gate opérateur a confirmé la revue d'horizon, la roadmap `0.1.1` à `0.1.7`, le maintien des domaines différés sans numéro, le prompt `007` et les `48/48` tests PGR avec les trois audits Markdown propres.
La revue d'horizon est matérialisée dans `003-V0_1_0_HORIZON_REVIEW.md`. Elle engage une séquence par domaines cohérents :
```text
0.1.1 Web frontend
0.1.2 Java / Gradle
0.1.3 Android
0.1.4 Tauri contrôlé, sous condition de readiness Web
0.1.5 adoption Games
0.1.6 adoption KSP
0.1.7 audits Rust/Clippy statiques Python-only
```
WASM, serveur Rust et deployment restent non numérotés. Le prompt `007-V0_1_1_START_PROMPT.md` est préparé pour la cible suivante mais ne devient exécutable qu'après publication de `v0.1.0` et vérification post-tag `PASS`.
### rc.1 — release candidate
Statut opérateur : **PASS**.
La gate opérateur a confirmé le scope gelé, les huit histories antérieurs avec leurs statuts réels, les deux dry-runs Rust/Cargo via la toolchain réelle, le contrat d’adoption, la convention `rel.N`, le handoff opérateur, la roadmap et le prompt `007`. Les `48/48` tests et les trois audits Markdown sont propres. Aucun owner ni domaine technique nouveau n’est entré dans la RC.
### rel.1 — promotion stable
Première utilisation de la convention corrigée `rel.1`. La promotion est strictement mécanique : `VERSION = 0.1.0`, `ROADMAP.md` marque `0.1.0` terminée, le `CHANGELOG` perd son marqueur `candidate`, README/index décrivent la baseline comme stable et le présent plan devient historique. Aucun owner, profil, template, skeleton ou script technique n’est modifié.
Le résultat opérateur de cette tranche appartient à `history/0.1.0/rel.1.md`, créé seulement après exécution de la gate. Si `rel.1` échoue, son history est conservé et un `rel.1.fix.N` corrige uniquement la fermeture ; la première tranche qui établit réellement la stable est incluse dans le commit `0.1.0` avant le tag `v0.1.0`. La vérification post-tag reste séparée et doit produire `pgr-0.1.0-publish.001-report.md` uniquement à partir de l’archive et des preuves réellement publiées.
## Stratégie de validation
Chaque tranche documentaire rejoue au minimum :
```text
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py ...
python3 -B scripts/audit_markdown_tables.py ...
python3 -B scripts/audit_markdown_links.py ...
```
Les scripts d'audit restent read-only et ne déclenchent aucun build. Les changements de workflow doivent recevoir des contrôles structurels ciblés qui vérifient la nomenclature future sans imposer de renommer les snapshots historiques.
Le dry-run de composition `alpha.5` doit privilégier les parsers/outils officiels lorsque disponibles. Une prévalidation générateur ne remplace pas le gate opérateur.
## Déclencheurs de REPLAN
REPLAN est requis si :
- `0.1.0` commence à absorber Web, Android, WASM, Actix ou le skeleton Tauri au lieu de les laisser à des releases `0.1.x` distinctes ;
- la convention de commit stable ne peut pas être définie sans ambiguïté avec les histories `FAIL`/fix ;
- le handoff automatique dépend de valeurs Git qui ne peuvent pas être établies de manière sûre ;
- l'adoption d'un projet existant exige de modifier rétroactivement son historique ;
- le dry-run révèle que la fondation ou le skeleton Rust/Cargo n'est pas réellement autonome ;
- la revue d'horizon transforme des candidats en numéros réservés sans scope suffisamment décidé.
## Clôture et transition
- documentation durable du workflow : `alpha.2` à `alpha.4` ;
- preuve de réutilisabilité : `alpha.5` ;
- réconciliation documentaire et revue d'horizon : `beta.1` ;
- `CHANGELOG` candidate et release gate : `rc.1` ;
- promotion stable et nouveau contrat `rel.1` : `rel.1` ;
- tag/post-tag : après le commit stable `0.1.0`, avec handoff opérateur automatique ;
- prompt suivant : créé uniquement si `beta.1` a réellement engagé la prochaine cible `0.1.x`.
## Revue d'horizon
État : **validée `PASS` par la gate opérateur de `beta.1`**.
Décision proposée par la revue :
- engager `0.1.1` Web frontend ;
- engager séparément `0.1.2` Java/Gradle et `0.1.3` Android ;
- engager `0.1.4` comme release de domaine Tauri, avec obligation de reconfirmer la readiness Web avant toute matérialisation de skeleton ;
- engager `0.1.5` pour l'adoption Games puis `0.1.6` pour l'adoption KSP ;
- engager `0.1.7` pour les audits Rust/Clippy statiques Python-only après retour réel des deux adoptions ;
- conserver WASM et serveur Rust comme candidats sans numéro ;
- conserver `saselang-bible` et la généricité hors logiciel pour une trajectoire ultérieure ;
- conserver deployment/operations comme horizon majeur ultérieur sans réserver aujourd'hui `0.4.x` ou `0.5.x`.
La revue complète et ses critères de réouverture sont possédés par `../studies/003-V0_1_0_HORIZON_REVIEW.md`.

View File

@@ -0,0 +1,506 @@
<!-- file: docs/plans/007-V0_1_1_WEB_FRONTEND_FOUNDATION_PLAN.md -->
<!-- version: 11 -->
# Plan 0.1.1 — fondation frontend Web contrôlée
## Statut et sources
Plan actif créé pendant `0.1.1-alpha.1` conformément à `prompts/007-V0_1_1_START_PROMPT.md`, après audit indépendant de la stable taggée `v0.1.0`, de son rapport post-tag et du corpus Games réellement fourni.
Sources autoritaires de reprise PGR :
```text
pgr-v0.1.0.zip bc8f3a8117d04afc1280344eceaaac8c6a4724ca94c285a6234fe42c1023b2be
pgr-0.1.0-publish.001-report.md a64dc4a5a81e1776b641894d8493eec3ef315932fffb2881e52ff4147eb8b6a5
```
Le rapport `publish.001` est `PASS`, porte sur cette même archive et confirme le commit stable `2ed8742f3b26695bcd2d1efc07eebf0cb88ff51d`. Le tag annoté `v0.1.0` possède l'objet tag `372650ea9fe313e7d5389ed43cacb6faa5f18f74` et se déréférence vers ce commit stable. L'absence de `.git` dans l'archive du tag est normale.
Corpus principal réellement fourni pour instruire le domaine Web :
```text
games-v0.3.6(1).zip ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
```
Le nom local comporte `(1)`, mais son SHA-256 correspond exactement à la baseline canonique `games-v0.3.6.zip` enregistrée dans le prompt `007`. L'archive Games est donc le corpus autoritaire attendu pour cette étude.
Un corpus secondaire récent a également été fourni :
```text
khadhroony-solana-project-v0.3.17.zip 2a9cabcb9f147a348dcf8d24df8bc6c5029089b6d49feb17bd4a42b4293c329a
```
KSP `0.3.17` ne devient ni une baseline requise de `0.1.1`, ni une cible de migration. Il sert uniquement à corroborer, lorsque cela évite de généraliser un choix Games accidentel, les responsabilités frontend déjà observées derrière Tauri. Toute adoption KSP reste réservée à `0.1.6`.
## Audit de la stable `v0.1.0`
### Intégrité de l'archive et preuve post-tag
L'archive stable contient `254` entrées sous une racine unique `pgr/`, soit `221` fichiers et `33` répertoires. Son CRC est propre, aucun lien symbolique n'est présent et `.git` est absent comme attendu pour une archive de tag Gitea.
`VERSION` vaut exactement `0.1.0`. `CHANGELOG.md` contient l'entrée stable `0.1.0`, `ROADMAP.md` marque `0.1.0` terminé et engage `0.1.1` à `0.1.7` sans réserver `0.1.8`.
La convention de clôture introduite par `0.1.0` est cohérente :
```text
tranche de clôture rel.1
history rel.1 PASS
commit stable 0.1.0
tag v0.1.0
publish.001 preuve externe post-tag PASS
```
Aucun ancien artefact `rel.001*` n'est renommé rétroactivement.
### Tests, audits et hygiène
Les quatre suites Python présentes donnent :
```text
48 / 48 tests PASS
```
Les audits documentaires donnent :
```text
Markdown header audit: clean (198 file(s))
Markdown table audit: clean (8 table(s), 198 file(s))
Markdown link audit: clean (193 local link(s), 198 file(s))
```
Les cinq templates Rust/Cargo TOML sont parsables. Aucun répertoire de sortie courant tel que `target/`, `build/`, `builds/`, `dist/`, `node_modules/` ou `__pycache__/` n'est embarqué dans la stable.
Les scripts d'audit restent des contrôles read-only. Aucun audit PGR ne devient un générateur, un formateur ou un wrapper de build.
### Chaîne delta/history et vérité opérateur
Les `72` deltas publiés disposent tous d'un history correspondant :
```text
0.0.1 12 / 12
0.0.2 12 / 12
0.0.3 10 / 10
0.0.4 9 / 9
0.0.5 19 / 19
0.1.0 10 / 10
```
Pour `0.1.0`, la vérité opérateur reste explicitement conservée :
```text
alpha.1 PASS
alpha.2 FAIL
alpha.2.fix.1 PASS
alpha.3 FAIL
alpha.3.fix.1 PASS
alpha.4 PASS
alpha.5 PASS
beta.1 PASS
rc.1 PASS
rel.1 PASS
```
Les `FAIL` ne sont donc ni écrasés ni requalifiés après coup.
### Règles, profils, templates et skeletons
La hiérarchie normative courante reste cohérente : gouvernance, workflow, skeletons, adoption, documentation, validation, langages/écosystèmes, plateformes et frameworks possèdent des owners explicites.
Profils techniques déjà matérialisés :
```text
510 Rust / Cargo
520 Java / Maven / Gradle
610 Android
710 Tauri 2
```
La stable possède :
- cinq templates techniques Rust/Cargo sous `templates/rust-cargo/` ;
- deux skeleton specifications concrètes, gouvernance locale et workspace Rust/Cargo ;
- les templates documentaires de reprise, handoff opérateur et adoption d'un projet existant ;
- les contrats de validation Rust/Cargo et les audits Markdown/Rust monotâches.
Aucun owner Web générique n'existe encore. Il serait incorrect de faire porter TypeScript, Vite ou Sass/CSS par `710-TAURI.md` uniquement parce qu'un host Tauri utilise une WebView.
## Décisions différées vérifiées
`docs/studies/002-TAURI_SKELETON_DECISION.md` conserve correctement le skeleton Tauri en `DEFER`. Ses conditions de sortie exigent notamment :
```text
TypeScript et conventions Web contrôlées
Vite et ownership du dev server / build outputs
Sass/CSS et statut des artefacts générés
validation frontend indépendante de Tauri
choix d'un framework CSS classé comme décision de skeleton, pas comme règle Tauri
```
`docs/studies/003-V0_1_0_HORIZON_REVIEW.md` et `ROADMAP.md` engagent `0.1.1` pour cette fondation frontend, puis `0.1.2` Java/Gradle, `0.1.3` Android, `0.1.4` réexamen Tauri, `0.1.5` adoption Games, `0.1.6` adoption KSP et `0.1.7` audits Rust/Clippy statiques Python.
Les sujets suivants restent volontairement hors de cette release :
- WASM, sans numéro réservé ;
- serveur Web Rust / Actix Web ou alternative, sans numéro réservé et sans corpus d'implémentation suffisant ;
- deployment & operations, horizon futur sans numéro précis réservé ;
- création du skeleton Tauri contrôlé, réservée à un réexamen objectif en `0.1.4`.
La réussite de `0.1.1` devra produire les owners nécessaires à ce réexamen, mais ne lèvera pas automatiquement le `DEFER`.
## Audit du corpus Games `0.3.6`
### Intégrité et portée
L'archive fournie contient `652` entrées sous une racine unique `games/`, soit `502` fichiers et `150` répertoires. Son CRC est propre et aucun lien symbolique n'est présent.
Games n'est pas supposé conforme à PGR à ce stade. Les observations suivantes décrivent un corpus d'implémentation réel servant à décider ce qui mérite d'être généralisé ; elles ne transforment pas ses choix locaux en norme.
### Frontends exercés
Trois packages frontend sont présents :
```text
Web/game-snake-poc/
Web/game-realtime-webtransport-browser-smoke/
crates/apps/game-snake-poc-tauri/
```
Ils exercent tous :
- un `package.json` privé ;
- TypeScript ;
- Vite ;
- un `frontend/` distinct des configurations/outils du host ;
- un build de production combinant `tsc` et `vite build` lorsque la chaîne frontend elle-même est validée ;
- `cacheDir` et `outDir` placés sous `../builds/sasedev-games/...`, donc hors de l'arborescence source ;
- une séparation entre sources versionnées et sorties générées.
Les deux hosts navigateur directs utilisent en plus un mode `preview`. Le host Tauri ajoute des paramètres propres à son environnement de développement ; ces paramètres ne sont pas des règles Vite universelles.
### Styles et assets
`Web/game-snake-poc` exerce réellement Sass via `sass-embedded`, Bootstrap et une politique explicite de sorties CSS/assets. Le smoke WebTransport n'a besoin ni de Sass ni de Bootstrap. Le host Tauri Snake utilise Vite et la copie d'assets, mais son manifest actuel n'impose pas Sass.
La preuve Games indique donc :
```text
CSS responsabilité frontend générale
Sass capacité optionnelle, pas obligation universelle
framework CSS (Bootstrap) choix de présentation/skeleton ou projet, pas règle Web universelle
copie d'assets besoin Vite réel, mais configuration dépendante du projet
```
Un owner Sass/CSS doit expliquer les sources et artefacts générés sans exiger un préprocesseur sur les frontends qui n'en ont pas besoin.
### Package manager, manifest et lockfiles
Les packages exercés utilisent des commandes npm, mais le corpus ne justifie pas de rendre npm obligatoire dans PGR.
La racine Games ignore explicitement :
```text
**/node_modules/
**/dist/
package-lock.json
pnpm-lock.yaml
yarn.lock
```
Aucun lockfile Node n'est versionné dans l'archive. Cette politique est un choix Games actuel, pas une preuve qu'un lockfile frontend doit toujours être ignoré.
`alpha.3` retient une politique fondée sur le rôle :
- une application privée ou déployable `SHOULD` versionner le lockfile produit par son package manager afin de figer l'arbre réellement résolu ;
- une bibliothèque publiée `MAY` versionner un lockfile pour stabiliser l'environnement contributeur/CI, mais le manifest et ses contraintes restent le contrat de résolution des consommateurs ;
- un exemple, template ou fixture sans résolution de dépendances réelle `MAY` ne pas posséder de lockfile ;
- un même package `SHOULD NOT` conserver simultanément plusieurs lockfiles de package managers concurrents, sauf migration explicitement temporaire ;
- lorsqu'un lockfile est versionné, CI `SHOULD` utiliser le mode gelé/immutable/clean-install équivalent du package manager sélectionné plutôt qu'une résolution permissive.
L'absence actuelle de lockfiles dans Games devient donc une décision à réexaminer pendant l'adoption `0.1.5` : les packages applicatifs pourront `ADOPT` la recommandation en versionnant leur lockfile, ou documenter un `OVERRIDE` s'ils conservent volontairement une autre politique.
Le corpus Games exerce également déjà des dépendances de déclarations TypeScript :
```text
Web/game-snake-poc @types/bootstrap + @types/node
Web/game-realtime-webtransport-browser-smoke @types/node
crates/apps/game-snake-poc-tauri @types/node
```
KSP `0.3.17` corrobore la même pratique sur ses applications Tauri, qui utilisent `@types/bootstrap` et `@types/node` en `devDependencies`. Cette répétition justifie une règle générique de découverte des déclarations nécessaires, mais ne justifie pas d'imposer ces deux packages à tous les frontends.
La règle retenue est donc : vérifier d'abord les types embarqués par le package, puis rechercher un `@types/...` seulement lorsqu'il est réellement nécessaire. Pour une application privée, ces déclarations de développement appartiennent normalement à `devDependencies`; une bibliothèque publiée doit en revanche conserver disponibles aux consommateurs les types requis par ses déclarations publiques.
### Relation avec WASM et host
Deux packages Games chaînent actuellement des commandes WASM avant Vite. Cela prouve une intégration locale, mais ne justifie pas de faire du WASM une responsabilité du futur owner Vite ou TypeScript.
La frontière à conserver est :
```text
validation frontend propre TypeScript / Vite / CSS / assets / outputs
validation du host Tauri, navigateur spécialisé ou autre host
validation WASM owner futur séparé si sa valeur est démontrée
```
Un frontend doit pouvoir être validé autant que possible indépendamment du host qui l'embarque. Les commandes de génération WASM observées restent donc hors scope normatif de `0.1.1`.
## Corroboration secondaire KSP `0.3.17`
KSP contient six applications Tauri possédant chacune un frontend Vite/TypeScript. Les six manifests exercent également `sass-embedded` et Bootstrap.
Cette répétition confirme que les owners TypeScript/Vite/Sass/CSS sont bien transversaux à plusieurs hosts et ne doivent pas être absorbés par le profil Tauri. Elle ne suffit toujours pas à rendre Sass ou Bootstrap obligatoires pour tous les frontends : le corpus Games contient déjà des contre-exemples utiles.
Aucune autre règle KSP n'est importée dans `0.1.1-alpha.1`.
## Décisions de revue après `alpha.1`
La gate opérateur de `alpha.1` est `PASS` : `48/48` tests, audits Markdown propres et scope Git conforme. Aucun fix de cadrage n'est nécessaire.
La revue ajoute trois préférences explicites à traduire avec la force normative `SHOULD` :
- **TypeScript** : fortement recommandé pour les frontends contrôlés, mais non obligatoire. Sa valeur attendue est le type-check statique avant exécution/génération du JavaScript et la possibilité de partager des contrats typés avec d'autres écosystèmes ; lorsqu'une frontière Rust existe, des générateurs comme TS-RS peuvent éviter la duplication manuelle des DTO.
- **Vite** : fortement recommandé comme build tool/dev server des frontends contrôlés lorsque ses capacités correspondent au besoin, mais non obligatoire. Une alternative justifiée reste valide.
- **Sass** : fortement recommandé pour les chaînes de styles non triviales, en particulier lorsqu'une dépendance installée via l'écosystème de packages expose un entrypoint Sass/SCSS, des variables, maps, mixins ou autres points de configuration permettant d'adapter la bibliothèque sans modifier ses sources. Sass reste optionnel pour un frontend simple.
Bootstrap constitue un exemple réel de dépendance offrant une chaîne Sass personnalisable ; il ne devient pas pour autant une dépendance PGR universelle. Pour du nouveau code Sass, `@use` / `@forward` est préféré lorsque compatible ; `@import` reste toléré pour les bibliothèques existantes qui l'exigent encore.
`alpha.2` matérialise donc quatre owners séparés dans la famille `500` :
```text
530 TypeScript
540 JavaScript package ecosystem
550 Vite
560 CSS / Sass
```
Cette granularité conserve l'indépendance d'applicabilité : un projet peut utiliser TypeScript sans Vite, Vite avec JavaScript, CSS sans Sass, ou un package manager sans aucune des trois autres briques.
### Classification initiale des choix Games
| Choix Games | Classification pour l'adoption future | Motif |
|--------------------------------------------|-------------------------------------------------|----------------------------------------------------------------|
| TypeScript pour les frontends durables | `ADOPT` | déjà exercé et conforme à la préférence PGR `SHOULD` |
| Vite comme build tool/dev server | `ADOPT` | déjà exercé ; reste remplaçable par une alternative justifiée |
| `package.json` comme manifest frontend | `ADOPT` | owner générique nécessaire |
| npm comme package manager concret | `KEEP-LOCAL` | PGR ne rend pas npm universel |
| absence/versionnement des lockfiles Games | `DEFER` jusqu'à l'adoption `0.1.5` | choisir alors `ADOPT` ou `OVERRIDE` selon le rôle du package |
| Sass dans `game-snake-poc` | `ADOPT` lorsque la chaîne de styles le justifie | capacité recommandée, applicabilité conditionnelle |
| Bootstrap | `KEEP-LOCAL` | choix de présentation/skeleton, pas règle Web universelle |
| `frontend/` comme layout | `KEEP-LOCAL` / candidat skeleton | ne pas transformer un layout observé en règle de langage/build |
| ports, aliases et plugins Vite | `KEEP-LOCAL` | valeurs propres au host/projet |
| commandes/génération WASM dans les scripts | `DEFER` | futur owner WASM séparé |
Aucun `OVERRIDE` n'est nécessaire à ce stade : Games n'est pas encore gouverné par ces nouveaux profils et sera réellement mappé pendant `0.1.5`.
## Mission de `0.1.1`
`0.1.1` doit produire la première fondation frontend Web contrôlée de PGR à partir des responsabilités réellement exercées, sans créer un catalogue théorique de technologies Web.
La release doit pouvoir répondre de manière générique à ces questions :
1. qui possède la configuration TypeScript et quelles options relèvent du langage/outillage plutôt que du host ;
2. qui possède Vite, son dev server, son build, son cache et ses sorties ;
3. comment distinguer CSS, Sass optionnel et framework CSS optionnel ;
4. comment choisir et documenter un package manager sans imposer npm ;
5. comment traiter le manifest et le lockfile selon leur rôle ;
6. quelles sorties sont sources, générées, ignorées ou publiables ;
7. comment valider le frontend indépendamment de Tauri, WASM ou d'un backend ;
8. quels templates, skeletons ou audits read-only apportent une preuve réellement réutilisable.
## Frontières d'ownership à décider
`alpha.1` ne fixe volontairement ni numéros de profils ni découpage définitif. Les faits indiquent plusieurs responsabilités possibles, mais `alpha.2` doit choisir la frontière la plus générale où chaque règle est vraie.
Les axes à distinguer sont au minimum :
```text
TypeScript langage / toolchain frontend
manifest + package manager écosystème de package et scripts
Vite bundler / dev server / build outputs
CSS source frontend standard
Sass préprocesseur optionnel
framework CSS choix de skeleton/projet si applicable
frontend host navigateur direct, Tauri ou autre, hors owner générique
```
Le découpage final MUST éviter :
- un profil monolithique « Web moderne » qui rendrait toutes les briques obligatoires ;
- un owner Tauri qui posséderait des règles TypeScript/Vite génériques ;
- un owner TypeScript qui posséderait des règles de bundler ;
- une politique npm codée en dur alors que le contrat doit rester compatible avec un autre package manager choisi explicitement ;
- une règle universelle de lockfile dérivée du seul choix historique de Games ;
- l'import implicite de WASM ou d'un serveur Rust.
## Artefacts candidats
Les artefacts suivants sont candidats, pas des livrables déjà décidés :
- un ou plusieurs profils normatifs dans les familles existantes lorsque leur owner est démontré ;
- guides/templates minimaux pour `package.json`, `tsconfig.json` et `vite.config.ts` seulement si les valeurs génériques peuvent être séparées des décisions locales ;
- contrat CSS/Sass expliquant source, génération et outputs sans imposer Sass ;
- skeleton frontend Web seulement si la composition devient suffisamment générique et indépendante de Tauri/WASM ;
- validations frontend sélectionnées selon les capacités réelles : parsing du manifest, TypeScript, build Vite, Sass/CSS, smoke navigateur si la promesse de la tranche l'exige ;
- audits Python uniquement pour des propriétés statiques génériques et certaines, en restant monotâches et read-only.
Aucun de ces artefacts n'est créé par `alpha.1`.
## Trajectoire prévisionnelle de `0.1.1`
### alpha.1 — audit de stable, corpus et plan
Auditer `v0.1.0`, `publish.001`, Games `0.3.6`, les décisions Tauri/horizon, puis créer le présent plan. Aucun changement normatif Web n'appartient à cette tranche.
### alpha.2 — frontières d'ownership Web
Statut opérateur : **FAIL**.
La tranche a matérialisé les quatre owners `530 / 540 / 550 / 560`, leurs frontières indépendantes et les recommandations `SHOULD` TypeScript/Vite/Sass. Les `48` tests et les trois audits Markdown sont restés propres et le scope Git observé correspond au delta.
La gate spécifique n'a toutefois pas pu atteindre son message final : le littéral Python `'Le profil s'applique uniquement lorsqu'un projet utilise réellement Vite.'` utilise des quotes simples autour d'un texte contenant l'apostrophe de `s'applique`, provoquant un `SyntaxError`. Aucun défaut normatif des profils livrés n'est établi.
### alpha.2.fix.1 — correction de la gate d'ownership Web
Statut opérateur : **PASS**.
Le correctif a conservé le `FAIL` historique de `alpha.2`, reconfirmé les quatre owners `530/540/550/560`, les recommandations `SHOULD`, la classification Games et le `DEFER` Tauri. Les `48/48` tests et les trois audits Markdown sont propres ; le scope du fix est resté limité à `VERSION`, au plan et au delta de correction.
### alpha.3 — TypeScript et écosystème de package
Statut opérateur : **PASS**.
La tranche a matérialisé un type-check indépendant sous le script canonique `typecheck`, un `tsconfig` strict sans émission comme baseline minimale, un `package.json` privé minimal pour les applications contrôlées et une politique de lockfile fondée sur le rôle de l'artefact et la reproductibilité, jamais sur une préférence npm.
La gate spécifique atteint son message final, les `48/48` tests et les trois audits Markdown sont propres, et le scope Git correspond exactement au delta. Vite est resté réservé à `alpha.4` et CSS/Sass à `alpha.5`.
La revue opérateur après PASS relève toutefois une précision appartenant exactement au scope de la tranche : le manifest réel doit rechercher et déclarer les types externes nécessaires (`@types/node`, `@types/bootstrap` ou équivalent) lorsque les dépendances utilisées ne fournissent pas déjà leurs propres déclarations. Le delta livré reste immuable ; cette précision est portée par un fix local.
### alpha.3.fix.1 — déclarations de types externes
Statut opérateur : **FAIL**.
Le correctif a livré la règle `types embarqués → @types si nécessaire`, la classification conditionnelle de `@types/node` / `@types/bootstrap`, la distinction application privée / bibliothèque publiée et l'intégration IDE attendue. Les `48/48` tests et les trois audits Markdown sont propres, et le scope Git correspond au delta.
La gate spécifique n'a toutefois pas atteint son message final : le littéral Python `'qualité TypeScript et à l'expérience IDE'` utilise des quotes simples autour d'un texte contenant l'apostrophe de `l'expérience`, provoquant un `SyntaxError`. Aucun défaut normatif du correctif n'est établi.
### alpha.3.fix.2 — correction de la gate des déclarations de types
Statut opérateur : **PASS**.
La gate corrigée atteint son message final, reconfirme le `FAIL` historique de `alpha.3.fix.1`, les règles de découverte des types externes et la séparation application/bibliothèque. Les `48/48` tests et les trois audits Markdown passent, et le scope Git reste limité à `VERSION`, au plan et au delta de correction.
Aucune règle TypeScript/package ni aucun template n'a été modifié par le fix. La trajectoire reprend donc normalement avec Vite.
### alpha.4 — Vite, dev server et outputs
Statut opérateur : **PASS**.
La tranche a matérialisé le contrat Vite sans créer de `vite.config.ts` universel artificiel. Les sources, cache, outputs et assets ont des statuts explicites ; le dev server reste borné ; les paramètres `root`, `base`, ports, aliases et plugins restent des décisions locales.
La gate spécifique a atteint son message final, les `48/48` tests et les trois audits Markdown sont propres, et le scope Git correspond exactement aux six chemins annoncés. TypeScript/package n'a pas été rouvert et CSS/Sass est resté réservé à `alpha.5`.
### alpha.5 — CSS/Sass et validation frontend
Statut opérateur : **PASS**.
La gate spécifique Web frontend a atteint son message final, les `48/48` tests et les trois audits Markdown sont propres, et le scope Git correspond exactement au delta. Le skeleton `003-WEB_FRONTEND.md` compose désormais les owners `530/540/550/560` sans ownership caché ni valeur universelle arbitraire.
La tranche retient les décisions suivantes :
- CSS reste une baseline valide sans préprocesseur ;
- Sass reste optionnel mais **SHOULD** être préféré lorsque la chaîne de styles est non triviale ou lorsqu'un package expose une API Sass utile ;
- le nouveau code Sass contrôlé privilégie `@use` / `@forward`, tandis que `@import` reste uniquement une voie de compatibilité pour les dépendances qui l'exigent encore ;
- les sources `.css` / `.scss` / `.sass` intentionnelles sont versionnées, mais les CSS compilées, minifiées, sourcemaps et copies présentes dans un output de build sont générées et ne doivent pas devenir un second source ;
- un package de styles doit être consommé via son entrypoint public/documenté plutôt que par des chemins internes arbitraires ;
- Bootstrap, Tailwind CSS ou une autre bibliothèque restent des choix de projet/skeleton, jamais une obligation de `560` ;
- lorsqu'un frontend utilise Vite + Sass, `sass-embedded` est un choix de développement recommandé lorsque compatible, mais le profil Sass ne dépend pas de Vite ;
- la validation frontend distingue restore reproductible, type-check, build/compilation des styles et smoke navigateur seulement lorsque celui-ci apporte une preuve supplémentaire ;
- un PASS frontend ne vaut pas PASS du host, et un host Tauri ne doit pas posséder les validations TypeScript/Vite/Sass génériques.
Les owners `530/540/550/560` sont désormais assez complets pour composer un skeleton Web sans ownership caché. La tranche crée donc `003-WEB_FRONTEND.md` comme specialization contrôlée : TypeScript et Vite y restent des `SHOULD`, Sass reste conditionnel, le package manager et le framework CSS restent des décisions explicites, et aucun layout `frontend/`, `vite.config.ts`, `main.scss`, port ou package concret n'est imposé.
Le skeleton ne lève pas le `DEFER` Tauri. `beta.1` devra encore réconcilier les cinq conditions de sortie de l'étude `002` et conclure factuellement si `0.1.4` peut réexaminer le candidat Tauri.
### beta.1 — réconciliation et preuve de préparation Tauri
Statut opérateur : **PASS**.
La gate opérateur confirme le dry-run structurel du skeleton Web, la couverture des cinq prérequis Web du futur réexamen Tauri, les `48/48` tests et les trois audits Markdown propres. Le `DEFER` Tauri reste explicitement réservé à `0.1.4` et aucun owner Web n'a été modifié pendant cette réconciliation.
Les cinq conditions de sortie de `002-TAURI_SKELETON_DECISION.md` sont désormais rattachées aux artefacts matérialisés suivants :
```text
1. TypeScript contrôlé 530 + 008 + templates web-typescript
2. Vite/dev server/build outputs 550 + 009
3. CSS/Sass + statut des artefacts générés 560 + 010
4. validation frontend indépendante du host validation 005
5. framework CSS classé comme choix local 560 + skeleton 003
```
La tranche exécute aussi un dry-run structurel du skeleton Web : copie des templates JSON génériques dans un répertoire temporaire, parsing réel de ces artefacts, contrôle des références vers les owners/guides/validation et vérification de l'absence de `vite.config.ts`, `main.scss`, host Tauri ou dépendance frontend arbitraire injectés par PGR.
Ce dry-run ne prétend pas remplacer `tsc`, Vite ou Sass : le dépôt PGR ne possède volontairement ni versions de dépendances frontend ni configuration de projet concrète. Une instanciation réelle doit toujours exécuter les toolchains officielles sélectionnées conformément à `005-WEB_FRONTEND_VALIDATION.md`.
Si les cinq conditions sont matériellement couvertes, `beta.1` peut conclure que `0.1.4` dispose désormais des prérequis PGR nécessaires pour réexaminer le candidat Tauri. Cette conclusion MUST NOT lever le `DEFER`, créer le skeleton Tauri, figer `frontend/`, Bootstrap, Sass ou Vite comme obligations Tauri, ni remplacer la réévaluation du corpus courant exigée par l'étude `002`.
Si une responsabilité Web nécessaire reste sans owner clair, effectuer un REPLAN avant RC plutôt que masquer la lacune.
### rc.1 — release candidate
Statut opérateur : **PASS**.
La gate opérateur a confirmé les neuf histories antérieurs avec leurs statuts réels, le scope Web gelé, le changelog candidat, le prompt `008`, le dry-run structurel du skeleton Web, les `48/48` tests, les trois audits Markdown et l'hygiène texte/JSON. Aucun owner, template technique, skeleton, validation ou étude technique n'a été modifié pendant la RC.
Le prompt `008-V0_1_2_START_PROMPT.md` conserve la séparation Java/Gradle générique versus Android : le profil `520` sera réévalué à partir du corpus Games, tandis qu'AGP, SDK Android, JNI/ABI et packaging APK/AAB restent hors scope et réservés à `0.1.3`.
### rel.1 — promotion stable
Première clôture stable de `0.1.1`. La promotion est strictement mécanique : `VERSION = 0.1.1`, `ROADMAP.md` marque `0.1.1` terminée, le `CHANGELOG` perd son marqueur `candidate`, README/index décrivent la fondation frontend Web comme stable et le présent plan devient historique. Aucun owner, profil, template, skeleton, validation, étude ou script technique n'est modifié.
Le résultat opérateur de cette tranche appartient à `history/0.1.1/rel.1.md`, créé seulement après exécution de la gate. Si `rel.1` échoue, son history est conservé et un `rel.1.fix.N` corrige uniquement la fermeture ; la première tranche qui établit réellement la stable est incluse dans le commit `0.1.1` avant le tag `v0.1.1`.
La vérification post-tag reste séparée : `pgr-0.1.1-publish.001-report.md` ne peut être produit qu'à partir de l'archive du tag réellement publiée et des preuves Git observées. Le prompt `008` ne devient le point de départ effectif de `0.1.2` qu'après cette preuve post-tag `PASS`.
## Stratégie de validation
Chaque tranche conserve les gates PGR de base applicables :
```text
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_markdown_headers.py ...
python3 -B scripts/audit_markdown_tables.py ...
python3 -B scripts/audit_markdown_links.py ...
```
Lorsqu'un artefact frontend réel est ajouté, la gate doit utiliser l'outil propriétaire lorsque disponible et pertinent au scope. Un audit Python peut prévalider une propriété statique précise, mais ne doit pas prétendre remplacer TypeScript, Vite, Sass ou le package manager.
Le choix des commandes Node/package manager doit être rendu explicite par le projet ou le fixture de validation. PGR ne doit pas utiliser `npm install` comme commande universelle simplement parce que Games l'utilise actuellement.
Les smokes navigateur ne sont requis que lorsqu'une tranche ou la release prétend supporter un comportement observable que le build statique ne suffit pas à prouver. Ils doivent être placés avant RC lorsque nécessaires, puis rejoués au release gate selon la matrice finale.
## Déclencheurs de REPLAN
Le plan MUST être révisé avant de continuer si :
- le découpage TypeScript/package/Vite/styles ne peut pas conserver un owner unique par règle ;
- `0.1.1` devrait absorber WASM, Tauri ou un serveur Rust pour être cohérent ;
- la politique de package manager/lockfile nécessite plusieurs catégories de projet non prévues ;
- un skeleton frontend ne peut être générique sans décisions propres à Games/KSP ;
- une tranche prévue dépasse nettement l'unité cohérente et indépendamment validable visée par PGR ;
- les validations réelles montrent qu'un outil ou une target supplémentaire est nécessaire pour soutenir une règle normative ;
- le périmètre total ne peut plus raisonnablement être clôturé dans la session/release prévue.
Un REPLAN peut scinder une tranche ou, si nécessaire, réexaminer la trajectoire conformément à la règle de revue d'horizon. Il ne doit pas artificiellement remplir la release avec des owners non prouvés.
## Clôture et transition
La release est prête pour RC lorsque :
- les owners Web retenus ont des frontières explicites et non redondantes ;
- TypeScript, package manager/manifest, Vite, CSS/Sass et outputs ont une politique contrôlée proportionnée ;
- la validation frontend est distinguée de la validation du host ;
- WASM, serveur Rust et Tauri n'ont pas été absorbés par proximité ;
- les choix Games non génériques restent classifiés comme locaux ou différés ;
- les conditions Tauri peuvent être réévaluées objectivement en `0.1.4` sans que `0.1.1` décide leur issue à l'avance.
Après publication `0.1.1` et `publish.001 PASS`, la reprise normale est `0.1.2` — réévaluation Java/Maven/Gradle — sauf REPLAN explicite de l'horizon fondé sur les résultats réels de la release.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/000-README.md -->
<!-- version: 10 -->
<!-- version: 15 -->
# Index des règles PGR
@@ -12,14 +12,22 @@ Les règles générales actuellement nécessaires restent dans `RULES.md`. La fa
## Familles actives
- [`200-GOVERNANCE.md`](200-GOVERNANCE.md) — versioning, lifecycle des releases, fixes, cadrage, replan et abandon/supersession.
- [`210-WORKFLOW.md`](210-WORKFLOW.md) — contrats des artefacts workflow, ordre delta/history/commit, reprise et baselines de release.
- [`210-WORKFLOW.md`](210-WORKFLOW.md) — contrats des artefacts workflow, ordre delta/history/commit, prompts versionnés, reprise et baselines de release.
- [`220-SKELETONS.md`](220-SKELETONS.md) — contrat commun des skeleton specifications, sélection des profils/templates, décisions, overrides et validation.
- [`230-ADOPTION.md`](230-ADOPTION.md) — contrat d’adoption PGR pour un dépôt existant, classification `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` et migration incrémentale.
- [`300-DOCUMENTATION.md`](300-DOCUMENTATION.md) — rôles des documents, taxonomie, révisions internes, documents vivants et snapshots historiques.
- [`400-VALIDATION.md`](400-VALIDATION.md) — matrice de validation, preuves proportionnelles, tests/audits/diagnostics, doubles de test et autorité du gate opérateur.
- [`500-LANGUAGES.md`](500-LANGUAGES.md) — contrat commun des profils langage/écosystème et de leurs spécialisations de build.
- [`510-RUST_CARGO.md`](510-RUST_CARGO.md) — profil Rust/Cargo et règles réutilisables propres à cet écosystème.
- [`520-JAVA_MAVEN_GRADLE.md`](520-JAVA_MAVEN_GRADLE.md) — profil Java et spécialisations de build Maven/Gradle.
- [`530-TYPESCRIPT.md`](530-TYPESCRIPT.md) — profil TypeScript, recommandation pour les frontends contrôlés, type-check et frontières typées.
- [`540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md) — package manager, `package.json`, dépendances, scripts et responsabilité du lockfile.
- [`550-VITE.md`](550-VITE.md) — profil Vite, build tool/dev server recommandé et ownership de son cache et de ses outputs.
- [`560-CSS_SASS.md`](560-CSS_SASS.md) — profil CSS/Sass, styles sources, prétraitement conditionnel et intégration de dépendances de styles.
- [`600-PLATFORMS.md`](600-PLATFORMS.md) — contrat commun des profils plateforme.
- [`610-ANDROID.md`](610-ANDROID.md) — profil plateforme Android et règles réutilisables de compatibilité, packaging et validation.
- [`700-FRAMEWORKS.md`](700-FRAMEWORKS.md) — contrat commun des profils framework et de leur composition avec les owners déjà applicables.
- [`710-TAURI.md`](710-TAURI.md) — profil Tauri 2 et règles réutilisables d'orchestration native/frontend, sécurité et validation.
Le modèle transversal d'ownership, d'applicabilité et de composition est décrit dans [`../architecture/003-RULE_PROFILE_MODEL.md`](../architecture/003-RULE_PROFILE_MODEL.md).

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/200-GOVERNANCE.md -->
<!-- version: 2 -->
<!-- version: 5 -->
# Governance rules
@@ -38,9 +38,20 @@ Lorsqu'un dépôt utilise le fichier racine `VERSION`, ce fichier :
Un manifeste technique MAY refléter exactement `VERSION` lorsque son propre contrat l'exige. Un autre mécanisme de versioning MAY rester indépendant lorsqu'il possède une sémantique différente, par exemple un `versionCode` Android, une révision de document ou une version de protocole.
PGR MUST NOT imposer une égalité globale entre tous les champs contenant un numéro de version.
PGR MUST NOT imposer une égalité globale entre tous les champs contenant un numéro de version. Pour éviter à la fois les divergences silencieuses et le churn mécanique, chaque valeur de version durable SHOULD être classée selon son rôle réel. Les catégories réutilisables sont notamment :
Un champ de version qui n'est ni requis par l'écosystème ni utile au projet SHOULD être omis plutôt que maintenu comme duplication décorative.
- `CANONICAL` — identité SemVer exacte de l'unité de release, normalement portée par `VERSION` ;
- `MIRROR-EXACT` — miroir technique qui suit exactement `VERSION`, prereleases et fixes compris ;
- `MIRROR-STABLE` — miroir du jalon produit `X.Y.Z` ciblé, stable pendant `X.Y.Z-alpha.*`, `beta.*`, `rc.*` et leurs fixes ;
- `INDEPENDENT-COUNTER` — compteur technique monotone possédant sa propre sémantique ;
- `INDEPENDENT-SCHEMA` — version de protocole, format ou schéma indépendante du produit ;
- `DOCUMENT-REVISION` — révision interne d'un document ou artefact documentaire.
Seul un `MIRROR-EXACT` est normalement modifié à chaque changement de `VERSION`. Un `MIRROR-STABLE` SHOULD être fixé ou vérifié lorsque la cible `X.Y.Z` est ouverte, puis ne pas être réécrit uniquement parce qu'une tranche passe de `alpha.N` à `alpha.N+1`, à un `.fix.N`, à une beta ou à une RC. La promotion stable vérifie qu'il représente toujours la release publiée.
Lorsqu'une prerelease est réellement distribuée comme artefact installable distinct et que son écosystème exige une identité de package propre, le champ concerné peut devenir `MIRROR-EXACT` ou suivre des jalons explicitement définis. Cette décision appartient au plan de versioning/packaging du projet ; elle ne doit pas résulter d'une égalité globale implicite.
Un champ de version qui n'est ni requis par l'écosystème ni utile au projet SHOULD être omis plutôt que maintenu comme duplication décorative. Réciproquement, PGR MUST NOT imposer la suppression d'un champ utile uniquement pour éviter de le modifier à chaque prerelease : il faut d'abord lui attribuer la bonne classe de synchronisation.
## Schéma SemVer PGR
@@ -66,6 +77,8 @@ vX.Y.Z
`rel.N` MAY identifier une livraison ou un artefact de clôture, mais MUST NOT être traité comme une version produit SemVer.
Pour les nouvelles releases gouvernées par cette convention, `N` commence à `1` et sa représentation canonique n'utilise pas de zéro de padding : `rel.1`, `rel.2`, etc. Les formes historiques déjà publiées telles que `rel.001` restent des snapshots immuables et MUST NOT être renommées rétroactivement.
Avant `1.0.0`, PGR recommande la convention suivante lorsqu'elle correspond au projet :
- `X = 0` indique que le contrat public durable n'est pas encore stabilisé ;
@@ -89,7 +102,9 @@ Cette convention pré-1.0 complète SemVer sans modifier sa syntaxe.
- les études ou décisions encore ouvertes ;
- les principaux risques et contraintes ;
- la stratégie de validation et les smokes nécessaires ;
- le dimensionnement des tranches.
- le dimensionnement des tranches ;
- lorsque la release possède un plan dédié, les responsabilités de clôture et de transition vers la suite ;
- l'état de l'horizon de roadmap et, lorsqu'il devient court ou incertain, le moment prévu pour le réexaminer.
Une tranche cible généralement un volume de travail cohérent et vérifiable. Une durée de l'ordre de 15 à 30 minutes MAY servir d'heuristique de découpage, mais MUST NOT être traitée comme une deadline ou un quota.
@@ -113,6 +128,16 @@ La promotion stable MUST néanmoins exécuter son propre gate proportionné pour
Le tag stable canonique est `vX.Y.Z`.
La clôture opérationnelle `rel.N[/fix.M]` n'est pas une prerelease SemVer et MAY intervenir alors que `VERSION` porte déjà `X.Y.Z`. En l'absence d'une convention locale explicitement documentée, PGR impose la distinction suivante pour le message du commit de clôture :
```text
rel.1 FAIL / PARTIAL / BLOCKED -> X.Y.Z-rel.1
rel.1.fix.1 FAIL / PARTIAL / BLOCKED -> X.Y.Z-rel.1.fix.1
première tranche de clôture PASS -> X.Y.Z
```
Le commit nommé `X.Y.Z` MUST inclure le history qui établit effectivement le `PASS` stable. Le tag `vX.Y.Z` MUST être créé seulement après ce commit. Une clôture échouée MUST rester identifiable par son nom de tranche et MUST NOT être présentée comme le commit stable final.
La vérification d'une publication ou d'une archive produite après le tag est une preuve distincte de la validation pré-tag.
## Correctifs de tranche
@@ -145,6 +170,8 @@ ABANDON
Une interruption de conversation ou de session MUST NOT créer artificiellement une nouvelle version. Le même état de version et de tranche continue tant que le scope reste valable.
Une revue stratégique de versions futures MAY également se tenir dans une session séparée. Cette frontière de conversation n'est ni une release, ni une phase SemVer, ni une raison de modifier `VERSION`. Si la discussion produit une décision durable à matérialiser dans le dépôt, cette modification passe ensuite par une tranche gouvernée appropriée.
## Abandon et supersession
Une version ou prerelease commencée n'est pas forcée vers stable uniquement pour préserver une séquence esthétique.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/210-WORKFLOW.md -->
<!-- version: 3 -->
<!-- version: 7 -->
# Workflow artifact rules
@@ -49,13 +49,25 @@ docs/plans/
Un plan :
- SHOULD être créé pendant le cadrage lorsque plusieurs tranches ou décisions doivent être coordonnées ;
- MAY évoluer lorsque le plan change réellement ;
- SHOULD être créé ou consolidé pendant `alpha.1` lorsque plusieurs tranches ou décisions doivent être coordonnées ;
- MAY évoluer lorsque la réalité invalide le forecast ;
- SHOULD NOT être modifié à chaque tranche uniquement pour recopier l'avancement ;
- MUST distinguer prévision et état réellement observé ;
- MUST NOT remplacer ROADMAP, delta ou history.
Un changement substantiel du plan MAY être porté par une tranche REPLAN conformément aux règles de gouvernance.
Lorsqu'un plan existe pour une release gouvernée par le workflow PGR, il MUST aussi rendre explicites, de manière proportionnée :
- la mission, le scope et le hors-scope actuellement applicables ;
- la stratégie de validation et les gates qui conditionnent réellement la fermeture ;
- la trajectoire prévisionnelle des responsabilités, sans transformer le forecast en promesse immuable ;
- une section ou un bloc **clôture et transition** indiquant où seront traités la réconciliation documentaire durable, le `CHANGELOG`, la mise à jour de `ROADMAP`, le prompt ou handoff de reprise, la fermeture du plan et la promotion/publication ;
- l'état de la **revue d'horizon** : soit elle n'est pas nécessaire parce que la roadmap possède déjà un horizon suffisant, soit son déclencheur et le moment où elle sera instruite sont identifiés.
Le plan MUST NOT inventer une version future uniquement pour remplir la rubrique de transition. Lorsque la cible suivante n'est pas suffisamment décidée, il l'indique explicitement et planifie une revue d'horizon ou un handoff approprié plutôt que de fabriquer un numéro, une mission ou un prompt.
Un changement substantiel du plan MAY être porté par une tranche REPLAN conformément aux règles de gouvernance. Le corps du plan reste l'état de pilotage actuellement applicable ; les deltas et histories conservent le détail historique des changements. PGR n'impose pas un journal `Revisions` alimenté à chaque tranche.
À la clôture `completed`, `abandoned` ou `superseded`, le plan devient principalement historique. Il ne doit plus être réécrit pour refléter silencieusement la connaissance acquise dans des releases ultérieures.
## Delta
@@ -74,6 +86,8 @@ alpha.3.md
alpha.3.fix.1.md
beta.1.md
rc.1.md
rel.1.md
rel.1.fix.1.md
```
Un delta MUST :
@@ -137,6 +151,18 @@ L'archive history contient uniquement le ou les fichiers history à appliquer po
Delta et history MUST rester des livraisons séparées afin que la preuve observée ne soit pas confondue avec l'intention prospective.
Lorsque la gate courante est `PASS` et que la tranche suivante est déjà déterminée par le plan sans décision ouverte, le générateur SHOULD préparer et remettre dans la même réponse :
```text
archive history de la tranche courante
+
archive delta de la tranche suivante
```
Les deux archives restent séparées. Cette optimisation de flux n'autorise jamais l'application du delta suivant avant l'application du history courant et le commit complet de la tranche.
Le delta suivant SHOULD NOT être anticipé lorsqu'une décision opérateur, un REPLAN non résolu, un abandon/supersession, une preuve externe post-tag ou toute autre dépendance peut encore modifier sa baseline ou son scope.
## Commit de tranche
Le commit d'une tranche doit représenter l'état complet de cette tranche, y compris son history.
@@ -150,9 +176,63 @@ current delta changes
doivent être présents, alors que le delta suivant MUST rester absent.
Le message de commit MAY suivre les conventions du projet. PGR n'impose pas Conventional Commits, GitFlow ou une topologie universelle de branches.
Pour une tranche alpha, beta, RC ou autre tranche qui n'établit pas la stable, le message de commit MAY suivre les conventions du projet tant que l'état et la tranche restent identifiables. PGR n'impose pas Conventional Commits, GitFlow ou une topologie universelle de branches.
L'important est que l'état et la tranche restent identifiables et que le repository ne mélange pas deux tranches non clôturées.
La clôture stable `rel.N[/fix.M]` possède une règle plus stricte afin de distinguer une tentative de fermeture de l'identité stable réellement obtenue. En l'absence d'un mapping local explicitement documenté :
```text
history rel.1 FAIL / PARTIAL / BLOCKED
-> commit X.Y.Z-rel.1
history rel.1.fix.1 FAIL / PARTIAL / BLOCKED
-> commit X.Y.Z-rel.1.fix.1
premier history rel.N[/fix.M] PASS qui établit réellement la stable
-> commit X.Y.Z
```
Le suffixe opérationnel n'est donc conservé dans le message du commit que tant que la clôture n'a pas obtenu le `PASS` stable. Le commit `X.Y.Z` MUST contenir le delta de clôture concerné et son history `PASS`; il MUST précéder le tag canonique `vX.Y.Z`.
Un projet qui possède une convention de message différente MAY utiliser un mapping équivalent, mais il MUST conserver sans ambiguïté la distinction entre tentative de clôture échouée et commit stable final.
Le repository ne doit jamais mélanger deux tranches non clôturées dans un même commit.
## Remise automatique des commandes opérateur
Après production d'un history destiné à être appliqué par l'opérateur, le générateur MUST remettre spontanément les commandes nécessaires pour fermer cette tranche. Il ne doit pas attendre une demande séparée du type « je commit avec quel message ? ».
Lorsque les valeurs Git sont établies par le projet ou par les sorties opérateur de la session, le bloc remis MUST utiliser les valeurs réelles : archive history, message de commit, remote et branche. Le générateur MUST NOT inventer un remote, une branche ou une politique de tag non établis. Une valeur encore inconnue doit être signalée explicitement ou résolue par une commande de découverte sûre avant la commande qui en dépend.
Pour une livraison ZIP et une tranche non stable, le handoff couvre normalement dans cet ordre :
```text
apply history archive
↓
git add / staged whitespace check / status
↓
commit avec le message attendu
↓
push de la branche courante
↓
apply du delta suivant ou du fix déjà livré
```
Lorsqu'un history `FAIL`, `PARTIAL` ou `BLOCKED` conduit à un `.fix.N`, le bloc de commandes ferme d'abord la tranche constatée sous son identité propre puis autorise seulement l'application du correctif. Lorsqu'un history `PASS` conduit à la tranche planifiée suivante, le même ordre s'applique.
Pour la première clôture `rel.N[/fix.M]` qui établit réellement la stable, le bloc MUST utiliser le message de commit stable `X.Y.Z`, puis fournir séparément les commandes de tag et de vérification applicables. Le tag MUST NOT être créé avant le commit stable et son push lorsque le projet exige que la branche canonique distante porte d'abord ce commit.
Le handoff de publication MUST également indiquer exactement ce que l'opérateur doit remettre au générateur pour produire la preuve post-tag applicable. Pour une archive source générée par la forge à partir du tag, cela inclut normalement :
- le ZIP téléchargé depuis le tag canonique ;
- le SHA du commit stable local observé avant ou pendant le tag ;
- le commit déréférencé localement par le tag ;
- la référence distante du tag ;
- pour un tag annoté, le commit distant déréférencé `refs/tags/vX.Y.Z^{}` afin de ne pas confondre l'objet tag avec son commit ;
- toute autre preuve explicitement requise par la politique locale de publication.
Le rapport `publish.*` est produit seulement à partir des artefacts et preuves réellement disponibles après publication. Il MUST NOT être prérempli avec un `PASS` futur.
[`../templates/006-OPERATOR_COMMAND_HANDOFF.md`](../templates/006-OPERATOR_COMMAND_HANDOFF.md) fournit le pattern de rendu des blocs de commandes. Il complète le présent contrat sans devenir une seconde source normative.
## Manifest de suppression
@@ -173,9 +253,9 @@ S'il existe :
Un manifest ne doit pas exister vide uniquement pour satisfaire une structure théorique.
## Prompt de démarrage
## Prompt de démarrage versionné
Un prompt de démarrage transmet la mission et le contexte nécessaires à une nouvelle version ou à une reprise explicitement prévue.
Un prompt de démarrage versionné transmet le contrat de reprise nécessaire pour ouvrir une nouvelle version depuis une baseline autoritaire sans reconstruire implicitement l'état du projet depuis une conversation antérieure, un workspace non fourni ou une mémoire informelle.
Le chemin canonique est :
@@ -185,19 +265,55 @@ prompts/NNN-VX_Y_Z_START_PROMPT.md
`NNN` est monotone à l'échelle du dépôt.
Le prompt :
Le prompt MUST rester un artefact de reprise et de cadrage. Il référence les règles, plans, histories, handoffs ou documents techniques qui possèdent déjà le détail ; il MUST NOT les recopier exhaustivement ni devenir une seconde source normative concurrente.
- doit transmettre la mission, la baseline et les règles de reprise utiles ;
- MUST NOT devenir une copie exhaustive du plan ou de l'historique ;
- SHOULD être finalisé à la clôture stable de la version précédente lorsqu'il prépare la version suivante.
### Contrat minimal
Une interruption au milieu d'une version MUST NOT produire artificiellement le prompt de la version suivante.
Le prompt MUST couvrir, sous des titres adaptés au projet plutôt que selon une forme imposée, les éléments suivants lorsqu'ils sont applicables :
Lors d'une nouvelle session ouverte depuis une stable publiée, une courte consigne manuelle MAY identifier l'archive du tag, le rapport post-tag lorsqu'il existe réellement, le prompt versionné à lire et la première gate. [`../templates/003-NEW_SESSION_PROMPT.md`](../templates/003-NEW_SESSION_PROMPT.md) décrit une forme réutilisable ; elle ne remplace ni le prompt versionné ni la preuve de publication.
1. **baseline autoritaire et cible** — identifier la source exacte depuis laquelle la version doit être ouverte, la version cible et la première tranche attendue ; préciser les limites matérielles de cette source, par exemple l'absence normale de `.git` dans une archive de tag ;
2. **ordre de lecture** — nommer les points d'entrée normatifs, plans, histories, handoffs ou documents de subsystem qui doivent être lus avant de modifier le projet lorsqu'un ordre est nécessaire pour reconstruire correctement le contexte ;
3. **état déjà acquis** — résumer uniquement les résultats stables nécessaires à la reprise et les décisions qui ne doivent pas être redébattues sans preuve nouvelle ; cet état MUST rester traçable à la baseline ou aux artefacts cités ;
4. **mission et résultat attendu** — décrire ce que la version doit rendre vrai ou livrer, sans substituer un catalogue de tâches à l'objectif ;
5. **scope et hors-scope** — borner les changements autorisés et les sujets explicitement différés afin d'éviter qu'une reprise étende silencieusement la release ;
6. **décisions gelées et questions ouvertes** — distinguer les choix déjà établis des décisions que la première tranche doit encore instruire ; une valeur non prouvée MUST rester ouverte plutôt qu'être figée arbitrairement ;
7. **première gate** — définir l'objectif de la première tranche, les lectures/audits ou preuves préalables attendus et, lorsque nécessaire, les travaux interdits avant fermeture de ce gate ;
8. **trajectoire prévisionnelle** — fournir uniquement le forecast nécessaire pour dimensionner la release et ordonner les responsabilités ; il reste non contraignant et peut être scindé, fusionné ou replanifié selon les preuves ;
9. **validation et responsabilité** — rappeler les familles de gates pertinentes, les validations déjà imposées par les règles applicables et toute séparation importante entre préparation, exécution opérateur et preuve observée, sans déclarer réussie une commande qui n'a pas été exécutée.
Un projet MAY regrouper plusieurs de ces éléments dans une même section lorsque le résultat reste explicite et non ambigu. Le prompt n'a pas à reproduire littéralement cette numérotation.
### Sources externes et données manquantes
Lorsqu'une release dépend de snapshots, corpus, rapports ou autres sources externes, le prompt MUST identifier celles qui sont réellement autoritaires pour la reprise et définir le comportement lorsque l'une d'elles manque.
L'absence d'une source attendue MUST être signalée. Le travail doit alors être borné à ce que les preuves disponibles permettent réellement de conclure ; le prompt MUST NOT autoriser à reconstituer silencieusement une version, un commit, un contenu ou un résultat depuis une conversation antérieure ou un workspace non fourni.
Une preuve externe complète la baseline seulement pour les propriétés qu'elle établit. Elle ne remplace pas l'audit de la source effectivement fournie à la nouvelle session.
### Décisions acquises et détails locaux
Le prompt SHOULD citer les décisions acquises qui empêchent une régression ou une réouverture inutile, mais il SHOULD pointer vers leur owner documentaire lorsque leur explication détaillée existe déjà.
Les contraintes locales de langage, plateforme, framework, architecture ou métier restent chez leurs owners respectifs. Leur présence dans un prompt de projet ne les élève pas au rang de règle générale PGR.
Le prompt MAY imposer un ordre de lecture détaillé ou une matrice de questions lorsque la taille du projet le justifie. Un petit projet SHOULD conserver une forme plus courte si elle couvre le même contrat de reprise.
### Création et clôture
Lorsque la version suivante est suffisamment connue, son prompt SHOULD être amorcé pendant la consolidation finale, vérifié pendant la RC et finalisé pendant la promotion stable. Il MUST être présent dans la stable taggée qui prépare cette reprise.
Lorsque la cible suivante n'est pas suffisamment connue, PGR MUST NOT fabriquer un prompt de version, un numéro ou une mission pour respecter une cérémonie. Le plan et la roadmap indiquent alors que l'horizon reste ouvert et un handoff `NEXT` ou une revue d'horizon porte la continuité nécessaire.
Une interruption au milieu d'une version MUST NOT produire artificiellement le prompt de la version suivante. La reprise de la tranche courante utilise son état committé et, si nécessaire, un handoff conforme au présent document.
Lorsqu'une stable publiée possède une cible suivante connue, le générateur MUST remettre spontanément à l'opérateur, après la vérification post-tag applicable, une courte consigne manuelle identifiant l'archive du tag, le rapport post-tag lorsqu'il existe réellement, le prompt versionné à lire et la première gate. [`../templates/003-NEW_SESSION_PROMPT.md`](../templates/003-NEW_SESSION_PROMPT.md) décrit cette forme courte ; elle reste distincte du prompt versionné et ne remplace ni son contrat détaillé ni la preuve de publication.
Si une preuve post-tag externe est requise pour la prochaine reprise, le prompt versionné MAY annoncer à l'avance son nom attendu mais MUST la décrire comme une preuve future extérieure au tag. La consigne manuelle finale ne la présente comme `PASS` qu'après sa production et sa vérification réelles.
## Handoff
Un handoff est un snapshot de continuité utilisé lorsqu'un travail doit être repris sans changer artificiellement de version ou de tranche.
Un handoff est un snapshot de continuité utilisé lorsqu'un travail doit être repris à une frontière de session ou de responsabilité sans changer artificiellement de version ou de tranche. Un REPLAN traité entièrement dans la même session n'a pas besoin d'un handoff uniquement pour laisser une trace : delta, history et plan possèdent déjà cette trace.
Le chemin canonique est :
@@ -217,9 +333,21 @@ SUPERSEDE
NEXT
```
Le handoff SHOULD enregistrer uniquement les informations nécessaires à une reprise fiable : état de version/tranche, résultat déjà acquis, travail restant, risques ou décisions ouvertes et commandes pertinentes.
Selon le besoin réel, un handoff SHOULD permettre de retrouver sans mémoire conversationnelle :
Une fois livré comme snapshot de reprise, il SHOULD être traité comme historique plutôt que réécrit continuellement.
- son type, la version source et une cible éventuelle ;
- la baseline autoritaire et le dernier état opérateur validé ;
- le dernier delta validé et tout delta livré mais encore en attente ;
- l'état du plan, le travail terminé et le travail restant ;
- les décisions acquises, les questions ouvertes et les validations restantes ;
- le prompt applicable lorsqu'il existe ;
- l'instruction exacte de reprise et, lorsque cela aide l'opérateur, un court texte copiable vers la nouvelle session.
Un petit handoff n'a pas à répéter les champs sans valeur pour son cas. Il référence les owners existants plutôt que recopier leurs règles.
Un `NEXT` après stable peut transmettre une version suivante connue. Si l'horizon est volontairement ouvert, il peut au contraire transmettre explicitement le besoin de revue d'horizon sans inventer une release.
Une fois livré comme snapshot de reprise, un handoff SHOULD être traité comme historique plutôt que réécrit continuellement.
Un changement de conversation ou de session n'est jamais, à lui seul, une raison de changer `VERSION`.
@@ -255,7 +383,13 @@ published source archive
post-tag verification
```
Un identifiant opérationnel tel que `rel.001` ou `publish.001` MAY être utilisé pour distinguer une clôture ou une vérification de publication sans devenir une nouvelle version SemVer produit.
Un identifiant opérationnel tel que `rel.1` ou `publish.001` MAY être utilisé pour distinguer une clôture ou une vérification de publication sans devenir une nouvelle version SemVer produit. La famille `rel.N` utilise la représentation sans zéro de padding définie par la gouvernance ; les anciennes formes `rel.001*` déjà publiées restent historiques et immuables.
`rel.1` est la première tranche de clôture stable pré-tag d'une nouvelle release utilisant cette convention. Si elle échoue, `rel.1.fix.N` corrige uniquement cette fermeture. La première de ces tranches qui obtient réellement `PASS` est incluse dans le commit stable `X.Y.Z`, puis seulement le tag `vX.Y.Z` est créé.
Une preuve `publish.001`, lorsqu'elle existe, porte sur l'artefact réellement publié après le tag et reste donc extérieure au tag qu'elle vérifie. Elle ne revalide pas fonctionnellement la release. La présente règle ne renomme pas `publish.001`; son identité reste indépendante de la correction `rel.001` -> `rel.1`.
Lorsqu'un rapport `publish.001` est un prérequis de la session suivante, la clôture post-tag MUST indiquer explicitement à l'opérateur qu'il doit fournir ce rapport avec l'archive taggée. Le démarrage suivant effectue toujours son propre audit d'intake de la baseline ; il ne traite pas pour autant la stable précédente comme une release encore en attente de validation.
## Conservation et immutabilité

123
docs/rules/220-SKELETONS.md Normal file
View File

@@ -0,0 +1,123 @@
<!-- file: docs/rules/220-SKELETONS.md -->
<!-- version: 1 -->
# Skeleton specification rules
## Scope
Ce document définit le contrat transversal des skeleton specifications PGR : applicabilité, sélection des règles et profils, composition de skeletons, usage des templates, décisions propres au projet, overrides, instanciation et validation initiale.
Il ne définit pas les règles propres à une technologie. Les profils restent possédés par leurs documents normatifs, notamment le modèle de composition de [`../architecture/003-RULE_PROFILE_MODEL.md`](../architecture/003-RULE_PROFILE_MODEL.md). Les règles de validation restent possédées par [`400-VALIDATION.md`](400-VALIDATION.md) et le workflow delta/history par [`210-WORKFLOW.md`](210-WORKFLOW.md).
Les skeleton specifications concrètes vivent sous [`../skeletons/`](../skeletons/000-README.md).
## Nature d'un skeleton
Un skeleton PGR est une spécification Markdown procédurale permettant de construire une baseline locale cohérente à partir de règles, profils, templates et décisions explicites.
Un skeleton MUST NOT devenir :
- un générateur obligatoire de projet ;
- une dépendance runtime ou build vers PGR ;
- un nouveau propriétaire implicite de règles déjà possédées ailleurs ;
- un moyen de figer une architecture au-delà du scope qu'il déclare ;
- un catalogue de technologies ou de fichiers créés par anticipation.
Après instanciation, le projet destinataire possède ses fichiers, ses décisions et ses règles locales. Une évolution ultérieure de PGR ne modifie pas automatiquement ce projet.
## Applicabilité
Chaque skeleton MUST rendre explicites son objectif et les faits qui déterminent son applicabilité.
L'applicabilité MUST reposer sur le besoin réel du projet : type de baseline recherchée, langage ou écosystème utilisé, plateforme ciblée, framework réellement présent ou autre propriété concrète du scope.
Un skeleton MUST NOT être appliqué uniquement parce qu'il est fréquent, recommandé dans un autre projet ou disponible dans PGR.
Un skeleton spécialisé MAY déclarer un autre skeleton comme fondation. Cette relation doit être explicite et ne rend pas les spécialisations sœurs applicables entre elles.
## Contenu minimal d'une specification
Une skeleton specification MUST permettre d'identifier sans ambiguïté :
- son objectif et son applicabilité ;
- les règles et profils sélectionnés ou requis ;
- les autres skeletons dont elle dépend éventuellement pour sa composition ;
- les fichiers à créer, copier, adapter ou omettre ;
- les templates techniques utilisés et les décisions d'adaptation associées ;
- les décisions obligatoires qui appartiennent au projet destinataire ;
- les options, exceptions et overrides explicitement permis ;
- l'ordre d'instanciation lorsque cet ordre est significatif ;
- la validation initiale proportionnée ;
- les éléments volontairement hors scope.
La structure Markdown exacte MAY varier si ces responsabilités restent clairement séparées. PGR MUST NOT imposer des sections vides uniquement pour respecter un format cérémoniel.
## Sélection des règles et profils
Un skeleton sélectionne les owners normatifs applicables ; il ne redéfinit pas leur contenu.
La sélection des profils MUST respecter l'applicabilité, la hiérarchie et la résolution définies dans [`../architecture/003-RULE_PROFILE_MODEL.md`](../architecture/003-RULE_PROFILE_MODEL.md).
Lorsqu'une règle générale est déjà applicable sans spécialisation, le skeleton SHOULD la référencer plutôt que la recopier comme si elle lui appartenait. Lors de l'instanciation, le projet destinataire doit néanmoins disposer localement des règles nécessaires à son fonctionnement autonome, sous la forme documentaire réellement adaptée à son propre référentiel.
Un skeleton MUST NOT sélectionner toute la bibliothèque PGR par défaut. Les profils ou familles sans rapport avec le projet restent absents.
## Templates et artefacts techniques
Un template reste un artefact technique copiable distinct du skeleton et de la règle qui justifie son usage.
Lorsqu'un skeleton utilise un template, il MUST identifier le template source et les valeurs qui doivent être revues ou adaptées avant adoption. Une valeur d'exemple, un placeholder, une version de toolchain, un nom de crate, un chemin de build ou un seuil de lint présent dans un template MUST NOT devenir une valeur universelle par simple copie.
Un skeleton MAY demander de copier un template tel quel seulement lorsque le contrat du template indique qu'aucune décision locale n'est requise pour le scope visé.
Un skeleton MUST NOT télécharger des dépendances, installer des toolchains ou exécuter implicitement des commandes externes à la place du projet destinataire. Ces opérations peuvent faire partie d'une validation explicitement demandée lorsque l'environnement et le scope les justifient.
## Décisions propres au projet
Toute décision qui ne découle pas d'une règle applicable ou d'une contrainte technique établie reste une décision du projet destinataire.
Le skeleton MUST distinguer une obligation normative d'une valeur d'exemple, d'un choix recommandé et d'une option libre lorsque cette distinction est nécessaire pour éviter une adoption accidentelle.
Les décisions nécessaires à une baseline fonctionnelle MUST être résolues ou laissées comme entrées explicites avant que l'instanciation soit présentée comme terminée. Un choix encore ouvert MUST NOT être converti silencieusement en règle ou valeur par défaut arbitraire.
Les décisions locales SHOULD être consignées dans les documents ou configurations qui les possèdent durablement dans le projet créé, et non uniquement dans une trace temporaire d'instanciation.
## Composition de plusieurs skeletons
La composition SHOULD partir de la fondation la plus générale explicitement requise, puis ajouter les spécialisations réellement applicables.
Un skeleton spécialisé SHOULD référencer les responsabilités déjà couvertes par sa fondation plutôt que les recopier. Il MAY ajouter des fichiers, décisions, templates ou validations propres à son scope.
L'ordre de composition ne crée aucune priorité normative implicite. Une règle plus spécifique ne remplace une règle plus générale que selon la hiérarchie normative, un profil applicable ou une exception explicitement documentée.
Si deux skeletons applicables exigent des choix incompatibles sans relation de spécialisation ou override défini, l'instanciation MUST s'arrêter sur cette décision au lieu de choisir arbitrairement le dernier appliqué.
PGR SHOULD NOT créer un skeleton composite pour chaque combinaison de technologies. Un skeleton composite n'est justifié que lorsqu'une interaction réelle possède des étapes, artefacts ou décisions qui ne peuvent pas être correctement possédés par les skeletons composants.
## Overrides et exceptions
Un override ou une exception MUST identifier la règle, le template, le choix ou l'étape concerné, son scope et sa raison.
Un skeleton MAY prévoir des points d'override lorsqu'ils correspondent à une variabilité légitime du projet. Il MUST NOT utiliser cette possibilité pour affaiblir silencieusement une règle applicable ou masquer une incompatibilité entre profils.
Une exception propre au projet est possédée par le projet destinataire après instanciation. Elle ne devient pas automatiquement une règle générale PGR.
## Validation de l'instanciation
Chaque skeleton MUST définir une validation initiale proportionnée à ce qu'il matérialise réellement.
La validation SHOULD utiliser le mécanisme le plus fiable disponible : parseur ou build tool officiel, linter, audit structurel read-only, test ciblé ou revue humaine selon la propriété à prouver.
Lorsqu'un skeleton prétend produire une baseline directement utilisable par une toolchain, une instanciation temporaire MAY être utilisée pour vérifier les fichiers copiés ou adaptés. Les ressources temporaires SHOULD être isolées et nettoyées après la gate.
La réussite d'un audit structurel ne remplace pas une validation de toolchain lorsque le contrat à prouver appartient à cette toolchain. Inversement, PGR SHOULD NOT imposer un build coûteux lorsqu'une propriété purement documentaire ou structurelle suffit à la tranche.
Une prévalidation réalisée lors de la préparation d'un delta ne remplace jamais la gate opérateur autoritaire définie par les règles de validation.
## Évolution
Une skeleton specification est un document vivant tant qu'elle reste la specification courante de son type de projet. Sa révision interne suit les règles documentaires PGR.
Modifier un skeleton PGR n'altère pas rétroactivement les projets déjà instanciés. Une migration depuis une ancienne baseline est une décision explicite du projet concerné.
PGR matérialise un nouveau skeleton uniquement lorsqu'un besoin réel, des owners normatifs suffisants et les artefacts nécessaires existent. Une technologie encore insuffisamment cadrée reste différée plutôt que représentée par un skeleton placeholder.

127
docs/rules/230-ADOPTION.md Normal file
View File

@@ -0,0 +1,127 @@
<!-- file: docs/rules/230-ADOPTION.md -->
<!-- version: 1 -->
# Existing project adoption rules
## Scope
Ce document définit le contrat transversal d’adoption de PGR par un projet **déjà existant**. Il couvre la reprise d’une baseline réelle, l’inventaire des owners applicables, la comparaison avec les contrats locaux, la classification des décisions d’adoption, la migration progressive, les exceptions et la validation de l’état obtenu.
L’adoption d’un dépôt existant est distincte de l’instanciation d’un nouveau projet par skeleton. Les skeleton specifications restent possédées par [`220-SKELETONS.md`](220-SKELETONS.md) ; l’adoption peut les utiliser comme référence de composition sans prétendre recréer rétroactivement le projet.
Les règles de workflow et de validation restent respectivement possédées par [`210-WORKFLOW.md`](210-WORKFLOW.md) et [`400-VALIDATION.md`](400-VALIDATION.md).
## Principe
PGR s’adapte au besoin réel du projet existant ; il ne cherche pas à effacer l’histoire du dépôt ni à imposer toute la bibliothèque de profils disponible.
Une adoption MUST partir d’une baseline autoritaire réellement observée : commit, tag, archive de release ou autre état explicitement accepté par le projet. Le travail d’adoption MUST distinguer ce qui existe déjà de ce que PGR propose d’ajouter ou de modifier.
Une migration réussie produit un projet autonome gouverné localement. Le projet destinataire ne devient pas dépendant runtime ou build du dépôt PGR.
## Audit initial de la baseline
Avant de modifier le projet, l’adoption MUST établir au minimum :
- la baseline autoritaire et son niveau de confiance ;
- les règles, conventions, outils, fichiers de gouvernance et validations déjà présents ;
- les langages, plateformes, frameworks et autres profils réellement applicables ;
- les contraintes locales qui ne doivent pas être remplacées par une règle générique ;
- les incohérences ou dettes qui nécessitent une décision au lieu d’une conversion automatique.
L’audit SHOULD réutiliser les outils du projet et les audits PGR applicables lorsqu’ils sont disponibles. Il MUST NOT interpréter l’absence d’un artefact PGR comme un défaut en soi tant qu’aucune règle applicable ne l’exige.
## Mapping des owners applicables
L’adoption MUST sélectionner les owners PGR à partir du scope réel du dépôt. Elle MUST NOT activer tous les profils PGR par défaut.
Chaque owner ou contrat candidat à l’adoption doit être comparé avec l’état local avant décision. Un profil non applicable reste hors scope ; une technologie envisagée mais non encore présente MAY rester `DEFER`.
Les owners PGR servent de référence normative pour ce qui est réellement adopté. Les règles propres au projet restent locales et ne deviennent pas automatiquement des règles générales PGR.
## Classification des décisions
Le mapping d’adoption utilise les quatre classifications suivantes :
```text
ADOPT
KEEP-LOCAL
OVERRIDE
DEFER
```
### ADOPT
`ADOPT` signifie que le projet retient le contrat PGR applicable et migre son état local lorsque nécessaire.
L’adoption MAY être immédiate ou découpée en plusieurs tranches si le changement est trop large pour être validé proprement en une fois.
### KEEP-LOCAL
`KEEP-LOCAL` signifie qu’un contrat local existant reste préférable ou nécessaire et qu’il n’entre pas en contradiction avec une obligation PGR réellement adoptée.
Cette classification ne crée pas une exception : elle reconnaît qu’un choix local demeure hors du besoin de normalisation ou qu’un owner PGR ne possède pas ce détail.
### OVERRIDE
`OVERRIDE` signifie qu’une règle PGR applicable est volontairement remplacée ou raffinée dans un scope local.
L’override MUST identifier la règle concernée, le scope, la raison et le contrat local retenu. Il ne doit pas être utilisé pour masquer une migration incomplète ou faire disparaître une violation non résolue.
### DEFER
`DEFER` signifie qu’une décision applicable est volontairement différée parce qu’un prérequis, un owner, une preuve ou une priorité manque encore.
Le report SHOULD indiquer ce qui permettrait de reprendre la décision. `DEFER` MUST NOT être présenté comme une adoption accomplie.
## Migration progressive
L’adoption SHOULD privilégier des tranches cohérentes et validables. Une migration massive n’est justifiée que si elle apporte moins de risque et de coût qu’une progression incrémentale.
Une tranche d’adoption SHOULD :
1. identifier le sous-ensemble de décisions concerné ;
2. modifier uniquement les owners locaux, configurations, templates ou structures nécessaires ;
3. appliquer une validation proportionnée aux contrats réellement modifiés ;
4. enregistrer les décisions durables chez leurs owners locaux ;
5. laisser les domaines non concernés inchangés.
L’adoption d’un profil ne force pas l’adoption simultanée des profils voisins. Par exemple, un dépôt Rust utilisant Tauri peut adopter les règles Rust/Cargo disponibles tout en différant les owners Web encore insuffisants.
## Préservation de l’historique
PGR MUST NOT demander de réécrire des commits, tags, histories, changelogs ou autres snapshots historiques uniquement pour donner l’apparence d’une conformité rétroactive.
Les conventions nouvelles s’appliquent à partir du point d’adoption explicitement établi. Les artefacts historiques restent interprétés selon leur contexte d’origine, sauf correction exceptionnelle justifiée par une erreur factuelle ou un risque réel.
Une adoption MAY documenter des écarts hérités comme dette, exception temporaire ou contexte historique sans modifier les snapshots qui les ont produits.
## Relation avec les skeletons et templates
Un skeleton PGR MAY servir de checklist de comparaison pour un projet existant. Il ne doit pas être appliqué comme si le dépôt était vide.
Lorsqu’un template PGR est pertinent, l’adoption MUST comparer sa responsabilité et ses valeurs avec le fichier local avant remplacement. Un fichier local fonctionnel ne doit pas être écrasé uniquement pour obtenir une copie identique au template PGR.
Une différence locale MAY être conservée si elle relève d’une décision du projet, d’un `KEEP-LOCAL` ou d’un `OVERRIDE` valide.
## Validation de l’adoption
Chaque étape d’adoption MUST sélectionner des preuves proportionnées selon [`400-VALIDATION.md`](400-VALIDATION.md).
La validation SHOULD d’abord prouver que le projet reste fonctionnel dans son environnement réel, puis que les nouveaux contrats de gouvernance ou de structure sont respectés. Un audit PGR read-only ne remplace pas une toolchain ou un smoke autoritaire lorsqu’un contrat appartient à cette toolchain ou à cet environnement.
Une adoption n’est terminée que lorsque les décisions de son scope sont classifiées, les changements retenus sont appliqués, les validations requises sont acquises et les `DEFER` restants sont explicitement hors du scope déclaré.
## Résultat attendu
Une adoption PGR réussie laisse :
- un projet autonome ;
- uniquement les owners PGR réellement applicables ;
- les choix locaux légitimes préservés ;
- les overrides explicites ;
- les domaines différés clairement identifiés ;
- un historique non falsifié ;
- une validation proportionnée au changement réellement effectué.
[`../templates/007-EXISTING_PROJECT_ADOPTION.md`](../templates/007-EXISTING_PROJECT_ADOPTION.md) fournit un pattern documentaire court pour préparer et suivre ce mapping sans imposer un format de migration unique.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/300-DOCUMENTATION.md -->
<!-- version: 2 -->
<!-- version: 4 -->
# Documentation rules
@@ -47,9 +47,9 @@ Il SHOULD NOT devenir un fichier monolithique contenant toutes les règles spéc
### `ROADMAP.md`
`ROADMAP.md` décrit la trajectoire macro du projet : objectifs de versions, grandes étapes et ordre fonctionnel attendu.
`ROADMAP.md` décrit la trajectoire macro **engagée** du projet : objectifs de versions, grandes étapes et ordre fonctionnel attendu. Elle n'est ni un catalogue de toutes les possibilités futures, ni une obligation de prévoir arbitrairement plusieurs versions à l'avance.
Il MUST NOT devenir un journal des prereleases ou recopier les histories de tranche.
Il MUST NOT devenir un journal des prereleases ou recopier les histories de tranche. Une idée, une étude ou une possibilité encore spéculative reste chez son owner tant qu'une décision suffisante ne justifie pas son entrée dans la trajectoire engagée.
Lorsqu'un projet utilise des statuts de roadmap, la convention PGR est :
@@ -62,6 +62,30 @@ Lorsqu'un projet utilise des statuts de roadmap, la convention PGR est :
Une autre convention MAY être adoptée par un projet si elle est explicitement définie et cohérente.
Une roadmap à horizon fini est valide. Le projet MUST NOT inventer un numéro de version, un objectif ou un engagement uniquement pour éviter que la roadmap se termine.
### Revue d'horizon
Une revue d'horizon est une activité de gouvernance qui décide si la trajectoire macro connue doit être étendue, maintenue volontairement ouverte, mise en pause ou considérée accomplie. Elle n'est pas une nouvelle phase SemVer.
Une revue SHOULD être planifiée lorsque l'un des signaux suivants devient pertinent :
- la release courante ou la suivante est la dernière entrée engagée de la roadmap alors que le projet doit continuer ;
- un jalon important change ce qu'il est raisonnable de planifier ensuite ;
- plusieurs ideas/studies ou décisions récentes peuvent modifier la trajectoire ;
- les hypothèses qui fondaient les versions futures ont été invalidées par le travail réel.
La revue MAY avoir lieu dans une tranche de la release courante ou dans une session stratégique séparée. Une session séparée ne change pas `VERSION` par elle-même.
Une revue d'horizon produit l'un des résultats utiles suivants :
- **étendre** `ROADMAP.md` avec des objectifs suffisamment décidés ;
- **laisser l'horizon ouvert** et enregistrer le déclencheur ou le moment de la prochaine revue ;
- **différer/mettre en pause** une trajectoire sans fabriquer de remplaçant ;
- **constater l'accomplissement** de l'objectif macro si aucune suite n'est nécessaire.
Le plan actif SHOULD indiquer si une telle revue est nécessaire avant sa fermeture et où elle aura lieu.
### `CHANGELOG.md`
`CHANGELOG.md` décrit les changements utiles aux utilisateurs ou intégrateurs d'une release.
@@ -76,6 +100,26 @@ Un document sous `docs/objectives/` décrit la mission durable, les objectifs, c
Il MUST NOT être remplacé par `ROADMAP.md` : les objectifs expliquent pourquoi le projet existe et ce qu'il cherche à garantir ; la roadmap décrit comment sa trajectoire est découpée.
## Registre local de contrats de fichiers ou familles
Un projet MAY maintenir un registre local lorsque plusieurs fichiers ou familles durables ont des responsabilités, sources de vérité ou règles de modification qui ne sont pas suffisamment évidentes depuis leur nom, leur écosystème ou leurs owners existants.
Ce registre est un outil de désambiguïsation, pas un inventaire exhaustif de l'arborescence. Il MUST NOT être créé uniquement pour recopier les rôles déjà définis par PGR, un manifeste, une toolchain ou une documentation locale plus appropriée. Un petit projet dont les responsabilités sont déjà claires SHOULD ne pas créer ce document.
Chaque entrée utile SHOULD identifier au minimum :
- le fichier, motif de chemin ou famille concernée ;
- sa responsabilité durable ;
- la règle ou le déclencheur pertinent de modification.
Selon le besoin, une entrée MAY aussi préciser une source de vérité, le caractère généré/versionné, un owner local ou une validation associée. Ces champs supplémentaires ne doivent être ajoutés que s'ils réduisent réellement une ambiguïté.
Le nom, l'emplacement et la forme du registre appartiennent au projet destinataire. PGR n'impose ni `FILE_CONTRACTS.md`, ni une table Markdown, ni un catalogue de chaque fichier. Une liste courte, une table ou une autre forme lisible sont équivalentes si le contrat reste explicite.
Lorsqu'un owner existant possède déjà la règle détaillée, le registre SHOULD le référencer plutôt que dupliquer son contenu. Il est mis à jour lorsque le contrat d'une famille change réellement ; l'ajout d'un fichier conforme à une famille déjà décrite ne force pas une nouvelle entrée.
[`../templates/004-FILE_FAMILY_CONTRACTS.md`](../templates/004-FILE_FAMILY_CONTRACTS.md) fournit un pattern documentaire court pour les projets qui choisissent d'adopter ce registre.
## Taxonomie documentaire
La taxonomie doit rester sémantique et proportionnée. Les familles communes comprennent notamment :
@@ -111,6 +155,22 @@ Si une décision est déjà imposée par une contrainte explicite et qu'aucune a
Les décisions durables doivent ensuite être reflétées dans l'architecture, les règles, objectifs ou autres documents vivants qui possèdent réellement ce contrat.
La maturation typique MAY suivre :
```text
idea
↓
study
↓
decision durable / architecture / règle
↓
roadmap ou plan lorsqu'un engagement de réalisation existe
↓
implementation
```
Toutes les possibilités n'ont pas à parcourir cette chaîne. Une idée ou une étude MAY être rejetée, différée, superseded ou rester inconclusive. Une conclusion `retained` ne crée pas automatiquement une promesse de roadmap : le passage vers `ROADMAP.md` exige encore une décision d'engagement macro explicite.
## Documents vivants et snapshots historiques
PGR distingue :

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/510-RUST_CARGO.md -->
<!-- version: 2 -->
<!-- version: 7 -->
# Profil Rust / Cargo
@@ -11,9 +11,13 @@ Il spécialise [`500-LANGUAGES.md`](500-LANGUAGES.md) pour les responsabilités
Une règle plus spécifique, par exemple Android, WASM, Tauri ou une frontière FFI, MAY raffiner ce profil dans son scope sans modifier la politique Rust générale.
Pour un **nouveau projet contrôlé** par l'organisation, PGR sélectionne par défaut le profil strict décrit ci-dessous : provenance des symboles visible, façade crate-root explicite, contrôle de flux explicite et noms de crates lisibles. Un projet existant ou imposé par un tiers MAY conserver des contraintes différentes via des règles project-specific ou des exceptions bornées ; cette adaptation ne rend pas le profil strict moins canonique pour les nouvelles baselines contrôlées.
## Toolchain et édition
Un nouveau projet Rust SHOULD utiliser une toolchain stable récente compatible avec ses dépendances et ses cibles. Une toolchain nightly, beta ou autre prerelease nécessite une justification explicite.
Un nouveau projet Rust contrôlé MUST utiliser l'édition Rust 2024 avec une toolchain stable compatible avec ses dépendances et ses cibles, sauf contrainte externe explicitement documentée. Une toolchain nightly, beta ou autre prerelease nécessite une justification explicite.
`2024` est la baseline normative actuelle des projets contrôlés ; PGR ne bascule pas automatiquement vers une future édition au seul motif qu'elle existe. Une évolution de cette baseline demande une décision PGR explicite et une validation de compatibilité.
PGR MUST NOT imposer un pin exact de toolchain uniquement parce qu'un projet source historique utilisait cette version. Un fichier `rust-toolchain.toml` ou équivalent SHOULD être ajouté uniquement lorsqu'un besoin réel de reproductibilité, de composant ou de compatibilité l'exige.
@@ -34,6 +38,62 @@ Un monorepo contenant plusieurs unités de release indépendantes MUST NOT fabri
Le répertoire `crates/` est le placement PGR recommandé pour les packages Rust d'un workspace structuré, sauf layout imposé par un framework, une plateforme ou un projet existant.
### Nomenclature des crates dans un projet contrôlé
Une crate appartenant à un projet contrôlé MUST commencer par le nom court canonique du projet ou une abréviation documentée et stable. Le reste du nom SHOULD rendre immédiatement lisibles sa responsabilité principale puis, lorsqu'il apporte une information réelle, son rôle ou sa cible.
La forme recommandée est :
```text
<project>-<responsibility>-<role-or-target>
```
Exemples de classificateurs utiles selon le projet :
```text
lib
api
worker
job
cli
desk
desktop
tauri
wasm
server
```
Cette liste n'est ni exhaustive ni un vocabulaire imposé. Un suffixe ou classificateur ne doit pas être ajouté par symétrie : `api` suppose un vrai contrat/extensibility boundary, `worker` un service continu identifiable, `cli` une interface ligne de commande, etc. À l'inverse, un rôle important ne doit pas être masqué dans un nom générique comme `common`, `core` ou `utils` sans responsabilité suffisamment précise.
Un projet historique MAY conserver un ordre local déjà stable, par exemple un rôle placé avant la responsabilité, si sa nomenclature est documentée et cohérente. PGR n'impose aucune campagne de renommage rétroactive uniquement pour adopter la grammaire recommandée.
### Les suffixes portent un contrat architectural
Dans un projet contrôlé, les classificateurs de nom ne sont pas décoratifs. Lorsqu'ils sont utilisés, ils décrivent une responsabilité que l'architecture et le graphe de dépendances doivent respecter.
Une crate terminée par `-api` porte principalement des contrats réutilisables : traits, types, DTOs, identifiants et primitives nécessaires à des implémentations séparées. Elle SHOULD rester passive et sans runtime. Une crate `-api` purement déclarative MUST NOT dépendre d'une crate de logging/tracing uniquement pour satisfaire une convention transversale. Une instrumentation n'y est ajoutée que si la crate possède un comportement réel à observer.
Une crate `-api` MUST NOT être créée uniquement pour obtenir une paire de noms symétrique. Elle est justifiée lorsqu'au moins une frontière réelle existe : implémentations multiples ou remplaçables, implémentation externe, backend injectable, lifecycle partagé ou contrat public dont l'implémentation doit pouvoir vivre dans une autre crate. Lorsqu'une seule implémentation est réellement prévue et qu'aucune frontière de contrat séparée n'apporte de valeur, une seule crate `-lib` est préférée.
Une crate terminée par `-lib` porte une implémentation ou fonctionnalité réutilisable. Par défaut, elle est une crate bibliothèque sans cible binaire. Des familles comme `worker`, `job`, `store`, `transport` ou `scenario` MAY apparaître dans la responsabilité avant le suffixe `-lib` lorsqu'elles décrivent ce que la bibliothèque implémente ; le suffixe terminal `-lib` continue alors d'indiquer qu'il s'agit d'une unité réutilisable et non d'un launcher.
### Séparation bibliothèques / exécutables
Hors exception de framework ou plateforme explicitement documentée, un package contrôlé MUST NOT combiner une bibliothèque réutilisable et une cible binaire uniquement par commodité. La logique réutilisable appartient à une ou plusieurs crates `-lib`; l'exécutable appartient à un package distinct qui les consomme.
Le nom d'un package exécutable SHOULD rendre visible son rôle de processus ou d'interface, par exemple `-cli`, `-desk`, `-worker`, `-job` ou `-server` lorsque ces termes décrivent réellement le launcher. Le binaire SHOULD rester une couche de composition mince : initialisation du processus, verrou/single-instance lorsque nécessaire, arguments CLI, wiring des bibliothèques, lifecycle et arrêt. La logique métier ou technique réutilisable ne doit pas être dupliquée dans `main.rs`.
Tauri constitue l'exception framework actuellement reconnue par PGR à cette séparation par défaut : son profil peut demander un package mixte bibliothèque + binaire pour servir simultanément les entrées desktop/mobile. Cette exception est possédée par [`710-TAURI.md`](710-TAURI.md) et ne justifie pas de généraliser les packages mixtes aux workers, jobs ou autres exécutables. Toute autre exception mixte demande une règle locale et une raison technique identifiable.
## Diagnostics structurés et ownership du logging
Pour les nouveaux projets Rust contrôlés, `tracing` est le mécanisme recommandé de diagnostics structurés. La façade `log` MAY être conservée comme bridge de compatibilité lorsqu'une dépendance l'impose, mais elle SHOULD NOT devenir le mécanisme principal d'un nouveau projet lorsqu'aucune contrainte externe ne le requiert.
Lorsqu'un workspace possède plusieurs crates runtime partageant les mêmes règles de diagnostics, il SHOULD centraliser la configuration de logging/tracing dans une crate transverse dédiée, typiquement `<project>-logging-lib` ou un nom équivalent conforme à la nomenclature locale. Dès que plusieurs exécutables ou bibliothèques ont besoin du même subscriber, des mêmes filtres/sinks ou du même lifecycle de guard, cet owner commun SHOULD remplacer les initialisations dupliquées. Un petit projet à exécutable unique n'est pas obligé de créer une crate dédiée sans valeur de réutilisation.
Cette crate commune possède normalement la composition de `tracing-subscriber`, l'usage de `tracing-appender` lorsque nécessaire, les filtres/sinks/formats partagés et le lifecycle d'initialisation. Une bibliothèque métier ou technique MAY émettre des événements structurés, mais SHOULD NOT installer silencieusement un subscriber global. Les crates `-api` purement déclaratives restent normalement sans dépendance de logging.
## Manifests et dépendances Cargo
Dans un workspace, une dépendance tierce réellement partagée par plusieurs crates SHOULD posséder sa contrainte de version canonique sous `[workspace.dependencies]`.
@@ -84,26 +144,57 @@ Lorsqu'une FFI ou une plateforme impose réellement une opération `unsafe`, l'e
Une exception FFI locale n'autorise donc pas à remplacer globalement `unsafe_code = "forbid"` par une politique permissive pour toutes les crates.
## API, visibilité et rustdoc
## API, visibilité, imports et chemins
Tout élément `pub` ou `pub(crate)` SHOULD posséder une rustdoc utile au point de déclaration lorsque son contrat dépasse une implémentation triviale locale.
Dans le profil strict d'un projet contrôlé, tout élément `pub` ou `pub(crate)` MUST posséder une rustdoc utile au point de déclaration. Toute réexportation `pub use` ou `pub(crate) use` visible au crate-root MUST également porter une rustdoc adjacente utile. Une rustdoc qui répète seulement le nom du symbole ne satisfait pas ce contrat.
Une crate réutilisable SHOULD exposer son API durable depuis son crate-root par des réexports explicites. Les modules d'implémentation SHOULD rester privés ; `pub mod` ne doit pas être utilisé uniquement pour éviter de concevoir une façade stable.
Les modules d'implémentation restent privés. `pub mod` MUST NOT être utilisé pour exposer paresseusement une arborescence interne ; `pub(super)` et `pub(in ...)` MUST NOT remplacer une façade crate-root explicite dans une baseline contrôlée.
Un élément partagé à l'échelle de sa propre crate SHOULD être consommable via `crate::Item` après réexport approprié. Les autres crates consomment l'API publique du crate propriétaire plutôt que ses chemins internes.
Un élément `pub` d'un module fichier MUST être réexporté explicitement au crate-root. Un élément `pub(crate)` consommé hors de son module MUST de même posséder un réexport `pub(crate)` au crate-root. Un helper réellement local SHOULD rester privé plutôt qu'élargir artificiellement sa visibilité.
Les glob imports SHOULD être évités. Un alias de réexport ne doit pas servir à masquer durablement une collision de noms dans l'API ; lorsqu'un nom fait partie du contrat public, le propriétaire SHOULD choisir un nom canonique non ambigu.
Les réexports d'éléments internes commencent par `self::` :
PGR ne généralise pas l'interdiction KSP plus stricte de tous les `use` non-traits : cette convention appartient à un profil ou projet plus spécifique tant qu'elle n'est pas nécessaire au contrat Rust général.
```rust
pub use self::foo::Foo;
pub(crate) use self::bar::InternalBar;
```
Un réexport de crate externe utilise son chemin public canonique. Les réexports groupés par accolades, les glob imports et les alias `as` servant à raccourcir ou masquer un nom MUST NOT être utilisés. Une collision durable se résout en donnant au symbole son nom canonique dans son module propriétaire.
### `use` réservé aux traits
Dans le profil strict, `use` MUST NOT importer une constante, fonction, structure, énumération, union, alias de type, module ou macro uniquement pour raccourcir son chemin. Les déclarations `use` sont réservées aux traits lorsqu'une résolution de méthode ou une contrainte du langage exige réellement leur mise en scope.
Un import de trait reste au niveau du module et ne mélange pas de symboles non-traits. Un projet MAY ajouter un marqueur de commentaire spécifique à son audit local, mais PGR n'impose pas un commentaire tel que `rust-rules: trait-import` : ce marqueur est un mécanisme d'enforcement, pas la règle sémantique elle-même.
Pour un élément fourni par une crate externe, le code utilise directement le **chemin public le plus court** exposé par cette crate, par exemple :
```rust
std::path::Path
serde_json::Value
other_crate::Item
```
et non un `use` non-trait destiné à raccourcir ce chemin. Un chemin interne plus long n'est pas préféré lorsque la crate externe expose déjà une façade publique plus courte.
### Façade crate-root et références intra-crate
Dès qu'un item partagé possède une identité crate-root, toute référence dans la même crate MUST utiliser `crate::Item`, y compris depuis son module de déclaration et depuis ses tests unitaires attachés. Les formes `Item`, `self::Item`, `super::Item`, `module::Item` et `crate::module::Item` ne sont pas des chemins de consommation canoniques pour cet item partagé.
Un élément strictement privé reste local au module et n'est pas réexporté. Dans un fichier de tests unitaires rattaché au module parent, un élément privé du parent peut être référencé via `super::PrivateItem`; un élément `pub` ou `pub(crate)` partagé continue d'être référencé via `crate::Item`.
Les autres crates consomment l'API publique du crate propriétaire via `owner_crate::Item`, jamais via ses modules internes. La visibilité d'un item MUST NOT être élargie uniquement pour permettre son test.
Ces conventions sont plus strictes que le Rust idiomatique minimal, mais elles sont retenues pour les projets contrôlés afin de rendre immédiatement visibles l'ownership et la provenance des symboles. Un projet externe contraint peut définir un override explicite ; l'exception ne devient pas la nouvelle règle PGR.
## Contrôle de flux et erreurs
Dans le code de production du profil strict PGR :
- `unwrap()` et `expect()` MUST NOT servir à traiter un chemin d'erreur récupérable ;
- `unwrap()` et `expect()` MUST NOT être utilisés ;
- `panic!` MUST NOT représenter une erreur métier récupérable ;
- les retours explicites sont la convention par défaut ;
- l'opérateur `?` est désactivé par le profil Clippy strict afin de conserver des chemins d'erreur explicites.
- les retours explicites sont obligatoires lorsque la fonction possède une valeur de retour ;
- l'opérateur `?` MUST NOT être utilisé ; les chemins `Ok`/`Err` et conversions d'erreur restent explicites.
Une règle plus spécifique MAY définir une politique d'erreur différente lorsqu'elle possède une justification architecturale explicite. PGR ne généralise pas l'interdiction d'une bibliothèque d'erreur particulière à partir d'un seul projet source.
@@ -129,12 +220,23 @@ L'édition de ce fichier MUST rester cohérente avec l'édition réellement util
Après une modification Rust, `cargo fmt --all` applique le formatage canonique puis `cargo fmt --all -- --check` vérifie l'état livré. Une modification produite uniquement par le formatter officiel ne crée pas artificiellement une nouvelle révision documentaire d'un fichier si aucun contenu réel n'a changé.
Le profil de style strict supplémentaire peut être adopté par un projet qui souhaite appliquer les conventions KSP/Games. Dans ce scope choisi, les lignes vides consécutives SHOULD être supprimées, ainsi que les lignes vides à l'intérieur des fonctions/méthodes et des définitions `struct`/`enum`. Ces propriétés ne sont pas entièrement possédées par Rustfmt. L'audit facultatif `scripts/audit_rust_blank_lines.py` contrôle ces deux formes d'espacement sur les seuls fichiers Rust sélectionnés.
Le profil structurel strict fait partie du défaut des nouvelles baselines Rust contrôlées. Un projet externe, historique ou imposé peut documenter un override borné ; cet override ne réduit pas le profil canonique des nouveaux projets. L'owner reste partagé entre `rustfmt` pour ce qu'il sait réécrire de manière fiable et des audits read-only monotâches pour les propriétés de structure qu'il ne possède pas.
Les constantes de module qui constituent un bloc homogène sans ordre sémantique SHOULD être regroupées dans l'ordre `pub`, `pub(crate)`, privé, puis par nom dans chaque visibilité : aucune ligne vide entre constantes d'une même visibilité et exactement une entre niveaux différents. `scripts/audit_rust_const_blocks.py` vérifie cette convention uniquement sur les constantes au niveau racine des fichiers choisis. Son exécution requiert une sélection explicite des fichiers pour lesquels cet ordre est réellement souhaité. Une table de protocole, une séquence de migrations ou tout autre ordre contractuel conserve son ordre propre ; le lecteur ne doit pas réordonner une telle séquence pour faire passer l'audit.
Les lignes vides consécutives MUST être supprimées. Aucune ligne vide n'est conservée à l'intérieur du corps d'une fonction ou méthode, ni à l'intérieur d'une définition `struct` ou `enum`. `scripts/audit_rust_blank_lines.py` contrôle ces deux propriétés sur les fichiers Rust sélectionnés.
L'ordre des `use`, réexports et déclarations `mod` que Rustfmt sait réordonner dans ses groupes appartient au formatteur ; les modules de test après les modules de production et l'organisation d'une façade relèvent de leur contrat local, avec revue ou audit dédié seulement si celui-ci apporte une preuve fiable. Les règles rustdoc et d'API conservent leurs propriétaires ci-dessus. Les scripts PGR ne prétendent pas parser toutes les macros ou les items Rust : une décision sémantique reste une revue.
Deux items Rust distincts et voisins d'un même scope — fonctions/méthodes, `struct`, `enum`, `union`, `trait`, blocs `impl` ou changements de catégorie/visibilité — MUST être séparés par exactement une ligne vide lorsqu'aucune syntaxe intermédiaire ne possède elle-même l'espacement. `scripts/audit_rust_item_spacing.py` contrôle cette séparation sans tenter d'interpréter les macros ou de posséder les blocs compacts `const`/`static`/`type`.
Les déclarations compactes d'un même type et d'une même visibilité SHOULD former un bloc sans ligne vide lorsque l'ordre n'a pas de signification sémantique. Pour les constantes de module sélectionnées, l'ordre canonique est `pub`, `pub(crate)`, privé, puis le nom dans chaque visibilité ; exactement une ligne vide sépare deux niveaux de visibilité. `scripts/audit_rust_const_blocks.py` possède uniquement ce contrat `const` au niveau racine. Il MUST NOT être appliqué aveuglément à une table de protocole, une séquence de migrations, un schéma, une table de dispatch ou toute autre série dont l'ordre est contractuel. Les blocs `static`/`type` peuvent suivre la même présentation par convention locale, mais PGR ne leur ajoute pas encore un audit dédié uniquement pour atteindre une symétrie théorique.
Les déclarations `mod` de production d'un même fichier MUST précéder les modules de tests conditionnels ; les deux groupes sont ordonnés alphabétiquement lorsque l'ordre ne porte aucune sémantique locale. `scripts/audit_rust_module_order.py` contrôle cette propriété. `rustfmt` reste propriétaire de l'ordre qu'il réécrit déjà à l'intérieur d'un bloc contigu.
Les `use` non exportés autorisés par le profil strict — donc normalement des imports de traits — restent au niveau du module, avant les déclarations Rust métier et dans un bloc contigu sans ligne vide interne. `scripts/audit_rust_trait_import_blocks.py` contrôle uniquement cette disposition ; il ne prétend pas déterminer lexicalement si le symbole importé est effectivement un trait. L'ordre intra-bloc reste celui de `cargo fmt --all`.
Au crate-root, les réexports `pub use` constituent un bloc avant les `pub(crate) use`. Aucune ligne vide n'est admise à l'intérieur d'un bloc de même visibilité et exactement une ligne vide sépare les deux niveaux lorsqu'ils existent tous deux. `scripts/audit_rust_reexport_blocks.py` contrôle cette structure sans imposer un second tri : l'ordre intra-bloc reste celui produit par Rustfmt. Les rustdocs adjacentes restent possédées par les règles d'API, pas par cet audit de forme.
Lorsqu'un `struct` et ses `impl` forment une unité locale, les `impl` SHOULD suivre la structure ; de même, les éléments visibles SHOULD généralement précéder les helpers privés lorsque cela rend l'API plus lisible. PGR n'impose toutefois pas un ordre global automatique `enum → struct → impl → fn` : un ordre métier, protocolaire ou pédagogique peut être plus important. Cette propriété reste une revue tant qu'un audit fiable ne peut pas distinguer la structure informative d'un ordre sémantique.
Les scripts PGR restent des analyseurs lexicaux ciblés, pas un parser Rust général. Une macro complexe, un item généré ou une syntaxe nouvelle peut nécessiter une revue humaine ou l'owner Rust officiel. Une règle déjà possédée par `rustfmt`, rustc ou Clippy MUST NOT être réimplémentée uniquement pour multiplier les gates.
## Configuration Cargo et artefacts générés
`.cargo/config.toml` est le propriétaire naturel d'une configuration Cargo partagée par le projet lorsqu'une telle configuration est nécessaire.
@@ -192,4 +294,8 @@ Lorsqu'une règle Rust devient objectivement automatisable dans un projet ou ske
Un éventuel wrapper d'orchestration MAY appeler plusieurs audits, mais chaque audit propriétaire doit conserver une responsabilité identifiable et rester read-only.
Les deux audits de style disponibles sont documentés dans [`../validation/002-RUST_STYLE_AUDITS.md`](../validation/002-RUST_STYLE_AUDITS.md). Ils restent optionnels et prennent un corpus Rust explicitement sélectionné ; le dépôt PGR lui-même ne contient pas de workspace Rust sur lequel une telle gate fournirait une preuve réelle.
Les deux audits de style disponibles sont documentés dans [`../validation/002-RUST_STYLE_AUDITS.md`](../validation/002-RUST_STYLE_AUDITS.md). Ils restent optionnels et prennent un corpus Rust explicitement sélectionné.
[`../validation/003-RUST_EXPORT_COMPLETENESS.md`](../validation/003-RUST_EXPORT_COMPLETENESS.md) documente séparément l'audit facultatif qui matérialise ce contrat strict. `RUST-API-201` vérifie la présence de la façade pour les items partagés ; `RUST-IMPORT-201` vérifie que les références intra-crate détectées passent réellement par `crate::Item`, y compris dans le module propriétaire, et pas seulement qu'un chemin interne long a été évité.
Cet audit ne rend pas le contrat strict obligatoire pour tous les projets Rust et ne remplace pas le compilateur. Il contrôle au contraire une convention architecturale que `rustc` et Clippy ne possèdent pas. Le dépôt PGR lui-même ne contient pas de workspace Rust sur lequel une telle gate fournirait une preuve runtime ou Cargo réelle.

View File

@@ -0,0 +1,102 @@
<!-- file: docs/rules/530-TYPESCRIPT.md -->
<!-- version: 3 -->
# Profil TypeScript
## Rôle et applicabilité
Ce profil possède les règles réutilisables propres à TypeScript lorsqu'un projet sélectionne TypeScript pour du code frontend ou un autre package JavaScript typé.
Il complète [`500-LANGUAGES.md`](500-LANGUAGES.md). Il ne possède ni le package manager, ni `package.json`, ni le bundler/dev server, ni la chaîne CSS/Sass, ni le host natif ou navigateur.
Le profil s'applique lorsqu'une partie du source contrôlé est écrite en TypeScript ou lorsque la validation du projet inclut explicitement la toolchain TypeScript.
## Recommandation pour les projets contrôlés
Pour un frontend que l'organisation contrôle, TypeScript **SHOULD** être préféré à du JavaScript non typé dès que le frontend porte une logique durable non triviale.
Cette préférence n'est pas une obligation universelle. Du JavaScript direct MAY rester approprié pour un artefact très petit, un script isolé, une contrainte externe ou un environnement où l'introduction de TypeScript n'apporte pas une valeur proportionnée.
La justification de la recommandation est fonctionnelle : TypeScript ajoute une vérification statique avant exécution et permet de détecter une partie des incohérences de types pendant la validation plutôt qu'au runtime.
## Frontières typées avec d'autres écosystèmes
TypeScript facilite également les frontières où des types doivent être partagés avec un autre langage ou runtime.
Lorsqu'un projet Rust expose des DTO, structures ou énumérations destinés au frontend et qu'un générateur de bindings tel que TS-RS est applicable, la génération de déclarations TypeScript depuis la source de vérité Rust SHOULD être préférée à la duplication manuelle des mêmes contrats.
Cette recommandation ne transforme pas TS-RS en dépendance générale de TypeScript. L'owner Rust, le framework ou le sous-système qui possède la frontière décide si cette génération est requise. Le profil Tauri peut notamment renforcer ce contrat dans son propre scope.
## Déclarations de types externes et intégration IDE
Les dépendances TypeScript ne nécessitent pas toutes un package `@types/*` séparé. Avant d'ajouter une déclaration externe, le projet MUST déterminer si le package consommé fournit déjà ses propres fichiers de déclaration TypeScript. Une déclaration déjà fournie par le package ne doit pas être doublée arbitrairement par un package `@types/*`.
Lorsqu'une dépendance utilisée par du code TypeScript ne fournit pas de déclarations suffisantes, le projet **SHOULD** rechercher une source de types maintenue et compatible, typiquement le package `@types/<nom>` publié depuis DefinitelyTyped lorsqu'il existe. Cette dépendance améliore le contrôle statique, la compréhension des API par le language service TypeScript et, par conséquent, les diagnostics, la navigation et la complétion dans les IDE compatibles.
Pour une application privée ou de l'outillage local, les packages de déclarations qui ne sont nécessaires qu'au développement **SHOULD** normalement être placés dans `devDependencies`. Exemples d'applicabilité :
```text
@types/node code, configuration ou outillage TypeScript utilisant réellement des API/globales Node
@types/bootstrap code TypeScript utilisant les API JavaScript Bootstrap lorsque Bootstrap ne fournit pas lui-même les déclarations requises
```
Ces exemples ne sont pas des dépendances PGR universelles. Un frontend navigateur qui n'analyse aucun code Node MUST NOT ajouter `@types/node` uniquement par habitude. Un projet qui ne consomme que le CSS/Sass de Bootstrap n'a pas besoin de `@types/bootstrap` pour cette seule raison.
Lorsqu'un `tsconfig.json` utilise explicitement `compilerOptions.types`, les packages de déclarations globales nécessaires au contexte analysé doivent être sélectionnés de manière cohérente avec cette liste. Les types importés depuis un module restent gouvernés par la résolution de modules applicable.
Pour une bibliothèque publiée, la classification diffère : si les déclarations publiques produites par la bibliothèque référencent un package de types externe requis par les consommateurs, ce package MUST rester disponible à ces consommateurs. Il ne doit donc pas être caché en `devDependencies` par simple convention d'application ; sa classification dans `dependencies`, `peerDependencies` ou une autre relation appropriée doit suivre le contrat de publication réel.
Les versions des déclarations externes SHOULD rester compatibles avec le package runtime concerné et avec la version TypeScript sélectionnée. PGR MUST NOT inventer une version `@types/*` dans un template générique sans dépendance réelle à typer.
## Configuration et validation
`tsconfig.json`, les options de compilation/type-check, les fichiers inclus/exclus et la commande TypeScript canonique appartiennent à ce profil.
Pour un nouveau package TypeScript contrôlé, la baseline PGR `SHOULD` activer au minimum :
```text
strict = true
noEmit = true
```
`strict` exprime la volonté d'utiliser le contrôle de types renforcé de TypeScript. `noEmit` sépare le type-check de la production des artefacts JavaScript lorsque cette production appartient à un bundler ou à un autre outil.
Pour une baseline stricte, PGR `SHOULD` également activer les contrôles simples suivants sauf incompatibilité documentée :
```text
noUnusedLocals = true
noUnusedParameters = true
noFallthroughCasesInSwitch = true
```
Les choix `target`, `module`, `moduleResolution`, `lib`, `types`, `jsx`, chemins/aliases, `include` et `exclude` dépendent du runtime, du bundler, du framework et du layout réel. PGR MUST NOT les figer dans le profil TypeScript générique uniquement parce qu'ils apparaissent dans Games.
Le package `SHOULD` exposer une validation TypeScript indépendante sous un script canonique :
```text
typecheck
```
Lorsque le compilateur local est installé dans le package, le pattern recommandé est :
```text
tsc --noEmit
```
Un build Vite, Tauri ou autre ne remplace pas automatiquement cette preuve ciblée lorsqu'une propriété de typage doit être validée indépendamment.
Le modèle minimal [`../../templates/web-typescript/tsconfig.json`](../../templates/web-typescript/tsconfig.json) active uniquement les options génériques ci-dessus. Le guide [`../templates/008-WEB_TYPESCRIPT_PACKAGE.md`](../templates/008-WEB_TYPESCRIPT_PACKAGE.md) liste les décisions à compléter avant adoption réelle.
## Ce que le profil n'impose pas
Ce profil ne rend obligatoire :
- ni Vite ;
- ni npm ou un autre package manager particulier ;
- ni Sass ou un framework CSS ;
- ni TS-RS pour un projet qui ne partage aucun contrat avec Rust ;
- ni un framework frontend particulier ;
- ni WASM ;
- ni Tauri.
Les choix correspondants restent possédés par leurs owners applicables.

View File

@@ -0,0 +1,78 @@
<!-- file: docs/rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md -->
<!-- version: 3 -->
# Profil écosystème de packages JavaScript
## Rôle et applicabilité
Ce profil possède le contrat réutilisable d'un package JavaScript/TypeScript utilisant un manifest `package.json` et un package manager compatible avec cet écosystème.
Il complète [`500-LANGUAGES.md`](500-LANGUAGES.md) et reste indépendant du choix entre JavaScript et TypeScript, du bundler, du framework frontend, de Sass et du host.
## Package manager
PGR MUST NOT imposer npm uniquement parce qu'il est utilisé par un corpus source.
Le projet MUST sélectionner explicitement le package manager qu'il utilise lorsque plusieurs outils sont possibles. npm, pnpm, yarn, Bun ou une autre solution compatible MAY être retenus si le besoin et la toolchain du projet le justifient.
Les commandes opérateur et CI doivent utiliser le package manager réellement sélectionné par le projet ; un exemple PGR ne doit pas transformer sa propre syntaxe en obligation universelle.
## Manifest et scripts
`package.json` appartient à cet owner lorsqu'il décrit le package frontend ou JavaScript/TypeScript concerné.
Pour une application locale/non publiée, `private: true` **SHOULD** être utilisé afin d'exprimer explicitement que le package n'est pas destiné à être publié par erreur. Un package destiné à un registry doit au contraire définir les métadonnées et versions nécessaires à sa publication réelle.
Le projet MUST sélectionner explicitement son package manager. Cette sélection peut être rendue machine-readable dans le manifest lorsque la toolchain retenue le permet, ou être possédée par la configuration/CI/documentation locale. PGR ne fixe ni le nom ni la version du package manager dans son template générique.
Les scripts du manifest doivent représenter des responsabilités utiles du package. Un script MAY orchestrer plusieurs outils, mais sa présence ne transfère pas l'ownership de TypeScript, Vite, Sass, WASM ou Tauri vers le package manager.
Pour un package TypeScript, le nom `typecheck` **SHOULD** désigner la vérification TypeScript indépendante. `dev`, `build` et `preview` restent disponibles pour les owners qui possèdent réellement ces comportements ; leur simple présence dans un exemple ne les rend pas obligatoires.
Les champs de version restent classifiés selon la gouvernance PGR et le rôle du package ; un package privé appartenant au même release train et un package publié indépendamment n'ont pas nécessairement la même politique.
## Dépendances et sorties téléchargées
Les dépendances téléchargées telles que `node_modules/` sont des artefacts reproductibles et SHOULD rester hors du source control.
Un package tiers peut exposer des entrypoints JavaScript, CSS, Sass ou d'autres assets. Leur utilisation active les owners correspondants selon le besoin réel du projet ; elle ne fait pas du package manager le propriétaire de leur configuration.
## Dépendances de développement et packages de déclarations
Le manifest réel doit distinguer les dépendances runtime des outils et déclarations nécessaires uniquement au développement. Pour une application TypeScript privée, le compilateur TypeScript, les outils de build et les packages de déclarations externes nécessaires au type-check **SHOULD** normalement être déclarés dans `devDependencies`.
Avant d'ajouter un package `@types/*`, le projet MUST vérifier si la dépendance runtime fournit déjà ses propres types. Si les types sont embarqués, un package `@types/*` redondant SHOULD NOT être ajouté. Si les types sont absents, un package `@types/<nom>` maintenu et compatible **SHOULD** être recherché et ajouté lorsqu'il améliore réellement l'analyse du code consommateur.
Des exemples comme `@types/node` et `@types/bootstrap` sont donc conditionnels :
- `@types/node` est pertinent lorsque le package analyse du code/config/outillage TypeScript qui utilise l'environnement Node ;
- `@types/bootstrap` est pertinent lorsque le code TypeScript consomme les API JavaScript Bootstrap et que les déclarations ne sont pas fournies par le package runtime ;
- aucun des deux ne doit être injecté dans tous les frontends par défaut.
Le template PGR générique conserve volontairement un `package.json` sans `devDependencies` préremplies : il ne connaît ni les dépendances runtime du projet, ni la version TypeScript, ni l'environnement Node éventuel. L'instanciation réelle du template doit ajouter TypeScript et les packages de déclarations effectivement requis avec des versions explicitement décidées.
Pour une bibliothèque publiée, une dépendance de déclarations exposée par les `.d.ts` publics peut être nécessaire chez le consommateur. Dans ce cas, la classer uniquement en `devDependencies` est insuffisant ; le manifest publié doit rendre cette dépendance disponible selon son contrat réel.
## Lockfile
La politique du lockfile MUST être explicitement décidée selon le rôle du package, la reproductibilité recherchée, les contraintes de publication et le package manager sélectionné.
Pour une application privée, un frontend déployable ou un outil livré comme unité exécutable, le lockfile produit par le package manager sélectionné **SHOULD** être versionné afin de conserver l'arbre effectivement résolu entre développeurs, CI et livraisons.
Pour une bibliothèque publiée, un lockfile **MAY** être versionné afin de stabiliser l'environnement de développement et de CI. Il ne remplace toutefois pas les contraintes du manifest qui pilotent la résolution chez les consommateurs.
Un exemple, un template ou une fixture qui ne résout aucune dépendance réelle **MAY** ne pas embarquer de lockfile.
Un package **SHOULD NOT** conserver simultanément plusieurs lockfiles concurrents (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` ou équivalent), sauf migration explicitement temporaire entre package managers.
Lorsqu'un lockfile est versionné, la CI **SHOULD** utiliser le mode de résolution gelé, immutable ou clean-install fourni par le package manager sélectionné. Le nom exact de cette commande reste local à l'outil ; PGR MUST NOT transformer `npm ci` en commande universelle.
L'absence actuelle de lockfiles dans Games reste historique. Lors de l'adoption `0.1.5`, chaque package concerné devra soit `ADOPT` cette recommandation, soit documenter un `OVERRIDE` si une autre politique reste préférable.
## Validation
Le parsing du manifest, l'installation/résolution de dépendances, le respect du lockfile et les scripts du package manager sont des preuves distinctes. Leur sélection reste proportionnée au scope conformément à [`400-VALIDATION.md`](400-VALIDATION.md).
Une validation statique PGR peut vérifier qu'un `package.json` template est du JSON valide et que les champs génériques attendus sont présents. Elle ne remplace pas l'installation/résolution réalisée par le package manager sélectionné.
Le modèle minimal [`../../templates/web-typescript/package.json`](../../templates/web-typescript/package.json) représente une application TypeScript privée sans choisir de package manager ni de versions de dépendances. Son adaptation est documentée par [`../templates/008-WEB_TYPESCRIPT_PACKAGE.md`](../templates/008-WEB_TYPESCRIPT_PACKAGE.md).

124
docs/rules/550-VITE.md Normal file
View File

@@ -0,0 +1,124 @@
<!-- file: docs/rules/550-VITE.md -->
<!-- version: 2 -->
# Profil Vite
## Rôle et applicabilité
Ce profil possède les règles réutilisables propres à Vite lorsqu'il est sélectionné comme build tool et dev server d'un frontend.
Vite est traité comme une spécialisation de build de l'écosystème frontend au sein de la famille [`500-LANGUAGES.md`](500-LANGUAGES.md), pas comme le propriétaire de TypeScript, Sass/CSS, du package manager, du framework UI ou du host Tauri.
Le profil s'applique uniquement lorsqu'un projet utilise réellement Vite.
## Recommandation pour les projets contrôlés
Pour un frontend moderne que l'organisation contrôle et dont les besoins sont compatibles, Vite **SHOULD** être le build tool/dev server privilégié.
Cette recommandation n'est pas une obligation. Un autre bundler, dev server ou build tool MAY être choisi lorsque ses capacités, les contraintes d'un framework, l'environnement cible ou le coût de migration le justifient mieux.
Le simple fait qu'un projet Web existe ne rend donc pas ce profil applicable automatiquement.
## Ownership
Lorsque Vite est sélectionné, cet owner possède notamment :
- `vite.config.ts` ou une configuration Vite équivalente ;
- la racine frontend présentée à Vite ;
- le dev server et son contrat de lancement ;
- le cache Vite ;
- les outputs du build Vite ;
- la copie/transformation d'assets configurée par Vite ou ses plugins ;
- les paramètres Vite nécessaires à l'intégration avec un host, sans posséder le host lui-même.
Le manifest et le package manager restent possédés par [`540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md). Lorsque Vite est sélectionné, le manifest réel **SHOULD** normalement déclarer Vite comme dépendance de développement avec une version décidée par le projet et MAY exposer les scripts `dev`, `build` et `preview` correspondant au workflow réel.
Un script Vite n'absorbe pas l'ownership du type-check TypeScript, de Sass, d'une génération WASM ou du host.
## Configuration et décisions locales
PGR ne fournit pas de `vite.config.ts` universel à ce stade. Une configuration copiable qui figerait arbitrairement le layout source, les chemins de build, le port, le `base`, les aliases ou les plugins transformerait des décisions locales en règles génériques.
Le projet qui sélectionne Vite doit donc décider explicitement, lorsqu'ils sont pertinents :
```text
root
base
publicDir
cacheDir
build.outDir
build.assetsDir
build.emptyOutDir
server.host
server.port
server.strictPort
preview.host / preview.port / preview.strictPort
aliases
plugins
```
Le guide [`../templates/009-WEB_VITE.md`](../templates/009-WEB_VITE.md) décrit comment adapter ces choix sans imposer de valeurs universelles.
## Sources, cache et outputs
Les sources frontend versionnées, le cache de développement et les outputs de production sont des catégories différentes.
Le cache Vite est un artefact reproductible. Il **SHOULD** rester hors Git. Pour les projets contrôlés, `cacheDir` **SHOULD** être externalisé hors de l'arborescence source lorsque cela reste simple et compatible avec la toolchain ; sinon le chemin retenu MUST être ignoré explicitement.
Le contenu de `build.outDir` est un output généré. Il **SHOULD** rester hors Git et **SHOULD** être externalisé hors de l'arborescence source lorsque cela reste raisonnable. Un projet qui conserve `dist/` ou un autre `outDir` interne MUST l'ignorer explicitement sauf artefact publié exceptionnellement et gouverné comme tel.
`build.emptyOutDir = true` ne doit être activé explicitement que lorsque le répertoire ciblé est dédié aux outputs Vite et que sa suppression complète avant build est sûre. Il MUST NOT pointer vers un répertoire partagé contenant des artefacts appartenant à d'autres owners.
Le nom exact de `outDir` et de `cacheDir` reste local au projet.
## Assets et `publicDir`
Un asset source importé/référencé par le frontend reste un source versionné selon la politique du projet. Sa copie, transformation ou version hashée dans `build.outDir` est générée et ne doit pas être traitée comme un second source.
`publicDir` est une capacité optionnelle. Lorsqu'elle est utilisée, son contenu source est servi/copied tel quel par Vite ; les copies produites dans `outDir` restent des outputs générés. Un projet MAY définir `publicDir: false` lorsqu'il n'a pas besoin de cette voie d'assets statiques.
Un plugin de copie statique MAY être utilisé lorsqu'il répond à un besoin réel. Il ne change pas l'ownership du fichier source copié et ne rend pas ce plugin obligatoire pour les autres projets.
Le découpage final des assets (`assets/`, `js/`, `css/`, `fonts/`, images ou autre) reste local tant qu'aucune contrainte commune ne le justifie.
## `root` et `base`
`root` désigne la racine frontend comprise par Vite. PGR MUST NOT imposer le nom `frontend/` à tous les projets uniquement parce que Games l'utilise. Si les sources ne résident pas à la racine du package, le projet **SHOULD** rendre cette frontière explicite dans sa configuration.
`base` dépend du mode de déploiement ou d'embarquement. PGR MUST NOT imposer `./`, `/` ou un chemin de sous-répertoire universel. Un host embarqué, un site servi à la racine et un déploiement sous sous-chemin peuvent légitimement demander des valeurs différentes.
## Dev server
Le dev server **SHOULD** rester limité à la machine locale/loopback lorsqu'aucun accès externe n'est requis.
L'écoute sur toutes les interfaces ou l'exposition au LAN **MAY** être activée pour un besoin explicite de test, de device ou d'intégration. Elle doit alors être traitée comme une décision réseau réelle et non comme un défaut PGR.
Les ports sont locaux au projet. Lorsqu'aucun consommateur ne dépend d'un port fixe, Vite MAY conserver son comportement normal de sélection. Lorsqu'un host, un smoke ou une autre intégration dépend d'une URL déterministe, le projet **SHOULD** configurer explicitement `server.port` avec `server.strictPort = true` afin d'échouer plutôt que de dériver silencieusement vers un autre port.
`server.allowedHosts = true` et `server.cors = true` **SHOULD NOT** être utilisés comme raccourcis génériques. Une ouverture réseau ou CORS large doit être justifiée et bornée selon le besoin réel.
Les réglages HMR/WebSocket, proxy, TLS et file-system allowlists restent locaux à l'intégration qui les exige.
## Preview
`vite preview` MAY servir de smoke local du build de production lorsqu'il apporte une preuve utile.
Il MUST NOT être présenté comme serveur de production. Le déploiement/serving de production appartient à l'owner de deployment/operations ou au host concerné, hors scope de `0.1.1`.
Un port de preview fixe MAY être utilisé lorsqu'un smoke automatisé en dépend ; dans ce cas `preview.strictPort = true` est recommandé pour obtenir une failure déterministe.
## Validation
Une validation Vite ciblée prouve le contrat de build/dev tool de Vite ; elle ne remplace pas automatiquement :
- le type-check TypeScript ;
- une compilation Sass spécifique lorsqu'elle est indépendante ;
- le smoke navigateur requis par un comportement observable ;
- la validation du host Tauri ;
- une génération WASM possédée par un autre owner.
Pour un projet réel ayant sélectionné Vite, le build de production via le package manager choisi **SHOULD** faire partie de la gate lorsqu'un changement touche Vite, ses entrées ou ses outputs.
Le script `typecheck` TypeScript **SHOULD** rester exécutable indépendamment. Une CI MAY exécuter `typecheck` puis `build` comme deux preuves distinctes plutôt que d'enfouir la première dans un script spécifique à un package manager.
Le guide [`../templates/009-WEB_VITE.md`](../templates/009-WEB_VITE.md) complète ce profil.

View File

@@ -0,0 +1,70 @@
<!-- file: docs/rules/560-CSS_SASS.md -->
<!-- version: 2 -->
# Profil CSS et Sass
## Rôle et applicabilité
Ce profil possède les règles réutilisables de la chaîne de styles frontend : sources CSS, prétraitement Sass lorsqu'il est sélectionné, dépendances de styles, points d'entrée publics et classification des artefacts générés.
Il complète [`500-LANGUAGES.md`](500-LANGUAGES.md). Il ne rend aucun framework CSS particulier obligatoire et ne possède ni TypeScript, ni Vite, ni le package manager, ni le host.
Le profil s'applique à un projet qui possède réellement des sources CSS/Sass ou une chaîne de styles correspondante. La présence d'un frontend sans styles n'oblige pas à créer des fichiers CSS/Sass artificiels.
## CSS comme baseline
Un frontend Web peut utiliser directement CSS sans préprocesseur. Sass n'est donc jamais requis par la simple présence de fichiers CSS.
Les styles sources intentionnels **SHOULD** être versionnés. Les CSS produits uniquement par compilation à partir de sources Sass, les variantes minifiées, les sourcemaps et les copies placées dans un output de build sont des artefacts générés et **SHOULD** rester hors du source control, sauf besoin explicite de distribution ou publication gouverné comme tel.
Un artefact généré MUST NOT être modifié manuellement comme s'il constituait un second source. La correction appartient au source ou à la configuration qui le produit.
PGR MUST NOT imposer un nom de répertoire universel tel que `css/`, `styles/` ou `sass/`. Le layout appartient au projet ou au skeleton qui le compose.
## Recommandation Sass pour les projets contrôlés
Pour un frontend contrôlé dont la chaîne de styles est non triviale, Sass **SHOULD** être préféré lorsqu'il apporte une valeur claire de composition, factorisation ou configuration.
Cette recommandation est particulièrement forte lorsqu'une dépendance installée par le package manager expose un entrypoint Sass/SCSS, des variables configurables, maps, mixins, fonctions ou modules permettant de personnaliser la bibliothèque à la compilation sans modifier ses sources.
Bootstrap constitue un exemple concret de cette catégorie : ses sources Sass permettent de sélectionner des parties de la bibliothèque et de configurer des variables. Cette observation n'en fait pas une dépendance PGR universelle.
Un frontend petit, un smoke minimal ou un projet dont les besoins sont couverts proprement par CSS MAY rester sans Sass.
## Implémentation Sass et intégration au build
Le profil Sass ne dépend d'aucun bundler particulier.
Lorsqu'un projet utilise Vite et sélectionne Sass, il MAY utiliser `sass` ou `sass-embedded` selon la compatibilité de sa toolchain. Pour une nouvelle baseline contrôlée compatible, `sass-embedded` **SHOULD** être préféré lorsque son intégration est supportée et apporte un gain proportionné ; ce choix reste une `devDependency` du projet réel et n'est pas prérempli dans un template PGR générique.
Un autre bundler ou une compilation Sass autonome MAY utiliser l'implémentation officielle adaptée à son environnement. PGR MUST NOT installer un plugin Vite spécifique uniquement pour activer Sass lorsque Vite prend déjà en charge le préprocesseur sélectionné.
## Modules Sass et compatibilité
Pour du nouveau code contrôlé, le système de modules Sass moderne (`@use` / `@forward`) **SHOULD** être préféré lorsque les dépendances et la toolchain le permettent.
L'ancien `@import` Sass est déprécié dans Dart Sass. Il MAY toutefois rester nécessaire à titre de compatibilité lorsqu'une bibliothèque tierce, une version existante ou sa documentation l'impose encore. PGR ne doit pas forcer une migration syntaxique qui casse une dépendance supportée.
Lorsqu'une bibliothèque expose une API Sass publique et configurable, le projet **SHOULD** suivre cette API documentée. Avec le système de modules, une configuration par `@use ... with (...)` ou un entrypoint réexporté via `@forward` est préférable lorsqu'elle est réellement supportée.
PGR **SHOULD NOT** dépendre de chemins internes non documentés sous `node_modules` ou d'une arborescence privée d'un package si celui-ci expose un entrypoint Sass public. Une compatibilité historique MAY justifier temporairement un chemin interne, mais cette dépendance doit rester explicite et révisable.
## Frameworks CSS et packages de styles
Bootstrap, Tailwind CSS ou une autre bibliothèque de présentation restent des décisions de skeleton/projet ou d'un futur owner spécifique si un contrat réutilisable distinct apparaît.
Le profil CSS/Sass possède uniquement la façon de traiter leurs sources/styles lorsqu'elles passent par CSS ou Sass ; il ne choisit pas la bibliothèque à la place du projet.
Un package npm apportant uniquement des styles n'impose pas l'ajout de déclarations `@types/*`. Les déclarations TypeScript sont requises seulement lorsque des API JavaScript/TypeScript réellement consommées en ont besoin, conformément à [`530-TYPESCRIPT.md`](530-TYPESCRIPT.md) et [`540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md).
## Validation des styles
La validation doit prouver la chaîne réellement utilisée sans dupliquer artificiellement la même propriété.
Lorsque Sass est compilé à l'intérieur du build Vite et qu'aucune compilation Sass indépendante n'existe, un build Vite réussi peut constituer la preuve de compilation des styles. PGR SHOULD NOT imposer en plus une seconde compilation Sass identique uniquement pour ajouter une commande à la gate.
Lorsqu'une compilation Sass autonome, un linter CSS/Sass ou une autre transformation possède un contrat distinct, sa commande officielle MAY être ajoutée comme preuve séparée.
Une validation de styles ne remplace ni le type-check TypeScript, ni le build frontend complet, ni un smoke navigateur nécessaire à un comportement observable, ni la validation du host.
Le contrat de validation frontend indépendant du host est décrit dans [`../validation/005-WEB_FRONTEND_VALIDATION.md`](../validation/005-WEB_FRONTEND_VALIDATION.md). Le guide [`../templates/010-WEB_CSS_SASS.md`](../templates/010-WEB_CSS_SASS.md) décrit l'adaptation pratique sans imposer de layout ou framework CSS universel.

View File

@@ -0,0 +1,125 @@
<!-- file: docs/rules/700-FRAMEWORKS.md -->
<!-- version: 2 -->
# Règles de profils framework
## Scope
Cette famille définit le contrat commun des profils liés à un framework réellement utilisé par le projet.
Un framework peut combiner plusieurs owners déjà applicables — langage/écosystème, plateforme, frontend, packaging ou runtime — sans devenir propriétaire de leurs règles générales. Son profil possède uniquement les contraintes et l'orchestration ajoutées par le framework lui-même.
## Responsabilités de la famille
Un profil framework MAY posséder les règles spécifiques concernant notamment :
- les fichiers de configuration réellement possédés par le framework ;
- la relation entre plusieurs toolchains que le framework orchestre ;
- les commandes de développement, build, packaging ou génération qui passent par son CLI ;
- les hooks exécutés par ce CLI et leur ordre de responsabilité ;
- les permissions, capabilities, manifests ou métadonnées propres au framework ;
- les artefacts générés par le framework et leur classification source/généré ;
- la cohérence de version lorsque le framework possède une version applicative distincte ou dérivée ;
- les gates d'intégration que les outils sous-jacents ne prouvent pas isolément.
Un profil framework MUST NOT recopier les règles d'un langage, d'une plateforme ou d'un build tool lorsqu'elles restent valides sans spécialisation.
## Composition
Un framework s'ajoute aux profils réellement applicables au projet. Il n'annule pas silencieusement les conventions des owners qu'il compose.
Par exemple :
```text
GENERAL
+ Rust / Cargo
+ Tauri
```
ou, pour une cible Android :
```text
GENERAL
+ Rust / Cargo
+ Android
+ Tauri
```
Lorsque PGR gouverne la baseline du projet, les règles des profils hérités restent applicables dans leur scope complet tant qu'un override plus spécifique n'est pas documenté. Un framework ne constitue pas à lui seul une justification pour affaiblir une convention de langage, de plateforme ou de sécurité.
Un projet existant ou imposé de l'extérieur MAY conserver des contraintes différentes. Ces écarts appartiennent alors au niveau project-specific ou à une exception explicite et bornée ; ils ne doivent pas être remontés comme nouvelle règle générale du framework.
La présence d'un frontend WebView n'active pas automatiquement un futur profil Web/Vite/WASM. Ces technologies restent sélectionnées selon les faits du projet et leurs propres owners.
## Profil framework et convention d'instanciation
Le profil framework décrit ce qui reste vrai pour toute adoption conforme du framework. Une skeleton specification ou une baseline locale MAY choisir en plus un layout, un bundler, un langage frontend, un package manager ou des bibliothèques préférées pour les projets que l'organisation contrôle.
Ces valeurs d'instanciation ne deviennent pas des invariants du framework :
```text
profil framework
→ responsabilités et contraintes propres au framework
skeleton / projet local
→ choix réutilisables de structure et de stack
```
Cette séparation permet d'appliquer PGR à un projet imposé sans lui forcer le skeleton préféré des nouveaux projets.
## Ownership des commandes d'intégration
Lorsqu'un framework possède un CLI qui orchestre plusieurs étapes, la validation de l'intégration SHOULD utiliser ce CLI plutôt que rejouer manuellement ses sous-commandes comme si elles prouvaient le même contrat.
Une commande sous-jacente reste utile pour une preuve ciblée : compiler le backend ne prouve pas les hooks frontend ; construire le frontend seul ne prouve pas l'intégration native ; un build framework complet n'est pas requis pour une modification purement documentaire qui n'invalide aucune de ces propriétés.
La gate sélectionnée reste proportionnée au scope et à la maturité conformément à [`400-VALIDATION.md`](400-VALIDATION.md).
## Sources, générés et configuration locale
Un framework MAY produire des répertoires générés, projets de plateforme, schémas, bindings ou artefacts de build. Leur simple origine framework ne suffit pas à décider leur politique Git.
Le profil spécifique doit distinguer :
```text
source intentionnelle
configuration durable
artefact reproductible
généré modifié intentionnellement
généré purement transitoire
secret / configuration locale
```
PGR MUST NOT appliquer une règle globale « tout `gen/` est ignoré » ou « tout généré est versionné » sans examiner le rôle réel de l'artefact.
Les secrets et valeurs locales restent possédés par les règles générales et les profils plateforme applicables.
## Version du framework et version produit
La version du framework/de ses dépendances et la version du produit sont deux contrats distincts.
Un projet MAY utiliser une plage compatible, un pin ou une politique de mise à jour adaptée au framework ; PGR ne copie pas une version observée dans un projet source comme règle générale.
Lorsqu'un framework expose une version applicative qui représente la même unité de release que `VERSION`, le profil spécifique doit définir une source de vérité ou une synchronisation explicite afin d'éviter plusieurs valeurs indépendantes.
## Validation spécialisée
Un profil framework doit expliquer ce que prouvent ses commandes propres et ce qu'elles ne prouvent pas.
Selon le scope, la preuve peut être :
- un check du langage/backend ;
- un build/test frontend ;
- un lancement framework avec smoke ciblé ;
- un build/package framework ;
- une validation de plateforme réelle lorsque le framework cible Android, iOS ou une autre plateforme.
Aucune de ces catégories n'est obligatoire à chaque tranche par simple présence du framework.
## Nomenclature documentaire
Le document `700-FRAMEWORKS.md` possède le contrat commun de la famille.
Les profils spécifiques utilisent la plage `710` à `799`. Leur numéro sert à la navigation et ne représente ni priorité normative, ni version du framework.
La résolution avec les autres profils suit [`../architecture/003-RULE_PROFILE_MODEL.md`](../architecture/003-RULE_PROFILE_MODEL.md).

215
docs/rules/710-TAURI.md Normal file
View File

@@ -0,0 +1,215 @@
<!-- file: docs/rules/710-TAURI.md -->
<!-- version: 6 -->
# Profil Tauri 2
## Rôle et applicabilité
Ce document possède les règles réutilisables propres à une application utilisant Tauri 2 comme host natif et orchestrateur d'intégration entre un host Rust et un frontend WebView.
Il complète [`700-FRAMEWORKS.md`](700-FRAMEWORKS.md) et [`510-RUST_CARGO.md`](510-RUST_CARGO.md). Les profils plateforme réellement ciblés, par exemple [`610-ANDROID.md`](610-ANDROID.md), restent applicables et possèdent leurs contraintes de SDK, packaging et smoke de plateforme.
Le profil est volontairement borné à Tauri 2. Une future génération incompatible du framework doit être réévaluée avant d'hériter automatiquement de ces règles.
## Héritage Rust du host Tauri
Un host Tauri est un projet Rust/Cargo. Tauri ne crée aucune exception implicite aux règles Rust sélectionnées par le projet.
Pour un projet dont PGR gouverne la baseline, le host Tauri MUST appliquer le profil Rust/Cargo et les conventions Rust locales retenues exactement comme une autre crate ou application Rust du même projet : édition, lints, safety, erreurs, formatage, façade, chemins canoniques, imports, organisation des sources et audits applicables restent possédés par leur owner Rust.
Un exemple généré par `create-tauri-app`, une documentation de plugin ou une macro Tauri MAY employer un style différent ; il doit être adapté aux règles Rust du projet lorsqu'il est intégré. La présence de Tauri ne justifie donc pas à elle seule `unwrap`, `expect`, `?`, un `use` non autorisé, un chemin interne non canonique ou un affaiblissement des lints si le profil Rust sélectionné les interdit.
Un projet Tauri existant ou imposé de l'extérieur MAY conserver d'autres conventions Rust. Ces différences doivent être traitées comme règles project-specific ou overrides explicites, pas comme un relâchement du profil Tauri général.
## Composition avec le frontend
Tauri ne détermine pas à lui seul le framework frontend, le bundler, le langage de style ou le package manager du projet.
PGR MUST NOT imposer universellement Vite, TypeScript, Sass, Bootstrap, Tailwind CSS, npm, pnpm, yarn, Bun, WASM ou une arborescence frontend particulière uniquement parce que Tauri est utilisé.
Le frontend possède ses propres règles et peut être sélectionné par une skeleton specification ou par la baseline locale du projet. Le profil Tauri possède seulement le contrat d'intégration entre ce frontend et le host natif.
Les owners frontend matérialisés par `0.1.1` sont [`530-TYPESCRIPT.md`](530-TYPESCRIPT.md), [`540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md), [`550-VITE.md`](550-VITE.md) et [`560-CSS_SASS.md`](560-CSS_SASS.md). Ils s'appliquent uniquement lorsque les technologies correspondantes sont réellement sélectionnées.
Pour les projets que l'organisation contrôle entièrement, une skeleton MAY choisir une stack frontend par défaut et un layout stable. Cette décision appartient au skeleton et aux profils Web applicables, pas au présent owner Tauri.
## WASM
WASM n'est pas une composante implicite d'un projet Tauri. Un package ou projet WASM SHOULD être traité comme une unité distincte appliquant ses propres profils Rust/Web/WASM, même s'il partage le même dépôt ou certaines crates avec une application Tauri.
Une application Tauri MAY consommer explicitement un artefact WASM lorsqu'un besoin architectural réel le justifie. Cette composition doit alors être documentée comme telle ; elle ne transforme pas les règles WASM en règles Tauri et ne justifie pas de placer systématiquement une chaîne WASM dans les hooks Tauri.
## Layout et fichiers possédés par Tauri
PGR MUST NOT imposer universellement un répertoire `src-tauri/` ni recopier le layout de `create-tauri-app`. Le projet peut utiliser le layout standard de Tauri ou une intégration différente lorsque la toolchain la supporte clairement.
Les éléments suivants appartiennent néanmoins au scope Tauri lorsqu'ils existent :
- le manifeste Cargo du host natif ;
- l'intégration build-time Tauri, généralement via `tauri-build` ;
- la configuration Tauri supportée par la version du framework, par exemple `tauri.conf.json` ;
- les capability files et permissions Tauri ;
- les icônes, ressources ou métadonnées de bundle référencées par la configuration ;
- les projets ou fichiers de plateforme produits/consommés par la toolchain Tauri.
Leur emplacement exact reste une décision du projet ou du skeleton retenu tant qu'il est supporté par la toolchain.
## Convention renforcée pour les projets contrôlés
Le contrat universel ci-dessus reste compatible avec des projets Tauri imposés de l'extérieur. Pour un **nouveau projet Tauri contrôlé par l'organisation** qui sélectionne le profil strict PGR, les conventions suivantes forment en revanche la baseline recommandée et ne doivent pas être abandonnées sans raison documentée.
Le host SHOULD être une crate Cargo mixte directement lisible, sans couche `src-tauri/` ajoutée uniquement pour reproduire `create-tauri-app`. Le layout recommandé est :
```text
<tauri-crate>/
├── Cargo.toml
├── build.rs
├── package.json
├── tsconfig.json
├── tauri.conf.json
├── capabilities/
├── src/
└── frontend/
```
Un fichier comme `vite.config.ts` appartient également à la racine lorsque Vite est le bundler sélectionné. Un projet externe MAY conserver `src-tauri/` ou une autre organisation lorsque cette structure est imposée ou qu'une migration n'apporte pas de valeur suffisante.
Dans le host Rust, le package mixte `lib + bin` constitue l'exception framework explicite à la séparation générale définie par `510-RUST_CARGO.md`. Pour une nouvelle baseline Tauri contrôlée :
- le package SHOULD déclarer explicitement une cible bibliothèque et une cible binaire ;
- leurs noms MUST être distincts même après la normalisation Cargo usuelle des tirets en underscores ; un modèle valide est package/bin `project-feature-desk` et lib `project_feature_desk_lib` ;
- `src/lib.rs` SHOULD rester une façade de modules/réexports et porter l'accès à la fonctionnalité applicative réutilisable ;
- `src/main.rs` SHOULD rester un launcher mince vers une fonction publique de la bibliothèque applicative ; il MAY posséder le verrou/single-instance, les arguments strictement process et le bootstrap exécutable qui ne peut pas appartenir à la bibliothèque ;
- `src/tauri.rs` SHOULD posséder l'assemblage Tauri et les wrappers `#[tauri::command]`, qui délèguent aux modules propriétaires plutôt que porter la logique métier ;
- une fenêtre ou responsabilité UI non triviale SHOULD posséder un module cohérent, avec sous-modules si nécessaire ; les helpers réellement partagés entre plusieurs fenêtres/responsabilités SHOULD être déplacés dans des modules communs dédiés ;
- un préfixe local comme `tw_` MAY être utilisé pour identifier les modules de fenêtres, mais PGR n'impose pas ce préfixe à tous les projets.
Lorsque le workspace possède une crate de logging/tracing commune, le host Tauri l'utilise pour initialiser le runtime de diagnostics. Un plugin Tauri de tracing sert alors d'adapter à la frontière desktop/mobile ; il ne remplace pas l'owner Rust de `tracing-subscriber`, des sinks ou du lifecycle de logging.
Lorsque le frontend sélectionné est TypeScript, les structures, énumérations et DTO Rust **possédés par le host** et partagés avec le frontend MUST utiliser TS-RS comme source de génération dans le profil strict, sauf incompatibilité technique explicitement documentée. Le contrat Rust reste la source de vérité ; les bindings générés ne sont pas modifiés manuellement et SHOULD rester hors Git lorsqu'ils sont entièrement reproductibles. Le skeleton MAY normaliser leur sortie sous `frontend/ts/bindings/`.
Pour les projets contrôlés, `frontend/` est le répertoire recommandé pour les sources Web versionnées. TypeScript et Vite sont fortement recommandés mais restent des `SHOULD`, jamais des obligations universelles. Sass est également fortement recommandé lorsque la chaîne de styles est non triviale ou qu'une dépendance expose des sources Sass/SCSS configurables ; il reste optionnel pour un frontend qui n'en tire pas de valeur. Bootstrap est la baseline de présentation privilégiée lorsque le futur skeleton choisit un framework CSS généraliste, mais il ne devient pas une dépendance Tauri ou Web universelle. Tailwind CSS n'est pas interdit ; son adoption reste une décision explicite du projet. Les règles correspondantes appartiennent aux profils `530`, `550` et `560`, puis au futur skeleton lorsqu'il choisira effectivement cette composition.
L'intégration d'un plugin SHOULD préférer les étapes explicites décrites par sa documentation — dépendance Cargo, initialisation Rust, package frontend et capabilities nécessaires — afin que chaque modification reste visible et revue. `cargo tauri add` MAY être utilisé lorsque ce raccourci apporte une vraie valeur, mais il n'est pas la voie canonique imposée aux projets contrôlés.
WASM reste normalement une unité séparée de la crate Tauri. Une adaptation WASM réutilisable SHOULD donc posséder sa propre crate/package et ses propres profils ; elle n'est intégrée au host Tauri que lorsqu'une composition architecturale explicite l'exige.
## Ownership du build et hooks frontend
Lorsqu'une validation concerne l'intégration Tauri complète, le CLI Tauri est l'owner de l'orchestration.
Si `beforeDevCommand`, `beforeBuildCommand` ou un hook Tauri équivalent est configuré, la gate d'intégration SHOULD invoquer le CLI Tauri afin que ce hook soit exécuté dans le contexte prévu.
Ainsi :
```text
cargo check / cargo clippy
→ preuve Rust ciblée
frontend build/test direct
→ preuve frontend ciblée
Tauri CLI dev/build
→ preuve d'orchestration Tauri + hooks correspondants
```
Un projet MUST NOT considérer `npm run build`, `cargo build` ou une autre sous-commande isolée comme équivalente à un build Tauri lorsque la propriété à valider dépend des hooks, de `frontendDist`, des capabilities, du contexte Tauri ou du bundling.
Le CLI MAY être invoqué via `cargo tauri`, un script du package manager frontend ou une autre forme officiellement supportée. PGR n'impose pas le package manager qui sert de lanceur.
## `devUrl`, `frontendDist` et sorties frontend
`devUrl` et `frontendDist` doivent pointer vers les entrées/sorties réellement possédées par la chaîne frontend du projet.
PGR ne fixe ni port, ni nom de répertoire de distribution, ni profondeur relative universelle.
Le répertoire produit par le frontend est un artefact de build lorsqu'il est reproductible ; il SHOULD rester hors du source control sauf besoin explicite contraire. La configuration Tauri qui le référence reste, elle, source durable.
## Version produit
Lorsque l'application Tauri appartient au même release train que le projet, `VERSION` reste la version canonique exacte de cette unité de release. Les champs de version de Tauri et du frontend ne sont toutefois pas obligés de suivre chaque prerelease ou fix : ils sont classés selon [`200-GOVERNANCE.md`](200-GOVERNANCE.md).
Tauri 2 accepte une `version` applicative explicite dans `tauri.conf.json` et l'utilise pour les métadonnées/bundles. Si ce champ est absent, Tauri peut utiliser la version du package Cargo du host. PGR MUST NOT imposer l'une de ces deux formes uniquement pour réduire le nombre de fichiers modifiés.
Pour un projet contrôlé qui conserve une `version` explicite dans `tauri.conf.json`, la politique recommandée lorsque les prereleases ne sont pas distribuées comme produits installables distincts est `MIRROR-STABLE` : le champ porte la cible `X.Y.Z` de la version en cours de développement, est fixé ou vérifié à l'ouverture de cette cible et reste stable pendant ses `alpha.*`, `beta.*`, `rc.*` et fixes. La promotion stable vérifie la cohérence sans provoquer de réécriture cérémonielle si la valeur est déjà correcte.
Si le projet distribue réellement des bundles prerelease qui doivent être identifiables séparément, `tauri.conf.json > version` MAY devenir `MIRROR-EXACT` ou suivre des jalons de packaging explicitement documentés. Le choix dépend du contrat de distribution, pas d'une préférence PGR pour l'omission du champ.
Pour un `package.json` frontend privé appartenant à la même application, une propriété `version` conservée SHOULD de même être classée `MIRROR-STABLE` par défaut : elle peut porter `X.Y.Z` pendant tout le développement de cette release sans suivre chaque tranche. Si le package frontend est publié ou versionné indépendamment, il possède alors sa propre unité/version et cette règle ne s'applique plus.
La chaîne de version d'un projet contrôlé peut donc être, par exemple :
```text
VERSION = X.Y.Z-alpha.N.fix.M # CANONICAL
workspace.package.version = X.Y.Z-alpha.N.fix.M # MIRROR-EXACT si le workspace l'a choisi
tauri.conf.json version = X.Y.Z # MIRROR-STABLE
package.json version = X.Y.Z # MIRROR-STABLE si conservée
```
Cette classification évite de réécrire `package.json` et `tauri.conf.json` à chaque delta tout en conservant des champs de version utiles et lisibles. Elle remplace explicitement les conventions historiques KSP/Games qui préféraient omettre la version Tauri comme solution générale au churn.
Les numéros propres aux plateformes, par exemple Android `versionCode`, restent possédés par le profil plateforme concerné et ne sont pas assimilés au SemVer produit.
## Capabilities, permissions et frontière WebView/native
Les capability files et permissions Tauri sont du source de sécurité et SHOULD être versionnés lorsqu'ils définissent intentionnellement la surface exposée au frontend.
Le projet SHOULD accorder uniquement les permissions nécessaires aux fenêtres/webviews concernées. Ajouter un plugin ou une commande native ne justifie pas automatiquement une capability globale plus large.
Les schémas générés référencés par les capability files servent à l'outillage et à la validation de configuration ; ils ne deviennent pas pour autant la source normative de la politique de permissions.
Toute permission distante, origine distante ou extension de scope sensible doit être explicitement justifiée et validée comme frontière de sécurité.
## Plugins
PGR ne définit aucun catalogue de plugins Tauri obligatoires et ne rend pas `cargo tauri add` obligatoire.
Les pages officielles des plugins peuvent décrire à la fois une commande d'ajout automatique et les étapes explicites correspondantes côté Cargo, initialisation Rust et bindings frontend. Un projet MAY préférer appliquer manuellement ces étapes afin que les modifications de `Cargo.toml`, du manifeste frontend et du code d'initialisation restent directement contrôlées et revues.
Si une commande de commodité telle que `tauri add` est utilisée, les fichiers qu'elle modifie MUST être relus comme toute autre génération avant validation. Le projet ne doit installer que les côtés réellement nécessaires du plugin : dépendance Rust, bindings frontend, capabilities/permissions ou configuration associée selon le cas.
## CSP, fenêtres et bundles
CSP, nombre de fenêtres, labels, tailles, ports, `bundle.active`, targets de bundle, icônes et ressources restent des décisions du produit ou de la plateforme tant qu'aucun invariant plus général ne les impose.
Une règle locale MAY renforcer ces choix. Elle ne doit pas être remontée dans le profil Tauri uniquement parce qu'elle apparaît dans plusieurs applications d'un même projet.
## Artefacts générés et projets mobiles
Les dépendances frontend téléchargées et sorties de build reproductibles, telles que `node_modules/` ou le `frontendDist`, SHOULD rester hors Git.
PGR MUST NOT appliquer en revanche une exclusion universelle de tout répertoire `gen/`. Tauri peut générer des projets de plateforme qui deviennent ensuite le lieu de personnalisations Android/iOS intentionnelles. Le projet doit classifier chaque sous-arbre : reproductible/transitoire, configuration durable ou généré modifié volontairement.
Un POC Tauri mobile non concluant pour un produit particulier ne constitue pas une preuve que Tauri Android/iOS est inadapté à tous les autres projets. Le support mobile doit être jugé selon le besoin, les ABI, plugins, intégrations natives et gates plateforme du projet concerné.
Les secrets de signature, keystores, credentials et fichiers locaux restent hors Git conformément aux règles générales et aux profils plateforme applicables.
## Validation proportionnée
| Scope modifié | Preuve Tauri normalement pertinente | Ce que cette preuve ne remplace pas |
|-------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------|
| backend Rust uniquement | gates Rust/Cargo sélectionnées | frontend, hooks, WebView ou packaging |
| frontend uniquement | build/tests/smoke du frontend selon son owner | host natif ou packaging Tauri |
| hooks, config, capabilities, IPC ou intégration | `tauri dev` ou équivalent + smoke ciblé | package release de plateforme |
| bundling, ressources ou version packagée | `tauri build` ou équivalent + inspection/smoke de l'artefact | exigences d'un store ou d'une plateforme non exercée |
| Android/iOS | commande mobile Tauri applicable + gates du profil plateforme concerné | autres plateformes |
La syntaxe exacte de la commande dépend du lanceur choisi (`cargo`, npm, pnpm, etc.) et de la plateforme. Le delta/plan du projet doit fournir la commande concrète.
Un `cargo check` direct MAY rester utile pour une modification Rust ciblée, mais il ne constitue pas un smoke Tauri complet. Inversement, un full `tauri build` n'est pas requis lorsqu'aucune propriété d'intégration ou de packaging n'a été invalidée.
## Ce que le profil n'impose pas
Ce profil ne crée pas :
- de `tauri.conf.json` universel ;
- de port de développement par défaut PGR ;
- de frontend Vite/TypeScript/Sass/Bootstrap obligatoire ;
- de frontend WASM implicite ;
- de plugin obligatoire ;
- de nombre ou taille de fenêtres ;
- de politique de bundle unique ;
- de layout universel imposé aux projets externes ; la convention stricte des projets contrôlés est définie séparément ci-dessus ;
- de version exacte de Tauri, `tauri-build` ou du CLI.
Ces décisions appartiennent au projet, à un profil plus spécifique ou à une skeleton specification seulement lorsqu'une valeur réutilisable est réellement démontrée.

View File

@@ -0,0 +1,34 @@
<!-- file: docs/skeletons/000-README.md -->
<!-- version: 6 -->
# Index des skeleton specifications PGR
Cette collection contient les recettes Markdown utilisées pour initialiser des baselines de projet ou composer plusieurs profils PGR sans transformer PGR en générateur.
Le contrat normatif commun des skeletons appartient à [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md). Le modèle de composition des profils reste défini par [`../architecture/003-RULE_PROFILE_MODEL.md`](../architecture/003-RULE_PROFILE_MODEL.md).
## Rôle de la collection
Chaque specification concrète doit décrire un besoin réel et actionnable. Elle sélectionne les owners normatifs et templates nécessaires, rend visibles les décisions propres au projet, définit l'ordre de composition utile et fournit une validation initiale proportionnée.
Les fichiers techniques copiables ne vivent pas ici : ils restent sous `templates/`. Leurs guides d'adaptation restent sous `docs/templates/`. Les règles restent sous `docs/rules/`.
Une specification peut se composer avec une fondation plus générale, mais la collection ne duplique pas artificiellement une recette pour chaque combinaison possible de technologies.
## Specifications actives
- [`001-PROJECT_GOVERNANCE_FOUNDATION.md`](001-PROJECT_GOVERNANCE_FOUNDATION.md) — fondation composable pour établir la gouvernance locale, la version, la documentation minimale, le workflow retenu et sa validation initiale sans imposer d'architecture applicative.
- [`002-RUST_CARGO_WORKSPACE.md`](002-RUST_CARGO_WORKSPACE.md) — specialization composable d'un workspace Rust/Cargo fondée sur `001`, les profils `500 + 510`, les cinq templates Rust/Cargo et une validation réelle de la toolchain.
- [`003-WEB_FRONTEND.md`](003-WEB_FRONTEND.md) — specialization composable d'un frontend Web contrôlé fondée sur les owners `530/540/550/560`, avec TypeScript/Vite recommandés, Sass conditionnel et validation indépendante du host.
Pour un projet existant, ces specifications servent de références de comparaison et non de recettes à recopier aveuglément. Le chemin canonique passe alors par [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md) et son mapping `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`.
Les familles Java/Android, JNI et autres domaines sans pièces suffisantes restent différées tant que leurs owners normatifs et artefacts d'instanciation ne permettent pas une baseline réellement actionnable.
Le skeleton Web `003` est matérialisé en `0.1.1-alpha.5` parce que les owners `530/540/550/560`, les guides d'adaptation et la validation frontend indépendante du host permettent désormais une composition sans ownership caché. Il ne fixe ni npm, ni Vite/Sass comme obligations, ni Bootstrap, ni un layout `frontend/` universel.
Le skeleton Tauri a fait l'objet d'une décision explicite en `0.0.5-alpha.9` : son host Rust/Tauri est cadré par `510` et `710`, mais sa promotion avait été différée tant que les owners Web nécessaires n'existaient pas. La décision `DEFER` et ses conditions de sortie restent enregistrées dans [`../studies/002-TAURI_SKELETON_DECISION.md`](../studies/002-TAURI_SKELETON_DECISION.md).
La création du skeleton Web ne lève pas automatiquement ce `DEFER`. `0.1.1-beta.1` doit encore réconcilier objectivement les conditions de sortie avant que `0.1.4` ne réexamine un éventuel skeleton Tauri, qui devra composer les owners Web au lieu de posséder leurs règles.
Aucun fichier placeholder ne doit être ajouté pour réserver un skeleton futur.

View File

@@ -0,0 +1,160 @@
<!-- file: docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md -->
<!-- version: 4 -->
# Skeleton — Project governance foundation
## Objectif
Cette specification décrit une fondation composable pour un projet qui choisit d'adopter la gouvernance PGR sans sélectionner encore de langage, plateforme, framework ou architecture applicative.
Elle permet d'établir une baseline locale cohérente : identité de version, point d'entrée normatif, documentation réellement utile, workflow de changement effectivement retenu et validation initiale proportionnée.
Le contrat commun des skeletons appartient à [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md). La présente specification sélectionne et adapte les owners généraux utiles ; elle n'en devient pas propriétaire.
## Applicabilité
Appliquer cette fondation lorsqu'un dépôt ou release unit veut utiliser PGR comme source de gouvernance locale et qu'aucune specialization technologique n'est nécessaire pour définir cette base commune.
Elle MAY servir de fondation à un skeleton spécialisé, qui ajoute ensuite uniquement les profils, templates, décisions et validations propres à son scope.
Pour un projet déjà existant, cette specification devient une checklist de comparaison : l’adoption MUST suivre [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md), classifier les décisions applicables et préserver les choix locaux légitimes. Le pattern [`../templates/007-EXISTING_PROJECT_ADOPTION.md`](../templates/007-EXISTING_PROJECT_ADOPTION.md) peut matérialiser cette comparaison. Il ne faut pas réinstancier le dépôt comme s’il était vide.
Ne pas l'appliquer comme cérémonie à un dépôt qui ne souhaite pas adopter le lifecycle ou les règles PGR. Elle ne transforme pas PGR en dépendance du projet destinataire.
## Owners sélectionnés
La fondation s'appuie sur les responsabilités PGR suivantes :
```text
docs/rules/200-GOVERNANCE.md
versioning, phases et discipline de changement
docs/rules/210-WORKFLOW.md
plans, deltas, histories, commits de tranche et artefacts à la demande
docs/rules/300-DOCUMENTATION.md
rôles documentaires, taxonomie, révisions et snapshots
docs/rules/400-VALIDATION.md
preuves proportionnées, statuts de gate et autorité opérateur
```
`docs/rules/220-SKELETONS.md` gouverne l'instanciation elle-même. Il n'est pas automatiquement une règle à recopier dans le projet destinataire si ce projet ne maintient pas sa propre collection de skeletons.
Aucun profil `500+` ou `600+` n'est sélectionné par cette fondation. Un skeleton spécialisé les ajoute seulement lorsqu'ils sont réellement applicables.
## Décisions destinataire avant matérialisation
Avant de considérer la fondation comme instanciée, résoudre explicitement les décisions suivantes :
1. identifier le release unit gouverné et sa version SemVer courante ;
2. décider si le projet utilise le fichier racine `VERSION` comme repère canonique simple ;
3. identifier les règles PGR réellement reprises et les adaptations locales nécessaires ;
4. déterminer quels documents vivants ont une responsabilité réelle dès la baseline ;
5. déterminer quels artefacts du workflow PGR sont effectivement utilisés et à partir de quel état gouverné ;
6. sélectionner les validations disponibles qui prouvent réellement cette baseline ;
7. consigner toute exception ou divergence intentionnelle dans le propriétaire local approprié.
Une décision non résolue MUST rester visible comme décision à prendre. Elle ne doit pas être remplacée par une valeur arbitraire provenant de PGR ou d'un autre projet.
## Baseline locale à matérialiser
### Point d'entrée normatif
Le projet destinataire MUST disposer d'un point d'entrée normatif local clairement identifiable. Lorsqu'il adopte la convention PGR, ce point d'entrée est `RULES.md`.
Ce document doit au minimum :
- déclarer le scope qu'il gouverne ;
- identifier les owners généraux ou spécialisés réellement applicables ;
- expliquer la priorité ou la spécialisation locale lorsqu'une adaptation existe ;
- renvoyer vers les documents détaillés au lieu de recopier leur contenu sans nécessité.
Le projet doit rester autonome : ses règles nécessaires vivent dans son dépôt ou dans un mécanisme de dépendance documentaire explicitement choisi par lui. Une URL vers PGR ne remplace pas à elle seule une baseline locale exploitable.
### Version
Le release unit MUST posséder une version SemVer courante explicite conformément au contrat local retenu.
Si le fichier racine `VERSION` est choisi, l'instanciation doit le créer ou l'adapter selon [`../rules/200-GOVERNANCE.md`](../rules/200-GOVERNANCE.md). Si l'écosystème possède un autre owner canonique, la relation avec `VERSION` doit être décidée explicitement plutôt que dupliquée par défaut.
La valeur de version initiale appartient au projet destinataire. Cette specification ne fournit pas de numéro universel.
### Documentation minimale
`README.md` SHOULD fournir l'onboarding et les points d'entrée de premier niveau du projet.
Créer `docs/000-README.md` uniquement si une documentation structurée sous `docs/` existe réellement. Créer ensuite uniquement les collections possédant un premier contenu utile. Une collection vide ou un document placeholder n'est pas requis par cette fondation.
Selon la réalité du projet :
- `ROADMAP.md` est utile lorsqu'une trajectoire macro doit être rendue explicite ;
- `CHANGELOG.md` est utile lorsque des changements de release doivent être communiqués aux utilisateurs ou intégrateurs ;
- `docs/objectives/` est utile lorsqu'une mission durable, des contraintes ou non-objectifs méritent un owner distinct ;
- `docs/architecture/` est utile lorsqu'un état architectural ou un profil local doit être possédé durablement ;
- `docs/validation/` est utile lorsqu'une matrice ou un contrat de preuve mérite un document séparé.
Pour un projet où plusieurs fichiers ou familles durables ont des responsabilités ou règles de modification difficiles à déduire, la fondation MAY aussi instancier un registre local selon [`../templates/004-FILE_FAMILY_CONTRACTS.md`](../templates/004-FILE_FAMILY_CONTRACTS.md). Ce registre reste facultatif : un projet simple ou déjà explicite n'a rien à matérialiser.
Lorsqu'une release possède plusieurs tranches ou responsabilités de fermeture, le projet SHOULD utiliser un plan explicite conforme à [`../templates/005-RELEASE_PLAN.md`](../templates/005-RELEASE_PLAN.md) ou une forme locale équivalente. Le plan doit notamment attribuer la clôture/transition et éviter qu'une roadmap arrivée à son horizon soit étendue par spéculation.
Ne pas créer ces fichiers uniquement pour reproduire l'arborescence du dépôt PGR.
### Workflow retenu
Si le projet adopte le workflow de tranches PGR, il doit préserver la séquence définie par [`../rules/210-WORKFLOW.md`](../rules/210-WORKFLOW.md) : intention prospective dans le delta, gate réelle, preuve rétrospective dans le history, puis commit de tranche avant application du delta suivant.
Les répertoires `deltas/`, `history/`, `prompts/`, `handoffs/` et `manifests/` sont créés à la demande lorsqu'un artefact réel les justifie. Ils ne constituent pas un layout obligatoire à précréer.
Un projet qui n'adopte qu'une partie du workflow PGR doit l'indiquer dans ses règles locales et ne pas présenter les artefacts omis comme s'ils étaient encore obligatoires.
### Validation initiale
La validation de la fondation doit prouver seulement les propriétés réellement matérialisées. Elle SHOULD combiner selon le scope :
```text
CHECK version courante conforme au mécanisme choisi
CHECK git diff --check ou équivalent du VCS retenu
AUDIT chemins et rôles documentaires réellement créés
AUDIT liens locaux principaux si la navigation Markdown a été modifiée
AUDIT owners sélectionnés et exceptions locales explicites
REVIEW absence de collections, profils ou placeholders non justifiés
```
Si le projet possède déjà des audits fiables pour ses headers, liens, structure ou règles, ils MAY être ajoutés. Cette fondation n'impose pas de copier les scripts du dépôt PGR sans décision explicite de réutilisation.
La prévalidation qui accompagne une instanciation ou un delta ne remplace pas la gate opérateur autoritaire du projet destinataire.
## Ordre de composition
Cette fondation SHOULD être appliquée avant une specialization qui la déclare comme base.
Une specialization technologique peut ensuite :
- sélectionner ses familles et profils applicables ;
- copier ou adapter les templates techniques correspondants ;
- ajouter ses décisions spécifiques ;
- étendre la validation initiale avec la toolchain réellement concernée.
Elle MUST NOT redéfinir les responsabilités générales déjà possédées par la fondation sauf specialization ou override explicitement justifié.
## Overrides et exceptions
Un projet MAY adapter la structure documentaire, le mécanisme de version, le VCS, le workflow ou une convention PGR lorsqu'une contrainte réelle le justifie et que l'owner local reste clair.
Une exception doit identifier son scope et sa raison. Elle ne devient pas une règle générale PGR et ne doit pas être masquée par la simple copie d'un fichier provenant de PGR.
## Hors scope
Cette fondation ne définit pas :
- l'architecture applicative ou les crates/modules/packages du produit ;
- un langage, une plateforme, un framework ou une toolchain ;
- des noms de package, versions de dépendances ou chemins de build ;
- des templates techniques génériques inexistants ;
- un CI/CD universel ;
- une politique de branching universelle ;
- une obligation de recopier la structure complète du dépôt PGR ;
- la migration rétroactive des anciennes releases ou anciens commits du projet destinataire.
Les spécialisations futures doivent rester indépendantes et composables au-dessus de cette fondation.

View File

@@ -0,0 +1,219 @@
<!-- file: docs/skeletons/002-RUST_CARGO_WORKSPACE.md -->
<!-- version: 6 -->
# Skeleton — Rust/Cargo workspace
## Objectif
Cette specification décrit la specialization Rust/Cargo d'un projet gouverné par PGR lorsque plusieurs packages Rust partagent réellement une même unité de release, une politique Cargo commune ou une validation de workspace commune.
Elle se compose avec [`001-PROJECT_GOVERNANCE_FOUNDATION.md`](001-PROJECT_GOVERNANCE_FOUNDATION.md), sélectionne les profils [`../rules/500-LANGUAGES.md`](../rules/500-LANGUAGES.md) et [`../rules/510-RUST_CARGO.md`](../rules/510-RUST_CARGO.md), puis utilise les templates et guides Rust/Cargo déjà présents dans PGR. Le contrat transversal des skeletons reste possédé par [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md).
Cette specification ne transforme pas PGR en générateur Cargo et ne crée aucune dépendance build ou runtime vers le dépôt PGR après instanciation.
## Applicabilité et composition
Appliquer ce skeleton lorsqu'un projet utilise Rust avec Cargo et qu'un workspace représente réellement son unité de gouvernance ou de release.
La composition normale est :
```text
001-PROJECT_GOVERNANCE_FOUNDATION
↓
500-LANGUAGES
↓
510-RUST_CARGO
↓
002-RUST_CARGO_WORKSPACE
```
Un dépôt contenant plusieurs unités de release indépendantes ne doit pas être forcé dans un workspace à version globale fictive. Un framework, une plateforme, WASM, Android, Tauri, une FFI ou un autre scope plus spécifique peut ajouter ses propres règles sans modifier le contrat Rust/Cargo général.
Pour un projet Rust/Cargo existant, ne pas appliquer ce skeleton comme une réinitialisation. Utiliser [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md), comparer le workspace réel avec la présente specification et classifier chaque écart utile en `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`. Les manifests ou fichiers d’outillage déjà fonctionnels ne sont remplacés que si la décision `ADOPT` le justifie réellement.
## Owners, guides et artefacts sélectionnés
Les responsabilités générales de version, workflow, documentation et validation sont déjà couvertes par la fondation `001`. La présente specialization ajoute :
```text
docs/rules/500-LANGUAGES.md
contrat commun langage/écosystème
docs/rules/510-RUST_CARGO.md
workspace, manifests, dépendances, lints, safety, formatage et validation Cargo
docs/templates/001-RUST_CARGO_TOOLING.md
adaptation de rustfmt.toml, clippy.toml et .cargo/config.toml
docs/templates/002-CARGO_MANIFESTS.md
adaptation du manifest workspace et du manifest membre
```
Les cinq artefacts techniques copiables sélectionnés sont :
```text
templates/rust-cargo/rustfmt.toml
templates/rust-cargo/clippy.toml
templates/rust-cargo/.cargo/config.toml
templates/rust-cargo/Cargo.toml
templates/rust-cargo/crates/project-core-lib/Cargo.toml
```
[`../validation/002-RUST_STYLE_AUDITS.md`](../validation/002-RUST_STYLE_AUDITS.md) et [`../validation/003-RUST_EXPORT_COMPLETENESS.md`](../validation/003-RUST_EXPORT_COMPLETENESS.md) sont seulement des options supplémentaires. Les scripts Rust PGR ne sont copiés que si le projet choisit explicitement les conventions correspondantes. Le helper `_rust_audit_common.py` peut être partagé entre ces audits.
## Décisions destinataire avant copie
Avant de considérer la specialization comme instanciée, résoudre explicitement au minimum :
1. le release unit gouverné et la relation entre son `VERSION` et `[workspace.package].version` ;
2. le nom court/abréviation canonique du projet, la liste réelle des packages membres, leurs responsabilités, rôles et chemins, puis la conformité de leurs noms au contrat de `510-RUST_CARGO.md` ;
3. l'édition Rust 2024, le resolver Cargo et la toolchain stable compatible, ou l'exception externe explicitement documentée ;
4. la politique de publication et les métadonnées réelles communes (`license`, `repository`, `authors`) lorsqu'elles existent ;
5. les dépendances réellement partagées, leurs contraintes de version et les features qui doivent rester locales à chaque membre ;
6. la politique de versionnement de `Cargo.lock` adaptée au type de produit ;
7. les niveaux de lints hérités, les éventuelles exceptions locales et tout besoin réel d'`unsafe` dans un scope étroit ;
8. les paramètres `rustfmt.toml` et `clippy.toml` à conserver ou adapter ;
9. l'emplacement des artefacts Cargo et l'identifiant unique utilisé dans `.cargo/config.toml` si cette politique externe au dépôt est retenue ;
10. les frontières `-api` / `-lib` réellement justifiées, les packages exécutables distincts de leurs bibliothèques et toute exception framework à cette séparation ;
11. l'ownership du logging/tracing : simple exécutable local ou crate transverse commune lorsque plusieurs runtimes partagent subscriber, sinks ou policy ;
12. les exceptions éventuelles au profil Rust strict ; pour une nouvelle baseline contrôlée, la façade crate-root, les chemins explicites et les conventions structurelles sans ordre métier sont sélectionnés par défaut ;
13. les fichiers pour lesquels un ordre mécanique des blocs `const` est réellement applicable, sans englober les tables/protocoles/schémas ordonnés ;
14. les validations Cargo réellement nécessaires au code et aux manifests créés.
Les valeurs `0.1.0`, `2024`, `project-name`, `project-core-lib`, les seuils Clippy et les chemins de build présents dans les templates sont des exemples ou baselines à revoir. Ils ne deviennent jamais des valeurs universelles par simple copie.
## Matérialisation du workspace
### Fondation gouvernée
Appliquer d'abord la fondation `001` et résoudre ses décisions générales. Ne recopier ni le workflow ni la structure documentaire complète de PGR lorsqu'ils ne sont pas nécessaires au projet destinataire.
La version canonique du release unit doit être décidée avant d'adapter les manifests. Pour un train de release Cargo unique, `[workspace.package].version` reflète cette version selon `510-RUST_CARGO.md`.
### Manifest workspace
Copier `templates/rust-cargo/Cargo.toml` vers `Cargo.toml`, puis :
- adapter le header `# file:` et démarrer la révision locale selon la convention documentaire retenue ;
- remplacer `members` par les packages réellement présents ;
- remplacer la version d'exemple par la version du release unit lorsque le workspace partage une seule release ;
- aligner `edition` et `resolver` sur la toolchain réellement choisie ;
- décider explicitement `publish` et les métadonnées communes ;
- ajouter sous `[workspace.dependencies]` uniquement les dépendances réellement partagées ;
- conserver, adapter ou documenter les niveaux de lints selon le profil local retenu.
Le projet ne doit pas remplir les champs manquants avec des identités fictives provenant de PGR, KSP ou Games.
### Packages membres
Pour chaque crate réellement nécessaire, utiliser `templates/rust-cargo/crates/project-core-lib/Cargo.toml` comme exemple de manifest membre puis adapter son chemin et son nom.
`project-core-lib` n'est pas un nom de crate imposé. Dans une nouvelle baseline contrôlée, remplacer `project` par le nom court/abréviation du projet et choisir une responsabilité puis un rôle/cible lisibles conformément à `510-RUST_CARGO.md`. Une crate bibliothèque, binaire ou spécialisée doit conserver le layout et les héritages qui correspondent à son rôle réel ; un suffixe n'est pas ajouté uniquement pour obtenir une symétrie artificielle.
Avant de créer une paire `*-api` / `*-lib`, démontrer la frontière contractuelle qui justifie deux packages. Une implémentation unique sans extension/backend/lifecycle séparé reste normalement une seule crate `-lib`. À l'inverse, une vraie crate `-api` reste principalement déclarative et ne reçoit pas le runtime de logging du projet par automatisme.
Les exécutables sont des packages distincts des bibliothèques qu'ils composent, sauf exception de framework sélectionnée. Leur `main.rs` reste mince. Si plusieurs crates runtime partagent la même configuration de diagnostics, prévoir une crate transverse de logging/tracing ; ne pas répliquer l'initialisation du subscriber dans chaque binaire ou bibliothèque.
Lorsque le membre hérite de la politique commune, `version.workspace = true`, `edition.workspace = true`, `publish.workspace = true` et `[lints] workspace = true` restent cohérents. Une exception locale, notamment de lint ou de safety, doit suivre le contrat de `510-RUST_CARGO.md` et ne pas affaiblir silencieusement les autres membres.
Le code source minimal requis par Cargo appartient au projet destinataire. PGR ne fournit pas de `src/lib.rs` ou `src/main.rs` universel, car leur contenu dépend du rôle réel de la crate.
### Outillage Rust/Cargo
Copier et adapter :
```text
rustfmt.toml
clippy.toml
.cargo/config.toml
```
Suivre [`../templates/001-RUST_CARGO_TOOLING.md`](../templates/001-RUST_CARGO_TOOLING.md) pour leurs décisions d'adaptation.
L'édition de `rustfmt.toml` doit rester cohérente avec le workspace. Les seuils de `clippy.toml` doivent être revus au regard des API réelles. Dans `.cargo/config.toml`, remplacer `project-name` ou choisir un autre emplacement d'artefacts ; ne pas copier un chemin machine ou un identifiant appartenant à un autre projet.
### Cargo.lock
Décider explicitement si `Cargo.lock` est versionné selon le type de produit, le mode de publication et le besoin de reproductibilité. La présence ou l'absence du lockfile dans un projet source historique ne constitue pas une règle suffisante pour le nouveau workspace.
### Audits Rust ciblés
Pour une nouvelle baseline contrôlée qui adopte le profil strict, [`../validation/002-RUST_STYLE_AUDITS.md`](../validation/002-RUST_STYLE_AUDITS.md) fournit des contrôles monotâches pour les propriétés structurelles que Rustfmt ne possède pas complètement : lignes vides, séparation des items, ordre des modules, bloc d'imports de traits et blocs de réexports. Copier seulement les scripts réellement retenus et adapter leurs headers aux chemins locaux.
L'audit `audit_rust_const_blocks.py` reste à sélection explicite par fichier : il ne doit jamais réordonner une table de protocole, une séquence de migrations, un schéma ou toute structure dont l'ordre possède une sémantique propre. Les blocs `static`/`type` peuvent reprendre localement la même présentation sans qu'un audit supplémentaire soit créé par symétrie.
Le contrat de façade décrit dans [`../validation/003-RUST_EXPORT_COMPLETENESS.md`](../validation/003-RUST_EXPORT_COMPLETENESS.md) appartient également au profil strict ; `audit_rust_export_completeness.py` avec `_rust_audit_common.py` SHOULD être adopté afin de contrôler les propriétés que `rustc` et Clippy ne possèdent pas. Une adoption d'un projet existant SHOULD commencer en `--report-only`, résoudre les écarts ou exceptions locales, puis seulement rendre l'audit bloquant.
Aucun script n'est copié uniquement parce qu'il existe dans PGR. Si un autre owner fiable possède déjà la propriété ou si l'ordre est sémantique, la revue ou l'outil officiel reste préférable.
## Validation initiale
Une instanciation minimale doit d'abord prouver que les manifests adaptés décrivent bien le workspace voulu, puis que les outils Rust/Cargo retenus acceptent la baseline réelle.
Lorsque la toolchain est disponible et que du code source minimal ou réel existe, la séquence normale comprend :
```bash
cargo metadata --format-version 1 --no-deps
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Ajouter des tests ciblés pour les crates qui possèdent déjà un comportement à vérifier. Un `cargo build` n'est nécessaire que lorsqu'un artefact de build doit réellement être produit.
Si des audits Rust facultatifs ont été sélectionnés, exécuter les audits de style après formatage sur les seuls chemins concernés et l'audit de façade sur la racine du projet une fois son contrat explicitement adopté.
La validation doit aussi confirmer :
```text
CHECK VERSION et workspace.package.version cohérents pour un train de release unique
CHECK aucun placeholder project-name/project-core-lib non résolu dans les fichiers adoptés
CHECK édition Rust cohérente entre Cargo.toml et rustfmt.toml
CHECK membres du workspace existants, préfixés et nommés selon leur responsabilité/rôle
CHECK édition Rust 2024 ou exception externe explicitement documentée
CHECK profil strict de chemins/façade appliqué ou override borné documenté
CHECK politique Cargo.lock explicitement décidée
CHECK artefacts Cargo hors des livraisons source selon la politique locale
REVIEW dépendances/features, lints et métadonnées réellement nécessaires
REVIEW aucune specialization plateforme/framework ajoutée sans besoin réel
```
Pour valider les templates PGR eux-mêmes, une instanciation temporaire minimale peut remplacer les placeholders, créer une crate source triviale et exécuter les commandes Cargo ci-dessus. Cette preuve vérifie l'adoption des templates sans transformer le dépôt PGR en workspace Rust. Le contrat réutilisable de cette preuve, ainsi que le dry-run distinct d’un projet existant, est documenté dans [`../validation/004-RUST_CARGO_BASELINE_DRY_RUN.md`](../validation/004-RUST_CARGO_BASELINE_DRY_RUN.md).
Une prévalidation PGR ou générateur ne remplace jamais la gate opérateur autoritaire du projet destinataire.
## Ordre de composition et extensions
La specialization Rust/Cargo doit être appliquée après `001` lorsqu'elle l'utilise comme fondation. Les profils plateforme ou framework viennent ensuite uniquement s'ils sont applicables.
Une specialization plus précise peut :
- ajouter des packages ou cibles spécifiques ;
- imposer une matrice de toolchain ou de SDK ;
- raffiner la politique d'artefacts ou de lockfile ;
- ajouter des features, dépendances ou validations propres à son scope ;
- définir une exception locale de safety strictement justifiée.
Elle ne doit pas réécrire les règles générales Cargo ou inventer un nouveau workspace composite si les owners existants suffisent.
## Overrides et exceptions
Toute divergence par rapport aux templates ou au profil `510` doit identifier le choix concerné, son scope et sa raison lorsqu'elle affecte le contrat durable du projet.
Un projet peut notamment choisir un layout sans `crates/`, un autre chemin d'artefacts, une autre largeur Rustfmt, une politique de lockfile différente, des seuils Clippy différents ou une crate à lints locaux. Ces choix restent locaux et ne modifient pas les defaults PGR pour les autres projets.
## Hors scope
Cette specification ne définit pas :
- un nom universel de workspace ou de crate ;
- une version Rust ou Cargo exacte à pinner sans justification ;
- une liste universelle de dépendances ou features ;
- une politique `Cargo.lock` identique pour bibliothèques et applications ;
- une architecture applicative au-delà du workspace Cargo ;
- une plateforme, un framework, WASM, Android, Tauri ou une FFI ;
- un CI/CD, packaging ou mécanisme de publication universel ;
- une obligation de copier les audits Rust facultatifs ;
- un `src/lib.rs` ou `src/main.rs` générique sans rôle réel.
Les spécialisations futures doivent rester composables au-dessus de ce skeleton plutôt que modifier rétroactivement son scope.

View File

@@ -0,0 +1,143 @@
<!-- file: docs/skeletons/003-WEB_FRONTEND.md -->
<!-- version: 1 -->
# Skeleton — Web frontend
## Objectif
Cette specification décrit une specialization composable pour créer une baseline frontend Web contrôlée sans confondre langage, package ecosystem, build tool, styles et host.
Elle se compose avec [`001-PROJECT_GOVERNANCE_FOUNDATION.md`](001-PROJECT_GOVERNANCE_FOUNDATION.md), sélectionne les owners Web réellement applicables de la famille `500` et utilise les templates/guides `008`, `009` et `010` lorsqu'ils correspondent aux choix du projet.
Le contrat transversal des skeletons reste possédé par [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md).
## Applicabilité
Appliquer cette specialization lorsqu'un projet ou sous-projet possède un frontend Web autonome ou embarqué dont la baseline frontend est contrôlée par le projet.
Elle peut servir de fondation frontend à un host plus spécifique, par exemple Tauri, sans rendre ce host applicable par elle-même.
Pour un projet existant, cette specification sert de référence de comparaison : l'adoption suit [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md) et classe les choix existants `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` plutôt que de réécrire son layout.
Ne pas appliquer ce skeleton à un backend sans frontend, à une page statique qui n'a besoin d'aucune de ces responsabilités, ni uniquement parce que Vite/TypeScript sont recommandés ailleurs.
## Owners sélectionnables
La composition de référence d'un frontend moderne contrôlé est :
```text
GENERAL
+ 500 language / ecosystem family
+ 530 TypeScript
+ 540 JavaScript package ecosystem
+ 550 Vite
+ 560 CSS / Sass
```
La sélection reste factuelle :
- `530` est sélectionné lorsque TypeScript est utilisé ; TypeScript **SHOULD** être préféré pour une baseline durable lorsqu'il est compatible avec le besoin ;
- `540` est sélectionné lorsqu'un `package.json`, un package manager ou des dépendances JavaScript sont réellement utilisés ;
- `550` est sélectionné uniquement si Vite est choisi ; Vite **SHOULD** être préféré pour les frontends compatibles, sans être obligatoire ;
- `560` est sélectionné si le frontend possède une chaîne CSS/Sass ; CSS seul reste valide et Sass reste optionnel, bien que recommandé pour une chaîne non triviale ou un package exposant une API Sass utile.
Le skeleton ne transforme pas une recommandation `SHOULD` en `MUST`.
## Fondation et fichiers de départ
Lorsque TypeScript + package ecosystem sont sélectionnés, le projet MAY partir des templates :
```text
templates/web-typescript/package.json
templates/web-typescript/tsconfig.json
```
Le guide [`../templates/008-WEB_TYPESCRIPT_PACKAGE.md`](../templates/008-WEB_TYPESCRIPT_PACKAGE.md) possède leur adaptation.
PGR ne fournit pas de `vite.config.ts` universel. Si Vite est sélectionné, créer ou adapter la configuration réelle à partir des décisions décrites dans [`../templates/009-WEB_VITE.md`](../templates/009-WEB_VITE.md).
PGR ne fournit pas non plus de `main.scss` ou de thème universel. Si CSS/Sass est sélectionné, organiser les sources selon les besoins réels et suivre [`../templates/010-WEB_CSS_SASS.md`](../templates/010-WEB_CSS_SASS.md).
Le nom `frontend/` est une convention possible, pas un chemin imposé par ce skeleton.
## Décisions destinataire avant matérialisation
Résoudre explicitement au minimum :
1. la racine et le scope exacts du frontend ;
2. TypeScript ou JavaScript, avec justification si une nouvelle baseline durable n'adopte pas la recommandation TypeScript ;
3. le package manager réel et la politique de lockfile adaptée au rôle du package ;
4. les versions réelles de TypeScript et des dépendances, ainsi que les déclarations `@types/*` réellement nécessaires ;
5. Vite ou un build tool alternatif, avec ses chemins `root`, cache, outputs, `base`, ports, plugins et assets lorsqu'ils s'appliquent ;
6. CSS seul ou Sass, puis l'implémentation Sass réelle si sélectionnée ;
7. le framework CSS éventuel : aucun, Bootstrap, Tailwind CSS ou autre ; ce choix reste local au projet ;
8. les entrypoints de styles publics des dépendances et les overrides réellement nécessaires ;
9. les scripts de package réellement utiles (`typecheck`, `dev`, `build`, `preview` ou équivalents) ;
10. la gate frontend indépendante du host et les éventuels smokes navigateur utiles ;
11. les prérequis produits par d'autres owners, s'il en existe, sans les faire absorber par le frontend.
Aucune décision ouverte ne doit être remplacée silencieusement par une valeur observée dans Games ou KSP.
## Dépendances et manifest
Le package réel **SHOULD** rester privé lorsqu'il représente une application non publiée, conformément à `540`.
Les dépendances de développement telles que TypeScript, Vite, Sass ou packages de déclarations sont ajoutées uniquement si les choix du projet les rendent nécessaires. Le skeleton MUST NOT préremplir `@types/node`, `@types/bootstrap`, `sass-embedded`, Vite ou Bootstrap sans besoin réel ni version décidée.
Lorsqu'une dépendance fournit déjà ses propres types, ne pas ajouter un package `@types/*` redondant.
## Styles
CSS source et Sass source sont des entrées versionnées. Les CSS compilées/minifiées, sourcemaps et copies dans l'output sont générées sauf contrat de distribution explicite.
Pour du nouveau Sass contrôlé, `@use` / `@forward` sont préférés lorsque les dépendances le permettent. Une compatibilité `@import` peut être conservée pour un package existant qui l'exige encore.
Le choix d'un framework CSS ne rend ni Bootstrap, ni Tailwind CSS, ni un thème spécifique normatif pour les autres projets.
## Build et outputs
Lorsque Vite est sélectionné, le cache et `build.outDir` restent générés et hors Git. Les chemins exacts restent locaux.
`build.emptyOutDir = true` n'est utilisé que sur un output dédié. `vite preview` reste un smoke/prévisualisation locale et ne devient pas un serveur de production.
Un autre build tool possède ses propres décisions project-specific tant qu'aucun owner PGR dédié n'existe.
## Validation initiale
La validation suit [`../validation/005-WEB_FRONTEND_VALIDATION.md`](../validation/005-WEB_FRONTEND_VALIDATION.md).
Selon les profils sélectionnés, elle doit pouvoir prouver indépendamment du host, autant que possible :
```text
restore reproductible
TypeScript typecheck
compilation/transformation des styles
build frontend de production
smoke navigateur seulement si nécessaire
```
La commande concrète appartient au package manager et aux outils réellement sélectionnés.
Le host reçoit ensuite sa propre gate d'intégration. Un PASS frontend ne constitue pas un PASS Tauri ou plateforme.
Une instanciation temporaire MAY être utilisée pour un dry-run de cette specialization. Elle doit employer les toolchains officielles réelles plutôt qu'un audit Python simulant TypeScript/Vite/Sass.
## Composition avec un host
Un host peut composer ce skeleton comme fondation frontend, puis ajouter son propre profil/skeleton.
Cette composition ne transfère jamais au host l'ownership de TypeScript, du package manager, de Vite ou de Sass/CSS.
Le skeleton Tauri reste `DEFER` pendant `0.1.1`. La présence du présent skeleton Web satisfait une pièce de préparation mais ne décide pas à elle seule la promotion du candidat Tauri.
## Hors scope
Cette specification ne possède pas :
- Tauri ou un autre host natif ;
- WASM ou ses bindings/générations ;
- backend/serveur Web ;
- deployment/operations ;
- choix de framework UI/CSS universel ;
- configuration de sécurité propre à un host ;
- service worker/PWA tant qu'un owner distinct n'est pas justifié.

View File

@@ -0,0 +1,14 @@
<!-- file: docs/studies/000-README.md -->
<!-- version: 4 -->
# Index des études PGR
Les études PGR enregistrent une analyse bornée nécessaire à une décision, une réconciliation ou une future normalisation sans transformer prématurément leurs conclusions en règles.
Une étude peut comparer des projets sources, des technologies ou plusieurs options. Elle doit distinguer les faits observés, les conclusions déjà suffisamment étayées, les décisions encore ouvertes et les éléments qui doivent rester spécifiques à leur contexte.
## Études actives
- [`001-KSP_GAMES_RECONCILIATION.md`](001-KSP_GAMES_RECONCILIATION.md) — première réconciliation explicite de PGR avec les baselines autoritaires fournies de `khadhroony-solana-project` et `sasedev-games`.
- [`002-TAURI_SKELETON_DECISION.md`](002-TAURI_SKELETON_DECISION.md) — décision historique `DEFER` du skeleton Tauri, complétée en `0.1.1-beta.1` par la preuve que ses cinq prérequis Web disposent désormais d'owners PGR, sans lever le report avant `0.1.4`.
- [`003-V0_1_0_HORIZON_REVIEW.md`](003-V0_1_0_HORIZON_REVIEW.md) — revue d'horizon `0.1.0-beta.1` engageant les prochaines releases `0.1.x` suffisamment décidées et conservant les autres axes sans numéro.

View File

@@ -0,0 +1,317 @@
<!-- file: docs/studies/001-KSP_GAMES_RECONCILIATION.md -->
<!-- version: 11 -->
# Étude de réconciliation PGR / KSP / sasedev-games
## Objet et statut des corpus
Cette étude exécute l'inventaire demandé par `prompts/005-V0_0_5_START_PROMPT.md` avant toute modification normative importante de `0.0.5`.
`khadhroony-solana-project` et `sasedev-games` sont ici des **corpus de conception et de réconciliation**. Ils n'ont pas encore adopté PGR comme référentiel de gouvernance. Une divergence observée dans leurs baselines ne constitue donc pas une non-conformité PGR et ne doit pas être « corrigée » rétroactivement dans ces projets pendant cette release.
La question utile est différente : quelles responsabilités déjà éprouvées doivent rester locales, lesquelles sont déjà correctement possédées par PGR, et lesquelles révèlent un besoin générique suffisamment réutilisable pour améliorer PGR avant une future adoption ?
## Sources autoritaires contrôlées
### PGR
Baseline : archive source `pgr-v0.0.4.zip`, annoncée comme téléchargement du tag Gitea `v0.0.4`, accompagnée du rapport externe `pgr-0.0.4-publish.001-report.md` avec statut `PASS`.
```text
SHA-256 7137bb084f017362323a2043d13ba71490be15b8786adc8d645981bf455b80ae
entrées 167
fichiers 139
répertoires 28
racine pgr/
CRC clean
.git absent
```
Aucun doublon ZIP, collision de casse, chemin dangereux ou lien symbolique n'a été détecté. Les `15` tests Python PGR passent ; les audits Markdown affichent `123` fichiers contrôlés, `3` tableaux propres et `116` liens locaux propres. Les cinq fichiers TOML du template Rust/Cargo se parsèrent correctement.
Le rapport post-tag donne le même hash et sépare explicitement la preuve de publication de l'état contenu dans l'archive.
### khadhroony-solana-project
Baseline autoritaire fournie : `khadhroony-solana-project-v0.3.16.zip`.
```text
SHA-256 db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0
entrées 2229
fichiers 2017
répertoires 212
racine khadhroony-solana-project/
CRC clean
.git absent
```
Aucun doublon ZIP, collision de casse, chemin dangereux ou lien symbolique n'a été détecté. Les audits Python fournis par la baseline passent :
```text
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
Markdown table audit: clean (352 table(s), 962 file(s))
```
### sasedev-games
Baseline autoritaire fournie : `games-v0.3.5.zip`.
```text
SHA-256 5f5fdee1a271386766d059657d6eaa831acdc263b3e722fed738808335c0a105
entrées 664
fichiers 508
répertoires 156
racine games/
CRC clean
.git absent
```
Aucun doublon ZIP, collision de casse, chemin dangereux ou lien symbolique n'a été détecté. Les audits Python fournis par la baseline passent :
```text
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
games.sasedev workspace audit: clean
Markdown table audit: clean (5 table(s), 304 file(s))
Distribution layout audit: clean (66 required path(s), 8 forbidden path(s) absent)
```
La toolchain `cargo` n'est pas disponible dans l'environnement utilisé pour cette étude ; aucun `cargo metadata`, build, test ou Clippy externe n'est donc présenté comme exécuté ici. Cette limite n'empêche pas l'inventaire documentaire et statique demandé à `alpha.1` et ne transforme pas les audits Python en preuve de compilation.
## Méthode de classification
Chaque propriété observée est classée selon l'un des états suivants :
```text
OWNED déjà correctement possédée par PGR ; l'usage local ne crée pas de nouvelle règle
COMMON besoin générique réel insuffisamment matérialisé dans PGR ; candidat de 0.0.5
LOCAL besoin spécifique au projet, à son architecture, son domaine ou sa plateforme
LEGACY divergence historique ou duplication locale à considérer lors d'une future adoption, pas à corriger ici
DEFER preuve insuffisante pour créer maintenant un owner PGR durable
```
La classification porte sur les responsabilités et contrats, pas sur la simple ressemblance des noms de fichiers.
## Réconciliation de la gouvernance et de la documentation
| Sujet observé | KSP / Games | Classification | Décision PGR |
|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| hiérarchie normative et exceptions bornées | présente dans les deux corpus | `OWNED` | `RULES.md` et le modèle de profils possèdent déjà ce contrat ; ne pas recopier les règles locales |
| langue code/chemins anglais, documentation interne française | commune | `OWNED` | déjà possédée par `RULES.md` et `300-DOCUMENTATION.md` |
| rôles de `README`, `RULES`, `ROADMAP`, `CHANGELOG`, plans et documents durables | largement communs | `OWNED` | `300-DOCUMENTATION.md` couvre déjà les rôles génériques |
| headers internes `file` / `version` | communs | `OWNED` | déjà possédés et audités par PGR ; les règles locales plus strictes restent locales tant qu'elles ajoutent une sémantique propre |
| `FILE_CONTRACTS.md` local décrivant responsabilité et règle de modification des familles importantes | présent dans les deux corpus | `COMMON` | fournir un pattern/template documentaire facultatif et l'intégrer à la fondation seulement lorsque la complexité du projet le justifie |
| prompt de démarrage autonome avec baseline, ordre de lecture, état validé, mission, hors-scope, première gate et validation | présent dans les deux corpus | `COMMON` | renforcer le contrat générique des prompts PGR et fournir une spécification réutilisable ; ne pas copier les commandes KSP/Games |
| règle « une version complète par session » | explicitement forte dans Games, structurante dans certaines pratiques locales | `LOCAL` | PGR conserve sa règle actuelle : une session ne force pas artificiellement une version ; un projet peut ajouter une contrainte locale plus forte |
| couloirs exacts de fermeture et numérotation de prereleases | plus détaillés dans KSP/Games | `DEFER` | conserver le principe PGR de consolidation/RC/stable ; ne pas généraliser des numéros ou un nombre fixe de tranches |
| absence de `history/` dans KSP `v0.3.16` et historique partiel dans Games | divergence de workflow antérieure à l'adoption de PGR | `LEGACY` | ne pas créer de dette rétroactive ; une future adoption décide son point de départ et ne réécrit pas l'historique |
## Réconciliation de la validation
PGR possède déjà le besoin générique le plus important : sélectionner les preuves à partir du scope, des risques invalidés et de la maturité, avec une matrice canonique facultative pour les projets suffisamment structurés.
Les matrices et documents de validation de Games et KSP confirment plusieurs pratiques déjà couvertes : tests ciblés pendant le développement, gates plus larges aux frontières de maturité, contrôles de dépendances seulement lorsqu'ils apportent une preuve, et distinction entre audit statique, build, smoke et diagnostic. Ces éléments restent `OWNED`.
Les audits spécialisés restent locaux :
- `audit_ksp_workspace_rules.py` contrôle des frontières, dépendances et conventions propres à KSP ;
- `audit_distribution_layout.py` contrôle le layout et plusieurs intégrations Web/Android/Gradle propres à Games ;
- ces scripts ne doivent pas être copiés dans PGR ni transformés en audits universels.
## Réconciliation Rust/Cargo
Les travaux `0.0.3` et `0.0.4` ont déjà absorbé les parties génériques évidentes des deux corpus : workspace Cargo, héritage des métadonnées et lints, templates `rustfmt.toml`/`clippy.toml`/`.cargo/config.toml`, manifests, safety/FFI bornée et audits de style ciblés. Ces propriétés restent `OWNED`.
Un besoin commun reste cependant suffisamment net pour être repris : les deux projets contiennent `audit_rust_export_completeness.py` avec le même contrat et le même corps fonctionnel à l'exception de la révision de fichier. Il contrôle la complétude de façade crate-root et les chemins canoniques associés, propriété que Rustfmt et Clippy ne possèdent pas. Le profil `510` décrit déjà cette architecture comme convention recommandée.
Décision : classer ce contrôle `COMMON`, mais ne pas copier le script tel quel en `alpha.1`. Une tranche dédiée doit d'abord :
1. séparer ce qui dépend du profil Rust général de ce qui dépend d'un style KSP/Games plus strict ;
2. conserver l'audit facultatif tant que la façade crate-root n'est qu'un `SHOULD` du profil ;
3. fournir des tests positifs/négatifs ciblés et documenter les limites du parsing lexical ;
4. éviter de réintroduire les règles déjà possédées par Rustfmt, Clippy ou les deux audits de style PGR existants.
#### Mesure alpha.5
La relecture du script historique révèle une limite importante : sa découverte `crates/*/Cargo.toml` couvre les `22` crates KSP placées directement sous `crates/`, mais aucune des `23` crates Games imbriquées sous `crates/apps`, `crates/common`, `crates/engines`, etc. Le code des deux scripts est bien commun, mais le résultat historique Games `0 candidate(s)` n'était pas une preuve d'audit des crates réelles.
La variante PGR corrige d'abord la découverte récursive. La revue opérateur de `alpha.5` montre ensuite que limiter la canonicalisation à `crate::module::Item` est insuffisant : les corpus contiennent de nombreuses références nues à des items pourtant réexportés, notamment dans leur module propriétaire, et ni `rustc` ni Clippy ne possèdent la convention « référence partagée = `crate::Item` partout dans la crate ». `alpha.5` est donc conservé `FAIL` et `alpha.5.fix.1` étend `RUST-IMPORT-201` à ce contrat réel.
La mesure corrigée, avec découverte récursive et séparation des cibles Cargo, donne `1525` lignes candidates `RUST-IMPORT-201` dans KSP sur `22` packages et `181` lignes candidates dans Games sur `23` packages (`2 RUST-API-201`, `179 RUST-IMPORT-201`). Ces volumes ne sont pas interprétés comme des défauts rétroactifs : ils montrent précisément pourquoi une adoption PGR d'un projet existant doit commencer en `--report-only`, puis migrer progressivement la convention avant d'en faire une gate bloquante.
Le grand `audit_rust_general_rules.py` des deux corpus reste `DEFER` comme source d'extraction, pas comme script à importer. Il mélange plusieurs responsabilités : headers, rustdoc, imports, structure de façade, blancs, constantes et règles locales ; Games y ajoute une exception FFI Android étroite. PGR doit continuer à extraire des audits monotâches seulement lorsqu'une propriété commune apporte une preuve non redondante.
L'orchestrateur `audit_rust_workspace_rules.py` est un pattern d'ergonomie utile mais ne possède aucune règle. PGR peut documenter comment composer des audits sélectionnés dans un projet destinataire sans fournir un lanceur universel qui supposerait les mêmes scripts partout.
## Réconciliation des frameworks et plateformes
### Tauri
Tauri est réellement présent dans les deux corpus et n'est plus un exemple isolé : KSP contient `6` applications Desk Tauri et Games `2` hôtes Tauri. Les `8` applications observées utilisent Tauri 2, un package Rust avec `tauri-build`, une configuration `tauri.conf.json`, des capability files, des hooks frontend et un `frontendDist` dédié.
Les différences sont tout aussi importantes que les points communs : KSP possède deux fenêtres par Desk, active le bundling et utilise des hooks npm simples ; Games utilise une fenêtre, désactive le bundling dans les POC observés et l'un de ses hooks construit d'abord un frontend WASM via un script Python. Les CSP, ports, identifiants, ressources et plugins ne sont pas uniformes.
Toutes les configurations observées omettent une version Tauri explicite tandis que leur package Cargo hérite de la version workspace. La relecture des règles montre que ce n'est pas un simple accident : KSP `VER-ID-015/016` et Games `VER-TAURI-001..004` ont tous deux utilisé l'omission de `tauri.conf.json > version` et la non-synchronisation systématique de `package.json` pour réduire le churn. La clarification opérateur de `alpha.6.fix.2` rejette toutefois la généralisation de cette solution : l'objectif durable est de **classifier la fréquence de synchronisation**, pas de supprimer les champs. PGR conserve donc la possibilité d'une version Tauri/frontend explicite et privilégie `MIRROR-STABLE` lorsque ces valeurs doivent seulement porter le jalon `X.Y.Z` cible.
Les deux corpus versionnent leurs capability files et ignorent les dépendances/sorties frontend reproductibles. Ils ignorent également `gen/`, mais ce dernier point n'est pas généralisé : les projets mobiles Tauri peuvent contenir sous leur projet généré des personnalisations de plateforme intentionnelles qui doivent être classifiées avant toute politique Git.
Décision `alpha.6` : classer Tauri `COMMON`, activer `700-FRAMEWORKS.md` et créer `710-TAURI.md`. Le profil possède l'orchestration Tauri : host Rust, configuration/capabilities, hooks frontend, version produit et gates d'intégration. Il ne possède pas à lui seul Vite, TypeScript, Sass, Bootstrap, WASM, le package manager, les ports, fenêtres, CSP, bundles ou plugins particuliers.
La revue opérateur de `alpha.6` apporte deux clarifications importantes. Premièrement, dans les projets Tauri que l'organisation contrôle, le host est traité comme n'importe quel projet Rust du même ensemble et doit donc hériter sans exception implicite du profil Rust sélectionné ; un projet imposé de l'extérieur peut conserver d'autres conventions via des overrides project-specific. Deuxièmement, les choix récurrents `frontend/`, Vite, TypeScript, Sass, Bootstrap et ajout explicite des dépendances de plugins décrivent un **candidat de skeleton pour projets contrôlés**, pas le contrat universel de Tauri.
Le POC Tauri mobile de Games n'a pas été concluant pour les besoins Games observés, notamment l'objectif Android/ABI et les contraintes de monétisation envisagées. Cette expérience ne permet pas de rejeter Tauri mobile pour d'autres produits : la capacité reste à évaluer par projet avec les profils plateforme applicables.
La règle de validation commune reste confirmée : lorsqu'une propriété dépend de `beforeDevCommand`, `beforeBuildCommand`, `frontendDist`, des capabilities ou du bundling, une sous-commande directe telle que `npm run build` ou `cargo build` ne prouve pas l'intégration Tauri complète. La gate doit passer par le CLI Tauri ou une forme officiellement équivalente ; les sous-commandes restent pertinentes pour leurs preuves ciblées.
Le CLI Tauri fournit une commande `add`, mais les documentations officielles des plugins détaillent également l'ajout explicite de la dépendance Cargo, l'initialisation Rust et, lorsqu'ils existent, les bindings frontend. PGR ne doit donc pas imposer la commande de commodité : un projet qui privilégie le contrôle manuel des manifests peut suivre explicitement ces étapes et revoir chaque modification.
#### Seconde passe de réconciliation des conventions Tauri/Rust
La clarification opérateur de `alpha.6.fix.1` déclenche une seconde lecture des règles versionnées plutôt qu'une simple extrapolation depuis les fichiers de configuration. Cette passe confirme plusieurs niveaux de preuve.
**Commun aux `8` hosts Tauri observés** : les `6` Desk KSP et les `2` hosts Games placent directement à la racine de leur crate `Cargo.toml`, `build.rs`, `package.json`, `tsconfig.json` et `tauri.conf.json`; tous possèdent `src/lib.rs`, `src/main.rs`, `src/tauri.rs` et `frontend/`; aucun ne possède `src-tauri/`. Cette convergence justifie une forte recommandation PGR pour les nouveaux projets contrôlés sans imposer une migration mécanique aux projets externes.
**Commun et déjà normatif dans les corpus** : KSP `KSP-APP-010..013` et Games `GAME-PLATFORM-010` convergent vers une bibliothèque applicative avec façade `lib.rs`, un launcher `main.rs` mince et un `tauri.rs` qui assemble Tauri et expose les wrappers de commandes. Games `GAME-PLATFORM-009` confirme aussi que l'adaptation WASM réutilisable reste distincte de la crate Tauri.
**KSP plus strict mais réutilisable** : `KSP-APP-023` place les sources Web sous `frontend/`, TypeScript sous `frontend/ts/`, Sass sous `frontend/sass/` et les bindings TS-RS sous `frontend/ts/bindings/`, les DTO Rust restant la source de vérité. La baseline KSP `0.3.16` contient `41` fichiers Rust applicatifs utilisant TS-RS dans les apps Desk. Games n'a pas encore ce contrat TS-RS : PGR le classe donc comme convention stricte des projets contrôlés, pas comme invariant universel de Tauri.
**Fortement recommandé mais pas universel** : le préfixe KSP `tw_`, le splashscreen commun, les paires de ports fixes, le plugin tracing précis et les détails de shell sont locaux. En revanche, un module cohérent par fenêtre/responsabilité, des helpers communs séparés et l'ajout explicite/revu des plugins sont des patterns réutilisables.
**Rust au-delà de Tauri** : `RULES_RUST.md` KSP contient un profil beaucoup plus complet que Games : `use` non-traits interdits, chemins externes explicites les plus courts, réexports `self::`, alias interdits, blocs de visibilité/ordre, contrôle de flux explicite et façade stricte. Games confirme le noyau façade/chemins/erreurs mais pas toutes les contraintes de style. Ces écarts doivent être traités en tranches Rust dédiées, avec KSP comme référence stricte et Games comme pression pour classifier correctement `MUST`/`SHOULD`/override.
**Nomenclature des crates** : KSP encode explicitement le rôle (`ksp-<role>-lib`, `ksp-<domain>-api`, `ksp-app-<role>-<interface>`, workers/jobs), tandis que Games conserve lui aussi des noms révélant rôle et cible (`game-logging-lib`, `*-desktop`, `*-tauri`, `*-wasm`, `engine-v1-*`). PGR doit donc étudier une convention générale « préfixe projet + responsabilité + suffixe de rôle/cible » sans figer les vocabulaires propres à KSP ou Games.
#### Décision `alpha.7` — profil Rust strict et nomenclature
La seconde passe sur les règles autoritaires confirme que KSP `RULES_RUST.md` version `10` matérialise le profil d'explicité le plus complet : Rust 2024, `use` réservé aux traits réellement nécessaires, chemins externes publics les plus courts, réexports internes `self::`, absence de glob/groupement/alias, façade crate-root, `crate::Item` intra-crate et contrôle de flux explicite. Games `RULES_RUST.md` version `7` confirme Rust 2024, façade crate-root, `crate::Item`, interdiction des globs, erreurs explicites et lints communs, tout en étant moins strict sur les imports non-traits et certaines formes de visibilité.
La décision PGR est de retenir ce niveau strict comme **défaut des nouvelles baselines Rust contrôlées**. Un projet externe ou historiquement contraint peut conserver une convention différente via un override project-specific borné ; cette exception ne réduit pas le profil canonique des nouveaux projets.
Les règles sémantiques retenues dans `alpha.7` sont :
- édition Rust 2024 comme baseline actuelle des projets contrôlés ;
- `use` réservé aux traits qui doivent réellement être mis en scope ;
- chemins explicites pour les autres symboles, avec le chemin public externe le plus court ;
- réexports internes explicites via `self::`, sans glob, regroupement par accolades ni alias de commodité ;
- façade crate-root pour les items partagés et `crate::Item` dans la crate, y compris dans le module propriétaire ;
- pas de visibilité élargie uniquement pour les tests ;
- `unwrap`, `expect` et `?` interdits en production dans le profil strict, avec retours et propagation d'erreurs explicites.
Le marqueur KSP `rust-rules: trait-import` n'est pas généralisé : il sert l'audit historique KSP et n'est pas la règle sémantique. De même, `alpha.7` n'importe aucun script composite KSP/Games ; l'enforcement complémentaire reste découpé entre les owners PGR existants et la tranche `alpha.8`.
La nomenclature converge sur une propriété utile sans imposer les vocabulaires locaux : KSP préfixe toutes ses crates avec `ksp-` et encode explicitement bibliothèque/API/application/worker/job ; Games emploie également des noms où responsabilité et cible restent visibles (`game-logging-lib`, `*-desktop`, `*-tauri`, `*-wasm`, familles `engine-v1-*`). PGR retient donc pour les nouveaux projets contrôlés un préfixe projet/abréviation obligatoire et recommande la forme `<project>-<responsibility>-<role-or-target>` lorsque le classificateur apporte une information réelle. Les ordres historiques déjà cohérents ne sont pas renommés rétroactivement.
Les règles de blocs homogènes, visibilité, espacement et ordre alphabétique restent volontairement hors de cette décision et appartiennent à `alpha.8`.
#### Correction `alpha.7.fix.1` — suffixes, packaging et tracing
La gate mécanique de `alpha.7` passe, mais la revue fonctionnelle opérateur révèle que la première matérialisation traitait encore les suffixes comme de simples indications de lisibilité. Le corpus KSP contient pourtant un contrat plus fort : `KSP-NAME-001..003` distingue implémentation réutilisable `-lib` et contrat extensible `-api`, `KSP-API-007` interdit de créer une API par symétrie, et `002-LAYERS_AND_DEPENDENCIES.md` réserve le logging aux crates ayant réellement du comportement.
La règle PGR devient donc sémantique : `-api` signifie frontière de contrat réellement justifiée et principalement passive ; `-lib` signifie implémentation/fonctionnalité réutilisable. Une implémentation unique sans besoin d'extension/backend/lifecycle ne crée pas artificiellement une paire `-api` / `-lib`. Les rôles `worker`, `job`, `store`, etc. peuvent faire partie du nom d'une bibliothèque, mais `-lib` continue d'indiquer qu'elle n'est pas le launcher.
Sur le packaging, les deux corpus ne doivent pas être fusionnés mécaniquement. Games `GAME-WS-007` sépare explicitement la lib de jeu et son runner Desktop. KSP contient encore `KSP-WORKER-014`, qui préférait à terme un package worker mixte bibliothèque + binaire. Cette dernière préférence n'est **pas généralisée** : la clarification opérateur retient désormais la séparation package bibliothèque / package exécutable par défaut, les exécutables restant des couches de composition minces. Tauri est l'exception framework actuelle.
Cette exception est elle-même fortement observée : les `6` hosts Tauri KSP `0.3.16` et les `2` hosts Tauri Games `0.3.5` déclarent une cible `lib` et une cible `bin` distinctes ; les libs utilisent un nom terminé par `_lib` tandis que le binaire conserve le nom applicatif. PGR exige donc, dans une nouvelle baseline Tauri contrôlée, des noms de targets distincts même après normalisation `-` → `_`. Le motif cross-platform exact à l'origine de cette convention n'est pas utilisé comme preuve normative ici ; le contrat observable et reproductible suffit.
Le logging converge également fortement. KSP possède `ksp-logging-lib` comme façade/runtime commun et garde ses `*-api` déclaratives sans logging ; Games définit `tracing` comme mécanisme canonique, `tracing-subscriber` comme owner de composition, `tracing-appender` lorsque nécessaire et `game-logging-lib` comme crate transverse. PGR retient donc `tracing` par défaut et recommande une crate commune de logging dès que plusieurs runtimes partagent subscriber, sinks, filtres ou lifecycle ; la façade `log` reste seulement une compatibilité possible, pas le default d'une nouvelle baseline contrôlée.
#### Politique de version Tauri/frontend réconciliée
La baseline KSP `0.3.16` illustre le défaut de l'ancienne convention : les six `tauri.conf.json` n'ont pas de champ `version`, tandis que leurs `package.json` portent des versions historiques différentes (`0.2.6`, `0.2.12-pre.9`, `0.3.7`, `0.3.8` ou `0.3.15`) sans représenter uniformément la release courante. Games `0.3.5` suit la même famille de règles. Cette situation réduit les modifications mécaniques mais affaiblit la lisibilité des manifests.
La décision PGR est donc :
- `VERSION` = `CANONICAL` exact de la tranche ;
- version Cargo = `MIRROR-EXACT` lorsque le profil Rust du projet la synchronise ;
- `tauri.conf.json > version` et `package.json > version`, lorsqu'ils sont conservés pour le même produit, SHOULD normalement être `MIRROR-STABLE` et porter la cible `X.Y.Z` pendant tout le développement ;
- une distribution réelle de prereleases peut sélectionner une politique plus fine (`MIRROR-EXACT` ou jalons de packaging) ;
- l'absence du champ reste autorisée lorsque le projet n'en tire aucune valeur, mais n'est plus la recommandation PGR destinée à éviter le churn.
Cette décision est cohérente avec le principe PGR historique qui distingue déjà version canonique, miroirs techniques, compteurs et versions de schéma au lieu d'exiger `tous les champs == VERSION`.
#### Décision `alpha.8` — formatage structurel et audits monotâches
La comparaison des `audit_rust_general_rules.py` KSP/Games confirme que leur grand script mélangeait plusieurs owners qui peuvent être séparés proprement. PGR possédait déjà `blank_lines` et `const_blocks`; la tranche extrait quatre propriétés supplémentaires sans copier les contrôles de headers, FFI, rustdoc, façade ou imports déjà possédés ailleurs.
Les nouveaux audits ciblés sont :
- `item_spacing` : exactement une ligne vide entre items distincts voisins d'un même scope ; les blocs compacts `const/static/type` homogènes sont délégués afin d'éviter les faux positifs sémantiques ;
- `module_order` : modules de production avant les modules de tests, ordre alphabétique de chaque groupe ;
- `trait_import_blocks` : `use` non exportés au niveau module, avant les déclarations et sans ligne vide interne ; la nature réelle du trait n'est pas inférée lexicalement ;
- `reexport_blocks` : bloc `pub use` avant `pub(crate) use`, aucun blanc interne et exactement un blanc entre niveaux ; Rustfmt reste owner du tri intra-bloc.
La mesure croisée sur tous les fichiers `crates/**/*.rs` donne `603` fichiers KSP et `87` Games. Les quatre nouveaux audits sont propres sur les deux corpus, de même que `blank_lines`. L'audit `const_blocks` produit en revanche `18` signaux KSP lorsqu'il est appliqué aveuglément et `0` Games ; certains signaux KSP correspondent à des tables ou schémas dont l'ordre est intentionnel. Cette différence confirme que `const_blocks` doit rester opt-in sur des fichiers explicitement sélectionnés.
PGR ne reprend pas automatiquement `RUST-FMT-110` du script KSP (item après `return` comme suspicion d'accolade déplacée), ni un ordre global `enum → struct → impl → fn`, ni l'idée que tous les éléments visibles doivent mécaniquement précéder les privés. Ces propriétés peuvent dépendre de la structure métier ; un audit lexical général créerait plus de faux positifs qu'il n'apporterait de preuve. La convention `struct` suivi de ses `impl` reste une forte préférence de lisibilité, pas un tri universel automatisé.
Cette extraction ferme le besoin identifié pour `alpha.8` sans créer de parser Rust général.
### Web / Vite / WASM
Les corpus et la clarification opérateur permettent désormais de séparer trois choses :
- le frontend Tauri est un owner distinct du host Rust et du framework Tauri ;
- Vite + TypeScript + Sass + Bootstrap constitue un candidat de stack par défaut pour les futurs skeletons de projets contrôlés, mais manque encore de profils Web dédiés dans PGR ;
- WASM n'est pas une dépendance implicite de Tauri et doit généralement rester un projet/package séparé appliquant ses propres profils, sauf composition architecturale explicitement voulue.
La création de profils Web/Vite/TypeScript/Sass reste `DEFER` pour `0.0.5` : cette release peut cadrer la future composition sans matérialiser précipitamment toute la famille Web.
La même clarification révèle un écart antérieur dans le profil Rust PGR : la conception initiale avait retenu le profil strict sans `use` non-trait, chemins explicites et conventions d'organisation, alors que le `510-RUST_CARGO.md` matérialisé conserve encore une formulation plus permissive. Ce sujet ne doit pas être absorbé par un fix Tauri ; il devient une tranche Rust normale dédiée avant toute décision de skeleton Tauri.
### Android / JNI
Android possède déjà un owner PGR `610`. Le JNI/Rust natif réellement observé est surtout propre à Games dans les baselines présentes. Les exceptions `unsafe`, ABI, exports JNI et génération Gradle doivent rester locales ou différées jusqu'à une étude composite Rust + Android/JNI suffisante. Classification : `DEFER`.
## Éléments qui doivent rester spécifiques
Les responsabilités suivantes sont utiles dans leurs projets mais ne fournissent pas un owner PGR générique :
- firewall de dépendances, protocoles Solana, transports, Store, workers/jobs, tracing targets et materialization de KSP ;
- générations de moteur, assets de jeux, Uroburas, serveurs temps réel, distribution Android/Web et politiques de hosting de Games ;
- noms métier exacts des crates, répertoires de config, schémas, routes, plugins et ressources propres à chaque application ; la convention générique de noms exprimant préfixe projet, responsabilité et rôle reste à réconcilier en `alpha.7` ;
- seuils Clippy, identifiants courts autorisés, ports de développement et paramètres de fenêtres lorsqu'ils n'expriment aucun invariant réutilisable.
Ces éléments servent à tester que PGR permet des règles locales spécifiques ; ils ne doivent pas être aspirés dans le référentiel central.
## Conséquences pour une future adoption de PGR
La future application de PGR à KSP et Games doit être une migration explicitement planifiée dans chacun des projets, après stabilisation de la release PGR retenue. Elle ne doit pas reconstruire artificiellement leurs anciens deltas/histories ni renommer rétroactivement toutes les conventions historiques.
Le point de départ attendu sera plutôt :
```text
prendre la stable réelle du projet
+ sélectionner les owners PGR applicables
+ comparer les règles locales actuelles
+ conserver les contraintes projet spécifiques
+ remplacer seulement les duplications devenues inutiles
+ introduire les nouveaux audits/templates de manière proportionnée
+ valider la migration comme une release du projet lui-même
```
`0.0.5` améliore donc le référentiel et ses points d'adoption ; il ne migre ni KSP ni Games.
## Réconciliation intégrée `beta.1`
Après les tranches `alpha.1` à `alpha.9`, la classification initiale peut être rejouée sur l'état PGR obtenu sans aspirer les architectures métier des corpus.
| Domaine | Owner / artefact PGR après réconciliation | Statut intégré | Décision durable |
|---------------------------------------------------------------|---------------------------------------------------------------------------------------|----------------|-------------------------------------------------------------------------------------------------------|
| prompt de démarrage versionné | `210-WORKFLOW.md` + prompts de release | `OWNED` | contrat générique renforcé ; commandes et baselines propres au projet restent locales |
| contrats de fichiers/familles | `300-DOCUMENTATION.md` + `004-FILE_FAMILY_CONTRACTS.md` | `OWNED` | pattern facultatif, jamais inventaire obligatoire |
| lifecycle inter-release / horizon | `200-GOVERNANCE.md`, `210-WORKFLOW.md`, `300-DOCUMENTATION.md`, `005-RELEASE_PLAN.md` | `OWNED` | fermeture, transition et revue d'horizon ont désormais des owners explicites |
| profil Rust contrôlé | `510-RUST_CARGO.md` + skeleton `002` | `OWNED` | explicité, crate-root, suffixes architecturaux, séparation lib/bin et tracing transverse bornés |
| audits Rust structurels | `002-RUST_STYLE_AUDITS.md`, `003-RUST_EXPORT_COMPLETENESS.md`, scripts monotâches | `OWNED` | pas d'audit composite ; `const_blocks` reste sélectionné lorsque l'ordre est sémantique |
| Tauri 2 | `700-FRAMEWORKS.md` + `710-TAURI.md` | `OWNED` | host/layout contrôlé, capabilities/plugins, TS-RS, versions et gate framework possédés |
| skeleton Tauri contrôlé complet | étude `002-TAURI_SKELETON_DECISION.md` | `DEFER` | report durable jusqu'à matérialisation d'owners Web ; repris dans `ROADMAP.md` sans numéro de release |
| Web / Vite / TypeScript / Sass | aucun owner dédié en `0.0.5` | `DEFER` | ne pas créer de profils placeholders pour satisfaire le skeleton Tauri |
| Android/JNI Rust, distribution Games, architecture métier KSP | owners locaux ou preuves insuffisantes | `LOCAL/DEFER` | aucune aspiration dans PGR central |
La navigation durable pointe désormais vers les owners correspondant réellement aux décisions livrées. Les skeletons `001` et `002` restent composables ; aucun `003-TAURI...` n'est créé par anticipation. Les audits réutilisables restent opt-in ou sélectionnés par profil selon leur propriété, et aucune divergence historique des corpus n'est transformée rétroactivement en dette PGR.
Le `DEFER` Tauri est le seul travail différé de cette réconciliation suffisamment décidé pour être reporté explicitement dans la roadmap. Les trois axes plus larges identifiés pendant `alpha.8` restent des **candidats d'horizon**, pas des engagements : maturation de profils techniques composables, projet documentaire/spécification avec `saselang-bible` comme corpus pilote possible, et audit de généricité de PGR hors développement logiciel.
Cette réconciliation confirme que la mission de `0.0.5` est suffisamment fermée pour entrer en RC après la gate `beta.1`, sous réserve qu'aucune incohérence documentaire ou de navigation ne soit révélée par l'opérateur.

View File

@@ -0,0 +1,234 @@
<!-- file: docs/studies/002-TAURI_SKELETON_DECISION.md -->
<!-- version: 2 -->
# Décision de skeleton Tauri pour projets contrôlés
## Objet
Cette étude enregistre la décision `0.0.5-alpha.9` sur la matérialisation d'un skeleton Tauri pour les nouveaux projets que l'organisation contrôle.
Elle ne redéfinit pas les règles Tauri. Leur owner normatif reste [`../rules/710-TAURI.md`](../rules/710-TAURI.md). Le contrat des skeletons reste possédé par [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md).
## Corpus et état observé
Le corpus de réconciliation reste celui de `0.0.5` :
```text
KSP 0.3.16 6 hosts Tauri
Games 0.3.5 2 hosts Tauri
```
Les `8` hosts possèdent le même socle structurel :
```text
Cargo.toml
build.rs
package.json
tsconfig.json
tauri.conf.json
vite.config.ts
capabilities/
src/lib.rs
src/main.rs
src/tauri.rs
frontend/
```
Aucun des `8` hosts n'utilise `src-tauri/`. Tous utilisent Vite et TypeScript. Les `6` hosts KSP utilisent en plus Bootstrap et `sass-embedded`, tandis que les `2` POC Games ne constituent pas une preuve suffisante pour imposer ces deux choix au profil Tauri universel.
KSP apporte également l'usage éprouvé de TS-RS pour les structures Rust partagées avec le frontend. Cette frontière est déjà cadrée par `710-TAURI.md` pour les projets contrôlés.
Ces observations qualifient un **candidat de skeleton organisationnel** ; elles ne suffisent pas à créer des règles Web générales.
## Owners déjà suffisants
Les responsabilités suivantes ont un owner PGR matérialisé :
- gouvernance et composition des skeletons : `200`, `210`, `220` ;
- Rust/Cargo et skeleton Rust : `510` + `002-RUST_CARGO_WORKSPACE.md` ;
- plateformes déjà matérialisées lorsqu'elles s'appliquent, notamment Android : `610` ;
- host Tauri, capabilities, plugins, hooks, version produit et frontière Rust/frontend : `710`.
La partie native du candidat n'a donc pas besoin d'un nouveau propriétaire caché dans le skeleton.
## Owner manquant
PGR `0.0.5` ne possède aucun profil Web dédié pour :
- organisation des sources frontend ;
- TypeScript comme langage frontend ;
- Vite comme bundler/dev server ;
- Sass/CSS et ownership des sorties générées ;
- framework CSS généraliste tel que Bootstrap ;
- validation Web proportionnée et artefacts de build correspondants.
Créer immédiatement un skeleton qui configure ces éléments ferait du skeleton le propriétaire normatif implicite de la stack Web. Ce serait contraire au principe suivant : un skeleton sélectionne et compose des owners ; il ne remplace pas les owners manquants.
## Vérification externe Tauri 2
La documentation Tauri 2 courante confirme deux points utiles mais ne comble pas le manque d'owner Web :
- `create-tauri-app` fournit plusieurs choix frontend et Tauri peut aussi être ajouté manuellement à un frontend existant ; le layout standard `src-tauri/` est donc un scaffold supporté, pas une obligation conceptuelle pour les projets PGR contrôlés ;
- les documentations de plugins décrivent aussi l'installation explicite des dépendances Cargo, l'initialisation Rust, les bindings JavaScript lorsque nécessaires et les permissions/capabilities, ce qui reste compatible avec la convention PGR d'intégration explicite.
Références vérifiées le `2026-09-25` :
- <https://v2.tauri.app/start/create-project/>
- <https://v2.tauri.app/start/project-structure/>
- <https://v2.tauri.app/plugin/file-system/>
- <https://v2.tauri.app/learn/security/using-plugin-permissions/>
## Décision
Décision `alpha.9` :
```text
DEFER
```
PGR `0.0.5` **ne crée pas** de skeleton Tauri `003`.
Le report est intentionnel : le profil Tauri est suffisamment mûr, mais le skeleton complet ne peut pas encore être instancié sans absorber prématurément les responsabilités Web.
Ce `DEFER` ne remet pas en cause les conventions Tauri déjà normalisées dans `710-TAURI.md` et ne réouvre pas les décisions `alpha.6` à `alpha.8`.
## Candidat conservé
Lorsque les owners Web seront suffisants, le skeleton candidat pour une nouvelle baseline contrôlée devra réévaluer puis, si toujours justifié, composer :
```text
001-PROJECT_GOVERNANCE_FOUNDATION
+ 002-RUST_CARGO_WORKSPACE
+ profil Tauri 710
+ profils Web réellement applicables
```
Le candidat organisationnel conserve les choix suivants sans les promouvoir aujourd'hui en règles Web :
- host Cargo direct sans `src-tauri/` ajouté uniquement pour reproduire le scaffold standard ;
- `frontend/` pour les sources Web ;
- Vite + TypeScript ;
- Sass pour la chaîne de styles ;
- Bootstrap comme baseline de présentation lorsqu'un framework CSS généraliste est utile ;
- TS-RS pour les DTO Rust possédés par le host et partagés avec TypeScript ;
- `tauri.rs` comme owner de l'assemblage et des wrappers `#[tauri::command]` ;
- ajout explicite et revu des plugins, dépendances frontend et capabilities minimales ;
- WASM dans une unité séparée par défaut ;
- politique de versions classifiée `CANONICAL` / `MIRROR-EXACT` / `MIRROR-STABLE` selon les owners concernés.
## Conditions de sortie du report
Un futur plan MAY promouvoir ce candidat lorsqu'il existe au minimum des owners suffisants pour :
1. TypeScript et conventions Web contrôlées ;
2. Vite et ownership des commandes/dev server/build outputs ;
3. Sass/CSS et statut des artefacts générés ;
4. validation frontend indépendante de la validation Tauri ;
5. choix Bootstrap ou alternative clairement classifié comme décision de skeleton plutôt que règle Tauri.
Le futur travail devra alors réexaminer le corpus courant au lieu de supposer que les versions ou outils observés dans KSP/Games restent les bons choix.
## Hors scope
Cette décision ne :
- crée pas de profil Web placeholder ;
- réserve pas un numéro de release futur ;
- transforme pas Bootstrap en dépendance Tauri ;
- impose pas npm plutôt qu'un autre package manager ;
- intègre pas WASM dans le host ;
- migre KSP ou Games vers PGR ;
- modifie pas les règles Tauri déjà stabilisées.
## Réexamen de préparation 0.1.1-beta.1
Le `DEFER` décidé en `0.0.5-alpha.9` reste la décision active pendant `0.1.1`. La présente révision n'autorise ni création ni adoption d'un skeleton Tauri ; elle vérifie uniquement si les responsabilités Web dont l'absence motivait le report possèdent désormais des owners PGR suffisants pour que `0.1.4` puisse réexaminer le candidat sur des bases concrètes.
### Condition 1 — TypeScript et conventions Web contrôlées
Couverture disponible :
```text
docs/rules/530-TYPESCRIPT.md
docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md
templates/web-typescript/tsconfig.json
templates/web-typescript/package.json
docs/skeletons/003-WEB_FRONTEND.md
```
Le langage/type-check, les déclarations externes, le manifest minimal et les décisions laissées au projet ont désormais des owners explicites. TypeScript reste une recommandation `SHOULD`, pas une obligation Tauri universelle.
État de préparation : **couvert**.
### Condition 2 — Vite et ownership des commandes/dev server/build outputs
Couverture disponible :
```text
docs/rules/550-VITE.md
docs/templates/009-WEB_VITE.md
docs/validation/005-WEB_FRONTEND_VALIDATION.md
```
Le dev server, le cache, `build.outDir`, `publicDir`, les scripts et la frontière source/généré sont possédés sans imposer de `vite.config.ts`, layout, port ou `base` universel.
État de préparation : **couvert**.
### Condition 3 — Sass/CSS et statut des artefacts générés
Couverture disponible :
```text
docs/rules/560-CSS_SASS.md
docs/templates/010-WEB_CSS_SASS.md
docs/validation/005-WEB_FRONTEND_VALIDATION.md
```
CSS seul reste valide ; Sass est optionnel mais recommandé lorsque utile. Sources, compilation, outputs, entrypoints de packages et compatibilité `@import` sont distingués sans imposer Bootstrap ni un `main.scss` générique.
État de préparation : **couvert**.
### Condition 4 — validation frontend indépendante de la validation Tauri
Couverture disponible :
```text
docs/validation/005-WEB_FRONTEND_VALIDATION.md
docs/validation/001-VALIDATION_MATRIX.md
docs/skeletons/003-WEB_FRONTEND.md
```
Restore, type-check, styles, build et smoke navigateur sont classifiés indépendamment du host. Un `PASS` frontend ne vaut explicitement pas `PASS` Tauri.
État de préparation : **couvert**.
### Condition 5 — framework CSS classé comme décision de skeleton/projet
Couverture disponible :
```text
docs/rules/560-CSS_SASS.md
docs/templates/010-WEB_CSS_SASS.md
docs/skeletons/003-WEB_FRONTEND.md
```
Bootstrap, Tailwind CSS ou une alternative sont des choix locaux. Leur présence dans Games/KSP ne les élève pas en règle Tauri ni en règle Web universelle.
État de préparation : **couvert**.
### Conclusion de préparation
Les cinq conditions de sortie formulées en `0.0.5-alpha.9` possèdent désormais des owners PGR matérialisés et non redondants.
Cela change le diagnostic de préparation, pas la décision de skeleton :
```text
conditions Web requises couvertes
skeleton Tauri dans 0.1.1 toujours DEFER
réexamen autorisé 0.1.4
création automatique interdite
```
`0.1.4` devra réexaminer le corpus alors courant, les versions/outils réellement soutenus, le profil `710-TAURI.md` et la composition avec `003-WEB_FRONTEND.md`. Il pourra confirmer, modifier ou abandonner le candidat historique. La présente étude ne préjuge pas de cette décision.
Le candidat historique `frontend/ + Vite + TypeScript + Sass + Bootstrap + TS-RS` reste donc une observation à réexaminer, pas une baseline déjà approuvée. En particulier, `frontend/`, Vite, Sass et Bootstrap ne deviennent pas des obligations Tauri du seul fait que les owners permettant de les encadrer existent désormais.

View File

@@ -0,0 +1,163 @@
<!-- file: docs/studies/003-V0_1_0_HORIZON_REVIEW.md -->
<!-- version: 1 -->
# Revue d'horizon 0.1.0 — trajectoire d'adoption et owners techniques
## Objet
Cette étude matérialise la revue d'horizon obligatoire prévue par `0.1.0-beta.1`. Elle intervient après validation de la première baseline Rust/Cargo réutilisable et avant RC.
Elle ne cherche pas à remplir artificiellement la roadmap. Elle engage seulement les releases `0.1.x` dont le domaine, l'ordre et les prérequis sont suffisamment décidés à partir des owners PGR existants et des corpus Games/KSP déjà audités.
## État acquis à l'entrée
`0.1.0-alpha.5` a démontré deux propriétés nécessaires à une adoption réelle :
```text
NEW les templates Rust/Cargo peuvent instancier un workspace temporaire accepté par Cargo/rustfmt/Clippy
ADOPTION un workspace Rust existant peut conserver des décisions KEEP-LOCAL / DEFER sans copie destructive
```
Le contrat `230-ADOPTION.md` permet donc de migrer progressivement un dépôt réel sans attendre que PGR possède un owner pour chaque technologie rencontrée.
Les profils suivants existent déjà :
```text
510 Rust / Cargo
520 Java / Maven / Gradle
610 Android
710 Tauri 2
```
Le skeleton Tauri reste toutefois `DEFER` tant que les owners Web requis par `002-TAURI_SKELETON_DECISION.md` ne sont pas matérialisés.
## Pression des corpus
### Games
La baseline Games fournie exerce déjà plusieurs domaines distincts :
- Rust/Cargo ;
- frontend Web avec TypeScript, Vite et Sass/CSS ;
- Java/Gradle ;
- Android/JNI/SDL ;
- Tauri ;
- WASM dans certains chemins ;
- trajectoire serveur future, mais sans implémentation Actix Web autoritaire suffisante dans le corpus audité.
Games possède déjà une future release locale `0.3.7` destinée à l'alignement PGR. PGR doit donc préparer rapidement les owners réellement nécessaires sans absorber tout le dépôt Games dans une seule release PGR.
### KSP
KSP exerce principalement Rust/Cargo et plusieurs applications Tauri. Son adoption ne doit pas attendre Java, Android, WASM ou un profil serveur qui ne lui sont pas nécessaires.
L'ordre retenu reste Games avant KSP, afin que la première adoption large fournisse un retour d'expérience avant la migration du second corpus.
## Releases `0.1.x` engagées
### `0.1.1` — fondation frontend Web
Domaine : Web frontend contrôlé.
Scope attendu :
- owner(s) TypeScript applicables ;
- Vite et contrat dev/build outputs ;
- Sass/CSS et statut des artefacts générés ;
- package manager et lockfile classifiés sans imposer arbitrairement npm ;
- validation frontend indépendante du host Tauri ;
- templates/skeletons/audits uniquement lorsqu'un besoin réutilisable est démontré.
Games est le corpus principal. Cette release ne crée pas le skeleton Tauri, n'intègre pas WASM et ne normalise pas encore un serveur Rust.
### `0.1.2` — réévaluation Java / Gradle
Domaine : Java et build Gradle génériques.
Le profil `520-JAVA_MAVEN_GRADLE.md` existe déjà. La release doit le confronter à Games, séparer ce qui appartient à Java/Gradle de ce qui appartient à Android, puis créer uniquement les templates, validations ou audits génériques manquants.
### `0.1.3` — réévaluation Android
Domaine : Android.
Le profil `610-ANDROID.md` existe déjà. La release doit l'éprouver sur le corpus Games, notamment autour du projet Gradle Android, des wrappers Java/JNI, des ressources et du packaging, sans transférer dans PGR les choix propres à un jeu ou à SDL lorsqu'ils ne sont pas génériques.
### `0.1.4` — Tauri contrôlé
Domaine : Tauri.
Cette release réexamine formellement le `DEFER` actuel après `0.1.1`. Le skeleton Tauri contrôlé n'est matérialisé que si les conditions de sortie de `002-TAURI_SKELETON_DECISION.md` sont réellement satisfaites par les owners Web alors disponibles.
Si ces conditions ne sont pas satisfaites, la release conserve explicitement le `DEFER` et REPLAN la suite au lieu de fabriquer un skeleton incomplet.
### `0.1.5` — adoption de Games
Domaine : adoption réelle de `sasedev-games`.
Utiliser `230-ADOPTION.md` et `007-EXISTING_PROJECT_ADOPTION.md` pour établir la baseline autoritaire, mapper les owners PGR applicables et découper la migration. Les domaines non encore possédés par PGR peuvent rester `KEEP-LOCAL` ou `DEFER` ; l'adoption ne doit pas créer une obligation de normaliser WASM ou le serveur uniquement pour obtenir un statut global artificiel.
### `0.1.6` — adoption de KSP
Domaine : adoption réelle de `khadhroony-solana-project`.
La pression principale attendue est Rust/Cargo + Tauri. La migration réutilise le retour d'expérience de Games et ne doit pas attendre les profils Java/Android/WASM/serveur non applicables.
### `0.1.7` — audits Rust/Clippy statiques Python
Domaine : prévalidation Rust dans un environnement Python-only.
Cette release reste volontairement après les deux adoptions afin de dériver les contrôles de conventions réellement utiles observés dans PGR, Games et KSP.
Les scripts :
- sont read-only et non interactifs ;
- fonctionnent sans Cargo ni `rustc` ;
- réutilisent les options Rust/Clippy possédées par PGR au lieu d'inventer une politique parallèle ;
- documentent chaque contrôle comme `FULL`, `LIMITED` ou `UNSUPPORTED` ;
- ne présentent jamais un `PASS` Python comme équivalent à `cargo clippy PASS`.
## Candidats laissés sans numéro
### WASM
Le corpus Games exerce WASM, mais la valeur d'un owner PGR séparé doit être confirmée pendant `0.1.5`. Aucun numéro n'est réservé maintenant.
### Serveur Web Rust
Actix Web ou une alternative reste un candidat à partir d'un corpus d'implémentation réel. La présence d'une trajectoire HTTP/3/WebTransport dans un roadmap projet ne suffit pas à normaliser aujourd'hui un framework serveur.
### Projets documentaires et généricité hors logiciel
`saselang-bible` reste un bon corpus futur pour tester PGR sur un projet documentaire/spécification. Cet axe, ainsi que la généricité hors logiciel, reste orienté vers une trajectoire `0.2.x` / `0.3.x` à décider ultérieurement.
### Déploiement et exploitation
Une future famille majeure devra traiter de manière composable les responsabilités de déploiement et d'exploitation : reverse proxy Nginx/Apache, PostgreSQL/MySQL ou autres bases, Docker/Compose, services Linux, environnements/secrets, migrations, backup/restore, health, observabilité et skeletons/audits de déploiement.
Un horizon `0.4.x` ou `0.5.x` est plausible, mais aucun numéro précis n'est réservé tant que les séries intermédiaires n'ont pas déterminé le découpage réel.
## Décision sur Tauri
La décision `DEFER` de `002-TAURI_SKELETON_DECISION.md` reste vraie pendant `0.1.0`.
La roadmap engage `0.1.4` comme release de domaine Tauri, pas comme autorisation anticipée de créer le skeleton. Son premier devoir sera de vérifier que `0.1.1` a effectivement fourni les owners Web nécessaires.
## Prochaine cible
La prochaine release PGR après publication de `0.1.0` est :
```text
0.1.1 — fondation frontend Web
```
Le prompt `prompts/007-V0_1_1_START_PROMPT.md` est donc préparé pendant `beta.1`, mais ne doit être exécuté qu'après stable `v0.1.0` et vérification post-tag `PASS`.
## Critère de réouverture de la revue
Une nouvelle revue macro est requise si :
- `0.1.1` révèle que le domaine Web doit être scindé avant de pouvoir servir Tauri ;
- Games ne peut pas être adopté avec `KEEP-LOCAL` / `DEFER` sans owner WASM ou serveur supplémentaire ;
- `0.1.4` ne peut pas lever le `DEFER` Tauri ;
- l'ordre Games puis KSP cesse d'être rationnel à cause d'une dépendance technique nouvellement démontrée ;
- une release engagée perd son besoin réel ou doit être remplacée par une autre responsabilité.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/templates/001-RUST_CARGO_TOOLING.md -->
<!-- version: 3 -->
<!-- version: 4 -->
# Templates d'outillage Rust/Cargo
@@ -33,6 +33,8 @@ Adapter le header `# file:` de chacun à son nouveau chemin relatif. Comme il s'
Le chemin de sortie sous `builds/` est externe au dépôt source ; il ne doit pas être inclus dans les archives du projet. Si l'environnement impose un autre emplacement, ajuster la configuration du projet au lieu de copier un chemin machine depuis KSP ou Games.
Dans un projet existant, ces fichiers sont des références de comparaison. `rustfmt.toml`, `clippy.toml` ou `.cargo/config.toml` déjà présents MUST être comparés avant remplacement ; une différence locale peut rester `KEEP-LOCAL`, devenir un `OVERRIDE` explicite ou rester `DEFER` conformément à [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md). L’adoption n’exige pas une copie byte-for-byte des templates PGR.
## Validation dans un projet Rust
Après adaptation, les contrôles utiles dépendent du code et des manifests effectivement présents :

View File

@@ -1,5 +1,5 @@
<!-- file: docs/templates/002-CARGO_MANIFESTS.md -->
<!-- version: 1 -->
<!-- version: 4 -->
# Modèles de manifests Cargo workspace et crate membre
@@ -9,6 +9,8 @@ Le [manifest racine](../../templates/rust-cargo/Cargo.toml) est celui d'un works
Ces modèles prolongent les trois configurations de [`001-RUST_CARGO_TOOLING.md`](001-RUST_CARGO_TOOLING.md). Le propriétaire des choix normatifs reste [`510-RUST_CARGO.md`](../rules/510-RUST_CARGO.md). Les chemins `project-core-lib`, le nom du package et la version `0.1.0` sont des **valeurs d'exemple à remplacer** : cette version ne reflète pas `VERSION` de PGR et ne définit pas la version d'un autre projet.
Pour un projet existant, ne pas remplacer le manifest racine ou les manifests membres uniquement parce qu’ils diffèrent des exemples PGR. Les héritages, noms, membres, lints, métadonnées et dépendances sont d’abord comparés selon [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md), puis classifiés `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`. Le dry-run de [`../validation/004-RUST_CARGO_BASELINE_DRY_RUN.md`](../validation/004-RUST_CARGO_BASELINE_DRY_RUN.md) exerce séparément ce chemin non destructif.
## Adopter le manifest racine
Copier `templates/rust-cargo/Cargo.toml` vers `Cargo.toml` du projet, corriger son header `# file:` et commencer sa propre révision de fichier à `1`. Adapter `members` aux répertoires qui existent effectivement, puis choisir la version canonique de l'unité de release. Lorsque toutes les crates partagent une seule release, aligner `[workspace.package].version` sur le `VERSION` de ce projet ; plusieurs unités de release indépendantes ne doivent pas hériter d'une version fictive commune.
@@ -23,11 +25,17 @@ Les trois lints Rust et les `18` niveaux Clippy reprennent la politique partagé
## Adopter le manifest membre
Copier le membre vers `crates/<nom>/Cargo.toml`, adapter `name`, son chemin dans `members` et le header `# file:`. `version.workspace = true`, `edition.workspace = true` et `publish.workspace = true` rendent visibles les héritages choisis ; ajouter séparément `license.workspace = true`, `repository.workspace = true` ou `authors.workspace = true` si les valeurs existent à la racine et concernent cette crate. `[lints] workspace = true` est requis pour reprendre les niveaux du workspace : leur présence à la racine ne suffit pas à les appliquer automatiquement aux membres.
Copier le membre vers `crates/<nom>/Cargo.toml`, adapter `name`, son chemin dans `members` et le header `# file:`. Pour un nouveau projet contrôlé, `<nom>` commence par le nom court ou l'abréviation canonique du projet et rend lisibles la responsabilité puis le rôle/cible utiles, conformément à [`510-RUST_CARGO.md`](../rules/510-RUST_CARGO.md). Ne pas conserver `project-core-lib` comme nom réel et ne pas ajouter un suffixe uniquement par symétrie. `version.workspace = true`, `edition.workspace = true` et `publish.workspace = true` rendent visibles les héritages choisis ; ajouter séparément `license.workspace = true`, `repository.workspace = true` ou `authors.workspace = true` si les valeurs existent à la racine et concernent cette crate. `[lints] workspace = true` est requis pour reprendre les niveaux du workspace : leur présence à la racine ne suffit pas à les appliquer automatiquement aux membres.
Le bloc `[dependencies]` vide se remplit selon les besoins de la crate. Pour une dépendance déjà déclarée sous `[workspace.dependencies]`, utiliser localement `nom = { workspace = true }`, avec `features = [...]` au besoin. Pour une dépendance strictement locale, choisir sa contrainte directement dans ce membre ; aucune liste tierce arbitraire n'est copiée par ce modèle.
Une application binaire peut reprendre les mêmes héritages après adaptation du nom, du layout et de sa cible `src/main.rs` ; ne pas fabriquer un deuxième manifest quasi identique. Une crate à version ou politique de publication réellement indépendante doit déclarer ses valeurs locales et ne plus hériter ces champs par automatisme.
Pour une nouvelle baseline contrôlée, une bibliothèque réutilisable et son exécutable sont normalement deux packages Cargo distincts. Le package binaire peut reprendre les mêmes héritages de workspace, mais son manifest est légitime parce qu'il exprime une frontière de packaging et de dépendances différente : il dépend des crates `-lib`, conserve un `main.rs` mince et porte un nom révélant son rôle (`-cli`, `-desk`, `-worker`, `-job`, `-server`, etc.) lorsque ce classificateur est réellement applicable. Ne pas fusionner `lib` + `bin` dans un seul package uniquement pour éviter un manifest membre supplémentaire.
Une paire `*-api` / `*-lib` n'est créée que si un vrai contrat séparé le justifie. Une crate `-api` purement déclarative ne reçoit normalement ni subscriber global ni dépendance vers la crate de logging. Une crate `-lib` unique suffit lorsqu'il n'existe qu'une implémentation utile et aucune frontière d'extension/backend/lifecycle.
Tauri est une exception framework documentée par [`710-TAURI.md`](../rules/710-TAURI.md) : son host peut être un package mixte `lib + bin`, mais les deux targets doivent alors posséder des noms distincts selon le contrat Tauri.
Une crate à version ou politique de publication réellement indépendante doit déclarer ses valeurs locales et ne plus hériter ces champs par automatisme.
## Exception locale de lints

View File

@@ -1,24 +1,25 @@
<!-- file: docs/templates/003-NEW_SESSION_PROMPT.md -->
<!-- version: 1 -->
<!-- version: 2 -->
# Spécification du prompt manuel de nouvelle session
## Usage
Cette spécification sert à préparer un court message de reprise après une stable publiée. Le prompt de démarrage propre à la version suivante reste un fichier `prompts/NNN-VX_Y_Z_START_PROMPT.md` finalisé selon [`210-WORKFLOW.md`](../rules/210-WORKFLOW.md). Le message manuel indique où commencer et quelles preuves fournir ; il ne copie ni ce prompt, ni le plan, ni le history de la release.
Cette spécification sert à préparer le court message opérateur remis après une stable publiée. Le prompt de démarrage propre à la version suivante reste un fichier `prompts/NNN-VX_Y_Z_START_PROMPT.md` finalisé selon [`210-WORKFLOW.md`](../rules/210-WORKFLOW.md). Le message manuel indique où commencer et quelles preuves fournir ; il ne copie ni ce prompt, ni le plan, ni le history de la release.
La comparaison des prompts PGR `002` et `003` montre une structure récurrente (baseline taggée, cible, première tranche et mission). `003` ajoute le rapport de vérification post-tag et un texte transmis explicitement à l'opérateur. Une forme courte commune réduit les oublis lors de la clôture suivante, sans rendre obligatoires des champs propres à PGR dans les autres projets.
Lorsque la cible suivante est connue et que la vérification post-tag applicable est terminée, ce message doit être remis spontanément à l'opérateur sans attendre qu'il le réclame. Lorsque la cible suivante n'est pas suffisamment décidée, PGR ne fabrique pas de version ou de prompt : le message de clôture indique que l'horizon reste ouvert et pointe vers le handoff ou la revue d'horizon applicable.
## Champs à renseigner
1. **Baseline** : identifier le tag stable, le nom réel de l'archive source téléchargée depuis ce tag et la forge d'origine. Une archive sans `.git` demande une vérification interne ; elle ne prouve pas à elle seule le commit du tag.
2. **Preuve post-tag** : si un rapport de publication/vérification distinct existe et est réellement `PASS`, indiquer son chemin exact et le joindre. Sinon, signaler explicitement qu'il est absent ou que son état n'est pas `PASS` ; ne jamais fabriquer cette preuve ni la confondre avec le tag.
1. **Baseline** : identifier le tag stable, le nom réel de l'archive source téléchargée depuis ce tag et la forge d'origine. Une archive sans `.git` est normale pour une archive de tag et se vérifie par sa cohérence interne ; elle ne porte pas elle-même les métadonnées Git du dépôt.
2. **Preuve post-tag** : si un rapport de publication/vérification distinct existe et est réellement `PASS`, indiquer son chemin exact et demander qu'il soit fourni avec l'archive. Sinon, signaler explicitement son état réel ; ne jamais fabriquer cette preuve ni la confondre avec le tag.
3. **Contrat de reprise** : indiquer le chemin du prompt `prompts/NNN-VX_Y_Z_START_PROMPT.md` existant dans la baseline, la version cible et la première tranche attendue. Le prompt versionné possède la mission détaillée et le scope de la release.
4. **Intake** : demander la vérification de l'archive, des règles applicables, de la gouvernance, de la structure documentaire et des deltas/histories avant de préparer la première tranche. Adapter la liste aux artefacts effectivement présents et aux risques du projet.
5. **Horizon ouvert** : si aucune version suivante n'est encore suffisamment décidée, remplacer le contrat de reprise de version par l'instruction exacte de revue/handoff applicable ; ne pas inventer un `NEXT` artificiel.
## Forme à remplir et à remettre
Après vérification des chemins et de l'état réel du rapport, écrire **une seule phrase** adaptée au projet. Si le rapport est `PASS` et fourni :
Après vérification des chemins et de l'état réel du rapport, écrire **une seule phrase** adaptée au projet lorsque la cible suivante est connue. Si le rapport est `PASS` et fourni :
```text
Partir de l'archive <nom exact du ZIP issu du tag vX.Y.Z> et du rapport post-tag <chemin exact du rapport PASS>. Lire et exécuter <chemin du prompt de démarrage dans la baseline>. Vérifier l'archive, les règles, la gouvernance, la structure documentaire, les deltas/histories et la cohérence globale avant de préparer <version cible-alpha.1>.
@@ -26,4 +27,6 @@ Partir de l'archive <nom exact du ZIP issu du tag vX.Y.Z> et du rapport post-tag
Si le rapport est absent ou non validé, retirer « et du rapport post-tag ... » de la phrase et préciser séparément son état réel à la nouvelle session. Conserver les noms exacts de la forge et des fichiers du projet : la forme `<nom exact du ZIP>` n'est qu'un champ de rédaction.
Rédiger le texte manuel à la clôture après le contrôle de l'archive publiée et le remettre à l'opérateur. Une interruption au milieu d'une prerelease suit le mécanisme de reprise de la tranche courante prévu dans `210-WORKFLOW.md` ; elle ne crée pas artificiellement un nouveau prompt de version.
Si l'horizon est ouvert, remettre plutôt une consigne courte qui identifie la stable publiée, les preuves disponibles et le handoff/revue d'horizon à reprendre. Cette consigne ne doit contenir ni numéro de version hypothétique, ni faux prompt de démarrage.
Une interruption au milieu d'une prerelease suit le mécanisme de reprise de la tranche courante prévu dans `210-WORKFLOW.md` ; elle ne crée pas artificiellement un nouveau prompt de version.

View File

@@ -0,0 +1,80 @@
<!-- file: docs/templates/004-FILE_FAMILY_CONTRACTS.md -->
<!-- version: 2 -->
# Pattern — contrats locaux de fichiers ou familles
## Objectif
Ce pattern aide un projet à expliciter quelques responsabilités de fichiers ou familles durables lorsqu'elles deviennent difficiles à déduire de l'arborescence, de la toolchain ou des règles déjà existantes.
Il complète le contrat documentaire de [`../rules/300-DOCUMENTATION.md`](../rules/300-DOCUMENTATION.md). Il n'impose aucun fichier particulier au projet destinataire.
## Quand l'utiliser
Créer un registre local seulement lorsqu'il réduit une ambiguïté réelle, par exemple lorsque :
- plusieurs familles voisines ont des rôles différents qui provoquent régulièrement des erreurs de placement ;
- un fichier est une source de vérité tandis qu'un autre est généré ou dérivé ;
- une famille possède une règle de modification ou de synchronisation non évidente ;
- des contributeurs doivent savoir quel owner modifier sans relire plusieurs documents spécialisés.
Ne pas l'utiliser pour inventorier chaque fichier d'un petit dépôt, recopier les rôles standards déjà décrits par PGR ou dupliquer un manifeste/build system qui possède déjà l'information.
## Forme minimale
Le nom et l'emplacement appartiennent au projet destinataire. `docs/rules/FILE_CONTRACTS.md` est un nom possible, pas une convention PGR obligatoire.
Une entrée utile contient au minimum :
```text
file or family
responsibility
modification rule
```
Lorsque ces informations sont utiles, le projet MAY ajouter :
```text
source of truth / generated status
local owner or reference
validation or synchronization requirement
```
Une table Markdown convient aux registres structurés :
```markdown
| Fichier ou famille | Responsabilité | Règle de modification |
|---------------------|------------------|----------------------------|
| `<path-or-pattern>` | `<rôle durable>` | `<quand/comment modifier>` |
```
Une liste courte est préférable lorsqu'elle reste plus lisible. La forme n'est pas normative ; la clarté de la responsabilité l'est pour le projet qui choisit d'adopter ce contrat.
## Règles d'adaptation
Lors de l'instanciation :
1. sélectionner uniquement les fichiers ou familles dont le contrat local apporte une information non évidente ;
2. référencer l'owner détaillé existant au lieu de recopier ses règles ;
3. regrouper les chemins qui partagent réellement le même contrat plutôt que créer une entrée par fichier ;
4. distinguer explicitement source de vérité et artefact généré lorsque cette distinction existe ;
5. supprimer ou fusionner une entrée devenue redondante lorsque son rôle est désormais évident ailleurs.
Le registre SHOULD évoluer lorsqu'une responsabilité ou règle de modification change réellement. Il SHOULD NOT être modifié uniquement parce qu'un nouveau fichier respecte déjà une famille décrite.
## Exemple abstrait
```markdown
| Fichier ou famille | Responsabilité | Règle de modification |
|--------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| `config/*.example` | Décrire les exemples versionnés de configuration locale. | Mettre à jour lorsqu'une option utilisateur versionnée est ajoutée ou retirée ; ne jamais y placer de secret réel. |
| `generated/**` | Contenir les sorties reconstruisibles produites par la toolchain choisie. | Ne pas modifier manuellement ; régénérer depuis la source de vérité documentée. |
```
Cet exemple illustre la forme uniquement. Il ne crée aucune règle universelle sur les chemins `config/` ou `generated/`.
## Critère de sortie
Le pattern est utile si un nouveau contributeur peut déterminer plus vite où une responsabilité vit et quand modifier une famille sans devoir maintenir un catalogue parallèle du dépôt.
S'il ajoute davantage de cérémonie que d'information, ne pas l'instancier ou le retirer.

85
docs/templates/005-RELEASE_PLAN.md vendored Normal file
View File

@@ -0,0 +1,85 @@
<!-- file: docs/templates/005-RELEASE_PLAN.md -->
<!-- version: 1 -->
# Pattern — plan de release
## Usage
Ce pattern aide un projet gouverné par PGR à construire un plan de release suffisamment précis pour piloter plusieurs tranches sans transformer le plan en journal d'activité. Il complète `alpha.1` et [`210-WORKFLOW.md`](../rules/210-WORKFLOW.md) ; il n'impose ni le titre exact des sections, ni un nombre fixe de prereleases.
Un petit changement qui ne nécessite pas de plan dédié n'a pas à instancier ce pattern.
## Contrat minimal
Un plan utile doit permettre de comprendre :
- d'où part la release et quelle mission elle doit rendre vraie ;
- ce qui est acquis, ouvert, inclus et explicitement hors-scope ;
- comment les risques, validations et smokes importants seront traités ;
- comment le travail est découpé actuellement et quels signaux imposeraient un REPLAN ;
- **où et quand la release sera clôturée** : documentation durable, `CHANGELOG`, `ROADMAP`, prompt/handoff suivant, plan et publication ;
- si l'horizon de roadmap doit être revu avant la fermeture et, si oui, à quel moment ou selon quel déclencheur.
## Forme candidate
```markdown
# Plan X.Y.Z — <mission courte>
## Statut et sources
Baseline, prompt, rapports ou corpus réellement autoritaires.
## Mission
Résultat attendu de la release.
## État acquis et questions ouvertes
Décisions déjà établies et points qui doivent encore être instruits.
## Scope et hors-scope
Frontières fonctionnelles, techniques et documentaires.
## Stratégie de validation
Gates, smokes et preuves importantes ; renvois vers la matrice plutôt que copie exhaustive.
## Trajectoire prévisionnelle
Responsabilité attendue de chaque tranche. Le forecast reste révisable.
## Déclencheurs de REPLAN
Signaux qui obligeraient à recalculer le travail restant.
## Clôture et transition
- réconciliation documentaire durable : <tranche/moment> ;
- entrée CHANGELOG candidate/finale : <tranche/moment> ;
- revue/mise à jour ROADMAP : <tranche/moment> ;
- prompt ou handoff de reprise : <tranche/moment ou cible encore ouverte> ;
- fermeture du plan : <tranche/moment> ;
- promotion stable et vérification post-tag : <mécanisme>.
## Revue d'horizon
- état : <non nécessaire / requise / horizon volontairement ouvert> ;
- raison : <pourquoi> ;
- moment ou déclencheur : <quand> ;
- sorties autorisées : <étendre / laisser ouvert / différer-pause / objectif accompli>.
```
## Règles d'adaptation
Le plan doit rester proportionné. Une responsabilité déjà possédée par une règle, une matrice ou une étude est référencée plutôt que recopiée. Les résultats détaillés des gates restent dans `history/`.
La rubrique `Clôture et transition` est un contrat d'attribution des responsabilités, pas l'obligation d'exécuter tous les travaux en fin de release. Une documentation directement liée à une fonctionnalité continue d'évoluer dans la tranche qui la modifie.
La rubrique `Revue d'horizon` peut simplement indiquer qu'aucune revue n'est nécessaire parce que la roadmap s'étend déjà suffisamment. Si la prochaine version n'est pas décidée, cette rubrique doit l'assumer explicitement plutôt que fabriquer une roadmap.
PGR n'impose pas un journal de révisions systématique dans le plan. Un REPLAN met à jour les parties devenues fausses et le delta/history correspondant conserve la preuve du changement.
## Critère de sortie
Le plan est prêt lorsqu'il autorise le développement sans laisser ambiguës les responsabilités de fermeture, les validations majeures ni le devenir de l'horizon macro. Après stable, abandon ou supersession, il devient une référence historique de la release.

View File

@@ -0,0 +1,126 @@
<!-- file: docs/templates/006-OPERATOR_COMMAND_HANDOFF.md -->
<!-- version: 1 -->
# Pattern — handoff des commandes opérateur
## Usage
Ce pattern matérialise la sortie opérateur exigée par [`210-WORKFLOW.md`](../rules/210-WORKFLOW.md) après production d'un history et pendant une clôture stable. Son objectif est d'éviter que l'opérateur doive demander séparément quelles commandes exécuter entre le history reçu, son commit, le delta suivant et, pour une stable, le tag puis la vérification post-tag.
Le pattern est un guide de rendu : `210-WORKFLOW.md` reste l'owner normatif.
## Informations à résoudre avant le rendu
Le générateur doit déterminer depuis les preuves disponibles :
```text
project
X.Y.Z
tranche courante
statut du history
archive history réellement livrée
message de commit attendu
remote Git établi
branche Git établie
delta/fix suivant déjà livré ou non
stable obtenue ou non
tag canonique attendu
forge/archive post-tag applicable
preuve publish.* attendue ou non
```
Une valeur non établie ne doit pas être inventée. Si le remote ou la branche manque, le rendu peut d'abord fournir une commande de découverte telle que `git remote -v` ou `git branch --show-current`, puis demander d'utiliser la valeur réellement observée ; il ne doit pas transformer silencieusement un exemple `origin/master` en règle universelle.
## Fermeture d'une tranche non stable
Lorsque le history est livré sous forme de ZIP et que remote/branche sont établis, le bloc remis suit cette forme :
```bash
unzip -o <project>-<X.Y.Z>-<tranche>.history.zip -d .
git add -A
git diff --cached --check
git status --short
git commit -m "<message attendu>"
git push <remote> <branche>
```
Si le delta suivant ou le fix est déjà livré dans la même réponse, son application est affichée **après** le bloc de commit/push :
```bash
unzip -o <archive delta suivante>.delta.zip -d .
```
L'ordre visuel du rendu doit refléter l'ordre autorisé : history → commit/push → delta suivant.
## Tranche échouée suivie d'un fix
Un `FAIL`, `PARTIAL` ou `BLOCKED` est d'abord committé avec l'identité de la tranche observée, puis le fix est appliqué. Exemple générique :
```bash
unzip -o <project>-<X.Y.Z>-alpha.2.history.zip -d .
git add -A
git diff --cached --check
git status --short
git commit -m "X.Y.Z-alpha.2"
git push <remote> <branche>
unzip -o <project>-<X.Y.Z>-alpha.2.fix.1.delta.zip -d .
```
Le history `FAIL` n'est jamais remplacé par le futur `PASS` du fix.
## Première clôture qui établit réellement la stable
Quand `rel.N[/fix.M]` obtient le premier `PASS` stable, le commit porte l'identité produit :
```bash
unzip -o <project>-<X.Y.Z>-<rel.N[/fix.M]>.history.zip -d .
git add -A
git diff --cached --check
git status --short
git commit -m "X.Y.Z"
git push <remote> <branche>
```
Le tag vient ensuite. Si la politique locale utilise un tag annoté, le bloc type est :
```bash
git status --short
git rev-parse HEAD
git tag -a vX.Y.Z -m "vX.Y.Z"
git push <remote> vX.Y.Z
git rev-list -n 1 vX.Y.Z
git ls-remote --exit-code --tags <remote> refs/tags/vX.Y.Z
git ls-remote <remote> 'refs/tags/vX.Y.Z^{}'
```
Pour un tag annoté, `refs/tags/vX.Y.Z` peut identifier l'objet tag et différer du SHA du commit. La référence déréférencée `refs/tags/vX.Y.Z^{}` est celle qui doit être comparée au commit stable.
Si le projet utilise volontairement une autre forme de tag, le bloc est adapté à cette politique au lieu d'imposer `git tag -a`.
## Remise nécessaire pour `publish.*`
Après création/push du tag et génération de l'archive par la forge, le générateur indique explicitement ce qu'il attend. Pour le cas source-archive usuel :
```text
1. télécharger depuis la forge le ZIP correspondant exactement au tag vX.Y.Z ;
2. fournir ce ZIP au générateur ;
3. fournir les sorties Git du commit/tag local et distant exécutées ci-dessus ;
4. fournir toute preuve de publication supplémentaire exigée localement.
```
Le générateur vérifie alors l'archive publiée, calcule son empreinte dans son propre environnement lorsque possible et produit le rapport `publish.*` à partir des observations réelles. Le rapport reste extérieur au tag qu'il vérifie.
## Après `publish.* PASS`
Si une version suivante est déjà décidée et son prompt existe dans la stable, le générateur remet automatiquement la phrase de nouvelle session définie par [`003-NEW_SESSION_PROMPT.md`](003-NEW_SESSION_PROMPT.md), avec les noms réels du ZIP taggé, du rapport post-tag et du prompt versionné.
Si l'horizon reste ouvert, il remet à la place le handoff ou la consigne de revue d'horizon applicable sans inventer de prochaine version.
## Critère de qualité
Le handoff est correct lorsque l'opérateur peut passer du history reçu au commit, au delta suivant ou à la publication sans devoir deviner une commande, un message de commit, un ordre d'application ou un artefact à fournir, tout en conservant explicites les valeurs Git qui ne sont pas encore établies.

View File

@@ -0,0 +1,97 @@
<!-- file: docs/templates/007-EXISTING_PROJECT_ADOPTION.md -->
<!-- version: 1 -->
# Pattern — adoption PGR d’un projet existant
## Usage
Ce pattern aide à préparer une adoption PGR sur un dépôt existant conformément à [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md). Il n’est pas un manifest obligatoire, un générateur de migration ni un remplacement du plan de release local.
Il peut être instancié comme étude, plan, tableau de décision ou section d’un document existant si le projet a besoin d’une trace durable. Un petit alignement dont les décisions sont évidentes MAY rester directement documenté dans le delta et le history correspondants.
## Baseline autoritaire
Consigner uniquement ce qui est réellement établi :
```text
repository / archive : <source>
commit / tag : <si connu>
version : <si applicable>
validation connue : <preuves déjà acquises et encore pertinentes>
```
Ne pas reconstruire une baseline à partir d’hypothèses ou d’une version plus récente de PGR.
## Inventaire utile
Identifier les éléments qui déterminent l’applicabilité :
- gouvernance et workflow déjà présents ;
- langages et build systems réellement utilisés ;
- plateformes et frameworks présents ;
- validations et scripts existants ;
- contraintes locales ou historiques à préserver ;
- profils PGR sans rapport avec le dépôt, explicitement hors scope si leur confusion est probable.
## Mapping d’adoption
La classification canonique est `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`. La forme exacte du mapping reste libre. Une table courte peut suffire :
```text
Owner / contrat État local Décision Action / justification
-------------------- ---------------- ------------ -----------------------
<RULE/PGR owner> <état observé> ADOPT <migration ciblée>
<contrat local> <état observé> KEEP-LOCAL <raison>
<RULE/PGR owner> <état observé> OVERRIDE <scope + raison>
<RULE/PGR owner> <état observé> DEFER <prérequis / déclencheur>
```
Les quatre décisions ont le sens normatif défini par `230-ADOPTION.md`. Ne pas créer une cinquième catégorie uniquement pour éviter de décider si un point est adopté, local, overridé ou différé.
## Découpage de migration
Pour chaque tranche réellement nécessaire, préciser :
```text
scope : <owners / fichiers / contrats concernés>
hors scope : <domaines laissés intacts>
risque principal : <ce qui pourrait être cassé>
preuve : <gate proportionnée>
```
Le découpage SHOULD favoriser des changements vérifiables indépendamment. Une migration ne doit pas embarquer une technologie future uniquement parce qu’un profil PGR existe.
## Historique et compatibilité
Noter les conventions qui commencent au point d’adoption et les snapshots historiques qui doivent rester inchangés.
Exemples :
```text
- ancienne nomenclature de tags conservée avant <point d’adoption> ;
- anciennes règles locales conservées dans les histories ;
- nouvelle convention appliquée uniquement aux prochaines tranches ;
- dette héritée documentée mais non réécrite rétroactivement.
```
## Validation de sortie
L’adoption du scope est prête lorsque :
- chaque owner candidat du scope est classifié ;
- les changements `ADOPT` sont réellement appliqués ;
- les `KEEP-LOCAL` et `OVERRIDE` sont compréhensibles et possédés localement ;
- les `DEFER` ont un motif et restent hors du résultat présenté comme terminé ;
- les validations nécessaires ont réussi ;
- le projet reste autonome par rapport au dépôt PGR.
## Limites
Ce pattern ne décide pas à la place du projet :
- quels profils sont applicables ;
- si Games, KSP ou un autre dépôt doit migrer maintenant ;
- si une règle locale doit devenir une règle PGR générale ;
- si une migration doit occuper une ou plusieurs releases.
Ces décisions appartiennent au contexte réel du projet et à son plan actif.

View File

@@ -0,0 +1,154 @@
<!-- file: docs/templates/008-WEB_TYPESCRIPT_PACKAGE.md -->
<!-- version: 2 -->
# Templates de package Web TypeScript
## Rôle
Cette spécification accompagne les deux fichiers copiables :
- [`package.json`](../../templates/web-typescript/package.json) ;
- [`tsconfig.json`](../../templates/web-typescript/tsconfig.json).
Ils constituent une baseline **minimale** pour une application frontend TypeScript privée. Ils ne constituent ni un projet complet, ni un skeleton Web, ni un choix de Vite, Sass, framework UI ou package manager.
Les owners normatifs restent [`530-TYPESCRIPT.md`](../rules/530-TYPESCRIPT.md) et [`540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md`](../rules/540-JAVASCRIPT_PACKAGE_ECOSYSTEM.md).
## Pourquoi les templates restent minimaux
PGR ne possède pas encore, à ce niveau générique, les décisions suivantes :
```text
package manager concret
version du package manager
version TypeScript
target ECMAScript
module / moduleResolution
lib / types
framework frontend
Vite ou autre bundler
Sass ou CSS direct
layout source final
aliases
WASM
host Tauri ou autre
```
Les templates MUST donc rester parsables sans figer arbitrairement ces choix.
`package.json` et `tsconfig.json` n'acceptent pas un header commentaire PGR sans sortir de leur grammaire standard. Leur chemin et leur rôle sont donc possédés par le présent document plutôt que par des commentaires internes `file/version`.
## `package.json`
Le template représente un package privé et contient uniquement :
```text
name valeur d'exemple à remplacer
private true
scripts typecheck
```
Avant utilisation :
1. remplacer `project-web` par le nom réellement choisi ;
2. sélectionner explicitement le package manager ;
3. ajouter TypeScript comme dépendance de développement avec une version compatible réellement décidée par le projet ;
4. ajouter les dépendances fonctionnelles seulement lorsqu'elles sont réellement nécessaires ;
5. pour chaque dépendance consommée depuis TypeScript, vérifier si elle fournit déjà ses propres déclarations ;
6. lorsque les déclarations manquent, rechercher le package `@types/...` maintenu correspondant et l'ajouter normalement à `devDependencies` pour une application privée ;
7. ajouter `@types/node` uniquement si du code/config/outillage TypeScript utilise réellement l'environnement Node, et `@types/bootstrap` uniquement si les API JavaScript Bootstrap typées sont consommées ;
8. vérifier la compatibilité de version entre la dépendance runtime, le package de déclarations éventuel et TypeScript ;
9. laisser le package manager choisi produire son lockfile si la politique applicable le recommande ;
10. ajouter `dev`, `build`, `preview` ou autres scripts uniquement lorsque leurs owners existent.
Le template ne contient pas de champ `version` parce qu'une application privée n'a pas besoin d'inventer une version npm distincte. Un projet qui aligne volontairement ce manifest sur sa release globale peut l'ajouter selon sa gouvernance locale.
## `devDependencies` et déclarations de types
Le fichier copiable n'inclut aucune `devDependencies` concrète, car PGR ne peut pas connaître à l'avance les versions ni les packages réellement utilisés. Un projet instancié doit toutefois compléter le manifest. Un exemple de forme, à adapter sans recopier les versions littéralement, est :
```json
{
"devDependencies": {
"typescript": "<version décidée>",
"@types/node": "<si Node est réellement utilisé>",
"@types/bootstrap": "<si les API JavaScript Bootstrap sont réellement utilisées et nécessitent des types externes>"
}
}
```
L'ordre de décision est important :
```text
package utilisé
↓
fournit-il déjà ses propres types ?
├─ oui → utiliser les types embarqués ; ne pas ajouter un @types redondant
└─ non → rechercher @types/<package> ou une déclaration maintenue équivalente
↓
vérifier compatibilité et besoin réel
↓
ajouter au manifest dans la classe de dépendance appropriée
```
Pour une application privée, un package de déclarations utilisé uniquement par le type-check appartient normalement à `devDependencies`. Pour une bibliothèque publiée, si les `.d.ts` publics produits référencent cette déclaration, le package doit rester disponible aux consommateurs et peut donc devoir appartenir aux dépendances publiées plutôt qu'aux seules `devDependencies`.
Cette étape participe directement à la qualité TypeScript et à l'expérience IDE : les déclarations permettent au language service de mieux comprendre les signatures et objets importés, d'améliorer les diagnostics et de fournir navigation et complétion lorsque l'éditeur les expose.
## `tsconfig.json`
Le template active uniquement les contrôles considérés génériques pour une baseline stricte :
```text
strict
noEmit
noUnusedLocals
noUnusedParameters
noFallthroughCasesInSwitch
```
Avant utilisation, le projet doit décider explicitement les options qui dépendent de sa target et de son host : `target`, `module`, `moduleResolution`, `lib`, `types`, `jsx`, `include`, `exclude`, aliases et éventuels chemins générés.
Le template ne copie donc pas les valeurs Games `ES2022`, `ESNext`, `bundler`, `vite/client`, `node` ou les aliases WASM. Ces valeurs restent des preuves de corpus et pourront être reprises seulement par l'owner qui les justifie.
## Type-check indépendant
Après installation locale de TypeScript, le script générique est :
```text
typecheck -> tsc --noEmit
```
Le type-check SHOULD pouvoir être exécuté indépendamment du bundler. Un futur script `build` MAY l'appeler avant le build de production, mais cela ne supprime pas sa responsabilité propre.
Exemples d'appel selon le package manager sélectionné :
```text
npm run typecheck
pnpm typecheck
yarn typecheck
```
Ces lignes sont des exemples, pas une sélection de package manager par PGR.
## Lockfile
Pour une application privée/deployable issue de ce template, le lockfile du package manager sélectionné SHOULD normalement être versionné.
Si le projet conserve volontairement une autre politique, l'écart doit être traité comme décision locale ou `OVERRIDE` lors d'une adoption PGR, avec justification proportionnée.
PGR MUST NOT conserver plusieurs lockfiles concurrents uniquement pour rendre le template compatible avec plusieurs package managers.
## Validation minimale du template dans PGR
Le dépôt PGR vérifie seulement que les deux fichiers sont du JSON parsable et qu'ils conservent les champs génériques attendus.
La validation réelle d'un projet destinataire sélectionne ensuite :
- le package manager choisi ;
- la résolution/install de dépendances si nécessaire ;
- le mode gelé/immutable lorsque le lockfile est versionné ;
- le script `typecheck` ;
- les validations Vite/CSS/Sass/host applicables dans leurs owners respectifs.
Le futur `alpha.5` de `0.1.1` réconciliera la validation frontend complète sans transformer cette paire de templates en skeleton prématuré.

174
docs/templates/009-WEB_VITE.md vendored Normal file
View File

@@ -0,0 +1,174 @@
<!-- file: docs/templates/009-WEB_VITE.md -->
<!-- version: 1 -->
# Guide d'adaptation Vite
## Rôle
Ce document accompagne le profil [`550-VITE.md`](../rules/550-VITE.md) lorsqu'un projet sélectionne réellement Vite.
Il ne fournit volontairement pas de `vite.config.ts` copiable universel. Les corpus montrent une responsabilité réutilisable claire pour Vite, mais pas des valeurs universelles pour les chemins, ports, aliases, plugins ou hosts.
L'objectif est donc de normaliser **ce qui doit être décidé et validé**, sans figer arbitrairement **la valeur de chaque décision**.
## Manifest
Le manifest réel du projet doit utiliser le package manager choisi par le projet et ajouter Vite comme outil de développement avec une version explicitement décidée.
Les scripts usuels, lorsqu'ils correspondent au workflow réel, sont conceptuellement :
```json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
```
Ce fragment n'est pas un template complet de `package.json` et ne sélectionne aucun package manager.
`dev` et `build` sont naturels lorsqu'un frontend Vite existe. `preview` MAY être omis si aucun smoke/prévisualisation locale ne l'utilise.
Le type-check TypeScript reste une preuve séparée :
```text
typecheck -> tsc --noEmit
build -> vite build
```
Une CI peut exécuter successivement ces deux scripts sans imposer une syntaxe npm particulière.
## Décider `root`
Si `index.html` et les sources se trouvent à la racine comprise par Vite, aucune valeur explicite n'est nécessaire uniquement pour respecter PGR.
Si le package contient une racine frontend dédiée, le projet doit configurer `root` vers cette racine. Le nom `frontend/` observé dans Games est une convention locale utile mais pas une obligation générique.
## Décider `base`
`base` doit suivre le mode réel de service/embarquement :
```text
site servi à la racine souvent /
site sous un sous-chemin chemin public correspondant
host embarqué valeur relative si réellement requise
```
PGR ne copie donc pas automatiquement `base: "./"` depuis Games dans tous les projets Vite.
## Cache
Le cache Vite est reproductible et ne doit pas devenir un source versionné.
Ordre de préférence PGR :
1. placer `cacheDir` hors de l'arborescence source lorsqu'un emplacement de build externe existe déjà et reste simple à utiliser ;
2. sinon accepter un cache interne dédié et l'ignorer explicitement ;
3. ne jamais versionner le cache uniquement pour accélérer une machine locale.
L'effacement du cache doit rester sans conséquence fonctionnelle autre qu'un recalcul.
## Output de production
`build.outDir` contient des artefacts générés.
Ordre de préférence PGR :
1. utiliser un répertoire de build externe au source tree si l'environnement du projet le permet proprement ;
2. sinon utiliser un répertoire interne dédié, tel que `dist/`, explicitement ignoré ;
3. ne versionner un output que si un autre contrat de distribution l'exige réellement et documente cet artefact comme livrable.
Si `build.emptyOutDir` est activé, `outDir` doit être dédié à Vite. Le build ne doit pas pouvoir vider un répertoire partagé avec du WASM, des artefacts Rust, Android ou d'autres owners.
## Assets
Trois catégories doivent rester distinguées :
```text
asset source importé/référencé source versionné
asset source dans publicDir source statique versionné
asset copié/transformé dans outDir output généré
```
`publicDir` MAY rester au défaut Vite, être déplacé ou être désactivé avec `false` selon le besoin du projet.
Une copie réalisée par plugin n'autorise pas à supprimer la source de son owner ni à versionner la copie de build comme second source.
## Dev server et exposition réseau
Pour un développement local simple, rester sur une écoute locale/loopback est préférable.
N'élargir `server.host` au LAN/toutes interfaces que lorsqu'un besoin réel l'impose, par exemple un test sur device ou un host externe. Dans ce cas, revoir aussi les contraintes de hosts autorisés, CORS, TLS, proxy et HMR selon l'intégration réelle.
PGR déconseille les raccourcis globaux :
```text
server.allowedHosts = true
server.cors = true
```
Ils ne doivent pas devenir des valeurs de template universelles.
## Ports déterministes
Un port fixe n'est pas une règle PGR universelle.
Si rien ne consomme une URL déterministe, laisser Vite gérer son port peut être suffisant.
Si un host ou un smoke attend un port connu, utiliser ensemble :
```text
server.port valeur locale choisie
server.strictPort true
```
Ainsi, un conflit de port échoue explicitement au lieu de déplacer silencieusement le dev server.
La même logique peut s'appliquer à `preview.port` + `preview.strictPort` lorsqu'un smoke de preview exige une URL stable.
## Preview
`vite preview` sert à vérifier localement le build produit. Il ne constitue pas un serveur de production PGR.
Un smoke MAY lancer `preview` après un build lorsque cette observation apporte une preuve nécessaire. Le deployment/serving réel reste hors du présent owner.
## Ce qui reste local
La configuration suivante n'est pas normalisée par ce guide sans preuve supplémentaire :
```text
ports exacts
host exact
base exact
aliases
plugins
noms de chunks/assets
minification
sourcemaps
proxy
TLS
HMR / WebSocket
filesystem allowlists
intégration WASM
intégration Tauri
```
Games fournit des exemples utiles pour plusieurs de ces points, mais PGR ne transforme pas ces valeurs en défauts génériques.
## Validation dans PGR et dans un projet destinataire
PGR ne livre pas encore de `vite.config.ts` exécutable générique dans cette tranche ; il n'installe donc pas Vite uniquement pour valider un fichier fictif.
Dans un projet réel qui adopte ce profil, la gate applicable doit sélectionner l'outil réel et peut comprendre :
```text
typecheck séparé
build Vite de production
inspection du outDir attendu
preview/smoke seulement si nécessaire
validation du host séparée
```
Les commandes concrètes passent par le package manager sélectionné par le projet. Un exemple npm dans une documentation tierce ne devient pas une obligation PGR.

111
docs/templates/010-WEB_CSS_SASS.md vendored Normal file
View File

@@ -0,0 +1,111 @@
<!-- file: docs/templates/010-WEB_CSS_SASS.md -->
<!-- version: 1 -->
# Guide d'adaptation CSS / Sass
## Objet
Ce guide accompagne le profil [`../rules/560-CSS_SASS.md`](../rules/560-CSS_SASS.md). Il aide un projet à décider sa chaîne de styles sans transformer Sass, Bootstrap, Vite ou un layout particulier en obligation universelle.
PGR ne fournit volontairement pas de `main.scss`, de thème Bootstrap ou de structure `styles/` copiable par défaut : ces fichiers ne deviennent utiles qu'après choix du framework, des entrypoints, du layout et du niveau de personnalisation réel.
## Décider d'abord si Sass apporte une valeur
CSS seul reste valide lorsque les besoins sont simples ou que les capacités CSS modernes suffisent.
Sass est particulièrement pertinent lorsque le projet a besoin de :
- variables et configuration de compilation ;
- mixins, fonctions ou composition de modules ;
- factorisation d'une chaîne de styles non triviale ;
- personnalisation d'un package qui expose officiellement des sources Sass/SCSS ;
- construction sélective d'un framework ou thème sans modifier les sources tierces.
La décision doit rester liée au besoin réel. Un smoke ou un petit frontend n'a pas à recevoir Sass uniquement pour ressembler à un autre projet.
## Choisir l'implémentation
Dans un projet Vite compatible, les sources `.scss` / `.sass` peuvent être prises en charge par Vite lorsque le préprocesseur correspondant est installé. Pour une nouvelle baseline contrôlée, `sass-embedded` est un bon choix de `devDependency` lorsqu'il est supporté ; `sass` reste une alternative légitime.
Le package manager, la version et la commande d'installation sont décidés par le projet. Le guide ne transforme donc pas un exemple `npm add -D ...` en commande normative.
Hors Vite, utiliser l'intégration officielle du bundler ou du compilateur Sass sélectionné.
## Organiser les sources
Le projet décide ses noms de répertoires et entrypoints. Une organisation possible peut séparer :
```text
variables / configuration
modules internes
adaptations de packages tiers
styles applicatifs
entrypoint principal
```
Cette organisation n'est qu'un pattern. PGR n'impose ni `frontend/sass/`, ni `_variables.scss`, ni `main.scss`.
Les fichiers sources intentionnels sont versionnés. Les CSS compilées, fichiers minifiés, sourcemaps et copies du build restent générés sauf artefact de distribution explicitement gouverné.
## Préférer les modules Sass modernes
Pour le nouveau code :
```text
@use
@forward
```
sont préférés lorsque les dépendances les supportent.
`@import` Sass peut rester nécessaire pour une dépendance historique ou une API tierce qui le documente encore. Cette compatibilité doit rester locale ; elle ne doit pas conduire à écrire de nouveau code PGR autour de `@import` lorsque le système de modules fonctionne.
Lorsqu'un module accepte une configuration, utiliser son API publique et ses variables configurables plutôt que copier/modifier ses sources dans le projet.
## Packages npm et entrypoints de styles
Pour une dépendance de styles :
1. vérifier l'entrypoint CSS/Sass public documenté par le package ;
2. vérifier s'il expose une configuration Sass supportée ;
3. utiliser cet entrypoint public avant d'envisager un chemin interne sous `node_modules` ;
4. conserver tout override dans un source possédé par le projet ;
5. ne jamais modifier directement le package installé.
Un package peut exposer CSS, Sass, JavaScript ou plusieurs de ces surfaces. Les dépendances `@types/*` ne concernent que les API JavaScript/TypeScript qui en ont réellement besoin ; importer uniquement le Sass/CSS d'un package ne suffit pas à justifier un package de déclarations.
## Exemple Bootstrap
Bootstrap illustre un package pouvant être utilisé de plusieurs façons : CSS précompilé, API JavaScript et sources Sass configurables.
Si le projet choisit Bootstrap avec Sass, il doit suivre l'API Sass de la version réellement sélectionnée, placer ses variables/overrides avant les étapes requises par cette API et conserver les adaptations dans ses propres sources.
PGR ne fixe ni Bootstrap, ni Bootswatch, ni un thème, ni un ordre d'import particulier comme baseline universelle. Un projet existant utilisant encore `@import` pour compatibilité MAY le conserver jusqu'à une migration sûre.
## Relation avec Vite
Lorsque Vite est sélectionné :
- l'import d'un entrypoint `.scss` depuis le graphe frontend peut suffire à déclencher la compilation ;
- `css.preprocessorOptions` MAY adapter le compilateur lorsque le projet en a réellement besoin ;
- une configuration globale injectée dans chaque fichier doit rester limitée aux symboles nécessaires ; injecter des styles complets partout peut dupliquer le CSS ;
- les CSS présentes dans `build.outDir` sont des outputs Vite générés, pas de nouveaux sources.
Le profil Vite reste propriétaire de `vite.config.ts`, du cache et de l'output ; le profil CSS/Sass reste propriétaire de la chaîne de styles elle-même.
## Validation
Pour un frontend où Sass est intégré au build Vite :
```text
typecheck preuve TypeScript séparée si applicable
build preuve Vite + compilation/transformation des styles
browser smoke seulement si une propriété observable le nécessite
host gate séparée
```
Ne pas ajouter une commande Sass autonome si elle ne prouve rien de plus que le build déjà exécuté.
Si le projet possède au contraire une compilation Sass autonome, un linter ou un package de styles publié séparément, ajouter la preuve officielle correspondante.
Le contrat complet est décrit dans [`../validation/005-WEB_FRONTEND_VALIDATION.md`](../validation/005-WEB_FRONTEND_VALIDATION.md).

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
<!-- version: 9 -->
<!-- version: 14 -->
# Matrice de validation PGR
@@ -27,7 +27,7 @@ Les catégories et règles de sélection sont définies dans [`../rules/400-VALI
Un contrôle manuel peut rester dans la matrice lorsqu'aucun audit automatisé fiable n'existe encore. PGR SHOULD automatiser uniquement les propriétés stables et objectivement contrôlables.
`PGR-MD-TABLE-001` reste volontairement monotâche : il contrôle uniquement la structure et l'alignement source des tableaux Markdown.
`PGR-MD-TABLE-001` reste volontairement monotâche : il contrôle uniquement la structure et l'alignement source des tableaux Markdown. Il couvre les tableaux Markdown ordinaires ainsi que les exemples placés dans des fences explicitement `markdown` ou `md`. Les autres blocs fenced restent ignorés afin de ne pas interpréter comme Markdown des sorties terminal, extraits de code ou tableaux ASCII d'un autre langage.
`PGR-MD-HEADER-001` contrôle seulement les deux premières lignes des fichiers Markdown sélectionnés : chemin relatif depuis la racine et révision interne positive. La revue `PGR-DOC-001` reste responsable du rôle documentaire et de la pertinence réelle d'un incrément de révision.
@@ -37,9 +37,19 @@ PGR préfère plusieurs audits simples avec une responsabilité identifiable à
## Contrôles Rust réutilisables, hors gate du dépôt PGR
[`002-RUST_STYLE_AUDITS.md`](002-RUST_STYLE_AUDITS.md) décrit deux audits facultatifs : `audit_rust_blank_lines.py` contrôle l'espacement des lignes vides, `audit_rust_const_blocks.py` contrôle l'ordre et l'espacement des blocs de constantes au niveau racine. Ils acceptent des chemins Rust sélectionnés et partagent un petit support lexical ; leur validation ciblée dans PGR est `python3 -B -m unittest discover -s tests -p test_rust_audits.py`.
[`002-RUST_STYLE_AUDITS.md`](002-RUST_STYLE_AUDITS.md) décrit les audits monotâches de structure Rust : lignes vides, blocs `const`, séparation des items, ordre des modules, disposition des imports de traits et blocs de réexports. Ils acceptent des chemins Rust sélectionnés et partagent un petit support lexical ; leur validation ciblée dans PGR est `python3 -B -m unittest discover -s tests -p test_rust_audits.py -v`.
Leur disponibilité ne transforme pas PGR en workspace Rust et ne rend pas automatiquement l'ordre alphabétique applicable à chaque fichier d'un projet. Lors d'une adoption, le projet propriétaire sélectionne ses chemins après `cargo fmt` et applique sa propre gate ; Rustfmt et Clippy conservent les contrôles qu'ils possèdent.
Pour une nouvelle baseline contrôlée, les propriétés sans ordre métier peuvent faire partie du profil strict. L'audit `const_blocks` reste explicitement sélectionné, car une table de protocole, un schéma ou une séquence normative ne doit jamais être réordonné pour satisfaire un tri mécanique. Leur disponibilité ne transforme pas PGR en workspace Rust ; le projet propriétaire exécute ces audits après `cargo fmt`, et Rustfmt/Clippy/rustc conservent les contrôles qu'ils possèdent.
[`003-RUST_EXPORT_COMPLETENESS.md`](003-RUST_EXPORT_COMPLETENESS.md) décrit séparément `audit_rust_export_completeness.py`, audit facultatif de façade crate-root. Sa validation ciblée dans PGR est `python3 -B -m unittest discover -s tests -p test_rust_export_completeness.py -v`. L'audit est destiné aux projets Rust qui choisissent explicitement ce contrat ; PGR n'exécute pas ce script sur son propre dépôt comme gate, car il ne constitue pas lui-même un workspace Rust.
[`004-RUST_CARGO_BASELINE_DRY_RUN.md`](004-RUST_CARGO_BASELINE_DRY_RUN.md) décrit une preuve temporaire de réutilisabilité des skeletons/templates Rust/Cargo. Le mode « nouveau projet » utilise la toolchain officielle dans un répertoire temporaire ; le mode « projet existant » vérifie qu’un mapping d’adoption n’écrase pas les décisions locales classées `KEEP-LOCAL` ou `DEFER`. Cette preuve est sélectionnée lorsque les artefacts Rust/Cargo eux-mêmes changent ou lorsqu’une phase de release doit reconfirmer leur composabilité ; elle n’est pas une cérémonie de chaque delta documentaire.
## Validation frontend Web réutilisable, hors gate du dépôt PGR
[`005-WEB_FRONTEND_VALIDATION.md`](005-WEB_FRONTEND_VALIDATION.md) décrit la validation indépendante du host pour un frontend réel : restauration reproductible selon le package manager choisi, type-check TypeScript, styles, build de production et smoke navigateur seulement lorsqu'il apporte une preuve supplémentaire.
Cette validation appartient aux projets qui possèdent réellement un frontend ou aux dry-runs de skeletons correspondants. Le dépôt PGR n'installe pas TypeScript, Vite ou Sass uniquement pour simuler une gate qu'il ne possède pas. Les outils officiels restent propriétaires de leurs preuves ; un audit Python PGR ne les réimplémente pas.
## Politique Eclipse actuelle

View File

@@ -1,34 +1,79 @@
<!-- file: docs/validation/002-RUST_STYLE_AUDITS.md -->
<!-- version: 1 -->
<!-- version: 2 -->
# Audits facultatifs de style Rust
# Audits monotâches de structure Rust
## Responsabilité et provenance
Les sources KSP `0.3.16` et Games `0.3.5` possèdent chacune un `audit_rust_general_rules.py` qui mêle plusieurs règles. Le découpage PGR fournit deux contrôles ciblés sans copier l'orchestrateur ni les règles propres aux deux projets. Le contrat de style facultatif est dans [`510-RUST_CARGO.md`](../rules/510-RUST_CARGO.md), et la sélection des preuves dans [`400-VALIDATION.md`](../rules/400-VALIDATION.md).
Les sources KSP `0.3.16` et Games `0.3.5` possèdent chacune un `audit_rust_general_rules.py` composite. `0.0.3` avait déjà extrait deux propriétés ciblées ; `0.0.5-alpha.8` termine la réconciliation des propriétés de forme communes sans importer cet orchestrateur monolithique ni ses règles locales.
`scripts/audit_rust_blank_lines.py` contrôle les lignes vides consécutives et les lignes vides dans un corps de fonction/méthode, `struct` ou `enum`. `scripts/audit_rust_const_blocks.py` contrôle l'ordre `pub`, `pub(crate)`, privé, le tri naturel des noms dans chaque visibilité et l'espacement entre constantes consécutives au niveau racine du fichier. `scripts/_rust_audit_common.py` partage la sélection des chemins et le masquage des commentaires/littéraux : il ne définit aucune nouvelle politique.
Le contrat normatif est dans [`510-RUST_CARGO.md`](../rules/510-RUST_CARGO.md). Les scripts disponibles sont read-only et chacun possède une seule famille de preuve :
```text
audit_rust_blank_lines.py
lignes vides consécutives et lignes vides dans fn/méthode/struct/enum
audit_rust_const_blocks.py
ordre visibilité/nom et espacement des blocs const explicitement sélectionnés
audit_rust_item_spacing.py
exactement une ligne vide entre items Rust distincts voisins d'un même scope
audit_rust_module_order.py
modules de production avant tests, ordre alphabétique de chaque groupe
audit_rust_trait_import_blocks.py
bloc de use non exportés au module, avant les déclarations et sans ligne vide interne
audit_rust_reexport_blocks.py
bloc pub use avant pub(crate) use, espacement exact entre/à l'intérieur des blocs
```
`scripts/_rust_audit_common.py` partage seulement la sélection de fichiers et le masquage lexical des commentaires/littéraux. Il ne définit aucune politique. `audit_rust_export_completeness.py` reste séparé dans [`003-RUST_EXPORT_COMPLETENESS.md`](003-RUST_EXPORT_COMPLETENESS.md), car il possède la façade et les chemins canoniques plutôt que le formatage.
## Adoption et commandes
Dans un projet Rust qui choisit ces conventions, copier les trois fichiers `scripts/*.py` concernés en gardant le helper à côté des deux audits. Adapter les headers `file` au chemin du projet et maintenir une révision de fichier propre à cette copie.
Choisir explicitement les fichiers concernés par chaque contrat. Après formatage :
Pour une nouvelle baseline Rust contrôlée qui sélectionne le profil strict, les audits sans interprétation métier peuvent être exécutés sur les sources concernées après Rustfmt :
```bash
cargo fmt --all -- --check
python3 -B scripts/audit_rust_blank_lines.py crates/example/src
python3 -B scripts/audit_rust_blank_lines.py crates
python3 -B scripts/audit_rust_item_spacing.py crates
python3 -B scripts/audit_rust_module_order.py crates
python3 -B scripts/audit_rust_trait_import_blocks.py crates
python3 -B scripts/audit_rust_reexport_blocks.py crates
```
L'audit des constantes reste différent : sélectionner seulement les fichiers dont les blocs `const` doivent réellement suivre l'ordre mécanique PGR. Exemple :
```bash
python3 -B scripts/audit_rust_const_blocks.py crates/example/src/constants.rs
```
Une invocation sans chemin est une erreur, de même qu'un chemin absent ou aucun fichier Rust sélectionné. Un répertoire sélectionne récursivement les fichiers `.rs` hors répertoires générés habituels. Les audits ne modifient ni les fichiers inspectés ni l'arborescence de build. Les sorties utilisent le chemin et la ligne ; le code de sortie est `0` si propre, `1` pour violation, `2` pour sélection/lecture impossible.
Une invocation sans chemin est une erreur, de même qu'un chemin absent ou aucun fichier Rust sélectionné. Un répertoire sélectionne récursivement les fichiers `.rs` hors répertoires générés habituels. Les audits ne modifient ni les sources ni l'arborescence de build. Le code de sortie est `0` si propre, `1` pour violation et `2` pour sélection/lecture impossible.
Ne sélectionner pour l'audit des constantes que les fichiers dont les blocs racine sans sémantique d'ordre doivent effectivement suivre ce contrat. Un tri de table de protocole, des migrations, des champs de wire format ou de toute séquence métier peut casser le programme : sa revue appartient au projet. Ne pas utiliser la sortie du script comme justification pour les réordonner.
`audit_rust_trait_import_blocks.py` ne prouve pas qu'un `use` importe réellement un trait ; cette sémantique appartient au profil et à la revue/compilation. `audit_rust_reexport_blocks.py` ne trie pas les symboles exportés. Dans les deux cas, Rustfmt reste l'owner de l'ordre intra-bloc lorsque les lignes sont contiguës.
## Limites mesurées
`audit_rust_item_spacing.py` ne possède pas l'espacement des blocs compacts homogènes `const`/`static`/`type` : il les délègue afin de ne pas transformer une séparation sémantique entre deux grandes tables en faux positif. L'audit spécialisé `const_blocks` reste opt-in sur des fichiers explicitement choisis.
La prévalidation des sources réels a porté sur `300` fichiers KSP et `59` Games sous `crates/**/src/`. L'audit des lignes vides n'y détecte aucun écart. L'audit de constantes détecte `17` signaux KSP et aucun Games lorsque tous ces fichiers lui sont soumis ; des fichiers KSP contiennent des séquences ordonnées selon le protocole ou le schéma, ce qui rend une gate globale du tri inappropriée. Ces observations ne sont pas une gate de validation opérateur PGR.
## Mesure croisée KSP / Games
L'analyse lexicale masque littéraux et commentaires courants, y compris commentaires imbriqués et chaînes Rust brutes. Elle n'est pas un parseur Rust : les macros élaborées, syntaxe nouvelle, attributs complexes, items associés dans `impl` et constantes dans modules inline n'entrent pas dans le contrat garanti de l'audit des blocs racine. Les lignes vides à l'intérieur d'un littéral multilignes sont exclues. Les cas qui demandent une interprétation sémantique nécessitent la revue humaine ou les outils Rust du projet.
La prévalidation `alpha.8` a exécuté les quatre nouveaux audits sur l'ensemble des fichiers Rust sous `crates/` des archives fournies : `603` fichiers KSP `0.3.16` et `87` fichiers Games `0.3.5`. Les quatre contrôles sont propres sur les deux corpus :
Rustfmt reste propriétaire de l'ordre qu'il réécrit déjà dans les groupes de `use`/`mod`. Clippy et le compilateur restent responsables de leurs diagnostics. La suite `tests/test_rust_audits.py` vérifie les propriétés ciblées avec des cas propres, des violations et des littéraux/commentaires qui contiennent des accolades.
```text
KSP 0.3.16 Games 0.3.5
item spacing clean / 603 clean / 87
module order clean / 603 clean / 87
trait import blocks clean / 603 clean / 87
re-export blocks clean / 603 clean / 87
```
L'audit des lignes vides est également propre sur les `603` et `87` fichiers. En revanche, l'audit `const_blocks` appliqué aveuglément à tout le corpus produit `18` signaux KSP et `0` Games. Certains signaux KSP concernent des tables/schémas dont l'ordre est intentionnel, ce qui confirme qu'il ne doit pas devenir une gate globale par défaut. Ces mesures sont des preuves de réconciliation PGR, pas une validation opérateur de KSP/Games.
## Limites et owners
Les analyses masquent les commentaires et littéraux courants, y compris chaînes brutes et commentaires imbriqués, mais ne constituent pas un parseur Rust. Elles n'essaient pas de comprendre les expansions de macros, l'ordre métier, les protocoles ou les dépendances sémantiques entre items.
PGR ne crée pas d'audit automatique pour imposer un ordre global des catégories `enum`, `struct`, `impl`, fonctions ou helpers privés. Le rapprochement `struct` puis `impl`, et la préférence des éléments visibles avant les helpers privés, restent des conventions de lisibilité soumises à la sémantique locale.
Rustfmt possède le formatage et les tris qu'il sait réellement réécrire ; rustc et Clippy conservent leurs diagnostics. Les tests PGR de ces scripts vivent dans `tests/test_rust_audits.py`.

View File

@@ -0,0 +1,145 @@
<!-- file: docs/validation/003-RUST_EXPORT_COMPLETENESS.md -->
<!-- version: 2 -->
# Audit facultatif de façade Rust et canonicalisation intra-crate
## Responsabilité
`scripts/audit_rust_export_completeness.py` contrôle un contrat Rust optionnel plus strict que les garanties du compilateur et de Clippy : une crate qui adopte cette convention possède une façade crate-root explicite pour ses items partagés, et toute consommation intra-crate d'un item possédant cette identité canonique passe par `crate::Item`.
Le propriétaire normatif reste [`../rules/510-RUST_CARGO.md`](../rules/510-RUST_CARGO.md). Le script ne définit pas une architecture à lui seul ; il matérialise uniquement le contrat strict lorsqu'un projet choisit de l'adopter.
L'audit émet deux familles de diagnostics :
```text
RUST-API-201
item `pub` d'un module fichier sans réexport explicite au crate-root,
ou item `pub(crate)` clairement consommé hors de son module sans réexport crate-root
RUST-IMPORT-201
référence intra-crate non canonique à un item possédant une identité crate-root ;
la forme attendue est `crate::Item`
```
`RUST-IMPORT-201` ne se limite donc pas à `crate::module::Item`. Il couvre notamment :
```text
Item
self::Item
super::Item
module::Item
crate::module::Item
```
lorsque ces formes désignent un item partagé déjà exposé comme `crate::Item`.
La règle s'applique également **dans le module qui déclare l'item**. Par exemple :
```rust
pub struct Runtime;
impl Runtime {
pub fn new() -> Runtime {
return Runtime;
}
}
```
n'est pas canonique après réexport de `Runtime`. Le contrat strict attend :
```rust
pub struct Runtime;
impl crate::Runtime {
pub fn new() -> crate::Runtime {
return crate::Runtime;
}
}
```
Le même principe vaut pour une fonction partagée appelée depuis son module propriétaire : `crate::build()` est canonique, `build()` ne l'est pas.
Les lignes de déclaration de l'item et les lignes de réexport qui construisent la façade sont naturellement exemptées. Un item strictement privé n'appartient pas à ce contrat ; dans un test unitaire attaché à son module parent, `super::PrivateItem` reste une forme locale légitime.
## Pourquoi Cargo/Clippy ne suffisent pas
Le compilateur vérifie la résolution et la visibilité des noms ; il ne possède pas la convention « tout accès partagé passe par `crate::Item` ». Clippy peut signaler certains imports ou réexports inutilisés, mais une seule consommation correcte de `crate::Item` peut suffire à rendre le réexport utilisé tandis que d'autres références continuent d'employer un nom nu ou un chemin interne.
L'audit fournit donc une preuve distincte : **uniformité de la façade et des chemins intra-crate**, pas simple compilabilité.
## Cibles Cargo et graphes de modules
La `version: 2` ne confond plus automatiquement tous les fichiers d'un package Cargo dans une seule crate. Un package peut contenir simultanément une bibliothèque `src/lib.rs` et un binaire `src/main.rs` ; ces deux cibles sont compilées comme des crates distinctes et `crate::Item` n'y désigne pas la même racine.
L'audit découvre les packages récursivement puis traite séparément les cibles standard/explicites `lib` et `bin`. Pour chaque cible, il suit les modules fichiers déclarés par `mod name;` et les modules `#[path = "..."]`, ce qui couvre notamment les `unit_tests/` attachés utilisés dans le corpus KSP/Games sans englober les tests d'intégration Cargo sous `tests/`, qui sont des crates externes.
Cette distinction évite de considérer à tort `owner_crate::Item` utilisé dans un binaire comme une violation de la bibliothèque du même package.
## Provenance et correction du corpus
KSP `0.3.16` et Games `0.3.5` contiennent un `audit_rust_export_completeness.py` historiquement identique à l'exception de sa révision. Cette convergence justifie l'extraction du concept, mais pas une copie littérale.
Deux limites historiques ont été identifiées :
1. la découverte `crates/*/Cargo.toml` couvrait les `22` packages KSP directement sous `crates/`, mais aucune des `23` crates Games imbriquées sous `crates/apps/`, `crates/common/`, `crates/engines/`, etc. ;
2. la canonicalisation détectait surtout `crate::module::Item` et quelques cas particuliers de tests, mais pas les références ordinaires par nom nu dans les modules de production, y compris le module propriétaire.
La première version PGR de `alpha.5` corrigeait seulement la découverte récursive et le chemin interne long. La revue opérateur après sa gate a explicitement révélé la seconde lacune ; `alpha.5` est donc conservé `FAIL` et `alpha.5.fix.1` étend `RUST-IMPORT-201` au contrat réellement attendu.
## Mesure de réconciliation après le fix
Avec la `version: 2`, en mode `--report-only --summary-only`, les baselines autoritaires de la réconciliation donnent :
```text
KSP 0.3.16
22 package(s)
1525 candidate(s)
RUST-IMPORT-201: 1525
Games 0.3.5
23 package(s)
181 candidate(s)
RUST-API-201: 2
RUST-IMPORT-201: 179
```
Ces nombres représentent des **lignes candidates**, pas des déclarations distinctes. Ils sont beaucoup plus élevés que la première mesure `0 / 2` parce que le contrat corrige précisément le blind spot signalé : les références nues déjà répandues dans les modules propriétaires et consumers deviennent enfin visibles.
KSP et Games n'étant pas encore gouvernés par cette version de PGR, ces résultats ne sont pas qualifiés de défauts rétroactifs et ne déclenchent aucune migration dans `0.0.5`. Ils constituent un inventaire d'adoption future. Pour un projet existant, l'usage initial en `--report-only` est donc particulièrement important.
## Adoption
Pour adopter cette convention dans un projet Rust, copier :
```text
scripts/_rust_audit_common.py
scripts/audit_rust_export_completeness.py
```
puis adapter les headers de fichiers au dépôt destinataire.
Commande canonique :
```bash
python3 -B scripts/audit_rust_export_completeness.py --root .
```
Le code de sortie est `0` lorsque le corpus est propre, `1` lorsqu'au moins un candidat est trouvé et `2` lorsque la racine est invalide, illisible ou ne contient aucun package Rust détectable. `--report-only` permet un inventaire sans bloquer la gate ; `--summary-only` réduit la sortie aux comptes.
Une adoption progressive d'un projet existant devrait commencer par :
```bash
python3 -B scripts/audit_rust_export_completeness.py --root . --report-only --summary-only
```
puis inventorier/corriger les familles d'écarts avant de rendre l'audit bloquant. Une nouvelle crate créée sous le contrat peut au contraire l'activer immédiatement.
## Limites
L'analyse reste lexicale et ne remplace pas un parseur Rust complet. Elle vise les déclarations module-level `pub`/`pub(crate)`, les réexports explicites et les références dans le graphe de modules d'une cible. Les macros générant des items, modules inline complexes, `include!`, formes de `#[path]` atypiques et réexports élaborés peuvent nécessiter une revue humaine.
Pour réduire les faux positifs, une fonction partagée est reconnue comme référence lorsqu'elle apparaît sous une forme d'appel directe ; l'usage d'une fonction comme valeur de premier ordre peut donc échapper à cette version. Les chemins explicitement qualifiés par une crate externe et les appels de méthodes `.name()` ne sont pas assimilés à un item local de même nom.
Un item `pub(crate)` qui n'est pas clairement consommé hors de son module n'est pas forcé au crate-root par `RUST-API-201`; sa visibilité peut nécessiter une revue séparée. Dès qu'un réexport crate-root existe, ses références détectées sont toutefois soumises à `RUST-IMPORT-201`, y compris dans son module de déclaration.
L'audit ne remplace ni `cargo check`, ni Clippy, ni rustdoc. Il complète ces outils avec une convention architecturale qu'ils ne possèdent pas.

View File

@@ -0,0 +1,100 @@
<!-- file: docs/validation/004-RUST_CARGO_BASELINE_DRY_RUN.md -->
<!-- version: 1 -->
# Dry-run de baseline Rust/Cargo
## Rôle
Ce contrat vérifie que la fondation PGR, le skeleton Rust/Cargo et les cinq templates techniques peuvent être utilisés sans dépendre de KSP ou Games.
Il possède deux modes distincts :
```text
NEW nouveau projet : instanciation temporaire réelle des templates
ADOPTION projet existant : comparaison et mapping non destructifs
```
Le dry-run n’est ni un générateur de projet permanent ni une nouvelle architecture applicative. Les répertoires temporaires sont supprimés après la preuve.
## Owners exercés
Le chemin `NEW` compose :
```text
001-PROJECT_GOVERNANCE_FOUNDATION
002-RUST_CARGO_WORKSPACE
500-LANGUAGES
510-RUST_CARGO
001-RUST_CARGO_TOOLING
002-CARGO_MANIFESTS
```
Le chemin `ADOPTION` ajoute [`../rules/230-ADOPTION.md`](../rules/230-ADOPTION.md) et traite `001` / `002` comme checklists de comparaison plutôt que comme recettes de remplacement.
## Mode NEW — nouveau workspace
La preuve temporaire SHOULD :
1. copier les cinq artefacts de `templates/rust-cargo/` dans un répertoire temporaire ;
2. remplacer `project-name`, `project-core-lib`, le membre workspace et la version d’exemple par des valeurs propres au dry-run ;
3. créer uniquement le `src/lib.rs` minimal nécessaire à Cargo ;
4. vérifier qu’aucun placeholder PGR ne reste dans les fichiers adoptés ;
5. parser les manifests/configurations TOML avec un parseur fiable ;
6. lorsque Cargo est disponible, exécuter au minimum :
```bash
cargo metadata --format-version 1 --no-deps
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Le code source temporaire ne devient pas un template PGR. Son seul rôle est de permettre à la toolchain officielle de vérifier les manifests et l’outillage copiés.
## Mode ADOPTION — workspace existant
La preuve d’adoption MUST partir d’un état local qui ne correspond pas byte-for-byte aux templates PGR. Elle doit démontrer au minimum un mapping contenant plusieurs décisions, par exemple :
```text
510-RUST_CARGO ADOPT
rustfmt.max_width local KEEP-LOCAL
configuration d’artefacts PGR DEFER
audit de façade strict DEFER
```
Le dry-run MUST vérifier que les fichiers classés `KEEP-LOCAL` ou `DEFER` restent inchangés. Une adoption n’est pas prouvée en recopiant les templates puis en déclarant que le projet existant était compatible.
Lorsque la toolchain est disponible, le workspace existant synthétique ou réel SHOULD rester valide avant et après le mapping : `cargo metadata`, `cargo fmt -- --check`, `cargo check` et, lorsque pertinent, `cargo clippy` restent les preuves autoritaires des contrats Cargo/Rust.
## Prévalidation sans Cargo
Un environnement disposant de Python mais pas de Cargo MAY prévalider :
- syntaxe TOML avec `tomllib` ou un parseur équivalent ;
- résolution des placeholders attendus ;
- cohérence des liens entre skeletons, templates et owners ;
- caractère non destructif du mapping d’adoption ;
- absence de dépendance à KSP/Games dans les artefacts copiables.
Cette prévalidation ne constitue pas un `PASS` de la toolchain. Lorsqu’une tranche exige le mode `NEW` complet, l’absence de Cargo conduit à `BLOCKED` ou à une preuve explicitement incomplète, jamais à un faux succès.
## Critères de sortie
Le dry-run est réussi lorsque :
```text
NEW
- templates adaptés sans placeholder résiduel ;
- TOML valide ;
- toolchain Rust/Cargo sélectionnée réussie ;
- aucun artefact temporaire n’entre dans le dépôt PGR.
ADOPTION
- baseline locale explicitement distincte ;
- mapping ADOPT / KEEP-LOCAL / OVERRIDE / DEFER valide ;
- fichiers KEEP-LOCAL / DEFER préservés ;
- toolchain locale toujours valide lorsque cette preuve est applicable ;
- aucun historique n’est réécrit.
```
Le résultat de release reste possédé par le history de la tranche qui exécute cette preuve.

View File

@@ -0,0 +1,128 @@
<!-- file: docs/validation/005-WEB_FRONTEND_VALIDATION.md -->
<!-- version: 1 -->
# Validation frontend Web indépendante du host
## Objet
Ce document décrit une validation réutilisable pour un frontend Web composé à partir des owners TypeScript/package/Vite/CSS-Sass de PGR.
Il complète [`../rules/400-VALIDATION.md`](../rules/400-VALIDATION.md). Il n'ajoute aucune gate au dépôt PGR lui-même, qui ne contient pas de frontend exécutable. Il sert aux projets destinataires et aux dry-runs de skeletons lorsqu'un frontend réel est présent.
## Principe d'indépendance
Le frontend **SHOULD** être validable indépendamment du host autant que son graphe réel le permet.
Un résultat frontend `PASS` prouve uniquement les propriétés frontend sélectionnées. Il ne vaut pas `PASS` Tauri, Android, WASM, backend ou deployment.
Inversement, un échec du host ne doit pas être requalifié en échec TypeScript/Vite/Sass lorsque la gate frontend indépendante est déjà propre et que le défaut appartient clairement à l'intégration du host.
Une dépendance d'entrée réellement générée par un autre owner reste un prérequis explicite. PGR ne doit pas prétendre à une indépendance complète lorsque le build frontend consomme effectivement un artefact externe absent.
## Couches de preuve
Une gate frontend sélectionne uniquement les couches applicables :
```text
1. restauration reproductible des dépendances
2. type-check TypeScript
3. compilation/transformation des styles si distincte
4. build frontend de production
5. inspection ciblée des outputs si nécessaire
6. preview / smoke navigateur si une propriété runtime le justifie
7. validation du host séparée
```
Ces étapes décrivent des responsabilités, pas une liste obligatoire de commandes.
## Restauration des dépendances
Si le package possède un lockfile versionné, CI et les gates reproductibles **SHOULD** utiliser le mode frozen/immutable/clean-install équivalent du package manager sélectionné.
PGR MUST NOT imposer `npm ci` à un projet pnpm, Yarn ou autre. La commande appartient au package manager réel.
Une tranche purement documentaire ou une preuve qui n'a pas besoin de résoudre les dépendances MAY réutiliser une installation déjà autorisée si les règles locales de reproductibilité le permettent.
## Type-check
Lorsqu'un frontend sélectionne le profil TypeScript `530`, le script canonique `typecheck` **SHOULD** rester directement exécutable.
La preuve conceptuelle est :
```text
<package-manager> run typecheck
```
La syntaxe exacte dépend de l'outil sélectionné.
Si le script `build` exécute déjà exactement le même type-check, la matrice locale MAY éviter une exécution redondante lorsque cette composition est stable et visible. Pour une séparation de diagnostic plus claire, exécuter `typecheck` puis `build` reste préférable lorsque le coût est faible.
## Styles
Si Sass/CSS est transformé à l'intérieur du build frontend, le build réussi MAY constituer la preuve de compilation des styles.
Une compilation Sass autonome, un linter CSS/Sass ou une publication de package de styles reçoit une gate séparée uniquement si elle possède un contrat distinct.
PGR SHOULD NOT lancer deux compilations équivalentes uniquement pour augmenter le nombre de checks.
## Build de production
Lorsqu'un bundler tel que Vite est sélectionné, un changement qui touche ses entrées, sa configuration ou ses outputs **SHOULD** exécuter le build de production réel :
```text
<package-manager> run build
```
La réussite du build prouve la capacité du frontend à produire ses outputs avec le graphe courant. Elle ne prouve pas automatiquement le comportement dans un navigateur ni le fonctionnement du host.
Un contrôle ciblé MAY vérifier l'existence ou l'emplacement d'un output critique lorsque cette propriété n'est pas déjà garantie de façon suffisante par le build.
## Preview et smoke navigateur
Un smoke navigateur n'est requis que lorsqu'une propriété importante ne peut pas être prouvée utilement par type-check/build seuls, par exemple :
- chargement réel de l'entrypoint ;
- résolution d'assets ou de `base` ;
- comportement runtime critique ;
- connexion à un service local de test ;
- intégration navigateur spécifique.
Avec Vite, `preview` MAY servir à exposer localement le build pour ce smoke. `preview` n'est pas un serveur de production.
Un smoke **SHOULD** rester court, déterministe autant que possible et centré sur la propriété qui justifie son existence.
## Host séparé
Un host tel que Tauri peut déclencher le dev/build frontend via ses hooks, mais ce couplage ne transfère pas l'ownership de la validation frontend au host.
La matrice locale **SHOULD** conserver au minimum une voie permettant d'exécuter les preuves frontend pertinentes sans lancer l'ensemble du host, lorsque la topologie réelle du projet le permet.
Ensuite seulement, une gate d'intégration du host vérifie la composition : hooks, chemins, artefacts attendus, capacités natives, packaging ou comportement end-to-end selon le framework.
## Matrice minimale adaptable
Exemple de classification, à adapter au projet :
```text
restore reproductible | lockfile versionné | package manager | mode frozen/immutable/clean-install
type-check | TypeScript sélectionné | TypeScript | script typecheck
styles | compilation distincte du build | Sass/CSS toolchain | commande officielle ciblée
build | bundler sélectionné | Vite ou alternative | script build
browser smoke | comportement runtime à prouver | navigateur / harness | smoke court
host integration | host présent | Tauri ou autre host | gate du host
```
Le projet peut fusionner deux lignes uniquement lorsque la même commande prouve réellement les deux contrats et que cette composition reste explicite.
## Validation d'un skeleton Web
Une instanciation temporaire du skeleton Web MAY être utilisée pour vérifier :
- que les fichiers copiés/adaptés sont parsables ;
- que le package manager et les versions sélectionnés résolvent réellement ;
- que `typecheck` passe ;
- que le build sélectionné produit les outputs attendus ;
- que les styles choisis compilent ;
- qu'aucune validation du host n'est nécessaire pour ces preuves frontend.
Cette preuve de toolchain doit utiliser les outils officiels réels. Un audit Python statique ne remplace pas TypeScript, Vite ou Sass pour les propriétés qu'ils possèdent.

76
history/0.0.4/alpha.1.md Normal file
View File

@@ -0,0 +1,76 @@
<!-- file: history/0.0.4/alpha.1.md -->
<!-- version: 1 -->
# History 0.0.4-alpha.1 — audit de baseline et cadrage des skeletons
## Statut
PASS
La gate de `0.0.4-alpha.1` exécutée par l'opérateur le `2026-09-24` valide la reprise depuis la stable `0.0.3`, le cadrage des premières skeleton specifications et le plan actif de `0.0.4`. Les contrôles mécaniques demandés sont propres et le scope Git observé correspond exactement au delta.
## Baseline et version
La tranche a été appliquée sur l'état stable `0.0.3` contrôlé pendant le cadrage depuis l'archive `pgr-v0.0.3.zip` et le rapport post-tag externe `pgr-0.0.3-publish.001-report.md` déclaré `PASS`.
La version contrôlée après application est :
```text
0.0.4-alpha.1
```
Le plan `docs/plans/004-V0_0_4_SKELETONS_PLAN.md` et le delta `deltas/0.0.4/alpha.1.md` sont présents ; `history/0.0.4/alpha.1.md` était absent pendant la gate. Les révisions attendues de `README.md` et `docs/000-README.md` sont respectivement `7` et `5`, et les deux documents référencent le plan actif.
## Validation opérateur observée
L'opérateur a fourni les sorties du `2026-09-24` depuis `~/Projects/pgr`. Le contrôle de `VERSION` a été exécuté à `13:48:46`, puis les autres contrôles et validations à `13:53:25`–`13:53:26`.
La suite Python globale a exécuté `15` tests, tous réussis :
```text
Ran 15 tests in 0.223s
OK
```
Les trois audits documentaires affichent :
```text
Markdown header audit: clean (101 file(s))
Markdown table audit: clean (3 table(s), 101 file(s))
Markdown link audit: clean (81 local link(s), 101 file(s))
```
Le contrôle structurel de la baseline affiche :
```text
Baseline structural audit: clean (34 prior delta/history pairs, 10/10 histories 0.0.3 PASS, 5 TOML parsed)
```
Il confirme notamment l'appariement des `12` deltas/histories de `0.0.1`, des `12` de `0.0.2` et des `10` de `0.0.3`, le statut `PASS` des dix histories `0.0.3`, la présence des trois scripts d'audit Rust attendus et le parsing des cinq fichiers TOML du template Rust/Cargo.
`git diff --check` et `git diff --cached --check` n'ont affiché aucun diagnostic. Après ajout des fichiers du delta, le statut indexé transmis est exactement :
```text
M README.md
M VERSION
A deltas/0.0.4/alpha.1.md
M docs/000-README.md
A docs/plans/004-V0_0_4_SKELETONS_PLAN.md
```
La transcription du terminal intercale un fragment du heredoc Python avec le début de la sortie `unittest`. Les quinze cas individuels, le résumé final `OK`, les trois audits documentaires, le contrôle structurel et le statut Git restent néanmoins identifiables et ne signalent aucun échec.
## Revue de cadrage
La revue du contenu livré confirme que le plan distingue bien les prévisions des règles déjà actives : le contrat commun des skeletons est présenté comme une cible à fixer dans `alpha.2`, et aucun chemin prévisionnel n'est transformé en propriétaire normatif avant sa création effective.
Les valeurs Rust/Cargo citées dans le plan restent explicitement des exemples ou décisions destinataire à adapter, notamment `0.1.0`, `2024`, `project-name`, `project-core-lib`, les seuils Clippy et les chemins de build. Aucun de ces choix n'est promu en valeur universelle.
Java/Maven/Gradle, Android, Web, JNI, Tauri et les autres familles sans pièces suffisantes restent explicitement différés. Aucun skeleton concret, profil supplémentaire, template ou artefact technologique de ces domaines n'est matérialisé dans `alpha.1`.
## Transition
Appliquer le présent history puis committer `0.0.4-alpha.1` avant tout delta `alpha.2`. Le commit futur n'est pas attesté par les sorties fournies.
Après ce commit, la tranche suivante est `0.0.4-alpha.2` et doit rester limitée au contrat de sélection et de composition des skeletons, à son propriétaire normatif et à l'index de la collection documentaire correspondante, conformément au plan actif.

103
history/0.0.4/alpha.2.md Normal file
View File

@@ -0,0 +1,103 @@
<!-- file: history/0.0.4/alpha.2.md -->
<!-- version: 1 -->
# History 0.0.4-alpha.2 — contrat de composition des skeletons
## Statut
PASS
La gate de `0.0.4-alpha.2` exécutée par l'opérateur le `2026-09-24` valide le propriétaire normatif transversal des skeleton specifications, l'activation de leur collection documentaire et la réconciliation des index et documents d'architecture concernés. Les contrôles mécaniques demandés sont propres et le scope Git observé correspond exactement au delta.
## Baseline et version
La tranche a été appliquée après le commit opérateur `bf306da` de `0.0.4-alpha.1`, qui contenait `history/0.0.4/alpha.1.md` avec statut `PASS` et avait été poussé sur `origin/master`.
La version contrôlée après application est :
```text
0.0.4-alpha.2
```
`history/0.0.4/alpha.1.md`, `deltas/0.0.4/alpha.2.md`, `docs/rules/220-SKELETONS.md` et `docs/skeletons/000-README.md` sont présents ; `history/0.0.4/alpha.2.md` était absent pendant la gate.
Les skeleton specifications concrètes prévues pour les tranches suivantes étaient bien absentes :
```text
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
```
## Validation opérateur observée
L'opérateur a fourni les sorties du `2026-09-24` depuis `~/Projects/pgr`, à `14:15:19`–`14:15:20`.
Les révisions documentaires attendues ont été confirmées :
```text
README.md version 8
RULES.md version 10
docs/000-README.md version 6
docs/architecture/002-GOVERNANCE_ARCHITECTURE.md version 3
docs/architecture/003-RULE_PROFILE_MODEL.md version 3
docs/rules/000-README.md version 11
docs/rules/220-SKELETONS.md version 1
docs/skeletons/000-README.md version 1
```
Les références attendues vers `docs/rules/220-SKELETONS.md` et `docs/skeletons/` sont présentes dans les points d'entrée, l'index normatif et les deux documents d'architecture concernés.
La suite Python globale a exécuté `15` tests, tous réussis :
```text
Ran 15 tests in 0.256s
OK
```
Les trois audits documentaires affichent :
```text
Markdown header audit: clean (105 file(s))
Markdown table audit: clean (3 table(s), 105 file(s))
Markdown link audit: clean (97 local link(s), 105 file(s))
```
Le contrôle structurel spécifique affiche :
```text
Skeleton contract audit: clean (alpha.1 PASS baseline, alpha.2 contract/index only)
```
Il confirme notamment que `history/0.0.4/alpha.1.md` est le seul history `0.0.4` présent pendant la gate, qu'il est `PASS`, que la collection `docs/skeletons/` ne contient encore que son index et que les huit responsabilités prévues du contrat `220` sont présentes.
`git diff --check` et `git diff --cached --check` n'ont affiché aucun diagnostic. Après ajout des fichiers du delta, le statut indexé transmis est exactement :
```text
M README.md
M RULES.md
M VERSION
A deltas/0.0.4/alpha.2.md
M docs/000-README.md
M docs/architecture/002-GOVERNANCE_ARCHITECTURE.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/rules/000-README.md
A docs/rules/220-SKELETONS.md
A docs/skeletons/000-README.md
```
La transcription du terminal intercale à deux endroits des fragments de commandes/heredoc avec la sortie de `unittest`. Les quinze cas individuels, le résumé final `OK`, les audits documentaires, le contrôle structurel et le statut Git restent néanmoins identifiables et ne signalent aucun échec.
## Revue de scope
La tranche reste conforme au plan `0.0.4` : `docs/rules/220-SKELETONS.md` possède le contrat transversal de sélection et composition, tandis que `docs/architecture/003-RULE_PROFILE_MODEL.md` conserve la propriété de la hiérarchie et de la résolution des profils.
La collection `docs/skeletons/` est réellement activée par son index mais ne contient aucun placeholder de specialization. Aucun skeleton de fondation, Rust/Cargo, Java/Android, Web, JNI, Tauri ou autre domaine technologique n'a été matérialisé dans `alpha.2`.
## Transition
Appliquer le présent history puis committer `0.0.4-alpha.2` avant d'appliquer le delta `0.0.4-alpha.3`.
Le history `alpha.2` et le delta `alpha.3` peuvent être livrés dans le même échange sous deux archives distinctes. Cette livraison simultanée ne change pas l'ordre d'application : le delta suivant MUST rester absent du dépôt jusqu'au commit de la tranche `alpha.2`.
La tranche suivante est `0.0.4-alpha.3` et doit rester limitée à la première skeleton specification composable de fondation de projet gouverné, sans specialization technologique.

96
history/0.0.4/alpha.3.md Normal file
View File

@@ -0,0 +1,96 @@
<!-- file: history/0.0.4/alpha.3.md -->
<!-- version: 1 -->
# History 0.0.4-alpha.3 — fondation de projet gouverné
## Statut
PASS
La gate de `0.0.4-alpha.3` exécutée par l'opérateur le `2026-09-24` valide la première skeleton specification concrète de PGR : une fondation composable de gouvernance locale sans specialization technologique. Les contrôles mécaniques demandés sont propres et le scope Git observé correspond exactement au delta.
## Baseline et version
La tranche a été appliquée après le commit opérateur `7408616` de `0.0.4-alpha.2`, qui contenait `history/0.0.4/alpha.2.md` avec statut `PASS` et avait été poussé sur `origin/master`.
La version contrôlée après application est :
```text
0.0.4-alpha.3
```
`history/0.0.4/alpha.2.md`, `deltas/0.0.4/alpha.3.md` et `docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md` sont présents ; `history/0.0.4/alpha.3.md` était absent pendant la gate.
Le skeleton technologique suivant était bien absent :
```text
docs/skeletons/002-RUST_CARGO_WORKSPACE.md
```
## Validation opérateur observée
L'opérateur a fourni les sorties du `2026-09-24` depuis `~/Projects/pgr`, à `14:30:21`–`14:31:25`.
Les révisions documentaires attendues ont été confirmées :
```text
README.md version 9
docs/000-README.md version 7
docs/skeletons/000-README.md version 2
docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md version 1
```
Les références attendues vers `001-PROJECT_GOVERNANCE_FOUNDATION.md` sont présentes dans `README.md`, `docs/000-README.md` et l'index `docs/skeletons/000-README.md`.
La suite Python globale a exécuté `15` tests, tous réussis :
```text
Ran 15 tests in 0.229s
OK
```
Les trois audits documentaires affichent :
```text
Markdown header audit: clean (108 file(s))
Markdown table audit: clean (3 table(s), 108 file(s))
Markdown link audit: clean (103 local link(s), 108 file(s))
```
Le contrôle structurel spécifique affiche :
```text
Governance foundation audit: clean (alpha.1/alpha.2 PASS baseline, one concrete non-technological skeleton)
```
Il confirme notamment que les seuls histories `0.0.4` présents pendant la gate étaient `alpha.1.md` et `alpha.2.md`, tous deux `PASS`, que la collection des skeletons contenait uniquement son index et la fondation `001`, et que les sections et owners généraux attendus étaient présents.
`git diff --check` et `git diff --cached --check` n'ont affiché aucun diagnostic. Après ajout des fichiers du delta, le statut indexé transmis est exactement :
```text
M README.md
M VERSION
A deltas/0.0.4/alpha.3.md
M docs/000-README.md
M docs/skeletons/000-README.md
A docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md
```
La transcription du terminal intercale des fragments de commandes/heredoc avec la sortie de `unittest`. Les quinze cas individuels, le résumé final `OK`, les audits documentaires, le contrôle structurel et le statut Git restent néanmoins identifiables et ne signalent aucun échec.
## Revue de scope
La fondation reste une procédure composable et non un template ou générateur implicite. Elle sélectionne uniquement les owners généraux `200`, `210`, `300` et `400`, conserve `220` comme contrat d'instanciation et ne sélectionne aucun profil `500+` ou `600+` par défaut.
Les documents et répertoires sont créés à la demande selon un contenu réel ; aucune copie exhaustive du layout PGR n'est imposée. Les décisions destinataire restent explicites et aucune valeur d'exemple technologique n'est introduite dans cette tranche.
L'ordre de composition permet à une specialization telle que Rust/Cargo d'ajouter ses profils, templates et validations sans redéfinir les responsabilités générales de la fondation.
## Transition
Appliquer le présent history puis committer `0.0.4-alpha.3` avant d'appliquer le delta `0.0.4-alpha.4`.
Le history `alpha.3` et le delta `alpha.4` peuvent être livrés dans le même échange sous deux archives distinctes. Cette livraison simultanée ne change pas l'ordre d'application : le delta suivant MUST rester absent du dépôt jusqu'au commit de la tranche `alpha.3`.
La tranche suivante est `0.0.4-alpha.4` et doit rester limitée au skeleton Rust/Cargo workspace, à sa composition avec la fondation `001`, aux cinq templates Rust/Cargo existants, aux décisions destinataire et à une validation d'instanciation proportionnée.

Some files were not shown because too many files have changed in this diff Show More